From e09b41010ba33a20a87472ee821fa407a5b8da36 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Mon, 11 Apr 2016 10:41:07 +0300 Subject: These changes are the raw update to linux-4.4.6-rt14. Kernel sources are taken from kernel.org, and rt patch from the rt wiki download page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen --- kernel/drivers/gpu/drm/nouveau/Kbuild | 1 - kernel/drivers/gpu/drm/nouveau/dispnv04/arb.c | 2 +- kernel/drivers/gpu/drm/nouveau/dispnv04/dac.c | 45 +- kernel/drivers/gpu/drm/nouveau/dispnv04/dfp.c | 23 +- kernel/drivers/gpu/drm/nouveau/dispnv04/disp.c | 8 +- kernel/drivers/gpu/drm/nouveau/dispnv04/disp.h | 2 +- kernel/drivers/gpu/drm/nouveau/dispnv04/hw.c | 29 +- kernel/drivers/gpu/drm/nouveau/dispnv04/hw.h | 26 +- kernel/drivers/gpu/drm/nouveau/dispnv04/overlay.c | 15 +- .../drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c | 2 +- kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 16 +- kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 30 +- kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h | 6 +- .../drivers/gpu/drm/nouveau/include/nvif/class.h | 199 +- .../drivers/gpu/drm/nouveau/include/nvif/client.h | 27 +- .../drivers/gpu/drm/nouveau/include/nvif/device.h | 73 +- .../drivers/gpu/drm/nouveau/include/nvif/ioctl.h | 34 +- .../drivers/gpu/drm/nouveau/include/nvif/notify.h | 12 +- .../drivers/gpu/drm/nouveau/include/nvif/object.h | 70 +- kernel/drivers/gpu/drm/nouveau/include/nvif/os.h | 8 +- .../gpu/drm/nouveau/include/nvkm/core/client.h | 65 +- .../gpu/drm/nouveau/include/nvkm/core/debug.h | 9 +- .../gpu/drm/nouveau/include/nvkm/core/device.h | 273 +- .../gpu/drm/nouveau/include/nvkm/core/devidx.h | 62 - .../gpu/drm/nouveau/include/nvkm/core/engctx.h | 51 - .../gpu/drm/nouveau/include/nvkm/core/engine.h | 81 +- .../gpu/drm/nouveau/include/nvkm/core/enum.h | 3 +- .../gpu/drm/nouveau/include/nvkm/core/gpuobj.h | 62 +- .../gpu/drm/nouveau/include/nvkm/core/handle.h | 34 - .../gpu/drm/nouveau/include/nvkm/core/memory.h | 53 + .../drivers/gpu/drm/nouveau/include/nvkm/core/mm.h | 3 +- .../gpu/drm/nouveau/include/nvkm/core/namedb.h | 53 - .../gpu/drm/nouveau/include/nvkm/core/object.h | 261 +- .../gpu/drm/nouveau/include/nvkm/core/oproxy.h | 22 + .../gpu/drm/nouveau/include/nvkm/core/option.h | 1 + .../gpu/drm/nouveau/include/nvkm/core/parent.h | 58 - .../gpu/drm/nouveau/include/nvkm/core/pci.h | 14 + .../gpu/drm/nouveau/include/nvkm/core/printk.h | 29 - .../gpu/drm/nouveau/include/nvkm/core/ramht.h | 28 +- .../gpu/drm/nouveau/include/nvkm/core/subdev.h | 139 +- .../gpu/drm/nouveau/include/nvkm/core/tegra.h | 46 + .../gpu/drm/nouveau/include/nvkm/engine/bsp.h | 4 +- .../gpu/drm/nouveau/include/nvkm/engine/ce.h | 17 +- .../gpu/drm/nouveau/include/nvkm/engine/cipher.h | 2 +- .../gpu/drm/nouveau/include/nvkm/engine/device.h | 30 - .../gpu/drm/nouveau/include/nvkm/engine/disp.h | 39 +- .../gpu/drm/nouveau/include/nvkm/engine/dma.h | 32 + .../gpu/drm/nouveau/include/nvkm/engine/dmaobj.h | 26 - .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 75 +- .../gpu/drm/nouveau/include/nvkm/engine/fifo.h | 160 +- .../gpu/drm/nouveau/include/nvkm/engine/gr.h | 118 +- .../gpu/drm/nouveau/include/nvkm/engine/mpeg.h | 63 +- .../gpu/drm/nouveau/include/nvkm/engine/mspdec.h | 9 +- .../gpu/drm/nouveau/include/nvkm/engine/msppp.h | 7 +- .../gpu/drm/nouveau/include/nvkm/engine/msvld.h | 10 +- .../gpu/drm/nouveau/include/nvkm/engine/pm.h | 35 +- .../gpu/drm/nouveau/include/nvkm/engine/sec.h | 4 +- .../gpu/drm/nouveau/include/nvkm/engine/sw.h | 50 +- .../gpu/drm/nouveau/include/nvkm/engine/vp.h | 4 +- .../gpu/drm/nouveau/include/nvkm/engine/xtensa.h | 38 +- .../gpu/drm/nouveau/include/nvkm/subdev/bar.h | 29 +- .../gpu/drm/nouveau/include/nvkm/subdev/bios.h | 15 +- .../gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h | 10 +- .../drm/nouveau/include/nvkm/subdev/bios/gpio.h | 1 + .../drm/nouveau/include/nvkm/subdev/bios/init.h | 1 + .../gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h | 2 - .../drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 26 +- .../drm/nouveau/include/nvkm/subdev/bios/rammap.h | 4 + .../drm/nouveau/include/nvkm/subdev/bios/volt.h | 15 +- .../gpu/drm/nouveau/include/nvkm/subdev/bus.h | 45 +- .../gpu/drm/nouveau/include/nvkm/subdev/clk.h | 70 +- .../gpu/drm/nouveau/include/nvkm/subdev/devinit.h | 43 +- .../gpu/drm/nouveau/include/nvkm/subdev/fb.h | 139 +- .../gpu/drm/nouveau/include/nvkm/subdev/fuse.h | 26 +- .../gpu/drm/nouveau/include/nvkm/subdev/gpio.h | 31 +- .../gpu/drm/nouveau/include/nvkm/subdev/i2c.h | 151 +- .../gpu/drm/nouveau/include/nvkm/subdev/ibus.h | 31 +- .../gpu/drm/nouveau/include/nvkm/subdev/instmem.h | 55 +- .../gpu/drm/nouveau/include/nvkm/subdev/ltc.h | 41 +- .../gpu/drm/nouveau/include/nvkm/subdev/mc.h | 31 +- .../gpu/drm/nouveau/include/nvkm/subdev/mmu.h | 78 +- .../gpu/drm/nouveau/include/nvkm/subdev/mxm.h | 30 +- .../gpu/drm/nouveau/include/nvkm/subdev/pci.h | 37 + .../gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 31 +- .../gpu/drm/nouveau/include/nvkm/subdev/therm.h | 106 +- .../gpu/drm/nouveau/include/nvkm/subdev/timer.h | 95 +- .../gpu/drm/nouveau/include/nvkm/subdev/vga.h | 30 +- .../gpu/drm/nouveau/include/nvkm/subdev/volt.h | 49 +- kernel/drivers/gpu/drm/nouveau/nouveau_abi16.c | 299 +- kernel/drivers/gpu/drm/nouveau/nouveau_abi16.h | 8 +- kernel/drivers/gpu/drm/nouveau/nouveau_acpi.c | 7 +- kernel/drivers/gpu/drm/nouveau/nouveau_acpi.h | 4 +- kernel/drivers/gpu/drm/nouveau/nouveau_agp.c | 195 -- kernel/drivers/gpu/drm/nouveau/nouveau_agp.h | 10 - kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c | 22 +- kernel/drivers/gpu/drm/nouveau/nouveau_bios.c | 44 +- kernel/drivers/gpu/drm/nouveau/nouveau_bo.c | 92 +- kernel/drivers/gpu/drm/nouveau/nouveau_chan.c | 139 +- kernel/drivers/gpu/drm/nouveau/nouveau_chan.h | 5 +- kernel/drivers/gpu/drm/nouveau/nouveau_connector.c | 43 +- kernel/drivers/gpu/drm/nouveau/nouveau_display.c | 87 +- kernel/drivers/gpu/drm/nouveau/nouveau_display.h | 11 +- kernel/drivers/gpu/drm/nouveau/nouveau_dma.c | 10 +- kernel/drivers/gpu/drm/nouveau/nouveau_dma.h | 2 +- kernel/drivers/gpu/drm/nouveau/nouveau_dp.c | 17 +- kernel/drivers/gpu/drm/nouveau/nouveau_drm.c | 184 +- kernel/drivers/gpu/drm/nouveau/nouveau_drm.h | 47 +- kernel/drivers/gpu/drm/nouveau/nouveau_encoder.h | 4 +- kernel/drivers/gpu/drm/nouveau/nouveau_fbcon.c | 63 +- kernel/drivers/gpu/drm/nouveau/nouveau_fence.c | 15 +- kernel/drivers/gpu/drm/nouveau/nouveau_fence.h | 2 +- kernel/drivers/gpu/drm/nouveau/nouveau_gem.c | 74 +- kernel/drivers/gpu/drm/nouveau/nouveau_hwmon.c | 10 +- kernel/drivers/gpu/drm/nouveau/nouveau_nvif.c | 8 +- kernel/drivers/gpu/drm/nouveau/nouveau_platform.c | 224 +- kernel/drivers/gpu/drm/nouveau/nouveau_platform.h | 47 +- kernel/drivers/gpu/drm/nouveau/nouveau_sysfs.c | 9 +- kernel/drivers/gpu/drm/nouveau/nouveau_ttm.c | 109 +- kernel/drivers/gpu/drm/nouveau/nouveau_usif.c | 20 +- kernel/drivers/gpu/drm/nouveau/nouveau_vga.c | 9 +- kernel/drivers/gpu/drm/nouveau/nv04_fbcon.c | 12 +- kernel/drivers/gpu/drm/nouveau/nv04_fence.c | 6 +- kernel/drivers/gpu/drm/nouveau/nv10_fence.c | 2 +- kernel/drivers/gpu/drm/nouveau/nv17_fence.c | 4 +- kernel/drivers/gpu/drm/nouveau/nv50_display.c | 196 +- kernel/drivers/gpu/drm/nouveau/nv50_fbcon.c | 5 +- kernel/drivers/gpu/drm/nouveau/nv50_fence.c | 4 +- kernel/drivers/gpu/drm/nouveau/nv84_fence.c | 6 +- kernel/drivers/gpu/drm/nouveau/nvc0_fbcon.c | 4 +- kernel/drivers/gpu/drm/nouveau/nvif/client.c | 68 +- kernel/drivers/gpu/drm/nouveau/nvif/device.c | 55 +- kernel/drivers/gpu/drm/nouveau/nvif/notify.c | 49 +- kernel/drivers/gpu/drm/nouveau/nvif/object.c | 200 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/Kbuild | 7 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/client.c | 188 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/engctx.c | 239 -- kernel/drivers/gpu/drm/nouveau/nvkm/core/engine.c | 154 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/enum.c | 28 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c | 379 ++- kernel/drivers/gpu/drm/nouveau/nvkm/core/handle.c | 221 -- kernel/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c | 395 ++- kernel/drivers/gpu/drm/nouveau/nvkm/core/memory.c | 64 + kernel/drivers/gpu/drm/nouveau/nvkm/core/mm.c | 2 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/namedb.c | 199 -- kernel/drivers/gpu/drm/nouveau/nvkm/core/object.c | 400 ++- kernel/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c | 200 ++ kernel/drivers/gpu/drm/nouveau/nvkm/core/option.c | 20 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/parent.c | 159 -- kernel/drivers/gpu/drm/nouveau/nvkm/core/printk.c | 103 - kernel/drivers/gpu/drm/nouveau/nvkm/core/ramht.c | 144 +- kernel/drivers/gpu/drm/nouveau/nvkm/core/subdev.c | 208 +- kernel/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild | 2 +- .../drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c | 79 +- .../gpu/drm/nouveau/nvkm/engine/ce/fuc/com.fuc | 8 +- .../drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h | 4 +- .../drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h | 4 +- .../drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c | 180 +- .../drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c | 174 +- .../drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c | 167 +- .../drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c | 144 +- .../drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h | 7 + .../gpu/drm/nouveau/nvkm/engine/cipher/g84.c | 189 +- .../gpu/drm/nouveau/nvkm/engine/device/Kbuild | 12 +- .../gpu/drm/nouveau/nvkm/engine/device/acpi.c | 8 +- .../gpu/drm/nouveau/nvkm/engine/device/acpi.h | 4 +- .../gpu/drm/nouveau/nvkm/engine/device/base.c | 2926 ++++++++++++++++---- .../gpu/drm/nouveau/nvkm/engine/device/ctrl.c | 82 +- .../gpu/drm/nouveau/nvkm/engine/device/ctrl.h | 12 + .../gpu/drm/nouveau/nvkm/engine/device/gf100.c | 358 --- .../gpu/drm/nouveau/nvkm/engine/device/gk104.c | 326 --- .../gpu/drm/nouveau/nvkm/engine/device/gm100.c | 190 -- .../gpu/drm/nouveau/nvkm/engine/device/nv04.c | 89 - .../gpu/drm/nouveau/nvkm/engine/device/nv10.c | 204 -- .../gpu/drm/nouveau/nvkm/engine/device/nv20.c | 131 - .../gpu/drm/nouveau/nvkm/engine/device/nv30.c | 153 - .../gpu/drm/nouveau/nvkm/engine/device/nv40.c | 427 --- .../gpu/drm/nouveau/nvkm/engine/device/nv50.c | 478 ---- .../gpu/drm/nouveau/nvkm/engine/device/pci.c | 1678 +++++++++++ .../gpu/drm/nouveau/nvkm/engine/device/priv.h | 54 +- .../gpu/drm/nouveau/nvkm/engine/device/tegra.c | 320 +++ .../gpu/drm/nouveau/nvkm/engine/device/user.c | 371 +++ .../gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 86 +- .../gpu/drm/nouveau/nvkm/engine/disp/base.c | 325 ++- .../gpu/drm/nouveau/nvkm/engine/disp/baseg84.c | 80 + .../gpu/drm/nouveau/nvkm/engine/disp/basegf119.c | 114 + .../gpu/drm/nouveau/nvkm/engine/disp/basegk104.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/basegk110.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/basegt200.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/basegt215.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/basenv50.c | 123 + .../gpu/drm/nouveau/nvkm/engine/disp/changf119.c | 49 + .../gpu/drm/nouveau/nvkm/engine/disp/channv50.c | 301 ++ .../gpu/drm/nouveau/nvkm/engine/disp/channv50.h | 127 + .../gpu/drm/nouveau/nvkm/engine/disp/conn.c | 118 +- .../gpu/drm/nouveau/nvkm/engine/disp/conn.h | 61 +- .../gpu/drm/nouveau/nvkm/engine/disp/coreg84.c | 117 + .../gpu/drm/nouveau/nvkm/engine/disp/coreg94.c | 63 + .../gpu/drm/nouveau/nvkm/engine/disp/coregf119.c | 244 ++ .../gpu/drm/nouveau/nvkm/engine/disp/coregk104.c | 132 + .../gpu/drm/nouveau/nvkm/engine/disp/coregk110.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/coregm107.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/coregm204.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/coregt200.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/coregt215.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/corenv50.c | 242 ++ .../gpu/drm/nouveau/nvkm/engine/disp/cursg84.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c | 68 + .../gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c | 63 +- .../gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c | 100 + .../gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c | 247 ++ .../gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h | 91 + .../gpu/drm/nouveau/nvkm/engine/disp/dport.c | 96 +- .../gpu/drm/nouveau/nvkm/engine/disp/dport.h | 6 + .../drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c | 275 +- .../drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 139 +- .../gpu/drm/nouveau/nvkm/engine/disp/gf110.c | 1310 --------- .../gpu/drm/nouveau/nvkm/engine/disp/gf119.c | 536 ++++ .../gpu/drm/nouveau/nvkm/engine/disp/gk104.c | 265 +- .../gpu/drm/nouveau/nvkm/engine/disp/gk110.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/disp/gm107.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/disp/gm204.c | 109 +- .../gpu/drm/nouveau/nvkm/engine/disp/gt200.c | 147 +- .../gpu/drm/nouveau/nvkm/engine/disp/gt215.c | 105 +- .../gpu/drm/nouveau/nvkm/engine/disp/hdagf110.c | 73 - .../gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c | 83 + .../gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c | 30 +- .../gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c | 55 +- .../gpu/drm/nouveau/nvkm/engine/disp/hdmigf110.c | 79 - .../gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c | 80 + .../gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c | 41 +- .../gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c | 55 +- .../gpu/drm/nouveau/nvkm/engine/disp/nv04.c | 186 +- .../gpu/drm/nouveau/nvkm/engine/disp/nv50.c | 1667 ++--------- .../gpu/drm/nouveau/nvkm/engine/disp/nv50.h | 231 +- .../gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c | 37 + .../gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c | 68 + .../gpu/drm/nouveau/nvkm/engine/disp/outp.c | 127 +- .../gpu/drm/nouveau/nvkm/engine/disp/outp.h | 82 +- .../gpu/drm/nouveau/nvkm/engine/disp/outpdp.c | 202 +- .../gpu/drm/nouveau/nvkm/engine/disp/outpdp.h | 63 +- .../gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c | 77 + .../gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c | 101 + .../gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c | 103 + .../gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c | 80 + .../gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c | 38 + .../gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c | 111 + .../gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c | 81 + .../gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c | 83 + .../gpu/drm/nouveau/nvkm/engine/disp/piornv50.c | 165 +- .../gpu/drm/nouveau/nvkm/engine/disp/priv.h | 78 +- .../gpu/drm/nouveau/nvkm/engine/disp/rootg84.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootg94.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c | 171 ++ .../gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c | 58 + .../gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c | 139 + .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c | 399 +++ .../gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h | 43 + .../gpu/drm/nouveau/nvkm/engine/disp/sorg94.c | 95 +- .../gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c | 124 - .../gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c | 117 + .../gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c | 74 +- .../gpu/drm/nouveau/nvkm/engine/disp/sornv50.c | 37 +- .../drivers/gpu/drm/nouveau/nvkm/engine/disp/vga.c | 138 +- .../drivers/gpu/drm/nouveau/nvkm/engine/dma/Kbuild | 11 + .../drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c | 157 ++ .../gpu/drm/nouveau/nvkm/engine/dma/gf100.c | 36 + .../gpu/drm/nouveau/nvkm/engine/dma/gf119.c | 36 + .../drivers/gpu/drm/nouveau/nvkm/engine/dma/nv04.c | 36 + .../drivers/gpu/drm/nouveau/nvkm/engine/dma/nv50.c | 36 + .../drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h | 18 + .../drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c | 144 + .../drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h | 18 + .../gpu/drm/nouveau/nvkm/engine/dma/usergf100.c | 149 + .../gpu/drm/nouveau/nvkm/engine/dma/usergf119.c | 131 + .../gpu/drm/nouveau/nvkm/engine/dma/usernv04.c | 133 + .../gpu/drm/nouveau/nvkm/engine/dma/usernv50.c | 156 ++ .../gpu/drm/nouveau/nvkm/engine/dmaobj/Kbuild | 5 - .../gpu/drm/nouveau/nvkm/engine/dmaobj/base.c | 164 -- .../gpu/drm/nouveau/nvkm/engine/dmaobj/gf100.c | 176 -- .../gpu/drm/nouveau/nvkm/engine/dmaobj/gf110.c | 165 -- .../gpu/drm/nouveau/nvkm/engine/dmaobj/nv04.c | 163 -- .../gpu/drm/nouveau/nvkm/engine/dmaobj/nv50.c | 195 -- .../gpu/drm/nouveau/nvkm/engine/dmaobj/priv.h | 28 - .../drivers/gpu/drm/nouveau/nvkm/engine/falcon.c | 292 +- .../gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 20 +- .../gpu/drm/nouveau/nvkm/engine/fifo/base.c | 345 ++- .../gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 415 +++ .../gpu/drm/nouveau/nvkm/engine/fifo/chan.h | 33 + .../gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 285 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/changf100.h | 24 + .../gpu/drm/nouveau/nvkm/engine/fifo/changk104.h | 29 + .../gpu/drm/nouveau/nvkm/engine/fifo/channv04.h | 24 + .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.c | 270 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/channv50.h | 35 + .../gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c | 93 + .../gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | 220 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c | 96 + .../gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c | 97 + .../gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c | 243 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c | 91 + .../drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c | 481 +--- .../gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 924 ++----- .../gpu/drm/nouveau/nvkm/engine/fifo/gf100.h | 31 + .../gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 1037 +++---- .../gpu/drm/nouveau/nvkm/engine/fifo/gk104.h | 89 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gk208.c | 30 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c | 30 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gm204.c | 45 +- .../gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c | 44 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c | 94 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c | 293 ++ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 323 +++ .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c | 34 + .../gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c | 92 + .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 638 ++--- .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.h | 170 +- .../gpu/drm/nouveau/nvkm/engine/fifo/nv10.c | 153 +- .../gpu/drm/nouveau/nvkm/engine/fifo/nv17.c | 208 +- .../gpu/drm/nouveau/nvkm/engine/fifo/nv40.c | 335 +-- .../gpu/drm/nouveau/nvkm/engine/fifo/nv50.c | 533 +--- .../gpu/drm/nouveau/nvkm/engine/fifo/nv50.h | 39 +- .../gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 26 + .../gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h | 132 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild | 48 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c | 136 + .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 327 +-- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 80 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c | 52 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c | 90 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c | 143 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c | 80 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c | 135 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c | 119 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c | 15 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c | 103 + .../gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.c | 13 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h | 9 +- .../gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c | 25 +- .../gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc | 8 +- .../drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h | 344 +-- .../drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h | 344 +-- .../drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h | 344 +-- .../drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h | 308 +-- .../drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h | 474 ++-- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.c | 196 ++ .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 1580 ++++++----- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 128 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c | 32 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c | 45 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c | 48 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | 35 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c | 35 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 227 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 43 +- .../gpu/drm/nouveau/nvkm/engine/gr/gk110b.c | 32 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c | 43 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 349 ++- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c | 215 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c | 223 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c | 32 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c | 83 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gt200.c | 47 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/gt215.c | 48 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp79.c | 46 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp89.c | 48 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c | 1213 ++++---- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c | 824 +++--- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h | 13 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv15.c | 59 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv17.c | 59 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c | 567 ++-- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h | 37 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c | 220 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c | 180 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c | 331 +-- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c | 218 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c | 218 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c | 591 ++-- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h | 37 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv44.c | 108 + .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c | 877 +++--- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h | 32 +- .../drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h | 38 + .../drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c | 84 +- .../gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c | 406 ++- .../gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h | 27 +- .../gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c | 107 +- .../gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c | 248 +- .../gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c | 228 +- .../gpu/drm/nouveau/nvkm/engine/mpeg/priv.h | 16 + .../gpu/drm/nouveau/nvkm/engine/mspdec/Kbuild | 2 + .../gpu/drm/nouveau/nvkm/engine/mspdec/base.c | 32 + .../gpu/drm/nouveau/nvkm/engine/mspdec/g98.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c | 98 +- .../gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c | 43 + .../gpu/drm/nouveau/nvkm/engine/mspdec/priv.h | 11 + .../gpu/drm/nouveau/nvkm/engine/msppp/Kbuild | 2 + .../gpu/drm/nouveau/nvkm/engine/msppp/base.c | 31 + .../gpu/drm/nouveau/nvkm/engine/msppp/g98.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/msppp/gf100.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/msppp/gt215.c | 43 + .../gpu/drm/nouveau/nvkm/engine/msppp/priv.h | 9 + .../gpu/drm/nouveau/nvkm/engine/msvld/Kbuild | 3 + .../gpu/drm/nouveau/nvkm/engine/msvld/base.c | 31 + .../gpu/drm/nouveau/nvkm/engine/msvld/g98.c | 101 +- .../gpu/drm/nouveau/nvkm/engine/msvld/gf100.c | 100 +- .../gpu/drm/nouveau/nvkm/engine/msvld/gk104.c | 98 +- .../gpu/drm/nouveau/nvkm/engine/msvld/gt215.c | 43 + .../gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c | 43 + .../gpu/drm/nouveau/nvkm/engine/msvld/priv.h | 11 + .../drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild | 5 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | 909 ++++-- .../gpu/drm/nouveau/nvkm/engine/pm/daemon.c | 108 - .../drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c | 126 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c | 214 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h | 16 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c | 66 + .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c | 80 + .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c | 154 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c | 57 - .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c | 157 ++ .../drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c | 113 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c | 97 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h | 18 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c | 152 +- .../drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h | 87 +- .../gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s | 6 +- .../drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h | 4 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c | 138 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild | 5 + .../drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c | 110 + .../drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c | 111 + .../drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h | 26 + .../drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c | 188 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c | 151 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c | 106 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c | 224 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h | 35 +- .../drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c | 85 + .../drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h | 21 + .../drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h | 21 + .../drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c | 79 +- .../drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c | 192 +- kernel/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild | 1 + .../drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild | 1 + .../drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c | 133 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c | 56 + .../gpu/drm/nouveau/nvkm/subdev/bar/gf100.c | 205 +- .../gpu/drm/nouveau/nvkm/subdev/bar/gf100.h | 23 + .../gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c | 40 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c | 287 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h | 26 + .../drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h | 33 +- .../gpu/drm/nouveau/nvkm/subdev/bios/M0203.c | 25 +- .../gpu/drm/nouveau/nvkm/subdev/bios/M0205.c | 20 +- .../gpu/drm/nouveau/nvkm/subdev/bios/M0209.c | 26 +- .../gpu/drm/nouveau/nvkm/subdev/bios/P0260.c | 14 +- .../gpu/drm/nouveau/nvkm/subdev/bios/base.c | 147 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/bit.c | 14 +- .../gpu/drm/nouveau/nvkm/subdev/bios/boost.c | 28 +- .../gpu/drm/nouveau/nvkm/subdev/bios/conn.c | 30 +- .../gpu/drm/nouveau/nvkm/subdev/bios/cstep.c | 26 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c | 72 +- .../gpu/drm/nouveau/nvkm/subdev/bios/disp.c | 36 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c | 81 +- .../gpu/drm/nouveau/nvkm/subdev/bios/extdev.c | 16 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c | 19 +- .../gpu/drm/nouveau/nvkm/subdev/bios/gpio.c | 30 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c | 57 +- .../gpu/drm/nouveau/nvkm/subdev/bios/image.c | 7 +- .../gpu/drm/nouveau/nvkm/subdev/bios/init.c | 624 +++-- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c | 33 +- .../gpu/drm/nouveau/nvkm/subdev/bios/npde.c | 11 +- .../gpu/drm/nouveau/nvkm/subdev/bios/pcir.c | 31 +- .../gpu/drm/nouveau/nvkm/subdev/bios/perf.c | 92 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c | 174 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c | 47 +- .../gpu/drm/nouveau/nvkm/subdev/bios/priv.h | 4 + .../gpu/drm/nouveau/nvkm/subdev/bios/ramcfg.c | 14 +- .../gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 189 +- .../gpu/drm/nouveau/nvkm/subdev/bios/shadow.c | 133 +- .../gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c | 8 +- .../gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c | 18 +- .../gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c | 18 +- .../gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c | 36 +- .../gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c | 26 +- .../gpu/drm/nouveau/nvkm/subdev/bios/therm.c | 38 +- .../gpu/drm/nouveau/nvkm/subdev/bios/timing.c | 98 +- .../gpu/drm/nouveau/nvkm/subdev/bios/vmap.c | 40 +- .../gpu/drm/nouveau/nvkm/subdev/bios/volt.c | 65 +- .../gpu/drm/nouveau/nvkm/subdev/bios/xpio.c | 26 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/Kbuild | 1 + .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c | 64 + .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/g94.c | 46 +- .../gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 71 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c | 64 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h | 12 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c | 78 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.h | 21 - .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 81 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 93 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h | 18 + .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild | 1 + .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 176 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c | 41 +- .../gpu/drm/nouveau/nvkm/subdev/clk/gf100.c | 318 +-- .../gpu/drm/nouveau/nvkm/subdev/clk/gk104.c | 326 +-- .../gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c | 356 ++- .../gpu/drm/nouveau/nvkm/subdev/clk/gt215.c | 347 +-- .../gpu/drm/nouveau/nvkm/subdev/clk/gt215.h | 6 +- .../gpu/drm/nouveau/nvkm/subdev/clk/mcp77.c | 282 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c | 56 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c | 173 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c | 294 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h | 24 +- .../gpu/drm/nouveau/nvkm/subdev/clk/pllgt215.c | 2 +- .../gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c | 6 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h | 26 + .../gpu/drm/nouveau/nvkm/subdev/devinit/base.c | 128 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/fbmem.h | 5 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/g84.c | 46 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/g98.c | 44 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c | 82 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c | 38 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/gm204.c | 125 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c | 77 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c | 44 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c | 242 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h | 18 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv05.c | 71 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv10.c | 44 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv1a.c | 24 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv20.c | 44 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c | 151 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h | 15 +- .../gpu/drm/nouveau/nvkm/subdev/devinit/priv.h | 33 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild | 2 + .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 197 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c | 23 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 26 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c | 5 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c | 121 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h | 25 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c | 27 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c | 55 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c | 27 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c | 23 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp77.c | 23 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp89.c | 23 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c | 60 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.h | 53 - .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c | 41 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c | 26 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c | 53 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c | 32 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c | 77 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c | 33 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c | 33 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c | 47 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.h | 14 - .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c | 54 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c | 57 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c | 29 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c | 27 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c | 27 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c | 27 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c | 351 ++- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h | 24 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 107 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c | 100 + .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h | 50 + .../gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h | 25 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 342 ++- .../gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 396 +-- .../gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c | 37 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | 403 ++- .../gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c | 104 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c | 54 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c | 39 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c | 38 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c | 47 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c | 176 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h | 14 + .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c | 51 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c | 50 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c | 51 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c | 35 +- .../gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 608 ++-- .../gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h | 1 + .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c | 8 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c | 8 +- .../gpu/drm/nouveau/nvkm/subdev/fuse/base.c | 37 +- .../gpu/drm/nouveau/nvkm/subdev/fuse/gf100.c | 57 +- .../gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c | 40 +- .../gpu/drm/nouveau/nvkm/subdev/fuse/nv50.c | 53 +- .../gpu/drm/nouveau/nvkm/subdev/fuse/priv.h | 9 +- .../gpu/drm/nouveau/nvkm/subdev/gpio/Kbuild | 2 +- .../gpu/drm/nouveau/nvkm/subdev/gpio/base.c | 147 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/gpio/g94.c | 41 +- .../gpu/drm/nouveau/nvkm/subdev/gpio/gf110.c | 84 - .../gpu/drm/nouveau/nvkm/subdev/gpio/gf119.c | 86 + .../gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c | 47 +- .../gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c | 41 +- .../gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c | 48 +- .../gpu/drm/nouveau/nvkm/subdev/gpio/priv.h | 37 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild | 30 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c | 374 ++- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c | 151 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h | 30 + .../gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c | 181 ++ .../gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c | 181 ++ .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 742 ++--- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c | 149 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c | 245 ++ .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h | 37 + .../gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c | 95 + .../gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c | 96 + .../gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c | 86 + .../gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c | 113 + .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c | 241 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c | 106 - .../gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c | 26 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/gf119.c | 40 + .../gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c | 39 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c | 199 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c | 104 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c | 96 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c | 109 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h | 32 - .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c | 119 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h | 107 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c | 87 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c | 51 + .../gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c | 87 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c | 18 +- .../gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c | 36 + .../gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c | 36 + .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h | 13 - .../drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h | 67 +- .../gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c | 110 +- .../gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c | 51 + .../gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c | 124 +- .../gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c | 97 +- .../gpu/drm/nouveau/nvkm/subdev/ibus/priv.h | 7 + .../gpu/drm/nouveau/nvkm/subdev/instmem/base.c | 306 +- .../gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c | 647 +++-- .../gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c | 240 +- .../gpu/drm/nouveau/nvkm/subdev/instmem/nv04.h | 36 - .../gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c | 247 +- .../gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c | 266 +- .../gpu/drm/nouveau/nvkm/subdev/instmem/priv.h | 60 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c | 138 +- .../gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c | 212 +- .../gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c | 45 +- .../gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c | 148 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h | 81 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild | 4 - .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c | 178 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c | 37 - .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c | 58 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c | 97 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c | 38 - .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c | 26 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c | 85 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.h | 20 - .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c | 44 - .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c | 46 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c | 36 - .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c | 66 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h | 46 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c | 234 +- .../gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c | 138 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c | 128 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h | 15 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c | 136 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c | 195 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c | 174 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h | 39 + .../drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c | 80 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c | 28 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h | 2 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c | 47 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h | 15 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild | 9 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c | 175 ++ .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h | 18 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c | 193 ++ .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c | 64 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c | 39 + .../gpu/drm/nouveau/nvkm/subdev/pci/gf100.c | 45 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv04.c | 58 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c | 65 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c | 51 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv4c.c | 37 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h | 25 + .../drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild | 3 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 230 +- .../gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4 | 70 - .../drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4.h | 1795 ------------ .../gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4 | 70 + .../drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h | 1795 ++++++++++++ .../gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c | 19 +- .../gpu/drm/nouveau/nvkm/subdev/pmu/gf110.c | 40 - .../gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c | 39 + .../gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c | 104 +- .../gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c | 59 +- .../gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c | 19 +- .../gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c | 149 +- .../gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c | 41 + .../gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 31 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c | 69 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 30 +- .../gpu/drm/nouveau/nvkm/subdev/therm/Kbuild | 2 +- .../gpu/drm/nouveau/nvkm/subdev/therm/base.c | 305 +- .../gpu/drm/nouveau/nvkm/subdev/therm/fan.c | 117 +- .../gpu/drm/nouveau/nvkm/subdev/therm/fannil.c | 3 +- .../gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c | 67 +- .../gpu/drm/nouveau/nvkm/subdev/therm/fantog.c | 80 +- .../gpu/drm/nouveau/nvkm/subdev/therm/g84.c | 190 +- .../gpu/drm/nouveau/nvkm/subdev/therm/gf110.c | 174 -- .../gpu/drm/nouveau/nvkm/subdev/therm/gf119.c | 153 + .../gpu/drm/nouveau/nvkm/subdev/therm/gm107.c | 66 +- .../gpu/drm/nouveau/nvkm/subdev/therm/gt215.c | 85 +- .../drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c | 51 +- .../gpu/drm/nouveau/nvkm/subdev/therm/nv40.c | 129 +- .../gpu/drm/nouveau/nvkm/subdev/therm/nv50.c | 106 +- .../gpu/drm/nouveau/nvkm/subdev/therm/priv.h | 86 +- .../gpu/drm/nouveau/nvkm/subdev/therm/temp.c | 122 +- .../gpu/drm/nouveau/nvkm/subdev/timer/Kbuild | 2 + .../gpu/drm/nouveau/nvkm/subdev/timer/base.c | 158 +- .../gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c | 43 +- .../gpu/drm/nouveau/nvkm/subdev/timer/nv04.c | 253 +- .../gpu/drm/nouveau/nvkm/subdev/timer/nv04.h | 25 - .../gpu/drm/nouveau/nvkm/subdev/timer/nv40.c | 88 + .../gpu/drm/nouveau/nvkm/subdev/timer/nv41.c | 85 + .../gpu/drm/nouveau/nvkm/subdev/timer/priv.h | 22 + .../gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h | 7 + .../gpu/drm/nouveau/nvkm/subdev/volt/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/subdev/volt/base.c | 137 +- .../gpu/drm/nouveau/nvkm/subdev/volt/gk104.c | 119 + .../gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c | 123 +- .../gpu/drm/nouveau/nvkm/subdev/volt/gpio.c | 15 +- .../gpu/drm/nouveau/nvkm/subdev/volt/nv40.c | 33 +- .../gpu/drm/nouveau/nvkm/subdev/volt/priv.h | 26 + 763 files changed, 47747 insertions(+), 41457 deletions(-) delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/devidx.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engctx.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h create mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h create mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h create mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/printk.h create mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/device.h create mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dmaobj.h create mode 100644 kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nouveau_agp.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nouveau_agp.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/engctx.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/handle.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/memory.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/namedb.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/parent.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/core/printk.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gf100.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv04.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv10.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv20.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv30.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/Kbuild create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf100.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv04.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/Kbuild delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/base.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf100.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf110.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv04.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv50.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt200.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp79.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp89.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv15.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv17.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv44.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/daemon.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf119.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv04.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv4c.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4 delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4 create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c delete mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv40.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv41.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h (limited to 'kernel/drivers/gpu/drm/nouveau') diff --git a/kernel/drivers/gpu/drm/nouveau/Kbuild b/kernel/drivers/gpu/drm/nouveau/Kbuild index 2b765663c..a34b437db 100644 --- a/kernel/drivers/gpu/drm/nouveau/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/Kbuild @@ -18,7 +18,6 @@ nouveau-y += $(nvkm-y) ifdef CONFIG_X86 nouveau-$(CONFIG_ACPI) += nouveau_acpi.o endif -nouveau-y += nouveau_agp.o nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o nouveau-y += nouveau_drm.o nouveau-y += nouveau_hwmon.o diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/arb.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/arb.c index c6361422a..82bd4658a 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/arb.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/arb.c @@ -198,7 +198,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, int *burst, int *lwm) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; struct nv_fifo_info fifo_data; struct nv_sim_state sim_data; int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY); diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/dac.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/dac.c index af7249ca0..78cb033bc 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/dac.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -65,8 +65,8 @@ int nv04_dac_output_offset(struct drm_encoder *encoder) static int sample_load_twice(struct drm_device *dev, bool sense[2]) { - struct nvif_device *device = &nouveau_drm(dev)->device; - struct nvkm_timer *ptimer = nvxx_timer(device); + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvif_object *device = &drm->device.object; int i; for (i = 0; i < 2; i++) { @@ -80,17 +80,22 @@ static int sample_load_twice(struct drm_device *dev, bool sense[2]) * use a 10ms timeout (guards against crtc being inactive, in * which case blank state would never change) */ - if (!nvkm_timer_wait_eq(ptimer, 10000000, - NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000000)) + if (nvif_msec(&drm->device, 10, + if (!(nvif_rd32(device, NV_PRMCIO_INP0__COLOR) & 1)) + break; + ) < 0) return -EBUSY; - if (!nvkm_timer_wait_eq(ptimer, 10000000, - NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000001)) + + if (nvif_msec(&drm->device, 10, + if ( (nvif_rd32(device, NV_PRMCIO_INP0__COLOR) & 1)) + break; + ) < 0) return -EBUSY; - if (!nvkm_timer_wait_eq(ptimer, 10000000, - NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000000)) + + if (nvif_msec(&drm->device, 10, + if (!(nvif_rd32(device, NV_PRMCIO_INP0__COLOR) & 1)) + break; + ) < 0) return -EBUSY; udelay(100); @@ -128,7 +133,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; struct nouveau_drm *drm = nouveau_drm(dev); uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode; uint8_t saved_palette0[3], saved_palette_mask; @@ -231,8 +236,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &nouveau_drm(dev)->device; - struct nvkm_gpio *gpio = nvxx_gpio(device); + struct nvif_object *device = &nouveau_drm(dev)->device.object; + struct nvkm_gpio *gpio = nvxx_gpio(&drm->device); struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, @@ -265,10 +270,10 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) } if (gpio) { - saved_gpio1 = gpio->get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); - saved_gpio0 = gpio->get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); - gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, dcb->type == DCB_OUTPUT_TV); - gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, dcb->type == DCB_OUTPUT_TV); + saved_gpio1 = nvkm_gpio_get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); + saved_gpio0 = nvkm_gpio_get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, dcb->type == DCB_OUTPUT_TV); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, dcb->type == DCB_OUTPUT_TV); } msleep(4); @@ -320,8 +325,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) nvif_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); if (gpio) { - gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, saved_gpio1); - gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, saved_gpio0); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, saved_gpio1); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, saved_gpio0); } return sample; diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 7cfb0cbc9..429ab5e30 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -281,7 +281,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; @@ -485,7 +485,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) { #ifdef __powerpc__ struct drm_device *dev = encoder->dev; - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; /* BIOS scripts usually take care of the backlight, thanks * Apple for your consistency. @@ -493,11 +493,11 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) if (dev->pdev->device == 0x0174 || dev->pdev->device == 0x0179 || dev->pdev->device == 0x0189 || dev->pdev->device == 0x0329) { if (mode == DRM_MODE_DPMS_ON) { - nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 1 << 31); - nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1); + nvif_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 1 << 31); + nvif_mask(device, NV_PCRTC_GPIO_EXT, 3, 1); } else { - nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); - nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 0); + nvif_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); + nvif_mask(device, NV_PCRTC_GPIO_EXT, 3, 0); } } #endif @@ -624,8 +624,8 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->device); - struct nvkm_i2c_port *port = i2c->find(i2c, 2); - struct nvkm_i2c_board_info info[] = { + struct nvkm_i2c_bus *bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI); + struct nvkm_i2c_bus_probe info[] = { { { .type = "sil164", @@ -639,16 +639,15 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) }; int type; - if (!nv_gf4_disp_arch(dev) || !port || - get_tmds_slave(encoder)) + if (!nv_gf4_disp_arch(dev) || !bus || get_tmds_slave(encoder)) return; - type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL); + type = nvkm_i2c_bus_probe(bus, "TMDS transmitter", info, NULL, NULL); if (type < 0) return; drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - &port->adapter, &info[type].dev); + &bus->i2c, &info[type].dev); } static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.c index 4131be550..9e650081c 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -47,7 +47,7 @@ nv04_display_create(struct drm_device *dev) if (!disp) return -ENOMEM; - nvif_object_map(nvif_object(&drm->device)); + nvif_object_map(&drm->device.object); nouveau_display(dev)->priv = disp; nouveau_display(dev)->dtor = nv04_display_destroy; @@ -101,7 +101,9 @@ nv04_display_create(struct drm_device *dev) list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - nv_encoder->i2c = i2c->find(i2c, nv_encoder->dcb->i2c_index); + struct nvkm_i2c_bus *bus = + nvkm_i2c_bus_find(i2c, nv_encoder->dcb->i2c_index); + nv_encoder->i2c = bus ? &bus->i2c : NULL; } /* Save previous state */ @@ -151,7 +153,7 @@ nv04_display_destroy(struct drm_device *dev) nouveau_display(dev)->priv = NULL; kfree(disp); - nvif_object_unmap(nvif_object(&drm->device)); + nvif_object_unmap(&drm->device.object); } int diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.h b/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.h index c910c5d5c..6c9a1e898 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -172,7 +172,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, u16 table, struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_bios *bios = nvxx_bios(&drm->device); struct nvbios_init init = { - .subdev = nv_subdev(bios), + .subdev = &bios->subdev, .bios = bios, .offset = table, .outp = outp, diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.c index 42e07afc4..956a833b8 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.c @@ -165,8 +165,8 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, struct nvkm_pll_vals *pllvals) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->device; - struct nvkm_bios *bios = nvxx_bios(device); + struct nvif_object *device = &drm->device.object; + struct nvkm_bios *bios = nvxx_bios(&drm->device); uint32_t reg1, pll1, pll2 = 0; struct nvbios_pll pll_lim; int ret; @@ -660,8 +660,7 @@ nv_load_state_ext(struct drm_device *dev, int head, struct nv04_mode_state *state) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->device; - struct nvkm_timer *ptimer = nvxx_timer(device); + struct nvif_object *device = &drm->device.object; struct nv04_crtc_reg *regp = &state->crtc_reg[head]; uint32_t reg900; int i; @@ -678,10 +677,10 @@ nv_load_state_ext(struct drm_device *dev, int head, nvif_wr32(device, NV_PVIDEO_INTR_EN, 0); nvif_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0); nvif_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0); - nvif_wr32(device, NV_PVIDEO_LIMIT(0), device->info.ram_size - 1); - nvif_wr32(device, NV_PVIDEO_LIMIT(1), device->info.ram_size - 1); - nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), device->info.ram_size - 1); - nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), device->info.ram_size - 1); + nvif_wr32(device, NV_PVIDEO_LIMIT(0), drm->device.info.ram_size - 1); + nvif_wr32(device, NV_PVIDEO_LIMIT(1), drm->device.info.ram_size - 1); + nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), drm->device.info.ram_size - 1); + nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), drm->device.info.ram_size - 1); nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0); NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); @@ -741,8 +740,14 @@ nv_load_state_ext(struct drm_device *dev, int head, if (drm->device.info.family < NV_DEVICE_INFO_V0_KELVIN) { /* Not waiting for vertical retrace before modifying CRE_53/CRE_54 causes lockups. */ - nvkm_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); - nvkm_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); + nvif_msec(&drm->device, 650, + if ( (nvif_rd32(device, NV_PRMCIO_INP0__COLOR) & 8)) + break; + ); + nvif_msec(&drm->device, 650, + if (!(nvif_rd32(device, NV_PRMCIO_INP0__COLOR) & 8)) + break; + ); } wr_cio_state(dev, head, regp, NV_CIO_CRE_42); @@ -765,7 +770,7 @@ static void nv_save_state_palette(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; int head_offset = head * NV_PRMDIO_SIZE, i; nvif_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset, @@ -784,7 +789,7 @@ void nouveau_hw_load_state_palette(struct drm_device *dev, int head, struct nv04_mode_state *state) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; int head_offset = head * NV_PRMDIO_SIZE, i; nvif_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset, diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.h b/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.h index 6c796178b..3bded60c5 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.h +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/hw.h @@ -60,7 +60,7 @@ extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, static inline uint32_t NVReadCRTC(struct drm_device *dev, int head, uint32_t reg) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; uint32_t val; if (head) reg += NV_PCRTC0_SIZE; @@ -71,7 +71,7 @@ static inline uint32_t NVReadCRTC(struct drm_device *dev, static inline void NVWriteCRTC(struct drm_device *dev, int head, uint32_t reg, uint32_t val) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; if (head) reg += NV_PCRTC0_SIZE; nvif_wr32(device, reg, val); @@ -80,7 +80,7 @@ static inline void NVWriteCRTC(struct drm_device *dev, static inline uint32_t NVReadRAMDAC(struct drm_device *dev, int head, uint32_t reg) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; uint32_t val; if (head) reg += NV_PRAMDAC0_SIZE; @@ -91,7 +91,7 @@ static inline uint32_t NVReadRAMDAC(struct drm_device *dev, static inline void NVWriteRAMDAC(struct drm_device *dev, int head, uint32_t reg, uint32_t val) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; if (head) reg += NV_PRAMDAC0_SIZE; nvif_wr32(device, reg, val); @@ -120,7 +120,7 @@ static inline void nv_write_tmds(struct drm_device *dev, static inline void NVWriteVgaCrtc(struct drm_device *dev, int head, uint8_t index, uint8_t value) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); nvif_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); } @@ -128,7 +128,7 @@ static inline void NVWriteVgaCrtc(struct drm_device *dev, static inline uint8_t NVReadVgaCrtc(struct drm_device *dev, int head, uint8_t index) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; uint8_t val; nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); val = nvif_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); @@ -165,7 +165,7 @@ static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_ static inline uint8_t NVReadPRMVIO(struct drm_device *dev, int head, uint32_t reg) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; struct nouveau_drm *drm = nouveau_drm(dev); uint8_t val; @@ -181,7 +181,7 @@ static inline uint8_t NVReadPRMVIO(struct drm_device *dev, static inline void NVWritePRMVIO(struct drm_device *dev, int head, uint32_t reg, uint8_t value) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; struct nouveau_drm *drm = nouveau_drm(dev); /* Only NV4x have two pvio ranges; other twoHeads cards MUST call @@ -194,14 +194,14 @@ static inline void NVWritePRMVIO(struct drm_device *dev, static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); } static inline bool NVGetEnablePalette(struct drm_device *dev, int head) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); return !(nvif_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); } @@ -209,7 +209,7 @@ static inline bool NVGetEnablePalette(struct drm_device *dev, int head) static inline void NVWriteVgaAttr(struct drm_device *dev, int head, uint8_t index, uint8_t value) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; if (NVGetEnablePalette(dev, head)) index &= ~0x20; else @@ -223,7 +223,7 @@ static inline void NVWriteVgaAttr(struct drm_device *dev, static inline uint8_t NVReadVgaAttr(struct drm_device *dev, int head, uint8_t index) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; uint8_t val; if (NVGetEnablePalette(dev, head)) index &= ~0x20; @@ -259,7 +259,7 @@ static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect) static inline bool nv_heads_tied(struct drm_device *dev) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nvif_object *device = &nouveau_drm(dev)->device.object; struct nouveau_drm *drm = nouveau_drm(dev); if (drm->device.info.chipset == 0x11) diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 9f2498571..aeebdd402 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -96,7 +96,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct nvif_device *dev = &nouveau_drm(plane->dev)->device; + struct nouveau_drm *drm = nouveau_drm(plane->dev); + struct nvif_object *dev = &drm->device.object; struct nouveau_plane *nv_plane = container_of(plane, struct nouveau_plane, base); struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); @@ -118,7 +119,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (format > 0xffff) return -ERANGE; - if (dev->info.chipset >= 0x30) { + if (drm->device.info.chipset >= 0x30) { if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1)) return -ERANGE; } else { @@ -173,7 +174,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, static int nv10_disable_plane(struct drm_plane *plane) { - struct nvif_device *dev = &nouveau_drm(plane->dev)->device; + struct nvif_object *dev = &nouveau_drm(plane->dev)->device.object; struct nouveau_plane *nv_plane = container_of(plane, struct nouveau_plane, base); @@ -197,7 +198,7 @@ nv_destroy_plane(struct drm_plane *plane) static void nv10_set_params(struct nouveau_plane *plane) { - struct nvif_device *dev = &nouveau_drm(plane->base.dev)->device; + struct nvif_object *dev = &nouveau_drm(plane->base.dev)->device.object; u32 luma = (plane->brightness - 512) << 16 | plane->contrast; u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) | (cos_mul(plane->hue, plane->saturation) & 0xffff); @@ -261,7 +262,7 @@ nv10_overlay_init(struct drm_device *device) { struct nouveau_drm *drm = nouveau_drm(device); struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); - int num_formats = ARRAY_SIZE(formats); + unsigned int num_formats = ARRAY_SIZE(formats); int ret; if (!plane) @@ -346,7 +347,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct nvif_device *dev = &nouveau_drm(plane->dev)->device; + struct nvif_object *dev = &nouveau_drm(plane->dev)->device.object; struct nouveau_plane *nv_plane = container_of(plane, struct nouveau_plane, base); struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); @@ -426,7 +427,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, static int nv04_disable_plane(struct drm_plane *plane) { - struct nvif_device *dev = &nouveau_drm(plane->dev)->device; + struct nvif_object *dev = &nouveau_drm(plane->dev)->device.object; struct nouveau_plane *nv_plane = container_of(plane, struct nouveau_plane, base); diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c index 08c6f5e50..903c473d2 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c @@ -32,7 +32,7 @@ #include "hw.h" #include "tvnv17.h" -char *nv17_tv_norm_names[NUM_TV_NORMS] = { +const char * const nv17_tv_norm_names[NUM_TV_NORMS] = { [TV_NORM_PAL] = "PAL", [TV_NORM_PAL_M] = "PAL-M", [TV_NORM_PAL_N] = "PAL-N", diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index 70e95cf6f..5345eb537 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -35,7 +35,7 @@ #include -static struct nvkm_i2c_board_info nv04_tv_encoder_info[] = { +static struct nvkm_i2c_bus_probe nv04_tv_encoder_info[] = { { { I2C_BOARD_INFO("ch7006", 0x75), @@ -55,9 +55,13 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->device); - - return i2c->identify(i2c, i2c_index, "TV encoder", - nv04_tv_encoder_info, NULL, NULL); + struct nvkm_i2c_bus *bus = nvkm_i2c_bus_find(i2c, i2c_index); + if (bus) { + return nvkm_i2c_bus_probe(bus, "TV encoder", + nv04_tv_encoder_info, + NULL, NULL); + } + return -ENODEV; } @@ -205,7 +209,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) struct drm_device *dev = connector->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->device); - struct nvkm_i2c_port *port = i2c->find(i2c, entry->i2c_index); + struct nvkm_i2c_bus *bus = nvkm_i2c_bus_find(i2c, entry->i2c_index); int type, ret; /* Ensure that we can talk to this encoder */ @@ -231,7 +235,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) /* Run the slave-specific initialization */ ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), - &port->adapter, + &bus->i2c, &nv04_tv_encoder_info[type].dev); if (ret < 0) goto fail_cleanup; diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index d9720dda8..b734195d8 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -62,8 +62,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) head = (dacclk & 0x100) >> 8; /* Save the previous state. */ - gpio1 = gpio->get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); - gpio0 = gpio->get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); + gpio1 = nvkm_gpio_get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); + gpio0 = nvkm_gpio_get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); @@ -74,8 +74,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); /* Prepare the DAC for load detection. */ - gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, true); - gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, true); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, true); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, true); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); @@ -120,8 +120,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); - gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, gpio1); - gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, gpio0); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, gpio1); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, gpio0); return sample; } @@ -130,18 +130,10 @@ static bool get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->device; + struct nvkm_device *device = nvxx_device(&drm->device); - /* Zotac FX5200 */ - if (nv_device_match(nvxx_object(device), 0x0322, 0x19da, 0x1035) || - nv_device_match(nvxx_object(device), 0x0322, 0x19da, 0x2035)) { - *pin_mask = 0xc; - return false; - } - - /* MSI nForce2 IGP */ - if (nv_device_match(nvxx_object(device), 0x01f0, 0x1462, 0x5710)) { - *pin_mask = 0xc; + if (device->quirk && device->quirk->tv_pin_mask) { + *pin_mask = device->quirk->tv_pin_mask; return false; } @@ -395,8 +387,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) nv_load_ptv(dev, regs, 200); - gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, mode == DRM_MODE_DPMS_ON); - gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, mode == DRM_MODE_DPMS_ON); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, mode == DRM_MODE_DPMS_ON); + nvkm_gpio_set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, mode == DRM_MODE_DPMS_ON); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } diff --git a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h index 225894cdc..1b07521cd 100644 --- a/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h +++ b/kernel/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h @@ -85,7 +85,7 @@ struct nv17_tv_encoder { #define to_tv_enc(x) container_of(nouveau_encoder(x), \ struct nv17_tv_encoder, base) -extern char *nv17_tv_norm_names[NUM_TV_NORMS]; +extern const char * const nv17_tv_norm_names[NUM_TV_NORMS]; extern struct nv17_tv_norm_params { enum { @@ -131,13 +131,13 @@ static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, uint32_t val) { struct nvif_device *device = &nouveau_drm(dev)->device; - nvif_wr32(device, reg, val); + nvif_wr32(&device->object, reg, val); } static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg) { struct nvif_device *device = &nouveau_drm(dev)->device; - return nvif_rd32(device, reg); + return nvif_rd32(&device->object, reg); } static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/class.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/class.h index 64f8b2f68..95a64d895 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -45,6 +45,11 @@ #define GM107_DISP 0x00009470 #define GM204_DISP 0x00009570 +#define NV31_MPEG 0x00003174 +#define G82_MPEG 0x00008274 + +#define NV74_VP2 0x00007476 + #define NV50_DISP_CURSOR 0x0000507a #define G82_DISP_CURSOR 0x0000827a #define GT214_DISP_CURSOR 0x0000857a @@ -94,15 +99,40 @@ #define MAXWELL_A 0x0000b097 #define MAXWELL_B 0x0000b197 +#define NV74_BSP 0x000074b0 + +#define GT212_MSVLD 0x000085b1 +#define IGT21A_MSVLD 0x000086b1 +#define G98_MSVLD 0x000088b1 +#define GF100_MSVLD 0x000090b1 +#define GK104_MSVLD 0x000095b1 + +#define GT212_MSPDEC 0x000085b2 +#define G98_MSPDEC 0x000088b2 +#define GF100_MSPDEC 0x000090b2 +#define GK104_MSPDEC 0x000095b2 + +#define GT212_MSPPP 0x000085b3 +#define G98_MSPPP 0x000088b3 +#define GF100_MSPPP 0x000090b3 + +#define G98_SEC 0x000088b4 + +#define GT212_DMA 0x000085b5 +#define FERMI_DMA 0x000090b5 +#define KEPLER_DMA_COPY_A 0x0000a0b5 +#define MAXWELL_DMA_COPY_A 0x0000b0b5 + +#define FERMI_DECOMPRESS 0x000090b8 + #define FERMI_COMPUTE_A 0x000090c0 #define FERMI_COMPUTE_B 0x000091c0 - #define KEPLER_COMPUTE_A 0x0000a0c0 #define KEPLER_COMPUTE_B 0x0000a1c0 - #define MAXWELL_COMPUTE_A 0x0000b0c0 #define MAXWELL_COMPUTE_B 0x0000b1c0 +#define NV74_CIPHER 0x000074c1 /******************************************************************************* * client @@ -126,32 +156,10 @@ struct nv_device_v0 { __u8 version; __u8 pad01[7]; __u64 device; /* device identifier, ~0 for client default */ -#define NV_DEVICE_V0_DISABLE_IDENTIFY 0x0000000000000001ULL -#define NV_DEVICE_V0_DISABLE_MMIO 0x0000000000000002ULL -#define NV_DEVICE_V0_DISABLE_VBIOS 0x0000000000000004ULL -#define NV_DEVICE_V0_DISABLE_CORE 0x0000000000000008ULL -#define NV_DEVICE_V0_DISABLE_DISP 0x0000000000010000ULL -#define NV_DEVICE_V0_DISABLE_FIFO 0x0000000000020000ULL -#define NV_DEVICE_V0_DISABLE_GR 0x0000000100000000ULL -#define NV_DEVICE_V0_DISABLE_MPEG 0x0000000200000000ULL -#define NV_DEVICE_V0_DISABLE_ME 0x0000000400000000ULL -#define NV_DEVICE_V0_DISABLE_VP 0x0000000800000000ULL -#define NV_DEVICE_V0_DISABLE_CIPHER 0x0000001000000000ULL -#define NV_DEVICE_V0_DISABLE_BSP 0x0000002000000000ULL -#define NV_DEVICE_V0_DISABLE_MSPPP 0x0000004000000000ULL -#define NV_DEVICE_V0_DISABLE_CE0 0x0000008000000000ULL -#define NV_DEVICE_V0_DISABLE_CE1 0x0000010000000000ULL -#define NV_DEVICE_V0_DISABLE_VIC 0x0000020000000000ULL -#define NV_DEVICE_V0_DISABLE_MSENC 0x0000040000000000ULL -#define NV_DEVICE_V0_DISABLE_CE2 0x0000080000000000ULL -#define NV_DEVICE_V0_DISABLE_MSVLD 0x0000100000000000ULL -#define NV_DEVICE_V0_DISABLE_SEC 0x0000200000000000ULL -#define NV_DEVICE_V0_DISABLE_MSPDEC 0x0000400000000000ULL - __u64 disable; /* disable particular subsystems */ - __u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */ }; #define NV_DEVICE_V0_INFO 0x00 +#define NV_DEVICE_V0_TIME 0x01 struct nv_device_info_v0 { __u8 version; @@ -176,6 +184,14 @@ struct nv_device_info_v0 { __u8 pad06[2]; __u64 ram_size; __u64 ram_user; + char chip[16]; + char name[64]; +}; + +struct nv_device_time_v0 { + __u8 version; + __u8 pad01[7]; + __u64 time; }; @@ -235,13 +251,13 @@ struct gf100_dma_v0 { __u8 pad03[5]; }; -struct gf110_dma_v0 { +struct gf119_dma_v0 { __u8 version; -#define GF110_DMA_V0_PAGE_LP 0x00 -#define GF110_DMA_V0_PAGE_SP 0x01 +#define GF119_DMA_V0_PAGE_LP 0x00 +#define GF119_DMA_V0_PAGE_SP 0x01 __u8 page; -#define GF110_DMA_V0_KIND_PITCH 0x00 -#define GF110_DMA_V0_KIND_VM 0xff +#define GF119_DMA_V0_KIND_PITCH 0x00 +#define GF119_DMA_V0_KIND_VM 0xff __u8 kind; __u8 pad03[5]; }; @@ -251,33 +267,74 @@ struct gf110_dma_v0 { * perfmon ******************************************************************************/ -struct nvif_perfctr_v0 { +#define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00 +#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01 +#define NVIF_PERFMON_V0_QUERY_SOURCE 0x02 + +struct nvif_perfmon_query_domain_v0 { __u8 version; - __u8 pad01[1]; - __u16 logic_op; - __u8 pad04[4]; - char name[4][64]; + __u8 id; + __u8 counter_nr; + __u8 iter; + __u16 signal_nr; + __u8 pad05[2]; + char name[64]; }; -#define NVIF_PERFCTR_V0_QUERY 0x00 -#define NVIF_PERFCTR_V0_SAMPLE 0x01 -#define NVIF_PERFCTR_V0_READ 0x02 +struct nvif_perfmon_query_signal_v0 { + __u8 version; + __u8 domain; + __u16 iter; + __u8 signal; + __u8 source_nr; + __u8 pad05[2]; + char name[64]; +}; -struct nvif_perfctr_query_v0 { +struct nvif_perfmon_query_source_v0 { __u8 version; - __u8 pad01[3]; - __u32 iter; + __u8 domain; + __u8 signal; + __u8 iter; + __u8 pad04[4]; + __u32 source; + __u32 mask; char name[64]; }; -struct nvif_perfctr_sample { + +/******************************************************************************* + * perfdom + ******************************************************************************/ + +struct nvif_perfdom_v0 { + __u8 version; + __u8 domain; + __u8 mode; + __u8 pad03[1]; + struct { + __u8 signal[4]; + __u64 source[4][8]; + __u16 logic_op; + } ctr[4]; }; -struct nvif_perfctr_read_v0 { +#define NVIF_PERFDOM_V0_INIT 0x00 +#define NVIF_PERFDOM_V0_SAMPLE 0x01 +#define NVIF_PERFDOM_V0_READ 0x02 + +struct nvif_perfdom_init { +}; + +struct nvif_perfdom_sample { +}; + +struct nvif_perfdom_read_v0 { __u8 version; __u8 pad01[7]; - __u32 ctr; + __u32 ctr[4]; __u32 clk; + __u8 pad04[4]; }; @@ -337,7 +394,16 @@ struct nv03_channel_dma_v0 { __u8 version; __u8 chid; __u8 pad02[2]; - __u32 pushbuf; + __u32 offset; + __u64 pushbuf; +}; + +struct nv50_channel_dma_v0 { + __u8 version; + __u8 chid; + __u8 pad02[6]; + __u64 vm; + __u64 pushbuf; __u64 offset; }; @@ -350,10 +416,20 @@ struct nv03_channel_dma_v0 { struct nv50_channel_gpfifo_v0 { __u8 version; __u8 chid; - __u8 pad01[6]; - __u32 pushbuf; + __u8 pad02[2]; __u32 ilength; __u64 ioffset; + __u64 pushbuf; + __u64 vm; +}; + +struct fermi_channel_gpfifo_v0 { + __u8 version; + __u8 chid; + __u8 pad02[2]; + __u32 ilength; + __u64 ioffset; + __u64 vm; }; struct kepler_channel_gpfifo_a_v0 { @@ -367,10 +443,9 @@ struct kepler_channel_gpfifo_a_v0 { #define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC 0x40 __u8 engine; __u16 chid; - __u8 pad04[4]; - __u32 pushbuf; __u32 ilength; __u64 ioffset; + __u64 vm; }; /******************************************************************************* @@ -491,8 +566,8 @@ struct nv50_disp_pior_pwr_v0 { /* core */ struct nv50_disp_core_channel_dma_v0 { __u8 version; - __u8 pad01[3]; - __u32 pushbuf; + __u8 pad01[7]; + __u64 pushbuf; }; #define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 @@ -509,9 +584,9 @@ struct nv50_disp_cursor_v0 { /* base */ struct nv50_disp_base_channel_dma_v0 { __u8 version; - __u8 pad01[2]; __u8 head; - __u32 pushbuf; + __u8 pad02[6]; + __u64 pushbuf; }; #define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 @@ -519,9 +594,9 @@ struct nv50_disp_base_channel_dma_v0 { /* overlay */ struct nv50_disp_overlay_channel_dma_v0 { __u8 version; - __u8 pad01[2]; __u8 head; - __u32 pushbuf; + __u8 pad02[6]; + __u64 pushbuf; }; #define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 @@ -535,6 +610,20 @@ struct nv50_disp_overlay_v0 { #define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00 +/******************************************************************************* + * software + ******************************************************************************/ + +#define NVSW_NTFY_UEVENT 0x00 + +#define NV04_NVSW_GET_REF 0x00 + +struct nv04_nvsw_get_ref_v0 { + __u8 version; + __u8 pad01[3]; + __u32 ref; +}; + /******************************************************************************* * fermi ******************************************************************************/ diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/client.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/client.h index eca648ef0..4a7f6f7b8 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/client.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/client.h @@ -4,36 +4,25 @@ #include struct nvif_client { - struct nvif_object base; - struct nvif_object *object; /*XXX: hack for nvif_object() */ + struct nvif_object object; const struct nvif_driver *driver; + u64 version; + u8 route; bool super; }; -static inline struct nvif_client * -nvif_client(struct nvif_object *object) -{ - while (object && object->parent != object) - object = object->parent; - return (void *)object; -} - -int nvif_client_init(void (*dtor)(struct nvif_client *), const char *, - const char *, u64, const char *, const char *, +int nvif_client_init(const char *drv, const char *name, u64 device, + const char *cfg, const char *dbg, struct nvif_client *); void nvif_client_fini(struct nvif_client *); -int nvif_client_new(const char *, const char *, u64, const char *, - const char *, struct nvif_client **); -void nvif_client_ref(struct nvif_client *, struct nvif_client **); int nvif_client_ioctl(struct nvif_client *, void *, u32); int nvif_client_suspend(struct nvif_client *); int nvif_client_resume(struct nvif_client *); /*XXX*/ #include -#define nvxx_client(a) ({ \ - struct nvif_client *_client = nvif_client(nvif_object(a)); \ - nvkm_client(_client->base.priv); \ +#define nvxx_client(a) ({ \ + struct nvif_client *_client = (a); \ + (struct nvkm_client *)_client->object.priv; \ }) - #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/device.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/device.h index 88553a741..700a9b206 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/device.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/device.h @@ -5,26 +5,35 @@ #include struct nvif_device { - struct nvif_object base; - struct nvif_object *object; /*XXX: hack for nvif_object() */ + struct nvif_object object; struct nv_device_info_v0 info; }; -static inline struct nvif_device * -nvif_device(struct nvif_object *object) -{ - while (object && object->oclass != 0x0080 /*XXX: NV_DEVICE_CLASS*/ ) - object = object->parent; - return (void *)object; -} - -int nvif_device_init(struct nvif_object *, void (*dtor)(struct nvif_device *), - u32 handle, u32 oclass, void *, u32, +int nvif_device_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32, struct nvif_device *); void nvif_device_fini(struct nvif_device *); -int nvif_device_new(struct nvif_object *, u32 handle, u32 oclass, - void *, u32, struct nvif_device **); -void nvif_device_ref(struct nvif_device *, struct nvif_device **); +u64 nvif_device_time(struct nvif_device *); + +/* Delay based on GPU time (ie. PTIMER). + * + * Will return -ETIMEDOUT unless the loop was terminated with 'break', + * where it will return the number of nanoseconds taken instead. + */ +#define nvif_nsec(d,n,cond...) ({ \ + struct nvif_device *_device = (d); \ + u64 _nsecs = (n), _time0 = nvif_device_time(_device); \ + s64 _taken = 0; \ + \ + do { \ + cond \ + } while (_taken = nvif_device_time(_device) - _time0, _taken < _nsecs);\ + \ + if (_taken >= _nsecs) \ + _taken = -ETIMEDOUT; \ + _taken; \ +}) +#define nvif_usec(d,u,cond...) nvif_nsec((d), (u) * 1000, ##cond) +#define nvif_msec(d,m,cond...) nvif_usec((d), (m) * 1000, ##cond) /*XXX*/ #include @@ -36,26 +45,30 @@ void nvif_device_ref(struct nvif_device *, struct nvif_device **); #include #include #include +#include -#define nvxx_device(a) nv_device(nvxx_object((a))) -#define nvxx_bios(a) nvkm_bios(nvxx_device(a)) -#define nvxx_fb(a) nvkm_fb(nvxx_device(a)) -#define nvxx_mmu(a) nvkm_mmu(nvxx_device(a)) -#define nvxx_bar(a) nvkm_bar(nvxx_device(a)) -#define nvxx_gpio(a) nvkm_gpio(nvxx_device(a)) -#define nvxx_clk(a) nvkm_clk(nvxx_device(a)) -#define nvxx_i2c(a) nvkm_i2c(nvxx_device(a)) -#define nvxx_timer(a) nvkm_timer(nvxx_device(a)) -#define nvxx_wait(a,b,c,d) nv_wait(nvxx_timer(a), (b), (c), (d)) -#define nvxx_wait_cb(a,b,c) nv_wait_cb(nvxx_timer(a), (b), (c)) -#define nvxx_therm(a) nvkm_therm(nvxx_device(a)) +#define nvxx_device(a) ({ \ + struct nvif_device *_device = (a); \ + struct { \ + struct nvkm_object object; \ + struct nvkm_device *device; \ + } *_udevice = _device->object.priv; \ + _udevice->device; \ +}) +#define nvxx_bios(a) nvxx_device(a)->bios +#define nvxx_fb(a) nvxx_device(a)->fb +#define nvxx_mmu(a) nvxx_device(a)->mmu +#define nvxx_bar(a) nvxx_device(a)->bar +#define nvxx_gpio(a) nvxx_device(a)->gpio +#define nvxx_clk(a) nvxx_device(a)->clk +#define nvxx_i2c(a) nvxx_device(a)->i2c +#define nvxx_therm(a) nvxx_device(a)->therm #include #include #include #include -#define nvxx_fifo(a) nvkm_fifo(nvxx_device(a)) -#define nvxx_fifo_chan(a) ((struct nvkm_fifo_chan *)nvxx_object(a)) -#define nvxx_gr(a) ((struct nvkm_gr *)nvkm_engine(nvxx_object(a), NVDEV_ENGINE_GR)) +#define nvxx_fifo(a) nvxx_device(a)->fifo +#define nvxx_gr(a) nvxx_device(a)->gr #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/ioctl.h index 4cd8e323b..b0ac0215e 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/ioctl.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/ioctl.h @@ -1,11 +1,10 @@ #ifndef __NVIF_IOCTL_H__ #define __NVIF_IOCTL_H__ +#define NVIF_VERSION_LATEST 0x0000000000000000ULL + struct nvif_ioctl_v0 { __u8 version; -#define NVIF_IOCTL_V0_OWNER_NVIF 0x00 -#define NVIF_IOCTL_V0_OWNER_ANY 0xff - __u8 owner; #define NVIF_IOCTL_V0_NOP 0x00 #define NVIF_IOCTL_V0_SCLASS 0x01 #define NVIF_IOCTL_V0_NEW 0x02 @@ -20,17 +19,20 @@ struct nvif_ioctl_v0 { #define NVIF_IOCTL_V0_NTFY_GET 0x0b #define NVIF_IOCTL_V0_NTFY_PUT 0x0c __u8 type; - __u8 path_nr; + __u8 pad02[4]; +#define NVIF_IOCTL_V0_OWNER_NVIF 0x00 +#define NVIF_IOCTL_V0_OWNER_ANY 0xff + __u8 owner; #define NVIF_IOCTL_V0_ROUTE_NVIF 0x00 #define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff - __u8 pad04[3]; __u8 route; __u64 token; - __u32 path[8]; /* in reverse */ + __u64 object; __u8 data[]; /* ioctl data (below) */ }; -struct nvif_ioctl_nop { +struct nvif_ioctl_nop_v0 { + __u64 version; }; struct nvif_ioctl_sclass_v0 { @@ -38,7 +40,11 @@ struct nvif_ioctl_sclass_v0 { __u8 version; __u8 count; __u8 pad02[6]; - __u32 oclass[]; + struct nvif_ioctl_sclass_oclass_v0 { + __s32 oclass; + __s16 minver; + __s16 maxver; + } oclass[]; }; struct nvif_ioctl_new_v0 { @@ -47,11 +53,17 @@ struct nvif_ioctl_new_v0 { __u8 pad01[6]; __u8 route; __u64 token; + __u64 object; __u32 handle; /* these class numbers are made up by us, and not nvidia-assigned */ -#define NVIF_IOCTL_NEW_V0_PERFCTR 0x0000ffff -#define NVIF_IOCTL_NEW_V0_CONTROL 0x0000fffe - __u32 oclass; +#define NVIF_IOCTL_NEW_V0_CONTROL -1 +#define NVIF_IOCTL_NEW_V0_PERFMON -2 +#define NVIF_IOCTL_NEW_V0_PERFDOM -3 +#define NVIF_IOCTL_NEW_V0_SW_NV04 -4 +#define NVIF_IOCTL_NEW_V0_SW_NV10 -5 +#define NVIF_IOCTL_NEW_V0_SW_NV50 -6 +#define NVIF_IOCTL_NEW_V0_SW_GF100 -7 + __s32 oclass; __u8 data[]; /* class data (class.h) */ }; diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/notify.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/notify.h index 9ebfa3b45..51e2eb580 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/notify.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/notify.h @@ -23,17 +23,11 @@ struct nvif_notify { struct work_struct work; }; -int nvif_notify_init(struct nvif_object *, void (*dtor)(struct nvif_notify *), - int (*func)(struct nvif_notify *), bool work, u8 type, - void *data, u32 size, u32 reply, struct nvif_notify *); +int nvif_notify_init(struct nvif_object *, int (*func)(struct nvif_notify *), + bool work, u8 type, void *data, u32 size, u32 reply, + struct nvif_notify *); int nvif_notify_fini(struct nvif_notify *); int nvif_notify_get(struct nvif_notify *); int nvif_notify_put(struct nvif_notify *); int nvif_notify(const void *, u32, const void *, u32); - -int nvif_notify_new(struct nvif_object *, int (*func)(struct nvif_notify *), - bool work, u8 type, void *data, u32 size, u32 reply, - struct nvif_notify **); -void nvif_notify_ref(struct nvif_notify *, struct nvif_notify **); - #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/object.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/object.h index 04c874707..8d8159677 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/object.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/object.h @@ -3,73 +3,73 @@ #include +struct nvif_sclass { + s32 oclass; + int minver; + int maxver; +}; + struct nvif_object { - struct nvif_object *parent; - struct nvif_object *object; /*XXX: hack for nvif_object() */ - struct kref refcount; + struct nvif_client *client; u32 handle; - u32 oclass; - void *data; - u32 size; + s32 oclass; void *priv; /*XXX: hack */ - void (*dtor)(struct nvif_object *); struct { void __iomem *ptr; u32 size; } map; }; -int nvif_object_init(struct nvif_object *, void (*dtor)(struct nvif_object *), - u32 handle, u32 oclass, void *, u32, +int nvif_object_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32, struct nvif_object *); void nvif_object_fini(struct nvif_object *); -int nvif_object_new(struct nvif_object *, u32 handle, u32 oclass, - void *, u32, struct nvif_object **); -void nvif_object_ref(struct nvif_object *, struct nvif_object **); int nvif_object_ioctl(struct nvif_object *, void *, u32, void **); -int nvif_object_sclass(struct nvif_object *, u32 *, int); +int nvif_object_sclass_get(struct nvif_object *, struct nvif_sclass **); +void nvif_object_sclass_put(struct nvif_sclass **); u32 nvif_object_rd(struct nvif_object *, int, u64); void nvif_object_wr(struct nvif_object *, int, u64, u32); int nvif_object_mthd(struct nvif_object *, u32, void *, u32); int nvif_object_map(struct nvif_object *); void nvif_object_unmap(struct nvif_object *); +#define nvif_handle(a) (unsigned long)(void *)(a) #define nvif_object(a) (a)->object -#define ioread8_native ioread8 -#define iowrite8_native iowrite8 -#define nvif_rd(a,b,c) ({ \ - struct nvif_object *_object = nvif_object(a); \ +#define nvif_rd(a,f,b,c) ({ \ + struct nvif_object *_object = (a); \ u32 _data; \ if (likely(_object->map.ptr)) \ - _data = ioread##b##_native((u8 __iomem *)_object->map.ptr + (c)); \ + _data = f((u8 __iomem *)_object->map.ptr + (c)); \ else \ - _data = nvif_object_rd(_object, (b) / 8, (c)); \ + _data = nvif_object_rd(_object, (b), (c)); \ _data; \ }) -#define nvif_wr(a,b,c,d) ({ \ - struct nvif_object *_object = nvif_object(a); \ +#define nvif_wr(a,f,b,c,d) ({ \ + struct nvif_object *_object = (a); \ if (likely(_object->map.ptr)) \ - iowrite##b##_native((d), (u8 __iomem *)_object->map.ptr + (c)); \ + f((d), (u8 __iomem *)_object->map.ptr + (c)); \ else \ - nvif_object_wr(_object, (b) / 8, (c), (d)); \ + nvif_object_wr(_object, (b), (c), (d)); \ }) -#define nvif_rd08(a,b) ({ u8 _v = nvif_rd((a), 8, (b)); _v; }) -#define nvif_rd16(a,b) ({ u16 _v = nvif_rd((a), 16, (b)); _v; }) -#define nvif_rd32(a,b) ({ u32 _v = nvif_rd((a), 32, (b)); _v; }) -#define nvif_wr08(a,b,c) nvif_wr((a), 8, (b), (u8)(c)) -#define nvif_wr16(a,b,c) nvif_wr((a), 16, (b), (u16)(c)) -#define nvif_wr32(a,b,c) nvif_wr((a), 32, (b), (u32)(c)) +#define nvif_rd08(a,b) ({ ((u8)nvif_rd((a), ioread8, 1, (b))); }) +#define nvif_rd16(a,b) ({ ((u16)nvif_rd((a), ioread16_native, 2, (b))); }) +#define nvif_rd32(a,b) ({ ((u32)nvif_rd((a), ioread32_native, 4, (b))); }) +#define nvif_wr08(a,b,c) nvif_wr((a), iowrite8, 1, (b), (u8)(c)) +#define nvif_wr16(a,b,c) nvif_wr((a), iowrite16_native, 2, (b), (u16)(c)) +#define nvif_wr32(a,b,c) nvif_wr((a), iowrite32_native, 4, (b), (u32)(c)) #define nvif_mask(a,b,c,d) ({ \ - u32 _v = nvif_rd32(nvif_object(a), (b)); \ - nvif_wr32(nvif_object(a), (b), (_v & ~(c)) | (d)); \ - _v; \ + struct nvif_object *__object = (a); \ + u32 _addr = (b), _data = nvif_rd32(__object, _addr); \ + nvif_wr32(__object, _addr, (_data & ~(c)) | (d)); \ + _data; \ }) -#define nvif_mthd(a,b,c,d) nvif_object_mthd(nvif_object(a), (b), (c), (d)) +#define nvif_mthd(a,b,c,d) nvif_object_mthd((a), (b), (c), (d)) /*XXX*/ #include -#define nvxx_object(a) ((struct nvkm_object *)nvif_object(a)->priv) - +#define nvxx_object(a) ({ \ + struct nvif_object *_object = (a); \ + (struct nvkm_object *)_object->priv; \ +}) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvif/os.h b/kernel/drivers/gpu/drm/nouveau/include/nvif/os.h index bdd05ee7e..9fcab67c8 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvif/os.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvif/os.h @@ -24,9 +24,16 @@ #include #include #include +#include +#include +#include +#include #include +#include +#include + #ifndef ioread32_native #ifdef __BIG_ENDIAN #define ioread16_native ioread16be @@ -40,5 +47,4 @@ #define iowrite32_native iowrite32 #endif /* def __BIG_ENDIAN else */ #endif /* !ioread32_native */ - #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index a35b38244..eaf5905a8 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -1,55 +1,52 @@ #ifndef __NVKM_CLIENT_H__ #define __NVKM_CLIENT_H__ -#include +#include struct nvkm_client { - struct nvkm_namedb namedb; - struct nvkm_handle *root; - struct nvkm_object *device; + struct nvkm_object object; char name[32]; + u64 device; u32 debug; - struct nvkm_vm *vm; + + struct nvkm_client_notify *notify[16]; + struct rb_root objroot; + struct rb_root dmaroot; + bool super; void *data; - int (*ntfy)(const void *, u32, const void *, u32); - struct nvkm_client_notify *notify[16]; + + struct nvkm_vm *vm; }; -static inline struct nvkm_client * -nv_client(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_CLIENT_CLASS))) - nv_assert("BAD CAST -> NvClient, %08x", nv_hclass(obj)); -#endif - return obj; -} - -static inline struct nvkm_client * -nvkm_client(void *obj) -{ - struct nvkm_object *client = nv_object(obj); - while (client && !(nv_iclass(client, NV_CLIENT_CLASS))) - client = client->parent; - return (void *)client; -} - -#define nvkm_client_create(n,c,oc,od,d) \ - nvkm_client_create_((n), (c), (oc), (od), sizeof(**d), (void **)d) - -int nvkm_client_create_(const char *name, u64 device, const char *cfg, - const char *dbg, int, void **); -#define nvkm_client_destroy(p) \ - nvkm_namedb_destroy(&(p)->base) +bool nvkm_client_insert(struct nvkm_client *, struct nvkm_object *); +void nvkm_client_remove(struct nvkm_client *, struct nvkm_object *); +struct nvkm_object *nvkm_client_search(struct nvkm_client *, u64 object); +int nvkm_client_new(const char *name, u64 device, const char *cfg, + const char *dbg, struct nvkm_client **); +void nvkm_client_del(struct nvkm_client **); int nvkm_client_init(struct nvkm_client *); int nvkm_client_fini(struct nvkm_client *, bool suspend); -const char *nvkm_client_name(void *obj); int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *, void *data, u32 size); int nvkm_client_notify_del(struct nvkm_client *, int index); int nvkm_client_notify_get(struct nvkm_client *, int index); int nvkm_client_notify_put(struct nvkm_client *, int index); + +/* logging for client-facing objects */ +#define nvif_printk(o,l,p,f,a...) do { \ + struct nvkm_object *_object = (o); \ + struct nvkm_client *_client = _object->client; \ + if (_client->debug >= NV_DBG_##l) \ + printk(KERN_##p "nouveau: %s:%08x:%08x: "f, _client->name, \ + _object->handle, _object->oclass, ##a); \ +} while(0) +#define nvif_fatal(o,f,a...) nvif_printk((o), FATAL, CRIT, f, ##a) +#define nvif_error(o,f,a...) nvif_printk((o), ERROR, ERR, f, ##a) +#define nvif_debug(o,f,a...) nvif_printk((o), DEBUG, INFO, f, ##a) +#define nvif_trace(o,f,a...) nvif_printk((o), TRACE, INFO, f, ##a) +#define nvif_info(o,f,a...) nvif_printk((o), INFO, INFO, f, ##a) +#define nvif_ioctl(o,f,a...) nvif_trace((o), "ioctl: "f, ##a) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h index d07cb860b..c59fd4e2a 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h @@ -1,18 +1,11 @@ #ifndef __NVKM_DEBUG_H__ #define __NVKM_DEBUG_H__ -extern int nv_info_debug_level; - #define NV_DBG_FATAL 0 #define NV_DBG_ERROR 1 #define NV_DBG_WARN 2 -#define NV_DBG_INFO nv_info_debug_level +#define NV_DBG_INFO 3 #define NV_DBG_DEBUG 4 #define NV_DBG_TRACE 5 #define NV_DBG_PARANOIA 6 #define NV_DBG_SPAM 7 - -#define NV_DBG_INFO_NORMAL 3 -#define NV_DBG_INFO_SILENT NV_DBG_DEBUG - -#define nv_debug_level(a) nv_info_debug_level = NV_DBG_INFO_##a #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 333db33a1..913192c94 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -1,24 +1,84 @@ #ifndef __NVKM_DEVICE_H__ #define __NVKM_DEVICE_H__ -#include #include +#include + +enum nvkm_devidx { + NVKM_SUBDEV_PCI, + NVKM_SUBDEV_VBIOS, + NVKM_SUBDEV_DEVINIT, + NVKM_SUBDEV_IBUS, + NVKM_SUBDEV_GPIO, + NVKM_SUBDEV_I2C, + NVKM_SUBDEV_FUSE, + NVKM_SUBDEV_MXM, + NVKM_SUBDEV_MC, + NVKM_SUBDEV_BUS, + NVKM_SUBDEV_TIMER, + NVKM_SUBDEV_FB, + NVKM_SUBDEV_LTC, + NVKM_SUBDEV_INSTMEM, + NVKM_SUBDEV_MMU, + NVKM_SUBDEV_BAR, + NVKM_SUBDEV_PMU, + NVKM_SUBDEV_VOLT, + NVKM_SUBDEV_THERM, + NVKM_SUBDEV_CLK, + + NVKM_ENGINE_DMAOBJ, + NVKM_ENGINE_IFB, + NVKM_ENGINE_FIFO, + NVKM_ENGINE_SW, + NVKM_ENGINE_GR, + NVKM_ENGINE_MPEG, + NVKM_ENGINE_ME, + NVKM_ENGINE_VP, + NVKM_ENGINE_CIPHER, + NVKM_ENGINE_BSP, + NVKM_ENGINE_MSPPP, + NVKM_ENGINE_CE0, + NVKM_ENGINE_CE1, + NVKM_ENGINE_CE2, + NVKM_ENGINE_VIC, + NVKM_ENGINE_MSENC, + NVKM_ENGINE_DISP, + NVKM_ENGINE_PM, + NVKM_ENGINE_MSVLD, + NVKM_ENGINE_SEC, + NVKM_ENGINE_MSPDEC, + + NVKM_SUBDEV_NR +}; + +enum nvkm_device_type { + NVKM_DEVICE_PCI, + NVKM_DEVICE_AGP, + NVKM_DEVICE_PCIE, + NVKM_DEVICE_TEGRA, +}; struct nvkm_device { - struct nvkm_engine engine; + const struct nvkm_device_func *func; + const struct nvkm_device_quirk *quirk; + struct device *dev; + enum nvkm_device_type type; + u64 handle; + const char *name; + const char *cfgopt; + const char *dbgopt; + struct list_head head; + struct mutex mutex; + int refcount; - struct pci_dev *pdev; - struct platform_device *platformdev; - u64 handle; + void __iomem *pri; struct nvkm_event event; - const char *cfgopt; - const char *dbgopt; - const char *name; - const char *cname; u64 disable_mask; + u32 debug; + const struct nvkm_device_chip *chip; enum { NV_04 = 0x04, NV_10 = 0x10, @@ -35,67 +95,156 @@ struct nvkm_device { u8 chiprev; u32 crystal; - struct nvkm_oclass *oclass[NVDEV_SUBDEV_NR]; - struct nvkm_object *subdev[NVDEV_SUBDEV_NR]; - struct { struct notifier_block nb; } acpi; + + struct nvkm_bar *bar; + struct nvkm_bios *bios; + struct nvkm_bus *bus; + struct nvkm_clk *clk; + struct nvkm_devinit *devinit; + struct nvkm_fb *fb; + struct nvkm_fuse *fuse; + struct nvkm_gpio *gpio; + struct nvkm_i2c *i2c; + struct nvkm_subdev *ibus; + struct nvkm_instmem *imem; + struct nvkm_ltc *ltc; + struct nvkm_mc *mc; + struct nvkm_mmu *mmu; + struct nvkm_subdev *mxm; + struct nvkm_pci *pci; + struct nvkm_pmu *pmu; + struct nvkm_therm *therm; + struct nvkm_timer *timer; + struct nvkm_volt *volt; + + struct nvkm_engine *bsp; + struct nvkm_engine *ce[3]; + struct nvkm_engine *cipher; + struct nvkm_disp *disp; + struct nvkm_dma *dma; + struct nvkm_fifo *fifo; + struct nvkm_gr *gr; + struct nvkm_engine *ifb; + struct nvkm_engine *me; + struct nvkm_engine *mpeg; + struct nvkm_engine *msenc; + struct nvkm_engine *mspdec; + struct nvkm_engine *msppp; + struct nvkm_engine *msvld; + struct nvkm_pm *pm; + struct nvkm_engine *sec; + struct nvkm_sw *sw; + struct nvkm_engine *vic; + struct nvkm_engine *vp; +}; + +struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int index); +struct nvkm_engine *nvkm_device_engine(struct nvkm_device *, int index); + +struct nvkm_device_func { + struct nvkm_device_pci *(*pci)(struct nvkm_device *); + struct nvkm_device_tegra *(*tegra)(struct nvkm_device *); + void *(*dtor)(struct nvkm_device *); + int (*preinit)(struct nvkm_device *); + int (*init)(struct nvkm_device *); + void (*fini)(struct nvkm_device *, bool suspend); + resource_size_t (*resource_addr)(struct nvkm_device *, unsigned bar); + resource_size_t (*resource_size)(struct nvkm_device *, unsigned bar); + bool cpu_coherent; +}; + +struct nvkm_device_quirk { + u8 tv_pin_mask; + u8 tv_gpio; +}; + +struct nvkm_device_chip { + const char *name; + + int (*bar )(struct nvkm_device *, int idx, struct nvkm_bar **); + int (*bios )(struct nvkm_device *, int idx, struct nvkm_bios **); + int (*bus )(struct nvkm_device *, int idx, struct nvkm_bus **); + int (*clk )(struct nvkm_device *, int idx, struct nvkm_clk **); + int (*devinit)(struct nvkm_device *, int idx, struct nvkm_devinit **); + int (*fb )(struct nvkm_device *, int idx, struct nvkm_fb **); + int (*fuse )(struct nvkm_device *, int idx, struct nvkm_fuse **); + int (*gpio )(struct nvkm_device *, int idx, struct nvkm_gpio **); + int (*i2c )(struct nvkm_device *, int idx, struct nvkm_i2c **); + int (*ibus )(struct nvkm_device *, int idx, struct nvkm_subdev **); + int (*imem )(struct nvkm_device *, int idx, struct nvkm_instmem **); + int (*ltc )(struct nvkm_device *, int idx, struct nvkm_ltc **); + int (*mc )(struct nvkm_device *, int idx, struct nvkm_mc **); + int (*mmu )(struct nvkm_device *, int idx, struct nvkm_mmu **); + int (*mxm )(struct nvkm_device *, int idx, struct nvkm_subdev **); + int (*pci )(struct nvkm_device *, int idx, struct nvkm_pci **); + int (*pmu )(struct nvkm_device *, int idx, struct nvkm_pmu **); + int (*therm )(struct nvkm_device *, int idx, struct nvkm_therm **); + int (*timer )(struct nvkm_device *, int idx, struct nvkm_timer **); + int (*volt )(struct nvkm_device *, int idx, struct nvkm_volt **); + + int (*bsp )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*ce[3] )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*cipher )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*disp )(struct nvkm_device *, int idx, struct nvkm_disp **); + int (*dma )(struct nvkm_device *, int idx, struct nvkm_dma **); + int (*fifo )(struct nvkm_device *, int idx, struct nvkm_fifo **); + int (*gr )(struct nvkm_device *, int idx, struct nvkm_gr **); + int (*ifb )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*me )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*mpeg )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*msenc )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*mspdec )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*msppp )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*msvld )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*pm )(struct nvkm_device *, int idx, struct nvkm_pm **); + int (*sec )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*sw )(struct nvkm_device *, int idx, struct nvkm_sw **); + int (*vic )(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*vp )(struct nvkm_device *, int idx, struct nvkm_engine **); }; struct nvkm_device *nvkm_device_find(u64 name); int nvkm_device_list(u64 *name, int size); -struct nvkm_device *nv_device(void *obj); - -static inline bool -nv_device_match(struct nvkm_object *object, u16 dev, u16 ven, u16 sub) -{ - struct nvkm_device *device = nv_device(object); - return device->pdev->device == dev && - device->pdev->subsystem_vendor == ven && - device->pdev->subsystem_device == sub; -} - -static inline bool -nv_device_is_pci(struct nvkm_device *device) -{ - return device->pdev != NULL; -} - -static inline bool -nv_device_is_cpu_coherent(struct nvkm_device *device) -{ - return (!IS_ENABLED(CONFIG_ARM) && nv_device_is_pci(device)); -} - -static inline struct device * -nv_device_base(struct nvkm_device *device) -{ - return nv_device_is_pci(device) ? &device->pdev->dev : - &device->platformdev->dev; -} - -resource_size_t -nv_device_resource_start(struct nvkm_device *device, unsigned int bar); - -resource_size_t -nv_device_resource_len(struct nvkm_device *device, unsigned int bar); - -int -nv_device_get_irq(struct nvkm_device *device, bool stall); - -struct platform_device; - -enum nv_bus_type { - NVKM_BUS_PCI, - NVKM_BUS_PLATFORM, +/* privileged register interface accessor macros */ +#define nvkm_rd08(d,a) ioread8((d)->pri + (a)) +#define nvkm_rd16(d,a) ioread16_native((d)->pri + (a)) +#define nvkm_rd32(d,a) ioread32_native((d)->pri + (a)) +#define nvkm_wr08(d,a,v) iowrite8((v), (d)->pri + (a)) +#define nvkm_wr16(d,a,v) iowrite16_native((v), (d)->pri + (a)) +#define nvkm_wr32(d,a,v) iowrite32_native((v), (d)->pri + (a)) +#define nvkm_mask(d,a,m,v) ({ \ + struct nvkm_device *_device = (d); \ + u32 _addr = (a), _temp = nvkm_rd32(_device, _addr); \ + nvkm_wr32(_device, _addr, (_temp & ~(m)) | (v)); \ + _temp; \ +}) + +void nvkm_device_del(struct nvkm_device **); + +struct nvkm_device_oclass { + int (*ctor)(struct nvkm_device *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + struct nvkm_sclass base; }; -#define nvkm_device_create(p,t,n,s,c,d,u) \ - nvkm_device_create_((void *)(p), (t), (n), (s), (c), (d), \ - sizeof(**u), (void **)u) -int nvkm_device_create_(void *, enum nv_bus_type type, u64 name, - const char *sname, const char *cfg, const char *dbg, - int, void **); +extern const struct nvkm_sclass nvkm_udevice_sclass; + +/* device logging */ +#define nvdev_printk_(d,l,p,f,a...) do { \ + struct nvkm_device *_device = (d); \ + if (_device->debug >= (l)) \ + dev_##p(_device->dev, f, ##a); \ +} while(0) +#define nvdev_printk(d,l,p,f,a...) nvdev_printk_((d), NV_DBG_##l, p, f, ##a) +#define nvdev_fatal(d,f,a...) nvdev_printk((d), FATAL, crit, f, ##a) +#define nvdev_error(d,f,a...) nvdev_printk((d), ERROR, err, f, ##a) +#define nvdev_warn(d,f,a...) nvdev_printk((d), WARN, notice, f, ##a) +#define nvdev_info(d,f,a...) nvdev_printk((d), INFO, info, f, ##a) +#define nvdev_debug(d,f,a...) nvdev_printk((d), DEBUG, info, f, ##a) +#define nvdev_trace(d,f,a...) nvdev_printk((d), TRACE, info, f, ##a) +#define nvdev_spam(d,f,a...) nvdev_printk((d), SPAM, dbg, f, ##a) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/devidx.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/devidx.h deleted file mode 100644 index 60c5888b5..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/devidx.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __NVKM_DEVIDX_H__ -#define __NVKM_DEVIDX_H__ -enum nvkm_devidx { - NVDEV_ENGINE_DEVICE, - NVDEV_SUBDEV_VBIOS, - - /* All subdevs from DEVINIT to DEVINIT_LAST will be created before - * *any* of them are initialised. This subdev category is used - * for any subdevs that the VBIOS init table parsing may call out - * to during POST. - */ - NVDEV_SUBDEV_DEVINIT, - NVDEV_SUBDEV_IBUS, - NVDEV_SUBDEV_GPIO, - NVDEV_SUBDEV_I2C, - NVDEV_SUBDEV_DEVINIT_LAST = NVDEV_SUBDEV_I2C, - - /* This grouping of subdevs are initialised right after they've - * been created, and are allowed to assume any subdevs in the - * list above them exist and have been initialised. - */ - NVDEV_SUBDEV_FUSE, - NVDEV_SUBDEV_MXM, - NVDEV_SUBDEV_MC, - NVDEV_SUBDEV_BUS, - NVDEV_SUBDEV_TIMER, - NVDEV_SUBDEV_FB, - NVDEV_SUBDEV_LTC, - NVDEV_SUBDEV_INSTMEM, - NVDEV_SUBDEV_MMU, - NVDEV_SUBDEV_BAR, - NVDEV_SUBDEV_PMU, - NVDEV_SUBDEV_VOLT, - NVDEV_SUBDEV_THERM, - NVDEV_SUBDEV_CLK, - - NVDEV_ENGINE_FIRST, - NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST, - NVDEV_ENGINE_IFB, - NVDEV_ENGINE_FIFO, - NVDEV_ENGINE_SW, - NVDEV_ENGINE_GR, - NVDEV_ENGINE_MPEG, - NVDEV_ENGINE_ME, - NVDEV_ENGINE_VP, - NVDEV_ENGINE_CIPHER, - NVDEV_ENGINE_BSP, - NVDEV_ENGINE_MSPPP, - NVDEV_ENGINE_CE0, - NVDEV_ENGINE_CE1, - NVDEV_ENGINE_CE2, - NVDEV_ENGINE_VIC, - NVDEV_ENGINE_MSENC, - NVDEV_ENGINE_DISP, - NVDEV_ENGINE_PM, - NVDEV_ENGINE_MSVLD, - NVDEV_ENGINE_SEC, - NVDEV_ENGINE_MSPDEC, - - NVDEV_SUBDEV_NR, -}; -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engctx.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engctx.h deleted file mode 100644 index 1bf2e8eb4..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engctx.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __NVKM_ENGCTX_H__ -#define __NVKM_ENGCTX_H__ -#include - -#include - -#define NV_ENGCTX_(eng,var) (NV_ENGCTX_CLASS | ((var) << 8) | (eng)) -#define NV_ENGCTX(name,var) NV_ENGCTX_(NVDEV_ENGINE_##name, (var)) - -struct nvkm_engctx { - struct nvkm_gpuobj gpuobj; - struct nvkm_vma vma; - struct list_head head; - unsigned long save; - u64 addr; -}; - -static inline struct nvkm_engctx * -nv_engctx(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_ENGCTX_CLASS))) - nv_assert("BAD CAST -> NvEngCtx, %08x", nv_hclass(obj)); -#endif - return obj; -} - -#define nvkm_engctx_create(p,e,c,g,s,a,f,d) \ - nvkm_engctx_create_((p), (e), (c), (g), (s), (a), (f), \ - sizeof(**d), (void **)d) - -int nvkm_engctx_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, struct nvkm_object *, - u32 size, u32 align, u32 flags, - int length, void **data); -void nvkm_engctx_destroy(struct nvkm_engctx *); -int nvkm_engctx_init(struct nvkm_engctx *); -int nvkm_engctx_fini(struct nvkm_engctx *, bool suspend); - -int _nvkm_engctx_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void _nvkm_engctx_dtor(struct nvkm_object *); -int _nvkm_engctx_init(struct nvkm_object *); -int _nvkm_engctx_fini(struct nvkm_object *, bool suspend); -#define _nvkm_engctx_rd32 _nvkm_gpuobj_rd32 -#define _nvkm_engctx_wr32 _nvkm_gpuobj_wr32 - -struct nvkm_object *nvkm_engctx_get(struct nvkm_engine *, u64 addr); -void nvkm_engctx_put(struct nvkm_object *); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h index faf0fd2f0..48bf12845 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h @@ -1,56 +1,49 @@ #ifndef __NVKM_ENGINE_H__ #define __NVKM_ENGINE_H__ +#define nvkm_engine(p) container_of((p), struct nvkm_engine, subdev) #include - -#define NV_ENGINE_(eng,var) (NV_ENGINE_CLASS | ((var) << 8) | (eng)) -#define NV_ENGINE(name,var) NV_ENGINE_(NVDEV_ENGINE_##name, (var)) +struct nvkm_fifo_chan; +struct nvkm_fb_tile; struct nvkm_engine { + const struct nvkm_engine_func *func; struct nvkm_subdev subdev; - struct nvkm_oclass *cclass; - struct nvkm_oclass *sclass; - - struct list_head contexts; spinlock_t lock; - void (*tile_prog)(struct nvkm_engine *, int region); - int (*tlb_flush)(struct nvkm_engine *); + int usecount; }; -static inline struct nvkm_engine * -nv_engine(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_ENGINE_CLASS))) - nv_assert("BAD CAST -> NvEngine, %08x", nv_hclass(obj)); -#endif - return obj; -} - -static inline int -nv_engidx(struct nvkm_engine *engine) -{ - return nv_subidx(&engine->subdev); -} - -struct nvkm_engine *nvkm_engine(void *obj, int idx); - -#define nvkm_engine_create(p,e,c,d,i,f,r) \ - nvkm_engine_create_((p), (e), (c), (d), (i), (f), \ - sizeof(**r),(void **)r) - -#define nvkm_engine_destroy(p) \ - nvkm_subdev_destroy(&(p)->subdev) -#define nvkm_engine_init(p) \ - nvkm_subdev_init(&(p)->subdev) -#define nvkm_engine_fini(p,s) \ - nvkm_subdev_fini(&(p)->subdev, (s)) - -int nvkm_engine_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, bool, const char *, - const char *, int, void **); +struct nvkm_engine_func { + void *(*dtor)(struct nvkm_engine *); + int (*oneinit)(struct nvkm_engine *); + int (*init)(struct nvkm_engine *); + int (*fini)(struct nvkm_engine *, bool suspend); + void (*intr)(struct nvkm_engine *); + void (*tile)(struct nvkm_engine *, int region, struct nvkm_fb_tile *); + + struct { + int (*sclass)(struct nvkm_oclass *, int index, + const struct nvkm_device_oclass **); + } base; + + struct { + int (*cclass)(struct nvkm_fifo_chan *, + const struct nvkm_oclass *, + struct nvkm_object **); + int (*sclass)(struct nvkm_oclass *, int index); + } fifo; + + const struct nvkm_object_func *cclass; + struct nvkm_sclass sclass[]; +}; -#define _nvkm_engine_dtor _nvkm_subdev_dtor -#define _nvkm_engine_init _nvkm_subdev_init -#define _nvkm_engine_fini _nvkm_subdev_fini +int nvkm_engine_ctor(const struct nvkm_engine_func *, struct nvkm_device *, + int index, u32 pmc_enable, bool enable, + struct nvkm_engine *); +int nvkm_engine_new_(const struct nvkm_engine_func *, struct nvkm_device *, + int index, u32 pmc_enable, bool enable, + struct nvkm_engine **); +struct nvkm_engine *nvkm_engine_ref(struct nvkm_engine *); +void nvkm_engine_unref(struct nvkm_engine **); +void nvkm_engine_tile(struct nvkm_engine *, int region); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h index e76f76f11..40429a82f 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h @@ -10,12 +10,11 @@ struct nvkm_enum { }; const struct nvkm_enum *nvkm_enum_find(const struct nvkm_enum *, u32 value); -const struct nvkm_enum *nvkm_enum_print(const struct nvkm_enum *, u32 value); struct nvkm_bitfield { u32 mask; const char *name; }; -void nvkm_bitfield_print(const struct nvkm_bitfield *, u32 value); +void nvkm_snprintbf(char *, int, const struct nvkm_bitfield *, u32 value); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h index e0187e7ab..d4f56eafb 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h @@ -1,64 +1,40 @@ #ifndef __NVKM_GPUOBJ_H__ #define __NVKM_GPUOBJ_H__ #include +#include #include struct nvkm_vma; struct nvkm_vm; #define NVOBJ_FLAG_ZERO_ALLOC 0x00000001 -#define NVOBJ_FLAG_ZERO_FREE 0x00000002 #define NVOBJ_FLAG_HEAP 0x00000004 struct nvkm_gpuobj { struct nvkm_object object; - struct nvkm_object *parent; + const struct nvkm_gpuobj_func *func; + struct nvkm_gpuobj *parent; + struct nvkm_memory *memory; struct nvkm_mm_node *node; - struct nvkm_mm heap; - u32 flags; u64 addr; u32 size; -}; + struct nvkm_mm heap; -static inline struct nvkm_gpuobj * -nv_gpuobj(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_GPUOBJ_CLASS))) - nv_assert("BAD CAST -> NvGpuObj, %08x", nv_hclass(obj)); -#endif - return obj; -} + void __iomem *map; +}; -#define nvkm_gpuobj_create(p,e,c,v,g,s,a,f,d) \ - nvkm_gpuobj_create_((p), (e), (c), (v), (g), (s), (a), (f), \ - sizeof(**d), (void **)d) -#define nvkm_gpuobj_init(p) nvkm_object_init(&(p)->object) -#define nvkm_gpuobj_fini(p,s) nvkm_object_fini(&(p)->object, (s)) -int nvkm_gpuobj_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32 pclass, - struct nvkm_object *, u32 size, u32 align, - u32 flags, int length, void **); -void nvkm_gpuobj_destroy(struct nvkm_gpuobj *); +struct nvkm_gpuobj_func { + void *(*acquire)(struct nvkm_gpuobj *); + void (*release)(struct nvkm_gpuobj *); + u32 (*rd32)(struct nvkm_gpuobj *, u32 offset); + void (*wr32)(struct nvkm_gpuobj *, u32 offset, u32 data); +}; -int nvkm_gpuobj_new(struct nvkm_object *, struct nvkm_object *, u32 size, - u32 align, u32 flags, struct nvkm_gpuobj **); -int nvkm_gpuobj_dup(struct nvkm_object *, struct nvkm_gpuobj *, - struct nvkm_gpuobj **); -int nvkm_gpuobj_map(struct nvkm_gpuobj *, u32 acc, struct nvkm_vma *); -int nvkm_gpuobj_map_vm(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, - struct nvkm_vma *); +int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero, + struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); +void nvkm_gpuobj_del(struct nvkm_gpuobj **); +int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); +int nvkm_gpuobj_map(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, + struct nvkm_vma *); void nvkm_gpuobj_unmap(struct nvkm_vma *); - -static inline void -nvkm_gpuobj_ref(struct nvkm_gpuobj *obj, struct nvkm_gpuobj **ref) -{ - nvkm_object_ref(&obj->object, (struct nvkm_object **)ref); -} - -void _nvkm_gpuobj_dtor(struct nvkm_object *); -int _nvkm_gpuobj_init(struct nvkm_object *); -int _nvkm_gpuobj_fini(struct nvkm_object *, bool); -u32 _nvkm_gpuobj_rd32(struct nvkm_object *, u64); -void _nvkm_gpuobj_wr32(struct nvkm_object *, u64, u32); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h deleted file mode 100644 index 67f384d09..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/handle.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __NVKM_HANDLE_H__ -#define __NVKM_HANDLE_H__ -#include -struct nvkm_object; - -struct nvkm_handle { - struct nvkm_namedb *namedb; - struct list_head node; - - struct list_head head; - struct list_head tree; - u32 name; - u32 priv; - - u8 route; - u64 token; - - struct nvkm_handle *parent; - struct nvkm_object *object; -}; - -int nvkm_handle_create(struct nvkm_object *, u32 parent, u32 handle, - struct nvkm_object *, struct nvkm_handle **); -void nvkm_handle_destroy(struct nvkm_handle *); -int nvkm_handle_init(struct nvkm_handle *); -int nvkm_handle_fini(struct nvkm_handle *, bool suspend); - -struct nvkm_object *nvkm_handle_ref(struct nvkm_object *, u32 name); - -struct nvkm_handle *nvkm_handle_get_class(struct nvkm_object *, u16); -struct nvkm_handle *nvkm_handle_get_vinst(struct nvkm_object *, u64); -struct nvkm_handle *nvkm_handle_get_cinst(struct nvkm_object *, u32); -void nvkm_handle_put(struct nvkm_handle *); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h new file mode 100644 index 000000000..9363b839a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h @@ -0,0 +1,53 @@ +#ifndef __NVKM_MEMORY_H__ +#define __NVKM_MEMORY_H__ +#include +struct nvkm_device; +struct nvkm_vma; +struct nvkm_vm; + +enum nvkm_memory_target { + NVKM_MEM_TARGET_INST, + NVKM_MEM_TARGET_VRAM, + NVKM_MEM_TARGET_HOST, +}; + +struct nvkm_memory { + const struct nvkm_memory_func *func; +}; + +struct nvkm_memory_func { + void *(*dtor)(struct nvkm_memory *); + enum nvkm_memory_target (*target)(struct nvkm_memory *); + u64 (*addr)(struct nvkm_memory *); + u64 (*size)(struct nvkm_memory *); + void (*boot)(struct nvkm_memory *, struct nvkm_vm *); + void __iomem *(*acquire)(struct nvkm_memory *); + void (*release)(struct nvkm_memory *); + u32 (*rd32)(struct nvkm_memory *, u64 offset); + void (*wr32)(struct nvkm_memory *, u64 offset, u32 data); + void (*map)(struct nvkm_memory *, struct nvkm_vma *, u64 offset); +}; + +void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *); +int nvkm_memory_new(struct nvkm_device *, enum nvkm_memory_target, + u64 size, u32 align, bool zero, struct nvkm_memory **); +void nvkm_memory_del(struct nvkm_memory **); +#define nvkm_memory_target(p) (p)->func->target(p) +#define nvkm_memory_addr(p) (p)->func->addr(p) +#define nvkm_memory_size(p) (p)->func->size(p) +#define nvkm_memory_boot(p,v) (p)->func->boot((p),(v)) +#define nvkm_memory_map(p,v,o) (p)->func->map((p),(v),(o)) + +/* accessor macros - kmap()/done() must bracket use of the other accessor + * macros to guarantee correct behaviour across all chipsets + */ +#define nvkm_kmap(o) (o)->func->acquire(o) +#define nvkm_ro32(o,a) (o)->func->rd32((o), (a)) +#define nvkm_wo32(o,a,d) (o)->func->wr32((o), (a), (d)) +#define nvkm_mo32(o,a,m,d) ({ \ + u32 _addr = (a), _data = nvkm_ro32((o), _addr); \ + nvkm_wo32((o), _addr, (_data & ~(m)) | (d)); \ + _data; \ +}) +#define nvkm_done(o) (o)->func->release(o) +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h index 096eb1a62..d92fd41e4 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h @@ -27,7 +27,7 @@ struct nvkm_mm { static inline bool nvkm_mm_initialised(struct nvkm_mm *mm) { - return mm->block_size != 0; + return mm->heap_nodes; } int nvkm_mm_init(struct nvkm_mm *, u32 offset, u32 length, u32 block); @@ -37,4 +37,5 @@ int nvkm_mm_head(struct nvkm_mm *, u8 heap, u8 type, u32 size_max, int nvkm_mm_tail(struct nvkm_mm *, u8 heap, u8 type, u32 size_max, u32 size_min, u32 align, struct nvkm_mm_node **); void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **); +void nvkm_mm_dump(struct nvkm_mm *, const char *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h deleted file mode 100644 index 4cfe16fcd..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __NVKM_NAMEDB_H__ -#define __NVKM_NAMEDB_H__ -#include -struct nvkm_handle; - -struct nvkm_namedb { - struct nvkm_parent parent; - rwlock_t lock; - struct list_head list; -}; - -static inline struct nvkm_namedb * -nv_namedb(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_NAMEDB_CLASS))) - nv_assert("BAD CAST -> NvNameDB, %08x", nv_hclass(obj)); -#endif - return obj; -} - -#define nvkm_namedb_create(p,e,c,v,s,m,d) \ - nvkm_namedb_create_((p), (e), (c), (v), (s), (m), \ - sizeof(**d), (void **)d) -#define nvkm_namedb_init(p) \ - nvkm_parent_init(&(p)->parent) -#define nvkm_namedb_fini(p,s) \ - nvkm_parent_fini(&(p)->parent, (s)) -#define nvkm_namedb_destroy(p) \ - nvkm_parent_destroy(&(p)->parent) - -int nvkm_namedb_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32 pclass, - struct nvkm_oclass *, u64 engcls, - int size, void **); - -int _nvkm_namedb_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -#define _nvkm_namedb_dtor _nvkm_parent_dtor -#define _nvkm_namedb_init _nvkm_parent_init -#define _nvkm_namedb_fini _nvkm_parent_fini - -int nvkm_namedb_insert(struct nvkm_namedb *, u32 name, struct nvkm_object *, - struct nvkm_handle *); -void nvkm_namedb_remove(struct nvkm_handle *); - -struct nvkm_handle *nvkm_namedb_get(struct nvkm_namedb *, u32); -struct nvkm_handle *nvkm_namedb_get_class(struct nvkm_namedb *, u16); -struct nvkm_handle *nvkm_namedb_get_vinst(struct nvkm_namedb *, u64); -struct nvkm_handle *nvkm_namedb_get_cinst(struct nvkm_namedb *, u32); -void nvkm_namedb_put(struct nvkm_handle *); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index 6e3cd3908..dcd048b91 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -1,203 +1,88 @@ #ifndef __NVKM_OBJECT_H__ #define __NVKM_OBJECT_H__ #include -#include - -#define NV_PARENT_CLASS 0x80000000 -#define NV_NAMEDB_CLASS 0x40000000 -#define NV_CLIENT_CLASS 0x20000000 -#define NV_SUBDEV_CLASS 0x10000000 -#define NV_ENGINE_CLASS 0x08000000 -#define NV_MEMOBJ_CLASS 0x04000000 -#define NV_GPUOBJ_CLASS 0x02000000 -#define NV_ENGCTX_CLASS 0x01000000 -#define NV_OBJECT_CLASS 0x0000ffff +#include +struct nvkm_event; +struct nvkm_gpuobj; +struct nvkm_oclass; struct nvkm_object { - struct nvkm_oclass *oclass; - struct nvkm_object *parent; + const struct nvkm_object_func *func; + struct nvkm_client *client; struct nvkm_engine *engine; - atomic_t refcount; - atomic_t usecount; -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA -#define NVKM_OBJECT_MAGIC 0x75ef0bad - struct list_head list; - u32 _magic; -#endif -}; - -static inline struct nvkm_object * -nv_object(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (likely(obj)) { - struct nvkm_object *object = obj; - if (unlikely(object->_magic != NVKM_OBJECT_MAGIC)) - nv_assert("BAD CAST -> NvObject, invalid magic"); - } -#endif - return obj; -} - -#define nvkm_object_create(p,e,c,s,d) \ - nvkm_object_create_((p), (e), (c), (s), sizeof(**d), (void **)d) -int nvkm_object_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32, int size, void **); -void nvkm_object_destroy(struct nvkm_object *); -int nvkm_object_init(struct nvkm_object *); -int nvkm_object_fini(struct nvkm_object *, bool suspend); - -int _nvkm_object_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - -extern struct nvkm_ofuncs nvkm_object_ofuncs; - -/* Don't allocate dynamically, because lockdep needs lock_class_keys to be in - * ".data". */ -struct nvkm_oclass { + s32 oclass; u32 handle; - struct nvkm_ofuncs * const ofuncs; - struct nvkm_omthds * const omthds; - struct lock_class_key lock_class_key; -}; - -#define nv_oclass(o) nv_object(o)->oclass -#define nv_hclass(o) nv_oclass(o)->handle -#define nv_iclass(o,i) (nv_hclass(o) & (i)) -#define nv_mclass(o) nv_iclass(o, NV_OBJECT_CLASS) -static inline struct nvkm_object * -nv_pclass(struct nvkm_object *parent, u32 oclass) -{ - while (parent && !nv_iclass(parent, oclass)) - parent = parent->parent; - return parent; -} + struct list_head head; + struct list_head tree; + u8 route; + u64 token; + u64 object; + struct rb_node node; +}; -struct nvkm_omthds { - u32 start; - u32 limit; - int (*call)(struct nvkm_object *, u32, void *, u32); +struct nvkm_object_func { + void *(*dtor)(struct nvkm_object *); + int (*init)(struct nvkm_object *); + int (*fini)(struct nvkm_object *, bool suspend); + int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size); + int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **); + int (*map)(struct nvkm_object *, u64 *addr, u32 *size); + int (*rd08)(struct nvkm_object *, u64 addr, u8 *data); + int (*rd16)(struct nvkm_object *, u64 addr, u16 *data); + int (*rd32)(struct nvkm_object *, u64 addr, u32 *data); + int (*wr08)(struct nvkm_object *, u64 addr, u8 data); + int (*wr16)(struct nvkm_object *, u64 addr, u16 data); + int (*wr32)(struct nvkm_object *, u64 addr, u32 data); + int (*bind)(struct nvkm_object *, struct nvkm_gpuobj *, int align, + struct nvkm_gpuobj **); + int (*sclass)(struct nvkm_object *, int index, struct nvkm_oclass *); }; -struct nvkm_event; -struct nvkm_ofuncs { - int (*ctor)(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *data, u32 size, +void nvkm_object_ctor(const struct nvkm_object_func *, + const struct nvkm_oclass *, struct nvkm_object *); +int nvkm_object_new_(const struct nvkm_object_func *, + const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); - void (*dtor)(struct nvkm_object *); - int (*init)(struct nvkm_object *); - int (*fini)(struct nvkm_object *, bool suspend); - int (*mthd)(struct nvkm_object *, u32, void *, u32); - int (*ntfy)(struct nvkm_object *, u32, struct nvkm_event **); - int (* map)(struct nvkm_object *, u64 *, u32 *); - u8 (*rd08)(struct nvkm_object *, u64 offset); - u16 (*rd16)(struct nvkm_object *, u64 offset); - u32 (*rd32)(struct nvkm_object *, u64 offset); - void (*wr08)(struct nvkm_object *, u64 offset, u8 data); - void (*wr16)(struct nvkm_object *, u64 offset, u16 data); - void (*wr32)(struct nvkm_object *, u64 offset, u32 data); +int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); +void nvkm_object_del(struct nvkm_object **); +void *nvkm_object_dtor(struct nvkm_object *); +int nvkm_object_init(struct nvkm_object *); +int nvkm_object_fini(struct nvkm_object *, bool suspend); +int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); +int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); +int nvkm_object_map(struct nvkm_object *, u64 *addr, u32 *size); +int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data); +int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data); +int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data); +int nvkm_object_wr08(struct nvkm_object *, u64 addr, u8 data); +int nvkm_object_wr16(struct nvkm_object *, u64 addr, u16 data); +int nvkm_object_wr32(struct nvkm_object *, u64 addr, u32 data); +int nvkm_object_bind(struct nvkm_object *, struct nvkm_gpuobj *, int align, + struct nvkm_gpuobj **); + +struct nvkm_sclass { + int minver; + int maxver; + s32 oclass; + const struct nvkm_object_func *func; + int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); }; -static inline struct nvkm_ofuncs * -nv_ofuncs(void *obj) -{ - return nv_oclass(obj)->ofuncs; -} - -int nvkm_object_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nvkm_object_ref(struct nvkm_object *, struct nvkm_object **); -int nvkm_object_inc(struct nvkm_object *); -int nvkm_object_dec(struct nvkm_object *, bool suspend); -void nvkm_object_debug(void); - -static inline int -nv_exec(void *obj, u32 mthd, void *data, u32 size) -{ - struct nvkm_omthds *method = nv_oclass(obj)->omthds; - - while (method && method->call) { - if (mthd >= method->start && mthd <= method->limit) - return method->call(obj, mthd, data, size); - method++; - } - - return -EINVAL; -} - -static inline int -nv_call(void *obj, u32 mthd, u32 data) -{ - return nv_exec(obj, mthd, &data, sizeof(data)); -} - -static inline u8 -nv_ro08(void *obj, u64 addr) -{ - u8 data = nv_ofuncs(obj)->rd08(obj, addr); - nv_spam(obj, "nv_ro08 0x%08llx 0x%02x\n", addr, data); - return data; -} - -static inline u16 -nv_ro16(void *obj, u64 addr) -{ - u16 data = nv_ofuncs(obj)->rd16(obj, addr); - nv_spam(obj, "nv_ro16 0x%08llx 0x%04x\n", addr, data); - return data; -} - -static inline u32 -nv_ro32(void *obj, u64 addr) -{ - u32 data = nv_ofuncs(obj)->rd32(obj, addr); - nv_spam(obj, "nv_ro32 0x%08llx 0x%08x\n", addr, data); - return data; -} - -static inline void -nv_wo08(void *obj, u64 addr, u8 data) -{ - nv_spam(obj, "nv_wo08 0x%08llx 0x%02x\n", addr, data); - nv_ofuncs(obj)->wr08(obj, addr, data); -} - -static inline void -nv_wo16(void *obj, u64 addr, u16 data) -{ - nv_spam(obj, "nv_wo16 0x%08llx 0x%04x\n", addr, data); - nv_ofuncs(obj)->wr16(obj, addr, data); -} - -static inline void -nv_wo32(void *obj, u64 addr, u32 data) -{ - nv_spam(obj, "nv_wo32 0x%08llx 0x%08x\n", addr, data); - nv_ofuncs(obj)->wr32(obj, addr, data); -} - -static inline u32 -nv_mo32(void *obj, u64 addr, u32 mask, u32 data) -{ - u32 temp = nv_ro32(obj, addr); - nv_wo32(obj, addr, (temp & ~mask) | data); - return temp; -} - -static inline int -nv_memcmp(void *obj, u32 addr, const char *str, u32 len) -{ - unsigned char c1, c2; - - while (len--) { - c1 = nv_ro08(obj, addr++); - c2 = *(str++); - if (c1 != c2) - return c1 - c2; - } - return 0; -} +struct nvkm_oclass { + int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); + struct nvkm_sclass base; + const void *priv; + const void *engn; + u32 handle; + u8 route; + u64 token; + u64 object; + struct nvkm_client *client; + struct nvkm_object *parent; + struct nvkm_engine *engine; +}; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h new file mode 100644 index 000000000..bd52236cc --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h @@ -0,0 +1,22 @@ +#ifndef __NVKM_OPROXY_H__ +#define __NVKM_OPROXY_H__ +#define nvkm_oproxy(p) container_of((p), struct nvkm_oproxy, base) +#include + +struct nvkm_oproxy { + const struct nvkm_oproxy_func *func; + struct nvkm_object base; + struct nvkm_object *object; +}; + +struct nvkm_oproxy_func { + void (*dtor[2])(struct nvkm_oproxy *); + int (*init[2])(struct nvkm_oproxy *); + int (*fini[2])(struct nvkm_oproxy *, bool suspend); +}; + +void nvkm_oproxy_ctor(const struct nvkm_oproxy_func *, + const struct nvkm_oclass *, struct nvkm_oproxy *); +int nvkm_oproxy_new_(const struct nvkm_oproxy_func *, + const struct nvkm_oclass *, struct nvkm_oproxy **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/option.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/option.h index 532bfa8e3..80fdc146e 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/option.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/option.h @@ -4,6 +4,7 @@ const char *nvkm_stropt(const char *optstr, const char *opt, int *len); bool nvkm_boolopt(const char *optstr, const char *opt, bool value); +long nvkm_longopt(const char *optstr, const char *opt, long value); int nvkm_dbgopt(const char *optstr, const char *sub); /* compares unterminated string 'str' with zero-terminated string 'cmp' */ diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h deleted file mode 100644 index 837e4fe96..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __NVKM_PARENT_H__ -#define __NVKM_PARENT_H__ -#include - -struct nvkm_sclass { - struct nvkm_sclass *sclass; - struct nvkm_engine *engine; - struct nvkm_oclass *oclass; -}; - -struct nvkm_parent { - struct nvkm_object object; - - struct nvkm_sclass *sclass; - u64 engine; - - int (*context_attach)(struct nvkm_object *, struct nvkm_object *); - int (*context_detach)(struct nvkm_object *, bool suspend, - struct nvkm_object *); - - int (*object_attach)(struct nvkm_object *parent, - struct nvkm_object *object, u32 name); - void (*object_detach)(struct nvkm_object *parent, int cookie); -}; - -static inline struct nvkm_parent * -nv_parent(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!(nv_iclass(obj, NV_PARENT_CLASS)))) - nv_assert("BAD CAST -> NvParent, %08x", nv_hclass(obj)); -#endif - return obj; -} - -#define nvkm_parent_create(p,e,c,v,s,m,d) \ - nvkm_parent_create_((p), (e), (c), (v), (s), (m), \ - sizeof(**d), (void **)d) -#define nvkm_parent_init(p) \ - nvkm_object_init(&(p)->object) -#define nvkm_parent_fini(p,s) \ - nvkm_object_fini(&(p)->object, (s)) - -int nvkm_parent_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32 pclass, - struct nvkm_oclass *, u64 engcls, - int size, void **); -void nvkm_parent_destroy(struct nvkm_parent *); - -void _nvkm_parent_dtor(struct nvkm_object *); -#define _nvkm_parent_init nvkm_object_init -#define _nvkm_parent_fini nvkm_object_fini - -int nvkm_parent_sclass(struct nvkm_object *, u16 handle, - struct nvkm_object **pengine, - struct nvkm_oclass **poclass); -int nvkm_parent_lclass(struct nvkm_object *, u32 *, int); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h new file mode 100644 index 000000000..78d41be20 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h @@ -0,0 +1,14 @@ +#ifndef __NVKM_DEVICE_PCI_H__ +#define __NVKM_DEVICE_PCI_H__ +#include + +struct nvkm_device_pci { + struct nvkm_device device; + struct pci_dev *pdev; + bool suspend; +}; + +int nvkm_device_pci_new(struct pci_dev *, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/printk.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/printk.h deleted file mode 100644 index 836481770..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/printk.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __NVKM_PRINTK_H__ -#define __NVKM_PRINTK_H__ -#include -#include -struct nvkm_object; - -void __printf(3, 4) -nv_printk_(struct nvkm_object *, int, const char *, ...); - -#define nv_printk(o,l,f,a...) do { \ - if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG) \ - nv_printk_(nv_object(o), NV_DBG_##l, f, ##a); \ -} while(0) - -#define nv_fatal(o,f,a...) nv_printk((o), FATAL, f, ##a) -#define nv_error(o,f,a...) nv_printk((o), ERROR, f, ##a) -#define nv_warn(o,f,a...) nv_printk((o), WARN, f, ##a) -#define nv_info(o,f,a...) nv_printk((o), INFO, f, ##a) -#define nv_debug(o,f,a...) nv_printk((o), DEBUG, f, ##a) -#define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a) -#define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a) -#define nv_ioctl(o,f,a...) nv_trace(nvkm_client(o), "ioctl: "f, ##a) - -#define nv_assert(f,a...) do { \ - if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG) \ - nv_printk_(NULL, NV_DBG_FATAL, f "\n", ##a); \ - BUG_ON(1); \ -} while(0) -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h index cc132eaa1..5ee629899 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h @@ -2,19 +2,27 @@ #define __NVKM_RAMHT_H__ #include +struct nvkm_ramht_data { + struct nvkm_gpuobj *inst; + int chid; + u32 handle; +}; + struct nvkm_ramht { - struct nvkm_gpuobj gpuobj; + struct nvkm_device *device; + struct nvkm_gpuobj *parent; + struct nvkm_gpuobj *gpuobj; + int size; int bits; + struct nvkm_ramht_data data[]; }; -int nvkm_ramht_insert(struct nvkm_ramht *, int chid, u32 handle, u32 context); +int nvkm_ramht_new(struct nvkm_device *, u32 size, u32 align, + struct nvkm_gpuobj *, struct nvkm_ramht **); +void nvkm_ramht_del(struct nvkm_ramht **); +int nvkm_ramht_insert(struct nvkm_ramht *, struct nvkm_object *, + int chid, int addr, u32 handle, u32 context); void nvkm_ramht_remove(struct nvkm_ramht *, int cookie); -int nvkm_ramht_new(struct nvkm_object *, struct nvkm_object *, u32 size, - u32 align, struct nvkm_ramht **); - -static inline void -nvkm_ramht_ref(struct nvkm_ramht *obj, struct nvkm_ramht **ref) -{ - nvkm_gpuobj_ref(&obj->gpuobj, (struct nvkm_gpuobj **)ref); -} +struct nvkm_gpuobj * +nvkm_ramht_search(struct nvkm_ramht *, int chid, u32 handle); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index 6fdc39116..3b5dc9c63 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -1,119 +1,50 @@ #ifndef __NVKM_SUBDEV_H__ #define __NVKM_SUBDEV_H__ -#include -#include - -#define NV_SUBDEV_(sub,var) (NV_SUBDEV_CLASS | ((var) << 8) | (sub)) -#define NV_SUBDEV(name,var) NV_SUBDEV_(NVDEV_SUBDEV_##name, (var)) +#include struct nvkm_subdev { - struct nvkm_object object; + const struct nvkm_subdev_func *func; + struct nvkm_device *device; + enum nvkm_devidx index; + u32 pmc_enable; struct mutex mutex; - const char *name; - void __iomem *mmio; u32 debug; - u32 unit; - void (*intr)(struct nvkm_subdev *); + bool oneinit; }; -static inline struct nvkm_subdev * -nv_subdev(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_SUBDEV_CLASS))) - nv_assert("BAD CAST -> NvSubDev, %08x", nv_hclass(obj)); -#endif - return obj; -} - -static inline int -nv_subidx(struct nvkm_subdev *subdev) -{ - return nv_hclass(subdev) & 0xff; -} - -struct nvkm_subdev *nvkm_subdev(void *obj, int idx); - -#define nvkm_subdev_create(p,e,o,v,s,f,d) \ - nvkm_subdev_create_((p), (e), (o), (v), (s), (f), \ - sizeof(**d),(void **)d) +struct nvkm_subdev_func { + void *(*dtor)(struct nvkm_subdev *); + int (*preinit)(struct nvkm_subdev *); + int (*oneinit)(struct nvkm_subdev *); + int (*init)(struct nvkm_subdev *); + int (*fini)(struct nvkm_subdev *, bool suspend); + void (*intr)(struct nvkm_subdev *); +}; -int nvkm_subdev_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32 pclass, - const char *sname, const char *fname, - int size, void **); -void nvkm_subdev_destroy(struct nvkm_subdev *); +extern const char *nvkm_subdev_name[NVKM_SUBDEV_NR]; +void nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *, + int index, u32 pmc_enable, struct nvkm_subdev *); +void nvkm_subdev_del(struct nvkm_subdev **); +int nvkm_subdev_preinit(struct nvkm_subdev *); int nvkm_subdev_init(struct nvkm_subdev *); int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend); -void nvkm_subdev_reset(struct nvkm_object *); - -void _nvkm_subdev_dtor(struct nvkm_object *); -int _nvkm_subdev_init(struct nvkm_object *); -int _nvkm_subdev_fini(struct nvkm_object *, bool suspend); - -#define s_printk(s,l,f,a...) do { \ - if ((s)->debug >= OS_DBG_##l) { \ - nv_printk((s)->base.parent, (s)->name, l, f, ##a); \ +void nvkm_subdev_intr(struct nvkm_subdev *); + +/* subdev logging */ +#define nvkm_printk_(s,l,p,f,a...) do { \ + struct nvkm_subdev *_subdev = (s); \ + if (_subdev->debug >= (l)) { \ + dev_##p(_subdev->device->dev, "%s: "f, \ + nvkm_subdev_name[_subdev->index], ##a); \ } \ } while(0) - -static inline u8 -nv_rd08(void *obj, u32 addr) -{ - struct nvkm_subdev *subdev = nv_subdev(obj); - u8 data = ioread8(subdev->mmio + addr); - nv_spam(subdev, "nv_rd08 0x%06x 0x%02x\n", addr, data); - return data; -} - -static inline u16 -nv_rd16(void *obj, u32 addr) -{ - struct nvkm_subdev *subdev = nv_subdev(obj); - u16 data = ioread16_native(subdev->mmio + addr); - nv_spam(subdev, "nv_rd16 0x%06x 0x%04x\n", addr, data); - return data; -} - -static inline u32 -nv_rd32(void *obj, u32 addr) -{ - struct nvkm_subdev *subdev = nv_subdev(obj); - u32 data = ioread32_native(subdev->mmio + addr); - nv_spam(subdev, "nv_rd32 0x%06x 0x%08x\n", addr, data); - return data; -} - -static inline void -nv_wr08(void *obj, u32 addr, u8 data) -{ - struct nvkm_subdev *subdev = nv_subdev(obj); - nv_spam(subdev, "nv_wr08 0x%06x 0x%02x\n", addr, data); - iowrite8(data, subdev->mmio + addr); -} - -static inline void -nv_wr16(void *obj, u32 addr, u16 data) -{ - struct nvkm_subdev *subdev = nv_subdev(obj); - nv_spam(subdev, "nv_wr16 0x%06x 0x%04x\n", addr, data); - iowrite16_native(data, subdev->mmio + addr); -} - -static inline void -nv_wr32(void *obj, u32 addr, u32 data) -{ - struct nvkm_subdev *subdev = nv_subdev(obj); - nv_spam(subdev, "nv_wr32 0x%06x 0x%08x\n", addr, data); - iowrite32_native(data, subdev->mmio + addr); -} - -static inline u32 -nv_mask(void *obj, u32 addr, u32 mask, u32 data) -{ - u32 temp = nv_rd32(obj, addr); - nv_wr32(obj, addr, (temp & ~mask) | data); - return temp; -} +#define nvkm_printk(s,l,p,f,a...) nvkm_printk_((s), NV_DBG_##l, p, f, ##a) +#define nvkm_fatal(s,f,a...) nvkm_printk((s), FATAL, crit, f, ##a) +#define nvkm_error(s,f,a...) nvkm_printk((s), ERROR, err, f, ##a) +#define nvkm_warn(s,f,a...) nvkm_printk((s), WARN, notice, f, ##a) +#define nvkm_info(s,f,a...) nvkm_printk((s), INFO, info, f, ##a) +#define nvkm_debug(s,f,a...) nvkm_printk((s), DEBUG, info, f, ##a) +#define nvkm_trace(s,f,a...) nvkm_printk((s), TRACE, info, f, ##a) +#define nvkm_spam(s,f,a...) nvkm_printk((s), SPAM, dbg, f, ##a) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h new file mode 100644 index 000000000..16641cec1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h @@ -0,0 +1,46 @@ +#ifndef __NVKM_DEVICE_TEGRA_H__ +#define __NVKM_DEVICE_TEGRA_H__ +#include +#include + +struct nvkm_device_tegra { + const struct nvkm_device_tegra_func *func; + struct nvkm_device device; + struct platform_device *pdev; + int irq; + + struct reset_control *rst; + struct clk *clk; + struct clk *clk_pwr; + + struct regulator *vdd; + + struct { + /* + * Protects accesses to mm from subsystems + */ + struct mutex mutex; + + struct nvkm_mm mm; + struct iommu_domain *domain; + unsigned long pgshift; + } iommu; + + int gpu_speedo; +}; + +struct nvkm_device_tegra_func { + /* + * If an IOMMU is used, indicates which address bit will trigger a + * IOMMU translation when set (when this bit is not set, IOMMU is + * bypassed). A value of 0 means an IOMMU is never used. + */ + u8 iommu_bit; +}; + +int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *, + struct platform_device *, + const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h index e489beef2..904820558 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h @@ -1,5 +1,5 @@ #ifndef __NVKM_BSP_H__ #define __NVKM_BSP_H__ -#include -extern struct nvkm_oclass g84_bsp_oclass; +#include +int g84_bsp_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h index e832f729e..e2e22cd53 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h @@ -1,16 +1,9 @@ #ifndef __NVKM_CE_H__ #define __NVKM_CE_H__ -#include +#include -void gt215_ce_intr(struct nvkm_subdev *); - -extern struct nvkm_oclass gt215_ce_oclass; -extern struct nvkm_oclass gf100_ce0_oclass; -extern struct nvkm_oclass gf100_ce1_oclass; -extern struct nvkm_oclass gk104_ce0_oclass; -extern struct nvkm_oclass gk104_ce1_oclass; -extern struct nvkm_oclass gk104_ce2_oclass; -extern struct nvkm_oclass gm204_ce0_oclass; -extern struct nvkm_oclass gm204_ce1_oclass; -extern struct nvkm_oclass gm204_ce2_oclass; +int gt215_ce_new(struct nvkm_device *, int, struct nvkm_engine **); +int gf100_ce_new(struct nvkm_device *, int, struct nvkm_engine **); +int gk104_ce_new(struct nvkm_device *, int, struct nvkm_engine **); +int gm204_ce_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h index 57c29e91b..03fa57a7c 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h @@ -1,5 +1,5 @@ #ifndef __NVKM_CIPHER_H__ #define __NVKM_CIPHER_H__ #include -extern struct nvkm_oclass g84_cipher_oclass; +int g84_cipher_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/device.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/device.h deleted file mode 100644 index 5d4805e67..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/device.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __NOUVEAU_SUBDEV_DEVICE_H__ -#define __NOUVEAU_SUBDEV_DEVICE_H__ - -#include - -struct platform_device; - -enum nv_bus_type { - NOUVEAU_BUS_PCI, - NOUVEAU_BUS_PLATFORM, -}; - -#define nouveau_device_create(p,t,n,s,c,d,u) \ - nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d), \ - sizeof(**u), (void **)u) - -int nouveau_device_create_(void *, enum nv_bus_type type, u64 name, - const char *sname, const char *cfg, const char *dbg, - int, void **); - -int nv04_identify(struct nouveau_device *); -int nv10_identify(struct nouveau_device *); -int nv20_identify(struct nouveau_device *); -int nv30_identify(struct nouveau_device *); -int nv40_identify(struct nouveau_device *); -int nv50_identify(struct nouveau_device *); -int nvc0_identify(struct nouveau_device *); -int nve0_identify(struct nouveau_device *); -int gm100_identify(struct nouveau_device *); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index a5e1ed813..efc74d033 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -1,32 +1,35 @@ #ifndef __NVKM_DISP_H__ #define __NVKM_DISP_H__ +#define nvkm_disp(p) container_of((p), struct nvkm_disp, engine) #include #include struct nvkm_disp { - struct nvkm_engine base; + const struct nvkm_disp_func *func; + struct nvkm_engine engine; + + struct nvkm_oproxy *client; struct list_head outp; + struct list_head conn; struct nvkm_event hpd; struct nvkm_event vblank; -}; -static inline struct nvkm_disp * -nvkm_disp(void *obj) -{ - return (void *)nvkm_engine(obj, NVDEV_ENGINE_DISP); -} + struct { + int nr; + } head; +}; -extern struct nvkm_oclass *nv04_disp_oclass; -extern struct nvkm_oclass *nv50_disp_oclass; -extern struct nvkm_oclass *g84_disp_oclass; -extern struct nvkm_oclass *gt200_disp_oclass; -extern struct nvkm_oclass *g94_disp_oclass; -extern struct nvkm_oclass *gt215_disp_oclass; -extern struct nvkm_oclass *gf110_disp_oclass; -extern struct nvkm_oclass *gk104_disp_oclass; -extern struct nvkm_oclass *gk110_disp_oclass; -extern struct nvkm_oclass *gm107_disp_oclass; -extern struct nvkm_oclass *gm204_disp_oclass; +int nv04_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int nv50_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int g84_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gt200_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int g94_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gt215_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gf119_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gk104_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gk110_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gm107_disp_new(struct nvkm_device *, int, struct nvkm_disp **); +int gm204_disp_new(struct nvkm_device *, int, struct nvkm_disp **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h new file mode 100644 index 000000000..114bfb737 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h @@ -0,0 +1,32 @@ +#ifndef __NVKM_DMA_H__ +#define __NVKM_DMA_H__ +#include +struct nvkm_client; + +struct nvkm_dmaobj { + const struct nvkm_dmaobj_func *func; + struct nvkm_dma *dma; + + struct nvkm_object object; + u32 target; + u32 access; + u64 start; + u64 limit; + + struct rb_node rb; + u64 handle; /*XXX HANDLE MERGE */ +}; + +struct nvkm_dma { + const struct nvkm_dma_func *func; + struct nvkm_engine engine; +}; + +struct nvkm_dmaobj * +nvkm_dma_search(struct nvkm_dma *, struct nvkm_client *, u64 object); + +int nv04_dma_new(struct nvkm_device *, int, struct nvkm_dma **); +int nv50_dma_new(struct nvkm_device *, int, struct nvkm_dma **); +int gf100_dma_new(struct nvkm_device *, int, struct nvkm_dma **); +int gf119_dma_new(struct nvkm_device *, int, struct nvkm_dma **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dmaobj.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dmaobj.h deleted file mode 100644 index c4fce8afc..000000000 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/dmaobj.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __NVKM_DMAOBJ_H__ -#define __NVKM_DMAOBJ_H__ -#include -struct nvkm_gpuobj; - -struct nvkm_dmaobj { - struct nvkm_object base; - u32 target; - u32 access; - u64 start; - u64 limit; -}; - -struct nvkm_dmaeng { - struct nvkm_engine base; - - /* creates a "physical" dma object from a struct nvkm_dmaobj */ - int (*bind)(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, - struct nvkm_gpuobj **); -}; - -extern struct nvkm_oclass *nv04_dmaeng_oclass; -extern struct nvkm_oclass *nv50_dmaeng_oclass; -extern struct nvkm_oclass *gf100_dmaeng_oclass; -extern struct nvkm_oclass *gf110_dmaeng_oclass; -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index bd38cf913..81c0bc66a 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -1,41 +1,18 @@ #ifndef __NVKM_FALCON_H__ #define __NVKM_FALCON_H__ -#include - -struct nvkm_falcon_chan { - struct nvkm_engctx base; -}; - -#define nvkm_falcon_context_create(p,e,c,g,s,a,f,d) \ - nvkm_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) -#define nvkm_falcon_context_destroy(d) \ - nvkm_engctx_destroy(&(d)->base) -#define nvkm_falcon_context_init(d) \ - nvkm_engctx_init(&(d)->base) -#define nvkm_falcon_context_fini(d,s) \ - nvkm_engctx_fini(&(d)->base, (s)) - -#define _nvkm_falcon_context_ctor _nvkm_engctx_ctor -#define _nvkm_falcon_context_dtor _nvkm_engctx_dtor -#define _nvkm_falcon_context_init _nvkm_engctx_init -#define _nvkm_falcon_context_fini _nvkm_engctx_fini -#define _nvkm_falcon_context_rd32 _nvkm_engctx_rd32 -#define _nvkm_falcon_context_wr32 _nvkm_engctx_wr32 - -struct nvkm_falcon_data { - bool external; -}; - +#define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine) #include +struct nvkm_fifo_chan; struct nvkm_falcon { - struct nvkm_engine base; + const struct nvkm_falcon_func *func; + struct nvkm_engine engine; u32 addr; u8 version; u8 secret; - struct nvkm_gpuobj *core; + struct nvkm_memory *core; bool external; struct { @@ -51,31 +28,21 @@ struct nvkm_falcon { } data; }; -#define nv_falcon(priv) (&(priv)->base) - -#define nvkm_falcon_create(p,e,c,b,d,i,f,r) \ - nvkm_falcon_create_((p), (e), (c), (b), (d), (i), (f), \ - sizeof(**r),(void **)r) -#define nvkm_falcon_destroy(p) \ - nvkm_engine_destroy(&(p)->base) -#define nvkm_falcon_init(p) ({ \ - struct nvkm_falcon *falcon = (p); \ - _nvkm_falcon_init(nv_object(falcon)); \ -}) -#define nvkm_falcon_fini(p,s) ({ \ - struct nvkm_falcon *falcon = (p); \ - _nvkm_falcon_fini(nv_object(falcon), (s)); \ -}) - -int nvkm_falcon_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32, bool, const char *, - const char *, int, void **); +int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *, + int index, bool enable, u32 addr, struct nvkm_engine **); -void nvkm_falcon_intr(struct nvkm_subdev *subdev); - -#define _nvkm_falcon_dtor _nvkm_engine_dtor -int _nvkm_falcon_init(struct nvkm_object *); -int _nvkm_falcon_fini(struct nvkm_object *, bool); -u32 _nvkm_falcon_rd32(struct nvkm_object *, u64); -void _nvkm_falcon_wr32(struct nvkm_object *, u64, u32); +struct nvkm_falcon_func { + struct { + u32 *data; + u32 size; + } code; + struct { + u32 *data; + u32 size; + } data; + u32 pmc_enable; + void (*init)(struct nvkm_falcon *); + void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *); + struct nvkm_sclass sclass[]; +}; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 97cdeab8e..9e6644955 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -1,127 +1,67 @@ #ifndef __NVKM_FIFO_H__ #define __NVKM_FIFO_H__ -#include +#include +#include + +#define NVKM_FIFO_CHID_NR 4096 + +struct nvkm_fifo_engn { + struct nvkm_object *object; + int refcount; + int usecount; +}; struct nvkm_fifo_chan { - struct nvkm_namedb namedb; - struct nvkm_dmaobj *pushdma; - struct nvkm_gpuobj *pushgpu; + const struct nvkm_fifo_chan_func *func; + struct nvkm_fifo *fifo; + u64 engines; + struct nvkm_object object; + + struct list_head head; + u16 chid; + struct nvkm_gpuobj *inst; + struct nvkm_gpuobj *push; + struct nvkm_vm *vm; void __iomem *user; u64 addr; u32 size; - u16 chid; - atomic_t refcnt; /* NV04_NVSW_SET_REF */ -}; - -static inline struct nvkm_fifo_chan * -nvkm_fifo_chan(void *obj) -{ - return (void *)nv_namedb(obj); -} - -#define nvkm_fifo_channel_create(p,e,c,b,a,s,n,m,d) \ - nvkm_fifo_channel_create_((p), (e), (c), (b), (a), (s), (n), \ - (m), sizeof(**d), (void **)d) -#define nvkm_fifo_channel_init(p) \ - nvkm_namedb_init(&(p)->namedb) -#define nvkm_fifo_channel_fini(p,s) \ - nvkm_namedb_fini(&(p)->namedb, (s)) - -int nvkm_fifo_channel_create_(struct nvkm_object *, - struct nvkm_object *, - struct nvkm_oclass *, - int bar, u32 addr, u32 size, u32 push, - u64 engmask, int len, void **); -void nvkm_fifo_channel_destroy(struct nvkm_fifo_chan *); -#define _nvkm_fifo_channel_init _nvkm_namedb_init -#define _nvkm_fifo_channel_fini _nvkm_namedb_fini - -void _nvkm_fifo_channel_dtor(struct nvkm_object *); -int _nvkm_fifo_channel_map(struct nvkm_object *, u64 *, u32 *); -u32 _nvkm_fifo_channel_rd32(struct nvkm_object *, u64); -void _nvkm_fifo_channel_wr32(struct nvkm_object *, u64, u32); -int _nvkm_fifo_channel_ntfy(struct nvkm_object *, u32, struct nvkm_event **); - -#include - -struct nvkm_fifo_base { - struct nvkm_gpuobj gpuobj; + struct nvkm_fifo_engn engn[NVKM_SUBDEV_NR]; }; -#define nvkm_fifo_context_create(p,e,c,g,s,a,f,d) \ - nvkm_gpuobj_create((p), (e), (c), 0, (g), (s), (a), (f), (d)) -#define nvkm_fifo_context_destroy(p) \ - nvkm_gpuobj_destroy(&(p)->gpuobj) -#define nvkm_fifo_context_init(p) \ - nvkm_gpuobj_init(&(p)->gpuobj) -#define nvkm_fifo_context_fini(p,s) \ - nvkm_gpuobj_fini(&(p)->gpuobj, (s)) - -#define _nvkm_fifo_context_dtor _nvkm_gpuobj_dtor -#define _nvkm_fifo_context_init _nvkm_gpuobj_init -#define _nvkm_fifo_context_fini _nvkm_gpuobj_fini -#define _nvkm_fifo_context_rd32 _nvkm_gpuobj_rd32 -#define _nvkm_fifo_context_wr32 _nvkm_gpuobj_wr32 - -#include -#include - struct nvkm_fifo { - struct nvkm_engine base; + const struct nvkm_fifo_func *func; + struct nvkm_engine engine; - struct nvkm_event cevent; /* channel creation event */ - struct nvkm_event uevent; /* async user trigger */ - - struct nvkm_object **channel; + DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR); + int nr; + struct list_head chan; spinlock_t lock; - u16 min; - u16 max; - int (*chid)(struct nvkm_fifo *, struct nvkm_object *); - void (*pause)(struct nvkm_fifo *, unsigned long *); - void (*start)(struct nvkm_fifo *, unsigned long *); + struct nvkm_event uevent; /* async user trigger */ + struct nvkm_event cevent; /* channel creation event */ }; -static inline struct nvkm_fifo * -nvkm_fifo(void *obj) -{ - return (void *)nvkm_engine(obj, NVDEV_ENGINE_FIFO); -} - -#define nvkm_fifo_create(o,e,c,fc,lc,d) \ - nvkm_fifo_create_((o), (e), (c), (fc), (lc), sizeof(**d), (void **)d) -#define nvkm_fifo_init(p) \ - nvkm_engine_init(&(p)->base) -#define nvkm_fifo_fini(p,s) \ - nvkm_engine_fini(&(p)->base, (s)) - -int nvkm_fifo_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int min, int max, - int size, void **); -void nvkm_fifo_destroy(struct nvkm_fifo *); -const char * -nvkm_client_name_for_fifo_chid(struct nvkm_fifo *fifo, u32 chid); - -#define _nvkm_fifo_init _nvkm_engine_init -#define _nvkm_fifo_fini _nvkm_engine_fini - -extern struct nvkm_oclass *nv04_fifo_oclass; -extern struct nvkm_oclass *nv10_fifo_oclass; -extern struct nvkm_oclass *nv17_fifo_oclass; -extern struct nvkm_oclass *nv40_fifo_oclass; -extern struct nvkm_oclass *nv50_fifo_oclass; -extern struct nvkm_oclass *g84_fifo_oclass; -extern struct nvkm_oclass *gf100_fifo_oclass; -extern struct nvkm_oclass *gk104_fifo_oclass; -extern struct nvkm_oclass *gk20a_fifo_oclass; -extern struct nvkm_oclass *gk208_fifo_oclass; -extern struct nvkm_oclass *gm204_fifo_oclass; - -int nvkm_fifo_uevent_ctor(struct nvkm_object *, void *, u32, - struct nvkm_notify *); -void nvkm_fifo_uevent(struct nvkm_fifo *); - -void nv04_fifo_intr(struct nvkm_subdev *); -int nv04_fifo_context_attach(struct nvkm_object *, struct nvkm_object *); +void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *); +void nvkm_fifo_start(struct nvkm_fifo *, unsigned long *); + +void nvkm_fifo_chan_put(struct nvkm_fifo *, unsigned long flags, + struct nvkm_fifo_chan **); +struct nvkm_fifo_chan * +nvkm_fifo_chan_inst(struct nvkm_fifo *, u64 inst, unsigned long *flags); +struct nvkm_fifo_chan * +nvkm_fifo_chan_chid(struct nvkm_fifo *, int chid, unsigned long *flags); + +int nv04_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int nv10_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int nv17_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int nv40_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int nv50_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int g84_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int gf100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int gk104_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int gk208_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int gk20a_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int gm204_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); +int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h index 7cbe20280..f126e54d2 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h @@ -1,88 +1,46 @@ #ifndef __NVKM_GR_H__ #define __NVKM_GR_H__ -#include - -struct nvkm_gr_chan { - struct nvkm_engctx base; -}; - -#define nvkm_gr_context_create(p,e,c,g,s,a,f,d) \ - nvkm_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) -#define nvkm_gr_context_destroy(d) \ - nvkm_engctx_destroy(&(d)->base) -#define nvkm_gr_context_init(d) \ - nvkm_engctx_init(&(d)->base) -#define nvkm_gr_context_fini(d,s) \ - nvkm_engctx_fini(&(d)->base, (s)) - -#define _nvkm_gr_context_dtor _nvkm_engctx_dtor -#define _nvkm_gr_context_init _nvkm_engctx_init -#define _nvkm_gr_context_fini _nvkm_engctx_fini -#define _nvkm_gr_context_rd32 _nvkm_engctx_rd32 -#define _nvkm_gr_context_wr32 _nvkm_engctx_wr32 - #include struct nvkm_gr { - struct nvkm_engine base; - - /* Returns chipset-specific counts of units packed into an u64. - */ - u64 (*units)(struct nvkm_gr *); + const struct nvkm_gr_func *func; + struct nvkm_engine engine; }; -static inline struct nvkm_gr * -nvkm_gr(void *obj) -{ - return (void *)nvkm_engine(obj, NVDEV_ENGINE_GR); -} - -#define nvkm_gr_create(p,e,c,y,d) \ - nvkm_engine_create((p), (e), (c), (y), "PGRAPH", "graphics", (d)) -#define nvkm_gr_destroy(d) \ - nvkm_engine_destroy(&(d)->base) -#define nvkm_gr_init(d) \ - nvkm_engine_init(&(d)->base) -#define nvkm_gr_fini(d,s) \ - nvkm_engine_fini(&(d)->base, (s)) - -#define _nvkm_gr_dtor _nvkm_engine_dtor -#define _nvkm_gr_init _nvkm_engine_init -#define _nvkm_gr_fini _nvkm_engine_fini - -extern struct nvkm_oclass nv04_gr_oclass; -extern struct nvkm_oclass nv10_gr_oclass; -extern struct nvkm_oclass nv20_gr_oclass; -extern struct nvkm_oclass nv25_gr_oclass; -extern struct nvkm_oclass nv2a_gr_oclass; -extern struct nvkm_oclass nv30_gr_oclass; -extern struct nvkm_oclass nv34_gr_oclass; -extern struct nvkm_oclass nv35_gr_oclass; -extern struct nvkm_oclass nv40_gr_oclass; -extern struct nvkm_oclass nv50_gr_oclass; -extern struct nvkm_oclass *gf100_gr_oclass; -extern struct nvkm_oclass *gf108_gr_oclass; -extern struct nvkm_oclass *gf104_gr_oclass; -extern struct nvkm_oclass *gf110_gr_oclass; -extern struct nvkm_oclass *gf117_gr_oclass; -extern struct nvkm_oclass *gf119_gr_oclass; -extern struct nvkm_oclass *gk104_gr_oclass; -extern struct nvkm_oclass *gk20a_gr_oclass; -extern struct nvkm_oclass *gk110_gr_oclass; -extern struct nvkm_oclass *gk110b_gr_oclass; -extern struct nvkm_oclass *gk208_gr_oclass; -extern struct nvkm_oclass *gm107_gr_oclass; -extern struct nvkm_oclass *gm204_gr_oclass; -extern struct nvkm_oclass *gm206_gr_oclass; - -#include - -extern const struct nvkm_bitfield nv04_gr_nsource[]; -extern struct nvkm_ofuncs nv04_gr_ofuncs; -bool nv04_gr_idle(void *obj); - -extern const struct nvkm_bitfield nv10_gr_intr_name[]; -extern const struct nvkm_bitfield nv10_gr_nstatus[]; - -extern const struct nvkm_enum nv50_data_error_names[]; +u64 nvkm_gr_units(struct nvkm_gr *); +int nvkm_gr_tlb_flush(struct nvkm_gr *); + +int nv04_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv10_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv15_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv17_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv20_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv25_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv2a_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv30_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv34_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv35_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv40_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv44_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int nv50_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int g84_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gt200_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int mcp79_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gt215_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int mcp89_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gf100_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gf104_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gf108_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gf110_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gf117_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gf119_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gk104_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gk110_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gk110b_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gk208_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gk20a_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gm107_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gm204_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gm206_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gm20b_gr_new(struct nvkm_device *, int, struct nvkm_gr **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h index 4e500b398..257738eff 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h @@ -1,62 +1,9 @@ #ifndef __NVKM_MPEG_H__ #define __NVKM_MPEG_H__ -#include - -struct nvkm_mpeg_chan { - struct nvkm_engctx base; -}; - -#define nvkm_mpeg_context_create(p,e,c,g,s,a,f,d) \ - nvkm_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) -#define nvkm_mpeg_context_destroy(d) \ - nvkm_engctx_destroy(&(d)->base) -#define nvkm_mpeg_context_init(d) \ - nvkm_engctx_init(&(d)->base) -#define nvkm_mpeg_context_fini(d,s) \ - nvkm_engctx_fini(&(d)->base, (s)) - -#define _nvkm_mpeg_context_dtor _nvkm_engctx_dtor -#define _nvkm_mpeg_context_init _nvkm_engctx_init -#define _nvkm_mpeg_context_fini _nvkm_engctx_fini -#define _nvkm_mpeg_context_rd32 _nvkm_engctx_rd32 -#define _nvkm_mpeg_context_wr32 _nvkm_engctx_wr32 - #include - -struct nvkm_mpeg { - struct nvkm_engine base; -}; - -#define nvkm_mpeg_create(p,e,c,d) \ - nvkm_engine_create((p), (e), (c), true, "PMPEG", "mpeg", (d)) -#define nvkm_mpeg_destroy(d) \ - nvkm_engine_destroy(&(d)->base) -#define nvkm_mpeg_init(d) \ - nvkm_engine_init(&(d)->base) -#define nvkm_mpeg_fini(d,s) \ - nvkm_engine_fini(&(d)->base, (s)) - -#define _nvkm_mpeg_dtor _nvkm_engine_dtor -#define _nvkm_mpeg_init _nvkm_engine_init -#define _nvkm_mpeg_fini _nvkm_engine_fini - -extern struct nvkm_oclass nv31_mpeg_oclass; -extern struct nvkm_oclass nv40_mpeg_oclass; -extern struct nvkm_oclass nv44_mpeg_oclass; -extern struct nvkm_oclass nv50_mpeg_oclass; -extern struct nvkm_oclass g84_mpeg_oclass; -extern struct nvkm_ofuncs nv31_mpeg_ofuncs; -extern struct nvkm_oclass nv31_mpeg_cclass; -extern struct nvkm_oclass nv31_mpeg_sclass[]; -extern struct nvkm_oclass nv40_mpeg_sclass[]; -void nv31_mpeg_intr(struct nvkm_subdev *); -void nv31_mpeg_tile_prog(struct nvkm_engine *, int); -int nv31_mpeg_init(struct nvkm_object *); - -extern struct nvkm_ofuncs nv50_mpeg_ofuncs; -int nv50_mpeg_context_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv50_mpeg_intr(struct nvkm_subdev *); -int nv50_mpeg_init(struct nvkm_object *); +int nv31_mpeg_new(struct nvkm_device *, int index, struct nvkm_engine **); +int nv40_mpeg_new(struct nvkm_device *, int index, struct nvkm_engine **); +int nv44_mpeg_new(struct nvkm_device *, int index, struct nvkm_engine **); +int nv50_mpeg_new(struct nvkm_device *, int index, struct nvkm_engine **); +int g84_mpeg_new(struct nvkm_device *, int index, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h index 54b7672ee..08516ca82 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h @@ -1,7 +1,8 @@ #ifndef __NVKM_MSPDEC_H__ #define __NVKM_MSPDEC_H__ -#include -extern struct nvkm_oclass g98_mspdec_oclass; -extern struct nvkm_oclass gf100_mspdec_oclass; -extern struct nvkm_oclass gk104_mspdec_oclass; +#include +int g98_mspdec_new(struct nvkm_device *, int, struct nvkm_engine **); +int gt215_mspdec_new(struct nvkm_device *, int, struct nvkm_engine **); +int gf100_mspdec_new(struct nvkm_device *, int, struct nvkm_engine **); +int gk104_mspdec_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h index c6c69d0a8..85fd30602 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h @@ -1,6 +1,7 @@ #ifndef __NVKM_MSPPP_H__ #define __NVKM_MSPPP_H__ -#include -extern struct nvkm_oclass g98_msppp_oclass; -extern struct nvkm_oclass gf100_msppp_oclass; +#include +int g98_msppp_new(struct nvkm_device *, int, struct nvkm_engine **); +int gt215_msppp_new(struct nvkm_device *, int, struct nvkm_engine **); +int gf100_msppp_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h index 1f193b7bd..99757ed96 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h @@ -1,7 +1,9 @@ #ifndef __NVKM_MSVLD_H__ #define __NVKM_MSVLD_H__ -#include -extern struct nvkm_oclass g98_msvld_oclass; -extern struct nvkm_oclass gf100_msvld_oclass; -extern struct nvkm_oclass gk104_msvld_oclass; +#include +int g98_msvld_new(struct nvkm_device *, int, struct nvkm_engine **); +int gt215_msvld_new(struct nvkm_device *, int, struct nvkm_engine **); +int mcp89_msvld_new(struct nvkm_device *, int, struct nvkm_engine **); +int gf100_msvld_new(struct nvkm_device *, int, struct nvkm_engine **); +int gk104_msvld_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h index 93181bbf0..240855ad8 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h @@ -2,33 +2,24 @@ #define __NVKM_PM_H__ #include -struct nvkm_perfdom; -struct nvkm_perfctr; struct nvkm_pm { - struct nvkm_engine base; + const struct nvkm_pm_func *func; + struct nvkm_engine engine; - struct nvkm_perfctx *context; - void *profile_data; + struct nvkm_object *perfmon; struct list_head domains; + struct list_head sources; u32 sequence; - - /*XXX: temp for daemon backend */ - u32 pwr[8]; - u32 last; }; -static inline struct nvkm_pm * -nvkm_pm(void *obj) -{ - return (void *)nvkm_engine(obj, NVDEV_ENGINE_PM); -} - -extern struct nvkm_oclass *nv40_pm_oclass; -extern struct nvkm_oclass *nv50_pm_oclass; -extern struct nvkm_oclass *g84_pm_oclass; -extern struct nvkm_oclass *gt215_pm_oclass; -extern struct nvkm_oclass gf100_pm_oclass; -extern struct nvkm_oclass gk104_pm_oclass; -extern struct nvkm_oclass gk110_pm_oclass; +int nv40_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int nv50_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int g84_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int gt200_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int gt215_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int gf100_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int gf108_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int gf117_pm_new(struct nvkm_device *, int, struct nvkm_pm **); +int gk104_pm_new(struct nvkm_device *, int, struct nvkm_pm **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h index 44590a2a4..7317ef4c0 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h @@ -1,5 +1,5 @@ #ifndef __NVKM_SEC_H__ #define __NVKM_SEC_H__ -#include -extern struct nvkm_oclass g98_sec_oclass; +#include +int g98_sec_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h index a529013c9..096e7dbd1 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h @@ -1,50 +1,18 @@ #ifndef __NVKM_SW_H__ #define __NVKM_SW_H__ -#include - -struct nvkm_sw_chan { - struct nvkm_engctx base; - - int (*flip)(void *); - void *flip_data; -}; - -#define nvkm_sw_context_create(p,e,c,d) \ - nvkm_engctx_create((p), (e), (c), (p), 0, 0, 0, (d)) -#define nvkm_sw_context_destroy(d) \ - nvkm_engctx_destroy(&(d)->base) -#define nvkm_sw_context_init(d) \ - nvkm_engctx_init(&(d)->base) -#define nvkm_sw_context_fini(d,s) \ - nvkm_engctx_fini(&(d)->base, (s)) - -#define _nvkm_sw_context_dtor _nvkm_engctx_dtor -#define _nvkm_sw_context_init _nvkm_engctx_init -#define _nvkm_sw_context_fini _nvkm_engctx_fini - #include struct nvkm_sw { - struct nvkm_engine base; -}; + const struct nvkm_sw_func *func; + struct nvkm_engine engine; -#define nvkm_sw_create(p,e,c,d) \ - nvkm_engine_create((p), (e), (c), true, "SW", "software", (d)) -#define nvkm_sw_destroy(d) \ - nvkm_engine_destroy(&(d)->base) -#define nvkm_sw_init(d) \ - nvkm_engine_init(&(d)->base) -#define nvkm_sw_fini(d,s) \ - nvkm_engine_fini(&(d)->base, (s)) - -#define _nvkm_sw_dtor _nvkm_engine_dtor -#define _nvkm_sw_init _nvkm_engine_init -#define _nvkm_sw_fini _nvkm_engine_fini + struct list_head chan; +}; -extern struct nvkm_oclass *nv04_sw_oclass; -extern struct nvkm_oclass *nv10_sw_oclass; -extern struct nvkm_oclass *nv50_sw_oclass; -extern struct nvkm_oclass *gf100_sw_oclass; +bool nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data); -void nv04_sw_intr(struct nvkm_subdev *); +int nv04_sw_new(struct nvkm_device *, int, struct nvkm_sw **); +int nv10_sw_new(struct nvkm_device *, int, struct nvkm_sw **); +int nv50_sw_new(struct nvkm_device *, int, struct nvkm_sw **); +int gf100_sw_new(struct nvkm_device *, int, struct nvkm_sw **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h index 7851f18c5..616ea91e0 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h @@ -1,5 +1,5 @@ #ifndef __NVKM_VP_H__ #define __NVKM_VP_H__ -#include -extern struct nvkm_oclass g84_vp_oclass; +#include +int g84_vp_new(struct nvkm_device *, int, struct nvkm_engine **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h index 7a216cca2..3128d21a5 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h @@ -1,35 +1,23 @@ #ifndef __NVKM_XTENSA_H__ #define __NVKM_XTENSA_H__ +#define nvkm_xtensa(p) container_of((p), struct nvkm_xtensa, engine) #include -struct nvkm_gpuobj; struct nvkm_xtensa { - struct nvkm_engine base; - + const struct nvkm_xtensa_func *func; u32 addr; - struct nvkm_gpuobj *gpu_fw; - u32 fifo_val; - u32 unkd28; -}; + struct nvkm_engine engine; -#define nvkm_xtensa_create(p,e,c,b,d,i,f,r) \ - nvkm_xtensa_create_((p), (e), (c), (b), (d), (i), (f), \ - sizeof(**r),(void **)r) + struct nvkm_memory *gpu_fw; +}; -int _nvkm_xtensa_engctx_ctor(struct nvkm_object *, - struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); +int nvkm_xtensa_new_(const struct nvkm_xtensa_func *, struct nvkm_device *, + int index, bool enable, u32 addr, struct nvkm_engine **); -void _nvkm_xtensa_intr(struct nvkm_subdev *); -int nvkm_xtensa_create_(struct nvkm_object *, - struct nvkm_object *, - struct nvkm_oclass *, u32, bool, - const char *, const char *, - int, void **); -#define _nvkm_xtensa_dtor _nvkm_engine_dtor -int _nvkm_xtensa_init(struct nvkm_object *); -int _nvkm_xtensa_fini(struct nvkm_object *, bool); -u32 _nvkm_xtensa_rd32(struct nvkm_object *, u64); -void _nvkm_xtensa_wr32(struct nvkm_object *, u64, u32); +struct nvkm_xtensa_func { + u32 pmc_enable; + u32 fifo_val; + u32 unkd28; + struct nvkm_sclass sclass[]; +}; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h index c7a007b8b..d3071b5a4 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h @@ -1,33 +1,24 @@ #ifndef __NVKM_BAR_H__ #define __NVKM_BAR_H__ #include -struct nvkm_mem; struct nvkm_vma; struct nvkm_bar { - struct nvkm_subdev base; + const struct nvkm_bar_func *func; + struct nvkm_subdev subdev; - int (*alloc)(struct nvkm_bar *, struct nvkm_object *, - struct nvkm_mem *, struct nvkm_object **); - - int (*kmap)(struct nvkm_bar *, struct nvkm_mem *, u32 flags, - struct nvkm_vma *); - int (*umap)(struct nvkm_bar *, struct nvkm_mem *, u32 flags, - struct nvkm_vma *); - void (*unmap)(struct nvkm_bar *, struct nvkm_vma *); - void (*flush)(struct nvkm_bar *); + spinlock_t lock; /* whether the BAR supports to be ioremapped WC or should be uncached */ bool iomap_uncached; }; -static inline struct nvkm_bar * -nvkm_bar(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_BAR); -} +void nvkm_bar_flush(struct nvkm_bar *); +struct nvkm_vm *nvkm_bar_kmap(struct nvkm_bar *); +int nvkm_bar_umap(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *); -extern struct nvkm_oclass nv50_bar_oclass; -extern struct nvkm_oclass gf100_bar_oclass; -extern struct nvkm_oclass gk20a_bar_oclass; +int nv50_bar_new(struct nvkm_device *, int, struct nvkm_bar **); +int g84_bar_new(struct nvkm_device *, int, struct nvkm_bar **); +int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **); +int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h index cef287e0b..e39a1fea9 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h @@ -3,7 +3,7 @@ #include struct nvkm_bios { - struct nvkm_subdev base; + struct nvkm_subdev subdev; u32 size; u8 *data; @@ -19,14 +19,13 @@ struct nvkm_bios { } version; }; -static inline struct nvkm_bios * -nvkm_bios(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_VBIOS); -} - u8 nvbios_checksum(const u8 *data, int size); u16 nvbios_findstr(const u8 *data, int size, const char *str, int len); +int nvbios_memcmp(struct nvkm_bios *, u32 addr, const char *, u32 len); + +#define nvbios_rd08(b,o) (b)->data[(o)] +#define nvbios_rd16(b,o) get_unaligned_le16(&(b)->data[(o)]) +#define nvbios_rd32(b,o) get_unaligned_le32(&(b)->data[(o)]) -extern struct nvkm_oclass nvkm_bios_oclass; +int nvkm_bios_new(struct nvkm_device *, int, struct nvkm_bios **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h index 4107aa546..3f0c7c414 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h @@ -4,8 +4,8 @@ static inline u16 bmp_version(struct nvkm_bios *bios) { if (bios->bmp_offset) { - return nv_ro08(bios, bios->bmp_offset + 5) << 8 | - nv_ro08(bios, bios->bmp_offset + 6); + return nvbios_rd08(bios, bios->bmp_offset + 5) << 8 | + nvbios_rd08(bios, bios->bmp_offset + 6); } return 0x0000; @@ -15,7 +15,7 @@ static inline u16 bmp_mem_init_table(struct nvkm_bios *bios) { if (bmp_version(bios) >= 0x0300) - return nv_ro16(bios, bios->bmp_offset + 24); + return nvbios_rd16(bios, bios->bmp_offset + 24); return 0x0000; } @@ -23,7 +23,7 @@ static inline u16 bmp_sdr_seq_table(struct nvkm_bios *bios) { if (bmp_version(bios) >= 0x0300) - return nv_ro16(bios, bios->bmp_offset + 26); + return nvbios_rd16(bios, bios->bmp_offset + 26); return 0x0000; } @@ -31,7 +31,7 @@ static inline u16 bmp_ddr_seq_table(struct nvkm_bios *bios) { if (bmp_version(bios) >= 0x0300) - return nv_ro16(bios, bios->bmp_offset + 28); + return nvbios_rd16(bios, bios->bmp_offset + 28); return 0x0000; } #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h index 33be260dd..a47d46dda 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h @@ -15,6 +15,7 @@ enum dcb_gpio_func_name { DCB_GPIO_VID5 = 0x74, DCB_GPIO_VID6 = 0x75, DCB_GPIO_VID7 = 0x76, + DCB_GPIO_VID_PWM = 0x81, }; #define DCB_GPIO_LOG_DIR 0x02 diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h index 578a667ee..4dc1c8af8 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h @@ -1,5 +1,6 @@ #ifndef __NVBIOS_INIT_H__ #define __NVBIOS_INIT_H__ + struct nvbios_init { struct nvkm_subdev *subdev; struct nvkm_bios *bios; diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h index d606875c1..3a643df6d 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h @@ -4,8 +4,6 @@ struct nvbios_pmuT { }; u32 nvbios_pmuTe(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); -u32 nvbios_pmuTp(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, - struct nvbios_pmuT *); struct nvbios_pmuE { u8 type; diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h index 420426793..dca6c060a 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h @@ -6,6 +6,11 @@ struct nvbios_ramcfg { unsigned rammap_min; unsigned rammap_max; union { + struct { + unsigned rammap_00_16_20:1; + unsigned rammap_00_16_40:1; + unsigned rammap_00_17_02:1; + }; struct { unsigned rammap_10_04_02:1; unsigned rammap_10_04_08:1; @@ -32,7 +37,26 @@ struct nvbios_ramcfg { unsigned ramcfg_ver; unsigned ramcfg_hdr; unsigned ramcfg_timing; + unsigned ramcfg_DLLoff; + unsigned ramcfg_RON; + unsigned ramcfg_FBVDDQ; union { + struct { + unsigned ramcfg_00_03_01:1; + unsigned ramcfg_00_03_02:1; + unsigned ramcfg_00_03_08:1; + unsigned ramcfg_00_03_10:1; + unsigned ramcfg_00_04_02:1; + unsigned ramcfg_00_04_04:1; + unsigned ramcfg_00_04_20:1; + unsigned ramcfg_00_05:8; + unsigned ramcfg_00_06:8; + unsigned ramcfg_00_07:8; + unsigned ramcfg_00_08:8; + unsigned ramcfg_00_09:8; + unsigned ramcfg_00_0a_0f:4; + unsigned ramcfg_00_0a_f0:4; + }; struct { unsigned ramcfg_10_02_01:1; unsigned ramcfg_10_02_02:1; @@ -40,7 +64,6 @@ struct nvbios_ramcfg { unsigned ramcfg_10_02_08:1; unsigned ramcfg_10_02_10:1; unsigned ramcfg_10_02_20:1; - unsigned ramcfg_10_DLLoff:1; unsigned ramcfg_10_03_0f:4; unsigned ramcfg_10_04_01:1; unsigned ramcfg_10_05:8; @@ -56,7 +79,6 @@ struct nvbios_ramcfg { unsigned ramcfg_11_01_04:1; unsigned ramcfg_11_01_08:1; unsigned ramcfg_11_01_10:1; - unsigned ramcfg_11_01_20:1; unsigned ramcfg_11_01_40:1; unsigned ramcfg_11_01_80:1; unsigned ramcfg_11_02_03:2; diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h index 609a905ec..8d8ee1372 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h @@ -7,6 +7,8 @@ u32 nvbios_rammapTe(struct nvkm_bios *, u8 *ver, u8 *hdr, u32 nvbios_rammapEe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u32 nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, + struct nvbios_ramcfg *p); u32 nvbios_rammapEp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *); u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz, @@ -15,6 +17,8 @@ u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz, u32 nvbios_rammapSe(struct nvkm_bios *, u32 data, u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, u8 *ver, u8 *hdr); +u32 nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, + struct nvbios_ramcfg *p); u32 nvbios_rammapSp(struct nvkm_bios *, u32 data, u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, u8 *ver, u8 *hdr, struct nvbios_ramcfg *); diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h index eb2de4b85..b0df610ce 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h @@ -1,11 +1,24 @@ #ifndef __NVBIOS_VOLT_H__ #define __NVBIOS_VOLT_H__ + +enum nvbios_volt_type { + NVBIOS_VOLT_GPIO = 0, + NVBIOS_VOLT_PWM, +}; + struct nvbios_volt { - u8 vidmask; + enum nvbios_volt_type type; u32 min; u32 max; u32 base; + + /* GPIO mode */ + u8 vidmask; s16 step; + + /* PWM mode */ + u32 pwm_freq; + u32 pwm_range; }; u16 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h index fba83c048..33a057c33 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h @@ -2,49 +2,24 @@ #define __NVKM_BUS_H__ #include -struct nvkm_bus_intr { - u32 stat; - u32 unit; -}; - struct nvkm_bus { - struct nvkm_subdev base; - int (*hwsq_exec)(struct nvkm_bus *, u32 *, u32); - u32 hwsq_size; + const struct nvkm_bus_func *func; + struct nvkm_subdev subdev; }; -static inline struct nvkm_bus * -nvkm_bus(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_BUS); -} - -#define nvkm_bus_create(p, e, o, d) \ - nvkm_subdev_create_((p), (e), (o), 0, "PBUS", "master", \ - sizeof(**d), (void **)d) -#define nvkm_bus_destroy(p) \ - nvkm_subdev_destroy(&(p)->base) -#define nvkm_bus_init(p) \ - nvkm_subdev_init(&(p)->base) -#define nvkm_bus_fini(p, s) \ - nvkm_subdev_fini(&(p)->base, (s)) - -#define _nvkm_bus_dtor _nvkm_subdev_dtor -#define _nvkm_bus_init _nvkm_subdev_init -#define _nvkm_bus_fini _nvkm_subdev_fini - -extern struct nvkm_oclass *nv04_bus_oclass; -extern struct nvkm_oclass *nv31_bus_oclass; -extern struct nvkm_oclass *nv50_bus_oclass; -extern struct nvkm_oclass *g94_bus_oclass; -extern struct nvkm_oclass *gf100_bus_oclass; - /* interface to sequencer */ struct nvkm_hwsq; -int nvkm_hwsq_init(struct nvkm_bus *, struct nvkm_hwsq **); +int nvkm_hwsq_init(struct nvkm_subdev *, struct nvkm_hwsq **); int nvkm_hwsq_fini(struct nvkm_hwsq **, bool exec); void nvkm_hwsq_wr32(struct nvkm_hwsq *, u32 addr, u32 data); void nvkm_hwsq_setf(struct nvkm_hwsq *, u8 flag, int data); void nvkm_hwsq_wait(struct nvkm_hwsq *, u8 flag, u8 data); +void nvkm_hwsq_wait_vblank(struct nvkm_hwsq *); void nvkm_hwsq_nsec(struct nvkm_hwsq *, u32 nsec); + +int nv04_bus_new(struct nvkm_device *, int, struct nvkm_bus **); +int nv31_bus_new(struct nvkm_device *, int, struct nvkm_bus **); +int nv50_bus_new(struct nvkm_device *, int, struct nvkm_bus **); +int g94_bus_new(struct nvkm_device *, int, struct nvkm_bus **); +int gf100_bus_new(struct nvkm_device *, int, struct nvkm_bus **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index f5d303850..8708f0a4e 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h @@ -71,9 +71,10 @@ struct nvkm_domain { }; struct nvkm_clk { - struct nvkm_subdev base; + const struct nvkm_clk_func *func; + struct nvkm_subdev subdev; - struct nvkm_domain *domains; + const struct nvkm_domain *domains; struct nvkm_pstate bstate; struct list_head states; @@ -94,68 +95,27 @@ struct nvkm_clk { bool allow_reclock; - int (*read)(struct nvkm_clk *, enum nv_clk_src); - int (*calc)(struct nvkm_clk *, struct nvkm_cstate *); - int (*prog)(struct nvkm_clk *); - void (*tidy)(struct nvkm_clk *); - /*XXX: die, these are here *only* to support the completely - * bat-shit insane what-was-nvkm_hw.c code + * bat-shit insane what-was-nouveau_hw.c code */ int (*pll_calc)(struct nvkm_clk *, struct nvbios_pll *, int clk, struct nvkm_pll_vals *pv); int (*pll_prog)(struct nvkm_clk *, u32 reg1, struct nvkm_pll_vals *pv); }; -static inline struct nvkm_clk * -nvkm_clk(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_CLK); -} - -#define nvkm_clk_create(p,e,o,i,r,s,n,d) \ - nvkm_clk_create_((p), (e), (o), (i), (r), (s), (n), sizeof(**d), \ - (void **)d) -#define nvkm_clk_destroy(p) ({ \ - struct nvkm_clk *clk = (p); \ - _nvkm_clk_dtor(nv_object(clk)); \ -}) -#define nvkm_clk_init(p) ({ \ - struct nvkm_clk *clk = (p); \ - _nvkm_clk_init(nv_object(clk)); \ -}) -#define nvkm_clk_fini(p,s) ({ \ - struct nvkm_clk *clk = (p); \ - _nvkm_clk_fini(nv_object(clk), (s)); \ -}) - -int nvkm_clk_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, - struct nvkm_domain *, struct nvkm_pstate *, - int, bool, int, void **); -void _nvkm_clk_dtor(struct nvkm_object *); -int _nvkm_clk_init(struct nvkm_object *); -int _nvkm_clk_fini(struct nvkm_object *, bool); - -extern struct nvkm_oclass nv04_clk_oclass; -extern struct nvkm_oclass nv40_clk_oclass; -extern struct nvkm_oclass *nv50_clk_oclass; -extern struct nvkm_oclass *g84_clk_oclass; -extern struct nvkm_oclass *mcp77_clk_oclass; -extern struct nvkm_oclass gt215_clk_oclass; -extern struct nvkm_oclass gf100_clk_oclass; -extern struct nvkm_oclass gk104_clk_oclass; -extern struct nvkm_oclass gk20a_clk_oclass; - -int nv04_clk_pll_set(struct nvkm_clk *, u32 type, u32 freq); -int nv04_clk_pll_calc(struct nvkm_clk *, struct nvbios_pll *, int clk, - struct nvkm_pll_vals *); -int nv04_clk_pll_prog(struct nvkm_clk *, u32 reg1, struct nvkm_pll_vals *); -int gt215_clk_pll_calc(struct nvkm_clk *, struct nvbios_pll *, - int clk, struct nvkm_pll_vals *); - +int nvkm_clk_read(struct nvkm_clk *, enum nv_clk_src); int nvkm_clk_ustate(struct nvkm_clk *, int req, int pwr); int nvkm_clk_astate(struct nvkm_clk *, int req, int rel, bool wait); int nvkm_clk_dstate(struct nvkm_clk *, int req, int rel); int nvkm_clk_tstate(struct nvkm_clk *, int req, int rel); + +int nv04_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int nv40_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int nv50_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int g84_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int mcp77_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int gt215_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int gf100_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int gk104_clk_new(struct nvkm_device *, int, struct nvkm_clk **); +int gk20a_clk_new(struct nvkm_device *, int, struct nvkm_clk **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h index d1bbe0d62..6c1407fd3 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h @@ -1,32 +1,31 @@ #ifndef __NVKM_DEVINIT_H__ #define __NVKM_DEVINIT_H__ #include +struct nvkm_devinit; struct nvkm_devinit { - struct nvkm_subdev base; + const struct nvkm_devinit_func *func; + struct nvkm_subdev subdev; bool post; - void (*meminit)(struct nvkm_devinit *); - int (*pll_set)(struct nvkm_devinit *, u32 type, u32 freq); - u32 (*mmio)(struct nvkm_devinit *, u32 addr); }; -static inline struct nvkm_devinit * -nvkm_devinit(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_DEVINIT); -} +u32 nvkm_devinit_mmio(struct nvkm_devinit *, u32 addr); +int nvkm_devinit_pll_set(struct nvkm_devinit *, u32 type, u32 khz); +void nvkm_devinit_meminit(struct nvkm_devinit *); +u64 nvkm_devinit_disable(struct nvkm_devinit *); +int nvkm_devinit_post(struct nvkm_devinit *, u64 *disable); -extern struct nvkm_oclass *nv04_devinit_oclass; -extern struct nvkm_oclass *nv05_devinit_oclass; -extern struct nvkm_oclass *nv10_devinit_oclass; -extern struct nvkm_oclass *nv1a_devinit_oclass; -extern struct nvkm_oclass *nv20_devinit_oclass; -extern struct nvkm_oclass *nv50_devinit_oclass; -extern struct nvkm_oclass *g84_devinit_oclass; -extern struct nvkm_oclass *g98_devinit_oclass; -extern struct nvkm_oclass *gt215_devinit_oclass; -extern struct nvkm_oclass *mcp89_devinit_oclass; -extern struct nvkm_oclass *gf100_devinit_oclass; -extern struct nvkm_oclass *gm107_devinit_oclass; -extern struct nvkm_oclass *gm204_devinit_oclass; +int nv04_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int nv05_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int nv10_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int nv1a_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int nv20_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int nv50_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int g84_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int g98_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int gt215_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int mcp89_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int gf100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); +int gm204_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index 16da56cf4..85ab72c7f 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -18,7 +18,7 @@ #define NV_MEM_TARGET_VM 3 #define NV_MEM_TARGET_GART 4 -#define NV_MEM_TYPE_VM 0x7f +#define NVKM_RAM_TYPE_VM 0x7f #define NV_MEM_COMP_VM 0x03 struct nvkm_mem { @@ -46,62 +46,47 @@ struct nvkm_fb_tile { }; struct nvkm_fb { - struct nvkm_subdev base; - - bool (*memtype_valid)(struct nvkm_fb *, u32 memtype); + const struct nvkm_fb_func *func; + struct nvkm_subdev subdev; struct nvkm_ram *ram; - struct nvkm_mm vram; - struct nvkm_mm tags; - struct { struct nvkm_fb_tile region[16]; int regions; - void (*init)(struct nvkm_fb *, int i, u32 addr, u32 size, - u32 pitch, u32 flags, struct nvkm_fb_tile *); - void (*comp)(struct nvkm_fb *, int i, u32 size, u32 flags, - struct nvkm_fb_tile *); - void (*fini)(struct nvkm_fb *, int i, struct nvkm_fb_tile *); - void (*prog)(struct nvkm_fb *, int i, struct nvkm_fb_tile *); } tile; }; -static inline struct nvkm_fb * -nvkm_fb(void *obj) -{ - /* fbram uses this before device subdev pointer is valid */ - if (nv_iclass(obj, NV_SUBDEV_CLASS) && - nv_subidx(obj) == NVDEV_SUBDEV_FB) - return obj; - - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_FB); -} - -extern struct nvkm_oclass *nv04_fb_oclass; -extern struct nvkm_oclass *nv10_fb_oclass; -extern struct nvkm_oclass *nv1a_fb_oclass; -extern struct nvkm_oclass *nv20_fb_oclass; -extern struct nvkm_oclass *nv25_fb_oclass; -extern struct nvkm_oclass *nv30_fb_oclass; -extern struct nvkm_oclass *nv35_fb_oclass; -extern struct nvkm_oclass *nv36_fb_oclass; -extern struct nvkm_oclass *nv40_fb_oclass; -extern struct nvkm_oclass *nv41_fb_oclass; -extern struct nvkm_oclass *nv44_fb_oclass; -extern struct nvkm_oclass *nv46_fb_oclass; -extern struct nvkm_oclass *nv47_fb_oclass; -extern struct nvkm_oclass *nv49_fb_oclass; -extern struct nvkm_oclass *nv4e_fb_oclass; -extern struct nvkm_oclass *nv50_fb_oclass; -extern struct nvkm_oclass *g84_fb_oclass; -extern struct nvkm_oclass *gt215_fb_oclass; -extern struct nvkm_oclass *mcp77_fb_oclass; -extern struct nvkm_oclass *mcp89_fb_oclass; -extern struct nvkm_oclass *gf100_fb_oclass; -extern struct nvkm_oclass *gk104_fb_oclass; -extern struct nvkm_oclass *gk20a_fb_oclass; -extern struct nvkm_oclass *gm107_fb_oclass; +bool nvkm_fb_memtype_valid(struct nvkm_fb *, u32 memtype); +void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *); +void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *); +void nvkm_fb_tile_prog(struct nvkm_fb *, int region, struct nvkm_fb_tile *); + +int nv04_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv10_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv1a_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv20_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv25_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv30_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv35_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv36_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv40_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv41_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv44_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv46_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv47_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv49_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv4e_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int nv50_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int g84_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int gt215_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int mcp77_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int mcp89_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int gf100_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int gk104_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int gk20a_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **); #include #include @@ -112,36 +97,35 @@ struct nvkm_ram_data { u32 freq; }; +enum nvkm_ram_type { + NVKM_RAM_TYPE_UNKNOWN = 0, + NVKM_RAM_TYPE_STOLEN, + NVKM_RAM_TYPE_SGRAM, + NVKM_RAM_TYPE_SDRAM, + NVKM_RAM_TYPE_DDR1, + NVKM_RAM_TYPE_DDR2, + NVKM_RAM_TYPE_DDR3, + NVKM_RAM_TYPE_GDDR2, + NVKM_RAM_TYPE_GDDR3, + NVKM_RAM_TYPE_GDDR4, + NVKM_RAM_TYPE_GDDR5 +}; + struct nvkm_ram { - struct nvkm_object base; - enum { - NV_MEM_TYPE_UNKNOWN = 0, - NV_MEM_TYPE_STOLEN, - NV_MEM_TYPE_SGRAM, - NV_MEM_TYPE_SDRAM, - NV_MEM_TYPE_DDR1, - NV_MEM_TYPE_DDR2, - NV_MEM_TYPE_DDR3, - NV_MEM_TYPE_GDDR2, - NV_MEM_TYPE_GDDR3, - NV_MEM_TYPE_GDDR4, - NV_MEM_TYPE_GDDR5 - } type; - u64 stolen; + const struct nvkm_ram_func *func; + struct nvkm_fb *fb; + enum nvkm_ram_type type; u64 size; - u32 tags; + +#define NVKM_RAM_MM_SHIFT 12 + struct nvkm_mm vram; + struct nvkm_mm tags; + u64 stolen; int ranks; int parts; int part_mask; - int (*get)(struct nvkm_fb *, u64 size, u32 align, u32 size_nc, - u32 type, struct nvkm_mem **); - void (*put)(struct nvkm_fb *, struct nvkm_mem **); - - int (*calc)(struct nvkm_fb *, u32 freq); - int (*prog)(struct nvkm_fb *); - void (*tidy)(struct nvkm_fb *); u32 freq; u32 mr[16]; u32 mr1_nuts; @@ -151,4 +135,17 @@ struct nvkm_ram { struct nvkm_ram_data xition; struct nvkm_ram_data target; }; + +struct nvkm_ram_func { + void *(*dtor)(struct nvkm_ram *); + int (*init)(struct nvkm_ram *); + + int (*get)(struct nvkm_ram *, u64 size, u32 align, u32 size_nc, + u32 type, struct nvkm_mem **); + void (*put)(struct nvkm_ram *, struct nvkm_mem **); + + int (*calc)(struct nvkm_ram *, u32 freq); + int (*prog)(struct nvkm_ram *); + void (*tidy)(struct nvkm_ram *); +}; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h index a1384786a..ae201e388 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h @@ -1,28 +1,16 @@ #ifndef __NVKM_FUSE_H__ #define __NVKM_FUSE_H__ #include -#include struct nvkm_fuse { - struct nvkm_subdev base; + const struct nvkm_fuse_func *func; + struct nvkm_subdev subdev; + spinlock_t lock; }; -static inline struct nvkm_fuse * -nvkm_fuse(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_FUSE); -} +u32 nvkm_fuse_read(struct nvkm_fuse *, u32 addr); -#define nvkm_fuse_create(p, e, o, d) \ - nvkm_fuse_create_((p), (e), (o), sizeof(**d), (void **)d) - -int nvkm_fuse_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_fuse_dtor(struct nvkm_object *); -int _nvkm_fuse_init(struct nvkm_object *); -#define _nvkm_fuse_fini _nvkm_subdev_fini - -extern struct nvkm_oclass nv50_fuse_oclass; -extern struct nvkm_oclass gf100_fuse_oclass; -extern struct nvkm_oclass gm107_fuse_oclass; +int nv50_fuse_new(struct nvkm_device *, int, struct nvkm_fuse **); +int gf100_fuse_new(struct nvkm_device *, int, struct nvkm_fuse **); +int gm107_fuse_new(struct nvkm_device *, int, struct nvkm_fuse **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h index ca5099a81..9b9c6d2f9 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h @@ -19,26 +19,21 @@ struct nvkm_gpio_ntfy_rep { }; struct nvkm_gpio { - struct nvkm_subdev base; + const struct nvkm_gpio_func *func; + struct nvkm_subdev subdev; struct nvkm_event event; - - void (*reset)(struct nvkm_gpio *, u8 func); - int (*find)(struct nvkm_gpio *, int idx, u8 tag, u8 line, - struct dcb_gpio_func *); - int (*set)(struct nvkm_gpio *, int idx, u8 tag, u8 line, int state); - int (*get)(struct nvkm_gpio *, int idx, u8 tag, u8 line); }; -static inline struct nvkm_gpio * -nvkm_gpio(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_GPIO); -} - -extern struct nvkm_oclass *nv10_gpio_oclass; -extern struct nvkm_oclass *nv50_gpio_oclass; -extern struct nvkm_oclass *g94_gpio_oclass; -extern struct nvkm_oclass *gf110_gpio_oclass; -extern struct nvkm_oclass *gk104_gpio_oclass; +void nvkm_gpio_reset(struct nvkm_gpio *, u8 func); +int nvkm_gpio_find(struct nvkm_gpio *, int idx, u8 tag, u8 line, + struct dcb_gpio_func *); +int nvkm_gpio_set(struct nvkm_gpio *, int idx, u8 tag, u8 line, int state); +int nvkm_gpio_get(struct nvkm_gpio *, int idx, u8 tag, u8 line); + +int nv10_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **); +int nv50_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **); +int g94_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **); +int gf119_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **); +int gk104_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h index a2e33730f..6b6224dbd 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h @@ -6,15 +6,6 @@ #include #include -#define NV_I2C_PORT(n) (0x00 + (n)) -#define NV_I2C_AUX(n) (0x10 + (n)) -#define NV_I2C_EXT(n) (0x20 + (n)) -#define NV_I2C_DEFAULT(n) (0x80 + (n)) - -#define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n)) -#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8) -#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8) - struct nvkm_i2c_ntfy_req { #define NVKM_I2C_PLUG 0x01 #define NVKM_I2C_UNPLUG 0x02 @@ -29,72 +20,79 @@ struct nvkm_i2c_ntfy_rep { u8 mask; }; -struct nvkm_i2c_port { - struct nvkm_object base; - struct i2c_adapter adapter; - struct mutex mutex; +struct nvkm_i2c_bus_probe { + struct i2c_board_info dev; + u8 udelay; /* set to 0 to use the standard delay */ +}; - struct list_head head; - u8 index; - int aux; +struct nvkm_i2c_bus { + const struct nvkm_i2c_bus_func *func; + struct nvkm_i2c_pad *pad; +#define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n) +#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) +#define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1 +#define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2 + int id; - const struct nvkm_i2c_func *func; + struct mutex mutex; + struct list_head head; + struct i2c_adapter i2c; }; -struct nvkm_i2c_func { - void (*drive_scl)(struct nvkm_i2c_port *, int); - void (*drive_sda)(struct nvkm_i2c_port *, int); - int (*sense_scl)(struct nvkm_i2c_port *); - int (*sense_sda)(struct nvkm_i2c_port *); +int nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *); +void nvkm_i2c_bus_release(struct nvkm_i2c_bus *); +int nvkm_i2c_bus_probe(struct nvkm_i2c_bus *, const char *, + struct nvkm_i2c_bus_probe *, + bool (*)(struct nvkm_i2c_bus *, + struct i2c_board_info *, void *), void *); - int (*aux)(struct nvkm_i2c_port *, bool, u8, u32, u8 *, u8); - int (*pattern)(struct nvkm_i2c_port *, int pattern); - int (*lnk_ctl)(struct nvkm_i2c_port *, int nr, int bw, bool enh); - int (*drv_ctl)(struct nvkm_i2c_port *, int lane, int sw, int pe); -}; +struct nvkm_i2c_aux { + const struct nvkm_i2c_aux_func *func; + struct nvkm_i2c_pad *pad; +#define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n) +#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) + int id; -struct nvkm_i2c_board_info { - struct i2c_board_info dev; - u8 udelay; /* set to 0 to use the standard delay */ + struct mutex mutex; + struct list_head head; + struct i2c_adapter i2c; + + u32 intr; }; +void nvkm_i2c_aux_monitor(struct nvkm_i2c_aux *, bool monitor); +int nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *); +void nvkm_i2c_aux_release(struct nvkm_i2c_aux *); +int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, + u32 addr, u8 *data, u8 size); +int nvkm_i2c_aux_lnk_ctl(struct nvkm_i2c_aux *, int link_nr, int link_bw, + bool enhanced_framing); + struct nvkm_i2c { - struct nvkm_subdev base; - struct nvkm_event event; + const struct nvkm_i2c_func *func; + struct nvkm_subdev subdev; - struct nvkm_i2c_port *(*find)(struct nvkm_i2c *, u8 index); - struct nvkm_i2c_port *(*find_type)(struct nvkm_i2c *, u16 type); - int (*acquire_pad)(struct nvkm_i2c_port *, unsigned long timeout); - void (*release_pad)(struct nvkm_i2c_port *); - int (*acquire)(struct nvkm_i2c_port *, unsigned long timeout); - void (*release)(struct nvkm_i2c_port *); - int (*identify)(struct nvkm_i2c *, int index, - const char *what, struct nvkm_i2c_board_info *, - bool (*match)(struct nvkm_i2c_port *, - struct i2c_board_info *, void *), - void *); - - wait_queue_head_t wait; - struct list_head ports; + struct list_head pad; + struct list_head bus; + struct list_head aux; + + struct nvkm_event event; }; -static inline struct nvkm_i2c * -nvkm_i2c(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_I2C); -} +struct nvkm_i2c_bus *nvkm_i2c_bus_find(struct nvkm_i2c *, int); +struct nvkm_i2c_aux *nvkm_i2c_aux_find(struct nvkm_i2c *, int); -extern struct nvkm_oclass *nv04_i2c_oclass; -extern struct nvkm_oclass *nv4e_i2c_oclass; -extern struct nvkm_oclass *nv50_i2c_oclass; -extern struct nvkm_oclass *g94_i2c_oclass; -extern struct nvkm_oclass *gf110_i2c_oclass; -extern struct nvkm_oclass *gf117_i2c_oclass; -extern struct nvkm_oclass *gk104_i2c_oclass; -extern struct nvkm_oclass *gm204_i2c_oclass; +int nv04_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int nv4e_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int nv50_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int g94_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int gf117_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int gf119_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int gk104_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); +int gm204_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); static inline int -nv_rdi2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg) +nvkm_rdi2cr(struct i2c_adapter *adap, u8 addr, u8 reg) { u8 val; struct i2c_msg msgs[] = { @@ -102,7 +100,7 @@ nv_rdi2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg) { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, }; - int ret = i2c_transfer(&port->adapter, msgs, 2); + int ret = i2c_transfer(adap, msgs, ARRAY_SIZE(msgs)); if (ret != 2) return -EIO; @@ -110,14 +108,14 @@ nv_rdi2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg) } static inline int -nv_wri2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg, u8 val) +nvkm_wri2cr(struct i2c_adapter *adap, u8 addr, u8 reg, u8 val) { u8 buf[2] = { reg, val }; struct i2c_msg msgs[] = { { .addr = addr, .flags = 0, .len = 2, .buf = buf }, }; - int ret = i2c_transfer(&port->adapter, msgs, 1); + int ret = i2c_transfer(adap, msgs, ARRAY_SIZE(msgs)); if (ret != 1) return -EIO; @@ -125,11 +123,30 @@ nv_wri2cr(struct nvkm_i2c_port *port, u8 addr, u8 reg, u8 val) } static inline bool -nv_probe_i2c(struct nvkm_i2c_port *port, u8 addr) +nvkm_probe_i2c(struct i2c_adapter *adap, u8 addr) { - return nv_rdi2cr(port, addr, 0) >= 0; + return nvkm_rdi2cr(adap, addr, 0) >= 0; } -int nv_rdaux(struct nvkm_i2c_port *, u32 addr, u8 *data, u8 size); -int nv_wraux(struct nvkm_i2c_port *, u32 addr, u8 *data, u8 size); +static inline int +nvkm_rdaux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size) +{ + int ret = nvkm_i2c_aux_acquire(aux); + if (ret == 0) { + ret = nvkm_i2c_aux_xfer(aux, true, 9, addr, data, size); + nvkm_i2c_aux_release(aux); + } + return ret; +} + +static inline int +nvkm_wraux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size) +{ + int ret = nvkm_i2c_aux_acquire(aux); + if (ret == 0) { + ret = nvkm_i2c_aux_xfer(aux, true, 8, addr, data, size); + nvkm_i2c_aux_release(aux); + } + return ret; +} #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h index 2150d8af0..c4dcd2680 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h @@ -2,31 +2,8 @@ #define __NVKM_IBUS_H__ #include -struct nvkm_ibus { - struct nvkm_subdev base; -}; - -static inline struct nvkm_ibus * -nvkm_ibus(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_IBUS); -} - -#define nvkm_ibus_create(p,e,o,d) \ - nvkm_subdev_create_((p), (e), (o), 0, "PIBUS", "ibus", \ - sizeof(**d), (void **)d) -#define nvkm_ibus_destroy(p) \ - nvkm_subdev_destroy(&(p)->base) -#define nvkm_ibus_init(p) \ - nvkm_subdev_init(&(p)->base) -#define nvkm_ibus_fini(p,s) \ - nvkm_subdev_fini(&(p)->base, (s)) - -#define _nvkm_ibus_dtor _nvkm_subdev_dtor -#define _nvkm_ibus_init _nvkm_subdev_init -#define _nvkm_ibus_fini _nvkm_subdev_fini - -extern struct nvkm_oclass gf100_ibus_oclass; -extern struct nvkm_oclass gk104_ibus_oclass; -extern struct nvkm_oclass gk20a_ibus_oclass; +int gf100_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); +int gf117_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); +int gk104_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); +int gk20a_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h index 1bcb763cf..40f845e31 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h @@ -1,49 +1,30 @@ #ifndef __NVKM_INSTMEM_H__ #define __NVKM_INSTMEM_H__ #include - -struct nvkm_instobj { - struct nvkm_object base; - struct list_head head; - u32 *suspend; - u64 addr; - u32 size; -}; - -static inline struct nvkm_instobj * -nv_memobj(void *obj) -{ -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!nv_iclass(obj, NV_MEMOBJ_CLASS))) - nv_assert("BAD CAST -> NvMemObj, %08x", nv_hclass(obj)); -#endif - return obj; -} +struct nvkm_memory; struct nvkm_instmem { - struct nvkm_subdev base; - struct list_head list; + const struct nvkm_instmem_func *func; + struct nvkm_subdev subdev; + spinlock_t lock; + struct list_head list; u32 reserved; - int (*alloc)(struct nvkm_instmem *, struct nvkm_object *, - u32 size, u32 align, struct nvkm_object **); + + struct nvkm_memory *vbios; + struct nvkm_ramht *ramht; + struct nvkm_memory *ramro; + struct nvkm_memory *ramfc; }; -static inline struct nvkm_instmem * -nvkm_instmem(void *obj) -{ - /* nv04/nv40 impls need to create objects in their constructor, - * which is before the subdev pointer is valid - */ - if (nv_iclass(obj, NV_SUBDEV_CLASS) && - nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM) - return obj; +u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr); +void nvkm_instmem_wr32(struct nvkm_instmem *, u32 addr, u32 data); +int nvkm_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero, + struct nvkm_memory **); - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_INSTMEM); -} -extern struct nvkm_oclass *nv04_instmem_oclass; -extern struct nvkm_oclass *nv40_instmem_oclass; -extern struct nvkm_oclass *nv50_instmem_oclass; -extern struct nvkm_oclass *gk20a_instmem_oclass; +int nv04_instmem_new(struct nvkm_device *, int, struct nvkm_instmem **); +int nv40_instmem_new(struct nvkm_device *, int, struct nvkm_instmem **); +int nv50_instmem_new(struct nvkm_device *, int, struct nvkm_instmem **); +int gk20a_instmem_new(struct nvkm_device *, int, struct nvkm_instmem **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h index cd5d29fc0..3d4dbbf9a 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h @@ -1,31 +1,40 @@ #ifndef __NVKM_LTC_H__ #define __NVKM_LTC_H__ #include -struct nvkm_mm_node; +#include #define NVKM_LTC_MAX_ZBC_CNT 16 struct nvkm_ltc { - struct nvkm_subdev base; + const struct nvkm_ltc_func *func; + struct nvkm_subdev subdev; - int (*tags_alloc)(struct nvkm_ltc *, u32 count, - struct nvkm_mm_node **); - void (*tags_free)(struct nvkm_ltc *, struct nvkm_mm_node **); - void (*tags_clear)(struct nvkm_ltc *, u32 first, u32 count); + u32 ltc_nr; + u32 lts_nr; + + u32 num_tags; + u32 tag_base; + struct nvkm_mm tags; + struct nvkm_mm_node *tag_ram; int zbc_min; int zbc_max; - int (*zbc_color_get)(struct nvkm_ltc *, int index, const u32[4]); - int (*zbc_depth_get)(struct nvkm_ltc *, int index, const u32); + u32 zbc_color[NVKM_LTC_MAX_ZBC_CNT][4]; + u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; }; -static inline struct nvkm_ltc * -nvkm_ltc(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_LTC); -} +int nvkm_ltc_tags_alloc(struct nvkm_ltc *, u32 count, struct nvkm_mm_node **); +void nvkm_ltc_tags_free(struct nvkm_ltc *, struct nvkm_mm_node **); +void nvkm_ltc_tags_clear(struct nvkm_ltc *, u32 first, u32 count); + +int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); +int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32); + +void nvkm_ltc_invalidate(struct nvkm_ltc *); +void nvkm_ltc_flush(struct nvkm_ltc *); -extern struct nvkm_oclass *gf100_ltc_oclass; -extern struct nvkm_oclass *gk104_ltc_oclass; -extern struct nvkm_oclass *gm107_ltc_oclass; +int gf100_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); +int gk104_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); +int gk20a_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); +int gm107_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h index 055bea770..4de05e718 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h @@ -3,26 +3,19 @@ #include struct nvkm_mc { - struct nvkm_subdev base; - bool use_msi; - unsigned int irq; - void (*unk260)(struct nvkm_mc *, u32); + const struct nvkm_mc_func *func; + struct nvkm_subdev subdev; }; -static inline struct nvkm_mc * -nvkm_mc(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_MC); -} +void nvkm_mc_intr(struct nvkm_mc *, bool *handled); +void nvkm_mc_intr_unarm(struct nvkm_mc *); +void nvkm_mc_intr_rearm(struct nvkm_mc *); +void nvkm_mc_unk260(struct nvkm_mc *, u32 data); -extern struct nvkm_oclass *nv04_mc_oclass; -extern struct nvkm_oclass *nv40_mc_oclass; -extern struct nvkm_oclass *nv44_mc_oclass; -extern struct nvkm_oclass *nv4c_mc_oclass; -extern struct nvkm_oclass *nv50_mc_oclass; -extern struct nvkm_oclass *g94_mc_oclass; -extern struct nvkm_oclass *g98_mc_oclass; -extern struct nvkm_oclass *gf100_mc_oclass; -extern struct nvkm_oclass *gf106_mc_oclass; -extern struct nvkm_oclass *gk20a_mc_oclass; +int nv04_mc_new(struct nvkm_device *, int, struct nvkm_mc **); +int nv44_mc_new(struct nvkm_device *, int, struct nvkm_mc **); +int nv50_mc_new(struct nvkm_device *, int, struct nvkm_mc **); +int g98_mc_new(struct nvkm_device *, int, struct nvkm_mc **); +int gf100_mc_new(struct nvkm_device *, int, struct nvkm_mc **); +int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h index 3a5368776..dcd3deff2 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h @@ -6,7 +6,7 @@ struct nvkm_device; struct nvkm_mem; struct nvkm_vm_pgt { - struct nvkm_gpuobj *obj[2]; + struct nvkm_memory *mem[2]; u32 refcount[2]; }; @@ -26,74 +26,23 @@ struct nvkm_vma { struct nvkm_vm { struct nvkm_mmu *mmu; + + struct mutex mutex; struct nvkm_mm mm; struct kref refcount; struct list_head pgd_list; - atomic_t engref[NVDEV_SUBDEV_NR]; + atomic_t engref[NVKM_SUBDEV_NR]; struct nvkm_vm_pgt *pgt; u32 fpde; u32 lpde; }; -struct nvkm_mmu { - struct nvkm_subdev base; - - u64 limit; - u8 dma_bits; - u32 pgt_bits; - u8 spg_shift; - u8 lpg_shift; - - int (*create)(struct nvkm_mmu *, u64 offset, u64 length, - u64 mm_offset, struct nvkm_vm **); - - void (*map_pgt)(struct nvkm_gpuobj *pgd, u32 pde, - struct nvkm_gpuobj *pgt[2]); - void (*map)(struct nvkm_vma *, struct nvkm_gpuobj *, - struct nvkm_mem *, u32 pte, u32 cnt, - u64 phys, u64 delta); - void (*map_sg)(struct nvkm_vma *, struct nvkm_gpuobj *, - struct nvkm_mem *, u32 pte, u32 cnt, dma_addr_t *); - void (*unmap)(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt); - void (*flush)(struct nvkm_vm *); -}; - -static inline struct nvkm_mmu * -nvkm_mmu(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_MMU); -} - -#define nvkm_mmu_create(p,e,o,i,f,d) \ - nvkm_subdev_create((p), (e), (o), 0, (i), (f), (d)) -#define nvkm_mmu_destroy(p) \ - nvkm_subdev_destroy(&(p)->base) -#define nvkm_mmu_init(p) \ - nvkm_subdev_init(&(p)->base) -#define nvkm_mmu_fini(p,s) \ - nvkm_subdev_fini(&(p)->base, (s)) - -#define _nvkm_mmu_dtor _nvkm_subdev_dtor -#define _nvkm_mmu_init _nvkm_subdev_init -#define _nvkm_mmu_fini _nvkm_subdev_fini - -extern struct nvkm_oclass nv04_mmu_oclass; -extern struct nvkm_oclass nv41_mmu_oclass; -extern struct nvkm_oclass nv44_mmu_oclass; -extern struct nvkm_oclass nv50_mmu_oclass; -extern struct nvkm_oclass gf100_mmu_oclass; - -int nv04_vm_create(struct nvkm_mmu *, u64, u64, u64, - struct nvkm_vm **); -void nv04_mmu_dtor(struct nvkm_object *); - -int nvkm_vm_create(struct nvkm_mmu *, u64 offset, u64 length, u64 mm_offset, - u32 block, struct nvkm_vm **); int nvkm_vm_new(struct nvkm_device *, u64 offset, u64 length, u64 mm_offset, - struct nvkm_vm **); + struct lock_class_key *, struct nvkm_vm **); int nvkm_vm_ref(struct nvkm_vm *, struct nvkm_vm **, struct nvkm_gpuobj *pgd); +int nvkm_vm_boot(struct nvkm_vm *, u64 size); int nvkm_vm_get(struct nvkm_vm *, u64 size, u32 page_shift, u32 access, struct nvkm_vma *); void nvkm_vm_put(struct nvkm_vma *); @@ -101,4 +50,19 @@ void nvkm_vm_map(struct nvkm_vma *, struct nvkm_mem *); void nvkm_vm_map_at(struct nvkm_vma *, u64 offset, struct nvkm_mem *); void nvkm_vm_unmap(struct nvkm_vma *); void nvkm_vm_unmap_at(struct nvkm_vma *, u64 offset, u64 length); + +struct nvkm_mmu { + const struct nvkm_mmu_func *func; + struct nvkm_subdev subdev; + + u64 limit; + u8 dma_bits; + u8 lpg_shift; +}; + +int nv04_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h index fba613477..ed0250139 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h @@ -2,33 +2,5 @@ #define __NVKM_MXM_H__ #include -#define MXM_SANITISE_DCB 0x00000001 - -struct nvkm_mxm { - struct nvkm_subdev base; - u32 action; - u8 *mxms; -}; - -static inline struct nvkm_mxm * -nvkm_mxm(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_MXM); -} - -#define nvkm_mxm_create(p,e,o,d) \ - nvkm_mxm_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_mxm_init(p) \ - nvkm_subdev_init(&(p)->base) -#define nvkm_mxm_fini(p,s) \ - nvkm_subdev_fini(&(p)->base, (s)) -int nvkm_mxm_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void nvkm_mxm_destroy(struct nvkm_mxm *); - -#define _nvkm_mxm_dtor _nvkm_subdev_dtor -#define _nvkm_mxm_init _nvkm_subdev_init -#define _nvkm_mxm_fini _nvkm_subdev_fini - -extern struct nvkm_oclass nv50_mxm_oclass; +int nv50_mxm_new(struct nvkm_device *, int, struct nvkm_subdev **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h new file mode 100644 index 000000000..fee0a97c4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h @@ -0,0 +1,37 @@ +#ifndef __NVKM_PCI_H__ +#define __NVKM_PCI_H__ +#include + +struct nvkm_pci { + const struct nvkm_pci_func *func; + struct nvkm_subdev subdev; + struct pci_dev *pdev; + int irq; + + struct { + struct agp_bridge_data *bridge; + u32 mode; + u64 base; + u64 size; + int mtrr; + bool cma; + bool acquired; + } agp; + + bool msi; +}; + +u32 nvkm_pci_rd32(struct nvkm_pci *, u16 addr); +void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data); +void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data); +u32 nvkm_pci_mask(struct nvkm_pci *, u16 addr, u32 mask, u32 value); +void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow); + +int nv04_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +int nv40_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +int nv46_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +int nv4c_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +int g84_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +int g94_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +int gf100_pci_new(struct nvkm_device *, int, struct nvkm_pci **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 755942352..e61923d5e 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -3,7 +3,8 @@ #include struct nvkm_pmu { - struct nvkm_subdev base; + const struct nvkm_pmu_func *func; + struct nvkm_subdev subdev; struct { u32 base; @@ -20,24 +21,20 @@ struct nvkm_pmu { u32 message; u32 data[2]; } recv; - - int (*message)(struct nvkm_pmu *, u32[2], u32, u32, u32, u32); - void (*pgob)(struct nvkm_pmu *, bool); }; -static inline struct nvkm_pmu * -nvkm_pmu(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_PMU); -} - -extern struct nvkm_oclass *gt215_pmu_oclass; -extern struct nvkm_oclass *gf100_pmu_oclass; -extern struct nvkm_oclass *gf110_pmu_oclass; -extern struct nvkm_oclass *gk104_pmu_oclass; -extern struct nvkm_oclass *gk110_pmu_oclass; -extern struct nvkm_oclass *gk208_pmu_oclass; -extern struct nvkm_oclass *gk20a_pmu_oclass; +int nvkm_pmu_send(struct nvkm_pmu *, u32 reply[2], u32 process, + u32 message, u32 data0, u32 data1); +void nvkm_pmu_pgob(struct nvkm_pmu *, bool enable); + +int gt215_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gf100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gf119_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gk104_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gk110_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gk208_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gk20a_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); /* interface to MEMX process running on PMU */ struct nvkm_memx; diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h index 6662829b6..b268b96fa 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h @@ -2,6 +2,28 @@ #define __NVKM_THERM_H__ #include +#include +#include +#include + +enum nvkm_therm_thrs_direction { + NVKM_THERM_THRS_FALLING = 0, + NVKM_THERM_THRS_RISING = 1 +}; + +enum nvkm_therm_thrs_state { + NVKM_THERM_THRS_LOWER = 0, + NVKM_THERM_THRS_HIGHER = 1 +}; + +enum nvkm_therm_thrs { + NVKM_THERM_THRS_FANBOOST = 0, + NVKM_THERM_THRS_DOWNCLOCK = 1, + NVKM_THERM_THRS_CRITICAL = 2, + NVKM_THERM_THRS_SHUTDOWN = 3, + NVKM_THERM_THRS_NR +}; + enum nvkm_therm_fan_mode { NVKM_THERM_CTRL_NONE = 0, NVKM_THERM_CTRL_MANUAL = 1, @@ -24,56 +46,54 @@ enum nvkm_therm_attr_type { }; struct nvkm_therm { - struct nvkm_subdev base; + const struct nvkm_therm_func *func; + struct nvkm_subdev subdev; - int (*pwm_ctrl)(struct nvkm_therm *, int line, bool); - int (*pwm_get)(struct nvkm_therm *, int line, u32 *, u32 *); - int (*pwm_set)(struct nvkm_therm *, int line, u32, u32); - int (*pwm_clock)(struct nvkm_therm *, int line); + /* automatic thermal management */ + struct nvkm_alarm alarm; + spinlock_t lock; + struct nvbios_therm_trip_point *last_trip; + int mode; + int cstate; + int suspend; + + /* bios */ + struct nvbios_therm_sensor bios_sensor; + + /* fan priv */ + struct nvkm_fan *fan; + + /* alarms priv */ + struct { + spinlock_t alarm_program_lock; + struct nvkm_alarm therm_poll_alarm; + enum nvkm_therm_thrs_state alarm_state[NVKM_THERM_THRS_NR]; + } sensor; + + /* what should be done if the card overheats */ + struct { + void (*downclock)(struct nvkm_therm *, bool active); + void (*pause)(struct nvkm_therm *, bool active); + } emergency; + + /* ic */ + struct i2c_client *ic; int (*fan_get)(struct nvkm_therm *); int (*fan_set)(struct nvkm_therm *, int); - int (*fan_sense)(struct nvkm_therm *); - - int (*temp_get)(struct nvkm_therm *); int (*attr_get)(struct nvkm_therm *, enum nvkm_therm_attr_type); int (*attr_set)(struct nvkm_therm *, enum nvkm_therm_attr_type, int); }; -static inline struct nvkm_therm * -nvkm_therm(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_THERM); -} - -#define nvkm_therm_create(p,e,o,d) \ - nvkm_therm_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_therm_destroy(p) ({ \ - struct nvkm_therm *therm = (p); \ - _nvkm_therm_dtor(nv_object(therm)); \ -}) -#define nvkm_therm_init(p) ({ \ - struct nvkm_therm *therm = (p); \ - _nvkm_therm_init(nv_object(therm)); \ -}) -#define nvkm_therm_fini(p,s) ({ \ - struct nvkm_therm *therm = (p); \ - _nvkm_therm_init(nv_object(therm), (s)); \ -}) - -int nvkm_therm_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_therm_dtor(struct nvkm_object *); -int _nvkm_therm_init(struct nvkm_object *); -int _nvkm_therm_fini(struct nvkm_object *, bool); - -int nvkm_therm_cstate(struct nvkm_therm *, int, int); - -extern struct nvkm_oclass nv40_therm_oclass; -extern struct nvkm_oclass nv50_therm_oclass; -extern struct nvkm_oclass g84_therm_oclass; -extern struct nvkm_oclass gt215_therm_oclass; -extern struct nvkm_oclass gf110_therm_oclass; -extern struct nvkm_oclass gm107_therm_oclass; +int nvkm_therm_temp_get(struct nvkm_therm *); +int nvkm_therm_fan_sense(struct nvkm_therm *); +int nvkm_therm_cstate(struct nvkm_therm *, int, int); + +int nv40_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int nv50_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int g84_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int gt215_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h index 4ad55082e..82d3e2891 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h @@ -9,53 +9,68 @@ struct nvkm_alarm { }; static inline void -nvkm_alarm_init(struct nvkm_alarm *alarm, - void (*func)(struct nvkm_alarm *)) +nvkm_alarm_init(struct nvkm_alarm *alarm, void (*func)(struct nvkm_alarm *)) { INIT_LIST_HEAD(&alarm->head); alarm->func = func; } -bool nvkm_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); -bool nvkm_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); -bool nvkm_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); -void nvkm_timer_alarm(void *, u32 nsec, struct nvkm_alarm *); -void nvkm_timer_alarm_cancel(void *, struct nvkm_alarm *); - -#define NV_WAIT_DEFAULT 2000000000ULL -#define nv_wait(o,a,m,v) \ - nvkm_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) -#define nv_wait_ne(o,a,m,v) \ - nvkm_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v)) -#define nv_wait_cb(o,c,d) \ - nvkm_timer_wait_cb((o), NV_WAIT_DEFAULT, (c), (d)) - struct nvkm_timer { - struct nvkm_subdev base; - u64 (*read)(struct nvkm_timer *); - void (*alarm)(struct nvkm_timer *, u64 time, struct nvkm_alarm *); - void (*alarm_cancel)(struct nvkm_timer *, struct nvkm_alarm *); + const struct nvkm_timer_func *func; + struct nvkm_subdev subdev; + + struct list_head alarms; + spinlock_t lock; }; -static inline struct nvkm_timer * -nvkm_timer(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_TIMER); -} +u64 nvkm_timer_read(struct nvkm_timer *); +void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *); +void nvkm_timer_alarm_cancel(struct nvkm_timer *, struct nvkm_alarm *); + +/* Delay based on GPU time (ie. PTIMER). + * + * Will return -ETIMEDOUT unless the loop was terminated with 'break', + * where it will return the number of nanoseconds taken instead. + * + * NVKM_DELAY can be passed for 'cond' to disable the timeout warning, + * which is useful for unconditional delay loops. + */ +#define NVKM_DELAY _warn = false; +#define nvkm_nsec(d,n,cond...) ({ \ + struct nvkm_device *_device = (d); \ + struct nvkm_timer *_tmr = _device->timer; \ + u64 _nsecs = (n), _time0 = nvkm_timer_read(_tmr); \ + s64 _taken = 0; \ + bool _warn = true; \ + \ + do { \ + cond \ + } while (_taken = nvkm_timer_read(_tmr) - _time0, _taken < _nsecs); \ + \ + if (_taken >= _nsecs) { \ + if (_warn) { \ + dev_warn(_device->dev, "timeout at %s:%d/%s()!\n", \ + __FILE__, __LINE__, __func__); \ + } \ + _taken = -ETIMEDOUT; \ + } \ + _taken; \ +}) +#define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond) +#define nvkm_msec(d,m,cond...) nvkm_usec((d), (m) * 1000, ##cond) + +#define nvkm_wait_nsec(d,n,addr,mask,data) \ + nvkm_nsec(d, n, \ + if ((nvkm_rd32(d, (addr)) & (mask)) == (data)) \ + break; \ + ) +#define nvkm_wait_usec(d,u,addr,mask,data) \ + nvkm_wait_nsec((d), (u) * 1000, (addr), (mask), (data)) +#define nvkm_wait_msec(d,m,addr,mask,data) \ + nvkm_wait_usec((d), (m) * 1000, (addr), (mask), (data)) -#define nvkm_timer_create(p,e,o,d) \ - nvkm_subdev_create_((p), (e), (o), 0, "PTIMER", "timer", \ - sizeof(**d), (void **)d) -#define nvkm_timer_destroy(p) \ - nvkm_subdev_destroy(&(p)->base) -#define nvkm_timer_init(p) \ - nvkm_subdev_init(&(p)->base) -#define nvkm_timer_fini(p,s) \ - nvkm_subdev_fini(&(p)->base, (s)) - -int nvkm_timer_create_(struct nvkm_object *, struct nvkm_engine *, - struct nvkm_oclass *, int size, void **); - -extern struct nvkm_oclass nv04_timer_oclass; -extern struct nvkm_oclass gk20a_timer_oclass; +int nv04_timer_new(struct nvkm_device *, int, struct nvkm_timer **); +int nv40_timer_new(struct nvkm_device *, int, struct nvkm_timer **); +int nv41_timer_new(struct nvkm_device *, int, struct nvkm_timer **); +int gk20a_timer_new(struct nvkm_device *, int, struct nvkm_timer **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h index fee09ad81..ce5636fe2 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h @@ -1,30 +1,28 @@ #ifndef __NOUVEAU_VGA_H__ #define __NOUVEAU_VGA_H__ - -#include +#include /* access to various legacy io ports */ -u8 nv_rdport(void *obj, int head, u16 port); -void nv_wrport(void *obj, int head, u16 port, u8 value); +u8 nvkm_rdport(struct nvkm_device *, int head, u16 port); +void nvkm_wrport(struct nvkm_device *, int head, u16 port, u8 value); /* VGA Sequencer */ -u8 nv_rdvgas(void *obj, int head, u8 index); -void nv_wrvgas(void *obj, int head, u8 index, u8 value); +u8 nvkm_rdvgas(struct nvkm_device *, int head, u8 index); +void nvkm_wrvgas(struct nvkm_device *, int head, u8 index, u8 value); /* VGA Graphics */ -u8 nv_rdvgag(void *obj, int head, u8 index); -void nv_wrvgag(void *obj, int head, u8 index, u8 value); +u8 nvkm_rdvgag(struct nvkm_device *, int head, u8 index); +void nvkm_wrvgag(struct nvkm_device *, int head, u8 index, u8 value); /* VGA CRTC */ -u8 nv_rdvgac(void *obj, int head, u8 index); -void nv_wrvgac(void *obj, int head, u8 index, u8 value); +u8 nvkm_rdvgac(struct nvkm_device *, int head, u8 index); +void nvkm_wrvgac(struct nvkm_device *, int head, u8 index, u8 value); /* VGA indexed port access dispatcher */ -u8 nv_rdvgai(void *obj, int head, u16 port, u8 index); -void nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value); - -bool nv_lockvgac(void *obj, bool lock); -u8 nv_rdvgaowner(void *obj); -void nv_wrvgaowner(void *obj, u8); +u8 nvkm_rdvgai(struct nvkm_device *, int head, u16 port, u8 index); +void nvkm_wrvgai(struct nvkm_device *, int head, u16 port, u8 index, u8 value); +bool nvkm_lockvgac(struct nvkm_device *, bool lock); +u8 nvkm_rdvgaowner(struct nvkm_device *); +void nvkm_wrvgaowner(struct nvkm_device *, u8); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index e3d7243fb..b458d046d 100644 --- a/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/kernel/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h @@ -2,19 +2,9 @@ #define __NVKM_VOLT_H__ #include -struct nvkm_voltage { - u32 uv; - u8 id; -}; - struct nvkm_volt { - struct nvkm_subdev base; - - int (*vid_get)(struct nvkm_volt *); - int (*get)(struct nvkm_volt *); - int (*vid_set)(struct nvkm_volt *, u8 vid); - int (*set)(struct nvkm_volt *, u32 uv); - int (*set_id)(struct nvkm_volt *, u8 id, int condition); + const struct nvkm_volt_func *func; + struct nvkm_subdev subdev; u8 vid_mask; u8 vid_nr; @@ -24,35 +14,10 @@ struct nvkm_volt { } vid[256]; }; -static inline struct nvkm_volt * -nvkm_volt(void *obj) -{ - return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_VOLT); -} - -#define nvkm_volt_create(p, e, o, d) \ - nvkm_volt_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_volt_destroy(p) ({ \ - struct nvkm_volt *v = (p); \ - _nvkm_volt_dtor(nv_object(v)); \ -}) -#define nvkm_volt_init(p) ({ \ - struct nvkm_volt *v = (p); \ - _nvkm_volt_init(nv_object(v)); \ -}) -#define nvkm_volt_fini(p,s) \ - nvkm_subdev_fini((p), (s)) - -int nvkm_volt_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_volt_dtor(struct nvkm_object *); -int _nvkm_volt_init(struct nvkm_object *); -#define _nvkm_volt_fini _nvkm_subdev_fini - -extern struct nvkm_oclass nv40_volt_oclass; -extern struct nvkm_oclass gk20a_volt_oclass; +int nvkm_volt_get(struct nvkm_volt *); +int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition); -int nvkm_voltgpio_init(struct nvkm_volt *); -int nvkm_voltgpio_get(struct nvkm_volt *); -int nvkm_voltgpio_set(struct nvkm_volt *, u8); +int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); +int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **); +int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.c b/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.c index d8b0891a1..7f50cf5f9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "nouveau_drm.h" #include "nouveau_dma.h" @@ -32,11 +33,10 @@ #include "nouveau_chan.h" #include "nouveau_abi16.h" -struct nouveau_abi16 * -nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) +static struct nouveau_abi16 * +nouveau_abi16(struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); - mutex_lock(&cli->mutex); if (!cli->abi16) { struct nouveau_abi16 *abi16; cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL); @@ -51,8 +51,7 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) * device (ie. the one that belongs to the fd it * opened) */ - if (nvif_device_init(&cli->base.base, NULL, - NOUVEAU_ABI16_DEVICE, NV_DEVICE, + if (nvif_device_init(&cli->base.object, 0, NV_DEVICE, &args, sizeof(args), &abi16->device) == 0) return cli->abi16; @@ -60,37 +59,46 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) kfree(cli->abi16); cli->abi16 = NULL; } - - mutex_unlock(&cli->mutex); } return cli->abi16; } +struct nouveau_abi16 * +nouveau_abi16_get(struct drm_file *file_priv) +{ + struct nouveau_cli *cli = nouveau_cli(file_priv); + mutex_lock(&cli->mutex); + if (nouveau_abi16(file_priv)) + return cli->abi16; + mutex_unlock(&cli->mutex); + return NULL; +} + int nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret) { - struct nouveau_cli *cli = (void *)nvif_client(&abi16->device.base); + struct nouveau_cli *cli = (void *)abi16->device.object.client; mutex_unlock(&cli->mutex); return ret; } -u16 +s32 nouveau_abi16_swclass(struct nouveau_drm *drm) { switch (drm->device.info.family) { case NV_DEVICE_INFO_V0_TNT: - return 0x006e; + return NVIF_IOCTL_NEW_V0_SW_NV04; case NV_DEVICE_INFO_V0_CELSIUS: case NV_DEVICE_INFO_V0_KELVIN: case NV_DEVICE_INFO_V0_RANKINE: case NV_DEVICE_INFO_V0_CURIE: - return 0x016e; + return NVIF_IOCTL_NEW_V0_SW_NV10; case NV_DEVICE_INFO_V0_TESLA: - return 0x506e; + return NVIF_IOCTL_NEW_V0_SW_NV50; case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: case NV_DEVICE_INFO_V0_MAXWELL: - return 0x906e; + return NVIF_IOCTL_NEW_V0_SW_GF100; } return 0x0000; @@ -100,6 +108,7 @@ static void nouveau_abi16_ntfy_fini(struct nouveau_abi16_chan *chan, struct nouveau_abi16_ntfy *ntfy) { + nvif_object_fini(&ntfy->object); nvkm_mm_free(&chan->heap, &ntfy->node); list_del(&ntfy->head); kfree(ntfy); @@ -132,7 +141,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, /* destroy channel object, all children will be killed too */ if (chan->chan) { - abi16->handles &= ~(1ULL << (chan->chan->object->handle & 0xffff)); + nouveau_channel_idle(chan->chan); nouveau_channel_del(&chan->chan); } @@ -143,7 +152,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, void nouveau_abi16_fini(struct nouveau_abi16 *abi16) { - struct nouveau_cli *cli = (void *)nvif_client(&abi16->device.base); + struct nouveau_cli *cli = (void *)abi16->device.object.client; struct nouveau_abi16_chan *chan, *temp; /* cleanup channels */ @@ -164,7 +173,6 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_device *device = &drm->device; - struct nvkm_timer *ptimer = nvxx_timer(device); struct nvkm_gr *gr = nvxx_gr(device); struct drm_nouveau_getparam *getparam = data; @@ -173,19 +181,19 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = device->info.chipset; break; case NOUVEAU_GETPARAM_PCI_VENDOR: - if (nv_device_is_pci(nvxx_device(device))) + if (nvxx_device(device)->func->pci) getparam->value = dev->pdev->vendor; else getparam->value = 0; break; case NOUVEAU_GETPARAM_PCI_DEVICE: - if (nv_device_is_pci(nvxx_device(device))) + if (nvxx_device(device)->func->pci) getparam->value = dev->pdev->device; else getparam->value = 0; break; case NOUVEAU_GETPARAM_BUS_TYPE: - if (!nv_device_is_pci(nvxx_device(device))) + if (!nvxx_device(device)->func->pci) getparam->value = 3; else if (drm_pci_device_is_agp(dev)) @@ -206,7 +214,7 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = 0; /* deprecated */ break; case NOUVEAU_GETPARAM_PTIMER_TIME: - getparam->value = ptimer->read(ptimer); + getparam->value = nvif_device_time(device); break; case NOUVEAU_GETPARAM_HAS_BO_USAGE: getparam->value = 1; @@ -215,10 +223,10 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = 1; break; case NOUVEAU_GETPARAM_GRAPH_UNITS: - getparam->value = gr->units ? gr->units(gr) : 0; + getparam->value = nvkm_gr_units(gr); break; default: - NV_PRINTK(debug, cli, "unknown parameter %lld\n", getparam->param); + NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param); return -EINVAL; } @@ -237,7 +245,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) struct drm_nouveau_channel_alloc *init = data; struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; struct nvif_device *device; int ret; @@ -267,26 +275,21 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) return nouveau_abi16_put(abi16, -EINVAL); /* allocate "abi16 channel" data and make up a handle for it */ - init->channel = __ffs64(~abi16->handles); - if (~abi16->handles == 0) - return nouveau_abi16_put(abi16, -ENOSPC); - chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) return nouveau_abi16_put(abi16, -ENOMEM); INIT_LIST_HEAD(&chan->notifiers); list_add(&chan->head, &abi16->channels); - abi16->handles |= (1ULL << init->channel); /* create channel object and initialise dma and fence management */ - ret = nouveau_channel_new(drm, device, - NOUVEAU_ABI16_CHAN(init->channel), - init->fb_ctxdma_handle, + ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle, init->tt_ctxdma_handle, &chan->chan); if (ret) goto done; + init->channel = chan->chan->chid; + if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART; @@ -337,18 +340,56 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel) struct nouveau_abi16_chan *chan; list_for_each_entry(chan, &abi16->channels, head) { - if (chan->chan->object->handle == NOUVEAU_ABI16_CHAN(channel)) + if (chan->chan->chid == channel) return chan; } return NULL; } +int +nouveau_abi16_usif(struct drm_file *file_priv, void *data, u32 size) +{ + union { + struct nvif_ioctl_v0 v0; + } *args = data; + struct nouveau_abi16_chan *chan; + struct nouveau_abi16 *abi16; + int ret; + + if (nvif_unpack(args->v0, 0, 0, true)) { + switch (args->v0.type) { + case NVIF_IOCTL_V0_NEW: + case NVIF_IOCTL_V0_MTHD: + case NVIF_IOCTL_V0_SCLASS: + break; + default: + return -EACCES; + } + } else + return ret; + + if (!(abi16 = nouveau_abi16(file_priv))) + return -ENOMEM; + + if (args->v0.token != ~0ULL) { + if (!(chan = nouveau_abi16_chan(abi16, args->v0.token))) + return -EINVAL; + args->v0.object = nvif_handle(&chan->chan->user); + args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; + return 0; + } + + args->v0.object = nvif_handle(&abi16->device.object); + args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; + return 0; +} + int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS) { struct drm_nouveau_channel_free *req = data; - struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; if (unlikely(!abi16)) @@ -365,40 +406,91 @@ int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) { struct drm_nouveau_grobj_alloc *init = data; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_new_v0 new; - } args = { - .ioctl.owner = NVIF_IOCTL_V0_OWNER_ANY, - .ioctl.type = NVIF_IOCTL_V0_NEW, - .ioctl.path_nr = 3, - .ioctl.path[2] = NOUVEAU_ABI16_CLIENT, - .ioctl.path[1] = NOUVEAU_ABI16_DEVICE, - .ioctl.path[0] = NOUVEAU_ABI16_CHAN(init->channel), - .new.route = NVDRM_OBJECT_ABI16, - .new.handle = init->handle, - .new.oclass = init->class, - }; - struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); - struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); + struct nouveau_abi16_chan *chan; + struct nouveau_abi16_ntfy *ntfy; struct nvif_client *client; - int ret; + struct nvif_sclass *sclass; + s32 oclass = 0; + int ret, i; if (unlikely(!abi16)) return -ENOMEM; if (init->handle == ~0) return nouveau_abi16_put(abi16, -EINVAL); - client = nvif_client(nvif_object(&abi16->device)); + client = abi16->device.object.client; - /* compatibility with userspace that assumes 506e for all chipsets */ - if (init->class == 0x506e) { - init->class = nouveau_abi16_swclass(drm); - if (init->class == 0x906e) - return nouveau_abi16_put(abi16, 0); + chan = nouveau_abi16_chan(abi16, init->channel); + if (!chan) + return nouveau_abi16_put(abi16, -ENOENT); + + ret = nvif_object_sclass_get(&chan->chan->user, &sclass); + if (ret < 0) + return nouveau_abi16_put(abi16, ret); + + if ((init->class & 0x00ff) == 0x006e) { + /* nvsw: compatibility with older 0x*6e class identifier */ + for (i = 0; !oclass && i < ret; i++) { + switch (sclass[i].oclass) { + case NVIF_IOCTL_NEW_V0_SW_NV04: + case NVIF_IOCTL_NEW_V0_SW_NV10: + case NVIF_IOCTL_NEW_V0_SW_NV50: + case NVIF_IOCTL_NEW_V0_SW_GF100: + oclass = sclass[i].oclass; + break; + default: + break; + } + } + } else + if ((init->class & 0x00ff) == 0x00b1) { + /* msvld: compatibility with incorrect version exposure */ + for (i = 0; i < ret; i++) { + if ((sclass[i].oclass & 0x00ff) == 0x00b1) { + oclass = sclass[i].oclass; + break; + } + } + } else + if ((init->class & 0x00ff) == 0x00b2) { /* mspdec */ + /* mspdec: compatibility with incorrect version exposure */ + for (i = 0; i < ret; i++) { + if ((sclass[i].oclass & 0x00ff) == 0x00b2) { + oclass = sclass[i].oclass; + break; + } + } + } else + if ((init->class & 0x00ff) == 0x00b3) { /* msppp */ + /* msppp: compatibility with incorrect version exposure */ + for (i = 0; i < ret; i++) { + if ((sclass[i].oclass & 0x00ff) == 0x00b3) { + oclass = sclass[i].oclass; + break; + } + } + } else { + oclass = init->class; } - ret = nvif_client_ioctl(client, &args, sizeof(args)); + nvif_object_sclass_put(&sclass); + if (!oclass) + return nouveau_abi16_put(abi16, -EINVAL); + + ntfy = kzalloc(sizeof(*ntfy), GFP_KERNEL); + if (!ntfy) + return nouveau_abi16_put(abi16, -ENOMEM); + + list_add(&ntfy->head, &chan->notifiers); + + client->route = NVDRM_OBJECT_ABI16; + ret = nvif_object_init(&chan->chan->user, init->handle, oclass, + NULL, 0, &ntfy->object); + client->route = NVDRM_OBJECT_NVIF; + + if (ret) + nouveau_abi16_ntfy_fini(chan, ntfy); return nouveau_abi16_put(abi16, ret); } @@ -406,27 +498,13 @@ int nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) { struct drm_nouveau_notifierobj_alloc *info = data; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_new_v0 new; - struct nv_dma_v0 ctxdma; - } args = { - .ioctl.owner = NVIF_IOCTL_V0_OWNER_ANY, - .ioctl.type = NVIF_IOCTL_V0_NEW, - .ioctl.path_nr = 3, - .ioctl.path[2] = NOUVEAU_ABI16_CLIENT, - .ioctl.path[1] = NOUVEAU_ABI16_DEVICE, - .ioctl.path[0] = NOUVEAU_ABI16_CHAN(info->channel), - .new.route = NVDRM_OBJECT_ABI16, - .new.handle = info->handle, - .new.oclass = NV_DMA_IN_MEMORY, - }; struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; struct nouveau_abi16_ntfy *ntfy; struct nvif_device *device = &abi16->device; struct nvif_client *client; + struct nv_dma_v0 args = {}; int ret; if (unlikely(!abi16)) @@ -435,7 +513,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) /* completely unnecessary for these chipsets... */ if (unlikely(device->info.family >= NV_DEVICE_INFO_V0_FERMI)) return nouveau_abi16_put(abi16, -EINVAL); - client = nvif_client(nvif_object(&abi16->device)); + client = abi16->device.object.client; chan = nouveau_abi16_chan(abi16, info->channel); if (!chan) @@ -446,41 +524,43 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) return nouveau_abi16_put(abi16, -ENOMEM); list_add(&ntfy->head, &chan->notifiers); - ntfy->handle = info->handle; ret = nvkm_mm_head(&chan->heap, 0, 1, info->size, info->size, 1, &ntfy->node); if (ret) goto done; - args.ctxdma.start = ntfy->node->offset; - args.ctxdma.limit = ntfy->node->offset + ntfy->node->length - 1; + args.start = ntfy->node->offset; + args.limit = ntfy->node->offset + ntfy->node->length - 1; if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { - args.ctxdma.target = NV_DMA_V0_TARGET_VM; - args.ctxdma.access = NV_DMA_V0_ACCESS_VM; - args.ctxdma.start += chan->ntfy_vma.offset; - args.ctxdma.limit += chan->ntfy_vma.offset; + args.target = NV_DMA_V0_TARGET_VM; + args.access = NV_DMA_V0_ACCESS_VM; + args.start += chan->ntfy_vma.offset; + args.limit += chan->ntfy_vma.offset; } else - if (drm->agp.stat == ENABLED) { - args.ctxdma.target = NV_DMA_V0_TARGET_AGP; - args.ctxdma.access = NV_DMA_V0_ACCESS_RDWR; - args.ctxdma.start += drm->agp.base + chan->ntfy->bo.offset; - args.ctxdma.limit += drm->agp.base + chan->ntfy->bo.offset; - client->super = true; + if (drm->agp.bridge) { + args.target = NV_DMA_V0_TARGET_AGP; + args.access = NV_DMA_V0_ACCESS_RDWR; + args.start += drm->agp.base + chan->ntfy->bo.offset; + args.limit += drm->agp.base + chan->ntfy->bo.offset; } else { - args.ctxdma.target = NV_DMA_V0_TARGET_VM; - args.ctxdma.access = NV_DMA_V0_ACCESS_RDWR; - args.ctxdma.start += chan->ntfy->bo.offset; - args.ctxdma.limit += chan->ntfy->bo.offset; + args.target = NV_DMA_V0_TARGET_VM; + args.access = NV_DMA_V0_ACCESS_RDWR; + args.start += chan->ntfy->bo.offset; + args.limit += chan->ntfy->bo.offset; } - ret = nvif_client_ioctl(client, &args, sizeof(args)); + client->route = NVDRM_OBJECT_ABI16; + client->super = true; + ret = nvif_object_init(&chan->chan->user, info->handle, + NV_DMA_IN_MEMORY, &args, sizeof(args), + &ntfy->object); client->super = false; + client->route = NVDRM_OBJECT_NVIF; if (ret) goto done; info->offset = ntfy->node->offset; - done: if (ret) nouveau_abi16_ntfy_fini(chan, ntfy); @@ -491,47 +571,28 @@ int nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS) { struct drm_nouveau_gpuobj_free *fini = data; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_del del; - } args = { - .ioctl.owner = NVDRM_OBJECT_ABI16, - .ioctl.type = NVIF_IOCTL_V0_DEL, - .ioctl.path_nr = 4, - .ioctl.path[3] = NOUVEAU_ABI16_CLIENT, - .ioctl.path[2] = NOUVEAU_ABI16_DEVICE, - .ioctl.path[1] = NOUVEAU_ABI16_CHAN(fini->channel), - .ioctl.path[0] = fini->handle, - }; - struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; struct nouveau_abi16_ntfy *ntfy; - struct nvif_client *client; - int ret; + int ret = -ENOENT; if (unlikely(!abi16)) return -ENOMEM; chan = nouveau_abi16_chan(abi16, fini->channel); if (!chan) - return nouveau_abi16_put(abi16, -ENOENT); - client = nvif_client(nvif_object(&abi16->device)); + return nouveau_abi16_put(abi16, -EINVAL); /* synchronize with the user channel and destroy the gpu object */ nouveau_channel_idle(chan->chan); - ret = nvif_client_ioctl(client, &args, sizeof(args)); - if (ret) - return nouveau_abi16_put(abi16, ret); - - /* cleanup extra state if this object was a notifier */ list_for_each_entry(ntfy, &chan->notifiers, head) { - if (ntfy->handle == fini->handle) { - nvkm_mm_free(&chan->heap, &ntfy->node); - list_del(&ntfy->head); + if (ntfy->object.handle == fini->handle) { + nouveau_abi16_ntfy_fini(chan, ntfy); + ret = 0; break; } } - return nouveau_abi16_put(abi16, 0); + return nouveau_abi16_put(abi16, ret); } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.h b/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.h index 86eb1caf4..841cc556f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -13,9 +13,9 @@ int nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS); struct nouveau_abi16_ntfy { + struct nvif_object object; struct list_head head; struct nvkm_mm_node *node; - u32 handle; }; struct nouveau_abi16_chan { @@ -33,11 +33,11 @@ struct nouveau_abi16 { u64 handles; }; -struct nouveau_drm; -struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *, struct drm_device *); +struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *); int nouveau_abi16_put(struct nouveau_abi16 *, int); void nouveau_abi16_fini(struct nouveau_abi16 *); -u16 nouveau_abi16_swclass(struct nouveau_drm *); +s32 nouveau_abi16_swclass(struct nouveau_drm *); +int nouveau_abi16_usif(struct drm_file *, void *data, u32 size); #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.c b/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.c index 622424692..d5e6938cc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -206,7 +206,7 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev) return VGA_SWITCHEROO_DIS; } -static struct vga_switcheroo_handler nouveau_dsm_handler = { +static const struct vga_switcheroo_handler nouveau_dsm_handler = { .switchto = nouveau_dsm_switchto, .power_state = nouveau_dsm_power_state, .get_client_id = nouveau_dsm_get_client_id, @@ -367,17 +367,18 @@ static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios, return -ENODEV; } obj = (union acpi_object *)buffer.pointer; + len = min(len, (int)obj->buffer.length); memcpy(bios+offset, obj->buffer.pointer, len); kfree(buffer.pointer); return len; } -bool nouveau_acpi_rom_supported(struct pci_dev *pdev) +bool nouveau_acpi_rom_supported(struct device *dev) { acpi_status status; acpi_handle dhandle, rom_handle; - dhandle = ACPI_HANDLE(&pdev->dev); + dhandle = ACPI_HANDLE(dev); if (!dhandle) return false; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.h b/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.h index 74acf0f87..2f03653af 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -10,7 +10,7 @@ void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); void nouveau_switcheroo_optimus_dsm(void); int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); -bool nouveau_acpi_rom_supported(struct pci_dev *pdev); +bool nouveau_acpi_rom_supported(struct device *); void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); #else static inline bool nouveau_is_optimus(void) { return false; }; @@ -18,7 +18,7 @@ static inline bool nouveau_is_v1_dsm(void) { return false; }; static inline void nouveau_register_dsm_handler(void) {} static inline void nouveau_unregister_dsm_handler(void) {} static inline void nouveau_switcheroo_optimus_dsm(void) {} -static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } +static inline bool nouveau_acpi_rom_supported(struct device *dev) { return false; } static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_agp.c b/kernel/drivers/gpu/drm/nouveau/nouveau_agp.c deleted file mode 100644 index 0b5970955..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_agp.c +++ /dev/null @@ -1,195 +0,0 @@ -#include - -#include "nouveau_drm.h" -#include "nouveau_agp.h" -#include "nouveau_reg.h" - -#if __OS_HAS_AGP -MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); -static int nouveau_agpmode = -1; -module_param_named(agpmode, nouveau_agpmode, int, 0400); - -struct nouveau_agpmode_quirk { - u16 hostbridge_vendor; - u16 hostbridge_device; - u16 chip_vendor; - u16 chip_device; - int mode; -}; - -static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = { - /* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo #20341 */ - { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, - - {}, -}; - -static unsigned long -get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info) -{ - struct nvif_device *device = &drm->device; - struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list; - int agpmode = nouveau_agpmode; - unsigned long mode = info->mode; - - /* - * FW seems to be broken on nv18, it makes the card lock up - * randomly. - */ - if (device->info.chipset == 0x18) - mode &= ~PCI_AGP_COMMAND_FW; - - /* - * Go through the quirks list and adjust the agpmode accordingly. - */ - while (agpmode == -1 && quirk->hostbridge_vendor) { - if (info->id_vendor == quirk->hostbridge_vendor && - info->id_device == quirk->hostbridge_device && - nvxx_device(device)->pdev->vendor == quirk->chip_vendor && - nvxx_device(device)->pdev->device == quirk->chip_device) { - agpmode = quirk->mode; - NV_INFO(drm, "Forcing agp mode to %dX. Use agpmode to override.\n", - agpmode); - break; - } - ++quirk; - } - - /* - * AGP mode set in the command line. - */ - if (agpmode > 0) { - bool agpv3 = mode & 0x8; - int rate = agpv3 ? agpmode / 4 : agpmode; - - mode = (mode & ~0x7) | (rate & 0x7); - } - - return mode; -} - -static bool -nouveau_agp_enabled(struct nouveau_drm *drm) -{ - struct drm_device *dev = drm->dev; - - if (!dev->pdev || !drm_pci_device_is_agp(dev) || !dev->agp) - return false; - - if (drm->agp.stat == UNKNOWN) { - if (!nouveau_agpmode) - return false; -#ifdef __powerpc__ - /* Disable AGP by default on all PowerPC machines for - * now -- At least some UniNorth-2 AGP bridges are - * known to be broken: DMA from the host to the card - * works just fine, but writeback from the card to the - * host goes straight to memory untranslated bypassing - * the GATT somehow, making them quite painful to deal - * with... - */ - if (nouveau_agpmode == -1) - return false; -#endif - return true; - } - - return (drm->agp.stat == ENABLED); -} -#endif - -void -nouveau_agp_reset(struct nouveau_drm *drm) -{ -#if __OS_HAS_AGP - struct nvif_device *device = &drm->device; - struct drm_device *dev = drm->dev; - u32 save[2]; - int ret; - - if (!nouveau_agp_enabled(drm)) - return; - - /* First of all, disable fast writes, otherwise if it's - * already enabled in the AGP bridge and we disable the card's - * AGP controller we might be locking ourselves out of it. */ - if ((nvif_rd32(device, NV04_PBUS_PCI_NV_19) | - dev->agp->mode) & PCI_AGP_COMMAND_FW) { - struct drm_agp_info info; - struct drm_agp_mode mode; - - ret = drm_agp_info(dev, &info); - if (ret) - return; - - mode.mode = get_agp_mode(drm, &info); - mode.mode &= ~PCI_AGP_COMMAND_FW; - - ret = drm_agp_enable(dev, mode); - if (ret) - return; - } - - - /* clear busmaster bit, and disable AGP */ - save[0] = nvif_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000); - nvif_wr32(device, NV04_PBUS_PCI_NV_19, 0); - - /* reset PGRAPH, PFIFO and PTIMER */ - save[1] = nvif_mask(device, 0x000200, 0x00011100, 0x00000000); - nvif_mask(device, 0x000200, 0x00011100, save[1]); - - /* and restore bustmaster bit (gives effect of resetting AGP) */ - nvif_wr32(device, NV04_PBUS_PCI_NV_1, save[0]); -#endif -} - -void -nouveau_agp_init(struct nouveau_drm *drm) -{ -#if __OS_HAS_AGP - struct drm_device *dev = drm->dev; - struct drm_agp_info info; - struct drm_agp_mode mode; - int ret; - - if (!nouveau_agp_enabled(drm)) - return; - drm->agp.stat = DISABLE; - - ret = drm_agp_acquire(dev); - if (ret) { - NV_ERROR(drm, "unable to acquire AGP: %d\n", ret); - return; - } - - ret = drm_agp_info(dev, &info); - if (ret) { - NV_ERROR(drm, "unable to get AGP info: %d\n", ret); - return; - } - - /* see agp.h for the AGPSTAT_* modes available */ - mode.mode = get_agp_mode(drm, &info); - - ret = drm_agp_enable(dev, mode); - if (ret) { - NV_ERROR(drm, "unable to enable AGP: %d\n", ret); - return; - } - - drm->agp.stat = ENABLED; - drm->agp.base = info.aperture_base; - drm->agp.size = info.aperture_size; -#endif -} - -void -nouveau_agp_fini(struct nouveau_drm *drm) -{ -#if __OS_HAS_AGP - struct drm_device *dev = drm->dev; - if (dev->agp && dev->agp->acquired) - drm_agp_release(dev); -#endif -} diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_agp.h b/kernel/drivers/gpu/drm/nouveau/nouveau_agp.h deleted file mode 100644 index b55c08652..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_agp.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __NOUVEAU_AGP_H__ -#define __NOUVEAU_AGP_H__ - -struct nouveau_drm; - -void nouveau_agp_reset(struct nouveau_drm *); -void nouveau_agp_init(struct nouveau_drm *); -void nouveau_agp_fini(struct nouveau_drm *); - -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c b/kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c index e566c5b53..89eb46040 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -40,7 +40,7 @@ static int nv40_get_intensity(struct backlight_device *bd) { struct nouveau_drm *drm = bl_get_data(bd); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK) >> 16; @@ -51,7 +51,7 @@ static int nv40_set_intensity(struct backlight_device *bd) { struct nouveau_drm *drm = bl_get_data(bd); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; int val = bd->props.brightness; int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT); @@ -71,7 +71,7 @@ static int nv40_backlight_init(struct drm_connector *connector) { struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; struct backlight_properties props; struct backlight_device *bd; @@ -97,7 +97,7 @@ nv50_get_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; int or = nv_encoder->or; u32 div = 1025; u32 val; @@ -112,7 +112,7 @@ nv50_set_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; int or = nv_encoder->or; u32 div = 1025; u32 val = (bd->props.brightness * div) / 100; @@ -133,7 +133,7 @@ nva3_get_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; int or = nv_encoder->or; u32 div, val; @@ -151,7 +151,7 @@ nva3_set_intensity(struct backlight_device *bd) { struct nouveau_encoder *nv_encoder = bl_get_data(bd); struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; int or = nv_encoder->or; u32 div, val; @@ -177,7 +177,7 @@ static int nv50_backlight_init(struct drm_connector *connector) { struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; struct nouveau_encoder *nv_encoder; struct backlight_properties props; struct backlight_device *bd; @@ -193,9 +193,9 @@ nv50_backlight_init(struct drm_connector *connector) if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or))) return 0; - if (device->info.chipset <= 0xa0 || - device->info.chipset == 0xaa || - device->info.chipset == 0xac) + if (drm->device.info.chipset <= 0xa0 || + drm->device.info.chipset == 0xaa || + drm->device.info.chipset == 0xac) ops = &nv50_bl_ops; else ops = &nva3_bl_ops; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_bios.c b/kernel/drivers/gpu/drm/nouveau/nouveau_bios.c index 0190b69bb..4dca65a63 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -215,7 +215,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head */ struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; struct nvbios *bios = &drm->vbios; uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; uint32_t sel_clk_binding, sel_clk; @@ -318,7 +318,8 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n static int get_fp_strap(struct drm_device *dev, struct nvbios *bios) { - struct nvif_device *device = &nouveau_drm(dev)->device; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvif_object *device = &drm->device.object; /* * The fp strap is normally dictated by the "User Strap" in @@ -332,7 +333,7 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios) if (bios->major_version < 5 && bios->data[0x48] & 0x4) return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf; - if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) + if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; else return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; @@ -634,7 +635,7 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, */ struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; struct nvbios *bios = &drm->vbios; int cv = bios->chip_version; uint16_t clktable = 0, scriptptr; @@ -1481,22 +1482,20 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, entry->dpconf.link_bw = 540000; break; } - entry->dpconf.link_nr = (conf & 0x0f000000) >> 24; - if (dcb->version < 0x41) { - switch (entry->dpconf.link_nr) { - case 0xf: - entry->dpconf.link_nr = 4; - break; - case 0x3: - entry->dpconf.link_nr = 2; - break; - default: - entry->dpconf.link_nr = 1; - break; - } + switch ((conf & 0x0f000000) >> 24) { + case 0xf: + case 0x4: + entry->dpconf.link_nr = 4; + break; + case 0x3: + case 0x2: + entry->dpconf.link_nr = 2; + break; + default: + entry->dpconf.link_nr = 1; + break; } link = entry->dpconf.sor.link; - entry->i2c_index += NV_I2C_AUX(0); break; case DCB_OUTPUT_TMDS: if (dcb->version >= 0x40) { @@ -1892,11 +1891,12 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) idx = -1; while ((conn = olddcb_conn(dev, ++idx))) { if (conn[0] != 0xff) { - NV_INFO(drm, "DCB conn %02d: ", idx); if (olddcb_conntab(dev)[3] < 4) - pr_cont("%04x\n", ROM16(conn[0])); + NV_INFO(drm, "DCB conn %02d: %04x\n", + idx, ROM16(conn[0])); else - pr_cont("%08x\n", ROM32(conn[0])); + NV_INFO(drm, "DCB conn %02d: %08x\n", + idx, ROM32(conn[0])); } } dcb_fake_connectors(bios); @@ -1915,7 +1915,7 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio */ struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->device; + struct nvif_object *device = &drm->device.object; uint8_t bytes_to_write; uint16_t hwsq_entry_offset; int i; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_bo.c b/kernel/drivers/gpu/drm/nouveau/nouveau_bo.c index 6edcce165..78f520d05 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -48,24 +48,19 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, { struct nouveau_drm *drm = nouveau_drm(dev); int i = reg - drm->tile.reg; - struct nvkm_fb *pfb = nvxx_fb(&drm->device); - struct nvkm_fb_tile *tile = &pfb->tile.region[i]; - struct nvkm_engine *engine; + struct nvkm_device *device = nvxx_device(&drm->device); + struct nvkm_fb *fb = device->fb; + struct nvkm_fb_tile *tile = &fb->tile.region[i]; nouveau_fence_unref(®->fence); if (tile->pitch) - pfb->tile.fini(pfb, i, tile); + nvkm_fb_tile_fini(fb, i, tile); if (pitch) - pfb->tile.init(pfb, i, addr, size, pitch, flags, tile); - - pfb->tile.prog(pfb, i, tile); + nvkm_fb_tile_init(fb, i, addr, size, pitch, flags, tile); - if ((engine = nvkm_engine(pfb, NVDEV_ENGINE_GR))) - engine->tile_prog(engine, i); - if ((engine = nvkm_engine(pfb, NVDEV_ENGINE_MPEG))) - engine->tile_prog(engine, i); + nvkm_fb_tile_prog(fb, i, tile); } static struct nouveau_drm_tile * @@ -105,18 +100,18 @@ nv10_bo_set_tiling(struct drm_device *dev, u32 addr, u32 size, u32 pitch, u32 flags) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_fb *pfb = nvxx_fb(&drm->device); + struct nvkm_fb *fb = nvxx_fb(&drm->device); struct nouveau_drm_tile *tile, *found = NULL; int i; - for (i = 0; i < pfb->tile.regions; i++) { + for (i = 0; i < fb->tile.regions; i++) { tile = nv10_bo_get_tile_region(dev, i); if (pitch && !found) { found = tile; continue; - } else if (tile && pfb->tile.region[i].pitch) { + } else if (tile && fb->tile.region[i].pitch) { /* Kill an unused tile region. */ nv10_bo_update_tile_region(dev, tile, 0, 0, 0, 0); } @@ -214,7 +209,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, nvbo->tile_flags = tile_flags; nvbo->bo.bdev = &drm->ttm.bdev; - if (!nv_device_is_cpu_coherent(nvxx_device(&drm->device))) + if (!nvxx_device(&drm->device)->func->cpu_coherent) nvbo->force_coherent = flags & TTM_PL_FLAG_UNCACHED; nvbo->page_shift = 12; @@ -471,8 +466,8 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) return; for (i = 0; i < ttm_dma->ttm.num_pages; i++) - dma_sync_single_for_device(nv_device_base(device), - ttm_dma->dma_address[i], PAGE_SIZE, DMA_TO_DEVICE); + dma_sync_single_for_device(device->dev, ttm_dma->dma_address[i], + PAGE_SIZE, DMA_TO_DEVICE); } void @@ -491,8 +486,8 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) return; for (i = 0; i < ttm_dma->ttm.num_pages; i++) - dma_sync_single_for_cpu(nv_device_base(device), - ttm_dma->dma_address[i], PAGE_SIZE, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(device->dev, ttm_dma->dma_address[i], + PAGE_SIZE, DMA_FROM_DEVICE); } int @@ -579,12 +574,11 @@ static struct ttm_tt * nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, uint32_t page_flags, struct page *dummy_read) { -#if __OS_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) struct nouveau_drm *drm = nouveau_bdev(bdev); - struct drm_device *dev = drm->dev; - if (drm->agp.stat == ENABLED) { - return ttm_agp_tt_create(bdev, dev->agp->bridge, size, + if (drm->agp.bridge) { + return ttm_agp_tt_create(bdev, drm->agp.bridge, size, page_flags, dummy_read); } #endif @@ -636,12 +630,12 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) man->func = &nouveau_gart_manager; else - if (drm->agp.stat != ENABLED) + if (!drm->agp.bridge) man->func = &nv04_gart_manager; else man->func = &ttm_bo_manager_func; - if (drm->agp.stat == ENABLED) { + if (drm->agp.bridge) { man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; @@ -1064,7 +1058,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_channel *chan = drm->ttm.chan; - struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base); + struct nouveau_cli *cli = (void *)chan->user.client; struct nouveau_fence *fence; int ret; @@ -1104,7 +1098,7 @@ nouveau_bo_move_init(struct nouveau_drm *drm) static const struct { const char *name; int engine; - u32 oclass; + s32 oclass; int (*exec)(struct nouveau_channel *, struct ttm_buffer_object *, struct ttm_mem_reg *, struct ttm_mem_reg *); @@ -1137,7 +1131,7 @@ nouveau_bo_move_init(struct nouveau_drm *drm) if (chan == NULL) continue; - ret = nvif_object_init(chan->object, NULL, + ret = nvif_object_init(&chan->user, mthd->oclass | (mthd->engine << 16), mthd->oclass, NULL, 0, &drm->ttm.copy); @@ -1356,6 +1350,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; struct nouveau_drm *drm = nouveau_bdev(bdev); + struct nvkm_device *device = nvxx_device(&drm->device); struct nvkm_mem *node = mem->mm_node; int ret; @@ -1371,11 +1366,11 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) /* System memory */ return 0; case TTM_PL_TT: -#if __OS_HAS_AGP - if (drm->agp.stat == ENABLED) { +#if IS_ENABLED(CONFIG_AGP) + if (drm->agp.bridge) { mem->bus.offset = mem->start << PAGE_SHIFT; mem->bus.base = drm->agp.base; - mem->bus.is_iomem = !drm->dev->agp->cant_use_aperture; + mem->bus.is_iomem = !drm->agp.cma; } #endif if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype) @@ -1384,16 +1379,20 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) /* fallthrough, tiled memory */ case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = nv_device_resource_start(nvxx_device(&drm->device), 1); + mem->bus.base = device->func->resource_addr(device, 1); mem->bus.is_iomem = true; if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { struct nvkm_bar *bar = nvxx_bar(&drm->device); + int page_shift = 12; + if (drm->device.info.family >= NV_DEVICE_INFO_V0_FERMI) + page_shift = node->page_shift; - ret = bar->umap(bar, node, NV_MEM_ACCESS_RW, - &node->bar_vma); + ret = nvkm_bar_umap(bar, node->size << 12, page_shift, + &node->bar_vma); if (ret) return ret; + nvkm_vm_map(&node->bar_vma, node); mem->bus.offset = node->bar_vma.offset; } break; @@ -1406,14 +1405,13 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) static void nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { - struct nouveau_drm *drm = nouveau_bdev(bdev); - struct nvkm_bar *bar = nvxx_bar(&drm->device); struct nvkm_mem *node = mem->mm_node; if (!node->bar_vma.node) return; - bar->unmap(bar, &node->bar_vma); + nvkm_vm_unmap(&node->bar_vma); + nvkm_vm_put(&node->bar_vma); } static int @@ -1421,8 +1419,8 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nvif_device *device = &drm->device; - u32 mappable = nv_device_resource_len(nvxx_device(device), 1) >> PAGE_SHIFT; + struct nvkm_device *device = nvxx_device(&drm->device); + u32 mappable = device->func->resource_size(device, 1) >> PAGE_SHIFT; int i, ret; /* as long as the bo isn't in vram, and isn't tiled, we've got @@ -1488,18 +1486,18 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) drm = nouveau_bdev(ttm->bdev); device = nvxx_device(&drm->device); dev = drm->dev; - pdev = nv_device_base(device); + pdev = device->dev; /* * Objects matching this condition have been marked as force_coherent, * so use the DMA API for them. */ - if (!nv_device_is_cpu_coherent(device) && + if (!nvxx_device(&drm->device)->func->cpu_coherent && ttm->caching_state == tt_uncached) return ttm_dma_populate(ttm_dma, dev->dev); -#if __OS_HAS_AGP - if (drm->agp.stat == ENABLED) { +#if IS_ENABLED(CONFIG_AGP) + if (drm->agp.bridge) { return ttm_agp_tt_populate(ttm); } #endif @@ -1553,20 +1551,20 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) drm = nouveau_bdev(ttm->bdev); device = nvxx_device(&drm->device); dev = drm->dev; - pdev = nv_device_base(device); + pdev = device->dev; /* * Objects matching this condition have been marked as force_coherent, * so use the DMA API for them. */ - if (!nv_device_is_cpu_coherent(device) && + if (!nvxx_device(&drm->device)->func->cpu_coherent && ttm->caching_state == tt_uncached) { ttm_dma_unpopulate(ttm_dma, dev->dev); return; } -#if __OS_HAS_AGP - if (drm->agp.stat == ENABLED) { +#if IS_ENABLED(CONFIG_AGP) + if (drm->agp.bridge) { ttm_agp_tt_unpopulate(ttm); return; } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_chan.c b/kernel/drivers/gpu/drm/nouveau/nouveau_chan.c index 0589babc5..1860f389f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -24,6 +24,7 @@ #include #include +#include /*XXX*/ #include @@ -42,20 +43,24 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); int nouveau_channel_idle(struct nouveau_channel *chan) { - struct nouveau_cli *cli = (void *)nvif_client(chan->object); - struct nouveau_fence *fence = NULL; - int ret; + if (likely(chan && chan->fence)) { + struct nouveau_cli *cli = (void *)chan->user.client; + struct nouveau_fence *fence = NULL; + int ret; + + ret = nouveau_fence_new(chan, false, &fence); + if (!ret) { + ret = nouveau_fence_wait(fence, false, false); + nouveau_fence_unref(&fence); + } - ret = nouveau_fence_new(chan, false, &fence); - if (!ret) { - ret = nouveau_fence_wait(fence, false, false); - nouveau_fence_unref(&fence); + if (ret) { + NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n", + chan->chid, nvxx_client(&cli->base)->name); + return ret; + } } - - if (ret) - NV_PRINTK(error, cli, "failed to idle channel 0x%08x [%s]\n", - chan->object->handle, nvxx_client(&cli->base)->name); - return ret; + return 0; } void @@ -63,21 +68,18 @@ nouveau_channel_del(struct nouveau_channel **pchan) { struct nouveau_channel *chan = *pchan; if (chan) { - if (chan->fence) { - nouveau_channel_idle(chan); + if (chan->fence) nouveau_fence(chan->drm)->context_del(chan); - } nvif_object_fini(&chan->nvsw); nvif_object_fini(&chan->gart); nvif_object_fini(&chan->vram); - nvif_object_ref(NULL, &chan->object); + nvif_object_fini(&chan->user); nvif_object_fini(&chan->push.ctxdma); nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma); nouveau_bo_unmap(chan->push.buffer); if (chan->push.buffer && chan->push.buffer->pin_refcnt) nouveau_bo_unpin(chan->push.buffer); nouveau_bo_ref(NULL, &chan->push.buffer); - nvif_device_ref(NULL, &chan->device); kfree(chan); } *pchan = NULL; @@ -85,9 +87,9 @@ nouveau_channel_del(struct nouveau_channel **pchan) static int nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, u32 size, struct nouveau_channel **pchan) + u32 size, struct nouveau_channel **pchan) { - struct nouveau_cli *cli = (void *)nvif_client(&device->base); + struct nouveau_cli *cli = (void *)device->object.client; struct nvkm_mmu *mmu = nvxx_mmu(device); struct nv_dma_v0 args = {}; struct nouveau_channel *chan; @@ -98,7 +100,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, if (!chan) return -ENOMEM; - nvif_device_ref(device, &chan->device); + chan->device = device; chan->drm = drm; /* allocate memory for dma push buffer */ @@ -146,7 +148,8 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, */ args.target = NV_DMA_V0_TARGET_PCI; args.access = NV_DMA_V0_ACCESS_RDWR; - args.start = nv_device_resource_start(nvxx_device(device), 1); + args.start = nvxx_device(device)->func-> + resource_addr(nvxx_device(device), 1); args.limit = args.start + device->info.ram_user - 1; } else { args.target = NV_DMA_V0_TARGET_VRAM; @@ -155,7 +158,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, args.limit = device->info.ram_user - 1; } } else { - if (chan->drm->agp.stat == ENABLED) { + if (chan->drm->agp.bridge) { args.target = NV_DMA_V0_TARGET_AGP; args.access = NV_DMA_V0_ACCESS_RDWR; args.start = chan->drm->agp.base; @@ -169,8 +172,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, } } - ret = nvif_object_init(nvif_object(device), NULL, NVDRM_PUSH | - (handle & 0xffff), NV_DMA_FROM_MEMORY, + ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY, &args, sizeof(args), &chan->push.ctxdma); if (ret) { nouveau_channel_del(pchan); @@ -182,7 +184,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, static int nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, u32 engine, struct nouveau_channel **pchan) + u32 engine, struct nouveau_channel **pchan) { static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A, KEPLER_CHANNEL_GPFIFO_A, @@ -193,14 +195,15 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, const u16 *oclass = oclasses; union { struct nv50_channel_gpfifo_v0 nv50; + struct fermi_channel_gpfifo_v0 fermi; struct kepler_channel_gpfifo_a_v0 kepler; - } args, *retn; + } args; struct nouveau_channel *chan; u32 size; int ret; /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan); + ret = nouveau_channel_prep(drm, device, 0x12000, &chan); *pchan = chan; if (ret) return ret; @@ -210,26 +213,36 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { args.kepler.version = 0; args.kepler.engine = engine; - args.kepler.pushbuf = chan->push.ctxdma.handle; args.kepler.ilength = 0x02000; args.kepler.ioffset = 0x10000 + chan->push.vma.offset; + args.kepler.vm = 0; size = sizeof(args.kepler); + } else + if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { + args.fermi.version = 0; + args.fermi.ilength = 0x02000; + args.fermi.ioffset = 0x10000 + chan->push.vma.offset; + args.fermi.vm = 0; + size = sizeof(args.fermi); } else { args.nv50.version = 0; - args.nv50.pushbuf = chan->push.ctxdma.handle; args.nv50.ilength = 0x02000; args.nv50.ioffset = 0x10000 + chan->push.vma.offset; + args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma); + args.nv50.vm = 0; size = sizeof(args.nv50); } - ret = nvif_object_new(nvif_object(device), handle, *oclass++, - &args, size, &chan->object); + ret = nvif_object_init(&device->object, 0, *oclass++, + &args, size, &chan->user); if (ret == 0) { - retn = chan->object->data; - if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A) - chan->chid = retn->kepler.chid; + if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) + chan->chid = args.kepler.chid; + else + if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) + chan->chid = args.fermi.chid; else - chan->chid = retn->nv50.chid; + chan->chid = args.nv50.chid; return ret; } } while (*oclass); @@ -240,7 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, static int nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, struct nouveau_channel **pchan) + struct nouveau_channel **pchan) { static const u16 oclasses[] = { NV40_CHANNEL_DMA, NV17_CHANNEL_DMA, @@ -248,27 +261,26 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, NV03_CHANNEL_DMA, 0 }; const u16 *oclass = oclasses; - struct nv03_channel_dma_v0 args, *retn; + struct nv03_channel_dma_v0 args; struct nouveau_channel *chan; int ret; /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan); + ret = nouveau_channel_prep(drm, device, 0x10000, &chan); *pchan = chan; if (ret) return ret; /* create channel object */ args.version = 0; - args.pushbuf = chan->push.ctxdma.handle; + args.pushbuf = nvif_handle(&chan->push.ctxdma); args.offset = chan->push.vma.offset; do { - ret = nvif_object_new(nvif_object(device), handle, *oclass++, - &args, sizeof(args), &chan->object); + ret = nvif_object_init(&device->object, 0, *oclass++, + &args, sizeof(args), &chan->user); if (ret == 0) { - retn = chan->object->data; - chan->chid = retn->chid; + chan->chid = args.chid; return ret; } } while (ret && *oclass); @@ -281,13 +293,12 @@ static int nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) { struct nvif_device *device = chan->device; - struct nouveau_cli *cli = (void *)nvif_client(&device->base); + struct nouveau_cli *cli = (void *)chan->user.client; struct nvkm_mmu *mmu = nvxx_mmu(device); - struct nvkm_sw_chan *swch; struct nv_dma_v0 args = {}; int ret, i; - nvif_object_map(chan->object); + nvif_object_map(&chan->user); /* allocate dma objects to cover all allowed vram, and gart */ if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { @@ -303,9 +314,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.limit = device->info.ram_user - 1; } - ret = nvif_object_init(chan->object, NULL, vram, - NV_DMA_IN_MEMORY, &args, - sizeof(args), &chan->vram); + ret = nvif_object_init(&chan->user, vram, NV_DMA_IN_MEMORY, + &args, sizeof(args), &chan->vram); if (ret) return ret; @@ -315,7 +325,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.start = 0; args.limit = cli->vm->mmu->limit - 1; } else - if (chan->drm->agp.stat == ENABLED) { + if (chan->drm->agp.bridge) { args.target = NV_DMA_V0_TARGET_AGP; args.access = NV_DMA_V0_ACCESS_RDWR; args.start = chan->drm->agp.base; @@ -328,15 +338,14 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.limit = mmu->limit - 1; } - ret = nvif_object_init(chan->object, NULL, gart, - NV_DMA_IN_MEMORY, &args, - sizeof(args), &chan->gart); + ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY, + &args, sizeof(args), &chan->gart); if (ret) return ret; } /* initialise dma tracking parameters */ - switch (chan->object->oclass & 0x00ff) { + switch (chan->user.oclass & 0x00ff) { case 0x006b: case 0x006e: chan->user_put = 0x40; @@ -368,15 +377,12 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) /* allocate software object class (used for fences on <= nv05) */ if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) { - ret = nvif_object_init(chan->object, NULL, 0x006e, 0x006e, + ret = nvif_object_init(&chan->user, 0x006e, + NVIF_IOCTL_NEW_V0_SW_NV04, NULL, 0, &chan->nvsw); if (ret) return ret; - swch = (void *)nvxx_object(&chan->nvsw)->parent; - swch->flip = nouveau_flip_complete; - swch->flip_data = chan; - ret = RING_SPACE(chan, 2); if (ret) return ret; @@ -392,10 +398,9 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) int nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, u32 arg0, u32 arg1, - struct nouveau_channel **pchan) + u32 arg0, u32 arg1, struct nouveau_channel **pchan) { - struct nouveau_cli *cli = (void *)nvif_client(&device->base); + struct nouveau_cli *cli = (void *)device->object.client; bool super; int ret; @@ -403,19 +408,19 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, super = cli->base.super; cli->base.super = true; - ret = nouveau_channel_ind(drm, device, handle, arg0, pchan); + ret = nouveau_channel_ind(drm, device, arg0, pchan); if (ret) { - NV_PRINTK(debug, cli, "ib channel create, %d\n", ret); - ret = nouveau_channel_dma(drm, device, handle, pchan); + NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); + ret = nouveau_channel_dma(drm, device, pchan); if (ret) { - NV_PRINTK(debug, cli, "dma channel create, %d\n", ret); + NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret); goto done; } } ret = nouveau_channel_init(*pchan, arg0, arg1); if (ret) { - NV_PRINTK(error, cli, "channel failed to initialise, %d\n", ret); + NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret); nouveau_channel_del(pchan); } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_chan.h b/kernel/drivers/gpu/drm/nouveau/nouveau_chan.h index 8b3640f69..48062c94f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -37,13 +37,12 @@ struct nouveau_channel { u32 user_get; u32 user_put; - struct nvif_object *object; + struct nvif_object user; }; int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, - u32 handle, u32 arg0, u32 arg1, - struct nouveau_channel **); + u32 arg0, u32 arg1, struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **); int nouveau_channel_idle(struct nouveau_channel *); diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_connector.c b/kernel/drivers/gpu/drm/nouveau/nouveau_connector.c index 3162040bc..2a5ed7460 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -125,9 +125,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) * is handled by the SOR itself, and not required for LVDS DDC. */ if (nv_connector->type == DCB_CONNECTOR_eDP) { - panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); + panel = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); if (panel == 0) { - gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); + nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); msleep(300); } } @@ -148,7 +148,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) break; } else if (nv_encoder->i2c) { - if (nv_probe_i2c(nv_encoder->i2c, 0x50)) + if (nvkm_probe_i2c(nv_encoder->i2c, 0x50)) break; } } @@ -157,7 +157,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) * state to avoid confusing the SOR for other output types. */ if (!nv_encoder && panel == 0) - gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); + nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); return nv_encoder; } @@ -241,7 +241,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_partner; - struct nvkm_i2c_port *i2c; + struct i2c_adapter *i2c; int type; int ret; enum drm_connector_status conn_status = connector_status_disconnected; @@ -259,7 +259,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) nv_encoder = nouveau_connector_ddc_detect(connector); if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { - nv_connector->edid = drm_get_edid(connector, &i2c->adapter); + nv_connector->edid = drm_get_edid(connector, i2c); drm_mode_connector_update_edid_property(connector, nv_connector->edid); if (!nv_connector->edid) { @@ -919,7 +919,7 @@ nouveau_connector_funcs_lvds = { .force = nouveau_connector_force }; -static void +static int nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) { struct nouveau_encoder *nv_encoder = NULL; @@ -930,15 +930,15 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) nv_encoder->dcb->type == DCB_OUTPUT_DP) { if (mode == DRM_MODE_DPMS_ON) { u8 data = DP_SET_POWER_D0; - nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1); + nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1); usleep_range(1000, 2000); } else { u8 data = DP_SET_POWER_D3; - nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1); + nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1); } } - drm_helper_connector_dpms(connector, mode); + return drm_helper_connector_dpms(connector, mode); } static const struct drm_connector_funcs @@ -969,10 +969,13 @@ nouveau_connector_hotplug(struct nvif_notify *notify) NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); + mutex_lock(&drm->dev->mode_config.mutex); if (plugged) drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); else drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + mutex_unlock(&drm->dev->mode_config.mutex); + drm_helper_hpd_irq_event(connector->dev); } @@ -980,29 +983,29 @@ nouveau_connector_hotplug(struct nvif_notify *notify) } static ssize_t -nouveau_connector_aux_xfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) +nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg) { struct nouveau_connector *nv_connector = - container_of(aux, typeof(*nv_connector), aux); + container_of(obj, typeof(*nv_connector), aux); struct nouveau_encoder *nv_encoder; - struct nvkm_i2c_port *port; + struct nvkm_i2c_aux *aux; int ret; nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); - if (!nv_encoder || !(port = nv_encoder->i2c)) + if (!nv_encoder || !(aux = nv_encoder->aux)) return -ENODEV; if (WARN_ON(msg->size > 16)) return -E2BIG; if (msg->size == 0) return msg->size; - ret = nvkm_i2c(port)->acquire(port, 0); + ret = nvkm_i2c_aux_acquire(aux); if (ret) return ret; - ret = port->func->aux(port, false, msg->request, msg->address, - msg->buffer, msg->size); - nvkm_i2c(port)->release(port); + ret = nvkm_i2c_aux_xfer(aux, false, msg->request, msg->address, + msg->buffer, msg->size); + nvkm_i2c_aux_release(aux); if (ret >= 0) { msg->reply = ret; return msg->size; @@ -1256,8 +1259,8 @@ nouveau_connector_create(struct drm_device *dev, int index) break; } - ret = nvif_notify_init(&disp->disp, NULL, nouveau_connector_hotplug, - true, NV04_DISP_NTFY_CONN, + ret = nvif_notify_init(&disp->disp, nouveau_connector_hotplug, true, + NV04_DISP_NTFY_CONN, &(struct nvif_notify_conn_req_v0) { .mask = NVIF_NOTIFY_CONN_V0_ANY, .conn = index, diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_display.c b/kernel/drivers/gpu/drm/nouveau/nouveau_display.c index 8670d90cd..58a3f7cf2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_display.c @@ -51,12 +51,12 @@ nouveau_display_vblank_handler(struct nvif_notify *notify) } int -nouveau_display_vblank_enable(struct drm_device *dev, int head) +nouveau_display_vblank_enable(struct drm_device *dev, unsigned int pipe) { struct drm_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - if (nv_crtc->index == head) { + if (nv_crtc->index == pipe) { nvif_notify_get(&nv_crtc->vblank); return 0; } @@ -65,12 +65,12 @@ nouveau_display_vblank_enable(struct drm_device *dev, int head) } void -nouveau_display_vblank_disable(struct drm_device *dev, int head) +nouveau_display_vblank_disable(struct drm_device *dev, unsigned int pipe) { struct drm_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - if (nv_crtc->index == head) { + if (nv_crtc->index == pipe) { nvif_notify_put(&nv_crtc->vblank); return; } @@ -103,6 +103,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, .base.head = nouveau_crtc(crtc)->index, }; struct nouveau_display *disp = nouveau_display(crtc->dev); + struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; int ret, retry = 1; do { @@ -116,7 +117,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, break; } - if (retry) ndelay(crtc->linedur_ns); + if (retry) ndelay(vblank->linedur_ns); } while (retry--); *hpos = args.scan.hline; @@ -131,13 +132,15 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, } int -nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) +nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe, + unsigned int flags, int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { struct drm_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (nouveau_crtc(crtc)->index == head) { + if (nouveau_crtc(crtc)->index == pipe) { return nouveau_display_scanoutpos_head(crtc, vpos, hpos, stime, etime); } @@ -147,15 +150,15 @@ nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags, } int -nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error, - struct timeval *time, unsigned flags) +nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe, + int *max_error, struct timeval *time, unsigned flags) { struct drm_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (nouveau_crtc(crtc)->index == head) { + if (nouveau_crtc(crtc)->index == pipe) { return drm_calc_vbltimestamp_from_scanoutpos(dev, - head, max_error, time, flags, crtc, + pipe, max_error, time, flags, &crtc->hwmode); } } @@ -185,7 +188,7 @@ nouveau_display_vblank_init(struct drm_device *dev) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - ret = nvif_notify_init(&disp->disp, NULL, + ret = nvif_notify_init(&disp->disp, nouveau_display_vblank_handler, false, NV04_DISP_NTFY_VBLANK, &(struct nvif_notify_head_req_v0) { @@ -358,6 +361,7 @@ int nouveau_display_init(struct drm_device *dev) { struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_connector *connector; int ret; @@ -374,6 +378,8 @@ nouveau_display_init(struct drm_device *dev) nvif_notify_get(&conn->hpd); } + /* enable flip completion events */ + nvif_notify_get(&drm->flip); return ret; } @@ -381,6 +387,7 @@ void nouveau_display_fini(struct drm_device *dev) { struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_connector *connector; int head; @@ -388,6 +395,9 @@ nouveau_display_fini(struct drm_device *dev) for (head = 0; head < dev->mode_config.num_crtc; head++) drm_vblank_off(dev, head); + /* disable flip completion events */ + nvif_notify_put(&drm->flip); + /* disable hotplug interrupts */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct nouveau_connector *conn = nouveau_connector(connector); @@ -438,6 +448,7 @@ int nouveau_display_create(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); + struct nvkm_device *device = nvxx_device(&drm->device); struct nouveau_display *disp; int ret; @@ -450,7 +461,7 @@ nouveau_display_create(struct drm_device *dev) drm_mode_create_dvi_i_properties(dev); dev->mode_config.funcs = &nouveau_mode_config_funcs; - dev->mode_config.fb_base = nv_device_resource_start(nvxx_device(&drm->device), 1); + dev->mode_config.fb_base = device->func->resource_addr(device, 1); dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; @@ -461,9 +472,13 @@ nouveau_display_create(struct drm_device *dev) if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { dev->mode_config.max_width = 4096; dev->mode_config.max_height = 4096; - } else { + } else + if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) { dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; + } else { + dev->mode_config.max_width = 16384; + dev->mode_config.max_height = 16384; } dev->mode_config.preferred_depth = 24; @@ -494,9 +509,8 @@ nouveau_display_create(struct drm_device *dev) int i; for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) { - ret = nvif_object_init(nvif_object(&drm->device), NULL, - NVDRM_DISPLAY, oclass[i], - NULL, 0, &disp->disp); + ret = nvif_object_init(&drm->device.object, 0, + oclass[i], NULL, 0, &disp->disp); } if (ret == 0) { @@ -620,10 +634,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) nv_crtc->lut.depth = 0; } - /* Make sure that drm and hw vblank irqs get resumed if needed. */ - for (head = 0; head < dev->mode_config.num_crtc; head++) - drm_vblank_on(dev, head); - /* This should ensure we don't hit a locking problem when someone * wakes us up via a connector. We should never go into suspend * while the display is on anyways. @@ -633,6 +643,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) drm_helper_resume_force_mode(dev); + /* Make sure that drm and hw vblank irqs get resumed if needed. */ + for (head = 0; head < dev->mode_config.num_crtc; head++) + drm_vblank_on(dev, head); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); @@ -711,7 +725,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, chan = drm->channel; if (!chan) return -ENODEV; - cli = (void *)nvif_client(&chan->device->base); + cli = (void *)chan->user.client; s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) @@ -815,7 +829,6 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, struct drm_device *dev = drm->dev; struct nouveau_page_flip_state *s; unsigned long flags; - int crtcid = -1; spin_lock_irqsave(&dev->event_lock, flags); @@ -827,15 +840,19 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); if (s->event) { - /* Vblank timestamps/counts are only correct on >= NV-50 */ - if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) - crtcid = s->crtc; + if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { + drm_arm_vblank_event(dev, s->crtc, s->event); + } else { + drm_send_vblank_event(dev, s->crtc, s->event); - drm_send_vblank_event(dev, crtcid, s->event); + /* Give up ownership of vblank for page-flipped crtc */ + drm_vblank_put(dev, s->crtc); + } + } + else { + /* Give up ownership of vblank for page-flipped crtc */ + drm_vblank_put(dev, s->crtc); } - - /* Give up ownership of vblank for page-flipped crtc */ - drm_vblank_put(dev, s->crtc); list_del(&s->head); if (ps) @@ -847,10 +864,10 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, } int -nouveau_flip_complete(void *data) +nouveau_flip_complete(struct nvif_notify *notify) { - struct nouveau_channel *chan = data; - struct nouveau_drm *drm = chan->drm; + struct nouveau_drm *drm = container_of(notify, typeof(*drm), flip); + struct nouveau_channel *chan = drm->channel; struct nouveau_page_flip_state state; if (!nouveau_finish_page_flip(chan, &state)) { @@ -861,7 +878,7 @@ nouveau_flip_complete(void *data) } } - return 0; + return NVIF_NOTIFY_KEEP; } int diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_display.h b/kernel/drivers/gpu/drm/nouveau/nouveau_display.h index a6213e242..856abe0f0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_display.h @@ -65,11 +65,12 @@ int nouveau_display_init(struct drm_device *dev); void nouveau_display_fini(struct drm_device *dev); int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); -int nouveau_display_vblank_enable(struct drm_device *, int); -void nouveau_display_vblank_disable(struct drm_device *, int); -int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int, - int *, int *, ktime_t *, ktime_t *); -int nouveau_display_vblstamp(struct drm_device *, int, int *, +int nouveau_display_vblank_enable(struct drm_device *, unsigned int); +void nouveau_display_vblank_disable(struct drm_device *, unsigned int); +int nouveau_display_scanoutpos(struct drm_device *, unsigned int, + unsigned int, int *, int *, ktime_t *, + ktime_t *, const struct drm_display_mode *); +int nouveau_display_vblstamp(struct drm_device *, unsigned int, int *, struct timeval *, unsigned); int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_dma.c b/kernel/drivers/gpu/drm/nouveau/nouveau_dma.c index 6d9245aa8..d168c6353 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -52,9 +52,9 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) { uint64_t val; - val = nvif_rd32(chan, chan->user_get); + val = nvif_rd32(&chan->user, chan->user_get); if (chan->user_get_hi) - val |= (uint64_t)nvif_rd32(chan, chan->user_get_hi) << 32; + val |= (uint64_t)nvif_rd32(&chan->user, chan->user_get_hi) << 32; /* reset counter as long as GET is still advancing, this is * to avoid misdetecting a GPU lockup if the GPU happens to @@ -82,7 +82,7 @@ void nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo, int delta, int length) { - struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base); + struct nouveau_cli *cli = (void *)chan->user.client; struct nouveau_bo *pb = chan->push.buffer; struct nvkm_vma *vma; int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; @@ -103,7 +103,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo, /* Flush writes. */ nouveau_bo_rd32(pb, 0); - nvif_wr32(chan, 0x8c, chan->dma.ib_put); + nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put); chan->dma.ib_free--; } @@ -113,7 +113,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) uint32_t cnt = 0, prev_get = 0; while (chan->dma.ib_free < count) { - uint32_t get = nvif_rd32(chan, 0x88); + uint32_t get = nvif_rd32(&chan->user, 0x88); if (get != prev_get) { prev_get = get; cnt = 0; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_dma.h b/kernel/drivers/gpu/drm/nouveau/nouveau_dma.h index 8da0a272c..aff3a9d0a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -140,7 +140,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data) #define WRITE_PUT(val) do { \ mb(); \ nouveau_bo_rd32(chan->push.buffer, 0); \ - nvif_wr32(chan, chan->user_put, ((val) << 2) + chan->push.vma.offset); \ + nvif_wr32(&chan->user, chan->user_put, ((val) << 2) + chan->push.vma.offset); \ } while (0) static inline void diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_dp.c b/kernel/drivers/gpu/drm/nouveau/nouveau_dp.c index c3ef30b3a..e17e15ec7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -31,8 +31,7 @@ #include "nouveau_crtc.h" static void -nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_port *auxch, - u8 *dpcd) +nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 *dpcd) { struct nouveau_drm *drm = nouveau_drm(dev); u8 buf[3]; @@ -40,11 +39,11 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_port *auxch, if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (!nv_rdaux(auxch, DP_SINK_OUI, buf, 3)) + if (!nvkm_rdaux(aux, DP_SINK_OUI, buf, 3)) NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (!nv_rdaux(auxch, DP_BRANCH_OUI, buf, 3)) + if (!nvkm_rdaux(aux, DP_BRANCH_OUI, buf, 3)) NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); @@ -55,15 +54,15 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c_port *auxch; + struct nvkm_i2c_aux *aux; u8 *dpcd = nv_encoder->dp.dpcd; int ret; - auxch = nv_encoder->i2c; - if (!auxch) + aux = nv_encoder->aux; + if (!aux) return -ENODEV; - ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8); + ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, 8); if (ret) return ret; @@ -84,6 +83,6 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) NV_DEBUG(drm, "maximum: %dx%d\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); - nouveau_dp_probe_oui(dev, auxch, dpcd); + nouveau_dp_probe_oui(dev, aux, dpcd); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c b/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c index cd6dae081..1d3ee5179 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -31,15 +32,15 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include #include #include +#include +#include #include "nouveau_drm.h" #include "nouveau_dma.h" #include "nouveau_ttm.h" #include "nouveau_gem.h" -#include "nouveau_agp.h" #include "nouveau_vga.h" #include "nouveau_sysfs.h" #include "nouveau_hwmon.h" @@ -104,14 +105,18 @@ nouveau_name(struct drm_device *dev) } static int -nouveau_cli_create(u64 name, const char *sname, +nouveau_cli_create(struct drm_device *dev, const char *sname, int size, void **pcli) { struct nouveau_cli *cli = *pcli = kzalloc(size, GFP_KERNEL); + int ret; if (cli) { - int ret = nvif_client_init(NULL, NULL, sname, name, - nouveau_config, nouveau_debug, - &cli->base); + snprintf(cli->name, sizeof(cli->name), "%s", sname); + cli->dev = dev; + + ret = nvif_client_init(NULL, cli->name, nouveau_name(dev), + nouveau_config, nouveau_debug, + &cli->base); if (ret == 0) { mutex_init(&cli->mutex); usif_client_init(cli); @@ -127,17 +132,23 @@ nouveau_cli_destroy(struct nouveau_cli *cli) nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); nvif_client_fini(&cli->base); usif_client_fini(cli); + kfree(cli); } static void nouveau_accel_fini(struct nouveau_drm *drm) { - nouveau_channel_del(&drm->channel); + nouveau_channel_idle(drm->channel); nvif_object_fini(&drm->ntfy); - nvkm_gpuobj_ref(NULL, &drm->notify); + nvkm_gpuobj_del(&drm->notify); + nvif_notify_fini(&drm->flip); nvif_object_fini(&drm->nvsw); - nouveau_channel_del(&drm->cechan); + nouveau_channel_del(&drm->channel); + + nouveau_channel_idle(drm->cechan); nvif_object_fini(&drm->ttm.copy); + nouveau_channel_del(&drm->cechan); + if (drm->fence) nouveau_fence(drm)->dtor(drm); } @@ -146,9 +157,9 @@ static void nouveau_accel_init(struct nouveau_drm *drm) { struct nvif_device *device = &drm->device; + struct nvif_sclass *sclass; u32 arg0, arg1; - u32 sclass[16]; - int ret, i; + int ret, i, n; if (nouveau_noaccel) return; @@ -157,12 +168,12 @@ nouveau_accel_init(struct nouveau_drm *drm) /*XXX: this is crap, but the fence/channel stuff is a little * backwards in some places. this will be fixed. */ - ret = nvif_object_sclass(&device->base, sclass, ARRAY_SIZE(sclass)); + ret = n = nvif_object_sclass_get(&device->object, &sclass); if (ret < 0) return; - for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) { - switch (sclass[i]) { + for (ret = -ENOSYS, i = 0; i < n; i++) { + switch (sclass[i].oclass) { case NV03_CHANNEL_DMA: ret = nv04_fence_create(drm); break; @@ -189,6 +200,7 @@ nouveau_accel_init(struct nouveau_drm *drm) } } + nvif_object_sclass_put(&sclass); if (ret) { NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret); nouveau_accel_fini(drm); @@ -196,7 +208,7 @@ nouveau_accel_init(struct nouveau_drm *drm) } if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { - ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, + ret = nouveau_channel_new(drm, &drm->device, KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, 0, &drm->cechan); @@ -209,7 +221,7 @@ nouveau_accel_init(struct nouveau_drm *drm) if (device->info.chipset >= 0xa3 && device->info.chipset != 0xaa && device->info.chipset != 0xac) { - ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, + ret = nouveau_channel_new(drm, &drm->device, NvDmaFB, NvDmaTT, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); @@ -221,18 +233,16 @@ nouveau_accel_init(struct nouveau_drm *drm) arg1 = NvDmaTT; } - ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1, - &drm->channel); + ret = nouveau_channel_new(drm, &drm->device, arg0, arg1, &drm->channel); if (ret) { NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); nouveau_accel_fini(drm); return; } - ret = nvif_object_init(drm->channel->object, NULL, NVDRM_NVSW, + ret = nvif_object_init(&drm->channel->user, NVDRM_NVSW, nouveau_abi16_swclass(drm), NULL, 0, &drm->nvsw); if (ret == 0) { - struct nvkm_sw_chan *swch; ret = RING_SPACE(drm->channel, 2); if (ret == 0) { if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { @@ -244,9 +254,16 @@ nouveau_accel_init(struct nouveau_drm *drm) OUT_RING (drm->channel, 0x001f0000); } } - swch = (void *)nvxx_object(&drm->nvsw)->parent; - swch->flip = nouveau_flip_complete; - swch->flip_data = drm->channel; + + ret = nvif_notify_init(&drm->nvsw, nouveau_flip_complete, + false, NVSW_NTFY_UEVENT, NULL, 0, 0, + &drm->flip); + if (ret == 0) + ret = nvif_notify_get(&drm->flip); + if (ret) { + nouveau_accel_fini(drm); + return; + } } if (ret) { @@ -256,15 +273,15 @@ nouveau_accel_init(struct nouveau_drm *drm) } if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { - ret = nvkm_gpuobj_new(nvxx_object(&drm->device), NULL, 32, - 0, 0, &drm->notify); + ret = nvkm_gpuobj_new(nvxx_device(&drm->device), 32, 0, false, + NULL, &drm->notify); if (ret) { NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); nouveau_accel_fini(drm); return; } - ret = nvif_object_init(drm->channel->object, NULL, NvNotify0, + ret = nvif_object_init(&drm->channel->user, NvNotify0, NV_DMA_IN_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_VRAM, @@ -319,9 +336,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev, remove_conflicting_framebuffers(aper, "nouveaufb", boot); kfree(aper); - ret = nvkm_device_create(pdev, NVKM_BUS_PCI, - nouveau_pci_name(pdev), pci_name(pdev), - nouveau_config, nouveau_debug, &device); + ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, + true, true, ~0ULL, &device); if (ret) return ret; @@ -329,7 +345,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev, ret = drm_get_pci_dev(pdev, pent, &driver_pci); if (ret) { - nvkm_object_ref(NULL, (struct nvkm_object **)&device); + nvkm_device_del(&device); return ret; } @@ -369,12 +385,10 @@ nouveau_get_hdmi_dev(struct nouveau_drm *drm) static int nouveau_drm_load(struct drm_device *dev, unsigned long flags) { - struct pci_dev *pdev = dev->pdev; struct nouveau_drm *drm; int ret; - ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm), - (void **)&drm); + ret = nouveau_cli_create(dev, "DRM", sizeof(*drm), (void **)&drm); if (ret) return ret; @@ -388,36 +402,9 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) nouveau_get_hdmi_dev(drm); - /* make sure AGP controller is in a consistent state before we - * (possibly) execute vbios init tables (see nouveau_agp.h) - */ - if (pdev && drm_pci_device_is_agp(dev) && dev->agp) { - const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY | - NV_DEVICE_V0_DISABLE_MMIO; - /* dummy device object, doesn't init anything, but allows - * agp code access to registers - */ - ret = nvif_device_init(&drm->client.base.base, NULL, - NVDRM_DEVICE, NV_DEVICE, - &(struct nv_device_v0) { - .device = ~0, - .disable = ~enables, - .debug0 = ~0, - }, sizeof(struct nv_device_v0), - &drm->device); - if (ret) - goto fail_device; - - nouveau_agp_reset(drm); - nvif_device_fini(&drm->device); - } - - ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE, - NV_DEVICE, + ret = nvif_device_init(&drm->client.base.object, 0, NV_DEVICE, &(struct nv_device_v0) { .device = ~0, - .disable = 0, - .debug0 = 0, }, sizeof(struct nv_device_v0), &drm->device); if (ret) @@ -430,14 +417,13 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) * better fix is found - assuming there is one... */ if (drm->device.info.chipset == 0xc1) - nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000); + nvif_mask(&drm->device.object, 0x00088080, 0x00000800, 0x00000000); nouveau_vga_init(drm); - nouveau_agp_init(drm); if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { ret = nvkm_vm_new(nvxx_device(&drm->device), 0, (1ULL << 40), - 0x1000, &drm->client.vm); + 0x1000, NULL, &drm->client.vm); if (ret) goto fail_device; @@ -484,7 +470,6 @@ fail_dispctor: fail_bios: nouveau_ttm_fini(drm); fail_ttm: - nouveau_agp_fini(drm); nouveau_vga_fini(drm); fail_device: nvif_device_fini(&drm->device); @@ -510,7 +495,6 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_bios_takedown(dev); nouveau_ttm_fini(drm); - nouveau_agp_fini(drm); nouveau_vga_fini(drm); nvif_device_fini(&drm->device); @@ -525,15 +509,14 @@ nouveau_drm_device_remove(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_client *client; - struct nvkm_object *device; + struct nvkm_device *device; dev->irq_enabled = false; client = nvxx_client(&drm->client.base); - device = client->device; + device = nvkm_device_find(client->device); drm_put_dev(dev); - nvkm_object_ref(NULL, &device); - nvkm_object_debug(); + nvkm_device_del(&device); } static void @@ -595,7 +578,6 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) if (ret) goto fail_client; - nouveau_agp_fini(drm); return 0; fail_client: @@ -620,13 +602,8 @@ nouveau_do_resume(struct drm_device *dev, bool runtime) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; - NV_INFO(drm, "re-enabling device...\n"); - - nouveau_agp_reset(drm); - NV_INFO(drm, "resuming kernel object tree...\n"); nvif_client_resume(&drm->client.base); - nouveau_agp_init(drm); NV_INFO(drm, "resuming client object trees...\n"); if (drm->fence && nouveau_fence(drm)->resume) @@ -666,6 +643,7 @@ nouveau_pmops_suspend(struct device *dev) pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); + udelay(200); return 0; } @@ -725,7 +703,6 @@ nouveau_pmops_runtime_suspend(struct device *dev) return -EBUSY; } - nv_debug_level(SILENT); drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); nouveau_switcheroo_optimus_dsm(); @@ -759,10 +736,9 @@ nouveau_pmops_runtime_resume(struct device *dev) ret = nouveau_do_resume(drm_dev, true); drm_kms_helper_poll_enable(drm_dev); /* do magic */ - nvif_mask(device, 0x88488, (1 << 25), (1 << 25)); + nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25)); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; - nv_debug_level(NORMAL); return ret; } @@ -823,8 +799,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) get_task_comm(tmpname, current); snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); - ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli), - (void **)&cli); + ret = nouveau_cli_create(dev, name, sizeof(*cli), (void **)&cli); if (ret) goto out_suspend; @@ -833,7 +808,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { ret = nvkm_vm_new(nvxx_device(&drm->device), 0, (1ULL << 40), - 0x1000, &cli->vm); + 0x1000, NULL, &cli->vm); if (ret) { nouveau_cli_destroy(cli); goto out_suspend; @@ -885,18 +860,18 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) static const struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW), }; long @@ -942,8 +917,8 @@ nouveau_driver_fops = { static struct drm_driver driver_stub = { .driver_features = - DRIVER_USE_AGP | - DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER, + DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | + DRIVER_KMS_LEGACY_CONTEXT, .load = nouveau_drm_load, .unload = nouveau_drm_unload, @@ -957,7 +932,7 @@ driver_stub = { .debugfs_cleanup = nouveau_debugfs_takedown, #endif - .get_vblank_counter = drm_vblank_count, + .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = nouveau_display_vblank_enable, .disable_vblank = nouveau_display_vblank_disable, .get_scanout_position = nouveau_display_scanoutpos, @@ -1053,18 +1028,17 @@ nouveau_drm_pci_driver = { }; struct drm_device * -nouveau_platform_device_create_(struct platform_device *pdev, int size, - void **pobject) +nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, + struct platform_device *pdev, + struct nvkm_device **pdevice) { struct drm_device *drm; int err; - err = nvkm_device_create_(pdev, NVKM_BUS_PLATFORM, - nouveau_platform_name(pdev), - dev_name(&pdev->dev), nouveau_config, - nouveau_debug, size, pobject); + err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, + true, true, ~0ULL, pdevice); if (err) - return ERR_PTR(err); + goto err_free; drm = drm_dev_alloc(&driver_platform, &pdev->dev); if (!drm) { @@ -1082,7 +1056,7 @@ nouveau_platform_device_create_(struct platform_device *pdev, int size, return drm; err_free: - nvkm_object_ref(NULL, (struct nvkm_object **)pobject); + nvkm_device_del(pdevice); return ERR_PTR(err); } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_drm.h b/kernel/drivers/gpu/drm/nouveau/nouveau_drm.h index dd726523c..a02813e99 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -9,8 +9,8 @@ #define DRIVER_DATE "20120801" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 2 +#define DRIVER_MINOR 3 +#define DRIVER_PATCHLEVEL 1 /* * 1.1.1: @@ -30,10 +30,16 @@ * - allow concurrent access to bo's mapped read/write. * 1.2.2: * - add NOUVEAU_GEM_DOMAIN_COHERENT flag + * 1.3.0: + * - NVIF ABI modified, safe because only (current) users are test + * programs that get directly linked with NVKM. + * 1.3.1: + * - implemented limited ABI16/NVIF interop */ #include #include +#include #include @@ -60,9 +66,10 @@ struct nouveau_drm_tile { }; enum nouveau_drm_object_route { - NVDRM_OBJECT_NVIF = 0, + NVDRM_OBJECT_NVIF = NVIF_IOCTL_V0_OWNER_NVIF, NVDRM_OBJECT_USIF, NVDRM_OBJECT_ABI16, + NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY, }; enum nouveau_drm_notify_route { @@ -71,11 +78,6 @@ enum nouveau_drm_notify_route { }; enum nouveau_drm_handle { - NVDRM_CLIENT = 0xffffffff, - NVDRM_DEVICE = 0xdddddddd, - NVDRM_CONTROL = 0xdddddddc, - NVDRM_DISPLAY = 0xd1500000, - NVDRM_PUSH = 0xbbbb0000, /* |= client chid */ NVDRM_CHAN = 0xcccc0000, /* |= client chid */ NVDRM_NVSW = 0x55550000, }; @@ -88,6 +90,8 @@ struct nouveau_cli { void *abi16; struct list_head objects; struct list_head notifys; + char name[32]; + struct drm_device *dev; }; static inline struct nouveau_cli * @@ -109,13 +113,10 @@ struct nouveau_drm { struct list_head clients; struct { - enum { - UNKNOWN = 0, - DISABLE = 1, - ENABLED = 2 - } stat; + struct agp_bridge_data *bridge; u32 base; u32 size; + bool cma; } agp; /* TTM interface support */ @@ -148,6 +149,7 @@ struct nouveau_drm { struct nouveau_fbdev *fbcon; struct nvif_object nvsw; struct nvif_object ntfy; + struct nvif_notify flip; /* nv10-nv40 tiling regions */ struct { @@ -180,22 +182,25 @@ nouveau_drm(struct drm_device *dev) int nouveau_pmops_suspend(struct device *); int nouveau_pmops_resume(struct device *); -#define nouveau_platform_device_create(p, u) \ - nouveau_platform_device_create_(p, sizeof(**u), (void **)u) +#include + struct drm_device * -nouveau_platform_device_create_(struct platform_device *pdev, - int size, void **pobject); +nouveau_platform_device_create(const struct nvkm_device_tegra_func *, + struct platform_device *, struct nvkm_device **); void nouveau_drm_device_remove(struct drm_device *dev); #define NV_PRINTK(l,c,f,a...) do { \ struct nouveau_cli *_cli = (c); \ - nv_##l(_cli->base.base.priv, f, ##a); \ + dev_##l(_cli->dev->dev, "%s: "f, _cli->name, ##a); \ } while(0) -#define NV_FATAL(drm,f,a...) NV_PRINTK(fatal, &(drm)->client, f, ##a) -#define NV_ERROR(drm,f,a...) NV_PRINTK(error, &(drm)->client, f, ##a) +#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) +#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) #define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a) #define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a) -#define NV_DEBUG(drm,f,a...) NV_PRINTK(debug, &(drm)->client, f, ##a) +#define NV_DEBUG(drm,f,a...) do { \ + if (unlikely(drm_debug & DRM_UT_DRIVER)) \ + NV_PRINTK(info, &(drm)->client, f, ##a); \ +} while(0) extern int nouveau_modeset; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_encoder.h b/kernel/drivers/gpu/drm/nouveau/nouveau_encoder.h index c57a37e8e..b37da9510 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -41,7 +41,9 @@ struct nouveau_encoder { struct dcb_output *dcb; int or; - struct nvkm_i2c_port *i2c; + + struct i2c_adapter *i2c; + struct nvkm_i2c_aux *aux; /* different to drm_encoder.crtc, this reflects what's * actually programmed on the hw, not the proposed crtc */ diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/kernel/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 6751553ab..59f27e774 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -84,7 +84,7 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) if (ret != -ENODEV) nouveau_fbcon_gpu_lockup(info); - cfb_fillrect(info, rect); + drm_fb_helper_cfb_fillrect(info, rect); } static void @@ -116,7 +116,7 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) if (ret != -ENODEV) nouveau_fbcon_gpu_lockup(info); - cfb_copyarea(info, image); + drm_fb_helper_cfb_copyarea(info, image); } static void @@ -148,7 +148,7 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) if (ret != -ENODEV) nouveau_fbcon_gpu_lockup(info); - cfb_imageblit(info, image); + drm_fb_helper_cfb_imageblit(info, image); } static int @@ -178,8 +178,30 @@ nouveau_fbcon_sync(struct fb_info *info) return 0; } +static int +nouveau_fbcon_open(struct fb_info *info, int user) +{ + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); + int ret = pm_runtime_get_sync(drm->dev->dev); + if (ret < 0 && ret != -EACCES) + return ret; + return 0; +} + +static int +nouveau_fbcon_release(struct fb_info *info, int user) +{ + struct nouveau_fbdev *fbcon = info->par; + struct nouveau_drm *drm = nouveau_drm(fbcon->dev); + pm_runtime_put(drm->dev->dev); + return 0; +} + static struct fb_ops nouveau_fbcon_ops = { .owner = THIS_MODULE, + .fb_open = nouveau_fbcon_open, + .fb_release = nouveau_fbcon_release, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, .fb_fillrect = nouveau_fbcon_fillrect, @@ -195,11 +217,13 @@ static struct fb_ops nouveau_fbcon_ops = { static struct fb_ops nouveau_fbcon_sw_ops = { .owner = THIS_MODULE, + .fb_open = nouveau_fbcon_open, + .fb_release = nouveau_fbcon_release, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_fillrect = drm_fb_helper_cfb_fillrect, + .fb_copyarea = drm_fb_helper_cfb_copyarea, + .fb_imageblit = drm_fb_helper_cfb_imageblit, .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, .fb_setcmap = drm_fb_helper_setcmap, @@ -319,7 +343,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, struct nouveau_channel *chan; struct nouveau_bo *nvbo; struct drm_mode_fb_cmd2 mode_cmd; - struct pci_dev *pdev = dev->pdev; int size, ret; mode_cmd.width = sizes->surface_width; @@ -365,20 +388,13 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, mutex_lock(&dev->struct_mutex); - info = framebuffer_alloc(0, &pdev->dev); - if (!info) { - ret = -ENOMEM; + info = drm_fb_helper_alloc_fbi(helper); + if (IS_ERR(info)) { + ret = PTR_ERR(info); goto out_unlock; } info->skip_vt_switch = 1; - ret = fb_alloc_cmap(&info->cmap, 256, 0); - if (ret) { - ret = -ENOMEM; - framebuffer_release(info); - goto out_unlock; - } - info->par = fbcon; nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo); @@ -388,7 +404,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, /* setup helper */ fbcon->helper.fb = fb; - fbcon->helper.fbdev = info; strcpy(info->fix.id, "nouveaufb"); if (!chan) @@ -450,15 +465,9 @@ static int nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) { struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb; - struct fb_info *info; - if (fbcon->helper.fbdev) { - info = fbcon->helper.fbdev; - unregister_framebuffer(info); - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } + drm_fb_helper_unregister_fbi(&fbcon->helper); + drm_fb_helper_release_fbi(&fbcon->helper); if (nouveau_fb->nvbo) { nouveau_bo_unmap(nouveau_fb->nvbo); @@ -496,7 +505,7 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state) console_lock(); if (state == FBINFO_STATE_RUNNING) nouveau_fbcon_accel_restore(dev); - fb_set_suspend(drm->fbcon->helper.fbdev, state); + drm_fb_helper_set_suspend(&drm->fbcon->helper, state); if (state != FBINFO_STATE_RUNNING) nouveau_fbcon_accel_save_disable(dev); console_unlock(); diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_fence.c b/kernel/drivers/gpu/drm/nouveau/nouveau_fence.c index c6d56bef5..574c36b49 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -169,7 +169,7 @@ void nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { struct nouveau_fence_priv *priv = (void*)chan->drm->fence; - struct nouveau_cli *cli = (void *)nvif_client(chan->object); + struct nouveau_cli *cli = (void *)chan->user.client; int ret; INIT_LIST_HEAD(&fctx->flip); @@ -188,13 +188,12 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha if (!priv->uevent) return; - ret = nvif_notify_init(chan->object, NULL, - nouveau_fence_wait_uevent_handler, false, - G82_CHANNEL_DMA_V0_NTFY_UEVENT, - &(struct nvif_notify_uevent_req) { }, - sizeof(struct nvif_notify_uevent_req), - sizeof(struct nvif_notify_uevent_rep), - &fctx->notify); + ret = nvif_notify_init(&chan->user, nouveau_fence_wait_uevent_handler, + false, G82_CHANNEL_DMA_V0_NTFY_UEVENT, + &(struct nvif_notify_uevent_req) { }, + sizeof(struct nvif_notify_uevent_req), + sizeof(struct nvif_notify_uevent_rep), + &fctx->notify); WARN_ON(ret); } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_fence.h b/kernel/drivers/gpu/drm/nouveau/nouveau_fence.h index d9241d824..2e3a62d38 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -85,7 +85,7 @@ int nv50_fence_create(struct nouveau_drm *); int nv84_fence_create(struct nouveau_drm *); int nvc0_fence_create(struct nouveau_drm *); -int nouveau_flip_complete(void *chan); +int nouveau_flip_complete(struct nvif_notify *); struct nv84_fence_chan { struct nouveau_fence_chan base; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_gem.c b/kernel/drivers/gpu/drm/nouveau/nouveau_gem.c index 0e690bf19..a0865c49e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -84,8 +84,10 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) } ret = pm_runtime_get_sync(dev); - if (ret < 0 && ret != -EACCES) + if (ret < 0 && ret != -EACCES) { + kfree(vma); goto out; + } ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); if (ret) @@ -227,11 +229,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nvkm_vma *vma; - if (nvbo->bo.mem.mem_type == TTM_PL_TT) + if (is_power_of_2(nvbo->valid_domains)) + rep->domain = nvbo->valid_domains; + else if (nvbo->bo.mem.mem_type == TTM_PL_TT) rep->domain = NOUVEAU_GEM_DOMAIN_GART; else rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; - rep->offset = nvbo->bo.offset; if (cli->vm) { vma = nouveau_bo_vma_find(nvbo, cli->vm); @@ -254,13 +257,13 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli = nouveau_cli(file_priv); - struct nvkm_fb *pfb = nvxx_fb(&drm->device); + struct nvkm_fb *fb = nvxx_fb(&drm->device); struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; int ret = 0; - if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { - NV_PRINTK(error, cli, "bad page flags: 0x%08x\n", req->info.tile_flags); + if (!nvkm_fb_memtype_valid(fb, req->info.tile_flags)) { + NV_PRINTK(err, cli, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } @@ -376,7 +379,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, ww_acquire_init(&op->ticket, &reservation_ww_class); retry: if (++trycnt > 100000) { - NV_PRINTK(error, cli, "%s failed and gave up.\n", __func__); + NV_PRINTK(err, cli, "%s failed and gave up.\n", __func__); return -EINVAL; } @@ -387,7 +390,7 @@ retry: gem = drm_gem_object_lookup(dev, file_priv, b->handle); if (!gem) { - NV_PRINTK(error, cli, "Unknown handle 0x%08x\n", b->handle); + NV_PRINTK(err, cli, "Unknown handle 0x%08x\n", b->handle); ret = -ENOENT; break; } @@ -399,7 +402,7 @@ retry: } if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { - NV_PRINTK(error, cli, "multiple instances of buffer %d on " + NV_PRINTK(err, cli, "multiple instances of buffer %d on " "validation list\n", b->handle); drm_gem_object_unreference_unlocked(gem); ret = -EINVAL; @@ -420,7 +423,7 @@ retry: } if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_PRINTK(error, cli, "fail reserve\n"); + NV_PRINTK(err, cli, "fail reserve\n"); break; } } @@ -438,7 +441,7 @@ retry: if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) list_add_tail(&nvbo->entry, &gart_list); else { - NV_PRINTK(error, cli, "invalid valid domains: 0x%08x\n", + NV_PRINTK(err, cli, "invalid valid domains: 0x%08x\n", b->valid_domains); list_add_tail(&nvbo->entry, &both_list); ret = -EINVAL; @@ -476,21 +479,21 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, b->write_domains, b->valid_domains); if (unlikely(ret)) { - NV_PRINTK(error, cli, "fail set_domain\n"); + NV_PRINTK(err, cli, "fail set_domain\n"); return ret; } ret = nouveau_bo_validate(nvbo, true, false); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_PRINTK(error, cli, "fail ttm_validate\n"); + NV_PRINTK(err, cli, "fail ttm_validate\n"); return ret; } ret = nouveau_fence_sync(nvbo, chan, !!b->write_domains, true); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_PRINTK(error, cli, "fail post-validate sync\n"); + NV_PRINTK(err, cli, "fail post-validate sync\n"); return ret; } @@ -537,14 +540,14 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_PRINTK(error, cli, "validate_init\n"); + NV_PRINTK(err, cli, "validate_init\n"); return ret; } ret = validate_list(chan, cli, &op->list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_PRINTK(error, cli, "validating bo list\n"); + NV_PRINTK(err, cli, "validating bo list\n"); validate_fini(op, NULL, NULL); return ret; } @@ -555,10 +558,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, static inline void u_free(void *addr) { - if (!is_vmalloc_addr(addr)) - kfree(addr); - else - vfree(addr); + kvfree(addr); } static inline void * @@ -603,7 +603,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, uint32_t data; if (unlikely(r->bo_index > req->nr_buffers)) { - NV_PRINTK(error, cli, "reloc bo index invalid\n"); + NV_PRINTK(err, cli, "reloc bo index invalid\n"); ret = -EINVAL; break; } @@ -613,7 +613,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, continue; if (unlikely(r->reloc_bo_index > req->nr_buffers)) { - NV_PRINTK(error, cli, "reloc container bo index invalid\n"); + NV_PRINTK(err, cli, "reloc container bo index invalid\n"); ret = -EINVAL; break; } @@ -621,7 +621,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, if (unlikely(r->reloc_bo_offset + 4 > nvbo->bo.mem.num_pages << PAGE_SHIFT)) { - NV_PRINTK(error, cli, "reloc outside of bo\n"); + NV_PRINTK(err, cli, "reloc outside of bo\n"); ret = -EINVAL; break; } @@ -630,7 +630,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, &nvbo->kmap); if (ret) { - NV_PRINTK(error, cli, "failed kmap for reloc\n"); + NV_PRINTK(err, cli, "failed kmap for reloc\n"); break; } nvbo->validate_mapped = true; @@ -653,7 +653,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, ret = ttm_bo_wait(&nvbo->bo, true, false, false); if (ret) { - NV_PRINTK(error, cli, "reloc wait_idle failed: %d\n", ret); + NV_PRINTK(err, cli, "reloc wait_idle failed: %d\n", ret); break; } @@ -668,7 +668,7 @@ int nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_abi16_chan *temp; struct nouveau_drm *drm = nouveau_drm(dev); @@ -684,7 +684,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, return -ENOMEM; list_for_each_entry(temp, &abi16->channels, head) { - if (temp->chan->object->handle == (NVDRM_CHAN | req->channel)) { + if (temp->chan->chid == req->channel) { chan = temp->chan; break; } @@ -699,19 +699,19 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, goto out_next; if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { - NV_PRINTK(error, cli, "pushbuf push count exceeds limit: %d max %d\n", + NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n", req->nr_push, NOUVEAU_GEM_MAX_PUSH); return nouveau_abi16_put(abi16, -EINVAL); } if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { - NV_PRINTK(error, cli, "pushbuf bo count exceeds limit: %d max %d\n", + NV_PRINTK(err, cli, "pushbuf bo count exceeds limit: %d max %d\n", req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); return nouveau_abi16_put(abi16, -EINVAL); } if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { - NV_PRINTK(error, cli, "pushbuf reloc count exceeds limit: %d max %d\n", + NV_PRINTK(err, cli, "pushbuf reloc count exceeds limit: %d max %d\n", req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); return nouveau_abi16_put(abi16, -EINVAL); } @@ -729,7 +729,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, /* Ensure all push buffers are on validate list */ for (i = 0; i < req->nr_push; i++) { if (push[i].bo_index >= req->nr_buffers) { - NV_PRINTK(error, cli, "push %d buffer not in list\n", i); + NV_PRINTK(err, cli, "push %d buffer not in list\n", i); ret = -EINVAL; goto out_prevalid; } @@ -740,7 +740,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, req->nr_buffers, &op, &do_reloc); if (ret) { if (ret != -ERESTARTSYS) - NV_PRINTK(error, cli, "validate: %d\n", ret); + NV_PRINTK(err, cli, "validate: %d\n", ret); goto out_prevalid; } @@ -748,7 +748,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (do_reloc) { ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo); if (ret) { - NV_PRINTK(error, cli, "reloc apply: %d\n", ret); + NV_PRINTK(err, cli, "reloc apply: %d\n", ret); goto out; } } @@ -756,7 +756,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (chan->dma.ib_max) { ret = nouveau_dma_wait(chan, req->nr_push + 1, 16); if (ret) { - NV_PRINTK(error, cli, "nv50cal_space: %d\n", ret); + NV_PRINTK(err, cli, "nv50cal_space: %d\n", ret); goto out; } @@ -771,7 +771,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (drm->device.info.chipset >= 0x25) { ret = RING_SPACE(chan, req->nr_push * 2); if (ret) { - NV_PRINTK(error, cli, "cal_space: %d\n", ret); + NV_PRINTK(err, cli, "cal_space: %d\n", ret); goto out; } @@ -785,7 +785,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } else { ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); if (ret) { - NV_PRINTK(error, cli, "jmp_space: %d\n", ret); + NV_PRINTK(err, cli, "jmp_space: %d\n", ret); goto out; } @@ -823,7 +823,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ret = nouveau_fence_new(chan, false, &fence); if (ret) { - NV_PRINTK(error, cli, "error fencing pushbuf: %d\n", ret); + NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); goto out; } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/kernel/drivers/gpu/drm/nouveau/nouveau_hwmon.c index 0dbe0060f..491c7149d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_hwmon.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_hwmon.c @@ -41,7 +41,7 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_therm *therm = nvxx_therm(&drm->device); - int temp = therm->temp_get(therm); + int temp = nvkm_therm_temp_get(therm); if (temp < 0) return temp; @@ -348,7 +348,7 @@ nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr, struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_therm *therm = nvxx_therm(&drm->device); - return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm)); + return snprintf(buf, PAGE_SIZE, "%d\n", nvkm_therm_fan_sense(therm)); } static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input, NULL, 0); @@ -571,7 +571,7 @@ nouveau_hwmon_init(struct drm_device *dev) return -ENOMEM; hwmon->dev = dev; - if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set) + if (!therm || !therm->attr_get || !therm->attr_set) return -ENODEV; hwmon_dev = hwmon_device_register(&dev->pdev->dev); @@ -588,7 +588,7 @@ nouveau_hwmon_init(struct drm_device *dev) goto error; /* if the card has a working thermal sensor */ - if (therm->temp_get(therm) >= 0) { + if (nvkm_therm_temp_get(therm) >= 0) { ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup); if (ret) goto error; @@ -606,7 +606,7 @@ nouveau_hwmon_init(struct drm_device *dev) } /* if the card can read the fan rpm */ - if (therm->fan_sense(therm) >= 0) { + if (nvkm_therm_fan_sense(therm) >= 0) { ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_fan_rpm_attrgroup); if (ret) diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_nvif.c b/kernel/drivers/gpu/drm/nouveau/nouveau_nvif.c index ca0ad9d15..55eb94284 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_nvif.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_nvif.c @@ -72,10 +72,8 @@ nvkm_client_suspend(void *priv) static void nvkm_client_driver_fini(void *priv) { - struct nvkm_object *client = priv; - nvkm_client_fini(nv_client(client), false); - atomic_set(&client->refcount, 1); - nvkm_object_ref(NULL, &client); + struct nvkm_client *client = priv; + nvkm_client_del(&client); } static int @@ -113,7 +111,7 @@ nvkm_client_driver_init(const char *name, u64 device, const char *cfg, struct nvkm_client *client; int ret; - ret = nvkm_client_create(name, device, cfg, dbg, &client); + ret = nvkm_client_new(name, device, cfg, dbg, &client); *ppriv = client; if (ret) return ret; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_platform.c b/kernel/drivers/gpu/drm/nouveau/nouveau_platform.c index 775277f1e..35ecc0d04 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -19,223 +19,51 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nouveau_drm.h" #include "nouveau_platform.h" -static int nouveau_platform_power_up(struct nouveau_platform_gpu *gpu) -{ - int err; - - err = regulator_enable(gpu->vdd); - if (err) - goto err_power; - - err = clk_prepare_enable(gpu->clk); - if (err) - goto err_clk; - err = clk_prepare_enable(gpu->clk_pwr); - if (err) - goto err_clk_pwr; - clk_set_rate(gpu->clk_pwr, 204000000); - udelay(10); - - reset_control_assert(gpu->rst); - udelay(10); - - err = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D); - if (err) - goto err_clamp; - udelay(10); - - reset_control_deassert(gpu->rst); - udelay(10); - - return 0; - -err_clamp: - clk_disable_unprepare(gpu->clk_pwr); -err_clk_pwr: - clk_disable_unprepare(gpu->clk); -err_clk: - regulator_disable(gpu->vdd); -err_power: - return err; -} - -static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu) -{ - int err; - - reset_control_assert(gpu->rst); - udelay(10); - - clk_disable_unprepare(gpu->clk_pwr); - clk_disable_unprepare(gpu->clk); - udelay(10); - - err = regulator_disable(gpu->vdd); - if (err) - return err; - - return 0; -} - -static void nouveau_platform_probe_iommu(struct device *dev, - struct nouveau_platform_gpu *gpu) -{ - int err; - unsigned long pgsize_bitmap; - - mutex_init(&gpu->iommu.mutex); - - if (iommu_present(&platform_bus_type)) { - gpu->iommu.domain = iommu_domain_alloc(&platform_bus_type); - if (IS_ERR(gpu->iommu.domain)) - goto error; - - /* - * A IOMMU is only usable if it supports page sizes smaller - * or equal to the system's PAGE_SIZE, with a preference if - * both are equal. - */ - pgsize_bitmap = gpu->iommu.domain->ops->pgsize_bitmap; - if (pgsize_bitmap & PAGE_SIZE) { - gpu->iommu.pgshift = PAGE_SHIFT; - } else { - gpu->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK); - if (gpu->iommu.pgshift == 0) { - dev_warn(dev, "unsupported IOMMU page size\n"); - goto free_domain; - } - gpu->iommu.pgshift -= 1; - } - - err = iommu_attach_device(gpu->iommu.domain, dev); - if (err) - goto free_domain; - - err = nvkm_mm_init(&gpu->iommu._mm, 0, - (1ULL << 40) >> gpu->iommu.pgshift, 1); - if (err) - goto detach_device; - - gpu->iommu.mm = &gpu->iommu._mm; - } - - return; - -detach_device: - iommu_detach_device(gpu->iommu.domain, dev); - -free_domain: - iommu_domain_free(gpu->iommu.domain); - -error: - gpu->iommu.domain = NULL; - gpu->iommu.pgshift = 0; - dev_err(dev, "cannot initialize IOMMU MM\n"); -} - -static void nouveau_platform_remove_iommu(struct device *dev, - struct nouveau_platform_gpu *gpu) -{ - if (gpu->iommu.domain) { - nvkm_mm_fini(&gpu->iommu._mm); - iommu_detach_device(gpu->iommu.domain, dev); - iommu_domain_free(gpu->iommu.domain); - } -} - static int nouveau_platform_probe(struct platform_device *pdev) { - struct nouveau_platform_gpu *gpu; - struct nouveau_platform_device *device; + const struct nvkm_device_tegra_func *func; + struct nvkm_device *device = NULL; struct drm_device *drm; - int err; - - gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL); - if (!gpu) - return -ENOMEM; - - gpu->vdd = devm_regulator_get(&pdev->dev, "vdd"); - if (IS_ERR(gpu->vdd)) - return PTR_ERR(gpu->vdd); - - gpu->rst = devm_reset_control_get(&pdev->dev, "gpu"); - if (IS_ERR(gpu->rst)) - return PTR_ERR(gpu->rst); - - gpu->clk = devm_clk_get(&pdev->dev, "gpu"); - if (IS_ERR(gpu->clk)) - return PTR_ERR(gpu->clk); - - gpu->clk_pwr = devm_clk_get(&pdev->dev, "pwr"); - if (IS_ERR(gpu->clk_pwr)) - return PTR_ERR(gpu->clk_pwr); + int ret; - nouveau_platform_probe_iommu(&pdev->dev, gpu); + func = of_device_get_match_data(&pdev->dev); - err = nouveau_platform_power_up(gpu); - if (err) - return err; + drm = nouveau_platform_device_create(func, pdev, &device); + if (IS_ERR(drm)) + return PTR_ERR(drm); - drm = nouveau_platform_device_create(pdev, &device); - if (IS_ERR(drm)) { - err = PTR_ERR(drm); - goto power_down; + ret = drm_dev_register(drm, 0); + if (ret < 0) { + drm_dev_unref(drm); + return ret; } - device->gpu = gpu; - device->gpu_speedo = tegra_sku_info.gpu_speedo_value; - - err = drm_dev_register(drm, 0); - if (err < 0) - goto err_unref; - return 0; - -err_unref: - drm_dev_unref(drm); - -power_down: - nouveau_platform_power_down(gpu); - nouveau_platform_remove_iommu(&pdev->dev, gpu); - - return err; } static int nouveau_platform_remove(struct platform_device *pdev) { - struct drm_device *drm_dev = platform_get_drvdata(pdev); - struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_device *device = nvxx_device(&drm->device); - struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu; - int err; - - nouveau_drm_device_remove(drm_dev); - - err = nouveau_platform_power_down(gpu); - - nouveau_platform_remove_iommu(&pdev->dev, gpu); - - return err; + struct drm_device *dev = platform_get_drvdata(pdev); + nouveau_drm_device_remove(dev); + return 0; } #if IS_ENABLED(CONFIG_OF) +static const struct nvkm_device_tegra_func gk20a_platform_data = { + .iommu_bit = 34, +}; + static const struct of_device_id nouveau_platform_match[] = { - { .compatible = "nvidia,gk20a" }, + { + .compatible = "nvidia,gk20a", + .data = &gk20a_platform_data, + }, + { + .compatible = "nvidia,gm20b", + .data = &gk20a_platform_data, + }, { } }; diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_platform.h b/kernel/drivers/gpu/drm/nouveau/nouveau_platform.h index 392874cf4..f41056d0f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_platform.h +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_platform.h @@ -19,54 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - #ifndef __NOUVEAU_PLATFORM_H__ #define __NOUVEAU_PLATFORM_H__ - -#include "core/device.h" -#include "core/mm.h" - -struct reset_control; -struct clk; -struct regulator; -struct iommu_domain; -struct platform_driver; - -struct nouveau_platform_gpu { - struct reset_control *rst; - struct clk *clk; - struct clk *clk_pwr; - - struct regulator *vdd; - - struct { - /* - * Protects accesses to mm from subsystems - */ - struct mutex mutex; - - struct nvkm_mm _mm; - /* - * Just points to _mm. We need this to avoid embedding - * struct nvkm_mm in os.h - */ - struct nvkm_mm *mm; - struct iommu_domain *domain; - unsigned long pgshift; - } iommu; -}; - -struct nouveau_platform_device { - struct nvkm_device device; - - struct nouveau_platform_gpu *gpu; - - int gpu_speedo; -}; - -#define nv_device_to_platform(d) \ - container_of(d, struct nouveau_platform_device, device) +#include "nouveau_drm.h" extern struct platform_driver nouveau_platform_driver; - #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/kernel/drivers/gpu/drm/nouveau/nouveau_sysfs.c index 1ec8f38ae..5dac3546c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_sysfs.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_sysfs.c @@ -165,7 +165,7 @@ nouveau_sysfs_fini(struct drm_device *dev) struct nvif_device *device = &drm->device; if (sysfs && sysfs->ctrl.priv) { - device_remove_file(nv_device_base(nvxx_device(device)), &dev_attr_pstate); + device_remove_file(nvxx_device(device)->dev, &dev_attr_pstate); nvif_object_fini(&sysfs->ctrl); } @@ -188,11 +188,10 @@ nouveau_sysfs_init(struct drm_device *dev) if (!sysfs) return -ENOMEM; - ret = nvif_object_init(nvif_object(device), NULL, NVDRM_CONTROL, - NVIF_IOCTL_NEW_V0_CONTROL, NULL, 0, - &sysfs->ctrl); + ret = nvif_object_init(&device->object, 0, NVIF_IOCTL_NEW_V0_CONTROL, + NULL, 0, &sysfs->ctrl); if (ret == 0) - device_create_file(nv_device_base(nvxx_device(device)), &dev_attr_pstate); + device_create_file(nvxx_device(device)->dev, &dev_attr_pstate); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_ttm.c b/kernel/drivers/gpu/drm/nouveau/nouveau_ttm.c index 18f449715..d2e7d209f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -29,12 +29,15 @@ #include "nouveau_gem.h" #include "drm_legacy.h" + +#include + static int nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) { struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_fb *pfb = nvxx_fb(&drm->device); - man->priv = pfb; + struct nvkm_fb *fb = nvxx_fb(&drm->device); + man->priv = fb; return 0; } @@ -64,9 +67,9 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_fb *pfb = nvxx_fb(&drm->device); + struct nvkm_ram *ram = nvxx_fb(&drm->device)->ram; nvkm_mem_node_cleanup(mem->mm_node); - pfb->ram->put(pfb, (struct nvkm_mem **)&mem->mm_node); + ram->func->put(ram, (struct nvkm_mem **)&mem->mm_node); } static int @@ -76,7 +79,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_fb *pfb = nvxx_fb(&drm->device); + struct nvkm_ram *ram = nvxx_fb(&drm->device)->ram; struct nouveau_bo *nvbo = nouveau_bo(bo); struct nvkm_mem *node; u32 size_nc = 0; @@ -88,9 +91,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->page_shift; - ret = pfb->ram->get(pfb, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, - (nvbo->tile_flags >> 8) & 0x3ff, &node); + ret = ram->func->get(ram, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, + (nvbo->tile_flags >> 8) & 0x3ff, &node); if (ret) { mem->mm_node = NULL; return (ret == -ENOSPC) ? 0 : ret; @@ -103,38 +106,11 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, return 0; } -static void -nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) -{ - struct nvkm_fb *pfb = man->priv; - struct nvkm_mm *mm = &pfb->vram; - struct nvkm_mm_node *r; - u32 total = 0, free = 0; - - mutex_lock(&nv_subdev(pfb)->mutex); - list_for_each_entry(r, &mm->nodes, nl_entry) { - printk(KERN_DEBUG "%s %d: 0x%010llx 0x%010llx\n", - prefix, r->type, ((u64)r->offset << 12), - (((u64)r->offset + r->length) << 12)); - - total += r->length; - if (!r->type) - free += r->length; - } - mutex_unlock(&nv_subdev(pfb)->mutex); - - printk(KERN_DEBUG "%s total: 0x%010llx free: 0x%010llx\n", - prefix, (u64)total << 12, (u64)free << 12); - printk(KERN_DEBUG "%s block: 0x%08x\n", - prefix, mm->block_size << 12); -} - const struct ttm_mem_type_manager_func nouveau_vram_manager = { nouveau_vram_manager_init, nouveau_vram_manager_fini, nouveau_vram_manager_new, nouveau_vram_manager_del, - nouveau_vram_manager_debug }; static int @@ -175,15 +151,24 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, node->page_shift = 12; switch (drm->device.info.family) { + case NV_DEVICE_INFO_V0_TNT: + case NV_DEVICE_INFO_V0_CELSIUS: + case NV_DEVICE_INFO_V0_KELVIN: + case NV_DEVICE_INFO_V0_RANKINE: + case NV_DEVICE_INFO_V0_CURIE: + break; case NV_DEVICE_INFO_V0_TESLA: if (drm->device.info.chipset != 0x50) node->memtype = (nvbo->tile_flags & 0x7f00) >> 8; break; case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: + case NV_DEVICE_INFO_V0_MAXWELL: node->memtype = (nvbo->tile_flags & 0xff00) >> 8; break; default: + NV_WARN(drm, "%s: unhandled family type %x\n", __func__, + drm->device.info.family); break; } @@ -212,7 +197,7 @@ nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) { struct nouveau_drm *drm = nouveau_bdev(man->bdev); struct nvkm_mmu *mmu = nvxx_mmu(&drm->device); - struct nv04_mmu_priv *priv = (void *)mmu; + struct nv04_mmu *priv = (void *)mmu; struct nvkm_vm *vm = NULL; nvkm_vm_ref(priv->vm, &vm, NULL); man->priv = vm; @@ -353,26 +338,46 @@ nouveau_ttm_global_release(struct nouveau_drm *drm) int nouveau_ttm_init(struct nouveau_drm *drm) { + struct nvkm_device *device = nvxx_device(&drm->device); + struct nvkm_pci *pci = device->pci; struct drm_device *dev = drm->dev; - u32 bits; + u8 bits; int ret; + if (pci && pci->agp.bridge) { + drm->agp.bridge = pci->agp.bridge; + drm->agp.base = pci->agp.base; + drm->agp.size = pci->agp.size; + drm->agp.cma = pci->agp.cma; + } + bits = nvxx_mmu(&drm->device)->dma_bits; - if (nv_device_is_pci(nvxx_device(&drm->device))) { - if (drm->agp.stat == ENABLED || - !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) + if (nvxx_device(&drm->device)->func->pci) { + if (drm->agp.bridge) bits = 32; + } else if (device->func->tegra) { + struct nvkm_device_tegra *tegra = device->func->tegra(device); - ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); - if (ret) - return ret; + /* + * If the platform can use a IOMMU, then the addressable DMA + * space is constrained by the IOMMU bit + */ + if (tegra->func->iommu_bit) + bits = min(bits, tegra->func->iommu_bit); + + } - ret = pci_set_consistent_dma_mask(dev->pdev, - DMA_BIT_MASK(bits)); - if (ret) - pci_set_consistent_dma_mask(dev->pdev, - DMA_BIT_MASK(32)); + ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); + if (ret && bits != 32) { + bits = 32; + ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); } + if (ret) + return ret; + + ret = dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(bits)); + if (ret) + dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(32)); ret = nouveau_ttm_global_init(drm); if (ret) @@ -399,11 +404,11 @@ nouveau_ttm_init(struct nouveau_drm *drm) return ret; } - drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(nvxx_device(&drm->device), 1), - nv_device_resource_len(nvxx_device(&drm->device), 1)); + drm->ttm.mtrr = arch_phys_wc_add(device->func->resource_addr(device, 1), + device->func->resource_size(device, 1)); /* GART init */ - if (drm->agp.stat != ENABLED) { + if (!drm->agp.bridge) { drm->gem.gart_available = nvxx_mmu(&drm->device)->limit; } else { drm->gem.gart_available = drm->agp.size; @@ -424,10 +429,8 @@ nouveau_ttm_init(struct nouveau_drm *drm) void nouveau_ttm_fini(struct nouveau_drm *drm) { - mutex_lock(&drm->dev->struct_mutex); ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM); ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT); - mutex_unlock(&drm->dev->struct_mutex); ttm_bo_device_release(&drm->ttm.bdev); diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_usif.c b/kernel/drivers/gpu/drm/nouveau/nouveau_usif.c index cb1182d7e..6ae1b3494 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_usif.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_usif.c @@ -24,6 +24,7 @@ #include "nouveau_drm.h" #include "nouveau_usif.h" +#include "nouveau_abi16.h" #include #include @@ -312,15 +313,28 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) if (nvif_unpack(argv->v0, 0, 0, true)) { /* block access to objects not created via this interface */ owner = argv->v0.owner; - argv->v0.owner = NVDRM_OBJECT_USIF; + if (argv->v0.object == 0ULL) + argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */ + else + argv->v0.owner = NVDRM_OBJECT_USIF; } else goto done; + /* USIF slightly abuses some return-only ioctl members in order + * to provide interoperability with the older ABI16 objects + */ mutex_lock(&cli->mutex); + if (argv->v0.route) { + if (ret = -EINVAL, argv->v0.route == 0xff) + ret = nouveau_abi16_usif(filp, argv, argc); + if (ret) { + mutex_unlock(&cli->mutex); + goto done; + } + } + switch (argv->v0.type) { case NVIF_IOCTL_V0_NEW: - /* ... except if we're creating children */ - argv->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; ret = usif_object_new(filp, data, size, argv, argc); break; case NVIF_IOCTL_V0_NTFY_NEW: diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_vga.c b/kernel/drivers/gpu/drm/nouveau/nouveau_vga.c index c7592ec8e..af89c3665 100644 --- a/kernel/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/kernel/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -12,13 +12,14 @@ static unsigned int nouveau_vga_set_decode(void *priv, bool state) { - struct nvif_device *device = &nouveau_drm(priv)->device; + struct nouveau_drm *drm = nouveau_drm(priv); + struct nvif_object *device = &drm->device.object; - if (device->info.family == NV_DEVICE_INFO_V0_CURIE && - device->info.chipset >= 0x4c) + if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE && + drm->device.info.chipset >= 0x4c) nvif_wr32(device, 0x088060, state); else - if (device->info.chipset >= 0x40) + if (drm->device.info.chipset >= 0x40) nvif_wr32(device, 0x088054, state); else nvif_wr32(device, 0x001854, state); diff --git a/kernel/drivers/gpu/drm/nouveau/nv04_fbcon.c b/kernel/drivers/gpu/drm/nouveau/nv04_fbcon.c index 495c57644..789dc2993 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/kernel/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -171,33 +171,33 @@ nv04_fbcon_accel_init(struct fb_info *info) return -EINVAL; } - ret = nvif_object_init(chan->object, NULL, 0x0062, + ret = nvif_object_init(&chan->user, 0x0062, device->info.family >= NV_DEVICE_INFO_V0_CELSIUS ? 0x0062 : 0x0042, NULL, 0, &nfbdev->surf2d); if (ret) return ret; - ret = nvif_object_init(chan->object, NULL, 0x0019, 0x0019, NULL, 0, + ret = nvif_object_init(&chan->user, 0x0019, 0x0019, NULL, 0, &nfbdev->clip); if (ret) return ret; - ret = nvif_object_init(chan->object, NULL, 0x0043, 0x0043, NULL, 0, + ret = nvif_object_init(&chan->user, 0x0043, 0x0043, NULL, 0, &nfbdev->rop); if (ret) return ret; - ret = nvif_object_init(chan->object, NULL, 0x0044, 0x0044, NULL, 0, + ret = nvif_object_init(&chan->user, 0x0044, 0x0044, NULL, 0, &nfbdev->patt); if (ret) return ret; - ret = nvif_object_init(chan->object, NULL, 0x004a, 0x004a, NULL, 0, + ret = nvif_object_init(&chan->user, 0x004a, 0x004a, NULL, 0, &nfbdev->gdi); if (ret) return ret; - ret = nvif_object_init(chan->object, NULL, 0x005f, + ret = nvif_object_init(&chan->user, 0x005f, device->info.chipset >= 0x11 ? 0x009f : 0x005f, NULL, 0, &nfbdev->blit); if (ret) diff --git a/kernel/drivers/gpu/drm/nouveau/nv04_fence.c b/kernel/drivers/gpu/drm/nouveau/nv04_fence.c index c2e05e64c..f3d705d67 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/kernel/drivers/gpu/drm/nouveau/nv04_fence.c @@ -57,8 +57,10 @@ nv04_fence_sync(struct nouveau_fence *fence, static u32 nv04_fence_read(struct nouveau_channel *chan) { - struct nvkm_fifo_chan *fifo = nvxx_fifo_chan(chan);; - return atomic_read(&fifo->refcnt); + struct nv04_nvsw_get_ref_v0 args = {}; + WARN_ON(nvif_object_mthd(&chan->nvsw, NV04_NVSW_GET_REF, + &args, sizeof(args))); + return args.ref; } static void diff --git a/kernel/drivers/gpu/drm/nouveau/nv10_fence.c b/kernel/drivers/gpu/drm/nouveau/nv10_fence.c index 5e1ea1cdc..2c35213da 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/kernel/drivers/gpu/drm/nouveau/nv10_fence.c @@ -50,7 +50,7 @@ nv10_fence_sync(struct nouveau_fence *fence, u32 nv10_fence_read(struct nouveau_channel *chan) { - return nvif_rd32(chan, 0x0048); + return nvif_rd32(&chan->user, 0x0048); } void diff --git a/kernel/drivers/gpu/drm/nouveau/nv17_fence.c b/kernel/drivers/gpu/drm/nouveau/nv17_fence.c index 57860cfa1..80b6eb8b3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/kernel/drivers/gpu/drm/nouveau/nv17_fence.c @@ -33,7 +33,7 @@ int nv17_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { - struct nouveau_cli *cli = (void *)nvif_client(&prev->device->base); + struct nouveau_cli *cli = (void *)prev->user.client; struct nv10_fence_priv *priv = chan->drm->fence; struct nv10_fence_chan *fctx = chan->fence; u32 value; @@ -89,7 +89,7 @@ nv17_fence_context_new(struct nouveau_channel *chan) fctx->base.read = nv10_fence_read; fctx->base.sync = nv17_fence_sync; - ret = nvif_object_init(chan->object, NULL, NvSema, NV_DMA_FROM_MEMORY, + ret = nvif_object_init(&chan->user, NvSema, NV_DMA_FROM_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_VRAM, .access = NV_DMA_V0_ACCESS_RDWR, diff --git a/kernel/drivers/gpu/drm/nouveau/nv50_display.c b/kernel/drivers/gpu/drm/nouveau/nv50_display.c index 981342d14..c053c50b3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv50_display.c +++ b/kernel/drivers/gpu/drm/nouveau/nv50_display.c @@ -60,35 +60,38 @@ struct nv50_chan { struct nvif_object user; + struct nvif_device *device; }; static int -nv50_chan_create(struct nvif_object *disp, const u32 *oclass, u8 head, - void *data, u32 size, struct nv50_chan *chan) +nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, + const s32 *oclass, u8 head, void *data, u32 size, + struct nv50_chan *chan) { - const u32 handle = (oclass[0] << 16) | head; - u32 sclass[8]; - int ret, i; + struct nvif_sclass *sclass; + int ret, i, n; + + chan->device = device; - ret = nvif_object_sclass(disp, sclass, ARRAY_SIZE(sclass)); - WARN_ON(ret > ARRAY_SIZE(sclass)); + ret = n = nvif_object_sclass_get(disp, &sclass); if (ret < 0) return ret; while (oclass[0]) { - for (i = 0; i < ARRAY_SIZE(sclass); i++) { - if (sclass[i] == oclass[0]) { - ret = nvif_object_init(disp, NULL, handle, - oclass[0], data, size, - &chan->user); + for (i = 0; i < n; i++) { + if (sclass[i].oclass == oclass[0]) { + ret = nvif_object_init(disp, 0, oclass[0], + data, size, &chan->user); if (ret == 0) nvif_object_map(&chan->user); + nvif_object_sclass_put(&sclass); return ret; } } oclass++; } + nvif_object_sclass_put(&sclass); return -ENOSYS; } @@ -113,10 +116,12 @@ nv50_pioc_destroy(struct nv50_pioc *pioc) } static int -nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head, - void *data, u32 size, struct nv50_pioc *pioc) +nv50_pioc_create(struct nvif_device *device, struct nvif_object *disp, + const s32 *oclass, u8 head, void *data, u32 size, + struct nv50_pioc *pioc) { - return nv50_chan_create(disp, oclass, head, data, size, &pioc->base); + return nv50_chan_create(device, disp, oclass, head, data, size, + &pioc->base); } /****************************************************************************** @@ -128,12 +133,13 @@ struct nv50_curs { }; static int -nv50_curs_create(struct nvif_object *disp, int head, struct nv50_curs *curs) +nv50_curs_create(struct nvif_device *device, struct nvif_object *disp, + int head, struct nv50_curs *curs) { struct nv50_disp_cursor_v0 args = { .head = head, }; - static const u32 oclass[] = { + static const s32 oclass[] = { GK104_DISP_CURSOR, GF110_DISP_CURSOR, GT214_DISP_CURSOR, @@ -142,8 +148,8 @@ nv50_curs_create(struct nvif_object *disp, int head, struct nv50_curs *curs) 0 }; - return nv50_pioc_create(disp, oclass, head, &args, sizeof(args), - &curs->base); + return nv50_pioc_create(device, disp, oclass, head, &args, sizeof(args), + &curs->base); } /****************************************************************************** @@ -155,12 +161,13 @@ struct nv50_oimm { }; static int -nv50_oimm_create(struct nvif_object *disp, int head, struct nv50_oimm *oimm) +nv50_oimm_create(struct nvif_device *device, struct nvif_object *disp, + int head, struct nv50_oimm *oimm) { struct nv50_disp_cursor_v0 args = { .head = head, }; - static const u32 oclass[] = { + static const s32 oclass[] = { GK104_DISP_OVERLAY, GF110_DISP_OVERLAY, GT214_DISP_OVERLAY, @@ -169,8 +176,8 @@ nv50_oimm_create(struct nvif_object *disp, int head, struct nv50_oimm *oimm) 0 }; - return nv50_pioc_create(disp, oclass, head, &args, sizeof(args), - &oimm->base); + return nv50_pioc_create(device, disp, oclass, head, &args, sizeof(args), + &oimm->base); } /****************************************************************************** @@ -194,36 +201,36 @@ struct nv50_dmac { static void nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp) { + struct nvif_device *device = dmac->base.device; + nvif_object_fini(&dmac->vram); nvif_object_fini(&dmac->sync); nv50_chan_destroy(&dmac->base); if (dmac->ptr) { - struct pci_dev *pdev = nvxx_device(nvif_device(disp))->pdev; - pci_free_consistent(pdev, PAGE_SIZE, dmac->ptr, dmac->handle); + struct device *dev = nvxx_device(device)->dev; + dma_free_coherent(dev, PAGE_SIZE, dmac->ptr, dmac->handle); } } static int -nv50_dmac_create(struct nvif_object *disp, const u32 *oclass, u8 head, - void *data, u32 size, u64 syncbuf, +nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, + const s32 *oclass, u8 head, void *data, u32 size, u64 syncbuf, struct nv50_dmac *dmac) { - struct nvif_device *device = nvif_device(disp); struct nv50_disp_core_channel_dma_v0 *args = data; struct nvif_object pushbuf; int ret; mutex_init(&dmac->lock); - dmac->ptr = pci_alloc_consistent(nvxx_device(device)->pdev, - PAGE_SIZE, &dmac->handle); + dmac->ptr = dma_alloc_coherent(nvxx_device(device)->dev, PAGE_SIZE, + &dmac->handle, GFP_KERNEL); if (!dmac->ptr) return -ENOMEM; - ret = nvif_object_init(nvif_object(device), NULL, - args->pushbuf, NV_DMA_FROM_MEMORY, + ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_PCI_US, .access = NV_DMA_V0_ACCESS_RD, @@ -233,13 +240,15 @@ nv50_dmac_create(struct nvif_object *disp, const u32 *oclass, u8 head, if (ret) return ret; - ret = nv50_chan_create(disp, oclass, head, data, size, &dmac->base); + args->pushbuf = nvif_handle(&pushbuf); + + ret = nv50_chan_create(device, disp, oclass, head, data, size, + &dmac->base); nvif_object_fini(&pushbuf); if (ret) return ret; - ret = nvif_object_init(&dmac->base.user, NULL, 0xf0000000, - NV_DMA_IN_MEMORY, + ret = nvif_object_init(&dmac->base.user, 0xf0000000, NV_DMA_IN_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_VRAM, .access = NV_DMA_V0_ACCESS_RDWR, @@ -250,8 +259,7 @@ nv50_dmac_create(struct nvif_object *disp, const u32 *oclass, u8 head, if (ret) return ret; - ret = nvif_object_init(&dmac->base.user, NULL, 0xf0000001, - NV_DMA_IN_MEMORY, + ret = nvif_object_init(&dmac->base.user, 0xf0000001, NV_DMA_IN_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_VRAM, .access = NV_DMA_V0_ACCESS_RDWR, @@ -274,12 +282,13 @@ struct nv50_mast { }; static int -nv50_core_create(struct nvif_object *disp, u64 syncbuf, struct nv50_mast *core) +nv50_core_create(struct nvif_device *device, struct nvif_object *disp, + u64 syncbuf, struct nv50_mast *core) { struct nv50_disp_core_channel_dma_v0 args = { .pushbuf = 0xb0007d00, }; - static const u32 oclass[] = { + static const s32 oclass[] = { GM204_DISP_CORE_CHANNEL_DMA, GM107_DISP_CORE_CHANNEL_DMA, GK110_DISP_CORE_CHANNEL_DMA, @@ -293,8 +302,8 @@ nv50_core_create(struct nvif_object *disp, u64 syncbuf, struct nv50_mast *core) 0 }; - return nv50_dmac_create(disp, oclass, 0, &args, sizeof(args), syncbuf, - &core->base); + return nv50_dmac_create(device, disp, oclass, 0, &args, sizeof(args), + syncbuf, &core->base); } /****************************************************************************** @@ -308,14 +317,14 @@ struct nv50_sync { }; static int -nv50_base_create(struct nvif_object *disp, int head, u64 syncbuf, - struct nv50_sync *base) +nv50_base_create(struct nvif_device *device, struct nvif_object *disp, + int head, u64 syncbuf, struct nv50_sync *base) { struct nv50_disp_base_channel_dma_v0 args = { .pushbuf = 0xb0007c00 | head, .head = head, }; - static const u32 oclass[] = { + static const s32 oclass[] = { GK110_DISP_BASE_CHANNEL_DMA, GK104_DISP_BASE_CHANNEL_DMA, GF110_DISP_BASE_CHANNEL_DMA, @@ -326,7 +335,7 @@ nv50_base_create(struct nvif_object *disp, int head, u64 syncbuf, 0 }; - return nv50_dmac_create(disp, oclass, head, &args, sizeof(args), + return nv50_dmac_create(device, disp, oclass, head, &args, sizeof(args), syncbuf, &base->base); } @@ -339,14 +348,14 @@ struct nv50_ovly { }; static int -nv50_ovly_create(struct nvif_object *disp, int head, u64 syncbuf, - struct nv50_ovly *ovly) +nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp, + int head, u64 syncbuf, struct nv50_ovly *ovly) { struct nv50_disp_overlay_channel_dma_v0 args = { .pushbuf = 0xb0007e00 | head, .head = head, }; - static const u32 oclass[] = { + static const s32 oclass[] = { GK104_DISP_OVERLAY_CONTROL_DMA, GF110_DISP_OVERLAY_CONTROL_DMA, GT214_DISP_OVERLAY_CHANNEL_DMA, @@ -356,7 +365,7 @@ nv50_ovly_create(struct nvif_object *disp, int head, u64 syncbuf, 0 }; - return nv50_dmac_create(disp, oclass, head, &args, sizeof(args), + return nv50_dmac_create(device, disp, oclass, head, &args, sizeof(args), syncbuf, &ovly->base); } @@ -413,6 +422,7 @@ static u32 * evo_wait(void *evoc, int nr) { struct nv50_dmac *dmac = evoc; + struct nvif_device *device = dmac->base.device; u32 put = nvif_rd32(&dmac->base.user, 0x0000) / 4; mutex_lock(&dmac->lock); @@ -420,9 +430,12 @@ evo_wait(void *evoc, int nr) dmac->ptr[put] = 0x20000000; nvif_wr32(&dmac->base.user, 0x0000, 0x00000000); - if (!nvxx_wait(&dmac->base.user, 0x0004, ~0, 0x00000000)) { + if (nvif_msec(device, 2000, + if (!nvif_rd32(&dmac->base.user, 0x0004)) + break; + ) < 0) { mutex_unlock(&dmac->lock); - nv_error(nvxx_object(&dmac->base.user), "channel stalled\n"); + printk(KERN_ERR "nouveau: evo channel stalled\n"); return NULL; } @@ -480,7 +493,10 @@ evo_sync(struct drm_device *dev) evo_data(push, 0x00000000); evo_data(push, 0x00000000); evo_kick(push, mast); - if (nv_wait_cb(nvxx_device(device), evo_sync_wait, disp->sync)) + if (nvif_msec(device, 2000, + if (evo_sync_wait(disp->sync)) + break; + ) >= 0) return 0; } @@ -535,7 +551,10 @@ nv50_display_flip_stop(struct drm_crtc *crtc) evo_kick(push, flip.chan); } - nv_wait_cb(nvxx_device(device), nv50_display_flip_wait, &flip); + nvif_msec(device, 2000, + if (nv50_display_flip_wait(&flip)) + break; + ); } int @@ -563,7 +582,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, if (unlikely(push == NULL)) return -EBUSY; - if (chan && chan->object->oclass < G82_CHANNEL_GPFIFO) { + if (chan && chan->user.oclass < G82_CHANNEL_GPFIFO) { ret = RING_SPACE(chan, 8); if (ret) return ret; @@ -577,7 +596,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, OUT_RING (chan, sync->addr); OUT_RING (chan, sync->data); } else - if (chan && chan->object->oclass < FERMI_CHANNEL_GPFIFO) { + if (chan && chan->user.oclass < FERMI_CHANNEL_GPFIFO) { u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr; ret = RING_SPACE(chan, 12); if (ret) @@ -1408,6 +1427,8 @@ static const struct drm_crtc_funcs nv50_crtc_func = { static int nv50_crtc_create(struct drm_device *dev, int index) { + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvif_device *device = &drm->device; struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; struct drm_crtc *crtc; @@ -1452,13 +1473,13 @@ nv50_crtc_create(struct drm_device *dev, int index) goto out; /* allocate cursor resources */ - ret = nv50_curs_create(disp->disp, index, &head->curs); + ret = nv50_curs_create(device, disp->disp, index, &head->curs); if (ret) goto out; /* allocate page flip / sync resources */ - ret = nv50_base_create(disp->disp, index, disp->sync->bo.offset, - &head->sync); + ret = nv50_base_create(device, disp->disp, index, disp->sync->bo.offset, + &head->sync); if (ret) goto out; @@ -1466,12 +1487,12 @@ nv50_crtc_create(struct drm_device *dev, int index) head->sync.data = 0x00000000; /* allocate overlay resources */ - ret = nv50_oimm_create(disp->disp, index, &head->oimm); + ret = nv50_oimm_create(device, disp->disp, index, &head->oimm); if (ret) goto out; - ret = nv50_ovly_create(disp->disp, index, disp->sync->bo.offset, - &head->ovly); + ret = nv50_ovly_create(device, disp->disp, index, disp->sync->bo.offset, + &head->ovly); if (ret) goto out; @@ -1678,6 +1699,7 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->device); + struct nvkm_i2c_bus *bus; struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; int type = DRM_MODE_ENCODER_DAC; @@ -1687,7 +1709,10 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) return -ENOMEM; nv_encoder->dcb = dcbe; nv_encoder->or = ffs(dcbe->or) - 1; - nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index); + + bus = nvkm_i2c_bus_find(i2c, dcbe->i2c_index); + if (bus) + nv_encoder->i2c = &bus->i2c; encoder = to_drm_encoder(nv_encoder); encoder->possible_crtcs = dcbe->heads; @@ -2081,9 +2106,22 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) return -ENOMEM; nv_encoder->dcb = dcbe; nv_encoder->or = ffs(dcbe->or) - 1; - nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index); nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; + if (dcbe->type == DCB_OUTPUT_DP) { + struct nvkm_i2c_aux *aux = + nvkm_i2c_aux_find(i2c, dcbe->i2c_index); + if (aux) { + nv_encoder->i2c = &aux->i2c; + nv_encoder->aux = aux; + } + } else { + struct nvkm_i2c_bus *bus = + nvkm_i2c_bus_find(i2c, dcbe->i2c_index); + if (bus) + nv_encoder->i2c = &bus->i2c; + } + encoder = to_drm_encoder(nv_encoder); encoder->possible_crtcs = dcbe->heads; encoder->possible_clones = 0; @@ -2234,18 +2272,22 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->device); - struct nvkm_i2c_port *ddc = NULL; + struct nvkm_i2c_bus *bus = NULL; + struct nvkm_i2c_aux *aux = NULL; + struct i2c_adapter *ddc; struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; int type; switch (dcbe->type) { case DCB_OUTPUT_TMDS: - ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(dcbe->extdev)); + bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_EXT(dcbe->extdev)); + ddc = bus ? &bus->i2c : NULL; type = DRM_MODE_ENCODER_TMDS; break; case DCB_OUTPUT_DP: - ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(dcbe->extdev)); + aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbe->extdev)); + ddc = aux ? &aux->i2c : NULL; type = DRM_MODE_ENCODER_TMDS; break; default: @@ -2258,6 +2300,7 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) nv_encoder->dcb = dcbe; nv_encoder->or = ffs(dcbe->or) - 1; nv_encoder->i2c = ddc; + nv_encoder->aux = aux; encoder = to_drm_encoder(nv_encoder); encoder->possible_crtcs = dcbe->heads; @@ -2295,7 +2338,7 @@ nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kin union { struct nv50_dma_v0 nv50; struct gf100_dma_v0 gf100; - struct gf110_dma_v0 gf110; + struct gf119_dma_v0 gf119; }; } args = {}; struct nv50_fbdma *fbdma; @@ -2331,15 +2374,15 @@ nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kin args.gf100.kind = kind; size += sizeof(args.gf100); } else { - args.gf110.page = GF110_DMA_V0_PAGE_LP; - args.gf110.kind = kind; - size += sizeof(args.gf110); + args.gf119.page = GF119_DMA_V0_PAGE_LP; + args.gf119.kind = kind; + size += sizeof(args.gf119); } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nv50_head *head = nv50_head(crtc); - int ret = nvif_object_init(&head->sync.base.base.user, NULL, - name, NV_DMA_IN_MEMORY, &args, size, + int ret = nvif_object_init(&head->sync.base.base.user, name, + NV_DMA_IN_MEMORY, &args, size, &fbdma->base[head->base.index]); if (ret) { nv50_fbdma_fini(fbdma); @@ -2347,9 +2390,8 @@ nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kin } } - ret = nvif_object_init(&mast->base.base.user, NULL, name, - NV_DMA_IN_MEMORY, &args, size, - &fbdma->core); + ret = nvif_object_init(&mast->base.base.user, name, NV_DMA_IN_MEMORY, + &args, size, &fbdma->core); if (ret) { nv50_fbdma_fini(fbdma); return ret; @@ -2502,14 +2544,14 @@ nv50_display_create(struct drm_device *dev) goto out; /* allocate master evo channel */ - ret = nv50_core_create(disp->disp, disp->sync->bo.offset, + ret = nv50_core_create(device, disp->disp, disp->sync->bo.offset, &disp->mast); if (ret) goto out; /* create crtc objects to represent the hw heads */ if (disp->disp->oclass >= GF110_DISP) - crtcs = nvif_rd32(device, 0x022448); + crtcs = nvif_rd32(&device->object, 0x022448); else crtcs = 2; diff --git a/kernel/drivers/gpu/drm/nouveau/nv50_fbcon.c b/kernel/drivers/gpu/drm/nouveau/nv50_fbcon.c index 394c89abc..e05499d6e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/kernel/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -183,12 +183,12 @@ nv50_fbcon_accel_init(struct fb_info *info) return -EINVAL; } - ret = nvif_object_init(chan->object, NULL, 0x502d, 0x502d, NULL, 0, + ret = nvif_object_init(&chan->user, 0x502d, 0x502d, NULL, 0, &nfbdev->twod); if (ret) return ret; - ret = RING_SPACE(chan, 59); + ret = RING_SPACE(chan, 58); if (ret) { nouveau_fbcon_gpu_lockup(info); return ret; @@ -252,6 +252,7 @@ nv50_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, info->var.yres_virtual); OUT_RING(chan, upper_32_bits(fb->vma.offset)); OUT_RING(chan, lower_32_bits(fb->vma.offset)); + FIRE_RING(chan); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nv50_fence.c b/kernel/drivers/gpu/drm/nouveau/nv50_fence.c index a82d9ea7c..f0d96e5da 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/kernel/drivers/gpu/drm/nouveau/nv50_fence.c @@ -51,7 +51,7 @@ nv50_fence_context_new(struct nouveau_channel *chan) fctx->base.read = nv10_fence_read; fctx->base.sync = nv17_fence_sync; - ret = nvif_object_init(chan->object, NULL, NvSema, NV_DMA_IN_MEMORY, + ret = nvif_object_init(&chan->user, NvSema, NV_DMA_IN_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_VRAM, .access = NV_DMA_V0_ACCESS_RDWR, @@ -66,7 +66,7 @@ nv50_fence_context_new(struct nouveau_channel *chan) u32 start = bo->bo.mem.start * PAGE_SIZE; u32 limit = start + bo->bo.mem.size - 1; - ret = nvif_object_init(chan->object, NULL, NvEvoSema0 + i, + ret = nvif_object_init(&chan->user, NvEvoSema0 + i, NV_DMA_IN_MEMORY, &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_VRAM, .access = NV_DMA_V0_ACCESS_RDWR, diff --git a/kernel/drivers/gpu/drm/nouveau/nv84_fence.c b/kernel/drivers/gpu/drm/nouveau/nv84_fence.c index a03db4368..412c5be5a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/kernel/drivers/gpu/drm/nouveau/nv84_fence.c @@ -131,7 +131,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) int nv84_fence_context_new(struct nouveau_channel *chan) { - struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base); + struct nouveau_cli *cli = (void *)chan->user.client; struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx; int ret, i; @@ -213,7 +213,7 @@ nv84_fence_destroy(struct nouveau_drm *drm) int nv84_fence_create(struct nouveau_drm *drm) { - struct nvkm_fifo *pfifo = nvxx_fifo(&drm->device); + struct nvkm_fifo *fifo = nvxx_fifo(&drm->device); struct nv84_fence_priv *priv; u32 domain; int ret; @@ -228,7 +228,7 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; - priv->base.contexts = pfifo->max + 1; + priv->base.contexts = fifo->nr; priv->base.context_base = fence_context_alloc(priv->base.contexts); priv->base.uevent = true; diff --git a/kernel/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/kernel/drivers/gpu/drm/nouveau/nvc0_fbcon.c index 61246677e..c97395b4a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ b/kernel/drivers/gpu/drm/nouveau/nvc0_fbcon.c @@ -156,7 +156,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) struct nouveau_channel *chan = drm->channel; int ret, format; - ret = nvif_object_init(chan->object, NULL, 0x902d, 0x902d, NULL, 0, + ret = nvif_object_init(&chan->user, 0x902d, 0x902d, NULL, 0, &nfbdev->twod); if (ret) return ret; @@ -188,7 +188,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) return -EINVAL; } - ret = RING_SPACE(chan, 60); + ret = RING_SPACE(chan, 58); if (ret) { WARN_ON(1); nouveau_fbcon_gpu_lockup(info); diff --git a/kernel/drivers/gpu/drm/nouveau/nvif/client.c b/kernel/drivers/gpu/drm/nouveau/nvif/client.c index 80b968442..1ee9294ec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvif/client.c +++ b/kernel/drivers/gpu/drm/nouveau/nvif/client.c @@ -29,29 +29,29 @@ int nvif_client_ioctl(struct nvif_client *client, void *data, u32 size) { - return client->driver->ioctl(client->base.priv, client->super, data, size, NULL); + return client->driver->ioctl(client->object.priv, client->super, data, size, NULL); } int nvif_client_suspend(struct nvif_client *client) { - return client->driver->suspend(client->base.priv); + return client->driver->suspend(client->object.priv); } int nvif_client_resume(struct nvif_client *client) { - return client->driver->resume(client->base.priv); + return client->driver->resume(client->object.priv); } void nvif_client_fini(struct nvif_client *client) { if (client->driver) { - client->driver->fini(client->base.priv); + client->driver->fini(client->object.priv); client->driver = NULL; - client->base.parent = NULL; - nvif_object_fini(&client->base); + client->object.client = NULL; + nvif_object_fini(&client->object); } } @@ -68,63 +68,39 @@ nvif_drivers[] = { }; int -nvif_client_init(void (*dtor)(struct nvif_client *), const char *driver, - const char *name, u64 device, const char *cfg, const char *dbg, - struct nvif_client *client) +nvif_client_init(const char *driver, const char *name, u64 device, + const char *cfg, const char *dbg, struct nvif_client *client) { + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_nop_v0 nop; + } args = {}; int ret, i; - ret = nvif_object_init(NULL, (void*)dtor, 0, 0, NULL, 0, &client->base); + ret = nvif_object_init(NULL, 0, 0, NULL, 0, &client->object); if (ret) return ret; - client->base.parent = &client->base; - client->base.handle = ~0; - client->object = &client->base; + client->object.client = client; + client->object.handle = ~0; + client->route = NVIF_IOCTL_V0_ROUTE_NVIF; client->super = true; for (i = 0, ret = -EINVAL; (client->driver = nvif_drivers[i]); i++) { if (!driver || !strcmp(client->driver->name, driver)) { ret = client->driver->init(name, device, cfg, dbg, - &client->base.priv); + &client->object.priv); if (!ret || driver) break; } } + if (ret == 0) { + ret = nvif_client_ioctl(client, &args, sizeof(args)); + client->version = args.nop.version; + } + if (ret) nvif_client_fini(client); return ret; } - -static void -nvif_client_del(struct nvif_client *client) -{ - nvif_client_fini(client); - kfree(client); -} - -int -nvif_client_new(const char *driver, const char *name, u64 device, - const char *cfg, const char *dbg, - struct nvif_client **pclient) -{ - struct nvif_client *client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client) { - int ret = nvif_client_init(nvif_client_del, driver, name, - device, cfg, dbg, client); - if (ret) { - kfree(client); - client = NULL; - } - *pclient = client; - return ret; - } - return -ENOMEM; -} - -void -nvif_client_ref(struct nvif_client *client, struct nvif_client **pclient) -{ - nvif_object_ref(&client->base, (struct nvif_object **)pclient); -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvif/device.c b/kernel/drivers/gpu/drm/nouveau/nvif/device.c index 6f72244c5..252d8c332 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvif/device.c +++ b/kernel/drivers/gpu/drm/nouveau/nvif/device.c @@ -24,55 +24,32 @@ #include +u64 +nvif_device_time(struct nvif_device *device) +{ + struct nv_device_time_v0 args = {}; + int ret = nvif_object_mthd(&device->object, NV_DEVICE_V0_TIME, + &args, sizeof(args)); + WARN_ON_ONCE(ret != 0); + return args.time; +} + void nvif_device_fini(struct nvif_device *device) { - nvif_object_fini(&device->base); + nvif_object_fini(&device->object); } int -nvif_device_init(struct nvif_object *parent, void (*dtor)(struct nvif_device *), - u32 handle, u32 oclass, void *data, u32 size, - struct nvif_device *device) +nvif_device_init(struct nvif_object *parent, u32 handle, s32 oclass, + void *data, u32 size, struct nvif_device *device) { - int ret = nvif_object_init(parent, (void *)dtor, handle, oclass, - data, size, &device->base); + int ret = nvif_object_init(parent, handle, oclass, data, size, + &device->object); if (ret == 0) { - device->object = &device->base; device->info.version = 0; - ret = nvif_object_mthd(&device->base, NV_DEVICE_V0_INFO, + ret = nvif_object_mthd(&device->object, NV_DEVICE_V0_INFO, &device->info, sizeof(device->info)); } return ret; } - -static void -nvif_device_del(struct nvif_device *device) -{ - nvif_device_fini(device); - kfree(device); -} - -int -nvif_device_new(struct nvif_object *parent, u32 handle, u32 oclass, - void *data, u32 size, struct nvif_device **pdevice) -{ - struct nvif_device *device = kzalloc(sizeof(*device), GFP_KERNEL); - if (device) { - int ret = nvif_device_init(parent, nvif_device_del, handle, - oclass, data, size, device); - if (ret) { - kfree(device); - device = NULL; - } - *pdevice = device; - return ret; - } - return -ENOMEM; -} - -void -nvif_device_ref(struct nvif_device *device, struct nvif_device **pdevice) -{ - nvif_object_ref(&device->base, (struct nvif_object **)pdevice); -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvif/notify.c b/kernel/drivers/gpu/drm/nouveau/nvif/notify.c index 8e3474870..b0787ff83 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvif/notify.c +++ b/kernel/drivers/gpu/drm/nouveau/nvif/notify.c @@ -124,7 +124,7 @@ nvif_notify(const void *header, u32 length, const void *data, u32 size) } if (!WARN_ON(notify == NULL)) { - struct nvif_client *client = nvif_client(notify->object); + struct nvif_client *client = notify->object->client; if (!WARN_ON(notify->size != size)) { atomic_inc(¬ify->putcnt); if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) { @@ -156,7 +156,7 @@ nvif_notify_fini(struct nvif_notify *notify) if (ret >= 0 && object) { ret = nvif_object_ioctl(object, &args, sizeof(args), NULL); if (ret == 0) { - nvif_object_ref(NULL, ¬ify->object); + notify->object = NULL; kfree((void *)notify->data); } } @@ -164,9 +164,9 @@ nvif_notify_fini(struct nvif_notify *notify) } int -nvif_notify_init(struct nvif_object *object, void (*dtor)(struct nvif_notify *), - int (*func)(struct nvif_notify *), bool work, u8 event, - void *data, u32 size, u32 reply, struct nvif_notify *notify) +nvif_notify_init(struct nvif_object *object, int (*func)(struct nvif_notify *), + bool work, u8 event, void *data, u32 size, u32 reply, + struct nvif_notify *notify) { struct { struct nvif_ioctl_v0 ioctl; @@ -175,11 +175,9 @@ nvif_notify_init(struct nvif_object *object, void (*dtor)(struct nvif_notify *), } *args; int ret = -ENOMEM; - notify->object = NULL; - nvif_object_ref(object, ¬ify->object); + notify->object = object; notify->flags = 0; atomic_set(¬ify->putcnt, 1); - notify->dtor = dtor; notify->func = func; notify->data = NULL; notify->size = reply; @@ -211,38 +209,3 @@ done: nvif_notify_fini(notify); return ret; } - -static void -nvif_notify_del(struct nvif_notify *notify) -{ - nvif_notify_fini(notify); - kfree(notify); -} - -void -nvif_notify_ref(struct nvif_notify *notify, struct nvif_notify **pnotify) -{ - BUG_ON(notify != NULL); - if (*pnotify) - (*pnotify)->dtor(*pnotify); - *pnotify = notify; -} - -int -nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *), - bool work, u8 type, void *data, u32 size, u32 reply, - struct nvif_notify **pnotify) -{ - struct nvif_notify *notify = kzalloc(sizeof(*notify), GFP_KERNEL); - if (notify) { - int ret = nvif_notify_init(object, nvif_notify_del, func, work, - type, data, size, reply, notify); - if (ret) { - kfree(notify); - notify = NULL; - } - *pnotify = notify; - return ret; - } - return -ENOMEM; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvif/object.c b/kernel/drivers/gpu/drm/nouveau/nvif/object.c index 3ab4e2f8c..c3fb6a20f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvif/object.c +++ b/kernel/drivers/gpu/drm/nouveau/nvif/object.c @@ -30,47 +30,71 @@ int nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack) { - struct nvif_client *client = nvif_client(object); + struct nvif_client *client = object->client; union { struct nvif_ioctl_v0 v0; } *args = data; if (size >= sizeof(*args) && args->v0.version == 0) { + if (object != &client->object) + args->v0.object = nvif_handle(object); + else + args->v0.object = 0; args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; - args->v0.path_nr = 0; - while (args->v0.path_nr < ARRAY_SIZE(args->v0.path)) { - args->v0.path[args->v0.path_nr++] = object->handle; - if (object->parent == object) - break; - object = object->parent; - } } else return -ENOSYS; - return client->driver->ioctl(client->base.priv, client->super, data, size, hack); + return client->driver->ioctl(client->object.priv, client->super, + data, size, hack); +} + +void +nvif_object_sclass_put(struct nvif_sclass **psclass) +{ + kfree(*psclass); + *psclass = NULL; } int -nvif_object_sclass(struct nvif_object *object, u32 *oclass, int count) +nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass) { struct { struct nvif_ioctl_v0 ioctl; struct nvif_ioctl_sclass_v0 sclass; - } *args; - u32 size = count * sizeof(args->sclass.oclass[0]); - int ret; + } *args = NULL; + int ret, cnt = 0, i; + u32 size; - if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) - return -ENOMEM; - args->ioctl.version = 0; - args->ioctl.type = NVIF_IOCTL_V0_SCLASS; - args->sclass.version = 0; - args->sclass.count = count; + while (1) { + size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]); + if (!(args = kmalloc(size, GFP_KERNEL))) + return -ENOMEM; + args->ioctl.version = 0; + args->ioctl.type = NVIF_IOCTL_V0_SCLASS; + args->sclass.version = 0; + args->sclass.count = cnt; + + ret = nvif_object_ioctl(object, args, size, NULL); + if (ret == 0 && args->sclass.count <= cnt) + break; + cnt = args->sclass.count; + kfree(args); + if (ret != 0) + return ret; + } + + *psclass = kzalloc(sizeof(**psclass) * args->sclass.count, GFP_KERNEL); + if (*psclass) { + for (i = 0; i < args->sclass.count; i++) { + (*psclass)[i].oclass = args->sclass.oclass[i].oclass; + (*psclass)[i].minver = args->sclass.oclass[i].minver; + (*psclass)[i].maxver = args->sclass.oclass[i].maxver; + } + ret = args->sclass.count; + } else { + ret = -ENOMEM; + } - memcpy(args->sclass.oclass, oclass, size); - ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL); - ret = ret ? ret : args->sclass.count; - memcpy(oclass, args->sclass.oclass, size); kfree(args); return ret; } @@ -145,7 +169,7 @@ void nvif_object_unmap(struct nvif_object *object) { if (object->map.size) { - struct nvif_client *client = nvif_client(object); + struct nvif_client *client = object->client; struct { struct nvif_ioctl_v0 ioctl; struct nvif_ioctl_unmap unmap; @@ -167,7 +191,7 @@ nvif_object_unmap(struct nvif_object *object) int nvif_object_map(struct nvif_object *object) { - struct nvif_client *client = nvif_client(object); + struct nvif_client *client = object->client; struct { struct nvif_ioctl_v0 ioctl; struct nvif_ioctl_map_v0 map; @@ -186,119 +210,65 @@ nvif_object_map(struct nvif_object *object) return ret; } -struct ctor { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_new_v0 new; -}; - void nvif_object_fini(struct nvif_object *object) { - struct ctor *ctor = container_of(object->data, typeof(*ctor), new.data); - if (object->parent) { - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_del del; - } args = { - .ioctl.type = NVIF_IOCTL_V0_DEL, - }; + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_del del; + } args = { + .ioctl.type = NVIF_IOCTL_V0_DEL, + }; - nvif_object_unmap(object); - nvif_object_ioctl(object, &args, sizeof(args), NULL); - if (object->data) { - object->size = 0; - object->data = NULL; - kfree(ctor); - } - nvif_object_ref(NULL, &object->parent); - } + if (!object->client) + return; + + nvif_object_unmap(object); + nvif_object_ioctl(object, &args, sizeof(args), NULL); + object->client = NULL; } int -nvif_object_init(struct nvif_object *parent, void (*dtor)(struct nvif_object *), - u32 handle, u32 oclass, void *data, u32 size, - struct nvif_object *object) +nvif_object_init(struct nvif_object *parent, u32 handle, s32 oclass, + void *data, u32 size, struct nvif_object *object) { - struct ctor *ctor; + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_new_v0 new; + } *args; int ret = 0; - object->parent = NULL; - object->object = object; - nvif_object_ref(parent, &object->parent); - kref_init(&object->refcount); + object->client = NULL; object->handle = handle; object->oclass = oclass; - object->data = NULL; - object->size = 0; - object->dtor = dtor; object->map.ptr = NULL; object->map.size = 0; - if (object->parent) { - if (!(ctor = kmalloc(sizeof(*ctor) + size, GFP_KERNEL))) { + if (parent) { + if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) { nvif_object_fini(object); return -ENOMEM; } - object->data = ctor->new.data; - object->size = size; - memcpy(object->data, data, size); - ctor->ioctl.version = 0; - ctor->ioctl.type = NVIF_IOCTL_V0_NEW; - ctor->new.version = 0; - ctor->new.route = NVIF_IOCTL_V0_ROUTE_NVIF; - ctor->new.token = (unsigned long)(void *)object; - ctor->new.handle = handle; - ctor->new.oclass = oclass; + args->ioctl.version = 0; + args->ioctl.type = NVIF_IOCTL_V0_NEW; + args->new.version = 0; + args->new.route = parent->client->route; + args->new.token = nvif_handle(object); + args->new.object = nvif_handle(object); + args->new.handle = handle; + args->new.oclass = oclass; - ret = nvif_object_ioctl(parent, ctor, sizeof(*ctor) + - object->size, &object->priv); + memcpy(args->new.data, data, size); + ret = nvif_object_ioctl(parent, args, sizeof(*args) + size, + &object->priv); + memcpy(data, args->new.data, size); + kfree(args); + if (ret == 0) + object->client = parent->client; } if (ret) nvif_object_fini(object); return ret; } - -static void -nvif_object_del(struct nvif_object *object) -{ - nvif_object_fini(object); - kfree(object); -} - -int -nvif_object_new(struct nvif_object *parent, u32 handle, u32 oclass, - void *data, u32 size, struct nvif_object **pobject) -{ - struct nvif_object *object = kzalloc(sizeof(*object), GFP_KERNEL); - if (object) { - int ret = nvif_object_init(parent, nvif_object_del, handle, - oclass, data, size, object); - if (ret) { - kfree(object); - object = NULL; - } - *pobject = object; - return ret; - } - return -ENOMEM; -} - -static void -nvif_object_put(struct kref *kref) -{ - struct nvif_object *object = - container_of(kref, typeof(*object), refcount); - object->dtor(object); -} - -void -nvif_object_ref(struct nvif_object *object, struct nvif_object **pobject) -{ - if (object) - kref_get(&object->refcount); - if (*pobject) - kref_put(&(*pobject)->refcount, nvif_object_put); - *pobject = object; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index a2bdb2069..7f66963f3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -1,17 +1,14 @@ nvkm-y := nvkm/core/client.o -nvkm-y += nvkm/core/engctx.o nvkm-y += nvkm/core/engine.o nvkm-y += nvkm/core/enum.o nvkm-y += nvkm/core/event.o nvkm-y += nvkm/core/gpuobj.o -nvkm-y += nvkm/core/handle.o nvkm-y += nvkm/core/ioctl.o +nvkm-y += nvkm/core/memory.o nvkm-y += nvkm/core/mm.o -nvkm-y += nvkm/core/namedb.o nvkm-y += nvkm/core/notify.o nvkm-y += nvkm/core/object.o +nvkm-y += nvkm/core/oproxy.o nvkm-y += nvkm/core/option.o -nvkm-y += nvkm/core/parent.o -nvkm-y += nvkm/core/printk.o nvkm-y += nvkm/core/ramht.o nvkm-y += nvkm/core/subdev.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/client.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/client.c index 878a82f8f..297e1e953 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -23,7 +23,6 @@ */ #include #include -#include #include #include @@ -91,7 +90,7 @@ int nvkm_client_notify_new(struct nvkm_object *object, struct nvkm_event *event, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(object); + struct nvkm_client *client = object->client; struct nvkm_client_notify *notify; union { struct nvif_notify_req_v0 v0; @@ -111,11 +110,11 @@ nvkm_client_notify_new(struct nvkm_object *object, if (!notify) return -ENOMEM; - nv_ioctl(client, "notify new size %d\n", size); + nvif_ioctl(object, "notify new size %d\n", size); if (nvif_unpack(req->v0, 0, 0, true)) { - nv_ioctl(client, "notify new vers %d reply %d route %02x " - "token %llx\n", req->v0.version, - req->v0.reply, req->v0.route, req->v0.token); + nvif_ioctl(object, "notify new vers %d reply %d route %02x " + "token %llx\n", req->v0.version, + req->v0.reply, req->v0.route, req->v0.token); notify->version = req->v0.version; notify->size = sizeof(notify->rep.v0); notify->rep.v0.version = req->v0.version; @@ -146,10 +145,10 @@ nvkm_client_mthd_devlist(struct nvkm_object *object, void *data, u32 size) } *args = data; int ret; - nv_ioctl(object, "client devlist size %d\n", size); + nvif_ioctl(object, "client devlist size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "client devlist vers %d count %d\n", - args->v0.version, args->v0.count); + nvif_ioctl(object, "client devlist vers %d count %d\n", + args->v0.version, args->v0.count); if (size == sizeof(args->v0.device[0]) * args->v0.count) { ret = nvkm_device_list(args->v0.device, args->v0.count); if (ret >= 0) { @@ -176,91 +175,134 @@ nvkm_client_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } -static void -nvkm_client_dtor(struct nvkm_object *object) +static int +nvkm_client_child_new(const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) { - struct nvkm_client *client = (void *)object; - int i; - for (i = 0; i < ARRAY_SIZE(client->notify); i++) - nvkm_client_notify_del(client, i); - nvkm_object_ref(NULL, &client->device); - nvkm_handle_destroy(client->root); - nvkm_namedb_destroy(&client->namedb); + return oclass->base.ctor(oclass, data, size, pobject); } -static struct nvkm_oclass -nvkm_client_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .dtor = nvkm_client_dtor, - .mthd = nvkm_client_mthd, - }, -}; - -int -nvkm_client_create_(const char *name, u64 devname, const char *cfg, - const char *dbg, int length, void **pobject) +static int +nvkm_client_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) { - struct nvkm_object *device; - struct nvkm_client *client; - int ret; + const struct nvkm_sclass *sclass; + + switch (index) { + case 0: sclass = &nvkm_udevice_sclass; break; + default: + return -EINVAL; + } - device = (void *)nvkm_device_find(devname); - if (!device) - return -ENODEV; + oclass->ctor = nvkm_client_child_new; + oclass->base = *sclass; + return 0; +} + +static const struct nvkm_object_func +nvkm_client_object_func = { + .mthd = nvkm_client_mthd, + .sclass = nvkm_client_child_get, +}; - ret = nvkm_namedb_create_(NULL, NULL, &nvkm_client_oclass, - NV_CLIENT_CLASS, NULL, - (1ULL << NVDEV_ENGINE_DEVICE), - length, pobject); - client = *pobject; - if (ret) - return ret; +void +nvkm_client_remove(struct nvkm_client *client, struct nvkm_object *object) +{ + if (!RB_EMPTY_NODE(&object->node)) + rb_erase(&object->node, &client->objroot); +} - ret = nvkm_handle_create(nv_object(client), ~0, ~0, nv_object(client), - &client->root); - if (ret) - return ret; +bool +nvkm_client_insert(struct nvkm_client *client, struct nvkm_object *object) +{ + struct rb_node **ptr = &client->objroot.rb_node; + struct rb_node *parent = NULL; - /* prevent init/fini being called, os in in charge of this */ - atomic_set(&nv_object(client)->usecount, 2); + while (*ptr) { + struct nvkm_object *this = + container_of(*ptr, typeof(*this), node); + parent = *ptr; + if (object->object < this->object) + ptr = &parent->rb_left; + else + if (object->object > this->object) + ptr = &parent->rb_right; + else + return false; + } - nvkm_object_ref(device, &client->device); - snprintf(client->name, sizeof(client->name), "%s", name); - client->debug = nvkm_dbgopt(dbg, "CLIENT"); - return 0; + rb_link_node(&object->node, parent, ptr); + rb_insert_color(&object->node, &client->objroot); + return true; } -int -nvkm_client_init(struct nvkm_client *client) +struct nvkm_object * +nvkm_client_search(struct nvkm_client *client, u64 handle) { - int ret; - nv_debug(client, "init running\n"); - ret = nvkm_handle_init(client->root); - nv_debug(client, "init completed with %d\n", ret); - return ret; + struct rb_node *node = client->objroot.rb_node; + while (node) { + struct nvkm_object *object = + container_of(node, typeof(*object), node); + if (handle < object->object) + node = node->rb_left; + else + if (handle > object->object) + node = node->rb_right; + else + return object; + } + return NULL; } int nvkm_client_fini(struct nvkm_client *client, bool suspend) { + struct nvkm_object *object = &client->object; const char *name[2] = { "fini", "suspend" }; - int ret, i; - nv_debug(client, "%s running\n", name[suspend]); - nv_debug(client, "%s notify\n", name[suspend]); + int i; + nvif_debug(object, "%s notify\n", name[suspend]); for (i = 0; i < ARRAY_SIZE(client->notify); i++) nvkm_client_notify_put(client, i); - nv_debug(client, "%s object\n", name[suspend]); - ret = nvkm_handle_fini(client->root, suspend); - nv_debug(client, "%s completed with %d\n", name[suspend], ret); - return ret; + return nvkm_object_fini(&client->object, suspend); +} + +int +nvkm_client_init(struct nvkm_client *client) +{ + return nvkm_object_init(&client->object); +} + +void +nvkm_client_del(struct nvkm_client **pclient) +{ + struct nvkm_client *client = *pclient; + int i; + if (client) { + nvkm_client_fini(client, false); + for (i = 0; i < ARRAY_SIZE(client->notify); i++) + nvkm_client_notify_del(client, i); + nvkm_object_dtor(&client->object); + kfree(*pclient); + *pclient = NULL; + } } -const char * -nvkm_client_name(void *obj) +int +nvkm_client_new(const char *name, u64 device, const char *cfg, + const char *dbg, struct nvkm_client **pclient) { - const char *client_name = "unknown"; - struct nvkm_client *client = nvkm_client(obj); - if (client) - client_name = client->name; - return client_name; + struct nvkm_oclass oclass = {}; + struct nvkm_client *client; + + if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL))) + return -ENOMEM; + oclass.client = client; + + nvkm_object_ctor(&nvkm_client_object_func, &oclass, &client->object); + snprintf(client->name, sizeof(client->name), "%s", name); + client->device = device; + client->debug = nvkm_dbgopt(dbg, "CLIENT"); + client->objroot = RB_ROOT; + client->dmaroot = RB_ROOT; + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/engctx.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/engctx.c deleted file mode 100644 index fb2acbca7..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/engctx.c +++ /dev/null @@ -1,239 +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 -#include -#include - -static inline int -nvkm_engctx_exists(struct nvkm_object *parent, - struct nvkm_engine *engine, void **pobject) -{ - struct nvkm_engctx *engctx; - struct nvkm_object *parctx; - - list_for_each_entry(engctx, &engine->contexts, head) { - parctx = nv_pclass(nv_object(engctx), NV_PARENT_CLASS); - if (parctx == parent) { - atomic_inc(&nv_object(engctx)->refcount); - *pobject = engctx; - return 1; - } - } - - return 0; -} - -int -nvkm_engctx_create_(struct nvkm_object *parent, struct nvkm_object *engobj, - struct nvkm_oclass *oclass, struct nvkm_object *pargpu, - u32 size, u32 align, u32 flags, int length, void **pobject) -{ - struct nvkm_client *client = nvkm_client(parent); - struct nvkm_engine *engine = nv_engine(engobj); - struct nvkm_object *engctx; - unsigned long save; - int ret; - - /* check if this engine already has a context for the parent object, - * and reference it instead of creating a new one - */ - spin_lock_irqsave(&engine->lock, save); - ret = nvkm_engctx_exists(parent, engine, pobject); - spin_unlock_irqrestore(&engine->lock, save); - if (ret) - return ret; - - /* create the new context, supports creating both raw objects and - * objects backed by instance memory - */ - if (size) { - ret = nvkm_gpuobj_create_(parent, engobj, oclass, - NV_ENGCTX_CLASS, pargpu, size, - align, flags, length, pobject); - } else { - ret = nvkm_object_create_(parent, engobj, oclass, - NV_ENGCTX_CLASS, length, pobject); - } - - engctx = *pobject; - if (ret) - return ret; - - /* must take the lock again and re-check a context doesn't already - * exist (in case of a race) - the lock had to be dropped before as - * it's not possible to allocate the object with it held. - */ - spin_lock_irqsave(&engine->lock, save); - ret = nvkm_engctx_exists(parent, engine, pobject); - if (ret) { - spin_unlock_irqrestore(&engine->lock, save); - nvkm_object_ref(NULL, &engctx); - return ret; - } - - if (client->vm) - atomic_inc(&client->vm->engref[nv_engidx(engine)]); - list_add(&nv_engctx(engctx)->head, &engine->contexts); - nv_engctx(engctx)->addr = ~0ULL; - spin_unlock_irqrestore(&engine->lock, save); - return 0; -} - -void -nvkm_engctx_destroy(struct nvkm_engctx *engctx) -{ - struct nvkm_engine *engine = engctx->gpuobj.object.engine; - struct nvkm_client *client = nvkm_client(engctx); - unsigned long save; - - nvkm_gpuobj_unmap(&engctx->vma); - spin_lock_irqsave(&engine->lock, save); - list_del(&engctx->head); - spin_unlock_irqrestore(&engine->lock, save); - - if (client->vm) - atomic_dec(&client->vm->engref[nv_engidx(engine)]); - - if (engctx->gpuobj.size) - nvkm_gpuobj_destroy(&engctx->gpuobj); - else - nvkm_object_destroy(&engctx->gpuobj.object); -} - -int -nvkm_engctx_init(struct nvkm_engctx *engctx) -{ - struct nvkm_object *object = nv_object(engctx); - struct nvkm_subdev *subdev = nv_subdev(object->engine); - struct nvkm_object *parent; - struct nvkm_subdev *pardev; - int ret; - - ret = nvkm_gpuobj_init(&engctx->gpuobj); - if (ret) - return ret; - - parent = nv_pclass(object->parent, NV_PARENT_CLASS); - pardev = nv_subdev(parent->engine); - if (nv_parent(parent)->context_attach) { - mutex_lock(&pardev->mutex); - ret = nv_parent(parent)->context_attach(parent, object); - mutex_unlock(&pardev->mutex); - } - - if (ret) { - nv_error(parent, "failed to attach %s context, %d\n", - subdev->name, ret); - return ret; - } - - nv_debug(parent, "attached %s context\n", subdev->name); - return 0; -} - -int -nvkm_engctx_fini(struct nvkm_engctx *engctx, bool suspend) -{ - struct nvkm_object *object = nv_object(engctx); - struct nvkm_subdev *subdev = nv_subdev(object->engine); - struct nvkm_object *parent; - struct nvkm_subdev *pardev; - int ret = 0; - - parent = nv_pclass(object->parent, NV_PARENT_CLASS); - pardev = nv_subdev(parent->engine); - if (nv_parent(parent)->context_detach) { - mutex_lock(&pardev->mutex); - ret = nv_parent(parent)->context_detach(parent, suspend, object); - mutex_unlock(&pardev->mutex); - } - - if (ret) { - nv_error(parent, "failed to detach %s context, %d\n", - subdev->name, ret); - return ret; - } - - nv_debug(parent, "detached %s context\n", subdev->name); - return nvkm_gpuobj_fini(&engctx->gpuobj, suspend); -} - -int -_nvkm_engctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_engctx *engctx; - int ret; - - ret = nvkm_engctx_create(parent, engine, oclass, NULL, 256, 256, - NVOBJ_FLAG_ZERO_ALLOC, &engctx); - *pobject = nv_object(engctx); - return ret; -} - -void -_nvkm_engctx_dtor(struct nvkm_object *object) -{ - nvkm_engctx_destroy(nv_engctx(object)); -} - -int -_nvkm_engctx_init(struct nvkm_object *object) -{ - return nvkm_engctx_init(nv_engctx(object)); -} - -int -_nvkm_engctx_fini(struct nvkm_object *object, bool suspend) -{ - return nvkm_engctx_fini(nv_engctx(object), suspend); -} - -struct nvkm_object * -nvkm_engctx_get(struct nvkm_engine *engine, u64 addr) -{ - struct nvkm_engctx *engctx; - unsigned long flags; - - spin_lock_irqsave(&engine->lock, flags); - list_for_each_entry(engctx, &engine->contexts, head) { - if (engctx->addr == addr) { - engctx->save = flags; - return nv_object(engctx); - } - } - spin_unlock_irqrestore(&engine->lock, flags); - return NULL; -} - -void -nvkm_engctx_put(struct nvkm_object *object) -{ - if (object) { - struct nvkm_engine *engine = nv_engine(object->engine); - struct nvkm_engctx *engctx = nv_engctx(object); - spin_unlock_irqrestore(&engine->lock, engctx->save); - } -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/engine.c index 60820173c..8a7bae7bd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -25,51 +25,141 @@ #include #include +#include + +void +nvkm_engine_unref(struct nvkm_engine **pengine) +{ + struct nvkm_engine *engine = *pengine; + if (engine) { + mutex_lock(&engine->subdev.mutex); + if (--engine->usecount == 0) + nvkm_subdev_fini(&engine->subdev, false); + mutex_unlock(&engine->subdev.mutex); + *pengine = NULL; + } +} + struct nvkm_engine * -nvkm_engine(void *obj, int idx) +nvkm_engine_ref(struct nvkm_engine *engine) { - obj = nvkm_subdev(obj, idx); - if (obj && nv_iclass(obj, NV_ENGINE_CLASS)) - return nv_engine(obj); - return NULL; + if (engine) { + mutex_lock(&engine->subdev.mutex); + if (++engine->usecount == 1) { + int ret = nvkm_subdev_init(&engine->subdev); + if (ret) { + engine->usecount--; + mutex_unlock(&engine->subdev.mutex); + return ERR_PTR(ret); + } + } + mutex_unlock(&engine->subdev.mutex); + } + return engine; } -int -nvkm_engine_create_(struct nvkm_object *parent, struct nvkm_object *engobj, - struct nvkm_oclass *oclass, bool enable, - const char *iname, const char *fname, - int length, void **pobject) +void +nvkm_engine_tile(struct nvkm_engine *engine, int region) { - struct nvkm_engine *engine; - int ret; + struct nvkm_fb *fb = engine->subdev.device->fb; + if (engine->func->tile) + engine->func->tile(engine, region, &fb->tile.region[region]); +} - ret = nvkm_subdev_create_(parent, engobj, oclass, NV_ENGINE_CLASS, - iname, fname, length, pobject); - engine = *pobject; - if (ret) - return ret; +static void +nvkm_engine_intr(struct nvkm_subdev *subdev) +{ + struct nvkm_engine *engine = nvkm_engine(subdev); + if (engine->func->intr) + engine->func->intr(engine); +} - if (parent) { - struct nvkm_device *device = nv_device(parent); - int engidx = nv_engidx(engine); +static int +nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend) +{ + struct nvkm_engine *engine = nvkm_engine(subdev); + if (engine->func->fini) + return engine->func->fini(engine, suspend); + return 0; +} - if (device->disable_mask & (1ULL << engidx)) { - if (!nvkm_boolopt(device->cfgopt, iname, false)) { - nv_debug(engine, "engine disabled by hw/fw\n"); - return -ENODEV; - } +static int +nvkm_engine_init(struct nvkm_subdev *subdev) +{ + struct nvkm_engine *engine = nvkm_engine(subdev); + struct nvkm_fb *fb = subdev->device->fb; + int ret = 0, i; + s64 time; - nv_warn(engine, "ignoring hw/fw engine disable\n"); - } + if (!engine->usecount) { + nvkm_trace(subdev, "init skipped, engine has no users\n"); + return ret; + } - if (!nvkm_boolopt(device->cfgopt, iname, enable)) { - if (!enable) - nv_warn(engine, "disabled, %s=1 to enable\n", iname); - return -ENODEV; + if (engine->func->oneinit && !engine->subdev.oneinit) { + nvkm_trace(subdev, "one-time init running...\n"); + time = ktime_to_us(ktime_get()); + ret = engine->func->oneinit(engine); + if (ret) { + nvkm_trace(subdev, "one-time init failed, %d\n", ret); + return ret; } + + engine->subdev.oneinit = true; + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "one-time init completed in %lldus\n", time); + } + + if (engine->func->init) + ret = engine->func->init(engine); + + for (i = 0; fb && i < fb->tile.regions; i++) + nvkm_engine_tile(engine, i); + return ret; +} + +static void * +nvkm_engine_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_engine *engine = nvkm_engine(subdev); + if (engine->func->dtor) + return engine->func->dtor(engine); + return engine; +} + +static const struct nvkm_subdev_func +nvkm_engine_func = { + .dtor = nvkm_engine_dtor, + .init = nvkm_engine_init, + .fini = nvkm_engine_fini, + .intr = nvkm_engine_intr, +}; + +int +nvkm_engine_ctor(const struct nvkm_engine_func *func, + struct nvkm_device *device, int index, u32 pmc_enable, + bool enable, struct nvkm_engine *engine) +{ + nvkm_subdev_ctor(&nvkm_engine_func, device, index, + pmc_enable, &engine->subdev); + engine->func = func; + + if (!nvkm_boolopt(device->cfgopt, nvkm_subdev_name[index], enable)) { + nvkm_debug(&engine->subdev, "disabled\n"); + return -ENODEV; } - INIT_LIST_HEAD(&engine->contexts); spin_lock_init(&engine->lock); return 0; } + +int +nvkm_engine_new_(const struct nvkm_engine_func *func, + struct nvkm_device *device, int index, u32 pmc_enable, + bool enable, struct nvkm_engine **pengine) +{ + if (!(*pengine = kzalloc(sizeof(**pengine), GFP_KERNEL))) + return -ENOMEM; + return nvkm_engine_ctor(func, device, index, pmc_enable, + enable, *pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/enum.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/enum.c index 4f92bfc13..b9581feb2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/enum.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/enum.c @@ -38,29 +38,19 @@ nvkm_enum_find(const struct nvkm_enum *en, u32 value) return NULL; } -const struct nvkm_enum * -nvkm_enum_print(const struct nvkm_enum *en, u32 value) -{ - en = nvkm_enum_find(en, value); - if (en) - pr_cont("%s", en->name); - else - pr_cont("(unknown enum 0x%08x)", value); - return en; -} - void -nvkm_bitfield_print(const struct nvkm_bitfield *bf, u32 value) +nvkm_snprintbf(char *data, int size, const struct nvkm_bitfield *bf, u32 value) { - while (bf->name) { + bool space = false; + while (size >= 1 && bf->name) { if (value & bf->mask) { - pr_cont(" %s", bf->name); - value &= ~bf->mask; + int this = snprintf(data, size, "%s%s", + space ? " " : "", bf->name); + size -= this; + data += this; + space = true; } - bf++; } - - if (value) - pr_cont(" (unknown bits 0x%08x)", value); + data[0] = '\0'; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c index 2eba801aa..c3a790eb8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c @@ -28,240 +28,205 @@ #include #include -void -nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj) +/* fast-path, where backend is able to provide direct pointer to memory */ +static u32 +nvkm_gpuobj_rd32_fast(struct nvkm_gpuobj *gpuobj, u32 offset) { - int i; - - if (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE) { - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, 0x00000000); - } - - if (gpuobj->node) - nvkm_mm_free(&nv_gpuobj(gpuobj->parent)->heap, &gpuobj->node); + return ioread32_native(gpuobj->map + offset); +} - if (gpuobj->heap.block_size) - nvkm_mm_fini(&gpuobj->heap); +static void +nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) +{ + iowrite32_native(data, gpuobj->map + offset); +} - nvkm_object_destroy(&gpuobj->object); +/* accessor functions for gpuobjs allocated directly from instmem */ +static u32 +nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) +{ + return nvkm_ro32(gpuobj->memory, offset); } -int -nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 pclass, - struct nvkm_object *pargpu, u32 size, u32 align, u32 flags, - int length, void **pobject) +static void +nvkm_gpuobj_heap_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { - struct nvkm_instmem *imem = nvkm_instmem(parent); - struct nvkm_bar *bar = nvkm_bar(parent); - struct nvkm_gpuobj *gpuobj; - struct nvkm_mm *heap = NULL; - int ret, i; - u64 addr; + nvkm_wo32(gpuobj->memory, offset, data); +} - *pobject = NULL; +static const struct nvkm_gpuobj_func nvkm_gpuobj_heap; +static void +nvkm_gpuobj_heap_release(struct nvkm_gpuobj *gpuobj) +{ + gpuobj->func = &nvkm_gpuobj_heap; + nvkm_done(gpuobj->memory); +} - if (pargpu) { - while ((pargpu = nv_pclass(pargpu, NV_GPUOBJ_CLASS))) { - if (nv_gpuobj(pargpu)->heap.block_size) - break; - pargpu = pargpu->parent; - } +static const struct nvkm_gpuobj_func +nvkm_gpuobj_heap_fast = { + .release = nvkm_gpuobj_heap_release, + .rd32 = nvkm_gpuobj_rd32_fast, + .wr32 = nvkm_gpuobj_wr32_fast, +}; - if (unlikely(pargpu == NULL)) { - nv_error(parent, "no gpuobj heap\n"); - return -EINVAL; - } +static const struct nvkm_gpuobj_func +nvkm_gpuobj_heap_slow = { + .release = nvkm_gpuobj_heap_release, + .rd32 = nvkm_gpuobj_heap_rd32, + .wr32 = nvkm_gpuobj_heap_wr32, +}; - addr = nv_gpuobj(pargpu)->addr; - heap = &nv_gpuobj(pargpu)->heap; - atomic_inc(&parent->refcount); - } else { - ret = imem->alloc(imem, parent, size, align, &parent); - pargpu = parent; - if (ret) - return ret; +static void * +nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj) +{ + gpuobj->map = nvkm_kmap(gpuobj->memory); + if (likely(gpuobj->map)) + gpuobj->func = &nvkm_gpuobj_heap_fast; + else + gpuobj->func = &nvkm_gpuobj_heap_slow; + return gpuobj->map; +} - addr = nv_memobj(pargpu)->addr; - size = nv_memobj(pargpu)->size; - - if (bar && bar->alloc) { - struct nvkm_instobj *iobj = (void *)parent; - struct nvkm_mem **mem = (void *)(iobj + 1); - struct nvkm_mem *node = *mem; - if (!bar->alloc(bar, parent, node, &pargpu)) { - nvkm_object_ref(NULL, &parent); - parent = pargpu; - } - } - } +static const struct nvkm_gpuobj_func +nvkm_gpuobj_heap = { + .acquire = nvkm_gpuobj_heap_acquire, +}; - ret = nvkm_object_create_(parent, engine, oclass, pclass | - NV_GPUOBJ_CLASS, length, pobject); - nvkm_object_ref(NULL, &parent); - gpuobj = *pobject; - if (ret) - return ret; +/* accessor functions for gpuobjs sub-allocated from a parent gpuobj */ +static u32 +nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) +{ + return nvkm_ro32(gpuobj->parent, gpuobj->node->offset + offset); +} - gpuobj->parent = pargpu; - gpuobj->flags = flags; - gpuobj->addr = addr; - gpuobj->size = size; +static void +nvkm_gpuobj_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) +{ + nvkm_wo32(gpuobj->parent, gpuobj->node->offset + offset, data); +} - if (heap) { - ret = nvkm_mm_head(heap, 0, 1, size, size, max(align, (u32)1), - &gpuobj->node); - if (ret) - return ret; +static const struct nvkm_gpuobj_func nvkm_gpuobj_func; +static void +nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj) +{ + gpuobj->func = &nvkm_gpuobj_func; + nvkm_done(gpuobj->parent); +} - gpuobj->addr += gpuobj->node->offset; - } +static const struct nvkm_gpuobj_func +nvkm_gpuobj_fast = { + .release = nvkm_gpuobj_release, + .rd32 = nvkm_gpuobj_rd32_fast, + .wr32 = nvkm_gpuobj_wr32_fast, +}; - if (gpuobj->flags & NVOBJ_FLAG_HEAP) { - ret = nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); - if (ret) - return ret; - } +static const struct nvkm_gpuobj_func +nvkm_gpuobj_slow = { + .release = nvkm_gpuobj_release, + .rd32 = nvkm_gpuobj_rd32, + .wr32 = nvkm_gpuobj_wr32, +}; - if (flags & NVOBJ_FLAG_ZERO_ALLOC) { - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, 0x00000000); +static void * +nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) +{ + gpuobj->map = nvkm_kmap(gpuobj->parent); + if (likely(gpuobj->map)) { + gpuobj->map = (u8 *)gpuobj->map + gpuobj->node->offset; + gpuobj->func = &nvkm_gpuobj_fast; + } else { + gpuobj->func = &nvkm_gpuobj_slow; } - - return ret; + return gpuobj->map; } -struct nvkm_gpuobj_class { - struct nvkm_object *pargpu; - u64 size; - u32 align; - u32 flags; +static const struct nvkm_gpuobj_func +nvkm_gpuobj_func = { + .acquire = nvkm_gpuobj_acquire, }; static int -_nvkm_gpuobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_gpuobj_ctor(struct nvkm_device *device, u32 size, int align, bool zero, + struct nvkm_gpuobj *parent, struct nvkm_gpuobj *gpuobj) { - struct nvkm_gpuobj_class *args = data; - struct nvkm_gpuobj *object; + u32 offset; int ret; - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, args->pargpu, - args->size, args->align, args->flags, - &object); - *pobject = nv_object(object); - if (ret) - return ret; + if (parent) { + if (align >= 0) { + ret = nvkm_mm_head(&parent->heap, 0, 1, size, size, + max(align, 1), &gpuobj->node); + } else { + ret = nvkm_mm_tail(&parent->heap, 0, 1, size, size, + -align, &gpuobj->node); + } + if (ret) + return ret; - return 0; -} + gpuobj->parent = parent; + gpuobj->func = &nvkm_gpuobj_func; + gpuobj->addr = parent->addr + gpuobj->node->offset; + gpuobj->size = gpuobj->node->length; -void -_nvkm_gpuobj_dtor(struct nvkm_object *object) -{ - nvkm_gpuobj_destroy(nv_gpuobj(object)); -} - -int -_nvkm_gpuobj_init(struct nvkm_object *object) -{ - return nvkm_gpuobj_init(nv_gpuobj(object)); -} + if (zero) { + nvkm_kmap(gpuobj); + for (offset = 0; offset < gpuobj->size; offset += 4) + nvkm_wo32(gpuobj, offset, 0x00000000); + nvkm_done(gpuobj); + } + } else { + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, + abs(align), zero, &gpuobj->memory); + if (ret) + return ret; -int -_nvkm_gpuobj_fini(struct nvkm_object *object, bool suspend) -{ - return nvkm_gpuobj_fini(nv_gpuobj(object), suspend); -} + gpuobj->func = &nvkm_gpuobj_heap; + gpuobj->addr = nvkm_memory_addr(gpuobj->memory); + gpuobj->size = nvkm_memory_size(gpuobj->memory); + } -u32 -_nvkm_gpuobj_rd32(struct nvkm_object *object, u64 addr) -{ - struct nvkm_gpuobj *gpuobj = nv_gpuobj(object); - struct nvkm_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent); - if (gpuobj->node) - addr += gpuobj->node->offset; - return pfuncs->rd32(gpuobj->parent, addr); + return nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); } void -_nvkm_gpuobj_wr32(struct nvkm_object *object, u64 addr, u32 data) +nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj) { - struct nvkm_gpuobj *gpuobj = nv_gpuobj(object); - struct nvkm_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent); - if (gpuobj->node) - addr += gpuobj->node->offset; - pfuncs->wr32(gpuobj->parent, addr, data); + struct nvkm_gpuobj *gpuobj = *pgpuobj; + if (gpuobj) { + if (gpuobj->parent) + nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); + nvkm_mm_fini(&gpuobj->heap); + nvkm_memory_del(&gpuobj->memory); + kfree(*pgpuobj); + *pgpuobj = NULL; + } } -static struct nvkm_oclass -_nvkm_gpuobj_oclass = { - .handle = 0x00000000, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_gpuobj_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, - }, -}; - int -nvkm_gpuobj_new(struct nvkm_object *parent, struct nvkm_object *pargpu, - u32 size, u32 align, u32 flags, - struct nvkm_gpuobj **pgpuobj) +nvkm_gpuobj_new(struct nvkm_device *device, u32 size, int align, bool zero, + struct nvkm_gpuobj *parent, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_object *engine = parent; - struct nvkm_gpuobj_class args = { - .pargpu = pargpu, - .size = size, - .align = align, - .flags = flags, - }; - - if (!nv_iclass(engine, NV_SUBDEV_CLASS)) - engine = &engine->engine->subdev.object; - BUG_ON(engine == NULL); - - return nvkm_object_ctor(parent, engine, &_nvkm_gpuobj_oclass, - &args, sizeof(args), - (struct nvkm_object **)pgpuobj); -} + struct nvkm_gpuobj *gpuobj; + int ret; -int -nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, u32 access, struct nvkm_vma *vma) -{ - struct nvkm_bar *bar = nvkm_bar(gpuobj); - int ret = -EINVAL; - - if (bar && bar->umap) { - struct nvkm_instobj *iobj = (void *) - nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); - struct nvkm_mem **mem = (void *)(iobj + 1); - ret = bar->umap(bar, *mem, access, vma); - } + if (!(gpuobj = *pgpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL))) + return -ENOMEM; + ret = nvkm_gpuobj_ctor(device, size, align, zero, parent, gpuobj); + if (ret) + nvkm_gpuobj_del(pgpuobj); return ret; } int -nvkm_gpuobj_map_vm(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, - u32 access, struct nvkm_vma *vma) +nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, + u32 access, struct nvkm_vma *vma) { - struct nvkm_instobj *iobj = (void *) - nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); - struct nvkm_mem **mem = (void *)(iobj + 1); - int ret; - - ret = nvkm_vm_get(vm, gpuobj->size, 12, access, vma); - if (ret) - return ret; - - nvkm_vm_map(vma, *mem); - return 0; + struct nvkm_memory *memory = gpuobj->memory; + int ret = nvkm_vm_get(vm, gpuobj->size, 12, access, vma); + if (ret == 0) + nvkm_memory_map(memory, vma, 0); + return ret; } void @@ -278,39 +243,13 @@ nvkm_gpuobj_unmap(struct nvkm_vma *vma) * anywhere else. */ -static void -nvkm_gpudup_dtor(struct nvkm_object *object) -{ - struct nvkm_gpuobj *gpuobj = (void *)object; - nvkm_object_ref(NULL, &gpuobj->parent); - nvkm_object_destroy(&gpuobj->object); -} - -static struct nvkm_oclass -nvkm_gpudup_oclass = { - .handle = NV_GPUOBJ_CLASS, - .ofuncs = &(struct nvkm_ofuncs) { - .dtor = nvkm_gpudup_dtor, - .init = nvkm_object_init, - .fini = nvkm_object_fini, - }, -}; - int -nvkm_gpuobj_dup(struct nvkm_object *parent, struct nvkm_gpuobj *base, - struct nvkm_gpuobj **pgpuobj) +nvkm_gpuobj_wrap(struct nvkm_memory *memory, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_gpuobj *gpuobj; - int ret; - - ret = nvkm_object_create(parent, &parent->engine->subdev.object, - &nvkm_gpudup_oclass, 0, &gpuobj); - *pgpuobj = gpuobj; - if (ret) - return ret; + if (!(*pgpuobj = kzalloc(sizeof(**pgpuobj), GFP_KERNEL))) + return -ENOMEM; - nvkm_object_ref(nv_object(base), &gpuobj->parent); - gpuobj->addr = base->addr; - gpuobj->size = base->size; + (*pgpuobj)->addr = nvkm_memory_addr(memory); + (*pgpuobj)->size = nvkm_memory_size(memory); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/handle.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/handle.c deleted file mode 100644 index dc7ff10eb..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/handle.c +++ /dev/null @@ -1,221 +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 -#include - -#define hprintk(h,l,f,a...) do { \ - struct nvkm_client *c = nvkm_client((h)->object); \ - struct nvkm_handle *p = (h)->parent; u32 n = p ? p->name : ~0; \ - nv_printk((c), l, "0x%08x:0x%08x "f, n, (h)->name, ##a); \ -} while(0) - -int -nvkm_handle_init(struct nvkm_handle *handle) -{ - struct nvkm_handle *item; - int ret; - - hprintk(handle, TRACE, "init running\n"); - ret = nvkm_object_inc(handle->object); - if (ret) - return ret; - - hprintk(handle, TRACE, "init children\n"); - list_for_each_entry(item, &handle->tree, head) { - ret = nvkm_handle_init(item); - if (ret) - goto fail; - } - - hprintk(handle, TRACE, "init completed\n"); - return 0; -fail: - hprintk(handle, ERROR, "init failed with %d\n", ret); - list_for_each_entry_continue_reverse(item, &handle->tree, head) { - nvkm_handle_fini(item, false); - } - - nvkm_object_dec(handle->object, false); - return ret; -} - -int -nvkm_handle_fini(struct nvkm_handle *handle, bool suspend) -{ - static char *name[2] = { "fini", "suspend" }; - struct nvkm_handle *item; - int ret; - - hprintk(handle, TRACE, "%s children\n", name[suspend]); - list_for_each_entry(item, &handle->tree, head) { - ret = nvkm_handle_fini(item, suspend); - if (ret && suspend) - goto fail; - } - - hprintk(handle, TRACE, "%s running\n", name[suspend]); - if (handle->object) { - ret = nvkm_object_dec(handle->object, suspend); - if (ret && suspend) - goto fail; - } - - hprintk(handle, TRACE, "%s completed\n", name[suspend]); - return 0; -fail: - hprintk(handle, ERROR, "%s failed with %d\n", name[suspend], ret); - list_for_each_entry_continue_reverse(item, &handle->tree, head) { - int rret = nvkm_handle_init(item); - if (rret) - hprintk(handle, FATAL, "failed to restart, %d\n", rret); - } - - return ret; -} - -int -nvkm_handle_create(struct nvkm_object *parent, u32 _parent, u32 _handle, - struct nvkm_object *object, struct nvkm_handle **phandle) -{ - struct nvkm_object *namedb; - struct nvkm_handle *handle; - int ret; - - namedb = parent; - while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) - namedb = namedb->parent; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - INIT_LIST_HEAD(&handle->head); - INIT_LIST_HEAD(&handle->tree); - handle->name = _handle; - handle->priv = ~0; - - ret = nvkm_namedb_insert(nv_namedb(namedb), _handle, object, handle); - if (ret) { - kfree(handle); - return ret; - } - - if (nv_parent(parent)->object_attach) { - ret = nv_parent(parent)->object_attach(parent, object, _handle); - if (ret < 0) { - nvkm_handle_destroy(handle); - return ret; - } - - handle->priv = ret; - } - - if (object != namedb) { - while (!nv_iclass(namedb, NV_CLIENT_CLASS)) - namedb = namedb->parent; - - handle->parent = nvkm_namedb_get(nv_namedb(namedb), _parent); - if (handle->parent) { - list_add(&handle->head, &handle->parent->tree); - nvkm_namedb_put(handle->parent); - } - } - - hprintk(handle, TRACE, "created\n"); - *phandle = handle; - return 0; -} - -void -nvkm_handle_destroy(struct nvkm_handle *handle) -{ - struct nvkm_handle *item, *temp; - - hprintk(handle, TRACE, "destroy running\n"); - list_for_each_entry_safe(item, temp, &handle->tree, head) { - nvkm_handle_destroy(item); - } - list_del(&handle->head); - - if (handle->priv != ~0) { - struct nvkm_object *parent = handle->parent->object; - nv_parent(parent)->object_detach(parent, handle->priv); - } - - hprintk(handle, TRACE, "destroy completed\n"); - nvkm_namedb_remove(handle); - kfree(handle); -} - -struct nvkm_object * -nvkm_handle_ref(struct nvkm_object *parent, u32 name) -{ - struct nvkm_object *object = NULL; - struct nvkm_handle *handle; - - while (!nv_iclass(parent, NV_NAMEDB_CLASS)) - parent = parent->parent; - - handle = nvkm_namedb_get(nv_namedb(parent), name); - if (handle) { - nvkm_object_ref(handle->object, &object); - nvkm_namedb_put(handle); - } - - return object; -} - -struct nvkm_handle * -nvkm_handle_get_class(struct nvkm_object *engctx, u16 oclass) -{ - struct nvkm_namedb *namedb; - if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) - return nvkm_namedb_get_class(namedb, oclass); - return NULL; -} - -struct nvkm_handle * -nvkm_handle_get_vinst(struct nvkm_object *engctx, u64 vinst) -{ - struct nvkm_namedb *namedb; - if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) - return nvkm_namedb_get_vinst(namedb, vinst); - return NULL; -} - -struct nvkm_handle * -nvkm_handle_get_cinst(struct nvkm_object *engctx, u32 cinst) -{ - struct nvkm_namedb *namedb; - if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) - return nvkm_namedb_get_cinst(namedb, cinst); - return NULL; -} - -void -nvkm_handle_put(struct nvkm_handle *handle) -{ - if (handle) - nvkm_namedb_put(handle); -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index 4459ff5f4..d87d6ab03 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -24,196 +24,154 @@ #include #include #include -#include -#include #include #include static int -nvkm_ioctl_nop(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_nop(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { - struct nvif_ioctl_nop none; + struct nvif_ioctl_nop_v0 v0; } *args = data; int ret; - nv_ioctl(object, "nop size %d\n", size); - if (nvif_unvers(args->none)) { - nv_ioctl(object, "nop\n"); + nvif_ioctl(object, "nop size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "nop vers %lld\n", args->v0.version); + args->v0.version = NVIF_VERSION_LATEST; } return ret; } static int -nvkm_ioctl_sclass(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_sclass(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_sclass_v0 v0; } *args = data; - int ret; + struct nvkm_oclass oclass; + int ret, i = 0; - if (!nv_iclass(object, NV_PARENT_CLASS)) { - nv_debug(object, "cannot have children (sclass)\n"); - return -ENODEV; - } - - nv_ioctl(object, "sclass size %d\n", size); + nvif_ioctl(object, "sclass size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "sclass vers %d count %d\n", - args->v0.version, args->v0.count); - if (size == args->v0.count * sizeof(args->v0.oclass[0])) { - ret = nvkm_parent_lclass(object, args->v0.oclass, - args->v0.count); - if (ret >= 0) { - args->v0.count = ret; - ret = 0; + nvif_ioctl(object, "sclass vers %d count %d\n", + args->v0.version, args->v0.count); + if (size != args->v0.count * sizeof(args->v0.oclass[0])) + return -EINVAL; + + while (object->func->sclass && + object->func->sclass(object, i, &oclass) >= 0) { + if (i < args->v0.count) { + args->v0.oclass[i].oclass = oclass.base.oclass; + args->v0.oclass[i].minver = oclass.base.minver; + args->v0.oclass[i].maxver = oclass.base.maxver; } - } else { - ret = -EINVAL; + i++; } + + args->v0.count = i; } return ret; } static int -nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_new(struct nvkm_object *parent, void *data, u32 size) { union { struct nvif_ioctl_new_v0 v0; } *args = data; - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *engctx = NULL; + struct nvkm_client *client = parent->client; struct nvkm_object *object = NULL; - struct nvkm_parent *parent; - struct nvkm_object *engine; - struct nvkm_oclass *oclass; - u32 _handle, _oclass; - int ret; + struct nvkm_oclass oclass; + int ret, i = 0; - nv_ioctl(client, "new size %d\n", size); + nvif_ioctl(parent, "new size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - _handle = args->v0.handle; - _oclass = args->v0.oclass; + nvif_ioctl(parent, "new vers %d handle %08x class %08x " + "route %02x token %llx object %016llx\n", + args->v0.version, args->v0.handle, args->v0.oclass, + args->v0.route, args->v0.token, args->v0.object); } else return ret; - nv_ioctl(client, "new vers %d handle %08x class %08x " - "route %02x token %llx\n", - args->v0.version, _handle, _oclass, - args->v0.route, args->v0.token); - - if (!nv_iclass(handle->object, NV_PARENT_CLASS)) { - nv_debug(handle->object, "cannot have children (ctor)\n"); - ret = -ENODEV; - goto fail_class; + if (!parent->func->sclass) { + nvif_ioctl(parent, "cannot have children\n"); + return -EINVAL; } - parent = nv_parent(handle->object); - - /* check that parent supports the requested subclass */ - ret = nvkm_parent_sclass(&parent->object, _oclass, &engine, &oclass); - if (ret) { - nv_debug(parent, "illegal class 0x%04x\n", _oclass); - goto fail_class; - } - - /* make sure engine init has been completed *before* any objects - * it controls are created - the constructors may depend on - * state calculated at init (ie. default context construction) - */ - if (engine) { - ret = nvkm_object_inc(engine); + do { + memset(&oclass, 0x00, sizeof(oclass)); + oclass.client = client; + oclass.handle = args->v0.handle; + oclass.object = args->v0.object; + oclass.parent = parent; + ret = parent->func->sclass(parent, i++, &oclass); if (ret) - goto fail_class; + return ret; + } while (oclass.base.oclass != args->v0.oclass); + + if (oclass.engine) { + oclass.engine = nvkm_engine_ref(oclass.engine); + if (IS_ERR(oclass.engine)) + return PTR_ERR(oclass.engine); } - /* if engine requires it, create a context object to insert - * between the parent and its children (eg. PGRAPH context) - */ - if (engine && nv_engine(engine)->cclass) { - ret = nvkm_object_ctor(&parent->object, engine, - nv_engine(engine)->cclass, - data, size, &engctx); - if (ret) - goto fail_engctx; - } else { - nvkm_object_ref(&parent->object, &engctx); + ret = oclass.ctor(&oclass, data, size, &object); + nvkm_engine_unref(&oclass.engine); + if (ret == 0) { + ret = nvkm_object_init(object); + if (ret == 0) { + list_add(&object->head, &parent->tree); + object->route = args->v0.route; + object->token = args->v0.token; + object->object = args->v0.object; + if (nvkm_client_insert(client, object)) { + client->data = object; + return 0; + } + ret = -EEXIST; + } + nvkm_object_fini(object, false); } - /* finally, create new object and bind it to its handle */ - ret = nvkm_object_ctor(engctx, engine, oclass, data, size, &object); - client->data = object; - if (ret) - goto fail_ctor; - - ret = nvkm_object_inc(object); - if (ret) - goto fail_init; - - ret = nvkm_handle_create(&parent->object, handle->name, - _handle, object, &handle); - if (ret) - goto fail_handle; - - ret = nvkm_handle_init(handle); - handle->route = args->v0.route; - handle->token = args->v0.token; - if (ret) - nvkm_handle_destroy(handle); - -fail_handle: - nvkm_object_dec(object, false); -fail_init: - nvkm_object_ref(NULL, &object); -fail_ctor: - nvkm_object_ref(NULL, &engctx); -fail_engctx: - if (engine) - nvkm_object_dec(engine, false); -fail_class: + nvkm_object_del(&object); return ret; } static int -nvkm_ioctl_del(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_del(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_del none; } *args = data; int ret; - nv_ioctl(object, "delete size %d\n", size); + nvif_ioctl(object, "delete size %d\n", size); if (nvif_unvers(args->none)) { - nv_ioctl(object, "delete\n"); - nvkm_handle_fini(handle, false); - nvkm_handle_destroy(handle); + nvif_ioctl(object, "delete\n"); + nvkm_object_fini(object, false); + nvkm_object_del(&object); } return ret; } static int -nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_mthd(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; - struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs; union { struct nvif_ioctl_mthd_v0 v0; } *args = data; int ret; - nv_ioctl(object, "mthd size %d\n", size); + nvif_ioctl(object, "mthd size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "mthd vers %d mthd %02x\n", - args->v0.version, args->v0.method); - if (ret = -ENODEV, ofuncs->mthd) - ret = ofuncs->mthd(object, args->v0.method, data, size); + nvif_ioctl(object, "mthd vers %d mthd %02x\n", + args->v0.version, args->v0.method); + ret = nvkm_object_mthd(object, args->v0.method, data, size); } return ret; @@ -221,37 +179,34 @@ nvkm_ioctl_mthd(struct nvkm_handle *handle, void *data, u32 size) static int -nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_rd(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; - struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs; union { struct nvif_ioctl_rd_v0 v0; } *args = data; + union { + u8 b08; + u16 b16; + u32 b32; + } v; int ret; - nv_ioctl(object, "rd size %d\n", size); + nvif_ioctl(object, "rd size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "rd vers %d size %d addr %016llx\n", - args->v0.version, args->v0.size, args->v0.addr); + nvif_ioctl(object, "rd vers %d size %d addr %016llx\n", + args->v0.version, args->v0.size, args->v0.addr); switch (args->v0.size) { case 1: - if (ret = -ENODEV, ofuncs->rd08) { - args->v0.data = nv_ro08(object, args->v0.addr); - ret = 0; - } + ret = nvkm_object_rd08(object, args->v0.addr, &v.b08); + args->v0.data = v.b08; break; case 2: - if (ret = -ENODEV, ofuncs->rd16) { - args->v0.data = nv_ro16(object, args->v0.addr); - ret = 0; - } + ret = nvkm_object_rd16(object, args->v0.addr, &v.b16); + args->v0.data = v.b16; break; case 4: - if (ret = -ENODEV, ofuncs->rd32) { - args->v0.data = nv_ro32(object, args->v0.addr); - ret = 0; - } + ret = nvkm_object_rd32(object, args->v0.addr, &v.b32); + args->v0.data = v.b32; break; default: ret = -EINVAL; @@ -263,104 +218,81 @@ nvkm_ioctl_rd(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_wr(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_wr(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; - struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs; union { struct nvif_ioctl_wr_v0 v0; } *args = data; int ret; - nv_ioctl(object, "wr size %d\n", size); + nvif_ioctl(object, "wr size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "wr vers %d size %d addr %016llx data %08x\n", - args->v0.version, args->v0.size, args->v0.addr, - args->v0.data); - switch (args->v0.size) { - case 1: - if (ret = -ENODEV, ofuncs->wr08) { - nv_wo08(object, args->v0.addr, args->v0.data); - ret = 0; - } - break; - case 2: - if (ret = -ENODEV, ofuncs->wr16) { - nv_wo16(object, args->v0.addr, args->v0.data); - ret = 0; - } - break; - case 4: - if (ret = -ENODEV, ofuncs->wr32) { - nv_wo32(object, args->v0.addr, args->v0.data); - ret = 0; - } - break; - default: - ret = -EINVAL; - break; - } + nvif_ioctl(object, + "wr vers %d size %d addr %016llx data %08x\n", + args->v0.version, args->v0.size, args->v0.addr, + args->v0.data); + } else + return ret; + + switch (args->v0.size) { + case 1: return nvkm_object_wr08(object, args->v0.addr, args->v0.data); + case 2: return nvkm_object_wr16(object, args->v0.addr, args->v0.data); + case 4: return nvkm_object_wr32(object, args->v0.addr, args->v0.data); + default: + break; } - return ret; + return -EINVAL; } static int -nvkm_ioctl_map(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_map(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; - struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs; union { struct nvif_ioctl_map_v0 v0; } *args = data; int ret; - nv_ioctl(object, "map size %d\n", size); + nvif_ioctl(object, "map size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "map vers %d\n", args->v0.version); - if (ret = -ENODEV, ofuncs->map) { - ret = ofuncs->map(object, &args->v0.handle, - &args->v0.length); - } + nvif_ioctl(object, "map vers %d\n", args->v0.version); + ret = nvkm_object_map(object, &args->v0.handle, + &args->v0.length); } return ret; } static int -nvkm_ioctl_unmap(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_unmap(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; union { struct nvif_ioctl_unmap none; } *args = data; int ret; - nv_ioctl(object, "unmap size %d\n", size); + nvif_ioctl(object, "unmap size %d\n", size); if (nvif_unvers(args->none)) { - nv_ioctl(object, "unmap\n"); + nvif_ioctl(object, "unmap\n"); } return ret; } static int -nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_new(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_object *object = handle->object; - struct nvkm_ofuncs *ofuncs = object->oclass->ofuncs; union { struct nvif_ioctl_ntfy_new_v0 v0; } *args = data; struct nvkm_event *event; int ret; - nv_ioctl(object, "ntfy new size %d\n", size); + nvif_ioctl(object, "ntfy new size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "ntfy new vers %d event %02x\n", - args->v0.version, args->v0.event); - if (ret = -ENODEV, ofuncs->ntfy) - ret = ofuncs->ntfy(object, args->v0.event, &event); + nvif_ioctl(object, "ntfy new vers %d event %02x\n", + args->v0.version, args->v0.event); + ret = nvkm_object_ntfy(object, args->v0.event, &event); if (ret == 0) { ret = nvkm_client_notify_new(object, event, data, size); if (ret >= 0) { @@ -374,19 +306,18 @@ nvkm_ioctl_ntfy_new(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_del(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *object = handle->object; + struct nvkm_client *client = object->client; union { struct nvif_ioctl_ntfy_del_v0 v0; } *args = data; int ret; - nv_ioctl(object, "ntfy del size %d\n", size); + nvif_ioctl(object, "ntfy del size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "ntfy del vers %d index %d\n", - args->v0.version, args->v0.index); + nvif_ioctl(object, "ntfy del vers %d index %d\n", + args->v0.version, args->v0.index); ret = nvkm_client_notify_del(client, args->v0.index); } @@ -394,19 +325,18 @@ nvkm_ioctl_ntfy_del(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_get(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *object = handle->object; + struct nvkm_client *client = object->client; union { struct nvif_ioctl_ntfy_get_v0 v0; } *args = data; int ret; - nv_ioctl(object, "ntfy get size %d\n", size); + nvif_ioctl(object, "ntfy get size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "ntfy get vers %d index %d\n", - args->v0.version, args->v0.index); + nvif_ioctl(object, "ntfy get vers %d index %d\n", + args->v0.version, args->v0.index); ret = nvkm_client_notify_get(client, args->v0.index); } @@ -414,19 +344,18 @@ nvkm_ioctl_ntfy_get(struct nvkm_handle *handle, void *data, u32 size) } static int -nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size) +nvkm_ioctl_ntfy_put(struct nvkm_object *object, void *data, u32 size) { - struct nvkm_client *client = nvkm_client(handle->object); - struct nvkm_object *object = handle->object; + struct nvkm_client *client = object->client; union { struct nvif_ioctl_ntfy_put_v0 v0; } *args = data; int ret; - nv_ioctl(object, "ntfy put size %d\n", size); + nvif_ioctl(object, "ntfy put size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "ntfy put vers %d index %d\n", - args->v0.version, args->v0.index); + nvif_ioctl(object, "ntfy put vers %d index %d\n", + args->v0.version, args->v0.index); ret = nvkm_client_notify_put(client, args->v0.index); } @@ -435,7 +364,7 @@ nvkm_ioctl_ntfy_put(struct nvkm_handle *handle, void *data, u32 size) static struct { int version; - int (*func)(struct nvkm_handle *, void *, u32); + int (*func)(struct nvkm_object *, void *, u32); } nvkm_ioctl_v0[] = { { 0x00, nvkm_ioctl_nop }, @@ -454,40 +383,31 @@ nvkm_ioctl_v0[] = { }; static int -nvkm_ioctl_path(struct nvkm_handle *parent, u32 type, u32 nr, u32 *path, +nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type, void *data, u32 size, u8 owner, u8 *route, u64 *token) { - struct nvkm_handle *handle = parent; - struct nvkm_namedb *namedb; struct nvkm_object *object; int ret; - while ((object = parent->object), nr--) { - nv_ioctl(object, "path 0x%08x\n", path[nr]); - if (!nv_iclass(object, NV_PARENT_CLASS)) { - nv_debug(object, "cannot have children (path)\n"); - return -EINVAL; - } - - if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) || - !(handle = nvkm_namedb_get(namedb, path[nr]))) { - nv_debug(object, "handle 0x%08x not found\n", path[nr]); - return -ENOENT; - } - nvkm_namedb_put(handle); - parent = handle; + if (handle) + object = nvkm_client_search(client, handle); + else + object = &client->object; + if (unlikely(!object)) { + nvif_ioctl(&client->object, "object not found\n"); + return -ENOENT; } - if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != handle->route) { - nv_ioctl(object, "object route != owner\n"); + if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != object->route) { + nvif_ioctl(&client->object, "route != owner\n"); return -EACCES; } - *route = handle->route; - *token = handle->token; + *route = object->route; + *token = object->token; if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) { if (nvkm_ioctl_v0[type].version == 0) - ret = nvkm_ioctl_v0[type].func(handle, data, size); + ret = nvkm_ioctl_v0[type].func(object, data, size); } return ret; @@ -497,25 +417,26 @@ int nvkm_ioctl(struct nvkm_client *client, bool supervisor, void *data, u32 size, void **hack) { + struct nvkm_object *object = &client->object; union { struct nvif_ioctl_v0 v0; } *args = data; int ret; client->super = supervisor; - nv_ioctl(client, "size %d\n", size); + nvif_ioctl(object, "size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(client, "vers %d type %02x path %d owner %02x\n", - args->v0.version, args->v0.type, args->v0.path_nr, - args->v0.owner); - ret = nvkm_ioctl_path(client->root, args->v0.type, - args->v0.path_nr, args->v0.path, + nvif_ioctl(object, + "vers %d type %02x object %016llx owner %02x\n", + args->v0.version, args->v0.type, args->v0.object, + args->v0.owner); + ret = nvkm_ioctl_path(client, args->v0.object, args->v0.type, data, size, args->v0.owner, &args->v0.route, &args->v0.token); } - nv_ioctl(client, "return %d\n", ret); + nvif_ioctl(object, "return %d\n", ret); if (hack) { *hack = client->data; client->data = NULL; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/memory.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/memory.c new file mode 100644 index 000000000..8903c04c9 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/memory.c @@ -0,0 +1,64 @@ +/* + * 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 + */ +#include +#include + +void +nvkm_memory_ctor(const struct nvkm_memory_func *func, + struct nvkm_memory *memory) +{ + memory->func = func; +} + +void +nvkm_memory_del(struct nvkm_memory **pmemory) +{ + struct nvkm_memory *memory = *pmemory; + if (memory && !WARN_ON(!memory->func)) { + if (memory->func->dtor) + *pmemory = memory->func->dtor(memory); + kfree(*pmemory); + *pmemory = NULL; + } +} + +int +nvkm_memory_new(struct nvkm_device *device, enum nvkm_memory_target target, + u64 size, u32 align, bool zero, + struct nvkm_memory **pmemory) +{ + struct nvkm_instmem *imem = device->imem; + struct nvkm_memory *memory; + int ret = -ENOSYS; + + if (unlikely(target != NVKM_MEM_TARGET_INST || !imem)) + return -ENOSYS; + + ret = nvkm_instobj_new(imem, size, align, zero, &memory); + if (ret) + return ret; + + *pmemory = memory; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/mm.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/mm.c index 7f458dfd5..09a1eee8f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/mm.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/mm.c @@ -26,7 +26,7 @@ #define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ list_entry((root)->nl_entry.dir, struct nvkm_mm_node, nl_entry) -static void +void nvkm_mm_dump(struct nvkm_mm *mm, const char *header) { struct nvkm_mm_node *node; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/namedb.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/namedb.c deleted file mode 100644 index 6400767c5..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/namedb.c +++ /dev/null @@ -1,199 +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 -#include -#include - -static struct nvkm_handle * -nvkm_namedb_lookup(struct nvkm_namedb *namedb, u32 name) -{ - struct nvkm_handle *handle; - - list_for_each_entry(handle, &namedb->list, node) { - if (handle->name == name) - return handle; - } - - return NULL; -} - -static struct nvkm_handle * -nvkm_namedb_lookup_class(struct nvkm_namedb *namedb, u16 oclass) -{ - struct nvkm_handle *handle; - - list_for_each_entry(handle, &namedb->list, node) { - if (nv_mclass(handle->object) == oclass) - return handle; - } - - return NULL; -} - -static struct nvkm_handle * -nvkm_namedb_lookup_vinst(struct nvkm_namedb *namedb, u64 vinst) -{ - struct nvkm_handle *handle; - - list_for_each_entry(handle, &namedb->list, node) { - if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { - if (nv_gpuobj(handle->object)->addr == vinst) - return handle; - } - } - - return NULL; -} - -static struct nvkm_handle * -nvkm_namedb_lookup_cinst(struct nvkm_namedb *namedb, u32 cinst) -{ - struct nvkm_handle *handle; - - list_for_each_entry(handle, &namedb->list, node) { - if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { - if (nv_gpuobj(handle->object)->node && - nv_gpuobj(handle->object)->node->offset == cinst) - return handle; - } - } - - return NULL; -} - -int -nvkm_namedb_insert(struct nvkm_namedb *namedb, u32 name, - struct nvkm_object *object, - struct nvkm_handle *handle) -{ - int ret = -EEXIST; - write_lock_irq(&namedb->lock); - if (!nvkm_namedb_lookup(namedb, name)) { - nvkm_object_ref(object, &handle->object); - handle->namedb = namedb; - list_add(&handle->node, &namedb->list); - ret = 0; - } - write_unlock_irq(&namedb->lock); - return ret; -} - -void -nvkm_namedb_remove(struct nvkm_handle *handle) -{ - struct nvkm_namedb *namedb = handle->namedb; - struct nvkm_object *object = handle->object; - write_lock_irq(&namedb->lock); - list_del(&handle->node); - write_unlock_irq(&namedb->lock); - nvkm_object_ref(NULL, &object); -} - -struct nvkm_handle * -nvkm_namedb_get(struct nvkm_namedb *namedb, u32 name) -{ - struct nvkm_handle *handle; - read_lock(&namedb->lock); - handle = nvkm_namedb_lookup(namedb, name); - if (handle == NULL) - read_unlock(&namedb->lock); - return handle; -} - -struct nvkm_handle * -nvkm_namedb_get_class(struct nvkm_namedb *namedb, u16 oclass) -{ - struct nvkm_handle *handle; - read_lock(&namedb->lock); - handle = nvkm_namedb_lookup_class(namedb, oclass); - if (handle == NULL) - read_unlock(&namedb->lock); - return handle; -} - -struct nvkm_handle * -nvkm_namedb_get_vinst(struct nvkm_namedb *namedb, u64 vinst) -{ - struct nvkm_handle *handle; - read_lock(&namedb->lock); - handle = nvkm_namedb_lookup_vinst(namedb, vinst); - if (handle == NULL) - read_unlock(&namedb->lock); - return handle; -} - -struct nvkm_handle * -nvkm_namedb_get_cinst(struct nvkm_namedb *namedb, u32 cinst) -{ - struct nvkm_handle *handle; - read_lock(&namedb->lock); - handle = nvkm_namedb_lookup_cinst(namedb, cinst); - if (handle == NULL) - read_unlock(&namedb->lock); - return handle; -} - -void -nvkm_namedb_put(struct nvkm_handle *handle) -{ - if (handle) - read_unlock(&handle->namedb->lock); -} - -int -nvkm_namedb_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 pclass, - struct nvkm_oclass *sclass, u64 engcls, - int length, void **pobject) -{ - struct nvkm_namedb *namedb; - int ret; - - ret = nvkm_parent_create_(parent, engine, oclass, pclass | - NV_NAMEDB_CLASS, sclass, engcls, - length, pobject); - namedb = *pobject; - if (ret) - return ret; - - rwlock_init(&namedb->lock); - INIT_LIST_HEAD(&namedb->list); - return 0; -} - -int -_nvkm_namedb_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_namedb *object; - int ret; - - ret = nvkm_namedb_create(parent, engine, oclass, 0, NULL, 0, &object); - *pobject = nv_object(object); - if (ret) - return ret; - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/object.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/object.c index 979f3627d..67aa7223d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -22,309 +22,243 @@ * Authors: Ben Skeggs */ #include +#include #include -#ifdef NVKM_OBJECT_MAGIC -static struct list_head _objlist = LIST_HEAD_INIT(_objlist); -static DEFINE_SPINLOCK(_objlist_lock); -#endif - int -nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 pclass, - int size, void **pobject) +nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { - struct nvkm_object *object; - - object = *pobject = kzalloc(size, GFP_KERNEL); - if (!object) - return -ENOMEM; - - nvkm_object_ref(parent, &object->parent); - nvkm_object_ref(engine, (struct nvkm_object **)&object->engine); - object->oclass = oclass; - object->oclass->handle |= pclass; - atomic_set(&object->refcount, 1); - atomic_set(&object->usecount, 0); - -#ifdef NVKM_OBJECT_MAGIC - object->_magic = NVKM_OBJECT_MAGIC; - spin_lock(&_objlist_lock); - list_add(&object->list, &_objlist); - spin_unlock(&_objlist_lock); -#endif - return 0; + if (likely(object->func->mthd)) + return object->func->mthd(object, mthd, data, size); + return -ENODEV; } int -_nvkm_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_object_ntfy(struct nvkm_object *object, u32 mthd, + struct nvkm_event **pevent) { - if (size != 0) - return -ENOSYS; - return nvkm_object_create(parent, engine, oclass, 0, pobject); + if (likely(object->func->ntfy)) + return object->func->ntfy(object, mthd, pevent); + return -ENODEV; } -void -nvkm_object_destroy(struct nvkm_object *object) +int +nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size) { -#ifdef NVKM_OBJECT_MAGIC - spin_lock(&_objlist_lock); - list_del(&object->list); - spin_unlock(&_objlist_lock); -#endif - nvkm_object_ref(NULL, (struct nvkm_object **)&object->engine); - nvkm_object_ref(NULL, &object->parent); - kfree(object); + if (likely(object->func->map)) + return object->func->map(object, addr, size); + return -ENODEV; } int -nvkm_object_init(struct nvkm_object *object) +nvkm_object_rd08(struct nvkm_object *object, u64 addr, u8 *data) { - return 0; + if (likely(object->func->rd08)) + return object->func->rd08(object, addr, data); + return -ENODEV; } int -nvkm_object_fini(struct nvkm_object *object, bool suspend) +nvkm_object_rd16(struct nvkm_object *object, u64 addr, u16 *data) { - return 0; + if (likely(object->func->rd16)) + return object->func->rd16(object, addr, data); + return -ENODEV; } -struct nvkm_ofuncs -nvkm_object_ofuncs = { - .ctor = _nvkm_object_ctor, - .dtor = nvkm_object_destroy, - .init = nvkm_object_init, - .fini = nvkm_object_fini, -}; - int -nvkm_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_object_rd32(struct nvkm_object *object, u64 addr, u32 *data) { - struct nvkm_ofuncs *ofuncs = oclass->ofuncs; - struct nvkm_object *object = NULL; - int ret; - - ret = ofuncs->ctor(parent, engine, oclass, data, size, &object); - *pobject = object; - if (ret < 0) { - if (ret != -ENODEV) { - nv_error(parent, "failed to create 0x%08x, %d\n", - oclass->handle, ret); - } - - if (object) { - ofuncs->dtor(object); - *pobject = NULL; - } - - return ret; - } - - if (ret == 0) { - nv_trace(object, "created\n"); - atomic_set(&object->refcount, 1); - } - - return 0; + if (likely(object->func->rd32)) + return object->func->rd32(object, addr, data); + return -ENODEV; } -static void -nvkm_object_dtor(struct nvkm_object *object) +int +nvkm_object_wr08(struct nvkm_object *object, u64 addr, u8 data) { - nv_trace(object, "destroying\n"); - nv_ofuncs(object)->dtor(object); + if (likely(object->func->wr08)) + return object->func->wr08(object, addr, data); + return -ENODEV; } -void -nvkm_object_ref(struct nvkm_object *obj, struct nvkm_object **ref) +int +nvkm_object_wr16(struct nvkm_object *object, u64 addr, u16 data) { - if (obj) { - atomic_inc(&obj->refcount); - nv_trace(obj, "inc() == %d\n", atomic_read(&obj->refcount)); - } + if (likely(object->func->wr16)) + return object->func->wr16(object, addr, data); + return -ENODEV; +} - if (*ref) { - int dead = atomic_dec_and_test(&(*ref)->refcount); - nv_trace(*ref, "dec() == %d\n", atomic_read(&(*ref)->refcount)); - if (dead) - nvkm_object_dtor(*ref); - } +int +nvkm_object_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + if (likely(object->func->wr32)) + return object->func->wr32(object, addr, data); + return -ENODEV; +} - *ref = obj; +int +nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj, + int align, struct nvkm_gpuobj **pgpuobj) +{ + if (object->func->bind) + return object->func->bind(object, gpuobj, align, pgpuobj); + return -ENODEV; } int -nvkm_object_inc(struct nvkm_object *object) +nvkm_object_fini(struct nvkm_object *object, bool suspend) { - int ref = atomic_add_return(1, &object->usecount); + const char *action = suspend ? "suspend" : "fini"; + struct nvkm_object *child; + s64 time; int ret; - nv_trace(object, "use(+1) == %d\n", atomic_read(&object->usecount)); - if (ref != 1) - return 0; - - nv_trace(object, "initialising...\n"); - if (object->parent) { - ret = nvkm_object_inc(object->parent); - if (ret) { - nv_error(object, "parent failed, %d\n", ret); - goto fail_parent; - } + nvif_debug(object, "%s children...\n", action); + time = ktime_to_us(ktime_get()); + list_for_each_entry(child, &object->tree, head) { + ret = nvkm_object_fini(child, suspend); + if (ret && suspend) + goto fail_child; } - if (object->engine) { - mutex_lock(&nv_subdev(object->engine)->mutex); - ret = nvkm_object_inc(&object->engine->subdev.object); - mutex_unlock(&nv_subdev(object->engine)->mutex); + nvif_debug(object, "%s running...\n", action); + if (object->func->fini) { + ret = object->func->fini(object, suspend); if (ret) { - nv_error(object, "engine failed, %d\n", ret); - goto fail_engine; + nvif_error(object, "%s failed with %d\n", action, ret); + if (suspend) + goto fail; } } - ret = nv_ofuncs(object)->init(object); - atomic_set(&object->usecount, 1); - if (ret) { - nv_error(object, "init failed, %d\n", ret); - goto fail_self; - } - - nv_trace(object, "initialised\n"); + time = ktime_to_us(ktime_get()) - time; + nvif_debug(object, "%s completed in %lldus\n", action, time); return 0; -fail_self: - if (object->engine) { - mutex_lock(&nv_subdev(object->engine)->mutex); - nvkm_object_dec(&object->engine->subdev.object, false); - mutex_unlock(&nv_subdev(object->engine)->mutex); +fail: + if (object->func->init) { + int rret = object->func->init(object); + if (rret) + nvif_fatal(object, "failed to restart, %d\n", rret); + } +fail_child: + list_for_each_entry_continue_reverse(child, &object->tree, head) { + nvkm_object_init(child); } -fail_engine: - if (object->parent) - nvkm_object_dec(object->parent, false); -fail_parent: - atomic_dec(&object->usecount); return ret; } -static int -nvkm_object_decf(struct nvkm_object *object) +int +nvkm_object_init(struct nvkm_object *object) { + struct nvkm_object *child; + s64 time; int ret; - nv_trace(object, "stopping...\n"); - - ret = nv_ofuncs(object)->fini(object, false); - atomic_set(&object->usecount, 0); - if (ret) - nv_warn(object, "failed fini, %d\n", ret); - - if (object->engine) { - mutex_lock(&nv_subdev(object->engine)->mutex); - nvkm_object_dec(&object->engine->subdev.object, false); - mutex_unlock(&nv_subdev(object->engine)->mutex); + nvif_debug(object, "init running...\n"); + time = ktime_to_us(ktime_get()); + if (object->func->init) { + ret = object->func->init(object); + if (ret) + goto fail; } - if (object->parent) - nvkm_object_dec(object->parent, false); + nvif_debug(object, "init children...\n"); + list_for_each_entry(child, &object->tree, head) { + ret = nvkm_object_init(child); + if (ret) + goto fail_child; + } - nv_trace(object, "stopped\n"); + time = ktime_to_us(ktime_get()) - time; + nvif_debug(object, "init completed in %lldus\n", time); return 0; + +fail_child: + list_for_each_entry_continue_reverse(child, &object->tree, head) + nvkm_object_fini(child, false); +fail: + nvif_error(object, "init failed with %d\n", ret); + if (object->func->fini) + object->func->fini(object, false); + return ret; } -static int -nvkm_object_decs(struct nvkm_object *object) +void * +nvkm_object_dtor(struct nvkm_object *object) { - int ret, rret; - - nv_trace(object, "suspending...\n"); - - ret = nv_ofuncs(object)->fini(object, true); - atomic_set(&object->usecount, 0); - if (ret) { - nv_error(object, "failed suspend, %d\n", ret); - return ret; + struct nvkm_object *child, *ctemp; + void *data = object; + s64 time; + + nvif_debug(object, "destroy children...\n"); + time = ktime_to_us(ktime_get()); + list_for_each_entry_safe(child, ctemp, &object->tree, head) { + nvkm_object_del(&child); } - if (object->engine) { - mutex_lock(&nv_subdev(object->engine)->mutex); - ret = nvkm_object_dec(&object->engine->subdev.object, true); - mutex_unlock(&nv_subdev(object->engine)->mutex); - if (ret) { - nv_warn(object, "engine failed suspend, %d\n", ret); - goto fail_engine; - } - } - - if (object->parent) { - ret = nvkm_object_dec(object->parent, true); - if (ret) { - nv_warn(object, "parent failed suspend, %d\n", ret); - goto fail_parent; - } - } - - nv_trace(object, "suspended\n"); - return 0; + nvif_debug(object, "destroy running...\n"); + if (object->func->dtor) + data = object->func->dtor(object); + nvkm_engine_unref(&object->engine); + time = ktime_to_us(ktime_get()) - time; + nvif_debug(object, "destroy completed in %lldus...\n", time); + return data; +} -fail_parent: - if (object->engine) { - mutex_lock(&nv_subdev(object->engine)->mutex); - rret = nvkm_object_inc(&object->engine->subdev.object); - mutex_unlock(&nv_subdev(object->engine)->mutex); - if (rret) - nv_fatal(object, "engine failed to reinit, %d\n", rret); +void +nvkm_object_del(struct nvkm_object **pobject) +{ + struct nvkm_object *object = *pobject; + if (object && !WARN_ON(!object->func)) { + *pobject = nvkm_object_dtor(object); + nvkm_client_remove(object->client, object); + list_del(&object->head); + kfree(*pobject); + *pobject = NULL; } +} -fail_engine: - rret = nv_ofuncs(object)->init(object); - if (rret) - nv_fatal(object, "failed to reinit, %d\n", rret); - - return ret; +void +nvkm_object_ctor(const struct nvkm_object_func *func, + const struct nvkm_oclass *oclass, struct nvkm_object *object) +{ + object->func = func; + object->client = oclass->client; + object->engine = nvkm_engine_ref(oclass->engine); + object->oclass = oclass->base.oclass; + object->handle = oclass->handle; + INIT_LIST_HEAD(&object->head); + INIT_LIST_HEAD(&object->tree); + RB_CLEAR_NODE(&object->node); + WARN_ON(oclass->engine && !object->engine); } int -nvkm_object_dec(struct nvkm_object *object, bool suspend) +nvkm_object_new_(const struct nvkm_object_func *func, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) { - int ref = atomic_add_return(-1, &object->usecount); - int ret; - - nv_trace(object, "use(-1) == %d\n", atomic_read(&object->usecount)); - - if (ref == 0) { - if (suspend) - ret = nvkm_object_decs(object); - else - ret = nvkm_object_decf(object); - - if (ret) { - atomic_inc(&object->usecount); - return ret; - } + if (size == 0) { + if (!(*pobject = kzalloc(sizeof(**pobject), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(func, oclass, *pobject); + return 0; } - - return 0; + return -ENOSYS; } -void -nvkm_object_debug(void) +static const struct nvkm_object_func +nvkm_object_func = { +}; + +int +nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) { -#ifdef NVKM_OBJECT_MAGIC - struct nvkm_object *object; - if (!list_empty(&_objlist)) { - nv_fatal(NULL, "*******************************************\n"); - nv_fatal(NULL, "* AIIIII! object(s) still exist!!!\n"); - nv_fatal(NULL, "*******************************************\n"); - list_for_each_entry(object, &_objlist, list) { - nv_fatal(object, "%p/%p/%d/%d\n", - object->parent, object->engine, - atomic_read(&object->refcount), - atomic_read(&object->usecount)); - } - } -#endif + const struct nvkm_object_func *func = + oclass->base.func ? oclass->base.func : &nvkm_object_func; + return nvkm_object_new_(func, oclass, data, size, pobject); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c new file mode 100644 index 000000000..e31a0479a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -0,0 +1,200 @@ +/* + * 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 + */ +#include + +static int +nvkm_oproxy_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + return nvkm_object_mthd(nvkm_oproxy(object)->object, mthd, data, size); +} + +static int +nvkm_oproxy_ntfy(struct nvkm_object *object, u32 mthd, + struct nvkm_event **pevent) +{ + return nvkm_object_ntfy(nvkm_oproxy(object)->object, mthd, pevent); +} + +static int +nvkm_oproxy_map(struct nvkm_object *object, u64 *addr, u32 *size) +{ + return nvkm_object_map(nvkm_oproxy(object)->object, addr, size); +} + +static int +nvkm_oproxy_rd08(struct nvkm_object *object, u64 addr, u8 *data) +{ + return nvkm_object_rd08(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_rd16(struct nvkm_object *object, u64 addr, u16 *data) +{ + return nvkm_object_rd16(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + return nvkm_object_rd32(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_wr08(struct nvkm_object *object, u64 addr, u8 data) +{ + return nvkm_object_wr08(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_wr16(struct nvkm_object *object, u64 addr, u16 data) +{ + return nvkm_object_wr16(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + return nvkm_object_wr32(nvkm_oproxy(object)->object, addr, data); +} + +static int +nvkm_oproxy_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + return nvkm_object_bind(nvkm_oproxy(object)->object, + parent, align, pgpuobj); +} + +static int +nvkm_oproxy_sclass(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + oclass->parent = oproxy->object; + if (!oproxy->object->func->sclass) + return -ENODEV; + return oproxy->object->func->sclass(oproxy->object, index, oclass); +} + +static int +nvkm_oproxy_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + int ret; + + if (oproxy->func->fini[0]) { + ret = oproxy->func->fini[0](oproxy, suspend); + if (ret && suspend) + return ret; + } + + if (oproxy->object->func->fini) { + ret = oproxy->object->func->fini(oproxy->object, suspend); + if (ret && suspend) + return ret; + } + + if (oproxy->func->fini[1]) { + ret = oproxy->func->fini[1](oproxy, suspend); + if (ret && suspend) + return ret; + } + + return 0; +} + +static int +nvkm_oproxy_init(struct nvkm_object *object) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + int ret; + + if (oproxy->func->init[0]) { + ret = oproxy->func->init[0](oproxy); + if (ret) + return ret; + } + + if (oproxy->object->func->init) { + ret = oproxy->object->func->init(oproxy->object); + if (ret) + return ret; + } + + if (oproxy->func->init[1]) { + ret = oproxy->func->init[1](oproxy); + if (ret) + return ret; + } + + return 0; +} + +static void * +nvkm_oproxy_dtor(struct nvkm_object *object) +{ + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + if (oproxy->func->dtor[0]) + oproxy->func->dtor[0](oproxy); + nvkm_object_del(&oproxy->object); + if (oproxy->func->dtor[1]) + oproxy->func->dtor[1](oproxy); + return oproxy; +} + +static const struct nvkm_object_func +nvkm_oproxy_func = { + .dtor = nvkm_oproxy_dtor, + .init = nvkm_oproxy_init, + .fini = nvkm_oproxy_fini, + .mthd = nvkm_oproxy_mthd, + .ntfy = nvkm_oproxy_ntfy, + .map = nvkm_oproxy_map, + .rd08 = nvkm_oproxy_rd08, + .rd16 = nvkm_oproxy_rd16, + .rd32 = nvkm_oproxy_rd32, + .wr08 = nvkm_oproxy_wr08, + .wr16 = nvkm_oproxy_wr16, + .wr32 = nvkm_oproxy_wr32, + .bind = nvkm_oproxy_bind, + .sclass = nvkm_oproxy_sclass, +}; + +void +nvkm_oproxy_ctor(const struct nvkm_oproxy_func *func, + const struct nvkm_oclass *oclass, struct nvkm_oproxy *oproxy) +{ + nvkm_object_ctor(&nvkm_oproxy_func, oclass, &oproxy->base); + oproxy->func = func; +} + +int +nvkm_oproxy_new_(const struct nvkm_oproxy_func *func, + const struct nvkm_oclass *oclass, struct nvkm_oproxy **poproxy) +{ + if (!(*poproxy = kzalloc(sizeof(**poproxy), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(func, oclass, *poproxy); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/option.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/option.c index 19d153f8c..3e62cf8cd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/option.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/option.c @@ -73,6 +73,24 @@ nvkm_boolopt(const char *optstr, const char *opt, bool value) return value; } +long +nvkm_longopt(const char *optstr, const char *opt, long value) +{ + long result = value; + int arglen; + char *s; + + optstr = nvkm_stropt(optstr, opt, &arglen); + if (optstr && (s = kstrndup(optstr, arglen, GFP_KERNEL))) { + int ret = kstrtol(s, 0, &value); + if (ret == 0) + result = value; + kfree(s); + } + + return result; +} + int nvkm_dbgopt(const char *optstr, const char *sub) { @@ -95,7 +113,7 @@ nvkm_dbgopt(const char *optstr, const char *sub) else if (!strncasecmpz(optstr, "warn", len)) level = NV_DBG_WARN; else if (!strncasecmpz(optstr, "info", len)) - level = NV_DBG_INFO_NORMAL; + level = NV_DBG_INFO; else if (!strncasecmpz(optstr, "debug", len)) level = NV_DBG_DEBUG; else if (!strncasecmpz(optstr, "trace", len)) diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/parent.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/parent.c deleted file mode 100644 index dd56cd1ee..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/parent.c +++ /dev/null @@ -1,159 +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 -#include -#include - -int -nvkm_parent_sclass(struct nvkm_object *parent, u16 handle, - struct nvkm_object **pengine, - struct nvkm_oclass **poclass) -{ - struct nvkm_sclass *sclass; - struct nvkm_engine *engine; - struct nvkm_oclass *oclass; - u64 mask; - - sclass = nv_parent(parent)->sclass; - while (sclass) { - if ((sclass->oclass->handle & 0xffff) == handle) { - *pengine = &parent->engine->subdev.object; - *poclass = sclass->oclass; - return 0; - } - - sclass = sclass->sclass; - } - - mask = nv_parent(parent)->engine; - while (mask) { - int i = __ffs64(mask); - - if (nv_iclass(parent, NV_CLIENT_CLASS)) - engine = nv_engine(nv_client(parent)->device); - else - engine = nvkm_engine(parent, i); - - if (engine) { - oclass = engine->sclass; - while (oclass->ofuncs) { - if ((oclass->handle & 0xffff) == handle) { - *pengine = nv_object(engine); - *poclass = oclass; - return 0; - } - oclass++; - } - } - - mask &= ~(1ULL << i); - } - - return -EINVAL; -} - -int -nvkm_parent_lclass(struct nvkm_object *parent, u32 *lclass, int size) -{ - struct nvkm_sclass *sclass; - struct nvkm_engine *engine; - struct nvkm_oclass *oclass; - int nr = -1, i; - u64 mask; - - sclass = nv_parent(parent)->sclass; - while (sclass) { - if (++nr < size) - lclass[nr] = sclass->oclass->handle & 0xffff; - sclass = sclass->sclass; - } - - mask = nv_parent(parent)->engine; - while (i = __ffs64(mask), mask) { - engine = nvkm_engine(parent, i); - if (engine && (oclass = engine->sclass)) { - while (oclass->ofuncs) { - if (++nr < size) - lclass[nr] = oclass->handle & 0xffff; - oclass++; - } - } - - mask &= ~(1ULL << i); - } - - return nr + 1; -} - -int -nvkm_parent_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 pclass, - struct nvkm_oclass *sclass, u64 engcls, - int size, void **pobject) -{ - struct nvkm_parent *object; - struct nvkm_sclass *nclass; - int ret; - - ret = nvkm_object_create_(parent, engine, oclass, pclass | - NV_PARENT_CLASS, size, pobject); - object = *pobject; - if (ret) - return ret; - - while (sclass && sclass->ofuncs) { - nclass = kzalloc(sizeof(*nclass), GFP_KERNEL); - if (!nclass) - return -ENOMEM; - - nclass->sclass = object->sclass; - object->sclass = nclass; - nclass->engine = engine ? nv_engine(engine) : NULL; - nclass->oclass = sclass; - sclass++; - } - - object->engine = engcls; - return 0; -} - -void -nvkm_parent_destroy(struct nvkm_parent *parent) -{ - struct nvkm_sclass *sclass; - - while ((sclass = parent->sclass)) { - parent->sclass = sclass->sclass; - kfree(sclass); - } - - nvkm_object_destroy(&parent->object); -} - - -void -_nvkm_parent_dtor(struct nvkm_object *object) -{ - nvkm_parent_destroy(nv_parent(object)); -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/printk.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/printk.c deleted file mode 100644 index 4a220eb91..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/printk.c +++ /dev/null @@ -1,103 +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 -#include -#include - -int nv_info_debug_level = NV_DBG_INFO_NORMAL; - -void -nv_printk_(struct nvkm_object *object, int level, const char *fmt, ...) -{ - static const char name[] = { '!', 'E', 'W', ' ', 'D', 'T', 'P', 'S' }; - const char *pfx; - char mfmt[256]; - va_list args; - - switch (level) { - case NV_DBG_FATAL: - pfx = KERN_CRIT; - break; - case NV_DBG_ERROR: - pfx = KERN_ERR; - break; - case NV_DBG_WARN: - pfx = KERN_WARNING; - break; - case NV_DBG_INFO_NORMAL: - pfx = KERN_INFO; - break; - case NV_DBG_DEBUG: - case NV_DBG_PARANOIA: - case NV_DBG_TRACE: - case NV_DBG_SPAM: - default: - pfx = KERN_DEBUG; - break; - } - - if (object && !nv_iclass(object, NV_CLIENT_CLASS)) { - struct nvkm_object *device; - struct nvkm_object *subdev; - char obuf[64], *ofmt = ""; - - if (object->engine == NULL) { - subdev = object; - while (subdev && !nv_iclass(subdev, NV_SUBDEV_CLASS)) - subdev = subdev->parent; - } else { - subdev = &object->engine->subdev.object; - } - - device = subdev; - if (device->parent) - device = device->parent; - - if (object != subdev) { - snprintf(obuf, sizeof(obuf), "[0x%08x]", - nv_hclass(object)); - ofmt = obuf; - } - - if (level > nv_subdev(subdev)->debug) - return; - - snprintf(mfmt, sizeof(mfmt), "%snouveau %c[%8s][%s]%s %s", pfx, - name[level], nv_subdev(subdev)->name, - nv_device(device)->name, ofmt, fmt); - } else - if (object && nv_iclass(object, NV_CLIENT_CLASS)) { - if (level > nv_client(object)->debug) - return; - - snprintf(mfmt, sizeof(mfmt), "%snouveau %c[%8s] %s", pfx, - name[level], nv_client(object)->name, fmt); - } else { - snprintf(mfmt, sizeof(mfmt), "%snouveau: %s", pfx, fmt); - } - - va_start(args, fmt); - vprintk(mfmt, args); - va_end(args); -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/ramht.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/ramht.c index ebd4d1547..3216e157a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/ramht.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/ramht.c @@ -22,8 +22,6 @@ #include #include -#include - static u32 nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) { @@ -35,72 +33,130 @@ nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) } hash ^= chid << (ramht->bits - 4); - hash = hash << 3; return hash; } -int -nvkm_ramht_insert(struct nvkm_ramht *ramht, int chid, u32 handle, u32 context) +struct nvkm_gpuobj * +nvkm_ramht_search(struct nvkm_ramht *ramht, int chid, u32 handle) { - struct nvkm_bar *bar = nvkm_bar(ramht); u32 co, ho; co = ho = nvkm_ramht_hash(ramht, chid, handle); do { - if (!nv_ro32(ramht, co + 4)) { - nv_wo32(ramht, co + 0, handle); - nv_wo32(ramht, co + 4, context); - if (bar) - bar->flush(bar); - return co; + if (ramht->data[co].chid == chid) { + if (ramht->data[co].handle == handle) + return ramht->data[co].inst; } - co += 8; - if (co >= nv_gpuobj(ramht)->size) + if (++co >= ramht->size) co = 0; } while (co != ho); - return -ENOMEM; + return NULL; +} + +static int +nvkm_ramht_update(struct nvkm_ramht *ramht, int co, struct nvkm_object *object, + int chid, int addr, u32 handle, u32 context) +{ + struct nvkm_ramht_data *data = &ramht->data[co]; + u64 inst = 0x00000040; /* just non-zero for <=g8x fifo ramht */ + int ret; + + nvkm_gpuobj_del(&data->inst); + data->chid = chid; + data->handle = handle; + + if (object) { + ret = nvkm_object_bind(object, ramht->parent, 16, &data->inst); + if (ret) { + if (ret != -ENODEV) { + data->chid = -1; + return ret; + } + data->inst = NULL; + } + + if (data->inst) { + if (ramht->device->card_type >= NV_50) + inst = data->inst->node->offset; + else + inst = data->inst->addr; + } + + if (addr < 0) context |= inst << -addr; + else context |= inst >> addr; + } + + nvkm_kmap(ramht->gpuobj); + nvkm_wo32(ramht->gpuobj, (co << 3) + 0, handle); + nvkm_wo32(ramht->gpuobj, (co << 3) + 4, context); + nvkm_done(ramht->gpuobj); + return co + 1; } void nvkm_ramht_remove(struct nvkm_ramht *ramht, int cookie) { - struct nvkm_bar *bar = nvkm_bar(ramht); - nv_wo32(ramht, cookie + 0, 0x00000000); - nv_wo32(ramht, cookie + 4, 0x00000000); - if (bar) - bar->flush(bar); + if (--cookie >= 0) + nvkm_ramht_update(ramht, cookie, NULL, -1, 0, 0, 0); +} + +int +nvkm_ramht_insert(struct nvkm_ramht *ramht, struct nvkm_object *object, + int chid, int addr, u32 handle, u32 context) +{ + u32 co, ho; + + if (nvkm_ramht_search(ramht, chid, handle)) + return -EEXIST; + + co = ho = nvkm_ramht_hash(ramht, chid, handle); + do { + if (ramht->data[co].chid < 0) { + return nvkm_ramht_update(ramht, co, object, chid, + addr, handle, context); + } + + if (++co >= ramht->size) + co = 0; + } while (co != ho); + + return -ENOSPC; } -static struct nvkm_oclass -nvkm_ramht_oclass = { - .handle = 0x0000abcd, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = NULL, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, - }, -}; +void +nvkm_ramht_del(struct nvkm_ramht **pramht) +{ + struct nvkm_ramht *ramht = *pramht; + if (ramht) { + nvkm_gpuobj_del(&ramht->gpuobj); + kfree(*pramht); + *pramht = NULL; + } +} int -nvkm_ramht_new(struct nvkm_object *parent, struct nvkm_object *pargpu, - u32 size, u32 align, struct nvkm_ramht **pramht) +nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align, + struct nvkm_gpuobj *parent, struct nvkm_ramht **pramht) { struct nvkm_ramht *ramht; - int ret; + int ret, i; - ret = nvkm_gpuobj_create(parent, parent->engine ? - &parent->engine->subdev.object : parent, /* > 3) * + sizeof(*ramht->data), GFP_KERNEL))) + return -ENOMEM; - ramht->bits = order_base_2(nv_gpuobj(ramht)->size >> 3); - return 0; + ramht->device = device; + ramht->parent = parent; + ramht->size = size >> 3; + ramht->bits = order_base_2(ramht->size); + for (i = 0; i < ramht->size; i++) + ramht->data[i].chid = -1; + + ret = nvkm_gpuobj_new(ramht->device, size, align, true, + ramht->parent, &ramht->gpuobj); + if (ret) + nvkm_ramht_del(pramht); + return ret; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/kernel/drivers/gpu/drm/nouveau/nvkm/core/subdev.c index c5fb3a793..7de98470a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/core/subdev.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/core/subdev.c @@ -25,96 +25,178 @@ #include #include -struct nvkm_subdev * -nvkm_subdev(void *obj, int idx) -{ - struct nvkm_object *object = nv_object(obj); - while (object && !nv_iclass(object, NV_SUBDEV_CLASS)) - object = object->parent; - if (object == NULL || nv_subidx(nv_subdev(object)) != idx) - object = nv_device(obj)->subdev[idx]; - return object ? nv_subdev(object) : NULL; -} +static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR]; + +const char * +nvkm_subdev_name[NVKM_SUBDEV_NR] = { + [NVKM_SUBDEV_BAR ] = "bar", + [NVKM_SUBDEV_VBIOS ] = "bios", + [NVKM_SUBDEV_BUS ] = "bus", + [NVKM_SUBDEV_CLK ] = "clk", + [NVKM_SUBDEV_DEVINIT] = "devinit", + [NVKM_SUBDEV_FB ] = "fb", + [NVKM_SUBDEV_FUSE ] = "fuse", + [NVKM_SUBDEV_GPIO ] = "gpio", + [NVKM_SUBDEV_I2C ] = "i2c", + [NVKM_SUBDEV_IBUS ] = "priv", + [NVKM_SUBDEV_INSTMEM] = "imem", + [NVKM_SUBDEV_LTC ] = "ltc", + [NVKM_SUBDEV_MC ] = "mc", + [NVKM_SUBDEV_MMU ] = "mmu", + [NVKM_SUBDEV_MXM ] = "mxm", + [NVKM_SUBDEV_PCI ] = "pci", + [NVKM_SUBDEV_PMU ] = "pmu", + [NVKM_SUBDEV_THERM ] = "therm", + [NVKM_SUBDEV_TIMER ] = "tmr", + [NVKM_SUBDEV_VOLT ] = "volt", + [NVKM_ENGINE_BSP ] = "bsp", + [NVKM_ENGINE_CE0 ] = "ce0", + [NVKM_ENGINE_CE1 ] = "ce1", + [NVKM_ENGINE_CE2 ] = "ce2", + [NVKM_ENGINE_CIPHER ] = "cipher", + [NVKM_ENGINE_DISP ] = "disp", + [NVKM_ENGINE_DMAOBJ ] = "dma", + [NVKM_ENGINE_FIFO ] = "fifo", + [NVKM_ENGINE_GR ] = "gr", + [NVKM_ENGINE_IFB ] = "ifb", + [NVKM_ENGINE_ME ] = "me", + [NVKM_ENGINE_MPEG ] = "mpeg", + [NVKM_ENGINE_MSENC ] = "msenc", + [NVKM_ENGINE_MSPDEC ] = "mspdec", + [NVKM_ENGINE_MSPPP ] = "msppp", + [NVKM_ENGINE_MSVLD ] = "msvld", + [NVKM_ENGINE_PM ] = "pm", + [NVKM_ENGINE_SEC ] = "sec", + [NVKM_ENGINE_SW ] = "sw", + [NVKM_ENGINE_VIC ] = "vic", + [NVKM_ENGINE_VP ] = "vp", +}; void -nvkm_subdev_reset(struct nvkm_object *subdev) +nvkm_subdev_intr(struct nvkm_subdev *subdev) { - nv_trace(subdev, "resetting...\n"); - nv_ofuncs(subdev)->fini(subdev, false); - nv_debug(subdev, "reset\n"); + if (subdev->func->intr) + subdev->func->intr(subdev); } int -nvkm_subdev_init(struct nvkm_subdev *subdev) +nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend) { - int ret = nvkm_object_init(&subdev->object); - if (ret) - return ret; + struct nvkm_device *device = subdev->device; + const char *action = suspend ? "suspend" : "fini"; + u32 pmc_enable = subdev->pmc_enable; + s64 time; - nvkm_subdev_reset(&subdev->object); - return 0; -} + nvkm_trace(subdev, "%s running...\n", action); + time = ktime_to_us(ktime_get()); -int -_nvkm_subdev_init(struct nvkm_object *object) -{ - return nvkm_subdev_init(nv_subdev(object)); -} + if (subdev->func->fini) { + int ret = subdev->func->fini(subdev, suspend); + if (ret) { + nvkm_error(subdev, "%s failed, %d\n", action, ret); + if (suspend) + return ret; + } + } -int -nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend) -{ - if (subdev->unit) { - nv_mask(subdev, 0x000200, subdev->unit, 0x00000000); - nv_mask(subdev, 0x000200, subdev->unit, subdev->unit); + if (pmc_enable) { + nvkm_mask(device, 0x000200, pmc_enable, 0x00000000); + nvkm_mask(device, 0x000200, pmc_enable, pmc_enable); + nvkm_rd32(device, 0x000200); } - return nvkm_object_fini(&subdev->object, suspend); + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "%s completed in %lldus\n", action, time); + return 0; } int -_nvkm_subdev_fini(struct nvkm_object *object, bool suspend) +nvkm_subdev_preinit(struct nvkm_subdev *subdev) { - return nvkm_subdev_fini(nv_subdev(object), suspend); -} + s64 time; -void -nvkm_subdev_destroy(struct nvkm_subdev *subdev) -{ - int subidx = nv_hclass(subdev) & 0xff; - nv_device(subdev)->subdev[subidx] = NULL; - nvkm_object_destroy(&subdev->object); -} + nvkm_trace(subdev, "preinit running...\n"); + time = ktime_to_us(ktime_get()); -void -_nvkm_subdev_dtor(struct nvkm_object *object) -{ - nvkm_subdev_destroy(nv_subdev(object)); + if (subdev->func->preinit) { + int ret = subdev->func->preinit(subdev); + if (ret) { + nvkm_error(subdev, "preinit failed, %d\n", ret); + return ret; + } + } + + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "preinit completed in %lldus\n", time); + return 0; } int -nvkm_subdev_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 pclass, - const char *subname, const char *sysname, - int size, void **pobject) +nvkm_subdev_init(struct nvkm_subdev *subdev) { - struct nvkm_subdev *subdev; + s64 time; int ret; - ret = nvkm_object_create_(parent, engine, oclass, pclass | - NV_SUBDEV_CLASS, size, pobject); - subdev = *pobject; - if (ret) - return ret; + nvkm_trace(subdev, "init running...\n"); + time = ktime_to_us(ktime_get()); + + if (subdev->func->oneinit && !subdev->oneinit) { + s64 time; + nvkm_trace(subdev, "one-time init running...\n"); + time = ktime_to_us(ktime_get()); + ret = subdev->func->oneinit(subdev); + if (ret) { + nvkm_error(subdev, "one-time init failed, %d\n", ret); + return ret; + } - __mutex_init(&subdev->mutex, subname, &oclass->lock_class_key); - subdev->name = subname; + subdev->oneinit = true; + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "one-time init completed in %lldus\n", time); + } - if (parent) { - struct nvkm_device *device = nv_device(parent); - subdev->debug = nvkm_dbgopt(device->dbgopt, subname); - subdev->mmio = nv_subdev(device)->mmio; + if (subdev->func->init) { + ret = subdev->func->init(subdev); + if (ret) { + nvkm_error(subdev, "init failed, %d\n", ret); + return ret; + } } + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "init completed in %lldus\n", time); return 0; } + +void +nvkm_subdev_del(struct nvkm_subdev **psubdev) +{ + struct nvkm_subdev *subdev = *psubdev; + s64 time; + + if (subdev && !WARN_ON(!subdev->func)) { + nvkm_trace(subdev, "destroy running...\n"); + time = ktime_to_us(ktime_get()); + if (subdev->func->dtor) + *psubdev = subdev->func->dtor(subdev); + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "destroy completed in %lldus\n", time); + kfree(*psubdev); + *psubdev = NULL; + } +} + +void +nvkm_subdev_ctor(const struct nvkm_subdev_func *func, + struct nvkm_device *device, int index, u32 pmc_enable, + struct nvkm_subdev *subdev) +{ + const char *name = nvkm_subdev_name[index]; + subdev->func = func; + subdev->device = device; + subdev->index = index; + subdev->pmc_enable = pmc_enable; + + __mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[index]); + subdev->debug = nvkm_dbgopt(device->dbgopt, name); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild index 6bd3d756f..36f724763 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild @@ -6,7 +6,7 @@ include $(src)/nvkm/engine/ce/Kbuild include $(src)/nvkm/engine/cipher/Kbuild include $(src)/nvkm/engine/device/Kbuild include $(src)/nvkm/engine/disp/Kbuild -include $(src)/nvkm/engine/dmaobj/Kbuild +include $(src)/nvkm/engine/dma/Kbuild include $(src)/nvkm/engine/fifo/Kbuild include $(src)/nvkm/engine/gr/Kbuild include $(src)/nvkm/engine/mpeg/Kbuild diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c index a0b1fd80f..3ef01071f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c @@ -22,72 +22,23 @@ * Authors: Ben Skeggs, Ilia Mirkin */ #include -#include -#include - -/******************************************************************************* - * BSP object classes - ******************************************************************************/ - -static struct nvkm_oclass -g84_bsp_sclass[] = { - { 0x74b0, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * BSP context - ******************************************************************************/ - -static struct nvkm_oclass -g84_bsp_cclass = { - .handle = NV_ENGCTX(BSP, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_xtensa_engctx_ctor, - .dtor = _nvkm_engctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - .rd32 = _nvkm_engctx_rd32, - .wr32 = _nvkm_engctx_wr32, - }, +#include + +static const struct nvkm_xtensa_func +g84_bsp = { + .pmc_enable = 0x04008000, + .fifo_val = 0x1111, + .unkd28 = 0x90044, + .sclass = { + { -1, -1, NV74_BSP }, + {} + } }; -/******************************************************************************* - * BSP engine/subdev functions - ******************************************************************************/ - -static int -g84_bsp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +g84_bsp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine) { - struct nvkm_xtensa *priv; - int ret; - - ret = nvkm_xtensa_create(parent, engine, oclass, 0x103000, true, - "PBSP", "bsp", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x04008000; - nv_engine(priv)->cclass = &g84_bsp_cclass; - nv_engine(priv)->sclass = g84_bsp_sclass; - priv->fifo_val = 0x1111; - priv->unkd28 = 0x90044; - return 0; + return nvkm_xtensa_new_(&g84_bsp, device, index, + true, 0x103000, pengine); } - -struct nvkm_oclass -g84_bsp_oclass = { - .handle = NV_ENGINE(BSP, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_bsp_ctor, - .dtor = _nvkm_xtensa_dtor, - .init = _nvkm_xtensa_init, - .fini = _nvkm_xtensa_fini, - .rd32 = _nvkm_xtensa_rd32, - .wr32 = _nvkm_xtensa_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/com.fuc b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/com.fuc index a558dfa4d..6226bcd98 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/com.fuc +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/com.fuc @@ -24,9 +24,9 @@ */ #ifdef GT215 -.section #gt215_pce_data +.section #gt215_ce_data #else -.section #gf100_pce_data +.section #gf100_ce_data #endif ctx_object: .b32 0 @@ -128,9 +128,9 @@ dispatch_dma: .b16 0x800 0 #ifdef GT215 -.section #gt215_pce_code +.section #gt215_ce_code #else -.section #gf100_pce_code +.section #gf100_ce_code #endif main: diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h index d9af6e4e4..05bb65608 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h @@ -1,4 +1,4 @@ -uint32_t gf100_pce_data[] = { +uint32_t gf100_ce_data[] = { /* 0x0000: ctx_object */ 0x00000000, /* 0x0004: ctx_query_address_high */ @@ -171,7 +171,7 @@ uint32_t gf100_pce_data[] = { 0x00000800, }; -uint32_t gf100_pce_code[] = { +uint32_t gf100_ce_code[] = { /* 0x0000: main */ 0x04fe04bd, 0x3517f000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h index f42c0d0d6..972281d10 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h @@ -1,4 +1,4 @@ -uint32_t gt215_pce_data[] = { +uint32_t gt215_ce_data[] = { /* 0x0000: ctx_object */ 0x00000000, /* 0x0004: ctx_dma */ @@ -183,7 +183,7 @@ uint32_t gt215_pce_data[] = { 0x00000800, }; -uint32_t gt215_pce_code[] = { +uint32_t gt215_ce_code[] = { /* 0x0000: main */ 0x04fe04bd, 0x3517f000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c index 2d2e549c2..92a9f35df 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c @@ -21,146 +21,60 @@ * * Authors: Ben Skeggs */ -#include -#include +#include "priv.h" #include "fuc/gf100.fuc3.h" -struct gf100_ce_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * Copy object classes - ******************************************************************************/ - -static struct nvkm_oclass -gf100_ce0_sclass[] = { - { 0x90b5, &nvkm_object_ofuncs }, - {}, -}; - -static struct nvkm_oclass -gf100_ce1_sclass[] = { - { 0x90b8, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PCE context - ******************************************************************************/ - -static struct nvkm_ofuncs -gf100_ce_context_ofuncs = { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, -}; - -static struct nvkm_oclass -gf100_ce0_cclass = { - .handle = NV_ENGCTX(CE0, 0xc0), - .ofuncs = &gf100_ce_context_ofuncs, -}; - -static struct nvkm_oclass -gf100_ce1_cclass = { - .handle = NV_ENGCTX(CE1, 0xc0), - .ofuncs = &gf100_ce_context_ofuncs, -}; - -/******************************************************************************* - * PCE engine/subdev functions - ******************************************************************************/ +#include -static int -gf100_ce_init(struct nvkm_object *object) +static void +gf100_ce_init(struct nvkm_falcon *ce) { - struct gf100_ce_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wo32(priv, 0x084, nv_engidx(&priv->base.base) - NVDEV_ENGINE_CE0); - return 0; + struct nvkm_device *device = ce->engine.subdev.device; + const int index = ce->engine.subdev.index - NVKM_ENGINE_CE0; + nvkm_wr32(device, ce->addr + 0x084, index); } -static int -gf100_ce0_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_ce_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x104000, true, - "PCE0", "ce0", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +gf100_ce0 = { + .code.data = gf100_ce_code, + .code.size = sizeof(gf100_ce_code), + .data.data = gf100_ce_data, + .data.size = sizeof(gf100_ce_data), + .pmc_enable = 0x00000040, + .init = gf100_ce_init, + .intr = gt215_ce_intr, + .sclass = { + { -1, -1, FERMI_DMA }, + {} + } +}; - nv_subdev(priv)->unit = 0x00000040; - nv_subdev(priv)->intr = gt215_ce_intr; - nv_engine(priv)->cclass = &gf100_ce0_cclass; - nv_engine(priv)->sclass = gf100_ce0_sclass; - nv_falcon(priv)->code.data = gf100_pce_code; - nv_falcon(priv)->code.size = sizeof(gf100_pce_code); - nv_falcon(priv)->data.data = gf100_pce_data; - nv_falcon(priv)->data.size = sizeof(gf100_pce_data); - return 0; -} +static const struct nvkm_falcon_func +gf100_ce1 = { + .code.data = gf100_ce_code, + .code.size = sizeof(gf100_ce_code), + .data.data = gf100_ce_data, + .data.size = sizeof(gf100_ce_data), + .pmc_enable = 0x00000080, + .init = gf100_ce_init, + .intr = gt215_ce_intr, + .sclass = { + { -1, -1, FERMI_DECOMPRESS }, + {} + } +}; -static int -gf100_ce1_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gf100_ce_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - struct gf100_ce_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x105000, true, - "PCE1", "ce1", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000080; - nv_subdev(priv)->intr = gt215_ce_intr; - nv_engine(priv)->cclass = &gf100_ce1_cclass; - nv_engine(priv)->sclass = gf100_ce1_sclass; - nv_falcon(priv)->code.data = gf100_pce_code; - nv_falcon(priv)->code.size = sizeof(gf100_pce_code); - nv_falcon(priv)->data.data = gf100_pce_data; - nv_falcon(priv)->data.size = sizeof(gf100_pce_data); - return 0; + if (index == NVKM_ENGINE_CE0) { + return nvkm_falcon_new_(&gf100_ce0, device, index, true, + 0x104000, pengine); + } else + if (index == NVKM_ENGINE_CE1) { + return nvkm_falcon_new_(&gf100_ce1, device, index, true, + 0x105000, pengine); + } + return -ENODEV; } - -struct nvkm_oclass -gf100_ce0_oclass = { - .handle = NV_ENGINE(CE0, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_ce0_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gf100_ce_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; - -struct nvkm_oclass -gf100_ce1_oclass = { - .handle = NV_ENGINE(CE1, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_ce1_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gf100_ce_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c index a998932fa..c541a1c01 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c @@ -21,153 +21,47 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" -#include +#include -struct gk104_ce_priv { - struct nvkm_engine base; -}; - -/******************************************************************************* - * Copy object classes - ******************************************************************************/ - -static struct nvkm_oclass -gk104_ce_sclass[] = { - { 0xa0b5, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PCE context - ******************************************************************************/ - -static struct nvkm_ofuncs -gk104_ce_context_ofuncs = { - .ctor = _nvkm_engctx_ctor, - .dtor = _nvkm_engctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - .rd32 = _nvkm_engctx_rd32, - .wr32 = _nvkm_engctx_wr32, -}; - -static struct nvkm_oclass -gk104_ce_cclass = { - .handle = NV_ENGCTX(CE0, 0xc0), - .ofuncs = &gk104_ce_context_ofuncs, -}; - -/******************************************************************************* - * PCE engine/subdev functions - ******************************************************************************/ - -static void -gk104_ce_intr(struct nvkm_subdev *subdev) +void +gk104_ce_intr(struct nvkm_engine *ce) { - const int ce = nv_subidx(subdev) - NVDEV_ENGINE_CE0; - struct gk104_ce_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, 0x104908 + (ce * 0x1000)); - + const u32 base = (ce->subdev.index - NVKM_ENGINE_CE0) * 0x1000; + struct nvkm_subdev *subdev = &ce->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x104908 + base); if (stat) { - nv_warn(priv, "unhandled intr 0x%08x\n", stat); - nv_wr32(priv, 0x104908 + (ce * 0x1000), stat); + nvkm_warn(subdev, "intr %08x\n", stat); + nvkm_wr32(device, 0x104908 + base, stat); } } -static int -gk104_ce0_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk104_ce_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCE0", "ce0", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000040; - nv_subdev(priv)->intr = gk104_ce_intr; - nv_engine(priv)->cclass = &gk104_ce_cclass; - nv_engine(priv)->sclass = gk104_ce_sclass; - return 0; -} - -static int -gk104_ce1_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk104_ce_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCE1", "ce1", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000080; - nv_subdev(priv)->intr = gk104_ce_intr; - nv_engine(priv)->cclass = &gk104_ce_cclass; - nv_engine(priv)->sclass = gk104_ce_sclass; - return 0; -} +static const struct nvkm_engine_func +gk104_ce = { + .intr = gk104_ce_intr, + .sclass = { + { -1, -1, KEPLER_DMA_COPY_A }, + {} + } +}; -static int -gk104_ce2_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gk104_ce_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - struct gk104_ce_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCE2", "ce2", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00200000; - nv_subdev(priv)->intr = gk104_ce_intr; - nv_engine(priv)->cclass = &gk104_ce_cclass; - nv_engine(priv)->sclass = gk104_ce_sclass; - return 0; + if (index == NVKM_ENGINE_CE0) { + return nvkm_engine_new_(&gk104_ce, device, index, + 0x00000040, true, pengine); + } else + if (index == NVKM_ENGINE_CE1) { + return nvkm_engine_new_(&gk104_ce, device, index, + 0x00000080, true, pengine); + } else + if (index == NVKM_ENGINE_CE2) { + return nvkm_engine_new_(&gk104_ce, device, index, + 0x00200000, true, pengine); + } + return -ENODEV; } - -struct nvkm_oclass -gk104_ce0_oclass = { - .handle = NV_ENGINE(CE0, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_ce0_ctor, - .dtor = _nvkm_engine_dtor, - .init = _nvkm_engine_init, - .fini = _nvkm_engine_fini, - }, -}; - -struct nvkm_oclass -gk104_ce1_oclass = { - .handle = NV_ENGINE(CE1, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_ce1_ctor, - .dtor = _nvkm_engine_dtor, - .init = _nvkm_engine_init, - .fini = _nvkm_engine_fini, - }, -}; - -struct nvkm_oclass -gk104_ce2_oclass = { - .handle = NV_ENGINE(CE2, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_ce2_ctor, - .dtor = _nvkm_engine_dtor, - .init = _nvkm_engine_init, - .fini = _nvkm_engine_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c index 577eb2eea..8eaa72a59 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c @@ -21,153 +21,34 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" -#include +#include -struct gm204_ce_priv { - struct nvkm_engine base; -}; - -/******************************************************************************* - * Copy object classes - ******************************************************************************/ - -static struct nvkm_oclass -gm204_ce_sclass[] = { - { 0xb0b5, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PCE context - ******************************************************************************/ - -static struct nvkm_ofuncs -gm204_ce_context_ofuncs = { - .ctor = _nvkm_engctx_ctor, - .dtor = _nvkm_engctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - .rd32 = _nvkm_engctx_rd32, - .wr32 = _nvkm_engctx_wr32, -}; - -static struct nvkm_oclass -gm204_ce_cclass = { - .handle = NV_ENGCTX(CE0, 0x24), - .ofuncs = &gm204_ce_context_ofuncs, +static const struct nvkm_engine_func +gm204_ce = { + .intr = gk104_ce_intr, + .sclass = { + { -1, -1, MAXWELL_DMA_COPY_A }, + {} + } }; -/******************************************************************************* - * PCE engine/subdev functions - ******************************************************************************/ - -static void -gm204_ce_intr(struct nvkm_subdev *subdev) +int +gm204_ce_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - const int ce = nv_subidx(subdev) - NVDEV_ENGINE_CE0; - struct gm204_ce_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, 0x104908 + (ce * 0x1000)); - - if (stat) { - nv_warn(priv, "unhandled intr 0x%08x\n", stat); - nv_wr32(priv, 0x104908 + (ce * 0x1000), stat); + if (index == NVKM_ENGINE_CE0) { + return nvkm_engine_new_(&gm204_ce, device, index, + 0x00000040, true, pengine); + } else + if (index == NVKM_ENGINE_CE1) { + return nvkm_engine_new_(&gm204_ce, device, index, + 0x00000080, true, pengine); + } else + if (index == NVKM_ENGINE_CE2) { + return nvkm_engine_new_(&gm204_ce, device, index, + 0x00200000, true, pengine); } + return -ENODEV; } - -static int -gm204_ce0_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gm204_ce_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCE0", "ce0", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000040; - nv_subdev(priv)->intr = gm204_ce_intr; - nv_engine(priv)->cclass = &gm204_ce_cclass; - nv_engine(priv)->sclass = gm204_ce_sclass; - return 0; -} - -static int -gm204_ce1_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gm204_ce_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCE1", "ce1", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000080; - nv_subdev(priv)->intr = gm204_ce_intr; - nv_engine(priv)->cclass = &gm204_ce_cclass; - nv_engine(priv)->sclass = gm204_ce_sclass; - return 0; -} - -static int -gm204_ce2_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gm204_ce_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCE2", "ce2", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00200000; - nv_subdev(priv)->intr = gm204_ce_intr; - nv_engine(priv)->cclass = &gm204_ce_cclass; - nv_engine(priv)->sclass = gm204_ce_sclass; - return 0; -} - -struct nvkm_oclass -gm204_ce0_oclass = { - .handle = NV_ENGINE(CE0, 0x24), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_ce0_ctor, - .dtor = _nvkm_engine_dtor, - .init = _nvkm_engine_init, - .fini = _nvkm_engine_fini, - }, -}; - -struct nvkm_oclass -gm204_ce1_oclass = { - .handle = NV_ENGINE(CE1, 0x24), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_ce1_ctor, - .dtor = _nvkm_engine_dtor, - .init = _nvkm_engine_init, - .fini = _nvkm_engine_fini, - }, -}; - -struct nvkm_oclass -gm204_ce2_oclass = { - .handle = NV_ENGINE(CE2, 0x24), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_ce2_ctor, - .dtor = _nvkm_engine_dtor, - .init = _nvkm_engine_init, - .fini = _nvkm_engine_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c index d8bb4293b..402dcbcc2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c @@ -21,50 +21,15 @@ * * Authors: Ben Skeggs */ -#include -#include -#include +#include "priv.h" #include "fuc/gt215.fuc3.h" #include -#include #include +#include +#include -struct gt215_ce_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * Copy object classes - ******************************************************************************/ - -static struct nvkm_oclass -gt215_ce_sclass[] = { - { 0x85b5, &nvkm_object_ofuncs }, - {} -}; - -/******************************************************************************* - * PCE context - ******************************************************************************/ - -static struct nvkm_oclass -gt215_ce_cclass = { - .handle = NV_ENGCTX(CE0, 0xa3), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - - }, -}; - -/******************************************************************************* - * PCE engine/subdev functions - ******************************************************************************/ +#include static const struct nvkm_enum gt215_ce_isr_error_name[] = { @@ -75,78 +40,45 @@ gt215_ce_isr_error_name[] = { }; void -gt215_ce_intr(struct nvkm_subdev *subdev) +gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_falcon *falcon = (void *)subdev; - struct nvkm_object *engctx; - u32 dispatch = nv_ro32(falcon, 0x01c); - u32 stat = nv_ro32(falcon, 0x008) & dispatch & ~(dispatch >> 16); - u64 inst = nv_ro32(falcon, 0x050) & 0x3fffffff; - u32 ssta = nv_ro32(falcon, 0x040) & 0x0000ffff; - u32 addr = nv_ro32(falcon, 0x040) >> 16; + struct nvkm_subdev *subdev = &ce->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 base = (subdev->index - NVKM_ENGINE_CE0) * 0x1000; + u32 ssta = nvkm_rd32(device, 0x104040 + base) & 0x0000ffff; + u32 addr = nvkm_rd32(device, 0x104040 + base) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_ro32(falcon, 0x044); - int chid; - - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); - - if (stat & 0x00000040) { - nv_error(falcon, "DISPATCH_ERROR ["); - nvkm_enum_print(gt215_ce_isr_error_name, ssta); - pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nvkm_client_name(engctx), subc, - mthd, data); - nv_wo32(falcon, 0x004, 0x00000040); - stat &= ~0x00000040; - } + u32 data = nvkm_rd32(device, 0x104044 + base); + const struct nvkm_enum *en = + nvkm_enum_find(gt215_ce_isr_error_name, ssta); + + nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] " + "subc %d mthd %04x data %08x\n", ssta, + en ? en->name : "", chan ? chan->chid : -1, + chan ? chan->inst->addr : 0, + chan ? chan->object.client->name : "unknown", + subc, mthd, data); +} - if (stat) { - nv_error(falcon, "unhandled intr 0x%08x\n", stat); - nv_wo32(falcon, 0x004, stat); +static const struct nvkm_falcon_func +gt215_ce = { + .code.data = gt215_ce_code, + .code.size = sizeof(gt215_ce_code), + .data.data = gt215_ce_data, + .data.size = sizeof(gt215_ce_data), + .pmc_enable = 0x00802000, + .intr = gt215_ce_intr, + .sclass = { + { -1, -1, GT212_DMA }, + {} } +}; - nvkm_engctx_put(engctx); -} - -static int -gt215_ce_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gt215_ce_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - bool enable = (nv_device(parent)->chipset != 0xaf); - struct gt215_ce_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x104000, enable, - "PCE0", "ce0", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00802000; - nv_subdev(priv)->intr = gt215_ce_intr; - nv_engine(priv)->cclass = >215_ce_cclass; - nv_engine(priv)->sclass = gt215_ce_sclass; - nv_falcon(priv)->code.data = gt215_pce_code; - nv_falcon(priv)->code.size = sizeof(gt215_pce_code); - nv_falcon(priv)->data.data = gt215_pce_data; - nv_falcon(priv)->data.size = sizeof(gt215_pce_data); - return 0; + return nvkm_falcon_new_(>215_ce, device, index, + (device->chipset != 0xaf), 0x104000, pengine); } - -struct nvkm_oclass -gt215_ce_oclass = { - .handle = NV_ENGINE(CE0, 0xa3), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt215_ce_ctor, - .dtor = _nvkm_falcon_dtor, - .init = _nvkm_falcon_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h new file mode 100644 index 000000000..e2fa8b161 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h @@ -0,0 +1,7 @@ +#ifndef __NVKM_CE_PRIV_H__ +#define __NVKM_CE_PRIV_H__ +#include + +void gt215_ce_intr(struct nvkm_falcon *, struct nvkm_fifo_chan *); +void gk104_ce_intr(struct nvkm_engine *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c index 13f30428a..bfd01625e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c @@ -25,76 +25,47 @@ #include #include -#include #include +#include -struct g84_cipher_priv { - struct nvkm_engine base; -}; - -/******************************************************************************* - * Crypt object classes - ******************************************************************************/ +#include static int -g84_cipher_object_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +g84_cipher_oclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_gpuobj *obj; - int ret; - - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, - 16, 16, 0, &obj); - *pobject = nv_object(obj); - if (ret) - return ret; - - nv_wo32(obj, 0x00, nv_mclass(obj)); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - return 0; + int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16, + align, false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, object->oclass); + nvkm_wo32(*pgpuobj, 0x04, 0x00000000); + nvkm_wo32(*pgpuobj, 0x08, 0x00000000); + nvkm_wo32(*pgpuobj, 0x0c, 0x00000000); + nvkm_done(*pgpuobj); + } + return ret; } -static struct nvkm_ofuncs -g84_cipher_ofuncs = { - .ctor = g84_cipher_object_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, +static const struct nvkm_object_func +g84_cipher_oclass_func = { + .bind = g84_cipher_oclass_bind, }; -static struct nvkm_oclass -g84_cipher_sclass[] = { - { 0x74c1, &g84_cipher_ofuncs }, - {} -}; +static int +g84_cipher_cclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + return nvkm_gpuobj_new(object->engine->subdev.device, 256, + align, true, parent, pgpuobj); -/******************************************************************************* - * PCIPHER context - ******************************************************************************/ +} -static struct nvkm_oclass +static const struct nvkm_object_func g84_cipher_cclass = { - .handle = NV_ENGCTX(CIPHER, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_engctx_ctor, - .dtor = _nvkm_engctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - .rd32 = _nvkm_engctx_rd32, - .wr32 = _nvkm_engctx_wr32, - }, + .bind = g84_cipher_cclass_bind, }; -/******************************************************************************* - * PCIPHER engine/subdev functions - ******************************************************************************/ - static const struct nvkm_bitfield g84_cipher_intr_mask[] = { { 0x00000001, "INVALID_STATE" }, @@ -106,79 +77,59 @@ g84_cipher_intr_mask[] = { }; static void -g84_cipher_intr(struct nvkm_subdev *subdev) +g84_cipher_intr(struct nvkm_engine *cipher) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct g84_cipher_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, 0x102130); - u32 mthd = nv_rd32(priv, 0x102190); - u32 data = nv_rd32(priv, 0x102194); - u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff; - int chid; - - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); - + struct nvkm_subdev *subdev = &cipher->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_fifo *fifo = device->fifo; + struct nvkm_fifo_chan *chan; + u32 stat = nvkm_rd32(device, 0x102130); + u32 mthd = nvkm_rd32(device, 0x102190); + u32 data = nvkm_rd32(device, 0x102194); + u32 inst = nvkm_rd32(device, 0x102188) & 0x7fffffff; + unsigned long flags; + char msg[128]; + + chan = nvkm_fifo_chan_inst(fifo, (u64)inst << 12, &flags); if (stat) { - nv_error(priv, "%s", ""); - nvkm_bitfield_print(g84_cipher_intr_mask, stat); - pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n", - chid, (u64)inst << 12, nvkm_client_name(engctx), - mthd, data); + nvkm_snprintbf(msg, sizeof(msg), g84_cipher_intr_mask, stat); + nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] " + "mthd %04x data %08x\n", stat, msg, + chan ? chan->chid : -1, (u64)inst << 12, + chan ? chan->object.client->name : "unknown", + mthd, data); } + nvkm_fifo_chan_put(fifo, flags, &chan); - nv_wr32(priv, 0x102130, stat); - nv_wr32(priv, 0x10200c, 0x10); - - nvkm_engctx_put(engctx); + nvkm_wr32(device, 0x102130, stat); + nvkm_wr32(device, 0x10200c, 0x10); } static int -g84_cipher_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +g84_cipher_init(struct nvkm_engine *cipher) { - struct g84_cipher_priv *priv; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, - "PCIPHER", "cipher", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00004000; - nv_subdev(priv)->intr = g84_cipher_intr; - nv_engine(priv)->cclass = &g84_cipher_cclass; - nv_engine(priv)->sclass = g84_cipher_sclass; + struct nvkm_device *device = cipher->subdev.device; + nvkm_wr32(device, 0x102130, 0xffffffff); + nvkm_wr32(device, 0x102140, 0xffffffbf); + nvkm_wr32(device, 0x10200c, 0x00000010); return 0; } -static int -g84_cipher_init(struct nvkm_object *object) -{ - struct g84_cipher_priv *priv = (void *)object; - int ret; - - ret = nvkm_engine_init(&priv->base); - if (ret) - return ret; +static const struct nvkm_engine_func +g84_cipher = { + .init = g84_cipher_init, + .intr = g84_cipher_intr, + .cclass = &g84_cipher_cclass, + .sclass = { + { -1, -1, NV74_CIPHER, &g84_cipher_oclass_func }, + {} + } +}; - nv_wr32(priv, 0x102130, 0xffffffff); - nv_wr32(priv, 0x102140, 0xffffffbf); - nv_wr32(priv, 0x10200c, 0x00000010); - return 0; +int +g84_cipher_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_engine_new_(&g84_cipher, device, index, + 0x00004000, true, pengine); } - -struct nvkm_oclass -g84_cipher_oclass = { - .handle = NV_ENGINE(CIPHER, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_cipher_ctor, - .dtor = _nvkm_engine_dtor, - .init = g84_cipher_init, - .fini = _nvkm_engine_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild index de1bf092b..09032ba36 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild @@ -1,12 +1,6 @@ nvkm-y += nvkm/engine/device/acpi.o nvkm-y += nvkm/engine/device/base.o nvkm-y += nvkm/engine/device/ctrl.o -nvkm-y += nvkm/engine/device/nv04.o -nvkm-y += nvkm/engine/device/nv10.o -nvkm-y += nvkm/engine/device/nv20.o -nvkm-y += nvkm/engine/device/nv30.o -nvkm-y += nvkm/engine/device/nv40.o -nvkm-y += nvkm/engine/device/nv50.o -nvkm-y += nvkm/engine/device/gf100.o -nvkm-y += nvkm/engine/device/gk104.o -nvkm-y += nvkm/engine/device/gm100.o +nvkm-y += nvkm/engine/device/pci.o +nvkm-y += nvkm/engine/device/tegra.o +nvkm-y += nvkm/engine/device/user.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c index f42706e1d..fdca90bc8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c @@ -40,21 +40,19 @@ nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data) } #endif -int -nvkm_acpi_fini(struct nvkm_device *device, bool suspend) +void +nvkm_acpi_fini(struct nvkm_device *device) { #ifdef CONFIG_ACPI unregister_acpi_notifier(&device->acpi.nb); #endif - return 0; } -int +void nvkm_acpi_init(struct nvkm_device *device) { #ifdef CONFIG_ACPI device->acpi.nb.notifier_call = nvkm_acpi_ntfy; register_acpi_notifier(&device->acpi.nb); #endif - return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h index 82dd359dd..1bbe76e07 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h @@ -3,6 +3,6 @@ #include struct nvkm_device; -int nvkm_acpi_init(struct nvkm_device *); -int nvkm_acpi_fini(struct nvkm_device *, bool); +void nvkm_acpi_init(struct nvkm_device *); +void nvkm_acpi_fini(struct nvkm_device *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 63d8e52f4..bbc9824af 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -24,33 +24,33 @@ #include "priv.h" #include "acpi.h" -#include -#include #include -#include -#include -#include -#include +#include -#include -#include +#include static DEFINE_MUTEX(nv_devices_mutex); static LIST_HEAD(nv_devices); -struct nvkm_device * -nvkm_device_find(u64 name) +static struct nvkm_device * +nvkm_device_find_locked(u64 handle) { - struct nvkm_device *device, *match = NULL; - mutex_lock(&nv_devices_mutex); + struct nvkm_device *device; list_for_each_entry(device, &nv_devices, head) { - if (device->handle == name) { - match = device; - break; - } + if (device->handle == handle) + return device; } + return NULL; +} + +struct nvkm_device * +nvkm_device_find(u64 handle) +{ + struct nvkm_device *device; + mutex_lock(&nv_devices_mutex); + device = nvkm_device_find_locked(handle); mutex_unlock(&nv_devices_mutex); - return match; + return device; } int @@ -67,280 +67,2275 @@ nvkm_device_list(u64 *name, int size) return nr; } -/****************************************************************************** - * nvkm_devobj (0x0080): class implementation - *****************************************************************************/ +static const struct nvkm_device_chip +null_chipset = { + .name = "NULL", + .bios = nvkm_bios_new, +}; + +static const struct nvkm_device_chip +nv4_chipset = { + .name = "NV04", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv04_devinit_new, + .fb = nv04_fb_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv04_fifo_new, + .gr = nv04_gr_new, + .sw = nv04_sw_new, +}; + +static const struct nvkm_device_chip +nv5_chipset = { + .name = "NV05", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv05_devinit_new, + .fb = nv04_fb_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv04_fifo_new, + .gr = nv04_gr_new, + .sw = nv04_sw_new, +}; + +static const struct nvkm_device_chip +nv10_chipset = { + .name = "NV10", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv10_devinit_new, + .fb = nv10_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .gr = nv10_gr_new, +}; + +static const struct nvkm_device_chip +nv11_chipset = { + .name = "NV11", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv10_devinit_new, + .fb = nv10_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv10_fifo_new, + .gr = nv15_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv15_chipset = { + .name = "NV15", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv10_devinit_new, + .fb = nv10_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv10_fifo_new, + .gr = nv15_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv17_chipset = { + .name = "NV17", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv10_devinit_new, + .fb = nv10_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv17_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv18_chipset = { + .name = "NV18", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv10_devinit_new, + .fb = nv10_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv17_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv1a_chipset = { + .name = "nForce", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv1a_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv10_fifo_new, + .gr = nv15_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv1f_chipset = { + .name = "nForce2", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv1a_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv17_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv20_chipset = { + .name = "NV20", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv20_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv20_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv25_chipset = { + .name = "NV25", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv25_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv25_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv28_chipset = { + .name = "NV28", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv25_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv25_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv2a_chipset = { + .name = "NV2A", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv25_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv2a_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv30_chipset = { + .name = "NV30", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv30_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv30_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv31_chipset = { + .name = "NV31", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv30_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv30_gr_new, + .mpeg = nv31_mpeg_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv34_chipset = { + .name = "NV34", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv04_clk_new, + .devinit = nv10_devinit_new, + .fb = nv10_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv34_gr_new, + .mpeg = nv31_mpeg_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv35_chipset = { + .name = "NV35", + .bios = nvkm_bios_new, + .bus = nv04_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv35_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv35_gr_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv36_chipset = { + .name = "NV36", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv04_clk_new, + .devinit = nv20_devinit_new, + .fb = nv36_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv04_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv04_pci_new, + .timer = nv04_timer_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv17_fifo_new, + .gr = nv35_gr_new, + .mpeg = nv31_mpeg_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv40_chipset = { + .name = "NV40", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv40_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv40_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv40_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv41_chipset = { + .name = "NV41", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv41_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv41_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv40_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv42_chipset = { + .name = "NV42", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv41_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv41_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv40_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv43_chipset = { + .name = "NV43", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv41_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv41_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv40_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv44_chipset = { + .name = "NV44", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv44_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv45_chipset = { + .name = "NV45", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv40_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv04_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv46_chipset = { + .name = "G72", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv46_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv46_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv47_chipset = { + .name = "G70", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv47_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv41_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv49_chipset = { + .name = "G71", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv49_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv41_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv4a_chipset = { + .name = "NV44A", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv44_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv4b_chipset = { + .name = "G73", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv49_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv04_mc_new, + .mmu = nv41_mmu_new, + .pci = nv40_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv40_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv4c_chipset = { + .name = "C61", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv46_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv4c_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv4e_chipset = { + .name = "C51", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv4e_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv4e_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv4c_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv50_chipset = { + .name = "G80", + .bar = nv50_bar_new, + .bios = nvkm_bios_new, + .bus = nv50_bus_new, + .clk = nv50_clk_new, + .devinit = nv50_devinit_new, + .fb = nv50_fb_new, + .fuse = nv50_fuse_new, + .gpio = nv50_gpio_new, + .i2c = nv50_i2c_new, + .imem = nv50_instmem_new, + .mc = nv50_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = nv46_pci_new, + .therm = nv50_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv50_disp_new, + .dma = nv50_dma_new, + .fifo = nv50_fifo_new, + .gr = nv50_gr_new, + .mpeg = nv50_mpeg_new, + .pm = nv50_pm_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nv63_chipset = { + .name = "C73", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv46_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv4c_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv67_chipset = { + .name = "C67", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv46_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv4c_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv68_chipset = { + .name = "C68", + .bios = nvkm_bios_new, + .bus = nv31_bus_new, + .clk = nv40_clk_new, + .devinit = nv1a_devinit_new, + .fb = nv46_fb_new, + .gpio = nv10_gpio_new, + .i2c = nv04_i2c_new, + .imem = nv40_instmem_new, + .mc = nv44_mc_new, + .mmu = nv44_mmu_new, + .pci = nv4c_pci_new, + .therm = nv40_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = nv04_disp_new, + .dma = nv04_dma_new, + .fifo = nv40_fifo_new, + .gr = nv44_gr_new, + .mpeg = nv44_mpeg_new, + .pm = nv40_pm_new, + .sw = nv10_sw_new, +}; + +static const struct nvkm_device_chip +nv84_chipset = { + .name = "G84", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = nv50_bus_new, + .clk = g84_clk_new, + .devinit = g84_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = nv50_gpio_new, + .i2c = nv50_i2c_new, + .imem = nv50_instmem_new, + .mc = nv50_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g84_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .bsp = g84_bsp_new, + .cipher = g84_cipher_new, + .disp = g84_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = g84_gr_new, + .mpeg = g84_mpeg_new, + .pm = g84_pm_new, + .sw = nv50_sw_new, + .vp = g84_vp_new, +}; + +static const struct nvkm_device_chip +nv86_chipset = { + .name = "G86", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = nv50_bus_new, + .clk = g84_clk_new, + .devinit = g84_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = nv50_gpio_new, + .i2c = nv50_i2c_new, + .imem = nv50_instmem_new, + .mc = nv50_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g84_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .bsp = g84_bsp_new, + .cipher = g84_cipher_new, + .disp = g84_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = g84_gr_new, + .mpeg = g84_mpeg_new, + .pm = g84_pm_new, + .sw = nv50_sw_new, + .vp = g84_vp_new, +}; + +static const struct nvkm_device_chip +nv92_chipset = { + .name = "G92", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = nv50_bus_new, + .clk = g84_clk_new, + .devinit = g84_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = nv50_gpio_new, + .i2c = nv50_i2c_new, + .imem = nv50_instmem_new, + .mc = nv50_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g84_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .bsp = g84_bsp_new, + .cipher = g84_cipher_new, + .disp = g84_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = g84_gr_new, + .mpeg = g84_mpeg_new, + .pm = g84_pm_new, + .sw = nv50_sw_new, + .vp = g84_vp_new, +}; + +static const struct nvkm_device_chip +nv94_chipset = { + .name = "G94", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = g84_clk_new, + .devinit = g84_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = nv50_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .bsp = g84_bsp_new, + .cipher = g84_cipher_new, + .disp = g94_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = g84_gr_new, + .mpeg = g84_mpeg_new, + .pm = g84_pm_new, + .sw = nv50_sw_new, + .vp = g84_vp_new, +}; + +static const struct nvkm_device_chip +nv96_chipset = { + .name = "G96", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = g84_clk_new, + .devinit = g84_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = nv50_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .bsp = g84_bsp_new, + .cipher = g84_cipher_new, + .disp = g94_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = g84_gr_new, + .mpeg = g84_mpeg_new, + .pm = g84_pm_new, + .sw = nv50_sw_new, + .vp = g84_vp_new, +}; + +static const struct nvkm_device_chip +nv98_chipset = { + .name = "G98", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = g84_clk_new, + .devinit = g98_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = g94_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = g84_gr_new, + .mspdec = g98_mspdec_new, + .msppp = g98_msppp_new, + .msvld = g98_msvld_new, + .pm = g84_pm_new, + .sec = g98_sec_new, + .sw = nv50_sw_new, +}; -struct nvkm_devobj { - struct nvkm_parent base; - struct nvkm_object *subdev[NVDEV_SUBDEV_NR]; +static const struct nvkm_device_chip +nva0_chipset = { + .name = "GT200", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = g84_clk_new, + .devinit = g84_devinit_new, + .fb = g84_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = nv50_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .bsp = g84_bsp_new, + .cipher = g84_cipher_new, + .disp = gt200_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = gt200_gr_new, + .mpeg = g84_mpeg_new, + .pm = gt200_pm_new, + .sw = nv50_sw_new, + .vp = g84_vp_new, +}; + +static const struct nvkm_device_chip +nva3_chipset = { + .name = "GT215", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = gt215_clk_new, + .devinit = gt215_devinit_new, + .fb = gt215_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gt215_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gt215_ce_new, + .disp = gt215_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = gt215_gr_new, + .mpeg = g84_mpeg_new, + .mspdec = gt215_mspdec_new, + .msppp = gt215_msppp_new, + .msvld = gt215_msvld_new, + .pm = gt215_pm_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nva5_chipset = { + .name = "GT216", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = gt215_clk_new, + .devinit = gt215_devinit_new, + .fb = gt215_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gt215_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gt215_ce_new, + .disp = gt215_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = gt215_gr_new, + .mspdec = gt215_mspdec_new, + .msppp = gt215_msppp_new, + .msvld = gt215_msvld_new, + .pm = gt215_pm_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nva8_chipset = { + .name = "GT218", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = gt215_clk_new, + .devinit = gt215_devinit_new, + .fb = gt215_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gt215_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gt215_ce_new, + .disp = gt215_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = gt215_gr_new, + .mspdec = gt215_mspdec_new, + .msppp = gt215_msppp_new, + .msvld = gt215_msvld_new, + .pm = gt215_pm_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nvaa_chipset = { + .name = "MCP77/MCP78", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = mcp77_clk_new, + .devinit = g98_devinit_new, + .fb = mcp77_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = g94_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = gt200_gr_new, + .mspdec = g98_mspdec_new, + .msppp = g98_msppp_new, + .msvld = g98_msvld_new, + .pm = g84_pm_new, + .sec = g98_sec_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nvac_chipset = { + .name = "MCP79/MCP7A", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = mcp77_clk_new, + .devinit = g98_devinit_new, + .fb = mcp77_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = g84_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .disp = g94_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = mcp79_gr_new, + .mspdec = g98_mspdec_new, + .msppp = g98_msppp_new, + .msvld = g98_msvld_new, + .pm = g84_pm_new, + .sec = g98_sec_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nvaf_chipset = { + .name = "MCP89", + .bar = g84_bar_new, + .bios = nvkm_bios_new, + .bus = g94_bus_new, + .clk = gt215_clk_new, + .devinit = mcp89_devinit_new, + .fb = mcp89_fb_new, + .fuse = nv50_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .imem = nv50_instmem_new, + .mc = g98_mc_new, + .mmu = nv50_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gt215_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gt215_ce_new, + .disp = gt215_disp_new, + .dma = nv50_dma_new, + .fifo = g84_fifo_new, + .gr = mcp89_gr_new, + .mspdec = gt215_mspdec_new, + .msppp = gt215_msppp_new, + .msvld = mcp89_msvld_new, + .pm = gt215_pm_new, + .sw = nv50_sw_new, +}; + +static const struct nvkm_device_chip +nvc0_chipset = { + .name = "GF100", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = gf100_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .ce[1] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf100_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf100_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvc1_chipset = { + .name = "GF108", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf108_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf108_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvc3_chipset = { + .name = "GF106", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf104_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf100_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvc4_chipset = { + .name = "GF104", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = gf100_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .ce[1] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf104_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf100_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvc8_chipset = { + .name = "GF110", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = gf100_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .ce[1] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf110_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf100_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvce_chipset = { + .name = "GF114", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = gf100_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .ce[1] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf104_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf100_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvcf_chipset = { + .name = "GF116", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = g94_gpio_new, + .i2c = g94_i2c_new, + .ibus = gf100_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gf100_pmu_new, + .therm = gt215_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .disp = gt215_disp_new, + .dma = gf100_dma_new, + .fifo = gf100_fifo_new, + .gr = gf104_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf100_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvd7_chipset = { + .name = "GF117", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = gf119_gpio_new, + .i2c = gf117_i2c_new, + .ibus = gf117_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .ce[0] = gf100_ce_new, + .disp = gf119_disp_new, + .dma = gf119_dma_new, + .fifo = gf100_fifo_new, + .gr = gf117_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf117_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvd9_chipset = { + .name = "GF119", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gf100_clk_new, + .devinit = gf100_devinit_new, + .fb = gf100_fb_new, + .fuse = gf100_fuse_new, + .gpio = gf119_gpio_new, + .i2c = gf119_i2c_new, + .ibus = gf117_ibus_new, + .imem = nv50_instmem_new, + .ltc = gf100_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gf119_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = nv40_volt_new, + .ce[0] = gf100_ce_new, + .disp = gf119_disp_new, + .dma = gf119_dma_new, + .fifo = gf100_fifo_new, + .gr = gf119_gr_new, + .mspdec = gf100_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gf100_msvld_new, + .pm = gf117_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nve4_chipset = { + .name = "GK104", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gk104_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk104_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk104_disp_new, + .dma = gf119_dma_new, + .fifo = gk104_fifo_new, + .gr = gk104_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .pm = gk104_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nve6_chipset = { + .name = "GK106", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gk104_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk104_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk104_disp_new, + .dma = gf119_dma_new, + .fifo = gk104_fifo_new, + .gr = gk104_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .pm = gk104_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nve7_chipset = { + .name = "GK107", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gk104_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk104_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk104_disp_new, + .dma = gf119_dma_new, + .fifo = gk104_fifo_new, + .gr = gk104_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .pm = gk104_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvea_chipset = { + .name = "GK20A", + .bar = gk20a_bar_new, + .bus = gf100_bus_new, + .clk = gk20a_clk_new, + .fb = gk20a_fb_new, + .fuse = gf100_fuse_new, + .ibus = gk20a_ibus_new, + .imem = gk20a_instmem_new, + .ltc = gk104_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .pmu = gk20a_pmu_new, + .timer = gk20a_timer_new, + .volt = gk20a_volt_new, + .ce[2] = gk104_ce_new, + .dma = gf119_dma_new, + .fifo = gk20a_fifo_new, + .gr = gk20a_gr_new, + .pm = gk104_pm_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvf0_chipset = { + .name = "GK110", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gk104_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk110_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk110_disp_new, + .dma = gf119_dma_new, + .fifo = gk104_fifo_new, + .gr = gk110_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nvf1_chipset = { + .name = "GK110B", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gf119_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gf100_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk110_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk110_disp_new, + .dma = gf119_dma_new, + .fifo = gk104_fifo_new, + .gr = gk110b_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nv106_chipset = { + .name = "GK208B", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gk104_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk208_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk110_disp_new, + .dma = gf119_dma_new, + .fifo = gk208_fifo_new, + .gr = gk208_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nv108_chipset = { + .name = "GK208", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gf100_devinit_new, + .fb = gk104_fb_new, + .fuse = gf100_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gk104_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gk104_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gk208_pmu_new, + .therm = gf119_therm_new, + .timer = nv41_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[1] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gk110_disp_new, + .dma = gf119_dma_new, + .fifo = gk208_fifo_new, + .gr = gk208_gr_new, + .mspdec = gk104_mspdec_new, + .msppp = gf100_msppp_new, + .msvld = gk104_msvld_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nv117_chipset = { + .name = "GM107", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .clk = gk104_clk_new, + .devinit = gm107_devinit_new, + .fb = gm107_fb_new, + .fuse = gm107_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gf119_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gm107_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gm107_pmu_new, + .therm = gm107_therm_new, + .timer = gk20a_timer_new, + .volt = gk104_volt_new, + .ce[0] = gk104_ce_new, + .ce[2] = gk104_ce_new, + .disp = gm107_disp_new, + .dma = gf119_dma_new, + .fifo = gk208_fifo_new, + .gr = gm107_gr_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nv124_chipset = { + .name = "GM204", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .devinit = gm204_devinit_new, + .fb = gm107_fb_new, + .fuse = gm107_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gm204_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gm107_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gm107_pmu_new, + .timer = gk20a_timer_new, + .volt = gk104_volt_new, + .ce[0] = gm204_ce_new, + .ce[1] = gm204_ce_new, + .ce[2] = gm204_ce_new, + .disp = gm204_disp_new, + .dma = gf119_dma_new, + .fifo = gm204_fifo_new, + .gr = gm204_gr_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nv126_chipset = { + .name = "GM206", + .bar = gf100_bar_new, + .bios = nvkm_bios_new, + .bus = gf100_bus_new, + .devinit = gm204_devinit_new, + .fb = gm107_fb_new, + .fuse = gm107_fuse_new, + .gpio = gk104_gpio_new, + .i2c = gm204_i2c_new, + .ibus = gk104_ibus_new, + .imem = nv50_instmem_new, + .ltc = gm107_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .mxm = nv50_mxm_new, + .pci = g94_pci_new, + .pmu = gm107_pmu_new, + .timer = gk20a_timer_new, + .volt = gk104_volt_new, + .ce[0] = gm204_ce_new, + .ce[1] = gm204_ce_new, + .ce[2] = gm204_ce_new, + .disp = gm204_disp_new, + .dma = gf119_dma_new, + .fifo = gm204_fifo_new, + .gr = gm206_gr_new, + .sw = gf100_sw_new, +}; + +static const struct nvkm_device_chip +nv12b_chipset = { + .name = "GM20B", + .bar = gk20a_bar_new, + .bus = gf100_bus_new, + .fb = gk20a_fb_new, + .fuse = gm107_fuse_new, + .ibus = gk20a_ibus_new, + .imem = gk20a_instmem_new, + .ltc = gm107_ltc_new, + .mc = gk20a_mc_new, + .mmu = gf100_mmu_new, + .timer = gk20a_timer_new, + .ce[2] = gm204_ce_new, + .dma = gf119_dma_new, + .fifo = gm20b_fifo_new, + .gr = gm20b_gr_new, + .sw = gf100_sw_new, }; static int -nvkm_devobj_info(struct nvkm_object *object, void *data, u32 size) +nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) { - struct nvkm_device *device = nv_device(object); - struct nvkm_fb *pfb = nvkm_fb(device); - struct nvkm_instmem *imem = nvkm_instmem(device); - union { - struct nv_device_info_v0 v0; - } *args = data; - int ret; - - nv_ioctl(object, "device info size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "device info vers %d\n", args->v0.version); - } else - return ret; + if (!WARN_ON(size != 0)) { + notify->size = 0; + notify->types = 1; + notify->index = 0; + return 0; + } + return -EINVAL; +} - switch (device->chipset) { - case 0x01a: - case 0x01f: - case 0x04c: - case 0x04e: - case 0x063: - case 0x067: - case 0x068: - case 0x0aa: - case 0x0ac: - case 0x0af: - args->v0.platform = NV_DEVICE_INFO_V0_IGP; - break; +static const struct nvkm_event_func +nvkm_device_event_func = { + .ctor = nvkm_device_event_ctor, +}; + +struct nvkm_subdev * +nvkm_device_subdev(struct nvkm_device *device, int index) +{ + struct nvkm_engine *engine; + + if (device->disable_mask & (1ULL << index)) + return NULL; + + switch (index) { +#define _(n,p,m) case NVKM_SUBDEV_##n: if (p) return (m); break + _(BAR , device->bar , &device->bar->subdev); + _(VBIOS , device->bios , &device->bios->subdev); + _(BUS , device->bus , &device->bus->subdev); + _(CLK , device->clk , &device->clk->subdev); + _(DEVINIT, device->devinit, &device->devinit->subdev); + _(FB , device->fb , &device->fb->subdev); + _(FUSE , device->fuse , &device->fuse->subdev); + _(GPIO , device->gpio , &device->gpio->subdev); + _(I2C , device->i2c , &device->i2c->subdev); + _(IBUS , device->ibus , device->ibus); + _(INSTMEM, device->imem , &device->imem->subdev); + _(LTC , device->ltc , &device->ltc->subdev); + _(MC , device->mc , &device->mc->subdev); + _(MMU , device->mmu , &device->mmu->subdev); + _(MXM , device->mxm , device->mxm); + _(PCI , device->pci , &device->pci->subdev); + _(PMU , device->pmu , &device->pmu->subdev); + _(THERM , device->therm , &device->therm->subdev); + _(TIMER , device->timer , &device->timer->subdev); + _(VOLT , device->volt , &device->volt->subdev); +#undef _ default: - if (device->pdev) { - if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP)) - args->v0.platform = NV_DEVICE_INFO_V0_AGP; - else - if (pci_is_pcie(device->pdev)) - args->v0.platform = NV_DEVICE_INFO_V0_PCIE; - else - args->v0.platform = NV_DEVICE_INFO_V0_PCI; - } else { - args->v0.platform = NV_DEVICE_INFO_V0_SOC; - } + engine = nvkm_device_engine(device, index); + if (engine) + return &engine->subdev; break; } + return NULL; +} - switch (device->card_type) { - case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break; - case NV_10: - case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break; - case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break; - case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break; - case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break; - case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break; - case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break; - case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break; - case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break; +struct nvkm_engine * +nvkm_device_engine(struct nvkm_device *device, int index) +{ + if (device->disable_mask & (1ULL << index)) + return NULL; + + switch (index) { +#define _(n,p,m) case NVKM_ENGINE_##n: if (p) return (m); break + _(BSP , device->bsp , device->bsp); + _(CE0 , device->ce[0] , device->ce[0]); + _(CE1 , device->ce[1] , device->ce[1]); + _(CE2 , device->ce[2] , device->ce[2]); + _(CIPHER , device->cipher , device->cipher); + _(DISP , device->disp , &device->disp->engine); + _(DMAOBJ , device->dma , &device->dma->engine); + _(FIFO , device->fifo , &device->fifo->engine); + _(GR , device->gr , &device->gr->engine); + _(IFB , device->ifb , device->ifb); + _(ME , device->me , device->me); + _(MPEG , device->mpeg , device->mpeg); + _(MSENC , device->msenc , device->msenc); + _(MSPDEC , device->mspdec , device->mspdec); + _(MSPPP , device->msppp , device->msppp); + _(MSVLD , device->msvld , device->msvld); + _(PM , device->pm , &device->pm->engine); + _(SEC , device->sec , device->sec); + _(SW , device->sw , &device->sw->engine); + _(VIC , device->vic , device->vic); + _(VP , device->vp , device->vp); +#undef _ default: - args->v0.family = 0; + WARN_ON(1); break; } + return NULL; +} + +int +nvkm_device_fini(struct nvkm_device *device, bool suspend) +{ + const char *action = suspend ? "suspend" : "fini"; + struct nvkm_subdev *subdev; + int ret, i; + s64 time; + + nvdev_trace(device, "%s running...\n", action); + time = ktime_to_us(ktime_get()); + + nvkm_acpi_fini(device); + + for (i = NVKM_SUBDEV_NR - 1; i >= 0; i--) { + if ((subdev = nvkm_device_subdev(device, i))) { + ret = nvkm_subdev_fini(subdev, suspend); + if (ret && suspend) + goto fail; + } + } - args->v0.chipset = device->chipset; - args->v0.revision = device->chiprev; - if (pfb && pfb->ram) - args->v0.ram_size = args->v0.ram_user = pfb->ram->size; - else - args->v0.ram_size = args->v0.ram_user = 0; - if (imem && args->v0.ram_size > 0) - args->v0.ram_user = args->v0.ram_user - imem->reserved; + if (device->func->fini) + device->func->fini(device, suspend); + + time = ktime_to_us(ktime_get()) - time; + nvdev_trace(device, "%s completed in %lldus...\n", action, time); return 0; + +fail: + do { + if ((subdev = nvkm_device_subdev(device, i))) { + int rret = nvkm_subdev_init(subdev); + if (rret) + nvkm_fatal(subdev, "failed restart, %d\n", ret); + } + } while (++i < NVKM_SUBDEV_NR); + + nvdev_trace(device, "%s failed with %d\n", action, ret); + return ret; } static int -nvkm_devobj_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +nvkm_device_preinit(struct nvkm_device *device) { - switch (mthd) { - case NV_DEVICE_V0_INFO: - return nvkm_devobj_info(object, data, size); - default: - break; + struct nvkm_subdev *subdev; + int ret, i; + s64 time; + + nvdev_trace(device, "preinit running...\n"); + time = ktime_to_us(ktime_get()); + + if (device->func->preinit) { + ret = device->func->preinit(device); + if (ret) + goto fail; } - return -EINVAL; -} -static u8 -nvkm_devobj_rd08(struct nvkm_object *object, u64 addr) -{ - return nv_rd08(object->engine, addr); -} + for (i = 0; i < NVKM_SUBDEV_NR; i++) { + if ((subdev = nvkm_device_subdev(device, i))) { + ret = nvkm_subdev_preinit(subdev); + if (ret) + goto fail; + } + } -static u16 -nvkm_devobj_rd16(struct nvkm_object *object, u64 addr) -{ - return nv_rd16(object->engine, addr); -} + ret = nvkm_devinit_post(device->devinit, &device->disable_mask); + if (ret) + goto fail; -static u32 -nvkm_devobj_rd32(struct nvkm_object *object, u64 addr) -{ - return nv_rd32(object->engine, addr); -} + time = ktime_to_us(ktime_get()) - time; + nvdev_trace(device, "preinit completed in %lldus\n", time); + return 0; -static void -nvkm_devobj_wr08(struct nvkm_object *object, u64 addr, u8 data) -{ - nv_wr08(object->engine, addr, data); +fail: + nvdev_error(device, "preinit failed with %d\n", ret); + return ret; } -static void -nvkm_devobj_wr16(struct nvkm_object *object, u64 addr, u16 data) +int +nvkm_device_init(struct nvkm_device *device) { - nv_wr16(object->engine, addr, data); -} + struct nvkm_subdev *subdev; + int ret, i; + s64 time; -static void -nvkm_devobj_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - nv_wr32(object->engine, addr, data); -} + ret = nvkm_device_preinit(device); + if (ret) + return ret; -static int -nvkm_devobj_map(struct nvkm_object *object, u64 *addr, u32 *size) -{ - struct nvkm_device *device = nv_device(object); - *addr = nv_device_resource_start(device, 0); - *size = nv_device_resource_len(device, 0); + nvkm_device_fini(device, false); + + nvdev_trace(device, "init running...\n"); + time = ktime_to_us(ktime_get()); + + if (device->func->init) { + ret = device->func->init(device); + if (ret) + goto fail; + } + + for (i = 0; i < NVKM_SUBDEV_NR; i++) { + if ((subdev = nvkm_device_subdev(device, i))) { + ret = nvkm_subdev_init(subdev); + if (ret) + goto fail_subdev; + } + } + + nvkm_acpi_init(device); + + time = ktime_to_us(ktime_get()) - time; + nvdev_trace(device, "init completed in %lldus\n", time); return 0; + +fail_subdev: + do { + if ((subdev = nvkm_device_subdev(device, i))) + nvkm_subdev_fini(subdev, false); + } while (--i >= 0); + +fail: + nvdev_error(device, "init failed with %d\n", ret); + return ret; } -static const u64 disable_map[] = { - [NVDEV_SUBDEV_VBIOS] = NV_DEVICE_V0_DISABLE_VBIOS, - [NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_GPIO] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_I2C] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_CLK ] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_MXM] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_MC] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_BUS] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_TIMER] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_FB] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_LTC] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_IBUS] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_MMU] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_BAR] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_VOLT] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_THERM] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_PMU] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_SUBDEV_FUSE] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_ENGINE_PM ] = NV_DEVICE_V0_DISABLE_CORE, - [NVDEV_ENGINE_FIFO] = NV_DEVICE_V0_DISABLE_FIFO, - [NVDEV_ENGINE_SW] = NV_DEVICE_V0_DISABLE_FIFO, - [NVDEV_ENGINE_GR] = NV_DEVICE_V0_DISABLE_GR, - [NVDEV_ENGINE_MPEG] = NV_DEVICE_V0_DISABLE_MPEG, - [NVDEV_ENGINE_ME] = NV_DEVICE_V0_DISABLE_ME, - [NVDEV_ENGINE_VP] = NV_DEVICE_V0_DISABLE_VP, - [NVDEV_ENGINE_CIPHER] = NV_DEVICE_V0_DISABLE_CIPHER, - [NVDEV_ENGINE_BSP] = NV_DEVICE_V0_DISABLE_BSP, - [NVDEV_ENGINE_MSPPP] = NV_DEVICE_V0_DISABLE_MSPPP, - [NVDEV_ENGINE_CE0] = NV_DEVICE_V0_DISABLE_CE0, - [NVDEV_ENGINE_CE1] = NV_DEVICE_V0_DISABLE_CE1, - [NVDEV_ENGINE_CE2] = NV_DEVICE_V0_DISABLE_CE2, - [NVDEV_ENGINE_VIC] = NV_DEVICE_V0_DISABLE_VIC, - [NVDEV_ENGINE_MSENC] = NV_DEVICE_V0_DISABLE_MSENC, - [NVDEV_ENGINE_DISP] = NV_DEVICE_V0_DISABLE_DISP, - [NVDEV_ENGINE_MSVLD] = NV_DEVICE_V0_DISABLE_MSVLD, - [NVDEV_ENGINE_SEC] = NV_DEVICE_V0_DISABLE_SEC, - [NVDEV_SUBDEV_NR] = 0, -}; - -static void -nvkm_devobj_dtor(struct nvkm_object *object) +void +nvkm_device_del(struct nvkm_device **pdevice) { - struct nvkm_devobj *devobj = (void *)object; + struct nvkm_device *device = *pdevice; int i; + if (device) { + mutex_lock(&nv_devices_mutex); + device->disable_mask = 0; + for (i = NVKM_SUBDEV_NR - 1; i >= 0; i--) { + struct nvkm_subdev *subdev = + nvkm_device_subdev(device, i); + nvkm_subdev_del(&subdev); + } - for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) - nvkm_object_ref(NULL, &devobj->subdev[i]); + nvkm_event_fini(&device->event); - nvkm_parent_destroy(&devobj->base); -} + if (device->pri) + iounmap(device->pri); + list_del(&device->head); -static struct nvkm_oclass -nvkm_devobj_oclass_super = { - .handle = NV_DEVICE, - .ofuncs = &(struct nvkm_ofuncs) { - .dtor = nvkm_devobj_dtor, - .init = _nvkm_parent_init, - .fini = _nvkm_parent_fini, - .mthd = nvkm_devobj_mthd, - .map = nvkm_devobj_map, - .rd08 = nvkm_devobj_rd08, - .rd16 = nvkm_devobj_rd16, - .rd32 = nvkm_devobj_rd32, - .wr08 = nvkm_devobj_wr08, - .wr16 = nvkm_devobj_wr16, - .wr32 = nvkm_devobj_wr32, + if (device->func->dtor) + *pdevice = device->func->dtor(device); + mutex_unlock(&nv_devices_mutex); + + kfree(*pdevice); + *pdevice = NULL; } -}; +} -static int -nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nvkm_device_ctor(const struct nvkm_device_func *func, + const struct nvkm_device_quirk *quirk, + struct device *dev, enum nvkm_device_type type, u64 handle, + const char *name, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device *device) { - union { - struct nv_device_v0 v0; - } *args = data; - struct nvkm_client *client = nv_client(parent); - struct nvkm_device *device; - struct nvkm_devobj *devobj; + struct nvkm_subdev *subdev; + u64 mmio_base, mmio_size; u32 boot0, strap; - u64 disable, mmio_base, mmio_size; void __iomem *map; - int ret, i, c; - - nv_ioctl(parent, "create device size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create device v%d device %016llx " - "disable %016llx debug0 %016llx\n", - args->v0.version, args->v0.device, - args->v0.disable, args->v0.debug0); - } else - return ret; + int ret = -EEXIST; + int i; - /* give priviledged clients register access */ - if (client->super) - oclass = &nvkm_devobj_oclass_super; + mutex_lock(&nv_devices_mutex); + if (nvkm_device_find_locked(handle)) + goto done; - /* find the device subdev that matches what the client requested */ - device = nv_device(client->device); - if (args->v0.device != ~0) { - device = nvkm_device_find(args->v0.device); - if (!device) - return -ENODEV; - } + device->func = func; + device->quirk = quirk; + device->dev = dev; + device->type = type; + device->handle = handle; + device->cfgopt = cfg; + device->dbgopt = dbg; + device->name = name; + list_add_tail(&device->head, &nv_devices); + device->debug = nvkm_dbgopt(device->dbgopt, "device"); - ret = nvkm_parent_create(parent, nv_object(device), oclass, 0, - nvkm_control_oclass, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_FIFO) | - (1ULL << NVDEV_ENGINE_DISP) | - (1ULL << NVDEV_ENGINE_PM), &devobj); - *pobject = nv_object(devobj); + ret = nvkm_event_init(&nvkm_device_event_func, 1, 1, &device->event); if (ret) - return ret; - - mmio_base = nv_device_resource_start(device, 0); - mmio_size = nv_device_resource_len(device, 0); + goto done; - /* translate api disable mask into internal mapping */ - disable = args->v0.debug0; - for (i = 0; i < NVDEV_SUBDEV_NR; i++) { - if (args->v0.disable & disable_map[i]) - disable |= (1ULL << i); - } + mmio_base = device->func->resource_addr(device, 0); + mmio_size = device->func->resource_size(device, 0); /* identify the chipset, and determine classes of subdev/engines */ - if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY) && - !device->card_type) { + if (detect) { map = ioremap(mmio_base, 0x102000); - if (map == NULL) - return -ENOMEM; + if (ret = -ENOMEM, map == NULL) + goto done; /* switch mmio to cpu's native endianness */ #ifndef __BIG_ENDIAN @@ -397,31 +2392,83 @@ nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, device->card_type = NV_04; } - switch (device->card_type) { - case NV_04: ret = nv04_identify(device); break; - case NV_10: - case NV_11: ret = nv10_identify(device); break; - case NV_20: ret = nv20_identify(device); break; - case NV_30: ret = nv30_identify(device); break; - case NV_40: ret = nv40_identify(device); break; - case NV_50: ret = nv50_identify(device); break; - case NV_C0: ret = gf100_identify(device); break; - case NV_E0: ret = gk104_identify(device); break; - case GM100: ret = gm100_identify(device); break; + switch (device->chipset) { + case 0x004: device->chip = &nv4_chipset; break; + case 0x005: device->chip = &nv5_chipset; break; + case 0x010: device->chip = &nv10_chipset; break; + case 0x011: device->chip = &nv11_chipset; break; + case 0x015: device->chip = &nv15_chipset; break; + case 0x017: device->chip = &nv17_chipset; break; + case 0x018: device->chip = &nv18_chipset; break; + case 0x01a: device->chip = &nv1a_chipset; break; + case 0x01f: device->chip = &nv1f_chipset; break; + case 0x020: device->chip = &nv20_chipset; break; + case 0x025: device->chip = &nv25_chipset; break; + case 0x028: device->chip = &nv28_chipset; break; + case 0x02a: device->chip = &nv2a_chipset; break; + case 0x030: device->chip = &nv30_chipset; break; + case 0x031: device->chip = &nv31_chipset; break; + case 0x034: device->chip = &nv34_chipset; break; + case 0x035: device->chip = &nv35_chipset; break; + case 0x036: device->chip = &nv36_chipset; break; + case 0x040: device->chip = &nv40_chipset; break; + case 0x041: device->chip = &nv41_chipset; break; + case 0x042: device->chip = &nv42_chipset; break; + case 0x043: device->chip = &nv43_chipset; break; + case 0x044: device->chip = &nv44_chipset; break; + case 0x045: device->chip = &nv45_chipset; break; + case 0x046: device->chip = &nv46_chipset; break; + case 0x047: device->chip = &nv47_chipset; break; + case 0x049: device->chip = &nv49_chipset; break; + case 0x04a: device->chip = &nv4a_chipset; break; + case 0x04b: device->chip = &nv4b_chipset; break; + case 0x04c: device->chip = &nv4c_chipset; break; + case 0x04e: device->chip = &nv4e_chipset; break; + case 0x050: device->chip = &nv50_chipset; break; + case 0x063: device->chip = &nv63_chipset; break; + case 0x067: device->chip = &nv67_chipset; break; + case 0x068: device->chip = &nv68_chipset; break; + case 0x084: device->chip = &nv84_chipset; break; + case 0x086: device->chip = &nv86_chipset; break; + case 0x092: device->chip = &nv92_chipset; break; + case 0x094: device->chip = &nv94_chipset; break; + case 0x096: device->chip = &nv96_chipset; break; + case 0x098: device->chip = &nv98_chipset; break; + case 0x0a0: device->chip = &nva0_chipset; break; + case 0x0a3: device->chip = &nva3_chipset; break; + case 0x0a5: device->chip = &nva5_chipset; break; + case 0x0a8: device->chip = &nva8_chipset; break; + case 0x0aa: device->chip = &nvaa_chipset; break; + case 0x0ac: device->chip = &nvac_chipset; break; + case 0x0af: device->chip = &nvaf_chipset; break; + case 0x0c0: device->chip = &nvc0_chipset; break; + case 0x0c1: device->chip = &nvc1_chipset; break; + case 0x0c3: device->chip = &nvc3_chipset; break; + case 0x0c4: device->chip = &nvc4_chipset; break; + case 0x0c8: device->chip = &nvc8_chipset; break; + case 0x0ce: device->chip = &nvce_chipset; break; + case 0x0cf: device->chip = &nvcf_chipset; break; + case 0x0d7: device->chip = &nvd7_chipset; break; + case 0x0d9: device->chip = &nvd9_chipset; break; + case 0x0e4: device->chip = &nve4_chipset; break; + case 0x0e6: device->chip = &nve6_chipset; break; + case 0x0e7: device->chip = &nve7_chipset; break; + case 0x0ea: device->chip = &nvea_chipset; break; + case 0x0f0: device->chip = &nvf0_chipset; break; + case 0x0f1: device->chip = &nvf1_chipset; break; + case 0x106: device->chip = &nv106_chipset; break; + case 0x108: device->chip = &nv108_chipset; break; + case 0x117: device->chip = &nv117_chipset; break; + case 0x124: device->chip = &nv124_chipset; break; + case 0x126: device->chip = &nv126_chipset; break; + case 0x12b: device->chip = &nv12b_chipset; break; default: - ret = -EINVAL; - break; - } - - if (ret) { - nv_error(device, "unknown chipset, 0x%08x\n", boot0); - return ret; + nvdev_error(device, "unknown chipset (%08x)\n", boot0); + goto done; } - nv_info(device, "BOOT0 : 0x%08x\n", boot0); - nv_info(device, "Chipset: %s (NV%02X)\n", - device->cname, device->chipset); - nv_info(device, "Family : NV%02X\n", device->card_type); + nvdev_info(device, "NVIDIA %s (%08x)\n", + device->chip->name, boot0); /* determine frequency of timing crystal */ if ( device->card_type <= NV_10 || device->chipset < 0x17 || @@ -436,300 +2483,89 @@ nvkm_devobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, case 0x00400000: device->crystal = 27000; break; case 0x00400040: device->crystal = 25000; break; } - - nv_debug(device, "crystal freq: %dKHz\n", device->crystal); - } else - if ( (args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY)) { - device->cname = "NULL"; - device->oclass[NVDEV_SUBDEV_VBIOS] = &nvkm_bios_oclass; - } - - if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_MMIO) && - !nv_subdev(device)->mmio) { - nv_subdev(device)->mmio = ioremap(mmio_base, mmio_size); - if (!nv_subdev(device)->mmio) { - nv_error(device, "unable to map device registers\n"); - return -ENOMEM; - } - } - - /* ensure requested subsystems are available for use */ - for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) { - if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) - continue; - - if (device->subdev[i]) { - nvkm_object_ref(device->subdev[i], &devobj->subdev[i]); - continue; - } - - ret = nvkm_object_ctor(nv_object(device), NULL, oclass, - NULL, i, &devobj->subdev[i]); - if (ret == -ENODEV) - continue; - if (ret) - return ret; - - device->subdev[i] = devobj->subdev[i]; - - /* note: can't init *any* subdevs until devinit has been run - * due to not knowing exactly what the vbios init tables will - * mess with. devinit also can't be run until all of its - * dependencies have been created. - * - * this code delays init of any subdev until all of devinit's - * dependencies have been created, and then initialises each - * subdev in turn as they're created. - */ - while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) { - struct nvkm_object *subdev = devobj->subdev[c++]; - if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) { - ret = nvkm_object_inc(subdev); - if (ret) - return ret; - atomic_dec(&nv_object(device)->usecount); - } else - if (subdev) { - nvkm_subdev_reset(subdev); - } - } - } - - return 0; -} - -static struct nvkm_ofuncs -nvkm_devobj_ofuncs = { - .ctor = nvkm_devobj_ctor, - .dtor = nvkm_devobj_dtor, - .init = _nvkm_parent_init, - .fini = _nvkm_parent_fini, - .mthd = nvkm_devobj_mthd, -}; - -/****************************************************************************** - * nvkm_device: engine functions - *****************************************************************************/ - -struct nvkm_device * -nv_device(void *obj) -{ - struct nvkm_object *device = nv_object(obj); - if (device->engine == NULL) { - while (device && device->parent) - device = device->parent; } else { - device = &nv_object(obj)->engine->subdev.object; - if (device && device->parent) - device = device->parent; + device->chip = &null_chipset; } -#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA - if (unlikely(!device)) - nv_assert("BAD CAST -> NvDevice, 0x%08x\n", nv_hclass(obj)); -#endif - return (void *)device; -} -static struct nvkm_oclass -nvkm_device_sclass[] = { - { 0x0080, &nvkm_devobj_ofuncs }, - {} -}; + if (!device->name) + device->name = device->chip->name; -static int -nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - if (!WARN_ON(size != 0)) { - notify->size = 0; - notify->types = 1; - notify->index = 0; - return 0; - } - return -EINVAL; -} - -static const struct nvkm_event_func -nvkm_device_event_func = { - .ctor = nvkm_device_event_ctor, -}; - -static int -nvkm_device_fini(struct nvkm_object *object, bool suspend) -{ - struct nvkm_device *device = (void *)object; - struct nvkm_object *subdev; - int ret, i; - - for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) { - if ((subdev = device->subdev[i])) { - if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { - ret = nvkm_object_dec(subdev, suspend); - if (ret && suspend) - goto fail; - } - } - } - - ret = nvkm_acpi_fini(device, suspend); -fail: - for (; ret && i < NVDEV_SUBDEV_NR; i++) { - if ((subdev = device->subdev[i])) { - if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { - ret = nvkm_object_inc(subdev); - if (ret) { - /* XXX */ - } - } + if (mmio) { + device->pri = ioremap(mmio_base, mmio_size); + if (!device->pri) { + nvdev_error(device, "unable to map PRI\n"); + return -ENOMEM; } } - return ret; -} - -static int -nvkm_device_init(struct nvkm_object *object) -{ - struct nvkm_device *device = (void *)object; - struct nvkm_object *subdev; - int ret, i = 0; - - ret = nvkm_acpi_init(device); - if (ret) - goto fail; - - for (i = 0; i < NVDEV_SUBDEV_NR; i++) { - if ((subdev = device->subdev[i])) { - if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { - ret = nvkm_object_inc(subdev); - if (ret) - goto fail; - } else { - nvkm_subdev_reset(subdev); - } + mutex_init(&device->mutex); + + for (i = 0; i < NVKM_SUBDEV_NR; i++) { +#define _(s,m) case s: \ + if (device->chip->m && (subdev_mask & (1ULL << (s)))) { \ + ret = device->chip->m(device, (s), &device->m); \ + if (ret) { \ + subdev = nvkm_device_subdev(device, (s)); \ + nvkm_subdev_del(&subdev); \ + device->m = NULL; \ + if (ret != -ENODEV) { \ + nvdev_error(device, "%s ctor failed, %d\n", \ + nvkm_subdev_name[s], ret); \ + goto done; \ + } \ + } \ + } \ + break + switch (i) { + _(NVKM_SUBDEV_BAR , bar); + _(NVKM_SUBDEV_VBIOS , bios); + _(NVKM_SUBDEV_BUS , bus); + _(NVKM_SUBDEV_CLK , clk); + _(NVKM_SUBDEV_DEVINIT, devinit); + _(NVKM_SUBDEV_FB , fb); + _(NVKM_SUBDEV_FUSE , fuse); + _(NVKM_SUBDEV_GPIO , gpio); + _(NVKM_SUBDEV_I2C , i2c); + _(NVKM_SUBDEV_IBUS , ibus); + _(NVKM_SUBDEV_INSTMEM, imem); + _(NVKM_SUBDEV_LTC , ltc); + _(NVKM_SUBDEV_MC , mc); + _(NVKM_SUBDEV_MMU , mmu); + _(NVKM_SUBDEV_MXM , mxm); + _(NVKM_SUBDEV_PCI , pci); + _(NVKM_SUBDEV_PMU , pmu); + _(NVKM_SUBDEV_THERM , therm); + _(NVKM_SUBDEV_TIMER , timer); + _(NVKM_SUBDEV_VOLT , volt); + _(NVKM_ENGINE_BSP , bsp); + _(NVKM_ENGINE_CE0 , ce[0]); + _(NVKM_ENGINE_CE1 , ce[1]); + _(NVKM_ENGINE_CE2 , ce[2]); + _(NVKM_ENGINE_CIPHER , cipher); + _(NVKM_ENGINE_DISP , disp); + _(NVKM_ENGINE_DMAOBJ , dma); + _(NVKM_ENGINE_FIFO , fifo); + _(NVKM_ENGINE_GR , gr); + _(NVKM_ENGINE_IFB , ifb); + _(NVKM_ENGINE_ME , me); + _(NVKM_ENGINE_MPEG , mpeg); + _(NVKM_ENGINE_MSENC , msenc); + _(NVKM_ENGINE_MSPDEC , mspdec); + _(NVKM_ENGINE_MSPPP , msppp); + _(NVKM_ENGINE_MSVLD , msvld); + _(NVKM_ENGINE_PM , pm); + _(NVKM_ENGINE_SEC , sec); + _(NVKM_ENGINE_SW , sw); + _(NVKM_ENGINE_VIC , vic); + _(NVKM_ENGINE_VP , vp); + default: + WARN_ON(1); + continue; } +#undef _ } ret = 0; -fail: - for (--i; ret && i >= 0; i--) { - if ((subdev = device->subdev[i])) { - if (!nv_iclass(subdev, NV_ENGINE_CLASS)) - nvkm_object_dec(subdev, false); - } - } - - if (ret) - nvkm_acpi_fini(device, false); - return ret; -} - -static void -nvkm_device_dtor(struct nvkm_object *object) -{ - struct nvkm_device *device = (void *)object; - - nvkm_event_fini(&device->event); - - mutex_lock(&nv_devices_mutex); - list_del(&device->head); - mutex_unlock(&nv_devices_mutex); - - if (nv_subdev(device)->mmio) - iounmap(nv_subdev(device)->mmio); - - nvkm_engine_destroy(&device->engine); -} - -resource_size_t -nv_device_resource_start(struct nvkm_device *device, unsigned int bar) -{ - if (nv_device_is_pci(device)) { - return pci_resource_start(device->pdev, bar); - } else { - struct resource *res; - res = platform_get_resource(device->platformdev, - IORESOURCE_MEM, bar); - if (!res) - return 0; - return res->start; - } -} - -resource_size_t -nv_device_resource_len(struct nvkm_device *device, unsigned int bar) -{ - if (nv_device_is_pci(device)) { - return pci_resource_len(device->pdev, bar); - } else { - struct resource *res; - res = platform_get_resource(device->platformdev, - IORESOURCE_MEM, bar); - if (!res) - return 0; - return resource_size(res); - } -} - -int -nv_device_get_irq(struct nvkm_device *device, bool stall) -{ - if (nv_device_is_pci(device)) { - return device->pdev->irq; - } else { - return platform_get_irq_byname(device->platformdev, - stall ? "stall" : "nonstall"); - } -} - -static struct nvkm_oclass -nvkm_device_oclass = { - .handle = NV_ENGINE(DEVICE, 0x00), - .ofuncs = &(struct nvkm_ofuncs) { - .dtor = nvkm_device_dtor, - .init = nvkm_device_init, - .fini = nvkm_device_fini, - }, -}; - -int -nvkm_device_create_(void *dev, enum nv_bus_type type, u64 name, - const char *sname, const char *cfg, const char *dbg, - int length, void **pobject) -{ - struct nvkm_device *device; - int ret = -EEXIST; - - mutex_lock(&nv_devices_mutex); - list_for_each_entry(device, &nv_devices, head) { - if (device->handle == name) - goto done; - } - - ret = nvkm_engine_create_(NULL, NULL, &nvkm_device_oclass, true, - "DEVICE", "device", length, pobject); - device = *pobject; - if (ret) - goto done; - - switch (type) { - case NVKM_BUS_PCI: - device->pdev = dev; - break; - case NVKM_BUS_PLATFORM: - device->platformdev = dev; - break; - } - device->handle = name; - device->cfgopt = cfg; - device->dbgopt = dbg; - device->name = sname; - - nv_subdev(device)->debug = nvkm_dbgopt(device->dbgopt, "DEVICE"); - nv_engine(device)->sclass = nvkm_device_sclass; - list_add(&device->head, &nv_devices); - - ret = nvkm_event_init(&nvkm_device_event_func, 1, 1, &device->event); done: mutex_unlock(&nv_devices_mutex); return ret; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c index 0b794b13c..cf8bc068e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c @@ -21,7 +21,7 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ctrl.h" #include #include @@ -31,18 +31,18 @@ #include static int -nvkm_control_mthd_pstate_info(struct nvkm_object *object, void *data, u32 size) +nvkm_control_mthd_pstate_info(struct nvkm_control *ctrl, void *data, u32 size) { union { struct nvif_control_pstate_info_v0 v0; } *args = data; - struct nvkm_clk *clk = nvkm_clk(object); + struct nvkm_clk *clk = ctrl->device->clk; int ret; - nv_ioctl(object, "control pstate info size %d\n", size); + nvif_ioctl(&ctrl->object, "control pstate info size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "control pstate info vers %d\n", - args->v0.version); + nvif_ioctl(&ctrl->object, "control pstate info vers %d\n", + args->v0.version); } else return ret; @@ -64,24 +64,24 @@ nvkm_control_mthd_pstate_info(struct nvkm_object *object, void *data, u32 size) } static int -nvkm_control_mthd_pstate_attr(struct nvkm_object *object, void *data, u32 size) +nvkm_control_mthd_pstate_attr(struct nvkm_control *ctrl, void *data, u32 size) { union { struct nvif_control_pstate_attr_v0 v0; } *args = data; - struct nvkm_clk *clk = nvkm_clk(object); - struct nvkm_domain *domain; + struct nvkm_clk *clk = ctrl->device->clk; + const struct nvkm_domain *domain; struct nvkm_pstate *pstate; struct nvkm_cstate *cstate; int i = 0, j = -1; u32 lo, hi; int ret; - nv_ioctl(object, "control pstate attr size %d\n", size); + nvif_ioctl(&ctrl->object, "control pstate attr size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "control pstate attr vers %d state %d " - "index %d\n", - args->v0.version, args->v0.state, args->v0.index); + nvif_ioctl(&ctrl->object, + "control pstate attr vers %d state %d index %d\n", + args->v0.version, args->v0.state, args->v0.index); if (!clk) return -ENODEV; if (args->v0.state < NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT) @@ -116,7 +116,7 @@ nvkm_control_mthd_pstate_attr(struct nvkm_object *object, void *data, u32 size) args->v0.state = pstate->pstate; } else { - lo = max(clk->read(clk, domain->name), 0); + lo = max(nvkm_clk_read(clk, domain->name), 0); hi = lo; } @@ -137,19 +137,19 @@ nvkm_control_mthd_pstate_attr(struct nvkm_object *object, void *data, u32 size) } static int -nvkm_control_mthd_pstate_user(struct nvkm_object *object, void *data, u32 size) +nvkm_control_mthd_pstate_user(struct nvkm_control *ctrl, void *data, u32 size) { union { struct nvif_control_pstate_user_v0 v0; } *args = data; - struct nvkm_clk *clk = nvkm_clk(object); + struct nvkm_clk *clk = ctrl->device->clk; int ret; - nv_ioctl(object, "control pstate user size %d\n", size); + nvif_ioctl(&ctrl->object, "control pstate user size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "control pstate user vers %d ustate %d " - "pwrsrc %d\n", args->v0.version, - args->v0.ustate, args->v0.pwrsrc); + nvif_ioctl(&ctrl->object, + "control pstate user vers %d ustate %d pwrsrc %d\n", + args->v0.version, args->v0.ustate, args->v0.pwrsrc); if (!clk) return -ENODEV; } else @@ -168,32 +168,44 @@ nvkm_control_mthd_pstate_user(struct nvkm_object *object, void *data, u32 size) static int nvkm_control_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { + struct nvkm_control *ctrl = nvkm_control(object); switch (mthd) { case NVIF_CONTROL_PSTATE_INFO: - return nvkm_control_mthd_pstate_info(object, data, size); + return nvkm_control_mthd_pstate_info(ctrl, data, size); case NVIF_CONTROL_PSTATE_ATTR: - return nvkm_control_mthd_pstate_attr(object, data, size); + return nvkm_control_mthd_pstate_attr(ctrl, data, size); case NVIF_CONTROL_PSTATE_USER: - return nvkm_control_mthd_pstate_user(object, data, size); + return nvkm_control_mthd_pstate_user(ctrl, data, size); default: break; } return -EINVAL; } -static struct nvkm_ofuncs -nvkm_control_ofuncs = { - .ctor = _nvkm_object_ctor, - .dtor = nvkm_object_destroy, - .init = nvkm_object_init, - .fini = nvkm_object_fini, +static const struct nvkm_object_func +nvkm_control = { .mthd = nvkm_control_mthd, }; -struct nvkm_oclass -nvkm_control_oclass[] = { - { .handle = NVIF_IOCTL_NEW_V0_CONTROL, - .ofuncs = &nvkm_control_ofuncs - }, - {} +static int +nvkm_control_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_control *ctrl; + + if (!(ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL))) + return -ENOMEM; + *pobject = &ctrl->object; + ctrl->device = device; + + nvkm_object_ctor(&nvkm_control, oclass, &ctrl->object); + return 0; +} + +const struct nvkm_device_oclass +nvkm_control_oclass = { + .base.oclass = NVIF_IOCTL_NEW_V0_CONTROL, + .base.minver = -1, + .base.maxver = -1, + .ctor = nvkm_control_new, }; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h new file mode 100644 index 000000000..20249d8e4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h @@ -0,0 +1,12 @@ +#ifndef __NVKM_DEVICE_CTRL_H__ +#define __NVKM_DEVICE_CTRL_H__ +#define nvkm_control(p) container_of((p), struct nvkm_control, object) +#include + +struct nvkm_control { + struct nvkm_object object; + struct nvkm_device *device; +}; + +extern const struct nvkm_device_oclass nvkm_control_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gf100.c deleted file mode 100644 index 82b38d7e9..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gf100.c +++ /dev/null @@ -1,358 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -gf100_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0xc0: - device->cname = "GF100"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf100_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf100_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gf100_ce1_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xc4: - device->cname = "GF104"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf100_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf104_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gf100_ce1_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xc3: - device->cname = "GF106"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf104_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xce: - device->cname = "GF114"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf100_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf104_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gf100_ce1_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xcf: - device->cname = "GF116"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf104_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xc1: - device->cname = "GF108"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf108_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xc8: - device->cname = "GF110"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf100_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf100_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf100_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf110_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gf100_ce1_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xd9: - device->cname = "GF119"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gf110_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gf110_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf110_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf119_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gf110_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - case 0xd7: - device->cname = "GF117"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gf110_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gf117_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gf100_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gf100_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gf100_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gf100_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gf117_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gf100_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gf100_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gf100_ce0_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gf110_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gf100_pm_oclass; - break; - default: - nv_fatal(device, "unknown Fermi chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c deleted file mode 100644 index 6a9483f65..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c +++ /dev/null @@ -1,326 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -gk104_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0xe4: - device->cname = "GK104"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gk104_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk104_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk104_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk104_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gk104_pm_oclass; - break; - case 0xe7: - device->cname = "GK107"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gk104_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf110_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk104_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk104_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gk104_pm_oclass; - break; - case 0xe6: - device->cname = "GK106"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gk104_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk104_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk104_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk104_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gk104_pm_oclass; - break; - case 0xea: - device->cname = "GK20A"; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk20a_clk_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = gk20a_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gk20a_bar_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk20a_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk20a_gr_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gk104_pm_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &gk20a_volt_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk20a_pmu_oclass; - break; - case 0xf0: - device->cname = "GK110"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gk104_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk110_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk110_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk110_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gk110_pm_oclass; - break; - case 0xf1: - device->cname = "GK110B"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gf110_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gf106_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk110_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk110b_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk110_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = &gk110_pm_oclass; - break; - case 0x106: - device->cname = "GK208B"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gk104_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk208_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk208_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk208_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk110_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - break; - case 0x108: - device->cname = "GK208"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gk104_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gf110_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gf100_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gk104_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk208_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk208_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gk208_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gk110_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; - break; - default: - nv_fatal(device, "unknown Kepler chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c deleted file mode 100644 index 70abf1ec7..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c +++ /dev/null @@ -1,190 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -gm100_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x117: - device->cname = "GM107"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gf110_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gm107_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &gm107_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gm107_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gm107_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gm107_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk208_pmu_oclass; - -#if 0 - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; -#endif - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gk208_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gm107_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gm107_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gk104_ce0_oclass; -#if 0 - device->oclass[NVDEV_ENGINE_CE1 ] = &gk104_ce1_oclass; -#endif - device->oclass[NVDEV_ENGINE_CE2 ] = &gk104_ce2_oclass; -#if 0 - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; -#endif - break; - case 0x124: - device->cname = "GM204"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gm204_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gm107_fuse_oclass; -#if 0 - /* looks to be some non-trivial changes */ - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - /* priv ring says no to 0x10eb14 writes */ - device->oclass[NVDEV_SUBDEV_THERM ] = &gm107_therm_oclass; -#endif - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gm204_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gm107_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gm107_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk208_pmu_oclass; -#if 0 - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; -#endif - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gm204_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gm204_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gm204_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gm204_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gm204_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gm204_ce2_oclass; -#if 0 - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; -#endif - break; - case 0x126: - device->cname = "GM206"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = gk104_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = gm204_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &gm107_fuse_oclass; -#if 0 - /* looks to be some non-trivial changes */ - device->oclass[NVDEV_SUBDEV_CLK ] = &gk104_clk_oclass; - /* priv ring says no to 0x10eb14 writes */ - device->oclass[NVDEV_SUBDEV_THERM ] = &gm107_therm_oclass; -#endif - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gm204_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = gf100_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gm107_fb_oclass; - device->oclass[NVDEV_SUBDEV_LTC ] = gm107_ltc_oclass; - device->oclass[NVDEV_SUBDEV_IBUS ] = &gk104_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gk208_pmu_oclass; -#if 0 - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; -#endif - device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = gm204_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gm206_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gm204_disp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = &gm204_ce0_oclass; - device->oclass[NVDEV_ENGINE_CE1 ] = &gm204_ce1_oclass; - device->oclass[NVDEV_ENGINE_CE2 ] = &gm204_ce2_oclass; -#if 0 - device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; -#endif - break; - default: - nv_fatal(device, "unknown Maxwell chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv04.c deleted file mode 100644 index 5a2ae043b..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv04.c +++ /dev/null @@ -1,89 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -int -nv04_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x04: - device->cname = "NV04"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv04_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv04_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv04_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x05: - device->cname = "NV05"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv05_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv04_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv04_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - default: - nv_fatal(device, "unknown RIVA chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv10.c deleted file mode 100644 index 94a1ca45e..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv10.c +++ /dev/null @@ -1,204 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -int -nv10_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x10: - device->cname = "NV10"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x15: - device->cname = "NV15"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x16: - device->cname = "NV16"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x1a: - device->cname = "nForce"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x11: - device->cname = "NV11"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x17: - device->cname = "NV17"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x1f: - device->cname = "nForce2"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x18: - device->cname = "NV18"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv10_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - default: - nv_fatal(device, "unknown Celsius chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv20.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv20.c deleted file mode 100644 index d5ec8937d..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv20.c +++ /dev/null @@ -1,131 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -int -nv20_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x20: - device->cname = "NV20"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv20_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv20_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x25: - device->cname = "NV25"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv25_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x28: - device->cname = "NV28"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv25_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x2a: - device->cname = "NV2A"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv2a_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - default: - nv_fatal(device, "unknown Kelvin chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv30.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv30.c deleted file mode 100644 index dda09621e..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv30.c +++ /dev/null @@ -1,153 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -int -nv30_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x30: - device->cname = "NV30"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv30_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x35: - device->cname = "NV35"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv35_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv35_gr_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x31: - device->cname = "NV31"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv30_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x36: - device->cname = "NV36"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv36_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv35_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - case 0x34: - device->cname = "NV34"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv04_clk_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv34_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - break; - default: - nv_fatal(device, "unknown Rankine chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c deleted file mode 100644 index c6301361d..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c +++ /dev/null @@ -1,427 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -int -nv40_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x40: - device->cname = "NV40"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv40_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x41: - device->cname = "NV41"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv41_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv41_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x42: - device->cname = "NV42"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv41_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv41_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x43: - device->cname = "NV43"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv41_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv41_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x45: - device->cname = "NV45"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv40_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv04_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x47: - device->cname = "G70"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv47_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv41_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x49: - device->cname = "G71"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv49_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv41_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x4b: - device->cname = "G73"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv49_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv41_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x44: - device->cname = "NV44"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv44_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x46: - device->cname = "G72"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x4a: - device->cname = "NV44A"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv44_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x4c: - device->cname = "C61"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x4e: - device->cname = "C51"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv4e_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv4e_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x63: - device->cname = "C73"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x67: - device->cname = "C67"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - case 0x68: - device->cname = "C68"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv44_mmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv10_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv40_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv40_pm_oclass; - break; - default: - nv_fatal(device, "unknown Curie chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv50.c deleted file mode 100644 index 249b84454..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/nv50.c +++ /dev/null @@ -1,478 +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 "priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -nv50_identify(struct nvkm_device *device) -{ - switch (device->chipset) { - case 0x50: - device->cname = "G80"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = nv50_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = nv50_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = nv50_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = nv50_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = nv50_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = nv50_pm_oclass; - break; - case 0x84: - device->cname = "G84"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g84_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_VP ] = &g84_vp_oclass; - device->oclass[NVDEV_ENGINE_CIPHER ] = &g84_cipher_oclass; - device->oclass[NVDEV_ENGINE_BSP ] = &g84_bsp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g84_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0x86: - device->cname = "G86"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g84_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_VP ] = &g84_vp_oclass; - device->oclass[NVDEV_ENGINE_CIPHER ] = &g84_cipher_oclass; - device->oclass[NVDEV_ENGINE_BSP ] = &g84_bsp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g84_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0x92: - device->cname = "G92"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g84_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_VP ] = &g84_vp_oclass; - device->oclass[NVDEV_ENGINE_CIPHER ] = &g84_cipher_oclass; - device->oclass[NVDEV_ENGINE_BSP ] = &g84_bsp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g84_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0x94: - device->cname = "G94"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g84_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g94_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_VP ] = &g84_vp_oclass; - device->oclass[NVDEV_ENGINE_CIPHER ] = &g84_cipher_oclass; - device->oclass[NVDEV_ENGINE_BSP ] = &g84_bsp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g94_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0x96: - device->cname = "G96"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g84_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g94_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_VP ] = &g84_vp_oclass; - device->oclass[NVDEV_ENGINE_CIPHER ] = &g84_cipher_oclass; - device->oclass[NVDEV_ENGINE_BSP ] = &g84_bsp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g94_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0x98: - device->cname = "G98"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g98_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_SEC ] = &g98_sec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g94_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0xa0: - device->cname = "G200"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = g84_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g84_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = g84_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_VP ] = &g84_vp_oclass; - device->oclass[NVDEV_ENGINE_CIPHER ] = &g84_cipher_oclass; - device->oclass[NVDEV_ENGINE_BSP ] = &g84_bsp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt200_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0xaa: - device->cname = "MCP77/MCP78"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = mcp77_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g98_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = mcp77_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_SEC ] = &g98_sec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g94_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0xac: - device->cname = "MCP79/MCP7A"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = mcp77_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &g84_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = g98_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = mcp77_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_SEC ] = &g98_sec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = g94_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; - break; - case 0xa3: - device->cname = "GT215"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = >215_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gt215_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gt215_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gt215_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MPEG ] = &g84_mpeg_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = >215_ce_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = gt215_pm_oclass; - break; - case 0xa5: - device->cname = "GT216"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = >215_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gt215_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gt215_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gt215_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = >215_ce_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = gt215_pm_oclass; - break; - case 0xa8: - device->cname = "GT218"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = >215_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = gt215_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = gt215_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gt215_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = >215_ce_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = gt215_pm_oclass; - break; - case 0xaf: - device->cname = "MCP89"; - device->oclass[NVDEV_SUBDEV_VBIOS ] = &nvkm_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = g94_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = g94_i2c_oclass; - device->oclass[NVDEV_SUBDEV_FUSE ] = &nv50_fuse_oclass; - device->oclass[NVDEV_SUBDEV_CLK ] = >215_clk_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = >215_therm_oclass; - device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; - device->oclass[NVDEV_SUBDEV_DEVINIT] = mcp89_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = g98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = g94_bus_oclass; - device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; - device->oclass[NVDEV_SUBDEV_FB ] = mcp89_fb_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; - device->oclass[NVDEV_SUBDEV_MMU ] = &nv50_mmu_oclass; - device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gt215_pmu_oclass; - device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; - device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass; - device->oclass[NVDEV_ENGINE_FIFO ] = g84_fifo_oclass; - device->oclass[NVDEV_ENGINE_SW ] = nv50_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = &nv50_gr_oclass; - device->oclass[NVDEV_ENGINE_MSPDEC ] = &g98_mspdec_oclass; - device->oclass[NVDEV_ENGINE_MSVLD ] = &g98_msvld_oclass; - device->oclass[NVDEV_ENGINE_MSPPP ] = &g98_msppp_oclass; - device->oclass[NVDEV_ENGINE_CE0 ] = >215_ce_oclass; - device->oclass[NVDEV_ENGINE_DISP ] = gt215_disp_oclass; - device->oclass[NVDEV_ENGINE_PM ] = gt215_pm_oclass; - break; - default: - nv_fatal(device, "unknown Tesla chipset\n"); - return -EINVAL; - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c new file mode 100644 index 000000000..62ad0300c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c @@ -0,0 +1,1678 @@ +/* + * 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 + */ +#include +#include "priv.h" + +struct nvkm_device_pci_device { + u16 device; + const char *name; + const struct nvkm_device_pci_vendor *vendor; +}; + +struct nvkm_device_pci_vendor { + u16 vendor; + u16 device; + const char *name; + const struct nvkm_device_quirk quirk; +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0189[] = { + /* Apple iMac G4 NV18 */ + { 0x10de, 0x0010, NULL, { .tv_gpio = 4 } }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_01f0[] = { + /* MSI nForce2 IGP */ + { 0x1462, 0x5710, NULL, { .tv_pin_mask = 0xc } }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0322[] = { + /* Zotac FX5200 */ + { 0x19da, 0x1035, NULL, { .tv_pin_mask = 0xc } }, + { 0x19da, 0x2035, NULL, { .tv_pin_mask = 0xc } }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_05e7[] = { + { 0x10de, 0x0595, "Tesla T10 Processor" }, + { 0x10de, 0x068f, "Tesla T10 Processor" }, + { 0x10de, 0x0697, "Tesla M1060" }, + { 0x10de, 0x0714, "Tesla M1060" }, + { 0x10de, 0x0743, "Tesla M1060" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0609[] = { + { 0x106b, 0x00a7, "GeForce 8800 GS" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_062e[] = { + { 0x106b, 0x0605, "GeForce GT 130" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0649[] = { + { 0x1043, 0x202d, "GeForce GT 220M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0652[] = { + { 0x152d, 0x0850, "GeForce GT 240M LE" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0654[] = { + { 0x1043, 0x14a2, "GeForce GT 320M" }, + { 0x1043, 0x14d2, "GeForce GT 320M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0655[] = { + { 0x106b, 0x0633, "GeForce GT 120" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0656[] = { + { 0x106b, 0x0693, "GeForce GT 120" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_06d1[] = { + { 0x10de, 0x0771, "Tesla C2050" }, + { 0x10de, 0x0772, "Tesla C2070" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_06d2[] = { + { 0x10de, 0x088f, "Tesla X2070" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_06de[] = { + { 0x10de, 0x0773, "Tesla S2050" }, + { 0x10de, 0x082f, "Tesla M2050" }, + { 0x10de, 0x0840, "Tesla X2070" }, + { 0x10de, 0x0842, "Tesla M2050" }, + { 0x10de, 0x0846, "Tesla M2050" }, + { 0x10de, 0x0866, "Tesla M2050" }, + { 0x10de, 0x0907, "Tesla M2050" }, + { 0x10de, 0x091e, "Tesla M2050" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_06e8[] = { + { 0x103c, 0x360b, "GeForce 9200M GE" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_06f9[] = { + { 0x10de, 0x060d, "Quadro FX 370 Low Profile" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_06ff[] = { + { 0x10de, 0x0711, "HICx8 + Graphics" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0866[] = { + { 0x106b, 0x00b1, "GeForce 9400M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0872[] = { + { 0x1043, 0x1c42, "GeForce G205M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0873[] = { + { 0x1043, 0x1c52, "GeForce G205M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0a6e[] = { + { 0x17aa, 0x3607, "Second Generation ION" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0a70[] = { + { 0x17aa, 0x3605, "Second Generation ION" }, + { 0x17aa, 0x3617, "Second Generation ION" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0a73[] = { + { 0x17aa, 0x3607, "Second Generation ION" }, + { 0x17aa, 0x3610, "Second Generation ION" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0a74[] = { + { 0x17aa, 0x903a, "GeForce G210" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0a75[] = { + { 0x17aa, 0x3605, "Second Generation ION" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0a7a[] = { + { 0x1462, 0xaa51, "GeForce 405" }, + { 0x1462, 0xaa58, "GeForce 405" }, + { 0x1462, 0xac71, "GeForce 405" }, + { 0x1462, 0xac82, "GeForce 405" }, + { 0x1642, 0x3980, "GeForce 405" }, + { 0x17aa, 0x3950, "GeForce 405M" }, + { 0x17aa, 0x397d, "GeForce 405M" }, + { 0x1b0a, 0x90b4, "GeForce 405" }, + { 0x1bfd, 0x0003, "GeForce 405" }, + { 0x1bfd, 0x8006, "GeForce 405" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0dd8[] = { + { 0x10de, 0x0914, "Quadro 2000D" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0de9[] = { + { 0x1025, 0x0692, "GeForce GT 620M" }, + { 0x1025, 0x0725, "GeForce GT 620M" }, + { 0x1025, 0x0728, "GeForce GT 620M" }, + { 0x1025, 0x072b, "GeForce GT 620M" }, + { 0x1025, 0x072e, "GeForce GT 620M" }, + { 0x1025, 0x0753, "GeForce GT 620M" }, + { 0x1025, 0x0754, "GeForce GT 620M" }, + { 0x17aa, 0x3977, "GeForce GT 640M LE" }, + { 0x1b0a, 0x2210, "GeForce GT 635M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0dea[] = { + { 0x17aa, 0x365a, "GeForce 615" }, + { 0x17aa, 0x365b, "GeForce 615" }, + { 0x17aa, 0x365e, "GeForce 615" }, + { 0x17aa, 0x3660, "GeForce 615" }, + { 0x17aa, 0x366c, "GeForce 615" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0df4[] = { + { 0x152d, 0x0952, "GeForce GT 630M" }, + { 0x152d, 0x0953, "GeForce GT 630M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0fd2[] = { + { 0x1028, 0x0595, "GeForce GT 640M LE" }, + { 0x1028, 0x05b2, "GeForce GT 640M LE" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_0fe3[] = { + { 0x103c, 0x2b16, "GeForce GT 745A" }, + { 0x17aa, 0x3675, "GeForce GT 745A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_104b[] = { + { 0x1043, 0x844c, "GeForce GT 625" }, + { 0x1043, 0x846b, "GeForce GT 625" }, + { 0x1462, 0xb590, "GeForce GT 625" }, + { 0x174b, 0x0625, "GeForce GT 625" }, + { 0x174b, 0xa625, "GeForce GT 625" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1058[] = { + { 0x103c, 0x2af1, "GeForce 610" }, + { 0x17aa, 0x3682, "GeForce 800A" }, + { 0x17aa, 0x3692, "GeForce 705A" }, + { 0x17aa, 0x3695, "GeForce 800A" }, + { 0x17aa, 0x36a8, "GeForce 800A" }, + { 0x17aa, 0x36ac, "GeForce 800A" }, + { 0x17aa, 0x36ad, "GeForce 800A" }, + { 0x705a, 0x3682, "GeForce 800A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_105b[] = { + { 0x103c, 0x2afb, "GeForce 705A" }, + { 0x17aa, 0x36a1, "GeForce 800A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1091[] = { + { 0x10de, 0x088e, "Tesla X2090" }, + { 0x10de, 0x0891, "Tesla X2090" }, + { 0x10de, 0x0974, "Tesla X2090" }, + { 0x10de, 0x098d, "Tesla X2090" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1096[] = { + { 0x10de, 0x0911, "Tesla C2050" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1140[] = { + { 0x1019, 0x999f, "GeForce GT 720M" }, + { 0x1025, 0x0600, "GeForce GT 620M" }, + { 0x1025, 0x0606, "GeForce GT 620M" }, + { 0x1025, 0x064a, "GeForce GT 620M" }, + { 0x1025, 0x064c, "GeForce GT 620M" }, + { 0x1025, 0x067a, "GeForce GT 620M" }, + { 0x1025, 0x0680, "GeForce GT 620M" }, + { 0x1025, 0x0686, "GeForce 710M" }, + { 0x1025, 0x0689, "GeForce 710M" }, + { 0x1025, 0x068b, "GeForce 710M" }, + { 0x1025, 0x068d, "GeForce 710M" }, + { 0x1025, 0x068e, "GeForce 710M" }, + { 0x1025, 0x0691, "GeForce 710M" }, + { 0x1025, 0x0692, "GeForce GT 620M" }, + { 0x1025, 0x0694, "GeForce GT 620M" }, + { 0x1025, 0x0702, "GeForce GT 620M" }, + { 0x1025, 0x0719, "GeForce GT 620M" }, + { 0x1025, 0x0725, "GeForce GT 620M" }, + { 0x1025, 0x0728, "GeForce GT 620M" }, + { 0x1025, 0x072b, "GeForce GT 620M" }, + { 0x1025, 0x072e, "GeForce GT 620M" }, + { 0x1025, 0x0732, "GeForce GT 620M" }, + { 0x1025, 0x0763, "GeForce GT 720M" }, + { 0x1025, 0x0773, "GeForce 710M" }, + { 0x1025, 0x0774, "GeForce 710M" }, + { 0x1025, 0x0776, "GeForce GT 720M" }, + { 0x1025, 0x077a, "GeForce 710M" }, + { 0x1025, 0x077b, "GeForce 710M" }, + { 0x1025, 0x077c, "GeForce 710M" }, + { 0x1025, 0x077d, "GeForce 710M" }, + { 0x1025, 0x077e, "GeForce 710M" }, + { 0x1025, 0x077f, "GeForce 710M" }, + { 0x1025, 0x0781, "GeForce GT 720M" }, + { 0x1025, 0x0798, "GeForce GT 720M" }, + { 0x1025, 0x0799, "GeForce GT 720M" }, + { 0x1025, 0x079b, "GeForce GT 720M" }, + { 0x1025, 0x079c, "GeForce GT 720M" }, + { 0x1025, 0x0807, "GeForce GT 720M" }, + { 0x1025, 0x0821, "GeForce 820M" }, + { 0x1025, 0x0823, "GeForce GT 720M" }, + { 0x1025, 0x0830, "GeForce GT 720M" }, + { 0x1025, 0x0833, "GeForce GT 720M" }, + { 0x1025, 0x0837, "GeForce GT 720M" }, + { 0x1025, 0x083e, "GeForce 820M" }, + { 0x1025, 0x0841, "GeForce 710M" }, + { 0x1025, 0x0853, "GeForce 820M" }, + { 0x1025, 0x0854, "GeForce 820M" }, + { 0x1025, 0x0855, "GeForce 820M" }, + { 0x1025, 0x0856, "GeForce 820M" }, + { 0x1025, 0x0857, "GeForce 820M" }, + { 0x1025, 0x0858, "GeForce 820M" }, + { 0x1025, 0x0863, "GeForce 820M" }, + { 0x1025, 0x0868, "GeForce 820M" }, + { 0x1025, 0x0869, "GeForce 810M" }, + { 0x1025, 0x0873, "GeForce 820M" }, + { 0x1025, 0x0878, "GeForce 820M" }, + { 0x1025, 0x087b, "GeForce 820M" }, + { 0x1025, 0x087f, "GeForce 820M" }, + { 0x1025, 0x0881, "GeForce 820M" }, + { 0x1025, 0x0885, "GeForce 820M" }, + { 0x1025, 0x088a, "GeForce 820M" }, + { 0x1025, 0x089b, "GeForce 820M" }, + { 0x1025, 0x0921, "GeForce 820M" }, + { 0x1025, 0x092e, "GeForce 810M" }, + { 0x1025, 0x092f, "GeForce 820M" }, + { 0x1025, 0x0932, "GeForce 820M" }, + { 0x1025, 0x093a, "GeForce 820M" }, + { 0x1025, 0x093c, "GeForce 820M" }, + { 0x1025, 0x093f, "GeForce 820M" }, + { 0x1025, 0x0941, "GeForce 820M" }, + { 0x1025, 0x0945, "GeForce 820M" }, + { 0x1025, 0x0954, "GeForce 820M" }, + { 0x1025, 0x0965, "GeForce 820M" }, + { 0x1028, 0x054d, "GeForce GT 630M" }, + { 0x1028, 0x054e, "GeForce GT 630M" }, + { 0x1028, 0x0554, "GeForce GT 620M" }, + { 0x1028, 0x0557, "GeForce GT 620M" }, + { 0x1028, 0x0562, "GeForce GT625M" }, + { 0x1028, 0x0565, "GeForce GT 630M" }, + { 0x1028, 0x0568, "GeForce GT 630M" }, + { 0x1028, 0x0590, "GeForce GT 630M" }, + { 0x1028, 0x0592, "GeForce GT625M" }, + { 0x1028, 0x0594, "GeForce GT625M" }, + { 0x1028, 0x0595, "GeForce GT625M" }, + { 0x1028, 0x05a2, "GeForce GT625M" }, + { 0x1028, 0x05b1, "GeForce GT625M" }, + { 0x1028, 0x05b3, "GeForce GT625M" }, + { 0x1028, 0x05da, "GeForce GT 630M" }, + { 0x1028, 0x05de, "GeForce GT 720M" }, + { 0x1028, 0x05e0, "GeForce GT 720M" }, + { 0x1028, 0x05e8, "GeForce GT 630M" }, + { 0x1028, 0x05f4, "GeForce GT 720M" }, + { 0x1028, 0x060f, "GeForce GT 720M" }, + { 0x1028, 0x062f, "GeForce GT 720M" }, + { 0x1028, 0x064e, "GeForce 820M" }, + { 0x1028, 0x0652, "GeForce 820M" }, + { 0x1028, 0x0653, "GeForce 820M" }, + { 0x1028, 0x0655, "GeForce 820M" }, + { 0x1028, 0x065e, "GeForce 820M" }, + { 0x1028, 0x0662, "GeForce 820M" }, + { 0x1028, 0x068d, "GeForce 820M" }, + { 0x1028, 0x06ad, "GeForce 820M" }, + { 0x1028, 0x06ae, "GeForce 820M" }, + { 0x1028, 0x06af, "GeForce 820M" }, + { 0x1028, 0x06b0, "GeForce 820M" }, + { 0x1028, 0x06c0, "GeForce 820M" }, + { 0x1028, 0x06c1, "GeForce 820M" }, + { 0x103c, 0x18ef, "GeForce GT 630M" }, + { 0x103c, 0x18f9, "GeForce GT 630M" }, + { 0x103c, 0x18fb, "GeForce GT 630M" }, + { 0x103c, 0x18fd, "GeForce GT 630M" }, + { 0x103c, 0x18ff, "GeForce GT 630M" }, + { 0x103c, 0x218a, "GeForce 820M" }, + { 0x103c, 0x21bb, "GeForce 820M" }, + { 0x103c, 0x21bc, "GeForce 820M" }, + { 0x103c, 0x220e, "GeForce 820M" }, + { 0x103c, 0x2210, "GeForce 820M" }, + { 0x103c, 0x2212, "GeForce 820M" }, + { 0x103c, 0x2214, "GeForce 820M" }, + { 0x103c, 0x2218, "GeForce 820M" }, + { 0x103c, 0x225b, "GeForce 820M" }, + { 0x103c, 0x225d, "GeForce 820M" }, + { 0x103c, 0x226d, "GeForce 820M" }, + { 0x103c, 0x226f, "GeForce 820M" }, + { 0x103c, 0x22d2, "GeForce 820M" }, + { 0x103c, 0x22d9, "GeForce 820M" }, + { 0x103c, 0x2335, "GeForce 820M" }, + { 0x103c, 0x2337, "GeForce 820M" }, + { 0x103c, 0x2aef, "GeForce GT 720A" }, + { 0x103c, 0x2af9, "GeForce 710A" }, + { 0x1043, 0x10dd, "NVS 5200M" }, + { 0x1043, 0x10ed, "NVS 5200M" }, + { 0x1043, 0x11fd, "GeForce GT 720M" }, + { 0x1043, 0x124d, "GeForce GT 720M" }, + { 0x1043, 0x126d, "GeForce GT 720M" }, + { 0x1043, 0x131d, "GeForce GT 720M" }, + { 0x1043, 0x13fd, "GeForce GT 720M" }, + { 0x1043, 0x14c7, "GeForce GT 720M" }, + { 0x1043, 0x1507, "GeForce GT 620M" }, + { 0x1043, 0x15ad, "GeForce 820M" }, + { 0x1043, 0x15ed, "GeForce 820M" }, + { 0x1043, 0x160d, "GeForce 820M" }, + { 0x1043, 0x163d, "GeForce 820M" }, + { 0x1043, 0x165d, "GeForce 820M" }, + { 0x1043, 0x166d, "GeForce 820M" }, + { 0x1043, 0x16cd, "GeForce 820M" }, + { 0x1043, 0x16dd, "GeForce 820M" }, + { 0x1043, 0x170d, "GeForce 820M" }, + { 0x1043, 0x176d, "GeForce 820M" }, + { 0x1043, 0x178d, "GeForce 820M" }, + { 0x1043, 0x179d, "GeForce 820M" }, + { 0x1043, 0x2132, "GeForce GT 620M" }, + { 0x1043, 0x2136, "NVS 5200M" }, + { 0x1043, 0x21ba, "GeForce GT 720M" }, + { 0x1043, 0x21fa, "GeForce GT 720M" }, + { 0x1043, 0x220a, "GeForce GT 720M" }, + { 0x1043, 0x221a, "GeForce GT 720M" }, + { 0x1043, 0x223a, "GeForce GT 710M" }, + { 0x1043, 0x224a, "GeForce GT 710M" }, + { 0x1043, 0x227a, "GeForce 820M" }, + { 0x1043, 0x228a, "GeForce 820M" }, + { 0x1043, 0x22fa, "GeForce 820M" }, + { 0x1043, 0x232a, "GeForce 820M" }, + { 0x1043, 0x233a, "GeForce 820M" }, + { 0x1043, 0x235a, "GeForce 820M" }, + { 0x1043, 0x236a, "GeForce 820M" }, + { 0x1043, 0x238a, "GeForce 820M" }, + { 0x1043, 0x8595, "GeForce GT 720M" }, + { 0x1043, 0x85ea, "GeForce GT 720M" }, + { 0x1043, 0x85eb, "GeForce 820M" }, + { 0x1043, 0x85ec, "GeForce 820M" }, + { 0x1043, 0x85ee, "GeForce GT 720M" }, + { 0x1043, 0x85f3, "GeForce 820M" }, + { 0x1043, 0x860e, "GeForce 820M" }, + { 0x1043, 0x861a, "GeForce 820M" }, + { 0x1043, 0x861b, "GeForce 820M" }, + { 0x1043, 0x8628, "GeForce 820M" }, + { 0x1043, 0x8643, "GeForce 820M" }, + { 0x1043, 0x864c, "GeForce 820M" }, + { 0x1043, 0x8652, "GeForce 820M" }, + { 0x1043, 0x8660, "GeForce 820M" }, + { 0x1043, 0x8661, "GeForce 820M" }, + { 0x105b, 0x0dac, "GeForce GT 720M" }, + { 0x105b, 0x0dad, "GeForce GT 720M" }, + { 0x105b, 0x0ef3, "GeForce GT 720M" }, + { 0x10cf, 0x17f5, "GeForce GT 720M" }, + { 0x1179, 0xfa01, "GeForce 710M" }, + { 0x1179, 0xfa02, "GeForce 710M" }, + { 0x1179, 0xfa03, "GeForce 710M" }, + { 0x1179, 0xfa05, "GeForce 710M" }, + { 0x1179, 0xfa11, "GeForce 710M" }, + { 0x1179, 0xfa13, "GeForce 710M" }, + { 0x1179, 0xfa18, "GeForce 710M" }, + { 0x1179, 0xfa19, "GeForce 710M" }, + { 0x1179, 0xfa21, "GeForce 710M" }, + { 0x1179, 0xfa23, "GeForce 710M" }, + { 0x1179, 0xfa2a, "GeForce 710M" }, + { 0x1179, 0xfa32, "GeForce 710M" }, + { 0x1179, 0xfa33, "GeForce 710M" }, + { 0x1179, 0xfa36, "GeForce 710M" }, + { 0x1179, 0xfa38, "GeForce 710M" }, + { 0x1179, 0xfa42, "GeForce 710M" }, + { 0x1179, 0xfa43, "GeForce 710M" }, + { 0x1179, 0xfa45, "GeForce 710M" }, + { 0x1179, 0xfa47, "GeForce 710M" }, + { 0x1179, 0xfa49, "GeForce 710M" }, + { 0x1179, 0xfa58, "GeForce 710M" }, + { 0x1179, 0xfa59, "GeForce 710M" }, + { 0x1179, 0xfa88, "GeForce 710M" }, + { 0x1179, 0xfa89, "GeForce 710M" }, + { 0x144d, 0xb092, "GeForce GT 620M" }, + { 0x144d, 0xc0d5, "GeForce GT 630M" }, + { 0x144d, 0xc0d7, "GeForce GT 620M" }, + { 0x144d, 0xc0e2, "NVS 5200M" }, + { 0x144d, 0xc0e3, "NVS 5200M" }, + { 0x144d, 0xc0e4, "NVS 5200M" }, + { 0x144d, 0xc10d, "GeForce 820M" }, + { 0x144d, 0xc652, "GeForce GT 620M" }, + { 0x144d, 0xc709, "GeForce 710M" }, + { 0x144d, 0xc711, "GeForce 710M" }, + { 0x144d, 0xc736, "GeForce 710M" }, + { 0x144d, 0xc737, "GeForce 710M" }, + { 0x144d, 0xc745, "GeForce 820M" }, + { 0x144d, 0xc750, "GeForce 820M" }, + { 0x1462, 0x10b8, "GeForce GT 710M" }, + { 0x1462, 0x10e9, "GeForce GT 720M" }, + { 0x1462, 0x1116, "GeForce 820M" }, + { 0x1462, 0xaa33, "GeForce 720M" }, + { 0x1462, 0xaaa2, "GeForce GT 720M" }, + { 0x1462, 0xaaa3, "GeForce 820M" }, + { 0x1462, 0xacb2, "GeForce GT 720M" }, + { 0x1462, 0xacc1, "GeForce GT 720M" }, + { 0x1462, 0xae61, "GeForce 720M" }, + { 0x1462, 0xae65, "GeForce GT 720M" }, + { 0x1462, 0xae6a, "GeForce 820M" }, + { 0x1462, 0xae71, "GeForce GT 720M" }, + { 0x14c0, 0x0083, "GeForce 820M" }, + { 0x152d, 0x0926, "GeForce 620M" }, + { 0x152d, 0x0982, "GeForce GT 630M" }, + { 0x152d, 0x0983, "GeForce GT 630M" }, + { 0x152d, 0x1005, "GeForce GT820M" }, + { 0x152d, 0x1012, "GeForce 710M" }, + { 0x152d, 0x1019, "GeForce 820M" }, + { 0x152d, 0x1030, "GeForce GT 630M" }, + { 0x152d, 0x1055, "GeForce 710M" }, + { 0x152d, 0x1067, "GeForce GT 720M" }, + { 0x152d, 0x1092, "GeForce 820M" }, + { 0x17aa, 0x2200, "NVS 5200M" }, + { 0x17aa, 0x2213, "GeForce GT 720M" }, + { 0x17aa, 0x2220, "GeForce GT 720M" }, + { 0x17aa, 0x309c, "GeForce GT 720A" }, + { 0x17aa, 0x30b4, "GeForce 820A" }, + { 0x17aa, 0x30b7, "GeForce 720A" }, + { 0x17aa, 0x30e4, "GeForce 820A" }, + { 0x17aa, 0x361b, "GeForce 820A" }, + { 0x17aa, 0x361c, "GeForce 820A" }, + { 0x17aa, 0x361d, "GeForce 820A" }, + { 0x17aa, 0x3656, "GeForce GT620M" }, + { 0x17aa, 0x365a, "GeForce 705M" }, + { 0x17aa, 0x365e, "GeForce 800M" }, + { 0x17aa, 0x3661, "GeForce 820A" }, + { 0x17aa, 0x366c, "GeForce 800M" }, + { 0x17aa, 0x3685, "GeForce 800M" }, + { 0x17aa, 0x3686, "GeForce 800M" }, + { 0x17aa, 0x3687, "GeForce 705A" }, + { 0x17aa, 0x3696, "GeForce 820A" }, + { 0x17aa, 0x369b, "GeForce 820A" }, + { 0x17aa, 0x369c, "GeForce 820A" }, + { 0x17aa, 0x369d, "GeForce 820A" }, + { 0x17aa, 0x369e, "GeForce 820A" }, + { 0x17aa, 0x36a6, "GeForce 820A" }, + { 0x17aa, 0x36a7, "GeForce 820A" }, + { 0x17aa, 0x36a9, "GeForce 820A" }, + { 0x17aa, 0x36af, "GeForce 820A" }, + { 0x17aa, 0x36b0, "GeForce 820A" }, + { 0x17aa, 0x36b6, "GeForce 820A" }, + { 0x17aa, 0x3800, "GeForce GT 720M" }, + { 0x17aa, 0x3801, "GeForce GT 720M" }, + { 0x17aa, 0x3802, "GeForce GT 720M" }, + { 0x17aa, 0x3803, "GeForce GT 720M" }, + { 0x17aa, 0x3804, "GeForce GT 720M" }, + { 0x17aa, 0x3806, "GeForce GT 720M" }, + { 0x17aa, 0x3808, "GeForce GT 720M" }, + { 0x17aa, 0x380d, "GeForce 820M" }, + { 0x17aa, 0x380e, "GeForce 820M" }, + { 0x17aa, 0x380f, "GeForce 820M" }, + { 0x17aa, 0x3811, "GeForce 820M" }, + { 0x17aa, 0x3812, "GeForce 820M" }, + { 0x17aa, 0x3813, "GeForce 820M" }, + { 0x17aa, 0x3816, "GeForce 820M" }, + { 0x17aa, 0x3817, "GeForce 820M" }, + { 0x17aa, 0x3818, "GeForce 820M" }, + { 0x17aa, 0x381a, "GeForce 820M" }, + { 0x17aa, 0x381c, "GeForce 820M" }, + { 0x17aa, 0x381d, "GeForce 820M" }, + { 0x17aa, 0x3901, "GeForce 610M" }, + { 0x17aa, 0x3902, "GeForce 710M" }, + { 0x17aa, 0x3903, "GeForce 710M" }, + { 0x17aa, 0x3904, "GeForce GT 625M" }, + { 0x17aa, 0x3905, "GeForce GT 720M" }, + { 0x17aa, 0x3907, "GeForce 820M" }, + { 0x17aa, 0x3910, "GeForce GT 720M" }, + { 0x17aa, 0x3912, "GeForce GT 720M" }, + { 0x17aa, 0x3913, "GeForce 820M" }, + { 0x17aa, 0x3915, "GeForce 820M" }, + { 0x17aa, 0x3983, "GeForce 610M" }, + { 0x17aa, 0x5001, "GeForce 610M" }, + { 0x17aa, 0x5003, "GeForce GT 720M" }, + { 0x17aa, 0x5005, "GeForce 705M" }, + { 0x17aa, 0x500d, "GeForce GT 620M" }, + { 0x17aa, 0x5014, "GeForce 710M" }, + { 0x17aa, 0x5017, "GeForce 710M" }, + { 0x17aa, 0x5019, "GeForce 710M" }, + { 0x17aa, 0x501a, "GeForce 710M" }, + { 0x17aa, 0x501f, "GeForce GT 720M" }, + { 0x17aa, 0x5025, "GeForce 710M" }, + { 0x17aa, 0x5027, "GeForce 710M" }, + { 0x17aa, 0x502a, "GeForce 710M" }, + { 0x17aa, 0x502b, "GeForce GT 720M" }, + { 0x17aa, 0x502d, "GeForce 710M" }, + { 0x17aa, 0x502e, "GeForce GT 720M" }, + { 0x17aa, 0x502f, "GeForce GT 720M" }, + { 0x17aa, 0x5030, "GeForce 705M" }, + { 0x17aa, 0x5031, "GeForce 705M" }, + { 0x17aa, 0x5032, "GeForce 820M" }, + { 0x17aa, 0x5033, "GeForce 820M" }, + { 0x17aa, 0x503e, "GeForce 710M" }, + { 0x17aa, 0x503f, "GeForce 820M" }, + { 0x17aa, 0x5040, "GeForce 820M" }, + { 0x1854, 0x0177, "GeForce 710M" }, + { 0x1854, 0x0180, "GeForce 710M" }, + { 0x1854, 0x0190, "GeForce GT 720M" }, + { 0x1854, 0x0192, "GeForce GT 720M" }, + { 0x1854, 0x0224, "GeForce 820M" }, + { 0x1b0a, 0x20dd, "GeForce GT 620M" }, + { 0x1b0a, 0x20df, "GeForce GT 620M" }, + { 0x1b0a, 0x210e, "GeForce 820M" }, + { 0x1b0a, 0x2202, "GeForce GT 720M" }, + { 0x1b0a, 0x90d7, "GeForce 820M" }, + { 0x1b0a, 0x90dd, "GeForce 820M" }, + { 0x1b50, 0x5530, "GeForce 820M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1185[] = { + { 0x10de, 0x106f, "GeForce GTX 760" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1189[] = { + { 0x10de, 0x1074, "GeForce GTX 760 Ti OEM" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1199[] = { + { 0x1458, 0xd001, "GeForce GTX 760" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_11e3[] = { + { 0x17aa, 0x3683, "GeForce GTX 760A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1247[] = { + { 0x1043, 0x212a, "GeForce GT 635M" }, + { 0x1043, 0x212b, "GeForce GT 635M" }, + { 0x1043, 0x212c, "GeForce GT 635M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_124d[] = { + { 0x1462, 0x10cc, "GeForce GT 635M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1290[] = { + { 0x103c, 0x2afa, "GeForce 730A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1292[] = { + { 0x17aa, 0x3675, "GeForce GT 740A" }, + { 0x17aa, 0x367c, "GeForce GT 740A" }, + { 0x17aa, 0x3684, "GeForce GT 740A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1295[] = { + { 0x103c, 0x2b0d, "GeForce 710A" }, + { 0x103c, 0x2b0f, "GeForce 710A" }, + { 0x103c, 0x2b20, "GeForce 810A" }, + { 0x103c, 0x2b21, "GeForce 810A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1299[] = { + { 0x17aa, 0x369b, "GeForce 920A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1340[] = { + { 0x103c, 0x2b2b, "GeForce 830A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1341[] = { + { 0x17aa, 0x3697, "GeForce 840A" }, + { 0x17aa, 0x3699, "GeForce 840A" }, + { 0x17aa, 0x369c, "GeForce 840A" }, + { 0x17aa, 0x36af, "GeForce 840A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1346[] = { + { 0x17aa, 0x30ba, "GeForce 930A" }, + { 0x17aa, 0x362c, "GeForce 930A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1347[] = { + { 0x17aa, 0x36b9, "GeForce 940A" }, + { 0x17aa, 0x36ba, "GeForce 940A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_137a[] = { + { 0x17aa, 0x2225, "Quadro K620M" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_137d[] = { + { 0x17aa, 0x3699, "GeForce 940A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1391[] = { + { 0x17aa, 0x3697, "GeForce GTX 850A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_1392[] = { + { 0x1028, 0x066a, "GeForce GPU" }, + { 0x1043, 0x861e, "GeForce GTX 750 Ti" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_139a[] = { + { 0x17aa, 0x36b9, "GeForce GTX 950A" }, + {} +}; + +static const struct nvkm_device_pci_vendor +nvkm_device_pci_10de_139b[] = { + { 0x1028, 0x06a3, "GeForce GTX 860M" }, + { 0x19da, 0xc248, "GeForce GTX 750 Ti" }, + {} +}; + +static const struct nvkm_device_pci_device +nvkm_device_pci_10de[] = { + { 0x0020, "RIVA TNT" }, + { 0x0028, "RIVA TNT2/TNT2 Pro" }, + { 0x0029, "RIVA TNT2 Ultra" }, + { 0x002c, "Vanta/Vanta LT" }, + { 0x002d, "RIVA TNT2 Model 64/Model 64 Pro" }, + { 0x0040, "GeForce 6800 Ultra" }, + { 0x0041, "GeForce 6800" }, + { 0x0042, "GeForce 6800 LE" }, + { 0x0043, "GeForce 6800 XE" }, + { 0x0044, "GeForce 6800 XT" }, + { 0x0045, "GeForce 6800 GT" }, + { 0x0046, "GeForce 6800 GT" }, + { 0x0047, "GeForce 6800 GS" }, + { 0x0048, "GeForce 6800 XT" }, + { 0x004e, "Quadro FX 4000" }, + { 0x0090, "GeForce 7800 GTX" }, + { 0x0091, "GeForce 7800 GTX" }, + { 0x0092, "GeForce 7800 GT" }, + { 0x0093, "GeForce 7800 GS" }, + { 0x0095, "GeForce 7800 SLI" }, + { 0x0098, "GeForce Go 7800" }, + { 0x0099, "GeForce Go 7800 GTX" }, + { 0x009d, "Quadro FX 4500" }, + { 0x00a0, "Aladdin TNT2" }, + { 0x00c0, "GeForce 6800 GS" }, + { 0x00c1, "GeForce 6800" }, + { 0x00c2, "GeForce 6800 LE" }, + { 0x00c3, "GeForce 6800 XT" }, + { 0x00c8, "GeForce Go 6800" }, + { 0x00c9, "GeForce Go 6800 Ultra" }, + { 0x00cc, "Quadro FX Go1400" }, + { 0x00cd, "Quadro FX 3450/4000 SDI" }, + { 0x00ce, "Quadro FX 1400" }, + { 0x00f1, "GeForce 6600 GT" }, + { 0x00f2, "GeForce 6600" }, + { 0x00f3, "GeForce 6200" }, + { 0x00f4, "GeForce 6600 LE" }, + { 0x00f5, "GeForce 7800 GS" }, + { 0x00f6, "GeForce 6800 GS" }, + { 0x00f8, "Quadro FX 3400/Quadro FX 4000" }, + { 0x00f9, "GeForce 6800 Ultra" }, + { 0x00fa, "GeForce PCX 5750" }, + { 0x00fb, "GeForce PCX 5900" }, + { 0x00fc, "Quadro FX 330/GeForce PCX 5300" }, + { 0x00fd, "Quadro FX 330/Quadro NVS 280 PCI-E" }, + { 0x00fe, "Quadro FX 1300" }, + { 0x0100, "GeForce 256" }, + { 0x0101, "GeForce DDR" }, + { 0x0103, "Quadro" }, + { 0x0110, "GeForce2 MX/MX 400" }, + { 0x0111, "GeForce2 MX 100/200" }, + { 0x0112, "GeForce2 Go" }, + { 0x0113, "Quadro2 MXR/EX/Go" }, + { 0x0140, "GeForce 6600 GT" }, + { 0x0141, "GeForce 6600" }, + { 0x0142, "GeForce 6600 LE" }, + { 0x0143, "GeForce 6600 VE" }, + { 0x0144, "GeForce Go 6600" }, + { 0x0145, "GeForce 6610 XL" }, + { 0x0146, "GeForce Go 6600 TE/6200 TE" }, + { 0x0147, "GeForce 6700 XL" }, + { 0x0148, "GeForce Go 6600" }, + { 0x0149, "GeForce Go 6600 GT" }, + { 0x014a, "Quadro NVS 440" }, + { 0x014c, "Quadro FX 540M" }, + { 0x014d, "Quadro FX 550" }, + { 0x014e, "Quadro FX 540" }, + { 0x014f, "GeForce 6200" }, + { 0x0150, "GeForce2 GTS/GeForce2 Pro" }, + { 0x0151, "GeForce2 Ti" }, + { 0x0152, "GeForce2 Ultra" }, + { 0x0153, "Quadro2 Pro" }, + { 0x0160, "GeForce 6500" }, + { 0x0161, "GeForce 6200 TurboCache(TM)" }, + { 0x0162, "GeForce 6200SE TurboCache(TM)" }, + { 0x0163, "GeForce 6200 LE" }, + { 0x0164, "GeForce Go 6200" }, + { 0x0165, "Quadro NVS 285" }, + { 0x0166, "GeForce Go 6400" }, + { 0x0167, "GeForce Go 6200" }, + { 0x0168, "GeForce Go 6400" }, + { 0x0169, "GeForce 6250" }, + { 0x016a, "GeForce 7100 GS" }, + { 0x0170, "GeForce4 MX 460" }, + { 0x0171, "GeForce4 MX 440" }, + { 0x0172, "GeForce4 MX 420" }, + { 0x0173, "GeForce4 MX 440-SE" }, + { 0x0174, "GeForce4 440 Go" }, + { 0x0175, "GeForce4 420 Go" }, + { 0x0176, "GeForce4 420 Go 32M" }, + { 0x0177, "GeForce4 460 Go" }, + { 0x0178, "Quadro4 550 XGL" }, + { 0x0179, "GeForce4 440 Go 64M" }, + { 0x017a, "Quadro NVS 400" }, + { 0x017c, "Quadro4 500 GoGL" }, + { 0x017d, "GeForce4 410 Go 16M" }, + { 0x0181, "GeForce4 MX 440 with AGP8X" }, + { 0x0182, "GeForce4 MX 440SE with AGP8X" }, + { 0x0183, "GeForce4 MX 420 with AGP8X" }, + { 0x0185, "GeForce4 MX 4000" }, + { 0x0188, "Quadro4 580 XGL" }, + { 0x0189, "GeForce4 MX with AGP8X (Mac)", nvkm_device_pci_10de_0189 }, + { 0x018a, "Quadro NVS 280 SD" }, + { 0x018b, "Quadro4 380 XGL" }, + { 0x018c, "Quadro NVS 50 PCI" }, + { 0x0191, "GeForce 8800 GTX" }, + { 0x0193, "GeForce 8800 GTS" }, + { 0x0194, "GeForce 8800 Ultra" }, + { 0x0197, "Tesla C870" }, + { 0x019d, "Quadro FX 5600" }, + { 0x019e, "Quadro FX 4600" }, + { 0x01a0, "GeForce2 Integrated GPU" }, + { 0x01d0, "GeForce 7350 LE" }, + { 0x01d1, "GeForce 7300 LE" }, + { 0x01d2, "GeForce 7550 LE" }, + { 0x01d3, "GeForce 7300 SE/7200 GS" }, + { 0x01d6, "GeForce Go 7200" }, + { 0x01d7, "GeForce Go 7300" }, + { 0x01d8, "GeForce Go 7400" }, + { 0x01da, "Quadro NVS 110M" }, + { 0x01db, "Quadro NVS 120M" }, + { 0x01dc, "Quadro FX 350M" }, + { 0x01dd, "GeForce 7500 LE" }, + { 0x01de, "Quadro FX 350" }, + { 0x01df, "GeForce 7300 GS" }, + { 0x01f0, "GeForce4 MX Integrated GPU", nvkm_device_pci_10de_01f0 }, + { 0x0200, "GeForce3" }, + { 0x0201, "GeForce3 Ti 200" }, + { 0x0202, "GeForce3 Ti 500" }, + { 0x0203, "Quadro DCC" }, + { 0x0211, "GeForce 6800" }, + { 0x0212, "GeForce 6800 LE" }, + { 0x0215, "GeForce 6800 GT" }, + { 0x0218, "GeForce 6800 XT" }, + { 0x0221, "GeForce 6200" }, + { 0x0222, "GeForce 6200 A-LE" }, + { 0x0240, "GeForce 6150" }, + { 0x0241, "GeForce 6150 LE" }, + { 0x0242, "GeForce 6100" }, + { 0x0244, "GeForce Go 6150" }, + { 0x0245, "Quadro NVS 210S / GeForce 6150LE" }, + { 0x0247, "GeForce Go 6100" }, + { 0x0250, "GeForce4 Ti 4600" }, + { 0x0251, "GeForce4 Ti 4400" }, + { 0x0253, "GeForce4 Ti 4200" }, + { 0x0258, "Quadro4 900 XGL" }, + { 0x0259, "Quadro4 750 XGL" }, + { 0x025b, "Quadro4 700 XGL" }, + { 0x0280, "GeForce4 Ti 4800" }, + { 0x0281, "GeForce4 Ti 4200 with AGP8X" }, + { 0x0282, "GeForce4 Ti 4800 SE" }, + { 0x0286, "GeForce4 4200 Go" }, + { 0x0288, "Quadro4 980 XGL" }, + { 0x0289, "Quadro4 780 XGL" }, + { 0x028c, "Quadro4 700 GoGL" }, + { 0x0290, "GeForce 7900 GTX" }, + { 0x0291, "GeForce 7900 GT/GTO" }, + { 0x0292, "GeForce 7900 GS" }, + { 0x0293, "GeForce 7950 GX2" }, + { 0x0294, "GeForce 7950 GX2" }, + { 0x0295, "GeForce 7950 GT" }, + { 0x0297, "GeForce Go 7950 GTX" }, + { 0x0298, "GeForce Go 7900 GS" }, + { 0x0299, "Quadro NVS 510M" }, + { 0x029a, "Quadro FX 2500M" }, + { 0x029b, "Quadro FX 1500M" }, + { 0x029c, "Quadro FX 5500" }, + { 0x029d, "Quadro FX 3500" }, + { 0x029e, "Quadro FX 1500" }, + { 0x029f, "Quadro FX 4500 X2" }, + { 0x02e0, "GeForce 7600 GT" }, + { 0x02e1, "GeForce 7600 GS" }, + { 0x02e2, "GeForce 7300 GT" }, + { 0x02e3, "GeForce 7900 GS" }, + { 0x02e4, "GeForce 7950 GT" }, + { 0x0301, "GeForce FX 5800 Ultra" }, + { 0x0302, "GeForce FX 5800" }, + { 0x0308, "Quadro FX 2000" }, + { 0x0309, "Quadro FX 1000" }, + { 0x0311, "GeForce FX 5600 Ultra" }, + { 0x0312, "GeForce FX 5600" }, + { 0x0314, "GeForce FX 5600XT" }, + { 0x031a, "GeForce FX Go5600" }, + { 0x031b, "GeForce FX Go5650" }, + { 0x031c, "Quadro FX Go700" }, + { 0x0320, "GeForce FX 5200" }, + { 0x0321, "GeForce FX 5200 Ultra" }, + { 0x0322, "GeForce FX 5200", nvkm_device_pci_10de_0322 }, + { 0x0323, "GeForce FX 5200LE" }, + { 0x0324, "GeForce FX Go5200" }, + { 0x0325, "GeForce FX Go5250" }, + { 0x0326, "GeForce FX 5500" }, + { 0x0327, "GeForce FX 5100" }, + { 0x0328, "GeForce FX Go5200 32M/64M" }, + { 0x032a, "Quadro NVS 55/280 PCI" }, + { 0x032b, "Quadro FX 500/FX 600" }, + { 0x032c, "GeForce FX Go53xx" }, + { 0x032d, "GeForce FX Go5100" }, + { 0x0330, "GeForce FX 5900 Ultra" }, + { 0x0331, "GeForce FX 5900" }, + { 0x0332, "GeForce FX 5900XT" }, + { 0x0333, "GeForce FX 5950 Ultra" }, + { 0x0334, "GeForce FX 5900ZT" }, + { 0x0338, "Quadro FX 3000" }, + { 0x033f, "Quadro FX 700" }, + { 0x0341, "GeForce FX 5700 Ultra" }, + { 0x0342, "GeForce FX 5700" }, + { 0x0343, "GeForce FX 5700LE" }, + { 0x0344, "GeForce FX 5700VE" }, + { 0x0347, "GeForce FX Go5700" }, + { 0x0348, "GeForce FX Go5700" }, + { 0x034c, "Quadro FX Go1000" }, + { 0x034e, "Quadro FX 1100" }, + { 0x038b, "GeForce 7650 GS" }, + { 0x0390, "GeForce 7650 GS" }, + { 0x0391, "GeForce 7600 GT" }, + { 0x0392, "GeForce 7600 GS" }, + { 0x0393, "GeForce 7300 GT" }, + { 0x0394, "GeForce 7600 LE" }, + { 0x0395, "GeForce 7300 GT" }, + { 0x0397, "GeForce Go 7700" }, + { 0x0398, "GeForce Go 7600" }, + { 0x0399, "GeForce Go 7600 GT" }, + { 0x039c, "Quadro FX 560M" }, + { 0x039e, "Quadro FX 560" }, + { 0x03d0, "GeForce 6150SE nForce 430" }, + { 0x03d1, "GeForce 6100 nForce 405" }, + { 0x03d2, "GeForce 6100 nForce 400" }, + { 0x03d5, "GeForce 6100 nForce 420" }, + { 0x03d6, "GeForce 7025 / nForce 630a" }, + { 0x0400, "GeForce 8600 GTS" }, + { 0x0401, "GeForce 8600 GT" }, + { 0x0402, "GeForce 8600 GT" }, + { 0x0403, "GeForce 8600 GS" }, + { 0x0404, "GeForce 8400 GS" }, + { 0x0405, "GeForce 9500M GS" }, + { 0x0406, "GeForce 8300 GS" }, + { 0x0407, "GeForce 8600M GT" }, + { 0x0408, "GeForce 9650M GS" }, + { 0x0409, "GeForce 8700M GT" }, + { 0x040a, "Quadro FX 370" }, + { 0x040b, "Quadro NVS 320M" }, + { 0x040c, "Quadro FX 570M" }, + { 0x040d, "Quadro FX 1600M" }, + { 0x040e, "Quadro FX 570" }, + { 0x040f, "Quadro FX 1700" }, + { 0x0410, "GeForce GT 330" }, + { 0x0420, "GeForce 8400 SE" }, + { 0x0421, "GeForce 8500 GT" }, + { 0x0422, "GeForce 8400 GS" }, + { 0x0423, "GeForce 8300 GS" }, + { 0x0424, "GeForce 8400 GS" }, + { 0x0425, "GeForce 8600M GS" }, + { 0x0426, "GeForce 8400M GT" }, + { 0x0427, "GeForce 8400M GS" }, + { 0x0428, "GeForce 8400M G" }, + { 0x0429, "Quadro NVS 140M" }, + { 0x042a, "Quadro NVS 130M" }, + { 0x042b, "Quadro NVS 135M" }, + { 0x042c, "GeForce 9400 GT" }, + { 0x042d, "Quadro FX 360M" }, + { 0x042e, "GeForce 9300M G" }, + { 0x042f, "Quadro NVS 290" }, + { 0x0531, "GeForce 7150M / nForce 630M" }, + { 0x0533, "GeForce 7000M / nForce 610M" }, + { 0x053a, "GeForce 7050 PV / nForce 630a" }, + { 0x053b, "GeForce 7050 PV / nForce 630a" }, + { 0x053e, "GeForce 7025 / nForce 630a" }, + { 0x05e0, "GeForce GTX 295" }, + { 0x05e1, "GeForce GTX 280" }, + { 0x05e2, "GeForce GTX 260" }, + { 0x05e3, "GeForce GTX 285" }, + { 0x05e6, "GeForce GTX 275" }, + { 0x05e7, "Tesla C1060", nvkm_device_pci_10de_05e7 }, + { 0x05ea, "GeForce GTX 260" }, + { 0x05eb, "GeForce GTX 295" }, + { 0x05ed, "Quadroplex 2200 D2" }, + { 0x05f8, "Quadroplex 2200 S4" }, + { 0x05f9, "Quadro CX" }, + { 0x05fd, "Quadro FX 5800" }, + { 0x05fe, "Quadro FX 4800" }, + { 0x05ff, "Quadro FX 3800" }, + { 0x0600, "GeForce 8800 GTS 512" }, + { 0x0601, "GeForce 9800 GT" }, + { 0x0602, "GeForce 8800 GT" }, + { 0x0603, "GeForce GT 230" }, + { 0x0604, "GeForce 9800 GX2" }, + { 0x0605, "GeForce 9800 GT" }, + { 0x0606, "GeForce 8800 GS" }, + { 0x0607, "GeForce GTS 240" }, + { 0x0608, "GeForce 9800M GTX" }, + { 0x0609, "GeForce 8800M GTS", nvkm_device_pci_10de_0609 }, + { 0x060a, "GeForce GTX 280M" }, + { 0x060b, "GeForce 9800M GT" }, + { 0x060c, "GeForce 8800M GTX" }, + { 0x060d, "GeForce 8800 GS" }, + { 0x060f, "GeForce GTX 285M" }, + { 0x0610, "GeForce 9600 GSO" }, + { 0x0611, "GeForce 8800 GT" }, + { 0x0612, "GeForce 9800 GTX/9800 GTX+" }, + { 0x0613, "GeForce 9800 GTX+" }, + { 0x0614, "GeForce 9800 GT" }, + { 0x0615, "GeForce GTS 250" }, + { 0x0617, "GeForce 9800M GTX" }, + { 0x0618, "GeForce GTX 260M" }, + { 0x0619, "Quadro FX 4700 X2" }, + { 0x061a, "Quadro FX 3700" }, + { 0x061b, "Quadro VX 200" }, + { 0x061c, "Quadro FX 3600M" }, + { 0x061d, "Quadro FX 2800M" }, + { 0x061e, "Quadro FX 3700M" }, + { 0x061f, "Quadro FX 3800M" }, + { 0x0621, "GeForce GT 230" }, + { 0x0622, "GeForce 9600 GT" }, + { 0x0623, "GeForce 9600 GS" }, + { 0x0625, "GeForce 9600 GSO 512" }, + { 0x0626, "GeForce GT 130" }, + { 0x0627, "GeForce GT 140" }, + { 0x0628, "GeForce 9800M GTS" }, + { 0x062a, "GeForce 9700M GTS" }, + { 0x062b, "GeForce 9800M GS" }, + { 0x062c, "GeForce 9800M GTS" }, + { 0x062d, "GeForce 9600 GT" }, + { 0x062e, "GeForce 9600 GT", nvkm_device_pci_10de_062e }, + { 0x0630, "GeForce 9700 S" }, + { 0x0631, "GeForce GTS 160M" }, + { 0x0632, "GeForce GTS 150M" }, + { 0x0635, "GeForce 9600 GSO" }, + { 0x0637, "GeForce 9600 GT" }, + { 0x0638, "Quadro FX 1800" }, + { 0x063a, "Quadro FX 2700M" }, + { 0x0640, "GeForce 9500 GT" }, + { 0x0641, "GeForce 9400 GT" }, + { 0x0643, "GeForce 9500 GT" }, + { 0x0644, "GeForce 9500 GS" }, + { 0x0645, "GeForce 9500 GS" }, + { 0x0646, "GeForce GT 120" }, + { 0x0647, "GeForce 9600M GT" }, + { 0x0648, "GeForce 9600M GS" }, + { 0x0649, "GeForce 9600M GT", nvkm_device_pci_10de_0649 }, + { 0x064a, "GeForce 9700M GT" }, + { 0x064b, "GeForce 9500M G" }, + { 0x064c, "GeForce 9650M GT" }, + { 0x0651, "GeForce G 110M" }, + { 0x0652, "GeForce GT 130M", nvkm_device_pci_10de_0652 }, + { 0x0653, "GeForce GT 120M" }, + { 0x0654, "GeForce GT 220M", nvkm_device_pci_10de_0654 }, + { 0x0655, NULL, nvkm_device_pci_10de_0655 }, + { 0x0656, NULL, nvkm_device_pci_10de_0656 }, + { 0x0658, "Quadro FX 380" }, + { 0x0659, "Quadro FX 580" }, + { 0x065a, "Quadro FX 1700M" }, + { 0x065b, "GeForce 9400 GT" }, + { 0x065c, "Quadro FX 770M" }, + { 0x06c0, "GeForce GTX 480" }, + { 0x06c4, "GeForce GTX 465" }, + { 0x06ca, "GeForce GTX 480M" }, + { 0x06cd, "GeForce GTX 470" }, + { 0x06d1, "Tesla C2050 / C2070", nvkm_device_pci_10de_06d1 }, + { 0x06d2, "Tesla M2070", nvkm_device_pci_10de_06d2 }, + { 0x06d8, "Quadro 6000" }, + { 0x06d9, "Quadro 5000" }, + { 0x06da, "Quadro 5000M" }, + { 0x06dc, "Quadro 6000" }, + { 0x06dd, "Quadro 4000" }, + { 0x06de, "Tesla T20 Processor", nvkm_device_pci_10de_06de }, + { 0x06df, "Tesla M2070-Q" }, + { 0x06e0, "GeForce 9300 GE" }, + { 0x06e1, "GeForce 9300 GS" }, + { 0x06e2, "GeForce 8400" }, + { 0x06e3, "GeForce 8400 SE" }, + { 0x06e4, "GeForce 8400 GS" }, + { 0x06e5, "GeForce 9300M GS" }, + { 0x06e6, "GeForce G100" }, + { 0x06e7, "GeForce 9300 SE" }, + { 0x06e8, "GeForce 9200M GS", nvkm_device_pci_10de_06e8 }, + { 0x06e9, "GeForce 9300M GS" }, + { 0x06ea, "Quadro NVS 150M" }, + { 0x06eb, "Quadro NVS 160M" }, + { 0x06ec, "GeForce G 105M" }, + { 0x06ef, "GeForce G 103M" }, + { 0x06f1, "GeForce G105M" }, + { 0x06f8, "Quadro NVS 420" }, + { 0x06f9, "Quadro FX 370 LP", nvkm_device_pci_10de_06f9 }, + { 0x06fa, "Quadro NVS 450" }, + { 0x06fb, "Quadro FX 370M" }, + { 0x06fd, "Quadro NVS 295" }, + { 0x06ff, "HICx16 + Graphics", nvkm_device_pci_10de_06ff }, + { 0x07e0, "GeForce 7150 / nForce 630i" }, + { 0x07e1, "GeForce 7100 / nForce 630i" }, + { 0x07e2, "GeForce 7050 / nForce 630i" }, + { 0x07e3, "GeForce 7050 / nForce 610i" }, + { 0x07e5, "GeForce 7050 / nForce 620i" }, + { 0x0840, "GeForce 8200M" }, + { 0x0844, "GeForce 9100M G" }, + { 0x0845, "GeForce 8200M G" }, + { 0x0846, "GeForce 9200" }, + { 0x0847, "GeForce 9100" }, + { 0x0848, "GeForce 8300" }, + { 0x0849, "GeForce 8200" }, + { 0x084a, "nForce 730a" }, + { 0x084b, "GeForce 9200" }, + { 0x084c, "nForce 980a/780a SLI" }, + { 0x084d, "nForce 750a SLI" }, + { 0x084f, "GeForce 8100 / nForce 720a" }, + { 0x0860, "GeForce 9400" }, + { 0x0861, "GeForce 9400" }, + { 0x0862, "GeForce 9400M G" }, + { 0x0863, "GeForce 9400M" }, + { 0x0864, "GeForce 9300" }, + { 0x0865, "ION" }, + { 0x0866, "GeForce 9400M G", nvkm_device_pci_10de_0866 }, + { 0x0867, "GeForce 9400" }, + { 0x0868, "nForce 760i SLI" }, + { 0x0869, "GeForce 9400" }, + { 0x086a, "GeForce 9400" }, + { 0x086c, "GeForce 9300 / nForce 730i" }, + { 0x086d, "GeForce 9200" }, + { 0x086e, "GeForce 9100M G" }, + { 0x086f, "GeForce 8200M G" }, + { 0x0870, "GeForce 9400M" }, + { 0x0871, "GeForce 9200" }, + { 0x0872, "GeForce G102M", nvkm_device_pci_10de_0872 }, + { 0x0873, "GeForce G102M", nvkm_device_pci_10de_0873 }, + { 0x0874, "ION" }, + { 0x0876, "ION" }, + { 0x087a, "GeForce 9400" }, + { 0x087d, "ION" }, + { 0x087e, "ION LE" }, + { 0x087f, "ION LE" }, + { 0x08a0, "GeForce 320M" }, + { 0x08a2, "GeForce 320M" }, + { 0x08a3, "GeForce 320M" }, + { 0x08a4, "GeForce 320M" }, + { 0x08a5, "GeForce 320M" }, + { 0x0a20, "GeForce GT 220" }, + { 0x0a22, "GeForce 315" }, + { 0x0a23, "GeForce 210" }, + { 0x0a26, "GeForce 405" }, + { 0x0a27, "GeForce 405" }, + { 0x0a28, "GeForce GT 230M" }, + { 0x0a29, "GeForce GT 330M" }, + { 0x0a2a, "GeForce GT 230M" }, + { 0x0a2b, "GeForce GT 330M" }, + { 0x0a2c, "NVS 5100M" }, + { 0x0a2d, "GeForce GT 320M" }, + { 0x0a32, "GeForce GT 415" }, + { 0x0a34, "GeForce GT 240M" }, + { 0x0a35, "GeForce GT 325M" }, + { 0x0a38, "Quadro 400" }, + { 0x0a3c, "Quadro FX 880M" }, + { 0x0a60, "GeForce G210" }, + { 0x0a62, "GeForce 205" }, + { 0x0a63, "GeForce 310" }, + { 0x0a64, "Second Generation ION" }, + { 0x0a65, "GeForce 210" }, + { 0x0a66, "GeForce 310" }, + { 0x0a67, "GeForce 315" }, + { 0x0a68, "GeForce G105M" }, + { 0x0a69, "GeForce G105M" }, + { 0x0a6a, "NVS 2100M" }, + { 0x0a6c, "NVS 3100M" }, + { 0x0a6e, "GeForce 305M", nvkm_device_pci_10de_0a6e }, + { 0x0a6f, "Second Generation ION" }, + { 0x0a70, "GeForce 310M", nvkm_device_pci_10de_0a70 }, + { 0x0a71, "GeForce 305M" }, + { 0x0a72, "GeForce 310M" }, + { 0x0a73, "GeForce 305M", nvkm_device_pci_10de_0a73 }, + { 0x0a74, "GeForce G210M", nvkm_device_pci_10de_0a74 }, + { 0x0a75, "GeForce 310M", nvkm_device_pci_10de_0a75 }, + { 0x0a76, "Second Generation ION" }, + { 0x0a78, "Quadro FX 380 LP" }, + { 0x0a7a, "GeForce 315M", nvkm_device_pci_10de_0a7a }, + { 0x0a7c, "Quadro FX 380M" }, + { 0x0ca0, "GeForce GT 330" }, + { 0x0ca2, "GeForce GT 320" }, + { 0x0ca3, "GeForce GT 240" }, + { 0x0ca4, "GeForce GT 340" }, + { 0x0ca5, "GeForce GT 220" }, + { 0x0ca7, "GeForce GT 330" }, + { 0x0ca8, "GeForce GTS 260M" }, + { 0x0ca9, "GeForce GTS 250M" }, + { 0x0cac, "GeForce GT 220" }, + { 0x0caf, "GeForce GT 335M" }, + { 0x0cb0, "GeForce GTS 350M" }, + { 0x0cb1, "GeForce GTS 360M" }, + { 0x0cbc, "Quadro FX 1800M" }, + { 0x0dc0, "GeForce GT 440" }, + { 0x0dc4, "GeForce GTS 450" }, + { 0x0dc5, "GeForce GTS 450" }, + { 0x0dc6, "GeForce GTS 450" }, + { 0x0dcd, "GeForce GT 555M" }, + { 0x0dce, "GeForce GT 555M" }, + { 0x0dd1, "GeForce GTX 460M" }, + { 0x0dd2, "GeForce GT 445M" }, + { 0x0dd3, "GeForce GT 435M" }, + { 0x0dd6, "GeForce GT 550M" }, + { 0x0dd8, "Quadro 2000", nvkm_device_pci_10de_0dd8 }, + { 0x0dda, "Quadro 2000M" }, + { 0x0de0, "GeForce GT 440" }, + { 0x0de1, "GeForce GT 430" }, + { 0x0de2, "GeForce GT 420" }, + { 0x0de3, "GeForce GT 635M" }, + { 0x0de4, "GeForce GT 520" }, + { 0x0de5, "GeForce GT 530" }, + { 0x0de7, "GeForce GT 610" }, + { 0x0de8, "GeForce GT 620M" }, + { 0x0de9, "GeForce GT 630M", nvkm_device_pci_10de_0de9 }, + { 0x0dea, "GeForce 610M", nvkm_device_pci_10de_0dea }, + { 0x0deb, "GeForce GT 555M" }, + { 0x0dec, "GeForce GT 525M" }, + { 0x0ded, "GeForce GT 520M" }, + { 0x0dee, "GeForce GT 415M" }, + { 0x0def, "NVS 5400M" }, + { 0x0df0, "GeForce GT 425M" }, + { 0x0df1, "GeForce GT 420M" }, + { 0x0df2, "GeForce GT 435M" }, + { 0x0df3, "GeForce GT 420M" }, + { 0x0df4, "GeForce GT 540M", nvkm_device_pci_10de_0df4 }, + { 0x0df5, "GeForce GT 525M" }, + { 0x0df6, "GeForce GT 550M" }, + { 0x0df7, "GeForce GT 520M" }, + { 0x0df8, "Quadro 600" }, + { 0x0df9, "Quadro 500M" }, + { 0x0dfa, "Quadro 1000M" }, + { 0x0dfc, "NVS 5200M" }, + { 0x0e22, "GeForce GTX 460" }, + { 0x0e23, "GeForce GTX 460 SE" }, + { 0x0e24, "GeForce GTX 460" }, + { 0x0e30, "GeForce GTX 470M" }, + { 0x0e31, "GeForce GTX 485M" }, + { 0x0e3a, "Quadro 3000M" }, + { 0x0e3b, "Quadro 4000M" }, + { 0x0f00, "GeForce GT 630" }, + { 0x0f01, "GeForce GT 620" }, + { 0x0f02, "GeForce GT 730" }, + { 0x0fc0, "GeForce GT 640" }, + { 0x0fc1, "GeForce GT 640" }, + { 0x0fc2, "GeForce GT 630" }, + { 0x0fc6, "GeForce GTX 650" }, + { 0x0fc8, "GeForce GT 740" }, + { 0x0fc9, "GeForce GT 730" }, + { 0x0fcd, "GeForce GT 755M" }, + { 0x0fce, "GeForce GT 640M LE" }, + { 0x0fd1, "GeForce GT 650M" }, + { 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 }, + { 0x0fd3, "GeForce GT 640M LE" }, + { 0x0fd4, "GeForce GTX 660M" }, + { 0x0fd5, "GeForce GT 650M" }, + { 0x0fd8, "GeForce GT 640M" }, + { 0x0fd9, "GeForce GT 645M" }, + { 0x0fdf, "GeForce GT 740M" }, + { 0x0fe0, "GeForce GTX 660M" }, + { 0x0fe1, "GeForce GT 730M" }, + { 0x0fe2, "GeForce GT 745M" }, + { 0x0fe3, "GeForce GT 745M", nvkm_device_pci_10de_0fe3 }, + { 0x0fe4, "GeForce GT 750M" }, + { 0x0fe9, "GeForce GT 750M" }, + { 0x0fea, "GeForce GT 755M" }, + { 0x0fec, "GeForce 710A" }, + { 0x0fef, "GRID K340" }, + { 0x0ff2, "GRID K1" }, + { 0x0ff3, "Quadro K420" }, + { 0x0ff6, "Quadro K1100M" }, + { 0x0ff8, "Quadro K500M" }, + { 0x0ff9, "Quadro K2000D" }, + { 0x0ffa, "Quadro K600" }, + { 0x0ffb, "Quadro K2000M" }, + { 0x0ffc, "Quadro K1000M" }, + { 0x0ffd, "NVS 510" }, + { 0x0ffe, "Quadro K2000" }, + { 0x0fff, "Quadro 410" }, + { 0x1001, "GeForce GTX TITAN Z" }, + { 0x1004, "GeForce GTX 780" }, + { 0x1005, "GeForce GTX TITAN" }, + { 0x1007, "GeForce GTX 780" }, + { 0x1008, "GeForce GTX 780 Ti" }, + { 0x100a, "GeForce GTX 780 Ti" }, + { 0x100c, "GeForce GTX TITAN Black" }, + { 0x1021, "Tesla K20Xm" }, + { 0x1022, "Tesla K20c" }, + { 0x1023, "Tesla K40m" }, + { 0x1024, "Tesla K40c" }, + { 0x1026, "Tesla K20s" }, + { 0x1027, "Tesla K40st" }, + { 0x1028, "Tesla K20m" }, + { 0x1029, "Tesla K40s" }, + { 0x102a, "Tesla K40t" }, + { 0x102d, "Tesla K80" }, + { 0x103a, "Quadro K6000" }, + { 0x103c, "Quadro K5200" }, + { 0x1040, "GeForce GT 520" }, + { 0x1042, "GeForce 510" }, + { 0x1048, "GeForce 605" }, + { 0x1049, "GeForce GT 620" }, + { 0x104a, "GeForce GT 610" }, + { 0x104b, "GeForce GT 625 (OEM)", nvkm_device_pci_10de_104b }, + { 0x104c, "GeForce GT 705" }, + { 0x1050, "GeForce GT 520M" }, + { 0x1051, "GeForce GT 520MX" }, + { 0x1052, "GeForce GT 520M" }, + { 0x1054, "GeForce 410M" }, + { 0x1055, "GeForce 410M" }, + { 0x1056, "NVS 4200M" }, + { 0x1057, "NVS 4200M" }, + { 0x1058, "GeForce 610M", nvkm_device_pci_10de_1058 }, + { 0x1059, "GeForce 610M" }, + { 0x105a, "GeForce 610M" }, + { 0x105b, "GeForce 705M", nvkm_device_pci_10de_105b }, + { 0x107c, "NVS 315" }, + { 0x107d, "NVS 310" }, + { 0x1080, "GeForce GTX 580" }, + { 0x1081, "GeForce GTX 570" }, + { 0x1082, "GeForce GTX 560 Ti" }, + { 0x1084, "GeForce GTX 560" }, + { 0x1086, "GeForce GTX 570" }, + { 0x1087, "GeForce GTX 560 Ti" }, + { 0x1088, "GeForce GTX 590" }, + { 0x1089, "GeForce GTX 580" }, + { 0x108b, "GeForce GTX 580" }, + { 0x1091, "Tesla M2090", nvkm_device_pci_10de_1091 }, + { 0x1094, "Tesla M2075" }, + { 0x1096, "Tesla C2075", nvkm_device_pci_10de_1096 }, + { 0x109a, "Quadro 5010M" }, + { 0x109b, "Quadro 7000" }, + { 0x10c0, "GeForce 9300 GS" }, + { 0x10c3, "GeForce 8400GS" }, + { 0x10c5, "GeForce 405" }, + { 0x10d8, "NVS 300" }, + { 0x1140, NULL, nvkm_device_pci_10de_1140 }, + { 0x1180, "GeForce GTX 680" }, + { 0x1183, "GeForce GTX 660 Ti" }, + { 0x1184, "GeForce GTX 770" }, + { 0x1185, "GeForce GTX 660", nvkm_device_pci_10de_1185 }, + { 0x1187, "GeForce GTX 760" }, + { 0x1188, "GeForce GTX 690" }, + { 0x1189, "GeForce GTX 670", nvkm_device_pci_10de_1189 }, + { 0x118a, "GRID K520" }, + { 0x118e, "GeForce GTX 760 (192-bit)" }, + { 0x118f, "Tesla K10" }, + { 0x1193, "GeForce GTX 760 Ti OEM" }, + { 0x1194, "Tesla K8" }, + { 0x1195, "GeForce GTX 660" }, + { 0x1198, "GeForce GTX 880M" }, + { 0x1199, "GeForce GTX 870M", nvkm_device_pci_10de_1199 }, + { 0x119a, "GeForce GTX 860M" }, + { 0x119d, "GeForce GTX 775M" }, + { 0x119e, "GeForce GTX 780M" }, + { 0x119f, "GeForce GTX 780M" }, + { 0x11a0, "GeForce GTX 680M" }, + { 0x11a1, "GeForce GTX 670MX" }, + { 0x11a2, "GeForce GTX 675MX" }, + { 0x11a3, "GeForce GTX 680MX" }, + { 0x11a7, "GeForce GTX 675MX" }, + { 0x11b4, "Quadro K4200" }, + { 0x11b6, "Quadro K3100M" }, + { 0x11b7, "Quadro K4100M" }, + { 0x11b8, "Quadro K5100M" }, + { 0x11ba, "Quadro K5000" }, + { 0x11bc, "Quadro K5000M" }, + { 0x11bd, "Quadro K4000M" }, + { 0x11be, "Quadro K3000M" }, + { 0x11bf, "GRID K2" }, + { 0x11c0, "GeForce GTX 660" }, + { 0x11c2, "GeForce GTX 650 Ti BOOST" }, + { 0x11c3, "GeForce GTX 650 Ti" }, + { 0x11c4, "GeForce GTX 645" }, + { 0x11c5, "GeForce GT 740" }, + { 0x11c6, "GeForce GTX 650 Ti" }, + { 0x11c8, "GeForce GTX 650" }, + { 0x11cb, "GeForce GT 740" }, + { 0x11e0, "GeForce GTX 770M" }, + { 0x11e1, "GeForce GTX 765M" }, + { 0x11e2, "GeForce GTX 765M" }, + { 0x11e3, "GeForce GTX 760M", nvkm_device_pci_10de_11e3 }, + { 0x11fa, "Quadro K4000" }, + { 0x11fc, "Quadro K2100M" }, + { 0x1200, "GeForce GTX 560 Ti" }, + { 0x1201, "GeForce GTX 560" }, + { 0x1203, "GeForce GTX 460 SE v2" }, + { 0x1205, "GeForce GTX 460 v2" }, + { 0x1206, "GeForce GTX 555" }, + { 0x1207, "GeForce GT 645" }, + { 0x1208, "GeForce GTX 560 SE" }, + { 0x1210, "GeForce GTX 570M" }, + { 0x1211, "GeForce GTX 580M" }, + { 0x1212, "GeForce GTX 675M" }, + { 0x1213, "GeForce GTX 670M" }, + { 0x1241, "GeForce GT 545" }, + { 0x1243, "GeForce GT 545" }, + { 0x1244, "GeForce GTX 550 Ti" }, + { 0x1245, "GeForce GTS 450" }, + { 0x1246, "GeForce GT 550M" }, + { 0x1247, "GeForce GT 555M", nvkm_device_pci_10de_1247 }, + { 0x1248, "GeForce GT 555M" }, + { 0x1249, "GeForce GTS 450" }, + { 0x124b, "GeForce GT 640" }, + { 0x124d, "GeForce GT 555M", nvkm_device_pci_10de_124d }, + { 0x1251, "GeForce GTX 560M" }, + { 0x1280, "GeForce GT 635" }, + { 0x1281, "GeForce GT 710" }, + { 0x1282, "GeForce GT 640" }, + { 0x1284, "GeForce GT 630" }, + { 0x1286, "GeForce GT 720" }, + { 0x1287, "GeForce GT 730" }, + { 0x1288, "GeForce GT 720" }, + { 0x1289, "GeForce GT 710" }, + { 0x1290, "GeForce GT 730M", nvkm_device_pci_10de_1290 }, + { 0x1291, "GeForce GT 735M" }, + { 0x1292, "GeForce GT 740M", nvkm_device_pci_10de_1292 }, + { 0x1293, "GeForce GT 730M" }, + { 0x1295, "GeForce 710M", nvkm_device_pci_10de_1295 }, + { 0x1296, "GeForce 825M" }, + { 0x1298, "GeForce GT 720M" }, + { 0x1299, "GeForce 920M", nvkm_device_pci_10de_1299 }, + { 0x129a, "GeForce 910M" }, + { 0x12b9, "Quadro K610M" }, + { 0x12ba, "Quadro K510M" }, + { 0x1340, "GeForce 830M", nvkm_device_pci_10de_1340 }, + { 0x1341, "GeForce 840M", nvkm_device_pci_10de_1341 }, + { 0x1344, "GeForce 845M" }, + { 0x1346, "GeForce 930M", nvkm_device_pci_10de_1346 }, + { 0x1347, "GeForce 940M", nvkm_device_pci_10de_1347 }, + { 0x137a, NULL, nvkm_device_pci_10de_137a }, + { 0x137d, NULL, nvkm_device_pci_10de_137d }, + { 0x1380, "GeForce GTX 750 Ti" }, + { 0x1381, "GeForce GTX 750" }, + { 0x1382, "GeForce GTX 745" }, + { 0x1390, "GeForce 845M" }, + { 0x1391, "GeForce GTX 850M", nvkm_device_pci_10de_1391 }, + { 0x1392, "GeForce GTX 860M", nvkm_device_pci_10de_1392 }, + { 0x1393, "GeForce 840M" }, + { 0x1398, "GeForce 845M" }, + { 0x139a, "GeForce GTX 950M", nvkm_device_pci_10de_139a }, + { 0x139b, "GeForce GTX 960M", nvkm_device_pci_10de_139b }, + { 0x139c, "GeForce 940M" }, + { 0x13b3, "Quadro K2200M" }, + { 0x13ba, "Quadro K2200" }, + { 0x13bb, "Quadro K620" }, + { 0x13bc, "Quadro K1200" }, + { 0x13c0, "GeForce GTX 980" }, + { 0x13c2, "GeForce GTX 970" }, + { 0x13d7, "GeForce GTX 980M" }, + { 0x13d8, "GeForce GTX 970M" }, + { 0x13d9, "GeForce GTX 965M" }, + { 0x1401, "GeForce GTX 960" }, + { 0x1617, "GeForce GTX 980M" }, + { 0x1618, "GeForce GTX 970M" }, + { 0x1619, "GeForce GTX 965M" }, + { 0x17c2, "GeForce GTX TITAN X" }, + { 0x17c8, "GeForce GTX 980 Ti" }, + { 0x17f0, "Quadro M6000" }, + {} +}; + +static struct nvkm_device_pci * +nvkm_device_pci(struct nvkm_device *device) +{ + return container_of(device, struct nvkm_device_pci, device); +} + +static resource_size_t +nvkm_device_pci_resource_addr(struct nvkm_device *device, unsigned bar) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + return pci_resource_start(pdev->pdev, bar); +} + +static resource_size_t +nvkm_device_pci_resource_size(struct nvkm_device *device, unsigned bar) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + return pci_resource_len(pdev->pdev, bar); +} + +static void +nvkm_device_pci_fini(struct nvkm_device *device, bool suspend) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + if (suspend) { + pci_disable_device(pdev->pdev); + pdev->suspend = true; + } +} + +static int +nvkm_device_pci_preinit(struct nvkm_device *device) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + if (pdev->suspend) { + int ret = pci_enable_device(pdev->pdev); + if (ret) + return ret; + pci_set_master(pdev->pdev); + pdev->suspend = false; + } + return 0; +} + +static void * +nvkm_device_pci_dtor(struct nvkm_device *device) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + pci_disable_device(pdev->pdev); + return pdev; +} + +static const struct nvkm_device_func +nvkm_device_pci_func = { + .pci = nvkm_device_pci, + .dtor = nvkm_device_pci_dtor, + .preinit = nvkm_device_pci_preinit, + .fini = nvkm_device_pci_fini, + .resource_addr = nvkm_device_pci_resource_addr, + .resource_size = nvkm_device_pci_resource_size, + .cpu_coherent = !IS_ENABLED(CONFIG_ARM), +}; + +int +nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **pdevice) +{ + const struct nvkm_device_quirk *quirk = NULL; + const struct nvkm_device_pci_device *pcid; + const struct nvkm_device_pci_vendor *pciv; + const char *name = NULL; + struct nvkm_device_pci *pdev; + int ret; + + ret = pci_enable_device(pci_dev); + if (ret) + return ret; + + switch (pci_dev->vendor) { + case 0x10de: pcid = nvkm_device_pci_10de; break; + default: + pcid = NULL; + break; + } + + while (pcid && pcid->device) { + if (pciv = pcid->vendor, pcid->device == pci_dev->device) { + while (pciv && pciv->vendor) { + if (pciv->vendor == pci_dev->subsystem_vendor && + pciv->device == pci_dev->subsystem_device) { + quirk = &pciv->quirk; + name = pciv->name; + break; + } + pciv++; + } + if (!name) + name = pcid->name; + break; + } + pcid++; + } + + if (!(pdev = kzalloc(sizeof(*pdev), GFP_KERNEL))) { + pci_disable_device(pci_dev); + return -ENOMEM; + } + *pdevice = &pdev->device; + pdev->pdev = pci_dev; + + return nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev, + pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE : + pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ? + NVKM_DEVICE_AGP : NVKM_DEVICE_PCI, + (u64)pci_domain_nr(pci_dev->bus) << 32 | + pci_dev->bus->number << 16 | + PCI_SLOT(pci_dev->devfn) << 8 | + PCI_FUNC(pci_dev->devfn), name, + cfg, dbg, detect, mmio, subdev_mask, + &pdev->device); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h index 8d3590e7b..ed3ad2c30 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h @@ -2,15 +2,49 @@ #define __NVKM_DEVICE_PRIV_H__ #include -extern struct nvkm_oclass nvkm_control_oclass[]; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -int nv04_identify(struct nvkm_device *); -int nv10_identify(struct nvkm_device *); -int nv20_identify(struct nvkm_device *); -int nv30_identify(struct nvkm_device *); -int nv40_identify(struct nvkm_device *); -int nv50_identify(struct nvkm_device *); -int gf100_identify(struct nvkm_device *); -int gk104_identify(struct nvkm_device *); -int gm100_identify(struct nvkm_device *); +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int nvkm_device_ctor(const struct nvkm_device_func *, + const struct nvkm_device_quirk *, + struct device *, enum nvkm_device_type, u64 handle, + const char *name, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device *); +int nvkm_device_init(struct nvkm_device *); +int nvkm_device_fini(struct nvkm_device *, bool suspend); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c new file mode 100644 index 000000000..e7e581d6a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * 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 AUTHORS OR COPYRIGHT HOLDERS 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 +#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER +#include "priv.h" + +static int +nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) +{ + int ret; + + ret = regulator_enable(tdev->vdd); + if (ret) + goto err_power; + + ret = clk_prepare_enable(tdev->clk); + if (ret) + goto err_clk; + ret = clk_prepare_enable(tdev->clk_pwr); + if (ret) + goto err_clk_pwr; + clk_set_rate(tdev->clk_pwr, 204000000); + udelay(10); + + reset_control_assert(tdev->rst); + udelay(10); + + ret = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D); + if (ret) + goto err_clamp; + udelay(10); + + reset_control_deassert(tdev->rst); + udelay(10); + + return 0; + +err_clamp: + clk_disable_unprepare(tdev->clk_pwr); +err_clk_pwr: + clk_disable_unprepare(tdev->clk); +err_clk: + regulator_disable(tdev->vdd); +err_power: + return ret; +} + +static int +nvkm_device_tegra_power_down(struct nvkm_device_tegra *tdev) +{ + reset_control_assert(tdev->rst); + udelay(10); + + clk_disable_unprepare(tdev->clk_pwr); + clk_disable_unprepare(tdev->clk); + udelay(10); + + return regulator_disable(tdev->vdd); +} + +static void +nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) +{ +#if IS_ENABLED(CONFIG_IOMMU_API) + struct device *dev = &tdev->pdev->dev; + unsigned long pgsize_bitmap; + int ret; + + if (!tdev->func->iommu_bit) + return; + + mutex_init(&tdev->iommu.mutex); + + if (iommu_present(&platform_bus_type)) { + tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); + if (IS_ERR(tdev->iommu.domain)) + goto error; + + /* + * A IOMMU is only usable if it supports page sizes smaller + * or equal to the system's PAGE_SIZE, with a preference if + * both are equal. + */ + pgsize_bitmap = tdev->iommu.domain->ops->pgsize_bitmap; + if (pgsize_bitmap & PAGE_SIZE) { + tdev->iommu.pgshift = PAGE_SHIFT; + } else { + tdev->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK); + if (tdev->iommu.pgshift == 0) { + dev_warn(dev, "unsupported IOMMU page size\n"); + goto free_domain; + } + tdev->iommu.pgshift -= 1; + } + + ret = iommu_attach_device(tdev->iommu.domain, dev); + if (ret) + goto free_domain; + + ret = nvkm_mm_init(&tdev->iommu.mm, 0, + (1ULL << tdev->func->iommu_bit) >> + tdev->iommu.pgshift, 1); + if (ret) + goto detach_device; + } + + return; + +detach_device: + iommu_detach_device(tdev->iommu.domain, dev); + +free_domain: + iommu_domain_free(tdev->iommu.domain); + +error: + tdev->iommu.domain = NULL; + tdev->iommu.pgshift = 0; + dev_err(dev, "cannot initialize IOMMU MM\n"); +#endif +} + +static void +nvkm_device_tegra_remove_iommu(struct nvkm_device_tegra *tdev) +{ +#if IS_ENABLED(CONFIG_IOMMU_API) + if (tdev->iommu.domain) { + nvkm_mm_fini(&tdev->iommu.mm); + iommu_detach_device(tdev->iommu.domain, tdev->device.dev); + iommu_domain_free(tdev->iommu.domain); + } +#endif +} + +static struct nvkm_device_tegra * +nvkm_device_tegra(struct nvkm_device *device) +{ + return container_of(device, struct nvkm_device_tegra, device); +} + +static struct resource * +nvkm_device_tegra_resource(struct nvkm_device *device, unsigned bar) +{ + struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); + return platform_get_resource(tdev->pdev, IORESOURCE_MEM, bar); +} + +static resource_size_t +nvkm_device_tegra_resource_addr(struct nvkm_device *device, unsigned bar) +{ + struct resource *res = nvkm_device_tegra_resource(device, bar); + return res ? res->start : 0; +} + +static resource_size_t +nvkm_device_tegra_resource_size(struct nvkm_device *device, unsigned bar) +{ + struct resource *res = nvkm_device_tegra_resource(device, bar); + return res ? resource_size(res) : 0; +} + +static irqreturn_t +nvkm_device_tegra_intr(int irq, void *arg) +{ + struct nvkm_device_tegra *tdev = arg; + struct nvkm_mc *mc = tdev->device.mc; + bool handled = false; + if (likely(mc)) { + nvkm_mc_intr_unarm(mc); + nvkm_mc_intr(mc, &handled); + nvkm_mc_intr_rearm(mc); + } + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static void +nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend) +{ + struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); + if (tdev->irq) { + free_irq(tdev->irq, tdev); + tdev->irq = 0; + }; +} + +static int +nvkm_device_tegra_init(struct nvkm_device *device) +{ + struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); + int irq, ret; + + irq = platform_get_irq_byname(tdev->pdev, "stall"); + if (irq < 0) + return irq; + + ret = request_irq(irq, nvkm_device_tegra_intr, + IRQF_SHARED, "nvkm", tdev); + if (ret) + return ret; + + tdev->irq = irq; + return 0; +} + +static void * +nvkm_device_tegra_dtor(struct nvkm_device *device) +{ + struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); + nvkm_device_tegra_power_down(tdev); + nvkm_device_tegra_remove_iommu(tdev); + return tdev; +} + +static const struct nvkm_device_func +nvkm_device_tegra_func = { + .tegra = nvkm_device_tegra, + .dtor = nvkm_device_tegra_dtor, + .init = nvkm_device_tegra_init, + .fini = nvkm_device_tegra_fini, + .resource_addr = nvkm_device_tegra_resource_addr, + .resource_size = nvkm_device_tegra_resource_size, + .cpu_coherent = false, +}; + +int +nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, + struct platform_device *pdev, + const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **pdevice) +{ + struct nvkm_device_tegra *tdev; + int ret; + + if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) + return -ENOMEM; + + tdev->func = func; + tdev->pdev = pdev; + tdev->irq = -1; + + tdev->vdd = devm_regulator_get(&pdev->dev, "vdd"); + if (IS_ERR(tdev->vdd)) { + ret = PTR_ERR(tdev->vdd); + goto free; + } + + tdev->rst = devm_reset_control_get(&pdev->dev, "gpu"); + if (IS_ERR(tdev->rst)) { + ret = PTR_ERR(tdev->rst); + goto free; + } + + tdev->clk = devm_clk_get(&pdev->dev, "gpu"); + if (IS_ERR(tdev->clk)) { + ret = PTR_ERR(tdev->clk); + goto free; + } + + tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr"); + if (IS_ERR(tdev->clk_pwr)) { + ret = PTR_ERR(tdev->clk_pwr); + goto free; + } + + nvkm_device_tegra_probe_iommu(tdev); + + ret = nvkm_device_tegra_power_up(tdev); + if (ret) + goto remove; + + tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value; + ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, + NVKM_DEVICE_TEGRA, pdev->id, NULL, + cfg, dbg, detect, mmio, subdev_mask, + &tdev->device); + if (ret) + goto powerdown; + + *pdevice = &tdev->device; + + return 0; + +powerdown: + nvkm_device_tegra_power_down(tdev); +remove: + nvkm_device_tegra_remove_iommu(tdev); +free: + kfree(tdev); + return ret; +} +#else +int +nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, + struct platform_device *pdev, + const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **pdevice) +{ + return -ENOSYS; +} +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c new file mode 100644 index 000000000..1ae48f270 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -0,0 +1,371 @@ +/* + * 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 + */ +#define nvkm_udevice(p) container_of((p), struct nvkm_udevice, object) +#include "priv.h" +#include "ctrl.h" + +#include +#include +#include +#include + +#include +#include + +struct nvkm_udevice { + struct nvkm_object object; + struct nvkm_device *device; +}; + +static int +nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size) +{ + struct nvkm_object *object = &udev->object; + struct nvkm_device *device = udev->device; + struct nvkm_fb *fb = device->fb; + struct nvkm_instmem *imem = device->imem; + union { + struct nv_device_info_v0 v0; + } *args = data; + int ret; + + nvif_ioctl(object, "device info size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "device info vers %d\n", args->v0.version); + } else + return ret; + + switch (device->chipset) { + case 0x01a: + case 0x01f: + case 0x04c: + case 0x04e: + case 0x063: + case 0x067: + case 0x068: + case 0x0aa: + case 0x0ac: + case 0x0af: + args->v0.platform = NV_DEVICE_INFO_V0_IGP; + break; + default: + switch (device->type) { + case NVKM_DEVICE_PCI: + args->v0.platform = NV_DEVICE_INFO_V0_PCI; + break; + case NVKM_DEVICE_AGP: + args->v0.platform = NV_DEVICE_INFO_V0_AGP; + break; + case NVKM_DEVICE_PCIE: + args->v0.platform = NV_DEVICE_INFO_V0_PCIE; + break; + case NVKM_DEVICE_TEGRA: + args->v0.platform = NV_DEVICE_INFO_V0_SOC; + break; + default: + WARN_ON(1); + break; + } + break; + } + + switch (device->card_type) { + case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break; + case NV_10: + case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break; + case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break; + case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break; + case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break; + case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break; + case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break; + case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break; + case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break; + default: + args->v0.family = 0; + break; + } + + args->v0.chipset = device->chipset; + args->v0.revision = device->chiprev; + if (fb && fb->ram) + args->v0.ram_size = args->v0.ram_user = fb->ram->size; + else + args->v0.ram_size = args->v0.ram_user = 0; + if (imem && args->v0.ram_size > 0) + args->v0.ram_user = args->v0.ram_user - imem->reserved; + + strncpy(args->v0.chip, device->chip->name, sizeof(args->v0.chip)); + strncpy(args->v0.name, device->name, sizeof(args->v0.name)); + return 0; +} + +static int +nvkm_udevice_time(struct nvkm_udevice *udev, void *data, u32 size) +{ + struct nvkm_device *device = udev->device; + union { + struct nv_device_time_v0 v0; + } *args = data; + int ret; + + if (nvif_unpack(args->v0, 0, 0, false)) { + args->v0.time = nvkm_timer_read(device->timer); + } + + return ret; +} + +static int +nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + switch (mthd) { + case NV_DEVICE_V0_INFO: + return nvkm_udevice_info(udev, data, size); + case NV_DEVICE_V0_TIME: + return nvkm_udevice_time(udev, data, size); + default: + break; + } + return -EINVAL; +} + +static int +nvkm_udevice_rd08(struct nvkm_object *object, u64 addr, u8 *data) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + *data = nvkm_rd08(udev->device, addr); + return 0; +} + +static int +nvkm_udevice_rd16(struct nvkm_object *object, u64 addr, u16 *data) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + *data = nvkm_rd16(udev->device, addr); + return 0; +} + +static int +nvkm_udevice_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + *data = nvkm_rd32(udev->device, addr); + return 0; +} + +static int +nvkm_udevice_wr08(struct nvkm_object *object, u64 addr, u8 data) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + nvkm_wr08(udev->device, addr, data); + return 0; +} + +static int +nvkm_udevice_wr16(struct nvkm_object *object, u64 addr, u16 data) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + nvkm_wr16(udev->device, addr, data); + return 0; +} + +static int +nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + nvkm_wr32(udev->device, addr, data); + return 0; +} + +static int +nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + struct nvkm_device *device = udev->device; + *addr = device->func->resource_addr(device, 0); + *size = device->func->resource_size(device, 0); + return 0; +} + +static int +nvkm_udevice_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + struct nvkm_device *device = udev->device; + int ret = 0; + + mutex_lock(&device->mutex); + if (!--device->refcount) { + ret = nvkm_device_fini(device, suspend); + if (ret && suspend) { + device->refcount++; + goto done; + } + } + +done: + mutex_unlock(&device->mutex); + return ret; +} + +static int +nvkm_udevice_init(struct nvkm_object *object) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + struct nvkm_device *device = udev->device; + int ret = 0; + + mutex_lock(&device->mutex); + if (!device->refcount++) { + ret = nvkm_device_init(device); + if (ret) { + device->refcount--; + goto done; + } + } + +done: + mutex_unlock(&device->mutex); + return ret; +} + +static int +nvkm_udevice_child_new(const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_udevice *udev = nvkm_udevice(oclass->parent); + const struct nvkm_device_oclass *sclass = oclass->priv; + return sclass->ctor(udev->device, oclass, data, size, pobject); +} + +static int +nvkm_udevice_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + struct nvkm_udevice *udev = nvkm_udevice(object); + struct nvkm_device *device = udev->device; + struct nvkm_engine *engine; + u64 mask = (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_FIFO) | + (1ULL << NVKM_ENGINE_DISP) | + (1ULL << NVKM_ENGINE_PM); + const struct nvkm_device_oclass *sclass = NULL; + int i; + + for (; i = __ffs64(mask), mask && !sclass; mask &= ~(1ULL << i)) { + if (!(engine = nvkm_device_engine(device, i)) || + !(engine->func->base.sclass)) + continue; + oclass->engine = engine; + + index -= engine->func->base.sclass(oclass, index, &sclass); + } + + if (!sclass) { + switch (index) { + case 0: sclass = &nvkm_control_oclass; break; + default: + return -EINVAL; + } + oclass->base = sclass->base; + } + + oclass->ctor = nvkm_udevice_child_new; + oclass->priv = sclass; + return 0; +} + +static const struct nvkm_object_func +nvkm_udevice_super = { + .init = nvkm_udevice_init, + .fini = nvkm_udevice_fini, + .mthd = nvkm_udevice_mthd, + .map = nvkm_udevice_map, + .rd08 = nvkm_udevice_rd08, + .rd16 = nvkm_udevice_rd16, + .rd32 = nvkm_udevice_rd32, + .wr08 = nvkm_udevice_wr08, + .wr16 = nvkm_udevice_wr16, + .wr32 = nvkm_udevice_wr32, + .sclass = nvkm_udevice_child_get, +}; + +static const struct nvkm_object_func +nvkm_udevice = { + .init = nvkm_udevice_init, + .fini = nvkm_udevice_fini, + .mthd = nvkm_udevice_mthd, + .sclass = nvkm_udevice_child_get, +}; + +int +nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + union { + struct nv_device_v0 v0; + } *args = data; + struct nvkm_client *client = oclass->client; + struct nvkm_object *parent = &client->object; + const struct nvkm_object_func *func; + struct nvkm_udevice *udev; + int ret; + + nvif_ioctl(parent, "create device size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create device v%d device %016llx\n", + args->v0.version, args->v0.device); + } else + return ret; + + /* give priviledged clients register access */ + if (client->super) + func = &nvkm_udevice_super; + else + func = &nvkm_udevice; + + if (!(udev = kzalloc(sizeof(*udev), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(func, oclass, &udev->object); + *pobject = &udev->object; + + /* find the device that matches what the client requested */ + if (args->v0.device != ~0) + udev->device = nvkm_device_find(args->v0.device); + else + udev->device = nvkm_device_find(client->device); + if (!udev->device) + return -ENODEV; + + return 0; +} + +const struct nvkm_sclass +nvkm_udevice_sclass = { + .oclass = NV_DEVICE, + .minver = 0, + .maxver = 0, + .ctor = nvkm_udevice_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index 16a4e2a37..04f604520 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -1,29 +1,93 @@ nvkm-y += nvkm/engine/disp/base.o -nvkm-y += nvkm/engine/disp/conn.o -nvkm-y += nvkm/engine/disp/outp.o -nvkm-y += nvkm/engine/disp/outpdp.o nvkm-y += nvkm/engine/disp/nv04.o nvkm-y += nvkm/engine/disp/nv50.o nvkm-y += nvkm/engine/disp/g84.o nvkm-y += nvkm/engine/disp/g94.o nvkm-y += nvkm/engine/disp/gt200.o nvkm-y += nvkm/engine/disp/gt215.o -nvkm-y += nvkm/engine/disp/gf110.o +nvkm-y += nvkm/engine/disp/gf119.o nvkm-y += nvkm/engine/disp/gk104.o nvkm-y += nvkm/engine/disp/gk110.o nvkm-y += nvkm/engine/disp/gm107.o nvkm-y += nvkm/engine/disp/gm204.o + +nvkm-y += nvkm/engine/disp/outp.o +nvkm-y += nvkm/engine/disp/outpdp.o nvkm-y += nvkm/engine/disp/dacnv50.o +nvkm-y += nvkm/engine/disp/piornv50.o +nvkm-y += nvkm/engine/disp/sornv50.o +nvkm-y += nvkm/engine/disp/sorg94.o +nvkm-y += nvkm/engine/disp/sorgf119.o +nvkm-y += nvkm/engine/disp/sorgm204.o nvkm-y += nvkm/engine/disp/dport.o + +nvkm-y += nvkm/engine/disp/conn.o + nvkm-y += nvkm/engine/disp/hdagt215.o -nvkm-y += nvkm/engine/disp/hdagf110.o +nvkm-y += nvkm/engine/disp/hdagf119.o + nvkm-y += nvkm/engine/disp/hdmig84.o nvkm-y += nvkm/engine/disp/hdmigt215.o -nvkm-y += nvkm/engine/disp/hdmigf110.o +nvkm-y += nvkm/engine/disp/hdmigf119.o nvkm-y += nvkm/engine/disp/hdmigk104.o -nvkm-y += nvkm/engine/disp/piornv50.o -nvkm-y += nvkm/engine/disp/sornv50.o -nvkm-y += nvkm/engine/disp/sorg94.o -nvkm-y += nvkm/engine/disp/sorgf110.o -nvkm-y += nvkm/engine/disp/sorgm204.o + nvkm-y += nvkm/engine/disp/vga.o + +nvkm-y += nvkm/engine/disp/rootnv04.o +nvkm-y += nvkm/engine/disp/rootnv50.o +nvkm-y += nvkm/engine/disp/rootg84.o +nvkm-y += nvkm/engine/disp/rootg94.o +nvkm-y += nvkm/engine/disp/rootgt200.o +nvkm-y += nvkm/engine/disp/rootgt215.o +nvkm-y += nvkm/engine/disp/rootgf119.o +nvkm-y += nvkm/engine/disp/rootgk104.o +nvkm-y += nvkm/engine/disp/rootgk110.o +nvkm-y += nvkm/engine/disp/rootgm107.o +nvkm-y += nvkm/engine/disp/rootgm204.o + +nvkm-y += nvkm/engine/disp/channv50.o +nvkm-y += nvkm/engine/disp/changf119.o + +nvkm-y += nvkm/engine/disp/dmacnv50.o +nvkm-y += nvkm/engine/disp/dmacgf119.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/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/coregm204.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/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/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 diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 23d1b5c0d..44b67719f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -25,7 +25,9 @@ #include "conn.h" #include "outp.h" +#include #include +#include #include #include @@ -33,7 +35,21 @@ #include #include -int +static void +nvkm_disp_vblank_fini(struct nvkm_event *event, int type, int head) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); + disp->func->head.vblank_fini(disp, head); +} + +static void +nvkm_disp_vblank_init(struct nvkm_event *event, int type, int head) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); + disp->func->head.vblank_init(disp, head); +} + +static int nvkm_disp_vblank_ctor(struct nvkm_object *object, void *data, u32 size, struct nvkm_notify *notify) { @@ -56,6 +72,13 @@ nvkm_disp_vblank_ctor(struct nvkm_object *object, void *data, u32 size, return ret; } +static const struct nvkm_event_func +nvkm_disp_vblank_func = { + .ctor = nvkm_disp_vblank_ctor, + .init = nvkm_disp_vblank_init, + .fini = nvkm_disp_vblank_fini, +}; + void nvkm_disp_vblank(struct nvkm_disp *disp, int head) { @@ -100,7 +123,7 @@ nvkm_disp_hpd_func = { int nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) { - struct nvkm_disp *disp = (void *)object->engine; + struct nvkm_disp *disp = nvkm_disp(object->engine); switch (type) { case NV04_DISP_NTFY_VBLANK: *event = &disp->vblank; @@ -114,127 +137,303 @@ nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) return -EINVAL; } -int -_nvkm_disp_fini(struct nvkm_object *object, bool suspend) +static void +nvkm_disp_class_del(struct nvkm_oproxy *oproxy) { - struct nvkm_disp *disp = (void *)object; - struct nvkm_output *outp; + struct nvkm_disp *disp = nvkm_disp(oproxy->base.engine); + mutex_lock(&disp->engine.subdev.mutex); + if (disp->client == oproxy) + disp->client = NULL; + mutex_unlock(&disp->engine.subdev.mutex); +} + +static const struct nvkm_oproxy_func +nvkm_disp_class = { + .dtor[1] = nvkm_disp_class_del, +}; + +static int +nvkm_disp_class_new(struct nvkm_device *device, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + const struct nvkm_disp_oclass *sclass = oclass->engn; + struct nvkm_disp *disp = nvkm_disp(oclass->engine); + struct nvkm_oproxy *oproxy; int ret; - list_for_each_entry(outp, &disp->outp, head) { - ret = nv_ofuncs(outp)->fini(nv_object(outp), suspend); - if (ret && suspend) - goto fail_outp; + ret = nvkm_oproxy_new_(&nvkm_disp_class, oclass, &oproxy); + if (ret) + return ret; + *pobject = &oproxy->base; + + mutex_lock(&disp->engine.subdev.mutex); + if (disp->client) { + mutex_unlock(&disp->engine.subdev.mutex); + return -EBUSY; } + disp->client = oproxy; + mutex_unlock(&disp->engine.subdev.mutex); - return nvkm_engine_fini(&disp->base, suspend); + return sclass->ctor(disp, oclass, data, size, &oproxy->object); +} -fail_outp: - list_for_each_entry_continue_reverse(outp, &disp->outp, head) { - nv_ofuncs(outp)->init(nv_object(outp)); +static const struct nvkm_device_oclass +nvkm_disp_sclass = { + .ctor = nvkm_disp_class_new, +}; + +static int +nvkm_disp_class_get(struct nvkm_oclass *oclass, int index, + const struct nvkm_device_oclass **class) +{ + struct nvkm_disp *disp = nvkm_disp(oclass->engine); + if (index == 0) { + const struct nvkm_disp_oclass *root = disp->func->root(disp); + oclass->base = root->base; + oclass->engn = root; + *class = &nvkm_disp_sclass; + return 0; } + return 1; +} - return ret; +static void +nvkm_disp_intr(struct nvkm_engine *engine) +{ + struct nvkm_disp *disp = nvkm_disp(engine); + disp->func->intr(disp); } -int -_nvkm_disp_init(struct nvkm_object *object) +static int +nvkm_disp_fini(struct nvkm_engine *engine, bool suspend) { - struct nvkm_disp *disp = (void *)object; + struct nvkm_disp *disp = nvkm_disp(engine); + struct nvkm_connector *conn; struct nvkm_output *outp; - int ret; - - ret = nvkm_engine_init(&disp->base); - if (ret) - return ret; list_for_each_entry(outp, &disp->outp, head) { - ret = nv_ofuncs(outp)->init(nv_object(outp)); - if (ret) - goto fail_outp; + nvkm_output_fini(outp); } - return ret; + list_for_each_entry(conn, &disp->conn, head) { + nvkm_connector_fini(conn); + } + + return 0; +} + +static int +nvkm_disp_init(struct nvkm_engine *engine) +{ + struct nvkm_disp *disp = nvkm_disp(engine); + struct nvkm_connector *conn; + struct nvkm_output *outp; -fail_outp: - list_for_each_entry_continue_reverse(outp, &disp->outp, head) { - nv_ofuncs(outp)->fini(nv_object(outp), false); + list_for_each_entry(conn, &disp->conn, head) { + nvkm_connector_init(conn); } - return ret; + list_for_each_entry(outp, &disp->outp, head) { + nvkm_output_init(outp); + } + + return 0; } -void -_nvkm_disp_dtor(struct nvkm_object *object) +static void * +nvkm_disp_dtor(struct nvkm_engine *engine) { - struct nvkm_disp *disp = (void *)object; - struct nvkm_output *outp, *outt; + struct nvkm_disp *disp = nvkm_disp(engine); + struct nvkm_connector *conn; + struct nvkm_output *outp; + void *data = disp; + + if (disp->func->dtor) + data = disp->func->dtor(disp); nvkm_event_fini(&disp->vblank); nvkm_event_fini(&disp->hpd); - if (disp->outp.next) { - list_for_each_entry_safe(outp, outt, &disp->outp, head) { - nvkm_object_ref(NULL, (struct nvkm_object **)&outp); - } + while (!list_empty(&disp->outp)) { + outp = list_first_entry(&disp->outp, typeof(*outp), head); + list_del(&outp->head); + nvkm_output_del(&outp); } - nvkm_engine_destroy(&disp->base); + while (!list_empty(&disp->conn)) { + conn = list_first_entry(&disp->conn, typeof(*conn), head); + list_del(&conn->head); + nvkm_connector_del(&conn); + } + + return data; } +static const struct nvkm_engine_func +nvkm_disp = { + .dtor = nvkm_disp_dtor, + .init = nvkm_disp_init, + .fini = nvkm_disp_fini, + .intr = nvkm_disp_intr, + .base.sclass = nvkm_disp_class_get, +}; + int -nvkm_disp_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int heads, const char *intname, - const char *extname, int length, void **pobject) +nvkm_disp_ctor(const struct nvkm_disp_func *func, struct nvkm_device *device, + int index, int heads, struct nvkm_disp *disp) { - struct nvkm_disp_impl *impl = (void *)oclass; - struct nvkm_bios *bios = nvkm_bios(parent); - struct nvkm_disp *disp; - struct nvkm_oclass **sclass; - struct nvkm_object *object; + struct nvkm_bios *bios = device->bios; + struct nvkm_output *outp, *outt, *pair; + struct nvkm_connector *conn; + struct nvbios_connE connE; struct dcb_output dcbE; u8 hpd = 0, ver, hdr; u32 data; int ret, i; - ret = nvkm_engine_create_(parent, engine, oclass, true, intname, - extname, length, pobject); - disp = *pobject; + INIT_LIST_HEAD(&disp->outp); + INIT_LIST_HEAD(&disp->conn); + disp->func = func; + disp->head.nr = heads; + + ret = nvkm_engine_ctor(&nvkm_disp, device, index, 0, + true, &disp->engine); if (ret) return ret; - INIT_LIST_HEAD(&disp->outp); - /* create output objects for each display path in the vbios */ i = -1; while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) { + const struct nvkm_disp_func_outp *outps; + int (*ctor)(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); + if (dcbE.type == DCB_OUTPUT_UNUSED) continue; if (dcbE.type == DCB_OUTPUT_EOL) break; - data = dcbE.location << 4 | dcbE.type; + outp = NULL; + + switch (dcbE.location) { + case 0: outps = &disp->func->outp.internal; break; + case 1: outps = &disp->func->outp.external; break; + default: + nvkm_warn(&disp->engine.subdev, + "dcb %d locn %d unknown\n", i, dcbE.location); + continue; + } - oclass = nvkm_output_oclass; - sclass = impl->outp; - while (sclass && sclass[0]) { - if (sclass[0]->handle == data) { - oclass = sclass[0]; - break; + switch (dcbE.type) { + case DCB_OUTPUT_ANALOG: ctor = outps->crt ; break; + case DCB_OUTPUT_TV : ctor = outps->tv ; break; + case DCB_OUTPUT_TMDS : ctor = outps->tmds; break; + case DCB_OUTPUT_LVDS : ctor = outps->lvds; break; + case DCB_OUTPUT_DP : ctor = outps->dp ; break; + default: + nvkm_warn(&disp->engine.subdev, + "dcb %d type %d unknown\n", i, dcbE.type); + continue; + } + + if (ctor) + ret = ctor(disp, i, &dcbE, &outp); + else + ret = -ENODEV; + + if (ret) { + if (ret == -ENODEV) { + nvkm_debug(&disp->engine.subdev, + "dcb %d %d/%d not supported\n", + i, dcbE.location, dcbE.type); + continue; } - sclass++; + nvkm_error(&disp->engine.subdev, + "failed to create output %d\n", i); + nvkm_output_del(&outp); + continue; } - nvkm_object_ctor(*pobject, NULL, oclass, &dcbE, i, &object); + list_add_tail(&outp->head, &disp->outp); hpd = max(hpd, (u8)(dcbE.connector + 1)); } + /* create connector objects based on the outputs we support */ + list_for_each_entry_safe(outp, outt, &disp->outp, head) { + /* bios data *should* give us the most useful information */ + data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, + &connE); + + /* no bios connector data... */ + if (!data) { + /* heuristic: anything with the same ccb index is + * considered to be on the same connector, any + * output path without an associated ccb entry will + * be put on its own connector + */ + int ccb_index = outp->info.i2c_index; + if (ccb_index != 0xf) { + list_for_each_entry(pair, &disp->outp, head) { + if (pair->info.i2c_index == ccb_index) { + outp->conn = pair->conn; + break; + } + } + } + + /* connector shared with another output path */ + if (outp->conn) + continue; + + memset(&connE, 0x00, sizeof(connE)); + connE.type = DCB_CONNECTOR_NONE; + i = -1; + } else { + i = outp->info.connector; + } + + /* check that we haven't already created this connector */ + list_for_each_entry(conn, &disp->conn, head) { + if (conn->index == outp->info.connector) { + outp->conn = conn; + break; + } + } + + if (outp->conn) + continue; + + /* apparently we need to create a new one! */ + ret = nvkm_connector_new(disp, i, &connE, &outp->conn); + if (ret) { + nvkm_error(&disp->engine.subdev, + "failed to create output %d conn: %d\n", + outp->index, ret); + nvkm_connector_del(&outp->conn); + list_del(&outp->head); + nvkm_output_del(&outp); + continue; + } + + list_add_tail(&outp->conn->head, &disp->conn); + } + ret = nvkm_event_init(&nvkm_disp_hpd_func, 3, hpd, &disp->hpd); if (ret) return ret; - ret = nvkm_event_init(impl->vblank, 1, heads, &disp->vblank); + ret = nvkm_event_init(&nvkm_disp_vblank_func, 1, heads, &disp->vblank); if (ret) return ret; return 0; } + +int +nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, + int index, int heads, struct nvkm_disp **pdisp) +{ + if (!(*pdisp = kzalloc(sizeof(**pdisp), GFP_KERNEL))) + return -ENOMEM; + return nvkm_disp_ctor(func, device, index, heads, *pdisp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c new file mode 100644 index 000000000..6d17630a3 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c @@ -0,0 +1,80 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +g84_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00c4, 0x610800 }, + { 0x00c8, 0x61080c }, + { 0x00cc, 0x610818 }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x00fc, 0x610824 }, + { 0x0100, 0x610894 }, + { 0x0104, 0x61082c }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +const struct nv50_disp_chan_mthd +g84_disp_base_chan_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c new file mode 100644 index 000000000..ebcb925e9 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c @@ -0,0 +1,114 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +gf119_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x661080 }, + { 0x0084, 0x661084 }, + { 0x0088, 0x661088 }, + { 0x008c, 0x66108c }, + { 0x0090, 0x661090 }, + { 0x0094, 0x661094 }, + { 0x00a0, 0x6610a0 }, + { 0x00a4, 0x6610a4 }, + { 0x00c0, 0x6610c0 }, + { 0x00c4, 0x6610c4 }, + { 0x00c8, 0x6610c8 }, + { 0x00cc, 0x6610cc }, + { 0x00e0, 0x6610e0 }, + { 0x00e4, 0x6610e4 }, + { 0x00e8, 0x6610e8 }, + { 0x00ec, 0x6610ec }, + { 0x00fc, 0x6610fc }, + { 0x0100, 0x661100 }, + { 0x0104, 0x661104 }, + { 0x0108, 0x661108 }, + { 0x010c, 0x66110c }, + { 0x0110, 0x661110 }, + { 0x0114, 0x661114 }, + { 0x0118, 0x661118 }, + { 0x011c, 0x66111c }, + { 0x0130, 0x661130 }, + { 0x0134, 0x661134 }, + { 0x0138, 0x661138 }, + { 0x013c, 0x66113c }, + { 0x0140, 0x661140 }, + { 0x0144, 0x661144 }, + { 0x0148, 0x661148 }, + { 0x014c, 0x66114c }, + { 0x0150, 0x661150 }, + { 0x0154, 0x661154 }, + { 0x0158, 0x661158 }, + { 0x015c, 0x66115c }, + { 0x0160, 0x661160 }, + { 0x0164, 0x661164 }, + { 0x0168, 0x661168 }, + { 0x016c, 0x66116c }, + {} + } +}; + +static const struct nv50_disp_mthd_list +gf119_disp_base_mthd_image = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0400, 0x661400 }, + { 0x0404, 0x661404 }, + { 0x0408, 0x661408 }, + { 0x040c, 0x66140c }, + { 0x0410, 0x661410 }, + {} + } +}; + +const struct nv50_disp_chan_mthd +gf119_disp_base_chan_mthd = { + .name = "Base", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_base_mthd_base }, + { "Image", 2, &gf119_disp_base_mthd_image }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c new file mode 100644 index 000000000..780a1d973 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c new file mode 100644 index 000000000..d8bdd246c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c new file mode 100644 index 000000000..93451e465 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c new file mode 100644 index 000000000..08e2b1fa3 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c new file mode 100644 index 000000000..1fd89edef --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c @@ -0,0 +1,123 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +#include +#include + +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) +{ + union { + struct nv50_disp_base_channel_dma_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; + u64 push; + + nvif_ioctl(parent, "create disp base channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp base channel dma vers %d " + "pushbuf %016llx head %d\n", + args->v0.version, args->v0.pushbuf, args->v0.head); + if (args->v0.head > disp->base.head.nr) + return -EINVAL; + push = args->v0.pushbuf; + head = args->v0.head; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, root, chid + head, + head, push, oclass, pobject); +} + +static const struct nv50_disp_mthd_list +nv50_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x0100, 0x610894 }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +const struct nv50_disp_mthd_list +nv50_disp_base_mthd_image = { + .mthd = 0x0400, + .addr = 0x000000, + .data = { + { 0x0800, 0x6108f0 }, + { 0x0804, 0x6108fc }, + { 0x0808, 0x61090c }, + { 0x080c, 0x610914 }, + { 0x0810, 0x610904 }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +nv50_disp_base_chan_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c new file mode 100644 index 000000000..17a3d835c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c @@ -0,0 +1,49 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "channv50.h" + +static void +gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x61008c, 0x00000001 << index); +} + +static void +gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_wr32(device, 0x61008c, 0x00000001 << index); + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); +} + +const struct nvkm_event_func +gf119_disp_chan_uevent = { + .ctor = nv50_disp_chan_uevent_ctor, + .init = gf119_disp_chan_uevent_init, + .fini = gf119_disp_chan_uevent_fini, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c new file mode 100644 index 000000000..01803c067 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -0,0 +1,301 @@ +/* + * 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 +#include +#include + +#include +#include +#include + +static void +nv50_disp_mthd_list(struct nv50_disp *disp, int debug, u32 base, int c, + const struct nv50_disp_mthd_list *list, int inst) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int i; + + for (i = 0; list->data[i].mthd; i++) { + if (list->data[i].addr) { + u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); + u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); + u32 mthd = list->data[i].mthd + (list->mthd * inst); + const char *name = list->data[i].name; + char mods[16]; + + if (prev != next) + snprintf(mods, sizeof(mods), "-> %08x", next); + else + snprintf(mods, sizeof(mods), "%13c", ' '); + + nvkm_printk_(subdev, debug, info, + "\t%04x: %08x %s%s%s\n", + mthd, prev, mods, name ? " // " : "", + name ? name : ""); + } + } +} + +void +nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) +{ + struct nv50_disp *disp = chan->root->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; + int i, j; + + if (debug > subdev->debug) + return; + + for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { + u32 base = chan->head * mthd->addr; + for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { + const char *cname = mthd->name; + const char *sname = ""; + char cname_[16], sname_[16]; + + if (mthd->addr) { + snprintf(cname_, sizeof(cname_), "%s %d", + mthd->name, chan->chid); + cname = cname_; + } + + if (mthd->data[i].nr > 1) { + snprintf(sname_, sizeof(sname_), " - %s %d", + mthd->data[i].name, j); + sname = sname_; + } + + nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); + nv50_disp_mthd_list(disp, debug, base, mthd->prev, + list, j); + } + } +} + +static void +nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x610020, 0x00000001 << index); +} + +static void +nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_wr32(device, 0x610020, 0x00000001 << index); + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); +} + +void +nv50_disp_chan_uevent_send(struct nv50_disp *disp, int chid) +{ + struct nvif_notify_uevent_rep { + } rep; + + nvkm_event_send(&disp->uevent, 1, chid, &rep, sizeof(rep)); +} + +int +nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + union { + struct nvif_notify_uevent_req none; + } *args = data; + int ret; + + if (nvif_unvers(args->none)) { + notify->size = sizeof(struct nvif_notify_uevent_rep); + notify->types = 1; + notify->index = chan->chid; + return 0; + } + + return ret; +} + +const struct nvkm_event_func +nv50_disp_chan_uevent = { + .ctor = nv50_disp_chan_uevent_ctor, + .init = nv50_disp_chan_uevent_init, + .fini = nv50_disp_chan_uevent_fini, +}; + +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 * 0x1000) + addr); + return 0; +} + +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 * 0x1000) + addr, data); + return 0; +} + +int +nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, + struct nvkm_event **pevent) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; + switch (type) { + case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: + *pevent = &disp->uevent; + return 0; + default: + break; + } + return -EINVAL; +} + +int +nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *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; + *addr = device->func->resource_addr(device, 0) + + 0x640000 + (chan->chid * 0x1000); + *size = 0x001000; + return 0; +} + +static int +nv50_disp_chan_child_new(const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(oclass->parent); + return chan->func->child_new(chan, oclass, data, size, pobject); +} + +static int +nv50_disp_chan_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + 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; + } + return -EINVAL; +} + +static int +nv50_disp_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + chan->func->fini(chan); + return 0; +} + +static int +nv50_disp_chan_init(struct nvkm_object *object) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + return chan->func->init(chan); +} + +static void * +nv50_disp_chan_dtor(struct nvkm_object *object) +{ + struct nv50_disp_chan *chan = nv50_disp_chan(object); + struct nv50_disp *disp = chan->root->disp; + if (chan->chid >= 0) + disp->chan[chan->chid] = NULL; + return chan->func->dtor ? chan->func->dtor(chan) : chan; +} + +static const struct nvkm_object_func +nv50_disp_chan = { + .dtor = nv50_disp_chan_dtor, + .init = nv50_disp_chan_init, + .fini = nv50_disp_chan_fini, + .rd32 = nv50_disp_chan_rd32, + .wr32 = nv50_disp_chan_wr32, + .ntfy = nv50_disp_chan_ntfy, + .map = nv50_disp_chan_map, + .sclass = nv50_disp_chan_child_get, +}; + +int +nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, int head, + const struct nvkm_oclass *oclass, + struct nv50_disp_chan *chan) +{ + struct nv50_disp *disp = root->disp; + + nvkm_object_ctor(&nv50_disp_chan, oclass, &chan->object); + chan->func = func; + chan->mthd = mthd; + chan->root = root; + chan->chid = chid; + chan->head = head; + + if (disp->chan[chan->chid]) { + chan->chid = -1; + return -EBUSY; + } + disp->chan[chan->chid] = 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 chid, 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, chid, head, oclass, chan); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h new file mode 100644 index 000000000..aee374884 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h @@ -0,0 +1,127 @@ +#ifndef __NV50_DISP_CHAN_H__ +#define __NV50_DISP_CHAN_H__ +#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) +#include "nv50.h" + +struct nv50_disp_chan { + const struct nv50_disp_chan_func *func; + const struct nv50_disp_chan_mthd *mthd; + struct nv50_disp_root *root; + int chid; + int head; + + struct nvkm_object object; +}; + +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 **); +}; + +int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, 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 chid, int head, + const struct nvkm_oclass *, struct nvkm_object **); + +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 nvkm_event_func gf119_disp_chan_uevent; + +struct nv50_disp_mthd_list { + u32 mthd; + u32 addr; + struct { + u32 mthd; + u32 addr; + const char *name; + } data[]; +}; + +struct nv50_disp_chan_mthd { + const char *name; + u32 addr; + s32 prev; + struct { + const char *name; + int nr; + const struct nv50_disp_mthd_list *mthd; + } data[]; +}; + +void nv50_disp_chan_mthd(struct nv50_disp_chan *, int debug); + +extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_base; +extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_sor; +extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_pior; +extern const struct nv50_disp_mthd_list nv50_disp_base_mthd_image; + +extern const struct nv50_disp_chan_mthd g84_disp_core_chan_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_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; + +struct nv50_disp_pioc_oclass { + int (*ctor)(const struct nv50_disp_chan_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_chan_func *func; + const struct nv50_disp_chan_mthd *mthd; + int 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; + + +int nv50_disp_curs_new(const struct nv50_disp_chan_func *, + const struct nv50_disp_chan_mthd *, + struct nv50_disp_root *, int chid, + 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 chid, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c index cf03e0240..c6910d644 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c @@ -33,15 +33,15 @@ static int nvkm_connector_hpd(struct nvkm_notify *notify) { struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd); - struct nvkm_disp *disp = nvkm_disp(conn); - struct nvkm_gpio *gpio = nvkm_gpio(conn); + struct nvkm_disp *disp = conn->disp; + struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio; const struct nvkm_gpio_ntfy_rep *line = notify->data; struct nvif_notify_conn_rep_v0 rep; int index = conn->index; - DBG("HPD: %d\n", line->mask); + CONN_DBG(conn, "HPD: %d", line->mask); - if (!gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index)) + if (!nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index)) rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG; else rep.mask = NVIF_NOTIFY_CONN_V0_PLUG; @@ -51,78 +51,58 @@ nvkm_connector_hpd(struct nvkm_notify *notify) return NVKM_NOTIFY_KEEP; } -int -_nvkm_connector_fini(struct nvkm_object *object, bool suspend) +void +nvkm_connector_fini(struct nvkm_connector *conn) { - struct nvkm_connector *conn = (void *)object; nvkm_notify_put(&conn->hpd); - return nvkm_object_fini(&conn->base, suspend); } -int -_nvkm_connector_init(struct nvkm_object *object) +void +nvkm_connector_init(struct nvkm_connector *conn) { - struct nvkm_connector *conn = (void *)object; - int ret = nvkm_object_init(&conn->base); - if (ret == 0) - nvkm_notify_get(&conn->hpd); - return ret; + nvkm_notify_get(&conn->hpd); } void -_nvkm_connector_dtor(struct nvkm_object *object) +nvkm_connector_del(struct nvkm_connector **pconn) { - struct nvkm_connector *conn = (void *)object; - nvkm_notify_fini(&conn->hpd); - nvkm_object_destroy(&conn->base); + struct nvkm_connector *conn = *pconn; + if (conn) { + nvkm_notify_fini(&conn->hpd); + kfree(*pconn); + *pconn = NULL; + } } -int -nvkm_connector_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, - struct nvbios_connE *info, int index, - int length, void **pobject) +static void +nvkm_connector_ctor(struct nvkm_disp *disp, int index, + struct nvbios_connE *info, struct nvkm_connector *conn) { static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 }; - struct nvkm_disp *disp = nvkm_disp(parent); - struct nvkm_gpio *gpio = nvkm_gpio(parent); - struct nvkm_connector *conn; - struct nvkm_output *outp; + struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio; struct dcb_gpio_func func; int ret; - list_for_each_entry(outp, &disp->outp, head) { - if (outp->conn && outp->conn->index == index) { - atomic_inc(&nv_object(outp->conn)->refcount); - *pobject = outp->conn; - return 1; - } - } - - ret = nvkm_object_create_(parent, engine, oclass, 0, length, pobject); - conn = *pobject; - if (ret) - return ret; - - conn->info = *info; + conn->disp = disp; conn->index = index; + conn->info = *info; - DBG("type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x\n", - info->type, info->location, info->hpd, info->dp, - info->di, info->sr, info->lcdid); + CONN_DBG(conn, "type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x", + info->type, info->location, info->hpd, info->dp, + info->di, info->sr, info->lcdid); if ((info->hpd = ffs(info->hpd))) { if (--info->hpd >= ARRAY_SIZE(hpd)) { - ERR("hpd %02x unknown\n", info->hpd); - return 0; + CONN_ERR(conn, "hpd %02x unknown", info->hpd); + return; } info->hpd = hpd[info->hpd]; - ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); + ret = nvkm_gpio_find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); if (ret) { - ERR("func %02x lookup failed, %d\n", info->hpd, ret); - return 0; + CONN_ERR(conn, "func %02x lookup failed, %d", + info->hpd, ret); + return; } ret = nvkm_notify_init(NULL, &gpio->event, nvkm_connector_hpd, @@ -134,41 +114,19 @@ nvkm_connector_create_(struct nvkm_object *parent, sizeof(struct nvkm_gpio_ntfy_rep), &conn->hpd); if (ret) { - ERR("func %02x failed, %d\n", info->hpd, ret); + CONN_ERR(conn, "func %02x failed, %d", info->hpd, ret); } else { - DBG("func %02x (HPD)\n", info->hpd); + CONN_DBG(conn, "func %02x (HPD)", info->hpd); } } - - return 0; } int -_nvkm_connector_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *info, u32 index, - struct nvkm_object **pobject) +nvkm_connector_new(struct nvkm_disp *disp, int index, + struct nvbios_connE *info, struct nvkm_connector **pconn) { - struct nvkm_connector *conn; - int ret; - - ret = nvkm_connector_create(parent, engine, oclass, info, index, &conn); - *pobject = nv_object(conn); - if (ret) - return ret; - + if (!(*pconn = kzalloc(sizeof(**pconn), GFP_KERNEL))) + return -ENOMEM; + nvkm_connector_ctor(disp, index, info, *pconn); return 0; } - -struct nvkm_oclass * -nvkm_connector_oclass = &(struct nvkm_connector_impl) { - .base = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_connector_ctor, - .dtor = _nvkm_connector_dtor, - .init = _nvkm_connector_init, - .fini = _nvkm_connector_fini, - }, - }, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h index c87a061f7..ed32fe7f1 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h @@ -1,58 +1,33 @@ #ifndef __NVKM_DISP_CONN_H__ #define __NVKM_DISP_CONN_H__ -#include -#include +#include +#include #include #include struct nvkm_connector { - struct nvkm_object base; - struct list_head head; - - struct nvbios_connE info; + struct nvkm_disp *disp; int index; + struct nvbios_connE info; struct nvkm_notify hpd; -}; -#define nvkm_connector_create(p,e,c,b,i,d) \ - nvkm_connector_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) -#define nvkm_connector_destroy(d) ({ \ - struct nvkm_connector *disp = (d); \ - _nvkm_connector_dtor(nv_object(disp)); \ -}) -#define nvkm_connector_init(d) ({ \ - struct nvkm_connector *disp = (d); \ - _nvkm_connector_init(nv_object(disp)); \ -}) -#define nvkm_connector_fini(d,s) ({ \ - struct nvkm_connector *disp = (d); \ - _nvkm_connector_fini(nv_object(disp), (s)); \ -}) - -int nvkm_connector_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, struct nvbios_connE *, - int, int, void **); - -int _nvkm_connector_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void _nvkm_connector_dtor(struct nvkm_object *); -int _nvkm_connector_init(struct nvkm_object *); -int _nvkm_connector_fini(struct nvkm_object *, bool); - -struct nvkm_connector_impl { - struct nvkm_oclass base; + struct list_head head; }; -#ifndef MSG -#define MSG(l,f,a...) do { \ - struct nvkm_connector *_conn = (void *)conn; \ - nv_##l(_conn, "%02x:%02x%02x: "f, _conn->index, \ - _conn->info.location, _conn->info.type, ##a); \ +int nvkm_connector_new(struct nvkm_disp *, int index, struct nvbios_connE *, + struct nvkm_connector **); +void nvkm_connector_del(struct nvkm_connector **); +void nvkm_connector_init(struct nvkm_connector *); +void nvkm_connector_fini(struct nvkm_connector *); + +#define CONN_MSG(c,l,f,a...) do { \ + struct nvkm_connector *_conn = (c); \ + nvkm_##l(&_conn->disp->engine.subdev, "conn %02x:%02x%02x: "f"\n", \ + _conn->index, _conn->info.location, _conn->info.type, ##a); \ } while(0) -#define DBG(f,a...) MSG(debug, f, ##a) -#define ERR(f,a...) MSG(error, f, ##a) -#endif +#define CONN_ERR(c,f,a...) CONN_MSG((c), error, f, ##a) +#define CONN_DBG(c,f,a...) CONN_MSG((c), debug, f, ##a) +#define CONN_TRACE(c,f,a...) CONN_MSG((c), trace, f, ##a) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c new file mode 100644 index 000000000..1baa5c34b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c @@ -0,0 +1,117 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +const struct nv50_disp_mthd_list +g84_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610bc4 }, + {} + } +}; + +const struct nv50_disp_mthd_list +g84_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x085c, 0x610c5c }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0878, 0x610c50 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x089c, 0x610c68 }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + { 0x0910, 0x610c70 }, + { 0x0914, 0x610c78 }, + {} + } +}; + +const struct nv50_disp_chan_mthd +g84_disp_core_chan_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c new file mode 100644 index 000000000..019379a3a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c @@ -0,0 +1,63 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +const struct nv50_disp_mthd_list +g94_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610794 }, + {} + } +}; + +const struct nv50_disp_chan_mthd +g94_disp_core_chan_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 4, &g94_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c new file mode 100644 index 000000000..6b1dc703d --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c @@ -0,0 +1,244 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include +#include + +#include +#include + +const struct nv50_disp_mthd_list +gf119_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x660080 }, + { 0x0084, 0x660084 }, + { 0x0088, 0x660088 }, + { 0x008c, 0x000000 }, + {} + } +}; + +const struct nv50_disp_mthd_list +gf119_disp_core_mthd_dac = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0180, 0x660180 }, + { 0x0184, 0x660184 }, + { 0x0188, 0x660188 }, + { 0x0190, 0x660190 }, + {} + } +}; + +const struct nv50_disp_mthd_list +gf119_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0200, 0x660200 }, + { 0x0204, 0x660204 }, + { 0x0208, 0x660208 }, + { 0x0210, 0x660210 }, + {} + } +}; + +const struct nv50_disp_mthd_list +gf119_disp_core_mthd_pior = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x660300 }, + { 0x0304, 0x660304 }, + { 0x0308, 0x660308 }, + { 0x0310, 0x660310 }, + {} + } +}; + +static const struct nv50_disp_mthd_list +gf119_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +gf119_disp_core_chan_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gf119_disp_core_mthd_head }, + {} + } +}; + +static void +gf119_disp_core_fini(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610490)); + } + + /* 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) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &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); + nvkm_wr32(device, 0x61049c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, 0x00000000); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +const struct nv50_disp_dmac_func +gf119_disp_core_func = { + .init = gf119_disp_core_init, + .fini = gf119_disp_core_fini, + .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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c new file mode 100644 index 000000000..088ab222e --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c @@ -0,0 +1,132 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +gk104_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x047c, 0x66047c }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x0488, 0x660488 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04a0, 0x6604a0 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x0520, 0x660520 }, + { 0x0524, 0x660524 }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +const struct nv50_disp_chan_mthd +gk104_disp_core_chan_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gk104_disp_core_mthd_head }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c new file mode 100644 index 000000000..df0f45c20 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c new file mode 100644 index 000000000..9e27f8fd9 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c new file mode 100644 index 000000000..222f4a822 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm204.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +const struct nv50_disp_dmac_oclass +gm204_disp_core_oclass = { + .base.oclass = GM204_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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c new file mode 100644 index 000000000..b23454770 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c new file mode 100644 index 000000000..8f5ba2018 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c new file mode 100644 index 000000000..db4a9b3e0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c @@ -0,0 +1,242 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include +#include + +#include +#include + +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) +{ + union { + struct nv50_disp_core_channel_dma_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + u64 push; + int ret; + + nvif_ioctl(parent, "create disp core channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp core channel dma vers %d " + "pushbuf %016llx\n", + args->v0.version, args->v0.pushbuf); + push = args->v0.pushbuf; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, root, chid, 0, + push, oclass, pobject); +} + +const struct nv50_disp_mthd_list +nv50_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x610bb8 }, + { 0x0088, 0x610b9c }, + { 0x008c, 0x000000 }, + {} + } +}; + +static const struct nv50_disp_mthd_list +nv50_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610828 }, + {} + } +}; + +const struct nv50_disp_mthd_list +nv50_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610b70 }, + {} + } +}; + +const struct nv50_disp_mthd_list +nv50_disp_core_mthd_pior = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0700, 0x610b80 }, + {} + } +}; + +static const struct nv50_disp_mthd_list +nv50_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +nv50_disp_core_chan_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &nv50_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &nv50_disp_core_mthd_head }, + {} + } +}; + +static void +nv50_disp_core_fini(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610200)); + } + + /* disable error reporting and completion notifications */ + nvkm_mask(device, 0x610028, 0x00010001, 0x00000000); +} + +static int +nv50_disp_core_init(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &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); + if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) + nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204, chan->push); + nvkm_wr32(device, 0x610208, 0x00010000); + nvkm_wr32(device, 0x61020c, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, 0x00000000); + nvkm_wr32(device, 0x610200, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610200)); + return -EBUSY; + } + + return 0; +} + +const struct nv50_disp_dmac_func +nv50_disp_core_func = { + .init = nv50_disp_core_init, + .fini = nv50_disp_core_fini, + .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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c new file mode 100644 index 000000000..dd99fc706 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c @@ -0,0 +1,37 @@ +/* + * 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 + */ +#include "channv50.h" +#include "rootnv50.h" + +#include + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c new file mode 100644 index 000000000..2a1574e06 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c @@ -0,0 +1,37 @@ +/* + * 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 + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c new file mode 100644 index 000000000..28e8f06c9 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c @@ -0,0 +1,37 @@ +/* + * 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 + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c new file mode 100644 index 000000000..d8a4b9ca1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c @@ -0,0 +1,37 @@ +/* + * 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 + */ +#include "channv50.h" +#include "rootnv50.h" + +#include + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c new file mode 100644 index 000000000..225858e62 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c @@ -0,0 +1,68 @@ +/* + * 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 + +#include +#include + +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 chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_cursor_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; + + nvif_ioctl(parent, "create disp cursor size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp cursor vers %d head %d\n", + args->v0.version, args->v0.head); + if (args->v0.head > disp->base.head.nr) + return -EINVAL; + head = args->v0.head; + } else + return ret; + + return nv50_disp_chan_new_(func, mthd, root, chid + 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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c index 0f7d1ec4d..9bfa9e7dc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c @@ -33,6 +33,7 @@ int nv50_dac_power(NV50_DISP_MTHD_V1) { + struct nvkm_device *device = disp->base.engine.subdev.device; const u32 doff = outp->or * 0x800; union { struct nv50_disp_dac_pwr_v0 v0; @@ -40,12 +41,12 @@ nv50_dac_power(NV50_DISP_MTHD_V1) u32 stat; int ret; - nv_ioctl(object, "disp dac pwr size %d\n", size); + nvif_ioctl(object, "disp dac pwr size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp dac pwr vers %d state %d data %d " - "vsync %d hsync %d\n", - args->v0.version, args->v0.state, args->v0.data, - args->v0.vsync, args->v0.hsync); + nvif_ioctl(object, "disp dac pwr vers %d state %d data %d " + "vsync %d hsync %d\n", + args->v0.version, args->v0.state, args->v0.data, + args->v0.vsync, args->v0.hsync); stat = 0x00000040 * !args->v0.state; stat |= 0x00000010 * !args->v0.data; stat |= 0x00000004 * !args->v0.vsync; @@ -53,15 +54,23 @@ nv50_dac_power(NV50_DISP_MTHD_V1) } else return ret; - nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); - nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat); - nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); + nvkm_mask(device, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); return 0; } int nv50_dac_sense(NV50_DISP_MTHD_V1) { + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; union { struct nv50_disp_dac_load_v0 v0; } *args = data; @@ -69,31 +78,49 @@ nv50_dac_sense(NV50_DISP_MTHD_V1) u32 loadval; int ret; - nv_ioctl(object, "disp dac load size %d\n", size); + nvif_ioctl(object, "disp dac load size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp dac load vers %d data %08x\n", - args->v0.version, args->v0.data); + nvif_ioctl(object, "disp dac load vers %d data %08x\n", + args->v0.version, args->v0.data); if (args->v0.data & 0xfff00000) return -EINVAL; loadval = args->v0.data; } else return ret; - nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000); - nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); + nvkm_mask(device, 0x61a004 + doff, 0x807f0000, 0x80150000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); - nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval); + nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); mdelay(9); udelay(500); - loadval = nv_mask(priv, 0x61a00c + doff, 0xffffffff, 0x00000000); + loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); - nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000); - nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); + nvkm_mask(device, 0x61a004 + doff, 0x807f0000, 0x80550000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); - nv_debug(priv, "DAC%d sense: 0x%08x\n", outp->or, loadval); + nvkm_debug(subdev, "DAC%d sense: %08x\n", outp->or, loadval); if (!(loadval & 0x80000000)) return -ETIMEDOUT; args->v0.load = (loadval & 0x38000000) >> 27; return 0; } + +static const struct nvkm_output_func +nv50_dac_output_func = { +}; + +int +nv50_dac_output_new(struct nvkm_disp *disp, int index, + struct dcb_output *dcbE, struct nvkm_output **poutp) +{ + return nvkm_output_new_(&nv50_dac_output_func, disp, + index, dcbE, poutp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c new file mode 100644 index 000000000..876b14549 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c @@ -0,0 +1,100 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include +#include + +int +gf119_disp_dmac_bind(struct nv50_disp_dmac *chan, + struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->base.root->ramht, object, + chan->base.chid, -9, handle, + chan->base.chid << 27 | 0x00000001); +} + +static void +gf119_disp_dmac_fini(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->base.chid; + + /* deactivate channel */ + nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", chid, + nvkm_rd32(device, 0x610490 + (chid * 0x10))); + } + + /* disable error reporting and completion notification */ + nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000); + nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000); +} + +static int +gf119_disp_dmac_init(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->base.chid; + + /* enable error reporting */ + nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494 + (chid * 0x0010), chan->push); + nvkm_wr32(device, 0x610498 + (chid * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61049c + (chid * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000); + nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", chid, + nvkm_rd32(device, 0x610490 + (chid * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nv50_disp_dmac_func +gf119_disp_dmac_func = { + .init = gf119_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .bind = gf119_disp_dmac_bind, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c new file mode 100644 index 000000000..9c6645a35 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c @@ -0,0 +1,247 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include +#include +#include +#include +#include +#include + +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, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_disp_root *root, int chid, int head, u64 push, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nvkm_device *device = root->disp->base.engine.subdev.device; + struct nvkm_client *client = oclass->client; + struct nvkm_dmaobj *dmaobj; + struct nv50_disp_dmac *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, head, oclass, &chan->base); + if (ret) + return ret; + + dmaobj = nvkm_dma_search(device->dma, client, push); + if (!dmaobj) + return -ENOENT; + + if (dmaobj->limit - dmaobj->start != 0xfff) + 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; + default: + return -EINVAL; + } + + return 0; +} + +int +nv50_disp_dmac_bind(struct nv50_disp_dmac *chan, + struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->base.root->ramht, object, + chan->base.chid, -10, handle, + chan->base.chid << 28 | + chan->base.chid); +} + +static void +nv50_disp_dmac_fini(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->base.chid; + + /* deactivate channel */ + nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini timeout, %08x\n", chid, + nvkm_rd32(device, 0x610200 + (chid * 0x10))); + } + + /* disable error reporting and completion notifications */ + nvkm_mask(device, 0x610028, 0x00010001 << chid, 0x00000000 << chid); +} + +static int +nv50_disp_dmac_init(struct nv50_disp_dmac *chan) +{ + struct nv50_disp *disp = chan->base.root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->base.chid; + + /* enable error reporting */ + nvkm_mask(device, 0x610028, 0x00010000 << chid, 0x00010000 << chid); + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204 + (chid * 0x0010), chan->push); + nvkm_wr32(device, 0x610208 + (chid * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61020c + (chid * 0x0010), chid); + nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000); + nvkm_wr32(device, 0x610200 + (chid * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init timeout, %08x\n", chid, + nvkm_rd32(device, 0x610200 + (chid * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nv50_disp_dmac_func +nv50_disp_dmac_func = { + .init = nv50_disp_dmac_init, + .fini = nv50_disp_dmac_fini, + .bind = nv50_disp_dmac_bind, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h new file mode 100644 index 000000000..c748ca23a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h @@ -0,0 +1,91 @@ +#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; +int gf119_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32); +extern const struct nv50_disp_dmac_func gf119_disp_core_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 gm204_disp_core_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c index 68347661a..9688970ec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c @@ -48,12 +48,12 @@ struct dp_state { static int dp_set_link_config(struct dp_state *dp) { - struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); struct nvkm_output_dp *outp = dp->outp; - struct nvkm_disp *disp = nvkm_disp(outp); - struct nvkm_bios *bios = nvkm_bios(disp); + struct nvkm_disp *disp = outp->base.disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvbios_init init = { - .subdev = nv_subdev(disp), + .subdev = subdev, .bios = bios, .offset = 0x0000, .outp = &outp->base.info, @@ -64,33 +64,33 @@ dp_set_link_config(struct dp_state *dp) u8 sink[2]; int ret; - DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); + OUTP_DBG(&outp->base, "%d lanes at %d KB/s", dp->link_nr, dp->link_bw); /* set desired link configuration on the source */ if ((lnkcmp = dp->outp->info.lnkcmp)) { if (outp->version < 0x30) { - while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp)) + while ((dp->link_bw / 10) < nvbios_rd16(bios, lnkcmp)) lnkcmp += 4; - init.offset = nv_ro16(bios, lnkcmp + 2); + init.offset = nvbios_rd16(bios, lnkcmp + 2); } else { - while ((dp->link_bw / 27000) < nv_ro08(bios, lnkcmp)) + while ((dp->link_bw / 27000) < nvbios_rd08(bios, lnkcmp)) lnkcmp += 3; - init.offset = nv_ro16(bios, lnkcmp + 1); + init.offset = nvbios_rd16(bios, lnkcmp + 1); } nvbios_exec(&init); } - ret = impl->lnk_ctl(outp, dp->link_nr, dp->link_bw / 27000, - outp->dpcd[DPCD_RC02] & - DPCD_RC02_ENHANCED_FRAME_CAP); + ret = outp->func->lnk_ctl(outp, dp->link_nr, dp->link_bw / 27000, + outp->dpcd[DPCD_RC02] & + DPCD_RC02_ENHANCED_FRAME_CAP); if (ret) { if (ret < 0) - ERR("lnk_ctl failed with %d\n", ret); + OUTP_ERR(&outp->base, "lnk_ctl failed with %d", ret); return ret; } - impl->lnk_pwr(outp, dp->link_nr); + outp->func->lnk_pwr(outp, dp->link_nr); /* set desired link configuration on the sink */ sink[0] = dp->link_bw / 27000; @@ -98,29 +98,27 @@ dp_set_link_config(struct dp_state *dp) if (outp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; - return nv_wraux(outp->base.edid, DPCD_LC00_LINK_BW_SET, sink, 2); + return nvkm_wraux(outp->aux, DPCD_LC00_LINK_BW_SET, sink, 2); } static void dp_set_training_pattern(struct dp_state *dp, u8 pattern) { - struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); struct nvkm_output_dp *outp = dp->outp; u8 sink_tp; - DBG("training pattern %d\n", pattern); - impl->pattern(outp, pattern); + OUTP_DBG(&outp->base, "training pattern %d", pattern); + outp->func->pattern(outp, pattern); - nv_rdaux(outp->base.edid, DPCD_LC02, &sink_tp, 1); + nvkm_rdaux(outp->aux, DPCD_LC02, &sink_tp, 1); sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; sink_tp |= pattern; - nv_wraux(outp->base.edid, DPCD_LC02, &sink_tp, 1); + nvkm_wraux(outp->aux, DPCD_LC02, &sink_tp, 1); } static int dp_link_train_commit(struct dp_state *dp, bool pc) { - struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); struct nvkm_output_dp *outp = dp->outp; int ret, i; @@ -146,16 +144,17 @@ dp_link_train_commit(struct dp_state *dp, bool pc) dp->conf[i] = (lpre << 3) | lvsw; dp->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4); - DBG("config lane %d %02x %02x\n", i, dp->conf[i], lpc2); - impl->drv_ctl(outp, i, lvsw & 3, lpre & 3, lpc2 & 3); + OUTP_DBG(&outp->base, "config lane %d %02x %02x", + i, dp->conf[i], lpc2); + outp->func->drv_ctl(outp, i, lvsw & 3, lpre & 3, lpc2 & 3); } - ret = nv_wraux(outp->base.edid, DPCD_LC03(0), dp->conf, 4); + ret = nvkm_wraux(outp->aux, DPCD_LC03(0), dp->conf, 4); if (ret) return ret; if (pc) { - ret = nv_wraux(outp->base.edid, DPCD_LC0F, dp->pc2conf, 2); + ret = nvkm_wraux(outp->aux, DPCD_LC0F, dp->pc2conf, 2); if (ret) return ret; } @@ -174,17 +173,18 @@ dp_link_train_update(struct dp_state *dp, bool pc, u32 delay) else udelay(delay); - ret = nv_rdaux(outp->base.edid, DPCD_LS02, dp->stat, 6); + ret = nvkm_rdaux(outp->aux, DPCD_LS02, dp->stat, 6); if (ret) return ret; if (pc) { - ret = nv_rdaux(outp->base.edid, DPCD_LS0C, &dp->pc2stat, 1); + ret = nvkm_rdaux(outp->aux, DPCD_LS0C, &dp->pc2stat, 1); if (ret) dp->pc2stat = 0x00; - DBG("status %6ph pc2 %02x\n", dp->stat, dp->pc2stat); + OUTP_DBG(&outp->base, "status %6ph pc2 %02x", + dp->stat, dp->pc2stat); } else { - DBG("status %6ph\n", dp->stat); + OUTP_DBG(&outp->base, "status %6ph", dp->stat); } return 0; @@ -260,11 +260,11 @@ static void dp_link_train_init(struct dp_state *dp, bool spread) { struct nvkm_output_dp *outp = dp->outp; - struct nvkm_disp *disp = nvkm_disp(outp); - struct nvkm_bios *bios = nvkm_bios(disp); + struct nvkm_disp *disp = outp->base.disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvbios_init init = { - .subdev = nv_subdev(disp), - .bios = bios, + .subdev = subdev, + .bios = subdev->device->bios, .outp = &outp->base.info, .crtc = -1, .execute = 1, @@ -286,11 +286,11 @@ static void dp_link_train_fini(struct dp_state *dp) { struct nvkm_output_dp *outp = dp->outp; - struct nvkm_disp *disp = nvkm_disp(outp); - struct nvkm_bios *bios = nvkm_bios(disp); + struct nvkm_disp *disp = outp->base.disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvbios_init init = { - .subdev = nv_subdev(disp), - .bios = bios, + .subdev = subdev, + .bios = subdev->device->bios, .outp = &outp->base.info, .crtc = -1, .execute = 1, @@ -322,19 +322,20 @@ void nvkm_dp_train(struct work_struct *w) { struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work); - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nv50_disp *disp = nv50_disp(outp->base.disp); const struct dp_rates *cfg = nvkm_dp_rates; struct dp_state _dp = { .outp = outp, }, *dp = &_dp; u32 datarate = 0; + u8 pwr; int ret; - if (!outp->base.info.location && priv->sor.magic) - priv->sor.magic(&outp->base); + if (!outp->base.info.location && disp->func->sor.magic) + disp->func->sor.magic(&outp->base); /* bring capabilities within encoder limits */ - if (nv_mclass(priv) < GF110_DISP) + if (disp->base.engine.subdev.device->chipset < 0xd0) outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED; if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) { outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT; @@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w) /* disable link interrupt handling during link training */ nvkm_notify_put(&outp->irq); + /* ensure sink is not in a low-power state */ + if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) { + if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { + pwr &= ~DPCD_SC00_SET_POWER; + pwr |= DPCD_SC00_SET_POWER_D0; + nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1); + } + } + /* enable down-spreading and execute pre-train script from vbios */ dp_link_train_init(dp, outp->dpcd[3] & 0x01); @@ -386,12 +396,12 @@ nvkm_dp_train(struct work_struct *w) /* finish link training and execute post-train script from vbios */ dp_set_training_pattern(dp, 0); if (ret < 0) - ERR("link training failed\n"); + OUTP_ERR(&outp->base, "link training failed"); dp_link_train_fini(dp); /* signal completion and enable link interrupt handling */ - DBG("training complete\n"); + OUTP_DBG(&outp->base, "training complete"); atomic_set(&outp->lt.done, 1); wake_up(&outp->lt.wait); nvkm_notify_get(&outp->irq); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h index 959629032..6e10c5e0e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h @@ -71,5 +71,11 @@ #define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c #define DPCD_LS0C_LANE0_POST_CURSOR2 0x03 +/* DPCD Sink Control */ +#define DPCD_SC00 0x00600 +#define DPCD_SC00_SET_POWER 0x03 +#define DPCD_SC00_SET_POWER_D0 0x01 +#define DPCD_SC00_SET_POWER_D3 0x03 + void nvkm_dp_train(struct work_struct *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index a0dcf534c..3e3e592cd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -22,251 +22,34 @@ * Authors: Ben Skeggs */ #include "nv50.h" - -#include - -/******************************************************************************* - * EVO master channel object - ******************************************************************************/ - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610bc4 }, - {} - } -}; - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x085c, 0x610c5c }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0878, 0x610c50 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x089c, 0x610c68 }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - { 0x0910, 0x610c70 }, - { 0x0914, 0x610c78 }, - {} - } -}; - -const struct nv50_disp_mthd_chan -g84_disp_core_mthd_chan = { - .name = "Core", - .addr = 0x000000, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -/******************************************************************************* - * EVO sync channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -g84_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00c4, 0x610800 }, - { 0x00c8, 0x61080c }, - { 0x00cc, 0x610818 }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x00fc, 0x610824 }, - { 0x0100, 0x610894 }, - { 0x0104, 0x61082c }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -const struct nv50_disp_mthd_chan -g84_disp_base_mthd_chan = { - .name = "Base", - .addr = 0x000540, - .data = { - { "Global", 1, &g84_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -/******************************************************************************* - * EVO overlay channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -g84_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -const struct nv50_disp_mthd_chan -g84_disp_ovly_mthd_chan = { - .name = "Overlay", - .addr = 0x000540, - .data = { - { "Global", 1, &g84_disp_ovly_mthd_base }, - {} - } -}; - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -g84_disp_sclass[] = { - { G82_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { G82_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { G82_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} -}; - -static struct nvkm_oclass -g84_disp_main_oclass[] = { - { G82_DISP, &nv50_disp_main_ofuncs }, - {} -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -g84_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +#include "rootnv50.h" + +static const struct nv50_disp_func +g84_disp = { + .intr = nv50_disp_intr, + .uevent = &nv50_disp_chan_uevent, + .super = nv50_disp_intr_supervisor, + .root = &g84_disp_root_oclass, + .head.vblank_init = nv50_disp_vblank_init, + .head.vblank_fini = nv50_disp_vblank_fini, + .head.scanoutpos = nv50_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.external.tmds = nv50_pior_output_new, + .outp.external.dp = nv50_pior_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 2, + .sor.power = nv50_sor_power, + .sor.hdmi = g84_hdmi_ctrl, + .pior.nr = 3, + .pior.power = nv50_pior_power, +}; + +int +g84_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP", - "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = g84_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); - priv->sclass = g84_disp_sclass; - priv->head.nr = 2; - priv->dac.nr = 3; - priv->sor.nr = 2; - priv->pior.nr = 3; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hdmi = g84_hdmi_ctrl; - priv->pior.power = nv50_pior_power; - return 0; + return nv50_disp_new_(&g84_disp, device, index, 2, pdisp); } - -struct nvkm_oclass * -g84_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x82), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &nv50_disp_vblank_func, - .base.outp = nv50_disp_outp_sclass, - .mthd.core = &g84_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = &g84_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, - .head.scanoutpos = nv50_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 1ab0d0ae3..7a7af3b47 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -22,118 +22,35 @@ * Authors: Ben Skeggs */ #include "nv50.h" -#include "outpdp.h" - -#include - -/******************************************************************************* - * EVO master channel object - ******************************************************************************/ - -const struct nv50_disp_mthd_list -g94_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610794 }, - {} - } -}; - -const struct nv50_disp_mthd_chan -g94_disp_core_mthd_chan = { - .name = "Core", - .addr = 0x000000, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 4, &g94_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } +#include "rootnv50.h" + +static const struct nv50_disp_func +g94_disp = { + .intr = nv50_disp_intr, + .uevent = &nv50_disp_chan_uevent, + .super = nv50_disp_intr_supervisor, + .root = &g94_disp_root_oclass, + .head.vblank_init = nv50_disp_vblank_init, + .head.vblank_fini = nv50_disp_vblank_fini, + .head.scanoutpos = nv50_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = g94_sor_dp_new, + .outp.external.tmds = nv50_pior_output_new, + .outp.external.dp = nv50_pior_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hdmi = g84_hdmi_ctrl, + .pior.nr = 3, + .pior.power = nv50_pior_power, }; -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -g94_disp_sclass[] = { - { GT206_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} -}; - -static struct nvkm_oclass -g94_disp_main_oclass[] = { - { GT206_DISP, &nv50_disp_main_ofuncs }, - {} -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -g94_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +g94_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP", - "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = g94_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); - priv->sclass = g94_disp_sclass; - priv->head.nr = 2; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->pior.nr = 3; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hdmi = g84_hdmi_ctrl; - priv->pior.power = nv50_pior_power; - return 0; + return nv50_disp_new_(&g94_disp, device, index, 2, pdisp); } - -struct nvkm_oclass * -g94_disp_outp_sclass[] = { - &nv50_pior_dp_impl.base.base, - &g94_sor_dp_impl.base.base, - NULL -}; - -struct nvkm_oclass * -g94_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x88), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = g94_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &nv50_disp_vblank_func, - .base.outp = g94_disp_outp_sclass, - .mthd.core = &g94_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = &g84_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, - .head.scanoutpos = nv50_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c deleted file mode 100644 index 9ef6728c5..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c +++ /dev/null @@ -1,1310 +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 "nv50.h" -#include "outp.h" -#include "outpdp.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/******************************************************************************* - * EVO channel base class - ******************************************************************************/ - -static void -gf110_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); - nv_mask(priv, 0x610090, 0x00000001 << index, 0x00000000 << index); - nv_wr32(priv, 0x61008c, 0x00000001 << index); -} - -static void -gf110_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); - nv_wr32(priv, 0x61008c, 0x00000001 << index); - nv_mask(priv, 0x610090, 0x00000001 << index, 0x00000001 << index); -} - -const struct nvkm_event_func -gf110_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = gf110_disp_chan_uevent_init, - .fini = gf110_disp_chan_uevent_fini, -}; - -/******************************************************************************* - * EVO DMA channel base class - ******************************************************************************/ - -static int -gf110_disp_dmac_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 name) -{ - struct nv50_disp_base *base = (void *)parent->parent; - struct nv50_disp_chan *chan = (void *)parent; - u32 addr = nv_gpuobj(object)->node->offset; - u32 data = (chan->chid << 27) | (addr << 9) | 0x00000001; - return nvkm_ramht_insert(base->ramht, chan->chid, name, data); -} - -static void -gf110_disp_dmac_object_detach(struct nvkm_object *parent, int cookie) -{ - struct nv50_disp_base *base = (void *)parent->parent; - nvkm_ramht_remove(base->ramht, cookie); -} - -static int -gf110_disp_dmac_init(struct nvkm_object *object) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; - int chid = dmac->base.chid; - int ret; - - ret = nv50_disp_chan_init(&dmac->base); - if (ret) - return ret; - - /* enable error reporting */ - nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); - - /* initialise channel for dma command submission */ - nv_wr32(priv, 0x610494 + (chid * 0x0010), dmac->push); - nv_wr32(priv, 0x610498 + (chid * 0x0010), 0x00010000); - nv_wr32(priv, 0x61049c + (chid * 0x0010), 0x00000001); - nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010); - nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000); - nv_wr32(priv, 0x610490 + (chid * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x80000000, 0x00000000)) { - nv_error(dmac, "init: 0x%08x\n", - nv_rd32(priv, 0x610490 + (chid * 0x10))); - return -EBUSY; - } - - return 0; -} - -static int -gf110_disp_dmac_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; - int chid = dmac->base.chid; - - /* deactivate channel */ - nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000); - nv_mask(priv, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000); - if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x001e0000, 0x00000000)) { - nv_error(dmac, "fini: 0x%08x\n", - nv_rd32(priv, 0x610490 + (chid * 0x10))); - if (suspend) - return -EBUSY; - } - - /* disable error reporting and completion notification */ - nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); - nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); - - return nv50_disp_chan_fini(&dmac->base, suspend); -} - -/******************************************************************************* - * EVO master channel object - ******************************************************************************/ - -const struct nv50_disp_mthd_list -gf110_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x660080 }, - { 0x0084, 0x660084 }, - { 0x0088, 0x660088 }, - { 0x008c, 0x000000 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf110_disp_core_mthd_dac = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0180, 0x660180 }, - { 0x0184, 0x660184 }, - { 0x0188, 0x660188 }, - { 0x0190, 0x660190 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf110_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0200, 0x660200 }, - { 0x0204, 0x660204 }, - { 0x0208, 0x660208 }, - { 0x0210, 0x660210 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf110_disp_core_mthd_pior = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x660300 }, - { 0x0304, 0x660304 }, - { 0x0308, 0x660308 }, - { 0x0310, 0x660310 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf110_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -static const struct nv50_disp_mthd_chan -gf110_disp_core_mthd_chan = { - .name = "Core", - .addr = 0x000000, - .data = { - { "Global", 1, &gf110_disp_core_mthd_base }, - { "DAC", 3, &gf110_disp_core_mthd_dac }, - { "SOR", 8, &gf110_disp_core_mthd_sor }, - { "PIOR", 4, &gf110_disp_core_mthd_pior }, - { "HEAD", 4, &gf110_disp_core_mthd_head }, - {} - } -}; - -static int -gf110_disp_core_init(struct nvkm_object *object) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; - int ret; - - ret = nv50_disp_chan_init(&mast->base); - if (ret) - return ret; - - /* enable error reporting */ - nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001); - - /* initialise channel for dma command submission */ - nv_wr32(priv, 0x610494, mast->push); - nv_wr32(priv, 0x610498, 0x00010000); - nv_wr32(priv, 0x61049c, 0x00000001); - nv_mask(priv, 0x610490, 0x00000010, 0x00000010); - nv_wr32(priv, 0x640000, 0x00000000); - nv_wr32(priv, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (!nv_wait(priv, 0x610490, 0x80000000, 0x00000000)) { - nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610490)); - return -EBUSY; - } - - return 0; -} - -static int -gf110_disp_core_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; - - /* deactivate channel */ - nv_mask(priv, 0x610490, 0x00000010, 0x00000000); - nv_mask(priv, 0x610490, 0x00000003, 0x00000000); - if (!nv_wait(priv, 0x610490, 0x001e0000, 0x00000000)) { - nv_error(mast, "fini: 0x%08x\n", nv_rd32(priv, 0x610490)); - if (suspend) - return -EBUSY; - } - - /* disable error reporting and completion notification */ - nv_mask(priv, 0x610090, 0x00000001, 0x00000000); - nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000); - - return nv50_disp_chan_fini(&mast->base, suspend); -} - -struct nv50_disp_chan_impl -gf110_disp_core_ofuncs = { - .base.ctor = nv50_disp_core_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = gf110_disp_core_init, - .base.fini = gf110_disp_core_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 0, - .attach = gf110_disp_dmac_object_attach, - .detach = gf110_disp_dmac_object_detach, -}; - -/******************************************************************************* - * EVO sync channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -gf110_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x661080 }, - { 0x0084, 0x661084 }, - { 0x0088, 0x661088 }, - { 0x008c, 0x66108c }, - { 0x0090, 0x661090 }, - { 0x0094, 0x661094 }, - { 0x00a0, 0x6610a0 }, - { 0x00a4, 0x6610a4 }, - { 0x00c0, 0x6610c0 }, - { 0x00c4, 0x6610c4 }, - { 0x00c8, 0x6610c8 }, - { 0x00cc, 0x6610cc }, - { 0x00e0, 0x6610e0 }, - { 0x00e4, 0x6610e4 }, - { 0x00e8, 0x6610e8 }, - { 0x00ec, 0x6610ec }, - { 0x00fc, 0x6610fc }, - { 0x0100, 0x661100 }, - { 0x0104, 0x661104 }, - { 0x0108, 0x661108 }, - { 0x010c, 0x66110c }, - { 0x0110, 0x661110 }, - { 0x0114, 0x661114 }, - { 0x0118, 0x661118 }, - { 0x011c, 0x66111c }, - { 0x0130, 0x661130 }, - { 0x0134, 0x661134 }, - { 0x0138, 0x661138 }, - { 0x013c, 0x66113c }, - { 0x0140, 0x661140 }, - { 0x0144, 0x661144 }, - { 0x0148, 0x661148 }, - { 0x014c, 0x66114c }, - { 0x0150, 0x661150 }, - { 0x0154, 0x661154 }, - { 0x0158, 0x661158 }, - { 0x015c, 0x66115c }, - { 0x0160, 0x661160 }, - { 0x0164, 0x661164 }, - { 0x0168, 0x661168 }, - { 0x016c, 0x66116c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf110_disp_base_mthd_image = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0400, 0x661400 }, - { 0x0404, 0x661404 }, - { 0x0408, 0x661408 }, - { 0x040c, 0x66140c }, - { 0x0410, 0x661410 }, - {} - } -}; - -const struct nv50_disp_mthd_chan -gf110_disp_base_mthd_chan = { - .name = "Base", - .addr = 0x001000, - .data = { - { "Global", 1, &gf110_disp_base_mthd_base }, - { "Image", 2, &gf110_disp_base_mthd_image }, - {} - } -}; - -struct nv50_disp_chan_impl -gf110_disp_base_ofuncs = { - .base.ctor = nv50_disp_base_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = gf110_disp_dmac_init, - .base.fini = gf110_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 1, - .attach = gf110_disp_dmac_object_attach, - .detach = gf110_disp_dmac_object_detach, -}; - -/******************************************************************************* - * EVO overlay channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -gf110_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -static const struct nv50_disp_mthd_chan -gf110_disp_ovly_mthd_chan = { - .name = "Overlay", - .addr = 0x001000, - .data = { - { "Global", 1, &gf110_disp_ovly_mthd_base }, - {} - } -}; - -struct nv50_disp_chan_impl -gf110_disp_ovly_ofuncs = { - .base.ctor = nv50_disp_ovly_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = gf110_disp_dmac_init, - .base.fini = gf110_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 5, - .attach = gf110_disp_dmac_object_attach, - .detach = gf110_disp_dmac_object_detach, -}; - -/******************************************************************************* - * EVO PIO channel base class - ******************************************************************************/ - -static int -gf110_disp_pioc_init(struct nvkm_object *object) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; - int chid = pioc->base.chid; - int ret; - - ret = nv50_disp_chan_init(&pioc->base); - if (ret) - return ret; - - /* enable error reporting */ - nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); - - /* activate channel */ - nv_wr32(priv, 0x610490 + (chid * 0x10), 0x00000001); - if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00010000)) { - nv_error(pioc, "init: 0x%08x\n", - nv_rd32(priv, 0x610490 + (chid * 0x10))); - return -EBUSY; - } - - return 0; -} - -static int -gf110_disp_pioc_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; - int chid = pioc->base.chid; - - nv_mask(priv, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000); - if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00000000)) { - nv_error(pioc, "timeout: 0x%08x\n", - nv_rd32(priv, 0x610490 + (chid * 0x10))); - if (suspend) - return -EBUSY; - } - - /* disable error reporting and completion notification */ - nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); - nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); - - return nv50_disp_chan_fini(&pioc->base, suspend); -} - -/******************************************************************************* - * EVO immediate overlay channel objects - ******************************************************************************/ - -struct nv50_disp_chan_impl -gf110_disp_oimm_ofuncs = { - .base.ctor = nv50_disp_oimm_ctor, - .base.dtor = nv50_disp_pioc_dtor, - .base.init = gf110_disp_pioc_init, - .base.fini = gf110_disp_pioc_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 9, -}; - -/******************************************************************************* - * EVO cursor channel objects - ******************************************************************************/ - -struct nv50_disp_chan_impl -gf110_disp_curs_ofuncs = { - .base.ctor = nv50_disp_curs_ctor, - .base.dtor = nv50_disp_pioc_dtor, - .base.init = gf110_disp_pioc_init, - .base.fini = gf110_disp_pioc_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 13, -}; - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -int -gf110_disp_main_scanoutpos(NV50_DISP_MTHD_V0) -{ - const u32 total = nv_rd32(priv, 0x640414 + (head * 0x300)); - const u32 blanke = nv_rd32(priv, 0x64041c + (head * 0x300)); - const u32 blanks = nv_rd32(priv, 0x640420 + (head * 0x300)); - union { - struct nv04_disp_scanoutpos_v0 v0; - } *args = data; - int ret; - - nv_ioctl(object, "disp scanoutpos size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version); - args->v0.vblanke = (blanke & 0xffff0000) >> 16; - args->v0.hblanke = (blanke & 0x0000ffff); - args->v0.vblanks = (blanks & 0xffff0000) >> 16; - args->v0.hblanks = (blanks & 0x0000ffff); - args->v0.vtotal = ( total & 0xffff0000) >> 16; - args->v0.htotal = ( total & 0x0000ffff); - args->v0.time[0] = ktime_to_ns(ktime_get()); - args->v0.vline = /* vline read locks hline */ - nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff; - args->v0.time[1] = ktime_to_ns(ktime_get()); - args->v0.hline = - nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff; - } else - return ret; - - return 0; -} - -static int -gf110_disp_main_init(struct nvkm_object *object) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_base *base = (void *)object; - int ret, i; - u32 tmp; - - ret = nvkm_parent_init(&base->base); - if (ret) - return ret; - - /* 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 */ - for (i = 0; i < priv->head.nr; i++) { - tmp = nv_rd32(priv, 0x616104 + (i * 0x800)); - nv_wr32(priv, 0x6101b4 + (i * 0x800), tmp); - tmp = nv_rd32(priv, 0x616108 + (i * 0x800)); - nv_wr32(priv, 0x6101b8 + (i * 0x800), tmp); - tmp = nv_rd32(priv, 0x61610c + (i * 0x800)); - nv_wr32(priv, 0x6101bc + (i * 0x800), tmp); - } - - /* ... DAC caps */ - for (i = 0; i < priv->dac.nr; i++) { - tmp = nv_rd32(priv, 0x61a000 + (i * 0x800)); - nv_wr32(priv, 0x6101c0 + (i * 0x800), tmp); - } - - /* ... SOR caps */ - for (i = 0; i < priv->sor.nr; i++) { - tmp = nv_rd32(priv, 0x61c000 + (i * 0x800)); - nv_wr32(priv, 0x6301c4 + (i * 0x800), tmp); - } - - /* steal display away from vbios, or something like that */ - if (nv_rd32(priv, 0x6100ac) & 0x00000100) { - nv_wr32(priv, 0x6100ac, 0x00000100); - nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000); - if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) { - nv_error(priv, "timeout acquiring display\n"); - return -EBUSY; - } - } - - /* point at display engine memory area (hash table, objects) */ - nv_wr32(priv, 0x610010, (nv_gpuobj(object->parent)->addr >> 8) | 9); - - /* enable supervisor interrupts, disable everything else */ - nv_wr32(priv, 0x610090, 0x00000000); - nv_wr32(priv, 0x6100a0, 0x00000000); - nv_wr32(priv, 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 - */ - for (i = 0; i < priv->head.nr; i++) - nv_mask(priv, 0x616308 + (i * 0x800), 0x00000111, 0x00000010); - - return 0; -} - -static int -gf110_disp_main_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_base *base = (void *)object; - - /* disable all interrupts */ - nv_wr32(priv, 0x6100b0, 0x00000000); - - return nvkm_parent_fini(&base->base, suspend); -} - -struct nvkm_ofuncs -gf110_disp_main_ofuncs = { - .ctor = nv50_disp_main_ctor, - .dtor = nv50_disp_main_dtor, - .init = gf110_disp_main_init, - .fini = gf110_disp_main_fini, - .mthd = nv50_disp_main_mthd, - .ntfy = nvkm_disp_ntfy, -}; - -static struct nvkm_oclass -gf110_disp_main_oclass[] = { - { GF110_DISP, &gf110_disp_main_ofuncs }, - {} -}; - -static struct nvkm_oclass -gf110_disp_sclass[] = { - { GF110_DISP_CORE_CHANNEL_DMA, &gf110_disp_core_ofuncs.base }, - { GF110_DISP_BASE_CHANNEL_DMA, &gf110_disp_base_ofuncs.base }, - { GF110_DISP_OVERLAY_CONTROL_DMA, &gf110_disp_ovly_ofuncs.base }, - { GF110_DISP_OVERLAY, &gf110_disp_oimm_ofuncs.base }, - { GF110_DISP_CURSOR, &gf110_disp_curs_ofuncs.base }, - {} -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static void -gf110_disp_vblank_init(struct nvkm_event *event, int type, int head) -{ - struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); - nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001); -} - -static void -gf110_disp_vblank_fini(struct nvkm_event *event, int type, int head) -{ - struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); - nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000); -} - -const struct nvkm_event_func -gf110_disp_vblank_func = { - .ctor = nvkm_disp_vblank_ctor, - .init = gf110_disp_vblank_init, - .fini = gf110_disp_vblank_fini, -}; - -static struct nvkm_output * -exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, - u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, - struct nvbios_outp *info) -{ - struct nvkm_bios *bios = nvkm_bios(priv); - struct nvkm_output *outp; - u16 mask, type; - - if (or < 4) { - type = DCB_OUTPUT_ANALOG; - mask = 0; - } else { - or -= 4; - switch (ctrl & 0x00000f00) { - case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; - case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; - case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break; - case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break; - case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break; - case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; - default: - nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); - return 0x0000; - } - } - - mask = 0x00c0 & (mask << 6); - mask |= 0x0001 << or; - mask |= 0x0100 << head; - - list_for_each_entry(outp, &priv->base.outp, head) { - if ((outp->info.hasht & 0xff) == type && - (outp->info.hashm & mask) == mask) { - *data = nvbios_outp_match(bios, outp->info.hasht, - outp->info.hashm, - ver, hdr, cnt, len, info); - if (!*data) - return NULL; - return outp; - } - } - - return NULL; -} - -static struct nvkm_output * -exec_script(struct nv50_disp_priv *priv, int head, int id) -{ - struct nvkm_bios *bios = nvkm_bios(priv); - struct nvkm_output *outp; - struct nvbios_outp info; - u8 ver, hdr, cnt, len; - u32 data, ctrl = 0; - int or; - - for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { - ctrl = nv_rd32(priv, 0x640180 + (or * 0x20)); - if (ctrl & (1 << head)) - break; - } - - if (or == 8) - return NULL; - - outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info); - if (outp) { - struct nvbios_init init = { - .subdev = nv_subdev(priv), - .bios = bios, - .offset = info.script[id], - .outp = &outp->info, - .crtc = head, - .execute = 1, - }; - - nvbios_exec(&init); - } - - return outp; -} - -static struct nvkm_output * -exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) -{ - struct nvkm_bios *bios = nvkm_bios(priv); - struct nvkm_output *outp; - struct nvbios_outp info1; - struct nvbios_ocfg info2; - u8 ver, hdr, cnt, len; - u32 data, ctrl = 0; - int or; - - for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { - ctrl = nv_rd32(priv, 0x660180 + (or * 0x20)); - if (ctrl & (1 << head)) - break; - } - - if (or == 8) - return NULL; - - outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); - if (!outp) - return NULL; - - switch (outp->info.type) { - case DCB_OUTPUT_TMDS: - *conf = (ctrl & 0x00000f00) >> 8; - if (pclk >= 165000) - *conf |= 0x0100; - break; - case DCB_OUTPUT_LVDS: - *conf = priv->sor.lvdsconf; - break; - case DCB_OUTPUT_DP: - *conf = (ctrl & 0x00000f00) >> 8; - break; - case DCB_OUTPUT_ANALOG: - default: - *conf = 0x00ff; - break; - } - - data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2); - if (data && id < 0xff) { - data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); - if (data) { - struct nvbios_init init = { - .subdev = nv_subdev(priv), - .bios = bios, - .offset = data, - .outp = &outp->info, - .crtc = head, - .execute = 1, - }; - - nvbios_exec(&init); - } - } - - return outp; -} - -static void -gf110_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head) -{ - exec_script(priv, head, 1); -} - -static void -gf110_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head) -{ - struct nvkm_output *outp = exec_script(priv, head, 2); - - /* see note in nv50_disp_intr_unk20_0() */ - if (outp && outp->info.type == DCB_OUTPUT_DP) { - struct nvkm_output_dp *outpdp = (void *)outp; - struct nvbios_init init = { - .subdev = nv_subdev(priv), - .bios = nvkm_bios(priv), - .outp = &outp->info, - .crtc = head, - .offset = outpdp->info.script[4], - .execute = 1, - }; - - nvbios_exec(&init); - atomic_set(&outpdp->lt.done, 0); - } -} - -static void -gf110_disp_intr_unk2_1(struct nv50_disp_priv *priv, int head) -{ - struct nvkm_devinit *devinit = nvkm_devinit(priv); - u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - if (pclk) - devinit->pll_set(devinit, PLL_VPLL0 + head, pclk); - nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000); -} - -static void -gf110_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head, - struct dcb_output *outp) -{ - const int or = ffs(outp->or) - 1; - const u32 ctrl = nv_rd32(priv, 0x660200 + (or * 0x020)); - const u32 conf = nv_rd32(priv, 0x660404 + (head * 0x300)); - const s32 vactive = nv_rd32(priv, 0x660414 + (head * 0x300)) & 0xffff; - const s32 vblanke = nv_rd32(priv, 0x66041c + (head * 0x300)) & 0xffff; - const s32 vblanks = nv_rd32(priv, 0x660420 + (head * 0x300)) & 0xffff; - const u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1; - const u32 hoff = (head * 0x800); - const u32 soff = ( or * 0x800); - const u32 loff = (link * 0x080) + soff; - const u32 symbol = 100000; - const u32 TU = 64; - u32 dpctrl = nv_rd32(priv, 0x61c10c + loff); - u32 clksor = nv_rd32(priv, 0x612300 + soff); - u32 datarate, link_nr, link_bw, bits; - u64 ratio, value; - - link_nr = hweight32(dpctrl & 0x000f0000); - link_bw = (clksor & 0x007c0000) >> 18; - link_bw *= 27000; - - /* symbols/hblank - algorithm taken from comments in tegra driver */ - value = vblanke + vactive - vblanks - 7; - value = value * link_bw; - do_div(value, pclk); - value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr); - nv_mask(priv, 0x616620 + hoff, 0x0000ffff, value); - - /* symbols/vblank - algorithm taken from comments in tegra driver */ - value = vblanks - vblanke - 25; - value = value * link_bw; - do_div(value, pclk); - value = value - ((36 / link_nr) + 3) - 1; - nv_mask(priv, 0x616624 + hoff, 0x00ffffff, value); - - /* watermark */ - if ((conf & 0x3c0) == 0x180) bits = 30; - else if ((conf & 0x3c0) == 0x140) bits = 24; - else bits = 18; - datarate = (pclk * bits) / 8; - - ratio = datarate; - ratio *= symbol; - do_div(ratio, link_nr * link_bw); - - value = (symbol - ratio) * TU; - value *= ratio; - do_div(value, symbol); - do_div(value, symbol); - - value += 5; - value |= 0x08000000; - - nv_wr32(priv, 0x616610 + hoff, value); -} - -static void -gf110_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head) -{ - struct nvkm_output *outp; - u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - u32 conf, addr, data; - - outp = exec_clkcmp(priv, head, 0xff, pclk, &conf); - if (!outp) - return; - - /* see note in nv50_disp_intr_unk20_2() */ - if (outp->info.type == DCB_OUTPUT_DP) { - u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); - switch ((sync & 0x000003c0) >> 6) { - case 6: pclk = pclk * 30; break; - case 5: pclk = pclk * 24; break; - case 2: - default: - pclk = pclk * 18; - break; - } - - if (nvkm_output_dp_train(outp, pclk, true)) - ERR("link not trained before attach\n"); - } else { - if (priv->sor.magic) - priv->sor.magic(outp); - } - - exec_clkcmp(priv, head, 0, pclk, &conf); - - if (outp->info.type == DCB_OUTPUT_ANALOG) { - addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800; - data = 0x00000000; - } else { - addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800; - data = (conf & 0x0100) ? 0x00000101 : 0x00000000; - switch (outp->info.type) { - case DCB_OUTPUT_TMDS: - nv_mask(priv, addr, 0x007c0000, 0x00280000); - break; - case DCB_OUTPUT_DP: - gf110_disp_intr_unk2_2_tu(priv, head, &outp->info); - break; - default: - break; - } - } - - nv_mask(priv, addr, 0x00000707, data); -} - -static void -gf110_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head) -{ - u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - u32 conf; - - exec_clkcmp(priv, head, 1, pclk, &conf); -} - -void -gf110_disp_intr_supervisor(struct work_struct *work) -{ - struct nv50_disp_priv *priv = - container_of(work, struct nv50_disp_priv, supervisor); - struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass; - u32 mask[4]; - int head; - - nv_debug(priv, "supervisor %d\n", ffs(priv->super)); - for (head = 0; head < priv->head.nr; head++) { - mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800)); - nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]); - } - - if (priv->super & 0x00000001) { - nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core); - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nv_debug(priv, "supervisor 1.0 - head %d\n", head); - gf110_disp_intr_unk1_0(priv, head); - } - } else - if (priv->super & 0x00000002) { - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nv_debug(priv, "supervisor 2.0 - head %d\n", head); - gf110_disp_intr_unk2_0(priv, head); - } - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00010000)) - continue; - nv_debug(priv, "supervisor 2.1 - head %d\n", head); - gf110_disp_intr_unk2_1(priv, head); - } - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nv_debug(priv, "supervisor 2.2 - head %d\n", head); - gf110_disp_intr_unk2_2(priv, head); - } - } else - if (priv->super & 0x00000004) { - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nv_debug(priv, "supervisor 3.0 - head %d\n", head); - gf110_disp_intr_unk4_0(priv, head); - } - } - - for (head = 0; head < priv->head.nr; head++) - nv_wr32(priv, 0x6101d4 + (head * 0x800), 0x00000000); - nv_wr32(priv, 0x6101d0, 0x80000000); -} - -static void -gf110_disp_intr_error(struct nv50_disp_priv *priv, int chid) -{ - const struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass; - u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12)); - u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12)); - u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12)); - - nv_error(priv, "chid %d mthd 0x%04x data 0x%08x " - "0x%08x 0x%08x\n", - chid, (mthd & 0x0000ffc), data, mthd, unkn); - - if (chid == 0) { - switch (mthd & 0xffc) { - case 0x0080: - nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0, - impl->mthd.core); - break; - default: - break; - } - } else - if (chid <= 4) { - switch (mthd & 0xffc) { - case 0x0080: - nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1, - impl->mthd.base); - break; - default: - break; - } - } else - if (chid <= 8) { - switch (mthd & 0xffc) { - case 0x0080: - nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5, - impl->mthd.ovly); - break; - default: - break; - } - } - - nv_wr32(priv, 0x61009c, (1 << chid)); - nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000); -} - -void -gf110_disp_intr(struct nvkm_subdev *subdev) -{ - struct nv50_disp_priv *priv = (void *)subdev; - u32 intr = nv_rd32(priv, 0x610088); - int i; - - if (intr & 0x00000001) { - u32 stat = nv_rd32(priv, 0x61008c); - while (stat) { - int chid = __ffs(stat); stat &= ~(1 << chid); - nv50_disp_chan_uevent_send(priv, chid); - nv_wr32(priv, 0x61008c, 1 << chid); - } - intr &= ~0x00000001; - } - - if (intr & 0x00000002) { - u32 stat = nv_rd32(priv, 0x61009c); - int chid = ffs(stat) - 1; - if (chid >= 0) - gf110_disp_intr_error(priv, chid); - intr &= ~0x00000002; - } - - if (intr & 0x00100000) { - u32 stat = nv_rd32(priv, 0x6100ac); - if (stat & 0x00000007) { - priv->super = (stat & 0x00000007); - schedule_work(&priv->supervisor); - nv_wr32(priv, 0x6100ac, priv->super); - stat &= ~0x00000007; - } - - if (stat) { - nv_info(priv, "unknown intr24 0x%08x\n", stat); - nv_wr32(priv, 0x6100ac, stat); - } - - intr &= ~0x00100000; - } - - for (i = 0; i < priv->head.nr; i++) { - u32 mask = 0x01000000 << i; - if (mask & intr) { - u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); - if (stat & 0x00000001) - nvkm_disp_vblank(&priv->base, i); - nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); - nv_rd32(priv, 0x6100c0 + (i * 0x800)); - } - } -} - -static int -gf110_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&gf110_disp_chan_uevent, 1, 17, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gf110_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = gf110_disp_intr; - INIT_WORK(&priv->supervisor, gf110_disp_intr_supervisor); - priv->sclass = gf110_disp_sclass; - priv->head.nr = heads; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hda_eld = gf110_hda_eld; - priv->sor.hdmi = gf110_hdmi_ctrl; - return 0; -} - -struct nvkm_oclass * -gf110_disp_outp_sclass[] = { - &gf110_sor_dp_impl.base.base, - NULL -}; - -struct nvkm_oclass * -gf110_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x90), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf110_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &gf110_disp_vblank_func, - .base.outp = gf110_disp_outp_sclass, - .mthd.core = &gf110_disp_core_mthd_chan, - .mthd.base = &gf110_disp_base_mthd_chan, - .mthd.ovly = &gf110_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, - .head.scanoutpos = gf110_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c new file mode 100644 index 000000000..186fd3ac7 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -0,0 +1,536 @@ +/* + * 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 "nv50.h" +#include "rootnv50.h" + +#include +#include +#include +#include +#include + +void +gf119_disp_vblank_init(struct nv50_disp *disp, int head) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_mask(device, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001); +} + +void +gf119_disp_vblank_fini(struct nv50_disp *disp, int head) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_mask(device, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000); +} + +static struct nvkm_output * +exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl, + u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, + struct nvbios_outp *info) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_bios *bios = subdev->device->bios; + struct nvkm_output *outp; + u16 mask, type; + + if (or < 4) { + type = DCB_OUTPUT_ANALOG; + mask = 0; + } else { + or -= 4; + switch (ctrl & 0x00000f00) { + case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; + case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; + case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break; + case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break; + case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break; + case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; + default: + nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl); + return NULL; + } + } + + mask = 0x00c0 & (mask << 6); + mask |= 0x0001 << or; + mask |= 0x0100 << head; + + list_for_each_entry(outp, &disp->base.outp, head) { + if ((outp->info.hasht & 0xff) == type && + (outp->info.hashm & mask) == mask) { + *data = nvbios_outp_match(bios, outp->info.hasht, + outp->info.hashm, + ver, hdr, cnt, len, info); + if (!*data) + return NULL; + return outp; + } + } + + return NULL; +} + +static struct nvkm_output * +exec_script(struct nv50_disp *disp, int head, int id) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; + struct nvkm_output *outp; + struct nvbios_outp info; + u8 ver, hdr, cnt, len; + u32 data, ctrl = 0; + int or; + + for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { + ctrl = nvkm_rd32(device, 0x640180 + (or * 0x20)); + if (ctrl & (1 << head)) + break; + } + + if (or == 8) + return NULL; + + outp = exec_lookup(disp, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info); + if (outp) { + struct nvbios_init init = { + .subdev = subdev, + .bios = bios, + .offset = info.script[id], + .outp = &outp->info, + .crtc = head, + .execute = 1, + }; + + nvbios_exec(&init); + } + + return outp; +} + +static struct nvkm_output * +exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; + struct nvkm_output *outp; + struct nvbios_outp info1; + struct nvbios_ocfg info2; + u8 ver, hdr, cnt, len; + u32 data, ctrl = 0; + int or; + + for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { + ctrl = nvkm_rd32(device, 0x660180 + (or * 0x20)); + if (ctrl & (1 << head)) + break; + } + + if (or == 8) + return NULL; + + outp = exec_lookup(disp, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); + if (!outp) + return NULL; + + switch (outp->info.type) { + case DCB_OUTPUT_TMDS: + *conf = (ctrl & 0x00000f00) >> 8; + if (pclk >= 165000) + *conf |= 0x0100; + break; + case DCB_OUTPUT_LVDS: + *conf = disp->sor.lvdsconf; + break; + case DCB_OUTPUT_DP: + *conf = (ctrl & 0x00000f00) >> 8; + break; + case DCB_OUTPUT_ANALOG: + default: + *conf = 0x00ff; + break; + } + + data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2); + if (data && id < 0xff) { + data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); + if (data) { + struct nvbios_init init = { + .subdev = subdev, + .bios = bios, + .offset = data, + .outp = &outp->info, + .crtc = head, + .execute = 1, + }; + + nvbios_exec(&init); + } + } + + return outp; +} + +static void +gf119_disp_intr_unk1_0(struct nv50_disp *disp, int head) +{ + exec_script(disp, head, 1); +} + +static void +gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_output *outp = exec_script(disp, head, 2); + + /* see note in nv50_disp_intr_unk20_0() */ + if (outp && outp->info.type == DCB_OUTPUT_DP) { + struct nvkm_output_dp *outpdp = nvkm_output_dp(outp); + struct nvbios_init init = { + .subdev = subdev, + .bios = subdev->device->bios, + .outp = &outp->info, + .crtc = head, + .offset = outpdp->info.script[4], + .execute = 1, + }; + + nvbios_exec(&init); + atomic_set(&outpdp->lt.done, 0); + } +} + +static void +gf119_disp_intr_unk2_1(struct nv50_disp *disp, int head) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_devinit *devinit = device->devinit; + u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000; + if (pclk) + nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk); + nvkm_wr32(device, 0x612200 + (head * 0x800), 0x00000000); +} + +static void +gf119_disp_intr_unk2_2_tu(struct nv50_disp *disp, int head, + struct dcb_output *outp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + const int or = ffs(outp->or) - 1; + const u32 ctrl = nvkm_rd32(device, 0x660200 + (or * 0x020)); + const u32 conf = nvkm_rd32(device, 0x660404 + (head * 0x300)); + const s32 vactive = nvkm_rd32(device, 0x660414 + (head * 0x300)) & 0xffff; + const s32 vblanke = nvkm_rd32(device, 0x66041c + (head * 0x300)) & 0xffff; + const s32 vblanks = nvkm_rd32(device, 0x660420 + (head * 0x300)) & 0xffff; + const u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000; + const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1; + const u32 hoff = (head * 0x800); + const u32 soff = ( or * 0x800); + const u32 loff = (link * 0x080) + soff; + const u32 symbol = 100000; + const u32 TU = 64; + u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff); + u32 clksor = nvkm_rd32(device, 0x612300 + soff); + u32 datarate, link_nr, link_bw, bits; + u64 ratio, value; + + link_nr = hweight32(dpctrl & 0x000f0000); + link_bw = (clksor & 0x007c0000) >> 18; + link_bw *= 27000; + + /* symbols/hblank - algorithm taken from comments in tegra driver */ + value = vblanke + vactive - vblanks - 7; + value = value * link_bw; + do_div(value, pclk); + value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr); + nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, value); + + /* symbols/vblank - algorithm taken from comments in tegra driver */ + value = vblanks - vblanke - 25; + value = value * link_bw; + do_div(value, pclk); + value = value - ((36 / link_nr) + 3) - 1; + nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, value); + + /* watermark */ + if ((conf & 0x3c0) == 0x180) bits = 30; + else if ((conf & 0x3c0) == 0x140) bits = 24; + else bits = 18; + datarate = (pclk * bits) / 8; + + ratio = datarate; + ratio *= symbol; + do_div(ratio, link_nr * link_bw); + + value = (symbol - ratio) * TU; + value *= ratio; + do_div(value, symbol); + do_div(value, symbol); + + value += 5; + value |= 0x08000000; + + nvkm_wr32(device, 0x616610 + hoff, value); +} + +static void +gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_output *outp; + u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000; + u32 conf, addr, data; + + outp = exec_clkcmp(disp, head, 0xff, pclk, &conf); + if (!outp) + return; + + /* see note in nv50_disp_intr_unk20_2() */ + if (outp->info.type == DCB_OUTPUT_DP) { + u32 sync = nvkm_rd32(device, 0x660404 + (head * 0x300)); + switch ((sync & 0x000003c0) >> 6) { + case 6: pclk = pclk * 30; break; + case 5: pclk = pclk * 24; break; + case 2: + default: + pclk = pclk * 18; + break; + } + + if (nvkm_output_dp_train(outp, pclk, true)) + OUTP_ERR(outp, "link not trained before attach"); + } else { + if (disp->func->sor.magic) + disp->func->sor.magic(outp); + } + + exec_clkcmp(disp, head, 0, pclk, &conf); + + if (outp->info.type == DCB_OUTPUT_ANALOG) { + addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800; + data = 0x00000000; + } else { + addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800; + data = (conf & 0x0100) ? 0x00000101 : 0x00000000; + switch (outp->info.type) { + case DCB_OUTPUT_TMDS: + nvkm_mask(device, addr, 0x007c0000, 0x00280000); + break; + case DCB_OUTPUT_DP: + gf119_disp_intr_unk2_2_tu(disp, head, &outp->info); + break; + default: + break; + } + } + + nvkm_mask(device, addr, 0x00000707, data); +} + +static void +gf119_disp_intr_unk4_0(struct nv50_disp *disp, int head) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000; + u32 conf; + + exec_clkcmp(disp, head, 1, pclk, &conf); +} + +void +gf119_disp_intr_supervisor(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; + u32 mask[4]; + int head; + + nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super)); + for (head = 0; head < disp->base.head.nr; head++) { + mask[head] = nvkm_rd32(device, 0x6101d4 + (head * 0x800)); + nvkm_debug(subdev, "head %d: %08x\n", head, mask[head]); + } + + if (disp->super & 0x00000001) { + nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); + for (head = 0; head < disp->base.head.nr; head++) { + if (!(mask[head] & 0x00001000)) + continue; + nvkm_debug(subdev, "supervisor 1.0 - head %d\n", head); + gf119_disp_intr_unk1_0(disp, head); + } + } else + if (disp->super & 0x00000002) { + for (head = 0; head < disp->base.head.nr; head++) { + if (!(mask[head] & 0x00001000)) + continue; + nvkm_debug(subdev, "supervisor 2.0 - head %d\n", head); + gf119_disp_intr_unk2_0(disp, head); + } + for (head = 0; head < disp->base.head.nr; head++) { + if (!(mask[head] & 0x00010000)) + continue; + nvkm_debug(subdev, "supervisor 2.1 - head %d\n", head); + gf119_disp_intr_unk2_1(disp, head); + } + for (head = 0; head < disp->base.head.nr; head++) { + if (!(mask[head] & 0x00001000)) + continue; + nvkm_debug(subdev, "supervisor 2.2 - head %d\n", head); + gf119_disp_intr_unk2_2(disp, head); + } + } else + if (disp->super & 0x00000004) { + for (head = 0; head < disp->base.head.nr; head++) { + if (!(mask[head] & 0x00001000)) + continue; + nvkm_debug(subdev, "supervisor 3.0 - head %d\n", head); + gf119_disp_intr_unk4_0(disp, head); + } + } + + for (head = 0; head < disp->base.head.nr; head++) + nvkm_wr32(device, 0x6101d4 + (head * 0x800), 0x00000000); + nvkm_wr32(device, 0x6101d0, 0x80000000); +} + +static void +gf119_disp_intr_error(struct nv50_disp *disp, int chid) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mthd = nvkm_rd32(device, 0x6101f0 + (chid * 12)); + u32 data = nvkm_rd32(device, 0x6101f4 + (chid * 12)); + u32 unkn = nvkm_rd32(device, 0x6101f8 + (chid * 12)); + + nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n", + chid, (mthd & 0x0000ffc), data, mthd, unkn); + + if (chid < ARRAY_SIZE(disp->chan)) { + switch (mthd & 0xffc) { + case 0x0080: + nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR); + break; + default: + break; + } + } + + nvkm_wr32(device, 0x61009c, (1 << chid)); + nvkm_wr32(device, 0x6101f0 + (chid * 12), 0x90000000); +} + +void +gf119_disp_intr(struct nv50_disp *disp) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x610088); + int i; + + if (intr & 0x00000001) { + u32 stat = nvkm_rd32(device, 0x61008c); + while (stat) { + int chid = __ffs(stat); stat &= ~(1 << chid); + nv50_disp_chan_uevent_send(disp, chid); + nvkm_wr32(device, 0x61008c, 1 << chid); + } + intr &= ~0x00000001; + } + + if (intr & 0x00000002) { + u32 stat = nvkm_rd32(device, 0x61009c); + int chid = ffs(stat) - 1; + if (chid >= 0) + gf119_disp_intr_error(disp, chid); + intr &= ~0x00000002; + } + + if (intr & 0x00100000) { + u32 stat = nvkm_rd32(device, 0x6100ac); + if (stat & 0x00000007) { + disp->super = (stat & 0x00000007); + schedule_work(&disp->supervisor); + nvkm_wr32(device, 0x6100ac, disp->super); + stat &= ~0x00000007; + } + + if (stat) { + nvkm_warn(subdev, "intr24 %08x\n", stat); + nvkm_wr32(device, 0x6100ac, stat); + } + + intr &= ~0x00100000; + } + + for (i = 0; i < disp->base.head.nr; i++) { + u32 mask = 0x01000000 << i; + if (mask & intr) { + u32 stat = nvkm_rd32(device, 0x6100bc + (i * 0x800)); + if (stat & 0x00000001) + nvkm_disp_vblank(&disp->base, i); + nvkm_mask(device, 0x6100bc + (i * 0x800), 0, 0); + nvkm_rd32(device, 0x6100c0 + (i * 0x800)); + } + } +} + +int +gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, + int index, struct nvkm_disp **pdisp) +{ + u32 heads = nvkm_rd32(device, 0x022448); + return nv50_disp_new_(func, device, index, heads, pdisp); +} + +static const struct nv50_disp_func +gf119_disp = { + .intr = gf119_disp_intr, + .uevent = &gf119_disp_chan_uevent, + .super = gf119_disp_intr_supervisor, + .root = &gf119_disp_root_oclass, + .head.vblank_init = gf119_disp_vblank_init, + .head.vblank_fini = gf119_disp_vblank_fini, + .head.scanoutpos = gf119_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = gf119_sor_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hda_eld = gf119_hda_eld, + .sor.hdmi = gf119_hdmi_ctrl, +}; + +int +gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) +{ + return gf119_disp_new_(&gf119_disp, device, index, pdisp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 6f4019ab4..a86384b8e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -22,247 +22,32 @@ * Authors: Ben Skeggs */ #include "nv50.h" - -#include - -/******************************************************************************* - * EVO master channel object - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -gk104_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x047c, 0x66047c }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x0488, 0x660488 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04a0, 0x6604a0 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x0520, 0x660520 }, - { 0x0524, 0x660524 }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -const struct nv50_disp_mthd_chan -gk104_disp_core_mthd_chan = { - .name = "Core", - .addr = 0x000000, - .data = { - { "Global", 1, &gf110_disp_core_mthd_base }, - { "DAC", 3, &gf110_disp_core_mthd_dac }, - { "SOR", 8, &gf110_disp_core_mthd_sor }, - { "PIOR", 4, &gf110_disp_core_mthd_pior }, - { "HEAD", 4, &gk104_disp_core_mthd_head }, - {} - } -}; - -/******************************************************************************* - * EVO overlay channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -gk104_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00c4, 0x6650c4 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0404, 0x665404 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -const struct nv50_disp_mthd_chan -gk104_disp_ovly_mthd_chan = { - .name = "Overlay", - .addr = 0x001000, - .data = { - { "Global", 1, &gk104_disp_ovly_mthd_base }, - {} - } +#include "rootnv50.h" + +static const struct nv50_disp_func +gk104_disp = { + .intr = gf119_disp_intr, + .uevent = &gf119_disp_chan_uevent, + .super = gf119_disp_intr_supervisor, + .root = &gk104_disp_root_oclass, + .head.vblank_init = gf119_disp_vblank_init, + .head.vblank_fini = gf119_disp_vblank_fini, + .head.scanoutpos = gf119_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = gf119_sor_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hda_eld = gf119_hda_eld, + .sor.hdmi = gk104_hdmi_ctrl, }; -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -gk104_disp_sclass[] = { - { GK104_DISP_CORE_CHANNEL_DMA, &gf110_disp_core_ofuncs.base }, - { GK104_DISP_BASE_CHANNEL_DMA, &gf110_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf110_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf110_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf110_disp_curs_ofuncs.base }, - {} -}; - -static struct nvkm_oclass -gk104_disp_main_oclass[] = { - { GK104_DISP, &gf110_disp_main_ofuncs }, - {} -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -gk104_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gk104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&gf110_disp_chan_uevent, 1, 17, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gk104_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = gf110_disp_intr; - INIT_WORK(&priv->supervisor, gf110_disp_intr_supervisor); - priv->sclass = gk104_disp_sclass; - priv->head.nr = heads; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hda_eld = gf110_hda_eld; - priv->sor.hdmi = gk104_hdmi_ctrl; - return 0; + return gf119_disp_new_(&gk104_disp, device, index, pdisp); } - -struct nvkm_oclass * -gk104_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x91), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &gf110_disp_vblank_func, - .base.outp = gf110_disp_outp_sclass, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf110_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, - .head.scanoutpos = gf110_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index daa4b460a..0d574c7e5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -22,82 +22,32 @@ * Authors: Ben Skeggs */ #include "nv50.h" - -#include - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -gk110_disp_sclass[] = { - { GK110_DISP_CORE_CHANNEL_DMA, &gf110_disp_core_ofuncs.base }, - { GK110_DISP_BASE_CHANNEL_DMA, &gf110_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf110_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf110_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf110_disp_curs_ofuncs.base }, - {} -}; - -static struct nvkm_oclass -gk110_disp_main_oclass[] = { - { GK110_DISP, &gf110_disp_main_ofuncs }, - {} +#include "rootnv50.h" + +static const struct nv50_disp_func +gk110_disp = { + .intr = gf119_disp_intr, + .uevent = &gf119_disp_chan_uevent, + .super = gf119_disp_intr_supervisor, + .root = &gk110_disp_root_oclass, + .head.vblank_init = gf119_disp_vblank_init, + .head.vblank_fini = gf119_disp_vblank_fini, + .head.scanoutpos = gf119_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = gf119_sor_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hda_eld = gf119_hda_eld, + .sor.hdmi = gk104_hdmi_ctrl, }; -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -gk110_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gk110_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&gf110_disp_chan_uevent, 1, 17, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gk110_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = gf110_disp_intr; - INIT_WORK(&priv->supervisor, gf110_disp_intr_supervisor); - priv->sclass = gk110_disp_sclass; - priv->head.nr = heads; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hda_eld = gf110_hda_eld; - priv->sor.hdmi = gk104_hdmi_ctrl; - return 0; + return gf119_disp_new_(&gk110_disp, device, index, pdisp); } - -struct nvkm_oclass * -gk110_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x92), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk110_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &gf110_disp_vblank_func, - .base.outp = gf110_disp_outp_sclass, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf110_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, - .head.scanoutpos = gf110_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index 881cc9438..b6944142d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -22,82 +22,32 @@ * Authors: Ben Skeggs */ #include "nv50.h" - -#include - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -gm107_disp_sclass[] = { - { GM107_DISP_CORE_CHANNEL_DMA, &gf110_disp_core_ofuncs.base }, - { GK110_DISP_BASE_CHANNEL_DMA, &gf110_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf110_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf110_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf110_disp_curs_ofuncs.base }, - {} -}; - -static struct nvkm_oclass -gm107_disp_main_oclass[] = { - { GM107_DISP, &gf110_disp_main_ofuncs }, - {} +#include "rootnv50.h" + +static const struct nv50_disp_func +gm107_disp = { + .intr = gf119_disp_intr, + .uevent = &gf119_disp_chan_uevent, + .super = gf119_disp_intr_supervisor, + .root = &gm107_disp_root_oclass, + .head.vblank_init = gf119_disp_vblank_init, + .head.vblank_fini = gf119_disp_vblank_fini, + .head.scanoutpos = gf119_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = gf119_sor_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hda_eld = gf119_hda_eld, + .sor.hdmi = gk104_hdmi_ctrl, }; -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -gm107_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&gf110_disp_chan_uevent, 1, 17, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gm107_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = gf110_disp_intr; - INIT_WORK(&priv->supervisor, gf110_disp_intr_supervisor); - priv->sclass = gm107_disp_sclass; - priv->head.nr = heads; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hda_eld = gf110_hda_eld; - priv->sor.hdmi = gk104_hdmi_ctrl; - return 0; + return gf119_disp_new_(&gm107_disp, device, index, pdisp); } - -struct nvkm_oclass * -gm107_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x07), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm107_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &gf110_disp_vblank_func, - .base.outp = gf110_disp_outp_sclass, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf110_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, - .head.scanoutpos = gf110_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c index 67004f830..30f1987b5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm204.c @@ -22,90 +22,33 @@ * Authors: Ben Skeggs */ #include "nv50.h" -#include "outpdp.h" - -#include - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -gm204_disp_sclass[] = { - { GM204_DISP_CORE_CHANNEL_DMA, &gf110_disp_core_ofuncs.base }, - { GK110_DISP_BASE_CHANNEL_DMA, &gf110_disp_base_ofuncs.base }, - { GK104_DISP_OVERLAY_CONTROL_DMA, &gf110_disp_ovly_ofuncs.base }, - { GK104_DISP_OVERLAY, &gf110_disp_oimm_ofuncs.base }, - { GK104_DISP_CURSOR, &gf110_disp_curs_ofuncs.base }, - {} +#include "rootnv50.h" + +static const struct nv50_disp_func +gm204_disp = { + .intr = gf119_disp_intr, + .uevent = &gf119_disp_chan_uevent, + .super = gf119_disp_intr_supervisor, + .root = &gm204_disp_root_oclass, + .head.vblank_init = gf119_disp_vblank_init, + .head.vblank_fini = gf119_disp_vblank_fini, + .head.scanoutpos = gf119_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = gm204_sor_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hda_eld = gf119_hda_eld, + .sor.hdmi = gk104_hdmi_ctrl, + .sor.magic = gm204_sor_magic, }; -static struct nvkm_oclass -gm204_disp_main_oclass[] = { - { GM204_DISP, &gf110_disp_main_ofuncs }, - {} -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -gm204_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gm204_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&gf110_disp_chan_uevent, 1, 17, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gm204_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = gf110_disp_intr; - INIT_WORK(&priv->supervisor, gf110_disp_intr_supervisor); - priv->sclass = gm204_disp_sclass; - priv->head.nr = heads; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hda_eld = gf110_hda_eld; - priv->sor.hdmi = gf110_hdmi_ctrl; - priv->sor.magic = gm204_sor_magic; - return 0; + return gf119_disp_new_(&gm204_disp, device, index, pdisp); } - -struct nvkm_oclass * -gm204_disp_outp_sclass[] = { - &gm204_sor_dp_impl.base.base, - NULL -}; - -struct nvkm_oclass * -gm204_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x07), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &gf110_disp_vblank_func, - .base.outp = gm204_disp_outp_sclass, - .mthd.core = &gk104_disp_core_mthd_chan, - .mthd.base = &gf110_disp_base_mthd_chan, - .mthd.ovly = &gk104_disp_ovly_mthd_chan, - .mthd.prev = -0x020000, - .head.scanoutpos = gf110_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index a45307213..6bc3bf096 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -22,127 +22,34 @@ * Authors: Ben Skeggs */ #include "nv50.h" - -#include - -/******************************************************************************* - * EVO overlay channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -gt200_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00b0, 0x610c98 }, - { 0x00b4, 0x610ca4 }, - { 0x00b8, 0x610cac }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_mthd_chan -gt200_disp_ovly_mthd_chan = { - .name = "Overlay", - .addr = 0x000540, - .data = { - { "Global", 1, >200_disp_ovly_mthd_base }, - {} - } -}; - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -gt200_disp_sclass[] = { - { GT200_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} +#include "rootnv50.h" + +static const struct nv50_disp_func +gt200_disp = { + .intr = nv50_disp_intr, + .uevent = &nv50_disp_chan_uevent, + .super = nv50_disp_intr_supervisor, + .root = >200_disp_root_oclass, + .head.vblank_init = nv50_disp_vblank_init, + .head.vblank_fini = nv50_disp_vblank_fini, + .head.scanoutpos = nv50_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.external.tmds = nv50_pior_output_new, + .outp.external.dp = nv50_pior_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 2, + .sor.power = nv50_sor_power, + .sor.hdmi = g84_hdmi_ctrl, + .pior.nr = 3, + .pior.power = nv50_pior_power, }; -static struct nvkm_oclass -gt200_disp_main_oclass[] = { - { GT200_DISP, &nv50_disp_main_ofuncs }, - {} -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -gt200_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gt200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP", - "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gt200_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); - priv->sclass = gt200_disp_sclass; - priv->head.nr = 2; - priv->dac.nr = 3; - priv->sor.nr = 2; - priv->pior.nr = 3; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hdmi = g84_hdmi_ctrl; - priv->pior.power = nv50_pior_power; - return 0; + return nv50_disp_new_(>200_disp, device, index, 2, pdisp); } - -struct nvkm_oclass * -gt200_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x83), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt200_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &nv50_disp_vblank_func, - .base.outp = nv50_disp_outp_sclass, - .mthd.core = &g84_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = >200_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, - .head.scanoutpos = nv50_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index 55f0d3ac5..94026288a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -22,83 +22,36 @@ * Authors: Ben Skeggs */ #include "nv50.h" - -#include - -/******************************************************************************* - * Base display object - ******************************************************************************/ - -static struct nvkm_oclass -gt215_disp_sclass[] = { - { GT214_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { GT214_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { GT214_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { GT214_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { GT214_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} -}; - -static struct nvkm_oclass -gt215_disp_main_oclass[] = { - { GT214_DISP, &nv50_disp_main_ofuncs }, - {} +#include "rootnv50.h" + +static const struct nv50_disp_func +gt215_disp = { + .intr = nv50_disp_intr, + .uevent = &nv50_disp_chan_uevent, + .super = nv50_disp_intr_supervisor, + .root = >215_disp_root_oclass, + .head.vblank_init = nv50_disp_vblank_init, + .head.vblank_fini = nv50_disp_vblank_fini, + .head.scanoutpos = nv50_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.internal.dp = g94_sor_dp_new, + .outp.external.tmds = nv50_pior_output_new, + .outp.external.dp = nv50_pior_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 4, + .sor.power = nv50_sor_power, + .sor.hda_eld = gt215_hda_eld, + .sor.hdmi = gt215_hdmi_ctrl, + .pior.nr = 3, + .pior.power = nv50_pior_power, }; -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static int -gt215_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gt215_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP", - "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = gt215_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); - priv->sclass = gt215_disp_sclass; - priv->head.nr = 2; - priv->dac.nr = 3; - priv->sor.nr = 4; - priv->pior.nr = 3; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->sor.hda_eld = gt215_hda_eld; - priv->sor.hdmi = gt215_hdmi_ctrl; - priv->pior.power = nv50_pior_power; - return 0; + return nv50_disp_new_(>215_disp, device, index, 2, pdisp); } - -struct nvkm_oclass * -gt215_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x85), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt215_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &nv50_disp_vblank_func, - .base.outp = g94_disp_outp_sclass, - .mthd.core = &g94_disp_core_mthd_chan, - .mthd.base = &g84_disp_base_mthd_chan, - .mthd.ovly = &g84_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, - .head.scanoutpos = nv50_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf110.c deleted file mode 100644 index b9813d246..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf110.c +++ /dev/null @@ -1,73 +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 "nv50.h" -#include "outp.h" - -#include -#include -#include -#include - -#include -#include - -int -gf110_hda_eld(NV50_DISP_MTHD_V1) -{ - union { - struct nv50_disp_sor_hda_eld_v0 v0; - } *args = data; - const u32 soff = outp->or * 0x030; - const u32 hoff = head * 0x800; - int ret, i; - - nv_ioctl(object, "disp sor hda eld size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version); - if (size > 0x60) - return -E2BIG; - } else - return ret; - - if (size && args->v0.data[0]) { - if (outp->info.type == DCB_OUTPUT_DP) { - nv_mask(priv, 0x616618 + hoff, 0x8000000c, 0x80000001); - nv_wait(priv, 0x616618 + hoff, 0x80000000, 0x00000000); - } - nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000); - for (i = 0; i < size; i++) - nv_wr32(priv, 0x10ec00 + soff, (i << 8) | args->v0.data[i]); - for (; i < 0x60; i++) - nv_wr32(priv, 0x10ec00 + soff, (i << 8)); - nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003); - } else { - if (outp->info.type == DCB_OUTPUT_DP) { - nv_mask(priv, 0x616618 + hoff, 0x80000001, 0x80000000); - nv_wait(priv, 0x616618 + hoff, 0x80000000, 0x00000000); - } - nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000000 | !!size); - } - - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c new file mode 100644 index 000000000..af99efbd6 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c @@ -0,0 +1,83 @@ +/* + * 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 "nv50.h" +#include "outp.h" + +#include +#include +#include +#include + +#include +#include + +int +gf119_hda_eld(NV50_DISP_MTHD_V1) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + union { + struct nv50_disp_sor_hda_eld_v0 v0; + } *args = data; + const u32 soff = outp->or * 0x030; + const u32 hoff = head * 0x800; + int ret, i; + + nvif_ioctl(object, "disp sor hda eld size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, true)) { + nvif_ioctl(object, "disp sor hda eld vers %d\n", + args->v0.version); + if (size > 0x60) + return -E2BIG; + } else + return ret; + + if (size && args->v0.data[0]) { + if (outp->info.type == DCB_OUTPUT_DP) { + nvkm_mask(device, 0x616618 + hoff, 0x8000000c, 0x80000001); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x616618 + hoff); + if (!(tmp & 0x80000000)) + break; + ); + } + nvkm_mask(device, 0x616548 + hoff, 0x00000070, 0x00000000); + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | args->v0.data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); + nvkm_mask(device, 0x10ec10 + soff, 0x80000003, 0x80000003); + } else { + if (outp->info.type == DCB_OUTPUT_DP) { + nvkm_mask(device, 0x616618 + hoff, 0x80000001, 0x80000000); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x616618 + hoff); + if (!(tmp & 0x80000000)) + break; + ); + } + nvkm_mask(device, 0x10ec10 + soff, 0x80000003, 0x80000000 | !!size); + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c index 891d1e7bf..c1590b746 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c @@ -33,15 +33,17 @@ int gt215_hda_eld(NV50_DISP_MTHD_V1) { + struct nvkm_device *device = disp->base.engine.subdev.device; union { struct nv50_disp_sor_hda_eld_v0 v0; } *args = data; const u32 soff = outp->or * 0x800; int ret, i; - nv_ioctl(object, "disp sor hda eld size %d\n", size); + nvif_ioctl(object, "disp sor hda eld size %d\n", size); if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version); + nvif_ioctl(object, "disp sor hda eld vers %d\n", + args->v0.version); if (size > 0x60) return -E2BIG; } else @@ -49,20 +51,28 @@ gt215_hda_eld(NV50_DISP_MTHD_V1) if (size && args->v0.data[0]) { if (outp->info.type == DCB_OUTPUT_DP) { - nv_mask(priv, 0x61c1e0 + soff, 0x8000000d, 0x80000001); - nv_wait(priv, 0x61c1e0 + soff, 0x80000000, 0x00000000); + nvkm_mask(device, 0x61c1e0 + soff, 0x8000000d, 0x80000001); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x61c1e0 + soff); + if (!(tmp & 0x80000000)) + break; + ); } for (i = 0; i < size; i++) - nv_wr32(priv, 0x61c440 + soff, (i << 8) | args->v0.data[0]); + nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[0]); for (; i < 0x60; i++) - nv_wr32(priv, 0x61c440 + soff, (i << 8)); - nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003); + nvkm_wr32(device, 0x61c440 + soff, (i << 8)); + nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003); } else { if (outp->info.type == DCB_OUTPUT_DP) { - nv_mask(priv, 0x61c1e0 + soff, 0x80000001, 0x80000000); - nv_wait(priv, 0x61c1e0 + soff, 0x80000000, 0x00000000); + nvkm_mask(device, 0x61c1e0 + soff, 0x80000001, 0x80000000); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x61c1e0 + soff); + if (!(tmp & 0x80000000)) + break; + ); } - nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000000 | !!size); + nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000000 | !!size); } return 0; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c index 621cb0b7f..ee9e800a8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c @@ -31,6 +31,7 @@ int g84_hdmi_ctrl(NV50_DISP_MTHD_V1) { + struct nvkm_device *device = disp->base.engine.subdev.device; const u32 hoff = (head * 0x800); union { struct nv50_disp_sor_hdmi_pwr_v0 v0; @@ -38,12 +39,12 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1) u32 ctrl; int ret; - nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size); + nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d " - "max_ac_packet %d rekey %d\n", - args->v0.version, args->v0.state, - args->v0.max_ac_packet, args->v0.rekey); + nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d " + "max_ac_packet %d rekey %d\n", + args->v0.version, args->v0.state, + args->v0.max_ac_packet, args->v0.rekey); if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) return -EINVAL; ctrl = 0x40000000 * !!args->v0.state; @@ -54,38 +55,38 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1) return ret; if (!(ctrl & 0x40000000)) { - nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000); - nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000); - nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); return 0; } /* AVI InfoFrame */ - nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000); - nv_wr32(priv, 0x616528 + hoff, 0x000d0282); - nv_wr32(priv, 0x61652c + hoff, 0x0000006f); - nv_wr32(priv, 0x616530 + hoff, 0x00000000); - nv_wr32(priv, 0x616534 + hoff, 0x00000000); - nv_wr32(priv, 0x616538 + hoff, 0x00000000); - nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000001); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x616528 + hoff, 0x000d0282); + nvkm_wr32(device, 0x61652c + hoff, 0x0000006f); + nvkm_wr32(device, 0x616530 + hoff, 0x00000000); + nvkm_wr32(device, 0x616534 + hoff, 0x00000000); + nvkm_wr32(device, 0x616538 + hoff, 0x00000000); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); /* Audio InfoFrame */ - nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000); - nv_wr32(priv, 0x616508 + hoff, 0x000a0184); - nv_wr32(priv, 0x61650c + hoff, 0x00000071); - nv_wr32(priv, 0x616510 + hoff, 0x00000000); - nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000001); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); + nvkm_wr32(device, 0x61650c + hoff, 0x00000071); + nvkm_wr32(device, 0x616510 + hoff, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); - nv_mask(priv, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nv_mask(priv, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nv_mask(priv, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ /* ??? */ - nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ /* HDMI_CTRL */ - nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, ctrl); + nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf110.c deleted file mode 100644 index c28449061..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf110.c +++ /dev/null @@ -1,79 +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 "nv50.h" - -#include - -#include -#include - -int -gf110_hdmi_ctrl(NV50_DISP_MTHD_V1) -{ - const u32 hoff = (head * 0x800); - union { - struct nv50_disp_sor_hdmi_pwr_v0 v0; - } *args = data; - u32 ctrl; - int ret; - - nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d " - "max_ac_packet %d rekey %d\n", - args->v0.version, args->v0.state, - args->v0.max_ac_packet, args->v0.rekey); - if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) - return -EINVAL; - ctrl = 0x40000000 * !!args->v0.state; - ctrl |= args->v0.max_ac_packet << 16; - ctrl |= args->v0.rekey; - } else - return ret; - - if (!(ctrl & 0x40000000)) { - nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000); - nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000); - return 0; - } - - /* AVI InfoFrame */ - nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000); - nv_wr32(priv, 0x61671c + hoff, 0x000d0282); - nv_wr32(priv, 0x616720 + hoff, 0x0000006f); - nv_wr32(priv, 0x616724 + hoff, 0x00000000); - nv_wr32(priv, 0x616728 + hoff, 0x00000000); - nv_wr32(priv, 0x61672c + hoff, 0x00000000); - nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000001); - - /* ??? InfoFrame? */ - nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nv_wr32(priv, 0x6167ac + hoff, 0x00000010); - nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001); - - /* HDMI_CTRL */ - nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl); - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c new file mode 100644 index 000000000..b5af025d3 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c @@ -0,0 +1,80 @@ +/* + * 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 "nv50.h" + +#include + +#include +#include + +int +gf119_hdmi_ctrl(NV50_DISP_MTHD_V1) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + const u32 hoff = (head * 0x800); + union { + struct nv50_disp_sor_hdmi_pwr_v0 v0; + } *args = data; + u32 ctrl; + int ret; + + nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d " + "max_ac_packet %d rekey %d\n", + args->v0.version, args->v0.state, + args->v0.max_ac_packet, args->v0.rekey); + if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) + return -EINVAL; + ctrl = 0x40000000 * !!args->v0.state; + ctrl |= args->v0.max_ac_packet << 16; + ctrl |= args->v0.rekey; + } else + return ret; + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + return 0; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x61671c + hoff, 0x000d0282); + nvkm_wr32(device, 0x616720 + hoff, 0x0000006f); + nvkm_wr32(device, 0x616724 + hoff, 0x00000000); + nvkm_wr32(device, 0x616728 + hoff, 0x00000000); + nvkm_wr32(device, 0x61672c + hoff, 0x00000000); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c index ca34ff81a..110dc19e4 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c @@ -31,6 +31,7 @@ int gk104_hdmi_ctrl(NV50_DISP_MTHD_V1) { + struct nvkm_device *device = disp->base.engine.subdev.device; const u32 hoff = (head * 0x800); const u32 hdmi = (head * 0x400); union { @@ -39,12 +40,12 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1) u32 ctrl; int ret; - nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size); + nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d " - "max_ac_packet %d rekey %d\n", - args->v0.version, args->v0.state, - args->v0.max_ac_packet, args->v0.rekey); + nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d " + "max_ac_packet %d rekey %d\n", + args->v0.version, args->v0.state, + args->v0.max_ac_packet, args->v0.rekey); if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) return -EINVAL; ctrl = 0x40000000 * !!args->v0.state; @@ -54,30 +55,30 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1) return ret; if (!(ctrl & 0x40000000)) { - nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000); - nv_mask(priv, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nv_mask(priv, 0x690000 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); return 0; } /* AVI InfoFrame */ - nv_mask(priv, 0x690000 + hdmi, 0x00000001, 0x00000000); - nv_wr32(priv, 0x690008 + hdmi, 0x000d0282); - nv_wr32(priv, 0x69000c + hdmi, 0x0000006f); - nv_wr32(priv, 0x690010 + hdmi, 0x00000000); - nv_wr32(priv, 0x690014 + hdmi, 0x00000000); - nv_wr32(priv, 0x690018 + hdmi, 0x00000000); - nv_mask(priv, 0x690000 + hdmi, 0x00000001, 0x00000001); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x690008 + hdmi, 0x000d0282); + nvkm_wr32(device, 0x69000c + hdmi, 0x0000006f); + nvkm_wr32(device, 0x690010 + hdmi, 0x00000000); + nvkm_wr32(device, 0x690014 + hdmi, 0x00000000); + nvkm_wr32(device, 0x690018 + hdmi, 0x00000000); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); /* ??? InfoFrame? */ - nv_mask(priv, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nv_wr32(priv, 0x6900cc + hdmi, 0x00000010); - nv_mask(priv, 0x6900c0 + hdmi, 0x00000001, 0x00000001); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); /* ??? */ - nv_wr32(priv, 0x690080 + hdmi, 0x82000000); + nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); /* HDMI_CTRL */ - nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl); + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c index b641c167d..61237dbfa 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c @@ -32,6 +32,7 @@ int gt215_hdmi_ctrl(NV50_DISP_MTHD_V1) { + struct nvkm_device *device = disp->base.engine.subdev.device; const u32 soff = outp->or * 0x800; union { struct nv50_disp_sor_hdmi_pwr_v0 v0; @@ -39,12 +40,12 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1) u32 ctrl; int ret; - nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size); + nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d " - "max_ac_packet %d rekey %d\n", - args->v0.version, args->v0.state, - args->v0.max_ac_packet, args->v0.rekey); + nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d " + "max_ac_packet %d rekey %d\n", + args->v0.version, args->v0.state, + args->v0.max_ac_packet, args->v0.rekey); if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f) return -EINVAL; ctrl = 0x40000000 * !!args->v0.state; @@ -55,38 +56,38 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1) return ret; if (!(ctrl & 0x40000000)) { - nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000); - nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000); - nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); return 0; } /* AVI InfoFrame */ - nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000); - nv_wr32(priv, 0x61c528 + soff, 0x000d0282); - nv_wr32(priv, 0x61c52c + soff, 0x0000006f); - nv_wr32(priv, 0x61c530 + soff, 0x00000000); - nv_wr32(priv, 0x61c534 + soff, 0x00000000); - nv_wr32(priv, 0x61c538 + soff, 0x00000000); - nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000001); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x61c528 + soff, 0x000d0282); + nvkm_wr32(device, 0x61c52c + soff, 0x0000006f); + nvkm_wr32(device, 0x61c530 + soff, 0x00000000); + nvkm_wr32(device, 0x61c534 + soff, 0x00000000); + nvkm_wr32(device, 0x61c538 + soff, 0x00000000); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); /* Audio InfoFrame */ - nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000); - nv_wr32(priv, 0x61c508 + soff, 0x000a0184); - nv_wr32(priv, 0x61c50c + soff, 0x00000071); - nv_wr32(priv, 0x61c510 + soff, 0x00000000); - nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000001); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); + nvkm_wr32(device, 0x61c50c + soff, 0x00000071); + nvkm_wr32(device, 0x61c510 + soff, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); - nv_mask(priv, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nv_mask(priv, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nv_mask(priv, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ /* ??? */ - nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ /* HDMI_CTRL */ - nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, ctrl); + nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c index ff09b2659..67254ce6f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c @@ -23,183 +23,63 @@ */ #include "priv.h" -#include -#include - -#include -#include - -struct nv04_disp_priv { - struct nvkm_disp base; -}; - -static int -nv04_disp_scanoutpos(struct nvkm_object *object, struct nv04_disp_priv *priv, - void *data, u32 size, int head) +static const struct nvkm_disp_oclass * +nv04_disp_root(struct nvkm_disp *disp) { - const u32 hoff = head * 0x2000; - union { - struct nv04_disp_scanoutpos_v0 v0; - } *args = data; - u32 line; - int ret; - - nv_ioctl(object, "disp scanoutpos size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version); - args->v0.vblanks = nv_rd32(priv, 0x680800 + hoff) & 0xffff; - args->v0.vtotal = nv_rd32(priv, 0x680804 + hoff) & 0xffff; - args->v0.vblanke = args->v0.vtotal - 1; - - args->v0.hblanks = nv_rd32(priv, 0x680820 + hoff) & 0xffff; - args->v0.htotal = nv_rd32(priv, 0x680824 + hoff) & 0xffff; - args->v0.hblanke = args->v0.htotal - 1; - - /* - * If output is vga instead of digital then vtotal/htotal is - * invalid so we have to give up and trigger the timestamping - * fallback in the drm core. - */ - if (!args->v0.vtotal || !args->v0.htotal) - return -ENOTSUPP; - - args->v0.time[0] = ktime_to_ns(ktime_get()); - line = nv_rd32(priv, 0x600868 + hoff); - args->v0.time[1] = ktime_to_ns(ktime_get()); - args->v0.hline = (line & 0xffff0000) >> 16; - args->v0.vline = (line & 0x0000ffff); - } else - return ret; - - return 0; + return &nv04_disp_root_oclass; } -static int -nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - union { - struct nv04_disp_mthd_v0 v0; - } *args = data; - struct nv04_disp_priv *priv = (void *)object->engine; - int head, ret; - - nv_ioctl(object, "disp mthd size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", - args->v0.version, args->v0.method, args->v0.head); - mthd = args->v0.method; - head = args->v0.head; - } else - return ret; - - if (head < 0 || head >= 2) - return -ENXIO; - - switch (mthd) { - case NV04_DISP_SCANOUTPOS: - return nv04_disp_scanoutpos(object, priv, data, size, head); - default: - break; - } - - return -EINVAL; -} - -static struct nvkm_ofuncs -nv04_disp_ofuncs = { - .ctor = _nvkm_object_ctor, - .dtor = nvkm_object_destroy, - .init = nvkm_object_init, - .fini = nvkm_object_fini, - .mthd = nv04_disp_mthd, - .ntfy = nvkm_disp_ntfy, -}; - -static struct nvkm_oclass -nv04_disp_sclass[] = { - { NV04_DISP, &nv04_disp_ofuncs }, - {}, -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - static void -nv04_disp_vblank_init(struct nvkm_event *event, int type, int head) +nv04_disp_vblank_init(struct nvkm_disp *disp, int head) { - struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); - nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000001); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head * 0x2000) , 0x00000001); } static void -nv04_disp_vblank_fini(struct nvkm_event *event, int type, int head) +nv04_disp_vblank_fini(struct nvkm_disp *disp, int head) { - struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); - nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000000); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head * 0x2000) , 0x00000000); } -static const struct nvkm_event_func -nv04_disp_vblank_func = { - .ctor = nvkm_disp_vblank_ctor, - .init = nv04_disp_vblank_init, - .fini = nv04_disp_vblank_fini, -}; - static void -nv04_disp_intr(struct nvkm_subdev *subdev) +nv04_disp_intr(struct nvkm_disp *disp) { - struct nv04_disp_priv *priv = (void *)subdev; - u32 crtc0 = nv_rd32(priv, 0x600100); - u32 crtc1 = nv_rd32(priv, 0x602100); + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + u32 crtc0 = nvkm_rd32(device, 0x600100); + u32 crtc1 = nvkm_rd32(device, 0x602100); u32 pvideo; if (crtc0 & 0x00000001) { - nvkm_disp_vblank(&priv->base, 0); - nv_wr32(priv, 0x600100, 0x00000001); + nvkm_disp_vblank(disp, 0); + nvkm_wr32(device, 0x600100, 0x00000001); } if (crtc1 & 0x00000001) { - nvkm_disp_vblank(&priv->base, 1); - nv_wr32(priv, 0x602100, 0x00000001); + nvkm_disp_vblank(disp, 1); + nvkm_wr32(device, 0x602100, 0x00000001); } - if (nv_device(priv)->chipset >= 0x10 && - nv_device(priv)->chipset <= 0x40) { - pvideo = nv_rd32(priv, 0x8100); + if (device->chipset >= 0x10 && device->chipset <= 0x40) { + pvideo = nvkm_rd32(device, 0x8100); if (pvideo & ~0x11) - nv_info(priv, "PVIDEO intr: %08x\n", pvideo); - nv_wr32(priv, 0x8100, pvideo); + nvkm_info(subdev, "PVIDEO intr: %08x\n", pvideo); + nvkm_wr32(device, 0x8100, pvideo); } } -static int -nv04_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv04_disp_priv *priv; - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, 2, "DISPLAY", - "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_disp_func +nv04_disp = { + .intr = nv04_disp_intr, + .root = nv04_disp_root, + .head.vblank_init = nv04_disp_vblank_init, + .head.vblank_fini = nv04_disp_vblank_fini, +}; - nv_engine(priv)->sclass = nv04_disp_sclass; - nv_subdev(priv)->intr = nv04_disp_intr; - return 0; +int +nv04_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) +{ + return nvkm_disp_new_(&nv04_disp, device, index, 2, pdisp); } - -struct nvkm_oclass * -nv04_disp_oclass = &(struct nvkm_disp_impl) { - .base.handle = NV_ENGINE(DISP, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .vblank = &nv04_disp_vblank_func, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 8ba808df2..32e73a975 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -22,1291 +22,158 @@ * Authors: Ben Skeggs */ #include "nv50.h" -#include "outp.h" -#include "outpdp.h" +#include "rootnv50.h" #include -#include -#include #include -#include -#include -#include +#include #include -#include #include #include #include #include -#include -#include -#include -#include -#include - -/******************************************************************************* - * EVO channel base class - ******************************************************************************/ - -static int -nv50_disp_chan_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, int head, - int length, void **pobject) -{ - const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs; - struct nv50_disp_base *base = (void *)parent; - struct nv50_disp_chan *chan; - int chid = impl->chid + head; - int ret; - - if (base->chan & (1 << chid)) - return -EBUSY; - base->chan |= (1 << chid); - - ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL, - (1ULL << NVDEV_ENGINE_DMAOBJ), - length, pobject); - chan = *pobject; - if (ret) - return ret; - chan->chid = chid; - - nv_parent(chan)->object_attach = impl->attach; - nv_parent(chan)->object_detach = impl->detach; - return 0; -} - -static void -nv50_disp_chan_destroy(struct nv50_disp_chan *chan) -{ - struct nv50_disp_base *base = (void *)nv_object(chan)->parent; - base->chan &= ~(1 << chan->chid); - nvkm_namedb_destroy(&chan->base); -} - -static void -nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); - nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000000 << index); - nv_wr32(priv, 0x610020, 0x00000001 << index); -} - -static void -nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); - nv_wr32(priv, 0x610020, 0x00000001 << index); - nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000001 << index); -} - -void -nv50_disp_chan_uevent_send(struct nv50_disp_priv *priv, int chid) -{ - struct nvif_notify_uevent_rep { - } rep; - - nvkm_event_send(&priv->uevent, 1, chid, &rep, sizeof(rep)); -} - -int -nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nv50_disp_dmac *dmac = (void *)object; - union { - struct nvif_notify_uevent_req none; - } *args = data; - int ret; - - if (nvif_unvers(args->none)) { - notify->size = sizeof(struct nvif_notify_uevent_rep); - notify->types = 1; - notify->index = dmac->base.chid; - return 0; - } - - return ret; -} - -const struct nvkm_event_func -nv50_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = nv50_disp_chan_uevent_init, - .fini = nv50_disp_chan_uevent_fini, -}; - -int -nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **pevent) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - switch (type) { - case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: - *pevent = &priv->uevent; - return 0; - default: - break; - } - return -EINVAL; -} - -int -nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) +static const struct nvkm_disp_oclass * +nv50_disp_root_(struct nvkm_disp *base) { - struct nv50_disp_chan *chan = (void *)object; - *addr = nv_device_resource_start(nv_device(object), 0) + - 0x640000 + (chan->chid * 0x1000); - *size = 0x001000; - return 0; + return nv50_disp(base)->func->root; } -u32 -nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_chan *chan = (void *)object; - return nv_rd32(priv, 0x640000 + (chan->chid * 0x1000) + addr); -} - -void -nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_chan *chan = (void *)object; - nv_wr32(priv, 0x640000 + (chan->chid * 0x1000) + addr, data); -} - -/******************************************************************************* - * EVO DMA channel base class - ******************************************************************************/ - static int -nv50_disp_dmac_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 name) -{ - struct nv50_disp_base *base = (void *)parent->parent; - struct nv50_disp_chan *chan = (void *)parent; - u32 addr = nv_gpuobj(object)->node->offset; - u32 chid = chan->chid; - u32 data = (chid << 28) | (addr << 10) | chid; - return nvkm_ramht_insert(base->ramht, chid, name, data); -} - -static void -nv50_disp_dmac_object_detach(struct nvkm_object *parent, int cookie) +nv50_disp_outp_internal_crt_(struct nvkm_disp *base, int index, + struct dcb_output *dcb, struct nvkm_output **poutp) { - struct nv50_disp_base *base = (void *)parent->parent; - nvkm_ramht_remove(base->ramht, cookie); + struct nv50_disp *disp = nv50_disp(base); + return disp->func->outp.internal.crt(base, index, dcb, poutp); } static int -nv50_disp_dmac_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 pushbuf, int head, - int length, void **pobject) -{ - struct nv50_disp_dmac *dmac; - int ret; - - ret = nv50_disp_chan_create_(parent, engine, oclass, head, - length, pobject); - dmac = *pobject; - if (ret) - return ret; - - dmac->pushdma = (void *)nvkm_handle_ref(parent, pushbuf); - if (!dmac->pushdma) - return -ENOENT; - - switch (nv_mclass(dmac->pushdma)) { - case 0x0002: - case 0x003d: - if (dmac->pushdma->limit - dmac->pushdma->start != 0xfff) - return -EINVAL; - - switch (dmac->pushdma->target) { - case NV_MEM_TARGET_VRAM: - dmac->push = 0x00000001 | dmac->pushdma->start >> 8; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - dmac->push = 0x00000003 | dmac->pushdma->start >> 8; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -void -nv50_disp_dmac_dtor(struct nvkm_object *object) +nv50_disp_outp_internal_tmds_(struct nvkm_disp *base, int index, + struct dcb_output *dcb, + struct nvkm_output **poutp) { - struct nv50_disp_dmac *dmac = (void *)object; - nvkm_object_ref(NULL, (struct nvkm_object **)&dmac->pushdma); - nv50_disp_chan_destroy(&dmac->base); + struct nv50_disp *disp = nv50_disp(base); + return disp->func->outp.internal.tmds(base, index, dcb, poutp); } static int -nv50_disp_dmac_init(struct nvkm_object *object) +nv50_disp_outp_internal_lvds_(struct nvkm_disp *base, int index, + struct dcb_output *dcb, + struct nvkm_output **poutp) { - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; - int chid = dmac->base.chid; - int ret; - - ret = nv50_disp_chan_init(&dmac->base); - if (ret) - return ret; - - /* enable error reporting */ - nv_mask(priv, 0x610028, 0x00010000 << chid, 0x00010000 << chid); - - /* initialise channel for dma command submission */ - nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push); - nv_wr32(priv, 0x610208 + (chid * 0x0010), 0x00010000); - nv_wr32(priv, 0x61020c + (chid * 0x0010), chid); - nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010); - nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000); - nv_wr32(priv, 0x610200 + (chid * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x80000000, 0x00000000)) { - nv_error(dmac, "init timeout, 0x%08x\n", - nv_rd32(priv, 0x610200 + (chid * 0x10))); - return -EBUSY; - } - - return 0; + struct nv50_disp *disp = nv50_disp(base); + return disp->func->outp.internal.lvds(base, index, dcb, poutp); } static int -nv50_disp_dmac_fini(struct nvkm_object *object, bool suspend) +nv50_disp_outp_internal_dp_(struct nvkm_disp *base, int index, + struct dcb_output *dcb, struct nvkm_output **poutp) { - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *dmac = (void *)object; - int chid = dmac->base.chid; - - /* deactivate channel */ - nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000); - nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000); - if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x001e0000, 0x00000000)) { - nv_error(dmac, "fini timeout, 0x%08x\n", - nv_rd32(priv, 0x610200 + (chid * 0x10))); - if (suspend) - return -EBUSY; - } - - /* disable error reporting and completion notifications */ - nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid); - - return nv50_disp_chan_fini(&dmac->base, suspend); -} - -/******************************************************************************* - * EVO master channel object - ******************************************************************************/ - -static void -nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c, - const struct nv50_disp_mthd_list *list, int inst) -{ - struct nvkm_object *disp = nv_object(priv); - int i; - - for (i = 0; list->data[i].mthd; i++) { - if (list->data[i].addr) { - u32 next = nv_rd32(priv, list->data[i].addr + base + 0); - u32 prev = nv_rd32(priv, list->data[i].addr + base + c); - u32 mthd = list->data[i].mthd + (list->mthd * inst); - const char *name = list->data[i].name; - char mods[16]; - - if (prev != next) - snprintf(mods, sizeof(mods), "-> 0x%08x", next); - else - snprintf(mods, sizeof(mods), "%13c", ' '); - - nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n", - mthd, prev, mods, name ? " // " : "", - name ? name : ""); - } - } -} - -void -nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head, - const struct nv50_disp_mthd_chan *chan) -{ - struct nvkm_object *disp = nv_object(priv); - const struct nv50_disp_impl *impl = (void *)disp->oclass; - const struct nv50_disp_mthd_list *list; - int i, j; - - if (debug > nv_subdev(priv)->debug) - return; - - for (i = 0; (list = chan->data[i].mthd) != NULL; i++) { - u32 base = head * chan->addr; - for (j = 0; j < chan->data[i].nr; j++, base += list->addr) { - const char *cname = chan->name; - const char *sname = ""; - char cname_[16], sname_[16]; - - if (chan->addr) { - snprintf(cname_, sizeof(cname_), "%s %d", - chan->name, head); - cname = cname_; - } - - if (chan->data[i].nr > 1) { - snprintf(sname_, sizeof(sname_), " - %s %d", - chan->data[i].name, j); - sname = sname_; - } - - nv_printk_(disp, debug, "%s%s:\n", cname, sname); - nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev, - list, j); - } - } -} - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x610bb8 }, - { 0x0088, 0x610b9c }, - { 0x008c, 0x000000 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610828 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610b70 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_pior = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0700, 0x610b80 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - {} - } -}; - -static const struct nv50_disp_mthd_chan -nv50_disp_core_mthd_chan = { - .name = "Core", - .addr = 0x000000, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &nv50_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &nv50_disp_core_mthd_head }, - {} - } -}; - -int -nv50_disp_core_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_core_channel_dma_v0 v0; - } *args = data; - struct nv50_disp_dmac *mast; - int ret; - - nv_ioctl(parent, "create disp core channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create disp core channel dma vers %d " - "pushbuf %08x\n", - args->v0.version, args->v0.pushbuf); - } else - return ret; - - ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf, - 0, sizeof(*mast), (void **)&mast); - *pobject = nv_object(mast); - if (ret) - return ret; - - return 0; + struct nv50_disp *disp = nv50_disp(base); + if (disp->func->outp.internal.dp) + return disp->func->outp.internal.dp(base, index, dcb, poutp); + return -ENODEV; } static int -nv50_disp_core_init(struct nvkm_object *object) +nv50_disp_outp_external_tmds_(struct nvkm_disp *base, int index, + struct dcb_output *dcb, + struct nvkm_output **poutp) { - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; - int ret; - - ret = nv50_disp_chan_init(&mast->base); - if (ret) - return ret; - - /* enable error reporting */ - nv_mask(priv, 0x610028, 0x00010000, 0x00010000); - - /* attempt to unstick channel from some unknown state */ - if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000) - nv_mask(priv, 0x610200, 0x00800000, 0x00800000); - if ((nv_rd32(priv, 0x610200) & 0x003f0000) == 0x00030000) - nv_mask(priv, 0x610200, 0x00600000, 0x00600000); - - /* initialise channel for dma command submission */ - nv_wr32(priv, 0x610204, mast->push); - nv_wr32(priv, 0x610208, 0x00010000); - nv_wr32(priv, 0x61020c, 0x00000000); - nv_mask(priv, 0x610200, 0x00000010, 0x00000010); - nv_wr32(priv, 0x640000, 0x00000000); - nv_wr32(priv, 0x610200, 0x01000013); - - /* wait for it to go inactive */ - if (!nv_wait(priv, 0x610200, 0x80000000, 0x00000000)) { - nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610200)); - return -EBUSY; - } - - return 0; + struct nv50_disp *disp = nv50_disp(base); + if (disp->func->outp.external.tmds) + return disp->func->outp.external.tmds(base, index, dcb, poutp); + return -ENODEV; } static int -nv50_disp_core_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_dmac *mast = (void *)object; - - /* deactivate channel */ - nv_mask(priv, 0x610200, 0x00000010, 0x00000000); - nv_mask(priv, 0x610200, 0x00000003, 0x00000000); - if (!nv_wait(priv, 0x610200, 0x001e0000, 0x00000000)) { - nv_error(mast, "fini: 0x%08x\n", nv_rd32(priv, 0x610200)); - if (suspend) - return -EBUSY; - } - - /* disable error reporting and completion notifications */ - nv_mask(priv, 0x610028, 0x00010001, 0x00000000); - - return nv50_disp_chan_fini(&mast->base, suspend); -} - -struct nv50_disp_chan_impl -nv50_disp_core_ofuncs = { - .base.ctor = nv50_disp_core_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = nv50_disp_core_init, - .base.fini = nv50_disp_core_fini, - .base.map = nv50_disp_chan_map, - .base.ntfy = nv50_disp_chan_ntfy, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 0, - .attach = nv50_disp_dmac_object_attach, - .detach = nv50_disp_dmac_object_detach, -}; - -/******************************************************************************* - * EVO sync channel objects - ******************************************************************************/ - -static const struct nv50_disp_mthd_list -nv50_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x0100, 0x610894 }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_base_mthd_image = { - .mthd = 0x0400, - .addr = 0x000000, - .data = { - { 0x0800, 0x6108f0 }, - { 0x0804, 0x6108fc }, - { 0x0808, 0x61090c }, - { 0x080c, 0x610914 }, - { 0x0810, 0x610904 }, - {} - } -}; - -static const struct nv50_disp_mthd_chan -nv50_disp_base_mthd_chan = { - .name = "Base", - .addr = 0x000540, - .data = { - { "Global", 1, &nv50_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -nv50_disp_base_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_outp_external_dp_(struct nvkm_disp *base, int index, + struct dcb_output *dcb, struct nvkm_output **poutp) { - union { - struct nv50_disp_base_channel_dma_v0 v0; - } *args = data; - struct nv50_disp_priv *priv = (void *)engine; - struct nv50_disp_dmac *dmac; - int ret; - - nv_ioctl(parent, "create disp base channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create disp base channel dma vers %d " - "pushbuf %08x head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (args->v0.head > priv->head.nr) - return -EINVAL; - } else - return ret; - - ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf, - args->v0.head, sizeof(*dmac), - (void **)&dmac); - *pobject = nv_object(dmac); - if (ret) - return ret; - - return 0; + struct nv50_disp *disp = nv50_disp(base); + if (disp->func->outp.external.dp) + return disp->func->outp.external.dp(base, index, dcb, poutp); + return -ENODEV; } -struct nv50_disp_chan_impl -nv50_disp_base_ofuncs = { - .base.ctor = nv50_disp_base_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = nv50_disp_dmac_init, - .base.fini = nv50_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 1, - .attach = nv50_disp_dmac_object_attach, - .detach = nv50_disp_dmac_object_detach, -}; - -/******************************************************************************* - * EVO overlay channel objects - ******************************************************************************/ - -const struct nv50_disp_mthd_list -nv50_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0009a0 }, - { 0x0088, 0x0009c0 }, - { 0x008c, 0x0009c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_mthd_chan -nv50_disp_ovly_mthd_chan = { - .name = "Overlay", - .addr = 0x000540, - .data = { - { "Global", 1, &nv50_disp_ovly_mthd_base }, - {} - } -}; - -int -nv50_disp_ovly_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_channel_dma_v0 v0; - } *args = data; - struct nv50_disp_priv *priv = (void *)engine; - struct nv50_disp_dmac *dmac; - int ret; - - nv_ioctl(parent, "create disp overlay channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create disp overlay channel dma vers %d " - "pushbuf %08x head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (args->v0.head > priv->head.nr) - return -EINVAL; - } else - return ret; - - ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf, - args->v0.head, sizeof(*dmac), - (void **)&dmac); - *pobject = nv_object(dmac); - if (ret) - return ret; - - return 0; -} - -struct nv50_disp_chan_impl -nv50_disp_ovly_ofuncs = { - .base.ctor = nv50_disp_ovly_ctor, - .base.dtor = nv50_disp_dmac_dtor, - .base.init = nv50_disp_dmac_init, - .base.fini = nv50_disp_dmac_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 3, - .attach = nv50_disp_dmac_object_attach, - .detach = nv50_disp_dmac_object_detach, -}; - -/******************************************************************************* - * EVO PIO channel base class - ******************************************************************************/ - -static int -nv50_disp_pioc_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, int head, - int length, void **pobject) -{ - return nv50_disp_chan_create_(parent, engine, oclass, head, - length, pobject); -} - -void -nv50_disp_pioc_dtor(struct nvkm_object *object) -{ - struct nv50_disp_pioc *pioc = (void *)object; - nv50_disp_chan_destroy(&pioc->base); -} - -static int -nv50_disp_pioc_init(struct nvkm_object *object) +static void +nv50_disp_vblank_fini_(struct nvkm_disp *base, int head) { - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; - int chid = pioc->base.chid; - int ret; - - ret = nv50_disp_chan_init(&pioc->base); - if (ret) - return ret; - - nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00002000); - if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00000000, 0x00000000)) { - nv_error(pioc, "timeout0: 0x%08x\n", - nv_rd32(priv, 0x610200 + (chid * 0x10))); - return -EBUSY; - } - - nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00000001); - if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00010000)) { - nv_error(pioc, "timeout1: 0x%08x\n", - nv_rd32(priv, 0x610200 + (chid * 0x10))); - return -EBUSY; - } - - return 0; + struct nv50_disp *disp = nv50_disp(base); + disp->func->head.vblank_fini(disp, head); } -static int -nv50_disp_pioc_fini(struct nvkm_object *object, bool suspend) +static void +nv50_disp_vblank_init_(struct nvkm_disp *base, int head) { - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_pioc *pioc = (void *)object; - int chid = pioc->base.chid; - - nv_mask(priv, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000); - if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00000000)) { - nv_error(pioc, "timeout: 0x%08x\n", - nv_rd32(priv, 0x610200 + (chid * 0x10))); - if (suspend) - return -EBUSY; - } - - return nv50_disp_chan_fini(&pioc->base, suspend); + struct nv50_disp *disp = nv50_disp(base); + disp->func->head.vblank_init(disp, head); } -/******************************************************************************* - * EVO immediate overlay channel objects - ******************************************************************************/ - -int -nv50_disp_oimm_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void +nv50_disp_intr_(struct nvkm_disp *base) { - union { - struct nv50_disp_overlay_v0 v0; - } *args = data; - struct nv50_disp_priv *priv = (void *)engine; - struct nv50_disp_pioc *pioc; - int ret; - - nv_ioctl(parent, "create disp overlay size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create disp overlay vers %d head %d\n", - args->v0.version, args->v0.head); - if (args->v0.head > priv->head.nr) - return -EINVAL; - } else - return ret; - - ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head, - sizeof(*pioc), (void **)&pioc); - *pobject = nv_object(pioc); - if (ret) - return ret; - - return 0; + struct nv50_disp *disp = nv50_disp(base); + disp->func->intr(disp); } -struct nv50_disp_chan_impl -nv50_disp_oimm_ofuncs = { - .base.ctor = nv50_disp_oimm_ctor, - .base.dtor = nv50_disp_pioc_dtor, - .base.init = nv50_disp_pioc_init, - .base.fini = nv50_disp_pioc_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 5, -}; - -/******************************************************************************* - * EVO cursor channel objects - ******************************************************************************/ - -int -nv50_disp_curs_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void * +nv50_disp_dtor_(struct nvkm_disp *base) { - union { - struct nv50_disp_cursor_v0 v0; - } *args = data; - struct nv50_disp_priv *priv = (void *)engine; - struct nv50_disp_pioc *pioc; - int ret; - - nv_ioctl(parent, "create disp cursor size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create disp cursor vers %d head %d\n", - args->v0.version, args->v0.head); - if (args->v0.head > priv->head.nr) - return -EINVAL; - } else - return ret; - - ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head, - sizeof(*pioc), (void **)&pioc); - *pobject = nv_object(pioc); - if (ret) - return ret; - - return 0; + struct nv50_disp *disp = nv50_disp(base); + nvkm_event_fini(&disp->uevent); + return disp; } -struct nv50_disp_chan_impl -nv50_disp_curs_ofuncs = { - .base.ctor = nv50_disp_curs_ctor, - .base.dtor = nv50_disp_pioc_dtor, - .base.init = nv50_disp_pioc_init, - .base.fini = nv50_disp_pioc_fini, - .base.ntfy = nv50_disp_chan_ntfy, - .base.map = nv50_disp_chan_map, - .base.rd32 = nv50_disp_chan_rd32, - .base.wr32 = nv50_disp_chan_wr32, - .chid = 7, +static const struct nvkm_disp_func +nv50_disp_ = { + .dtor = nv50_disp_dtor_, + .intr = nv50_disp_intr_, + .root = nv50_disp_root_, + .outp.internal.crt = nv50_disp_outp_internal_crt_, + .outp.internal.tmds = nv50_disp_outp_internal_tmds_, + .outp.internal.lvds = nv50_disp_outp_internal_lvds_, + .outp.internal.dp = nv50_disp_outp_internal_dp_, + .outp.external.tmds = nv50_disp_outp_external_tmds_, + .outp.external.dp = nv50_disp_outp_external_dp_, + .head.vblank_init = nv50_disp_vblank_init_, + .head.vblank_fini = nv50_disp_vblank_fini_, }; -/******************************************************************************* - * Base display object - ******************************************************************************/ - int -nv50_disp_main_scanoutpos(NV50_DISP_MTHD_V0) +nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, + int index, int heads, struct nvkm_disp **pdisp) { - const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540)); - const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540)); - const u32 total = nv_rd32(priv, 0x610afc + (head * 0x540)); - union { - struct nv04_disp_scanoutpos_v0 v0; - } *args = data; + struct nv50_disp *disp; int ret; - nv_ioctl(object, "disp scanoutpos size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version); - args->v0.vblanke = (blanke & 0xffff0000) >> 16; - args->v0.hblanke = (blanke & 0x0000ffff); - args->v0.vblanks = (blanks & 0xffff0000) >> 16; - args->v0.hblanks = (blanks & 0x0000ffff); - args->v0.vtotal = ( total & 0xffff0000) >> 16; - args->v0.htotal = ( total & 0x0000ffff); - args->v0.time[0] = ktime_to_ns(ktime_get()); - args->v0.vline = /* vline read locks hline */ - nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff; - args->v0.time[1] = ktime_to_ns(ktime_get()); - args->v0.hline = - nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff; - } else - return ret; - - return 0; -} - -int -nv50_disp_main_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine); - union { - struct nv50_disp_mthd_v0 v0; - struct nv50_disp_mthd_v1 v1; - } *args = data; - struct nv50_disp_priv *priv = (void *)object->engine; - struct nvkm_output *outp = NULL; - struct nvkm_output *temp; - u16 type, mask = 0; - int head, ret; - - if (mthd != NV50_DISP_MTHD) - return -EINVAL; - - nv_ioctl(object, "disp mthd size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", - args->v0.version, args->v0.method, args->v0.head); - mthd = args->v0.method; - head = args->v0.head; - } else - if (nvif_unpack(args->v1, 1, 1, true)) { - nv_ioctl(object, "disp mthd vers %d mthd %02x " - "type %04x mask %04x\n", - args->v1.version, args->v1.method, - args->v1.hasht, args->v1.hashm); - mthd = args->v1.method; - type = args->v1.hasht; - mask = args->v1.hashm; - head = ffs((mask >> 8) & 0x0f) - 1; - } else - return ret; - - if (head < 0 || head >= priv->head.nr) - return -ENXIO; - - if (mask) { - list_for_each_entry(temp, &priv->base.outp, head) { - if ((temp->info.hasht == type) && - (temp->info.hashm & mask) == mask) { - outp = temp; - break; - } - } - if (outp == NULL) - return -ENXIO; - } - - switch (mthd) { - case NV50_DISP_SCANOUTPOS: - return impl->head.scanoutpos(object, priv, data, size, head); - default: - break; - } - - switch (mthd * !!outp) { - case NV50_DISP_MTHD_V1_DAC_PWR: - return priv->dac.power(object, priv, data, size, head, outp); - case NV50_DISP_MTHD_V1_DAC_LOAD: - return priv->dac.sense(object, priv, data, size, head, outp); - case NV50_DISP_MTHD_V1_SOR_PWR: - return priv->sor.power(object, priv, data, size, head, outp); - case NV50_DISP_MTHD_V1_SOR_HDA_ELD: - if (!priv->sor.hda_eld) - return -ENODEV; - return priv->sor.hda_eld(object, priv, data, size, head, outp); - case NV50_DISP_MTHD_V1_SOR_HDMI_PWR: - if (!priv->sor.hdmi) - return -ENODEV; - return priv->sor.hdmi(object, priv, data, size, head, outp); - case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: { - union { - struct nv50_disp_sor_lvds_script_v0 v0; - } *args = data; - nv_ioctl(object, "disp sor lvds script size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor lvds script " - "vers %d name %04x\n", - args->v0.version, args->v0.script); - priv->sor.lvdsconf = args->v0.script; - return 0; - } else - return ret; - } - break; - case NV50_DISP_MTHD_V1_SOR_DP_PWR: { - struct nvkm_output_dp *outpdp = (void *)outp; - union { - struct nv50_disp_sor_dp_pwr_v0 v0; - } *args = data; - nv_ioctl(object, "disp sor dp pwr size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor dp pwr vers %d state %d\n", - args->v0.version, args->v0.state); - if (args->v0.state == 0) { - nvkm_notify_put(&outpdp->irq); - ((struct nvkm_output_dp_impl *)nv_oclass(outp)) - ->lnk_pwr(outpdp, 0); - atomic_set(&outpdp->lt.done, 0); - return 0; - } else - if (args->v0.state != 0) { - nvkm_output_dp_train(&outpdp->base, 0, true); - return 0; - } - } else - return ret; - } - break; - case NV50_DISP_MTHD_V1_PIOR_PWR: - if (!priv->pior.power) - return -ENODEV; - return priv->pior.power(object, priv, data, size, head, outp); - default: - break; - } - - return -EINVAL; -} - -int -nv50_disp_main_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_disp_priv *priv = (void *)engine; - struct nv50_disp_base *base; - int ret; + if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL))) + return -ENOMEM; + INIT_WORK(&disp->supervisor, func->super); + disp->func = func; + *pdisp = &disp->base; - ret = nvkm_parent_create(parent, engine, oclass, 0, - priv->sclass, 0, &base); - *pobject = nv_object(base); + ret = nvkm_disp_ctor(&nv50_disp_, device, index, heads, &disp->base); if (ret) return ret; - return nvkm_ramht_new(nv_object(base), nv_object(base), 0x1000, 0, - &base->ramht); + return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent); } void -nv50_disp_main_dtor(struct nvkm_object *object) -{ - struct nv50_disp_base *base = (void *)object; - nvkm_ramht_ref(NULL, &base->ramht); - nvkm_parent_destroy(&base->base); -} - -static int -nv50_disp_main_init(struct nvkm_object *object) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_base *base = (void *)object; - int ret, i; - u32 tmp; - - ret = nvkm_parent_init(&base->base); - if (ret) - return ret; - - /* 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 = nv_rd32(priv, 0x614004); - nv_wr32(priv, 0x610184, tmp); - - /* ... CRTC caps */ - for (i = 0; i < priv->head.nr; i++) { - tmp = nv_rd32(priv, 0x616100 + (i * 0x800)); - nv_wr32(priv, 0x610190 + (i * 0x10), tmp); - tmp = nv_rd32(priv, 0x616104 + (i * 0x800)); - nv_wr32(priv, 0x610194 + (i * 0x10), tmp); - tmp = nv_rd32(priv, 0x616108 + (i * 0x800)); - nv_wr32(priv, 0x610198 + (i * 0x10), tmp); - tmp = nv_rd32(priv, 0x61610c + (i * 0x800)); - nv_wr32(priv, 0x61019c + (i * 0x10), tmp); - } - - /* ... DAC caps */ - for (i = 0; i < priv->dac.nr; i++) { - tmp = nv_rd32(priv, 0x61a000 + (i * 0x800)); - nv_wr32(priv, 0x6101d0 + (i * 0x04), tmp); - } - - /* ... SOR caps */ - for (i = 0; i < priv->sor.nr; i++) { - tmp = nv_rd32(priv, 0x61c000 + (i * 0x800)); - nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp); - } - - /* ... PIOR caps */ - for (i = 0; i < priv->pior.nr; i++) { - tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); - nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); - } - - /* steal display away from vbios, or something like that */ - if (nv_rd32(priv, 0x610024) & 0x00000100) { - nv_wr32(priv, 0x610024, 0x00000100); - nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000); - if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) { - nv_error(priv, "timeout acquiring display\n"); - return -EBUSY; - } - } - - /* point at display engine memory area (hash table, objects) */ - nv_wr32(priv, 0x610010, (nv_gpuobj(base->ramht)->addr >> 8) | 9); - - /* enable supervisor interrupts, disable everything else */ - nv_wr32(priv, 0x61002c, 0x00000370); - nv_wr32(priv, 0x610028, 0x00000000); - return 0; -} - -static int -nv50_disp_main_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - struct nv50_disp_base *base = (void *)object; - - /* disable all interrupts */ - nv_wr32(priv, 0x610024, 0x00000000); - nv_wr32(priv, 0x610020, 0x00000000); - - return nvkm_parent_fini(&base->base, suspend); -} - -struct nvkm_ofuncs -nv50_disp_main_ofuncs = { - .ctor = nv50_disp_main_ctor, - .dtor = nv50_disp_main_dtor, - .init = nv50_disp_main_init, - .fini = nv50_disp_main_fini, - .mthd = nv50_disp_main_mthd, - .ntfy = nvkm_disp_ntfy, -}; - -static struct nvkm_oclass -nv50_disp_main_oclass[] = { - { NV50_DISP, &nv50_disp_main_ofuncs }, - {} -}; - -static struct nvkm_oclass -nv50_disp_sclass[] = { - { NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base }, - { NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base }, - { NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base }, - { NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base }, - { NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base }, - {} -}; - -/******************************************************************************* - * Display context, tracks instmem allocation and prevents more than one - * client using the display hardware at any time. - ******************************************************************************/ - -static int -nv50_disp_data_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_disp_priv *priv = (void *)engine; - struct nvkm_engctx *ectx; - int ret = -EBUSY; - - /* no context needed for channel objects... */ - if (nv_mclass(parent) != NV_DEVICE) { - atomic_inc(&parent->refcount); - *pobject = parent; - return 1; - } - - /* allocate display hardware to client */ - mutex_lock(&nv_subdev(priv)->mutex); - if (list_empty(&nv_engine(priv)->contexts)) { - ret = nvkm_engctx_create(parent, engine, oclass, NULL, 0x10000, - 0x10000, NVOBJ_FLAG_HEAP, &ectx); - *pobject = nv_object(ectx); - } - mutex_unlock(&nv_subdev(priv)->mutex); - return ret; -} - -struct nvkm_oclass -nv50_disp_cclass = { - .handle = NV_ENGCTX(DISP, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_disp_data_ctor, - .dtor = _nvkm_engctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - .rd32 = _nvkm_engctx_rd32, - .wr32 = _nvkm_engctx_wr32, - }, -}; - -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static void -nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head) +nv50_disp_vblank_fini(struct nv50_disp *disp, int head) { - struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); - nv_mask(disp, 0x61002c, (4 << head), 0); + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_mask(device, 0x61002c, (4 << head), 0); } -static void -nv50_disp_vblank_init(struct nvkm_event *event, int type, int head) +void +nv50_disp_vblank_init(struct nv50_disp *disp, int head) { - struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank); - nv_mask(disp, 0x61002c, (4 << head), (4 << head)); + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_mask(device, 0x61002c, (4 << head), (4 << head)); } -const struct nvkm_event_func -nv50_disp_vblank_func = { - .ctor = nvkm_disp_vblank_ctor, - .init = nv50_disp_vblank_init, - .fini = nv50_disp_vblank_fini, -}; - static const struct nvkm_enum nv50_disp_intr_error_type[] = { { 3, "ILLEGAL_MTHD" }, @@ -1323,70 +190,46 @@ nv50_disp_intr_error_code[] = { }; static void -nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid) +nv50_disp_intr_error(struct nv50_disp *disp, int chid) { - struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass; - u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08)); - u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08)); + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08)); + u32 addr = nvkm_rd32(device, 0x610080 + (chid * 0x08)); u32 code = (addr & 0x00ff0000) >> 16; u32 type = (addr & 0x00007000) >> 12; u32 mthd = (addr & 0x00000ffc); const struct nvkm_enum *ec, *et; - char ecunk[6], etunk[6]; et = nvkm_enum_find(nv50_disp_intr_error_type, type); - if (!et) - snprintf(etunk, sizeof(etunk), "UNK%02X", type); - ec = nvkm_enum_find(nv50_disp_intr_error_code, code); - if (!ec) - snprintf(ecunk, sizeof(ecunk), "UNK%02X", code); - nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n", - et ? et->name : etunk, ec ? ec->name : ecunk, - chid, mthd, data); + nvkm_error(subdev, + "ERROR %d [%s] %02x [%s] chid %d mthd %04x data %08x\n", + type, et ? et->name : "", code, ec ? ec->name : "", + chid, mthd, data); - if (chid == 0) { - switch (mthd) { - case 0x0080: - nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0, - impl->mthd.core); - break; - default: - break; - } - } else - if (chid <= 2) { - switch (mthd) { - case 0x0080: - nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1, - impl->mthd.base); - break; - default: - break; - } - } else - if (chid <= 4) { + if (chid < ARRAY_SIZE(disp->chan)) { switch (mthd) { case 0x0080: - nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3, - impl->mthd.ovly); + nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR); break; default: break; } } - nv_wr32(priv, 0x610020, 0x00010000 << chid); - nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000); + nvkm_wr32(device, 0x610020, 0x00010000 << chid); + nvkm_wr32(device, 0x610080 + (chid * 0x08), 0x90000000); } static struct nvkm_output * -exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, +exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl, u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *info) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvkm_output *outp; u16 mask, type; @@ -1403,7 +246,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break; case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; default: - nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); + nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl); return NULL; } or -= 4; @@ -1412,9 +255,9 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, type = 0x0010; mask = 0; switch (ctrl & 0x00000f00) { - case 0x00000000: type |= priv->pior.type[or]; break; + case 0x00000000: type |= disp->pior.type[or]; break; default: - nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl); + nvkm_error(subdev, "unknown PIOR mc %08x\n", ctrl); return NULL; } } @@ -1423,7 +266,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, mask |= 0x0001 << or; mask |= 0x0100 << head; - list_for_each_entry(outp, &priv->base.outp, head) { + list_for_each_entry(outp, &disp->base.outp, head) { if ((outp->info.hasht & 0xff) == type && (outp->info.hashm & mask) == mask) { *data = nvbios_outp_match(bios, outp->info.hasht, @@ -1439,9 +282,11 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, } static struct nvkm_output * -exec_script(struct nv50_disp_priv *priv, int head, int id) +exec_script(struct nv50_disp *disp, int head, int id) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct nvkm_output *outp; struct nvbios_outp info; u8 ver, hdr, cnt, len; @@ -1450,27 +295,27 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) int i; /* DAC */ - for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++) - ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); + for (i = 0; !(ctrl & (1 << head)) && i < disp->func->dac.nr; i++) + ctrl = nvkm_rd32(device, 0x610b5c + (i * 8)); /* SOR */ if (!(ctrl & (1 << head))) { - if (nv_device(priv)->chipset < 0x90 || - nv_device(priv)->chipset == 0x92 || - nv_device(priv)->chipset == 0xa0) { + if (device->chipset < 0x90 || + device->chipset == 0x92 || + device->chipset == 0xa0) { reg = 0x610b74; } else { reg = 0x610798; } - for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++) - ctrl = nv_rd32(priv, reg + (i * 8)); + for (i = 0; !(ctrl & (1 << head)) && i < disp->func->sor.nr; i++) + ctrl = nvkm_rd32(device, reg + (i * 8)); i += 4; } /* PIOR */ if (!(ctrl & (1 << head))) { - for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++) - ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); + for (i = 0; !(ctrl & (1 << head)) && i < disp->func->pior.nr; i++) + ctrl = nvkm_rd32(device, 0x610b84 + (i * 8)); i += 8; } @@ -1478,10 +323,10 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) return NULL; i--; - outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info); + outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info); if (outp) { struct nvbios_init init = { - .subdev = nv_subdev(priv), + .subdev = subdev, .bios = bios, .offset = info.script[id], .outp = &outp->info, @@ -1496,9 +341,11 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) } static struct nvkm_output * -exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) +exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct nvkm_output *outp; struct nvbios_outp info1; struct nvbios_ocfg info2; @@ -1508,27 +355,27 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) int i; /* DAC */ - for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++) - ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); + for (i = 0; !(ctrl & (1 << head)) && i < disp->func->dac.nr; i++) + ctrl = nvkm_rd32(device, 0x610b58 + (i * 8)); /* SOR */ if (!(ctrl & (1 << head))) { - if (nv_device(priv)->chipset < 0x90 || - nv_device(priv)->chipset == 0x92 || - nv_device(priv)->chipset == 0xa0) { + if (device->chipset < 0x90 || + device->chipset == 0x92 || + device->chipset == 0xa0) { reg = 0x610b70; } else { reg = 0x610794; } - for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++) - ctrl = nv_rd32(priv, reg + (i * 8)); + for (i = 0; !(ctrl & (1 << head)) && i < disp->func->sor.nr; i++) + ctrl = nvkm_rd32(device, reg + (i * 8)); i += 4; } /* PIOR */ if (!(ctrl & (1 << head))) { - for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++) - ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); + for (i = 0; !(ctrl & (1 << head)) && i < disp->func->pior.nr; i++) + ctrl = nvkm_rd32(device, 0x610b80 + (i * 8)); i += 8; } @@ -1536,7 +383,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) return NULL; i--; - outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); + outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); if (!outp) return NULL; @@ -1548,7 +395,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) *conf |= 0x0100; break; case DCB_OUTPUT_LVDS: - *conf = priv->sor.lvdsconf; + *conf = disp->sor.lvdsconf; break; case DCB_OUTPUT_DP: *conf = (ctrl & 0x00000f00) >> 8; @@ -1568,7 +415,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); if (data) { struct nvbios_init init = { - .subdev = nv_subdev(priv), + .subdev = subdev, .bios = bios, .offset = data, .outp = &outp->info, @@ -1584,15 +431,16 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) } static void -nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head) { - exec_script(priv, head, 1); + exec_script(disp, head, 1); } static void -nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head) { - struct nvkm_output *outp = exec_script(priv, head, 2); + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_output *outp = exec_script(disp, head, 2); /* the binary driver does this outside of the supervisor handling * (after the third supervisor from a detach). we (currently?) @@ -1608,10 +456,10 @@ nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) * in a blank screen (SOR_PWR off/on can restore it) */ if (outp && outp->info.type == DCB_OUTPUT_DP) { - struct nvkm_output_dp *outpdp = (void *)outp; + struct nvkm_output_dp *outpdp = nvkm_output_dp(outp); struct nvbios_init init = { - .subdev = nv_subdev(priv), - .bios = nvkm_bios(priv), + .subdev = subdev, + .bios = subdev->device->bios, .outp = &outp->info, .crtc = head, .offset = outpdp->info.script[4], @@ -1624,29 +472,32 @@ nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) } static void -nv50_disp_intr_unk20_1(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk20_1(struct nv50_disp *disp, int head) { - struct nvkm_devinit *devinit = nvkm_devinit(priv); - u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_devinit *devinit = device->devinit; + u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff; if (pclk) - devinit->pll_set(devinit, PLL_VPLL0 + head, pclk); + nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk); } static void -nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, int head, +nv50_disp_intr_unk20_2_dp(struct nv50_disp *disp, int head, struct dcb_output *outp, u32 pclk) { + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; const int link = !(outp->sorconf.link & 1); const int or = ffs(outp->or) - 1; const u32 soff = ( or * 0x800); const u32 loff = (link * 0x080) + soff; - const u32 ctrl = nv_rd32(priv, 0x610794 + (or * 8)); + const u32 ctrl = nvkm_rd32(device, 0x610794 + (or * 8)); const u32 symbol = 100000; - const s32 vactive = nv_rd32(priv, 0x610af8 + (head * 0x540)) & 0xffff; - const s32 vblanke = nv_rd32(priv, 0x610ae8 + (head * 0x540)) & 0xffff; - const s32 vblanks = nv_rd32(priv, 0x610af0 + (head * 0x540)) & 0xffff; - u32 dpctrl = nv_rd32(priv, 0x61c10c + loff); - u32 clksor = nv_rd32(priv, 0x614300 + soff); + const s32 vactive = nvkm_rd32(device, 0x610af8 + (head * 0x540)) & 0xffff; + const s32 vblanke = nvkm_rd32(device, 0x610ae8 + (head * 0x540)) & 0xffff; + const s32 vblanks = nvkm_rd32(device, 0x610af0 + (head * 0x540)) & 0xffff; + u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff); + u32 clksor = nvkm_rd32(device, 0x614300 + soff); int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; int TU, VTUi, VTUf, VTUa; u64 link_data_rate, link_ratio, unk; @@ -1662,14 +513,14 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, int head, value = value * link_bw; do_div(value, pclk); value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr); - nv_mask(priv, 0x61c1e8 + soff, 0x0000ffff, value); + nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, value); /* symbols/vblank - algorithm taken from comments in tegra driver */ value = vblanks - vblanke - 25; value = value * link_bw; do_div(value, pclk); value = value - ((36 / link_nr) + 3) - 1; - nv_mask(priv, 0x61c1ec + soff, 0x00ffffff, value); + nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, value); /* watermark / activesym */ if ((ctrl & 0xf0000) == 0x60000) bits = 30; @@ -1734,7 +585,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, int head, } if (!bestTU) { - nv_error(priv, "unable to find suitable dp config\n"); + nvkm_error(subdev, "unable to find suitable dp config\n"); return; } @@ -1745,22 +596,23 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, int head, do_div(unk, symbol); unk += 6; - nv_mask(priv, 0x61c10c + loff, 0x000001fc, bestTU << 2); - nv_mask(priv, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 | + nvkm_mask(device, 0x61c10c + loff, 0x000001fc, bestTU << 2); + nvkm_mask(device, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 | bestVTUf << 16 | bestVTUi << 8 | unk); } static void -nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head) { + struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_output *outp; - u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff; u32 hval, hreg = 0x614200 + (head * 0x800); u32 oval, oreg; u32 mask, conf; - outp = exec_clkcmp(priv, head, 0xff, pclk, &conf); + outp = exec_clkcmp(disp, head, 0xff, pclk, &conf); if (!outp) return; @@ -1787,10 +639,10 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) u32 ctrl, datarate; if (outp->info.location == 0) { - ctrl = nv_rd32(priv, 0x610794 + soff); + ctrl = nvkm_rd32(device, 0x610794 + soff); soff = 1; } else { - ctrl = nv_rd32(priv, 0x610b80 + soff); + ctrl = nvkm_rd32(device, 0x610b80 + soff); soff = 2; } @@ -1804,10 +656,10 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) } if (nvkm_output_dp_train(outp, datarate / soff, true)) - ERR("link not trained before attach\n"); + OUTP_ERR(outp, "link not trained before attach"); } - exec_clkcmp(priv, head, 0, pclk, &conf); + exec_clkcmp(disp, head, 0, pclk, &conf); if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) { oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800; @@ -1817,7 +669,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) } else if (!outp->info.location) { if (outp->info.type == DCB_OUTPUT_DP) - nv50_disp_intr_unk20_2_dp(priv, head, &outp->info, pclk); + nv50_disp_intr_unk20_2_dp(disp, head, &outp->info, pclk); oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800; oval = (conf & 0x0100) ? 0x00000101 : 0x00000000; hval = 0x00000000; @@ -1829,8 +681,8 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) mask = 0x00000707; } - nv_mask(priv, hreg, 0x0000000f, hval); - nv_mask(priv, oreg, mask, oval); + nvkm_mask(device, hreg, 0x0000000f, hval); + nvkm_mask(device, oreg, mask, oval); } /* If programming a TMDS output on a SOR that can also be configured for @@ -1842,10 +694,11 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) * programmed for DisplayPort. */ static void -nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, +nv50_disp_intr_unk40_0_tmds(struct nv50_disp *disp, struct dcb_output *outp) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_bios *bios = device->bios; const int link = !(outp->sorconf.link & 1); const int or = ffs(outp->or) - 1; const u32 loff = (or * 0x800) + (link * 0x80); @@ -1854,166 +707,136 @@ nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, u8 ver, hdr; if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match)) - nv_mask(priv, 0x61c10c + loff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c10c + loff, 0x00000001, 0x00000000); } static void -nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk40_0(struct nv50_disp *disp, int head) { + struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_output *outp; - u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff; u32 conf; - outp = exec_clkcmp(priv, head, 1, pclk, &conf); + outp = exec_clkcmp(disp, head, 1, pclk, &conf); if (!outp) return; if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS) - nv50_disp_intr_unk40_0_tmds(priv, &outp->info); + nv50_disp_intr_unk40_0_tmds(disp, &outp->info); } void nv50_disp_intr_supervisor(struct work_struct *work) { - struct nv50_disp_priv *priv = - container_of(work, struct nv50_disp_priv, supervisor); - struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass; - u32 super = nv_rd32(priv, 0x610030); + 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; + u32 super = nvkm_rd32(device, 0x610030); int head; - nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super); + nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super); - if (priv->super & 0x00000010) { - nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core); - for (head = 0; head < priv->head.nr; head++) { + if (disp->super & 0x00000010) { + nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); + for (head = 0; head < disp->base.head.nr; head++) { if (!(super & (0x00000020 << head))) continue; if (!(super & (0x00000080 << head))) continue; - nv50_disp_intr_unk10_0(priv, head); + nv50_disp_intr_unk10_0(disp, head); } } else - if (priv->super & 0x00000020) { - for (head = 0; head < priv->head.nr; head++) { + if (disp->super & 0x00000020) { + for (head = 0; head < disp->base.head.nr; head++) { if (!(super & (0x00000080 << head))) continue; - nv50_disp_intr_unk20_0(priv, head); + nv50_disp_intr_unk20_0(disp, head); } - for (head = 0; head < priv->head.nr; head++) { + for (head = 0; head < disp->base.head.nr; head++) { if (!(super & (0x00000200 << head))) continue; - nv50_disp_intr_unk20_1(priv, head); + nv50_disp_intr_unk20_1(disp, head); } - for (head = 0; head < priv->head.nr; head++) { + for (head = 0; head < disp->base.head.nr; head++) { if (!(super & (0x00000080 << head))) continue; - nv50_disp_intr_unk20_2(priv, head); + nv50_disp_intr_unk20_2(disp, head); } } else - if (priv->super & 0x00000040) { - for (head = 0; head < priv->head.nr; head++) { + if (disp->super & 0x00000040) { + for (head = 0; head < disp->base.head.nr; head++) { if (!(super & (0x00000080 << head))) continue; - nv50_disp_intr_unk40_0(priv, head); + nv50_disp_intr_unk40_0(disp, head); } } - nv_wr32(priv, 0x610030, 0x80000000); + nvkm_wr32(device, 0x610030, 0x80000000); } void -nv50_disp_intr(struct nvkm_subdev *subdev) +nv50_disp_intr(struct nv50_disp *disp) { - struct nv50_disp_priv *priv = (void *)subdev; - u32 intr0 = nv_rd32(priv, 0x610020); - u32 intr1 = nv_rd32(priv, 0x610024); + struct nvkm_device *device = disp->base.engine.subdev.device; + u32 intr0 = nvkm_rd32(device, 0x610020); + u32 intr1 = nvkm_rd32(device, 0x610024); while (intr0 & 0x001f0000) { u32 chid = __ffs(intr0 & 0x001f0000) - 16; - nv50_disp_intr_error(priv, chid); + nv50_disp_intr_error(disp, chid); intr0 &= ~(0x00010000 << chid); } while (intr0 & 0x0000001f) { u32 chid = __ffs(intr0 & 0x0000001f); - nv50_disp_chan_uevent_send(priv, chid); + nv50_disp_chan_uevent_send(disp, chid); intr0 &= ~(0x00000001 << chid); } if (intr1 & 0x00000004) { - nvkm_disp_vblank(&priv->base, 0); - nv_wr32(priv, 0x610024, 0x00000004); - intr1 &= ~0x00000004; + nvkm_disp_vblank(&disp->base, 0); + nvkm_wr32(device, 0x610024, 0x00000004); } if (intr1 & 0x00000008) { - nvkm_disp_vblank(&priv->base, 1); - nv_wr32(priv, 0x610024, 0x00000008); - intr1 &= ~0x00000008; + nvkm_disp_vblank(&disp->base, 1); + nvkm_wr32(device, 0x610024, 0x00000008); } if (intr1 & 0x00000070) { - priv->super = (intr1 & 0x00000070); - schedule_work(&priv->supervisor); - nv_wr32(priv, 0x610024, priv->super); - intr1 &= ~0x00000070; - } -} + disp->super = (intr1 & 0x00000070); + schedule_work(&disp->supervisor); + nvkm_wr32(device, 0x610024, disp->super); + } +} + +static const struct nv50_disp_func +nv50_disp = { + .intr = nv50_disp_intr, + .uevent = &nv50_disp_chan_uevent, + .super = nv50_disp_intr_supervisor, + .root = &nv50_disp_root_oclass, + .head.vblank_init = nv50_disp_vblank_init, + .head.vblank_fini = nv50_disp_vblank_fini, + .head.scanoutpos = nv50_disp_root_scanoutpos, + .outp.internal.crt = nv50_dac_output_new, + .outp.internal.tmds = nv50_sor_output_new, + .outp.internal.lvds = nv50_sor_output_new, + .outp.external.tmds = nv50_pior_output_new, + .outp.external.dp = nv50_pior_dp_new, + .dac.nr = 3, + .dac.power = nv50_dac_power, + .dac.sense = nv50_dac_sense, + .sor.nr = 2, + .sor.power = nv50_sor_power, + .pior.nr = 3, + .pior.power = nv50_pior_power, +}; -static int -nv50_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - struct nv50_disp_priv *priv; - int ret; - - ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP", - "display", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); - if (ret) - return ret; - - nv_engine(priv)->sclass = nv50_disp_main_oclass; - nv_engine(priv)->cclass = &nv50_disp_cclass; - nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); - priv->sclass = nv50_disp_sclass; - priv->head.nr = 2; - priv->dac.nr = 3; - priv->sor.nr = 2; - priv->pior.nr = 3; - priv->dac.power = nv50_dac_power; - priv->dac.sense = nv50_dac_sense; - priv->sor.power = nv50_sor_power; - priv->pior.power = nv50_pior_power; - return 0; + return nv50_disp_new_(&nv50_disp, device, index, 2, pdisp); } - -struct nvkm_oclass * -nv50_disp_outp_sclass[] = { - &nv50_pior_dp_impl.base.base, - NULL -}; - -struct nvkm_oclass * -nv50_disp_oclass = &(struct nv50_disp_impl) { - .base.base.handle = NV_ENGINE(DISP, 0x50), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_disp_ctor, - .dtor = _nvkm_disp_dtor, - .init = _nvkm_disp_init, - .fini = _nvkm_disp_fini, - }, - .base.vblank = &nv50_disp_vblank_func, - .base.outp = nv50_disp_outp_sclass, - .mthd.core = &nv50_disp_core_mthd_chan, - .mthd.base = &nv50_disp_base_mthd_chan, - .mthd.ovly = &nv50_disp_ovly_mthd_chan, - .mthd.prev = 0x000004, - .head.scanoutpos = nv50_disp_main_scanoutpos, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index b4ed62007..aecebd871 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -1,17 +1,18 @@ #ifndef __NV50_DISP_H__ #define __NV50_DISP_H__ +#define nv50_disp(p) container_of((p), struct nv50_disp, base) #include "priv.h" struct nvkm_output; struct nvkm_output_dp; #define NV50_DISP_MTHD_ struct nvkm_object *object, \ - struct nv50_disp_priv *priv, void *data, u32 size + struct nv50_disp *disp, void *data, u32 size #define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head #define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp -struct nv50_disp_priv { +struct nv50_disp { + const struct nv50_disp_func *func; struct nvkm_disp base; - struct nvkm_oclass *sclass; struct work_struct supervisor; u32 super; @@ -19,208 +20,98 @@ struct nv50_disp_priv { struct nvkm_event uevent; struct { - int nr; - } head; - struct { - int nr; - int (*power)(NV50_DISP_MTHD_V1); - int (*sense)(NV50_DISP_MTHD_V1); - } dac; - struct { - int nr; - int (*power)(NV50_DISP_MTHD_V1); - int (*hda_eld)(NV50_DISP_MTHD_V1); - int (*hdmi)(NV50_DISP_MTHD_V1); u32 lvdsconf; - void (*magic)(struct nvkm_output *); } sor; + struct { - int nr; - int (*power)(NV50_DISP_MTHD_V1); u8 type[3]; } pior; -}; -struct nv50_disp_impl { - struct nvkm_disp_impl base; - struct { - const struct nv50_disp_mthd_chan *core; - const struct nv50_disp_mthd_chan *base; - const struct nv50_disp_mthd_chan *ovly; - int prev; - } mthd; - struct { - int (*scanoutpos)(NV50_DISP_MTHD_V0); - } head; + struct nv50_disp_chan *chan[17]; }; -int nv50_disp_main_scanoutpos(NV50_DISP_MTHD_V0); -int nv50_disp_main_mthd(struct nvkm_object *, u32, void *, u32); +int nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0); -int gf110_disp_main_scanoutpos(NV50_DISP_MTHD_V0); +int gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0); int nv50_dac_power(NV50_DISP_MTHD_V1); int nv50_dac_sense(NV50_DISP_MTHD_V1); int gt215_hda_eld(NV50_DISP_MTHD_V1); -int gf110_hda_eld(NV50_DISP_MTHD_V1); +int gf119_hda_eld(NV50_DISP_MTHD_V1); int g84_hdmi_ctrl(NV50_DISP_MTHD_V1); int gt215_hdmi_ctrl(NV50_DISP_MTHD_V1); -int gf110_hdmi_ctrl(NV50_DISP_MTHD_V1); +int gf119_hdmi_ctrl(NV50_DISP_MTHD_V1); int gk104_hdmi_ctrl(NV50_DISP_MTHD_V1); int nv50_sor_power(NV50_DISP_MTHD_V1); int nv50_pior_power(NV50_DISP_MTHD_V1); -#include - -struct nv50_disp_base { - struct nvkm_parent base; - struct nvkm_ramht *ramht; - u32 chan; -}; - -struct nv50_disp_chan_impl { - struct nvkm_ofuncs base; - int chid; - int (*attach)(struct nvkm_object *, struct nvkm_object *, u32); - void (*detach)(struct nvkm_object *, int); +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 **); + +struct nv50_disp_func_outp { + int (* crt)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (* tv)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (*tmds)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (*lvds)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (* dp)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); }; -#include +struct nv50_disp_func { + void (*intr)(struct nv50_disp *); -struct nv50_disp_chan { - struct nvkm_namedb base; - int chid; -}; + const struct nvkm_event_func *uevent; + void (*super)(struct work_struct *); -int nv50_disp_chan_ntfy(struct nvkm_object *, u32, struct nvkm_event **); -int nv50_disp_chan_map(struct nvkm_object *, u64 *, u32 *); -u32 nv50_disp_chan_rd32(struct nvkm_object *, u64); -void nv50_disp_chan_wr32(struct nvkm_object *, u64, u32); -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_priv *, int); - -extern const struct nvkm_event_func gf110_disp_chan_uevent; - -#define nv50_disp_chan_init(a) \ - nvkm_namedb_init(&(a)->base) -#define nv50_disp_chan_fini(a,b) \ - nvkm_namedb_fini(&(a)->base, (b)) - -struct nv50_disp_dmac { - struct nv50_disp_chan base; - struct nvkm_dmaobj *pushdma; - u32 push; -}; + const struct nvkm_disp_oclass *root; -void nv50_disp_dmac_dtor(struct nvkm_object *); + struct { + void (*vblank_init)(struct nv50_disp *, int head); + void (*vblank_fini)(struct nv50_disp *, int head); + int (*scanoutpos)(NV50_DISP_MTHD_V0); + } head; -struct nv50_disp_pioc { - struct nv50_disp_chan base; -}; + struct { + const struct nv50_disp_func_outp internal; + const struct nv50_disp_func_outp external; + } outp; -void nv50_disp_pioc_dtor(struct nvkm_object *); + struct { + int nr; + int (*power)(NV50_DISP_MTHD_V1); + int (*sense)(NV50_DISP_MTHD_V1); + } dac; -struct nv50_disp_mthd_list { - u32 mthd; - u32 addr; struct { - u32 mthd; - u32 addr; - const char *name; - } data[]; -}; + int nr; + int (*power)(NV50_DISP_MTHD_V1); + int (*hda_eld)(NV50_DISP_MTHD_V1); + int (*hdmi)(NV50_DISP_MTHD_V1); + void (*magic)(struct nvkm_output *); + } sor; -struct nv50_disp_mthd_chan { - const char *name; - u32 addr; struct { - const char *name; int nr; - const struct nv50_disp_mthd_list *mthd; - } data[]; + int (*power)(NV50_DISP_MTHD_V1); + } pior; }; -extern struct nv50_disp_chan_impl nv50_disp_core_ofuncs; -int nv50_disp_core_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_pior; -extern struct nv50_disp_chan_impl nv50_disp_base_ofuncs; -int nv50_disp_base_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern const struct nv50_disp_mthd_list nv50_disp_base_mthd_image; -extern struct nv50_disp_chan_impl nv50_disp_ovly_ofuncs; -int nv50_disp_ovly_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base; -extern struct nv50_disp_chan_impl nv50_disp_oimm_ofuncs; -int nv50_disp_oimm_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nv50_disp_chan_impl nv50_disp_curs_ofuncs; -int nv50_disp_curs_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -extern struct nvkm_ofuncs nv50_disp_main_ofuncs; -int nv50_disp_main_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv50_disp_main_dtor(struct nvkm_object *); -extern struct nvkm_omthds nv50_disp_main_omthds[]; -extern struct nvkm_oclass nv50_disp_cclass; -void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head, - const struct nv50_disp_mthd_chan *); +void nv50_disp_vblank_init(struct nv50_disp *, int); +void nv50_disp_vblank_fini(struct nv50_disp *, int); +void nv50_disp_intr(struct nv50_disp *); void nv50_disp_intr_supervisor(struct work_struct *); -void nv50_disp_intr(struct nvkm_subdev *); -extern const struct nvkm_event_func nv50_disp_vblank_func; - -extern const struct nv50_disp_mthd_chan g84_disp_core_mthd_chan; -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_mthd_chan g84_disp_base_mthd_chan; -extern const struct nv50_disp_mthd_chan g84_disp_ovly_mthd_chan; - -extern const struct nv50_disp_mthd_chan g94_disp_core_mthd_chan; - -extern struct nv50_disp_chan_impl gf110_disp_core_ofuncs; -extern const struct nv50_disp_mthd_list gf110_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list gf110_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list gf110_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list gf110_disp_core_mthd_pior; -extern struct nv50_disp_chan_impl gf110_disp_base_ofuncs; -extern struct nv50_disp_chan_impl gf110_disp_ovly_ofuncs; -extern const struct nv50_disp_mthd_chan gf110_disp_base_mthd_chan; -extern struct nv50_disp_chan_impl gf110_disp_oimm_ofuncs; -extern struct nv50_disp_chan_impl gf110_disp_curs_ofuncs; -extern struct nvkm_ofuncs gf110_disp_main_ofuncs; -extern struct nvkm_oclass gf110_disp_cclass; -void gf110_disp_intr_supervisor(struct work_struct *); -void gf110_disp_intr(struct nvkm_subdev *); -extern const struct nvkm_event_func gf110_disp_vblank_func; - -extern const struct nv50_disp_mthd_chan gk104_disp_core_mthd_chan; -extern const struct nv50_disp_mthd_chan gk104_disp_ovly_mthd_chan; - -extern struct nvkm_output_dp_impl nv50_pior_dp_impl; -extern struct nvkm_oclass *nv50_disp_outp_sclass[]; - -extern struct nvkm_output_dp_impl g94_sor_dp_impl; -int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); -extern struct nvkm_oclass *g94_disp_outp_sclass[]; - -extern struct nvkm_output_dp_impl gf110_sor_dp_impl; -int gf110_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool); -extern struct nvkm_oclass *gf110_disp_outp_sclass[]; - -void gm204_sor_magic(struct nvkm_output *outp); -extern struct nvkm_output_dp_impl gm204_sor_dp_impl; + +void gf119_disp_vblank_init(struct nv50_disp *, int); +void gf119_disp_vblank_fini(struct nv50_disp *, int); +void gf119_disp_intr(struct nv50_disp *); +void gf119_disp_intr_supervisor(struct work_struct *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c new file mode 100644 index 000000000..54a4ae8d6 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c @@ -0,0 +1,37 @@ +/* + * 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 + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c new file mode 100644 index 000000000..c658db54a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c @@ -0,0 +1,37 @@ +/* + * 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 + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c new file mode 100644 index 000000000..b1fde8c12 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c @@ -0,0 +1,37 @@ +/* + * 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 + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c new file mode 100644 index 000000000..f4e7eb3d1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c @@ -0,0 +1,37 @@ +/* + * 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 + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c new file mode 100644 index 000000000..cd888a1e4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c @@ -0,0 +1,68 @@ +/* + * 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 + +#include +#include + +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 chid, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_overlay_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; + + nvif_ioctl(parent, "create disp overlay size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp overlay vers %d head %d\n", + args->v0.version, args->v0.head); + if (args->v0.head > disp->base.head.nr) + return -EINVAL; + head = args->v0.head; + } else + return ret; + + return nv50_disp_chan_new_(func, mthd, root, chid + 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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c index 9224bcbf0..bbe5ec0de 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c @@ -22,121 +22,66 @@ * Authors: Ben Skeggs */ #include "outp.h" -#include "priv.h" #include -#include #include #include -int -_nvkm_output_fini(struct nvkm_object *object, bool suspend) +void +nvkm_output_fini(struct nvkm_output *outp) { - struct nvkm_output *outp = (void *)object; - nv_ofuncs(outp->conn)->fini(nv_object(outp->conn), suspend); - return nvkm_object_fini(&outp->base, suspend); + if (outp->func->fini) + outp->func->fini(outp); } -int -_nvkm_output_init(struct nvkm_object *object) +void +nvkm_output_init(struct nvkm_output *outp) { - struct nvkm_output *outp = (void *)object; - int ret = nvkm_object_init(&outp->base); - if (ret == 0) - nv_ofuncs(outp->conn)->init(nv_object(outp->conn)); - return 0; + if (outp->func->init) + outp->func->init(outp); } void -_nvkm_output_dtor(struct nvkm_object *object) +nvkm_output_del(struct nvkm_output **poutp) { - struct nvkm_output *outp = (void *)object; - list_del(&outp->head); - nvkm_object_ref(NULL, (void *)&outp->conn); - nvkm_object_destroy(&outp->base); + struct nvkm_output *outp = *poutp; + if (outp && !WARN_ON(!outp->func)) { + if (outp->func->dtor) + *poutp = outp->func->dtor(outp); + kfree(*poutp); + *poutp = NULL; + } } -int -nvkm_output_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, - struct dcb_output *dcbE, int index, - int length, void **pobject) +void +nvkm_output_ctor(const struct nvkm_output_func *func, struct nvkm_disp *disp, + int index, struct dcb_output *dcbE, struct nvkm_output *outp) { - struct nvkm_disp *disp = nvkm_disp(parent); - struct nvkm_bios *bios = nvkm_bios(parent); - struct nvkm_i2c *i2c = nvkm_i2c(parent); - struct nvbios_connE connE; - struct nvkm_output *outp; - u8 ver, hdr; - u32 data; - int ret; + struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; - ret = nvkm_object_create_(parent, engine, oclass, 0, length, pobject); - outp = *pobject; - if (ret) - return ret; - - outp->info = *dcbE; + outp->func = func; + outp->disp = disp; outp->index = index; + outp->info = *dcbE; + outp->i2c = nvkm_i2c_bus_find(i2c, dcbE->i2c_index); outp->or = ffs(outp->info.or) - 1; - DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n", - dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ? - dcbE->sorconf.link : 0, dcbE->connector, dcbE->i2c_index, - dcbE->bus, dcbE->heads); - - if (outp->info.type != DCB_OUTPUT_DP) - outp->port = i2c->find(i2c, NV_I2C_PORT(outp->info.i2c_index)); - else - outp->port = i2c->find(i2c, NV_I2C_AUX(outp->info.i2c_index)); - outp->edid = outp->port; - - data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE); - if (!data) { - DBG("vbios connector data not found\n"); - memset(&connE, 0x00, sizeof(connE)); - connE.type = DCB_CONNECTOR_NONE; - } - - ret = nvkm_object_ctor(parent, NULL, nvkm_connector_oclass, - &connE, outp->info.connector, - (struct nvkm_object **)&outp->conn); - if (ret < 0) { - ERR("error %d creating connector, disabling\n", ret); - return ret; - } - - list_add_tail(&outp->head, &disp->outp); - return 0; + OUTP_DBG(outp, "type %02x loc %d or %d link %d con %x " + "edid %x bus %d head %x", + outp->info.type, outp->info.location, outp->info.or, + outp->info.type >= 2 ? outp->info.sorconf.link : 0, + outp->info.connector, outp->info.i2c_index, + outp->info.bus, outp->info.heads); } int -_nvkm_output_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *dcbE, u32 index, - struct nvkm_object **pobject) +nvkm_output_new_(const struct nvkm_output_func *func, + struct nvkm_disp *disp, int index, struct dcb_output *dcbE, + struct nvkm_output **poutp) { - struct nvkm_output *outp; - int ret; - - ret = nvkm_output_create(parent, engine, oclass, dcbE, index, &outp); - *pobject = nv_object(outp); - if (ret) - return ret; + if (!(*poutp = kzalloc(sizeof(**poutp), GFP_KERNEL))) + return -ENOMEM; + nvkm_output_ctor(func, disp, index, dcbE, *poutp); return 0; } - -struct nvkm_oclass * -nvkm_output_oclass = &(struct nvkm_output_impl) { - .base = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_output_ctor, - .dtor = _nvkm_output_dtor, - .init = _nvkm_output_init, - .fini = _nvkm_output_fini, - }, - }, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index d9253d26c..2590fec67 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -1,61 +1,55 @@ #ifndef __NVKM_DISP_OUTP_H__ #define __NVKM_DISP_OUTP_H__ -#include +#include #include #include struct nvkm_output { - struct nvkm_object base; - struct list_head head; - - struct dcb_output info; + const struct nvkm_output_func *func; + struct nvkm_disp *disp; int index; - int or; + struct dcb_output info; - struct nvkm_i2c_port *port; - struct nvkm_i2c_port *edid; + // whatever (if anything) is pointed at by the dcb device entry + struct nvkm_i2c_bus *i2c; + int or; + struct list_head head; struct nvkm_connector *conn; }; -#define nvkm_output_create(p,e,c,b,i,d) \ - nvkm_output_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) -#define nvkm_output_destroy(d) ({ \ - struct nvkm_output *_outp = (d); \ - _nvkm_output_dtor(nv_object(_outp)); \ -}) -#define nvkm_output_init(d) ({ \ - struct nvkm_output *_outp = (d); \ - _nvkm_output_init(nv_object(_outp)); \ -}) -#define nvkm_output_fini(d,s) ({ \ - struct nvkm_output *_outp = (d); \ - _nvkm_output_fini(nv_object(_outp), (s)); \ -}) - -int nvkm_output_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, struct dcb_output *, - int, int, void **); - -int _nvkm_output_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void _nvkm_output_dtor(struct nvkm_object *); -int _nvkm_output_init(struct nvkm_object *); -int _nvkm_output_fini(struct nvkm_object *, bool); - -struct nvkm_output_impl { - struct nvkm_oclass base; +struct nvkm_output_func { + void *(*dtor)(struct nvkm_output *); + void (*init)(struct nvkm_output *); + void (*fini)(struct nvkm_output *); }; -#ifndef MSG -#define MSG(l,f,a...) do { \ - struct nvkm_output *_outp = (void *)outp; \ - nv_##l(_outp, "%02x:%04x:%04x: "f, _outp->index, \ - _outp->info.hasht, _outp->info.hashm, ##a); \ +void nvkm_output_ctor(const struct nvkm_output_func *, struct nvkm_disp *, + int index, struct dcb_output *, struct nvkm_output *); +int nvkm_output_new_(const struct nvkm_output_func *, struct nvkm_disp *, + int index, struct dcb_output *, struct nvkm_output **); +void nvkm_output_del(struct nvkm_output **); +void nvkm_output_init(struct nvkm_output *); +void nvkm_output_fini(struct nvkm_output *); + +int nv50_dac_output_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int nv50_sor_output_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int nv50_pior_output_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); + +u32 g94_sor_dp_lane_map(struct nvkm_device *, u8 lane); + +void gm204_sor_magic(struct nvkm_output *outp); + +#define OUTP_MSG(o,l,f,a...) do { \ + struct nvkm_output *_outp = (o); \ + nvkm_##l(&_outp->disp->engine.subdev, "outp %02x:%04x:%04x: "f"\n", \ + _outp->index, _outp->info.hasht, _outp->info.hashm, ##a); \ } while(0) -#define DBG(f,a...) MSG(debug, f, ##a) -#define ERR(f,a...) MSG(error, f, ##a) -#endif +#define OUTP_ERR(o,f,a...) OUTP_MSG((o), error, f, ##a) +#define OUTP_DBG(o,f,a...) OUTP_MSG((o), debug, f, ##a) +#define OUTP_TRACE(o,f,a...) OUTP_MSG((o), trace, f, ##a) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c index 0bde0fa5b..3b7a9e7a1 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c @@ -33,16 +33,17 @@ int nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait) { - struct nvkm_output_dp *outp = (void *)base; + struct nvkm_output_dp *outp = nvkm_output_dp(base); bool retrain = true; u8 link[2], stat[3]; u32 linkrate; int ret, i; /* check that the link is trained at a high enough rate */ - ret = nv_rdaux(outp->base.edid, DPCD_LC00_LINK_BW_SET, link, 2); + ret = nvkm_rdaux(outp->aux, DPCD_LC00_LINK_BW_SET, link, 2); if (ret) { - DBG("failed to read link config, assuming no sink\n"); + OUTP_DBG(&outp->base, + "failed to read link config, assuming no sink"); goto done; } @@ -50,14 +51,15 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait) linkrate = (linkrate * 8) / 10; /* 8B/10B coding overhead */ datarate = (datarate + 9) / 10; /* -> decakilobits */ if (linkrate < datarate) { - DBG("link not trained at sufficient rate\n"); + OUTP_DBG(&outp->base, "link not trained at sufficient rate"); goto done; } /* check that link is still trained */ - ret = nv_rdaux(outp->base.edid, DPCD_LS02, stat, 3); + ret = nvkm_rdaux(outp->aux, DPCD_LS02, stat, 3); if (ret) { - DBG("failed to read link status, assuming no sink\n"); + OUTP_DBG(&outp->base, + "failed to read link status, assuming no sink"); goto done; } @@ -67,13 +69,14 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait) if (!(lane & DPCD_LS02_LANE0_CR_DONE) || !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) { - DBG("lane %d not equalised\n", lane); + OUTP_DBG(&outp->base, + "lane %d not equalised", lane); goto done; } } retrain = false; } else { - DBG("no inter-lane alignment\n"); + OUTP_DBG(&outp->base, "no inter-lane alignment"); } done: @@ -102,150 +105,138 @@ done: } static void -nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool present) +nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable) { - struct nvkm_i2c_port *port = outp->base.edid; - if (present) { + struct nvkm_i2c_aux *aux = outp->aux; + + if (enable) { if (!outp->present) { - nvkm_i2c(port)->acquire_pad(port, 0); - DBG("aux power -> always\n"); + OUTP_DBG(&outp->base, "aux power -> always"); + nvkm_i2c_aux_monitor(aux, true); outp->present = true; } - nvkm_output_dp_train(&outp->base, 0, true); - } else { - if (outp->present) { - nvkm_i2c(port)->release_pad(port); - DBG("aux power -> demand\n"); - outp->present = false; + + if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dpcd, + sizeof(outp->dpcd))) { + nvkm_output_dp_train(&outp->base, 0, true); + return; } - atomic_set(&outp->lt.done, 0); } -} -static void -nvkm_output_dp_detect(struct nvkm_output_dp *outp) -{ - struct nvkm_i2c_port *port = outp->base.edid; - int ret = nvkm_i2c(port)->acquire_pad(port, 0); - if (ret == 0) { - ret = nv_rdaux(outp->base.edid, DPCD_RC00_DPCD_REV, - outp->dpcd, sizeof(outp->dpcd)); - nvkm_output_dp_enable(outp, ret == 0); - nvkm_i2c(port)->release_pad(port); + if (outp->present) { + OUTP_DBG(&outp->base, "aux power -> demand"); + nvkm_i2c_aux_monitor(aux, false); + outp->present = false; } + + atomic_set(&outp->lt.done, 0); } static int nvkm_output_dp_hpd(struct nvkm_notify *notify) { - struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd); - struct nvkm_output_dp *outp; - struct nvkm_disp *disp = nvkm_disp(conn); const struct nvkm_i2c_ntfy_rep *line = notify->data; + struct nvkm_output_dp *outp = container_of(notify, typeof(*outp), hpd); + struct nvkm_connector *conn = outp->base.conn; + struct nvkm_disp *disp = outp->base.disp; struct nvif_notify_conn_rep_v0 rep = {}; - list_for_each_entry(outp, &disp->outp, base.head) { - if (outp->base.conn == conn && - outp->info.type == DCB_OUTPUT_DP) { - DBG("HPD: %d\n", line->mask); - nvkm_output_dp_detect(outp); + OUTP_DBG(&outp->base, "HPD: %d", line->mask); + nvkm_output_dp_enable(outp, true); - if (line->mask & NVKM_I2C_UNPLUG) - rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG; - if (line->mask & NVKM_I2C_PLUG) - rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG; + if (line->mask & NVKM_I2C_UNPLUG) + rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG; + if (line->mask & NVKM_I2C_PLUG) + rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG; - nvkm_event_send(&disp->hpd, rep.mask, conn->index, - &rep, sizeof(rep)); - return NVKM_NOTIFY_KEEP; - } - } - - WARN_ON(1); - return NVKM_NOTIFY_DROP; + nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep)); + return NVKM_NOTIFY_KEEP; } static int nvkm_output_dp_irq(struct nvkm_notify *notify) { - struct nvkm_output_dp *outp = container_of(notify, typeof(*outp), irq); - struct nvkm_disp *disp = nvkm_disp(outp); const struct nvkm_i2c_ntfy_rep *line = notify->data; + struct nvkm_output_dp *outp = container_of(notify, typeof(*outp), irq); + struct nvkm_connector *conn = outp->base.conn; + struct nvkm_disp *disp = outp->base.disp; struct nvif_notify_conn_rep_v0 rep = { .mask = NVIF_NOTIFY_CONN_V0_IRQ, }; - int index = outp->base.info.connector; - DBG("IRQ: %d\n", line->mask); + OUTP_DBG(&outp->base, "IRQ: %d", line->mask); nvkm_output_dp_train(&outp->base, 0, true); - nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep)); + nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep)); return NVKM_NOTIFY_DROP; } -int -_nvkm_output_dp_fini(struct nvkm_object *object, bool suspend) +static void +nvkm_output_dp_fini(struct nvkm_output *base) { - struct nvkm_output_dp *outp = (void *)object; + struct nvkm_output_dp *outp = nvkm_output_dp(base); + nvkm_notify_put(&outp->hpd); nvkm_notify_put(&outp->irq); + flush_work(&outp->lt.work); nvkm_output_dp_enable(outp, false); - return nvkm_output_fini(&outp->base, suspend); } -int -_nvkm_output_dp_init(struct nvkm_object *object) +static void +nvkm_output_dp_init(struct nvkm_output *base) { - struct nvkm_output_dp *outp = (void *)object; - nvkm_output_dp_detect(outp); - return nvkm_output_init(&outp->base); + struct nvkm_output_dp *outp = nvkm_output_dp(base); + nvkm_notify_put(&outp->base.conn->hpd); + nvkm_output_dp_enable(outp, true); + nvkm_notify_get(&outp->hpd); } -void -_nvkm_output_dp_dtor(struct nvkm_object *object) +static void * +nvkm_output_dp_dtor(struct nvkm_output *base) { - struct nvkm_output_dp *outp = (void *)object; + struct nvkm_output_dp *outp = nvkm_output_dp(base); + nvkm_notify_fini(&outp->hpd); nvkm_notify_fini(&outp->irq); - nvkm_output_destroy(&outp->base); + return outp; } +static const struct nvkm_output_func +nvkm_output_dp_func = { + .dtor = nvkm_output_dp_dtor, + .init = nvkm_output_dp_init, + .fini = nvkm_output_dp_fini, +}; + int -nvkm_output_dp_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, - struct dcb_output *info, int index, - int length, void **pobject) +nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func, + struct nvkm_disp *disp, int index, struct dcb_output *dcbE, + struct nvkm_i2c_aux *aux, struct nvkm_output_dp *outp) { - struct nvkm_bios *bios = nvkm_bios(parent); - struct nvkm_i2c *i2c = nvkm_i2c(parent); - struct nvkm_output_dp *outp; + struct nvkm_device *device = disp->engine.subdev.device; + struct nvkm_bios *bios = device->bios; + struct nvkm_i2c *i2c = device->i2c; u8 hdr, cnt, len; u32 data; int ret; - ret = nvkm_output_create_(parent, engine, oclass, info, index, - length, pobject); - outp = *pobject; - if (ret) - return ret; - - nvkm_notify_fini(&outp->base.conn->hpd); - - /* access to the aux channel is not optional... */ - if (!outp->base.edid) { - ERR("aux channel not found\n"); + nvkm_output_ctor(&nvkm_output_dp_func, disp, index, dcbE, &outp->base); + outp->func = func; + outp->aux = aux; + if (!outp->aux) { + OUTP_ERR(&outp->base, "no aux"); return -ENODEV; } - /* nor is the bios data for this output... */ + /* bios data is not optional */ data = nvbios_dpout_match(bios, outp->base.info.hasht, outp->base.info.hashm, &outp->version, &hdr, &cnt, &len, &outp->info); if (!data) { - ERR("no bios dp data\n"); + OUTP_ERR(&outp->base, "no bios dp data"); return -ENODEV; } - DBG("bios dp %02x %02x %02x %02x\n", outp->version, hdr, cnt, len); + OUTP_DBG(&outp->base, "bios dp %02x %02x %02x %02x", + outp->version, hdr, cnt, len); /* link training */ INIT_WORK(&outp->lt.work, nvkm_dp_train); @@ -256,13 +247,13 @@ nvkm_output_dp_create_(struct nvkm_object *parent, ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_irq, true, &(struct nvkm_i2c_ntfy_req) { .mask = NVKM_I2C_IRQ, - .port = outp->base.edid->index, + .port = outp->aux->id, }, sizeof(struct nvkm_i2c_ntfy_req), sizeof(struct nvkm_i2c_ntfy_rep), &outp->irq); if (ret) { - ERR("error monitoring aux irq event: %d\n", ret); + OUTP_ERR(&outp->base, "error monitoring aux irq: %d", ret); return ret; } @@ -270,13 +261,13 @@ nvkm_output_dp_create_(struct nvkm_object *parent, ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_hpd, true, &(struct nvkm_i2c_ntfy_req) { .mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG, - .port = outp->base.edid->index, + .port = outp->aux->id, }, sizeof(struct nvkm_i2c_ntfy_req), sizeof(struct nvkm_i2c_ntfy_rep), - &outp->base.conn->hpd); + &outp->hpd); if (ret) { - ERR("error monitoring aux hpd events: %d\n", ret); + OUTP_ERR(&outp->base, "error monitoring aux hpd: %d", ret); return ret; } @@ -284,18 +275,17 @@ nvkm_output_dp_create_(struct nvkm_object *parent, } int -_nvkm_output_dp_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *info, u32 index, - struct nvkm_object **pobject) +nvkm_output_dp_new_(const struct nvkm_output_dp_func *func, + struct nvkm_disp *disp, int index, struct dcb_output *dcbE, + struct nvkm_output **poutp) { + struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; + struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, dcbE->i2c_index); struct nvkm_output_dp *outp; - int ret; - ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp); - *pobject = nv_object(outp); - if (ret) - return ret; + if (!(outp = kzalloc(sizeof(*outp), GFP_KERNEL))) + return -ENOMEM; + *poutp = &outp->base; - return 0; + return nvkm_output_dp_ctor(func, disp, index, dcbE, aux, outp); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h index 70c77aec4..731136d66 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h @@ -1,5 +1,14 @@ #ifndef __NVKM_DISP_OUTP_DP_H__ #define __NVKM_DISP_OUTP_DP_H__ +#define nvkm_output_dp(p) container_of((p), struct nvkm_output_dp, base) +#ifndef MSG +#define MSG(l,f,a...) \ + nvkm_##l(&outp->base.disp->engine.subdev, "%02x:%04x:%04x: "f, \ + outp->base.index, outp->base.info.hasht, \ + outp->base.info.hashm, ##a) +#define DBG(f,a...) MSG(debug, f, ##a) +#define ERR(f,a...) MSG(error, f, ##a) +#endif #include "outp.h" #include @@ -7,12 +16,16 @@ #include struct nvkm_output_dp { + const struct nvkm_output_dp_func *func; struct nvkm_output base; struct nvbios_dpout info; u8 version; + struct nvkm_i2c_aux *aux; + struct nvkm_notify irq; + struct nvkm_notify hpd; bool present; u8 dpcd[16]; @@ -23,34 +36,7 @@ struct nvkm_output_dp { } lt; }; -#define nvkm_output_dp_create(p,e,c,b,i,d) \ - nvkm_output_dp_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) -#define nvkm_output_dp_destroy(d) ({ \ - struct nvkm_output_dp *_outp = (d); \ - _nvkm_output_dp_dtor(nv_object(_outp)); \ -}) -#define nvkm_output_dp_init(d) ({ \ - struct nvkm_output_dp *_outp = (d); \ - _nvkm_output_dp_init(nv_object(_outp)); \ -}) -#define nvkm_output_dp_fini(d,s) ({ \ - struct nvkm_output_dp *_outp = (d); \ - _nvkm_output_dp_fini(nv_object(_outp), (s)); \ -}) - -int nvkm_output_dp_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, struct dcb_output *, - int, int, void **); - -int _nvkm_output_dp_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void _nvkm_output_dp_dtor(struct nvkm_object *); -int _nvkm_output_dp_init(struct nvkm_object *); -int _nvkm_output_dp_fini(struct nvkm_object *, bool); - -struct nvkm_output_dp_impl { - struct nvkm_output_impl base; +struct nvkm_output_dp_func { int (*pattern)(struct nvkm_output_dp *, int); int (*lnk_pwr)(struct nvkm_output_dp *, int nr); int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef); @@ -58,4 +44,25 @@ struct nvkm_output_dp_impl { }; int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait); + +int nvkm_output_dp_ctor(const struct nvkm_output_dp_func *, struct nvkm_disp *, + int index, struct dcb_output *, struct nvkm_i2c_aux *, + struct nvkm_output_dp *); +int nvkm_output_dp_new_(const struct nvkm_output_dp_func *, struct nvkm_disp *, + int index, struct dcb_output *, + struct nvkm_output **); + +int nv50_pior_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); + +int g94_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); + +int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); +int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool); + +int gm204_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *, + struct nvkm_output **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c new file mode 100644 index 000000000..db6234eeb --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c @@ -0,0 +1,77 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +g84_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +const struct nv50_disp_chan_mthd +g84_disp_ovly_chan_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_ovly_mthd_base }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c new file mode 100644 index 000000000..5985879ab --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c @@ -0,0 +1,101 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +gf119_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +gf119_disp_ovly_chan_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_ovly_mthd_base }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c new file mode 100644 index 000000000..2e2dc0641 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c @@ -0,0 +1,103 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +gk104_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00c4, 0x6650c4 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0404, 0x665404 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +gk104_disp_ovly_chan_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gk104_disp_ovly_mthd_base }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c new file mode 100644 index 000000000..f858053db --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c @@ -0,0 +1,80 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +static const struct nv50_disp_mthd_list +gt200_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00b0, 0x610c98 }, + { 0x00b4, 0x610ca4 }, + { 0x00b8, 0x610cac }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +gt200_disp_ovly_chan_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, >200_disp_ovly_mthd_base }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c new file mode 100644 index 000000000..c947e1e16 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c @@ -0,0 +1,38 @@ +/* + * 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 + */ +#include "dmacnv50.h" +#include "rootnv50.h" + +#include + +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/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c new file mode 100644 index 000000000..6fa296c04 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c @@ -0,0 +1,111 @@ +/* + * 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 "dmacnv50.h" +#include "rootnv50.h" + +#include + +#include +#include + +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) +{ + union { + struct nv50_disp_overlay_channel_dma_v0 v0; + } *args = data; + struct nvkm_object *parent = oclass->parent; + struct nv50_disp *disp = root->disp; + int head, ret; + u64 push; + + nvif_ioctl(parent, "create disp overlay channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create disp overlay channel dma vers %d " + "pushbuf %016llx head %d\n", + args->v0.version, args->v0.pushbuf, args->v0.head); + if (args->v0.head > disp->base.head.nr) + return -EINVAL; + push = args->v0.pushbuf; + head = args->v0.head; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, root, chid + head, + head, push, oclass, pobject); +} + +static const struct nv50_disp_mthd_list +nv50_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0009a0 }, + { 0x0088, 0x0009c0 }, + { 0x008c, 0x0009c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nv50_disp_chan_mthd +nv50_disp_ovly_chan_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_ovly_mthd_base }, + {} + } +}; + +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, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c new file mode 100644 index 000000000..a625a9876 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c @@ -0,0 +1,81 @@ +/* + * 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 + +static void +gf119_disp_pioc_fini(struct nv50_disp_chan *chan) +{ + struct nv50_disp *disp = chan->root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->chid; + + nvkm_mask(device, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", chid, + nvkm_rd32(device, 0x610490 + (chid * 0x10))); + } + + /* disable error reporting and completion notification */ + nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000); + nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000); +} + +static int +gf119_disp_pioc_init(struct nv50_disp_chan *chan) +{ + struct nv50_disp *disp = chan->root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->chid; + + /* enable error reporting */ + nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); + + /* activate channel */ + nvkm_wr32(device, 0x610490 + (chid * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610490 + (chid * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", chid, + nvkm_rd32(device, 0x610490 + (chid * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nv50_disp_chan_func +gf119_disp_pioc_func = { + .init = gf119_disp_pioc_init, + .fini = gf119_disp_pioc_fini, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c new file mode 100644 index 000000000..9d2618dac --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c @@ -0,0 +1,83 @@ +/* + * 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 + +static void +nv50_disp_pioc_fini(struct nv50_disp_chan *chan) +{ + struct nv50_disp *disp = chan->root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->chid; + + nvkm_mask(device, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout: %08x\n", chid, + nvkm_rd32(device, 0x610200 + (chid * 0x10))); + } +} + +static int +nv50_disp_pioc_init(struct nv50_disp_chan *chan) +{ + struct nv50_disp *disp = chan->root->disp; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int chid = chan->chid; + + nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00002000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout0: %08x\n", chid, + nvkm_rd32(device, 0x610200 + (chid * 0x10))); + return -EBUSY; + } + + nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610200 + (chid * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout1: %08x\n", chid, + nvkm_rd32(device, 0x610200 + (chid * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nv50_disp_chan_func +nv50_disp_pioc_func = { + .init = nv50_disp_pioc_init, + .fini = nv50_disp_pioc_fini, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c index 2a1d8871b..ab524bde7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c @@ -21,8 +21,8 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" #include "outpdp.h" +#include "nv50.h" #include #include @@ -31,140 +31,101 @@ #include #include -/****************************************************************************** - * TMDS - *****************************************************************************/ - -static int -nv50_pior_tmds_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *info, u32 index, - struct nvkm_object **pobject) +int +nv50_pior_power(NV50_DISP_MTHD_V1) { - struct nvkm_i2c *i2c = nvkm_i2c(parent); - struct nvkm_output *outp; + struct nvkm_device *device = disp->base.engine.subdev.device; + const u32 soff = outp->or * 0x800; + union { + struct nv50_disp_pior_pwr_v0 v0; + } *args = data; + u32 ctrl, type; int ret; - ret = nvkm_output_create(parent, engine, oclass, info, index, &outp); - *pobject = nv_object(outp); - if (ret) + nvif_ioctl(object, "disp pior pwr size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp pior pwr vers %d state %d type %x\n", + args->v0.version, args->v0.state, args->v0.type); + if (args->v0.type > 0x0f) + return -EINVAL; + ctrl = !!args->v0.state; + type = args->v0.type; + } else return ret; - outp->edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(outp->info.extdev)); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61e004 + soff) & 0x80000000)) + break; + ); + nvkm_mask(device, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61e004 + soff) & 0x80000000)) + break; + ); + disp->pior.type[outp->or] = type; return 0; } -struct nvkm_output_impl -nv50_pior_tmds_impl = { - .base.handle = DCB_OUTPUT_TMDS | 0x0100, - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_pior_tmds_ctor, - .dtor = _nvkm_output_dtor, - .init = _nvkm_output_init, - .fini = _nvkm_output_fini, - }, -}; - /****************************************************************************** - * DisplayPort + * TMDS *****************************************************************************/ +static const struct nvkm_output_func +nv50_pior_output_func = { +}; -static int -nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern) +int +nv50_pior_output_new(struct nvkm_disp *disp, int index, + struct dcb_output *dcbE, struct nvkm_output **poutp) { - struct nvkm_i2c_port *port = outp->base.edid; - if (port && port->func->pattern) - return port->func->pattern(port, pattern); - return port ? 0 : -ENODEV; + return nvkm_output_new_(&nv50_pior_output_func, disp, + index, dcbE, poutp); } +/****************************************************************************** + * DisplayPort + *****************************************************************************/ static int -nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) +nv50_pior_output_dp_pattern(struct nvkm_output_dp *outp, int pattern) { return 0; } static int -nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) -{ - struct nvkm_i2c_port *port = outp->base.edid; - if (port && port->func->lnk_ctl) - return port->func->lnk_ctl(port, nr, bw, ef); - return port ? 0 : -ENODEV; -} - -static int -nv50_pior_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) +nv50_pior_output_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) { - struct nvkm_i2c_port *port = outp->base.edid; - if (port && port->func->drv_ctl) - return port->func->drv_ctl(port, ln, vs, pe); - return port ? 0 : -ENODEV; + return 0; } static int -nv50_pior_dp_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *info, u32 index, - struct nvkm_object **pobject) +nv50_pior_output_dp_lnk_ctl(struct nvkm_output_dp *outp, + int nr, int bw, bool ef) { - struct nvkm_i2c *i2c = nvkm_i2c(parent); - struct nvkm_output_dp *outp; - int ret; - - ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp); - *pobject = nv_object(outp); + int ret = nvkm_i2c_aux_lnk_ctl(outp->aux, nr, bw, ef); if (ret) return ret; - - outp->base.edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX( - outp->base.info.extdev)); - return 0; + return 1; } -struct nvkm_output_dp_impl -nv50_pior_dp_impl = { - .base.base.handle = DCB_OUTPUT_DP | 0x0010, - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_pior_dp_ctor, - .dtor = _nvkm_output_dp_dtor, - .init = _nvkm_output_dp_init, - .fini = _nvkm_output_dp_fini, - }, - .pattern = nv50_pior_dp_pattern, - .lnk_pwr = nv50_pior_dp_lnk_pwr, - .lnk_ctl = nv50_pior_dp_lnk_ctl, - .drv_ctl = nv50_pior_dp_drv_ctl, +static const struct nvkm_output_dp_func +nv50_pior_output_dp_func = { + .pattern = nv50_pior_output_dp_pattern, + .lnk_pwr = nv50_pior_output_dp_lnk_pwr, + .lnk_ctl = nv50_pior_output_dp_lnk_ctl, }; -/****************************************************************************** - * General PIOR handling - *****************************************************************************/ - int -nv50_pior_power(NV50_DISP_MTHD_V1) +nv50_pior_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, + struct nvkm_output **poutp) { - const u32 soff = outp->or * 0x800; - union { - struct nv50_disp_pior_pwr_v0 v0; - } *args = data; - u32 ctrl, type; - int ret; + struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; + struct nvkm_i2c_aux *aux = + nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev)); + struct nvkm_output_dp *outp; - nv_ioctl(object, "disp pior pwr size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp pior pwr vers %d state %d type %x\n", - args->v0.version, args->v0.state, args->v0.type); - if (args->v0.type > 0x0f) - return -EINVAL; - ctrl = !!args->v0.state; - type = args->v0.type; - } else - return ret; + if (!(outp = kzalloc(sizeof(*outp), GFP_KERNEL))) + return -ENOMEM; + *poutp = &outp->base; - nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000); - nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl); - nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000); - priv->pior.type[outp->or] = type; - return 0; + return nvkm_output_dp_ctor(&nv50_pior_output_dp_func, disp, + index, dcbE, aux, outp); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index 961ce8bb2..c2452957f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -1,42 +1,52 @@ #ifndef __NVKM_DISP_PRIV_H__ #define __NVKM_DISP_PRIV_H__ #include +#include "outp.h" +#include "outpdp.h" -struct nvkm_disp_impl { - struct nvkm_oclass base; - struct nvkm_oclass **outp; - struct nvkm_oclass **conn; - const struct nvkm_event_func *vblank; +int nvkm_disp_ctor(const struct nvkm_disp_func *, struct nvkm_device *, + int index, int heads, struct nvkm_disp *); +int nvkm_disp_new_(const struct nvkm_disp_func *, struct nvkm_device *, + int index, int heads, struct nvkm_disp **); +void nvkm_disp_vblank(struct nvkm_disp *, int head); + +struct nvkm_disp_func_outp { + int (* crt)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (* tv)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (*tmds)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (*lvds)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); + int (* dp)(struct nvkm_disp *, int index, struct dcb_output *, + struct nvkm_output **); +}; + +struct nvkm_disp_func { + void *(*dtor)(struct nvkm_disp *); + void (*intr)(struct nvkm_disp *); + + const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *); + + struct { + void (*vblank_init)(struct nvkm_disp *, int head); + void (*vblank_fini)(struct nvkm_disp *, int head); + } head; + + struct { + const struct nvkm_disp_func_outp internal; + const struct nvkm_disp_func_outp external; + } outp; }; -#define nvkm_disp_create(p,e,c,h,i,x,d) \ - nvkm_disp_create_((p), (e), (c), (h), (i), (x), \ - sizeof(**d), (void **)d) -#define nvkm_disp_destroy(d) ({ \ - struct nvkm_disp *disp = (d); \ - _nvkm_disp_dtor(nv_object(disp)); \ -}) -#define nvkm_disp_init(d) ({ \ - struct nvkm_disp *disp = (d); \ - _nvkm_disp_init(nv_object(disp)); \ -}) -#define nvkm_disp_fini(d,s) ({ \ - struct nvkm_disp *disp = (d); \ - _nvkm_disp_fini(nv_object(disp), (s)); \ -}) - -int nvkm_disp_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int heads, - const char *, const char *, int, void **); -void _nvkm_disp_dtor(struct nvkm_object *); -int _nvkm_disp_init(struct nvkm_object *); -int _nvkm_disp_fini(struct nvkm_object *, bool); - -extern struct nvkm_oclass *nvkm_output_oclass; -extern struct nvkm_oclass *nvkm_connector_oclass; - -int nvkm_disp_vblank_ctor(struct nvkm_object *, void *data, u32 size, - struct nvkm_notify *); -void nvkm_disp_vblank(struct nvkm_disp *, int head); int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); + +extern const struct nvkm_disp_oclass nv04_disp_root_oclass; + +struct nvkm_disp_oclass { + int (*ctor)(struct nvkm_disp *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + struct nvkm_sclass base; +}; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c new file mode 100644 index 000000000..721e4f74d --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +g84_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_(&g84_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +g84_disp_root_oclass = { + .base.oclass = G82_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = g84_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c new file mode 100644 index 000000000..9493f6edf --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +g94_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_(&g94_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +g94_disp_root_oclass = { + .base.oclass = GT206_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = g94_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c new file mode 100644 index 000000000..859172687 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c @@ -0,0 +1,171 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include +#include +#include + +#include +#include + +int +gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + const u32 total = nvkm_rd32(device, 0x640414 + (head * 0x300)); + const u32 blanke = nvkm_rd32(device, 0x64041c + (head * 0x300)); + const u32 blanks = nvkm_rd32(device, 0x640420 + (head * 0x300)); + union { + struct nv04_disp_scanoutpos_v0 v0; + } *args = data; + int ret; + + nvif_ioctl(object, "disp scanoutpos size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp scanoutpos vers %d\n", + args->v0.version); + args->v0.vblanke = (blanke & 0xffff0000) >> 16; + args->v0.hblanke = (blanke & 0x0000ffff); + args->v0.vblanks = (blanks & 0xffff0000) >> 16; + args->v0.hblanks = (blanks & 0x0000ffff); + args->v0.vtotal = ( total & 0xffff0000) >> 16; + args->v0.htotal = ( total & 0x0000ffff); + args->v0.time[0] = ktime_to_ns(ktime_get()); + args->v0.vline = /* vline read locks hline */ + nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff; + args->v0.time[1] = ktime_to_ns(ktime_get()); + args->v0.hline = + nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff; + } else + return ret; + + return 0; +} + +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_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 */ + for (i = 0; i < disp->base.head.nr; i++) { + tmp = nvkm_rd32(device, 0x616104 + (i * 0x800)); + nvkm_wr32(device, 0x6101b4 + (i * 0x800), tmp); + tmp = nvkm_rd32(device, 0x616108 + (i * 0x800)); + nvkm_wr32(device, 0x6101b8 + (i * 0x800), tmp); + tmp = nvkm_rd32(device, 0x61610c + (i * 0x800)); + nvkm_wr32(device, 0x6101bc + (i * 0x800), 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 + */ + for (i = 0; i < disp->base.head.nr; i++) + nvkm_mask(device, 0x616308 + (i * 0x800), 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, + }, +}; + +static int +gf119_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_(&gf119_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gf119_disp_root_oclass = { + .base.oclass = GF110_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gf119_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c new file mode 100644 index 000000000..0bfdb1d1c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +gk104_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_(&gk104_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gk104_disp_root_oclass = { + .base.oclass = GK104_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gk104_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c new file mode 100644 index 000000000..1e8dbed8a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +gk110_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_(&gk110_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gk110_disp_root_oclass = { + .base.oclass = GK110_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gk110_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c new file mode 100644 index 000000000..44c55be69 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +gm107_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_(&gm107_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gm107_disp_root_oclass = { + .base.oclass = GM107_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gm107_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c new file mode 100644 index 000000000..168bffe06 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm204.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +static const struct nv50_disp_root_func +gm204_disp_root = { + .init = gf119_disp_root_init, + .fini = gf119_disp_root_fini, + .dmac = { + &gm204_disp_core_oclass, + &gk110_disp_base_oclass, + &gk104_disp_ovly_oclass, + }, + .pioc = { + &gk104_disp_oimm_oclass, + &gk104_disp_curs_oclass, + }, +}; + +static int +gm204_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_(&gm204_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gm204_disp_root_oclass = { + .base.oclass = GM204_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gm204_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c new file mode 100644 index 000000000..124a0c24f --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +gt200_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_(>200_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gt200_disp_root_oclass = { + .base.oclass = GT200_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gt200_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c new file mode 100644 index 000000000..dff52f306 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c @@ -0,0 +1,58 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include + +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, + }, +}; + +static int +gt215_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_(>215_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gt215_disp_root_oclass = { + .base.oclass = GT214_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gt215_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c new file mode 100644 index 000000000..2be846374 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c @@ -0,0 +1,139 @@ +/* + * 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 + */ +#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object) +#include "priv.h" + +#include + +#include +#include + +struct nv04_disp_root { + struct nvkm_object object; + struct nvkm_disp *disp; +}; + +static int +nv04_disp_scanoutpos(struct nv04_disp_root *root, + void *data, u32 size, int head) +{ + struct nvkm_device *device = root->disp->engine.subdev.device; + struct nvkm_object *object = &root->object; + const u32 hoff = head * 0x2000; + union { + struct nv04_disp_scanoutpos_v0 v0; + } *args = data; + u32 line; + int ret; + + nvif_ioctl(object, "disp scanoutpos size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp scanoutpos vers %d\n", + args->v0.version); + args->v0.vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0xffff; + args->v0.vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0xffff; + args->v0.vblanke = args->v0.vtotal - 1; + + args->v0.hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0xffff; + args->v0.htotal = nvkm_rd32(device, 0x680824 + hoff) & 0xffff; + args->v0.hblanke = args->v0.htotal - 1; + + /* + * If output is vga instead of digital then vtotal/htotal is + * invalid so we have to give up and trigger the timestamping + * fallback in the drm core. + */ + if (!args->v0.vtotal || !args->v0.htotal) + return -ENOTSUPP; + + args->v0.time[0] = ktime_to_ns(ktime_get()); + line = nvkm_rd32(device, 0x600868 + hoff); + args->v0.time[1] = ktime_to_ns(ktime_get()); + args->v0.hline = (line & 0xffff0000) >> 16; + args->v0.vline = (line & 0x0000ffff); + } else + return ret; + + return 0; +} + +static int +nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + struct nv04_disp_root *root = nv04_disp_root(object); + union { + struct nv04_disp_mthd_v0 v0; + } *args = data; + int head, ret; + + nvif_ioctl(object, "disp mthd size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, true)) { + nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", + args->v0.version, args->v0.method, args->v0.head); + mthd = args->v0.method; + head = args->v0.head; + } else + return ret; + + if (head < 0 || head >= 2) + return -ENXIO; + + switch (mthd) { + case NV04_DISP_SCANOUTPOS: + return nv04_disp_scanoutpos(root, data, size, head); + default: + break; + } + + return -EINVAL; +} + +static const struct nvkm_object_func +nv04_disp_root = { + .mthd = nv04_disp_mthd, + .ntfy = nvkm_disp_ntfy, +}; + +static int +nv04_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nv04_disp_root *root; + + if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) + return -ENOMEM; + root->disp = disp; + *pobject = &root->object; + + nvkm_object_ctor(&nv04_disp_root, oclass, &root->object); + return 0; +} + +const struct nvkm_disp_oclass +nv04_disp_root_oclass = { + .base.oclass = NV04_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = nv04_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c new file mode 100644 index 000000000..06fb24d88 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -0,0 +1,399 @@ +/* + * 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 "rootnv50.h" +#include "dmacnv50.h" + +#include +#include +#include + +#include +#include + +int +nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + const u32 blanke = nvkm_rd32(device, 0x610aec + (head * 0x540)); + const u32 blanks = nvkm_rd32(device, 0x610af4 + (head * 0x540)); + const u32 total = nvkm_rd32(device, 0x610afc + (head * 0x540)); + union { + struct nv04_disp_scanoutpos_v0 v0; + } *args = data; + int ret; + + nvif_ioctl(object, "disp scanoutpos size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp scanoutpos vers %d\n", + args->v0.version); + args->v0.vblanke = (blanke & 0xffff0000) >> 16; + args->v0.hblanke = (blanke & 0x0000ffff); + args->v0.vblanks = (blanks & 0xffff0000) >> 16; + args->v0.hblanks = (blanks & 0x0000ffff); + args->v0.vtotal = ( total & 0xffff0000) >> 16; + args->v0.htotal = ( total & 0x0000ffff); + args->v0.time[0] = ktime_to_ns(ktime_get()); + args->v0.vline = /* vline read locks hline */ + nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff; + args->v0.time[1] = ktime_to_ns(ktime_get()); + args->v0.hline = + nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff; + } else + return ret; + + return 0; +} + +int +nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + union { + struct nv50_disp_mthd_v0 v0; + struct nv50_disp_mthd_v1 v1; + } *args = data; + struct nv50_disp_root *root = nv50_disp_root(object); + struct nv50_disp *disp = root->disp; + const struct nv50_disp_func *func = disp->func; + struct nvkm_output *outp = NULL; + struct nvkm_output *temp; + u16 type, mask = 0; + int head, ret; + + if (mthd != NV50_DISP_MTHD) + return -EINVAL; + + nvif_ioctl(object, "disp mthd size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, true)) { + nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", + args->v0.version, args->v0.method, args->v0.head); + mthd = args->v0.method; + head = args->v0.head; + } else + if (nvif_unpack(args->v1, 1, 1, true)) { + nvif_ioctl(object, "disp mthd vers %d mthd %02x " + "type %04x mask %04x\n", + args->v1.version, args->v1.method, + args->v1.hasht, args->v1.hashm); + mthd = args->v1.method; + type = args->v1.hasht; + mask = args->v1.hashm; + head = ffs((mask >> 8) & 0x0f) - 1; + } else + return ret; + + if (head < 0 || head >= disp->base.head.nr) + return -ENXIO; + + if (mask) { + list_for_each_entry(temp, &disp->base.outp, head) { + if ((temp->info.hasht == type) && + (temp->info.hashm & mask) == mask) { + outp = temp; + break; + } + } + if (outp == NULL) + return -ENXIO; + } + + switch (mthd) { + case NV50_DISP_SCANOUTPOS: + return func->head.scanoutpos(object, disp, data, size, head); + default: + break; + } + + switch (mthd * !!outp) { + case NV50_DISP_MTHD_V1_DAC_PWR: + return func->dac.power(object, disp, data, size, head, outp); + case NV50_DISP_MTHD_V1_DAC_LOAD: + return func->dac.sense(object, disp, data, size, head, outp); + case NV50_DISP_MTHD_V1_SOR_PWR: + return func->sor.power(object, disp, data, size, head, outp); + case NV50_DISP_MTHD_V1_SOR_HDA_ELD: + if (!func->sor.hda_eld) + return -ENODEV; + return func->sor.hda_eld(object, disp, data, size, head, outp); + case NV50_DISP_MTHD_V1_SOR_HDMI_PWR: + if (!func->sor.hdmi) + return -ENODEV; + return func->sor.hdmi(object, disp, data, size, head, outp); + case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: { + union { + struct nv50_disp_sor_lvds_script_v0 v0; + } *args = data; + nvif_ioctl(object, "disp sor lvds script size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp sor lvds script " + "vers %d name %04x\n", + args->v0.version, args->v0.script); + disp->sor.lvdsconf = args->v0.script; + return 0; + } else + return ret; + } + break; + case NV50_DISP_MTHD_V1_SOR_DP_PWR: { + struct nvkm_output_dp *outpdp = nvkm_output_dp(outp); + union { + struct nv50_disp_sor_dp_pwr_v0 v0; + } *args = data; + nvif_ioctl(object, "disp sor dp pwr size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, "disp sor dp pwr vers %d state %d\n", + args->v0.version, args->v0.state); + if (args->v0.state == 0) { + nvkm_notify_put(&outpdp->irq); + outpdp->func->lnk_pwr(outpdp, 0); + atomic_set(&outpdp->lt.done, 0); + return 0; + } else + if (args->v0.state != 0) { + nvkm_output_dp_train(&outpdp->base, 0, true); + return 0; + } + } else + return ret; + } + break; + case NV50_DISP_MTHD_V1_PIOR_PWR: + if (!func->pior.power) + return -ENODEV; + return func->pior.power(object, disp, data, size, head, outp); + default: + break; + } + + return -EINVAL; +} + +static int +nv50_disp_root_dmac_new_(const struct nvkm_oclass *oclass, + void *data, u32 size, 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, + oclass, data, size, pobject); +} + +static int +nv50_disp_root_child_get_(struct nvkm_object *object, int index, + struct nvkm_oclass *sclass) +{ + 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_; + 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); + return root->func->init(root); +} + +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_, +}; + +int +nv50_disp_root_new_(const struct nv50_disp_root_func *func, + struct nvkm_disp *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + 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; + *pobject = &root->object; + + 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_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 */ + for (i = 0; i < disp->base.head.nr; i++) { + tmp = nvkm_rd32(device, 0x616100 + (i * 0x800)); + nvkm_wr32(device, 0x610190 + (i * 0x10), tmp); + tmp = nvkm_rd32(device, 0x616104 + (i * 0x800)); + nvkm_wr32(device, 0x610194 + (i * 0x10), tmp); + tmp = nvkm_rd32(device, 0x616108 + (i * 0x800)); + nvkm_wr32(device, 0x610198 + (i * 0x10), tmp); + tmp = nvkm_rd32(device, 0x61610c + (i * 0x800)); + nvkm_wr32(device, 0x61019c + (i * 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, + }, +}; + +static int +nv50_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_(&nv50_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +nv50_disp_root_oclass = { + .base.oclass = NV50_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = nv50_disp_root_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h new file mode 100644 index 000000000..5b2c903ce --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h @@ -0,0 +1,43 @@ +#ifndef __NV50_DISP_ROOT_H__ +#define __NV50_DISP_ROOT_H__ +#define nv50_disp_root(p) container_of((p), struct nv50_disp_root, object) +#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 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; +extern const struct nvkm_disp_oclass g94_disp_root_oclass; +extern const struct nvkm_disp_oclass gt200_disp_root_oclass; +extern const struct nvkm_disp_oclass gt215_disp_root_oclass; +extern const struct nvkm_disp_oclass gf119_disp_root_oclass; +extern const struct nvkm_disp_oclass gk104_disp_root_oclass; +extern const struct nvkm_disp_oclass gk110_disp_root_oclass; +extern const struct nvkm_disp_oclass gm107_disp_root_oclass; +extern const struct nvkm_disp_oclass gm204_disp_root_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c index 8918da7ff..1bb9d661e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c @@ -24,7 +24,6 @@ #include "nv50.h" #include "outpdp.h" -#include #include static inline u32 @@ -39,12 +38,33 @@ g94_sor_loff(struct nvkm_output_dp *outp) return g94_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80; } -static inline u32 -g94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) +/******************************************************************************* + * TMDS/LVDS + ******************************************************************************/ +static const struct nvkm_output_func +g94_sor_output_func = { +}; + +int +g94_sor_output_new(struct nvkm_disp *disp, int index, + struct dcb_output *dcbE, struct nvkm_output **poutp) +{ + return nvkm_output_new_(&g94_sor_output_func, disp, + index, dcbE, poutp); +} + +/******************************************************************************* + * DisplayPort + ******************************************************************************/ +u32 +g94_sor_dp_lane_map(struct nvkm_device *device, u8 lane) { + static const u8 gm100[] = { 0, 8, 16, 24 }; static const u8 mcp89[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ - static const u8 g94[] = { 16, 8, 0, 24 }; - if (nv_device(priv)->chipset == 0xaf) + static const u8 g94[] = { 16, 8, 0, 24 }; + if (device->chipset >= 0x110) + return gm100[lane]; + if (device->chipset == 0xaf) return mcp89[lane]; return g94[lane]; } @@ -52,33 +72,36 @@ g94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) static int g94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; const u32 loff = g94_sor_loff(outp); - nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24); + nvkm_mask(device, 0x61c10c + loff, 0x0f000000, pattern << 24); return 0; } int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; const u32 soff = g94_sor_soff(outp); const u32 loff = g94_sor_loff(outp); u32 mask = 0, i; for (i = 0; i < nr; i++) - mask |= 1 << (g94_sor_dp_lane_map(priv, i) >> 3); - - nv_mask(priv, 0x61c130 + loff, 0x0000000f, mask); - nv_mask(priv, 0x61c034 + soff, 0x80000000, 0x80000000); - nv_wait(priv, 0x61c034 + soff, 0x80000000, 0x00000000); + mask |= 1 << (g94_sor_dp_lane_map(device, i) >> 3); + + nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); + nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) + break; + ); return 0; } static int g94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; const u32 soff = g94_sor_soff(outp); const u32 loff = g94_sor_loff(outp); u32 dpctrl = 0x00000000; @@ -90,17 +113,17 @@ g94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) if (bw > 0x06) clksor |= 0x00040000; - nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor); - nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); + nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); return 0; } static int g94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); - struct nvkm_bios *bios = nvkm_bios(priv); - const u32 shift = g94_sor_dp_lane_map(priv, ln); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; + struct nvkm_bios *bios = device->bios; + const u32 shift = g94_sor_dp_lane_map(device, ln); const u32 loff = g94_sor_loff(outp); u32 addr, data[3]; u8 ver, hdr, cnt, len; @@ -109,37 +132,37 @@ g94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) addr = nvbios_dpout_match(bios, outp->base.info.hasht, outp->base.info.hashm, - &ver, &hdr, &cnt, &len, &info); + &ver, &hdr, &cnt, &len, &info); if (!addr) return -ENODEV; addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe, - &ver, &hdr, &cnt, &len, &ocfg); + &ver, &hdr, &cnt, &len, &ocfg); if (!addr) return -EINVAL; - data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nv_rd32(priv, 0x61c130 + loff); + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); - nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); - nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); - nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8)); + nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); return 0; } -struct nvkm_output_dp_impl -g94_sor_dp_impl = { - .base.base.handle = DCB_OUTPUT_DP, - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_output_dp_ctor, - .dtor = _nvkm_output_dp_dtor, - .init = _nvkm_output_dp_init, - .fini = _nvkm_output_dp_fini, - }, +static const struct nvkm_output_dp_func +g94_sor_dp_func = { .pattern = g94_sor_dp_pattern, .lnk_pwr = g94_sor_dp_lnk_pwr, .lnk_ctl = g94_sor_dp_lnk_ctl, .drv_ctl = g94_sor_dp_drv_ctl, }; + +int +g94_sor_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, + struct nvkm_output **poutp) +{ + return nvkm_output_dp_new_(&g94_sor_dp_func, disp, index, dcbE, poutp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c deleted file mode 100644 index 52fbe4880..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf110.c +++ /dev/null @@ -1,124 +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 "nv50.h" -#include "outpdp.h" - -static inline u32 -gf110_sor_soff(struct nvkm_output_dp *outp) -{ - return (ffs(outp->base.info.or) - 1) * 0x800; -} - -static inline u32 -gf110_sor_loff(struct nvkm_output_dp *outp) -{ - return gf110_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80; -} - -static inline u32 -gf110_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) -{ - static const u8 gf110[] = { 16, 8, 0, 24 }; - return gf110[lane]; -} - -static int -gf110_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) -{ - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); - const u32 loff = gf110_sor_loff(outp); - nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); - return 0; -} - -int -gf110_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) -{ - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); - const u32 soff = gf110_sor_soff(outp); - const u32 loff = gf110_sor_loff(outp); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - clksor |= bw << 18; - dpctrl |= ((1 << nr) - 1) << 16; - if (ef) - dpctrl |= 0x00004000; - - nv_mask(priv, 0x612300 + soff, 0x007c0000, clksor); - nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); - return 0; -} - -static int -gf110_sor_dp_drv_ctl(struct nvkm_output_dp *outp, - int ln, int vs, int pe, int pc) -{ - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); - struct nvkm_bios *bios = nvkm_bios(priv); - const u32 shift = gf110_sor_dp_lane_map(priv, ln); - const u32 loff = gf110_sor_loff(outp); - u32 addr, data[4]; - u8 ver, hdr, cnt, len; - struct nvbios_dpout info; - struct nvbios_dpcfg ocfg; - - addr = nvbios_dpout_match(bios, outp->base.info.hasht, - outp->base.info.hashm, - &ver, &hdr, &cnt, &len, &info); - if (!addr) - return -ENODEV; - - addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe, - &ver, &hdr, &cnt, &len, &ocfg); - if (!addr) - return -EINVAL; - - data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nv_rd32(priv, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); - nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); - nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); - nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8)); - data[3] = nv_rd32(priv, 0x61c13c + loff) & ~(0x000000ff << shift); - nv_wr32(priv, 0x61c13c + loff, data[3] | (ocfg.pc << shift)); - return 0; -} - -struct nvkm_output_dp_impl -gf110_sor_dp_impl = { - .base.base.handle = DCB_OUTPUT_DP, - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_output_dp_ctor, - .dtor = _nvkm_output_dp_dtor, - .init = _nvkm_output_dp_init, - .fini = _nvkm_output_dp_fini, - }, - .pattern = gf110_sor_dp_pattern, - .lnk_pwr = g94_sor_dp_lnk_pwr, - .lnk_ctl = gf110_sor_dp_lnk_ctl, - .drv_ctl = gf110_sor_dp_drv_ctl, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c new file mode 100644 index 000000000..b4b41b135 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c @@ -0,0 +1,117 @@ +/* + * 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 "nv50.h" +#include "outpdp.h" + +static inline u32 +gf119_sor_soff(struct nvkm_output_dp *outp) +{ + return (ffs(outp->base.info.or) - 1) * 0x800; +} + +static inline u32 +gf119_sor_loff(struct nvkm_output_dp *outp) +{ + return gf119_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80; +} + +static int +gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) +{ + struct nvkm_device *device = outp->base.disp->engine.subdev.device; + const u32 loff = gf119_sor_loff(outp); + nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); + return 0; +} + +int +gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) +{ + struct nvkm_device *device = outp->base.disp->engine.subdev.device; + const u32 soff = gf119_sor_soff(outp); + const u32 loff = gf119_sor_loff(outp); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + clksor |= bw << 18; + dpctrl |= ((1 << nr) - 1) << 16; + if (ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); + return 0; +} + +static int +gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp, + int ln, int vs, int pe, int pc) +{ + struct nvkm_device *device = outp->base.disp->engine.subdev.device; + struct nvkm_bios *bios = device->bios; + const u32 shift = g94_sor_dp_lane_map(device, ln); + const u32 loff = gf119_sor_loff(outp); + u32 addr, data[4]; + u8 ver, hdr, cnt, len; + struct nvbios_dpout info; + struct nvbios_dpcfg ocfg; + + addr = nvbios_dpout_match(bios, outp->base.info.hasht, + outp->base.info.hashm, + &ver, &hdr, &cnt, &len, &info); + if (!addr) + return -ENODEV; + + addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe, + &ver, &hdr, &cnt, &len, &ocfg); + if (!addr) + return -EINVAL; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); + nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (ocfg.pc << shift)); + return 0; +} + +static const struct nvkm_output_dp_func +gf119_sor_dp_func = { + .pattern = gf119_sor_dp_pattern, + .lnk_pwr = g94_sor_dp_lnk_pwr, + .lnk_ctl = gf119_sor_dp_lnk_ctl, + .drv_ctl = gf119_sor_dp_drv_ctl, +}; + +int +gf119_sor_dp_new(struct nvkm_disp *disp, int index, + struct dcb_output *dcbE, struct nvkm_output **poutp) +{ + return nvkm_output_dp_new_(&gf119_sor_dp_func, disp, index, dcbE, poutp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c index 1e40dfe11..029e5f16c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm204.c @@ -41,17 +41,17 @@ gm204_sor_loff(struct nvkm_output_dp *outp) void gm204_sor_magic(struct nvkm_output *outp) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nvkm_device *device = outp->disp->engine.subdev.device; const u32 soff = outp->or * 0x100; const u32 data = outp->or + 1; if (outp->info.sorconf.link & 1) - nv_mask(priv, 0x612308 + soff, 0x0000001f, 0x00000000 | data); + nvkm_mask(device, 0x612308 + soff, 0x0000001f, 0x00000000 | data); if (outp->info.sorconf.link & 2) - nv_mask(priv, 0x612388 + soff, 0x0000001f, 0x00000010 | data); + nvkm_mask(device, 0x612388 + soff, 0x0000001f, 0x00000010 | data); } static inline u32 -gm204_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) +gm204_sor_dp_lane_map(struct nvkm_device *device, u8 lane) { return lane * 0x08; } @@ -59,30 +59,33 @@ gm204_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) static int gm204_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; const u32 soff = gm204_sor_soff(outp); const u32 data = 0x01010101 * pattern; if (outp->base.info.sorconf.link & 1) - nv_mask(priv, 0x61c110 + soff, 0x0f0f0f0f, data); + nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data); else - nv_mask(priv, 0x61c12c + soff, 0x0f0f0f0f, data); + nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data); return 0; } static int gm204_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; const u32 soff = gm204_sor_soff(outp); const u32 loff = gm204_sor_loff(outp); u32 mask = 0, i; for (i = 0; i < nr; i++) - mask |= 1 << (gm204_sor_dp_lane_map(priv, i) >> 3); + mask |= 1 << (gm204_sor_dp_lane_map(device, i) >> 3); - nv_mask(priv, 0x61c130 + loff, 0x0000000f, mask); - nv_mask(priv, 0x61c034 + soff, 0x80000000, 0x80000000); - nv_wait(priv, 0x61c034 + soff, 0x80000000, 0x00000000); + nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); + nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) + break; + ); return 0; } @@ -90,9 +93,9 @@ static int gm204_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) { - struct nv50_disp_priv *priv = (void *)nvkm_disp(outp); - struct nvkm_bios *bios = nvkm_bios(priv); - const u32 shift = gm204_sor_dp_lane_map(priv, ln); + struct nvkm_device *device = outp->base.disp->engine.subdev.device; + struct nvkm_bios *bios = device->bios; + const u32 shift = gm204_sor_dp_lane_map(device, ln); const u32 loff = gm204_sor_loff(outp); u32 addr, data[4]; u8 ver, hdr, cnt, len; @@ -109,31 +112,32 @@ gm204_sor_dp_drv_ctl(struct nvkm_output_dp *outp, &ver, &hdr, &cnt, &len, &ocfg); if (!addr) return -EINVAL; + ocfg.tx_pu &= 0x0f; - data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nv_rd32(priv, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); - nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); - nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); - nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8)); - data[3] = nv_rd32(priv, 0x61c13c + loff) & ~(0x000000ff << shift); - nv_wr32(priv, 0x61c13c + loff, data[3] | (ocfg.pc << shift)); + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x00000f00) < (ocfg.tx_pu << 8) || ln == 0) + data[2] = (data[2] & ~0x00000f00) | (ocfg.tx_pu << 8); + nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (ocfg.pc << shift)); return 0; } -struct nvkm_output_dp_impl -gm204_sor_dp_impl = { - .base.base.handle = DCB_OUTPUT_DP, - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_output_dp_ctor, - .dtor = _nvkm_output_dp_dtor, - .init = _nvkm_output_dp_init, - .fini = _nvkm_output_dp_fini, - }, +static const struct nvkm_output_dp_func +gm204_sor_dp_func = { .pattern = gm204_sor_dp_pattern, .lnk_pwr = gm204_sor_dp_lnk_pwr, - .lnk_ctl = gf110_sor_dp_lnk_ctl, + .lnk_ctl = gf119_sor_dp_lnk_ctl, .drv_ctl = gm204_sor_dp_drv_ctl, }; + +int +gm204_sor_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, + struct nvkm_output **poutp) +{ + return nvkm_output_dp_new_(&gm204_sor_dp_func, disp, index, dcbE, poutp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c index b229a311c..29e0d2a9a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c @@ -33,6 +33,7 @@ int nv50_sor_power(NV50_DISP_MTHD_V1) { + struct nvkm_device *device = disp->base.engine.subdev.device; union { struct nv50_disp_sor_pwr_v0 v0; } *args = data; @@ -40,17 +41,39 @@ nv50_sor_power(NV50_DISP_MTHD_V1) u32 stat; int ret; - nv_ioctl(object, "disp sor pwr size %d\n", size); + nvif_ioctl(object, "disp sor pwr size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "disp sor pwr vers %d state %d\n", - args->v0.version, args->v0.state); + nvif_ioctl(object, "disp sor pwr vers %d state %d\n", + args->v0.version, args->v0.state); stat = !!args->v0.state; } else return ret; - nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000); - nv_mask(priv, 0x61c004 + soff, 0x80000001, 0x80000000 | stat); - nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000); - nv_wait(priv, 0x61c030 + soff, 0x10000000, 0x00000000); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) + break; + ); + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000 | stat); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) + break; + ); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); return 0; } + +static const struct nvkm_output_func +nv50_sor_output_func = { +}; + +int +nv50_sor_output_new(struct nvkm_disp *disp, int index, + struct dcb_output *dcbE, struct nvkm_output **poutp) +{ + return nvkm_output_new_(&nv50_sor_output_func, disp, + index, dcbE, poutp); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/vga.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/vga.c index c4622c738..8bff95c63 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/vga.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/disp/vga.c @@ -23,131 +23,119 @@ */ #include -#include - u8 -nv_rdport(void *obj, int head, u16 port) +nvkm_rdport(struct nvkm_device *device, int head, u16 port) { - struct nvkm_device *device = nv_device(obj); - if (device->card_type >= NV_50) - return nv_rd08(obj, 0x601000 + port); + return nvkm_rd08(device, 0x601000 + port); if (port == 0x03c0 || port == 0x03c1 || /* AR */ port == 0x03c2 || port == 0x03da || /* INP0 */ port == 0x03d4 || port == 0x03d5) /* CR */ - return nv_rd08(obj, 0x601000 + (head * 0x2000) + port); + return nvkm_rd08(device, 0x601000 + (head * 0x2000) + port); if (port == 0x03c2 || port == 0x03cc || /* MISC */ port == 0x03c4 || port == 0x03c5 || /* SR */ port == 0x03ce || port == 0x03cf) { /* GR */ if (device->card_type < NV_40) head = 0; /* CR44 selects head */ - return nv_rd08(obj, 0x0c0000 + (head * 0x2000) + port); + return nvkm_rd08(device, 0x0c0000 + (head * 0x2000) + port); } - nv_error(obj, "unknown vga port 0x%04x\n", port); return 0x00; } void -nv_wrport(void *obj, int head, u16 port, u8 data) +nvkm_wrport(struct nvkm_device *device, int head, u16 port, u8 data) { - struct nvkm_device *device = nv_device(obj); - if (device->card_type >= NV_50) - nv_wr08(obj, 0x601000 + port, data); + nvkm_wr08(device, 0x601000 + port, data); else if (port == 0x03c0 || port == 0x03c1 || /* AR */ port == 0x03c2 || port == 0x03da || /* INP0 */ port == 0x03d4 || port == 0x03d5) /* CR */ - nv_wr08(obj, 0x601000 + (head * 0x2000) + port, data); + nvkm_wr08(device, 0x601000 + (head * 0x2000) + port, data); else if (port == 0x03c2 || port == 0x03cc || /* MISC */ port == 0x03c4 || port == 0x03c5 || /* SR */ port == 0x03ce || port == 0x03cf) { /* GR */ if (device->card_type < NV_40) head = 0; /* CR44 selects head */ - nv_wr08(obj, 0x0c0000 + (head * 0x2000) + port, data); - } else - nv_error(obj, "unknown vga port 0x%04x\n", port); + nvkm_wr08(device, 0x0c0000 + (head * 0x2000) + port, data); + } } u8 -nv_rdvgas(void *obj, int head, u8 index) +nvkm_rdvgas(struct nvkm_device *device, int head, u8 index) { - nv_wrport(obj, head, 0x03c4, index); - return nv_rdport(obj, head, 0x03c5); + nvkm_wrport(device, head, 0x03c4, index); + return nvkm_rdport(device, head, 0x03c5); } void -nv_wrvgas(void *obj, int head, u8 index, u8 value) +nvkm_wrvgas(struct nvkm_device *device, int head, u8 index, u8 value) { - nv_wrport(obj, head, 0x03c4, index); - nv_wrport(obj, head, 0x03c5, value); + nvkm_wrport(device, head, 0x03c4, index); + nvkm_wrport(device, head, 0x03c5, value); } u8 -nv_rdvgag(void *obj, int head, u8 index) +nvkm_rdvgag(struct nvkm_device *device, int head, u8 index) { - nv_wrport(obj, head, 0x03ce, index); - return nv_rdport(obj, head, 0x03cf); + nvkm_wrport(device, head, 0x03ce, index); + return nvkm_rdport(device, head, 0x03cf); } void -nv_wrvgag(void *obj, int head, u8 index, u8 value) +nvkm_wrvgag(struct nvkm_device *device, int head, u8 index, u8 value) { - nv_wrport(obj, head, 0x03ce, index); - nv_wrport(obj, head, 0x03cf, value); + nvkm_wrport(device, head, 0x03ce, index); + nvkm_wrport(device, head, 0x03cf, value); } u8 -nv_rdvgac(void *obj, int head, u8 index) +nvkm_rdvgac(struct nvkm_device *device, int head, u8 index) { - nv_wrport(obj, head, 0x03d4, index); - return nv_rdport(obj, head, 0x03d5); + nvkm_wrport(device, head, 0x03d4, index); + return nvkm_rdport(device, head, 0x03d5); } void -nv_wrvgac(void *obj, int head, u8 index, u8 value) +nvkm_wrvgac(struct nvkm_device *device, int head, u8 index, u8 value) { - nv_wrport(obj, head, 0x03d4, index); - nv_wrport(obj, head, 0x03d5, value); + nvkm_wrport(device, head, 0x03d4, index); + nvkm_wrport(device, head, 0x03d5, value); } u8 -nv_rdvgai(void *obj, int head, u16 port, u8 index) +nvkm_rdvgai(struct nvkm_device *device, int head, u16 port, u8 index) { - if (port == 0x03c4) return nv_rdvgas(obj, head, index); - if (port == 0x03ce) return nv_rdvgag(obj, head, index); - if (port == 0x03d4) return nv_rdvgac(obj, head, index); - nv_error(obj, "unknown indexed vga port 0x%04x\n", port); + if (port == 0x03c4) return nvkm_rdvgas(device, head, index); + if (port == 0x03ce) return nvkm_rdvgag(device, head, index); + if (port == 0x03d4) return nvkm_rdvgac(device, head, index); return 0x00; } void -nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value) +nvkm_wrvgai(struct nvkm_device *device, int head, u16 port, u8 index, u8 value) { - if (port == 0x03c4) nv_wrvgas(obj, head, index, value); - else if (port == 0x03ce) nv_wrvgag(obj, head, index, value); - else if (port == 0x03d4) nv_wrvgac(obj, head, index, value); - else nv_error(obj, "unknown indexed vga port 0x%04x\n", port); + if (port == 0x03c4) nvkm_wrvgas(device, head, index, value); + else if (port == 0x03ce) nvkm_wrvgag(device, head, index, value); + else if (port == 0x03d4) nvkm_wrvgac(device, head, index, value); } bool -nv_lockvgac(void *obj, bool lock) +nvkm_lockvgac(struct nvkm_device *device, bool lock) { - struct nvkm_device *dev = nv_device(obj); - - bool locked = !nv_rdvgac(obj, 0, 0x1f); + bool locked = !nvkm_rdvgac(device, 0, 0x1f); u8 data = lock ? 0x99 : 0x57; - if (dev->card_type < NV_50) - nv_wrvgac(obj, 0, 0x1f, data); + if (device->card_type < NV_50) + nvkm_wrvgac(device, 0, 0x1f, data); else - nv_wrvgac(obj, 0, 0x3f, data); - if (dev->chipset == 0x11) { - if (!(nv_rd32(obj, 0x001084) & 0x10000000)) - nv_wrvgac(obj, 1, 0x1f, data); + nvkm_wrvgac(device, 0, 0x3f, data); + if (device->chipset == 0x11) { + if (!(nvkm_rd32(device, 0x001084) & 0x10000000)) + nvkm_wrvgac(device, 1, 0x1f, data); } return locked; } @@ -171,16 +159,16 @@ nv_lockvgac(void *obj, bool lock) * other values are treated as literal values to set */ u8 -nv_rdvgaowner(void *obj) +nvkm_rdvgaowner(struct nvkm_device *device) { - if (nv_device(obj)->card_type < NV_50) { - if (nv_device(obj)->chipset == 0x11) { - u32 tied = nv_rd32(obj, 0x001084) & 0x10000000; + if (device->card_type < NV_50) { + if (device->chipset == 0x11) { + u32 tied = nvkm_rd32(device, 0x001084) & 0x10000000; if (tied == 0) { - u8 slA = nv_rdvgac(obj, 0, 0x28) & 0x80; - u8 tvA = nv_rdvgac(obj, 0, 0x33) & 0x01; - u8 slB = nv_rdvgac(obj, 1, 0x28) & 0x80; - u8 tvB = nv_rdvgac(obj, 1, 0x33) & 0x01; + u8 slA = nvkm_rdvgac(device, 0, 0x28) & 0x80; + u8 tvA = nvkm_rdvgac(device, 0, 0x33) & 0x01; + u8 slB = nvkm_rdvgac(device, 1, 0x28) & 0x80; + u8 tvB = nvkm_rdvgac(device, 1, 0x33) & 0x01; if (slA && !tvA) return 0x00; if (slB && !tvB) return 0x03; if (slA) return 0x00; @@ -190,30 +178,28 @@ nv_rdvgaowner(void *obj) return 0x04; } - return nv_rdvgac(obj, 0, 0x44); + return nvkm_rdvgac(device, 0, 0x44); } - nv_error(obj, "rdvgaowner after nv4x\n"); return 0x00; } void -nv_wrvgaowner(void *obj, u8 select) +nvkm_wrvgaowner(struct nvkm_device *device, u8 select) { - if (nv_device(obj)->card_type < NV_50) { + if (device->card_type < NV_50) { u8 owner = (select == 1) ? 3 : select; - if (nv_device(obj)->chipset == 0x11) { + if (device->chipset == 0x11) { /* workaround hw lockup bug */ - nv_rdvgac(obj, 0, 0x1f); - nv_rdvgac(obj, 1, 0x1f); + nvkm_rdvgac(device, 0, 0x1f); + nvkm_rdvgac(device, 1, 0x1f); } - nv_wrvgac(obj, 0, 0x44, owner); + nvkm_wrvgac(device, 0, 0x44, owner); - if (nv_device(obj)->chipset == 0x11) { - nv_wrvgac(obj, 0, 0x2e, owner); - nv_wrvgac(obj, 0, 0x2e, owner); + if (device->chipset == 0x11) { + nvkm_wrvgac(device, 0, 0x2e, owner); + nvkm_wrvgac(device, 0, 0x2e, owner); } - } else - nv_error(obj, "wrvgaowner after nv4x\n"); + } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/Kbuild new file mode 100644 index 000000000..c4a2ce9b0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/Kbuild @@ -0,0 +1,11 @@ +nvkm-y += nvkm/engine/dma/base.o +nvkm-y += nvkm/engine/dma/nv04.o +nvkm-y += nvkm/engine/dma/nv50.o +nvkm-y += nvkm/engine/dma/gf100.o +nvkm-y += nvkm/engine/dma/gf119.o + +nvkm-y += nvkm/engine/dma/user.o +nvkm-y += nvkm/engine/dma/usernv04.o +nvkm-y += nvkm/engine/dma/usernv50.o +nvkm-y += nvkm/engine/dma/usergf100.o +nvkm-y += nvkm/engine/dma/usergf119.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c new file mode 100644 index 000000000..9769fc0d5 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c @@ -0,0 +1,157 @@ +/* + * 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 "priv.h" + +#include +#include + +#include + +struct nvkm_dmaobj * +nvkm_dma_search(struct nvkm_dma *dma, struct nvkm_client *client, u64 object) +{ + struct rb_node *node = client->dmaroot.rb_node; + while (node) { + struct nvkm_dmaobj *dmaobj = + container_of(node, typeof(*dmaobj), rb); + if (object < dmaobj->handle) + node = node->rb_left; + else + if (object > dmaobj->handle) + node = node->rb_right; + else + return dmaobj; + } + return NULL; +} + +static int +nvkm_dma_oclass_new(struct nvkm_device *device, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_dma *dma = nvkm_dma(oclass->engine); + struct nvkm_dmaobj *dmaobj = NULL; + struct nvkm_client *client = oclass->client; + struct rb_node **ptr = &client->dmaroot.rb_node; + struct rb_node *parent = NULL; + int ret; + + ret = dma->func->class_new(dma, oclass, data, size, &dmaobj); + if (dmaobj) + *pobject = &dmaobj->object; + if (ret) + return ret; + + dmaobj->handle = oclass->object; + + while (*ptr) { + struct nvkm_dmaobj *obj = container_of(*ptr, typeof(*obj), rb); + parent = *ptr; + if (dmaobj->handle < obj->handle) + ptr = &parent->rb_left; + else + if (dmaobj->handle > obj->handle) + ptr = &parent->rb_right; + else + return -EEXIST; + } + + rb_link_node(&dmaobj->rb, parent, ptr); + rb_insert_color(&dmaobj->rb, &client->dmaroot); + return 0; +} + +static const struct nvkm_device_oclass +nvkm_dma_oclass_base = { + .ctor = nvkm_dma_oclass_new, +}; + +static int +nvkm_dma_oclass_fifo_new(const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + return nvkm_dma_oclass_new(oclass->engine->subdev.device, + oclass, data, size, pobject); +} + +static const struct nvkm_sclass +nvkm_dma_sclass[] = { + { 0, 0, NV_DMA_FROM_MEMORY, NULL, nvkm_dma_oclass_fifo_new }, + { 0, 0, NV_DMA_TO_MEMORY, NULL, nvkm_dma_oclass_fifo_new }, + { 0, 0, NV_DMA_IN_MEMORY, NULL, nvkm_dma_oclass_fifo_new }, +}; + +static int +nvkm_dma_oclass_base_get(struct nvkm_oclass *sclass, int index, + const struct nvkm_device_oclass **class) +{ + const int count = ARRAY_SIZE(nvkm_dma_sclass); + if (index < count) { + const struct nvkm_sclass *oclass = &nvkm_dma_sclass[index]; + sclass->base = oclass[0]; + sclass->engn = oclass; + *class = &nvkm_dma_oclass_base; + return index; + } + return count; +} + +static int +nvkm_dma_oclass_fifo_get(struct nvkm_oclass *oclass, int index) +{ + const int count = ARRAY_SIZE(nvkm_dma_sclass); + if (index < count) { + oclass->base = nvkm_dma_sclass[index]; + return index; + } + return count; +} + +static void * +nvkm_dma_dtor(struct nvkm_engine *engine) +{ + return nvkm_dma(engine); +} + +static const struct nvkm_engine_func +nvkm_dma = { + .dtor = nvkm_dma_dtor, + .base.sclass = nvkm_dma_oclass_base_get, + .fifo.sclass = nvkm_dma_oclass_fifo_get, +}; + +int +nvkm_dma_new_(const struct nvkm_dma_func *func, struct nvkm_device *device, + int index, struct nvkm_dma **pdma) +{ + struct nvkm_dma *dma; + + if (!(dma = *pdma = kzalloc(sizeof(*dma), GFP_KERNEL))) + return -ENOMEM; + dma->func = func; + + return nvkm_engine_ctor(&nvkm_dma, device, index, + 0, true, &dma->engine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf100.c new file mode 100644 index 000000000..efec5d322 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf100.c @@ -0,0 +1,36 @@ +/* + * 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 "priv.h" +#include "user.h" + +static const struct nvkm_dma_func +gf100_dma = { + .class_new = gf100_dmaobj_new, +}; + +int +gf100_dma_new(struct nvkm_device *device, int index, struct nvkm_dma **pdma) +{ + return nvkm_dma_new_(&gf100_dma, device, index, pdma); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf119.c new file mode 100644 index 000000000..34c766039 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/gf119.c @@ -0,0 +1,36 @@ +/* + * 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 "priv.h" +#include "user.h" + +static const struct nvkm_dma_func +gf119_dma = { + .class_new = gf119_dmaobj_new, +}; + +int +gf119_dma_new(struct nvkm_device *device, int index, struct nvkm_dma **pdma) +{ + return nvkm_dma_new_(&gf119_dma, device, index, pdma); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv04.c new file mode 100644 index 000000000..30747a0ce --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv04.c @@ -0,0 +1,36 @@ +/* + * 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 "priv.h" +#include "user.h" + +static const struct nvkm_dma_func +nv04_dma = { + .class_new = nv04_dmaobj_new, +}; + +int +nv04_dma_new(struct nvkm_device *device, int index, struct nvkm_dma **pdma) +{ + return nvkm_dma_new_(&nv04_dma, device, index, pdma); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv50.c new file mode 100644 index 000000000..77aca7b71 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/nv50.c @@ -0,0 +1,36 @@ +/* + * 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 "priv.h" +#include "user.h" + +static const struct nvkm_dma_func +nv50_dma = { + .class_new = nv50_dmaobj_new, +}; + +int +nv50_dma_new(struct nvkm_device *device, int index, struct nvkm_dma **pdma) +{ + return nvkm_dma_new_(&nv50_dma, device, index, pdma); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h new file mode 100644 index 000000000..deb37ee55 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h @@ -0,0 +1,18 @@ +#ifndef __NVKM_DMA_PRIV_H__ +#define __NVKM_DMA_PRIV_H__ +#define nvkm_dma(p) container_of((p), struct nvkm_dma, engine) +#include + +struct nvkm_dmaobj_func { + int (*bind)(struct nvkm_dmaobj *, struct nvkm_gpuobj *, int align, + struct nvkm_gpuobj **); +}; + +int nvkm_dma_new_(const struct nvkm_dma_func *, struct nvkm_device *, + int index, struct nvkm_dma **); + +struct nvkm_dma_func { + int (*class_new)(struct nvkm_dma *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_dmaobj **); +}; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c new file mode 100644 index 000000000..45ab06266 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c @@ -0,0 +1,144 @@ +/* + * 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 "user.h" + +#include +#include +#include +#include + +#include +#include + +static int +nvkm_dmaobj_bind(struct nvkm_object *base, struct nvkm_gpuobj *gpuobj, + int align, struct nvkm_gpuobj **pgpuobj) +{ + struct nvkm_dmaobj *dmaobj = nvkm_dmaobj(base); + return dmaobj->func->bind(dmaobj, gpuobj, align, pgpuobj); +} + +static void * +nvkm_dmaobj_dtor(struct nvkm_object *base) +{ + struct nvkm_dmaobj *dmaobj = nvkm_dmaobj(base); + if (!RB_EMPTY_NODE(&dmaobj->rb)) + rb_erase(&dmaobj->rb, &dmaobj->object.client->dmaroot); + return dmaobj; +} + +static const struct nvkm_object_func +nvkm_dmaobj_func = { + .dtor = nvkm_dmaobj_dtor, + .bind = nvkm_dmaobj_bind, +}; + +int +nvkm_dmaobj_ctor(const struct nvkm_dmaobj_func *func, struct nvkm_dma *dma, + const struct nvkm_oclass *oclass, void **pdata, u32 *psize, + struct nvkm_dmaobj *dmaobj) +{ + union { + struct nv_dma_v0 v0; + } *args = *pdata; + struct nvkm_device *device = dma->engine.subdev.device; + struct nvkm_client *client = oclass->client; + struct nvkm_object *parent = oclass->parent; + struct nvkm_instmem *instmem = device->imem; + struct nvkm_fb *fb = device->fb; + void *data = *pdata; + u32 size = *psize; + int ret; + + nvkm_object_ctor(&nvkm_dmaobj_func, oclass, &dmaobj->object); + dmaobj->func = func; + dmaobj->dma = dma; + RB_CLEAR_NODE(&dmaobj->rb); + + nvif_ioctl(parent, "create dma size %d\n", *psize); + if (nvif_unpack(args->v0, 0, 0, true)) { + nvif_ioctl(parent, "create dma vers %d target %d access %d " + "start %016llx limit %016llx\n", + args->v0.version, args->v0.target, args->v0.access, + args->v0.start, args->v0.limit); + dmaobj->target = args->v0.target; + dmaobj->access = args->v0.access; + dmaobj->start = args->v0.start; + dmaobj->limit = args->v0.limit; + } else + return ret; + + *pdata = data; + *psize = size; + + if (dmaobj->start > dmaobj->limit) + return -EINVAL; + + switch (dmaobj->target) { + case NV_DMA_V0_TARGET_VM: + dmaobj->target = NV_MEM_TARGET_VM; + break; + case NV_DMA_V0_TARGET_VRAM: + if (!client->super) { + if (dmaobj->limit >= fb->ram->size - instmem->reserved) + return -EACCES; + if (device->card_type >= NV_50) + return -EACCES; + } + dmaobj->target = NV_MEM_TARGET_VRAM; + break; + case NV_DMA_V0_TARGET_PCI: + if (!client->super) + return -EACCES; + dmaobj->target = NV_MEM_TARGET_PCI; + break; + case NV_DMA_V0_TARGET_PCI_US: + case NV_DMA_V0_TARGET_AGP: + if (!client->super) + return -EACCES; + dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP; + break; + default: + return -EINVAL; + } + + switch (dmaobj->access) { + case NV_DMA_V0_ACCESS_VM: + dmaobj->access = NV_MEM_ACCESS_VM; + break; + case NV_DMA_V0_ACCESS_RD: + dmaobj->access = NV_MEM_ACCESS_RO; + break; + case NV_DMA_V0_ACCESS_WR: + dmaobj->access = NV_MEM_ACCESS_WO; + break; + case NV_DMA_V0_ACCESS_RDWR: + dmaobj->access = NV_MEM_ACCESS_RW; + break; + default: + return -EINVAL; + } + + return ret; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h new file mode 100644 index 000000000..69a7f1034 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h @@ -0,0 +1,18 @@ +#ifndef __NVKM_DMA_USER_H__ +#define __NVKM_DMA_USER_H__ +#define nvkm_dmaobj(p) container_of((p), struct nvkm_dmaobj, object) +#include "priv.h" + +int nvkm_dmaobj_ctor(const struct nvkm_dmaobj_func *, struct nvkm_dma *, + const struct nvkm_oclass *, void **data, u32 *size, + struct nvkm_dmaobj *); + +int nv04_dmaobj_new(struct nvkm_dma *, const struct nvkm_oclass *, void *, u32, + struct nvkm_dmaobj **); +int nv50_dmaobj_new(struct nvkm_dma *, const struct nvkm_oclass *, void *, u32, + struct nvkm_dmaobj **); +int gf100_dmaobj_new(struct nvkm_dma *, const struct nvkm_oclass *, void *, u32, + struct nvkm_dmaobj **); +int gf119_dmaobj_new(struct nvkm_dma *, const struct nvkm_oclass *, void *, u32, + struct nvkm_dmaobj **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c new file mode 100644 index 000000000..13e341cc4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c @@ -0,0 +1,149 @@ +/* + * 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 + */ +#define gf100_dmaobj(p) container_of((p), struct gf100_dmaobj, base) +#include "user.h" + +#include +#include +#include + +#include +#include + +struct gf100_dmaobj { + struct nvkm_dmaobj base; + u32 flags0; + u32 flags5; +}; + +static int +gf100_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + struct gf100_dmaobj *dmaobj = gf100_dmaobj(base); + struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device; + int ret; + + ret = nvkm_gpuobj_new(device, 24, align, false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0); + nvkm_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->base.limit)); + nvkm_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->base.start)); + nvkm_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->base.limit) << 24 | + upper_32_bits(dmaobj->base.start)); + nvkm_wo32(*pgpuobj, 0x10, 0x00000000); + nvkm_wo32(*pgpuobj, 0x14, dmaobj->flags5); + nvkm_done(*pgpuobj); + } + + return ret; +} + +static const struct nvkm_dmaobj_func +gf100_dmaobj_func = { + .bind = gf100_dmaobj_bind, +}; + +int +gf100_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_dmaobj **pdmaobj) +{ + union { + struct gf100_dma_v0 v0; + } *args; + struct nvkm_object *parent = oclass->parent; + struct gf100_dmaobj *dmaobj; + u32 kind, user, unkn; + int ret; + + if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL))) + return -ENOMEM; + *pdmaobj = &dmaobj->base; + + ret = nvkm_dmaobj_ctor(&gf100_dmaobj_func, dma, oclass, + &data, &size, &dmaobj->base); + if (ret) + return ret; + + args = data; + + nvif_ioctl(parent, "create gf100 dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, + "create gf100 dma vers %d priv %d kind %02x\n", + args->v0.version, args->v0.priv, args->v0.kind); + kind = args->v0.kind; + user = args->v0.priv; + unkn = 0; + } else + if (size == 0) { + if (dmaobj->base.target != NV_MEM_TARGET_VM) { + kind = GF100_DMA_V0_KIND_PITCH; + user = GF100_DMA_V0_PRIV_US; + unkn = 2; + } else { + kind = GF100_DMA_V0_KIND_VM; + user = GF100_DMA_V0_PRIV_VM; + unkn = 0; + } + } else + return ret; + + if (user > 2) + return -EINVAL; + dmaobj->flags0 |= (kind << 22) | (user << 20) | oclass->base.oclass; + dmaobj->flags5 |= (unkn << 16); + + switch (dmaobj->base.target) { + case NV_MEM_TARGET_VM: + dmaobj->flags0 |= 0x00000000; + break; + case NV_MEM_TARGET_VRAM: + dmaobj->flags0 |= 0x00010000; + break; + case NV_MEM_TARGET_PCI: + dmaobj->flags0 |= 0x00020000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + dmaobj->flags0 |= 0x00030000; + break; + default: + return -EINVAL; + } + + switch (dmaobj->base.access) { + case NV_MEM_ACCESS_VM: + break; + case NV_MEM_ACCESS_RO: + dmaobj->flags0 |= 0x00040000; + break; + case NV_MEM_ACCESS_WO: + case NV_MEM_ACCESS_RW: + dmaobj->flags0 |= 0x00080000; + break; + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c new file mode 100644 index 000000000..0e1af8b4d --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c @@ -0,0 +1,131 @@ +/* + * 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 + */ +#define gf119_dmaobj(p) container_of((p), struct gf119_dmaobj, base) +#include "user.h" + +#include +#include +#include + +#include +#include + +struct gf119_dmaobj { + struct nvkm_dmaobj base; + u32 flags0; +}; + +static int +gf119_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + struct gf119_dmaobj *dmaobj = gf119_dmaobj(base); + struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device; + int ret; + + ret = nvkm_gpuobj_new(device, 24, align, false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0); + nvkm_wo32(*pgpuobj, 0x04, dmaobj->base.start >> 8); + nvkm_wo32(*pgpuobj, 0x08, dmaobj->base.limit >> 8); + nvkm_wo32(*pgpuobj, 0x0c, 0x00000000); + nvkm_wo32(*pgpuobj, 0x10, 0x00000000); + nvkm_wo32(*pgpuobj, 0x14, 0x00000000); + nvkm_done(*pgpuobj); + } + + return ret; +} + +static const struct nvkm_dmaobj_func +gf119_dmaobj_func = { + .bind = gf119_dmaobj_bind, +}; + +int +gf119_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_dmaobj **pdmaobj) +{ + union { + struct gf119_dma_v0 v0; + } *args; + struct nvkm_object *parent = oclass->parent; + struct gf119_dmaobj *dmaobj; + u32 kind, page; + int ret; + + if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL))) + return -ENOMEM; + *pdmaobj = &dmaobj->base; + + ret = nvkm_dmaobj_ctor(&gf119_dmaobj_func, dma, oclass, + &data, &size, &dmaobj->base); + if (ret) + return ret; + + args = data; + + nvif_ioctl(parent, "create gf119 dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, + "create gf100 dma vers %d page %d kind %02x\n", + args->v0.version, args->v0.page, args->v0.kind); + kind = args->v0.kind; + page = args->v0.page; + } else + if (size == 0) { + if (dmaobj->base.target != NV_MEM_TARGET_VM) { + kind = GF119_DMA_V0_KIND_PITCH; + page = GF119_DMA_V0_PAGE_SP; + } else { + kind = GF119_DMA_V0_KIND_VM; + page = GF119_DMA_V0_PAGE_LP; + } + } else + return ret; + + if (page > 1) + return -EINVAL; + dmaobj->flags0 = (kind << 20) | (page << 6); + + switch (dmaobj->base.target) { + case NV_MEM_TARGET_VRAM: + dmaobj->flags0 |= 0x00000009; + break; + case NV_MEM_TARGET_VM: + case NV_MEM_TARGET_PCI: + case NV_MEM_TARGET_PCI_NOSNOOP: + /* XXX: don't currently know how to construct a real one + * of these. we only use them to represent pushbufs + * on these chipsets, and the classes that use them + * deal with the target themselves. + */ + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c new file mode 100644 index 000000000..c95942ef8 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c @@ -0,0 +1,133 @@ +/* + * 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 + */ +#define nv04_dmaobj(p) container_of((p), struct nv04_dmaobj, base) +#include "user.h" + +#include +#include +#include + +#include + +struct nv04_dmaobj { + struct nvkm_dmaobj base; + bool clone; + u32 flags0; + u32 flags2; +}; + +static int +nv04_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + struct nv04_dmaobj *dmaobj = nv04_dmaobj(base); + struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device; + u64 offset = dmaobj->base.start & 0xfffff000; + u64 adjust = dmaobj->base.start & 0x00000fff; + u32 length = dmaobj->base.limit - dmaobj->base.start; + int ret; + + if (dmaobj->clone) { + struct nv04_mmu *mmu = nv04_mmu(device->mmu); + struct nvkm_memory *pgt = mmu->vm->pgt[0].mem[0]; + if (!dmaobj->base.start) + return nvkm_gpuobj_wrap(pgt, pgpuobj); + nvkm_kmap(pgt); + offset = nvkm_ro32(pgt, 8 + (offset >> 10)); + offset &= 0xfffff000; + nvkm_done(pgt); + } + + ret = nvkm_gpuobj_new(device, 16, align, false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0 | (adjust << 20)); + nvkm_wo32(*pgpuobj, 0x04, length); + nvkm_wo32(*pgpuobj, 0x08, dmaobj->flags2 | offset); + nvkm_wo32(*pgpuobj, 0x0c, dmaobj->flags2 | offset); + nvkm_done(*pgpuobj); + } + + return ret; +} + +static const struct nvkm_dmaobj_func +nv04_dmaobj_func = { + .bind = nv04_dmaobj_bind, +}; + +int +nv04_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_dmaobj **pdmaobj) +{ + struct nvkm_device *device = dma->engine.subdev.device; + struct nv04_dmaobj *dmaobj; + int ret; + + if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL))) + return -ENOMEM; + *pdmaobj = &dmaobj->base; + + ret = nvkm_dmaobj_ctor(&nv04_dmaobj_func, dma, oclass, + &data, &size, &dmaobj->base); + if (ret) + return ret; + + if (dmaobj->base.target == NV_MEM_TARGET_VM) { + if (device->mmu->func == &nv04_mmu) + dmaobj->clone = true; + dmaobj->base.target = NV_MEM_TARGET_PCI; + dmaobj->base.access = NV_MEM_ACCESS_RW; + } + + dmaobj->flags0 = oclass->base.oclass; + switch (dmaobj->base.target) { + case NV_MEM_TARGET_VRAM: + dmaobj->flags0 |= 0x00003000; + break; + case NV_MEM_TARGET_PCI: + dmaobj->flags0 |= 0x00023000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + dmaobj->flags0 |= 0x00033000; + break; + default: + return -EINVAL; + } + + switch (dmaobj->base.access) { + case NV_MEM_ACCESS_RO: + dmaobj->flags0 |= 0x00004000; + break; + case NV_MEM_ACCESS_WO: + dmaobj->flags0 |= 0x00008000; + case NV_MEM_ACCESS_RW: + dmaobj->flags2 |= 0x00000002; + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c new file mode 100644 index 000000000..5b7ce313e --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c @@ -0,0 +1,156 @@ +/* + * 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 + */ +#define nv50_dmaobj(p) container_of((p), struct nv50_dmaobj, base) +#include "user.h" + +#include +#include +#include + +#include +#include + +struct nv50_dmaobj { + struct nvkm_dmaobj base; + u32 flags0; + u32 flags5; +}; + +static int +nv50_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + struct nv50_dmaobj *dmaobj = nv50_dmaobj(base); + struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device; + int ret; + + ret = nvkm_gpuobj_new(device, 24, align, false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0); + nvkm_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->base.limit)); + nvkm_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->base.start)); + nvkm_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->base.limit) << 24 | + upper_32_bits(dmaobj->base.start)); + nvkm_wo32(*pgpuobj, 0x10, 0x00000000); + nvkm_wo32(*pgpuobj, 0x14, dmaobj->flags5); + nvkm_done(*pgpuobj); + } + + return ret; +} + +static const struct nvkm_dmaobj_func +nv50_dmaobj_func = { + .bind = nv50_dmaobj_bind, +}; + +int +nv50_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_dmaobj **pdmaobj) +{ + union { + struct nv50_dma_v0 v0; + } *args; + struct nvkm_object *parent = oclass->parent; + struct nv50_dmaobj *dmaobj; + u32 user, part, comp, kind; + int ret; + + if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL))) + return -ENOMEM; + *pdmaobj = &dmaobj->base; + + ret = nvkm_dmaobj_ctor(&nv50_dmaobj_func, dma, oclass, + &data, &size, &dmaobj->base); + if (ret) + return ret; + + args = data; + + nvif_ioctl(parent, "create nv50 dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create nv50 dma vers %d priv %d part %d " + "comp %d kind %02x\n", args->v0.version, + args->v0.priv, args->v0.part, args->v0.comp, + args->v0.kind); + user = args->v0.priv; + part = args->v0.part; + comp = args->v0.comp; + kind = args->v0.kind; + } else + if (size == 0) { + if (dmaobj->base.target != NV_MEM_TARGET_VM) { + user = NV50_DMA_V0_PRIV_US; + part = NV50_DMA_V0_PART_256; + comp = NV50_DMA_V0_COMP_NONE; + kind = NV50_DMA_V0_KIND_PITCH; + } else { + user = NV50_DMA_V0_PRIV_VM; + part = NV50_DMA_V0_PART_VM; + comp = NV50_DMA_V0_COMP_VM; + kind = NV50_DMA_V0_KIND_VM; + } + } else + return ret; + + if (user > 2 || part > 2 || comp > 3 || kind > 0x7f) + return -EINVAL; + dmaobj->flags0 = (comp << 29) | (kind << 22) | (user << 20) | + oclass->base.oclass; + dmaobj->flags5 = (part << 16); + + switch (dmaobj->base.target) { + case NV_MEM_TARGET_VM: + dmaobj->flags0 |= 0x00000000; + break; + case NV_MEM_TARGET_VRAM: + dmaobj->flags0 |= 0x00010000; + break; + case NV_MEM_TARGET_PCI: + dmaobj->flags0 |= 0x00020000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + dmaobj->flags0 |= 0x00030000; + break; + default: + return -EINVAL; + } + + switch (dmaobj->base.access) { + case NV_MEM_ACCESS_VM: + break; + case NV_MEM_ACCESS_RO: + dmaobj->flags0 |= 0x00040000; + break; + case NV_MEM_ACCESS_WO: + case NV_MEM_ACCESS_RW: + dmaobj->flags0 |= 0x00080000; + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/Kbuild deleted file mode 100644 index 7529632db..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -nvkm-y += nvkm/engine/dmaobj/base.o -nvkm-y += nvkm/engine/dmaobj/nv04.o -nvkm-y += nvkm/engine/dmaobj/nv50.o -nvkm-y += nvkm/engine/dmaobj/gf100.o -nvkm-y += nvkm/engine/dmaobj/gf110.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/base.c deleted file mode 100644 index a2b60d86b..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/base.c +++ /dev/null @@ -1,164 +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 "priv.h" - -#include -#include -#include -#include - -#include -#include - -static int -nvkm_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, - struct nvkm_gpuobj **pgpuobj) -{ - const struct nvkm_dmaeng_impl *impl = (void *) - nv_oclass(nv_object(dmaobj)->engine); - int ret = 0; - - if (nv_object(dmaobj) == parent) { /* ctor bind */ - if (nv_mclass(parent->parent) == NV_DEVICE) { - /* delayed, or no, binding */ - return 0; - } - ret = impl->bind(dmaobj, parent, pgpuobj); - if (ret == 0) - nvkm_object_ref(NULL, &parent); - return ret; - } - - return impl->bind(dmaobj, parent, pgpuobj); -} - -int -nvkm_dmaobj_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void **pdata, u32 *psize, - int length, void **pobject) -{ - union { - struct nv_dma_v0 v0; - } *args = *pdata; - struct nvkm_instmem *instmem = nvkm_instmem(parent); - struct nvkm_client *client = nvkm_client(parent); - struct nvkm_device *device = nv_device(parent); - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_dmaobj *dmaobj; - void *data = *pdata; - u32 size = *psize; - int ret; - - ret = nvkm_object_create_(parent, engine, oclass, 0, length, pobject); - dmaobj = *pobject; - if (ret) - return ret; - - nv_ioctl(parent, "create dma size %d\n", *psize); - if (nvif_unpack(args->v0, 0, 0, true)) { - nv_ioctl(parent, "create dma vers %d target %d access %d " - "start %016llx limit %016llx\n", - args->v0.version, args->v0.target, args->v0.access, - args->v0.start, args->v0.limit); - dmaobj->target = args->v0.target; - dmaobj->access = args->v0.access; - dmaobj->start = args->v0.start; - dmaobj->limit = args->v0.limit; - } else - return ret; - - *pdata = data; - *psize = size; - - if (dmaobj->start > dmaobj->limit) - return -EINVAL; - - switch (dmaobj->target) { - case NV_DMA_V0_TARGET_VM: - dmaobj->target = NV_MEM_TARGET_VM; - break; - case NV_DMA_V0_TARGET_VRAM: - if (!client->super) { - if (dmaobj->limit >= pfb->ram->size - instmem->reserved) - return -EACCES; - if (device->card_type >= NV_50) - return -EACCES; - } - dmaobj->target = NV_MEM_TARGET_VRAM; - break; - case NV_DMA_V0_TARGET_PCI: - if (!client->super) - return -EACCES; - dmaobj->target = NV_MEM_TARGET_PCI; - break; - case NV_DMA_V0_TARGET_PCI_US: - case NV_DMA_V0_TARGET_AGP: - if (!client->super) - return -EACCES; - dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP; - break; - default: - return -EINVAL; - } - - switch (dmaobj->access) { - case NV_DMA_V0_ACCESS_VM: - dmaobj->access = NV_MEM_ACCESS_VM; - break; - case NV_DMA_V0_ACCESS_RD: - dmaobj->access = NV_MEM_ACCESS_RO; - break; - case NV_DMA_V0_ACCESS_WR: - dmaobj->access = NV_MEM_ACCESS_WO; - break; - case NV_DMA_V0_ACCESS_RDWR: - dmaobj->access = NV_MEM_ACCESS_RW; - break; - default: - return -EINVAL; - } - - return ret; -} - -int -_nvkm_dmaeng_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - const struct nvkm_dmaeng_impl *impl = (void *)oclass; - struct nvkm_dmaeng *dmaeng; - int ret; - - ret = nvkm_engine_create(parent, engine, oclass, true, "DMAOBJ", - "dmaobj", &dmaeng); - *pobject = nv_object(dmaeng); - if (ret) - return ret; - - nv_engine(dmaeng)->sclass = impl->sclass; - dmaeng->bind = nvkm_dmaobj_bind; - return 0; -} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf100.c deleted file mode 100644 index f880e5167..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf100.c +++ /dev/null @@ -1,176 +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 "priv.h" - -#include -#include -#include - -#include -#include - -struct gf100_dmaobj_priv { - struct nvkm_dmaobj base; - u32 flags0; - u32 flags5; -}; - -static int -gf100_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, - struct nvkm_gpuobj **pgpuobj) -{ - struct gf100_dmaobj_priv *priv = (void *)dmaobj; - int ret; - - if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { - switch (nv_mclass(parent->parent)) { - case GT214_DISP_CORE_CHANNEL_DMA: - case GT214_DISP_BASE_CHANNEL_DMA: - case GT214_DISP_OVERLAY_CHANNEL_DMA: - break; - default: - return -EINVAL; - } - } else - return 0; - - ret = nvkm_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); - if (ret == 0) { - nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj)); - nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit)); - nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start)); - nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 | - upper_32_bits(priv->base.start)); - nv_wo32(*pgpuobj, 0x10, 0x00000000); - nv_wo32(*pgpuobj, 0x14, priv->flags5); - } - - return ret; -} - -static int -gf100_dmaobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_dmaeng *dmaeng = (void *)engine; - union { - struct gf100_dma_v0 v0; - } *args; - struct gf100_dmaobj_priv *priv; - u32 kind, user, unkn; - int ret; - - ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - args = data; - - nv_ioctl(parent, "create gf100 dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create gf100 dma vers %d priv %d kind %02x\n", - args->v0.version, args->v0.priv, args->v0.kind); - kind = args->v0.kind; - user = args->v0.priv; - unkn = 0; - } else - if (size == 0) { - if (priv->base.target != NV_MEM_TARGET_VM) { - kind = GF100_DMA_V0_KIND_PITCH; - user = GF100_DMA_V0_PRIV_US; - unkn = 2; - } else { - kind = GF100_DMA_V0_KIND_VM; - user = GF100_DMA_V0_PRIV_VM; - unkn = 0; - } - } else - return ret; - - if (user > 2) - return -EINVAL; - priv->flags0 |= (kind << 22) | (user << 20); - priv->flags5 |= (unkn << 16); - - switch (priv->base.target) { - case NV_MEM_TARGET_VM: - priv->flags0 |= 0x00000000; - break; - case NV_MEM_TARGET_VRAM: - priv->flags0 |= 0x00010000; - break; - case NV_MEM_TARGET_PCI: - priv->flags0 |= 0x00020000; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - priv->flags0 |= 0x00030000; - break; - default: - return -EINVAL; - } - - switch (priv->base.access) { - case NV_MEM_ACCESS_VM: - break; - case NV_MEM_ACCESS_RO: - priv->flags0 |= 0x00040000; - break; - case NV_MEM_ACCESS_WO: - case NV_MEM_ACCESS_RW: - priv->flags0 |= 0x00080000; - break; - } - - return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); -} - -static struct nvkm_ofuncs -gf100_dmaobj_ofuncs = { - .ctor = gf100_dmaobj_ctor, - .dtor = _nvkm_dmaobj_dtor, - .init = _nvkm_dmaobj_init, - .fini = _nvkm_dmaobj_fini, -}; - -static struct nvkm_oclass -gf100_dmaeng_sclass[] = { - { NV_DMA_FROM_MEMORY, &gf100_dmaobj_ofuncs }, - { NV_DMA_TO_MEMORY, &gf100_dmaobj_ofuncs }, - { NV_DMA_IN_MEMORY, &gf100_dmaobj_ofuncs }, - {} -}; - -struct nvkm_oclass * -gf100_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { - .base.handle = NV_ENGINE(DMAOBJ, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_dmaeng_ctor, - .dtor = _nvkm_dmaeng_dtor, - .init = _nvkm_dmaeng_init, - .fini = _nvkm_dmaeng_fini, - }, - .sclass = gf100_dmaeng_sclass, - .bind = gf100_dmaobj_bind, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf110.c deleted file mode 100644 index bf8f0f209..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/gf110.c +++ /dev/null @@ -1,165 +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 "priv.h" - -#include -#include -#include - -#include -#include - -struct gf110_dmaobj_priv { - struct nvkm_dmaobj base; - u32 flags0; -}; - -static int -gf110_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, - struct nvkm_gpuobj **pgpuobj) -{ - struct gf110_dmaobj_priv *priv = (void *)dmaobj; - int ret; - - if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { - switch (nv_mclass(parent->parent)) { - case GF110_DISP_CORE_CHANNEL_DMA: - case GK104_DISP_CORE_CHANNEL_DMA: - case GK110_DISP_CORE_CHANNEL_DMA: - case GM107_DISP_CORE_CHANNEL_DMA: - case GM204_DISP_CORE_CHANNEL_DMA: - case GF110_DISP_BASE_CHANNEL_DMA: - case GK104_DISP_BASE_CHANNEL_DMA: - case GK110_DISP_BASE_CHANNEL_DMA: - case GF110_DISP_OVERLAY_CONTROL_DMA: - case GK104_DISP_OVERLAY_CONTROL_DMA: - break; - default: - return -EINVAL; - } - } else - return 0; - - ret = nvkm_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); - if (ret == 0) { - nv_wo32(*pgpuobj, 0x00, priv->flags0); - nv_wo32(*pgpuobj, 0x04, priv->base.start >> 8); - nv_wo32(*pgpuobj, 0x08, priv->base.limit >> 8); - nv_wo32(*pgpuobj, 0x0c, 0x00000000); - nv_wo32(*pgpuobj, 0x10, 0x00000000); - nv_wo32(*pgpuobj, 0x14, 0x00000000); - } - - return ret; -} - -static int -gf110_dmaobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_dmaeng *dmaeng = (void *)engine; - union { - struct gf110_dma_v0 v0; - } *args; - struct gf110_dmaobj_priv *priv; - u32 kind, page; - int ret; - - ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - args = data; - - nv_ioctl(parent, "create gf110 dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create gf100 dma vers %d page %d kind %02x\n", - args->v0.version, args->v0.page, args->v0.kind); - kind = args->v0.kind; - page = args->v0.page; - } else - if (size == 0) { - if (priv->base.target != NV_MEM_TARGET_VM) { - kind = GF110_DMA_V0_KIND_PITCH; - page = GF110_DMA_V0_PAGE_SP; - } else { - kind = GF110_DMA_V0_KIND_VM; - page = GF110_DMA_V0_PAGE_LP; - } - } else - return ret; - - if (page > 1) - return -EINVAL; - priv->flags0 = (kind << 20) | (page << 6); - - switch (priv->base.target) { - case NV_MEM_TARGET_VRAM: - priv->flags0 |= 0x00000009; - break; - case NV_MEM_TARGET_VM: - case NV_MEM_TARGET_PCI: - case NV_MEM_TARGET_PCI_NOSNOOP: - /* XXX: don't currently know how to construct a real one - * of these. we only use them to represent pushbufs - * on these chipsets, and the classes that use them - * deal with the target themselves. - */ - break; - default: - return -EINVAL; - } - - return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); -} - -static struct nvkm_ofuncs -gf110_dmaobj_ofuncs = { - .ctor = gf110_dmaobj_ctor, - .dtor = _nvkm_dmaobj_dtor, - .init = _nvkm_dmaobj_init, - .fini = _nvkm_dmaobj_fini, -}; - -static struct nvkm_oclass -gf110_dmaeng_sclass[] = { - { NV_DMA_FROM_MEMORY, &gf110_dmaobj_ofuncs }, - { NV_DMA_TO_MEMORY, &gf110_dmaobj_ofuncs }, - { NV_DMA_IN_MEMORY, &gf110_dmaobj_ofuncs }, - {} -}; - -struct nvkm_oclass * -gf110_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { - .base.handle = NV_ENGINE(DMAOBJ, 0xd0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_dmaeng_ctor, - .dtor = _nvkm_dmaeng_dtor, - .init = _nvkm_dmaeng_init, - .fini = _nvkm_dmaeng_fini, - }, - .sclass = gf110_dmaeng_sclass, - .bind = gf110_dmaobj_bind, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv04.c deleted file mode 100644 index b4379c2a2..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv04.c +++ /dev/null @@ -1,163 +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 "priv.h" - -#include -#include -#include - -#include - -struct nv04_dmaobj_priv { - struct nvkm_dmaobj base; - bool clone; - u32 flags0; - u32 flags2; -}; - -static int -nv04_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, - struct nvkm_gpuobj **pgpuobj) -{ - struct nv04_dmaobj_priv *priv = (void *)dmaobj; - struct nvkm_gpuobj *gpuobj; - u64 offset = priv->base.start & 0xfffff000; - u64 adjust = priv->base.start & 0x00000fff; - u32 length = priv->base.limit - priv->base.start; - int ret; - - if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { - switch (nv_mclass(parent->parent)) { - case NV03_CHANNEL_DMA: - case NV10_CHANNEL_DMA: - case NV17_CHANNEL_DMA: - case NV40_CHANNEL_DMA: - break; - default: - return -EINVAL; - } - } - - if (priv->clone) { - struct nv04_mmu_priv *mmu = nv04_mmu(dmaobj); - struct nvkm_gpuobj *pgt = mmu->vm->pgt[0].obj[0]; - if (!dmaobj->start) - return nvkm_gpuobj_dup(parent, pgt, pgpuobj); - offset = nv_ro32(pgt, 8 + (offset >> 10)); - offset &= 0xfffff000; - } - - ret = nvkm_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj); - *pgpuobj = gpuobj; - if (ret == 0) { - nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20)); - nv_wo32(*pgpuobj, 0x04, length); - nv_wo32(*pgpuobj, 0x08, priv->flags2 | offset); - nv_wo32(*pgpuobj, 0x0c, priv->flags2 | offset); - } - - return ret; -} - -static int -nv04_dmaobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_dmaeng *dmaeng = (void *)engine; - struct nv04_mmu_priv *mmu = nv04_mmu(engine); - struct nv04_dmaobj_priv *priv; - int ret; - - ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv); - *pobject = nv_object(priv); - if (ret || (ret = -ENOSYS, size)) - return ret; - - if (priv->base.target == NV_MEM_TARGET_VM) { - if (nv_object(mmu)->oclass == &nv04_mmu_oclass) - priv->clone = true; - priv->base.target = NV_MEM_TARGET_PCI; - priv->base.access = NV_MEM_ACCESS_RW; - } - - priv->flags0 = nv_mclass(priv); - switch (priv->base.target) { - case NV_MEM_TARGET_VRAM: - priv->flags0 |= 0x00003000; - break; - case NV_MEM_TARGET_PCI: - priv->flags0 |= 0x00023000; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - priv->flags0 |= 0x00033000; - break; - default: - return -EINVAL; - } - - switch (priv->base.access) { - case NV_MEM_ACCESS_RO: - priv->flags0 |= 0x00004000; - break; - case NV_MEM_ACCESS_WO: - priv->flags0 |= 0x00008000; - case NV_MEM_ACCESS_RW: - priv->flags2 |= 0x00000002; - break; - default: - return -EINVAL; - } - - return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); -} - -static struct nvkm_ofuncs -nv04_dmaobj_ofuncs = { - .ctor = nv04_dmaobj_ctor, - .dtor = _nvkm_dmaobj_dtor, - .init = _nvkm_dmaobj_init, - .fini = _nvkm_dmaobj_fini, -}; - -static struct nvkm_oclass -nv04_dmaeng_sclass[] = { - { NV_DMA_FROM_MEMORY, &nv04_dmaobj_ofuncs }, - { NV_DMA_TO_MEMORY, &nv04_dmaobj_ofuncs }, - { NV_DMA_IN_MEMORY, &nv04_dmaobj_ofuncs }, - {} -}; - -struct nvkm_oclass * -nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { - .base.handle = NV_ENGINE(DMAOBJ, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_dmaeng_ctor, - .dtor = _nvkm_dmaeng_dtor, - .init = _nvkm_dmaeng_init, - .fini = _nvkm_dmaeng_fini, - }, - .sclass = nv04_dmaeng_sclass, - .bind = nv04_dmaobj_bind, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv50.c deleted file mode 100644 index 4d3c828fe..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/nv50.c +++ /dev/null @@ -1,195 +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 "priv.h" - -#include -#include -#include - -#include -#include - -struct nv50_dmaobj_priv { - struct nvkm_dmaobj base; - u32 flags0; - u32 flags5; -}; - -static int -nv50_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, - struct nvkm_gpuobj **pgpuobj) -{ - struct nv50_dmaobj_priv *priv = (void *)dmaobj; - int ret; - - if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { - switch (nv_mclass(parent->parent)) { - case NV40_CHANNEL_DMA: - case NV50_CHANNEL_GPFIFO: - case G82_CHANNEL_GPFIFO: - case NV50_DISP_CORE_CHANNEL_DMA: - case G82_DISP_CORE_CHANNEL_DMA: - case GT206_DISP_CORE_CHANNEL_DMA: - case GT200_DISP_CORE_CHANNEL_DMA: - case GT214_DISP_CORE_CHANNEL_DMA: - case NV50_DISP_BASE_CHANNEL_DMA: - case G82_DISP_BASE_CHANNEL_DMA: - case GT200_DISP_BASE_CHANNEL_DMA: - case GT214_DISP_BASE_CHANNEL_DMA: - case NV50_DISP_OVERLAY_CHANNEL_DMA: - case G82_DISP_OVERLAY_CHANNEL_DMA: - case GT200_DISP_OVERLAY_CHANNEL_DMA: - case GT214_DISP_OVERLAY_CHANNEL_DMA: - break; - default: - return -EINVAL; - } - } - - ret = nvkm_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); - if (ret == 0) { - nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj)); - nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit)); - nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start)); - nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 | - upper_32_bits(priv->base.start)); - nv_wo32(*pgpuobj, 0x10, 0x00000000); - nv_wo32(*pgpuobj, 0x14, priv->flags5); - } - - return ret; -} - -static int -nv50_dmaobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_dmaeng *dmaeng = (void *)engine; - union { - struct nv50_dma_v0 v0; - } *args; - struct nv50_dmaobj_priv *priv; - u32 user, part, comp, kind; - int ret; - - ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - args = data; - - nv_ioctl(parent, "create nv50 dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create nv50 dma vers %d priv %d part %d " - "comp %d kind %02x\n", args->v0.version, - args->v0.priv, args->v0.part, args->v0.comp, - args->v0.kind); - user = args->v0.priv; - part = args->v0.part; - comp = args->v0.comp; - kind = args->v0.kind; - } else - if (size == 0) { - if (priv->base.target != NV_MEM_TARGET_VM) { - user = NV50_DMA_V0_PRIV_US; - part = NV50_DMA_V0_PART_256; - comp = NV50_DMA_V0_COMP_NONE; - kind = NV50_DMA_V0_KIND_PITCH; - } else { - user = NV50_DMA_V0_PRIV_VM; - part = NV50_DMA_V0_PART_VM; - comp = NV50_DMA_V0_COMP_VM; - kind = NV50_DMA_V0_KIND_VM; - } - } else - return ret; - - if (user > 2 || part > 2 || comp > 3 || kind > 0x7f) - return -EINVAL; - priv->flags0 = (comp << 29) | (kind << 22) | (user << 20); - priv->flags5 = (part << 16); - - switch (priv->base.target) { - case NV_MEM_TARGET_VM: - priv->flags0 |= 0x00000000; - break; - case NV_MEM_TARGET_VRAM: - priv->flags0 |= 0x00010000; - break; - case NV_MEM_TARGET_PCI: - priv->flags0 |= 0x00020000; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - priv->flags0 |= 0x00030000; - break; - default: - return -EINVAL; - } - - switch (priv->base.access) { - case NV_MEM_ACCESS_VM: - break; - case NV_MEM_ACCESS_RO: - priv->flags0 |= 0x00040000; - break; - case NV_MEM_ACCESS_WO: - case NV_MEM_ACCESS_RW: - priv->flags0 |= 0x00080000; - break; - default: - return -EINVAL; - } - - return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject); -} - -static struct nvkm_ofuncs -nv50_dmaobj_ofuncs = { - .ctor = nv50_dmaobj_ctor, - .dtor = _nvkm_dmaobj_dtor, - .init = _nvkm_dmaobj_init, - .fini = _nvkm_dmaobj_fini, -}; - -static struct nvkm_oclass -nv50_dmaeng_sclass[] = { - { NV_DMA_FROM_MEMORY, &nv50_dmaobj_ofuncs }, - { NV_DMA_TO_MEMORY, &nv50_dmaobj_ofuncs }, - { NV_DMA_IN_MEMORY, &nv50_dmaobj_ofuncs }, - {} -}; - -struct nvkm_oclass * -nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) { - .base.handle = NV_ENGINE(DMAOBJ, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_dmaeng_ctor, - .dtor = _nvkm_dmaeng_dtor, - .init = _nvkm_dmaeng_init, - .fini = _nvkm_dmaeng_fini, - }, - .sclass = nv50_dmaeng_sclass, - .bind = nv50_dmaobj_bind, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/priv.h deleted file mode 100644 index 44ae8a0ca..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/priv.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __NVKM_DMAOBJ_PRIV_H__ -#define __NVKM_DMAOBJ_PRIV_H__ -#include - -#define nvkm_dmaobj_create(p,e,c,pa,sa,d) \ - nvkm_dmaobj_create_((p), (e), (c), (pa), (sa), sizeof(**d), (void **)d) - -int nvkm_dmaobj_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void **, u32 *, - int, void **); -#define _nvkm_dmaobj_dtor nvkm_object_destroy -#define _nvkm_dmaobj_init nvkm_object_init -#define _nvkm_dmaobj_fini nvkm_object_fini - -int _nvkm_dmaeng_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -#define _nvkm_dmaeng_dtor _nvkm_engine_dtor -#define _nvkm_dmaeng_init _nvkm_engine_init -#define _nvkm_dmaeng_fini _nvkm_engine_fini - -struct nvkm_dmaeng_impl { - struct nvkm_oclass base; - struct nvkm_oclass *sclass; - int (*bind)(struct nvkm_dmaobj *, struct nvkm_object *, - struct nvkm_gpuobj **); -}; -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c index 30958c19e..74000602f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c @@ -21,40 +21,95 @@ */ #include -#include +#include #include +#include -void -nvkm_falcon_intr(struct nvkm_subdev *subdev) +static int +nvkm_falcon_oclass_get(struct nvkm_oclass *oclass, int index) { - struct nvkm_falcon *falcon = (void *)subdev; - u32 dispatch = nv_ro32(falcon, 0x01c); - u32 intr = nv_ro32(falcon, 0x008) & dispatch & ~(dispatch >> 16); + struct nvkm_falcon *falcon = nvkm_falcon(oclass->engine); + int c = 0; + + while (falcon->func->sclass[c].oclass) { + if (c++ == index) { + oclass->base = falcon->func->sclass[index]; + return index; + } + } + + return c; +} + +static int +nvkm_falcon_cclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + return nvkm_gpuobj_new(object->engine->subdev.device, 256, + align, true, parent, pgpuobj); +} + +static const struct nvkm_object_func +nvkm_falcon_cclass = { + .bind = nvkm_falcon_cclass_bind, +}; + +static void +nvkm_falcon_intr(struct nvkm_engine *engine) +{ + struct nvkm_falcon *falcon = nvkm_falcon(engine); + struct nvkm_subdev *subdev = &falcon->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 base = falcon->addr; + u32 dest = nvkm_rd32(device, base + 0x01c); + u32 intr = nvkm_rd32(device, base + 0x008) & dest & ~(dest >> 16); + u32 inst = nvkm_rd32(device, base + 0x050) & 0x3fffffff; + struct nvkm_fifo_chan *chan; + unsigned long flags; + + chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags); + + if (intr & 0x00000040) { + if (falcon->func->intr) { + falcon->func->intr(falcon, chan); + nvkm_wr32(device, base + 0x004, 0x00000040); + intr &= ~0x00000040; + } + } if (intr & 0x00000010) { - nv_debug(falcon, "ucode halted\n"); - nv_wo32(falcon, 0x004, 0x00000010); + nvkm_debug(subdev, "ucode halted\n"); + nvkm_wr32(device, base + 0x004, 0x00000010); intr &= ~0x00000010; } if (intr) { - nv_error(falcon, "unhandled intr 0x%08x\n", intr); - nv_wo32(falcon, 0x004, intr); + nvkm_error(subdev, "intr %08x\n", intr); + nvkm_wr32(device, base + 0x004, intr); } -} -u32 -_nvkm_falcon_rd32(struct nvkm_object *object, u64 addr) -{ - struct nvkm_falcon *falcon = (void *)object; - return nv_rd32(falcon, falcon->addr + addr); + nvkm_fifo_chan_put(device->fifo, flags, &chan); } -void -_nvkm_falcon_wr32(struct nvkm_object *object, u64 addr, u32 data) +static int +nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend) { - struct nvkm_falcon *falcon = (void *)object; - nv_wr32(falcon, falcon->addr + addr, data); + struct nvkm_falcon *falcon = nvkm_falcon(engine); + struct nvkm_device *device = falcon->engine.subdev.device; + const u32 base = falcon->addr; + + if (!suspend) { + nvkm_memory_del(&falcon->core); + if (falcon->external) { + vfree(falcon->data.data); + vfree(falcon->code.data); + falcon->code.data = NULL; + } + } + + nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000); + nvkm_wr32(device, base + 0x014, 0xffffffff); + return 0; } static void * @@ -67,51 +122,66 @@ vmemdup(const void *src, size_t len) return p; } -int -_nvkm_falcon_init(struct nvkm_object *object) +static int +nvkm_falcon_oneinit(struct nvkm_engine *engine) { - struct nvkm_device *device = nv_device(object); - struct nvkm_falcon *falcon = (void *)object; - const struct firmware *fw; - char name[32] = "internal"; - int ret, i; + struct nvkm_falcon *falcon = nvkm_falcon(engine); + struct nvkm_subdev *subdev = &falcon->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 base = falcon->addr; u32 caps; - /* enable engine, and determine its capabilities */ - ret = nvkm_engine_init(&falcon->base); - if (ret) - return ret; - + /* determine falcon capabilities */ if (device->chipset < 0xa3 || device->chipset == 0xaa || device->chipset == 0xac) { falcon->version = 0; falcon->secret = (falcon->addr == 0x087000) ? 1 : 0; } else { - caps = nv_ro32(falcon, 0x12c); + caps = nvkm_rd32(device, base + 0x12c); falcon->version = (caps & 0x0000000f); falcon->secret = (caps & 0x00000030) >> 4; } - caps = nv_ro32(falcon, 0x108); + caps = nvkm_rd32(device, base + 0x108); falcon->code.limit = (caps & 0x000001ff) << 8; falcon->data.limit = (caps & 0x0003fe00) >> 1; - nv_debug(falcon, "falcon version: %d\n", falcon->version); - nv_debug(falcon, "secret level: %d\n", falcon->secret); - nv_debug(falcon, "code limit: %d\n", falcon->code.limit); - nv_debug(falcon, "data limit: %d\n", falcon->data.limit); + nvkm_debug(subdev, "falcon version: %d\n", falcon->version); + nvkm_debug(subdev, "secret level: %d\n", falcon->secret); + nvkm_debug(subdev, "code limit: %d\n", falcon->code.limit); + nvkm_debug(subdev, "data limit: %d\n", falcon->data.limit); + return 0; +} + +static int +nvkm_falcon_init(struct nvkm_engine *engine) +{ + struct nvkm_falcon *falcon = nvkm_falcon(engine); + struct nvkm_subdev *subdev = &falcon->engine.subdev; + struct nvkm_device *device = subdev->device; + const struct firmware *fw; + char name[32] = "internal"; + const u32 base = falcon->addr; + int ret, i; /* wait for 'uc halted' to be signalled before continuing */ if (falcon->secret && falcon->version < 4) { - if (!falcon->version) - nv_wait(falcon, 0x008, 0x00000010, 0x00000010); - else - nv_wait(falcon, 0x180, 0x80000000, 0); - nv_wo32(falcon, 0x004, 0x00000010); + if (!falcon->version) { + nvkm_msec(device, 2000, + if (nvkm_rd32(device, base + 0x008) & 0x00000010) + break; + ); + } else { + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, base + 0x180) & 0x80000000)) + break; + ); + } + nvkm_wr32(device, base + 0x004, 0x00000010); } /* disable all interrupts */ - nv_wo32(falcon, 0x014, 0xffffffff); + nvkm_wr32(device, base + 0x014, 0xffffffff); /* no default ucode provided by the engine implementation, try and * locate a "self-bootstrapping" firmware image for the engine @@ -120,7 +190,7 @@ _nvkm_falcon_init(struct nvkm_object *object) snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x", device->chipset, falcon->addr >> 12); - ret = request_firmware(&fw, name, nv_device_base(device)); + ret = request_firmware(&fw, name, device->dev); if (ret == 0) { falcon->code.data = vmemdup(fw->data, fw->size); falcon->code.size = fw->size; @@ -139,10 +209,10 @@ _nvkm_falcon_init(struct nvkm_object *object) snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xd", device->chipset, falcon->addr >> 12); - ret = request_firmware(&fw, name, nv_device_base(device)); + ret = request_firmware(&fw, name, device->dev); if (ret) { - nv_error(falcon, "unable to load firmware data\n"); - return ret; + nvkm_error(subdev, "unable to load firmware data\n"); + return -ENODEV; } falcon->data.data = vmemdup(fw->data, fw->size); @@ -154,10 +224,10 @@ _nvkm_falcon_init(struct nvkm_object *object) snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xc", device->chipset, falcon->addr >> 12); - ret = request_firmware(&fw, name, nv_device_base(device)); + ret = request_firmware(&fw, name, device->dev); if (ret) { - nv_error(falcon, "unable to load firmware code\n"); - return ret; + nvkm_error(subdev, "unable to load firmware code\n"); + return -ENODEV; } falcon->code.data = vmemdup(fw->data, fw->size); @@ -167,111 +237,117 @@ _nvkm_falcon_init(struct nvkm_object *object) return -ENOMEM; } - nv_debug(falcon, "firmware: %s (%s)\n", name, falcon->data.data ? - "static code/data segments" : "self-bootstrapping"); + nvkm_debug(subdev, "firmware: %s (%s)\n", name, falcon->data.data ? + "static code/data segments" : "self-bootstrapping"); /* ensure any "self-bootstrapping" firmware image is in vram */ if (!falcon->data.data && !falcon->core) { - ret = nvkm_gpuobj_new(object->parent, NULL, falcon->code.size, - 256, 0, &falcon->core); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + falcon->code.size, 256, false, + &falcon->core); if (ret) { - nv_error(falcon, "core allocation failed, %d\n", ret); + nvkm_error(subdev, "core allocation failed, %d\n", ret); return ret; } + nvkm_kmap(falcon->core); for (i = 0; i < falcon->code.size; i += 4) - nv_wo32(falcon->core, i, falcon->code.data[i / 4]); + nvkm_wo32(falcon->core, i, falcon->code.data[i / 4]); + nvkm_done(falcon->core); } /* upload firmware bootloader (or the full code segments) */ if (falcon->core) { + u64 addr = nvkm_memory_addr(falcon->core); if (device->card_type < NV_C0) - nv_wo32(falcon, 0x618, 0x04000000); + nvkm_wr32(device, base + 0x618, 0x04000000); else - nv_wo32(falcon, 0x618, 0x00000114); - nv_wo32(falcon, 0x11c, 0); - nv_wo32(falcon, 0x110, falcon->core->addr >> 8); - nv_wo32(falcon, 0x114, 0); - nv_wo32(falcon, 0x118, 0x00006610); + nvkm_wr32(device, base + 0x618, 0x00000114); + nvkm_wr32(device, base + 0x11c, 0); + nvkm_wr32(device, base + 0x110, addr >> 8); + nvkm_wr32(device, base + 0x114, 0); + nvkm_wr32(device, base + 0x118, 0x00006610); } else { if (falcon->code.size > falcon->code.limit || falcon->data.size > falcon->data.limit) { - nv_error(falcon, "ucode exceeds falcon limit(s)\n"); + nvkm_error(subdev, "ucode exceeds falcon limit(s)\n"); return -EINVAL; } if (falcon->version < 3) { - nv_wo32(falcon, 0xff8, 0x00100000); + nvkm_wr32(device, base + 0xff8, 0x00100000); for (i = 0; i < falcon->code.size / 4; i++) - nv_wo32(falcon, 0xff4, falcon->code.data[i]); + nvkm_wr32(device, base + 0xff4, falcon->code.data[i]); } else { - nv_wo32(falcon, 0x180, 0x01000000); + nvkm_wr32(device, base + 0x180, 0x01000000); for (i = 0; i < falcon->code.size / 4; i++) { if ((i & 0x3f) == 0) - nv_wo32(falcon, 0x188, i >> 6); - nv_wo32(falcon, 0x184, falcon->code.data[i]); + nvkm_wr32(device, base + 0x188, i >> 6); + nvkm_wr32(device, base + 0x184, falcon->code.data[i]); } } } /* upload data segment (if necessary), zeroing the remainder */ if (falcon->version < 3) { - nv_wo32(falcon, 0xff8, 0x00000000); + nvkm_wr32(device, base + 0xff8, 0x00000000); for (i = 0; !falcon->core && i < falcon->data.size / 4; i++) - nv_wo32(falcon, 0xff4, falcon->data.data[i]); + nvkm_wr32(device, base + 0xff4, falcon->data.data[i]); for (; i < falcon->data.limit; i += 4) - nv_wo32(falcon, 0xff4, 0x00000000); + nvkm_wr32(device, base + 0xff4, 0x00000000); } else { - nv_wo32(falcon, 0x1c0, 0x01000000); + nvkm_wr32(device, base + 0x1c0, 0x01000000); for (i = 0; !falcon->core && i < falcon->data.size / 4; i++) - nv_wo32(falcon, 0x1c4, falcon->data.data[i]); + nvkm_wr32(device, base + 0x1c4, falcon->data.data[i]); for (; i < falcon->data.limit / 4; i++) - nv_wo32(falcon, 0x1c4, 0x00000000); + nvkm_wr32(device, base + 0x1c4, 0x00000000); } /* start it running */ - nv_wo32(falcon, 0x10c, 0x00000001); /* BLOCK_ON_FIFO */ - nv_wo32(falcon, 0x104, 0x00000000); /* ENTRY */ - nv_wo32(falcon, 0x100, 0x00000002); /* TRIGGER */ - nv_wo32(falcon, 0x048, 0x00000003); /* FIFO | CHSW */ + nvkm_wr32(device, base + 0x10c, 0x00000001); /* BLOCK_ON_FIFO */ + nvkm_wr32(device, base + 0x104, 0x00000000); /* ENTRY */ + nvkm_wr32(device, base + 0x100, 0x00000002); /* TRIGGER */ + nvkm_wr32(device, base + 0x048, 0x00000003); /* FIFO | CHSW */ + + if (falcon->func->init) + falcon->func->init(falcon); return 0; } -int -_nvkm_falcon_fini(struct nvkm_object *object, bool suspend) +static void * +nvkm_falcon_dtor(struct nvkm_engine *engine) { - struct nvkm_falcon *falcon = (void *)object; - - if (!suspend) { - nvkm_gpuobj_ref(NULL, &falcon->core); - if (falcon->external) { - vfree(falcon->data.data); - vfree(falcon->code.data); - falcon->code.data = NULL; - } - } - - nv_mo32(falcon, 0x048, 0x00000003, 0x00000000); - nv_wo32(falcon, 0x014, 0xffffffff); - - return nvkm_engine_fini(&falcon->base, suspend); + return nvkm_falcon(engine); } +static const struct nvkm_engine_func +nvkm_falcon = { + .dtor = nvkm_falcon_dtor, + .oneinit = nvkm_falcon_oneinit, + .init = nvkm_falcon_init, + .fini = nvkm_falcon_fini, + .intr = nvkm_falcon_intr, + .fifo.sclass = nvkm_falcon_oclass_get, + .cclass = &nvkm_falcon_cclass, +}; + int -nvkm_falcon_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 addr, bool enable, - const char *iname, const char *fname, - int length, void **pobject) +nvkm_falcon_new_(const struct nvkm_falcon_func *func, + struct nvkm_device *device, int index, bool enable, + u32 addr, struct nvkm_engine **pengine) { struct nvkm_falcon *falcon; - int ret; - - ret = nvkm_engine_create_(parent, engine, oclass, enable, iname, - fname, length, pobject); - falcon = *pobject; - if (ret) - return ret; + if (!(falcon = kzalloc(sizeof(*falcon), GFP_KERNEL))) + return -ENOMEM; + falcon->func = func; falcon->addr = addr; - return 0; + falcon->code.data = func->code.data; + falcon->code.size = func->code.size; + falcon->data.data = func->data.data; + falcon->data.size = func->data.size; + *pengine = &falcon->engine; + + return nvkm_engine_ctor(&nvkm_falcon, device, index, func->pmc_enable, + enable, &falcon->engine); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 42891cb71..74993c144 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -7,6 +7,24 @@ nvkm-y += nvkm/engine/fifo/nv50.o nvkm-y += nvkm/engine/fifo/g84.o nvkm-y += nvkm/engine/fifo/gf100.o nvkm-y += nvkm/engine/fifo/gk104.o -nvkm-y += nvkm/engine/fifo/gk20a.o nvkm-y += nvkm/engine/fifo/gk208.o +nvkm-y += nvkm/engine/fifo/gk20a.o nvkm-y += nvkm/engine/fifo/gm204.o +nvkm-y += nvkm/engine/fifo/gm20b.o + +nvkm-y += nvkm/engine/fifo/chan.o +nvkm-y += nvkm/engine/fifo/channv50.o +nvkm-y += nvkm/engine/fifo/chang84.o + +nvkm-y += nvkm/engine/fifo/dmanv04.o +nvkm-y += nvkm/engine/fifo/dmanv10.o +nvkm-y += nvkm/engine/fifo/dmanv17.o +nvkm-y += nvkm/engine/fifo/dmanv40.o +nvkm-y += nvkm/engine/fifo/dmanv50.o +nvkm-y += nvkm/engine/fifo/dmag84.o + +nvkm-y += nvkm/engine/fifo/gpfifonv50.o +nvkm-y += nvkm/engine/fifo/gpfifog84.o +nvkm-y += nvkm/engine/fifo/gpfifogf100.o +nvkm-y += nvkm/engine/fifo/gpfifogk104.o +nvkm-y += nvkm/engine/fifo/gpfifogm204.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index fa223f88d..1fbbfbe6c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -21,156 +21,108 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" +#include "chan.h" #include -#include -#include +#include #include -#include -#include #include #include -static int -nvkm_fifo_event_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) +void +nvkm_fifo_pause(struct nvkm_fifo *fifo, unsigned long *flags) { - if (size == 0) { - notify->size = 0; - notify->types = 1; - notify->index = 0; - return 0; - } - return -ENOSYS; + return fifo->func->pause(fifo, flags); } -static const struct nvkm_event_func -nvkm_fifo_event_func = { - .ctor = nvkm_fifo_event_ctor, -}; - -int -nvkm_fifo_channel_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, - int bar, u32 addr, u32 size, u32 pushbuf, - u64 engmask, int len, void **ptr) +void +nvkm_fifo_start(struct nvkm_fifo *fifo, unsigned long *flags) { - struct nvkm_device *device = nv_device(engine); - struct nvkm_fifo *priv = (void *)engine; - struct nvkm_fifo_chan *chan; - struct nvkm_dmaeng *dmaeng; - unsigned long flags; - int ret; - - /* create base object class */ - ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL, - engmask, len, ptr); - chan = *ptr; - if (ret) - return ret; + return fifo->func->start(fifo, flags); +} - /* validate dma object representing push buffer */ - chan->pushdma = (void *)nvkm_handle_ref(parent, pushbuf); - if (!chan->pushdma) - return -ENOENT; - - dmaeng = (void *)chan->pushdma->base.engine; - switch (chan->pushdma->base.oclass->handle) { - case NV_DMA_FROM_MEMORY: - case NV_DMA_IN_MEMORY: - break; - default: - return -EINVAL; +void +nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags, + struct nvkm_fifo_chan **pchan) +{ + struct nvkm_fifo_chan *chan = *pchan; + if (likely(chan)) { + *pchan = NULL; + spin_unlock_irqrestore(&fifo->lock, flags); } +} - ret = dmaeng->bind(chan->pushdma, parent, &chan->pushgpu); - if (ret) - return ret; - - /* find a free fifo channel */ - spin_lock_irqsave(&priv->lock, flags); - for (chan->chid = priv->min; chan->chid < priv->max; chan->chid++) { - if (!priv->channel[chan->chid]) { - priv->channel[chan->chid] = nv_object(chan); - break; +struct nvkm_fifo_chan * +nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags) +{ + struct nvkm_fifo_chan *chan; + unsigned long flags; + spin_lock_irqsave(&fifo->lock, flags); + list_for_each_entry(chan, &fifo->chan, head) { + if (chan->inst->addr == inst) { + list_del(&chan->head); + list_add(&chan->head, &fifo->chan); + *rflags = flags; + return chan; } } - spin_unlock_irqrestore(&priv->lock, flags); - - if (chan->chid == priv->max) { - nv_error(priv, "no free channels\n"); - return -ENOSPC; - } - - chan->addr = nv_device_resource_start(device, bar) + - addr + size * chan->chid; - chan->size = size; - nvkm_event_send(&priv->cevent, 1, 0, NULL, 0); - return 0; + spin_unlock_irqrestore(&fifo->lock, flags); + return NULL; } -void -nvkm_fifo_channel_destroy(struct nvkm_fifo_chan *chan) +struct nvkm_fifo_chan * +nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags) { - struct nvkm_fifo *priv = (void *)nv_object(chan)->engine; + struct nvkm_fifo_chan *chan; unsigned long flags; - - if (chan->user) - iounmap(chan->user); - - spin_lock_irqsave(&priv->lock, flags); - priv->channel[chan->chid] = NULL; - spin_unlock_irqrestore(&priv->lock, flags); - - nvkm_gpuobj_ref(NULL, &chan->pushgpu); - nvkm_object_ref(NULL, (struct nvkm_object **)&chan->pushdma); - nvkm_namedb_destroy(&chan->namedb); + spin_lock_irqsave(&fifo->lock, flags); + list_for_each_entry(chan, &fifo->chan, head) { + if (chan->chid == chid) { + list_del(&chan->head); + list_add(&chan->head, &fifo->chan); + *rflags = flags; + return chan; + } + } + spin_unlock_irqrestore(&fifo->lock, flags); + return NULL; } -void -_nvkm_fifo_channel_dtor(struct nvkm_object *object) +static int +nvkm_fifo_event_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) { - struct nvkm_fifo_chan *chan = (void *)object; - nvkm_fifo_channel_destroy(chan); + if (size == 0) { + notify->size = 0; + notify->types = 1; + notify->index = 0; + return 0; + } + return -ENOSYS; } -int -_nvkm_fifo_channel_map(struct nvkm_object *object, u64 *addr, u32 *size) -{ - struct nvkm_fifo_chan *chan = (void *)object; - *addr = chan->addr; - *size = chan->size; - return 0; -} +static const struct nvkm_event_func +nvkm_fifo_event_func = { + .ctor = nvkm_fifo_event_ctor, +}; -u32 -_nvkm_fifo_channel_rd32(struct nvkm_object *object, u64 addr) +static void +nvkm_fifo_uevent_fini(struct nvkm_event *event, int type, int index) { - struct nvkm_fifo_chan *chan = (void *)object; - if (unlikely(!chan->user)) { - chan->user = ioremap(chan->addr, chan->size); - if (WARN_ON_ONCE(chan->user == NULL)) - return 0; - } - return ioread32_native(chan->user + addr); + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); + fifo->func->uevent_fini(fifo); } -void -_nvkm_fifo_channel_wr32(struct nvkm_object *object, u64 addr, u32 data) +static void +nvkm_fifo_uevent_init(struct nvkm_event *event, int type, int index) { - struct nvkm_fifo_chan *chan = (void *)object; - if (unlikely(!chan->user)) { - chan->user = ioremap(chan->addr, chan->size); - if (WARN_ON_ONCE(chan->user == NULL)) - return; - } - iowrite32_native(data, chan->user + addr); + struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); + fifo->func->uevent_init(fifo); } -int +static int nvkm_fifo_uevent_ctor(struct nvkm_object *object, void *data, u32 size, struct nvkm_notify *notify) { @@ -188,6 +140,13 @@ nvkm_fifo_uevent_ctor(struct nvkm_object *object, void *data, u32 size, return ret; } +static const struct nvkm_event_func +nvkm_fifo_uevent_func = { + .ctor = nvkm_fifo_uevent_ctor, + .init = nvkm_fifo_uevent_init, + .fini = nvkm_fifo_uevent_fini, +}; + void nvkm_fifo_uevent(struct nvkm_fifo *fifo) { @@ -196,87 +155,123 @@ nvkm_fifo_uevent(struct nvkm_fifo *fifo) nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep)); } -int -_nvkm_fifo_channel_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **event) +static int +nvkm_fifo_class_new(struct nvkm_device *device, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) { - struct nvkm_fifo *fifo = (void *)object->engine; - switch (type) { - case G82_CHANNEL_DMA_V0_NTFY_UEVENT: - if (nv_mclass(object) >= G82_CHANNEL_DMA) { - *event = &fifo->uevent; - return 0; - } - break; - default: - break; - } - return -EINVAL; + const struct nvkm_fifo_chan_oclass *sclass = oclass->engn; + struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); + return sclass->ctor(fifo, oclass, data, size, pobject); } +static const struct nvkm_device_oclass +nvkm_fifo_class = { + .ctor = nvkm_fifo_class_new, +}; + static int -nvkm_fifo_chid(struct nvkm_fifo *priv, struct nvkm_object *object) +nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, + const struct nvkm_device_oclass **class) { - int engidx = nv_hclass(priv) & 0xff; - - while (object && object->parent) { - if ( nv_iclass(object->parent, NV_ENGCTX_CLASS) && - (nv_hclass(object->parent) & 0xff) == engidx) - return nvkm_fifo_chan(object)->chid; - object = object->parent; + struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); + const struct nvkm_fifo_chan_oclass *sclass; + int c = 0; + + while ((sclass = fifo->func->chan[c])) { + if (c++ == index) { + oclass->base = sclass->base; + oclass->engn = sclass; + *class = &nvkm_fifo_class; + return 0; + } } - return -1; + return c; } -const char * -nvkm_client_name_for_fifo_chid(struct nvkm_fifo *fifo, u32 chid) +static void +nvkm_fifo_intr(struct nvkm_engine *engine) { - struct nvkm_fifo_chan *chan = NULL; - unsigned long flags; + struct nvkm_fifo *fifo = nvkm_fifo(engine); + fifo->func->intr(fifo); +} - spin_lock_irqsave(&fifo->lock, flags); - if (chid >= fifo->min && chid <= fifo->max) - chan = (void *)fifo->channel[chid]; - spin_unlock_irqrestore(&fifo->lock, flags); +static int +nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) +{ + struct nvkm_fifo *fifo = nvkm_fifo(engine); + if (fifo->func->fini) + fifo->func->fini(fifo); + return 0; +} - return nvkm_client_name(chan); +static int +nvkm_fifo_oneinit(struct nvkm_engine *engine) +{ + struct nvkm_fifo *fifo = nvkm_fifo(engine); + if (fifo->func->oneinit) + return fifo->func->oneinit(fifo); + return 0; } -void -nvkm_fifo_destroy(struct nvkm_fifo *priv) +static int +nvkm_fifo_init(struct nvkm_engine *engine) { - kfree(priv->channel); - nvkm_event_fini(&priv->uevent); - nvkm_event_fini(&priv->cevent); - nvkm_engine_destroy(&priv->base); + struct nvkm_fifo *fifo = nvkm_fifo(engine); + fifo->func->init(fifo); + return 0; } +static void * +nvkm_fifo_dtor(struct nvkm_engine *engine) +{ + struct nvkm_fifo *fifo = nvkm_fifo(engine); + void *data = fifo; + if (fifo->func->dtor) + data = fifo->func->dtor(fifo); + nvkm_event_fini(&fifo->cevent); + nvkm_event_fini(&fifo->uevent); + return data; +} + +static const struct nvkm_engine_func +nvkm_fifo = { + .dtor = nvkm_fifo_dtor, + .oneinit = nvkm_fifo_oneinit, + .init = nvkm_fifo_init, + .fini = nvkm_fifo_fini, + .intr = nvkm_fifo_intr, + .base.sclass = nvkm_fifo_class_get, +}; + int -nvkm_fifo_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, - int min, int max, int length, void **pobject) +nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device, + int index, int nr, struct nvkm_fifo *fifo) { - struct nvkm_fifo *priv; int ret; - ret = nvkm_engine_create_(parent, engine, oclass, true, "PFIFO", - "fifo", length, pobject); - priv = *pobject; - if (ret) - return ret; + fifo->func = func; + INIT_LIST_HEAD(&fifo->chan); + spin_lock_init(&fifo->lock); - priv->min = min; - priv->max = max; - priv->channel = kzalloc(sizeof(*priv->channel) * (max + 1), GFP_KERNEL); - if (!priv->channel) - return -ENOMEM; + if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) + fifo->nr = NVKM_FIFO_CHID_NR; + else + fifo->nr = nr; + bitmap_clear(fifo->mask, 0, fifo->nr); - ret = nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &priv->cevent); + ret = nvkm_engine_ctor(&nvkm_fifo, device, index, 0x00000100, + true, &fifo->engine); if (ret) return ret; - priv->chid = nvkm_fifo_chid; - spin_lock_init(&priv->lock); - return 0; + if (func->uevent_init) { + ret = nvkm_event_init(&nvkm_fifo_uevent_func, 1, 1, + &fifo->uevent); + if (ret) + return ret; + } + + return nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &fifo->cevent); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c new file mode 100644 index 000000000..dc6d4678f --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -0,0 +1,415 @@ +/* + * 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 "chan.h" + +#include +#include +#include +#include +#include + +struct nvkm_fifo_chan_object { + struct nvkm_oproxy oproxy; + struct nvkm_fifo_chan *chan; + int hash; +}; + +static int +nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend) +{ + struct nvkm_fifo_chan_object *object = + container_of(base, typeof(*object), oproxy); + struct nvkm_engine *engine = object->oproxy.object->engine; + struct nvkm_fifo_chan *chan = object->chan; + struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index]; + const char *name = nvkm_subdev_name[engine->subdev.index]; + int ret = 0; + + if (--engn->usecount) + return 0; + + if (chan->func->engine_fini) { + ret = chan->func->engine_fini(chan, engine, suspend); + if (ret) { + nvif_error(&chan->object, + "detach %s failed, %d\n", name, ret); + return ret; + } + } + + if (engn->object) { + ret = nvkm_object_fini(engn->object, suspend); + if (ret && suspend) + return ret; + } + + nvif_trace(&chan->object, "detached %s\n", name); + return ret; +} + +static int +nvkm_fifo_chan_child_init(struct nvkm_oproxy *base) +{ + struct nvkm_fifo_chan_object *object = + container_of(base, typeof(*object), oproxy); + struct nvkm_engine *engine = object->oproxy.object->engine; + struct nvkm_fifo_chan *chan = object->chan; + struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index]; + const char *name = nvkm_subdev_name[engine->subdev.index]; + int ret; + + if (engn->usecount++) + return 0; + + if (engn->object) { + ret = nvkm_object_init(engn->object); + if (ret) + return ret; + } + + if (chan->func->engine_init) { + ret = chan->func->engine_init(chan, engine); + if (ret) { + nvif_error(&chan->object, + "attach %s failed, %d\n", name, ret); + return ret; + } + } + + nvif_trace(&chan->object, "attached %s\n", name); + return 0; +} + +static void +nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) +{ + struct nvkm_fifo_chan_object *object = + container_of(base, typeof(*object), oproxy); + struct nvkm_engine *engine = object->oproxy.base.engine; + struct nvkm_fifo_chan *chan = object->chan; + struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index]; + + if (chan->func->object_dtor) + chan->func->object_dtor(chan, object->hash); + + if (!--engn->refcount) { + if (chan->func->engine_dtor) + chan->func->engine_dtor(chan, engine); + nvkm_object_del(&engn->object); + if (chan->vm) + atomic_dec(&chan->vm->engref[engine->subdev.index]); + } +} + +static const struct nvkm_oproxy_func +nvkm_fifo_chan_child_func = { + .dtor[0] = nvkm_fifo_chan_child_del, + .init[0] = nvkm_fifo_chan_child_init, + .fini[0] = nvkm_fifo_chan_child_fini, +}; + +static int +nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_engine *engine = oclass->engine; + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent); + struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index]; + struct nvkm_fifo_chan_object *object; + int ret = 0; + + if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy); + object->chan = chan; + *pobject = &object->oproxy.base; + + if (!engn->refcount++) { + struct nvkm_oclass cclass = { + .client = oclass->client, + .engine = oclass->engine, + }; + + if (chan->vm) + atomic_inc(&chan->vm->engref[engine->subdev.index]); + + if (engine->func->fifo.cclass) { + ret = engine->func->fifo.cclass(chan, &cclass, + &engn->object); + } else + if (engine->func->cclass) { + ret = nvkm_object_new_(engine->func->cclass, &cclass, + NULL, 0, &engn->object); + } + if (ret) + return ret; + + if (chan->func->engine_ctor) { + ret = chan->func->engine_ctor(chan, oclass->engine, + engn->object); + if (ret) + return ret; + } + } + + ret = oclass->base.ctor(&(const struct nvkm_oclass) { + .base = oclass->base, + .engn = oclass->engn, + .handle = oclass->handle, + .object = oclass->object, + .client = oclass->client, + .parent = engn->object ? + engn->object : + oclass->parent, + .engine = engine, + }, data, size, &object->oproxy.object); + if (ret) + return ret; + + if (chan->func->object_ctor) { + object->hash = + chan->func->object_ctor(chan, object->oproxy.object); + if (object->hash < 0) + return object->hash; + } + + return 0; +} + +static int +nvkm_fifo_chan_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + struct nvkm_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_engine *engine; + u64 mask = chan->engines; + int ret, i, c; + + for (; c = 0, i = __ffs64(mask), mask; mask &= ~(1ULL << i)) { + if (!(engine = nvkm_device_engine(device, i))) + continue; + oclass->engine = engine; + oclass->base.oclass = 0; + + if (engine->func->fifo.sclass) { + ret = engine->func->fifo.sclass(oclass, index); + if (oclass->base.oclass) { + if (!oclass->base.ctor) + oclass->base.ctor = nvkm_object_new; + oclass->ctor = nvkm_fifo_chan_child_new; + return 0; + } + + index -= ret; + continue; + } + + while (engine->func->sclass[c].oclass) { + if (c++ == index) { + oclass->base = engine->func->sclass[index]; + if (!oclass->base.ctor) + oclass->base.ctor = nvkm_object_new; + oclass->ctor = nvkm_fifo_chan_child_new; + return 0; + } + } + index -= c; + } + + return -EINVAL; +} + +static int +nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type, + struct nvkm_event **pevent) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + if (chan->func->ntfy) + return chan->func->ntfy(chan, type, pevent); + return -ENODEV; +} + +static int +nvkm_fifo_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + *addr = chan->addr; + *size = chan->size; + return 0; +} + +static int +nvkm_fifo_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + if (unlikely(!chan->user)) { + chan->user = ioremap(chan->addr, chan->size); + if (!chan->user) + return -ENOMEM; + } + if (unlikely(addr + 4 > chan->size)) + return -EINVAL; + *data = ioread32_native(chan->user + addr); + return 0; +} + +static int +nvkm_fifo_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + if (unlikely(!chan->user)) { + chan->user = ioremap(chan->addr, chan->size); + if (!chan->user) + return -ENOMEM; + } + if (unlikely(addr + 4 > chan->size)) + return -EINVAL; + iowrite32_native(data, chan->user + addr); + return 0; +} + +static int +nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + chan->func->fini(chan); + return 0; +} + +static int +nvkm_fifo_chan_init(struct nvkm_object *object) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + chan->func->init(chan); + return 0; +} + +static void * +nvkm_fifo_chan_dtor(struct nvkm_object *object) +{ + struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + struct nvkm_fifo *fifo = chan->fifo; + void *data = chan->func->dtor(chan); + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + if (!list_empty(&chan->head)) { + __clear_bit(chan->chid, fifo->mask); + list_del(&chan->head); + } + spin_unlock_irqrestore(&fifo->lock, flags); + + if (chan->user) + iounmap(chan->user); + + nvkm_vm_ref(NULL, &chan->vm, NULL); + + nvkm_gpuobj_del(&chan->push); + nvkm_gpuobj_del(&chan->inst); + return data; +} + +static const struct nvkm_object_func +nvkm_fifo_chan_func = { + .dtor = nvkm_fifo_chan_dtor, + .init = nvkm_fifo_chan_init, + .fini = nvkm_fifo_chan_fini, + .ntfy = nvkm_fifo_chan_ntfy, + .map = nvkm_fifo_chan_map, + .rd32 = nvkm_fifo_chan_rd32, + .wr32 = nvkm_fifo_chan_wr32, + .sclass = nvkm_fifo_chan_child_get, +}; + +int +nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, + struct nvkm_fifo *fifo, u32 size, u32 align, bool zero, + u64 vm, u64 push, u64 engines, int bar, u32 base, u32 user, + const struct nvkm_oclass *oclass, + struct nvkm_fifo_chan *chan) +{ + struct nvkm_client *client = oclass->client; + struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_mmu *mmu = device->mmu; + struct nvkm_dmaobj *dmaobj; + unsigned long flags; + int ret; + + nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object); + chan->func = func; + chan->fifo = fifo; + chan->engines = engines; + INIT_LIST_HEAD(&chan->head); + + /* instance memory */ + ret = nvkm_gpuobj_new(device, size, align, zero, NULL, &chan->inst); + if (ret) + return ret; + + /* allocate push buffer ctxdma instance */ + if (push) { + dmaobj = nvkm_dma_search(device->dma, oclass->client, push); + if (!dmaobj) + return -ENOENT; + + ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, + &chan->push); + if (ret) + return ret; + } + + /* channel address space */ + if (!vm && mmu) { + if (!client->vm || client->vm->mmu == mmu) { + ret = nvkm_vm_ref(client->vm, &chan->vm, NULL); + if (ret) + return ret; + } else { + return -EINVAL; + } + } else { + return -ENOENT; + } + + /* allocate channel id */ + spin_lock_irqsave(&fifo->lock, flags); + chan->chid = find_first_zero_bit(fifo->mask, NVKM_FIFO_CHID_NR); + if (chan->chid >= NVKM_FIFO_CHID_NR) { + spin_unlock_irqrestore(&fifo->lock, flags); + return -ENOSPC; + } + list_add(&chan->head, &fifo->chan); + __set_bit(chan->chid, fifo->mask); + spin_unlock_irqrestore(&fifo->lock, flags); + + /* determine address of this channel's user registers */ + chan->addr = device->func->resource_addr(device, bar) + + base + user * chan->chid; + chan->size = user; + + nvkm_event_send(&fifo->cevent, 1, 0, NULL, 0); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h new file mode 100644 index 000000000..55dc415c5 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h @@ -0,0 +1,33 @@ +#ifndef __NVKM_FIFO_CHAN_H__ +#define __NVKM_FIFO_CHAN_H__ +#define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object) +#include "priv.h" + +struct nvkm_fifo_chan_func { + void *(*dtor)(struct nvkm_fifo_chan *); + void (*init)(struct nvkm_fifo_chan *); + void (*fini)(struct nvkm_fifo_chan *); + int (*ntfy)(struct nvkm_fifo_chan *, u32 type, struct nvkm_event **); + int (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *, + struct nvkm_object *); + void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *); + int (*engine_init)(struct nvkm_fifo_chan *, struct nvkm_engine *); + int (*engine_fini)(struct nvkm_fifo_chan *, struct nvkm_engine *, + bool suspend); + int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *); + void (*object_dtor)(struct nvkm_fifo_chan *, int); +}; + +int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, + u32 size, u32 align, bool zero, u64 vm, u64 push, + u64 engines, int bar, u32 base, u32 user, + const struct nvkm_oclass *, struct nvkm_fifo_chan *); + +struct nvkm_fifo_chan_oclass { + int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + struct nvkm_sclass base; +}; + +int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c new file mode 100644 index 000000000..04305241c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -0,0 +1,285 @@ +/* + * 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 +#include +#include +#include + +#include + +int +g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, + struct nvkm_event **pevent) +{ + switch (type) { + case G82_CHANNEL_DMA_V0_NTFY_UEVENT: + *pevent = &chan->fifo->uevent; + return 0; + default: + break; + } + return -EINVAL; +} + +static int +g84_fifo_chan_engine(struct nvkm_engine *engine) +{ + switch (engine->subdev.index) { + case NVKM_ENGINE_GR : return 0; + case NVKM_ENGINE_MPEG : + case NVKM_ENGINE_MSPPP : return 1; + case NVKM_ENGINE_CE0 : return 2; + case NVKM_ENGINE_VP : + case NVKM_ENGINE_MSPDEC: return 3; + case NVKM_ENGINE_CIPHER: + case NVKM_ENGINE_SEC : return 4; + case NVKM_ENGINE_BSP : + case NVKM_ENGINE_MSVLD : return 5; + default: + WARN_ON(1); + return 0; + } +} + +static int +g84_fifo_chan_engine_addr(struct nvkm_engine *engine) +{ + switch (engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW : return -1; + case NVKM_ENGINE_GR : return 0x0020; + case NVKM_ENGINE_VP : + case NVKM_ENGINE_MSPDEC: return 0x0040; + case NVKM_ENGINE_MPEG : + case NVKM_ENGINE_MSPPP : return 0x0060; + case NVKM_ENGINE_BSP : + case NVKM_ENGINE_MSVLD : return 0x0080; + case NVKM_ENGINE_CIPHER: + case NVKM_ENGINE_SEC : return 0x00a0; + case NVKM_ENGINE_CE0 : return 0x00c0; + default: + WARN_ON(1); + return -1; + } +} + +static int +g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, bool suspend) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nv50_fifo *fifo = chan->fifo; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 engn, save; + int offset; + bool done; + + offset = g84_fifo_chan_engine_addr(engine); + if (offset < 0) + return 0; + + engn = g84_fifo_chan_engine(engine); + save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn); + nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12); + done = nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) + break; + ) >= 0; + nvkm_wr32(device, 0x002520, save); + if (!done) { + nvkm_error(subdev, "channel %d [%s] unload timeout\n", + chan->base.chid, chan->base.object.client->name); + if (suspend) + return -EBUSY; + } + + nvkm_kmap(chan->eng); + nvkm_wo32(chan->eng, offset + 0x00, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x04, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x08, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); + nvkm_done(chan->eng); + return 0; +} + + +int +g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index]; + u64 limit, start; + int offset; + + offset = g84_fifo_chan_engine_addr(engine); + if (offset < 0) + return 0; + limit = engn->addr + engn->size - 1; + start = engn->addr; + + nvkm_kmap(chan->eng); + nvkm_wo32(chan->eng, offset + 0x00, 0x00190000); + nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit)); + nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start)); + nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); + nvkm_done(chan->eng); + return 0; +} + +static int +g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, + struct nvkm_object *object) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + int engn = engine->subdev.index; + + if (g84_fifo_chan_engine_addr(engine) < 0) + return 0; + + return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]); +} + +int +g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, + struct nvkm_object *object) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + u32 handle = object->handle; + u32 context; + + switch (object->engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW : context = 0x00000000; break; + case NVKM_ENGINE_GR : context = 0x00100000; break; + case NVKM_ENGINE_MPEG : + case NVKM_ENGINE_MSPPP : context = 0x00200000; break; + case NVKM_ENGINE_ME : + case NVKM_ENGINE_CE0 : context = 0x00300000; break; + case NVKM_ENGINE_VP : + case NVKM_ENGINE_MSPDEC: context = 0x00400000; break; + case NVKM_ENGINE_CIPHER: + case NVKM_ENGINE_SEC : + case NVKM_ENGINE_VIC : context = 0x00500000; break; + case NVKM_ENGINE_BSP : + case NVKM_ENGINE_MSVLD : context = 0x00600000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); +} + +static void +g84_fifo_chan_init(struct nvkm_fifo_chan *base) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nv50_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u64 addr = chan->ramfc->addr >> 8; + u32 chid = chan->base.chid; + + nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr); + nv50_fifo_runlist_update(fifo); +} + +static const struct nvkm_fifo_chan_func +g84_fifo_chan_func = { + .dtor = nv50_fifo_chan_dtor, + .init = g84_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .ntfy = g84_fifo_chan_ntfy, + .engine_ctor = g84_fifo_chan_engine_ctor, + .engine_dtor = nv50_fifo_chan_engine_dtor, + .engine_init = g84_fifo_chan_engine_init, + .engine_fini = g84_fifo_chan_engine_fini, + .object_ctor = g84_fifo_chan_object_ctor, + .object_dtor = nv50_fifo_chan_object_dtor, +}; + +int +g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, + const struct nvkm_oclass *oclass, + struct nv50_fifo_chan *chan) +{ + struct nvkm_device *device = fifo->base.engine.subdev.device; + int ret; + + ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base, + 0x10000, 0x1000, false, vm, push, + (1ULL << NVKM_ENGINE_BSP) | + (1ULL << NVKM_ENGINE_CE0) | + (1ULL << NVKM_ENGINE_CIPHER) | + (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_ME) | + (1ULL << NVKM_ENGINE_MPEG) | + (1ULL << NVKM_ENGINE_MSPDEC) | + (1ULL << NVKM_ENGINE_MSPPP) | + (1ULL << NVKM_ENGINE_MSVLD) | + (1ULL << NVKM_ENGINE_SEC) | + (1ULL << NVKM_ENGINE_SW) | + (1ULL << NVKM_ENGINE_VIC) | + (1ULL << NVKM_ENGINE_VP), + 0, 0xc00000, 0x2000, oclass, &chan->base); + chan->fifo = fifo; + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst, + &chan->eng); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst, + &chan->pgd); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst, + &chan->cache); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst, + &chan->ramfc); + if (ret) + return ret; + + ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); + if (ret) + return ret; + + return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h new file mode 100644 index 000000000..7d697e2dc --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h @@ -0,0 +1,24 @@ +#ifndef __GF100_FIFO_CHAN_H__ +#define __GF100_FIFO_CHAN_H__ +#define gf100_fifo_chan(p) container_of((p), struct gf100_fifo_chan, base) +#include "chan.h" +#include "gf100.h" + +struct gf100_fifo_chan { + struct nvkm_fifo_chan base; + struct gf100_fifo *fifo; + + struct list_head head; + bool killed; + + struct nvkm_gpuobj *pgd; + struct nvkm_vm *vm; + + struct { + struct nvkm_gpuobj *inst; + struct nvkm_vma vma; + } engn[NVKM_SUBDEV_NR]; +}; + +extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h new file mode 100644 index 000000000..97bdddb76 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -0,0 +1,29 @@ +#ifndef __GK104_FIFO_CHAN_H__ +#define __GK104_FIFO_CHAN_H__ +#define gk104_fifo_chan(p) container_of((p), struct gk104_fifo_chan, base) +#include "chan.h" +#include "gk104.h" + +struct gk104_fifo_chan { + struct nvkm_fifo_chan base; + struct gk104_fifo *fifo; + int engine; + + struct list_head head; + bool killed; + + struct nvkm_gpuobj *pgd; + struct nvkm_vm *vm; + + struct { + struct nvkm_gpuobj *inst; + struct nvkm_vma vma; + } engn[NVKM_SUBDEV_NR]; +}; + +int gk104_fifo_gpfifo_new(struct nvkm_fifo *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + +extern const struct nvkm_fifo_chan_oclass gk104_fifo_gpfifo_oclass; +extern const struct nvkm_fifo_chan_oclass gm204_fifo_gpfifo_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h new file mode 100644 index 000000000..3361a1fd0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h @@ -0,0 +1,24 @@ +#ifndef __NV04_FIFO_CHAN_H__ +#define __NV04_FIFO_CHAN_H__ +#define nv04_fifo_chan(p) container_of((p), struct nv04_fifo_chan, base) +#include "chan.h" +#include "nv04.h" + +struct nv04_fifo_chan { + struct nvkm_fifo_chan base; + struct nv04_fifo *fifo; + u32 ramfc; + struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR]; +}; + +extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func; +void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *); +void nv04_fifo_dma_init(struct nvkm_fifo_chan *); +void nv04_fifo_dma_fini(struct nvkm_fifo_chan *); +void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int); + +extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass; +extern const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass; +extern const struct nvkm_fifo_chan_oclass nv17_fifo_dma_oclass; +extern const struct nvkm_fifo_chan_oclass nv40_fifo_dma_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c new file mode 100644 index 000000000..25b60aff4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -0,0 +1,270 @@ +/* + * 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 +#include +#include +#include + +static int +nv50_fifo_chan_engine_addr(struct nvkm_engine *engine) +{ + switch (engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW : return -1; + case NVKM_ENGINE_GR : return 0x0000; + case NVKM_ENGINE_MPEG : return 0x0060; + default: + WARN_ON(1); + return -1; + } +} + +static int +nv50_fifo_chan_engine_fini(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, bool suspend) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nv50_fifo *fifo = chan->fifo; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int offset, ret = 0; + u32 me; + + offset = nv50_fifo_chan_engine_addr(engine); + if (offset < 0) + return 0; + + /* HW bug workaround: + * + * PFIFO will hang forever if the connected engines don't report + * that they've processed the context switch request. + * + * In order for the kickoff to work, we need to ensure all the + * connected engines are in a state where they can answer. + * + * Newer chipsets don't seem to suffer from this issue, and well, + * there's also a "ignore these engines" bitmask reg we can use + * if we hit the issue there.. + */ + me = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001); + + /* do the kickoff... */ + nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) + break; + ) < 0) { + nvkm_error(subdev, "channel %d [%s] unload timeout\n", + chan->base.chid, chan->base.object.client->name); + if (suspend) + ret = -EBUSY; + } + nvkm_wr32(device, 0x00b860, me); + + if (ret == 0) { + nvkm_kmap(chan->eng); + nvkm_wo32(chan->eng, offset + 0x00, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x04, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x08, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); + nvkm_done(chan->eng); + } + + return ret; +} + +static int +nv50_fifo_chan_engine_init(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index]; + u64 limit, start; + int offset; + + offset = nv50_fifo_chan_engine_addr(engine); + if (offset < 0) + return 0; + limit = engn->addr + engn->size - 1; + start = engn->addr; + + nvkm_kmap(chan->eng); + nvkm_wo32(chan->eng, offset + 0x00, 0x00190000); + nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit)); + nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start)); + nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); + nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); + nvkm_done(chan->eng); + return 0; +} + +void +nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + nvkm_gpuobj_del(&chan->engn[engine->subdev.index]); +} + +static int +nv50_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, + struct nvkm_object *object) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + int engn = engine->subdev.index; + + if (nv50_fifo_chan_engine_addr(engine) < 0) + return 0; + + return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]); +} + +void +nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *base, int cookie) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + nvkm_ramht_remove(chan->ramht, cookie); +} + +static int +nv50_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, + struct nvkm_object *object) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + u32 handle = object->handle; + u32 context; + + switch (object->engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW : context = 0x00000000; break; + case NVKM_ENGINE_GR : context = 0x00100000; break; + case NVKM_ENGINE_MPEG : context = 0x00200000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); +} + +void +nv50_fifo_chan_fini(struct nvkm_fifo_chan *base) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nv50_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 chid = chan->base.chid; + + /* remove channel from runlist, fifo will unload context */ + nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x00000000); + nv50_fifo_runlist_update(fifo); + nvkm_wr32(device, 0x002600 + (chid * 4), 0x00000000); +} + +static void +nv50_fifo_chan_init(struct nvkm_fifo_chan *base) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + struct nv50_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u64 addr = chan->ramfc->addr >> 12; + u32 chid = chan->base.chid; + + nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr); + nv50_fifo_runlist_update(fifo); +} + +void * +nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) +{ + struct nv50_fifo_chan *chan = nv50_fifo_chan(base); + nvkm_vm_ref(NULL, &chan->vm, chan->pgd); + nvkm_ramht_del(&chan->ramht); + nvkm_gpuobj_del(&chan->pgd); + nvkm_gpuobj_del(&chan->eng); + nvkm_gpuobj_del(&chan->cache); + nvkm_gpuobj_del(&chan->ramfc); + return chan; +} + +static const struct nvkm_fifo_chan_func +nv50_fifo_chan_func = { + .dtor = nv50_fifo_chan_dtor, + .init = nv50_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .engine_ctor = nv50_fifo_chan_engine_ctor, + .engine_dtor = nv50_fifo_chan_engine_dtor, + .engine_init = nv50_fifo_chan_engine_init, + .engine_fini = nv50_fifo_chan_engine_fini, + .object_ctor = nv50_fifo_chan_object_ctor, + .object_dtor = nv50_fifo_chan_object_dtor, +}; + +int +nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, + const struct nvkm_oclass *oclass, + struct nv50_fifo_chan *chan) +{ + struct nvkm_device *device = fifo->base.engine.subdev.device; + int ret; + + ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base, + 0x10000, 0x1000, false, vm, push, + (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_SW) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_MPEG), + 0, 0xc00000, 0x2000, oclass, &chan->base); + chan->fifo = fifo; + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->base.inst, + &chan->ramfc); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->base.inst, + &chan->eng); + if (ret) + return ret; + + ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst, + &chan->pgd); + if (ret) + return ret; + + ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); + if (ret) + return ret; + + return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h new file mode 100644 index 000000000..4b9da469b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -0,0 +1,35 @@ +#ifndef __NV50_FIFO_CHAN_H__ +#define __NV50_FIFO_CHAN_H__ +#define nv50_fifo_chan(p) container_of((p), struct nv50_fifo_chan, base) +#include "chan.h" +#include "nv50.h" + +struct nv50_fifo_chan { + struct nv50_fifo *fifo; + struct nvkm_fifo_chan base; + + struct nvkm_gpuobj *ramfc; + struct nvkm_gpuobj *cache; + struct nvkm_gpuobj *eng; + struct nvkm_gpuobj *pgd; + struct nvkm_ramht *ramht; + struct nvkm_vm *vm; + + struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR]; +}; + +int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, + const struct nvkm_oclass *, struct nv50_fifo_chan *); +void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); +void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); +void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); +void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); + +int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, + const struct nvkm_oclass *, struct nv50_fifo_chan *); + +extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass; +extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass; +extern const struct nvkm_fifo_chan_oclass g84_fifo_dma_oclass; +extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c new file mode 100644 index 000000000..a5ca52c7b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c @@ -0,0 +1,93 @@ +/* + * 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 +#include + +#include +#include + +static int +g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv50_channel_dma_v0 v0; + } *args = data; + struct nv50_fifo *fifo = nv50_fifo(base); + struct nv50_fifo_chan *chan; + int ret; + + nvif_ioctl(parent, "create channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel dma vers %d vm %llx " + "pushbuf %llx offset %016llx\n", + args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.offset); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + oclass, chan); + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + + nvkm_kmap(chan->ramfc); + nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078); + nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); + nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4); + nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff); + nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); + nvkm_wo32(chan->ramfc, 0x78, 0x00000000); + nvkm_wo32(chan->ramfc, 0x7c, 0x30000001); + nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->node->offset >> 4)); + nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10); + nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12); + nvkm_done(chan->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +g84_fifo_dma_oclass = { + .base.oclass = G82_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = g84_fifo_dma_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c new file mode 100644 index 000000000..bfcc6408a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -0,0 +1,220 @@ +/* + * 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 "channv04.h" +#include "regsnv04.h" + +#include +#include +#include + +#include +#include + +void +nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; + nvkm_ramht_remove(imem->ramht, cookie); +} + +static int +nv04_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, + struct nvkm_object *object) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; + u32 context = 0x80000000 | chan->base.chid << 24; + u32 handle = object->handle; + int hash; + + switch (object->engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW : context |= 0x00000000; break; + case NVKM_ENGINE_GR : context |= 0x00010000; break; + case NVKM_ENGINE_MPEG : context |= 0x00020000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + mutex_lock(&chan->fifo->base.engine.subdev.mutex); + hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4, + handle, context); + mutex_unlock(&chan->fifo->base.engine.subdev.mutex); + return hash; +} + +void +nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_memory *fctx = device->imem->ramfc; + const struct nv04_fifo_ramfc *c; + unsigned long flags; + u32 mask = fifo->base.nr - 1; + u32 data = chan->ramfc; + u32 chid; + + /* prevent fifo context switches */ + spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_wr32(device, NV03_PFIFO_CACHES, 0); + + /* if this channel is active, replace it with a null context */ + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask; + if (chid == chan->base.chid) { + nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0); + nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + + c = fifo->ramfc; + do { + u32 rm = ((1ULL << c->bits) - 1) << c->regs; + u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; + u32 rv = (nvkm_rd32(device, c->regp) & rm) >> c->regs; + u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm); + nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); + } while ((++c)->bits); + + c = fifo->ramfc; + do { + nvkm_wr32(device, c->regp, 0x00000000); + } while ((++c)->bits); + + nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); + } + + /* restore normal operation, after disabling dma mode */ + nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); + nvkm_wr32(device, NV03_PFIFO_CACHES, 1); + spin_unlock_irqrestore(&fifo->base.lock, flags); +} + +void +nv04_fifo_dma_init(struct nvkm_fifo_chan *base) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 mask = 1 << chan->base.chid; + unsigned long flags; + spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_mask(device, NV04_PFIFO_MODE, mask, mask); + spin_unlock_irqrestore(&fifo->base.lock, flags); +} + +void * +nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem; + const struct nv04_fifo_ramfc *c = fifo->ramfc; + + nvkm_kmap(imem->ramfc); + do { + nvkm_wo32(imem->ramfc, chan->ramfc + c->ctxp, 0x00000000); + } while ((++c)->bits); + nvkm_done(imem->ramfc); + return chan; +} + +const struct nvkm_fifo_chan_func +nv04_fifo_dma_func = { + .dtor = nv04_fifo_dma_dtor, + .init = nv04_fifo_dma_init, + .fini = nv04_fifo_dma_fini, + .object_ctor = nv04_fifo_dma_object_ctor, + .object_dtor = nv04_fifo_dma_object_dtor, +}; + +static int +nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv03_channel_dma_v0 v0; + } *args = data; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nv04_fifo_chan *chan = NULL; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + int ret; + + nvif_ioctl(parent, "create channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " + "offset %08x\n", args->v0.version, + args->v0.pushbuf, args->v0.offset); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base, + 0x1000, 0x1000, false, 0, args->v0.pushbuf, + (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_SW), + 0, 0x800000, 0x10000, oclass, &chan->base); + chan->fifo = fifo; + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + chan->ramfc = chan->base.chid * 32; + + nvkm_kmap(imem->ramfc); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.push->addr >> 4); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x10, + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_done(imem->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +nv04_fifo_dma_oclass = { + .base.oclass = NV03_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv04_fifo_dma_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c new file mode 100644 index 000000000..34f68e5bd --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c @@ -0,0 +1,96 @@ +/* + * 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 "channv04.h" +#include "regsnv04.h" + +#include +#include +#include + +#include +#include + +static int +nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv03_channel_dma_v0 v0; + } *args = data; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nv04_fifo_chan *chan = NULL; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + int ret; + + nvif_ioctl(parent, "create channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " + "offset %08x\n", args->v0.version, + args->v0.pushbuf, args->v0.offset); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base, + 0x1000, 0x1000, false, 0, args->v0.pushbuf, + (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_SW), + 0, 0x800000, 0x10000, oclass, &chan->base); + chan->fifo = fifo; + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + chan->ramfc = chan->base.chid * 32; + + nvkm_kmap(imem->ramfc); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x14, + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_done(imem->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +nv10_fifo_dma_oclass = { + .base.oclass = NV10_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv10_fifo_dma_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c new file mode 100644 index 000000000..ed7cc9f2b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c @@ -0,0 +1,97 @@ +/* + * 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 "channv04.h" +#include "regsnv04.h" + +#include +#include +#include + +#include +#include + +static int +nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv03_channel_dma_v0 v0; + } *args = data; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nv04_fifo_chan *chan = NULL; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + int ret; + + nvif_ioctl(parent, "create channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " + "offset %08x\n", args->v0.version, + args->v0.pushbuf, args->v0.offset); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base, + 0x1000, 0x1000, false, 0, args->v0.pushbuf, + (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_MPEG) | /* NV31- */ + (1ULL << NVKM_ENGINE_SW), + 0, 0x800000, 0x10000, oclass, &chan->base); + chan->fifo = fifo; + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + chan->ramfc = chan->base.chid * 64; + + nvkm_kmap(imem->ramfc); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x14, + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_done(imem->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +nv17_fifo_dma_oclass = { + .base.oclass = NV17_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv17_fifo_dma_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c new file mode 100644 index 000000000..043b6c325 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c @@ -0,0 +1,243 @@ +/* + * 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 "channv04.h" +#include "regsnv04.h" + +#include +#include +#include + +#include +#include + +static bool +nv40_fifo_dma_engine(struct nvkm_engine *engine, u32 *reg, u32 *ctx) +{ + switch (engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW: + return false; + case NVKM_ENGINE_GR: + *reg = 0x0032e0; + *ctx = 0x38; + return true; + case NVKM_ENGINE_MPEG: + *reg = 0x00330c; + *ctx = 0x54; + return true; + default: + WARN_ON(1); + return false; + } +} + +static int +nv40_fifo_dma_engine_fini(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, bool suspend) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + unsigned long flags; + u32 reg, ctx; + int chid; + + if (!nv40_fifo_dma_engine(engine, ®, &ctx)) + return 0; + + spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_mask(device, 0x002500, 0x00000001, 0x00000000); + + chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1); + if (chid == chan->base.chid) + nvkm_wr32(device, reg, 0x00000000); + nvkm_kmap(imem->ramfc); + nvkm_wo32(imem->ramfc, chan->ramfc + ctx, 0x00000000); + nvkm_done(imem->ramfc); + + nvkm_mask(device, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&fifo->base.lock, flags); + return 0; +} + +static int +nv40_fifo_dma_engine_init(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nv04_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + unsigned long flags; + u32 inst, reg, ctx; + int chid; + + if (!nv40_fifo_dma_engine(engine, ®, &ctx)) + return 0; + inst = chan->engn[engine->subdev.index]->addr >> 4; + + spin_lock_irqsave(&fifo->base.lock, flags); + nvkm_mask(device, 0x002500, 0x00000001, 0x00000000); + + chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1); + if (chid == chan->base.chid) + nvkm_wr32(device, reg, inst); + nvkm_kmap(imem->ramfc); + nvkm_wo32(imem->ramfc, chan->ramfc + ctx, inst); + nvkm_done(imem->ramfc); + + nvkm_mask(device, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&fifo->base.lock, flags); + return 0; +} + +static void +nv40_fifo_dma_engine_dtor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + nvkm_gpuobj_del(&chan->engn[engine->subdev.index]); +} + +static int +nv40_fifo_dma_engine_ctor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, + struct nvkm_object *object) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + const int engn = engine->subdev.index; + u32 reg, ctx; + + if (!nv40_fifo_dma_engine(engine, ®, &ctx)) + return 0; + + return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]); +} + +static int +nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base, + struct nvkm_object *object) +{ + struct nv04_fifo_chan *chan = nv04_fifo_chan(base); + struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; + u32 context = chan->base.chid << 23; + u32 handle = object->handle; + int hash; + + switch (object->engine->subdev.index) { + case NVKM_ENGINE_DMAOBJ: + case NVKM_ENGINE_SW : context |= 0x00000000; break; + case NVKM_ENGINE_GR : context |= 0x00100000; break; + case NVKM_ENGINE_MPEG : context |= 0x00200000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + mutex_lock(&chan->fifo->base.engine.subdev.mutex); + hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4, + handle, context); + mutex_unlock(&chan->fifo->base.engine.subdev.mutex); + return hash; +} + +static const struct nvkm_fifo_chan_func +nv40_fifo_dma_func = { + .dtor = nv04_fifo_dma_dtor, + .init = nv04_fifo_dma_init, + .fini = nv04_fifo_dma_fini, + .engine_ctor = nv40_fifo_dma_engine_ctor, + .engine_dtor = nv40_fifo_dma_engine_dtor, + .engine_init = nv40_fifo_dma_engine_init, + .engine_fini = nv40_fifo_dma_engine_fini, + .object_ctor = nv40_fifo_dma_object_ctor, + .object_dtor = nv04_fifo_dma_object_dtor, +}; + +static int +nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv03_channel_dma_v0 v0; + } *args = data; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nv04_fifo_chan *chan = NULL; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + int ret; + + nvif_ioctl(parent, "create channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx " + "offset %08x\n", args->v0.version, + args->v0.pushbuf, args->v0.offset); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nvkm_fifo_chan_ctor(&nv40_fifo_dma_func, &fifo->base, + 0x1000, 0x1000, false, 0, args->v0.pushbuf, + (1ULL << NVKM_ENGINE_DMAOBJ) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_MPEG) | + (1ULL << NVKM_ENGINE_SW), + 0, 0xc00000, 0x1000, oclass, &chan->base); + chan->fifo = fifo; + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + chan->ramfc = chan->base.chid * 128; + + nvkm_kmap(imem->ramfc); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x18, 0x30000000 | + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nvkm_wo32(imem->ramfc, chan->ramfc + 0x3c, 0x0001ffff); + nvkm_done(imem->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +nv40_fifo_dma_oclass = { + .base.oclass = NV40_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv40_fifo_dma_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c new file mode 100644 index 000000000..6b3b15f12 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c @@ -0,0 +1,91 @@ +/* + * 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 +#include + +#include +#include + +static int +nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv50_channel_dma_v0 v0; + } *args = data; + struct nv50_fifo *fifo = nv50_fifo(base); + struct nv50_fifo_chan *chan; + int ret; + + nvif_ioctl(parent, "create channel dma size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel dma vers %d vm %llx " + "pushbuf %llx offset %016llx\n", + args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.offset); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + oclass, chan); + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + + nvkm_kmap(chan->ramfc); + nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset)); + nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078); + nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); + nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4); + nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff); + nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); + nvkm_wo32(chan->ramfc, 0x78, 0x00000000); + nvkm_wo32(chan->ramfc, 0x7c, 0x30000001); + nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->node->offset >> 4)); + nvkm_done(chan->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +nv50_fifo_dma_oclass = { + .base.oclass = NV50_CHANNEL_DMA, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_fifo_dma_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c index a04920b3c..ff7b52976 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c @@ -22,466 +22,41 @@ * Authors: Ben Skeggs */ #include "nv50.h" -#include "nv04.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ - -static int -g84_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *object) -{ - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_base *base = (void *)parent->parent; - struct nvkm_gpuobj *ectx = (void *)object; - u64 limit = ectx->addr + ectx->size - 1; - u64 start = ectx->addr; - u32 addr; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0020; break; - case NVDEV_ENGINE_VP : - case NVDEV_ENGINE_MSPDEC: addr = 0x0040; break; - case NVDEV_ENGINE_MSPPP : - case NVDEV_ENGINE_MPEG : addr = 0x0060; break; - case NVDEV_ENGINE_BSP : - case NVDEV_ENGINE_MSVLD : addr = 0x0080; break; - case NVDEV_ENGINE_CIPHER: - case NVDEV_ENGINE_SEC : addr = 0x00a0; break; - case NVDEV_ENGINE_CE0 : addr = 0x00c0; break; - default: - return -EINVAL; - } - - nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; - nv_wo32(base->eng, addr + 0x00, 0x00190000); - nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); - nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); - nv_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 | - upper_32_bits(start)); - nv_wo32(base->eng, addr + 0x10, 0x00000000); - nv_wo32(base->eng, addr + 0x14, 0x00000000); - bar->flush(bar); - return 0; -} - -static int -g84_fifo_context_detach(struct nvkm_object *parent, bool suspend, - struct nvkm_object *object) -{ - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_priv *priv = (void *)parent->engine; - struct nv50_fifo_base *base = (void *)parent->parent; - struct nv50_fifo_chan *chan = (void *)parent; - u32 addr, save, engn; - bool done; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break; - case NVDEV_ENGINE_VP : - case NVDEV_ENGINE_MSPDEC: engn = 3; addr = 0x0040; break; - case NVDEV_ENGINE_MSPPP : - case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break; - case NVDEV_ENGINE_BSP : - case NVDEV_ENGINE_MSVLD : engn = 5; addr = 0x0080; break; - case NVDEV_ENGINE_CIPHER: - case NVDEV_ENGINE_SEC : engn = 4; addr = 0x00a0; break; - case NVDEV_ENGINE_CE0 : engn = 2; addr = 0x00c0; break; - default: - return -EINVAL; - } - - save = nv_mask(priv, 0x002520, 0x0000003f, 1 << engn); - nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); - done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); - nv_wr32(priv, 0x002520, save); - if (!done) { - nv_error(priv, "channel %d [%s] unload timeout\n", - chan->base.chid, nvkm_client_name(chan)); - if (suspend) - return -EBUSY; - } - - nv_wo32(base->eng, addr + 0x00, 0x00000000); - nv_wo32(base->eng, addr + 0x04, 0x00000000); - nv_wo32(base->eng, addr + 0x08, 0x00000000); - nv_wo32(base->eng, addr + 0x0c, 0x00000000); - nv_wo32(base->eng, addr + 0x10, 0x00000000); - nv_wo32(base->eng, addr + 0x14, 0x00000000); - bar->flush(bar); - return 0; -} - -static int -g84_fifo_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 handle) -{ - struct nv50_fifo_chan *chan = (void *)parent; - u32 context; - - if (nv_iclass(object, NV_GPUOBJ_CLASS)) - context = nv_gpuobj(object)->node->offset >> 4; - else - context = 0x00000004; /* just non-zero */ - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_DMAOBJ: - case NVDEV_ENGINE_SW : context |= 0x00000000; break; - case NVDEV_ENGINE_GR : context |= 0x00100000; break; - case NVDEV_ENGINE_MPEG : - case NVDEV_ENGINE_MSPPP : context |= 0x00200000; break; - case NVDEV_ENGINE_ME : - case NVDEV_ENGINE_CE0 : context |= 0x00300000; break; - case NVDEV_ENGINE_VP : - case NVDEV_ENGINE_MSPDEC: context |= 0x00400000; break; - case NVDEV_ENGINE_CIPHER: - case NVDEV_ENGINE_SEC : - case NVDEV_ENGINE_VIC : context |= 0x00500000; break; - case NVDEV_ENGINE_BSP : - case NVDEV_ENGINE_MSVLD : context |= 0x00600000; break; - default: - return -EINVAL; - } - - return nvkm_ramht_insert(chan->ramht, 0, handle, context); -} - -static int -g84_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_base *base = (void *)parent; - struct nv50_fifo_chan *chan; - int ret; - - nv_ioctl(parent, "create channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " - "offset %016llx\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, - 0x2000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_MPEG) | - (1ULL << NVDEV_ENGINE_ME) | - (1ULL << NVDEV_ENGINE_VP) | - (1ULL << NVDEV_ENGINE_CIPHER) | - (1ULL << NVDEV_ENGINE_SEC) | - (1ULL << NVDEV_ENGINE_BSP) | - (1ULL << NVDEV_ENGINE_MSVLD) | - (1ULL << NVDEV_ENGINE_MSPDEC) | - (1ULL << NVDEV_ENGINE_MSPPP) | - (1ULL << NVDEV_ENGINE_CE0) | - (1ULL << NVDEV_ENGINE_VIC), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - ret = nvkm_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16, - &chan->ramht); - if (ret) - return ret; - - nv_parent(chan)->context_attach = g84_fifo_context_attach; - nv_parent(chan)->context_detach = g84_fifo_context_detach; - nv_parent(chan)->object_attach = g84_fifo_object_attach; - nv_parent(chan)->object_detach = nv50_fifo_object_detach; - - nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x3c, 0x003f6078); - nv_wo32(base->ramfc, 0x44, 0x01003fff); - nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); - nv_wo32(base->ramfc, 0x4c, 0xffffffff); - nv_wo32(base->ramfc, 0x60, 0x7fffffff); - nv_wo32(base->ramfc, 0x78, 0x00000000); - nv_wo32(base->ramfc, 0x7c, 0x30000001); - nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj.node->offset >> 4)); - nv_wo32(base->ramfc, 0x88, base->cache->addr >> 10); - nv_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12); - bar->flush(bar); - return 0; -} - -static int -g84_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv50_channel_gpfifo_v0 v0; - } *args = data; - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_base *base = (void *)parent; - struct nv50_fifo_chan *chan; - u64 ioffset, ilength; - int ret; - - nv_ioctl(parent, "create channel gpfifo size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x " - "ioffset %016llx ilength %08x\n", - args->v0.version, args->v0.pushbuf, args->v0.ioffset, - args->v0.ilength); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, - 0x2000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_MPEG) | - (1ULL << NVDEV_ENGINE_ME) | - (1ULL << NVDEV_ENGINE_VP) | - (1ULL << NVDEV_ENGINE_CIPHER) | - (1ULL << NVDEV_ENGINE_SEC) | - (1ULL << NVDEV_ENGINE_BSP) | - (1ULL << NVDEV_ENGINE_MSVLD) | - (1ULL << NVDEV_ENGINE_MSPDEC) | - (1ULL << NVDEV_ENGINE_MSPPP) | - (1ULL << NVDEV_ENGINE_CE0) | - (1ULL << NVDEV_ENGINE_VIC), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - ret = nvkm_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16, - &chan->ramht); - if (ret) - return ret; - - nv_parent(chan)->context_attach = g84_fifo_context_attach; - nv_parent(chan)->context_detach = g84_fifo_context_detach; - nv_parent(chan)->object_attach = g84_fifo_object_attach; - nv_parent(chan)->object_detach = nv50_fifo_object_detach; - - ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); - - nv_wo32(base->ramfc, 0x3c, 0x403f6078); - nv_wo32(base->ramfc, 0x44, 0x01003fff); - nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); - nv_wo32(base->ramfc, 0x50, lower_32_bits(ioffset)); - nv_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); - nv_wo32(base->ramfc, 0x60, 0x7fffffff); - nv_wo32(base->ramfc, 0x78, 0x00000000); - nv_wo32(base->ramfc, 0x7c, 0x30000001); - nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj.node->offset >> 4)); - nv_wo32(base->ramfc, 0x88, base->cache->addr >> 10); - nv_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12); - bar->flush(bar); - return 0; -} - -static int -g84_fifo_chan_init(struct nvkm_object *object) -{ - struct nv50_fifo_priv *priv = (void *)object->engine; - struct nv50_fifo_base *base = (void *)object->parent; - struct nv50_fifo_chan *chan = (void *)object; - struct nvkm_gpuobj *ramfc = base->ramfc; - u32 chid = chan->base.chid; - int ret; - - ret = nvkm_fifo_channel_init(&chan->base); - if (ret) - return ret; - - nv_wr32(priv, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 8); - nv50_fifo_playlist_update(priv); - return 0; -} - -static struct nvkm_ofuncs -g84_fifo_ofuncs_dma = { - .ctor = g84_fifo_chan_ctor_dma, - .dtor = nv50_fifo_chan_dtor, - .init = g84_fifo_chan_init, - .fini = nv50_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_ofuncs -g84_fifo_ofuncs_ind = { - .ctor = g84_fifo_chan_ctor_ind, - .dtor = nv50_fifo_chan_dtor, - .init = g84_fifo_chan_init, - .fini = nv50_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -g84_fifo_sclass[] = { - { G82_CHANNEL_DMA, &g84_fifo_ofuncs_dma }, - { G82_CHANNEL_GPFIFO, &g84_fifo_ofuncs_ind }, - {} -}; - -/******************************************************************************* - * FIFO context - basically just the instmem reserved for the channel - ******************************************************************************/ - -static int -g84_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_fifo_base *base; - int ret; - - ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x10000, - 0x1000, NVOBJ_FLAG_HEAP, &base); - *pobject = nv_object(base); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x0200, 0, - NVOBJ_FLAG_ZERO_ALLOC, &base->eng); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x4000, 0, - 0, &base->pgd); - if (ret) - return ret; - - ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x1000, - 0x400, NVOBJ_FLAG_ZERO_ALLOC, &base->cache); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x0100, - 0x100, NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc); - if (ret) - return ret; - - return 0; -} - -static struct nvkm_oclass -g84_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_fifo_context_ctor, - .dtor = nv50_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, - }, -}; - -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ +#include "channv50.h" static void -g84_fifo_uevent_init(struct nvkm_event *event, int type, int index) +g84_fifo_uevent_fini(struct nvkm_fifo *fifo) { - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - nv_mask(fifo, 0x002140, 0x40000000, 0x40000000); + struct nvkm_device *device = fifo->engine.subdev.device; + nvkm_mask(device, 0x002140, 0x40000000, 0x00000000); } static void -g84_fifo_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - nv_mask(fifo, 0x002140, 0x40000000, 0x00000000); -} - -static const struct nvkm_event_func -g84_fifo_uevent_func = { - .ctor = nvkm_fifo_uevent_ctor, - .init = g84_fifo_uevent_init, - .fini = g84_fifo_uevent_fini, +g84_fifo_uevent_init(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + nvkm_mask(device, 0x002140, 0x40000000, 0x40000000); +} + +static const struct nvkm_fifo_func +g84_fifo = { + .dtor = nv50_fifo_dtor, + .oneinit = nv50_fifo_oneinit, + .init = nv50_fifo_init, + .intr = nv04_fifo_intr, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .uevent_init = g84_fifo_uevent_init, + .uevent_fini = g84_fifo_uevent_fini, + .chan = { + &g84_fifo_dma_oclass, + &g84_fifo_gpfifo_oclass, + NULL + }, }; -static int -g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +g84_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) { - struct nv50_fifo_priv *priv; - int ret; - - ret = nvkm_fifo_create(parent, engine, oclass, 1, 127, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0, - &priv->playlist[0]); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0, - &priv->playlist[1]); - if (ret) - return ret; - - ret = nvkm_event_init(&g84_fifo_uevent_func, 1, 1, &priv->base.uevent); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = nv04_fifo_intr; - nv_engine(priv)->cclass = &g84_fifo_cclass; - nv_engine(priv)->sclass = g84_fifo_sclass; - priv->base.pause = nv04_fifo_pause; - priv->base.start = nv04_fifo_start; - return 0; + return nv50_fifo_new_(&g84_fifo, device, index, pfifo); } - -struct nvkm_oclass * -g84_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_fifo_ctor, - .dtor = nv50_fifo_dtor, - .init = nv50_fifo_init, - .fini = _nvkm_fifo_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index b745252f2..ff6fcbda6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -21,365 +21,72 @@ * * Authors: Ben Skeggs */ -#include +#include "gf100.h" +#include "changf100.h" #include -#include #include -#include +#include #include -#include -#include -#include +#include #include -#include - -struct gf100_fifo_priv { - struct nvkm_fifo base; - - struct work_struct fault; - u64 mask; - - struct { - struct nvkm_gpuobj *mem[2]; - int active; - wait_queue_head_t wait; - } runlist; - - struct { - struct nvkm_gpuobj *mem; - struct nvkm_vma bar; - } user; - int spoon_nr; -}; - -struct gf100_fifo_base { - struct nvkm_fifo_base base; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; -}; - -struct gf100_fifo_chan { - struct nvkm_fifo_chan base; - enum { - STOPPED, - RUNNING, - KILLED - } state; -}; - -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ static void -gf100_fifo_runlist_update(struct gf100_fifo_priv *priv) +gf100_fifo_uevent_init(struct nvkm_fifo *fifo) { - struct nvkm_bar *bar = nvkm_bar(priv); - struct nvkm_gpuobj *cur; - int i, p; - - mutex_lock(&nv_subdev(priv)->mutex); - cur = priv->runlist.mem[priv->runlist.active]; - priv->runlist.active = !priv->runlist.active; - - for (i = 0, p = 0; i < 128; i++) { - struct gf100_fifo_chan *chan = (void *)priv->base.channel[i]; - if (chan && chan->state == RUNNING) { - nv_wo32(cur, p + 0, i); - nv_wo32(cur, p + 4, 0x00000004); - p += 8; - } - } - bar->flush(bar); - - nv_wr32(priv, 0x002270, cur->addr >> 12); - nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3)); - - if (wait_event_timeout(priv->runlist.wait, - !(nv_rd32(priv, 0x00227c) & 0x00100000), - msecs_to_jiffies(2000)) == 0) - nv_error(priv, "runlist update timeout\n"); - mutex_unlock(&nv_subdev(priv)->mutex); + struct nvkm_device *device = fifo->engine.subdev.device; + nvkm_mask(device, 0x002140, 0x80000000, 0x80000000); } -static int -gf100_fifo_context_attach(struct nvkm_object *parent, - struct nvkm_object *object) -{ - struct nvkm_bar *bar = nvkm_bar(parent); - struct gf100_fifo_base *base = (void *)parent->parent; - struct nvkm_engctx *ectx = (void *)object; - u32 addr; - int ret; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0210; break; - case NVDEV_ENGINE_CE0 : addr = 0x0230; break; - case NVDEV_ENGINE_CE1 : addr = 0x0240; break; - case NVDEV_ENGINE_MSVLD : addr = 0x0270; break; - case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break; - case NVDEV_ENGINE_MSPPP : addr = 0x0260; break; - default: - return -EINVAL; - } - - if (!ectx->vma.node) { - ret = nvkm_gpuobj_map_vm(nv_gpuobj(ectx), base->vm, - NV_MEM_ACCESS_RW, &ectx->vma); - if (ret) - return ret; - - nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; - } - - nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); - nv_wo32(base, addr + 0x04, upper_32_bits(ectx->vma.offset)); - bar->flush(bar); - return 0; -} - -static int -gf100_fifo_context_detach(struct nvkm_object *parent, bool suspend, - struct nvkm_object *object) +static void +gf100_fifo_uevent_fini(struct nvkm_fifo *fifo) { - struct nvkm_bar *bar = nvkm_bar(parent); - struct gf100_fifo_priv *priv = (void *)parent->engine; - struct gf100_fifo_base *base = (void *)parent->parent; - struct gf100_fifo_chan *chan = (void *)parent; - u32 addr; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0210; break; - case NVDEV_ENGINE_CE0 : addr = 0x0230; break; - case NVDEV_ENGINE_CE1 : addr = 0x0240; break; - case NVDEV_ENGINE_MSVLD : addr = 0x0270; break; - case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break; - case NVDEV_ENGINE_MSPPP : addr = 0x0260; break; - default: - return -EINVAL; - } - - nv_wr32(priv, 0x002634, chan->base.chid); - if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { - nv_error(priv, "channel %d [%s] kick timeout\n", - chan->base.chid, nvkm_client_name(chan)); - if (suspend) - return -EBUSY; - } - - nv_wo32(base, addr + 0x00, 0x00000000); - nv_wo32(base, addr + 0x04, 0x00000000); - bar->flush(bar); - return 0; + struct nvkm_device *device = fifo->engine.subdev.device; + nvkm_mask(device, 0x002140, 0x80000000, 0x00000000); } -static int -gf100_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +void +gf100_fifo_runlist_update(struct gf100_fifo *fifo) { - union { - struct nv50_channel_gpfifo_v0 v0; - } *args = data; - struct nvkm_bar *bar = nvkm_bar(parent); - struct gf100_fifo_priv *priv = (void *)engine; - struct gf100_fifo_base *base = (void *)parent; struct gf100_fifo_chan *chan; - u64 usermem, ioffset, ilength; - int ret, i; - - nv_ioctl(parent, "create channel gpfifo size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x " - "ioffset %016llx ilength %08x\n", - args->v0.version, args->v0.pushbuf, args->v0.ioffset, - args->v0.ilength); - } else - return ret; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_memory *cur; + int nr = 0; - ret = nvkm_fifo_channel_create(parent, engine, oclass, 1, - priv->user.bar.offset, 0x1000, - args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_CE0) | - (1ULL << NVDEV_ENGINE_CE1) | - (1ULL << NVDEV_ENGINE_MSVLD) | - (1ULL << NVDEV_ENGINE_MSPDEC) | - (1ULL << NVDEV_ENGINE_MSPPP), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; + mutex_lock(&subdev->mutex); + cur = fifo->runlist.mem[fifo->runlist.active]; + fifo->runlist.active = !fifo->runlist.active; - args->v0.chid = chan->base.chid; - - nv_parent(chan)->context_attach = gf100_fifo_context_attach; - nv_parent(chan)->context_detach = gf100_fifo_context_detach; - - usermem = chan->base.chid * 0x1000; - ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); - - for (i = 0; i < 0x1000; i += 4) - nv_wo32(priv->user.mem, usermem + i, 0x00000000); - - nv_wo32(base, 0x08, lower_32_bits(priv->user.mem->addr + usermem)); - nv_wo32(base, 0x0c, upper_32_bits(priv->user.mem->addr + usermem)); - nv_wo32(base, 0x10, 0x0000face); - nv_wo32(base, 0x30, 0xfffff902); - nv_wo32(base, 0x48, lower_32_bits(ioffset)); - nv_wo32(base, 0x4c, upper_32_bits(ioffset) | (ilength << 16)); - nv_wo32(base, 0x54, 0x00000002); - nv_wo32(base, 0x84, 0x20400000); - nv_wo32(base, 0x94, 0x30000001); - nv_wo32(base, 0x9c, 0x00000100); - nv_wo32(base, 0xa4, 0x1f1f1f1f); - nv_wo32(base, 0xa8, 0x1f1f1f1f); - nv_wo32(base, 0xac, 0x0000001f); - nv_wo32(base, 0xb8, 0xf8000000); - nv_wo32(base, 0xf8, 0x10003080); /* 0x002310 */ - nv_wo32(base, 0xfc, 0x10000010); /* 0x002350 */ - bar->flush(bar); - return 0; -} - -static int -gf100_fifo_chan_init(struct nvkm_object *object) -{ - struct nvkm_gpuobj *base = nv_gpuobj(object->parent); - struct gf100_fifo_priv *priv = (void *)object->engine; - struct gf100_fifo_chan *chan = (void *)object; - u32 chid = chan->base.chid; - int ret; - - ret = nvkm_fifo_channel_init(&chan->base); - if (ret) - return ret; - - nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12); - - if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) { - nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001); - gf100_fifo_runlist_update(priv); - } - - return 0; -} - -static void gf100_fifo_intr_engine(struct gf100_fifo_priv *priv); - -static int -gf100_fifo_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct gf100_fifo_priv *priv = (void *)object->engine; - struct gf100_fifo_chan *chan = (void *)object; - u32 chid = chan->base.chid; - - if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) { - nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); - gf100_fifo_runlist_update(priv); + nvkm_kmap(cur); + list_for_each_entry(chan, &fifo->chan, head) { + nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid); + nvkm_wo32(cur, (nr * 8) + 4, 0x00000004); + nr++; } + nvkm_done(cur); - gf100_fifo_intr_engine(priv); - - nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000); - return nvkm_fifo_channel_fini(&chan->base, suspend); -} - -static struct nvkm_ofuncs -gf100_fifo_ofuncs = { - .ctor = gf100_fifo_chan_ctor, - .dtor = _nvkm_fifo_channel_dtor, - .init = gf100_fifo_chan_init, - .fini = gf100_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -gf100_fifo_sclass[] = { - { FERMI_CHANNEL_GPFIFO, &gf100_fifo_ofuncs }, - {} -}; - -/******************************************************************************* - * FIFO context - instmem heap and vm setup - ******************************************************************************/ - -static int -gf100_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_fifo_base *base; - int ret; - - ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_HEAP, &base); - *pobject = nv_object(base); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), NULL, 0x10000, 0x1000, 0, - &base->pgd); - if (ret) - return ret; - - nv_wo32(base, 0x0200, lower_32_bits(base->pgd->addr)); - nv_wo32(base, 0x0204, upper_32_bits(base->pgd->addr)); - nv_wo32(base, 0x0208, 0xffffffff); - nv_wo32(base, 0x020c, 0x000000ff); + nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12); + nvkm_wr32(device, 0x002274, 0x01f00000 | nr); - ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd); - if (ret) - return ret; - - return 0; -} - -static void -gf100_fifo_context_dtor(struct nvkm_object *object) -{ - struct gf100_fifo_base *base = (void *)object; - nvkm_vm_ref(NULL, &base->vm, base->pgd); - nvkm_gpuobj_ref(NULL, &base->pgd); - nvkm_fifo_context_destroy(&base->base); + if (wait_event_timeout(fifo->runlist.wait, + !(nvkm_rd32(device, 0x00227c) & 0x00100000), + msecs_to_jiffies(2000)) == 0) + nvkm_error(subdev, "runlist update timeout\n"); + mutex_unlock(&subdev->mutex); } -static struct nvkm_oclass -gf100_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_fifo_context_ctor, - .dtor = gf100_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, - }, -}; - -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - static inline int -gf100_fifo_engidx(struct gf100_fifo_priv *priv, u32 engn) +gf100_fifo_engidx(struct gf100_fifo *fifo, u32 engn) { switch (engn) { - case NVDEV_ENGINE_GR : engn = 0; break; - case NVDEV_ENGINE_MSVLD : engn = 1; break; - case NVDEV_ENGINE_MSPPP : engn = 2; break; - case NVDEV_ENGINE_MSPDEC: engn = 3; break; - case NVDEV_ENGINE_CE0 : engn = 4; break; - case NVDEV_ENGINE_CE1 : engn = 5; break; + case NVKM_ENGINE_GR : engn = 0; break; + case NVKM_ENGINE_MSVLD : engn = 1; break; + case NVKM_ENGINE_MSPPP : engn = 2; break; + case NVKM_ENGINE_MSPDEC: engn = 3; break; + case NVKM_ENGINE_CE0 : engn = 4; break; + case NVKM_ENGINE_CE1 : engn = 5; break; default: return -1; } @@ -388,95 +95,73 @@ gf100_fifo_engidx(struct gf100_fifo_priv *priv, u32 engn) } static inline struct nvkm_engine * -gf100_fifo_engine(struct gf100_fifo_priv *priv, u32 engn) +gf100_fifo_engine(struct gf100_fifo *fifo, u32 engn) { + struct nvkm_device *device = fifo->base.engine.subdev.device; + switch (engn) { - case 0: engn = NVDEV_ENGINE_GR; break; - case 1: engn = NVDEV_ENGINE_MSVLD; break; - case 2: engn = NVDEV_ENGINE_MSPPP; break; - case 3: engn = NVDEV_ENGINE_MSPDEC; break; - case 4: engn = NVDEV_ENGINE_CE0; break; - case 5: engn = NVDEV_ENGINE_CE1; break; + case 0: engn = NVKM_ENGINE_GR; break; + case 1: engn = NVKM_ENGINE_MSVLD; break; + case 2: engn = NVKM_ENGINE_MSPPP; break; + case 3: engn = NVKM_ENGINE_MSPDEC; break; + case 4: engn = NVKM_ENGINE_CE0; break; + case 5: engn = NVKM_ENGINE_CE1; break; default: return NULL; } - return nvkm_engine(priv, engn); + return nvkm_device_engine(device, engn); } static void gf100_fifo_recover_work(struct work_struct *work) { - struct gf100_fifo_priv *priv = container_of(work, typeof(*priv), fault); - struct nvkm_object *engine; + struct gf100_fifo *fifo = container_of(work, typeof(*fifo), fault); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_engine *engine; unsigned long flags; u32 engn, engm = 0; u64 mask, todo; - spin_lock_irqsave(&priv->base.lock, flags); - mask = priv->mask; - priv->mask = 0ULL; - spin_unlock_irqrestore(&priv->base.lock, flags); + spin_lock_irqsave(&fifo->base.lock, flags); + mask = fifo->mask; + fifo->mask = 0ULL; + spin_unlock_irqrestore(&fifo->base.lock, flags); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) - engm |= 1 << gf100_fifo_engidx(priv, engn); - nv_mask(priv, 0x002630, engm, engm); + engm |= 1 << gf100_fifo_engidx(fifo, engn); + nvkm_mask(device, 0x002630, engm, engm); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { - if ((engine = (void *)nvkm_engine(priv, engn))) { - nv_ofuncs(engine)->fini(engine, false); - WARN_ON(nv_ofuncs(engine)->init(engine)); + if ((engine = nvkm_device_engine(device, engn))) { + nvkm_subdev_fini(&engine->subdev, false); + WARN_ON(nvkm_subdev_init(&engine->subdev)); } } - gf100_fifo_runlist_update(priv); - nv_wr32(priv, 0x00262c, engm); - nv_mask(priv, 0x002630, engm, 0x00000000); + gf100_fifo_runlist_update(fifo); + nvkm_wr32(device, 0x00262c, engm); + nvkm_mask(device, 0x002630, engm, 0x00000000); } static void -gf100_fifo_recover(struct gf100_fifo_priv *priv, struct nvkm_engine *engine, +gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, struct gf100_fifo_chan *chan) { + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; u32 chid = chan->base.chid; - unsigned long flags; - nv_error(priv, "%s engine fault on channel %d, recovering...\n", - nv_subdev(engine)->name, chid); + nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n", + nvkm_subdev_name[engine->subdev.index], chid); + assert_spin_locked(&fifo->base.lock); - nv_mask(priv, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000); - chan->state = KILLED; + nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000); + list_del_init(&chan->head); + chan->killed = true; - spin_lock_irqsave(&priv->base.lock, flags); - priv->mask |= 1ULL << nv_engidx(engine); - spin_unlock_irqrestore(&priv->base.lock, flags); - schedule_work(&priv->fault); -} - -static int -gf100_fifo_swmthd(struct gf100_fifo_priv *priv, u32 chid, u32 mthd, u32 data) -{ - struct gf100_fifo_chan *chan = NULL; - struct nvkm_handle *bind; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&priv->base.lock, flags); - if (likely(chid >= priv->base.min && chid <= priv->base.max)) - chan = (void *)priv->base.channel[chid]; - if (unlikely(!chan)) - goto out; - - bind = nvkm_namedb_get_class(nv_namedb(chan), 0x906e); - if (likely(bind)) { - if (!mthd || !nv_call(bind->object, mthd, data)) - ret = 0; - nvkm_namedb_put(bind); - } - -out: - spin_unlock_irqrestore(&priv->base.lock, flags); - return ret; + fifo->mask |= 1ULL << engine->subdev.index; + schedule_work(&fifo->fault); } static const struct nvkm_enum @@ -486,14 +171,17 @@ gf100_fifo_sched_reason[] = { }; static void -gf100_fifo_intr_sched_ctxsw(struct gf100_fifo_priv *priv) +gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo) { + struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_engine *engine; struct gf100_fifo_chan *chan; + unsigned long flags; u32 engn; + spin_lock_irqsave(&fifo->base.lock, flags); for (engn = 0; engn < 6; engn++) { - u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04)); + u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04)); u32 busy = (stat & 0x80000000); u32 save = (stat & 0x00100000); /* maybe? */ u32 unk0 = (stat & 0x00040000); @@ -502,32 +190,36 @@ gf100_fifo_intr_sched_ctxsw(struct gf100_fifo_priv *priv) (void)save; if (busy && unk0 && unk1) { - if (!(chan = (void *)priv->base.channel[chid])) - continue; - if (!(engine = gf100_fifo_engine(priv, engn))) - continue; - gf100_fifo_recover(priv, engine, chan); + list_for_each_entry(chan, &fifo->chan, head) { + if (chan->base.chid == chid) { + engine = gf100_fifo_engine(fifo, engn); + if (!engine) + break; + gf100_fifo_recover(fifo, engine, chan); + break; + } + } } } + spin_unlock_irqrestore(&fifo->base.lock, flags); } static void -gf100_fifo_intr_sched(struct gf100_fifo_priv *priv) +gf100_fifo_intr_sched(struct gf100_fifo *fifo) { - u32 intr = nv_rd32(priv, 0x00254c); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x00254c); u32 code = intr & 0x000000ff; const struct nvkm_enum *en; - char enunk[6] = ""; en = nvkm_enum_find(gf100_fifo_sched_reason, code); - if (!en) - snprintf(enunk, sizeof(enunk), "UNK%02x", code); - nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk); + nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : ""); switch (code) { case 0x0a: - gf100_fifo_intr_sched_ctxsw(priv); + gf100_fifo_intr_sched_ctxsw(fifo); break; default: break; @@ -536,17 +228,17 @@ gf100_fifo_intr_sched(struct gf100_fifo_priv *priv) static const struct nvkm_enum gf100_fifo_fault_engine[] = { - { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR }, - { 0x03, "PEEPHOLE", NULL, NVDEV_ENGINE_IFB }, - { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR }, - { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM }, - { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO }, - { 0x10, "PMSVLD", NULL, NVDEV_ENGINE_MSVLD }, - { 0x11, "PMSPPP", NULL, NVDEV_ENGINE_MSPPP }, + { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, + { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB }, + { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, + { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM }, + { 0x07, "PFIFO", NULL, NVKM_ENGINE_FIFO }, + { 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD }, + { 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP }, { 0x13, "PCOUNTER" }, - { 0x14, "PMSPDEC", NULL, NVDEV_ENGINE_MSPDEC }, - { 0x15, "PCE0", NULL, NVDEV_ENGINE_CE0 }, - { 0x16, "PCE1", NULL, NVDEV_ENGINE_CE1 }, + { 0x14, "PMSPDEC", NULL, NVKM_ENGINE_MSPDEC }, + { 0x15, "PCE0", NULL, NVKM_ENGINE_CE0 }, + { 0x16, "PCE1", NULL, NVKM_ENGINE_CE1 }, { 0x17, "PDAEMON" }, {} }; @@ -594,79 +286,65 @@ gf100_fifo_fault_gpcclient[] = { }; static void -gf100_fifo_intr_fault(struct gf100_fifo_priv *priv, int unit) +gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit) { - u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10)); - u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10)); - u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); - u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); + u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); + u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); + u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10)); u32 gpc = (stat & 0x1f000000) >> 24; u32 client = (stat & 0x00001f00) >> 8; u32 write = (stat & 0x00000080); u32 hub = (stat & 0x00000040); u32 reason = (stat & 0x0000000f); - struct nvkm_object *engctx = NULL, *object; - struct nvkm_engine *engine = NULL; const struct nvkm_enum *er, *eu, *ec; - char erunk[6] = ""; - char euunk[6] = ""; - char ecunk[6] = ""; - char gpcid[3] = ""; + struct nvkm_engine *engine = NULL; + struct nvkm_fifo_chan *chan; + unsigned long flags; + char gpcid[8] = ""; er = nvkm_enum_find(gf100_fifo_fault_reason, reason); - if (!er) - snprintf(erunk, sizeof(erunk), "UNK%02X", reason); - eu = nvkm_enum_find(gf100_fifo_fault_engine, unit); + if (hub) { + ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client); + } else { + ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client); + snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc); + } + if (eu) { switch (eu->data2) { - case NVDEV_SUBDEV_BAR: - nv_mask(priv, 0x001704, 0x00000000, 0x00000000); + case NVKM_SUBDEV_BAR: + nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); break; - case NVDEV_SUBDEV_INSTMEM: - nv_mask(priv, 0x001714, 0x00000000, 0x00000000); + case NVKM_SUBDEV_INSTMEM: + nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); break; - case NVDEV_ENGINE_IFB: - nv_mask(priv, 0x001718, 0x00000000, 0x00000000); + case NVKM_ENGINE_IFB: + nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); break; default: - engine = nvkm_engine(priv, eu->data2); - if (engine) - engctx = nvkm_engctx_get(engine, inst); + engine = nvkm_device_engine(device, eu->data2); break; } - } else { - snprintf(euunk, sizeof(euunk), "UNK%02x", unit); } - if (hub) { - ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client); - } else { - ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client); - snprintf(gpcid, sizeof(gpcid), "%d", gpc); - } + chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags); - if (!ec) - snprintf(ecunk, sizeof(ecunk), "UNK%02x", client); - - nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on " - "channel 0x%010llx [%s]\n", write ? "write" : "read", - (u64)vahi << 32 | valo, er ? er->name : erunk, - eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/", - ec ? ec->name : ecunk, (u64)inst << 12, - nvkm_client_name(engctx)); - - object = engctx; - while (object) { - switch (nv_mclass(object)) { - case FERMI_CHANNEL_GPFIFO: - gf100_fifo_recover(priv, engine, (void *)object); - break; - } - object = object->parent; - } + nvkm_error(subdev, + "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " + "reason %02x [%s] on channel %d [%010llx %s]\n", + write ? "write" : "read", (u64)vahi << 32 | valo, + unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "", + reason, er ? er->name : "", chan ? chan->chid : -1, + (u64)inst << 12, + chan ? chan->object.client->name : "unknown"); - nvkm_engctx_put(engctx); + if (engine && chan) + gf100_fifo_recover(fifo, engine, (void *)chan); + nvkm_fifo_chan_put(&fifo->base, flags, &chan); } static const struct nvkm_bitfield @@ -678,290 +356,288 @@ gf100_fifo_pbdma_intr[] = { }; static void -gf100_fifo_intr_pbdma(struct gf100_fifo_priv *priv, int unit) +gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) { - u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); - u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); - u32 data = nv_rd32(priv, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0x7f; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)); + u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000)); + u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000)); + u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f; u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); - u32 show = stat; + struct nvkm_fifo_chan *chan; + unsigned long flags; + u32 show= stat; + char msg[128]; if (stat & 0x00800000) { - if (!gf100_fifo_swmthd(priv, chid, mthd, data)) - show &= ~0x00800000; + if (device->sw) { + if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) + show &= ~0x00800000; + } } if (show) { - nv_error(priv, "PBDMA%d:", unit); - nvkm_bitfield_print(gf100_fifo_pbdma_intr, show); - pr_cont("\n"); - nv_error(priv, - "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, - nvkm_client_name_for_fifo_chid(&priv->base, chid), - subc, mthd, data); - } - - nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); - nv_wr32(priv, 0x040108 + (unit * 0x2000), stat); + nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show); + chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " + "subc %d mthd %04x data %08x\n", + unit, show, msg, chid, chan ? chan->inst->addr : 0, + chan ? chan->object.client->name : "unknown", + subc, mthd, data); + nvkm_fifo_chan_put(&fifo->base, flags, &chan); + } + + nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); + nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); } static void -gf100_fifo_intr_runlist(struct gf100_fifo_priv *priv) +gf100_fifo_intr_runlist(struct gf100_fifo *fifo) { - u32 intr = nv_rd32(priv, 0x002a00); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x002a00); if (intr & 0x10000000) { - wake_up(&priv->runlist.wait); - nv_wr32(priv, 0x002a00, 0x10000000); + wake_up(&fifo->runlist.wait); + nvkm_wr32(device, 0x002a00, 0x10000000); intr &= ~0x10000000; } if (intr) { - nv_error(priv, "RUNLIST 0x%08x\n", intr); - nv_wr32(priv, 0x002a00, intr); + nvkm_error(subdev, "RUNLIST %08x\n", intr); + nvkm_wr32(device, 0x002a00, intr); } } static void -gf100_fifo_intr_engine_unit(struct gf100_fifo_priv *priv, int engn) +gf100_fifo_intr_engine_unit(struct gf100_fifo *fifo, int engn) { - u32 intr = nv_rd32(priv, 0x0025a8 + (engn * 0x04)); - u32 inte = nv_rd32(priv, 0x002628); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x0025a8 + (engn * 0x04)); + u32 inte = nvkm_rd32(device, 0x002628); u32 unkn; - nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr); + nvkm_wr32(device, 0x0025a8 + (engn * 0x04), intr); for (unkn = 0; unkn < 8; unkn++) { u32 ints = (intr >> (unkn * 0x04)) & inte; if (ints & 0x1) { - nvkm_fifo_uevent(&priv->base); + nvkm_fifo_uevent(&fifo->base); ints &= ~1; } if (ints) { - nv_error(priv, "ENGINE %d %d %01x", engn, unkn, ints); - nv_mask(priv, 0x002628, ints, 0); + nvkm_error(subdev, "ENGINE %d %d %01x", + engn, unkn, ints); + nvkm_mask(device, 0x002628, ints, 0); } } } -static void -gf100_fifo_intr_engine(struct gf100_fifo_priv *priv) +void +gf100_fifo_intr_engine(struct gf100_fifo *fifo) { - u32 mask = nv_rd32(priv, 0x0025a4); + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 mask = nvkm_rd32(device, 0x0025a4); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_engine_unit(priv, unit); + gf100_fifo_intr_engine_unit(fifo, unit); mask &= ~(1 << unit); } } static void -gf100_fifo_intr(struct nvkm_subdev *subdev) +gf100_fifo_intr(struct nvkm_fifo *base) { - struct gf100_fifo_priv *priv = (void *)subdev; - u32 mask = nv_rd32(priv, 0x002140); - u32 stat = nv_rd32(priv, 0x002100) & mask; + struct gf100_fifo *fifo = gf100_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mask = nvkm_rd32(device, 0x002140); + u32 stat = nvkm_rd32(device, 0x002100) & mask; if (stat & 0x00000001) { - u32 intr = nv_rd32(priv, 0x00252c); - nv_warn(priv, "INTR 0x00000001: 0x%08x\n", intr); - nv_wr32(priv, 0x002100, 0x00000001); + u32 intr = nvkm_rd32(device, 0x00252c); + nvkm_warn(subdev, "INTR 00000001: %08x\n", intr); + nvkm_wr32(device, 0x002100, 0x00000001); stat &= ~0x00000001; } if (stat & 0x00000100) { - gf100_fifo_intr_sched(priv); - nv_wr32(priv, 0x002100, 0x00000100); + gf100_fifo_intr_sched(fifo); + nvkm_wr32(device, 0x002100, 0x00000100); stat &= ~0x00000100; } if (stat & 0x00010000) { - u32 intr = nv_rd32(priv, 0x00256c); - nv_warn(priv, "INTR 0x00010000: 0x%08x\n", intr); - nv_wr32(priv, 0x002100, 0x00010000); + u32 intr = nvkm_rd32(device, 0x00256c); + nvkm_warn(subdev, "INTR 00010000: %08x\n", intr); + nvkm_wr32(device, 0x002100, 0x00010000); stat &= ~0x00010000; } if (stat & 0x01000000) { - u32 intr = nv_rd32(priv, 0x00258c); - nv_warn(priv, "INTR 0x01000000: 0x%08x\n", intr); - nv_wr32(priv, 0x002100, 0x01000000); + u32 intr = nvkm_rd32(device, 0x00258c); + nvkm_warn(subdev, "INTR 01000000: %08x\n", intr); + nvkm_wr32(device, 0x002100, 0x01000000); stat &= ~0x01000000; } if (stat & 0x10000000) { - u32 mask = nv_rd32(priv, 0x00259c); + u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_fault(priv, unit); - nv_wr32(priv, 0x00259c, (1 << unit)); + gf100_fifo_intr_fault(fifo, unit); + nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } stat &= ~0x10000000; } if (stat & 0x20000000) { - u32 mask = nv_rd32(priv, 0x0025a0); + u32 mask = nvkm_rd32(device, 0x0025a0); while (mask) { u32 unit = __ffs(mask); - gf100_fifo_intr_pbdma(priv, unit); - nv_wr32(priv, 0x0025a0, (1 << unit)); + gf100_fifo_intr_pbdma(fifo, unit); + nvkm_wr32(device, 0x0025a0, (1 << unit)); mask &= ~(1 << unit); } stat &= ~0x20000000; } if (stat & 0x40000000) { - gf100_fifo_intr_runlist(priv); + gf100_fifo_intr_runlist(fifo); stat &= ~0x40000000; } if (stat & 0x80000000) { - gf100_fifo_intr_engine(priv); + gf100_fifo_intr_engine(fifo); stat &= ~0x80000000; } if (stat) { - nv_error(priv, "INTR 0x%08x\n", stat); - nv_mask(priv, 0x002140, stat, 0x00000000); - nv_wr32(priv, 0x002100, stat); + nvkm_error(subdev, "INTR %08x\n", stat); + nvkm_mask(device, 0x002140, stat, 0x00000000); + nvkm_wr32(device, 0x002100, stat); } } -static void -gf100_fifo_uevent_init(struct nvkm_event *event, int type, int index) -{ - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - nv_mask(fifo, 0x002140, 0x80000000, 0x80000000); -} - -static void -gf100_fifo_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - nv_mask(fifo, 0x002140, 0x80000000, 0x00000000); -} - -static const struct nvkm_event_func -gf100_fifo_uevent_func = { - .ctor = nvkm_fifo_uevent_ctor, - .init = gf100_fifo_uevent_init, - .fini = gf100_fifo_uevent_fini, -}; - static int -gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_fifo_oneinit(struct nvkm_fifo *base) { - struct gf100_fifo_priv *priv; + struct gf100_fifo *fifo = gf100_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; int ret; - ret = nvkm_fifo_create(parent, engine, oclass, 0, 127, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - INIT_WORK(&priv->fault, gf100_fifo_recover_work); - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, - &priv->runlist.mem[0]); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, + false, &fifo->runlist.mem[0]); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, - &priv->runlist.mem[1]); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, + false, &fifo->runlist.mem[1]); if (ret) return ret; - init_waitqueue_head(&priv->runlist.wait); + init_waitqueue_head(&fifo->runlist.wait); - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 128 * 0x1000, 0x1000, 0, - &priv->user.mem); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000, + 0x1000, false, &fifo->user.mem); if (ret) return ret; - ret = nvkm_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, - &priv->user.bar); + ret = nvkm_bar_umap(device->bar, 128 * 0x1000, 12, &fifo->user.bar); if (ret) return ret; - ret = nvkm_event_init(&gf100_fifo_uevent_func, 1, 1, &priv->base.uevent); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = gf100_fifo_intr; - nv_engine(priv)->cclass = &gf100_fifo_cclass; - nv_engine(priv)->sclass = gf100_fifo_sclass; + nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0); return 0; } static void -gf100_fifo_dtor(struct nvkm_object *object) +gf100_fifo_fini(struct nvkm_fifo *base) { - struct gf100_fifo_priv *priv = (void *)object; - - nvkm_gpuobj_unmap(&priv->user.bar); - nvkm_gpuobj_ref(NULL, &priv->user.mem); - nvkm_gpuobj_ref(NULL, &priv->runlist.mem[0]); - nvkm_gpuobj_ref(NULL, &priv->runlist.mem[1]); - - nvkm_fifo_destroy(&priv->base); + struct gf100_fifo *fifo = gf100_fifo(base); + flush_work(&fifo->fault); } -static int -gf100_fifo_init(struct nvkm_object *object) +static void +gf100_fifo_init(struct nvkm_fifo *base) { - struct gf100_fifo_priv *priv = (void *)object; - int ret, i; - - ret = nvkm_fifo_init(&priv->base); - if (ret) - return ret; + struct gf100_fifo *fifo = gf100_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int i; - nv_wr32(priv, 0x000204, 0xffffffff); - nv_wr32(priv, 0x002204, 0xffffffff); + nvkm_wr32(device, 0x000204, 0xffffffff); + nvkm_wr32(device, 0x002204, 0xffffffff); - priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204)); - nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr); + fifo->spoon_nr = hweight32(nvkm_rd32(device, 0x002204)); + nvkm_debug(subdev, "%d PBDMA unit(s)\n", fifo->spoon_nr); /* assign engines to PBDMAs */ - if (priv->spoon_nr >= 3) { - nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */ - nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */ - nv_wr32(priv, 0x002210, ~(1 << 1)); /* PMSPP */ - nv_wr32(priv, 0x002214, ~(1 << 1)); /* PMSVLD */ - nv_wr32(priv, 0x002218, ~(1 << 2)); /* PCE0 */ - nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */ + if (fifo->spoon_nr >= 3) { + nvkm_wr32(device, 0x002208, ~(1 << 0)); /* PGRAPH */ + nvkm_wr32(device, 0x00220c, ~(1 << 1)); /* PVP */ + nvkm_wr32(device, 0x002210, ~(1 << 1)); /* PMSPP */ + nvkm_wr32(device, 0x002214, ~(1 << 1)); /* PMSVLD */ + nvkm_wr32(device, 0x002218, ~(1 << 2)); /* PCE0 */ + nvkm_wr32(device, 0x00221c, ~(1 << 1)); /* PCE1 */ } /* PBDMA[n] */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + for (i = 0; i < fifo->spoon_nr; i++) { + nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ } - nv_mask(priv, 0x002200, 0x00000001, 0x00000001); - nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); + nvkm_mask(device, 0x002200, 0x00000001, 0x00000001); + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12); - nv_wr32(priv, 0x002100, 0xffffffff); - nv_wr32(priv, 0x002140, 0x7fffffff); - nv_wr32(priv, 0x002628, 0x00000001); /* ENGINE_INTR_EN */ - return 0; + nvkm_wr32(device, 0x002100, 0xffffffff); + nvkm_wr32(device, 0x002140, 0x7fffffff); + nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */ +} + +static void * +gf100_fifo_dtor(struct nvkm_fifo *base) +{ + struct gf100_fifo *fifo = gf100_fifo(base); + nvkm_vm_put(&fifo->user.bar); + nvkm_memory_del(&fifo->user.mem); + nvkm_memory_del(&fifo->runlist.mem[0]); + nvkm_memory_del(&fifo->runlist.mem[1]); + return fifo; } -struct nvkm_oclass * -gf100_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_fifo_ctor, - .dtor = gf100_fifo_dtor, - .init = gf100_fifo_init, - .fini = _nvkm_fifo_fini, +static const struct nvkm_fifo_func +gf100_fifo = { + .dtor = gf100_fifo_dtor, + .oneinit = gf100_fifo_oneinit, + .init = gf100_fifo_init, + .fini = gf100_fifo_fini, + .intr = gf100_fifo_intr, + .uevent_init = gf100_fifo_uevent_init, + .uevent_fini = gf100_fifo_uevent_fini, + .chan = { + &gf100_fifo_gpfifo_oclass, + NULL }, }; + +int +gf100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + struct gf100_fifo *fifo; + + if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) + return -ENOMEM; + INIT_LIST_HEAD(&fifo->chan); + INIT_WORK(&fifo->fault, gf100_fifo_recover_work); + *pfifo = &fifo->base; + + return nvkm_fifo_ctor(&gf100_fifo, device, index, 128, &fifo->base); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h new file mode 100644 index 000000000..c649ca9b5 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -0,0 +1,31 @@ +#ifndef __GF100_FIFO_H__ +#define __GF100_FIFO_H__ +#define gf100_fifo(p) container_of((p), struct gf100_fifo, base) +#include "priv.h" + +#include + +struct gf100_fifo { + struct nvkm_fifo base; + + struct list_head chan; + + struct work_struct fault; + u64 mask; + + struct { + struct nvkm_memory *mem[2]; + int active; + wait_queue_head_t wait; + } runlist; + + struct { + struct nvkm_memory *mem; + struct nvkm_vma bar; + } user; + int spoon_nr; +}; + +void gf100_fifo_intr_engine(struct gf100_fifo *); +void gf100_fifo_runlist_update(struct gf100_fifo *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index e10f96441..98970a0b7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -22,486 +22,121 @@ * Authors: Ben Skeggs */ #include "gk104.h" +#include "changk104.h" #include -#include #include -#include +#include #include -#include -#include -#include +#include #include -#include - -#define _(a,b) { (a), ((1ULL << (a)) | (b)) } -static const struct { - u64 subdev; - u64 mask; -} fifo_engine[] = { - _(NVDEV_ENGINE_GR , (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_CE2)), - _(NVDEV_ENGINE_MSPDEC , 0), - _(NVDEV_ENGINE_MSPPP , 0), - _(NVDEV_ENGINE_MSVLD , 0), - _(NVDEV_ENGINE_CE0 , 0), - _(NVDEV_ENGINE_CE1 , 0), - _(NVDEV_ENGINE_MSENC , 0), -}; -#undef _ -#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine) - -struct gk104_fifo_engn { - struct nvkm_gpuobj *runlist[2]; - int cur_runlist; - wait_queue_head_t wait; -}; - -struct gk104_fifo_priv { - struct nvkm_fifo base; - - struct work_struct fault; - u64 mask; - - struct gk104_fifo_engn engine[FIFO_ENGINE_NR]; - struct { - struct nvkm_gpuobj *mem; - struct nvkm_vma bar; - } user; - int spoon_nr; -}; - -struct gk104_fifo_base { - struct nvkm_fifo_base base; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; -}; - -struct gk104_fifo_chan { - struct nvkm_fifo_chan base; - u32 engine; - enum { - STOPPED, - RUNNING, - KILLED - } state; -}; - -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ - -static void -gk104_fifo_runlist_update(struct gk104_fifo_priv *priv, u32 engine) -{ - struct nvkm_bar *bar = nvkm_bar(priv); - struct gk104_fifo_engn *engn = &priv->engine[engine]; - struct nvkm_gpuobj *cur; - int i, p; - - mutex_lock(&nv_subdev(priv)->mutex); - cur = engn->runlist[engn->cur_runlist]; - engn->cur_runlist = !engn->cur_runlist; - - for (i = 0, p = 0; i < priv->base.max; i++) { - struct gk104_fifo_chan *chan = (void *)priv->base.channel[i]; - if (chan && chan->state == RUNNING && chan->engine == engine) { - nv_wo32(cur, p + 0, i); - nv_wo32(cur, p + 4, 0x00000000); - p += 8; - } - } - bar->flush(bar); - - nv_wr32(priv, 0x002270, cur->addr >> 12); - nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); - - if (wait_event_timeout(engn->wait, !(nv_rd32(priv, 0x002284 + - (engine * 0x08)) & 0x00100000), - msecs_to_jiffies(2000)) == 0) - nv_error(priv, "runlist %d update timeout\n", engine); - mutex_unlock(&nv_subdev(priv)->mutex); -} -static int -gk104_fifo_context_attach(struct nvkm_object *parent, - struct nvkm_object *object) +void +gk104_fifo_uevent_fini(struct nvkm_fifo *fifo) { - struct nvkm_bar *bar = nvkm_bar(parent); - struct gk104_fifo_base *base = (void *)parent->parent; - struct nvkm_engctx *ectx = (void *)object; - u32 addr; - int ret; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : - return 0; - case NVDEV_ENGINE_CE0: - case NVDEV_ENGINE_CE1: - case NVDEV_ENGINE_CE2: - nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; - return 0; - case NVDEV_ENGINE_GR : addr = 0x0210; break; - case NVDEV_ENGINE_MSVLD : addr = 0x0270; break; - case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break; - case NVDEV_ENGINE_MSPPP : addr = 0x0260; break; - default: - return -EINVAL; - } - - if (!ectx->vma.node) { - ret = nvkm_gpuobj_map_vm(nv_gpuobj(ectx), base->vm, - NV_MEM_ACCESS_RW, &ectx->vma); - if (ret) - return ret; - - nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; - } - - nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); - nv_wo32(base, addr + 0x04, upper_32_bits(ectx->vma.offset)); - bar->flush(bar); - return 0; + struct nvkm_device *device = fifo->engine.subdev.device; + nvkm_mask(device, 0x002140, 0x80000000, 0x00000000); } -static int -gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, - struct nvkm_object *object) +void +gk104_fifo_uevent_init(struct nvkm_fifo *fifo) { - struct nvkm_bar *bar = nvkm_bar(parent); - struct gk104_fifo_priv *priv = (void *)parent->engine; - struct gk104_fifo_base *base = (void *)parent->parent; - struct gk104_fifo_chan *chan = (void *)parent; - u32 addr; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_CE0 : - case NVDEV_ENGINE_CE1 : - case NVDEV_ENGINE_CE2 : addr = 0x0000; break; - case NVDEV_ENGINE_GR : addr = 0x0210; break; - case NVDEV_ENGINE_MSVLD : addr = 0x0270; break; - case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break; - case NVDEV_ENGINE_MSPPP : addr = 0x0260; break; - default: - return -EINVAL; - } - - nv_wr32(priv, 0x002634, chan->base.chid); - if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { - nv_error(priv, "channel %d [%s] kick timeout\n", - chan->base.chid, nvkm_client_name(chan)); - if (suspend) - return -EBUSY; - } - - if (addr) { - nv_wo32(base, addr + 0x00, 0x00000000); - nv_wo32(base, addr + 0x04, 0x00000000); - bar->flush(bar); - } - - return 0; + struct nvkm_device *device = fifo->engine.subdev.device; + nvkm_mask(device, 0x002140, 0x80000000, 0x80000000); } -static int -gk104_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +void +gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine) { - union { - struct kepler_channel_gpfifo_a_v0 v0; - } *args = data; - struct nvkm_bar *bar = nvkm_bar(parent); - struct gk104_fifo_priv *priv = (void *)engine; - struct gk104_fifo_base *base = (void *)parent; + struct gk104_fifo_engn *engn = &fifo->engine[engine]; struct gk104_fifo_chan *chan; - u64 usermem, ioffset, ilength; - int ret, i; - - nv_ioctl(parent, "create channel gpfifo size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x " - "ioffset %016llx ilength %08x engine %08x\n", - args->v0.version, args->v0.pushbuf, args->v0.ioffset, - args->v0.ilength, args->v0.engine); - } else - return ret; - - for (i = 0; i < FIFO_ENGINE_NR; i++) { - if (args->v0.engine & (1 << i)) { - if (nvkm_engine(parent, fifo_engine[i].subdev)) { - args->v0.engine = (1 << i); - break; - } - } - } - - if (i == FIFO_ENGINE_NR) { - nv_error(priv, "unsupported engines 0x%08x\n", args->v0.engine); - return -ENODEV; - } - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 1, - priv->user.bar.offset, 0x200, - args->v0.pushbuf, - fifo_engine[i].mask, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - nv_parent(chan)->context_attach = gk104_fifo_context_attach; - nv_parent(chan)->context_detach = gk104_fifo_context_detach; - chan->engine = i; - - usermem = chan->base.chid * 0x200; - ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); - - for (i = 0; i < 0x200; i += 4) - nv_wo32(priv->user.mem, usermem + i, 0x00000000); - - nv_wo32(base, 0x08, lower_32_bits(priv->user.mem->addr + usermem)); - nv_wo32(base, 0x0c, upper_32_bits(priv->user.mem->addr + usermem)); - nv_wo32(base, 0x10, 0x0000face); - nv_wo32(base, 0x30, 0xfffff902); - nv_wo32(base, 0x48, lower_32_bits(ioffset)); - nv_wo32(base, 0x4c, upper_32_bits(ioffset) | (ilength << 16)); - nv_wo32(base, 0x84, 0x20400000); - nv_wo32(base, 0x94, 0x30000001); - nv_wo32(base, 0x9c, 0x00000100); - nv_wo32(base, 0xac, 0x0000001f); - nv_wo32(base, 0xe8, chan->base.chid); - nv_wo32(base, 0xb8, 0xf8000000); - nv_wo32(base, 0xf8, 0x10003080); /* 0x002310 */ - nv_wo32(base, 0xfc, 0x10000010); /* 0x002350 */ - bar->flush(bar); - return 0; -} - -static int -gk104_fifo_chan_init(struct nvkm_object *object) -{ - struct nvkm_gpuobj *base = nv_gpuobj(object->parent); - struct gk104_fifo_priv *priv = (void *)object->engine; - struct gk104_fifo_chan *chan = (void *)object; - u32 chid = chan->base.chid; - int ret; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_memory *cur; + int nr = 0; - ret = nvkm_fifo_channel_init(&chan->base); - if (ret) - return ret; - - nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16); - nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); - - if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) { - nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); - gk104_fifo_runlist_update(priv, chan->engine); - nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); - } - - return 0; -} - -static int -gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct gk104_fifo_priv *priv = (void *)object->engine; - struct gk104_fifo_chan *chan = (void *)object; - u32 chid = chan->base.chid; + mutex_lock(&subdev->mutex); + cur = engn->runlist[engn->cur_runlist]; + engn->cur_runlist = !engn->cur_runlist; - if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) { - nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800); - gk104_fifo_runlist_update(priv, chan->engine); + nvkm_kmap(cur); + list_for_each_entry(chan, &engn->chan, head) { + nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid); + nvkm_wo32(cur, (nr * 8) + 4, 0x00000000); + nr++; } + nvkm_done(cur); - nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); - return nvkm_fifo_channel_fini(&chan->base, suspend); -} - -struct nvkm_ofuncs -gk104_fifo_chan_ofuncs = { - .ctor = gk104_fifo_chan_ctor, - .dtor = _nvkm_fifo_channel_dtor, - .init = gk104_fifo_chan_init, - .fini = gk104_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -gk104_fifo_sclass[] = { - { KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs }, - {} -}; - -/******************************************************************************* - * FIFO context - instmem heap and vm setup - ******************************************************************************/ - -static int -gk104_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk104_fifo_base *base; - int ret; - - ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base); - *pobject = nv_object(base); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), NULL, 0x10000, 0x1000, 0, - &base->pgd); - if (ret) - return ret; - - nv_wo32(base, 0x0200, lower_32_bits(base->pgd->addr)); - nv_wo32(base, 0x0204, upper_32_bits(base->pgd->addr)); - nv_wo32(base, 0x0208, 0xffffffff); - nv_wo32(base, 0x020c, 0x000000ff); - - ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd); - if (ret) - return ret; - - return 0; -} - -static void -gk104_fifo_context_dtor(struct nvkm_object *object) -{ - struct gk104_fifo_base *base = (void *)object; - nvkm_vm_ref(NULL, &base->vm, base->pgd); - nvkm_gpuobj_ref(NULL, &base->pgd); - nvkm_fifo_context_destroy(&base->base); -} - -static struct nvkm_oclass -gk104_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_fifo_context_ctor, - .dtor = gk104_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, - }, -}; + nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12); + nvkm_wr32(device, 0x002274, (engine << 20) | nr); -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - -static inline int -gk104_fifo_engidx(struct gk104_fifo_priv *priv, u32 engn) -{ - switch (engn) { - case NVDEV_ENGINE_GR : - case NVDEV_ENGINE_CE2 : engn = 0; break; - case NVDEV_ENGINE_MSVLD : engn = 1; break; - case NVDEV_ENGINE_MSPPP : engn = 2; break; - case NVDEV_ENGINE_MSPDEC: engn = 3; break; - case NVDEV_ENGINE_CE0 : engn = 4; break; - case NVDEV_ENGINE_CE1 : engn = 5; break; - case NVDEV_ENGINE_MSENC : engn = 6; break; - default: - return -1; - } - - return engn; + if (wait_event_timeout(engn->wait, !(nvkm_rd32(device, 0x002284 + + (engine * 0x08)) & 0x00100000), + msecs_to_jiffies(2000)) == 0) + nvkm_error(subdev, "runlist %d update timeout\n", engine); + mutex_unlock(&subdev->mutex); } static inline struct nvkm_engine * -gk104_fifo_engine(struct gk104_fifo_priv *priv, u32 engn) +gk104_fifo_engine(struct gk104_fifo *fifo, u32 engn) { - if (engn >= ARRAY_SIZE(fifo_engine)) - return NULL; - return nvkm_engine(priv, fifo_engine[engn].subdev); + struct nvkm_device *device = fifo->base.engine.subdev.device; + u64 subdevs = gk104_fifo_engine_subdev(engn); + if (subdevs) + return nvkm_device_engine(device, __ffs(subdevs)); + return NULL; } static void gk104_fifo_recover_work(struct work_struct *work) { - struct gk104_fifo_priv *priv = container_of(work, typeof(*priv), fault); - struct nvkm_object *engine; + struct gk104_fifo *fifo = container_of(work, typeof(*fifo), fault); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_engine *engine; unsigned long flags; u32 engn, engm = 0; u64 mask, todo; - spin_lock_irqsave(&priv->base.lock, flags); - mask = priv->mask; - priv->mask = 0ULL; - spin_unlock_irqrestore(&priv->base.lock, flags); + spin_lock_irqsave(&fifo->base.lock, flags); + mask = fifo->mask; + fifo->mask = 0ULL; + spin_unlock_irqrestore(&fifo->base.lock, flags); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) - engm |= 1 << gk104_fifo_engidx(priv, engn); - nv_mask(priv, 0x002630, engm, engm); + engm |= 1 << gk104_fifo_subdev_engine(engn); + nvkm_mask(device, 0x002630, engm, engm); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { - if ((engine = (void *)nvkm_engine(priv, engn))) { - nv_ofuncs(engine)->fini(engine, false); - WARN_ON(nv_ofuncs(engine)->init(engine)); + if ((engine = nvkm_device_engine(device, engn))) { + nvkm_subdev_fini(&engine->subdev, false); + WARN_ON(nvkm_subdev_init(&engine->subdev)); } - gk104_fifo_runlist_update(priv, gk104_fifo_engidx(priv, engn)); + gk104_fifo_runlist_update(fifo, gk104_fifo_subdev_engine(engn)); } - nv_wr32(priv, 0x00262c, engm); - nv_mask(priv, 0x002630, engm, 0x00000000); + nvkm_wr32(device, 0x00262c, engm); + nvkm_mask(device, 0x002630, engm, 0x00000000); } static void -gk104_fifo_recover(struct gk104_fifo_priv *priv, struct nvkm_engine *engine, +gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine, struct gk104_fifo_chan *chan) { + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; u32 chid = chan->base.chid; - unsigned long flags; - nv_error(priv, "%s engine fault on channel %d, recovering...\n", - nv_subdev(engine)->name, chid); + nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n", + nvkm_subdev_name[engine->subdev.index], chid); + assert_spin_locked(&fifo->base.lock); - nv_mask(priv, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800); - chan->state = KILLED; + nvkm_mask(device, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800); + list_del_init(&chan->head); + chan->killed = true; - spin_lock_irqsave(&priv->base.lock, flags); - priv->mask |= 1ULL << nv_engidx(engine); - spin_unlock_irqrestore(&priv->base.lock, flags); - schedule_work(&priv->fault); -} - -static int -gk104_fifo_swmthd(struct gk104_fifo_priv *priv, u32 chid, u32 mthd, u32 data) -{ - struct gk104_fifo_chan *chan = NULL; - struct nvkm_handle *bind; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&priv->base.lock, flags); - if (likely(chid >= priv->base.min && chid <= priv->base.max)) - chan = (void *)priv->base.channel[chid]; - if (unlikely(!chan)) - goto out; - - bind = nvkm_namedb_get_class(nv_namedb(chan), 0x906e); - if (likely(bind)) { - if (!mthd || !nv_call(bind->object, mthd, data)) - ret = 0; - nvkm_namedb_put(bind); - } - -out: - spin_unlock_irqrestore(&priv->base.lock, flags); - return ret; + fifo->mask |= 1ULL << engine->subdev.index; + schedule_work(&fifo->fault); } static const struct nvkm_enum @@ -516,18 +151,16 @@ gk104_fifo_bind_reason[] = { }; static void -gk104_fifo_intr_bind(struct gk104_fifo_priv *priv) +gk104_fifo_intr_bind(struct gk104_fifo *fifo) { - u32 intr = nv_rd32(priv, 0x00252c); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x00252c); u32 code = intr & 0x000000ff; - const struct nvkm_enum *en; - char enunk[6] = ""; - - en = nvkm_enum_find(gk104_fifo_bind_reason, code); - if (!en) - snprintf(enunk, sizeof(enunk), "UNK%02x", code); + const struct nvkm_enum *en = + nvkm_enum_find(gk104_fifo_bind_reason, code); - nv_error(priv, "BIND_ERROR [ %s ]\n", en ? en->name : enunk); + nvkm_error(subdev, "BIND_ERROR %02x [%s]\n", code, en ? en->name : ""); } static const struct nvkm_enum @@ -537,14 +170,17 @@ gk104_fifo_sched_reason[] = { }; static void -gk104_fifo_intr_sched_ctxsw(struct gk104_fifo_priv *priv) +gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo) { + struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_engine *engine; struct gk104_fifo_chan *chan; + unsigned long flags; u32 engn; - for (engn = 0; engn < ARRAY_SIZE(fifo_engine); engn++) { - u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04)); + spin_lock_irqsave(&fifo->base.lock, flags); + for (engn = 0; engn < ARRAY_SIZE(fifo->engine); engn++) { + u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04)); u32 busy = (stat & 0x80000000); u32 next = (stat & 0x07ff0000) >> 16; u32 chsw = (stat & 0x00008000); @@ -555,32 +191,35 @@ gk104_fifo_intr_sched_ctxsw(struct gk104_fifo_priv *priv) (void)save; if (busy && chsw) { - if (!(chan = (void *)priv->base.channel[chid])) - continue; - if (!(engine = gk104_fifo_engine(priv, engn))) - continue; - gk104_fifo_recover(priv, engine, chan); + list_for_each_entry(chan, &fifo->engine[engn].chan, head) { + if (chan->base.chid == chid) { + engine = gk104_fifo_engine(fifo, engn); + if (!engine) + break; + gk104_fifo_recover(fifo, engine, chan); + break; + } + } } } + spin_unlock_irqrestore(&fifo->base.lock, flags); } static void -gk104_fifo_intr_sched(struct gk104_fifo_priv *priv) +gk104_fifo_intr_sched(struct gk104_fifo *fifo) { - u32 intr = nv_rd32(priv, 0x00254c); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x00254c); u32 code = intr & 0x000000ff; - const struct nvkm_enum *en; - char enunk[6] = ""; - - en = nvkm_enum_find(gk104_fifo_sched_reason, code); - if (!en) - snprintf(enunk, sizeof(enunk), "UNK%02x", code); + const struct nvkm_enum *en = + nvkm_enum_find(gk104_fifo_sched_reason, code); - nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk); + nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : ""); switch (code) { case 0x0a: - gk104_fifo_intr_sched_ctxsw(priv); + gk104_fifo_intr_sched_ctxsw(fifo); break; default: break; @@ -588,38 +227,42 @@ gk104_fifo_intr_sched(struct gk104_fifo_priv *priv) } static void -gk104_fifo_intr_chsw(struct gk104_fifo_priv *priv) +gk104_fifo_intr_chsw(struct gk104_fifo *fifo) { - u32 stat = nv_rd32(priv, 0x00256c); - nv_error(priv, "CHSW_ERROR 0x%08x\n", stat); - nv_wr32(priv, 0x00256c, stat); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x00256c); + nvkm_error(subdev, "CHSW_ERROR %08x\n", stat); + nvkm_wr32(device, 0x00256c, stat); } static void -gk104_fifo_intr_dropped_fault(struct gk104_fifo_priv *priv) +gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo) { - u32 stat = nv_rd32(priv, 0x00259c); - nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x00259c); + nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat); } static const struct nvkm_enum gk104_fifo_fault_engine[] = { - { 0x00, "GR", NULL, NVDEV_ENGINE_GR }, - { 0x03, "IFB", NULL, NVDEV_ENGINE_IFB }, - { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR }, - { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM }, - { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO }, - { 0x08, "PBDMA1", NULL, NVDEV_ENGINE_FIFO }, - { 0x09, "PBDMA2", NULL, NVDEV_ENGINE_FIFO }, - { 0x10, "MSVLD", NULL, NVDEV_ENGINE_MSVLD }, - { 0x11, "MSPPP", NULL, NVDEV_ENGINE_MSPPP }, + { 0x00, "GR", NULL, NVKM_ENGINE_GR }, + { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, + { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, + { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM }, + { 0x07, "PBDMA0", NULL, NVKM_ENGINE_FIFO }, + { 0x08, "PBDMA1", NULL, NVKM_ENGINE_FIFO }, + { 0x09, "PBDMA2", NULL, NVKM_ENGINE_FIFO }, + { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD }, + { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP }, { 0x13, "PERF" }, - { 0x14, "MSPDEC", NULL, NVDEV_ENGINE_MSPDEC }, - { 0x15, "CE0", NULL, NVDEV_ENGINE_CE0 }, - { 0x16, "CE1", NULL, NVDEV_ENGINE_CE1 }, + { 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC }, + { 0x15, "CE0", NULL, NVKM_ENGINE_CE0 }, + { 0x16, "CE1", NULL, NVKM_ENGINE_CE1 }, { 0x17, "PMU" }, - { 0x19, "MSENC", NULL, NVDEV_ENGINE_MSENC }, - { 0x1b, "CE2", NULL, NVDEV_ENGINE_CE2 }, + { 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC }, + { 0x1b, "CE2", NULL, NVKM_ENGINE_CE2 }, {} }; @@ -708,80 +351,65 @@ gk104_fifo_fault_gpcclient[] = { }; static void -gk104_fifo_intr_fault(struct gk104_fifo_priv *priv, int unit) +gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit) { - u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10)); - u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10)); - u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); - u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); + u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); + u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); + u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10)); u32 gpc = (stat & 0x1f000000) >> 24; u32 client = (stat & 0x00001f00) >> 8; u32 write = (stat & 0x00000080); u32 hub = (stat & 0x00000040); u32 reason = (stat & 0x0000000f); - struct nvkm_object *engctx = NULL, *object; - struct nvkm_engine *engine = NULL; const struct nvkm_enum *er, *eu, *ec; - char erunk[6] = ""; - char euunk[6] = ""; - char ecunk[6] = ""; - char gpcid[3] = ""; + struct nvkm_engine *engine = NULL; + struct nvkm_fifo_chan *chan; + unsigned long flags; + char gpcid[8] = ""; er = nvkm_enum_find(gk104_fifo_fault_reason, reason); - if (!er) - snprintf(erunk, sizeof(erunk), "UNK%02X", reason); - eu = nvkm_enum_find(gk104_fifo_fault_engine, unit); + if (hub) { + ec = nvkm_enum_find(gk104_fifo_fault_hubclient, client); + } else { + ec = nvkm_enum_find(gk104_fifo_fault_gpcclient, client); + snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc); + } + if (eu) { switch (eu->data2) { - case NVDEV_SUBDEV_BAR: - nv_mask(priv, 0x001704, 0x00000000, 0x00000000); + case NVKM_SUBDEV_BAR: + nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); break; - case NVDEV_SUBDEV_INSTMEM: - nv_mask(priv, 0x001714, 0x00000000, 0x00000000); + case NVKM_SUBDEV_INSTMEM: + nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); break; - case NVDEV_ENGINE_IFB: - nv_mask(priv, 0x001718, 0x00000000, 0x00000000); + case NVKM_ENGINE_IFB: + nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); break; default: - engine = nvkm_engine(priv, eu->data2); - if (engine) - engctx = nvkm_engctx_get(engine, inst); + engine = nvkm_device_engine(device, eu->data2); break; } - } else { - snprintf(euunk, sizeof(euunk), "UNK%02x", unit); } - if (hub) { - ec = nvkm_enum_find(gk104_fifo_fault_hubclient, client); - } else { - ec = nvkm_enum_find(gk104_fifo_fault_gpcclient, client); - snprintf(gpcid, sizeof(gpcid), "%d", gpc); - } + chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags); - if (!ec) - snprintf(ecunk, sizeof(ecunk), "UNK%02x", client); - - nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on " - "channel 0x%010llx [%s]\n", write ? "write" : "read", - (u64)vahi << 32 | valo, er ? er->name : erunk, - eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/", - ec ? ec->name : ecunk, (u64)inst << 12, - nvkm_client_name(engctx)); - - object = engctx; - while (object) { - switch (nv_mclass(object)) { - case KEPLER_CHANNEL_GPFIFO_A: - case MAXWELL_CHANNEL_GPFIFO_A: - gk104_fifo_recover(priv, engine, (void *)object); - break; - } - object = object->parent; - } + nvkm_error(subdev, + "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " + "reason %02x [%s] on channel %d [%010llx %s]\n", + write ? "write" : "read", (u64)vahi << 32 | valo, + unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "", + reason, er ? er->name : "", chan ? chan->chid : -1, + (u64)inst << 12, + chan ? chan->object.client->name : "unknown"); - nvkm_engctx_put(engctx); + if (engine && chan) + gk104_fifo_recover(fifo, engine, (void *)chan); + nvkm_fifo_chan_put(&fifo->base, flags, &chan); } static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { @@ -819,35 +447,42 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { }; static void -gk104_fifo_intr_pbdma_0(struct gk104_fifo_priv *priv, int unit) +gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit) { - u32 mask = nv_rd32(priv, 0x04010c + (unit * 0x2000)); - u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)) & mask; - u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); - u32 data = nv_rd32(priv, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0xfff; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mask = nvkm_rd32(device, 0x04010c + (unit * 0x2000)); + u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)) & mask; + u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000)); + u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000)); + u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff; u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); u32 show = stat; + struct nvkm_fifo_chan *chan; + unsigned long flags; + char msg[128]; if (stat & 0x00800000) { - if (!gk104_fifo_swmthd(priv, chid, mthd, data)) - show &= ~0x00800000; - nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); + if (device->sw) { + if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) + show &= ~0x00800000; + } + nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); } if (show) { - nv_error(priv, "PBDMA%d:", unit); - nvkm_bitfield_print(gk104_fifo_pbdma_intr_0, show); - pr_cont("\n"); - nv_error(priv, - "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, - nvkm_client_name_for_fifo_chid(&priv->base, chid), - subc, mthd, data); + nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_0, show); + chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] " + "subc %d mthd %04x data %08x\n", + unit, show, msg, chid, chan ? chan->inst->addr : 0, + chan ? chan->object.client->name : "unknown", + subc, mthd, data); + nvkm_fifo_chan_put(&fifo->base, flags, &chan); } - nv_wr32(priv, 0x040108 + (unit * 0x2000), stat); + nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat); } static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { @@ -860,280 +495,266 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { }; static void -gk104_fifo_intr_pbdma_1(struct gk104_fifo_priv *priv, int unit) +gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit) { - u32 mask = nv_rd32(priv, 0x04014c + (unit * 0x2000)); - u32 stat = nv_rd32(priv, 0x040148 + (unit * 0x2000)) & mask; - u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0xfff; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mask = nvkm_rd32(device, 0x04014c + (unit * 0x2000)); + u32 stat = nvkm_rd32(device, 0x040148 + (unit * 0x2000)) & mask; + u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff; + char msg[128]; if (stat) { - nv_error(priv, "PBDMA%d:", unit); - nvkm_bitfield_print(gk104_fifo_pbdma_intr_1, stat); - pr_cont("\n"); - nv_error(priv, "PBDMA%d: ch %d %08x %08x\n", unit, chid, - nv_rd32(priv, 0x040150 + (unit * 0x2000)), - nv_rd32(priv, 0x040154 + (unit * 0x2000))); + nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_1, stat); + nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n", + unit, stat, msg, chid, + nvkm_rd32(device, 0x040150 + (unit * 0x2000)), + nvkm_rd32(device, 0x040154 + (unit * 0x2000))); } - nv_wr32(priv, 0x040148 + (unit * 0x2000), stat); + nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat); } static void -gk104_fifo_intr_runlist(struct gk104_fifo_priv *priv) +gk104_fifo_intr_runlist(struct gk104_fifo *fifo) { - u32 mask = nv_rd32(priv, 0x002a00); + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 mask = nvkm_rd32(device, 0x002a00); while (mask) { u32 engn = __ffs(mask); - wake_up(&priv->engine[engn].wait); - nv_wr32(priv, 0x002a00, 1 << engn); + wake_up(&fifo->engine[engn].wait); + nvkm_wr32(device, 0x002a00, 1 << engn); mask &= ~(1 << engn); } } static void -gk104_fifo_intr_engine(struct gk104_fifo_priv *priv) +gk104_fifo_intr_engine(struct gk104_fifo *fifo) { - nvkm_fifo_uevent(&priv->base); + nvkm_fifo_uevent(&fifo->base); } -static void -gk104_fifo_intr(struct nvkm_subdev *subdev) +void +gk104_fifo_intr(struct nvkm_fifo *base) { - struct gk104_fifo_priv *priv = (void *)subdev; - u32 mask = nv_rd32(priv, 0x002140); - u32 stat = nv_rd32(priv, 0x002100) & mask; + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mask = nvkm_rd32(device, 0x002140); + u32 stat = nvkm_rd32(device, 0x002100) & mask; if (stat & 0x00000001) { - gk104_fifo_intr_bind(priv); - nv_wr32(priv, 0x002100, 0x00000001); + gk104_fifo_intr_bind(fifo); + nvkm_wr32(device, 0x002100, 0x00000001); stat &= ~0x00000001; } if (stat & 0x00000010) { - nv_error(priv, "PIO_ERROR\n"); - nv_wr32(priv, 0x002100, 0x00000010); + nvkm_error(subdev, "PIO_ERROR\n"); + nvkm_wr32(device, 0x002100, 0x00000010); stat &= ~0x00000010; } if (stat & 0x00000100) { - gk104_fifo_intr_sched(priv); - nv_wr32(priv, 0x002100, 0x00000100); + gk104_fifo_intr_sched(fifo); + nvkm_wr32(device, 0x002100, 0x00000100); stat &= ~0x00000100; } if (stat & 0x00010000) { - gk104_fifo_intr_chsw(priv); - nv_wr32(priv, 0x002100, 0x00010000); + gk104_fifo_intr_chsw(fifo); + nvkm_wr32(device, 0x002100, 0x00010000); stat &= ~0x00010000; } if (stat & 0x00800000) { - nv_error(priv, "FB_FLUSH_TIMEOUT\n"); - nv_wr32(priv, 0x002100, 0x00800000); + nvkm_error(subdev, "FB_FLUSH_TIMEOUT\n"); + nvkm_wr32(device, 0x002100, 0x00800000); stat &= ~0x00800000; } if (stat & 0x01000000) { - nv_error(priv, "LB_ERROR\n"); - nv_wr32(priv, 0x002100, 0x01000000); + nvkm_error(subdev, "LB_ERROR\n"); + nvkm_wr32(device, 0x002100, 0x01000000); stat &= ~0x01000000; } if (stat & 0x08000000) { - gk104_fifo_intr_dropped_fault(priv); - nv_wr32(priv, 0x002100, 0x08000000); + gk104_fifo_intr_dropped_fault(fifo); + nvkm_wr32(device, 0x002100, 0x08000000); stat &= ~0x08000000; } if (stat & 0x10000000) { - u32 mask = nv_rd32(priv, 0x00259c); + u32 mask = nvkm_rd32(device, 0x00259c); while (mask) { u32 unit = __ffs(mask); - gk104_fifo_intr_fault(priv, unit); - nv_wr32(priv, 0x00259c, (1 << unit)); + gk104_fifo_intr_fault(fifo, unit); + nvkm_wr32(device, 0x00259c, (1 << unit)); mask &= ~(1 << unit); } stat &= ~0x10000000; } if (stat & 0x20000000) { - u32 mask = nv_rd32(priv, 0x0025a0); + u32 mask = nvkm_rd32(device, 0x0025a0); while (mask) { u32 unit = __ffs(mask); - gk104_fifo_intr_pbdma_0(priv, unit); - gk104_fifo_intr_pbdma_1(priv, unit); - nv_wr32(priv, 0x0025a0, (1 << unit)); + gk104_fifo_intr_pbdma_0(fifo, unit); + gk104_fifo_intr_pbdma_1(fifo, unit); + nvkm_wr32(device, 0x0025a0, (1 << unit)); mask &= ~(1 << unit); } stat &= ~0x20000000; } if (stat & 0x40000000) { - gk104_fifo_intr_runlist(priv); + gk104_fifo_intr_runlist(fifo); stat &= ~0x40000000; } if (stat & 0x80000000) { - nv_wr32(priv, 0x002100, 0x80000000); - gk104_fifo_intr_engine(priv); + nvkm_wr32(device, 0x002100, 0x80000000); + gk104_fifo_intr_engine(fifo); stat &= ~0x80000000; } if (stat) { - nv_error(priv, "INTR 0x%08x\n", stat); - nv_mask(priv, 0x002140, stat, 0x00000000); - nv_wr32(priv, 0x002100, stat); + nvkm_error(subdev, "INTR %08x\n", stat); + nvkm_mask(device, 0x002140, stat, 0x00000000); + nvkm_wr32(device, 0x002100, stat); } } -static void -gk104_fifo_uevent_init(struct nvkm_event *event, int type, int index) +void +gk104_fifo_fini(struct nvkm_fifo *base) { - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - nv_mask(fifo, 0x002140, 0x80000000, 0x80000000); + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + flush_work(&fifo->fault); + /* allow mmu fault interrupts, even when we're not using fifo */ + nvkm_mask(device, 0x002140, 0x10000000, 0x10000000); } -static void -gk104_fifo_uevent_fini(struct nvkm_event *event, int type, int index) +int +gk104_fifo_oneinit(struct nvkm_fifo *base) { - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent); - nv_mask(fifo, 0x002140, 0x80000000, 0x00000000); -} + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + int ret, i; -static const struct nvkm_event_func -gk104_fifo_uevent_func = { - .ctor = nvkm_fifo_uevent_ctor, - .init = gk104_fifo_uevent_init, - .fini = gk104_fifo_uevent_fini, -}; + for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) { + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + 0x8000, 0x1000, false, + &fifo->engine[i].runlist[0]); + if (ret) + return ret; -int -gk104_fifo_fini(struct nvkm_object *object, bool suspend) -{ - struct gk104_fifo_priv *priv = (void *)object; - int ret; + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + 0x8000, 0x1000, false, + &fifo->engine[i].runlist[1]); + if (ret) + return ret; + + init_waitqueue_head(&fifo->engine[i].wait); + INIT_LIST_HEAD(&fifo->engine[i].chan); + } - ret = nvkm_fifo_fini(&priv->base, suspend); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + fifo->base.nr * 0x200, 0x1000, true, + &fifo->user.mem); if (ret) return ret; - /* allow mmu fault interrupts, even when we're not using fifo */ - nv_mask(priv, 0x002140, 0x10000000, 0x10000000); + ret = nvkm_bar_umap(device->bar, fifo->base.nr * 0x200, 12, + &fifo->user.bar); + if (ret) + return ret; + + nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0); return 0; } -int -gk104_fifo_init(struct nvkm_object *object) +void +gk104_fifo_init(struct nvkm_fifo *base) { - struct gk104_fifo_priv *priv = (void *)object; - int ret, i; - - ret = nvkm_fifo_init(&priv->base); - if (ret) - return ret; + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int i; /* enable all available PBDMA units */ - nv_wr32(priv, 0x000204, 0xffffffff); - priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204)); - nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr); + nvkm_wr32(device, 0x000204, 0xffffffff); + fifo->spoon_nr = hweight32(nvkm_rd32(device, 0x000204)); + nvkm_debug(subdev, "%d PBDMA unit(s)\n", fifo->spoon_nr); /* PBDMA[n] */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + for (i = 0; i < fifo->spoon_nr; i++) { + nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ } /* PBDMA[n].HCE */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_wr32(priv, 0x040148 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(priv, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ + for (i = 0; i < fifo->spoon_nr; i++) { + nvkm_wr32(device, 0x040148 + (i * 0x2000), 0xffffffff); /* INTR */ + nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ } - nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12); - nv_wr32(priv, 0x002100, 0xffffffff); - nv_wr32(priv, 0x002140, 0x7fffffff); - return 0; + nvkm_wr32(device, 0x002100, 0xffffffff); + nvkm_wr32(device, 0x002140, 0x7fffffff); } -void -gk104_fifo_dtor(struct nvkm_object *object) +void * +gk104_fifo_dtor(struct nvkm_fifo *base) { - struct gk104_fifo_priv *priv = (void *)object; + struct gk104_fifo *fifo = gk104_fifo(base); int i; - nvkm_gpuobj_unmap(&priv->user.bar); - nvkm_gpuobj_ref(NULL, &priv->user.mem); + nvkm_vm_put(&fifo->user.bar); + nvkm_memory_del(&fifo->user.mem); - for (i = 0; i < FIFO_ENGINE_NR; i++) { - nvkm_gpuobj_ref(NULL, &priv->engine[i].runlist[1]); - nvkm_gpuobj_ref(NULL, &priv->engine[i].runlist[0]); + for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) { + nvkm_memory_del(&fifo->engine[i].runlist[1]); + nvkm_memory_del(&fifo->engine[i].runlist[0]); } - nvkm_fifo_destroy(&priv->base); + return fifo; } int -gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gk104_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, + int index, int nr, struct nvkm_fifo **pfifo) { - struct gk104_fifo_impl *impl = (void *)oclass; - struct gk104_fifo_priv *priv; - int ret, i; + struct gk104_fifo *fifo; - ret = nvkm_fifo_create(parent, engine, oclass, 0, - impl->channels - 1, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - INIT_WORK(&priv->fault, gk104_fifo_recover_work); - - for (i = 0; i < FIFO_ENGINE_NR; i++) { - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, - 0, &priv->engine[i].runlist[0]); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, - 0, &priv->engine[i].runlist[1]); - if (ret) - return ret; - - init_waitqueue_head(&priv->engine[i].wait); - } - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, impl->channels * 0x200, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); - if (ret) - return ret; + if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) + return -ENOMEM; + INIT_WORK(&fifo->fault, gk104_fifo_recover_work); + *pfifo = &fifo->base; - ret = nvkm_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, - &priv->user.bar); - if (ret) - return ret; - - ret = nvkm_event_init(&gk104_fifo_uevent_func, 1, 1, &priv->base.uevent); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = gk104_fifo_intr; - nv_engine(priv)->cclass = &gk104_fifo_cclass; - nv_engine(priv)->sclass = gk104_fifo_sclass; - return 0; + return nvkm_fifo_ctor(func, device, index, nr, &fifo->base); } -struct nvkm_oclass * -gk104_fifo_oclass = &(struct gk104_fifo_impl) { - .base.handle = NV_ENGINE(FIFO, 0xe0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_fifo_ctor, - .dtor = gk104_fifo_dtor, - .init = gk104_fifo_init, - .fini = gk104_fifo_fini, +static const struct nvkm_fifo_func +gk104_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .chan = { + &gk104_fifo_gpfifo_oclass, + NULL }, - .channels = 4096, -}.base; +}; + +int +gk104_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return gk104_fifo_new_(&gk104_fifo, device, index, 4096, pfifo); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 318d30d6e..5afd9b5ec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -1,18 +1,77 @@ -#ifndef __NVKM_FIFO_NVE0_H__ -#define __NVKM_FIFO_NVE0_H__ -#include - -int gk104_fifo_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void gk104_fifo_dtor(struct nvkm_object *); -int gk104_fifo_init(struct nvkm_object *); -int gk104_fifo_fini(struct nvkm_object *, bool); - -struct gk104_fifo_impl { - struct nvkm_oclass base; - u32 channels; +#ifndef __GK104_FIFO_H__ +#define __GK104_FIFO_H__ +#define gk104_fifo(p) container_of((p), struct gk104_fifo, base) +#include "priv.h" + +#include + +struct gk104_fifo_engn { + struct nvkm_memory *runlist[2]; + int cur_runlist; + wait_queue_head_t wait; + struct list_head chan; +}; + +struct gk104_fifo { + struct nvkm_fifo base; + + struct work_struct fault; + u64 mask; + + struct gk104_fifo_engn engine[7]; + struct { + struct nvkm_memory *mem; + struct nvkm_vma bar; + } user; + int spoon_nr; }; -extern struct nvkm_ofuncs gk104_fifo_chan_ofuncs; +int gk104_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, + int index, int nr, struct nvkm_fifo **); +void *gk104_fifo_dtor(struct nvkm_fifo *); +int gk104_fifo_oneinit(struct nvkm_fifo *); +void gk104_fifo_init(struct nvkm_fifo *); +void gk104_fifo_fini(struct nvkm_fifo *); +void gk104_fifo_intr(struct nvkm_fifo *); +void gk104_fifo_uevent_init(struct nvkm_fifo *); +void gk104_fifo_uevent_fini(struct nvkm_fifo *); +void gk104_fifo_runlist_update(struct gk104_fifo *, u32 engine); + +static inline u64 +gk104_fifo_engine_subdev(int engine) +{ + switch (engine) { + case 0: return (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_SW) | + (1ULL << NVKM_ENGINE_CE2); + case 1: return (1ULL << NVKM_ENGINE_MSPDEC); + case 2: return (1ULL << NVKM_ENGINE_MSPPP); + case 3: return (1ULL << NVKM_ENGINE_MSVLD); + case 4: return (1ULL << NVKM_ENGINE_CE0); + case 5: return (1ULL << NVKM_ENGINE_CE1); + case 6: return (1ULL << NVKM_ENGINE_MSENC); + default: + WARN_ON(1); + return 0; + } +} + +static inline int +gk104_fifo_subdev_engine(int subdev) +{ + switch (subdev) { + case NVKM_ENGINE_GR: + case NVKM_ENGINE_SW: + case NVKM_ENGINE_CE2 : return 0; + case NVKM_ENGINE_MSPDEC: return 1; + case NVKM_ENGINE_MSPPP : return 2; + case NVKM_ENGINE_MSVLD : return 3; + case NVKM_ENGINE_CE0 : return 4; + case NVKM_ENGINE_CE1 : return 5; + case NVKM_ENGINE_MSENC : return 6; + default: + WARN_ON(1); + return 0; + } +} #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 927092217..ce01c1a7d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -22,15 +22,25 @@ * Authors: Ben Skeggs */ #include "gk104.h" +#include "changk104.h" -struct nvkm_oclass * -gk208_fifo_oclass = &(struct gk104_fifo_impl) { - .base.handle = NV_ENGINE(FIFO, 0x08), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_fifo_ctor, - .dtor = gk104_fifo_dtor, - .init = gk104_fifo_init, - .fini = _nvkm_fifo_fini, +static const struct nvkm_fifo_func +gk208_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .chan = { + &gk104_fifo_gpfifo_oclass, + NULL }, - .channels = 1024, -}.base; +}; + +int +gk208_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return gk104_fifo_new_(&gk208_fifo, device, index, 1024, pfifo); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index b30dc87a1..b47fe98f4 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -20,15 +20,25 @@ * DEALINGS IN THE SOFTWARE. */ #include "gk104.h" +#include "changk104.h" -struct nvkm_oclass * -gk20a_fifo_oclass = &(struct gk104_fifo_impl) { - .base.handle = NV_ENGINE(FIFO, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_fifo_ctor, - .dtor = gk104_fifo_dtor, - .init = gk104_fifo_init, - .fini = gk104_fifo_fini, +static const struct nvkm_fifo_func +gk20a_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .chan = { + &gk104_fifo_gpfifo_oclass, + NULL }, - .channels = 128, -}.base; +}; + +int +gk20a_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return gk104_fifo_new_(&gk20a_fifo, device, index, 128, pfifo); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c index 749d525dd..2db629f1b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c @@ -22,36 +22,25 @@ * Authors: Ben Skeggs */ #include "gk104.h" +#include "changk104.h" -#include - -static struct nvkm_oclass -gm204_fifo_sclass[] = { - { MAXWELL_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs }, - {} +static const struct nvkm_fifo_func +gm204_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .chan = { + &gm204_fifo_gpfifo_oclass, + NULL + }, }; -static int -gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gm204_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) { - int ret = gk104_fifo_ctor(parent, engine, oclass, data, size, pobject); - if (ret == 0) { - struct gk104_fifo_priv *priv = (void *)*pobject; - nv_engine(priv)->sclass = gm204_fifo_sclass; - } - return ret; + return gk104_fifo_new_(&gm204_fifo, device, index, 4096, pfifo); } - -struct nvkm_oclass * -gm204_fifo_oclass = &(struct gk104_fifo_impl) { - .base.handle = NV_ENGINE(FIFO, 0x24), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_fifo_ctor, - .dtor = gk104_fifo_dtor, - .init = gk104_fifo_init, - .fini = _nvkm_fifo_fini, - }, - .channels = 4096, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c new file mode 100644 index 000000000..ae6375d97 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include "gk104.h" +#include "changk104.h" + +static const struct nvkm_fifo_func +gm20b_fifo = { + .dtor = gk104_fifo_dtor, + .oneinit = gk104_fifo_oneinit, + .init = gk104_fifo_init, + .fini = gk104_fifo_fini, + .intr = gk104_fifo_intr, + .uevent_init = gk104_fifo_uevent_init, + .uevent_fini = gk104_fifo_uevent_fini, + .chan = { + &gm204_fifo_gpfifo_oclass, + NULL + }, +}; + +int +gm20b_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return gk104_fifo_new_(&gm20b_fifo, device, index, 512, pfifo); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c new file mode 100644 index 000000000..820132363 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c @@ -0,0 +1,94 @@ +/* + * 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 +#include + +#include +#include + +static int +g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv50_channel_gpfifo_v0 v0; + } *args = data; + struct nv50_fifo *fifo = nv50_fifo(base); + struct nv50_fifo_chan *chan; + u64 ioffset, ilength; + int ret; + + nvif_ioctl(parent, "create channel gpfifo size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + "pushbuf %llx ioffset %016llx " + "ilength %08x\n", + args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.ioffset, args->v0.ilength); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + oclass, chan); + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + ioffset = args->v0.ioffset; + ilength = order_base_2(args->v0.ilength / 8); + + nvkm_kmap(chan->ramfc); + nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); + nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); + nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4); + nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset)); + nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); + nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); + nvkm_wo32(chan->ramfc, 0x78, 0x00000000); + nvkm_wo32(chan->ramfc, 0x7c, 0x30000001); + nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->node->offset >> 4)); + nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10); + nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12); + nvkm_done(chan->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +g84_fifo_gpfifo_oclass = { + .base.oclass = G82_CHANNEL_GPFIFO, + .base.minver = 0, + .base.maxver = 0, + .ctor = g84_fifo_gpfifo_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c new file mode 100644 index 000000000..e7cbc139c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -0,0 +1,293 @@ +/* + * 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 "changf100.h" + +#include +#include +#include +#include + +#include +#include + +static u32 +gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) +{ + switch (engine->subdev.index) { + case NVKM_ENGINE_SW : return 0; + case NVKM_ENGINE_GR : return 0x0210; + case NVKM_ENGINE_CE0 : return 0x0230; + case NVKM_ENGINE_CE1 : return 0x0240; + case NVKM_ENGINE_MSPDEC: return 0x0250; + case NVKM_ENGINE_MSPPP : return 0x0260; + case NVKM_ENGINE_MSVLD : return 0x0270; + default: + WARN_ON(1); + return 0; + } +} + +static int +gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, bool suspend) +{ + const u32 offset = gf100_fifo_gpfifo_engine_addr(engine); + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + struct nvkm_subdev *subdev = &chan->fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_gpuobj *inst = chan->base.inst; + int ret = 0; + + nvkm_wr32(device, 0x002634, chan->base.chid); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x002634) == chan->base.chid) + break; + ) < 0) { + nvkm_error(subdev, "channel %d [%s] kick timeout\n", + chan->base.chid, chan->base.object.client->name); + ret = -EBUSY; + if (suspend) + return ret; + } + + if (offset) { + nvkm_kmap(inst); + nvkm_wo32(inst, offset + 0x00, 0x00000000); + nvkm_wo32(inst, offset + 0x04, 0x00000000); + nvkm_done(inst); + } + + return ret; +} + +static int +gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + const u32 offset = gf100_fifo_gpfifo_engine_addr(engine); + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + struct nvkm_gpuobj *inst = chan->base.inst; + + if (offset) { + u64 addr = chan->engn[engine->subdev.index].vma.offset; + nvkm_kmap(inst); + nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4); + nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr)); + nvkm_done(inst); + } + + return 0; +} + +static void +gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma); + nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); +} + +static int +gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, + struct nvkm_object *object) +{ + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + int engn = engine->subdev.index; + int ret; + + if (!gf100_fifo_gpfifo_engine_addr(engine)) + return 0; + + ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst); + if (ret) + return ret; + + return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm, + NV_MEM_ACCESS_RW, &chan->engn[engn].vma); +} + +static void +gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) +{ + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + struct gf100_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 coff = chan->base.chid * 8; + + if (!list_empty(&chan->head) && !chan->killed) { + list_del_init(&chan->head); + nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000); + gf100_fifo_runlist_update(fifo); + } + + gf100_fifo_intr_engine(fifo); + + nvkm_wr32(device, 0x003000 + coff, 0x00000000); +} + +static void +gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) +{ + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + struct gf100_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 addr = chan->base.inst->addr >> 12; + u32 coff = chan->base.chid * 8; + + nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr); + + if (list_empty(&chan->head) && !chan->killed) { + list_add_tail(&chan->head, &fifo->chan); + nvkm_wr32(device, 0x003004 + coff, 0x001f0001); + gf100_fifo_runlist_update(fifo); + } +} + +static void * +gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) +{ + struct gf100_fifo_chan *chan = gf100_fifo_chan(base); + nvkm_vm_ref(NULL, &chan->vm, chan->pgd); + nvkm_gpuobj_del(&chan->pgd); + return chan; +} + +static const struct nvkm_fifo_chan_func +gf100_fifo_gpfifo_func = { + .dtor = gf100_fifo_gpfifo_dtor, + .init = gf100_fifo_gpfifo_init, + .fini = gf100_fifo_gpfifo_fini, + .ntfy = g84_fifo_chan_ntfy, + .engine_ctor = gf100_fifo_gpfifo_engine_ctor, + .engine_dtor = gf100_fifo_gpfifo_engine_dtor, + .engine_init = gf100_fifo_gpfifo_engine_init, + .engine_fini = gf100_fifo_gpfifo_engine_fini, +}; + +static int +gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + union { + struct fermi_channel_gpfifo_v0 v0; + } *args = data; + struct gf100_fifo *fifo = gf100_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_object *parent = oclass->parent; + struct gf100_fifo_chan *chan; + u64 usermem, ioffset, ilength; + int ret, i; + + nvif_ioctl(parent, "create channel gpfifo size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + "ioffset %016llx ilength %08x\n", + args->v0.version, args->v0.vm, args->v0.ioffset, + args->v0.ilength); + } else + return ret; + + /* allocate channel */ + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + chan->fifo = fifo; + INIT_LIST_HEAD(&chan->head); + + ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base, + 0x1000, 0x1000, true, args->v0.vm, 0, + (1ULL << NVKM_ENGINE_CE0) | + (1ULL << NVKM_ENGINE_CE1) | + (1ULL << NVKM_ENGINE_GR) | + (1ULL << NVKM_ENGINE_MSPDEC) | + (1ULL << NVKM_ENGINE_MSPPP) | + (1ULL << NVKM_ENGINE_MSVLD) | + (1ULL << NVKM_ENGINE_SW), + 1, fifo->user.bar.offset, 0x1000, + oclass, &chan->base); + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + + /* page directory */ + ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd); + if (ret) + return ret; + + nvkm_kmap(chan->base.inst); + nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr)); + nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr)); + nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff); + nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff); + nvkm_done(chan->base.inst); + + ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); + if (ret) + return ret; + + /* clear channel control registers */ + + usermem = chan->base.chid * 0x1000; + ioffset = args->v0.ioffset; + ilength = order_base_2(args->v0.ilength / 8); + + nvkm_kmap(fifo->user.mem); + for (i = 0; i < 0x1000; i += 4) + nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000); + nvkm_done(fifo->user.mem); + usermem = nvkm_memory_addr(fifo->user.mem) + usermem; + + /* RAMFC */ + nvkm_kmap(chan->base.inst); + nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem)); + nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem)); + nvkm_wo32(chan->base.inst, 0x10, 0x0000face); + nvkm_wo32(chan->base.inst, 0x30, 0xfffff902); + nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset)); + nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) | + (ilength << 16)); + nvkm_wo32(chan->base.inst, 0x54, 0x00000002); + nvkm_wo32(chan->base.inst, 0x84, 0x20400000); + nvkm_wo32(chan->base.inst, 0x94, 0x30000001); + nvkm_wo32(chan->base.inst, 0x9c, 0x00000100); + nvkm_wo32(chan->base.inst, 0xa4, 0x1f1f1f1f); + nvkm_wo32(chan->base.inst, 0xa8, 0x1f1f1f1f); + nvkm_wo32(chan->base.inst, 0xac, 0x0000001f); + nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000); + nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */ + nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */ + nvkm_done(chan->base.inst); + return 0; +} + +const struct nvkm_fifo_chan_oclass +gf100_fifo_gpfifo_oclass = { + .base.oclass = FERMI_CHANNEL_GPFIFO, + .base.minver = 0, + .base.maxver = 0, + .ctor = gf100_fifo_gpfifo_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c new file mode 100644 index 000000000..0b817540a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -0,0 +1,323 @@ +/* + * 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 "changk104.h" + +#include +#include +#include +#include +#include + +#include +#include + +static int +gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) +{ + struct gk104_fifo *fifo = chan->fifo; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_client *client = chan->base.object.client; + + nvkm_wr32(device, 0x002634, chan->base.chid); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x002634) & 0x00100000)) + break; + ) < 0) { + nvkm_error(subdev, "channel %d [%s] kick timeout\n", + chan->base.chid, client->name); + return -EBUSY; + } + + return 0; +} + +static u32 +gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) +{ + switch (engine->subdev.index) { + case NVKM_ENGINE_SW : + case NVKM_ENGINE_CE0 : + case NVKM_ENGINE_CE1 : + case NVKM_ENGINE_CE2 : return 0x0000; + case NVKM_ENGINE_GR : return 0x0210; + case NVKM_ENGINE_MSPDEC: return 0x0250; + case NVKM_ENGINE_MSPPP : return 0x0260; + case NVKM_ENGINE_MSVLD : return 0x0270; + default: + WARN_ON(1); + return 0; + } +} + +static int +gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, bool suspend) +{ + const u32 offset = gk104_fifo_gpfifo_engine_addr(engine); + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + struct nvkm_gpuobj *inst = chan->base.inst; + int ret; + + ret = gk104_fifo_gpfifo_kick(chan); + if (ret && suspend) + return ret; + + if (offset) { + nvkm_kmap(inst); + nvkm_wo32(inst, offset + 0x00, 0x00000000); + nvkm_wo32(inst, offset + 0x04, 0x00000000); + nvkm_done(inst); + } + + return ret; +} + +static int +gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + const u32 offset = gk104_fifo_gpfifo_engine_addr(engine); + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + struct nvkm_gpuobj *inst = chan->base.inst; + + if (offset) { + u64 addr = chan->engn[engine->subdev.index].vma.offset; + nvkm_kmap(inst); + nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4); + nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr)); + nvkm_done(inst); + } + + return 0; +} + +static void +gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma); + nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); +} + +static int +gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, + struct nvkm_object *object) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + int engn = engine->subdev.index; + int ret; + + if (!gk104_fifo_gpfifo_engine_addr(engine)) + return 0; + + ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst); + if (ret) + return ret; + + return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm, + NV_MEM_ACCESS_RW, &chan->engn[engn].vma); +} + +static void +gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + struct gk104_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 coff = chan->base.chid * 8; + + if (!list_empty(&chan->head)) { + list_del_init(&chan->head); + nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800); + gk104_fifo_runlist_update(fifo, chan->engine); + } + + nvkm_wr32(device, 0x800000 + coff, 0x00000000); +} + +static void +gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + struct gk104_fifo *fifo = chan->fifo; + struct nvkm_device *device = fifo->base.engine.subdev.device; + u32 addr = chan->base.inst->addr >> 12; + u32 coff = chan->base.chid * 8; + + nvkm_mask(device, 0x800004 + coff, 0x000f0000, chan->engine << 16); + nvkm_wr32(device, 0x800000 + coff, 0x80000000 | addr); + + if (list_empty(&chan->head) && !chan->killed) { + list_add_tail(&chan->head, &fifo->engine[chan->engine].chan); + nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); + gk104_fifo_runlist_update(fifo, chan->engine); + nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); + } +} + +static void * +gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + nvkm_vm_ref(NULL, &chan->vm, chan->pgd); + nvkm_gpuobj_del(&chan->pgd); + return chan; +} + +static const struct nvkm_fifo_chan_func +gk104_fifo_gpfifo_func = { + .dtor = gk104_fifo_gpfifo_dtor, + .init = gk104_fifo_gpfifo_init, + .fini = gk104_fifo_gpfifo_fini, + .ntfy = g84_fifo_chan_ntfy, + .engine_ctor = gk104_fifo_gpfifo_engine_ctor, + .engine_dtor = gk104_fifo_gpfifo_engine_dtor, + .engine_init = gk104_fifo_gpfifo_engine_init, + .engine_fini = gk104_fifo_gpfifo_engine_fini, +}; + +int +gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + union { + struct kepler_channel_gpfifo_a_v0 v0; + } *args = data; + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_object *parent = oclass->parent; + struct gk104_fifo_chan *chan; + u64 usermem, ioffset, ilength; + u32 engines; + int ret, i; + + nvif_ioctl(parent, "create channel gpfifo size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + "ioffset %016llx ilength %08x engine %08x\n", + args->v0.version, args->v0.vm, args->v0.ioffset, + args->v0.ilength, args->v0.engine); + } else + return ret; + + /* determine which downstream engines are present */ + for (i = 0, engines = 0; i < ARRAY_SIZE(fifo->engine); i++) { + u64 subdevs = gk104_fifo_engine_subdev(i); + if (!nvkm_device_engine(device, __ffs64(subdevs))) + continue; + engines |= (1 << i); + } + + /* if this is an engine mask query, we're done */ + if (!args->v0.engine) { + args->v0.engine = engines; + return nvkm_object_new(oclass, NULL, 0, pobject); + } + + /* check that we support a requested engine - note that the user + * argument is a mask in order to allow the user to request (for + * example) *any* copy engine, but doesn't matter which. + */ + args->v0.engine &= engines; + if (!args->v0.engine) { + nvif_ioctl(parent, "no supported engine\n"); + return -ENODEV; + } + + /* allocate the channel */ + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + chan->fifo = fifo; + chan->engine = __ffs(args->v0.engine); + INIT_LIST_HEAD(&chan->head); + + ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, + 0x1000, 0x1000, true, args->v0.vm, 0, + gk104_fifo_engine_subdev(chan->engine), + 1, fifo->user.bar.offset, 0x200, + oclass, &chan->base); + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + + /* page directory */ + ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd); + if (ret) + return ret; + + nvkm_kmap(chan->base.inst); + nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr)); + nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr)); + nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff); + nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff); + nvkm_done(chan->base.inst); + + ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); + if (ret) + return ret; + + /* clear channel control registers */ + usermem = chan->base.chid * 0x200; + ioffset = args->v0.ioffset; + ilength = order_base_2(args->v0.ilength / 8); + + nvkm_kmap(fifo->user.mem); + for (i = 0; i < 0x200; i += 4) + nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000); + nvkm_done(fifo->user.mem); + usermem = nvkm_memory_addr(fifo->user.mem) + usermem; + + /* RAMFC */ + nvkm_kmap(chan->base.inst); + nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem)); + nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem)); + nvkm_wo32(chan->base.inst, 0x10, 0x0000face); + nvkm_wo32(chan->base.inst, 0x30, 0xfffff902); + nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset)); + nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) | + (ilength << 16)); + nvkm_wo32(chan->base.inst, 0x84, 0x20400000); + nvkm_wo32(chan->base.inst, 0x94, 0x30000001); + nvkm_wo32(chan->base.inst, 0x9c, 0x00000100); + nvkm_wo32(chan->base.inst, 0xac, 0x0000001f); + nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid); + nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000); + nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */ + nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */ + nvkm_done(chan->base.inst); + return 0; +} + +const struct nvkm_fifo_chan_oclass +gk104_fifo_gpfifo_oclass = { + .base.oclass = KEPLER_CHANNEL_GPFIFO_A, + .base.minver = 0, + .base.maxver = 0, + .ctor = gk104_fifo_gpfifo_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c new file mode 100644 index 000000000..6511d6e21 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c @@ -0,0 +1,34 @@ +/* + * 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 + */ +#include "changk104.h" + +#include + +const struct nvkm_fifo_chan_oclass +gm204_fifo_gpfifo_oclass = { + .base.oclass = MAXWELL_CHANNEL_GPFIFO_A, + .base.minver = 0, + .base.maxver = 0, + .ctor = gk104_fifo_gpfifo_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c new file mode 100644 index 000000000..a8c69f878 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c @@ -0,0 +1,92 @@ +/* + * 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 +#include + +#include +#include + +static int +nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + struct nvkm_object *parent = oclass->parent; + union { + struct nv50_channel_gpfifo_v0 v0; + } *args = data; + struct nv50_fifo *fifo = nv50_fifo(base); + struct nv50_fifo_chan *chan; + u64 ioffset, ilength; + int ret; + + nvif_ioctl(parent, "create channel gpfifo size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + "pushbuf %llx ioffset %016llx " + "ilength %08x\n", + args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.ioffset, args->v0.ilength); + if (!args->v0.pushbuf) + return -EINVAL; + } else + return ret; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + oclass, chan); + if (ret) + return ret; + + args->v0.chid = chan->base.chid; + ioffset = args->v0.ioffset; + ilength = order_base_2(args->v0.ilength / 8); + + nvkm_kmap(chan->ramfc); + nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); + nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); + nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4); + nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset)); + nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); + nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); + nvkm_wo32(chan->ramfc, 0x78, 0x00000000); + nvkm_wo32(chan->ramfc, 0x7c, 0x30000001); + nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->node->offset >> 4)); + nvkm_done(chan->ramfc); + return 0; +} + +const struct nvkm_fifo_chan_oclass +nv50_fifo_gpfifo_oclass = { + .base.oclass = NV50_CHANNEL_GPFIFO, + .base.minver = 0, + .base.maxver = 0, + .ctor = nv50_fifo_gpfifo_new, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index 043e42960..ad707ff17 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -22,20 +22,17 @@ * Authors: Ben Skeggs */ #include "nv04.h" +#include "channv04.h" +#include "regsnv04.h" #include -#include -#include -#include #include -#include +#include #include +#include -#include -#include - -static struct ramfc_desc -nv04_ramfc[] = { +static const struct nv04_fifo_ramfc +nv04_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, @@ -47,268 +44,19 @@ nv04_ramfc[] = { {} }; -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ - -int -nv04_fifo_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 handle) -{ - struct nv04_fifo_priv *priv = (void *)parent->engine; - struct nv04_fifo_chan *chan = (void *)parent; - u32 context, chid = chan->base.chid; - int ret; - - if (nv_iclass(object, NV_GPUOBJ_CLASS)) - context = nv_gpuobj(object)->addr >> 4; - else - context = 0x00000004; /* just non-zero */ - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_DMAOBJ: - case NVDEV_ENGINE_SW: - context |= 0x00000000; - break; - case NVDEV_ENGINE_GR: - context |= 0x00010000; - break; - case NVDEV_ENGINE_MPEG: - context |= 0x00020000; - break; - default: - return -EINVAL; - } - - context |= 0x80000000; /* valid */ - context |= chid << 24; - - mutex_lock(&nv_subdev(priv)->mutex); - ret = nvkm_ramht_insert(priv->ramht, chid, handle, context); - mutex_unlock(&nv_subdev(priv)->mutex); - return ret; -} - -void -nv04_fifo_object_detach(struct nvkm_object *parent, int cookie) -{ - struct nv04_fifo_priv *priv = (void *)parent->engine; - mutex_lock(&nv_subdev(priv)->mutex); - nvkm_ramht_remove(priv->ramht, cookie); - mutex_unlock(&nv_subdev(priv)->mutex); -} - -int -nv04_fifo_context_attach(struct nvkm_object *parent, - struct nvkm_object *object) -{ - nv_engctx(object)->addr = nvkm_fifo_chan(parent)->chid; - return 0; -} - -static int -nv04_fifo_chan_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo_priv *priv = (void *)engine; - struct nv04_fifo_chan *chan; - int ret; - - nv_ioctl(parent, "create channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " - "offset %016llx\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000, - 0x10000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - nv_parent(chan)->object_attach = nv04_fifo_object_attach; - nv_parent(chan)->object_detach = nv04_fifo_object_detach; - nv_parent(chan)->context_attach = nv04_fifo_context_attach; - chan->ramfc = chan->base.chid * 32; - - nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4); - nv_wo32(priv->ramfc, chan->ramfc + 0x10, - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - return 0; -} - -void -nv04_fifo_chan_dtor(struct nvkm_object *object) -{ - struct nv04_fifo_priv *priv = (void *)object->engine; - struct nv04_fifo_chan *chan = (void *)object; - struct ramfc_desc *c = priv->ramfc_desc; - - do { - nv_wo32(priv->ramfc, chan->ramfc + c->ctxp, 0x00000000); - } while ((++c)->bits); - - nvkm_fifo_channel_destroy(&chan->base); -} - -int -nv04_fifo_chan_init(struct nvkm_object *object) -{ - struct nv04_fifo_priv *priv = (void *)object->engine; - struct nv04_fifo_chan *chan = (void *)object; - u32 mask = 1 << chan->base.chid; - unsigned long flags; - int ret; - - ret = nvkm_fifo_channel_init(&chan->base); - if (ret) - return ret; - - spin_lock_irqsave(&priv->base.lock, flags); - nv_mask(priv, NV04_PFIFO_MODE, mask, mask); - spin_unlock_irqrestore(&priv->base.lock, flags); - return 0; -} - -int -nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct nv04_fifo_priv *priv = (void *)object->engine; - struct nv04_fifo_chan *chan = (void *)object; - struct nvkm_gpuobj *fctx = priv->ramfc; - struct ramfc_desc *c; - unsigned long flags; - u32 data = chan->ramfc; - u32 chid; - - /* prevent fifo context switches */ - spin_lock_irqsave(&priv->base.lock, flags); - nv_wr32(priv, NV03_PFIFO_CACHES, 0); - - /* if this channel is active, replace it with a null context */ - chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max; - if (chid == chan->base.chid) { - nv_mask(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 0); - nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); - - c = priv->ramfc_desc; - do { - u32 rm = ((1ULL << c->bits) - 1) << c->regs; - u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; - u32 rv = (nv_rd32(priv, c->regp) & rm) >> c->regs; - u32 cv = (nv_ro32(fctx, c->ctxp + data) & ~cm); - nv_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); - } while ((++c)->bits); - - c = priv->ramfc_desc; - do { - nv_wr32(priv, c->regp, 0x00000000); - } while ((++c)->bits); - - nv_wr32(priv, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUT, 0); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); - } - - /* restore normal operation, after disabling dma mode */ - nv_mask(priv, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); - nv_wr32(priv, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&priv->base.lock, flags); - - return nvkm_fifo_channel_fini(&chan->base, suspend); -} - -static struct nvkm_ofuncs -nv04_fifo_ofuncs = { - .ctor = nv04_fifo_chan_ctor, - .dtor = nv04_fifo_chan_dtor, - .init = nv04_fifo_chan_init, - .fini = nv04_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -nv04_fifo_sclass[] = { - { NV03_CHANNEL_DMA, &nv04_fifo_ofuncs }, - {} -}; - -/******************************************************************************* - * FIFO context - basically just the instmem reserved for the channel - ******************************************************************************/ - -int -nv04_fifo_context_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv04_fifo_base *base; - int ret; - - ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000, - 0x1000, NVOBJ_FLAG_HEAP, &base); - *pobject = nv_object(base); - if (ret) - return ret; - - return 0; -} - -static struct nvkm_oclass -nv04_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fifo_context_ctor, - .dtor = _nvkm_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, - }, -}; - -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - void -nv04_fifo_pause(struct nvkm_fifo *pfifo, unsigned long *pflags) -__acquires(priv->base.lock) +nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags) +__acquires(fifo->base.lock) { - struct nv04_fifo_priv *priv = (void *)pfifo; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; unsigned long flags; - spin_lock_irqsave(&priv->base.lock, flags); + spin_lock_irqsave(&fifo->base.lock, flags); *pflags = flags; - nv_wr32(priv, NV03_PFIFO_CACHES, 0x00000000); - nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000000); + nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000000); + nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000000); /* in some cases the puller may be left in an inconsistent state * if you try to stop it while it's busy translating handles. @@ -319,28 +67,31 @@ __acquires(priv->base.lock) * to avoid this, we invalidate the most recently calculated * instance. */ - if (!nv_wait(priv, NV04_PFIFO_CACHE1_PULL0, - NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0x00000000)) - nv_warn(priv, "timeout idling puller\n"); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, NV04_PFIFO_CACHE1_PULL0); + if (!(tmp & NV04_PFIFO_CACHE1_PULL0_HASH_BUSY)) + break; + ); - if (nv_rd32(priv, NV04_PFIFO_CACHE1_PULL0) & + if (nvkm_rd32(device, NV04_PFIFO_CACHE1_PULL0) & NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) - nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); + nvkm_wr32(device, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); - nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0x00000000); + nvkm_wr32(device, NV04_PFIFO_CACHE1_HASH, 0x00000000); } void -nv04_fifo_start(struct nvkm_fifo *pfifo, unsigned long *pflags) -__releases(priv->base.lock) +nv04_fifo_start(struct nvkm_fifo *base, unsigned long *pflags) +__releases(fifo->base.lock) { - struct nv04_fifo_priv *priv = (void *)pfifo; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; unsigned long flags = *pflags; - nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001); - nv_wr32(priv, NV03_PFIFO_CACHES, 0x00000001); + nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001); + nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000001); - spin_unlock_irqrestore(&priv->base.lock, flags); + spin_unlock_irqrestore(&fifo->base.lock, flags); } static const char * @@ -354,61 +105,40 @@ nv_dma_state_err(u32 state) } static bool -nv04_fifo_swmthd(struct nv04_fifo_priv *priv, u32 chid, u32 addr, u32 data) +nv04_fifo_swmthd(struct nvkm_device *device, u32 chid, u32 addr, u32 data) { - struct nv04_fifo_chan *chan = NULL; - struct nvkm_handle *bind; - const int subc = (addr >> 13) & 0x7; - const int mthd = addr & 0x1ffc; + struct nvkm_sw *sw = device->sw; + const int subc = (addr & 0x0000e000) >> 13; + const int mthd = (addr & 0x00001ffc); + const u32 mask = 0x0000000f << (subc * 4); + u32 engine = nvkm_rd32(device, 0x003280); bool handled = false; - unsigned long flags; - u32 engine; - - spin_lock_irqsave(&priv->base.lock, flags); - if (likely(chid >= priv->base.min && chid <= priv->base.max)) - chan = (void *)priv->base.channel[chid]; - if (unlikely(!chan)) - goto out; switch (mthd) { - case 0x0000: - bind = nvkm_namedb_get(nv_namedb(chan), data); - if (unlikely(!bind)) - break; - - if (nv_engidx(bind->object->engine) == NVDEV_ENGINE_SW) { - engine = 0x0000000f << (subc * 4); - chan->subc[subc] = data; - handled = true; - - nv_mask(priv, NV04_PFIFO_CACHE1_ENGINE, engine, 0); - } - - nvkm_namedb_put(bind); + case 0x0000 ... 0x0000: /* subchannel's engine -> software */ + nvkm_wr32(device, 0x003280, (engine &= ~mask)); + case 0x0180 ... 0x01fc: /* handle -> instance */ + data = nvkm_rd32(device, 0x003258) & 0x0000ffff; + case 0x0100 ... 0x017c: + case 0x0200 ... 0x1ffc: /* pass method down to sw */ + if (!(engine & mask) && sw) + handled = nvkm_sw_mthd(sw, chid, subc, mthd, data); break; default: - engine = nv_rd32(priv, NV04_PFIFO_CACHE1_ENGINE); - if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) - break; - - bind = nvkm_namedb_get(nv_namedb(chan), chan->subc[subc]); - if (likely(bind)) { - if (!nv_call(bind->object, mthd, data)) - handled = true; - nvkm_namedb_put(bind); - } break; } -out: - spin_unlock_irqrestore(&priv->base.lock, flags); return handled; } static void -nv04_fifo_cache_error(struct nvkm_device *device, - struct nv04_fifo_priv *priv, u32 chid, u32 get) +nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get) { + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_fifo_chan *chan; + unsigned long flags; + u32 pull0 = nvkm_rd32(device, 0x003250); u32 mthd, data; int ptr; @@ -420,216 +150,214 @@ nv04_fifo_cache_error(struct nvkm_device *device, ptr = (get & 0x7ff) >> 2; if (device->card_type < NV_40) { - mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr)); + mthd = nvkm_rd32(device, NV04_PFIFO_CACHE1_METHOD(ptr)); + data = nvkm_rd32(device, NV04_PFIFO_CACHE1_DATA(ptr)); } else { - mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr)); + mthd = nvkm_rd32(device, NV40_PFIFO_CACHE1_METHOD(ptr)); + data = nvkm_rd32(device, NV40_PFIFO_CACHE1_DATA(ptr)); } - if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { - const char *client_name = - nvkm_client_name_for_fifo_chid(&priv->base, chid); - nv_error(priv, - "CACHE_ERROR - ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", - chid, client_name, (mthd >> 13) & 7, mthd & 0x1ffc, - data); + if (!(pull0 & 0x00000100) || + !nv04_fifo_swmthd(device, chid, mthd, data)) { + chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + nvkm_error(subdev, "CACHE_ERROR - " + "ch %d [%s] subc %d mthd %04x data %08x\n", + chid, chan ? chan->object.client->name : "unknown", + (mthd >> 13) & 7, mthd & 0x1ffc, data); + nvkm_fifo_chan_put(&fifo->base, flags, &chan); } - nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); + nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nvkm_wr32(device, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); - nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, + nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, get + 4); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, + nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH0) | 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_HASH, 0); - nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, - nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, + nvkm_rd32(device, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); } static void -nv04_fifo_dma_pusher(struct nvkm_device *device, - struct nv04_fifo_priv *priv, u32 chid) +nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid) { - const char *client_name; - u32 dma_get = nv_rd32(priv, 0x003244); - u32 dma_put = nv_rd32(priv, 0x003240); - u32 push = nv_rd32(priv, 0x003220); - u32 state = nv_rd32(priv, 0x003228); - - client_name = nvkm_client_name_for_fifo_chid(&priv->base, chid); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 dma_get = nvkm_rd32(device, 0x003244); + u32 dma_put = nvkm_rd32(device, 0x003240); + u32 push = nvkm_rd32(device, 0x003220); + u32 state = nvkm_rd32(device, 0x003228); + struct nvkm_fifo_chan *chan; + unsigned long flags; + const char *name; + chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags); + name = chan ? chan->object.client->name : "unknown"; if (device->card_type == NV_50) { - u32 ho_get = nv_rd32(priv, 0x003328); - u32 ho_put = nv_rd32(priv, 0x003320); - u32 ib_get = nv_rd32(priv, 0x003334); - u32 ib_put = nv_rd32(priv, 0x003330); - - nv_error(priv, - "DMA_PUSHER - ch %d [%s] get 0x%02x%08x put 0x%02x%08x ib_get 0x%08x ib_put 0x%08x state 0x%08x (err: %s) push 0x%08x\n", - chid, client_name, ho_get, dma_get, ho_put, dma_put, - ib_get, ib_put, state, nv_dma_state_err(state), push); + u32 ho_get = nvkm_rd32(device, 0x003328); + u32 ho_put = nvkm_rd32(device, 0x003320); + u32 ib_get = nvkm_rd32(device, 0x003334); + u32 ib_put = nvkm_rd32(device, 0x003330); + + nvkm_error(subdev, "DMA_PUSHER - " + "ch %d [%s] get %02x%08x put %02x%08x ib_get %08x " + "ib_put %08x state %08x (err: %s) push %08x\n", + chid, name, ho_get, dma_get, ho_put, dma_put, + ib_get, ib_put, state, nv_dma_state_err(state), + push); /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ - nv_wr32(priv, 0x003364, 0x00000000); + nvkm_wr32(device, 0x003364, 0x00000000); if (dma_get != dma_put || ho_get != ho_put) { - nv_wr32(priv, 0x003244, dma_put); - nv_wr32(priv, 0x003328, ho_put); + nvkm_wr32(device, 0x003244, dma_put); + nvkm_wr32(device, 0x003328, ho_put); } else if (ib_get != ib_put) - nv_wr32(priv, 0x003334, ib_put); + nvkm_wr32(device, 0x003334, ib_put); } else { - nv_error(priv, - "DMA_PUSHER - ch %d [%s] get 0x%08x put 0x%08x state 0x%08x (err: %s) push 0x%08x\n", - chid, client_name, dma_get, dma_put, state, - nv_dma_state_err(state), push); + nvkm_error(subdev, "DMA_PUSHER - ch %d [%s] get %08x put %08x " + "state %08x (err: %s) push %08x\n", + chid, name, dma_get, dma_put, state, + nv_dma_state_err(state), push); if (dma_get != dma_put) - nv_wr32(priv, 0x003244, dma_put); + nvkm_wr32(device, 0x003244, dma_put); } + nvkm_fifo_chan_put(&fifo->base, flags, &chan); - nv_wr32(priv, 0x003228, 0x00000000); - nv_wr32(priv, 0x003220, 0x00000001); - nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); + nvkm_wr32(device, 0x003228, 0x00000000); + nvkm_wr32(device, 0x003220, 0x00000001); + nvkm_wr32(device, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); } void -nv04_fifo_intr(struct nvkm_subdev *subdev) +nv04_fifo_intr(struct nvkm_fifo *base) { - struct nvkm_device *device = nv_device(subdev); - struct nv04_fifo_priv *priv = (void *)subdev; - u32 mask = nv_rd32(priv, NV03_PFIFO_INTR_EN_0); - u32 stat = nv_rd32(priv, NV03_PFIFO_INTR_0) & mask; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 mask = nvkm_rd32(device, NV03_PFIFO_INTR_EN_0); + u32 stat = nvkm_rd32(device, NV03_PFIFO_INTR_0) & mask; u32 reassign, chid, get, sem; - reassign = nv_rd32(priv, NV03_PFIFO_CACHES) & 1; - nv_wr32(priv, NV03_PFIFO_CACHES, 0); + reassign = nvkm_rd32(device, NV03_PFIFO_CACHES) & 1; + nvkm_wr32(device, NV03_PFIFO_CACHES, 0); - chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max; - get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET); + chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & (fifo->base.nr - 1); + get = nvkm_rd32(device, NV03_PFIFO_CACHE1_GET); if (stat & NV_PFIFO_INTR_CACHE_ERROR) { - nv04_fifo_cache_error(device, priv, chid, get); + nv04_fifo_cache_error(fifo, chid, get); stat &= ~NV_PFIFO_INTR_CACHE_ERROR; } if (stat & NV_PFIFO_INTR_DMA_PUSHER) { - nv04_fifo_dma_pusher(device, priv, chid); + nv04_fifo_dma_pusher(fifo, chid); stat &= ~NV_PFIFO_INTR_DMA_PUSHER; } if (stat & NV_PFIFO_INTR_SEMAPHORE) { stat &= ~NV_PFIFO_INTR_SEMAPHORE; - nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_SEMAPHORE); + nvkm_wr32(device, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_SEMAPHORE); - sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE); - nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); + sem = nvkm_rd32(device, NV10_PFIFO_CACHE1_SEMAPHORE); + nvkm_wr32(device, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); - nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, get + 4); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); } if (device->card_type == NV_50) { if (stat & 0x00000010) { stat &= ~0x00000010; - nv_wr32(priv, 0x002100, 0x00000010); + nvkm_wr32(device, 0x002100, 0x00000010); } if (stat & 0x40000000) { - nv_wr32(priv, 0x002100, 0x40000000); - nvkm_fifo_uevent(&priv->base); + nvkm_wr32(device, 0x002100, 0x40000000); + nvkm_fifo_uevent(&fifo->base); stat &= ~0x40000000; } } if (stat) { - nv_warn(priv, "unknown intr 0x%08x\n", stat); - nv_mask(priv, NV03_PFIFO_INTR_EN_0, stat, 0x00000000); - nv_wr32(priv, NV03_PFIFO_INTR_0, stat); + nvkm_warn(subdev, "intr %08x\n", stat); + nvkm_mask(device, NV03_PFIFO_INTR_EN_0, stat, 0x00000000); + nvkm_wr32(device, NV03_PFIFO_INTR_0, stat); } - nv_wr32(priv, NV03_PFIFO_CACHES, reassign); -} - -static int -nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv04_instmem_priv *imem = nv04_instmem(parent); - struct nv04_fifo_priv *priv; - int ret; - - ret = nvkm_fifo_create(parent, engine, oclass, 0, 15, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nvkm_ramht_ref(imem->ramht, &priv->ramht); - nvkm_gpuobj_ref(imem->ramro, &priv->ramro); - nvkm_gpuobj_ref(imem->ramfc, &priv->ramfc); - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = nv04_fifo_intr; - nv_engine(priv)->cclass = &nv04_fifo_cclass; - nv_engine(priv)->sclass = nv04_fifo_sclass; - priv->base.pause = nv04_fifo_pause; - priv->base.start = nv04_fifo_start; - priv->ramfc_desc = nv04_ramfc; - return 0; + nvkm_wr32(device, NV03_PFIFO_CACHES, reassign); } void -nv04_fifo_dtor(struct nvkm_object *object) +nv04_fifo_init(struct nvkm_fifo *base) { - struct nv04_fifo_priv *priv = (void *)object; - nvkm_gpuobj_ref(NULL, &priv->ramfc); - nvkm_gpuobj_ref(NULL, &priv->ramro); - nvkm_ramht_ref(NULL, &priv->ramht); - nvkm_fifo_destroy(&priv->base); + struct nv04_fifo *fifo = nv04_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + struct nvkm_ramht *ramht = imem->ramht; + struct nvkm_memory *ramro = imem->ramro; + struct nvkm_memory *ramfc = imem->ramfc; + + nvkm_wr32(device, NV04_PFIFO_DELAY_0, 0x000000ff); + nvkm_wr32(device, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); + + nvkm_wr32(device, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((ramht->bits - 9) << 16) | + (ramht->gpuobj->addr >> 8)); + nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8); + nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8); + + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1); + + nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff); + nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); + nvkm_wr32(device, NV03_PFIFO_CACHES, 1); } int -nv04_fifo_init(struct nvkm_object *object) +nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, + int index, int nr, const struct nv04_fifo_ramfc *ramfc, + struct nvkm_fifo **pfifo) { - struct nv04_fifo_priv *priv = (void *)object; + struct nv04_fifo *fifo; int ret; - ret = nvkm_fifo_init(&priv->base); + if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) + return -ENOMEM; + fifo->ramfc = ramfc; + *pfifo = &fifo->base; + + ret = nvkm_fifo_ctor(func, device, index, nr, &fifo->base); if (ret) return ret; - nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff); - nv_wr32(priv, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); - - nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((priv->ramht->bits - 9) << 16) | - (priv->ramht->gpuobj.addr >> 8)); - nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); - - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - - nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); - - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(priv, NV03_PFIFO_CACHES, 1); + set_bit(nr - 1, fifo->base.mask); /* inactive channel */ return 0; } -struct nvkm_oclass * -nv04_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fifo_ctor, - .dtor = nv04_fifo_dtor, - .init = nv04_fifo_init, - .fini = _nvkm_fifo_fini, +static const struct nvkm_fifo_func +nv04_fifo = { + .init = nv04_fifo_init, + .intr = nv04_fifo_intr, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .chan = { + &nv04_fifo_dma_oclass, + NULL }, }; + +int +nv04_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return nv04_fifo_new_(&nv04_fifo, device, index, 16, + nv04_fifo_ramfc, pfifo); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h index e0e0c47cb..03f60004b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h @@ -1,137 +1,9 @@ #ifndef __NV04_FIFO_H__ #define __NV04_FIFO_H__ -#include +#define nv04_fifo(p) container_of((p), struct nv04_fifo, base) +#include "priv.h" -#define NV04_PFIFO_DELAY_0 0x00002040 -#define NV04_PFIFO_DMA_TIMESLICE 0x00002044 -#define NV04_PFIFO_NEXT_CHANNEL 0x00002050 -#define NV03_PFIFO_INTR_0 0x00002100 -#define NV03_PFIFO_INTR_EN_0 0x00002140 -# define NV_PFIFO_INTR_CACHE_ERROR (1<<0) -# define NV_PFIFO_INTR_RUNOUT (1<<4) -# define NV_PFIFO_INTR_RUNOUT_OVERFLOW (1<<8) -# define NV_PFIFO_INTR_DMA_PUSHER (1<<12) -# define NV_PFIFO_INTR_DMA_PT (1<<16) -# define NV_PFIFO_INTR_SEMAPHORE (1<<20) -# define NV_PFIFO_INTR_ACQUIRE_TIMEOUT (1<<24) -#define NV03_PFIFO_RAMHT 0x00002210 -#define NV03_PFIFO_RAMFC 0x00002214 -#define NV03_PFIFO_RAMRO 0x00002218 -#define NV40_PFIFO_RAMFC 0x00002220 -#define NV03_PFIFO_CACHES 0x00002500 -#define NV04_PFIFO_MODE 0x00002504 -#define NV04_PFIFO_DMA 0x00002508 -#define NV04_PFIFO_SIZE 0x0000250c -#define NV50_PFIFO_CTX_TABLE(c) (0x2600+(c)*4) -#define NV50_PFIFO_CTX_TABLE__SIZE 128 -#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED (1<<31) -#define NV50_PFIFO_CTX_TABLE_UNK30_BAD (1<<30) -#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 0x0FFFFFFF -#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 0x00FFFFFF -#define NV03_PFIFO_CACHE0_PUSH0 0x00003000 -#define NV03_PFIFO_CACHE0_PULL0 0x00003040 -#define NV04_PFIFO_CACHE0_PULL0 0x00003050 -#define NV04_PFIFO_CACHE0_PULL1 0x00003054 -#define NV03_PFIFO_CACHE1_PUSH0 0x00003200 -#define NV03_PFIFO_CACHE1_PUSH1 0x00003204 -#define NV03_PFIFO_CACHE1_PUSH1_DMA (1<<8) -#define NV40_PFIFO_CACHE1_PUSH1_DMA (1<<16) -#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000000f -#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000001f -#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000007f -#define NV03_PFIFO_CACHE1_PUT 0x00003210 -#define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 -#define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000008 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000010 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000018 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000020 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000028 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000030 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000038 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000040 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000048 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x00000050 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x00000058 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x00000060 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x00000068 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x00000070 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x00000078 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000080 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000088 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000090 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000098 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x000000A0 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x000000A8 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x000000B0 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x000000B8 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x000000C0 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x000000C8 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x000000D0 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x000000D8 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x000000E0 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x000000E8 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x000000F0 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x000000F8 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00002000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00004000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00006000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00008000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x0000A000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x0000C000 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x0000E000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00010000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00020000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00030000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00040000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00050000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00060000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00070000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00080000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00090000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x000A0000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x000B0000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x000C0000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x000D0000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x000E0000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x000F0000 -# define NV_PFIFO_CACHE1_ENDIAN 0x80000000 -# define NV_PFIFO_CACHE1_LITTLE_ENDIAN 0x7FFFFFFF -# define NV_PFIFO_CACHE1_BIG_ENDIAN 0x80000000 -#define NV04_PFIFO_CACHE1_DMA_STATE 0x00003228 -#define NV04_PFIFO_CACHE1_DMA_INSTANCE 0x0000322c -#define NV04_PFIFO_CACHE1_DMA_CTL 0x00003230 -#define NV04_PFIFO_CACHE1_DMA_PUT 0x00003240 -#define NV04_PFIFO_CACHE1_DMA_GET 0x00003244 -#define NV10_PFIFO_CACHE1_REF_CNT 0x00003248 -#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C -#define NV03_PFIFO_CACHE1_PULL0 0x00003240 -#define NV04_PFIFO_CACHE1_PULL0 0x00003250 -# define NV04_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000010 -# define NV04_PFIFO_CACHE1_PULL0_HASH_BUSY 0x00001000 -#define NV03_PFIFO_CACHE1_PULL1 0x00003250 -#define NV04_PFIFO_CACHE1_PULL1 0x00003254 -#define NV04_PFIFO_CACHE1_HASH 0x00003258 -#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT 0x00003260 -#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP 0x00003264 -#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE 0x00003268 -#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C -#define NV03_PFIFO_CACHE1_GET 0x00003270 -#define NV04_PFIFO_CACHE1_ENGINE 0x00003280 -#define NV04_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0 -#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0 -#define NV40_PFIFO_UNK32E4 0x000032E4 -#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8)) -#define NV04_PFIFO_CACHE1_DATA(i) (0x00003804+(i*8)) -#define NV40_PFIFO_CACHE1_METHOD(i) (0x00090000+(i*8)) -#define NV40_PFIFO_CACHE1_DATA(i) (0x00090004+(i*8)) - -struct ramfc_desc { +struct nv04_fifo_ramfc { unsigned bits:6; unsigned ctxs:5; unsigned ctxp:8; @@ -139,37 +11,13 @@ struct ramfc_desc { unsigned regp; }; -struct nv04_fifo_priv { +struct nv04_fifo { struct nvkm_fifo base; - struct ramfc_desc *ramfc_desc; - struct nvkm_ramht *ramht; - struct nvkm_gpuobj *ramro; - struct nvkm_gpuobj *ramfc; -}; - -struct nv04_fifo_base { - struct nvkm_fifo_base base; -}; - -struct nv04_fifo_chan { - struct nvkm_fifo_chan base; - u32 subc[8]; - u32 ramfc; + const struct nv04_fifo_ramfc *ramfc; }; -int nv04_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32); -void nv04_fifo_object_detach(struct nvkm_object *, int); - -void nv04_fifo_chan_dtor(struct nvkm_object *); -int nv04_fifo_chan_init(struct nvkm_object *); -int nv04_fifo_chan_fini(struct nvkm_object *, bool suspend); - -int nv04_fifo_context_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - -void nv04_fifo_dtor(struct nvkm_object *); -int nv04_fifo_init(struct nvkm_object *); -void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); -void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); +int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, + int index, int nr, const struct nv04_fifo_ramfc *, + struct nvkm_fifo **); +void nv04_fifo_init(struct nvkm_fifo *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c index 48ce4af6f..f9a87deb2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c @@ -22,17 +22,11 @@ * Authors: Ben Skeggs */ #include "nv04.h" +#include "channv04.h" +#include "regsnv04.h" -#include -#include -#include -#include - -#include -#include - -static struct ramfc_desc -nv10_ramfc[] = { +static const struct nv04_fifo_ramfc +nv10_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -45,134 +39,21 @@ nv10_ramfc[] = { {} }; -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ - -static int -nv10_fifo_chan_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo_priv *priv = (void *)engine; - struct nv04_fifo_chan *chan; - int ret; - - nv_ioctl(parent, "create channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " - "offset %016llx\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000, - 0x10000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - nv_parent(chan)->object_attach = nv04_fifo_object_attach; - nv_parent(chan)->object_detach = nv04_fifo_object_detach; - nv_parent(chan)->context_attach = nv04_fifo_context_attach; - chan->ramfc = chan->base.chid * 32; - - nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); - nv_wo32(priv->ramfc, chan->ramfc + 0x14, - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - return 0; -} - -static struct nvkm_ofuncs -nv10_fifo_ofuncs = { - .ctor = nv10_fifo_chan_ctor, - .dtor = nv04_fifo_chan_dtor, - .init = nv04_fifo_chan_init, - .fini = nv04_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -nv10_fifo_sclass[] = { - { NV10_CHANNEL_DMA, &nv10_fifo_ofuncs }, - {} -}; - -/******************************************************************************* - * FIFO context - basically just the instmem reserved for the channel - ******************************************************************************/ - -static struct nvkm_oclass -nv10_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0x10), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fifo_context_ctor, - .dtor = _nvkm_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, +static const struct nvkm_fifo_func +nv10_fifo = { + .init = nv04_fifo_init, + .intr = nv04_fifo_intr, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .chan = { + &nv10_fifo_dma_oclass, + NULL }, }; -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - -static int -nv10_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv10_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) { - struct nv04_instmem_priv *imem = nv04_instmem(parent); - struct nv04_fifo_priv *priv; - int ret; - - ret = nvkm_fifo_create(parent, engine, oclass, 0, 31, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nvkm_ramht_ref(imem->ramht, &priv->ramht); - nvkm_gpuobj_ref(imem->ramro, &priv->ramro); - nvkm_gpuobj_ref(imem->ramfc, &priv->ramfc); - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = nv04_fifo_intr; - nv_engine(priv)->cclass = &nv10_fifo_cclass; - nv_engine(priv)->sclass = nv10_fifo_sclass; - priv->base.pause = nv04_fifo_pause; - priv->base.start = nv04_fifo_start; - priv->ramfc_desc = nv10_ramfc; - return 0; + return nv04_fifo_new_(&nv10_fifo, device, index, 32, + nv10_fifo_ramfc, pfifo); } - -struct nvkm_oclass * -nv10_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0x10), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_fifo_ctor, - .dtor = nv04_fifo_dtor, - .init = nv04_fifo_init, - .fini = _nvkm_fifo_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c index 4a20a6fd3..f6d383a21 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c @@ -22,17 +22,14 @@ * Authors: Ben Skeggs */ #include "nv04.h" +#include "channv04.h" +#include "regsnv04.h" -#include -#include #include -#include +#include -#include -#include - -static struct ramfc_desc -nv17_ramfc[] = { +static const struct nv04_fifo_ramfc +nv17_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -50,166 +47,51 @@ nv17_ramfc[] = { {} }; -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ - -static int -nv17_fifo_chan_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void +nv17_fifo_init(struct nvkm_fifo *base) { - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo_priv *priv = (void *)engine; - struct nv04_fifo_chan *chan; - int ret; - - nv_ioctl(parent, "create channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " - "offset %016llx\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000, - 0x10000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_MPEG), /* NV31- */ - &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - nv_parent(chan)->object_attach = nv04_fifo_object_attach; - nv_parent(chan)->object_detach = nv04_fifo_object_detach; - nv_parent(chan)->context_attach = nv04_fifo_context_attach; - chan->ramfc = chan->base.chid * 64; - - nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); - nv_wo32(priv->ramfc, chan->ramfc + 0x14, - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - return 0; + struct nv04_fifo *fifo = nv04_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_instmem *imem = device->imem; + struct nvkm_ramht *ramht = imem->ramht; + struct nvkm_memory *ramro = imem->ramro; + struct nvkm_memory *ramfc = imem->ramfc; + + nvkm_wr32(device, NV04_PFIFO_DELAY_0, 0x000000ff); + nvkm_wr32(device, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); + + nvkm_wr32(device, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((ramht->bits - 9) << 16) | + (ramht->gpuobj->addr >> 8)); + nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8); + nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8 | + 0x00010000); + + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1); + + nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff); + nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); + nvkm_wr32(device, NV03_PFIFO_CACHES, 1); } -static struct nvkm_ofuncs -nv17_fifo_ofuncs = { - .ctor = nv17_fifo_chan_ctor, - .dtor = nv04_fifo_chan_dtor, - .init = nv04_fifo_chan_init, - .fini = nv04_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -nv17_fifo_sclass[] = { - { NV17_CHANNEL_DMA, &nv17_fifo_ofuncs }, - {} -}; - -/******************************************************************************* - * FIFO context - basically just the instmem reserved for the channel - ******************************************************************************/ - -static struct nvkm_oclass -nv17_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0x17), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fifo_context_ctor, - .dtor = _nvkm_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, +static const struct nvkm_fifo_func +nv17_fifo = { + .init = nv17_fifo_init, + .intr = nv04_fifo_intr, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .chan = { + &nv17_fifo_dma_oclass, + NULL }, }; -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - -static int -nv17_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv17_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) { - struct nv04_instmem_priv *imem = nv04_instmem(parent); - struct nv04_fifo_priv *priv; - int ret; - - ret = nvkm_fifo_create(parent, engine, oclass, 0, 31, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nvkm_ramht_ref(imem->ramht, &priv->ramht); - nvkm_gpuobj_ref(imem->ramro, &priv->ramro); - nvkm_gpuobj_ref(imem->ramfc, &priv->ramfc); - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = nv04_fifo_intr; - nv_engine(priv)->cclass = &nv17_fifo_cclass; - nv_engine(priv)->sclass = nv17_fifo_sclass; - priv->base.pause = nv04_fifo_pause; - priv->base.start = nv04_fifo_start; - priv->ramfc_desc = nv17_ramfc; - return 0; -} - -static int -nv17_fifo_init(struct nvkm_object *object) -{ - struct nv04_fifo_priv *priv = (void *)object; - int ret; - - ret = nvkm_fifo_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff); - nv_wr32(priv, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); - - nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((priv->ramht->bits - 9) << 16) | - (priv->ramht->gpuobj.addr >> 8)); - nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8 | 0x00010000); - - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - - nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); - - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(priv, NV03_PFIFO_CACHES, 1); - return 0; + return nv04_fifo_new_(&nv17_fifo, device, index, 32, + nv17_fifo_ramfc, pfifo); } - -struct nvkm_oclass * -nv17_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0x17), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv17_fifo_ctor, - .dtor = nv04_fifo_dtor, - .init = nv17_fifo_init, - .fini = _nvkm_fifo_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c index 5bfc96265..8c7ba3276 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c @@ -22,19 +22,15 @@ * Authors: Ben Skeggs */ #include "nv04.h" +#include "channv04.h" +#include "regsnv04.h" -#include -#include -#include #include #include -#include +#include -#include -#include - -static struct ramfc_desc -nv40_ramfc[] = { +static const struct nv04_fifo_ramfc +nv40_fifo_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -60,297 +56,72 @@ nv40_ramfc[] = { {} }; -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ - -static int -nv40_fifo_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 handle) -{ - struct nv04_fifo_priv *priv = (void *)parent->engine; - struct nv04_fifo_chan *chan = (void *)parent; - u32 context, chid = chan->base.chid; - int ret; - - if (nv_iclass(object, NV_GPUOBJ_CLASS)) - context = nv_gpuobj(object)->addr >> 4; - else - context = 0x00000004; /* just non-zero */ - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_DMAOBJ: - case NVDEV_ENGINE_SW: - context |= 0x00000000; - break; - case NVDEV_ENGINE_GR: - context |= 0x00100000; - break; - case NVDEV_ENGINE_MPEG: - context |= 0x00200000; - break; - default: - return -EINVAL; - } - - context |= chid << 23; - - mutex_lock(&nv_subdev(priv)->mutex); - ret = nvkm_ramht_insert(priv->ramht, chid, handle, context); - mutex_unlock(&nv_subdev(priv)->mutex); - return ret; -} - -static int -nv40_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *engctx) -{ - struct nv04_fifo_priv *priv = (void *)parent->engine; - struct nv04_fifo_chan *chan = (void *)parent; - unsigned long flags; - u32 reg, ctx; - - switch (nv_engidx(engctx->engine)) { - case NVDEV_ENGINE_SW: - return 0; - case NVDEV_ENGINE_GR: - reg = 0x32e0; - ctx = 0x38; - break; - case NVDEV_ENGINE_MPEG: - reg = 0x330c; - ctx = 0x54; - break; - default: - return -EINVAL; - } - - spin_lock_irqsave(&priv->base.lock, flags); - nv_engctx(engctx)->addr = nv_gpuobj(engctx)->addr >> 4; - nv_mask(priv, 0x002500, 0x00000001, 0x00000000); - - if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) - nv_wr32(priv, reg, nv_engctx(engctx)->addr); - nv_wo32(priv->ramfc, chan->ramfc + ctx, nv_engctx(engctx)->addr); - - nv_mask(priv, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&priv->base.lock, flags); - return 0; -} - -static int -nv40_fifo_context_detach(struct nvkm_object *parent, bool suspend, - struct nvkm_object *engctx) +static void +nv40_fifo_init(struct nvkm_fifo *base) { - struct nv04_fifo_priv *priv = (void *)parent->engine; - struct nv04_fifo_chan *chan = (void *)parent; - unsigned long flags; - u32 reg, ctx; - - switch (nv_engidx(engctx->engine)) { - case NVDEV_ENGINE_SW: - return 0; - case NVDEV_ENGINE_GR: - reg = 0x32e0; - ctx = 0x38; - break; - case NVDEV_ENGINE_MPEG: - reg = 0x330c; - ctx = 0x54; - break; - default: - return -EINVAL; - } - - spin_lock_irqsave(&priv->base.lock, flags); - nv_mask(priv, 0x002500, 0x00000001, 0x00000000); - - if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) - nv_wr32(priv, reg, 0x00000000); - nv_wo32(priv->ramfc, chan->ramfc + ctx, 0x00000000); - - nv_mask(priv, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&priv->base.lock, flags); - return 0; -} - -static int -nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nv04_fifo_priv *priv = (void *)engine; - struct nv04_fifo_chan *chan; - int ret; - - nv_ioctl(parent, "create channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " - "offset %016llx\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, - 0x1000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_MPEG), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - nv_parent(chan)->context_attach = nv40_fifo_context_attach; - nv_parent(chan)->context_detach = nv40_fifo_context_detach; - nv_parent(chan)->object_attach = nv40_fifo_object_attach; - nv_parent(chan)->object_detach = nv04_fifo_object_detach; - chan->ramfc = chan->base.chid * 128; - - nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset); - nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); - nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 | - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | -#endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nv_wo32(priv->ramfc, chan->ramfc + 0x3c, 0x0001ffff); - return 0; -} - -static struct nvkm_ofuncs -nv40_fifo_ofuncs = { - .ctor = nv40_fifo_chan_ctor, - .dtor = nv04_fifo_chan_dtor, - .init = nv04_fifo_chan_init, - .fini = nv04_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -nv40_fifo_sclass[] = { - { NV40_CHANNEL_DMA, &nv40_fifo_ofuncs }, - {} -}; - -/******************************************************************************* - * FIFO context - basically just the instmem reserved for the channel - ******************************************************************************/ - -static struct nvkm_oclass -nv40_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fifo_context_ctor, - .dtor = _nvkm_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, - }, -}; - -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - -static int -nv40_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv04_instmem_priv *imem = nv04_instmem(parent); - struct nv04_fifo_priv *priv; - int ret; - - ret = nvkm_fifo_create(parent, engine, oclass, 0, 31, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nvkm_ramht_ref(imem->ramht, &priv->ramht); - nvkm_gpuobj_ref(imem->ramro, &priv->ramro); - nvkm_gpuobj_ref(imem->ramfc, &priv->ramfc); - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = nv04_fifo_intr; - nv_engine(priv)->cclass = &nv40_fifo_cclass; - nv_engine(priv)->sclass = nv40_fifo_sclass; - priv->base.pause = nv04_fifo_pause; - priv->base.start = nv04_fifo_start; - priv->ramfc_desc = nv40_ramfc; - return 0; -} - -static int -nv40_fifo_init(struct nvkm_object *object) -{ - struct nv04_fifo_priv *priv = (void *)object; - struct nvkm_fb *pfb = nvkm_fb(object); - int ret; - - ret = nvkm_fifo_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x002040, 0x000000ff); - nv_wr32(priv, 0x002044, 0x2101ffff); - nv_wr32(priv, 0x002058, 0x00000001); - - nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((priv->ramht->bits - 9) << 16) | - (priv->ramht->gpuobj.addr >> 8)); - nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - - switch (nv_device(priv)->chipset) { + struct nv04_fifo *fifo = nv04_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_fb *fb = device->fb; + struct nvkm_instmem *imem = device->imem; + struct nvkm_ramht *ramht = imem->ramht; + struct nvkm_memory *ramro = imem->ramro; + struct nvkm_memory *ramfc = imem->ramfc; + + nvkm_wr32(device, 0x002040, 0x000000ff); + nvkm_wr32(device, 0x002044, 0x2101ffff); + nvkm_wr32(device, 0x002058, 0x00000001); + + nvkm_wr32(device, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((ramht->bits - 9) << 16) | + (ramht->gpuobj->addr >> 8)); + nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8); + + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: - nv_wr32(priv, 0x002230, 0x00000001); + nvkm_wr32(device, 0x002230, 0x00000001); case 0x40: case 0x41: case 0x42: case 0x43: case 0x45: case 0x48: - nv_wr32(priv, 0x002220, 0x00030002); + nvkm_wr32(device, 0x002220, 0x00030002); break; default: - nv_wr32(priv, 0x002230, 0x00000000); - nv_wr32(priv, 0x002220, ((pfb->ram->size - 512 * 1024 + - priv->ramfc->addr) >> 16) | - 0x00030000); + nvkm_wr32(device, 0x002230, 0x00000000); + nvkm_wr32(device, 0x002220, ((fb->ram->size - 512 * 1024 + + nvkm_memory_addr(ramfc)) >> 16) | + 0x00030000); break; } - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1); - nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff); + nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(priv, NV03_PFIFO_CACHES, 1); - return 0; + nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1); + nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1); + nvkm_wr32(device, NV03_PFIFO_CACHES, 1); } -struct nvkm_oclass * -nv40_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_fifo_ctor, - .dtor = nv04_fifo_dtor, - .init = nv40_fifo_init, - .fini = _nvkm_fifo_fini, +static const struct nvkm_fifo_func +nv40_fifo = { + .init = nv40_fifo_init, + .intr = nv04_fifo_intr, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .chan = { + &nv40_fifo_dma_oclass, + NULL }, }; + +int +nv40_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return nv04_fifo_new_(&nv40_fifo, device, index, 32, + nv40_fifo_ramfc, pfifo); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index f25f0fd06..66eb12c2b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -22,513 +22,126 @@ * Authors: Ben Skeggs */ #include "nv50.h" -#include "nv04.h" +#include "channv50.h" -#include -#include -#include -#include -#include -#include - -#include -#include - -/******************************************************************************* - * FIFO channel objects - ******************************************************************************/ +#include static void -nv50_fifo_playlist_update_locked(struct nv50_fifo_priv *priv) +nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo) { - struct nvkm_bar *bar = nvkm_bar(priv); - struct nvkm_gpuobj *cur; + struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_memory *cur; int i, p; - cur = priv->playlist[priv->cur_playlist]; - priv->cur_playlist = !priv->cur_playlist; - - for (i = priv->base.min, p = 0; i < priv->base.max; i++) { - if (nv_rd32(priv, 0x002600 + (i * 4)) & 0x80000000) - nv_wo32(cur, p++ * 4, i); - } - - bar->flush(bar); - - nv_wr32(priv, 0x0032f4, cur->addr >> 12); - nv_wr32(priv, 0x0032ec, p); - nv_wr32(priv, 0x002500, 0x00000101); -} - -void -nv50_fifo_playlist_update(struct nv50_fifo_priv *priv) -{ - mutex_lock(&nv_subdev(priv)->mutex); - nv50_fifo_playlist_update_locked(priv); - mutex_unlock(&nv_subdev(priv)->mutex); -} - -static int -nv50_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *object) -{ - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_base *base = (void *)parent->parent; - struct nvkm_gpuobj *ectx = (void *)object; - u64 limit = ectx->addr + ectx->size - 1; - u64 start = ectx->addr; - u32 addr; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0000; break; - case NVDEV_ENGINE_MPEG : addr = 0x0060; break; - default: - return -EINVAL; - } - - nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; - nv_wo32(base->eng, addr + 0x00, 0x00190000); - nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); - nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); - nv_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 | - upper_32_bits(start)); - nv_wo32(base->eng, addr + 0x10, 0x00000000); - nv_wo32(base->eng, addr + 0x14, 0x00000000); - bar->flush(bar); - return 0; -} - -static int -nv50_fifo_context_detach(struct nvkm_object *parent, bool suspend, - struct nvkm_object *object) -{ - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_priv *priv = (void *)parent->engine; - struct nv50_fifo_base *base = (void *)parent->parent; - struct nv50_fifo_chan *chan = (void *)parent; - u32 addr, me; - int ret = 0; - - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0000; break; - case NVDEV_ENGINE_MPEG : addr = 0x0060; break; - default: - return -EINVAL; - } - - /* HW bug workaround: - * - * PFIFO will hang forever if the connected engines don't report - * that they've processed the context switch request. - * - * In order for the kickoff to work, we need to ensure all the - * connected engines are in a state where they can answer. - * - * Newer chipsets don't seem to suffer from this issue, and well, - * there's also a "ignore these engines" bitmask reg we can use - * if we hit the issue there.. - */ - me = nv_mask(priv, 0x00b860, 0x00000001, 0x00000001); - - /* do the kickoff... */ - nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); - if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { - nv_error(priv, "channel %d [%s] unload timeout\n", - chan->base.chid, nvkm_client_name(chan)); - if (suspend) - ret = -EBUSY; - } - nv_wr32(priv, 0x00b860, me); - - if (ret == 0) { - nv_wo32(base->eng, addr + 0x00, 0x00000000); - nv_wo32(base->eng, addr + 0x04, 0x00000000); - nv_wo32(base->eng, addr + 0x08, 0x00000000); - nv_wo32(base->eng, addr + 0x0c, 0x00000000); - nv_wo32(base->eng, addr + 0x10, 0x00000000); - nv_wo32(base->eng, addr + 0x14, 0x00000000); - bar->flush(bar); - } - - return ret; -} - -static int -nv50_fifo_object_attach(struct nvkm_object *parent, - struct nvkm_object *object, u32 handle) -{ - struct nv50_fifo_chan *chan = (void *)parent; - u32 context; - - if (nv_iclass(object, NV_GPUOBJ_CLASS)) - context = nv_gpuobj(object)->node->offset >> 4; - else - context = 0x00000004; /* just non-zero */ + cur = fifo->runlist[fifo->cur_runlist]; + fifo->cur_runlist = !fifo->cur_runlist; - switch (nv_engidx(object->engine)) { - case NVDEV_ENGINE_DMAOBJ: - case NVDEV_ENGINE_SW : context |= 0x00000000; break; - case NVDEV_ENGINE_GR : context |= 0x00100000; break; - case NVDEV_ENGINE_MPEG : context |= 0x00200000; break; - default: - return -EINVAL; + nvkm_kmap(cur); + for (i = 0, p = 0; i < fifo->base.nr; i++) { + if (nvkm_rd32(device, 0x002600 + (i * 4)) & 0x80000000) + nvkm_wo32(cur, p++ * 4, i); } + nvkm_done(cur); - return nvkm_ramht_insert(chan->ramht, 0, handle, context); + nvkm_wr32(device, 0x0032f4, nvkm_memory_addr(cur) >> 12); + nvkm_wr32(device, 0x0032ec, p); + nvkm_wr32(device, 0x002500, 0x00000101); } void -nv50_fifo_object_detach(struct nvkm_object *parent, int cookie) +nv50_fifo_runlist_update(struct nv50_fifo *fifo) { - struct nv50_fifo_chan *chan = (void *)parent; - nvkm_ramht_remove(chan->ramht, cookie); + mutex_lock(&fifo->base.engine.subdev.mutex); + nv50_fifo_runlist_update_locked(fifo); + mutex_unlock(&fifo->base.engine.subdev.mutex); } -static int -nv50_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv50_fifo_oneinit(struct nvkm_fifo *base) { - union { - struct nv03_channel_dma_v0 v0; - } *args = data; - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_base *base = (void *)parent; - struct nv50_fifo_chan *chan; + struct nv50_fifo *fifo = nv50_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; int ret; - nv_ioctl(parent, "create channel dma size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel dma vers %d pushbuf %08x " - "offset %016llx\n", args->v0.version, - args->v0.pushbuf, args->v0.offset); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, - 0x2000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_MPEG), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - args->v0.chid = chan->base.chid; - - nv_parent(chan)->context_attach = nv50_fifo_context_attach; - nv_parent(chan)->context_detach = nv50_fifo_context_detach; - nv_parent(chan)->object_attach = nv50_fifo_object_attach; - nv_parent(chan)->object_detach = nv50_fifo_object_detach; - - ret = nvkm_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16, - &chan->ramht); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, + false, &fifo->runlist[0]); if (ret) return ret; - nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset)); - nv_wo32(base->ramfc, 0x3c, 0x003f6078); - nv_wo32(base->ramfc, 0x44, 0x01003fff); - nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); - nv_wo32(base->ramfc, 0x4c, 0xffffffff); - nv_wo32(base->ramfc, 0x60, 0x7fffffff); - nv_wo32(base->ramfc, 0x78, 0x00000000); - nv_wo32(base->ramfc, 0x7c, 0x30000001); - nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj.node->offset >> 4)); - bar->flush(bar); - return 0; + return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, + false, &fifo->runlist[1]); } -static int -nv50_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +void +nv50_fifo_init(struct nvkm_fifo *base) { - union { - struct nv50_channel_gpfifo_v0 v0; - } *args = data; - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_fifo_base *base = (void *)parent; - struct nv50_fifo_chan *chan; - u64 ioffset, ilength; - int ret; + struct nv50_fifo *fifo = nv50_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; + int i; - nv_ioctl(parent, "create channel gpfifo size %d\n", size); - if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x " - "ioffset %016llx ilength %08x\n", - args->v0.version, args->v0.pushbuf, args->v0.ioffset, - args->v0.ilength); - } else - return ret; - - ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, - 0x2000, args->v0.pushbuf, - (1ULL << NVDEV_ENGINE_DMAOBJ) | - (1ULL << NVDEV_ENGINE_SW) | - (1ULL << NVDEV_ENGINE_GR) | - (1ULL << NVDEV_ENGINE_MPEG), &chan); - *pobject = nv_object(chan); - if (ret) - return ret; + nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); + nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); + nvkm_wr32(device, 0x00250c, 0x6f3cfc34); + nvkm_wr32(device, 0x002044, 0x01003fff); - args->v0.chid = chan->base.chid; + nvkm_wr32(device, 0x002100, 0xffffffff); + nvkm_wr32(device, 0x002140, 0xbfffffff); - nv_parent(chan)->context_attach = nv50_fifo_context_attach; - nv_parent(chan)->context_detach = nv50_fifo_context_detach; - nv_parent(chan)->object_attach = nv50_fifo_object_attach; - nv_parent(chan)->object_detach = nv50_fifo_object_detach; - - ret = nvkm_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16, - &chan->ramht); - if (ret) - return ret; - - ioffset = args->v0.ioffset; - ilength = order_base_2(args->v0.ilength / 8); + for (i = 0; i < 128; i++) + nvkm_wr32(device, 0x002600 + (i * 4), 0x00000000); + nv50_fifo_runlist_update_locked(fifo); - nv_wo32(base->ramfc, 0x3c, 0x403f6078); - nv_wo32(base->ramfc, 0x44, 0x01003fff); - nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); - nv_wo32(base->ramfc, 0x50, lower_32_bits(ioffset)); - nv_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); - nv_wo32(base->ramfc, 0x60, 0x7fffffff); - nv_wo32(base->ramfc, 0x78, 0x00000000); - nv_wo32(base->ramfc, 0x7c, 0x30000001); - nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj.node->offset >> 4)); - bar->flush(bar); - return 0; + nvkm_wr32(device, 0x003200, 0x00000001); + nvkm_wr32(device, 0x003250, 0x00000001); + nvkm_wr32(device, 0x002500, 0x00000001); } -void -nv50_fifo_chan_dtor(struct nvkm_object *object) +void * +nv50_fifo_dtor(struct nvkm_fifo *base) { - struct nv50_fifo_chan *chan = (void *)object; - nvkm_ramht_ref(NULL, &chan->ramht); - nvkm_fifo_channel_destroy(&chan->base); -} - -static int -nv50_fifo_chan_init(struct nvkm_object *object) -{ - struct nv50_fifo_priv *priv = (void *)object->engine; - struct nv50_fifo_base *base = (void *)object->parent; - struct nv50_fifo_chan *chan = (void *)object; - struct nvkm_gpuobj *ramfc = base->ramfc; - u32 chid = chan->base.chid; - int ret; - - ret = nvkm_fifo_channel_init(&chan->base); - if (ret) - return ret; - - nv_wr32(priv, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 12); - nv50_fifo_playlist_update(priv); - return 0; + struct nv50_fifo *fifo = nv50_fifo(base); + nvkm_memory_del(&fifo->runlist[1]); + nvkm_memory_del(&fifo->runlist[0]); + return fifo; } int -nv50_fifo_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_fifo_priv *priv = (void *)object->engine; - struct nv50_fifo_chan *chan = (void *)object; - u32 chid = chan->base.chid; - - /* remove channel from playlist, fifo will unload context */ - nv_mask(priv, 0x002600 + (chid * 4), 0x80000000, 0x00000000); - nv50_fifo_playlist_update(priv); - nv_wr32(priv, 0x002600 + (chid * 4), 0x00000000); - - return nvkm_fifo_channel_fini(&chan->base, suspend); -} - -static struct nvkm_ofuncs -nv50_fifo_ofuncs_dma = { - .ctor = nv50_fifo_chan_ctor_dma, - .dtor = nv50_fifo_chan_dtor, - .init = nv50_fifo_chan_init, - .fini = nv50_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_ofuncs -nv50_fifo_ofuncs_ind = { - .ctor = nv50_fifo_chan_ctor_ind, - .dtor = nv50_fifo_chan_dtor, - .init = nv50_fifo_chan_init, - .fini = nv50_fifo_chan_fini, - .map = _nvkm_fifo_channel_map, - .rd32 = _nvkm_fifo_channel_rd32, - .wr32 = _nvkm_fifo_channel_wr32, - .ntfy = _nvkm_fifo_channel_ntfy -}; - -static struct nvkm_oclass -nv50_fifo_sclass[] = { - { NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma }, - { NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind }, - {} -}; - -/******************************************************************************* - * FIFO context - basically just the instmem reserved for the channel - ******************************************************************************/ - -static int -nv50_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, + int index, struct nvkm_fifo **pfifo) { - struct nv50_fifo_base *base; + struct nv50_fifo *fifo; int ret; - ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x10000, - 0x1000, NVOBJ_FLAG_HEAP, &base); - *pobject = nv_object(base); - if (ret) - return ret; + if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) + return -ENOMEM; + *pfifo = &fifo->base; - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x0200, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x1200, 0, - NVOBJ_FLAG_ZERO_ALLOC, &base->eng); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x4000, 0, 0, - &base->pgd); - if (ret) - return ret; - - ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd); + ret = nvkm_fifo_ctor(func, device, index, 128, &fifo->base); if (ret) return ret; + set_bit(0, fifo->base.mask); /* PIO channel */ + set_bit(127, fifo->base.mask); /* inactive channel */ return 0; } -void -nv50_fifo_context_dtor(struct nvkm_object *object) -{ - struct nv50_fifo_base *base = (void *)object; - nvkm_vm_ref(NULL, &base->vm, base->pgd); - nvkm_gpuobj_ref(NULL, &base->pgd); - nvkm_gpuobj_ref(NULL, &base->eng); - nvkm_gpuobj_ref(NULL, &base->ramfc); - nvkm_gpuobj_ref(NULL, &base->cache); - nvkm_fifo_context_destroy(&base->base); -} - -static struct nvkm_oclass -nv50_fifo_cclass = { - .handle = NV_ENGCTX(FIFO, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fifo_context_ctor, - .dtor = nv50_fifo_context_dtor, - .init = _nvkm_fifo_context_init, - .fini = _nvkm_fifo_context_fini, - .rd32 = _nvkm_fifo_context_rd32, - .wr32 = _nvkm_fifo_context_wr32, +static const struct nvkm_fifo_func +nv50_fifo = { + .dtor = nv50_fifo_dtor, + .oneinit = nv50_fifo_oneinit, + .init = nv50_fifo_init, + .intr = nv04_fifo_intr, + .pause = nv04_fifo_pause, + .start = nv04_fifo_start, + .chan = { + &nv50_fifo_dma_oclass, + &nv50_fifo_gpfifo_oclass, + NULL }, }; -/******************************************************************************* - * PFIFO engine - ******************************************************************************/ - -static int -nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_fifo_priv *priv; - int ret; - - ret = nvkm_fifo_create(parent, engine, oclass, 1, 127, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0, - &priv->playlist[0]); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0, - &priv->playlist[1]); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000100; - nv_subdev(priv)->intr = nv04_fifo_intr; - nv_engine(priv)->cclass = &nv50_fifo_cclass; - nv_engine(priv)->sclass = nv50_fifo_sclass; - priv->base.pause = nv04_fifo_pause; - priv->base.start = nv04_fifo_start; - return 0; -} - -void -nv50_fifo_dtor(struct nvkm_object *object) -{ - struct nv50_fifo_priv *priv = (void *)object; - - nvkm_gpuobj_ref(NULL, &priv->playlist[1]); - nvkm_gpuobj_ref(NULL, &priv->playlist[0]); - - nvkm_fifo_destroy(&priv->base); -} - int -nv50_fifo_init(struct nvkm_object *object) +nv50_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) { - struct nv50_fifo_priv *priv = (void *)object; - int ret, i; - - ret = nvkm_fifo_init(&priv->base); - if (ret) - return ret; - - nv_mask(priv, 0x000200, 0x00000100, 0x00000000); - nv_mask(priv, 0x000200, 0x00000100, 0x00000100); - nv_wr32(priv, 0x00250c, 0x6f3cfc34); - nv_wr32(priv, 0x002044, 0x01003fff); - - nv_wr32(priv, 0x002100, 0xffffffff); - nv_wr32(priv, 0x002140, 0xbfffffff); - - for (i = 0; i < 128; i++) - nv_wr32(priv, 0x002600 + (i * 4), 0x00000000); - nv50_fifo_playlist_update_locked(priv); - - nv_wr32(priv, 0x003200, 0x00000001); - nv_wr32(priv, 0x003250, 0x00000001); - nv_wr32(priv, 0x002500, 0x00000001); - return 0; + return nv50_fifo_new_(&nv50_fifo, device, index, pfifo); } - -struct nvkm_oclass * -nv50_fifo_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(FIFO, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fifo_ctor, - .dtor = nv50_fifo_dtor, - .init = nv50_fifo_init, - .fini = _nvkm_fifo_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h index 09ed93c66..8ab53948c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h @@ -1,36 +1,19 @@ #ifndef __NV50_FIFO_H__ #define __NV50_FIFO_H__ -#include +#define nv50_fifo(p) container_of((p), struct nv50_fifo, base) +#include "priv.h" -struct nv50_fifo_priv { +struct nv50_fifo { struct nvkm_fifo base; - struct nvkm_gpuobj *playlist[2]; - int cur_playlist; + struct nvkm_memory *runlist[2]; + int cur_runlist; }; -struct nv50_fifo_base { - struct nvkm_fifo_base base; - struct nvkm_gpuobj *ramfc; - struct nvkm_gpuobj *cache; - struct nvkm_gpuobj *eng; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; -}; - -struct nv50_fifo_chan { - struct nvkm_fifo_chan base; - u32 subc[8]; - struct nvkm_ramht *ramht; -}; - -void nv50_fifo_playlist_update(struct nv50_fifo_priv *); - -void nv50_fifo_object_detach(struct nvkm_object *, int); -void nv50_fifo_chan_dtor(struct nvkm_object *); -int nv50_fifo_chan_fini(struct nvkm_object *, bool); - -void nv50_fifo_context_dtor(struct nvkm_object *); +int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, + int index, struct nvkm_fifo **); -void nv50_fifo_dtor(struct nvkm_object *); -int nv50_fifo_init(struct nvkm_object *); +void *nv50_fifo_dtor(struct nvkm_fifo *); +int nv50_fifo_oneinit(struct nvkm_fifo *); +void nv50_fifo_init(struct nvkm_fifo *); +void nv50_fifo_runlist_update(struct nv50_fifo *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h new file mode 100644 index 000000000..cb1432e9b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_FIFO_PRIV_H__ +#define __NVKM_FIFO_PRIV_H__ +#define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine) +#include + +int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, + int index, int nr, struct nvkm_fifo *); +void nvkm_fifo_uevent(struct nvkm_fifo *); + +struct nvkm_fifo_func { + void *(*dtor)(struct nvkm_fifo *); + int (*oneinit)(struct nvkm_fifo *); + void (*init)(struct nvkm_fifo *); + void (*fini)(struct nvkm_fifo *); + void (*intr)(struct nvkm_fifo *); + void (*pause)(struct nvkm_fifo *, unsigned long *); + void (*start)(struct nvkm_fifo *, unsigned long *); + void (*uevent_init)(struct nvkm_fifo *); + void (*uevent_fini)(struct nvkm_fifo *); + const struct nvkm_fifo_chan_oclass *chan[]; +}; + +void nv04_fifo_intr(struct nvkm_fifo *); +void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *); +void nv04_fifo_start(struct nvkm_fifo *, unsigned long *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h new file mode 100644 index 000000000..92d562211 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h @@ -0,0 +1,132 @@ +#ifndef __NV04_FIFO_REGS_H__ +#define __NV04_FIFO_REGS_H__ + +#define NV04_PFIFO_DELAY_0 0x00002040 +#define NV04_PFIFO_DMA_TIMESLICE 0x00002044 +#define NV04_PFIFO_NEXT_CHANNEL 0x00002050 +#define NV03_PFIFO_INTR_0 0x00002100 +#define NV03_PFIFO_INTR_EN_0 0x00002140 +# define NV_PFIFO_INTR_CACHE_ERROR (1<<0) +# define NV_PFIFO_INTR_RUNOUT (1<<4) +# define NV_PFIFO_INTR_RUNOUT_OVERFLOW (1<<8) +# define NV_PFIFO_INTR_DMA_PUSHER (1<<12) +# define NV_PFIFO_INTR_DMA_PT (1<<16) +# define NV_PFIFO_INTR_SEMAPHORE (1<<20) +# define NV_PFIFO_INTR_ACQUIRE_TIMEOUT (1<<24) +#define NV03_PFIFO_RAMHT 0x00002210 +#define NV03_PFIFO_RAMFC 0x00002214 +#define NV03_PFIFO_RAMRO 0x00002218 +#define NV40_PFIFO_RAMFC 0x00002220 +#define NV03_PFIFO_CACHES 0x00002500 +#define NV04_PFIFO_MODE 0x00002504 +#define NV04_PFIFO_DMA 0x00002508 +#define NV04_PFIFO_SIZE 0x0000250c +#define NV50_PFIFO_CTX_TABLE(c) (0x2600+(c)*4) +#define NV50_PFIFO_CTX_TABLE__SIZE 128 +#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED (1<<31) +#define NV50_PFIFO_CTX_TABLE_UNK30_BAD (1<<30) +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 0x0FFFFFFF +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 0x00FFFFFF +#define NV03_PFIFO_CACHE0_PUSH0 0x00003000 +#define NV03_PFIFO_CACHE0_PULL0 0x00003040 +#define NV04_PFIFO_CACHE0_PULL0 0x00003050 +#define NV04_PFIFO_CACHE0_PULL1 0x00003054 +#define NV03_PFIFO_CACHE1_PUSH0 0x00003200 +#define NV03_PFIFO_CACHE1_PUSH1 0x00003204 +#define NV03_PFIFO_CACHE1_PUSH1_DMA (1<<8) +#define NV40_PFIFO_CACHE1_PUSH1_DMA (1<<16) +#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000000f +#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000001f +#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000007f +#define NV03_PFIFO_CACHE1_PUT 0x00003210 +#define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 +#define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000008 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000010 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000018 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000020 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000028 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000030 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000038 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000040 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000048 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x00000050 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x00000058 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x00000060 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x00000068 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x00000070 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x00000078 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000080 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000088 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000090 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000098 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x000000A0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x000000A8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x000000B0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x000000B8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x000000C0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x000000C8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x000000D0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x000000D8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x000000E0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x000000E8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x000000F0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x000000F8 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00002000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00004000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00006000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00008000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x0000A000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x0000C000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00010000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00020000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00030000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00040000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00050000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00060000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00070000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00080000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00090000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x000A0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x000B0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x000C0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x000D0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x000E0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x000F0000 +# define NV_PFIFO_CACHE1_ENDIAN 0x80000000 +# define NV_PFIFO_CACHE1_LITTLE_ENDIAN 0x7FFFFFFF +# define NV_PFIFO_CACHE1_BIG_ENDIAN 0x80000000 +#define NV04_PFIFO_CACHE1_DMA_STATE 0x00003228 +#define NV04_PFIFO_CACHE1_DMA_INSTANCE 0x0000322c +#define NV04_PFIFO_CACHE1_DMA_CTL 0x00003230 +#define NV04_PFIFO_CACHE1_DMA_PUT 0x00003240 +#define NV04_PFIFO_CACHE1_DMA_GET 0x00003244 +#define NV10_PFIFO_CACHE1_REF_CNT 0x00003248 +#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C +#define NV03_PFIFO_CACHE1_PULL0 0x00003240 +#define NV04_PFIFO_CACHE1_PULL0 0x00003250 +# define NV04_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000010 +# define NV04_PFIFO_CACHE1_PULL0_HASH_BUSY 0x00001000 +#define NV03_PFIFO_CACHE1_PULL1 0x00003250 +#define NV04_PFIFO_CACHE1_PULL1 0x00003254 +#define NV04_PFIFO_CACHE1_HASH 0x00003258 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT 0x00003260 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP 0x00003264 +#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE 0x00003268 +#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C +#define NV03_PFIFO_CACHE1_GET 0x00003270 +#define NV04_PFIFO_CACHE1_ENGINE 0x00003280 +#define NV04_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0 +#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0 +#define NV40_PFIFO_UNK32E4 0x000032E4 +#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8)) +#define NV04_PFIFO_CACHE1_DATA(i) (0x00003804+(i*8)) +#define NV40_PFIFO_CACHE1_METHOD(i) (0x00090000+(i*8)) +#define NV40_PFIFO_CACHE1_DATA(i) (0x00090004+(i*8)) +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild index 2e1b92f71..9ad0d0e78 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild @@ -1,21 +1,8 @@ -nvkm-y += nvkm/engine/gr/ctxnv40.o -nvkm-y += nvkm/engine/gr/ctxnv50.o -nvkm-y += nvkm/engine/gr/ctxgf100.o -nvkm-y += nvkm/engine/gr/ctxgf108.o -nvkm-y += nvkm/engine/gr/ctxgf104.o -nvkm-y += nvkm/engine/gr/ctxgf110.o -nvkm-y += nvkm/engine/gr/ctxgf117.o -nvkm-y += nvkm/engine/gr/ctxgf119.o -nvkm-y += nvkm/engine/gr/ctxgk104.o -nvkm-y += nvkm/engine/gr/ctxgk20a.o -nvkm-y += nvkm/engine/gr/ctxgk110.o -nvkm-y += nvkm/engine/gr/ctxgk110b.o -nvkm-y += nvkm/engine/gr/ctxgk208.o -nvkm-y += nvkm/engine/gr/ctxgm107.o -nvkm-y += nvkm/engine/gr/ctxgm204.o -nvkm-y += nvkm/engine/gr/ctxgm206.o +nvkm-y += nvkm/engine/gr/base.o nvkm-y += nvkm/engine/gr/nv04.o nvkm-y += nvkm/engine/gr/nv10.o +nvkm-y += nvkm/engine/gr/nv15.o +nvkm-y += nvkm/engine/gr/nv17.o nvkm-y += nvkm/engine/gr/nv20.o nvkm-y += nvkm/engine/gr/nv25.o nvkm-y += nvkm/engine/gr/nv2a.o @@ -23,18 +10,43 @@ nvkm-y += nvkm/engine/gr/nv30.o nvkm-y += nvkm/engine/gr/nv34.o nvkm-y += nvkm/engine/gr/nv35.o nvkm-y += nvkm/engine/gr/nv40.o +nvkm-y += nvkm/engine/gr/nv44.o nvkm-y += nvkm/engine/gr/nv50.o +nvkm-y += nvkm/engine/gr/g84.o +nvkm-y += nvkm/engine/gr/gt200.o +nvkm-y += nvkm/engine/gr/mcp79.o +nvkm-y += nvkm/engine/gr/gt215.o +nvkm-y += nvkm/engine/gr/mcp89.o nvkm-y += nvkm/engine/gr/gf100.o -nvkm-y += nvkm/engine/gr/gf108.o nvkm-y += nvkm/engine/gr/gf104.o +nvkm-y += nvkm/engine/gr/gf108.o nvkm-y += nvkm/engine/gr/gf110.o nvkm-y += nvkm/engine/gr/gf117.o nvkm-y += nvkm/engine/gr/gf119.o nvkm-y += nvkm/engine/gr/gk104.o -nvkm-y += nvkm/engine/gr/gk20a.o nvkm-y += nvkm/engine/gr/gk110.o nvkm-y += nvkm/engine/gr/gk110b.o nvkm-y += nvkm/engine/gr/gk208.o +nvkm-y += nvkm/engine/gr/gk20a.o nvkm-y += nvkm/engine/gr/gm107.o nvkm-y += nvkm/engine/gr/gm204.o nvkm-y += nvkm/engine/gr/gm206.o +nvkm-y += nvkm/engine/gr/gm20b.o + +nvkm-y += nvkm/engine/gr/ctxnv40.o +nvkm-y += nvkm/engine/gr/ctxnv50.o +nvkm-y += nvkm/engine/gr/ctxgf100.o +nvkm-y += nvkm/engine/gr/ctxgf104.o +nvkm-y += nvkm/engine/gr/ctxgf108.o +nvkm-y += nvkm/engine/gr/ctxgf110.o +nvkm-y += nvkm/engine/gr/ctxgf117.o +nvkm-y += nvkm/engine/gr/ctxgf119.o +nvkm-y += nvkm/engine/gr/ctxgk104.o +nvkm-y += nvkm/engine/gr/ctxgk110.o +nvkm-y += nvkm/engine/gr/ctxgk110b.o +nvkm-y += nvkm/engine/gr/ctxgk208.o +nvkm-y += nvkm/engine/gr/ctxgk20a.o +nvkm-y += nvkm/engine/gr/ctxgm107.o +nvkm-y += nvkm/engine/gr/ctxgm204.o +nvkm-y += nvkm/engine/gr/ctxgm206.o +nvkm-y += nvkm/engine/gr/ctxgm20b.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c new file mode 100644 index 000000000..090765ff0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c @@ -0,0 +1,136 @@ +/* + * 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 + */ +#include "priv.h" + +#include + +static void +nvkm_gr_tile(struct nvkm_engine *engine, int region, struct nvkm_fb_tile *tile) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + if (gr->func->tile) + gr->func->tile(gr, region, tile); +} + +u64 +nvkm_gr_units(struct nvkm_gr *gr) +{ + if (gr->func->units) + return gr->func->units(gr); + return 0; +} + +int +nvkm_gr_tlb_flush(struct nvkm_gr *gr) +{ + if (gr->func->tlb_flush) + return gr->func->tlb_flush(gr); + return -ENODEV; +} + +static int +nvkm_gr_oclass_get(struct nvkm_oclass *oclass, int index) +{ + struct nvkm_gr *gr = nvkm_gr(oclass->engine); + int c = 0; + + if (gr->func->object_get) { + int ret = gr->func->object_get(gr, index, &oclass->base); + if (oclass->base.oclass) + return index; + return ret; + } + + while (gr->func->sclass[c].oclass) { + if (c++ == index) { + oclass->base = gr->func->sclass[index]; + return index; + } + } + + return c; +} + +static int +nvkm_gr_cclass_new(struct nvkm_fifo_chan *chan, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nvkm_gr *gr = nvkm_gr(oclass->engine); + if (gr->func->chan_new) + return gr->func->chan_new(gr, chan, oclass, pobject); + return 0; +} + +static void +nvkm_gr_intr(struct nvkm_engine *engine) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + gr->func->intr(gr); +} + +static int +nvkm_gr_oneinit(struct nvkm_engine *engine) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + if (gr->func->oneinit) + return gr->func->oneinit(gr); + return 0; +} + +static int +nvkm_gr_init(struct nvkm_engine *engine) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + return gr->func->init(gr); +} + +static void * +nvkm_gr_dtor(struct nvkm_engine *engine) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + if (gr->func->dtor) + return gr->func->dtor(gr); + return gr; +} + +static const struct nvkm_engine_func +nvkm_gr = { + .dtor = nvkm_gr_dtor, + .oneinit = nvkm_gr_oneinit, + .init = nvkm_gr_init, + .intr = nvkm_gr_intr, + .tile = nvkm_gr_tile, + .fifo.cclass = nvkm_gr_cclass_new, + .fifo.sclass = nvkm_gr_oclass_get, +}; + +int +nvkm_gr_ctor(const struct nvkm_gr_func *func, struct nvkm_device *device, + int index, u32 pmc_enable, bool enable, struct nvkm_gr *gr) +{ + gr->func = func; + return nvkm_engine_ctor(&nvkm_gr, device, index, pmc_enable, + enable, &gr->engine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 57e2c5b13..56f392d3d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -23,7 +23,6 @@ */ #include "ctxgf100.h" -#include #include #include #include @@ -1005,6 +1004,7 @@ void gf100_grctx_mmio_item(struct gf100_grctx *info, u32 addr, u32 data, int shift, int buffer) { + struct nvkm_device *device = info->gr->base.engine.subdev.device; if (info->data) { if (shift >= 0) { info->mmio->addr = addr; @@ -1021,29 +1021,29 @@ gf100_grctx_mmio_item(struct gf100_grctx *info, u32 addr, u32 data, return; } - nv_wr32(info->priv, addr, data); + nvkm_wr32(device, addr, data); } void gf100_grctx_generate_bundle(struct gf100_grctx *info) { - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); + const struct gf100_grctx_func *grctx = info->gr->func->grctx; const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, impl->bundle_size, (1 << s), access); + const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); mmio_refn(info, 0x408004, 0x00000000, s, b); - mmio_wr32(info, 0x408008, 0x80000000 | (impl->bundle_size >> s)); + mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); mmio_refn(info, 0x418808, 0x00000000, s, b); - mmio_wr32(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s)); + mmio_wr32(info, 0x41880c, 0x80000000 | (grctx->bundle_size >> s)); } void gf100_grctx_generate_pagepool(struct gf100_grctx *info) { - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); + const struct gf100_grctx_func *grctx = info->gr->func->grctx; const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); @@ -1053,13 +1053,13 @@ gf100_grctx_generate_pagepool(struct gf100_grctx *info) void gf100_grctx_generate_attrib(struct gf100_grctx *info) { - struct gf100_gr_priv *priv = info->priv; - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(priv); - const u32 attrib = impl->attrib_nr; - const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max); + struct gf100_gr *gr = info->gr; + const struct gf100_grctx_func *grctx = gr->func->grctx; + const u32 attrib = grctx->attrib_nr; + const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); int gpc, tpc; u32 bo = 0; @@ -1067,91 +1067,95 @@ gf100_grctx_generate_attrib(struct gf100_grctx *info) mmio_refn(info, 0x419848, 0x10000000, s, b); mmio_wr32(info, 0x405830, (attrib << 16)); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { const u32 o = TPC_UNIT(gpc, tpc, 0x0520); mmio_skip(info, o, (attrib << 16) | ++bo); mmio_wr32(info, o, (attrib << 16) | --bo); - bo += impl->attrib_nr_max; + bo += grctx->attrib_nr_max; } } } void -gf100_grctx_generate_unkn(struct gf100_gr_priv *priv) +gf100_grctx_generate_unkn(struct gf100_gr *gr) { } void -gf100_grctx_generate_tpcid(struct gf100_gr_priv *priv) +gf100_grctx_generate_tpcid(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; int gpc, tpc, id; for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tpc < priv->tpc_nr[gpc]) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x4e8), id); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + if (tpc < gr->tpc_nr[gpc]) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x698), id); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x4e8), id); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), id); id++; } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c08), gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c8c), gr->tpc_nr[gpc]); } } } void -gf100_grctx_generate_r406028(struct gf100_gr_priv *priv) +gf100_grctx_generate_r406028(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; u32 tmp[GPC_MAX / 8] = {}, i = 0; - for (i = 0; i < priv->gpc_nr; i++) - tmp[i / 8] |= priv->tpc_nr[i] << ((i % 8) * 4); + for (i = 0; i < gr->gpc_nr; i++) + tmp[i / 8] |= gr->tpc_nr[i] << ((i % 8) * 4); for (i = 0; i < 4; i++) { - nv_wr32(priv, 0x406028 + (i * 4), tmp[i]); - nv_wr32(priv, 0x405870 + (i * 4), tmp[i]); + nvkm_wr32(device, 0x406028 + (i * 4), tmp[i]); + nvkm_wr32(device, 0x405870 + (i * 4), tmp[i]); } } void -gf100_grctx_generate_r4060a8(struct gf100_gr_priv *priv) +gf100_grctx_generate_r4060a8(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; u8 tpcnr[GPC_MAX], data[TPC_MAX]; int gpc, tpc, i; - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); memset(data, 0x1f, sizeof(data)); gpc = -1; - for (tpc = 0; tpc < priv->tpc_total; tpc++) { + for (tpc = 0; tpc < gr->tpc_total; tpc++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; data[tpc] = gpc; } for (i = 0; i < 4; i++) - nv_wr32(priv, 0x4060a8 + (i * 4), ((u32 *)data)[i]); + nvkm_wr32(device, 0x4060a8 + (i * 4), ((u32 *)data)[i]); } void -gf100_grctx_generate_r418bb8(struct gf100_gr_priv *priv) +gf100_grctx_generate_r418bb8(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; u32 data[6] = {}, data2[2] = {}; u8 tpcnr[GPC_MAX]; u8 shift, ntpcv; int gpc, tpc, i; /* calculate first set of magics */ - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < priv->tpc_total; tpc++) { + for (tpc = 0; tpc < gr->tpc_total; tpc++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -1163,7 +1167,7 @@ gf100_grctx_generate_r418bb8(struct gf100_gr_priv *priv) /* and the second... */ shift = 0; - ntpcv = priv->tpc_total; + ntpcv = gr->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -1176,202 +1180,211 @@ gf100_grctx_generate_r418bb8(struct gf100_gr_priv *priv) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* GPC_BROADCAST */ - nv_wr32(priv, 0x418bb8, (priv->tpc_total << 8) | - priv->magic_not_rop_nr); + nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) | + gr->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(priv, 0x418b08 + (i * 4), data[i]); + nvkm_wr32(device, 0x418b08 + (i * 4), data[i]); /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(priv, 0x419bd0, (priv->tpc_total << 8) | - priv->magic_not_rop_nr | data2[0]); - nv_wr32(priv, 0x419be4, data2[1]); + nvkm_wr32(device, 0x419bd0, (gr->tpc_total << 8) | + gr->magic_not_rop_nr | data2[0]); + nvkm_wr32(device, 0x419be4, data2[1]); for (i = 0; i < 6; i++) - nv_wr32(priv, 0x419b00 + (i * 4), data[i]); + nvkm_wr32(device, 0x419b00 + (i * 4), data[i]); /* UNK78xx */ - nv_wr32(priv, 0x4078bc, (priv->tpc_total << 8) | - priv->magic_not_rop_nr); + nvkm_wr32(device, 0x4078bc, (gr->tpc_total << 8) | + gr->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(priv, 0x40780c + (i * 4), data[i]); + nvkm_wr32(device, 0x40780c + (i * 4), data[i]); } void -gf100_grctx_generate_r406800(struct gf100_gr_priv *priv) +gf100_grctx_generate_r406800(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; u64 tpc_mask = 0, tpc_set = 0; u8 tpcnr[GPC_MAX]; int gpc, tpc; int i, a, b; - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) - tpc_mask |= ((1ULL << priv->tpc_nr[gpc]) - 1) << (gpc * 8); + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); + for (gpc = 0; gpc < gr->gpc_nr; gpc++) + tpc_mask |= ((1ULL << gr->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (priv->tpc_total - 1)) / 32; + a = (i * (gr->tpc_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; tpc_set |= 1ULL << ((gpc * 8) + tpc); } - nv_wr32(priv, 0x406800 + (i * 0x20), lower_32_bits(tpc_set)); - nv_wr32(priv, 0x406c00 + (i * 0x20), lower_32_bits(tpc_set ^ tpc_mask)); - if (priv->gpc_nr > 4) { - nv_wr32(priv, 0x406804 + (i * 0x20), upper_32_bits(tpc_set)); - nv_wr32(priv, 0x406c04 + (i * 0x20), upper_32_bits(tpc_set ^ tpc_mask)); + nvkm_wr32(device, 0x406800 + (i * 0x20), lower_32_bits(tpc_set)); + nvkm_wr32(device, 0x406c00 + (i * 0x20), lower_32_bits(tpc_set ^ tpc_mask)); + if (gr->gpc_nr > 4) { + nvkm_wr32(device, 0x406804 + (i * 0x20), upper_32_bits(tpc_set)); + nvkm_wr32(device, 0x406c04 + (i * 0x20), upper_32_bits(tpc_set ^ tpc_mask)); } } } void -gf100_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) +gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) { - struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; - - nvkm_mc(priv)->unk260(nvkm_mc(priv), 0); - - gf100_gr_mmio(priv, oclass->hub); - gf100_gr_mmio(priv, oclass->gpc); - gf100_gr_mmio(priv, oclass->zcull); - gf100_gr_mmio(priv, oclass->tpc); - gf100_gr_mmio(priv, oclass->ppc); - - nv_wr32(priv, 0x404154, 0x00000000); - - oclass->bundle(info); - oclass->pagepool(info); - oclass->attrib(info); - oclass->unkn(priv); - - gf100_grctx_generate_tpcid(priv); - gf100_grctx_generate_r406028(priv); - gf100_grctx_generate_r4060a8(priv); - gf100_grctx_generate_r418bb8(priv); - gf100_grctx_generate_r406800(priv); - - gf100_gr_icmd(priv, oclass->icmd); - nv_wr32(priv, 0x404154, 0x00000400); - gf100_gr_mthd(priv, oclass->mthd); - nvkm_mc(priv)->unk260(nvkm_mc(priv), 1); + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; + + nvkm_mc_unk260(device->mc, 0); + + gf100_gr_mmio(gr, grctx->hub); + gf100_gr_mmio(gr, grctx->gpc); + gf100_gr_mmio(gr, grctx->zcull); + gf100_gr_mmio(gr, grctx->tpc); + gf100_gr_mmio(gr, grctx->ppc); + + nvkm_wr32(device, 0x404154, 0x00000000); + + grctx->bundle(info); + grctx->pagepool(info); + grctx->attrib(info); + grctx->unkn(gr); + + gf100_grctx_generate_tpcid(gr); + gf100_grctx_generate_r406028(gr); + gf100_grctx_generate_r4060a8(gr); + gf100_grctx_generate_r418bb8(gr); + gf100_grctx_generate_r406800(gr); + + gf100_gr_icmd(gr, grctx->icmd); + nvkm_wr32(device, 0x404154, 0x00000400); + gf100_gr_mthd(gr, grctx->mthd); + nvkm_mc_unk260(device->mc, 1); } int -gf100_grctx_generate(struct gf100_gr_priv *priv) +gf100_grctx_generate(struct gf100_gr *gr) { - struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; - struct nvkm_bar *bar = nvkm_bar(priv); - struct nvkm_gpuobj *chan; + const struct gf100_grctx_func *grctx = gr->func->grctx; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_memory *chan; struct gf100_grctx info; int ret, i; + u64 addr; /* allocate memory to for a "channel", which we'll use to generate * the default context values */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x80000 + priv->size, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &chan); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x80000 + gr->size, + 0x1000, true, &chan); if (ret) { - nv_error(priv, "failed to allocate channel memory, %d\n", ret); + nvkm_error(subdev, "failed to allocate chan memory, %d\n", ret); return ret; } + addr = nvkm_memory_addr(chan); + /* PGD pointer */ - nv_wo32(chan, 0x0200, lower_32_bits(chan->addr + 0x1000)); - nv_wo32(chan, 0x0204, upper_32_bits(chan->addr + 0x1000)); - nv_wo32(chan, 0x0208, 0xffffffff); - nv_wo32(chan, 0x020c, 0x000000ff); + nvkm_kmap(chan); + nvkm_wo32(chan, 0x0200, lower_32_bits(addr + 0x1000)); + nvkm_wo32(chan, 0x0204, upper_32_bits(addr + 0x1000)); + nvkm_wo32(chan, 0x0208, 0xffffffff); + nvkm_wo32(chan, 0x020c, 0x000000ff); /* PGT[0] pointer */ - nv_wo32(chan, 0x1000, 0x00000000); - nv_wo32(chan, 0x1004, 0x00000001 | (chan->addr + 0x2000) >> 8); + nvkm_wo32(chan, 0x1000, 0x00000000); + nvkm_wo32(chan, 0x1004, 0x00000001 | (addr + 0x2000) >> 8); /* identity-map the whole "channel" into its own vm */ - for (i = 0; i < chan->size / 4096; i++) { - u64 addr = ((chan->addr + (i * 4096)) >> 8) | 1; - nv_wo32(chan, 0x2000 + (i * 8), lower_32_bits(addr)); - nv_wo32(chan, 0x2004 + (i * 8), upper_32_bits(addr)); + for (i = 0; i < nvkm_memory_size(chan) / 4096; i++) { + u64 addr = ((nvkm_memory_addr(chan) + (i * 4096)) >> 8) | 1; + nvkm_wo32(chan, 0x2000 + (i * 8), lower_32_bits(addr)); + nvkm_wo32(chan, 0x2004 + (i * 8), upper_32_bits(addr)); } /* context pointer (virt) */ - nv_wo32(chan, 0x0210, 0x00080004); - nv_wo32(chan, 0x0214, 0x00000000); + nvkm_wo32(chan, 0x0210, 0x00080004); + nvkm_wo32(chan, 0x0214, 0x00000000); + nvkm_done(chan); - bar->flush(bar); - - nv_wr32(priv, 0x100cb8, (chan->addr + 0x1000) >> 8); - nv_wr32(priv, 0x100cbc, 0x80000001); - nv_wait(priv, 0x100c80, 0x00008000, 0x00008000); + nvkm_wr32(device, 0x100cb8, (addr + 0x1000) >> 8); + nvkm_wr32(device, 0x100cbc, 0x80000001); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100c80) & 0x00008000) + break; + ); /* setup default state for mmio list construction */ - info.priv = priv; - info.data = priv->mmio_data; - info.mmio = priv->mmio_list; + info.gr = gr; + info.data = gr->mmio_data; + info.mmio = gr->mmio_list; info.addr = 0x2000 + (i * 8); info.buffer_nr = 0; /* make channel current */ - if (priv->firmware) { - nv_wr32(priv, 0x409840, 0x00000030); - nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); - nv_wr32(priv, 0x409504, 0x00000003); - if (!nv_wait(priv, 0x409800, 0x00000010, 0x00000010)) - nv_error(priv, "load_ctx timeout\n"); - - nv_wo32(chan, 0x8001c, 1); - nv_wo32(chan, 0x80020, 0); - nv_wo32(chan, 0x80028, 0); - nv_wo32(chan, 0x8002c, 0); - bar->flush(bar); + if (gr->firmware) { + nvkm_wr32(device, 0x409840, 0x00000030); + nvkm_wr32(device, 0x409500, 0x80000000 | addr >> 12); + nvkm_wr32(device, 0x409504, 0x00000003); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800) & 0x00000010) + break; + ); + + nvkm_kmap(chan); + nvkm_wo32(chan, 0x8001c, 1); + nvkm_wo32(chan, 0x80020, 0); + nvkm_wo32(chan, 0x80028, 0); + nvkm_wo32(chan, 0x8002c, 0); + nvkm_done(chan); } else { - nv_wr32(priv, 0x409840, 0x80000000); - nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); - nv_wr32(priv, 0x409504, 0x00000001); - if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) - nv_error(priv, "HUB_SET_CHAN timeout\n"); + nvkm_wr32(device, 0x409840, 0x80000000); + nvkm_wr32(device, 0x409500, 0x80000000 | addr >> 12); + nvkm_wr32(device, 0x409504, 0x00000001); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800) & 0x80000000) + break; + ); } - oclass->main(priv, &info); + grctx->main(gr, &info); /* trigger a context unload by unsetting the "next channel valid" bit * and faking a context switch interrupt */ - nv_mask(priv, 0x409b04, 0x80000000, 0x00000000); - nv_wr32(priv, 0x409000, 0x00000100); - if (!nv_wait(priv, 0x409b00, 0x80000000, 0x00000000)) { - nv_error(priv, "grctx template channel unload timeout\n"); + nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000); + nvkm_wr32(device, 0x409000, 0x00000100); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x409b00) & 0x80000000)) + break; + ) < 0) { ret = -EBUSY; goto done; } - priv->data = kmalloc(priv->size, GFP_KERNEL); - if (priv->data) { - for (i = 0; i < priv->size; i += 4) - priv->data[i / 4] = nv_ro32(chan, 0x80000 + i); + gr->data = kmalloc(gr->size, GFP_KERNEL); + if (gr->data) { + nvkm_kmap(chan); + for (i = 0; i < gr->size; i += 4) + gr->data[i / 4] = nvkm_ro32(chan, 0x80000 + i); + nvkm_done(chan); ret = 0; } else { ret = -ENOMEM; } done: - nvkm_gpuobj_ref(NULL, &chan); + nvkm_memory_del(&chan); return ret; } -struct nvkm_oclass * -gf100_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gf100_grctx = { .main = gf100_grctx_generate_main, .unkn = gf100_grctx_generate_unkn, .hub = gf100_grctx_pack_hub, @@ -1387,4 +1400,4 @@ gf100_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib = gf100_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 3676a3342..3c64040ec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -3,7 +3,7 @@ #include "gf100.h" struct gf100_grctx { - struct gf100_gr_priv *priv; + struct gf100_gr *gr; struct gf100_gr_data *data; struct gf100_gr_mmio *mmio; int buffer_nr; @@ -19,12 +19,11 @@ void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int) #define mmio_skip(a,b,c) mmio_refn((a), (b), (c), -1, -1) #define mmio_wr32(a,b,c) mmio_refn((a), (b), (c), 0, -1) -struct gf100_grctx_oclass { - struct nvkm_oclass base; +struct gf100_grctx_func { /* main context generation function */ - void (*main)(struct gf100_gr_priv *, struct gf100_grctx *); + void (*main)(struct gf100_gr *, struct gf100_grctx *); /* context-specific modify-on-first-load list generation function */ - void (*unkn)(struct gf100_gr_priv *); + void (*unkn)(struct gf100_gr *); /* mmio context data */ const struct gf100_gr_pack *hub; const struct gf100_gr_pack *gpc; @@ -50,60 +49,61 @@ struct gf100_grctx_oclass { u32 alpha_nr; }; -static inline const struct gf100_grctx_oclass * -gf100_grctx_impl(struct gf100_gr_priv *priv) -{ - return (void *)nv_engine(priv)->cclass; -} - -extern struct nvkm_oclass *gf100_grctx_oclass; -int gf100_grctx_generate(struct gf100_gr_priv *); -void gf100_grctx_generate_main(struct gf100_gr_priv *, struct gf100_grctx *); +extern const struct gf100_grctx_func gf100_grctx; +int gf100_grctx_generate(struct gf100_gr *); +void gf100_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *); void gf100_grctx_generate_bundle(struct gf100_grctx *); void gf100_grctx_generate_pagepool(struct gf100_grctx *); void gf100_grctx_generate_attrib(struct gf100_grctx *); -void gf100_grctx_generate_unkn(struct gf100_gr_priv *); -void gf100_grctx_generate_tpcid(struct gf100_gr_priv *); -void gf100_grctx_generate_r406028(struct gf100_gr_priv *); -void gf100_grctx_generate_r4060a8(struct gf100_gr_priv *); -void gf100_grctx_generate_r418bb8(struct gf100_gr_priv *); -void gf100_grctx_generate_r406800(struct gf100_gr_priv *); - -extern struct nvkm_oclass *gf108_grctx_oclass; +void gf100_grctx_generate_unkn(struct gf100_gr *); +void gf100_grctx_generate_tpcid(struct gf100_gr *); +void gf100_grctx_generate_r406028(struct gf100_gr *); +void gf100_grctx_generate_r4060a8(struct gf100_gr *); +void gf100_grctx_generate_r418bb8(struct gf100_gr *); +void gf100_grctx_generate_r406800(struct gf100_gr *); + +extern const struct gf100_grctx_func gf108_grctx; void gf108_grctx_generate_attrib(struct gf100_grctx *); -void gf108_grctx_generate_unkn(struct gf100_gr_priv *); +void gf108_grctx_generate_unkn(struct gf100_gr *); -extern struct nvkm_oclass *gf104_grctx_oclass; -extern struct nvkm_oclass *gf110_grctx_oclass; +extern const struct gf100_grctx_func gf104_grctx; +extern const struct gf100_grctx_func gf110_grctx; -extern struct nvkm_oclass *gf117_grctx_oclass; +extern const struct gf100_grctx_func gf117_grctx; void gf117_grctx_generate_attrib(struct gf100_grctx *); -extern struct nvkm_oclass *gf119_grctx_oclass; +extern const struct gf100_grctx_func gf119_grctx; -extern struct nvkm_oclass *gk104_grctx_oclass; -extern struct nvkm_oclass *gk20a_grctx_oclass; -void gk104_grctx_generate_main(struct gf100_gr_priv *, struct gf100_grctx *); +extern const struct gf100_grctx_func gk104_grctx; +extern const struct gf100_grctx_func gk20a_grctx; +void gk104_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *); void gk104_grctx_generate_bundle(struct gf100_grctx *); void gk104_grctx_generate_pagepool(struct gf100_grctx *); -void gk104_grctx_generate_unkn(struct gf100_gr_priv *); -void gk104_grctx_generate_r418bb8(struct gf100_gr_priv *); -void gk104_grctx_generate_rop_active_fbps(struct gf100_gr_priv *); +void gk104_grctx_generate_unkn(struct gf100_gr *); +void gk104_grctx_generate_r418bb8(struct gf100_gr *); +void gk104_grctx_generate_rop_active_fbps(struct gf100_gr *); + +void gm107_grctx_generate_bundle(struct gf100_grctx *); +void gm107_grctx_generate_pagepool(struct gf100_grctx *); +void gm107_grctx_generate_attrib(struct gf100_grctx *); -extern struct nvkm_oclass *gk110_grctx_oclass; -extern struct nvkm_oclass *gk110b_grctx_oclass; -extern struct nvkm_oclass *gk208_grctx_oclass; +extern const struct gf100_grctx_func gk110_grctx; +extern const struct gf100_grctx_func gk110b_grctx; +extern const struct gf100_grctx_func gk208_grctx; -extern struct nvkm_oclass *gm107_grctx_oclass; +extern const struct gf100_grctx_func gm107_grctx; void gm107_grctx_generate_bundle(struct gf100_grctx *); void gm107_grctx_generate_pagepool(struct gf100_grctx *); void gm107_grctx_generate_attrib(struct gf100_grctx *); -extern struct nvkm_oclass *gm204_grctx_oclass; -void gm204_grctx_generate_main(struct gf100_gr_priv *, struct gf100_grctx *); +extern const struct gf100_grctx_func gm204_grctx; +void gm204_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *); +void gm204_grctx_generate_tpcid(struct gf100_gr *); +void gm204_grctx_generate_405b60(struct gf100_gr *); -extern struct nvkm_oclass *gm206_grctx_oclass; +extern const struct gf100_grctx_func gm206_grctx; +extern const struct gf100_grctx_func gm20b_grctx; /* context init value lists */ diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c index c5a8d55e2..54fd74e9c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c @@ -79,17 +79,8 @@ gf104_grctx_pack_tpc[] = { * PGRAPH context implementation ******************************************************************************/ -struct nvkm_oclass * -gf104_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xc3), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gf104_grctx = { .main = gf100_grctx_generate_main, .unkn = gf100_grctx_generate_unkn, .hub = gf100_grctx_pack_hub, @@ -105,4 +96,4 @@ gf104_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib = gf100_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c index 87c844a5f..505cdcbfc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c @@ -730,18 +730,18 @@ gf108_grctx_pack_tpc[] = { void gf108_grctx_generate_attrib(struct gf100_grctx *info) { - struct gf100_gr_priv *priv = info->priv; - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(priv); - const u32 alpha = impl->alpha_nr; - const u32 beta = impl->attrib_nr; - const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max); + struct gf100_gr *gr = info->gr; + const struct gf100_grctx_func *grctx = gr->func->grctx; + const u32 alpha = grctx->alpha_nr; + const u32 beta = grctx->attrib_nr; + const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); const int timeslice_mode = 1; const int max_batches = 0xffff; u32 bo = 0; - u32 ao = bo + impl->attrib_nr_max * priv->tpc_total; + u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; int gpc, tpc; mmio_refn(info, 0x418810, 0x80000000, s, b); @@ -749,43 +749,35 @@ gf108_grctx_generate_attrib(struct gf100_grctx *info) mmio_wr32(info, 0x405830, (beta << 16) | alpha); mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { const u32 a = alpha; const u32 b = beta; const u32 t = timeslice_mode; const u32 o = TPC_UNIT(gpc, tpc, 0x500); mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo); mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo); - bo += impl->attrib_nr_max; + bo += grctx->attrib_nr_max; mmio_wr32(info, o + 0x44, (a << 16) | ao); - ao += impl->alpha_nr_max; + ao += grctx->alpha_nr_max; } } } void -gf108_grctx_generate_unkn(struct gf100_gr_priv *priv) +gf108_grctx_generate_unkn(struct gf100_gr *gr) { - nv_mask(priv, 0x418c6c, 0x00000001, 0x00000001); - nv_mask(priv, 0x41980c, 0x00000010, 0x00000010); - nv_mask(priv, 0x419814, 0x00000004, 0x00000004); - nv_mask(priv, 0x4064c0, 0x80000000, 0x80000000); - nv_mask(priv, 0x405800, 0x08000000, 0x08000000); - nv_mask(priv, 0x419c00, 0x00000008, 0x00000008); + struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_mask(device, 0x418c6c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x41980c, 0x00000010, 0x00000010); + nvkm_mask(device, 0x419814, 0x00000004, 0x00000004); + nvkm_mask(device, 0x4064c0, 0x80000000, 0x80000000); + nvkm_mask(device, 0x405800, 0x08000000, 0x08000000); + nvkm_mask(device, 0x419c00, 0x00000008, 0x00000008); } -struct nvkm_oclass * -gf108_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xc1), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gf108_grctx = { .main = gf100_grctx_generate_main, .unkn = gf108_grctx_generate_unkn, .hub = gf108_grctx_pack_hub, @@ -803,4 +795,4 @@ gf108_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x324, .alpha_nr = 0x218, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c index b3acd931b..7df398b53 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c @@ -330,17 +330,8 @@ gf110_grctx_pack_gpc[] = { * PGRAPH context implementation ******************************************************************************/ -struct nvkm_oclass * -gf110_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xc8), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gf110_grctx = { .main = gf100_grctx_generate_main, .unkn = gf100_grctx_generate_unkn, .hub = gf100_grctx_pack_hub, @@ -356,4 +347,4 @@ gf110_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib = gf100_grctx_generate_attrib, .attrib_nr_max = 0x324, .attrib_nr = 0x218, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c index 9bbe2c975..74de7a96c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c @@ -182,18 +182,18 @@ gf117_grctx_pack_ppc[] = { void gf117_grctx_generate_attrib(struct gf100_grctx *info) { - struct gf100_gr_priv *priv = info->priv; - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(priv); - const u32 alpha = impl->alpha_nr; - const u32 beta = impl->attrib_nr; - const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max); + struct gf100_gr *gr = info->gr; + const struct gf100_grctx_func *grctx = gr->func->grctx; + const u32 alpha = grctx->alpha_nr; + const u32 beta = grctx->attrib_nr; + const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); const int timeslice_mode = 1; const int max_batches = 0xffff; u32 bo = 0; - u32 ao = bo + impl->attrib_nr_max * priv->tpc_total; + u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; int gpc, ppc; mmio_refn(info, 0x418810, 0x80000000, s, b); @@ -201,68 +201,62 @@ gf117_grctx_generate_attrib(struct gf100_grctx *info) mmio_wr32(info, 0x405830, (beta << 16) | alpha); mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) { - const u32 a = alpha * priv->ppc_tpc_nr[gpc][ppc]; - const u32 b = beta * priv->ppc_tpc_nr[gpc][ppc]; + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) { + const u32 a = alpha * gr->ppc_tpc_nr[gpc][ppc]; + const u32 b = beta * gr->ppc_tpc_nr[gpc][ppc]; const u32 t = timeslice_mode; const u32 o = PPC_UNIT(gpc, ppc, 0); + if (!(gr->ppc_mask[gpc] & (1 << ppc))) + continue; mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo); mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo); - bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc]; + bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc]; mmio_wr32(info, o + 0xe4, (a << 16) | ao); - ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc]; + ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; } } } void -gf117_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) +gf117_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) { - struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; int i; - nvkm_mc(priv)->unk260(nvkm_mc(priv), 0); + nvkm_mc_unk260(device->mc, 0); - gf100_gr_mmio(priv, oclass->hub); - gf100_gr_mmio(priv, oclass->gpc); - gf100_gr_mmio(priv, oclass->zcull); - gf100_gr_mmio(priv, oclass->tpc); - gf100_gr_mmio(priv, oclass->ppc); + gf100_gr_mmio(gr, grctx->hub); + gf100_gr_mmio(gr, grctx->gpc); + gf100_gr_mmio(gr, grctx->zcull); + gf100_gr_mmio(gr, grctx->tpc); + gf100_gr_mmio(gr, grctx->ppc); - nv_wr32(priv, 0x404154, 0x00000000); + nvkm_wr32(device, 0x404154, 0x00000000); - oclass->bundle(info); - oclass->pagepool(info); - oclass->attrib(info); - oclass->unkn(priv); + grctx->bundle(info); + grctx->pagepool(info); + grctx->attrib(info); + grctx->unkn(gr); - gf100_grctx_generate_tpcid(priv); - gf100_grctx_generate_r406028(priv); - gf100_grctx_generate_r4060a8(priv); - gk104_grctx_generate_r418bb8(priv); - gf100_grctx_generate_r406800(priv); + gf100_grctx_generate_tpcid(gr); + gf100_grctx_generate_r406028(gr); + gf100_grctx_generate_r4060a8(gr); + gk104_grctx_generate_r418bb8(gr); + gf100_grctx_generate_r406800(gr); for (i = 0; i < 8; i++) - nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); + nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); - gf100_gr_icmd(priv, oclass->icmd); - nv_wr32(priv, 0x404154, 0x00000400); - gf100_gr_mthd(priv, oclass->mthd); - nvkm_mc(priv)->unk260(nvkm_mc(priv), 1); + gf100_gr_icmd(gr, grctx->icmd); + nvkm_wr32(device, 0x404154, 0x00000400); + gf100_gr_mthd(gr, grctx->mthd); + nvkm_mc_unk260(device->mc, 1); } -struct nvkm_oclass * -gf117_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xd7), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gf117_grctx = { .main = gf117_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gf117_grctx_pack_hub, @@ -281,4 +275,4 @@ gf117_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x7ff, .alpha_nr = 0x324, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c index 8d8761443..605185b07 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c @@ -498,17 +498,8 @@ gf119_grctx_pack_tpc[] = { * PGRAPH context implementation ******************************************************************************/ -struct nvkm_oclass * -gf119_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xd9), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gf119_grctx = { .main = gf100_grctx_generate_main, .unkn = gf108_grctx_generate_unkn, .hub = gf119_grctx_pack_hub, @@ -526,4 +517,4 @@ gf119_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x324, .alpha_nr = 0x218, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index b12f6a9fd..a843e3689 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -843,27 +843,27 @@ gk104_grctx_pack_ppc[] = { void gk104_grctx_generate_bundle(struct gf100_grctx *info) { - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); - const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth, - impl->bundle_size / 0x20); - const u32 token_limit = impl->bundle_token_limit; + const struct gf100_grctx_func *grctx = info->gr->func->grctx; + const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, + grctx->bundle_size / 0x20); + const u32 token_limit = grctx->bundle_token_limit; const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, impl->bundle_size, (1 << s), access); + const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); mmio_refn(info, 0x408004, 0x00000000, s, b); - mmio_wr32(info, 0x408008, 0x80000000 | (impl->bundle_size >> s)); + mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); mmio_refn(info, 0x418808, 0x00000000, s, b); - mmio_wr32(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s)); + mmio_wr32(info, 0x41880c, 0x80000000 | (grctx->bundle_size >> s)); mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit); } void gk104_grctx_generate_pagepool(struct gf100_grctx *info) { - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); + const struct gf100_grctx_func *grctx = info->gr->func->grctx; const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); @@ -872,31 +872,33 @@ gk104_grctx_generate_pagepool(struct gf100_grctx *info) } void -gk104_grctx_generate_unkn(struct gf100_gr_priv *priv) +gk104_grctx_generate_unkn(struct gf100_gr *gr) { - nv_mask(priv, 0x418c6c, 0x00000001, 0x00000001); - nv_mask(priv, 0x41980c, 0x00000010, 0x00000010); - nv_mask(priv, 0x41be08, 0x00000004, 0x00000004); - nv_mask(priv, 0x4064c0, 0x80000000, 0x80000000); - nv_mask(priv, 0x405800, 0x08000000, 0x08000000); - nv_mask(priv, 0x419c00, 0x00000008, 0x00000008); + struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_mask(device, 0x418c6c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x41980c, 0x00000010, 0x00000010); + nvkm_mask(device, 0x41be08, 0x00000004, 0x00000004); + nvkm_mask(device, 0x4064c0, 0x80000000, 0x80000000); + nvkm_mask(device, 0x405800, 0x08000000, 0x08000000); + nvkm_mask(device, 0x419c00, 0x00000008, 0x00000008); } void -gk104_grctx_generate_r418bb8(struct gf100_gr_priv *priv) +gk104_grctx_generate_r418bb8(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; u32 data[6] = {}, data2[2] = {}; u8 tpcnr[GPC_MAX]; u8 shift, ntpcv; int gpc, tpc, i; /* calculate first set of magics */ - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < priv->tpc_total; tpc++) { + for (tpc = 0; tpc < gr->tpc_total; tpc++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -908,7 +910,7 @@ gk104_grctx_generate_r418bb8(struct gf100_gr_priv *priv) /* and the second... */ shift = 0; - ntpcv = priv->tpc_total; + ntpcv = gr->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -921,86 +923,79 @@ gk104_grctx_generate_r418bb8(struct gf100_gr_priv *priv) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* GPC_BROADCAST */ - nv_wr32(priv, 0x418bb8, (priv->tpc_total << 8) | - priv->magic_not_rop_nr); + nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) | + gr->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(priv, 0x418b08 + (i * 4), data[i]); + nvkm_wr32(device, 0x418b08 + (i * 4), data[i]); /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(priv, 0x41bfd0, (priv->tpc_total << 8) | - priv->magic_not_rop_nr | data2[0]); - nv_wr32(priv, 0x41bfe4, data2[1]); + nvkm_wr32(device, 0x41bfd0, (gr->tpc_total << 8) | + gr->magic_not_rop_nr | data2[0]); + nvkm_wr32(device, 0x41bfe4, data2[1]); for (i = 0; i < 6; i++) - nv_wr32(priv, 0x41bf00 + (i * 4), data[i]); + nvkm_wr32(device, 0x41bf00 + (i * 4), data[i]); /* UNK78xx */ - nv_wr32(priv, 0x4078bc, (priv->tpc_total << 8) | - priv->magic_not_rop_nr); + nvkm_wr32(device, 0x4078bc, (gr->tpc_total << 8) | + gr->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(priv, 0x40780c + (i * 4), data[i]); + nvkm_wr32(device, 0x40780c + (i * 4), data[i]); } void -gk104_grctx_generate_rop_active_fbps(struct gf100_gr_priv *priv) +gk104_grctx_generate_rop_active_fbps(struct gf100_gr *gr) { - const u32 fbp_count = nv_rd32(priv, 0x120074); - nv_mask(priv, 0x408850, 0x0000000f, fbp_count); /* zrop */ - nv_mask(priv, 0x408958, 0x0000000f, fbp_count); /* crop */ + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 fbp_count = nvkm_rd32(device, 0x120074); + nvkm_mask(device, 0x408850, 0x0000000f, fbp_count); /* zrop */ + nvkm_mask(device, 0x408958, 0x0000000f, fbp_count); /* crop */ } void -gk104_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) +gk104_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) { - struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; int i; - nvkm_mc(priv)->unk260(nvkm_mc(priv), 0); + nvkm_mc_unk260(device->mc, 0); - gf100_gr_mmio(priv, oclass->hub); - gf100_gr_mmio(priv, oclass->gpc); - gf100_gr_mmio(priv, oclass->zcull); - gf100_gr_mmio(priv, oclass->tpc); - gf100_gr_mmio(priv, oclass->ppc); + gf100_gr_mmio(gr, grctx->hub); + gf100_gr_mmio(gr, grctx->gpc); + gf100_gr_mmio(gr, grctx->zcull); + gf100_gr_mmio(gr, grctx->tpc); + gf100_gr_mmio(gr, grctx->ppc); - nv_wr32(priv, 0x404154, 0x00000000); + nvkm_wr32(device, 0x404154, 0x00000000); - oclass->bundle(info); - oclass->pagepool(info); - oclass->attrib(info); - oclass->unkn(priv); + grctx->bundle(info); + grctx->pagepool(info); + grctx->attrib(info); + grctx->unkn(gr); - gf100_grctx_generate_tpcid(priv); - gf100_grctx_generate_r406028(priv); - gk104_grctx_generate_r418bb8(priv); - gf100_grctx_generate_r406800(priv); + gf100_grctx_generate_tpcid(gr); + gf100_grctx_generate_r406028(gr); + gk104_grctx_generate_r418bb8(gr); + gf100_grctx_generate_r406800(gr); for (i = 0; i < 8; i++) - nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); + nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); - nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); - gk104_grctx_generate_rop_active_fbps(priv); - nv_mask(priv, 0x419f78, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr); + gk104_grctx_generate_rop_active_fbps(gr); + nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000); - gf100_gr_icmd(priv, oclass->icmd); - nv_wr32(priv, 0x404154, 0x00000400); - gf100_gr_mthd(priv, oclass->mthd); - nvkm_mc(priv)->unk260(nvkm_mc(priv), 1); + gf100_gr_icmd(gr, grctx->icmd); + nvkm_wr32(device, 0x404154, 0x00000400); + gf100_gr_mthd(gr, grctx->mthd); + nvkm_mc_unk260(device->mc, 1); - nv_mask(priv, 0x418800, 0x00200000, 0x00200000); - nv_mask(priv, 0x41be10, 0x00800000, 0x00800000); + nvkm_mask(device, 0x418800, 0x00200000, 0x00200000); + nvkm_mask(device, 0x41be10, 0x00800000, 0x00800000); } -struct nvkm_oclass * -gk104_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xe4), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gk104_grctx = { .main = gk104_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gk104_grctx_pack_hub, @@ -1021,4 +1016,4 @@ gk104_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x7ff, .alpha_nr = 0x648, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c index b3f58be04..7b95ec2fe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c @@ -808,17 +808,8 @@ gk110_grctx_pack_ppc[] = { * PGRAPH context implementation ******************************************************************************/ -struct nvkm_oclass * -gk110_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xf0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gk110_grctx = { .main = gk104_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gk110_grctx_pack_hub, @@ -839,4 +830,4 @@ gk110_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x7ff, .alpha_nr = 0x648, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c index b11c26794..048b1152d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c @@ -69,17 +69,8 @@ gk110b_grctx_pack_tpc[] = { * PGRAPH context implementation ******************************************************************************/ -struct nvkm_oclass * -gk110b_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xf1), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gk110b_grctx = { .main = gk104_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gk110_grctx_pack_hub, @@ -100,4 +91,4 @@ gk110b_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x7ff, .alpha_nr = 0x648, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c index 6e8ce9fc3..67b7a1b43 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c @@ -530,17 +530,8 @@ gk208_grctx_pack_ppc[] = { * PGRAPH context implementation ******************************************************************************/ -struct nvkm_oclass * -gk208_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0x08), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gk208_grctx = { .main = gk104_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gk208_grctx_pack_hub, @@ -561,4 +552,4 @@ gk208_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x218, .alpha_nr_max = 0x7ff, .alpha_nr = 0x648, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c index 2f241f6f0..ddaa16a71 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,34 +20,60 @@ * DEALINGS IN THE SOFTWARE. */ #include "ctxgf100.h" +#include "gf100.h" -static const struct gf100_gr_pack -gk20a_grctx_pack_mthd[] = { - { gk104_grctx_init_a097_0, 0xa297 }, - { gf100_grctx_init_902d_0, 0x902d }, - {} -}; +#include + +static void +gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; + int idle_timeout_save; + int i; + + gf100_gr_mmio(gr, gr->fuc_sw_ctx); + + gf100_gr_wait_idle(gr); + + idle_timeout_save = nvkm_rd32(device, 0x404154); + nvkm_wr32(device, 0x404154, 0x00000000); + + grctx->attrib(info); + + grctx->unkn(gr); + + gf100_grctx_generate_tpcid(gr); + gf100_grctx_generate_r406028(gr); + gk104_grctx_generate_r418bb8(gr); + gf100_grctx_generate_r406800(gr); + + for (i = 0; i < 8; i++) + nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); -struct nvkm_oclass * -gk20a_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, - .main = gk104_grctx_generate_main, + nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr); + + gk104_grctx_generate_rop_active_fbps(gr); + + nvkm_mask(device, 0x5044b0, 0x8000000, 0x8000000); + + gf100_gr_wait_idle(gr); + + nvkm_wr32(device, 0x404154, idle_timeout_save); + gf100_gr_wait_idle(gr); + + gf100_gr_mthd(gr, gr->fuc_method); + gf100_gr_wait_idle(gr); + + gf100_gr_icmd(gr, gr->fuc_bundle); + grctx->pagepool(info); + grctx->bundle(info); +} + +const struct gf100_grctx_func +gk20a_grctx = { + .main = gk20a_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, - .hub = gk104_grctx_pack_hub, - .gpc = gk104_grctx_pack_gpc, - .zcull = gf100_grctx_pack_zcull, - .tpc = gk104_grctx_pack_tpc, - .ppc = gk104_grctx_pack_ppc, - .icmd = gk104_grctx_pack_icmd, - .mthd = gk20a_grctx_pack_mthd, .bundle = gk104_grctx_generate_bundle, .bundle_size = 0x1800, .bundle_min_gpm_fifo_depth = 0x62, @@ -59,4 +85,4 @@ gk20a_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x240, .alpha_nr_max = 0x648 + (0x648 / 2), .alpha_nr = 0x648, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index fbeaae3ae..95f59e316 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -863,27 +863,27 @@ gm107_grctx_pack_ppc[] = { void gm107_grctx_generate_bundle(struct gf100_grctx *info) { - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); - const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth, - impl->bundle_size / 0x20); - const u32 token_limit = impl->bundle_token_limit; + const struct gf100_grctx_func *grctx = info->gr->func->grctx; + const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, + grctx->bundle_size / 0x20); + const u32 token_limit = grctx->bundle_token_limit; const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, impl->bundle_size, (1 << s), access); + const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); mmio_refn(info, 0x408004, 0x00000000, s, b); - mmio_wr32(info, 0x408008, 0x80000000 | (impl->bundle_size >> s)); + mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); mmio_refn(info, 0x418e24, 0x00000000, s, b); - mmio_wr32(info, 0x418e28, 0x80000000 | (impl->bundle_size >> s)); + mmio_wr32(info, 0x418e28, 0x80000000 | (grctx->bundle_size >> s)); mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit); } void gm107_grctx_generate_pagepool(struct gf100_grctx *info) { - const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); + const struct gf100_grctx_func *grctx = info->gr->func->grctx; const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); @@ -895,17 +895,17 @@ gm107_grctx_generate_pagepool(struct gf100_grctx *info) void gm107_grctx_generate_attrib(struct gf100_grctx *info) { - struct gf100_gr_priv *priv = info->priv; - const struct gf100_grctx_oclass *impl = (void *)gf100_grctx_impl(priv); - const u32 alpha = impl->alpha_nr; - const u32 attrib = impl->attrib_nr; - const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max); + struct gf100_gr *gr = info->gr; + const struct gf100_grctx_func *grctx = gr->func->grctx; + const u32 alpha = grctx->alpha_nr; + const u32 attrib = grctx->attrib_nr; + const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); const int max_batches = 0xffff; u32 bo = 0; - u32 ao = bo + impl->attrib_nr_max * priv->tpc_total; + u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; int gpc, ppc, n = 0; mmio_refn(info, 0x418810, 0x80000000, s, b); @@ -914,97 +914,90 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info) mmio_wr32(info, 0x405830, (attrib << 16) | alpha); mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++, n++) { - const u32 as = alpha * priv->ppc_tpc_nr[gpc][ppc]; - const u32 bs = attrib * priv->ppc_tpc_nr[gpc][ppc]; + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { + const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; + const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc]; const u32 u = 0x418ea0 + (n * 0x04); const u32 o = PPC_UNIT(gpc, ppc, 0); mmio_wr32(info, o + 0xc0, bs); mmio_wr32(info, o + 0xf4, bo); - bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc]; + bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc]; mmio_wr32(info, o + 0xe4, as); mmio_wr32(info, o + 0xf8, ao); - ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc]; + ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc]; mmio_wr32(info, u, ((bs / 3 /*XXX*/) << 16) | bs); } } } -static void -gm107_grctx_generate_tpcid(struct gf100_gr_priv *priv) +void +gm107_grctx_generate_tpcid(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; int gpc, tpc, id; for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tpc < priv->tpc_nr[gpc]) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + if (tpc < gr->tpc_nr[gpc]) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x698), id); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), id); id++; } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c08), gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c8c), gr->tpc_nr[gpc]); } } } static void -gm107_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) +gm107_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) { - struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; int i; - gf100_gr_mmio(priv, oclass->hub); - gf100_gr_mmio(priv, oclass->gpc); - gf100_gr_mmio(priv, oclass->zcull); - gf100_gr_mmio(priv, oclass->tpc); - gf100_gr_mmio(priv, oclass->ppc); + gf100_gr_mmio(gr, grctx->hub); + gf100_gr_mmio(gr, grctx->gpc); + gf100_gr_mmio(gr, grctx->zcull); + gf100_gr_mmio(gr, grctx->tpc); + gf100_gr_mmio(gr, grctx->ppc); - nv_wr32(priv, 0x404154, 0x00000000); + nvkm_wr32(device, 0x404154, 0x00000000); - oclass->bundle(info); - oclass->pagepool(info); - oclass->attrib(info); - oclass->unkn(priv); + grctx->bundle(info); + grctx->pagepool(info); + grctx->attrib(info); + grctx->unkn(gr); - gm107_grctx_generate_tpcid(priv); - gf100_grctx_generate_r406028(priv); - gk104_grctx_generate_r418bb8(priv); - gf100_grctx_generate_r406800(priv); + gm107_grctx_generate_tpcid(gr); + gf100_grctx_generate_r406028(gr); + gk104_grctx_generate_r418bb8(gr); + gf100_grctx_generate_r406800(gr); - nv_wr32(priv, 0x4064d0, 0x00000001); + nvkm_wr32(device, 0x4064d0, 0x00000001); for (i = 1; i < 8; i++) - nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); - nv_wr32(priv, 0x406500, 0x00000001); + nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); + nvkm_wr32(device, 0x406500, 0x00000001); - nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); + nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr); - gk104_grctx_generate_rop_active_fbps(priv); + gk104_grctx_generate_rop_active_fbps(gr); - gf100_gr_icmd(priv, oclass->icmd); - nv_wr32(priv, 0x404154, 0x00000400); - gf100_gr_mthd(priv, oclass->mthd); + gf100_gr_icmd(gr, grctx->icmd); + nvkm_wr32(device, 0x404154, 0x00000400); + gf100_gr_mthd(gr, grctx->mthd); - nv_mask(priv, 0x419e00, 0x00808080, 0x00808080); - nv_mask(priv, 0x419ccc, 0x80000000, 0x80000000); - nv_mask(priv, 0x419f80, 0x80000000, 0x80000000); - nv_mask(priv, 0x419f88, 0x80000000, 0x80000000); + nvkm_mask(device, 0x419e00, 0x00808080, 0x00808080); + nvkm_mask(device, 0x419ccc, 0x80000000, 0x80000000); + nvkm_mask(device, 0x419f80, 0x80000000, 0x80000000); + nvkm_mask(device, 0x419f88, 0x80000000, 0x80000000); } -struct nvkm_oclass * -gm107_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0x08), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gm107_grctx = { .main = gm107_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gm107_grctx_pack_hub, @@ -1025,4 +1018,4 @@ gm107_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0xaa0, .alpha_nr_max = 0x1800, .alpha_nr = 0x1000, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c index ea8e66151..170cbfdbe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c @@ -918,17 +918,18 @@ gm204_grctx_pack_ppc[] = { * PGRAPH context implementation ******************************************************************************/ -static void -gm204_grctx_generate_tpcid(struct gf100_gr_priv *priv) +void +gm204_grctx_generate_tpcid(struct gf100_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; int gpc, tpc, id; for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tpc < priv->tpc_nr[gpc]) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + if (tpc < gr->tpc_nr[gpc]) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x698), id); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), id); id++; } } @@ -936,101 +937,95 @@ gm204_grctx_generate_tpcid(struct gf100_gr_priv *priv) } static void -gm204_grctx_generate_rop_active_fbps(struct gf100_gr_priv *priv) +gm204_grctx_generate_rop_active_fbps(struct gf100_gr *gr) { - const u32 fbp_count = nv_rd32(priv, 0x12006c); - nv_mask(priv, 0x408850, 0x0000000f, fbp_count); /* zrop */ - nv_mask(priv, 0x408958, 0x0000000f, fbp_count); /* crop */ + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 fbp_count = nvkm_rd32(device, 0x12006c); + nvkm_mask(device, 0x408850, 0x0000000f, fbp_count); /* zrop */ + nvkm_mask(device, 0x408958, 0x0000000f, fbp_count); /* crop */ } -static void -gm204_grctx_generate_405b60(struct gf100_gr_priv *priv) +void +gm204_grctx_generate_405b60(struct gf100_gr *gr) { - const u32 dist_nr = DIV_ROUND_UP(priv->tpc_total, 4); - u32 dist[TPC_MAX] = {}; + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 dist_nr = DIV_ROUND_UP(gr->tpc_total, 4); + u32 dist[TPC_MAX / 4] = {}; u32 gpcs[GPC_MAX] = {}; u8 tpcnr[GPC_MAX]; int tpc, gpc, i; - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); /* won't result in the same distribution as the binary driver where * some of the gpcs have more tpcs than others, but this shall do * for the moment. the code for earlier gpus has this issue too. */ - for (gpc = -1, i = 0; i < priv->tpc_total; i++) { + for (gpc = -1, i = 0; i < gr->tpc_total; i++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while(!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; dist[i / 4] |= ((gpc << 4) | tpc) << ((i % 4) * 8); gpcs[gpc] |= i << (tpc * 8); } for (i = 0; i < dist_nr; i++) - nv_wr32(priv, 0x405b60 + (i * 4), dist[i]); - for (i = 0; i < priv->gpc_nr; i++) - nv_wr32(priv, 0x405ba0 + (i * 4), gpcs[i]); + nvkm_wr32(device, 0x405b60 + (i * 4), dist[i]); + for (i = 0; i < gr->gpc_nr; i++) + nvkm_wr32(device, 0x405ba0 + (i * 4), gpcs[i]); } void -gm204_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) +gm204_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) { - struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; u32 tmp; int i; - gf100_gr_mmio(priv, oclass->hub); - gf100_gr_mmio(priv, oclass->gpc); - gf100_gr_mmio(priv, oclass->zcull); - gf100_gr_mmio(priv, oclass->tpc); - gf100_gr_mmio(priv, oclass->ppc); + gf100_gr_mmio(gr, grctx->hub); + gf100_gr_mmio(gr, grctx->gpc); + gf100_gr_mmio(gr, grctx->zcull); + gf100_gr_mmio(gr, grctx->tpc); + gf100_gr_mmio(gr, grctx->ppc); - nv_wr32(priv, 0x404154, 0x00000000); + nvkm_wr32(device, 0x404154, 0x00000000); - oclass->bundle(info); - oclass->pagepool(info); - oclass->attrib(info); - oclass->unkn(priv); + grctx->bundle(info); + grctx->pagepool(info); + grctx->attrib(info); + grctx->unkn(gr); - gm204_grctx_generate_tpcid(priv); - gf100_grctx_generate_r406028(priv); - gk104_grctx_generate_r418bb8(priv); + gm204_grctx_generate_tpcid(gr); + gf100_grctx_generate_r406028(gr); + gk104_grctx_generate_r418bb8(gr); for (i = 0; i < 8; i++) - nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); - nv_wr32(priv, 0x406500, 0x00000000); + nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); + nvkm_wr32(device, 0x406500, 0x00000000); - nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); + nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr); - gm204_grctx_generate_rop_active_fbps(priv); + gm204_grctx_generate_rop_active_fbps(gr); - for (tmp = 0, i = 0; i < priv->gpc_nr; i++) - tmp |= ((1 << priv->tpc_nr[i]) - 1) << (i * 4); - nv_wr32(priv, 0x4041c4, tmp); + for (tmp = 0, i = 0; i < gr->gpc_nr; i++) + tmp |= ((1 << gr->tpc_nr[i]) - 1) << (i * 4); + nvkm_wr32(device, 0x4041c4, tmp); - gm204_grctx_generate_405b60(priv); + gm204_grctx_generate_405b60(gr); - gf100_gr_icmd(priv, oclass->icmd); - nv_wr32(priv, 0x404154, 0x00000800); - gf100_gr_mthd(priv, oclass->mthd); + gf100_gr_icmd(gr, grctx->icmd); + nvkm_wr32(device, 0x404154, 0x00000800); + gf100_gr_mthd(gr, grctx->mthd); - nv_mask(priv, 0x418e94, 0xffffffff, 0xc4230000); - nv_mask(priv, 0x418e4c, 0xffffffff, 0x70000000); + nvkm_mask(device, 0x418e94, 0xffffffff, 0xc4230000); + nvkm_mask(device, 0x418e4c, 0xffffffff, 0x70000000); } -struct nvkm_oclass * -gm204_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0x24), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gm204_grctx = { .main = gm204_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gm204_grctx_pack_hub, @@ -1051,4 +1046,4 @@ gm204_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x400, .alpha_nr_max = 0x1800, .alpha_nr = 0x1000, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c index 91ec41617..d6be6034c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c @@ -49,17 +49,8 @@ gm206_grctx_pack_gpc[] = { {} }; -struct nvkm_oclass * -gm206_grctx_oclass = &(struct gf100_grctx_oclass) { - .base.handle = NV_ENGCTX(GR, 0x26), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_context_ctor, - .dtor = gf100_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +const struct gf100_grctx_func +gm206_grctx = { .main = gm204_grctx_generate_main, .unkn = gk104_grctx_generate_unkn, .hub = gm204_grctx_pack_hub, @@ -80,4 +71,4 @@ gm206_grctx_oclass = &(struct gf100_grctx_oclass) { .attrib_nr = 0x400, .alpha_nr_max = 0x1800, .alpha_nr = 0x1000, -}.base; +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c new file mode 100644 index 000000000..670260402 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * 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 AUTHORS OR COPYRIGHT HOLDERS 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 "ctxgf100.h" + +static void +gm20b_grctx_generate_r406028(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + u32 tpc_per_gpc = 0; + int i; + + for (i = 0; i < gr->gpc_nr; i++) + tpc_per_gpc |= gr->tpc_nr[i] << (4 * i); + + nvkm_wr32(device, 0x406028, tpc_per_gpc); + nvkm_wr32(device, 0x405870, tpc_per_gpc); +} + +static void +gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + const struct gf100_grctx_func *grctx = gr->func->grctx; + int idle_timeout_save; + int i, tmp; + + gf100_gr_mmio(gr, gr->fuc_sw_ctx); + + gf100_gr_wait_idle(gr); + + idle_timeout_save = nvkm_rd32(device, 0x404154); + nvkm_wr32(device, 0x404154, 0x00000000); + + grctx->attrib(info); + + grctx->unkn(gr); + + gm204_grctx_generate_tpcid(gr); + gm20b_grctx_generate_r406028(gr); + gk104_grctx_generate_r418bb8(gr); + + for (i = 0; i < 8; i++) + nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000); + + nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr); + + gk104_grctx_generate_rop_active_fbps(gr); + nvkm_wr32(device, 0x408908, nvkm_rd32(device, 0x410108) | 0x80000000); + + for (tmp = 0, i = 0; i < gr->gpc_nr; i++) + tmp |= ((1 << gr->tpc_nr[i]) - 1) << (i * 4); + nvkm_wr32(device, 0x4041c4, tmp); + + gm204_grctx_generate_405b60(gr); + + gf100_gr_wait_idle(gr); + + nvkm_wr32(device, 0x404154, idle_timeout_save); + gf100_gr_wait_idle(gr); + + gf100_gr_mthd(gr, gr->fuc_method); + gf100_gr_wait_idle(gr); + + gf100_gr_icmd(gr, gr->fuc_bundle); + grctx->pagepool(info); + grctx->bundle(info); +} + +const struct gf100_grctx_func +gm20b_grctx = { + .main = gm20b_grctx_generate_main, + .unkn = gk104_grctx_generate_unkn, + .bundle = gm107_grctx_generate_bundle, + .bundle_size = 0x1800, + .bundle_min_gpm_fifo_depth = 0x182, + .bundle_token_limit = 0x1c0, + .pagepool = gm107_grctx_generate_pagepool, + .pagepool_size = 0x8000, + .attrib = gm107_grctx_generate_attrib, + .attrib_nr_max = 0x600, + .attrib_nr = 0x400, + .alpha_nr_max = 0xc00, + .alpha_nr = 0x800, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.c index dc31462af..80a6b017a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.c @@ -111,7 +111,6 @@ #include "ctxnv40.h" #include "nv40.h" -#include /* TODO: * - get vs count from 0x1540 @@ -583,13 +582,13 @@ nv40_gr_construct_shader(struct nvkm_grctx *ctx) offset += 0x0280/4; for (i = 0; i < 16; i++, offset += 2) - nv_wo32(obj, offset * 4, 0x3f800000); + nvkm_wo32(obj, offset * 4, 0x3f800000); for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { for (i = 0; i < vs_nr_b0 * 6; i += 6) - nv_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001); + nvkm_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001); for (i = 0; i < vs_nr_b1 * 4; i += 4) - nv_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000); + nvkm_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000); } } @@ -675,7 +674,7 @@ nv40_grctx_init(struct nvkm_device *device, u32 *size) struct nvkm_grctx ctx = { .device = device, .mode = NVKM_GRCTX_PROG, - .data = ctxprog, + .ucode = ctxprog, .ctxprog_max = 256, }; @@ -684,9 +683,9 @@ nv40_grctx_init(struct nvkm_device *device, u32 *size) nv40_grctx_generate(&ctx); - nv_wr32(device, 0x400324, 0); + nvkm_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) - nv_wr32(device, 0x400328, ctxprog[i]); + nvkm_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; kfree(ctxprog); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h index 8a8996195..50e808e9f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h @@ -9,7 +9,8 @@ struct nvkm_grctx { NVKM_GRCTX_PROG, NVKM_GRCTX_VALS } mode; - void *data; + u32 *ucode; + struct nvkm_gpuobj *data; u32 ctxprog_max; u32 ctxprog_len; @@ -22,7 +23,7 @@ struct nvkm_grctx { static inline void cp_out(struct nvkm_grctx *ctx, u32 inst) { - u32 *ctxprog = ctx->data; + u32 *ctxprog = ctx->ucode; if (ctx->mode != NVKM_GRCTX_PROG) return; @@ -56,7 +57,7 @@ cp_ctx(struct nvkm_grctx *ctx, u32 reg, u32 length) static inline void cp_name(struct nvkm_grctx *ctx, int name) { - u32 *ctxprog = ctx->data; + u32 *ctxprog = ctx->ucode; int i; if (ctx->mode != NVKM_GRCTX_PROG) @@ -124,6 +125,6 @@ gr_def(struct nvkm_grctx *ctx, u32 reg, u32 val) reg = (reg - 0x00400000) / 4; reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; - nv_wo32(ctx->data, reg * 4, val); + nvkm_wo32(ctx->data, reg * 4, val); } #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c index 9c9528d2c..1e13278cf 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c @@ -107,7 +107,6 @@ #include "ctxnv40.h" -#include #include #define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) @@ -269,7 +268,7 @@ nv50_grctx_init(struct nvkm_device *device, u32 *size) struct nvkm_grctx ctx = { .device = device, .mode = NVKM_GRCTX_PROG, - .data = ctxprog, + .ucode = ctxprog, .ctxprog_max = 512, }; @@ -277,9 +276,9 @@ nv50_grctx_init(struct nvkm_device *device, u32 *size) return -ENOMEM; nv50_grctx_generate(&ctx); - nv_wr32(device, 0x400324, 0); + nvkm_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) - nv_wr32(device, 0x400328, ctxprog[i]); + nvkm_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; kfree(ctxprog); return 0; @@ -299,7 +298,7 @@ nv50_gr_construct_mmio(struct nvkm_grctx *ctx) struct nvkm_device *device = ctx->device; int i, j; int offset, base; - u32 units = nv_rd32 (ctx->device, 0x1540); + u32 units = nvkm_rd32(device, 0x1540); /* 0800: DISPATCH */ cp_ctx(ctx, 0x400808, 7); @@ -570,7 +569,7 @@ nv50_gr_construct_mmio(struct nvkm_grctx *ctx) else if (device->chipset < 0xa0) gr_def(ctx, 0x407d08, 0x00390040); else { - if (nvkm_fb(device)->ram->type != NV_MEM_TYPE_GDDR5) + if (device->fb->ram->type != NVKM_RAM_TYPE_GDDR5) gr_def(ctx, 0x407d08, 0x003d0040); else gr_def(ctx, 0x407d08, 0x003c0040); @@ -784,9 +783,10 @@ nv50_gr_construct_mmio(struct nvkm_grctx *ctx) static void dd_emit(struct nvkm_grctx *ctx, int num, u32 val) { int i; - if (val && ctx->mode == NVKM_GRCTX_VALS) + if (val && ctx->mode == NVKM_GRCTX_VALS) { for (i = 0; i < num; i++) - nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + i), val); + nvkm_wo32(ctx->data, 4 * (ctx->ctxvals_pos + i), val); + } ctx->ctxvals_pos += num; } @@ -1156,9 +1156,10 @@ nv50_gr_construct_mmio_ddata(struct nvkm_grctx *ctx) static void xf_emit(struct nvkm_grctx *ctx, int num, u32 val) { int i; - if (val && ctx->mode == NVKM_GRCTX_VALS) + if (val && ctx->mode == NVKM_GRCTX_VALS) { for (i = 0; i < num; i++) - nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val); + nvkm_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val); + } ctx->ctxvals_pos += num << 3; } @@ -1190,7 +1191,7 @@ nv50_gr_construct_xfer1(struct nvkm_grctx *ctx) int i; int offset; int size = 0; - u32 units = nv_rd32 (ctx->device, 0x1540); + u32 units = nvkm_rd32(device, 0x1540); offset = (ctx->ctxvals_pos+0x3f)&~0x3f; ctx->ctxvals_base = offset; @@ -3273,7 +3274,7 @@ nv50_gr_construct_xfer2(struct nvkm_grctx *ctx) struct nvkm_device *device = ctx->device; int i; u32 offset; - u32 units = nv_rd32 (ctx->device, 0x1540); + u32 units = nvkm_rd32(device, 0x1540); int size = 0; offset = (ctx->ctxvals_pos+0x3f)&~0x3f; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc index 194afe910..7dacb3cc0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc @@ -52,10 +52,12 @@ mmio_list_base: #endif #ifdef INCLUDE_CODE +#define gpc_addr(reg,addr) /* +*/ imm32(reg,addr) /* +*/ or reg NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE #define gpc_wr32(addr,reg) /* +*/ gpc_addr($r14,addr) /* */ mov b32 $r15 reg /* -*/ imm32($r14, addr) /* -*/ or $r14 NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE /* */ call(nv_wr32) // reports an exception to the host @@ -161,7 +163,7 @@ init: #if NV_PGRAPH_GPCX_UNK__SIZE > 0 // figure out which, and how many, UNKs are actually present - imm32($r14, 0x500c30) + gpc_addr($r14, 0x500c30) clear b32 $r2 clear b32 $r3 clear b32 $r4 diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h index 64d07df4b..bb820ff28 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h @@ -314,7 +314,7 @@ uint32_t gf117_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe0542, + 0x10fe0545, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -338,184 +338,184 @@ uint32_t gf117_grgpc_code[] = { 0x02d00103, 0xf104bd00, 0xf00c30e7, - 0x24bd50e3, - 0x44bd34bd, -/* 0x0430: init_unk_loop */ - 0xb06821f4, - 0x0bf400f6, - 0x01f7f00f, - 0xfd04f2bb, - 0x30b6054f, -/* 0x0445: init_unk_next */ - 0x0120b601, - 0xb004e0b6, - 0x1bf40126, -/* 0x0451: init_unk_done */ - 0x070380e2, - 0xf1080480, - 0xf0010027, - 0x22cf0223, - 0x9534bd00, - 0x07f10825, - 0x03f0c000, - 0x0005d001, - 0x07f104bd, - 0x03f0c100, - 0x0005d001, - 0x0e9804bd, - 0x010f9800, - 0x015021f5, - 0xbb002fbb, - 0x0e98003f, - 0x020f9801, - 0x015021f5, - 0xfd050e98, - 0x2ebb00ef, - 0x003ebb00, - 0x98020e98, - 0x21f5030f, - 0x0e980150, - 0x00effd07, - 0xbb002ebb, - 0x35b6003e, - 0x0007f102, - 0x0103f0d3, - 0xbd0003d0, - 0x0825b604, - 0xb60635b6, - 0x30b60120, - 0x0824b601, - 0xb90834b6, - 0x21f5022f, - 0x2fbb02d3, - 0x003fbb00, - 0x010007f1, - 0xd00203f0, + 0xe5f050e3, + 0xbd24bd01, +/* 0x0433: init_unk_loop */ + 0xf444bd34, + 0xf6b06821, + 0x0f0bf400, + 0xbb01f7f0, + 0x4ffd04f2, + 0x0130b605, +/* 0x0448: init_unk_next */ + 0xb60120b6, + 0x26b004e0, + 0xe21bf401, +/* 0x0454: init_unk_done */ + 0x80070380, + 0x27f10804, + 0x23f00100, + 0x0022cf02, + 0x259534bd, + 0x0007f108, + 0x0103f0c0, + 0xbd0005d0, + 0x0007f104, + 0x0103f0c1, + 0xbd0005d0, + 0x000e9804, + 0xf5010f98, + 0xbb015021, + 0x3fbb002f, + 0x010e9800, + 0xf5020f98, + 0x98015021, + 0xeffd050e, + 0x002ebb00, + 0x98003ebb, + 0x0f98020e, + 0x5021f503, + 0x070e9801, + 0xbb00effd, + 0x3ebb002e, + 0x0235b600, + 0xd30007f1, + 0xd00103f0, 0x04bd0003, - 0x29f024bd, - 0x0007f11f, - 0x0203f008, - 0xbd0002d0, -/* 0x0505: main */ - 0x0031f404, - 0xf00028f4, - 0x21f424d7, - 0xf401f439, - 0xf404e4b0, - 0x81fe1e18, - 0x0627f001, - 0x12fd20bd, - 0x01e4b604, - 0xfe051efd, - 0x21f50018, - 0x0ef405fa, -/* 0x0535: main_not_ctx_xfer */ - 0x10ef94d3, - 0xf501f5f0, - 0xf4037e21, -/* 0x0542: ih */ - 0x80f9c60e, - 0xf90188fe, - 0xf990f980, - 0xf9b0f9a0, - 0xf9e0f9d0, - 0xf104bdf0, - 0xf00200a7, - 0xaacf00a3, - 0x04abc400, - 0xf02c0bf4, - 0xe7f124d7, - 0xe3f01a00, - 0x00eecf00, - 0x1900f7f1, - 0xcf00f3f0, - 0x21f400ff, - 0x01e7f004, - 0x1d0007f1, - 0xd00003f0, - 0x04bd000e, -/* 0x0590: ih_no_fifo */ - 0x010007f1, - 0xd00003f0, - 0x04bd000a, - 0xe0fcf0fc, - 0xb0fcd0fc, - 0x90fca0fc, - 0x88fe80fc, - 0xf480fc00, - 0x01f80032, -/* 0x05b4: hub_barrier_done */ - 0x9801f7f0, - 0xfebb040e, - 0x02ffb904, - 0x9418e7f1, - 0xf440e3f0, - 0x00f89d21, -/* 0x05cc: ctx_redswitch */ - 0xf120f7f0, + 0xb60825b6, + 0x20b60635, + 0x0130b601, + 0xb60824b6, + 0x2fb90834, + 0xd321f502, + 0x002fbb02, + 0xf1003fbb, + 0xf0010007, + 0x03d00203, + 0xbd04bd00, + 0x1f29f024, + 0x080007f1, + 0xd00203f0, + 0x04bd0002, +/* 0x0508: main */ + 0xf40031f4, + 0xd7f00028, + 0x3921f424, + 0xb0f401f4, + 0x18f404e4, + 0x0181fe1e, + 0xbd0627f0, + 0x0412fd20, + 0xfd01e4b6, + 0x18fe051e, + 0xfd21f500, + 0xd30ef405, +/* 0x0538: main_not_ctx_xfer */ + 0xf010ef94, + 0x21f501f5, + 0x0ef4037e, +/* 0x0545: ih */ + 0xfe80f9c6, + 0x80f90188, + 0xa0f990f9, + 0xd0f9b0f9, + 0xf0f9e0f9, + 0xa7f104bd, + 0xa3f00200, + 0x00aacf00, + 0xf404abc4, + 0xd7f02c0b, + 0x00e7f124, + 0x00e3f01a, + 0xf100eecf, + 0xf01900f7, + 0xffcf00f3, + 0x0421f400, + 0xf101e7f0, + 0xf01d0007, + 0x0ed00003, +/* 0x0593: ih_no_fifo */ + 0xf104bd00, + 0xf0010007, + 0x0ad00003, + 0xfc04bd00, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x32f480fc, +/* 0x05b7: hub_barrier_done */ + 0xf001f800, + 0x0e9801f7, + 0x04febb04, + 0xf102ffb9, + 0xf09418e7, + 0x21f440e3, +/* 0x05cf: ctx_redswitch */ + 0xf000f89d, + 0x07f120f7, + 0x03f08500, + 0x000fd001, + 0xe7f004bd, +/* 0x05e1: ctx_redswitch_delay */ + 0x01e2b608, + 0xf1fd1bf4, + 0xf10800f5, + 0xf10200f5, 0xf0850007, 0x0fd00103, - 0xf004bd00, -/* 0x05de: ctx_redswitch_delay */ - 0xe2b608e7, - 0xfd1bf401, - 0x0800f5f1, - 0x0200f5f1, - 0x850007f1, - 0xd00103f0, - 0x04bd000f, -/* 0x05fa: ctx_xfer */ - 0x07f100f8, - 0x03f08100, - 0x000fd002, - 0x11f404bd, - 0xcc21f507, -/* 0x060d: ctx_xfer_not_load */ - 0x6a21f505, - 0xf124bd02, - 0xf047fc07, - 0x02d00203, - 0xf004bd00, - 0x20b6012c, - 0xfc07f103, - 0x0203f04a, - 0xbd0002d0, - 0x01acf004, - 0xf102a5f0, - 0xf00000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98000c, - 0x00e7f001, - 0x016f21f5, - 0xf101acf0, - 0xf04000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98010c, - 0x060f9802, - 0x0800e7f1, - 0x016f21f5, + 0xf804bd00, +/* 0x05fd: ctx_xfer */ + 0x0007f100, + 0x0203f081, + 0xbd000fd0, + 0x0711f404, + 0x05cf21f5, +/* 0x0610: ctx_xfer_not_load */ + 0x026a21f5, + 0x07f124bd, + 0x03f047fc, + 0x0002d002, + 0x2cf004bd, + 0x0320b601, + 0x4afc07f1, + 0xd00203f0, + 0x04bd0002, 0xf001acf0, - 0xb7f104a5, - 0xb3f03000, + 0xb7f102a5, + 0xb3f00000, 0x040c9850, 0xbb0fc4b6, 0x0c9800bc, - 0x030d9802, - 0xf1080f98, - 0xf50200e7, - 0xf5016f21, - 0xf4025e21, - 0x12f40601, -/* 0x06a9: ctx_xfer_post */ - 0x7f21f507, -/* 0x06ad: ctx_xfer_done */ - 0xb421f502, - 0x0000f805, - 0x00000000, + 0x010d9800, + 0xf500e7f0, + 0xf0016f21, + 0xb7f101ac, + 0xb3f04000, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x020d9801, + 0xf1060f98, + 0xf50800e7, + 0xf0016f21, + 0xa5f001ac, + 0x00b7f104, + 0x50b3f030, + 0xb6040c98, + 0xbcbb0fc4, + 0x020c9800, + 0x98030d98, + 0xe7f1080f, + 0x21f50200, + 0x21f5016f, + 0x01f4025e, + 0x0712f406, +/* 0x06ac: ctx_xfer_post */ + 0x027f21f5, +/* 0x06b0: ctx_xfer_done */ + 0x05b721f5, + 0x000000f8, 0x00000000, 0x00000000, 0x00000000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h index 2f596433c..911976d20 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h @@ -314,7 +314,7 @@ uint32_t gk104_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe0542, + 0x10fe0545, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -338,184 +338,184 @@ uint32_t gk104_grgpc_code[] = { 0x02d00103, 0xf104bd00, 0xf00c30e7, - 0x24bd50e3, - 0x44bd34bd, -/* 0x0430: init_unk_loop */ - 0xb06821f4, - 0x0bf400f6, - 0x01f7f00f, - 0xfd04f2bb, - 0x30b6054f, -/* 0x0445: init_unk_next */ - 0x0120b601, - 0xb004e0b6, - 0x1bf40126, -/* 0x0451: init_unk_done */ - 0x070380e2, - 0xf1080480, - 0xf0010027, - 0x22cf0223, - 0x9534bd00, - 0x07f10825, - 0x03f0c000, - 0x0005d001, - 0x07f104bd, - 0x03f0c100, - 0x0005d001, - 0x0e9804bd, - 0x010f9800, - 0x015021f5, - 0xbb002fbb, - 0x0e98003f, - 0x020f9801, - 0x015021f5, - 0xfd050e98, - 0x2ebb00ef, - 0x003ebb00, - 0x98020e98, - 0x21f5030f, - 0x0e980150, - 0x00effd07, - 0xbb002ebb, - 0x35b6003e, - 0x0007f102, - 0x0103f0d3, - 0xbd0003d0, - 0x0825b604, - 0xb60635b6, - 0x30b60120, - 0x0824b601, - 0xb90834b6, - 0x21f5022f, - 0x2fbb02d3, - 0x003fbb00, - 0x010007f1, - 0xd00203f0, + 0xe5f050e3, + 0xbd24bd01, +/* 0x0433: init_unk_loop */ + 0xf444bd34, + 0xf6b06821, + 0x0f0bf400, + 0xbb01f7f0, + 0x4ffd04f2, + 0x0130b605, +/* 0x0448: init_unk_next */ + 0xb60120b6, + 0x26b004e0, + 0xe21bf401, +/* 0x0454: init_unk_done */ + 0x80070380, + 0x27f10804, + 0x23f00100, + 0x0022cf02, + 0x259534bd, + 0x0007f108, + 0x0103f0c0, + 0xbd0005d0, + 0x0007f104, + 0x0103f0c1, + 0xbd0005d0, + 0x000e9804, + 0xf5010f98, + 0xbb015021, + 0x3fbb002f, + 0x010e9800, + 0xf5020f98, + 0x98015021, + 0xeffd050e, + 0x002ebb00, + 0x98003ebb, + 0x0f98020e, + 0x5021f503, + 0x070e9801, + 0xbb00effd, + 0x3ebb002e, + 0x0235b600, + 0xd30007f1, + 0xd00103f0, 0x04bd0003, - 0x29f024bd, - 0x0007f11f, - 0x0203f008, - 0xbd0002d0, -/* 0x0505: main */ - 0x0031f404, - 0xf00028f4, - 0x21f424d7, - 0xf401f439, - 0xf404e4b0, - 0x81fe1e18, - 0x0627f001, - 0x12fd20bd, - 0x01e4b604, - 0xfe051efd, - 0x21f50018, - 0x0ef405fa, -/* 0x0535: main_not_ctx_xfer */ - 0x10ef94d3, - 0xf501f5f0, - 0xf4037e21, -/* 0x0542: ih */ - 0x80f9c60e, - 0xf90188fe, - 0xf990f980, - 0xf9b0f9a0, - 0xf9e0f9d0, - 0xf104bdf0, - 0xf00200a7, - 0xaacf00a3, - 0x04abc400, - 0xf02c0bf4, - 0xe7f124d7, - 0xe3f01a00, - 0x00eecf00, - 0x1900f7f1, - 0xcf00f3f0, - 0x21f400ff, - 0x01e7f004, - 0x1d0007f1, - 0xd00003f0, - 0x04bd000e, -/* 0x0590: ih_no_fifo */ - 0x010007f1, - 0xd00003f0, - 0x04bd000a, - 0xe0fcf0fc, - 0xb0fcd0fc, - 0x90fca0fc, - 0x88fe80fc, - 0xf480fc00, - 0x01f80032, -/* 0x05b4: hub_barrier_done */ - 0x9801f7f0, - 0xfebb040e, - 0x02ffb904, - 0x9418e7f1, - 0xf440e3f0, - 0x00f89d21, -/* 0x05cc: ctx_redswitch */ - 0xf120f7f0, + 0xb60825b6, + 0x20b60635, + 0x0130b601, + 0xb60824b6, + 0x2fb90834, + 0xd321f502, + 0x002fbb02, + 0xf1003fbb, + 0xf0010007, + 0x03d00203, + 0xbd04bd00, + 0x1f29f024, + 0x080007f1, + 0xd00203f0, + 0x04bd0002, +/* 0x0508: main */ + 0xf40031f4, + 0xd7f00028, + 0x3921f424, + 0xb0f401f4, + 0x18f404e4, + 0x0181fe1e, + 0xbd0627f0, + 0x0412fd20, + 0xfd01e4b6, + 0x18fe051e, + 0xfd21f500, + 0xd30ef405, +/* 0x0538: main_not_ctx_xfer */ + 0xf010ef94, + 0x21f501f5, + 0x0ef4037e, +/* 0x0545: ih */ + 0xfe80f9c6, + 0x80f90188, + 0xa0f990f9, + 0xd0f9b0f9, + 0xf0f9e0f9, + 0xa7f104bd, + 0xa3f00200, + 0x00aacf00, + 0xf404abc4, + 0xd7f02c0b, + 0x00e7f124, + 0x00e3f01a, + 0xf100eecf, + 0xf01900f7, + 0xffcf00f3, + 0x0421f400, + 0xf101e7f0, + 0xf01d0007, + 0x0ed00003, +/* 0x0593: ih_no_fifo */ + 0xf104bd00, + 0xf0010007, + 0x0ad00003, + 0xfc04bd00, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x32f480fc, +/* 0x05b7: hub_barrier_done */ + 0xf001f800, + 0x0e9801f7, + 0x04febb04, + 0xf102ffb9, + 0xf09418e7, + 0x21f440e3, +/* 0x05cf: ctx_redswitch */ + 0xf000f89d, + 0x07f120f7, + 0x03f08500, + 0x000fd001, + 0xe7f004bd, +/* 0x05e1: ctx_redswitch_delay */ + 0x01e2b608, + 0xf1fd1bf4, + 0xf10800f5, + 0xf10200f5, 0xf0850007, 0x0fd00103, - 0xf004bd00, -/* 0x05de: ctx_redswitch_delay */ - 0xe2b608e7, - 0xfd1bf401, - 0x0800f5f1, - 0x0200f5f1, - 0x850007f1, - 0xd00103f0, - 0x04bd000f, -/* 0x05fa: ctx_xfer */ - 0x07f100f8, - 0x03f08100, - 0x000fd002, - 0x11f404bd, - 0xcc21f507, -/* 0x060d: ctx_xfer_not_load */ - 0x6a21f505, - 0xf124bd02, - 0xf047fc07, - 0x02d00203, - 0xf004bd00, - 0x20b6012c, - 0xfc07f103, - 0x0203f04a, - 0xbd0002d0, - 0x01acf004, - 0xf102a5f0, - 0xf00000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98000c, - 0x00e7f001, - 0x016f21f5, - 0xf101acf0, - 0xf04000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98010c, - 0x060f9802, - 0x0800e7f1, - 0x016f21f5, + 0xf804bd00, +/* 0x05fd: ctx_xfer */ + 0x0007f100, + 0x0203f081, + 0xbd000fd0, + 0x0711f404, + 0x05cf21f5, +/* 0x0610: ctx_xfer_not_load */ + 0x026a21f5, + 0x07f124bd, + 0x03f047fc, + 0x0002d002, + 0x2cf004bd, + 0x0320b601, + 0x4afc07f1, + 0xd00203f0, + 0x04bd0002, 0xf001acf0, - 0xb7f104a5, - 0xb3f03000, + 0xb7f102a5, + 0xb3f00000, 0x040c9850, 0xbb0fc4b6, 0x0c9800bc, - 0x030d9802, - 0xf1080f98, - 0xf50200e7, - 0xf5016f21, - 0xf4025e21, - 0x12f40601, -/* 0x06a9: ctx_xfer_post */ - 0x7f21f507, -/* 0x06ad: ctx_xfer_done */ - 0xb421f502, - 0x0000f805, - 0x00000000, + 0x010d9800, + 0xf500e7f0, + 0xf0016f21, + 0xb7f101ac, + 0xb3f04000, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x020d9801, + 0xf1060f98, + 0xf50800e7, + 0xf0016f21, + 0xa5f001ac, + 0x00b7f104, + 0x50b3f030, + 0xb6040c98, + 0xbcbb0fc4, + 0x020c9800, + 0x98030d98, + 0xe7f1080f, + 0x21f50200, + 0x21f5016f, + 0x01f4025e, + 0x0712f406, +/* 0x06ac: ctx_xfer_post */ + 0x027f21f5, +/* 0x06b0: ctx_xfer_done */ + 0x05b721f5, + 0x000000f8, 0x00000000, 0x00000000, 0x00000000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h index ee8e54db8..1c6e11b05 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h @@ -314,7 +314,7 @@ uint32_t gk110_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe0542, + 0x10fe0545, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -338,184 +338,184 @@ uint32_t gk110_grgpc_code[] = { 0x02d00103, 0xf104bd00, 0xf00c30e7, - 0x24bd50e3, - 0x44bd34bd, -/* 0x0430: init_unk_loop */ - 0xb06821f4, - 0x0bf400f6, - 0x01f7f00f, - 0xfd04f2bb, - 0x30b6054f, -/* 0x0445: init_unk_next */ - 0x0120b601, - 0xb004e0b6, - 0x1bf40226, -/* 0x0451: init_unk_done */ - 0x070380e2, - 0xf1080480, - 0xf0010027, - 0x22cf0223, - 0x9534bd00, - 0x07f10825, - 0x03f0c000, - 0x0005d001, - 0x07f104bd, - 0x03f0c100, - 0x0005d001, - 0x0e9804bd, - 0x010f9800, - 0x015021f5, - 0xbb002fbb, - 0x0e98003f, - 0x020f9801, - 0x015021f5, - 0xfd050e98, - 0x2ebb00ef, - 0x003ebb00, - 0x98020e98, - 0x21f5030f, - 0x0e980150, - 0x00effd07, - 0xbb002ebb, - 0x35b6003e, - 0x0007f102, - 0x0103f0d3, - 0xbd0003d0, - 0x0825b604, - 0xb60635b6, - 0x30b60120, - 0x0824b601, - 0xb90834b6, - 0x21f5022f, - 0x2fbb02d3, - 0x003fbb00, - 0x010007f1, - 0xd00203f0, + 0xe5f050e3, + 0xbd24bd01, +/* 0x0433: init_unk_loop */ + 0xf444bd34, + 0xf6b06821, + 0x0f0bf400, + 0xbb01f7f0, + 0x4ffd04f2, + 0x0130b605, +/* 0x0448: init_unk_next */ + 0xb60120b6, + 0x26b004e0, + 0xe21bf402, +/* 0x0454: init_unk_done */ + 0x80070380, + 0x27f10804, + 0x23f00100, + 0x0022cf02, + 0x259534bd, + 0x0007f108, + 0x0103f0c0, + 0xbd0005d0, + 0x0007f104, + 0x0103f0c1, + 0xbd0005d0, + 0x000e9804, + 0xf5010f98, + 0xbb015021, + 0x3fbb002f, + 0x010e9800, + 0xf5020f98, + 0x98015021, + 0xeffd050e, + 0x002ebb00, + 0x98003ebb, + 0x0f98020e, + 0x5021f503, + 0x070e9801, + 0xbb00effd, + 0x3ebb002e, + 0x0235b600, + 0xd30007f1, + 0xd00103f0, 0x04bd0003, - 0x29f024bd, - 0x0007f11f, - 0x0203f030, - 0xbd0002d0, -/* 0x0505: main */ - 0x0031f404, - 0xf00028f4, - 0x21f424d7, - 0xf401f439, - 0xf404e4b0, - 0x81fe1e18, - 0x0627f001, - 0x12fd20bd, - 0x01e4b604, - 0xfe051efd, - 0x21f50018, - 0x0ef405fa, -/* 0x0535: main_not_ctx_xfer */ - 0x10ef94d3, - 0xf501f5f0, - 0xf4037e21, -/* 0x0542: ih */ - 0x80f9c60e, - 0xf90188fe, - 0xf990f980, - 0xf9b0f9a0, - 0xf9e0f9d0, - 0xf104bdf0, - 0xf00200a7, - 0xaacf00a3, - 0x04abc400, - 0xf02c0bf4, - 0xe7f124d7, - 0xe3f01a00, - 0x00eecf00, - 0x1900f7f1, - 0xcf00f3f0, - 0x21f400ff, - 0x01e7f004, - 0x1d0007f1, - 0xd00003f0, - 0x04bd000e, -/* 0x0590: ih_no_fifo */ - 0x010007f1, - 0xd00003f0, - 0x04bd000a, - 0xe0fcf0fc, - 0xb0fcd0fc, - 0x90fca0fc, - 0x88fe80fc, - 0xf480fc00, - 0x01f80032, -/* 0x05b4: hub_barrier_done */ - 0x9801f7f0, - 0xfebb040e, - 0x02ffb904, - 0x9418e7f1, - 0xf440e3f0, - 0x00f89d21, -/* 0x05cc: ctx_redswitch */ - 0xf120f7f0, + 0xb60825b6, + 0x20b60635, + 0x0130b601, + 0xb60824b6, + 0x2fb90834, + 0xd321f502, + 0x002fbb02, + 0xf1003fbb, + 0xf0010007, + 0x03d00203, + 0xbd04bd00, + 0x1f29f024, + 0x300007f1, + 0xd00203f0, + 0x04bd0002, +/* 0x0508: main */ + 0xf40031f4, + 0xd7f00028, + 0x3921f424, + 0xb0f401f4, + 0x18f404e4, + 0x0181fe1e, + 0xbd0627f0, + 0x0412fd20, + 0xfd01e4b6, + 0x18fe051e, + 0xfd21f500, + 0xd30ef405, +/* 0x0538: main_not_ctx_xfer */ + 0xf010ef94, + 0x21f501f5, + 0x0ef4037e, +/* 0x0545: ih */ + 0xfe80f9c6, + 0x80f90188, + 0xa0f990f9, + 0xd0f9b0f9, + 0xf0f9e0f9, + 0xa7f104bd, + 0xa3f00200, + 0x00aacf00, + 0xf404abc4, + 0xd7f02c0b, + 0x00e7f124, + 0x00e3f01a, + 0xf100eecf, + 0xf01900f7, + 0xffcf00f3, + 0x0421f400, + 0xf101e7f0, + 0xf01d0007, + 0x0ed00003, +/* 0x0593: ih_no_fifo */ + 0xf104bd00, + 0xf0010007, + 0x0ad00003, + 0xfc04bd00, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x32f480fc, +/* 0x05b7: hub_barrier_done */ + 0xf001f800, + 0x0e9801f7, + 0x04febb04, + 0xf102ffb9, + 0xf09418e7, + 0x21f440e3, +/* 0x05cf: ctx_redswitch */ + 0xf000f89d, + 0x07f120f7, + 0x03f08500, + 0x000fd001, + 0xe7f004bd, +/* 0x05e1: ctx_redswitch_delay */ + 0x01e2b608, + 0xf1fd1bf4, + 0xf10800f5, + 0xf10200f5, 0xf0850007, 0x0fd00103, - 0xf004bd00, -/* 0x05de: ctx_redswitch_delay */ - 0xe2b608e7, - 0xfd1bf401, - 0x0800f5f1, - 0x0200f5f1, - 0x850007f1, - 0xd00103f0, - 0x04bd000f, -/* 0x05fa: ctx_xfer */ - 0x07f100f8, - 0x03f08100, - 0x000fd002, - 0x11f404bd, - 0xcc21f507, -/* 0x060d: ctx_xfer_not_load */ - 0x6a21f505, - 0xf124bd02, - 0xf047fc07, - 0x02d00203, - 0xf004bd00, - 0x20b6012c, - 0xfc07f103, - 0x0203f04a, - 0xbd0002d0, - 0x01acf004, - 0xf102a5f0, - 0xf00000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98000c, - 0x00e7f001, - 0x016f21f5, - 0xf101acf0, - 0xf04000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98010c, - 0x060f9802, - 0x0800e7f1, - 0x016f21f5, + 0xf804bd00, +/* 0x05fd: ctx_xfer */ + 0x0007f100, + 0x0203f081, + 0xbd000fd0, + 0x0711f404, + 0x05cf21f5, +/* 0x0610: ctx_xfer_not_load */ + 0x026a21f5, + 0x07f124bd, + 0x03f047fc, + 0x0002d002, + 0x2cf004bd, + 0x0320b601, + 0x4afc07f1, + 0xd00203f0, + 0x04bd0002, 0xf001acf0, - 0xb7f104a5, - 0xb3f03000, + 0xb7f102a5, + 0xb3f00000, 0x040c9850, 0xbb0fc4b6, 0x0c9800bc, - 0x030d9802, - 0xf1080f98, - 0xf50200e7, - 0xf5016f21, - 0xf4025e21, - 0x12f40601, -/* 0x06a9: ctx_xfer_post */ - 0x7f21f507, -/* 0x06ad: ctx_xfer_done */ - 0xb421f502, - 0x0000f805, - 0x00000000, + 0x010d9800, + 0xf500e7f0, + 0xf0016f21, + 0xb7f101ac, + 0xb3f04000, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x020d9801, + 0xf1060f98, + 0xf50800e7, + 0xf0016f21, + 0xa5f001ac, + 0x00b7f104, + 0x50b3f030, + 0xb6040c98, + 0xbcbb0fc4, + 0x020c9800, + 0x98030d98, + 0xe7f1080f, + 0x21f50200, + 0x21f5016f, + 0x01f4025e, + 0x0712f406, +/* 0x06ac: ctx_xfer_post */ + 0x027f21f5, +/* 0x06b0: ctx_xfer_done */ + 0x05b721f5, + 0x000000f8, 0x00000000, 0x00000000, 0x00000000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h index fbcc342f8..84af7ec6a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h @@ -276,7 +276,7 @@ uint32_t gk208_grgpc_code[] = { 0x02020014, 0xf6120040, 0x04bd0002, - 0xfe048141, + 0xfe048441, 0x00400010, 0x0000f607, 0x040204bd, @@ -295,165 +295,165 @@ uint32_t gk208_grgpc_code[] = { 0x01c90080, 0xbd0002f6, 0x0c308e04, - 0xbd24bd50, -/* 0x0383: init_unk_loop */ - 0x7e44bd34, - 0xb0000065, - 0x0bf400f6, - 0xbb010f0e, - 0x4ffd04f2, - 0x0130b605, -/* 0x0398: init_unk_next */ - 0xb60120b6, - 0x26b004e0, - 0xe21bf401, -/* 0x03a4: init_unk_done */ - 0xb50703b5, - 0x00820804, - 0x22cf0201, - 0x9534bd00, - 0x00800825, - 0x05f601c0, - 0x8004bd00, - 0xf601c100, - 0x04bd0005, - 0x98000e98, - 0x207e010f, - 0x2fbb0001, - 0x003fbb00, - 0x98010e98, - 0x207e020f, - 0x0e980001, - 0x00effd05, - 0xbb002ebb, - 0x0e98003e, - 0x030f9802, - 0x0001207e, - 0xfd070e98, - 0x2ebb00ef, - 0x003ebb00, - 0x800235b6, - 0xf601d300, - 0x04bd0003, - 0xb60825b6, - 0x20b60635, - 0x0130b601, - 0xb60824b6, - 0x2fb20834, - 0x0002687e, - 0xbb002fbb, - 0x0080003f, - 0x03f60201, - 0xbd04bd00, - 0x1f29f024, - 0x02300080, - 0xbd0002f6, -/* 0x0445: main */ - 0x0031f404, - 0x0d0028f4, - 0x00377e24, - 0xf401f400, - 0xf404e4b0, - 0x81fe1d18, - 0xbd060201, - 0x0412fd20, - 0xfd01e4b6, - 0x18fe051e, - 0x05187e00, - 0xd40ef400, -/* 0x0474: main_not_ctx_xfer */ - 0xf010ef94, - 0xf87e01f5, - 0x0ef40002, -/* 0x0481: ih */ - 0xfe80f9c7, - 0x80f90188, - 0xa0f990f9, - 0xd0f9b0f9, - 0xf0f9e0f9, - 0x004a04bd, - 0x00aacf02, - 0xf404abc4, - 0x240d1f0b, - 0xcf1a004e, - 0x004f00ee, - 0x00ffcf19, - 0x0000047e, - 0x0040010e, - 0x000ef61d, -/* 0x04be: ih_no_fifo */ - 0x004004bd, - 0x000af601, - 0xf0fc04bd, - 0xd0fce0fc, - 0xa0fcb0fc, - 0x80fc90fc, - 0xfc0088fe, - 0x0032f480, -/* 0x04de: hub_barrier_done */ - 0x010f01f8, - 0xbb040e98, - 0xffb204fe, - 0x4094188e, - 0x00008f7e, -/* 0x04f2: ctx_redswitch */ - 0x200f00f8, + 0x01e5f050, + 0x34bd24bd, +/* 0x0386: init_unk_loop */ + 0x657e44bd, + 0xf6b00000, + 0x0e0bf400, + 0xf2bb010f, + 0x054ffd04, +/* 0x039b: init_unk_next */ + 0xb60130b6, + 0xe0b60120, + 0x0126b004, +/* 0x03a7: init_unk_done */ + 0xb5e21bf4, + 0x04b50703, + 0x01008208, + 0x0022cf02, + 0x259534bd, + 0xc0008008, + 0x0005f601, + 0x008004bd, + 0x05f601c1, + 0x9804bd00, + 0x0f98000e, + 0x01207e01, + 0x002fbb00, + 0x98003fbb, + 0x0f98010e, + 0x01207e02, + 0x050e9800, + 0xbb00effd, + 0x3ebb002e, + 0x020e9800, + 0x7e030f98, + 0x98000120, + 0xeffd070e, + 0x002ebb00, + 0xb6003ebb, + 0x00800235, + 0x03f601d3, + 0xb604bd00, + 0x35b60825, + 0x0120b606, + 0xb60130b6, + 0x34b60824, + 0x7e2fb208, + 0xbb000268, + 0x3fbb002f, + 0x01008000, + 0x0003f602, + 0x24bd04bd, + 0x801f29f0, + 0xf6023000, + 0x04bd0002, +/* 0x0448: main */ + 0xf40031f4, + 0x240d0028, + 0x0000377e, + 0xb0f401f4, + 0x18f404e4, + 0x0181fe1d, + 0x20bd0602, + 0xb60412fd, + 0x1efd01e4, + 0x0018fe05, + 0x00051b7e, +/* 0x0477: main_not_ctx_xfer */ + 0x94d40ef4, + 0xf5f010ef, + 0x02f87e01, + 0xc70ef400, +/* 0x0484: ih */ + 0x88fe80f9, + 0xf980f901, + 0xf9a0f990, + 0xf9d0f9b0, + 0xbdf0f9e0, + 0x02004a04, + 0xc400aacf, + 0x0bf404ab, + 0x4e240d1f, + 0xeecf1a00, + 0x19004f00, + 0x7e00ffcf, + 0x0e000004, + 0x1d004001, + 0xbd000ef6, +/* 0x04c1: ih_no_fifo */ + 0x01004004, + 0xbd000af6, + 0xfcf0fc04, + 0xfcd0fce0, + 0xfca0fcb0, + 0xfe80fc90, + 0x80fc0088, + 0xf80032f4, +/* 0x04e1: hub_barrier_done */ + 0x98010f01, + 0xfebb040e, + 0x8effb204, + 0x7e409418, + 0xf800008f, +/* 0x04f5: ctx_redswitch */ + 0x80200f00, + 0xf6018500, + 0x04bd000f, +/* 0x0502: ctx_redswitch_delay */ + 0xe2b6080e, + 0xfd1bf401, + 0x0800f5f1, + 0x0200f5f1, 0x01850080, 0xbd000ff6, -/* 0x04ff: ctx_redswitch_delay */ - 0xb6080e04, - 0x1bf401e2, - 0x00f5f1fd, - 0x00f5f108, - 0x85008002, - 0x000ff601, - 0x00f804bd, -/* 0x0518: ctx_xfer */ - 0x02810080, - 0xbd000ff6, - 0x0711f404, - 0x0004f27e, -/* 0x0528: ctx_xfer_not_load */ - 0x0002167e, - 0xfc8024bd, - 0x02f60247, - 0xf004bd00, - 0x20b6012c, - 0x4afc8003, +/* 0x051b: ctx_xfer */ + 0x8000f804, + 0xf6028100, + 0x04bd000f, + 0x7e0711f4, +/* 0x052b: ctx_xfer_not_load */ + 0x7e0004f5, + 0xbd000216, + 0x47fc8024, 0x0002f602, - 0xacf004bd, - 0x02a5f001, - 0x5000008b, - 0xb6040c98, - 0xbcbb0fc4, - 0x000c9800, - 0x0e010d98, - 0x013d7e00, - 0x01acf000, - 0x5040008b, - 0xb6040c98, - 0xbcbb0fc4, - 0x010c9800, - 0x98020d98, - 0x004e060f, - 0x013d7e08, - 0x01acf000, - 0x8b04a5f0, - 0x98503000, + 0x2cf004bd, + 0x0320b601, + 0x024afc80, + 0xbd0002f6, + 0x01acf004, + 0x8b02a5f0, + 0x98500000, 0xc4b6040c, 0x00bcbb0f, - 0x98020c98, - 0x0f98030d, - 0x02004e08, + 0x98000c98, + 0x000e010d, 0x00013d7e, - 0x00020a7e, - 0xf40601f4, -/* 0x05b2: ctx_xfer_post */ - 0x277e0712, -/* 0x05b6: ctx_xfer_done */ - 0xde7e0002, - 0x00f80004, - 0x00000000, + 0x8b01acf0, + 0x98504000, + 0xc4b6040c, + 0x00bcbb0f, + 0x98010c98, + 0x0f98020d, + 0x08004e06, + 0x00013d7e, + 0xf001acf0, + 0x008b04a5, + 0x0c985030, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98020c, + 0x080f9803, + 0x7e02004e, + 0x7e00013d, + 0xf400020a, + 0x12f40601, +/* 0x05b5: ctx_xfer_post */ + 0x02277e07, +/* 0x05b9: ctx_xfer_done */ + 0x04e17e00, + 0x0000f800, 0x00000000, 0x00000000, 0x00000000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h index 51f5c3c6e..11bf363a6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h @@ -289,7 +289,7 @@ uint32_t gm107_grgpc_code[] = { 0x020014fe, 0x12004002, 0xbd0002f6, - 0x05b04104, + 0x05b34104, 0x400010fe, 0x00f60700, 0x0204bd00, @@ -308,259 +308,259 @@ uint32_t gm107_grgpc_code[] = { 0xc900800f, 0x0002f601, 0x308e04bd, - 0x24bd500c, - 0x44bd34bd, -/* 0x03b0: init_unk_loop */ - 0x0000657e, - 0xf400f6b0, - 0x010f0e0b, - 0xfd04f2bb, - 0x30b6054f, -/* 0x03c5: init_unk_next */ - 0x0120b601, - 0xb004e0b6, - 0x1bf40226, -/* 0x03d1: init_unk_done */ - 0x0703b5e2, - 0x820804b5, - 0xcf020100, - 0x34bd0022, - 0x80082595, - 0xf601c000, + 0xe5f0500c, + 0xbd24bd01, +/* 0x03b3: init_unk_loop */ + 0x7e44bd34, + 0xb0000065, + 0x0bf400f6, + 0xbb010f0e, + 0x4ffd04f2, + 0x0130b605, +/* 0x03c8: init_unk_next */ + 0xb60120b6, + 0x26b004e0, + 0xe21bf402, +/* 0x03d4: init_unk_done */ + 0xb50703b5, + 0x00820804, + 0x22cf0201, + 0x9534bd00, + 0x00800825, + 0x05f601c0, + 0x8004bd00, + 0xf601c100, 0x04bd0005, - 0x01c10080, - 0xbd0005f6, - 0x000e9804, - 0x7e010f98, - 0xbb000120, - 0x3fbb002f, - 0x010e9800, - 0x7e020f98, - 0x98000120, - 0xeffd050e, - 0x002ebb00, - 0x98003ebb, - 0x0f98020e, - 0x01207e03, - 0x070e9800, - 0xbb00effd, - 0x3ebb002e, - 0x0235b600, - 0x01d30080, - 0xbd0003f6, - 0x0825b604, - 0xb60635b6, - 0x30b60120, - 0x0824b601, - 0xb20834b6, - 0x02687e2f, - 0x002fbb00, - 0x0f003fbb, - 0x8effb23f, - 0xf0501d60, - 0x8f7e01e5, - 0x0c0f0000, - 0xa88effb2, - 0xe5f0501d, - 0x008f7e01, - 0x03147e00, - 0xb23f0f00, - 0x1d608eff, - 0x01e5f050, - 0x00008f7e, - 0xffb2000f, - 0x501d9c8e, - 0x7e01e5f0, - 0x0f00008f, - 0x03147e01, - 0x8effb200, + 0x98000e98, + 0x207e010f, + 0x2fbb0001, + 0x003fbb00, + 0x98010e98, + 0x207e020f, + 0x0e980001, + 0x00effd05, + 0xbb002ebb, + 0x0e98003e, + 0x030f9802, + 0x0001207e, + 0xfd070e98, + 0x2ebb00ef, + 0x003ebb00, + 0x800235b6, + 0xf601d300, + 0x04bd0003, + 0xb60825b6, + 0x20b60635, + 0x0130b601, + 0xb60824b6, + 0x2fb20834, + 0x0002687e, + 0xbb002fbb, + 0x3f0f003f, + 0x501d608e, + 0xb201e5f0, + 0x008f7eff, + 0x8e0c0f00, 0xf0501da8, - 0x8f7e01e5, - 0xff0f0000, - 0x988effb2, + 0xffb201e5, + 0x00008f7e, + 0x0003147e, + 0x608e3f0f, 0xe5f0501d, - 0x008f7e01, - 0xb2020f00, - 0x1da88eff, + 0x7effb201, + 0x0f00008f, + 0x1d9c8e00, 0x01e5f050, - 0x00008f7e, + 0x8f7effb2, + 0x010f0000, 0x0003147e, - 0x85050498, - 0x98504000, - 0x64b60406, - 0x0056bb0f, -/* 0x04e0: tpc_strand_init_tpc_loop */ - 0x05705eb8, - 0x00657e00, - 0xbdf6b200, -/* 0x04ed: tpc_strand_init_idx_loop */ - 0x605eb874, - 0x7fb20005, - 0x00008f7e, - 0x05885eb8, - 0x082f9500, - 0x00008f7e, - 0x058c5eb8, - 0x082f9500, + 0x501da88e, + 0xb201e5f0, + 0x008f7eff, + 0x8eff0f00, + 0xf0501d98, + 0xffb201e5, 0x00008f7e, - 0x05905eb8, - 0x00657e00, - 0x06f5b600, - 0xb601f0b6, - 0x2fbb08f4, - 0x003fbb00, - 0xb60170b6, - 0x1bf40162, - 0x0050b7bf, - 0x0142b608, - 0x0fa81bf4, - 0x8effb23f, - 0xf0501d60, - 0x8f7e01e5, - 0x0d0f0000, - 0xa88effb2, + 0xa88e020f, 0xe5f0501d, - 0x008f7e01, - 0x03147e00, - 0x01008000, - 0x0003f602, - 0x24bd04bd, - 0x801f29f0, - 0xf6023000, - 0x04bd0002, -/* 0x0574: main */ - 0xf40031f4, - 0x240d0028, - 0x0000377e, - 0xb0f401f4, - 0x18f404e4, - 0x0181fe1d, - 0x20bd0602, - 0xb60412fd, - 0x1efd01e4, - 0x0018fe05, - 0x0006477e, -/* 0x05a3: main_not_ctx_xfer */ - 0x94d40ef4, - 0xf5f010ef, - 0x02f87e01, - 0xc70ef400, -/* 0x05b0: ih */ - 0x88fe80f9, - 0xf980f901, - 0xf9a0f990, - 0xf9d0f9b0, - 0xbdf0f9e0, - 0x02004a04, - 0xc400aacf, - 0x0bf404ab, - 0x4e240d1f, - 0xeecf1a00, - 0x19004f00, - 0x7e00ffcf, - 0x0e000004, - 0x1d004001, - 0xbd000ef6, -/* 0x05ed: ih_no_fifo */ - 0x01004004, - 0xbd000af6, - 0xfcf0fc04, - 0xfcd0fce0, - 0xfca0fcb0, - 0xfe80fc90, - 0x80fc0088, - 0xf80032f4, -/* 0x060d: hub_barrier_done */ - 0x98010f01, - 0xfebb040e, - 0x8effb204, - 0x7e409418, - 0xf800008f, -/* 0x0621: ctx_redswitch */ - 0x80200f00, + 0x7effb201, + 0x7e00008f, + 0x98000314, + 0x00850504, + 0x06985040, + 0x0f64b604, +/* 0x04e3: tpc_strand_init_tpc_loop */ + 0xb80056bb, + 0x0005705e, + 0x0000657e, + 0x74bdf6b2, +/* 0x04f0: tpc_strand_init_idx_loop */ + 0x05605eb8, + 0x7e7fb200, + 0xb800008f, + 0x0005885e, + 0x7e082f95, + 0xb800008f, + 0x00058c5e, + 0x7e082f95, + 0xb800008f, + 0x0005905e, + 0x0000657e, + 0xb606f5b6, + 0xf4b601f0, + 0x002fbb08, + 0xb6003fbb, + 0x62b60170, + 0xbf1bf401, + 0x080050b7, + 0xf40142b6, + 0x3f0fa81b, + 0x501d608e, + 0xb201e5f0, + 0x008f7eff, + 0x8e0d0f00, + 0xf0501da8, + 0xffb201e5, + 0x00008f7e, + 0x0003147e, + 0x02010080, + 0xbd0003f6, + 0xf024bd04, + 0x00801f29, + 0x02f60230, +/* 0x0577: main */ + 0xf404bd00, + 0x28f40031, + 0x7e240d00, + 0xf4000037, + 0xe4b0f401, + 0x1d18f404, + 0x020181fe, + 0xfd20bd06, + 0xe4b60412, + 0x051efd01, + 0x7e0018fe, + 0xf400064a, +/* 0x05a6: main_not_ctx_xfer */ + 0xef94d40e, + 0x01f5f010, + 0x0002f87e, +/* 0x05b3: ih */ + 0xf9c70ef4, + 0x0188fe80, + 0x90f980f9, + 0xb0f9a0f9, + 0xe0f9d0f9, + 0x04bdf0f9, + 0xcf02004a, + 0xabc400aa, + 0x1f0bf404, + 0x004e240d, + 0x00eecf1a, + 0xcf19004f, + 0x047e00ff, + 0x010e0000, + 0xf61d0040, + 0x04bd000e, +/* 0x05f0: ih_no_fifo */ + 0xf6010040, + 0x04bd000a, + 0xe0fcf0fc, + 0xb0fcd0fc, + 0x90fca0fc, + 0x88fe80fc, + 0xf480fc00, + 0x01f80032, +/* 0x0610: hub_barrier_done */ + 0x0e98010f, + 0x04febb04, + 0x188effb2, + 0x8f7e4094, + 0x00f80000, +/* 0x0624: ctx_redswitch */ + 0x0080200f, + 0x0ff60185, + 0x0e04bd00, +/* 0x0631: ctx_redswitch_delay */ + 0x01e2b608, + 0xf1fd1bf4, + 0xf10800f5, + 0x800200f5, 0xf6018500, 0x04bd000f, -/* 0x062e: ctx_redswitch_delay */ - 0xe2b6080e, - 0xfd1bf401, - 0x0800f5f1, - 0x0200f5f1, - 0x01850080, - 0xbd000ff6, -/* 0x0647: ctx_xfer */ - 0x8000f804, - 0xf6028100, - 0x04bd000f, - 0xc48effb2, - 0xe5f0501d, - 0x008f7e01, - 0x0711f400, - 0x0006217e, -/* 0x0664: ctx_xfer_not_load */ - 0x0002167e, - 0xfc8024bd, - 0x02f60247, - 0xf004bd00, - 0x20b6012c, - 0x4afc8003, +/* 0x064a: ctx_xfer */ + 0x008000f8, + 0x0ff60281, + 0x8e04bd00, + 0xf0501dc4, + 0xffb201e5, + 0x00008f7e, + 0x7e0711f4, +/* 0x0667: ctx_xfer_not_load */ + 0x7e000624, + 0xbd000216, + 0x47fc8024, 0x0002f602, - 0x0c0f04bd, - 0xa88effb2, - 0xe5f0501d, - 0x008f7e01, - 0x03147e00, - 0xb23f0f00, - 0x1d608eff, - 0x01e5f050, + 0x2cf004bd, + 0x0320b601, + 0x024afc80, + 0xbd0002f6, + 0x8e0c0f04, + 0xf0501da8, + 0xffb201e5, 0x00008f7e, - 0xffb2000f, - 0x501d9c8e, - 0x7e01e5f0, + 0x0003147e, + 0x608e3f0f, + 0xe5f0501d, + 0x7effb201, 0x0f00008f, - 0x03147e01, - 0x01fcf000, - 0xb203f0b6, - 0x1da88eff, + 0x1d9c8e00, 0x01e5f050, - 0x00008f7e, - 0xf001acf0, - 0x008b02a5, - 0x0c985000, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98000c, - 0x7e000e01, - 0xf000013d, - 0x008b01ac, - 0x0c985040, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98010c, - 0x060f9802, - 0x7e08004e, - 0xf000013d, + 0x8f7effb2, + 0x010f0000, + 0x0003147e, + 0xb601fcf0, + 0xa88e03f0, + 0xe5f0501d, + 0x7effb201, + 0xf000008f, 0xa5f001ac, - 0x30008b04, + 0x00008b02, 0x040c9850, 0xbb0fc4b6, 0x0c9800bc, - 0x030d9802, - 0x4e080f98, - 0x3d7e0200, - 0x0a7e0001, - 0x147e0002, - 0x01f40003, - 0x1a12f406, -/* 0x073c: ctx_xfer_post */ - 0x0002277e, - 0xffb20d0f, - 0x501da88e, - 0x7e01e5f0, - 0x7e00008f, -/* 0x0753: ctx_xfer_done */ - 0x7e000314, - 0xf800060d, - 0x00000000, + 0x010d9800, + 0x3d7e000e, + 0xacf00001, + 0x40008b01, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x020d9801, + 0x4e060f98, + 0x3d7e0800, + 0xacf00001, + 0x04a5f001, + 0x5030008b, + 0xb6040c98, + 0xbcbb0fc4, + 0x020c9800, + 0x98030d98, + 0x004e080f, + 0x013d7e02, + 0x020a7e00, + 0x03147e00, + 0x0601f400, +/* 0x073f: ctx_xfer_post */ + 0x7e1a12f4, + 0x0f000227, + 0x1da88e0d, + 0x01e5f050, + 0x8f7effb2, + 0x147e0000, +/* 0x0756: ctx_xfer_done */ + 0x107e0003, + 0x00f80006, 0x00000000, 0x00000000, 0x00000000, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.c new file mode 100644 index 000000000..ce9133005 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.c @@ -0,0 +1,196 @@ +/* + * 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 "nv50.h" + +#include + +static const struct nvkm_bitfield nv50_gr_status[] = { + { 0x00000001, "BUSY" }, /* set when any bit is set */ + { 0x00000002, "DISPATCH" }, + { 0x00000004, "UNK2" }, + { 0x00000008, "UNK3" }, + { 0x00000010, "UNK4" }, + { 0x00000020, "UNK5" }, + { 0x00000040, "M2MF" }, + { 0x00000080, "UNK7" }, + { 0x00000100, "CTXPROG" }, + { 0x00000200, "VFETCH" }, + { 0x00000400, "CCACHE_PREGEOM" }, + { 0x00000800, "STRMOUT_VATTR_POSTGEOM" }, + { 0x00001000, "VCLIP" }, + { 0x00002000, "RATTR_APLANE" }, + { 0x00004000, "TRAST" }, + { 0x00008000, "CLIPID" }, + { 0x00010000, "ZCULL" }, + { 0x00020000, "ENG2D" }, + { 0x00040000, "RMASK" }, + { 0x00080000, "TPC_RAST" }, + { 0x00100000, "TPC_PROP" }, + { 0x00200000, "TPC_TEX" }, + { 0x00400000, "TPC_GEOM" }, + { 0x00800000, "TPC_MP" }, + { 0x01000000, "ROP" }, + {} +}; + +static const struct nvkm_bitfield +nv50_gr_vstatus_0[] = { + { 0x01, "VFETCH" }, + { 0x02, "CCACHE" }, + { 0x04, "PREGEOM" }, + { 0x08, "POSTGEOM" }, + { 0x10, "VATTR" }, + { 0x20, "STRMOUT" }, + { 0x40, "VCLIP" }, + {} +}; + +static const struct nvkm_bitfield +nv50_gr_vstatus_1[] = { + { 0x01, "TPC_RAST" }, + { 0x02, "TPC_PROP" }, + { 0x04, "TPC_TEX" }, + { 0x08, "TPC_GEOM" }, + { 0x10, "TPC_MP" }, + {} +}; + +static const struct nvkm_bitfield +nv50_gr_vstatus_2[] = { + { 0x01, "RATTR" }, + { 0x02, "APLANE" }, + { 0x04, "TRAST" }, + { 0x08, "CLIPID" }, + { 0x10, "ZCULL" }, + { 0x20, "ENG2D" }, + { 0x40, "RMASK" }, + { 0x80, "ROP" }, + {} +}; + +static void +nvkm_gr_vstatus_print(struct nv50_gr *gr, int r, + const struct nvkm_bitfield *units, u32 status) +{ + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + u32 stat = status; + u8 mask = 0x00; + char msg[64]; + int i; + + for (i = 0; units[i].name && status; i++) { + if ((status & 7) == 1) + mask |= (1 << i); + status >>= 3; + } + + nvkm_snprintbf(msg, sizeof(msg), units, mask); + nvkm_error(subdev, "PGRAPH_VSTATUS%d: %08x [%s]\n", r, stat, msg); +} + +int +g84_gr_tlb_flush(struct nvkm_gr *base) +{ + struct nv50_gr *gr = nv50_gr(base); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_timer *tmr = device->timer; + bool idle, timeout = false; + unsigned long flags; + char status[128]; + u64 start; + u32 tmp; + + spin_lock_irqsave(&gr->lock, flags); + nvkm_mask(device, 0x400500, 0x00000001, 0x00000000); + + start = nvkm_timer_read(tmr); + do { + idle = true; + + for (tmp = nvkm_rd32(device, 0x400380); tmp && idle; tmp >>= 3) { + if ((tmp & 7) == 1) + idle = false; + } + + for (tmp = nvkm_rd32(device, 0x400384); tmp && idle; tmp >>= 3) { + if ((tmp & 7) == 1) + idle = false; + } + + for (tmp = nvkm_rd32(device, 0x400388); tmp && idle; tmp >>= 3) { + if ((tmp & 7) == 1) + idle = false; + } + } while (!idle && + !(timeout = nvkm_timer_read(tmr) - start > 2000000000)); + + if (timeout) { + nvkm_error(subdev, "PGRAPH TLB flush idle timeout fail\n"); + + tmp = nvkm_rd32(device, 0x400700); + nvkm_snprintbf(status, sizeof(status), nv50_gr_status, tmp); + nvkm_error(subdev, "PGRAPH_STATUS %08x [%s]\n", tmp, status); + + nvkm_gr_vstatus_print(gr, 0, nv50_gr_vstatus_0, + nvkm_rd32(device, 0x400380)); + nvkm_gr_vstatus_print(gr, 1, nv50_gr_vstatus_1, + nvkm_rd32(device, 0x400384)); + nvkm_gr_vstatus_print(gr, 2, nv50_gr_vstatus_2, + nvkm_rd32(device, 0x400388)); + } + + + nvkm_wr32(device, 0x100c80, 0x00000001); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) + break; + ); + nvkm_mask(device, 0x400500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&gr->lock, flags); + return timeout ? -EBUSY : 0; +} + +static const struct nvkm_gr_func +g84_gr = { + .init = nv50_gr_init, + .intr = nv50_gr_intr, + .chan_new = nv50_gr_chan_new, + .tlb_flush = g84_gr_tlb_flush, + .units = nv50_gr_units, + .sclass = { + { -1, -1, 0x0030, &nv50_gr_object }, + { -1, -1, 0x502d, &nv50_gr_object }, + { -1, -1, 0x5039, &nv50_gr_object }, + { -1, -1, 0x50c0, &nv50_gr_object }, + { -1, -1, 0x8297, &nv50_gr_object }, + {} + } +}; + +int +g84_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv50_gr_new_(&g84_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5606c25e5..9f5dfc851 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -26,13 +26,12 @@ #include "fuc/os.h" #include -#include -#include #include -#include #include #include +#include #include +#include #include #include @@ -42,35 +41,36 @@ ******************************************************************************/ static void -gf100_gr_zbc_clear_color(struct gf100_gr_priv *priv, int zbc) +gf100_gr_zbc_clear_color(struct gf100_gr *gr, int zbc) { - if (priv->zbc_color[zbc].format) { - nv_wr32(priv, 0x405804, priv->zbc_color[zbc].ds[0]); - nv_wr32(priv, 0x405808, priv->zbc_color[zbc].ds[1]); - nv_wr32(priv, 0x40580c, priv->zbc_color[zbc].ds[2]); - nv_wr32(priv, 0x405810, priv->zbc_color[zbc].ds[3]); - } - nv_wr32(priv, 0x405814, priv->zbc_color[zbc].format); - nv_wr32(priv, 0x405820, zbc); - nv_wr32(priv, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */ + struct nvkm_device *device = gr->base.engine.subdev.device; + if (gr->zbc_color[zbc].format) { + nvkm_wr32(device, 0x405804, gr->zbc_color[zbc].ds[0]); + nvkm_wr32(device, 0x405808, gr->zbc_color[zbc].ds[1]); + nvkm_wr32(device, 0x40580c, gr->zbc_color[zbc].ds[2]); + nvkm_wr32(device, 0x405810, gr->zbc_color[zbc].ds[3]); + } + nvkm_wr32(device, 0x405814, gr->zbc_color[zbc].format); + nvkm_wr32(device, 0x405820, zbc); + nvkm_wr32(device, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */ } static int -gf100_gr_zbc_color_get(struct gf100_gr_priv *priv, int format, +gf100_gr_zbc_color_get(struct gf100_gr *gr, int format, const u32 ds[4], const u32 l2[4]) { - struct nvkm_ltc *ltc = nvkm_ltc(priv); + struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; int zbc = -ENOSPC, i; for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { - if (priv->zbc_color[i].format) { - if (priv->zbc_color[i].format != format) + if (gr->zbc_color[i].format) { + if (gr->zbc_color[i].format != format) continue; - if (memcmp(priv->zbc_color[i].ds, ds, sizeof( - priv->zbc_color[i].ds))) + if (memcmp(gr->zbc_color[i].ds, ds, sizeof( + gr->zbc_color[i].ds))) continue; - if (memcmp(priv->zbc_color[i].l2, l2, sizeof( - priv->zbc_color[i].l2))) { + if (memcmp(gr->zbc_color[i].l2, l2, sizeof( + gr->zbc_color[i].l2))) { WARN_ON(1); return -EINVAL; } @@ -83,38 +83,39 @@ gf100_gr_zbc_color_get(struct gf100_gr_priv *priv, int format, if (zbc < 0) return zbc; - memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds)); - memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2)); - priv->zbc_color[zbc].format = format; - ltc->zbc_color_get(ltc, zbc, l2); - gf100_gr_zbc_clear_color(priv, zbc); + memcpy(gr->zbc_color[zbc].ds, ds, sizeof(gr->zbc_color[zbc].ds)); + memcpy(gr->zbc_color[zbc].l2, l2, sizeof(gr->zbc_color[zbc].l2)); + gr->zbc_color[zbc].format = format; + nvkm_ltc_zbc_color_get(ltc, zbc, l2); + gf100_gr_zbc_clear_color(gr, zbc); return zbc; } static void -gf100_gr_zbc_clear_depth(struct gf100_gr_priv *priv, int zbc) +gf100_gr_zbc_clear_depth(struct gf100_gr *gr, int zbc) { - if (priv->zbc_depth[zbc].format) - nv_wr32(priv, 0x405818, priv->zbc_depth[zbc].ds); - nv_wr32(priv, 0x40581c, priv->zbc_depth[zbc].format); - nv_wr32(priv, 0x405820, zbc); - nv_wr32(priv, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */ + struct nvkm_device *device = gr->base.engine.subdev.device; + if (gr->zbc_depth[zbc].format) + nvkm_wr32(device, 0x405818, gr->zbc_depth[zbc].ds); + nvkm_wr32(device, 0x40581c, gr->zbc_depth[zbc].format); + nvkm_wr32(device, 0x405820, zbc); + nvkm_wr32(device, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */ } static int -gf100_gr_zbc_depth_get(struct gf100_gr_priv *priv, int format, +gf100_gr_zbc_depth_get(struct gf100_gr *gr, int format, const u32 ds, const u32 l2) { - struct nvkm_ltc *ltc = nvkm_ltc(priv); + struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; int zbc = -ENOSPC, i; for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { - if (priv->zbc_depth[i].format) { - if (priv->zbc_depth[i].format != format) + if (gr->zbc_depth[i].format) { + if (gr->zbc_depth[i].format != format) continue; - if (priv->zbc_depth[i].ds != ds) + if (gr->zbc_depth[i].ds != ds) continue; - if (priv->zbc_depth[i].l2 != l2) { + if (gr->zbc_depth[i].l2 != l2) { WARN_ON(1); return -EINVAL; } @@ -127,11 +128,11 @@ gf100_gr_zbc_depth_get(struct gf100_gr_priv *priv, int format, if (zbc < 0) return zbc; - priv->zbc_depth[zbc].format = format; - priv->zbc_depth[zbc].ds = ds; - priv->zbc_depth[zbc].l2 = l2; - ltc->zbc_depth_get(ltc, zbc, l2); - gf100_gr_zbc_clear_depth(priv, zbc); + gr->zbc_depth[zbc].format = format; + gr->zbc_depth[zbc].ds = ds; + gr->zbc_depth[zbc].l2 = l2; + nvkm_ltc_zbc_depth_get(ltc, zbc, l2); + gf100_gr_zbc_clear_depth(gr, zbc); return zbc; } @@ -142,7 +143,7 @@ gf100_gr_zbc_depth_get(struct gf100_gr_priv *priv, int format, static int gf100_fermi_mthd_zbc_color(struct nvkm_object *object, void *data, u32 size) { - struct gf100_gr_priv *priv = (void *)object->engine; + struct gf100_gr *gr = gf100_gr(nvkm_gr(object->engine)); union { struct fermi_a_zbc_color_v0 v0; } *args = data; @@ -169,7 +170,7 @@ gf100_fermi_mthd_zbc_color(struct nvkm_object *object, void *data, u32 size) case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8: case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10: case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11: - ret = gf100_gr_zbc_color_get(priv, args->v0.format, + ret = gf100_gr_zbc_color_get(gr, args->v0.format, args->v0.ds, args->v0.l2); if (ret >= 0) { @@ -188,7 +189,7 @@ gf100_fermi_mthd_zbc_color(struct nvkm_object *object, void *data, u32 size) static int gf100_fermi_mthd_zbc_depth(struct nvkm_object *object, void *data, u32 size) { - struct gf100_gr_priv *priv = (void *)object->engine; + struct gf100_gr *gr = gf100_gr(nvkm_gr(object->engine)); union { struct fermi_a_zbc_depth_v0 v0; } *args = data; @@ -197,7 +198,7 @@ gf100_fermi_mthd_zbc_depth(struct nvkm_object *object, void *data, u32 size) if (nvif_unpack(args->v0, 0, 0, false)) { switch (args->v0.format) { case FERMI_A_ZBC_DEPTH_V0_FMT_FP32: - ret = gf100_gr_zbc_depth_get(priv, args->v0.format, + ret = gf100_gr_zbc_depth_get(gr, args->v0.format, args->v0.ds, args->v0.l2); return (ret >= 0) ? 0 : -ENOSPC; @@ -223,106 +224,176 @@ gf100_fermi_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } -struct nvkm_ofuncs -gf100_fermi_ofuncs = { - .ctor = _nvkm_object_ctor, - .dtor = nvkm_object_destroy, - .init = nvkm_object_init, - .fini = nvkm_object_fini, +const struct nvkm_object_func +gf100_fermi = { .mthd = gf100_fermi_mthd, }; -static int -gf100_gr_set_shader_exceptions(struct nvkm_object *object, u32 mthd, - void *pdata, u32 size) +static void +gf100_gr_mthd_set_shader_exceptions(struct nvkm_device *device, u32 data) { - struct gf100_gr_priv *priv = (void *)object->engine; - if (size >= sizeof(u32)) { - u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000; - nv_wr32(priv, 0x419e44, data); - nv_wr32(priv, 0x419e4c, data); - return 0; + nvkm_wr32(device, 0x419e44, data ? 0xffffffff : 0x00000000); + nvkm_wr32(device, 0x419e4c, data ? 0xffffffff : 0x00000000); +} + +static bool +gf100_gr_mthd_sw(struct nvkm_device *device, u16 class, u32 mthd, u32 data) +{ + switch (class & 0x00ff) { + case 0x97: + case 0xc0: + switch (mthd) { + case 0x1528: + gf100_gr_mthd_set_shader_exceptions(device, data); + return true; + default: + break; + } + break; + default: + break; } - return -EINVAL; + return false; } -struct nvkm_omthds -gf100_gr_9097_omthds[] = { - { 0x1528, 0x1528, gf100_gr_set_shader_exceptions }, - {} -}; +static int +gf100_gr_object_get(struct nvkm_gr *base, int index, struct nvkm_sclass *sclass) +{ + struct gf100_gr *gr = gf100_gr(base); + int c = 0; -struct nvkm_omthds -gf100_gr_90c0_omthds[] = { - { 0x1528, 0x1528, gf100_gr_set_shader_exceptions }, - {} -}; + while (gr->func->sclass[c].oclass) { + if (c++ == index) { + *sclass = gr->func->sclass[index]; + return index; + } + } -struct nvkm_oclass -gf100_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs }, - { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; + return c; +} /******************************************************************************* * PGRAPH context ******************************************************************************/ -int -gf100_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *args, u32 size, - struct nvkm_object **pobject) +static int +gf100_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_vm *vm = nvkm_client(parent)->vm; - struct gf100_gr_priv *priv = (void *)engine; - struct gf100_gr_data *data = priv->mmio_data; - struct gf100_gr_mmio *mmio = priv->mmio_list; - struct gf100_gr_chan *chan; + struct gf100_gr_chan *chan = gf100_gr_chan(object); + struct gf100_gr *gr = chan->gr; int ret, i; - /* allocate memory for context, and fill with default values */ - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, - priv->size, 0x100, - NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + ret = nvkm_gpuobj_new(gr->base.engine.subdev.device, gr->size, + align, false, parent, pgpuobj); if (ret) return ret; + nvkm_kmap(*pgpuobj); + for (i = 0; i < gr->size; i += 4) + nvkm_wo32(*pgpuobj, i, gr->data[i / 4]); + + if (!gr->firmware) { + nvkm_wo32(*pgpuobj, 0x00, chan->mmio_nr / 2); + nvkm_wo32(*pgpuobj, 0x04, chan->mmio_vma.offset >> 8); + } else { + nvkm_wo32(*pgpuobj, 0xf4, 0); + nvkm_wo32(*pgpuobj, 0xf8, 0); + nvkm_wo32(*pgpuobj, 0x10, chan->mmio_nr / 2); + nvkm_wo32(*pgpuobj, 0x14, lower_32_bits(chan->mmio_vma.offset)); + nvkm_wo32(*pgpuobj, 0x18, upper_32_bits(chan->mmio_vma.offset)); + nvkm_wo32(*pgpuobj, 0x1c, 1); + nvkm_wo32(*pgpuobj, 0x20, 0); + nvkm_wo32(*pgpuobj, 0x28, 0); + nvkm_wo32(*pgpuobj, 0x2c, 0); + } + nvkm_done(*pgpuobj); + return 0; +} + +static void * +gf100_gr_chan_dtor(struct nvkm_object *object) +{ + struct gf100_gr_chan *chan = gf100_gr_chan(object); + int i; + + for (i = 0; i < ARRAY_SIZE(chan->data); i++) { + if (chan->data[i].vma.node) { + nvkm_vm_unmap(&chan->data[i].vma); + nvkm_vm_put(&chan->data[i].vma); + } + nvkm_memory_del(&chan->data[i].mem); + } + + if (chan->mmio_vma.node) { + nvkm_vm_unmap(&chan->mmio_vma); + nvkm_vm_put(&chan->mmio_vma); + } + nvkm_memory_del(&chan->mmio); + return chan; +} + +static const struct nvkm_object_func +gf100_gr_chan = { + .dtor = gf100_gr_chan_dtor, + .bind = gf100_gr_chan_bind, +}; + +static int +gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct gf100_gr *gr = gf100_gr(base); + struct gf100_gr_data *data = gr->mmio_data; + struct gf100_gr_mmio *mmio = gr->mmio_list; + struct gf100_gr_chan *chan; + struct nvkm_device *device = gr->base.engine.subdev.device; + int ret, i; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&gf100_gr_chan, oclass, &chan->object); + chan->gr = gr; + *pobject = &chan->object; + /* allocate memory for a "mmio list" buffer that's used by the HUB * fuc to modify some per-context register settings on first load * of the context. */ - ret = nvkm_gpuobj_new(nv_object(chan), NULL, 0x1000, 0x100, 0, - &chan->mmio); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x100, + false, &chan->mmio); if (ret) return ret; - ret = nvkm_gpuobj_map_vm(nv_gpuobj(chan->mmio), vm, - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &chan->mmio_vma); + ret = nvkm_vm_get(fifoch->vm, 0x1000, 12, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &chan->mmio_vma); if (ret) return ret; + nvkm_memory_map(chan->mmio, &chan->mmio_vma, 0); + /* allocate buffers referenced by mmio list */ - for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) { - ret = nvkm_gpuobj_new(nv_object(chan), NULL, data->size, - data->align, 0, &chan->data[i].mem); + for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) { + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + data->size, data->align, false, + &chan->data[i].mem); if (ret) return ret; - ret = nvkm_gpuobj_map_vm(chan->data[i].mem, vm, data->access, - &chan->data[i].vma); + ret = nvkm_vm_get(fifoch->vm, + nvkm_memory_size(chan->data[i].mem), 12, + data->access, &chan->data[i].vma); if (ret) return ret; + nvkm_memory_map(chan->data[i].mem, &chan->data[i].vma, 0); data++; } /* finally, fill in the mmio list and point the context at it */ - for (i = 0; mmio->addr && i < ARRAY_SIZE(priv->mmio_list); i++) { + nvkm_kmap(chan->mmio); + for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) { u32 addr = mmio->addr; u32 data = mmio->data; @@ -331,49 +402,14 @@ gf100_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, data |= info >> mmio->shift; } - nv_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); - nv_wo32(chan->mmio, chan->mmio_nr++ * 4, data); + nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); + nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data); mmio++; } - - for (i = 0; i < priv->size; i += 4) - nv_wo32(chan, i, priv->data[i / 4]); - - if (!priv->firmware) { - nv_wo32(chan, 0x00, chan->mmio_nr / 2); - nv_wo32(chan, 0x04, chan->mmio_vma.offset >> 8); - } else { - nv_wo32(chan, 0xf4, 0); - nv_wo32(chan, 0xf8, 0); - nv_wo32(chan, 0x10, chan->mmio_nr / 2); - nv_wo32(chan, 0x14, lower_32_bits(chan->mmio_vma.offset)); - nv_wo32(chan, 0x18, upper_32_bits(chan->mmio_vma.offset)); - nv_wo32(chan, 0x1c, 1); - nv_wo32(chan, 0x20, 0); - nv_wo32(chan, 0x28, 0); - nv_wo32(chan, 0x2c, 0); - } - + nvkm_done(chan->mmio); return 0; } -void -gf100_gr_context_dtor(struct nvkm_object *object) -{ - struct gf100_gr_chan *chan = (void *)object; - int i; - - for (i = 0; i < ARRAY_SIZE(chan->data); i++) { - nvkm_gpuobj_unmap(&chan->data[i].vma); - nvkm_gpuobj_ref(NULL, &chan->data[i].mem); - } - - nvkm_gpuobj_unmap(&chan->mmio_vma); - nvkm_gpuobj_ref(NULL, &chan->mmio); - - nvkm_gr_context_destroy(&chan->base); -} - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -635,7 +671,7 @@ gf100_gr_pack_mmio[] = { ******************************************************************************/ void -gf100_gr_zbc_init(struct gf100_gr_priv *priv) +gf100_gr_zbc_init(struct gf100_gr *gr) { const u32 zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; @@ -645,27 +681,62 @@ gf100_gr_zbc_init(struct gf100_gr_priv *priv) 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; - struct nvkm_ltc *ltc = nvkm_ltc(priv); + struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc; int index; - if (!priv->zbc_color[0].format) { - gf100_gr_zbc_color_get(priv, 1, & zero[0], &zero[4]); - gf100_gr_zbc_color_get(priv, 2, & one[0], &one[4]); - gf100_gr_zbc_color_get(priv, 4, &f32_0[0], &f32_0[4]); - gf100_gr_zbc_color_get(priv, 4, &f32_1[0], &f32_1[4]); - gf100_gr_zbc_depth_get(priv, 1, 0x00000000, 0x00000000); - gf100_gr_zbc_depth_get(priv, 1, 0x3f800000, 0x3f800000); + if (!gr->zbc_color[0].format) { + gf100_gr_zbc_color_get(gr, 1, & zero[0], &zero[4]); + gf100_gr_zbc_color_get(gr, 2, & one[0], &one[4]); + gf100_gr_zbc_color_get(gr, 4, &f32_0[0], &f32_0[4]); + gf100_gr_zbc_color_get(gr, 4, &f32_1[0], &f32_1[4]); + gf100_gr_zbc_depth_get(gr, 1, 0x00000000, 0x00000000); + gf100_gr_zbc_depth_get(gr, 1, 0x3f800000, 0x3f800000); } for (index = ltc->zbc_min; index <= ltc->zbc_max; index++) - gf100_gr_zbc_clear_color(priv, index); + gf100_gr_zbc_clear_color(gr, index); for (index = ltc->zbc_min; index <= ltc->zbc_max; index++) - gf100_gr_zbc_clear_depth(priv, index); + gf100_gr_zbc_clear_depth(gr, index); +} + +/** + * Wait until GR goes idle. GR is considered idle if it is disabled by the + * MC (0x200) register, or GR is not busy and a context switch is not in + * progress. + */ +int +gf100_gr_wait_idle(struct gf100_gr *gr) +{ + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000); + bool gr_enabled, ctxsw_active, gr_busy; + + do { + /* + * required to make sure FIFO_ENGINE_STATUS (0x2640) is + * up-to-date + */ + nvkm_rd32(device, 0x400700); + + gr_enabled = nvkm_rd32(device, 0x200) & 0x1000; + ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000; + gr_busy = nvkm_rd32(device, 0x40060c) & 0x1; + + if (!gr_enabled || (!gr_busy && !ctxsw_active)) + return 0; + } while (time_before(jiffies, end_jiffies)); + + nvkm_error(subdev, + "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n", + gr_enabled, ctxsw_active, gr_busy); + return -EAGAIN; } void -gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) +gf100_gr_mmio(struct gf100_gr *gr, const struct gf100_gr_pack *p) { + struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_gr_pack *pack; const struct gf100_gr_init *init; @@ -673,43 +744,54 @@ gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) u32 next = init->addr + init->count * init->pitch; u32 addr = init->addr; while (addr < next) { - nv_wr32(priv, addr, init->data); + nvkm_wr32(device, addr, init->data); addr += init->pitch; } } } void -gf100_gr_icmd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) +gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p) { + struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_gr_pack *pack; const struct gf100_gr_init *init; u32 data = 0; - nv_wr32(priv, 0x400208, 0x80000000); + nvkm_wr32(device, 0x400208, 0x80000000); pack_for_each_init(init, pack, p) { u32 next = init->addr + init->count * init->pitch; u32 addr = init->addr; if ((pack == p && init == p->init) || data != init->data) { - nv_wr32(priv, 0x400204, init->data); + nvkm_wr32(device, 0x400204, init->data); data = init->data; } while (addr < next) { - nv_wr32(priv, 0x400200, addr); - nv_wait(priv, 0x400700, 0x00000002, 0x00000000); + nvkm_wr32(device, 0x400200, addr); + /** + * Wait for GR to go idle after submitting a + * GO_IDLE bundle + */ + if ((addr & 0xffff) == 0xe100) + gf100_gr_wait_idle(gr); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x400700) & 0x00000004)) + break; + ); addr += init->pitch; } } - nv_wr32(priv, 0x400208, 0x00000000); + nvkm_wr32(device, 0x400208, 0x00000000); } void -gf100_gr_mthd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) +gf100_gr_mthd(struct gf100_gr *gr, const struct gf100_gr_pack *p) { + struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_gr_pack *pack; const struct gf100_gr_init *init; u32 data = 0; @@ -720,79 +802,75 @@ gf100_gr_mthd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) u32 addr = init->addr; if ((pack == p && init == p->init) || data != init->data) { - nv_wr32(priv, 0x40448c, init->data); + nvkm_wr32(device, 0x40448c, init->data); data = init->data; } while (addr < next) { - nv_wr32(priv, 0x404488, ctrl | (addr << 14)); + nvkm_wr32(device, 0x404488, ctrl | (addr << 14)); addr += init->pitch; } } } u64 -gf100_gr_units(struct nvkm_gr *gr) +gf100_gr_units(struct nvkm_gr *base) { - struct gf100_gr_priv *priv = (void *)gr; + struct gf100_gr *gr = gf100_gr(base); u64 cfg; - cfg = (u32)priv->gpc_nr; - cfg |= (u32)priv->tpc_total << 8; - cfg |= (u64)priv->rop_nr << 32; + cfg = (u32)gr->gpc_nr; + cfg |= (u32)gr->tpc_total << 8; + cfg |= (u64)gr->rop_nr << 32; return cfg; } -static const struct nvkm_enum gk104_sked_error[] = { - { 7, "CONSTANT_BUFFER_SIZE" }, - { 9, "LOCAL_MEMORY_SIZE_POS" }, - { 10, "LOCAL_MEMORY_SIZE_NEG" }, - { 11, "WARP_CSTACK_SIZE" }, - { 12, "TOTAL_TEMP_SIZE" }, - { 13, "REGISTER_COUNT" }, - { 18, "TOTAL_THREADS" }, - { 20, "PROGRAM_OFFSET" }, - { 21, "SHARED_MEMORY_SIZE" }, - { 25, "SHARED_CONFIG_TOO_SMALL" }, - { 26, "TOTAL_REGISTER_COUNT" }, +static const struct nvkm_bitfield gk104_sked_error[] = { + { 0x00000080, "CONSTANT_BUFFER_SIZE" }, + { 0x00000200, "LOCAL_MEMORY_SIZE_POS" }, + { 0x00000400, "LOCAL_MEMORY_SIZE_NEG" }, + { 0x00000800, "WARP_CSTACK_SIZE" }, + { 0x00001000, "TOTAL_TEMP_SIZE" }, + { 0x00002000, "REGISTER_COUNT" }, + { 0x00040000, "TOTAL_THREADS" }, + { 0x00100000, "PROGRAM_OFFSET" }, + { 0x00200000, "SHARED_MEMORY_SIZE" }, + { 0x02000000, "SHARED_CONFIG_TOO_SMALL" }, + { 0x04000000, "TOTAL_REGISTER_COUNT" }, {} }; -static const struct nvkm_enum gf100_gpc_rop_error[] = { - { 1, "RT_PITCH_OVERRUN" }, - { 4, "RT_WIDTH_OVERRUN" }, - { 5, "RT_HEIGHT_OVERRUN" }, - { 7, "ZETA_STORAGE_TYPE_MISMATCH" }, - { 8, "RT_STORAGE_TYPE_MISMATCH" }, - { 10, "RT_LINEAR_MISMATCH" }, +static const struct nvkm_bitfield gf100_gpc_rop_error[] = { + { 0x00000002, "RT_PITCH_OVERRUN" }, + { 0x00000010, "RT_WIDTH_OVERRUN" }, + { 0x00000020, "RT_HEIGHT_OVERRUN" }, + { 0x00000080, "ZETA_STORAGE_TYPE_MISMATCH" }, + { 0x00000100, "RT_STORAGE_TYPE_MISMATCH" }, + { 0x00000400, "RT_LINEAR_MISMATCH" }, {} }; static void -gf100_gr_trap_gpc_rop(struct gf100_gr_priv *priv, int gpc) +gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc) { + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + char error[128]; u32 trap[4]; - int i; - trap[0] = nv_rd32(priv, GPC_UNIT(gpc, 0x0420)); - trap[1] = nv_rd32(priv, GPC_UNIT(gpc, 0x0434)); - trap[2] = nv_rd32(priv, GPC_UNIT(gpc, 0x0438)); - trap[3] = nv_rd32(priv, GPC_UNIT(gpc, 0x043c)); + trap[0] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0420)) & 0x3fffffff; + trap[1] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0434)); + trap[2] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0438)); + trap[3] = nvkm_rd32(device, GPC_UNIT(gpc, 0x043c)); - nv_error(priv, "GPC%d/PROP trap:", gpc); - for (i = 0; i <= 29; ++i) { - if (!(trap[0] & (1 << i))) - continue; - pr_cont(" "); - nvkm_enum_print(gf100_gpc_rop_error, i); - } - pr_cont("\n"); + nvkm_snprintbf(error, sizeof(error), gf100_gpc_rop_error, trap[0]); - nv_error(priv, "x = %u, y = %u, format = %x, storage type = %x\n", - trap[1] & 0xffff, trap[1] >> 16, (trap[2] >> 8) & 0x3f, - trap[3] & 0xff); - nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nvkm_error(subdev, "GPC%d/PROP trap: %08x [%s] x = %u, y = %u, " + "format = %x, storage type = %x\n", + gpc, trap[0], error, trap[1] & 0xffff, trap[1] >> 16, + (trap[2] >> 8) & 0x3f, trap[3] & 0xff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000); } static const struct nvkm_enum gf100_mp_warp_error[] = { @@ -804,6 +882,7 @@ static const struct nvkm_enum gf100_mp_warp_error[] = { { 0x0d, "GPR_OUT_OF_BOUNDS" }, { 0x0e, "MEM_OUT_OF_BOUNDS" }, { 0x0f, "UNALIGNED_MEM_ACCESS" }, + { 0x10, "INVALID_ADDR_SPACE" }, { 0x11, "INVALID_PARAM" }, {} }; @@ -815,401 +894,418 @@ static const struct nvkm_bitfield gf100_mp_global_error[] = { }; static void -gf100_gr_trap_mp(struct gf100_gr_priv *priv, int gpc, int tpc) +gf100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc) { - u32 werr = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x648)); - u32 gerr = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x650)); - - nv_error(priv, "GPC%i/TPC%i/MP trap:", gpc, tpc); - nvkm_bitfield_print(gf100_mp_global_error, gerr); - if (werr) { - pr_cont(" "); - nvkm_enum_print(gf100_mp_warp_error, werr & 0xffff); - } - pr_cont("\n"); - - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x648), 0x00000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x650), gerr); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 werr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x648)); + u32 gerr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x650)); + const struct nvkm_enum *warp; + char glob[128]; + + nvkm_snprintbf(glob, sizeof(glob), gf100_mp_global_error, gerr); + warp = nvkm_enum_find(gf100_mp_warp_error, werr & 0xffff); + + nvkm_error(subdev, "GPC%i/TPC%i/MP trap: " + "global %08x [%s] warp %04x [%s]\n", + gpc, tpc, gerr, glob, werr, warp ? warp->name : ""); + + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x648), 0x00000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x650), gerr); } static void -gf100_gr_trap_tpc(struct gf100_gr_priv *priv, int gpc, int tpc) +gf100_gr_trap_tpc(struct gf100_gr *gr, int gpc, int tpc) { - u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0508)); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0508)); if (stat & 0x00000001) { - u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0224)); - nv_error(priv, "GPC%d/TPC%d/TEX: 0x%08x\n", gpc, tpc, trap); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000); + u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0224)); + nvkm_error(subdev, "GPC%d/TPC%d/TEX: %08x\n", gpc, tpc, trap); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000); stat &= ~0x00000001; } if (stat & 0x00000002) { - gf100_gr_trap_mp(priv, gpc, tpc); + gf100_gr_trap_mp(gr, gpc, tpc); stat &= ~0x00000002; } if (stat & 0x00000004) { - u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0084)); - nv_error(priv, "GPC%d/TPC%d/POLY: 0x%08x\n", gpc, tpc, trap); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000); + u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0084)); + nvkm_error(subdev, "GPC%d/TPC%d/POLY: %08x\n", gpc, tpc, trap); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000); stat &= ~0x00000004; } if (stat & 0x00000008) { - u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x048c)); - nv_error(priv, "GPC%d/TPC%d/L1C: 0x%08x\n", gpc, tpc, trap); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000); + u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x048c)); + nvkm_error(subdev, "GPC%d/TPC%d/L1C: %08x\n", gpc, tpc, trap); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000); stat &= ~0x00000008; } if (stat) { - nv_error(priv, "GPC%d/TPC%d/0x%08x: unknown\n", gpc, tpc, stat); + nvkm_error(subdev, "GPC%d/TPC%d/%08x: unknown\n", gpc, tpc, stat); } } static void -gf100_gr_trap_gpc(struct gf100_gr_priv *priv, int gpc) +gf100_gr_trap_gpc(struct gf100_gr *gr, int gpc) { - u32 stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90)); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, GPC_UNIT(gpc, 0x2c90)); int tpc; if (stat & 0x00000001) { - gf100_gr_trap_gpc_rop(priv, gpc); + gf100_gr_trap_gpc_rop(gr, gpc); stat &= ~0x00000001; } if (stat & 0x00000002) { - u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900)); - nv_error(priv, "GPC%d/ZCULL: 0x%08x\n", gpc, trap); - nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0900)); + nvkm_error(subdev, "GPC%d/ZCULL: %08x\n", gpc, trap); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000); stat &= ~0x00000002; } if (stat & 0x00000004) { - u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028)); - nv_error(priv, "GPC%d/CCACHE: 0x%08x\n", gpc, trap); - nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x1028)); + nvkm_error(subdev, "GPC%d/CCACHE: %08x\n", gpc, trap); + nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000); stat &= ~0x00000004; } if (stat & 0x00000008) { - u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824)); - nv_error(priv, "GPC%d/ESETUP: 0x%08x\n", gpc, trap); - nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); + u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0824)); + nvkm_error(subdev, "GPC%d/ESETUP: %08x\n", gpc, trap); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000); stat &= ~0x00000009; } - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { u32 mask = 0x00010000 << tpc; if (stat & mask) { - gf100_gr_trap_tpc(priv, gpc, tpc); - nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), mask); + gf100_gr_trap_tpc(gr, gpc, tpc); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), mask); stat &= ~mask; } } if (stat) { - nv_error(priv, "GPC%d/0x%08x: unknown\n", gpc, stat); + nvkm_error(subdev, "GPC%d/%08x: unknown\n", gpc, stat); } } static void -gf100_gr_trap_intr(struct gf100_gr_priv *priv) +gf100_gr_trap_intr(struct gf100_gr *gr) { - u32 trap = nv_rd32(priv, 0x400108); - int rop, gpc, i; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 trap = nvkm_rd32(device, 0x400108); + int rop, gpc; if (trap & 0x00000001) { - u32 stat = nv_rd32(priv, 0x404000); - nv_error(priv, "DISPATCH 0x%08x\n", stat); - nv_wr32(priv, 0x404000, 0xc0000000); - nv_wr32(priv, 0x400108, 0x00000001); + u32 stat = nvkm_rd32(device, 0x404000); + nvkm_error(subdev, "DISPATCH %08x\n", stat); + nvkm_wr32(device, 0x404000, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x00000001); trap &= ~0x00000001; } if (trap & 0x00000002) { - u32 stat = nv_rd32(priv, 0x404600); - nv_error(priv, "M2MF 0x%08x\n", stat); - nv_wr32(priv, 0x404600, 0xc0000000); - nv_wr32(priv, 0x400108, 0x00000002); + u32 stat = nvkm_rd32(device, 0x404600); + nvkm_error(subdev, "M2MF %08x\n", stat); + nvkm_wr32(device, 0x404600, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x00000002); trap &= ~0x00000002; } if (trap & 0x00000008) { - u32 stat = nv_rd32(priv, 0x408030); - nv_error(priv, "CCACHE 0x%08x\n", stat); - nv_wr32(priv, 0x408030, 0xc0000000); - nv_wr32(priv, 0x400108, 0x00000008); + u32 stat = nvkm_rd32(device, 0x408030); + nvkm_error(subdev, "CCACHE %08x\n", stat); + nvkm_wr32(device, 0x408030, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x00000008); trap &= ~0x00000008; } if (trap & 0x00000010) { - u32 stat = nv_rd32(priv, 0x405840); - nv_error(priv, "SHADER 0x%08x\n", stat); - nv_wr32(priv, 0x405840, 0xc0000000); - nv_wr32(priv, 0x400108, 0x00000010); + u32 stat = nvkm_rd32(device, 0x405840); + nvkm_error(subdev, "SHADER %08x\n", stat); + nvkm_wr32(device, 0x405840, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x00000010); trap &= ~0x00000010; } if (trap & 0x00000040) { - u32 stat = nv_rd32(priv, 0x40601c); - nv_error(priv, "UNK6 0x%08x\n", stat); - nv_wr32(priv, 0x40601c, 0xc0000000); - nv_wr32(priv, 0x400108, 0x00000040); + u32 stat = nvkm_rd32(device, 0x40601c); + nvkm_error(subdev, "UNK6 %08x\n", stat); + nvkm_wr32(device, 0x40601c, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x00000040); trap &= ~0x00000040; } if (trap & 0x00000080) { - u32 stat = nv_rd32(priv, 0x404490); - nv_error(priv, "MACRO 0x%08x\n", stat); - nv_wr32(priv, 0x404490, 0xc0000000); - nv_wr32(priv, 0x400108, 0x00000080); + u32 stat = nvkm_rd32(device, 0x404490); + nvkm_error(subdev, "MACRO %08x\n", stat); + nvkm_wr32(device, 0x404490, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x00000080); trap &= ~0x00000080; } if (trap & 0x00000100) { - u32 stat = nv_rd32(priv, 0x407020); + u32 stat = nvkm_rd32(device, 0x407020) & 0x3fffffff; + char sked[128]; - nv_error(priv, "SKED:"); - for (i = 0; i <= 29; ++i) { - if (!(stat & (1 << i))) - continue; - pr_cont(" "); - nvkm_enum_print(gk104_sked_error, i); - } - pr_cont("\n"); + nvkm_snprintbf(sked, sizeof(sked), gk104_sked_error, stat); + nvkm_error(subdev, "SKED: %08x [%s]\n", stat, sked); - if (stat & 0x3fffffff) - nv_wr32(priv, 0x407020, 0x40000000); - nv_wr32(priv, 0x400108, 0x00000100); + if (stat) + nvkm_wr32(device, 0x407020, 0x40000000); + nvkm_wr32(device, 0x400108, 0x00000100); trap &= ~0x00000100; } if (trap & 0x01000000) { - u32 stat = nv_rd32(priv, 0x400118); - for (gpc = 0; stat && gpc < priv->gpc_nr; gpc++) { + u32 stat = nvkm_rd32(device, 0x400118); + for (gpc = 0; stat && gpc < gr->gpc_nr; gpc++) { u32 mask = 0x00000001 << gpc; if (stat & mask) { - gf100_gr_trap_gpc(priv, gpc); - nv_wr32(priv, 0x400118, mask); + gf100_gr_trap_gpc(gr, gpc); + nvkm_wr32(device, 0x400118, mask); stat &= ~mask; } } - nv_wr32(priv, 0x400108, 0x01000000); + nvkm_wr32(device, 0x400108, 0x01000000); trap &= ~0x01000000; } if (trap & 0x02000000) { - for (rop = 0; rop < priv->rop_nr; rop++) { - u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); - u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); - nv_error(priv, "ROP%d 0x%08x 0x%08x\n", + for (rop = 0; rop < gr->rop_nr; rop++) { + u32 statz = nvkm_rd32(device, ROP_UNIT(rop, 0x070)); + u32 statc = nvkm_rd32(device, ROP_UNIT(rop, 0x144)); + nvkm_error(subdev, "ROP%d %08x %08x\n", rop, statz, statc); - nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000); } - nv_wr32(priv, 0x400108, 0x02000000); + nvkm_wr32(device, 0x400108, 0x02000000); trap &= ~0x02000000; } if (trap) { - nv_error(priv, "TRAP UNHANDLED 0x%08x\n", trap); - nv_wr32(priv, 0x400108, trap); + nvkm_error(subdev, "TRAP UNHANDLED %08x\n", trap); + nvkm_wr32(device, 0x400108, trap); } } static void -gf100_gr_ctxctl_debug_unit(struct gf100_gr_priv *priv, u32 base) +gf100_gr_ctxctl_debug_unit(struct gf100_gr *gr, u32 base) { - nv_error(priv, "%06x - done 0x%08x\n", base, - nv_rd32(priv, base + 0x400)); - nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(priv, base + 0x800), nv_rd32(priv, base + 0x804), - nv_rd32(priv, base + 0x808), nv_rd32(priv, base + 0x80c)); - nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(priv, base + 0x810), nv_rd32(priv, base + 0x814), - nv_rd32(priv, base + 0x818), nv_rd32(priv, base + 0x81c)); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + nvkm_error(subdev, "%06x - done %08x\n", base, + nvkm_rd32(device, base + 0x400)); + nvkm_error(subdev, "%06x - stat %08x %08x %08x %08x\n", base, + nvkm_rd32(device, base + 0x800), + nvkm_rd32(device, base + 0x804), + nvkm_rd32(device, base + 0x808), + nvkm_rd32(device, base + 0x80c)); + nvkm_error(subdev, "%06x - stat %08x %08x %08x %08x\n", base, + nvkm_rd32(device, base + 0x810), + nvkm_rd32(device, base + 0x814), + nvkm_rd32(device, base + 0x818), + nvkm_rd32(device, base + 0x81c)); } void -gf100_gr_ctxctl_debug(struct gf100_gr_priv *priv) +gf100_gr_ctxctl_debug(struct gf100_gr *gr) { - u32 gpcnr = nv_rd32(priv, 0x409604) & 0xffff; + struct nvkm_device *device = gr->base.engine.subdev.device; + u32 gpcnr = nvkm_rd32(device, 0x409604) & 0xffff; u32 gpc; - gf100_gr_ctxctl_debug_unit(priv, 0x409000); + gf100_gr_ctxctl_debug_unit(gr, 0x409000); for (gpc = 0; gpc < gpcnr; gpc++) - gf100_gr_ctxctl_debug_unit(priv, 0x502000 + (gpc * 0x8000)); + gf100_gr_ctxctl_debug_unit(gr, 0x502000 + (gpc * 0x8000)); } static void -gf100_gr_ctxctl_isr(struct gf100_gr_priv *priv) +gf100_gr_ctxctl_isr(struct gf100_gr *gr) { - u32 stat = nv_rd32(priv, 0x409c18); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x409c18); if (stat & 0x00000001) { - u32 code = nv_rd32(priv, 0x409814); + u32 code = nvkm_rd32(device, 0x409814); if (code == E_BAD_FWMTHD) { - u32 class = nv_rd32(priv, 0x409808); - u32 addr = nv_rd32(priv, 0x40980c); + u32 class = nvkm_rd32(device, 0x409808); + u32 addr = nvkm_rd32(device, 0x40980c); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); - u32 data = nv_rd32(priv, 0x409810); + u32 data = nvkm_rd32(device, 0x409810); - nv_error(priv, "FECS MTHD subc %d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - subc, class, mthd, data); + nvkm_error(subdev, "FECS MTHD subc %d class %04x " + "mthd %04x data %08x\n", + subc, class, mthd, data); - nv_wr32(priv, 0x409c20, 0x00000001); + nvkm_wr32(device, 0x409c20, 0x00000001); stat &= ~0x00000001; } else { - nv_error(priv, "FECS ucode error %d\n", code); + nvkm_error(subdev, "FECS ucode error %d\n", code); } } if (stat & 0x00080000) { - nv_error(priv, "FECS watchdog timeout\n"); - gf100_gr_ctxctl_debug(priv); - nv_wr32(priv, 0x409c20, 0x00080000); + nvkm_error(subdev, "FECS watchdog timeout\n"); + gf100_gr_ctxctl_debug(gr); + nvkm_wr32(device, 0x409c20, 0x00080000); stat &= ~0x00080000; } if (stat) { - nv_error(priv, "FECS 0x%08x\n", stat); - gf100_gr_ctxctl_debug(priv); - nv_wr32(priv, 0x409c20, stat); + nvkm_error(subdev, "FECS %08x\n", stat); + gf100_gr_ctxctl_debug(gr); + nvkm_wr32(device, 0x409c20, stat); } } static void -gf100_gr_intr(struct nvkm_subdev *subdev) +gf100_gr_intr(struct nvkm_gr *base) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct nvkm_handle *handle; - struct gf100_gr_priv *priv = (void *)subdev; - u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff; - u32 stat = nv_rd32(priv, 0x400100); - u32 addr = nv_rd32(priv, 0x400704); + struct gf100_gr *gr = gf100_gr(base); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_fifo_chan *chan; + unsigned long flags; + u64 inst = nvkm_rd32(device, 0x409b00) & 0x0fffffff; + u32 stat = nvkm_rd32(device, 0x400100); + u32 addr = nvkm_rd32(device, 0x400704); u32 mthd = (addr & 0x00003ffc); u32 subc = (addr & 0x00070000) >> 16; - u32 data = nv_rd32(priv, 0x400708); - u32 code = nv_rd32(priv, 0x400110); + u32 data = nvkm_rd32(device, 0x400708); + u32 code = nvkm_rd32(device, 0x400110); u32 class; - int chid; + const char *name = "unknown"; + int chid = -1; - if (nv_device(priv)->card_type < NV_E0 || subc < 4) - class = nv_rd32(priv, 0x404200 + (subc * 4)); + chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags); + if (chan) { + name = chan->object.client->name; + chid = chan->chid; + } + + if (device->card_type < NV_E0 || subc < 4) + class = nvkm_rd32(device, 0x404200 + (subc * 4)); else class = 0x0000; - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); - if (stat & 0x00000001) { /* * notifier interrupt, only needed for cyclestats * can be safely ignored */ - nv_wr32(priv, 0x400100, 0x00000001); + nvkm_wr32(device, 0x400100, 0x00000001); stat &= ~0x00000001; } if (stat & 0x00000010) { - handle = nvkm_handle_get_class(engctx, class); - if (!handle || nv_call(handle->object, mthd, data)) { - nv_error(priv, - "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nvkm_client_name(engctx), - subc, class, mthd, data); + if (!gf100_gr_mthd_sw(device, class, mthd, data)) { + nvkm_error(subdev, "ILLEGAL_MTHD ch %d [%010llx %s] " + "subc %d class %04x mthd %04x data %08x\n", + chid, inst << 12, name, subc, + class, mthd, data); } - nvkm_handle_put(handle); - nv_wr32(priv, 0x400100, 0x00000010); + nvkm_wr32(device, 0x400100, 0x00000010); stat &= ~0x00000010; } if (stat & 0x00000020) { - nv_error(priv, - "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nvkm_client_name(engctx), subc, - class, mthd, data); - nv_wr32(priv, 0x400100, 0x00000020); + nvkm_error(subdev, "ILLEGAL_CLASS ch %d [%010llx %s] " + "subc %d class %04x mthd %04x data %08x\n", + chid, inst << 12, name, subc, class, mthd, data); + nvkm_wr32(device, 0x400100, 0x00000020); stat &= ~0x00000020; } if (stat & 0x00100000) { - nv_error(priv, "DATA_ERROR ["); - nvkm_enum_print(nv50_data_error_names, code); - pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nvkm_client_name(engctx), subc, - class, mthd, data); - nv_wr32(priv, 0x400100, 0x00100000); + const struct nvkm_enum *en = + nvkm_enum_find(nv50_data_error_names, code); + nvkm_error(subdev, "DATA_ERROR %08x [%s] ch %d [%010llx %s] " + "subc %d class %04x mthd %04x data %08x\n", + code, en ? en->name : "", chid, inst << 12, + name, subc, class, mthd, data); + nvkm_wr32(device, 0x400100, 0x00100000); stat &= ~0x00100000; } if (stat & 0x00200000) { - nv_error(priv, "TRAP ch %d [0x%010llx %s]\n", chid, inst << 12, - nvkm_client_name(engctx)); - gf100_gr_trap_intr(priv); - nv_wr32(priv, 0x400100, 0x00200000); + nvkm_error(subdev, "TRAP ch %d [%010llx %s]\n", + chid, inst << 12, name); + gf100_gr_trap_intr(gr); + nvkm_wr32(device, 0x400100, 0x00200000); stat &= ~0x00200000; } if (stat & 0x00080000) { - gf100_gr_ctxctl_isr(priv); - nv_wr32(priv, 0x400100, 0x00080000); + gf100_gr_ctxctl_isr(gr); + nvkm_wr32(device, 0x400100, 0x00080000); stat &= ~0x00080000; } if (stat) { - nv_error(priv, "unknown stat 0x%08x\n", stat); - nv_wr32(priv, 0x400100, stat); + nvkm_error(subdev, "intr %08x\n", stat); + nvkm_wr32(device, 0x400100, stat); } - nv_wr32(priv, 0x400500, 0x00010001); - nvkm_engctx_put(engctx); + nvkm_wr32(device, 0x400500, 0x00010001); + nvkm_fifo_chan_put(device->fifo, flags, &chan); } void -gf100_gr_init_fw(struct gf100_gr_priv *priv, u32 fuc_base, +gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base, struct gf100_gr_fuc *code, struct gf100_gr_fuc *data) { + struct nvkm_device *device = gr->base.engine.subdev.device; int i; - nv_wr32(priv, fuc_base + 0x01c0, 0x01000000); + nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000); for (i = 0; i < data->size / 4; i++) - nv_wr32(priv, fuc_base + 0x01c4, data->data[i]); + nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]); - nv_wr32(priv, fuc_base + 0x0180, 0x01000000); + nvkm_wr32(device, fuc_base + 0x0180, 0x01000000); for (i = 0; i < code->size / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(priv, fuc_base + 0x0188, i >> 6); - nv_wr32(priv, fuc_base + 0x0184, code->data[i]); + nvkm_wr32(device, fuc_base + 0x0188, i >> 6); + nvkm_wr32(device, fuc_base + 0x0184, code->data[i]); } /* code must be padded to 0x40 words */ for (; i & 0x3f; i++) - nv_wr32(priv, fuc_base + 0x0184, 0); + nvkm_wr32(device, fuc_base + 0x0184, 0); } static void -gf100_gr_init_csdata(struct gf100_gr_priv *priv, +gf100_gr_init_csdata(struct gf100_gr *gr, const struct gf100_gr_pack *pack, u32 falcon, u32 starstar, u32 base) { + struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_gr_pack *iter; const struct gf100_gr_init *init; u32 addr = ~0, prev = ~0, xfer = 0; u32 star, temp; - nv_wr32(priv, falcon + 0x01c0, 0x02000000 + starstar); - star = nv_rd32(priv, falcon + 0x01c4); - temp = nv_rd32(priv, falcon + 0x01c4); + nvkm_wr32(device, falcon + 0x01c0, 0x02000000 + starstar); + star = nvkm_rd32(device, falcon + 0x01c4); + temp = nvkm_rd32(device, falcon + 0x01c4); if (temp > star) star = temp; - nv_wr32(priv, falcon + 0x01c0, 0x01000000 + star); + nvkm_wr32(device, falcon + 0x01c0, 0x01000000 + star); pack_for_each_init(init, iter, pack) { u32 head = init->addr - base; @@ -1218,7 +1314,7 @@ gf100_gr_init_csdata(struct gf100_gr_priv *priv, if (head != prev + 4 || xfer >= 32) { if (xfer) { u32 data = ((--xfer << 26) | addr); - nv_wr32(priv, falcon + 0x01c4, data); + nvkm_wr32(device, falcon + 0x01c4, data); star += 4; } addr = head; @@ -1230,157 +1326,166 @@ gf100_gr_init_csdata(struct gf100_gr_priv *priv, } } - nv_wr32(priv, falcon + 0x01c4, (--xfer << 26) | addr); - nv_wr32(priv, falcon + 0x01c0, 0x01000004 + starstar); - nv_wr32(priv, falcon + 0x01c4, star + 4); + nvkm_wr32(device, falcon + 0x01c4, (--xfer << 26) | addr); + nvkm_wr32(device, falcon + 0x01c0, 0x01000004 + starstar); + nvkm_wr32(device, falcon + 0x01c4, star + 4); } int -gf100_gr_init_ctxctl(struct gf100_gr_priv *priv) +gf100_gr_init_ctxctl(struct gf100_gr *gr) { - struct gf100_gr_oclass *oclass = (void *)nv_object(priv)->oclass; - struct gf100_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass; + const struct gf100_grctx_func *grctx = gr->func->grctx; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; int i; - if (priv->firmware) { + if (gr->firmware) { /* load fuc microcode */ - nvkm_mc(priv)->unk260(nvkm_mc(priv), 0); - gf100_gr_init_fw(priv, 0x409000, &priv->fuc409c, - &priv->fuc409d); - gf100_gr_init_fw(priv, 0x41a000, &priv->fuc41ac, - &priv->fuc41ad); - nvkm_mc(priv)->unk260(nvkm_mc(priv), 1); + nvkm_mc_unk260(device->mc, 0); + gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); + gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); + nvkm_mc_unk260(device->mc, 1); /* start both of them running */ - nv_wr32(priv, 0x409840, 0xffffffff); - nv_wr32(priv, 0x41a10c, 0x00000000); - nv_wr32(priv, 0x40910c, 0x00000000); - nv_wr32(priv, 0x41a100, 0x00000002); - nv_wr32(priv, 0x409100, 0x00000002); - if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) - nv_warn(priv, "0x409800 wait failed\n"); - - nv_wr32(priv, 0x409840, 0xffffffff); - nv_wr32(priv, 0x409500, 0x7fffffff); - nv_wr32(priv, 0x409504, 0x00000021); - - nv_wr32(priv, 0x409840, 0xffffffff); - nv_wr32(priv, 0x409500, 0x00000000); - nv_wr32(priv, 0x409504, 0x00000010); - if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { - nv_error(priv, "fuc09 req 0x10 timeout\n"); + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x41a10c, 0x00000000); + nvkm_wr32(device, 0x40910c, 0x00000000); + nvkm_wr32(device, 0x41a100, 0x00000002); + nvkm_wr32(device, 0x409100, 0x00000002); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800) & 0x00000001) + break; + ) < 0) return -EBUSY; - } - priv->size = nv_rd32(priv, 0x409800); - nv_wr32(priv, 0x409840, 0xffffffff); - nv_wr32(priv, 0x409500, 0x00000000); - nv_wr32(priv, 0x409504, 0x00000016); - if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { - nv_error(priv, "fuc09 req 0x16 timeout\n"); + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x7fffffff); + nvkm_wr32(device, 0x409504, 0x00000021); + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000010); + if (nvkm_msec(device, 2000, + if ((gr->size = nvkm_rd32(device, 0x409800))) + break; + ) < 0) return -EBUSY; - } - nv_wr32(priv, 0x409840, 0xffffffff); - nv_wr32(priv, 0x409500, 0x00000000); - nv_wr32(priv, 0x409504, 0x00000025); - if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { - nv_error(priv, "fuc09 req 0x25 timeout\n"); + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000016); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000025); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) return -EBUSY; - } - if (nv_device(priv)->chipset >= 0xe0) { - nv_wr32(priv, 0x409800, 0x00000000); - nv_wr32(priv, 0x409500, 0x00000001); - nv_wr32(priv, 0x409504, 0x00000030); - if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { - nv_error(priv, "fuc09 req 0x30 timeout\n"); + if (device->chipset >= 0xe0) { + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000030); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) return -EBUSY; - } - nv_wr32(priv, 0x409810, 0xb00095c8); - nv_wr32(priv, 0x409800, 0x00000000); - nv_wr32(priv, 0x409500, 0x00000001); - nv_wr32(priv, 0x409504, 0x00000031); - if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { - nv_error(priv, "fuc09 req 0x31 timeout\n"); + nvkm_wr32(device, 0x409810, 0xb00095c8); + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000031); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) return -EBUSY; - } - nv_wr32(priv, 0x409810, 0x00080420); - nv_wr32(priv, 0x409800, 0x00000000); - nv_wr32(priv, 0x409500, 0x00000001); - nv_wr32(priv, 0x409504, 0x00000032); - if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { - nv_error(priv, "fuc09 req 0x32 timeout\n"); + nvkm_wr32(device, 0x409810, 0x00080420); + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000032); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) return -EBUSY; - } - nv_wr32(priv, 0x409614, 0x00000070); - nv_wr32(priv, 0x409614, 0x00000770); - nv_wr32(priv, 0x40802c, 0x00000001); + nvkm_wr32(device, 0x409614, 0x00000070); + nvkm_wr32(device, 0x409614, 0x00000770); + nvkm_wr32(device, 0x40802c, 0x00000001); } - if (priv->data == NULL) { - int ret = gf100_grctx_generate(priv); + if (gr->data == NULL) { + int ret = gf100_grctx_generate(gr); if (ret) { - nv_error(priv, "failed to construct context\n"); + nvkm_error(subdev, "failed to construct context\n"); return ret; } } return 0; } else - if (!oclass->fecs.ucode) { + if (!gr->func->fecs.ucode) { return -ENOSYS; } /* load HUB microcode */ - nvkm_mc(priv)->unk260(nvkm_mc(priv), 0); - nv_wr32(priv, 0x4091c0, 0x01000000); - for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++) - nv_wr32(priv, 0x4091c4, oclass->fecs.ucode->data.data[i]); + nvkm_mc_unk260(device->mc, 0); + nvkm_wr32(device, 0x4091c0, 0x01000000); + for (i = 0; i < gr->func->fecs.ucode->data.size / 4; i++) + nvkm_wr32(device, 0x4091c4, gr->func->fecs.ucode->data.data[i]); - nv_wr32(priv, 0x409180, 0x01000000); - for (i = 0; i < oclass->fecs.ucode->code.size / 4; i++) { + nvkm_wr32(device, 0x409180, 0x01000000); + for (i = 0; i < gr->func->fecs.ucode->code.size / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(priv, 0x409188, i >> 6); - nv_wr32(priv, 0x409184, oclass->fecs.ucode->code.data[i]); + nvkm_wr32(device, 0x409188, i >> 6); + nvkm_wr32(device, 0x409184, gr->func->fecs.ucode->code.data[i]); } /* load GPC microcode */ - nv_wr32(priv, 0x41a1c0, 0x01000000); - for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++) - nv_wr32(priv, 0x41a1c4, oclass->gpccs.ucode->data.data[i]); + nvkm_wr32(device, 0x41a1c0, 0x01000000); + for (i = 0; i < gr->func->gpccs.ucode->data.size / 4; i++) + nvkm_wr32(device, 0x41a1c4, gr->func->gpccs.ucode->data.data[i]); - nv_wr32(priv, 0x41a180, 0x01000000); - for (i = 0; i < oclass->gpccs.ucode->code.size / 4; i++) { + nvkm_wr32(device, 0x41a180, 0x01000000); + for (i = 0; i < gr->func->gpccs.ucode->code.size / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(priv, 0x41a188, i >> 6); - nv_wr32(priv, 0x41a184, oclass->gpccs.ucode->code.data[i]); + nvkm_wr32(device, 0x41a188, i >> 6); + nvkm_wr32(device, 0x41a184, gr->func->gpccs.ucode->code.data[i]); } - nvkm_mc(priv)->unk260(nvkm_mc(priv), 1); + nvkm_mc_unk260(device->mc, 1); /* load register lists */ - gf100_gr_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000); - gf100_gr_init_csdata(priv, cclass->gpc, 0x41a000, 0x000, 0x418000); - gf100_gr_init_csdata(priv, cclass->tpc, 0x41a000, 0x004, 0x419800); - gf100_gr_init_csdata(priv, cclass->ppc, 0x41a000, 0x008, 0x41be00); + gf100_gr_init_csdata(gr, grctx->hub, 0x409000, 0x000, 0x000000); + gf100_gr_init_csdata(gr, grctx->gpc, 0x41a000, 0x000, 0x418000); + gf100_gr_init_csdata(gr, grctx->tpc, 0x41a000, 0x004, 0x419800); + gf100_gr_init_csdata(gr, grctx->ppc, 0x41a000, 0x008, 0x41be00); /* start HUB ucode running, it'll init the GPCs */ - nv_wr32(priv, 0x40910c, 0x00000000); - nv_wr32(priv, 0x409100, 0x00000002); - if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { - nv_error(priv, "HUB_INIT timed out\n"); - gf100_gr_ctxctl_debug(priv); + nvkm_wr32(device, 0x40910c, 0x00000000); + nvkm_wr32(device, 0x409100, 0x00000002); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800) & 0x80000000) + break; + ) < 0) { + gf100_gr_ctxctl_debug(gr); return -EBUSY; } - priv->size = nv_rd32(priv, 0x409804); - if (priv->data == NULL) { - int ret = gf100_grctx_generate(priv); + gr->size = nvkm_rd32(device, 0x409804); + if (gr->data == NULL) { + int ret = gf100_grctx_generate(gr); if (ret) { - nv_error(priv, "failed to construct context\n"); + nvkm_error(subdev, "failed to construct context\n"); return ret; } } @@ -1388,143 +1493,162 @@ gf100_gr_init_ctxctl(struct gf100_gr_priv *priv) return 0; } -int -gf100_gr_init(struct nvkm_object *object) +static int +gf100_gr_oneinit(struct nvkm_gr *base) { - struct gf100_gr_oclass *oclass = (void *)object->oclass; - struct gf100_gr_priv *priv = (void *)object; - const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); - u32 data[TPC_MAX / 8] = {}; - u8 tpcnr[GPC_MAX]; - int gpc, tpc, rop; - int ret, i; + struct gf100_gr *gr = gf100_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + int ret, i, j; + + nvkm_pmu_pgob(device->pmu, false); - ret = nvkm_gr_init(&priv->base); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false, + &gr->unk4188b4); if (ret) return ret; - nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0888), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x088c), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); - - gf100_gr_mmio(priv, oclass->mmio); - - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); - for (i = 0, gpc = -1; i < priv->tpc_total; i++) { - do { - gpc = (gpc + 1) % priv->gpc_nr; - } while (!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; - - data[i / 8] |= tpc << ((i % 8) * 4); - } - - nv_wr32(priv, GPC_BCAST(0x0980), data[0]); - nv_wr32(priv, GPC_BCAST(0x0984), data[1]); - nv_wr32(priv, GPC_BCAST(0x0988), data[2]); - nv_wr32(priv, GPC_BCAST(0x098c), data[3]); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(priv, GPC_UNIT(gpc, 0x0914), - priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | - priv->tpc_total); - nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); - } + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false, + &gr->unk4188b8); + if (ret) + return ret; - if (nv_device(priv)->chipset != 0xd7) - nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); - else - nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); - - nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); - - nv_wr32(priv, 0x400500, 0x00010001); - - nv_wr32(priv, 0x400100, 0xffffffff); - nv_wr32(priv, 0x40013c, 0xffffffff); - - nv_wr32(priv, 0x409c24, 0x000f0000); - nv_wr32(priv, 0x404000, 0xc0000000); - nv_wr32(priv, 0x404600, 0xc0000000); - nv_wr32(priv, 0x408030, 0xc0000000); - nv_wr32(priv, 0x40601c, 0xc0000000); - nv_wr32(priv, 0x404490, 0xc0000000); - nv_wr32(priv, 0x406018, 0xc0000000); - nv_wr32(priv, 0x405840, 0xc0000000); - nv_wr32(priv, 0x405844, 0x00ffffff); - nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); - nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); + nvkm_kmap(gr->unk4188b4); + for (i = 0; i < 0x1000; i += 4) + nvkm_wo32(gr->unk4188b4, i, 0x00000010); + nvkm_done(gr->unk4188b4); + + nvkm_kmap(gr->unk4188b8); + for (i = 0; i < 0x1000; i += 4) + nvkm_wo32(gr->unk4188b8, i, 0x00000010); + nvkm_done(gr->unk4188b8); + + gr->rop_nr = (nvkm_rd32(device, 0x409604) & 0x001f0000) >> 16; + gr->gpc_nr = nvkm_rd32(device, 0x409604) & 0x0000001f; + for (i = 0; i < gr->gpc_nr; i++) { + gr->tpc_nr[i] = nvkm_rd32(device, GPC_UNIT(i, 0x2608)); + gr->tpc_total += gr->tpc_nr[i]; + gr->ppc_nr[i] = gr->func->ppc_nr; + for (j = 0; j < gr->ppc_nr[i]; j++) { + u8 mask = nvkm_rd32(device, GPC_UNIT(i, 0x0c30 + (j * 4))); + if (mask) + gr->ppc_mask[i] |= (1 << j); + gr->ppc_tpc_nr[i][j] = hweight8(mask); } - nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } - for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); - nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); + /*XXX: these need figuring out... though it might not even matter */ + switch (device->chipset) { + case 0xc0: + if (gr->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ + gr->magic_not_rop_nr = 0x07; + } else + if (gr->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ + gr->magic_not_rop_nr = 0x05; + } else + if (gr->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ + gr->magic_not_rop_nr = 0x06; + } + break; + case 0xc3: /* 450, 4/0/0/0, 2 */ + gr->magic_not_rop_nr = 0x03; + break; + case 0xc4: /* 460, 3/4/0/0, 4 */ + gr->magic_not_rop_nr = 0x01; + break; + case 0xc1: /* 2/0/0/0, 1 */ + gr->magic_not_rop_nr = 0x01; + break; + case 0xc8: /* 4/4/3/4, 5 */ + gr->magic_not_rop_nr = 0x06; + break; + case 0xce: /* 4/4/0/0, 4 */ + gr->magic_not_rop_nr = 0x03; + break; + case 0xcf: /* 4/0/0/0, 3 */ + gr->magic_not_rop_nr = 0x03; + break; + case 0xd7: + case 0xd9: /* 1/0/0/0, 1 */ + case 0xea: /* gk20a */ + case 0x12b: /* gm20b */ + gr->magic_not_rop_nr = 0x01; + break; } - nv_wr32(priv, 0x400108, 0xffffffff); - nv_wr32(priv, 0x400138, 0xffffffff); - nv_wr32(priv, 0x400118, 0xffffffff); - nv_wr32(priv, 0x400130, 0xffffffff); - nv_wr32(priv, 0x40011c, 0xffffffff); - nv_wr32(priv, 0x400134, 0xffffffff); - - nv_wr32(priv, 0x400054, 0x34ce3464); - - gf100_gr_zbc_init(priv); + return 0; +} - return gf100_gr_init_ctxctl(priv); +int +gf100_gr_init_(struct nvkm_gr *base) +{ + struct gf100_gr *gr = gf100_gr(base); + nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false); + return gr->func->init(gr); } -static void +void gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc) { kfree(fuc->data); fuc->data = NULL; } +void * +gf100_gr_dtor(struct nvkm_gr *base) +{ + struct gf100_gr *gr = gf100_gr(base); + + if (gr->func->dtor) + gr->func->dtor(gr); + kfree(gr->data); + + gf100_gr_dtor_fw(&gr->fuc409c); + gf100_gr_dtor_fw(&gr->fuc409d); + gf100_gr_dtor_fw(&gr->fuc41ac); + gf100_gr_dtor_fw(&gr->fuc41ad); + + nvkm_memory_del(&gr->unk4188b8); + nvkm_memory_del(&gr->unk4188b4); + return gr; +} + +static const struct nvkm_gr_func +gf100_gr_ = { + .dtor = gf100_gr_dtor, + .oneinit = gf100_gr_oneinit, + .init = gf100_gr_init_, + .intr = gf100_gr_intr, + .units = gf100_gr_units, + .chan_new = gf100_gr_chan_new, + .object_get = gf100_gr_object_get, +}; + int -gf100_gr_ctor_fw(struct gf100_gr_priv *priv, const char *fwname, +gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname, struct gf100_gr_fuc *fuc) { - struct nvkm_device *device = nv_device(priv); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; const struct firmware *fw; - char f[32]; + char f[64]; + char cname[16]; int ret; + int i; - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); - ret = request_firmware(&fw, f, nv_device_base(device)); + /* Convert device name to lowercase */ + strncpy(cname, device->chip->name, sizeof(cname)); + cname[sizeof(cname) - 1] = '\0'; + i = strlen(cname); + while (i) { + --i; + cname[i] = tolower(cname[i]); + } + + snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); + ret = request_firmware(&fw, f, device->dev); if (ret) { - snprintf(f, sizeof(f), "nouveau/%s", fwname); - ret = request_firmware(&fw, f, nv_device_base(device)); - if (ret) { - nv_error(priv, "failed to load %s\n", fwname); - return ret; - } + nvkm_error(subdev, "failed to load %s\n", fwname); + return ret; } fuc->size = fw->size; @@ -1533,126 +1657,150 @@ gf100_gr_ctor_fw(struct gf100_gr_priv *priv, const char *fwname, return (fuc->data != NULL) ? 0 : -ENOMEM; } -void -gf100_gr_dtor(struct nvkm_object *object) +int +gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device, + int index, struct gf100_gr *gr) { - struct gf100_gr_priv *priv = (void *)object; + int ret; - kfree(priv->data); + gr->func = func; + gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW", + func->fecs.ucode == NULL); - gf100_gr_dtor_fw(&priv->fuc409c); - gf100_gr_dtor_fw(&priv->fuc409d); - gf100_gr_dtor_fw(&priv->fuc41ac); - gf100_gr_dtor_fw(&priv->fuc41ad); + ret = nvkm_gr_ctor(&gf100_gr_, device, index, 0x08001000, + gr->firmware || func->fecs.ucode != NULL, + &gr->base); + if (ret) + return ret; - nvkm_gpuobj_ref(NULL, &priv->unk4188b8); - nvkm_gpuobj_ref(NULL, &priv->unk4188b4); + if (gr->firmware) { + nvkm_info(&gr->base.engine.subdev, "using external firmware\n"); + if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fuc409c) || + gf100_gr_ctor_fw(gr, "fecs_data", &gr->fuc409d) || + gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->fuc41ac) || + gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad)) + return -ENODEV; + } - nvkm_gr_destroy(&priv->base); + return 0; } int -gf100_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *bclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, + int index, struct nvkm_gr **pgr) { - struct gf100_gr_oclass *oclass = (void *)bclass; - struct nvkm_device *device = nv_device(parent); - struct gf100_gr_priv *priv; - bool use_ext_fw, enable; - int ret, i, j; + struct gf100_gr *gr; + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + *pgr = &gr->base; + return gf100_gr_ctor(func, device, index, gr); +} - use_ext_fw = nvkm_boolopt(device->cfgopt, "NvGrUseFW", - oclass->fecs.ucode == NULL); - enable = use_ext_fw || oclass->fecs.ucode != NULL; +int +gf100_gr_init(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); + u32 data[TPC_MAX / 8] = {}; + u8 tpcnr[GPC_MAX]; + int gpc, tpc, rop; + int i; - ret = nvkm_gr_create(parent, engine, bclass, enable, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8); + nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8); - nv_subdev(priv)->unit = 0x08001000; - nv_subdev(priv)->intr = gf100_gr_intr; + gf100_gr_mmio(gr, gr->func->mmio); - priv->base.units = gf100_gr_units; + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); + for (i = 0, gpc = -1; i < gr->tpc_total; i++) { + do { + gpc = (gpc + 1) % gr->gpc_nr; + } while (!tpcnr[gpc]); + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; - if (use_ext_fw) { - nv_info(priv, "using external firmware\n"); - if (gf100_gr_ctor_fw(priv, "fuc409c", &priv->fuc409c) || - gf100_gr_ctor_fw(priv, "fuc409d", &priv->fuc409d) || - gf100_gr_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || - gf100_gr_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) - return -ENODEV; - priv->firmware = true; + data[i / 8] |= tpc << ((i % 8) * 4); } - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, - &priv->unk4188b4); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, - &priv->unk4188b8); - if (ret) - return ret; + nvkm_wr32(device, GPC_BCAST(0x0980), data[0]); + nvkm_wr32(device, GPC_BCAST(0x0984), data[1]); + nvkm_wr32(device, GPC_BCAST(0x0988), data[2]); + nvkm_wr32(device, GPC_BCAST(0x098c), data[3]); - for (i = 0; i < 0x1000; i += 4) { - nv_wo32(priv->unk4188b4, i, 0x00000010); - nv_wo32(priv->unk4188b8, i, 0x00000010); + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0914), + gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 | + gr->tpc_total); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918); } - priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; - priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; - for (i = 0; i < priv->gpc_nr; i++) { - priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); - priv->tpc_total += priv->tpc_nr[i]; - priv->ppc_nr[i] = oclass->ppc_nr; - for (j = 0; j < priv->ppc_nr[i]; j++) { - u8 mask = nv_rd32(priv, GPC_UNIT(i, 0x0c30 + (j * 4))); - priv->ppc_tpc_nr[i][j] = hweight8(mask); + if (device->chipset != 0xd7) + nvkm_wr32(device, GPC_BCAST(0x1bd4), magicgpc918); + else + nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918); + + nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800)); + + nvkm_wr32(device, 0x400500, 0x00010001); + + nvkm_wr32(device, 0x400100, 0xffffffff); + nvkm_wr32(device, 0x40013c, 0xffffffff); + + nvkm_wr32(device, 0x409c24, 0x000f0000); + nvkm_wr32(device, 0x404000, 0xc0000000); + nvkm_wr32(device, 0x404600, 0xc0000000); + nvkm_wr32(device, 0x408030, 0xc0000000); + nvkm_wr32(device, 0x40601c, 0xc0000000); + nvkm_wr32(device, 0x404490, 0xc0000000); + nvkm_wr32(device, 0x406018, 0xc0000000); + nvkm_wr32(device, 0x405840, 0xc0000000); + nvkm_wr32(device, 0x405844, 0x00ffffff); + nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008); + nvkm_mask(device, 0x419eb4, 0x00001000, 0x00001000); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); } + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } - /*XXX: these need figuring out... though it might not even matter */ - switch (nv_device(priv)->chipset) { - case 0xc0: - if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ - priv->magic_not_rop_nr = 0x07; - } else - if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ - priv->magic_not_rop_nr = 0x05; - } else - if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ - priv->magic_not_rop_nr = 0x06; - } - break; - case 0xc3: /* 450, 4/0/0/0, 2 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xc4: /* 460, 3/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x01; - break; - case 0xc1: /* 2/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; - case 0xc8: /* 4/4/3/4, 5 */ - priv->magic_not_rop_nr = 0x06; - break; - case 0xce: /* 4/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xcf: /* 4/0/0/0, 3 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xd7: - case 0xd9: /* 1/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; + for (rop = 0; rop < gr->rop_nr; rop++) { + nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff); + nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff); } - nv_engine(priv)->cclass = *oclass->cclass; - nv_engine(priv)->sclass = oclass->sclass; - return 0; + nvkm_wr32(device, 0x400108, 0xffffffff); + nvkm_wr32(device, 0x400138, 0xffffffff); + nvkm_wr32(device, 0x400118, 0xffffffff); + nvkm_wr32(device, 0x400130, 0xffffffff); + nvkm_wr32(device, 0x40011c, 0xffffffff); + nvkm_wr32(device, 0x400134, 0xffffffff); + + nvkm_wr32(device, 0x400054, 0x34ce3464); + + gf100_gr_zbc_init(gr); + + return gf100_gr_init_ctxctl(gr); } #include "fuc/hubgf100.fuc3.h" @@ -1675,18 +1823,24 @@ gf100_gr_gpccs_ucode = { .data.size = sizeof(gf100_grgpc_data), }; -struct nvkm_oclass * -gf100_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gf100_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gf100_grctx_oclass, - .sclass = gf100_gr_sclass, +static const struct gf100_gr_func +gf100_gr = { + .init = gf100_gr_init, .mmio = gf100_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, -}.base; + .grctx = &gf100_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, FERMI_MEMORY_TO_MEMORY_FORMAT_A }, + { -1, -1, FERMI_A, &gf100_fermi }, + { -1, -1, FERMI_COMPUTE_A }, + {} + } +}; + +int +gf100_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gf100_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 8af1a89ed..02e78b8d9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -21,11 +21,14 @@ * * Authors: Ben Skeggs */ -#ifndef __NVC0_GR_H__ -#define __NVC0_GR_H__ -#include +#ifndef __GF100_GR_H__ +#define __GF100_GR_H__ +#define gf100_gr(p) container_of((p), struct gf100_gr, base) +#include "priv.h" +#include #include +#include #define GPC_MAX 32 #define TPC_MAX (GPC_MAX * 8) @@ -67,7 +70,8 @@ struct gf100_gr_zbc_depth { u32 l2; }; -struct gf100_gr_priv { +struct gf100_gr { + const struct gf100_gr_func *func; struct nvkm_gr base; struct gf100_gr_fuc fuc409c; @@ -76,6 +80,15 @@ struct gf100_gr_priv { struct gf100_gr_fuc fuc41ad; bool firmware; + /* + * Used if the register packs are loaded from NVIDIA fw instead of + * using hardcoded arrays. + */ + struct gf100_gr_pack *fuc_sw_nonctx; + struct gf100_gr_pack *fuc_sw_ctx; + struct gf100_gr_pack *fuc_bundle; + struct gf100_gr_pack *fuc_method; + struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_CNT]; struct gf100_gr_zbc_depth zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; @@ -84,10 +97,11 @@ struct gf100_gr_priv { u8 tpc_nr[GPC_MAX]; u8 tpc_total; u8 ppc_nr[GPC_MAX]; + u8 ppc_mask[GPC_MAX]; u8 ppc_tpc_nr[GPC_MAX][4]; - struct nvkm_gpuobj *unk4188b4; - struct nvkm_gpuobj *unk4188b8; + struct nvkm_memory *unk4188b4; + struct nvkm_memory *unk4188b8; struct gf100_gr_data mmio_data[4]; struct gf100_gr_mmio mmio_list[4096/8]; @@ -97,48 +111,65 @@ struct gf100_gr_priv { u8 magic_not_rop_nr; }; +int gf100_gr_ctor(const struct gf100_gr_func *, struct nvkm_device *, + int, struct gf100_gr *); +int gf100_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, + int, struct nvkm_gr **); +void *gf100_gr_dtor(struct nvkm_gr *); + +struct gf100_gr_func { + void (*dtor)(struct gf100_gr *); + int (*init)(struct gf100_gr *); + void (*init_gpc_mmu)(struct gf100_gr *); + void (*set_hww_esr_report_mask)(struct gf100_gr *); + const struct gf100_gr_pack *mmio; + struct { + struct gf100_gr_ucode *ucode; + } fecs; + struct { + struct gf100_gr_ucode *ucode; + } gpccs; + int ppc_nr; + const struct gf100_grctx_func *grctx; + struct nvkm_sclass sclass[]; +}; + +int gf100_gr_init(struct gf100_gr *); + +int gk104_gr_init(struct gf100_gr *); + +int gk20a_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, + int, struct nvkm_gr **); +void gk20a_gr_dtor(struct gf100_gr *); +int gk20a_gr_init(struct gf100_gr *); + +int gm204_gr_init(struct gf100_gr *); + +#define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) + struct gf100_gr_chan { - struct nvkm_gr_chan base; + struct nvkm_object object; + struct gf100_gr *gr; - struct nvkm_gpuobj *mmio; + struct nvkm_memory *mmio; struct nvkm_vma mmio_vma; int mmio_nr; + struct { - struct nvkm_gpuobj *mem; + struct nvkm_memory *mem; struct nvkm_vma vma; } data[4]; }; -int gf100_gr_context_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void gf100_gr_context_dtor(struct nvkm_object *); - -void gf100_gr_ctxctl_debug(struct gf100_gr_priv *); +void gf100_gr_ctxctl_debug(struct gf100_gr *); +void gf100_gr_dtor_fw(struct gf100_gr_fuc *); +int gf100_gr_ctor_fw(struct gf100_gr *, const char *, + struct gf100_gr_fuc *); u64 gf100_gr_units(struct nvkm_gr *); -int gf100_gr_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); -void gf100_gr_dtor(struct nvkm_object *); -int gf100_gr_init(struct nvkm_object *); -void gf100_gr_zbc_init(struct gf100_gr_priv *); - -int gk104_gr_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); -int gk104_gr_init(struct nvkm_object *); - -int gm204_gr_init(struct nvkm_object *); +void gf100_gr_zbc_init(struct gf100_gr *); -extern struct nvkm_ofuncs gf100_fermi_ofuncs; - -extern struct nvkm_oclass gf100_gr_sclass[]; -extern struct nvkm_omthds gf100_gr_9097_omthds[]; -extern struct nvkm_omthds gf100_gr_90c0_omthds[]; -extern struct nvkm_oclass gf110_gr_sclass[]; -extern struct nvkm_oclass gk110_gr_sclass[]; -extern struct nvkm_oclass gm204_gr_sclass[]; +extern const struct nvkm_object_func gf100_fermi; struct gf100_gr_init { u32 addr; @@ -167,24 +198,11 @@ extern struct gf100_gr_ucode gf100_gr_gpccs_ucode; extern struct gf100_gr_ucode gk110_gr_fecs_ucode; extern struct gf100_gr_ucode gk110_gr_gpccs_ucode; -struct gf100_gr_oclass { - struct nvkm_oclass base; - struct nvkm_oclass **cclass; - struct nvkm_oclass *sclass; - const struct gf100_gr_pack *mmio; - struct { - struct gf100_gr_ucode *ucode; - } fecs; - struct { - struct gf100_gr_ucode *ucode; - } gpccs; - int ppc_nr; -}; - -void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *); -void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *); -void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *); -int gf100_gr_init_ctxctl(struct gf100_gr_priv *); +int gf100_gr_wait_idle(struct gf100_gr *); +void gf100_gr_mmio(struct gf100_gr *, const struct gf100_gr_pack *); +void gf100_gr_icmd(struct gf100_gr *, const struct gf100_gr_pack *); +void gf100_gr_mthd(struct gf100_gr *, const struct gf100_gr_pack *); +int gf100_gr_init_ctxctl(struct gf100_gr *); /* register init value lists */ @@ -260,7 +278,7 @@ extern const struct gf100_gr_init gm107_gr_init_tex_0[]; extern const struct gf100_gr_init gm107_gr_init_l1c_0[]; extern const struct gf100_gr_init gm107_gr_init_wwdx_0[]; extern const struct gf100_gr_init gm107_gr_init_cbm_0[]; -void gm107_gr_init_bios(struct gf100_gr_priv *); +void gm107_gr_init_bios(struct gf100_gr *); extern const struct gf100_gr_pack gm204_gr_pack_mmio[]; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c index 20d3b85db..8f253e0a2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c @@ -24,6 +24,8 @@ #include "gf100.h" #include "ctxgf100.h" +#include + /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -110,18 +112,24 @@ gf104_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -struct nvkm_oclass * -gf104_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xc3), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gf100_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gf104_grctx_oclass, - .sclass = gf100_gr_sclass, +static const struct gf100_gr_func +gf104_gr = { + .init = gf100_gr_init, .mmio = gf104_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, -}.base; + .grctx = &gf104_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, FERMI_MEMORY_TO_MEMORY_FORMAT_A }, + { -1, -1, FERMI_A, &gf100_fermi }, + { -1, -1, FERMI_COMPUTE_A }, + {} + } +}; + +int +gf104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gf104_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index 8df73421c..815a5aafa 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -26,20 +26,6 @@ #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -static struct nvkm_oclass -gf108_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs }, - { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { FERMI_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -117,18 +103,25 @@ gf108_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -struct nvkm_oclass * -gf108_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xc1), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gf100_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gf108_grctx_oclass, - .sclass = gf108_gr_sclass, +static const struct gf100_gr_func +gf108_gr = { + .init = gf100_gr_init, .mmio = gf108_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, -}.base; + .grctx = &gf108_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, FERMI_MEMORY_TO_MEMORY_FORMAT_A }, + { -1, -1, FERMI_A, &gf100_fermi }, + { -1, -1, FERMI_B, &gf100_fermi }, + { -1, -1, FERMI_COMPUTE_A }, + {} + } +}; + +int +gf108_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gf108_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index ef76e2dd1..d081ee41f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -26,21 +26,6 @@ #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -struct nvkm_oclass -gf110_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs }, - { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { FERMI_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { FERMI_C, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -99,18 +84,27 @@ gf110_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -struct nvkm_oclass * -gf110_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xc8), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gf100_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gf110_grctx_oclass, - .sclass = gf110_gr_sclass, +static const struct gf100_gr_func +gf110_gr = { + .init = gf100_gr_init, .mmio = gf110_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, -}.base; + .grctx = &gf110_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, FERMI_MEMORY_TO_MEMORY_FORMAT_A }, + { -1, -1, FERMI_A, &gf100_fermi }, + { -1, -1, FERMI_B, &gf100_fermi }, + { -1, -1, FERMI_C, &gf100_fermi }, + { -1, -1, FERMI_COMPUTE_A }, + { -1, -1, FERMI_COMPUTE_B }, + {} + } +}; + +int +gf110_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gf110_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index 871ac5f80..d8e8af4d3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -24,6 +24,8 @@ #include "gf100.h" #include "ctxgf100.h" +#include + /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -118,19 +120,28 @@ gf117_gr_gpccs_ucode = { .data.size = sizeof(gf117_grgpc_data), }; -struct nvkm_oclass * -gf117_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xd7), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gf100_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gf117_grctx_oclass, - .sclass = gf110_gr_sclass, +static const struct gf100_gr_func +gf117_gr = { + .init = gf100_gr_init, .mmio = gf117_gr_pack_mmio, .fecs.ucode = &gf117_gr_fecs_ucode, .gpccs.ucode = &gf117_gr_gpccs_ucode, .ppc_nr = 1, -}.base; + .grctx = &gf117_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, FERMI_MEMORY_TO_MEMORY_FORMAT_A }, + { -1, -1, FERMI_A, &gf100_fermi }, + { -1, -1, FERMI_B, &gf100_fermi }, + { -1, -1, FERMI_C, &gf100_fermi }, + { -1, -1, FERMI_COMPUTE_A }, + { -1, -1, FERMI_COMPUTE_B }, + {} + } +}; + +int +gf117_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gf117_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index e6dd651e2..01faf9a73 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c @@ -24,6 +24,8 @@ #include "gf100.h" #include "ctxgf100.h" +#include + /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -173,18 +175,27 @@ gf119_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -struct nvkm_oclass * -gf119_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xd9), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gf100_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gf119_grctx_oclass, - .sclass = gf110_gr_sclass, +static const struct gf100_gr_func +gf119_gr = { + .init = gf100_gr_init, .mmio = gf119_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, -}.base; + .grctx = &gf119_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, FERMI_MEMORY_TO_MEMORY_FORMAT_A }, + { -1, -1, FERMI_A, &gf100_fermi }, + { -1, -1, FERMI_B, &gf100_fermi }, + { -1, -1, FERMI_C, &gf100_fermi }, + { -1, -1, FERMI_COMPUTE_A }, + { -1, -1, FERMI_COMPUTE_B }, + {} + } +}; + +int +gf119_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gf119_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index 46f7844ec..abf54928a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -24,23 +24,8 @@ #include "gf100.h" #include "ctxgf100.h" -#include - #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -static struct nvkm_oclass -gk104_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { KEPLER_INLINE_TO_MEMORY_A, &nvkm_object_ofuncs }, - { KEPLER_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { KEPLER_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -193,132 +178,112 @@ gk104_gr_pack_mmio[] = { ******************************************************************************/ int -gk104_gr_init(struct nvkm_object *object) +gk104_gr_init(struct gf100_gr *gr) { - struct gf100_gr_oclass *oclass = (void *)object->oclass; - struct gf100_gr_priv *priv = (void *)object; - struct nvkm_pmu *pmu = nvkm_pmu(priv); - const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); u32 data[TPC_MAX / 8] = {}; u8 tpcnr[GPC_MAX]; int gpc, tpc, rop; - int ret, i; - - if (pmu) - pmu->pgob(pmu, false); + int i; - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; + nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8); + nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8); - nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0888), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x088c), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + gf100_gr_mmio(gr, gr->func->mmio); - gf100_gr_mmio(priv, oclass->mmio); - - nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); + nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001); memset(data, 0x00, sizeof(data)); - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); - for (i = 0, gpc = -1; i < priv->tpc_total; i++) { + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); + for (i = 0, gpc = -1; i < gr->tpc_total; i++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(priv, GPC_BCAST(0x0980), data[0]); - nv_wr32(priv, GPC_BCAST(0x0984), data[1]); - nv_wr32(priv, GPC_BCAST(0x0988), data[2]); - nv_wr32(priv, GPC_BCAST(0x098c), data[3]); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(priv, GPC_UNIT(gpc, 0x0914), - priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | - priv->tpc_total); - nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); + nvkm_wr32(device, GPC_BCAST(0x0980), data[0]); + nvkm_wr32(device, GPC_BCAST(0x0984), data[1]); + nvkm_wr32(device, GPC_BCAST(0x0988), data[2]); + nvkm_wr32(device, GPC_BCAST(0x098c), data[3]); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0914), + gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 | + gr->tpc_total); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); - nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); - - nv_wr32(priv, 0x400500, 0x00010001); - - nv_wr32(priv, 0x400100, 0xffffffff); - nv_wr32(priv, 0x40013c, 0xffffffff); - - nv_wr32(priv, 0x409ffc, 0x00000000); - nv_wr32(priv, 0x409c14, 0x00003e3e); - nv_wr32(priv, 0x409c24, 0x000f0001); - nv_wr32(priv, 0x404000, 0xc0000000); - nv_wr32(priv, 0x404600, 0xc0000000); - nv_wr32(priv, 0x408030, 0xc0000000); - nv_wr32(priv, 0x404490, 0xc0000000); - nv_wr32(priv, 0x406018, 0xc0000000); - nv_wr32(priv, 0x407020, 0x40000000); - nv_wr32(priv, 0x405840, 0xc0000000); - nv_wr32(priv, 0x405844, 0x00ffffff); - nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); - nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); + nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918); + nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800)); + + nvkm_wr32(device, 0x400500, 0x00010001); + + nvkm_wr32(device, 0x400100, 0xffffffff); + nvkm_wr32(device, 0x40013c, 0xffffffff); + + nvkm_wr32(device, 0x409ffc, 0x00000000); + nvkm_wr32(device, 0x409c14, 0x00003e3e); + nvkm_wr32(device, 0x409c24, 0x000f0001); + nvkm_wr32(device, 0x404000, 0xc0000000); + nvkm_wr32(device, 0x404600, 0xc0000000); + nvkm_wr32(device, 0x408030, 0xc0000000); + nvkm_wr32(device, 0x404490, 0xc0000000); + nvkm_wr32(device, 0x406018, 0xc0000000); + nvkm_wr32(device, 0x407020, 0x40000000); + nvkm_wr32(device, 0x405840, 0xc0000000); + nvkm_wr32(device, 0x405844, 0x00ffffff); + nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008); + nvkm_mask(device, 0x419eb4, 0x00001000, 0x00001000); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x3038), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); } - nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } - for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); - nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); + for (rop = 0; rop < gr->rop_nr; rop++) { + nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff); + nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff); } - nv_wr32(priv, 0x400108, 0xffffffff); - nv_wr32(priv, 0x400138, 0xffffffff); - nv_wr32(priv, 0x400118, 0xffffffff); - nv_wr32(priv, 0x400130, 0xffffffff); - nv_wr32(priv, 0x40011c, 0xffffffff); - nv_wr32(priv, 0x400134, 0xffffffff); + nvkm_wr32(device, 0x400108, 0xffffffff); + nvkm_wr32(device, 0x400138, 0xffffffff); + nvkm_wr32(device, 0x400118, 0xffffffff); + nvkm_wr32(device, 0x400130, 0xffffffff); + nvkm_wr32(device, 0x40011c, 0xffffffff); + nvkm_wr32(device, 0x400134, 0xffffffff); - nv_wr32(priv, 0x400054, 0x34ce3464); + nvkm_wr32(device, 0x400054, 0x34ce3464); - gf100_gr_zbc_init(priv); + gf100_gr_zbc_init(gr); - return gf100_gr_init_ctxctl(priv); -} - -int -gk104_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_pmu *pmu = nvkm_pmu(parent); - if (pmu) - pmu->pgob(pmu, false); - return gf100_gr_ctor(parent, engine, oclass, data, size, pobject); + return gf100_gr_init_ctxctl(gr); } #include "fuc/hubgk104.fuc3.h" @@ -341,19 +306,25 @@ gk104_gr_gpccs_ucode = { .data.size = sizeof(gk104_grgpc_data), }; -struct nvkm_oclass * -gk104_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xe4), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gk104_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gk104_grctx_oclass, - .sclass = gk104_gr_sclass, +static const struct gf100_gr_func +gk104_gr = { + .init = gk104_gr_init, .mmio = gk104_gr_pack_mmio, .fecs.ucode = &gk104_gr_fecs_ucode, .gpccs.ucode = &gk104_gr_gpccs_ucode, .ppc_nr = 1, -}.base; + .grctx = &gk104_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_A }, + { -1, -1, KEPLER_A, &gf100_fermi }, + { -1, -1, KEPLER_COMPUTE_A }, + {} + } +}; + +int +gk104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gk104_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index f4cd8e554..32aa2946e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -28,19 +28,6 @@ #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -struct nvkm_oclass -gk110_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, - { KEPLER_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { KEPLER_COMPUTE_B, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -193,19 +180,25 @@ gk110_gr_gpccs_ucode = { .data.size = sizeof(gk110_grgpc_data), }; -struct nvkm_oclass * -gk110_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xf0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gk104_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gk110_grctx_oclass, - .sclass = gk110_gr_sclass, +static const struct gf100_gr_func +gk110_gr = { + .init = gk104_gr_init, .mmio = gk110_gr_pack_mmio, .fecs.ucode = &gk110_gr_fecs_ucode, .gpccs.ucode = &gk110_gr_gpccs_ucode, .ppc_nr = 2, -}.base; + .grctx = &gk110_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, KEPLER_B, &gf100_fermi }, + { -1, -1, KEPLER_COMPUTE_B }, + {} + } +}; + +int +gk110_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gk110_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index 9ff9eab0c..22f88afbf 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -24,6 +24,8 @@ #include "gf100.h" #include "ctxgf100.h" +#include + /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -98,19 +100,25 @@ gk110b_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -struct nvkm_oclass * -gk110b_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xf1), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gk104_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gk110b_grctx_oclass, - .sclass = gk110_gr_sclass, +static const struct gf100_gr_func +gk110b_gr = { + .init = gk104_gr_init, .mmio = gk110b_gr_pack_mmio, .fecs.ucode = &gk110_gr_fecs_ucode, .gpccs.ucode = &gk110_gr_gpccs_ucode, .ppc_nr = 2, -}.base; + .grctx = &gk110b_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, KEPLER_B, &gf100_fermi }, + { -1, -1, KEPLER_COMPUTE_B }, + {} + } +}; + +int +gk110b_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gk110b_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index 85f44a3d5..ee7554fc8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -28,19 +28,6 @@ #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -static struct nvkm_oclass -gk208_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, - { KEPLER_B, &gf100_fermi_ofuncs }, - { KEPLER_COMPUTE_B, &nvkm_object_ofuncs }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -172,19 +159,25 @@ gk208_gr_gpccs_ucode = { .data.size = sizeof(gk208_grgpc_data), }; -struct nvkm_oclass * -gk208_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0x08), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gk104_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gk208_grctx_oclass, - .sclass = gk208_gr_sclass, +static const struct gf100_gr_func +gk208_gr = { + .init = gk104_gr_init, .mmio = gk208_gr_pack_mmio, .fecs.ucode = &gk208_gr_fecs_ucode, .gpccs.ucode = &gk208_gr_gpccs_ucode, .ppc_nr = 1, -}.base; + .grctx = &gk208_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, KEPLER_B, &gf100_fermi }, + { -1, -1, KEPLER_COMPUTE_B }, + {} + } +}; + +int +gk208_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gk208_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 40ff5eb91..b8758d3b8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,28 +22,335 @@ #include "gf100.h" #include "ctxgf100.h" +#include + #include -static struct nvkm_oclass -gk20a_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { KEPLER_INLINE_TO_MEMORY_A, &nvkm_object_ofuncs }, - { KEPLER_C, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { KEPLER_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} +static void +gk20a_gr_init_dtor(struct gf100_gr_pack *pack) +{ + vfree(pack); +} + +struct gk20a_fw_av +{ + u32 addr; + u32 data; +}; + +static struct gf100_gr_pack * +gk20a_gr_av_to_init(struct gf100_gr_fuc *fuc) +{ + struct gf100_gr_init *init; + struct gf100_gr_pack *pack; + const int nent = (fuc->size / sizeof(struct gk20a_fw_av)); + int i; + + pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); + if (!pack) + return ERR_PTR(-ENOMEM); + + init = (void *)(pack + 2); + + pack[0].init = init; + + for (i = 0; i < nent; i++) { + struct gf100_gr_init *ent = &init[i]; + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc->data)[i]; + + ent->addr = av->addr; + ent->data = av->data; + ent->count = 1; + ent->pitch = 1; + } + + return pack; +} + +struct gk20a_fw_aiv +{ + u32 addr; + u32 index; + u32 data; }; -struct nvkm_oclass * -gk20a_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gk104_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gk20a_grctx_oclass, - .sclass = gk20a_gr_sclass, - .mmio = gk104_gr_pack_mmio, +static struct gf100_gr_pack * +gk20a_gr_aiv_to_init(struct gf100_gr_fuc *fuc) +{ + struct gf100_gr_init *init; + struct gf100_gr_pack *pack; + const int nent = (fuc->size / sizeof(struct gk20a_fw_aiv)); + int i; + + pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); + if (!pack) + return ERR_PTR(-ENOMEM); + + init = (void *)(pack + 2); + + pack[0].init = init; + + for (i = 0; i < nent; i++) { + struct gf100_gr_init *ent = &init[i]; + struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)fuc->data)[i]; + + ent->addr = av->addr; + ent->data = av->data; + ent->count = 1; + ent->pitch = 1; + } + + return pack; +} + +static struct gf100_gr_pack * +gk20a_gr_av_to_method(struct gf100_gr_fuc *fuc) +{ + struct gf100_gr_init *init; + struct gf100_gr_pack *pack; + /* We don't suppose we will initialize more than 16 classes here... */ + static const unsigned int max_classes = 16; + const int nent = (fuc->size / sizeof(struct gk20a_fw_av)); + int i, classidx = 0; + u32 prevclass = 0; + + pack = vzalloc((sizeof(*pack) * max_classes) + + (sizeof(*init) * (nent + 1))); + if (!pack) + return ERR_PTR(-ENOMEM); + + init = (void *)(pack + max_classes); + + for (i = 0; i < nent; i++) { + struct gf100_gr_init *ent = &init[i]; + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc->data)[i]; + u32 class = av->addr & 0xffff; + u32 addr = (av->addr & 0xffff0000) >> 14; + + if (prevclass != class) { + pack[classidx].init = ent; + pack[classidx].type = class; + prevclass = class; + if (++classidx >= max_classes) { + vfree(pack); + return ERR_PTR(-ENOSPC); + } + } + + ent->addr = addr; + ent->data = av->data; + ent->count = 1; + ent->pitch = 1; + } + + return pack; +} + +static int +gk20a_gr_wait_mem_scrubbing(struct gf100_gr *gr) +{ + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x40910c) & 0x00000006)) + break; + ) < 0) { + nvkm_error(subdev, "FECS mem scrubbing timeout\n"); + return -ETIMEDOUT; + } + + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x41a10c) & 0x00000006)) + break; + ) < 0) { + nvkm_error(subdev, "GPCCS mem scrubbing timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void +gk20a_gr_set_hww_esr_report_mask(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_wr32(device, 0x419e44, 0x1ffffe); + nvkm_wr32(device, 0x419e4c, 0x7f); +} + +int +gk20a_gr_init(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); + u32 data[TPC_MAX / 8] = {}; + u8 tpcnr[GPC_MAX]; + int gpc, tpc; + int ret, i; + + /* Clear SCC RAM */ + nvkm_wr32(device, 0x40802c, 0x1); + + gf100_gr_mmio(gr, gr->fuc_sw_nonctx); + + ret = gk20a_gr_wait_mem_scrubbing(gr); + if (ret) + return ret; + + ret = gf100_gr_wait_idle(gr); + if (ret) + return ret; + + /* MMU debug buffer */ + nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(gr->unk4188b4) >> 8); + nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(gr->unk4188b8) >> 8); + + if (gr->func->init_gpc_mmu) + gr->func->init_gpc_mmu(gr); + + /* Set the PE as stream master */ + nvkm_mask(device, 0x503018, 0x1, 0x1); + + /* Zcull init */ + memset(data, 0x00, sizeof(data)); + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); + for (i = 0, gpc = -1; i < gr->tpc_total; i++) { + do { + gpc = (gpc + 1) % gr->gpc_nr; + } while (!tpcnr[gpc]); + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; + + data[i / 8] |= tpc << ((i % 8) * 4); + } + + nvkm_wr32(device, GPC_BCAST(0x0980), data[0]); + nvkm_wr32(device, GPC_BCAST(0x0984), data[1]); + nvkm_wr32(device, GPC_BCAST(0x0988), data[2]); + nvkm_wr32(device, GPC_BCAST(0x098c), data[3]); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0914), + gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 | + gr->tpc_total); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918); + } + + nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918); + + /* Enable FIFO access */ + nvkm_wr32(device, 0x400500, 0x00010001); + + /* Enable interrupts */ + nvkm_wr32(device, 0x400100, 0xffffffff); + nvkm_wr32(device, 0x40013c, 0xffffffff); + + /* Enable FECS error interrupts */ + nvkm_wr32(device, 0x409c24, 0x000f0000); + + /* Enable hardware warning exceptions */ + nvkm_wr32(device, 0x404000, 0xc0000000); + nvkm_wr32(device, 0x404600, 0xc0000000); + + if (gr->func->set_hww_esr_report_mask) + gr->func->set_hww_esr_report_mask(gr); + + /* Enable TPC exceptions per GPC */ + nvkm_wr32(device, 0x419d0c, 0x2); + nvkm_wr32(device, 0x41ac94, (((1 << gr->tpc_total) - 1) & 0xff) << 16); + + /* Reset and enable all exceptions */ + nvkm_wr32(device, 0x400108, 0xffffffff); + nvkm_wr32(device, 0x400138, 0xffffffff); + nvkm_wr32(device, 0x400118, 0xffffffff); + nvkm_wr32(device, 0x400130, 0xffffffff); + nvkm_wr32(device, 0x40011c, 0xffffffff); + nvkm_wr32(device, 0x400134, 0xffffffff); + + gf100_gr_zbc_init(gr); + + return gf100_gr_init_ctxctl(gr); +} + +void +gk20a_gr_dtor(struct gf100_gr *gr) +{ + gk20a_gr_init_dtor(gr->fuc_method); + gk20a_gr_init_dtor(gr->fuc_bundle); + gk20a_gr_init_dtor(gr->fuc_sw_ctx); + gk20a_gr_init_dtor(gr->fuc_sw_nonctx); +} + +int +gk20a_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, + int index, struct nvkm_gr **pgr) +{ + struct gf100_gr_fuc fuc; + struct gf100_gr *gr; + int ret; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + *pgr = &gr->base; + + ret = gf100_gr_ctor(func, device, index, gr); + if (ret) + return ret; + + ret = gf100_gr_ctor_fw(gr, "sw_nonctx", &fuc); + if (ret) + return ret; + gr->fuc_sw_nonctx = gk20a_gr_av_to_init(&fuc); + gf100_gr_dtor_fw(&fuc); + if (IS_ERR(gr->fuc_sw_nonctx)) + return PTR_ERR(gr->fuc_sw_nonctx); + + ret = gf100_gr_ctor_fw(gr, "sw_ctx", &fuc); + if (ret) + return ret; + gr->fuc_sw_ctx = gk20a_gr_aiv_to_init(&fuc); + gf100_gr_dtor_fw(&fuc); + if (IS_ERR(gr->fuc_sw_ctx)) + return PTR_ERR(gr->fuc_sw_ctx); + + ret = gf100_gr_ctor_fw(gr, "sw_bundle_init", &fuc); + if (ret) + return ret; + gr->fuc_bundle = gk20a_gr_av_to_init(&fuc); + gf100_gr_dtor_fw(&fuc); + if (IS_ERR(gr->fuc_bundle)) + return PTR_ERR(gr->fuc_bundle); + + ret = gf100_gr_ctor_fw(gr, "sw_method_init", &fuc); + if (ret) + return ret; + gr->fuc_method = gk20a_gr_av_to_method(&fuc); + gf100_gr_dtor_fw(&fuc); + if (IS_ERR(gr->fuc_method)) + return PTR_ERR(gr->fuc_method); + + return 0; +} + +static const struct gf100_gr_func +gk20a_gr = { + .dtor = gk20a_gr_dtor, + .init = gk20a_gr_init, + .set_hww_esr_report_mask = gk20a_gr_set_hww_esr_report_mask, .ppc_nr = 1, -}.base; + .grctx = &gk20a_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_A }, + { -1, -1, KEPLER_C, &gf100_fermi }, + { -1, -1, KEPLER_COMPUTE_A }, + {} + } +}; + +int +gk20a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gk20a_gr_new_(&gk20a_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c index a5ebd459b..56e960212 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c @@ -29,19 +29,6 @@ #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -static struct nvkm_oclass -gm107_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, - { MAXWELL_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { MAXWELL_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -292,7 +279,7 @@ gm107_gr_pack_mmio[] = { ******************************************************************************/ void -gm107_gr_init_bios(struct gf100_gr_priv *priv) +gm107_gr_init_bios(struct gf100_gr *gr) { static const struct { u32 ctrl; @@ -304,7 +291,8 @@ gm107_gr_init_bios(struct gf100_gr_priv *priv) { 0x419af0, 0x419af4 }, { 0x419af8, 0x419afc }, }; - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_device *device = gr->base.engine.subdev.device; + struct nvkm_bios *bios = device->bios; struct nvbios_P0260E infoE; struct nvbios_P0260X infoX; int E = -1, X; @@ -312,124 +300,119 @@ gm107_gr_init_bios(struct gf100_gr_priv *priv) while (nvbios_P0260Ep(bios, ++E, &ver, &hdr, &infoE)) { if (X = -1, E < ARRAY_SIZE(regs)) { - nv_wr32(priv, regs[E].ctrl, infoE.data); + nvkm_wr32(device, regs[E].ctrl, infoE.data); while (nvbios_P0260Xp(bios, ++X, &ver, &hdr, &infoX)) - nv_wr32(priv, regs[E].data, infoX.data); + nvkm_wr32(device, regs[E].data, infoX.data); } } } int -gm107_gr_init(struct nvkm_object *object) +gm107_gr_init(struct gf100_gr *gr) { - struct gf100_gr_oclass *oclass = (void *)object->oclass; - struct gf100_gr_priv *priv = (void *)object; - const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); u32 data[TPC_MAX / 8] = {}; u8 tpcnr[GPC_MAX]; int gpc, tpc, ppc, rop; - int ret, i; - - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; + int i; - nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000); - nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000); + nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8); + nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8); - gf100_gr_mmio(priv, oclass->mmio); + gf100_gr_mmio(gr, gr->func->mmio); - gm107_gr_init_bios(priv); + gm107_gr_init_bios(gr); - nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); + nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001); memset(data, 0x00, sizeof(data)); - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); - for (i = 0, gpc = -1; i < priv->tpc_total; i++) { + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); + for (i = 0, gpc = -1; i < gr->tpc_total; i++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(priv, GPC_BCAST(0x0980), data[0]); - nv_wr32(priv, GPC_BCAST(0x0984), data[1]); - nv_wr32(priv, GPC_BCAST(0x0988), data[2]); - nv_wr32(priv, GPC_BCAST(0x098c), data[3]); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(priv, GPC_UNIT(gpc, 0x0914), - priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | - priv->tpc_total); - nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); + nvkm_wr32(device, GPC_BCAST(0x0980), data[0]); + nvkm_wr32(device, GPC_BCAST(0x0984), data[1]); + nvkm_wr32(device, GPC_BCAST(0x0988), data[2]); + nvkm_wr32(device, GPC_BCAST(0x098c), data[3]); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0914), + gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 | + gr->tpc_total); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); - nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); - - nv_wr32(priv, 0x400500, 0x00010001); - - nv_wr32(priv, 0x400100, 0xffffffff); - nv_wr32(priv, 0x40013c, 0xffffffff); - nv_wr32(priv, 0x400124, 0x00000002); - nv_wr32(priv, 0x409c24, 0x000e0000); - - nv_wr32(priv, 0x404000, 0xc0000000); - nv_wr32(priv, 0x404600, 0xc0000000); - nv_wr32(priv, 0x408030, 0xc0000000); - nv_wr32(priv, 0x404490, 0xc0000000); - nv_wr32(priv, 0x406018, 0xc0000000); - nv_wr32(priv, 0x407020, 0x40000000); - nv_wr32(priv, 0x405840, 0xc0000000); - nv_wr32(priv, 0x405844, 0x00ffffff); - nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (ppc = 0; ppc < 2 /* priv->ppc_nr[gpc] */; ppc++) - nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005); + nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918); + nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800)); + + nvkm_wr32(device, 0x400500, 0x00010001); + + nvkm_wr32(device, 0x400100, 0xffffffff); + nvkm_wr32(device, 0x40013c, 0xffffffff); + nvkm_wr32(device, 0x400124, 0x00000002); + nvkm_wr32(device, 0x409c24, 0x000e0000); + + nvkm_wr32(device, 0x404000, 0xc0000000); + nvkm_wr32(device, 0x404600, 0xc0000000); + nvkm_wr32(device, 0x408030, 0xc0000000); + nvkm_wr32(device, 0x404490, 0xc0000000); + nvkm_wr32(device, 0x406018, 0xc0000000); + nvkm_wr32(device, 0x407020, 0x40000000); + nvkm_wr32(device, 0x405840, 0xc0000000); + nvkm_wr32(device, 0x405844, 0x00ffffff); + nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (ppc = 0; ppc < 2 /* gr->ppc_nr[gpc] */; ppc++) + nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005); } - nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } - for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000); - nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000); - nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); + for (rop = 0; rop < gr->rop_nr; rop++) { + nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0x40000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0x40000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff); + nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff); } - nv_wr32(priv, 0x400108, 0xffffffff); - nv_wr32(priv, 0x400138, 0xffffffff); - nv_wr32(priv, 0x400118, 0xffffffff); - nv_wr32(priv, 0x400130, 0xffffffff); - nv_wr32(priv, 0x40011c, 0xffffffff); - nv_wr32(priv, 0x400134, 0xffffffff); + nvkm_wr32(device, 0x400108, 0xffffffff); + nvkm_wr32(device, 0x400138, 0xffffffff); + nvkm_wr32(device, 0x400118, 0xffffffff); + nvkm_wr32(device, 0x400130, 0xffffffff); + nvkm_wr32(device, 0x40011c, 0xffffffff); + nvkm_wr32(device, 0x400134, 0xffffffff); - nv_wr32(priv, 0x400054, 0x2c350f63); + nvkm_wr32(device, 0x400054, 0x2c350f63); - gf100_gr_zbc_init(priv); + gf100_gr_zbc_init(gr); - return gf100_gr_init_ctxctl(priv); + return gf100_gr_init_ctxctl(gr); } #include "fuc/hubgm107.fuc5.h" @@ -452,19 +435,25 @@ gm107_gr_gpccs_ucode = { .data.size = sizeof(gm107_grgpc_data), }; -struct nvkm_oclass * -gm107_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0x07), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gm107_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gm107_grctx_oclass, - .sclass = gm107_gr_sclass, +static const struct gf100_gr_func +gm107_gr = { + .init = gm107_gr_init, .mmio = gm107_gr_pack_mmio, .fecs.ucode = &gm107_gr_fecs_ucode, .gpccs.ucode = &gm107_gr_gpccs_ucode, .ppc_nr = 2, -}.base; + .grctx = &gm107_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, MAXWELL_A, &gf100_fermi }, + { -1, -1, MAXWELL_COMPUTE_A }, + {} + } +}; + +int +gm107_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gm107_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c index fdb1dcf16..90381dde4 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c @@ -26,19 +26,6 @@ #include -/******************************************************************************* - * Graphics object classes - ******************************************************************************/ - -struct nvkm_oclass -gm204_gr_sclass[] = { - { FERMI_TWOD_A, &nvkm_object_ofuncs }, - { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, - { MAXWELL_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, - { MAXWELL_COMPUTE_B, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, - {} -}; - /******************************************************************************* * PGRAPH register lists ******************************************************************************/ @@ -243,144 +230,144 @@ gm204_gr_data[] = { ******************************************************************************/ static int -gm204_gr_init_ctxctl(struct gf100_gr_priv *priv) +gm204_gr_init_ctxctl(struct gf100_gr *gr) { return 0; } int -gm204_gr_init(struct nvkm_object *object) +gm204_gr_init(struct gf100_gr *gr) { - struct gf100_gr_oclass *oclass = (void *)object->oclass; - struct gf100_gr_priv *priv = (void *)object; - const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); - u32 data[TPC_MAX / 8] = {}; + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); + u32 data[TPC_MAX / 8] = {}, tmp; u8 tpcnr[GPC_MAX]; int gpc, tpc, ppc, rop; - int ret, i; - u32 tmp; - - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; + int i; - tmp = nv_rd32(priv, 0x100c80); /*XXX: mask? */ - nv_wr32(priv, 0x418880, 0x00001000 | (tmp & 0x00000fff)); - nv_wr32(priv, 0x418890, 0x00000000); - nv_wr32(priv, 0x418894, 0x00000000); - nv_wr32(priv, 0x4188b4, priv->unk4188b4->addr >> 8); - nv_wr32(priv, 0x4188b8, priv->unk4188b8->addr >> 8); - nv_mask(priv, 0x4188b0, 0x00040000, 0x00040000); + tmp = nvkm_rd32(device, 0x100c80); /*XXX: mask? */ + nvkm_wr32(device, 0x418880, 0x00001000 | (tmp & 0x00000fff)); + nvkm_wr32(device, 0x418890, 0x00000000); + nvkm_wr32(device, 0x418894, 0x00000000); + nvkm_wr32(device, 0x4188b4, nvkm_memory_addr(gr->unk4188b4) >> 8); + nvkm_wr32(device, 0x4188b8, nvkm_memory_addr(gr->unk4188b8) >> 8); + nvkm_mask(device, 0x4188b0, 0x00040000, 0x00040000); /*XXX: belongs in fb */ - nv_wr32(priv, 0x100cc8, priv->unk4188b4->addr >> 8); - nv_wr32(priv, 0x100ccc, priv->unk4188b8->addr >> 8); - nv_mask(priv, 0x100cc4, 0x00040000, 0x00040000); + nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(gr->unk4188b4) >> 8); + nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(gr->unk4188b8) >> 8); + nvkm_mask(device, 0x100cc4, 0x00040000, 0x00040000); - gf100_gr_mmio(priv, oclass->mmio); + gf100_gr_mmio(gr, gr->func->mmio); - gm107_gr_init_bios(priv); + gm107_gr_init_bios(gr); - nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); + nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001); memset(data, 0x00, sizeof(data)); - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); - for (i = 0, gpc = -1; i < priv->tpc_total; i++) { + memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr)); + for (i = 0, gpc = -1; i < gr->tpc_total; i++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % gr->gpc_nr; } while (!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--; data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(priv, GPC_BCAST(0x0980), data[0]); - nv_wr32(priv, GPC_BCAST(0x0984), data[1]); - nv_wr32(priv, GPC_BCAST(0x0988), data[2]); - nv_wr32(priv, GPC_BCAST(0x098c), data[3]); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(priv, GPC_UNIT(gpc, 0x0914), - priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | - priv->tpc_total); - nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); + nvkm_wr32(device, GPC_BCAST(0x0980), data[0]); + nvkm_wr32(device, GPC_BCAST(0x0984), data[1]); + nvkm_wr32(device, GPC_BCAST(0x0988), data[2]); + nvkm_wr32(device, GPC_BCAST(0x098c), data[3]); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0914), + gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 | + gr->tpc_total); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); - nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); - nv_wr32(priv, GPC_BCAST(0x033c), nv_rd32(priv, 0x100804)); - - nv_wr32(priv, 0x400500, 0x00010001); - nv_wr32(priv, 0x400100, 0xffffffff); - nv_wr32(priv, 0x40013c, 0xffffffff); - nv_wr32(priv, 0x400124, 0x00000002); - nv_wr32(priv, 0x409c24, 0x000e0000); - nv_wr32(priv, 0x405848, 0xc0000000); - nv_wr32(priv, 0x40584c, 0x00000001); - nv_wr32(priv, 0x404000, 0xc0000000); - nv_wr32(priv, 0x404600, 0xc0000000); - nv_wr32(priv, 0x408030, 0xc0000000); - nv_wr32(priv, 0x404490, 0xc0000000); - nv_wr32(priv, 0x406018, 0xc0000000); - nv_wr32(priv, 0x407020, 0x40000000); - nv_wr32(priv, 0x405840, 0xc0000000); - nv_wr32(priv, 0x405844, 0x00ffffff); - nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) - nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); - for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe); - nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005); + nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918); + nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800)); + nvkm_wr32(device, GPC_BCAST(0x033c), nvkm_rd32(device, 0x100804)); + + nvkm_wr32(device, 0x400500, 0x00010001); + nvkm_wr32(device, 0x400100, 0xffffffff); + nvkm_wr32(device, 0x40013c, 0xffffffff); + nvkm_wr32(device, 0x400124, 0x00000002); + nvkm_wr32(device, 0x409c24, 0x000e0000); + nvkm_wr32(device, 0x405848, 0xc0000000); + nvkm_wr32(device, 0x40584c, 0x00000001); + nvkm_wr32(device, 0x404000, 0xc0000000); + nvkm_wr32(device, 0x404600, 0xc0000000); + nvkm_wr32(device, 0x408030, 0xc0000000); + nvkm_wr32(device, 0x404490, 0xc0000000); + nvkm_wr32(device, 0x406018, 0xc0000000); + nvkm_wr32(device, 0x407020, 0x40000000); + nvkm_wr32(device, 0x405840, 0xc0000000); + nvkm_wr32(device, 0x405844, 0x00ffffff); + nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008); + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) + nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) { + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005); } - nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } - for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000); - nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000); - nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); + for (rop = 0; rop < gr->rop_nr; rop++) { + nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0x40000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0x40000000); + nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff); + nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff); } - nv_wr32(priv, 0x400108, 0xffffffff); - nv_wr32(priv, 0x400138, 0xffffffff); - nv_wr32(priv, 0x400118, 0xffffffff); - nv_wr32(priv, 0x400130, 0xffffffff); - nv_wr32(priv, 0x40011c, 0xffffffff); - nv_wr32(priv, 0x400134, 0xffffffff); + nvkm_wr32(device, 0x400108, 0xffffffff); + nvkm_wr32(device, 0x400138, 0xffffffff); + nvkm_wr32(device, 0x400118, 0xffffffff); + nvkm_wr32(device, 0x400130, 0xffffffff); + nvkm_wr32(device, 0x40011c, 0xffffffff); + nvkm_wr32(device, 0x400134, 0xffffffff); - nv_wr32(priv, 0x400054, 0x2c350f63); + nvkm_wr32(device, 0x400054, 0x2c350f63); - gf100_gr_zbc_init(priv); + gf100_gr_zbc_init(gr); - return gm204_gr_init_ctxctl(priv); + return gm204_gr_init_ctxctl(gr); } -struct nvkm_oclass * -gm204_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0x24), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gm204_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gm204_grctx_oclass, - .sclass = gm204_gr_sclass, +static const struct gf100_gr_func +gm204_gr = { + .init = gm204_gr_init, .mmio = gm204_gr_pack_mmio, .ppc_nr = 2, -}.base; + .grctx = &gm204_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, MAXWELL_B, &gf100_fermi }, + { -1, -1, MAXWELL_COMPUTE_B }, + {} + } +}; + +int +gm204_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gm204_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c index 04b9733d1..341dc560a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c @@ -24,17 +24,25 @@ #include "gf100.h" #include "ctxgf100.h" -struct nvkm_oclass * -gm206_gr_oclass = &(struct gf100_gr_oclass) { - .base.handle = NV_ENGINE(GR, 0x26), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, - .dtor = gf100_gr_dtor, - .init = gm204_gr_init, - .fini = _nvkm_gr_fini, - }, - .cclass = &gm206_grctx_oclass, - .sclass = gm204_gr_sclass, +#include + +static const struct gf100_gr_func +gm206_gr = { + .init = gm204_gr_init, .mmio = gm204_gr_pack_mmio, .ppc_nr = 2, -}.base; + .grctx = &gm206_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, MAXWELL_B, &gf100_fermi }, + { -1, -1, MAXWELL_COMPUTE_B }, + {} + } +}; + +int +gm206_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(&gm206_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c new file mode 100644 index 000000000..65b6e3d1e --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include "gf100.h" +#include "ctxgf100.h" + +#include + +#include + +static void +gm20b_gr_init_gpc_mmu(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + u32 val; + + /* TODO this needs to be removed once secure boot works */ + if (1) { + nvkm_wr32(device, 0x100ce4, 0xffffffff); + } + + /* TODO update once secure boot works */ + val = nvkm_rd32(device, 0x100c80); + val &= 0xf000087f; + nvkm_wr32(device, 0x418880, val); + nvkm_wr32(device, 0x418890, 0); + nvkm_wr32(device, 0x418894, 0); + + nvkm_wr32(device, 0x4188b0, nvkm_rd32(device, 0x100cc4)); + nvkm_wr32(device, 0x4188b4, nvkm_rd32(device, 0x100cc8)); + nvkm_wr32(device, 0x4188b8, nvkm_rd32(device, 0x100ccc)); + + nvkm_wr32(device, 0x4188ac, nvkm_rd32(device, 0x100800)); +} + +static void +gm20b_gr_set_hww_esr_report_mask(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_wr32(device, 0x419e44, 0xdffffe); + nvkm_wr32(device, 0x419e4c, 0x5); +} + +static const struct gf100_gr_func +gm20b_gr = { + .dtor = gk20a_gr_dtor, + .init = gk20a_gr_init, + .init_gpc_mmu = gm20b_gr_init_gpc_mmu, + .set_hww_esr_report_mask = gm20b_gr_set_hww_esr_report_mask, + .ppc_nr = 1, + .grctx = &gm20b_grctx, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, MAXWELL_B, &gf100_fermi }, + { -1, -1, MAXWELL_COMPUTE_B }, + {} + } +}; + +int +gm20b_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gk20a_gr_new_(&gm20b_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt200.c new file mode 100644 index 000000000..2e68919f0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt200.c @@ -0,0 +1,47 @@ +/* + * 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 "nv50.h" + +static const struct nvkm_gr_func +gt200_gr = { + .init = nv50_gr_init, + .intr = nv50_gr_intr, + .chan_new = nv50_gr_chan_new, + .tlb_flush = g84_gr_tlb_flush, + .units = nv50_gr_units, + .sclass = { + { -1, -1, 0x0030, &nv50_gr_object }, + { -1, -1, 0x502d, &nv50_gr_object }, + { -1, -1, 0x5039, &nv50_gr_object }, + { -1, -1, 0x50c0, &nv50_gr_object }, + { -1, -1, 0x8397, &nv50_gr_object }, + {} + } +}; + +int +gt200_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv50_gr_new_(>200_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt215.c new file mode 100644 index 000000000..2bf7aac36 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/gt215.c @@ -0,0 +1,48 @@ +/* + * 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 "nv50.h" + +static const struct nvkm_gr_func +gt215_gr = { + .init = nv50_gr_init, + .intr = nv50_gr_intr, + .chan_new = nv50_gr_chan_new, + .tlb_flush = g84_gr_tlb_flush, + .units = nv50_gr_units, + .sclass = { + { -1, -1, 0x0030, &nv50_gr_object }, + { -1, -1, 0x502d, &nv50_gr_object }, + { -1, -1, 0x5039, &nv50_gr_object }, + { -1, -1, 0x50c0, &nv50_gr_object }, + { -1, -1, 0x8597, &nv50_gr_object }, + { -1, -1, 0x85c0, &nv50_gr_object }, + {} + } +}; + +int +gt215_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv50_gr_new_(>215_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp79.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp79.c new file mode 100644 index 000000000..95d5219fa --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp79.c @@ -0,0 +1,46 @@ +/* + * 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 "nv50.h" + +static const struct nvkm_gr_func +mcp79_gr = { + .init = nv50_gr_init, + .intr = nv50_gr_intr, + .chan_new = nv50_gr_chan_new, + .units = nv50_gr_units, + .sclass = { + { -1, -1, 0x0030, &nv50_gr_object }, + { -1, -1, 0x502d, &nv50_gr_object }, + { -1, -1, 0x5039, &nv50_gr_object }, + { -1, -1, 0x50c0, &nv50_gr_object }, + { -1, -1, 0x8397, &nv50_gr_object }, + {} + } +}; + +int +mcp79_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv50_gr_new_(&mcp79_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp89.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp89.c new file mode 100644 index 000000000..027b58e59 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp89.c @@ -0,0 +1,48 @@ +/* + * 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 "nv50.h" + +static const struct nvkm_gr_func +mcp89_gr = { + .init = nv50_gr_init, + .intr = nv50_gr_intr, + .chan_new = nv50_gr_chan_new, + .tlb_flush = g84_gr_tlb_flush, + .units = nv50_gr_units, + .sclass = { + { -1, -1, 0x0030, &nv50_gr_object }, + { -1, -1, 0x502d, &nv50_gr_object }, + { -1, -1, 0x5039, &nv50_gr_object }, + { -1, -1, 0x50c0, &nv50_gr_object }, + { -1, -1, 0x85c0, &nv50_gr_object }, + { -1, -1, 0x8697, &nv50_gr_object }, + {} + } +}; + +int +mcp89_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv50_gr_new_(&mcp89_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c index 2614510c2..85c5b7fea 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c @@ -21,13 +21,13 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include +#include "priv.h" #include "regs.h" #include -#include -#include +#include #include +#include #include #include @@ -346,25 +346,23 @@ nv04_gr_ctx_regs[] = { NV04_PGRAPH_DEBUG_3 }; -struct nv04_gr_priv { +#define nv04_gr(p) container_of((p), struct nv04_gr, base) + +struct nv04_gr { struct nvkm_gr base; struct nv04_gr_chan *chan[16]; spinlock_t lock; }; +#define nv04_gr_chan(p) container_of((p), struct nv04_gr_chan, object) + struct nv04_gr_chan { - struct nvkm_object base; + struct nvkm_object object; + struct nv04_gr *gr; int chid; u32 nv04[ARRAY_SIZE(nv04_gr_ctx_regs)]; }; - -static inline struct nv04_gr_priv * -nv04_gr_priv(struct nv04_gr_chan *chan) -{ - return (void *)nv_object(chan)->engine; -} - /******************************************************************************* * Graphics object classes ******************************************************************************/ @@ -444,35 +442,34 @@ nv04_gr_priv(struct nv04_gr_chan *chan) */ static void -nv04_gr_set_ctx1(struct nvkm_object *object, u32 mask, u32 value) +nv04_gr_set_ctx1(struct nvkm_device *device, u32 inst, u32 mask, u32 value) { - struct nv04_gr_priv *priv = (void *)object->engine; - int subc = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; + int subc = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; u32 tmp; - tmp = nv_ro32(object, 0x00); + tmp = nvkm_rd32(device, 0x700000 + inst); tmp &= ~mask; tmp |= value; - nv_wo32(object, 0x00, tmp); + nvkm_wr32(device, 0x700000 + inst, tmp); - nv_wr32(priv, NV04_PGRAPH_CTX_SWITCH1, tmp); - nv_wr32(priv, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); + nvkm_wr32(device, NV04_PGRAPH_CTX_SWITCH1, tmp); + nvkm_wr32(device, NV04_PGRAPH_CTX_CACHE1 + (subc << 2), tmp); } static void -nv04_gr_set_ctx_val(struct nvkm_object *object, u32 mask, u32 value) +nv04_gr_set_ctx_val(struct nvkm_device *device, u32 inst, u32 mask, u32 value) { int class, op, valid = 1; u32 tmp, ctx1; - ctx1 = nv_ro32(object, 0x00); + ctx1 = nvkm_rd32(device, 0x700000 + inst); class = ctx1 & 0xff; op = (ctx1 >> 15) & 7; - tmp = nv_ro32(object, 0x0c); + tmp = nvkm_rd32(device, 0x70000c + inst); tmp &= ~mask; tmp |= value; - nv_wo32(object, 0x0c, tmp); + nvkm_wr32(device, 0x70000c + inst, tmp); /* check for valid surf2d/surf_dst/surf_color */ if (!(tmp & 0x02000000)) @@ -504,527 +501,567 @@ nv04_gr_set_ctx_val(struct nvkm_object *object, u32 mask, u32 value) break; } - nv04_gr_set_ctx1(object, 0x01000000, valid << 24); + nv04_gr_set_ctx1(device, inst, 0x01000000, valid << 24); } -static int -nv04_gr_mthd_set_operation(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_set_operation(struct nvkm_device *device, u32 inst, u32 data) { - u32 class = nv_ro32(object, 0) & 0xff; - u32 data = *(u32 *)args; + u8 class = nvkm_rd32(device, 0x700000) & 0x000000ff; if (data > 5) - return 1; + return false; /* Old versions of the objects only accept first three operations. */ if (data > 2 && class < 0x40) - return 1; - nv04_gr_set_ctx1(object, 0x00038000, data << 15); + return false; + nv04_gr_set_ctx1(device, inst, 0x00038000, data << 15); /* changing operation changes set of objects needed for validation */ - nv04_gr_set_ctx_val(object, 0, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0, 0); + return true; } -static int -nv04_gr_mthd_surf3d_clip_h(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_surf3d_clip_h(struct nvkm_device *device, u32 inst, u32 data) { - struct nv04_gr_priv *priv = (void *)object->engine; - u32 data = *(u32 *)args; u32 min = data & 0xffff, max; u32 w = data >> 16; if (min & 0x8000) /* too large */ - return 1; + return false; if (w & 0x8000) /* yes, it accepts negative for some reason. */ w |= 0xffff0000; max = min + w; max &= 0x3ffff; - nv_wr32(priv, 0x40053c, min); - nv_wr32(priv, 0x400544, max); - return 0; + nvkm_wr32(device, 0x40053c, min); + nvkm_wr32(device, 0x400544, max); + return true; } -static int -nv04_gr_mthd_surf3d_clip_v(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_surf3d_clip_v(struct nvkm_device *device, u32 inst, u32 data) { - struct nv04_gr_priv *priv = (void *)object->engine; - u32 data = *(u32 *)args; u32 min = data & 0xffff, max; u32 w = data >> 16; if (min & 0x8000) /* too large */ - return 1; + return false; if (w & 0x8000) /* yes, it accepts negative for some reason. */ w |= 0xffff0000; max = min + w; max &= 0x3ffff; - nv_wr32(priv, 0x400540, min); - nv_wr32(priv, 0x400548, max); - return 0; + nvkm_wr32(device, 0x400540, min); + nvkm_wr32(device, 0x400548, max); + return true; } -static u16 -nv04_gr_mthd_bind_class(struct nvkm_object *object, u32 *args, u32 size) +static u8 +nv04_gr_mthd_bind_class(struct nvkm_device *device, u32 inst) { - struct nvkm_instmem *imem = nvkm_instmem(object); - u32 inst = *(u32 *)args << 4; - return nv_ro32(imem, inst); + return nvkm_rd32(device, 0x700000 + (inst << 4)); } -static int -nv04_gr_mthd_bind_surf2d(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_surf2d(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx1(object, 0x00004000, 0); - nv04_gr_set_ctx_val(object, 0x02000000, 0); - return 0; + nv04_gr_set_ctx1(device, inst, 0x00004000, 0); + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0); + return true; case 0x42: - nv04_gr_set_ctx1(object, 0x00004000, 0); - nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); - return 0; + nv04_gr_set_ctx1(device, inst, 0x00004000, 0); + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx1(object, 0x00004000, 0); - nv04_gr_set_ctx_val(object, 0x02000000, 0); - return 0; + nv04_gr_set_ctx1(device, inst, 0x00004000, 0); + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0); + return true; case 0x42: - nv04_gr_set_ctx1(object, 0x00004000, 0); - nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); - return 0; + nv04_gr_set_ctx1(device, inst, 0x00004000, 0); + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000); + return true; case 0x52: - nv04_gr_set_ctx1(object, 0x00004000, 0x00004000); - nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); - return 0; + nv04_gr_set_ctx1(device, inst, 0x00004000, 0x00004000); + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000); + return true; } - return 1; + return false; } -static int -nv01_gr_mthd_bind_patt(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv01_gr_mthd_bind_patt(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x08000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x08000000, 0); + return true; case 0x18: - nv04_gr_set_ctx_val(object, 0x08000000, 0x08000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x08000000, 0x08000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_patt(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_patt(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x08000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x08000000, 0); + return true; case 0x44: - nv04_gr_set_ctx_val(object, 0x08000000, 0x08000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x08000000, 0x08000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_rop(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_rop(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x10000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x10000000, 0); + return true; case 0x43: - nv04_gr_set_ctx_val(object, 0x10000000, 0x10000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x10000000, 0x10000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_beta1(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_beta1(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x20000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x20000000, 0); + return true; case 0x12: - nv04_gr_set_ctx_val(object, 0x20000000, 0x20000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x20000000, 0x20000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_beta4(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_beta4(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x40000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x40000000, 0); + return true; case 0x72: - nv04_gr_set_ctx_val(object, 0x40000000, 0x40000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x40000000, 0x40000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_surf_dst(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_surf_dst(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x02000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0); + return true; case 0x58: - nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_surf_src(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_surf_src(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x04000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x04000000, 0); + return true; case 0x59: - nv04_gr_set_ctx_val(object, 0x04000000, 0x04000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x04000000, 0x04000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_surf_color(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_surf_color(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x02000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0); + return true; case 0x5a: - nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000); + return true; } - return 1; + return false; } -static int -nv04_gr_mthd_bind_surf_zeta(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv04_gr_mthd_bind_surf_zeta(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx_val(object, 0x04000000, 0); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x04000000, 0); + return true; case 0x5b: - nv04_gr_set_ctx_val(object, 0x04000000, 0x04000000); - return 0; + nv04_gr_set_ctx_val(device, inst, 0x04000000, 0x04000000); + return true; } - return 1; + return false; } -static int -nv01_gr_mthd_bind_clip(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv01_gr_mthd_bind_clip(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx1(object, 0x2000, 0); - return 0; + nv04_gr_set_ctx1(device, inst, 0x2000, 0); + return true; case 0x19: - nv04_gr_set_ctx1(object, 0x2000, 0x2000); - return 0; + nv04_gr_set_ctx1(device, inst, 0x2000, 0x2000); + return true; } - return 1; + return false; } -static int -nv01_gr_mthd_bind_chroma(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +nv01_gr_mthd_bind_chroma(struct nvkm_device *device, u32 inst, u32 data) { - switch (nv04_gr_mthd_bind_class(object, args, size)) { + switch (nv04_gr_mthd_bind_class(device, data)) { case 0x30: - nv04_gr_set_ctx1(object, 0x1000, 0); - return 0; + nv04_gr_set_ctx1(device, inst, 0x1000, 0); + return true; /* Yes, for some reason even the old versions of objects * accept 0x57 and not 0x17. Consistency be damned. */ case 0x57: - nv04_gr_set_ctx1(object, 0x1000, 0x1000); - return 0; + nv04_gr_set_ctx1(device, inst, 0x1000, 0x1000); + return true; } - return 1; + return false; } -static struct nvkm_omthds -nv03_gr_gdi_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_patt }, - { 0x0188, 0x0188, nv04_gr_mthd_bind_rop }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_beta1 }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_surf_dst }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; - -static struct nvkm_omthds -nv04_gr_gdi_omthds[] = { - { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv03_gr_mthd_gdi(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_patt; break; + case 0x0188: func = nv04_gr_mthd_bind_rop; break; + case 0x018c: func = nv04_gr_mthd_bind_beta1; break; + case 0x0190: func = nv04_gr_mthd_bind_surf_dst; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv01_gr_blit_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, - { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, - { 0x018c, 0x018c, nv01_gr_mthd_bind_patt }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_surf_dst }, - { 0x019c, 0x019c, nv04_gr_mthd_bind_surf_src }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv04_gr_mthd_gdi(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0188: func = nv04_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_beta4; break; + case 0x0198: func = nv04_gr_mthd_bind_surf2d; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_blit_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, - { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_patt }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_beta4 }, - { 0x019c, 0x019c, nv04_gr_mthd_bind_surf2d }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv01_gr_mthd_blit(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_chroma; break; + case 0x0188: func = nv01_gr_mthd_bind_clip; break; + case 0x018c: func = nv01_gr_mthd_bind_patt; break; + case 0x0190: func = nv04_gr_mthd_bind_rop; break; + case 0x0194: func = nv04_gr_mthd_bind_beta1; break; + case 0x0198: func = nv04_gr_mthd_bind_surf_dst; break; + case 0x019c: func = nv04_gr_mthd_bind_surf_src; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_iifc_omthds[] = { - { 0x0188, 0x0188, nv01_gr_mthd_bind_chroma }, - { 0x018c, 0x018c, nv01_gr_mthd_bind_clip }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_patt }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_rop }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_beta1 }, - { 0x019c, 0x019c, nv04_gr_mthd_bind_beta4 }, - { 0x01a0, 0x01a0, nv04_gr_mthd_bind_surf2d_swzsurf }, - { 0x03e4, 0x03e4, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv04_gr_mthd_blit(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_chroma; break; + case 0x0188: func = nv01_gr_mthd_bind_clip; break; + case 0x018c: func = nv04_gr_mthd_bind_patt; break; + case 0x0190: func = nv04_gr_mthd_bind_rop; break; + case 0x0194: func = nv04_gr_mthd_bind_beta1; break; + case 0x0198: func = nv04_gr_mthd_bind_beta4; break; + case 0x019c: func = nv04_gr_mthd_bind_surf2d; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv01_gr_ifc_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, - { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, - { 0x018c, 0x018c, nv01_gr_mthd_bind_patt }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_surf_dst }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv04_gr_mthd_iifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0188: func = nv01_gr_mthd_bind_chroma; break; + case 0x018c: func = nv01_gr_mthd_bind_clip; break; + case 0x0190: func = nv04_gr_mthd_bind_patt; break; + case 0x0194: func = nv04_gr_mthd_bind_rop; break; + case 0x0198: func = nv04_gr_mthd_bind_beta1; break; + case 0x019c: func = nv04_gr_mthd_bind_beta4; break; + case 0x01a0: func = nv04_gr_mthd_bind_surf2d_swzsurf; break; + case 0x03e4: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_ifc_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, - { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_patt }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_beta4 }, - { 0x019c, 0x019c, nv04_gr_mthd_bind_surf2d }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv01_gr_mthd_ifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_chroma; break; + case 0x0188: func = nv01_gr_mthd_bind_clip; break; + case 0x018c: func = nv01_gr_mthd_bind_patt; break; + case 0x0190: func = nv04_gr_mthd_bind_rop; break; + case 0x0194: func = nv04_gr_mthd_bind_beta1; break; + case 0x0198: func = nv04_gr_mthd_bind_surf_dst; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv03_gr_sifc_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, - { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv04_gr_mthd_ifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_chroma; break; + case 0x0188: func = nv01_gr_mthd_bind_clip; break; + case 0x018c: func = nv04_gr_mthd_bind_patt; break; + case 0x0190: func = nv04_gr_mthd_bind_rop; break; + case 0x0194: func = nv04_gr_mthd_bind_beta1; break; + case 0x0198: func = nv04_gr_mthd_bind_beta4; break; + case 0x019c: func = nv04_gr_mthd_bind_surf2d; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_sifc_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, - { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv03_gr_mthd_sifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_chroma; break; + case 0x0188: func = nv01_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv03_gr_sifm_omthds[] = { - { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, - { 0x0304, 0x0304, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv04_gr_mthd_sifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_chroma; break; + case 0x0188: func = nv04_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_beta4; break; + case 0x0198: func = nv04_gr_mthd_bind_surf2d; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_sifm_omthds[] = { - { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, - { 0x0304, 0x0304, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv03_gr_mthd_sifm(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0188: func = nv01_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break; + case 0x0304: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_surf3d_omthds[] = { - { 0x02f8, 0x02f8, nv04_gr_mthd_surf3d_clip_h }, - { 0x02fc, 0x02fc, nv04_gr_mthd_surf3d_clip_v }, - {} -}; +static bool +nv04_gr_mthd_sifm(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0188: func = nv04_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_beta4; break; + case 0x0198: func = nv04_gr_mthd_bind_surf2d; break; + case 0x0304: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv03_gr_ttri_omthds[] = { - { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_surf_color }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_surf_zeta }, - {} -}; +static bool +nv04_gr_mthd_surf3d(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x02f8: func = nv04_gr_mthd_surf3d_clip_h; break; + case 0x02fc: func = nv04_gr_mthd_surf3d_clip_v; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv01_gr_prim_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_clip }, - { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv03_gr_mthd_ttri(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0188: func = nv01_gr_mthd_bind_clip; break; + case 0x018c: func = nv04_gr_mthd_bind_surf_color; break; + case 0x0190: func = nv04_gr_mthd_bind_surf_zeta; break; + default: + return false; + } + return func(device, inst, data); +} -static struct nvkm_omthds -nv04_gr_prim_omthds[] = { - { 0x0184, 0x0184, nv01_gr_mthd_bind_clip }, - { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, - { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, - { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, - { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, - { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, - { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, - {} -}; +static bool +nv01_gr_mthd_prim(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_clip; break; + case 0x0188: func = nv01_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} -static int -nv04_gr_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static bool +nv04_gr_mthd_prim(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) { - struct nvkm_gpuobj *obj; - int ret; + bool (*func)(struct nvkm_device *, u32, u32); + switch (mthd) { + case 0x0184: func = nv01_gr_mthd_bind_clip; break; + case 0x0188: func = nv04_gr_mthd_bind_patt; break; + case 0x018c: func = nv04_gr_mthd_bind_rop; break; + case 0x0190: func = nv04_gr_mthd_bind_beta1; break; + case 0x0194: func = nv04_gr_mthd_bind_beta4; break; + case 0x0198: func = nv04_gr_mthd_bind_surf2d; break; + case 0x02fc: func = nv04_gr_mthd_set_operation; break; + default: + return false; + } + return func(device, inst, data); +} - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, - 16, 16, 0, &obj); - *pobject = nv_object(obj); - if (ret) - return ret; +static bool +nv04_gr_mthd(struct nvkm_device *device, u32 inst, u32 mthd, u32 data) +{ + bool (*func)(struct nvkm_device *, u32, u32, u32); + switch (nvkm_rd32(device, 0x700000 + inst) & 0x000000ff) { + case 0x1c ... 0x1e: + func = nv01_gr_mthd_prim; break; + case 0x1f: func = nv01_gr_mthd_blit; break; + case 0x21: func = nv01_gr_mthd_ifc; break; + case 0x36: func = nv03_gr_mthd_sifc; break; + case 0x37: func = nv03_gr_mthd_sifm; break; + case 0x48: func = nv03_gr_mthd_ttri; break; + case 0x4a: func = nv04_gr_mthd_gdi; break; + case 0x4b: func = nv03_gr_mthd_gdi; break; + case 0x53: func = nv04_gr_mthd_surf3d; break; + case 0x5c ... 0x5e: + func = nv04_gr_mthd_prim; break; + case 0x5f: func = nv04_gr_mthd_blit; break; + case 0x60: func = nv04_gr_mthd_iifc; break; + case 0x61: func = nv04_gr_mthd_ifc; break; + case 0x76: func = nv04_gr_mthd_sifc; break; + case 0x77: func = nv04_gr_mthd_sifm; break; + default: + return false; + } + return func(device, inst, mthd, data); +} - nv_wo32(obj, 0x00, nv_mclass(obj)); +static int +nv04_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) +{ + int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16, align, + false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, object->oclass); #ifdef __BIG_ENDIAN - nv_mo32(obj, 0x00, 0x00080000, 0x00080000); + nvkm_mo32(*pgpuobj, 0x00, 0x00080000, 0x00080000); #endif - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - return 0; + nvkm_wo32(*pgpuobj, 0x04, 0x00000000); + nvkm_wo32(*pgpuobj, 0x08, 0x00000000); + nvkm_wo32(*pgpuobj, 0x0c, 0x00000000); + nvkm_done(*pgpuobj); + } + return ret; } -struct nvkm_ofuncs -nv04_gr_ofuncs = { - .ctor = nv04_gr_object_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, -}; - -static struct nvkm_oclass -nv04_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ - { 0x0017, &nv04_gr_ofuncs }, /* chroma */ - { 0x0018, &nv04_gr_ofuncs }, /* pattern (nv01) */ - { 0x0019, &nv04_gr_ofuncs }, /* clip */ - { 0x001c, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* line */ - { 0x001d, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* tri */ - { 0x001e, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* rect */ - { 0x001f, &nv04_gr_ofuncs, nv01_gr_blit_omthds }, - { 0x0021, &nv04_gr_ofuncs, nv01_gr_ifc_omthds }, - { 0x0030, &nv04_gr_ofuncs }, /* null */ - { 0x0036, &nv04_gr_ofuncs, nv03_gr_sifc_omthds }, - { 0x0037, &nv04_gr_ofuncs, nv03_gr_sifm_omthds }, - { 0x0038, &nv04_gr_ofuncs }, /* dvd subpicture */ - { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ - { 0x0042, &nv04_gr_ofuncs }, /* surf2d */ - { 0x0043, &nv04_gr_ofuncs }, /* rop */ - { 0x0044, &nv04_gr_ofuncs }, /* pattern */ - { 0x0048, &nv04_gr_ofuncs, nv03_gr_ttri_omthds }, - { 0x004a, &nv04_gr_ofuncs, nv04_gr_gdi_omthds }, - { 0x004b, &nv04_gr_ofuncs, nv03_gr_gdi_omthds }, - { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ - { 0x0053, &nv04_gr_ofuncs, nv04_gr_surf3d_omthds }, - { 0x0054, &nv04_gr_ofuncs }, /* ttri */ - { 0x0055, &nv04_gr_ofuncs }, /* mtri */ - { 0x0057, &nv04_gr_ofuncs }, /* chroma */ - { 0x0058, &nv04_gr_ofuncs }, /* surf_dst */ - { 0x0059, &nv04_gr_ofuncs }, /* surf_src */ - { 0x005a, &nv04_gr_ofuncs }, /* surf_color */ - { 0x005b, &nv04_gr_ofuncs }, /* surf_zeta */ - { 0x005c, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* line */ - { 0x005d, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* tri */ - { 0x005e, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* rect */ - { 0x005f, &nv04_gr_ofuncs, nv04_gr_blit_omthds }, - { 0x0060, &nv04_gr_ofuncs, nv04_gr_iifc_omthds }, - { 0x0061, &nv04_gr_ofuncs, nv04_gr_ifc_omthds }, - { 0x0064, &nv04_gr_ofuncs }, /* iifc (nv05) */ - { 0x0065, &nv04_gr_ofuncs }, /* ifc (nv05) */ - { 0x0066, &nv04_gr_ofuncs }, /* sifc (nv05) */ - { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ - { 0x0076, &nv04_gr_ofuncs, nv04_gr_sifc_omthds }, - { 0x0077, &nv04_gr_ofuncs, nv04_gr_sifm_omthds }, - {}, +const struct nvkm_object_func +nv04_gr_object = { + .bind = nv04_gr_object_bind, }; /******************************************************************************* @@ -1032,13 +1069,14 @@ nv04_gr_sclass[] = { ******************************************************************************/ static struct nv04_gr_chan * -nv04_gr_channel(struct nv04_gr_priv *priv) +nv04_gr_channel(struct nv04_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; struct nv04_gr_chan *chan = NULL; - if (nv_rd32(priv, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) { - int chid = nv_rd32(priv, NV04_PGRAPH_CTX_USER) >> 24; - if (chid < ARRAY_SIZE(priv->chan)) - chan = priv->chan[chid]; + if (nvkm_rd32(device, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) { + int chid = nvkm_rd32(device, NV04_PGRAPH_CTX_USER) >> 24; + if (chid < ARRAY_SIZE(gr->chan)) + chan = gr->chan[chid]; } return chan; } @@ -1046,55 +1084,52 @@ nv04_gr_channel(struct nv04_gr_priv *priv) static int nv04_gr_load_context(struct nv04_gr_chan *chan, int chid) { - struct nv04_gr_priv *priv = nv04_gr_priv(chan); + struct nvkm_device *device = chan->gr->base.engine.subdev.device; int i; for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) - nv_wr32(priv, nv04_gr_ctx_regs[i], chan->nv04[i]); + nvkm_wr32(device, nv04_gr_ctx_regs[i], chan->nv04[i]); - nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL, 0x10010100); - nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24); - nv_mask(priv, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000); + nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10010100); + nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24); + nvkm_mask(device, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000); return 0; } static int nv04_gr_unload_context(struct nv04_gr_chan *chan) { - struct nv04_gr_priv *priv = nv04_gr_priv(chan); + struct nvkm_device *device = chan->gr->base.engine.subdev.device; int i; for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) - chan->nv04[i] = nv_rd32(priv, nv04_gr_ctx_regs[i]); + chan->nv04[i] = nvkm_rd32(device, nv04_gr_ctx_regs[i]); - nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL, 0x10000000); - nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); + nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10000000); + nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); return 0; } static void -nv04_gr_context_switch(struct nv04_gr_priv *priv) +nv04_gr_context_switch(struct nv04_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; struct nv04_gr_chan *prev = NULL; struct nv04_gr_chan *next = NULL; - unsigned long flags; int chid; - spin_lock_irqsave(&priv->lock, flags); - nv04_gr_idle(priv); + nv04_gr_idle(&gr->base); /* If previous context is valid, we need to save it */ - prev = nv04_gr_channel(priv); + prev = nv04_gr_channel(gr); if (prev) nv04_gr_unload_context(prev); /* load context for next channel */ - chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f; - next = priv->chan[chid]; + chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f; + next = gr->chan[chid]; if (next) nv04_gr_load_context(next, chid); - - spin_unlock_irqrestore(&priv->lock, flags); } static u32 *ctx_reg(struct nv04_gr_chan *chan, u32 reg) @@ -1109,98 +1144,85 @@ static u32 *ctx_reg(struct nv04_gr_chan *chan, u32 reg) return NULL; } -static int -nv04_gr_context_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void * +nv04_gr_chan_dtor(struct nvkm_object *object) { - struct nvkm_fifo_chan *fifo = (void *)parent; - struct nv04_gr_priv *priv = (void *)engine; - struct nv04_gr_chan *chan; + struct nv04_gr_chan *chan = nv04_gr_chan(object); + struct nv04_gr *gr = chan->gr; unsigned long flags; - int ret; - - ret = nvkm_object_create(parent, engine, oclass, 0, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - spin_lock_irqsave(&priv->lock, flags); - if (priv->chan[fifo->chid]) { - *pobject = nv_object(priv->chan[fifo->chid]); - atomic_inc(&(*pobject)->refcount); - spin_unlock_irqrestore(&priv->lock, flags); - nvkm_object_destroy(&chan->base); - return 1; - } - *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; - - priv->chan[fifo->chid] = chan; - chan->chid = fifo->chid; - spin_unlock_irqrestore(&priv->lock, flags); - return 0; + spin_lock_irqsave(&gr->lock, flags); + gr->chan[chan->chid] = NULL; + spin_unlock_irqrestore(&gr->lock, flags); + return chan; } -static void -nv04_gr_context_dtor(struct nvkm_object *object) +static int +nv04_gr_chan_fini(struct nvkm_object *object, bool suspend) { - struct nv04_gr_priv *priv = (void *)object->engine; - struct nv04_gr_chan *chan = (void *)object; + struct nv04_gr_chan *chan = nv04_gr_chan(object); + struct nv04_gr *gr = chan->gr; + struct nvkm_device *device = gr->base.engine.subdev.device; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - priv->chan[chan->chid] = NULL; - spin_unlock_irqrestore(&priv->lock, flags); - - nvkm_object_destroy(&chan->base); + spin_lock_irqsave(&gr->lock, flags); + nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + if (nv04_gr_channel(gr) == chan) + nv04_gr_unload_context(chan); + nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&gr->lock, flags); + return 0; } +static const struct nvkm_object_func +nv04_gr_chan = { + .dtor = nv04_gr_chan_dtor, + .fini = nv04_gr_chan_fini, +}; + static int -nv04_gr_context_fini(struct nvkm_object *object, bool suspend) +nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nv04_gr_priv *priv = (void *)object->engine; - struct nv04_gr_chan *chan = (void *)object; + struct nv04_gr *gr = nv04_gr(base); + struct nv04_gr_chan *chan; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (nv04_gr_channel(priv) == chan) - nv04_gr_unload_context(chan); - nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&priv->lock, flags); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv04_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; - return nvkm_object_fini(&chan->base, suspend); -} + *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; -static struct nvkm_oclass -nv04_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_gr_context_ctor, - .dtor = nv04_gr_context_dtor, - .init = nvkm_object_init, - .fini = nv04_gr_context_fini, - }, -}; + spin_lock_irqsave(&gr->lock, flags); + gr->chan[chan->chid] = chan; + spin_unlock_irqrestore(&gr->lock, flags); + return 0; +} /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ bool -nv04_gr_idle(void *obj) +nv04_gr_idle(struct nvkm_gr *gr) { - struct nvkm_gr *gr = nvkm_gr(obj); + struct nvkm_subdev *subdev = &gr->engine.subdev; + struct nvkm_device *device = subdev->device; u32 mask = 0xffffffff; - if (nv_device(obj)->card_type == NV_40) + if (device->card_type == NV_40) mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; - if (!nv_wait(gr, NV04_PGRAPH_STATUS, mask, 0)) { - nv_error(gr, "idle timed out with status 0x%08x\n", - nv_rd32(gr, NV04_PGRAPH_STATUS)); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, NV04_PGRAPH_STATUS) & mask)) + break; + ) < 0) { + nvkm_error(subdev, "idle timed out with status %08x\n", + nvkm_rd32(device, NV04_PGRAPH_STATUS)); return false; } @@ -1247,136 +1269,159 @@ nv04_gr_nsource[] = { }; static void -nv04_gr_intr(struct nvkm_subdev *subdev) +nv04_gr_intr(struct nvkm_gr *base) { - struct nv04_gr_priv *priv = (void *)subdev; - struct nv04_gr_chan *chan = NULL; - struct nvkm_namedb *namedb = NULL; - struct nvkm_handle *handle = NULL; - u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); - u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + struct nv04_gr *gr = nv04_gr(base); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); + u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); + u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); + u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); u32 chid = (addr & 0x0f000000) >> 24; u32 subc = (addr & 0x0000e000) >> 13; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(priv, 0x400180 + subc * 4) & 0xff; - u32 inst = (nv_rd32(priv, 0x40016c) & 0xffff) << 4; + u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nvkm_rd32(device, 0x400180 + subc * 4) & 0xff; + u32 inst = (nvkm_rd32(device, 0x40016c) & 0xffff) << 4; u32 show = stat; + char msg[128], src[128], sta[128]; + struct nv04_gr_chan *chan; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - chan = priv->chan[chid]; - if (chan) - namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&gr->lock, flags); + chan = gr->chan[chid]; if (stat & NV_PGRAPH_INTR_NOTIFY) { if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { - handle = nvkm_namedb_get_vinst(namedb, inst); - if (handle && !nv_call(handle->object, mthd, data)) + if (!nv04_gr_mthd(device, inst, mthd, data)) show &= ~NV_PGRAPH_INTR_NOTIFY; } } if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv04_gr_context_switch(priv); + nv04_gr_context_switch(gr); } - nv_wr32(priv, NV03_PGRAPH_INTR, stat); - nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + nvkm_wr32(device, NV03_PGRAPH_INTR, stat); + nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); - nvkm_bitfield_print(nv04_gr_intr_name, show); - pr_cont(" nsource:"); - nvkm_bitfield_print(nv04_gr_nsource, nsource); - pr_cont(" nstatus:"); - nvkm_bitfield_print(nv04_gr_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, nvkm_client_name(chan), subc, class, mthd, - data); + nvkm_snprintbf(msg, sizeof(msg), nv04_gr_intr_name, show); + nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); + nvkm_snprintbf(sta, sizeof(sta), nv04_gr_nstatus, nstatus); + nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " + "nstatus %08x [%s] ch %d [%s] subc %d " + "class %04x mthd %04x data %08x\n", + show, msg, nsource, src, nstatus, sta, chid, + chan ? chan->object.client->name : "unknown", + subc, class, mthd, data); } - nvkm_namedb_put(handle); + spin_unlock_irqrestore(&gr->lock, flags); } static int -nv04_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_gr_init(struct nvkm_gr *base) { - struct nv04_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv04_gr_intr; - nv_engine(priv)->cclass = &nv04_gr_cclass; - nv_engine(priv)->sclass = nv04_gr_sclass; - spin_lock_init(&priv->lock); - return 0; -} - -static int -nv04_gr_init(struct nvkm_object *object) -{ - struct nvkm_engine *engine = nv_engine(object); - struct nv04_gr_priv *priv = (void *)engine; - int ret; - - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; + struct nv04_gr *gr = nv04_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; /* Enable PGRAPH interrupts */ - nv_wr32(priv, NV03_PGRAPH_INTR, 0xFFFFFFFF); - nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(priv, NV04_PGRAPH_VALID1, 0); - nv_wr32(priv, NV04_PGRAPH_VALID2, 0); - /*nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x000001FF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x1231c000); + nvkm_wr32(device, NV03_PGRAPH_INTR, 0xFFFFFFFF); + nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nvkm_wr32(device, NV04_PGRAPH_VALID1, 0); + nvkm_wr32(device, NV04_PGRAPH_VALID2, 0); + /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x000001FF); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x1231c000); /*1231C000 blob, 001 haiku*/ /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ - nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x72111100); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x72111100); /*0x72111100 blob , 01 haiku*/ - /*nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ - nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x11d5f071); + /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ + nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f071); /*haiku same*/ - /*nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ - nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); + /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ + nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); /*haiku and blob 10d4*/ - nv_wr32(priv, NV04_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL , 0x10000100); - nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); + nvkm_wr32(device, NV04_PGRAPH_STATE , 0xFFFFFFFF); + nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL , 0x10000100); + nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); /* These don't belong here, they're part of a per-channel context */ - nv_wr32(priv, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); - nv_wr32(priv, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); + nvkm_wr32(device, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); + nvkm_wr32(device, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); return 0; } -struct nvkm_oclass -nv04_gr_oclass = { - .handle = NV_ENGINE(GR, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_gr_ctor, - .dtor = _nvkm_gr_dtor, - .init = nv04_gr_init, - .fini = _nvkm_gr_fini, - }, +static const struct nvkm_gr_func +nv04_gr = { + .init = nv04_gr_init, + .intr = nv04_gr_intr, + .chan_new = nv04_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0017, &nv04_gr_object }, /* chroma */ + { -1, -1, 0x0018, &nv04_gr_object }, /* pattern (nv01) */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x001c, &nv04_gr_object }, /* line */ + { -1, -1, 0x001d, &nv04_gr_object }, /* tri */ + { -1, -1, 0x001e, &nv04_gr_object }, /* rect */ + { -1, -1, 0x001f, &nv04_gr_object }, + { -1, -1, 0x0021, &nv04_gr_object }, + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0036, &nv04_gr_object }, + { -1, -1, 0x0037, &nv04_gr_object }, + { -1, -1, 0x0038, &nv04_gr_object }, /* dvd subpicture */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0042, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* pattern */ + { -1, -1, 0x0048, &nv04_gr_object }, + { -1, -1, 0x004a, &nv04_gr_object }, + { -1, -1, 0x004b, &nv04_gr_object }, + { -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x0053, &nv04_gr_object }, + { -1, -1, 0x0054, &nv04_gr_object }, /* ttri */ + { -1, -1, 0x0055, &nv04_gr_object }, /* mtri */ + { -1, -1, 0x0057, &nv04_gr_object }, /* chroma */ + { -1, -1, 0x0058, &nv04_gr_object }, /* surf_dst */ + { -1, -1, 0x0059, &nv04_gr_object }, /* surf_src */ + { -1, -1, 0x005a, &nv04_gr_object }, /* surf_color */ + { -1, -1, 0x005b, &nv04_gr_object }, /* surf_zeta */ + { -1, -1, 0x005c, &nv04_gr_object }, /* line */ + { -1, -1, 0x005d, &nv04_gr_object }, /* tri */ + { -1, -1, 0x005e, &nv04_gr_object }, /* rect */ + { -1, -1, 0x005f, &nv04_gr_object }, + { -1, -1, 0x0060, &nv04_gr_object }, + { -1, -1, 0x0061, &nv04_gr_object }, + { -1, -1, 0x0064, &nv04_gr_object }, /* iifc (nv05) */ + { -1, -1, 0x0065, &nv04_gr_object }, /* ifc (nv05) */ + { -1, -1, 0x0066, &nv04_gr_object }, /* sifc (nv05) */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0076, &nv04_gr_object }, + { -1, -1, 0x0077, &nv04_gr_object }, + {} + } }; + +int +nv04_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + struct nv04_gr *gr; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + spin_lock_init(&gr->lock); + *pgr = &gr->base; + + return nvkm_gr_ctor(&nv04_gr, device, index, 0x00001000, + true, &gr->base); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c index 389904eb6..4542867fa 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c @@ -21,13 +21,13 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include +#include "nv10.h" #include "regs.h" #include -#include -#include +#include #include +#include #include struct pipe_state { @@ -386,14 +386,19 @@ static int nv17_gr_ctx_regs[] = { 0x00400a04, }; -struct nv10_gr_priv { +#define nv10_gr(p) container_of((p), struct nv10_gr, base) + +struct nv10_gr { struct nvkm_gr base; struct nv10_gr_chan *chan[32]; spinlock_t lock; }; +#define nv10_gr_chan(p) container_of((p), struct nv10_gr_chan, object) + struct nv10_gr_chan { - struct nvkm_object base; + struct nvkm_object object; + struct nv10_gr *gr; int chid; int nv10[ARRAY_SIZE(nv10_gr_ctx_regs)]; int nv17[ARRAY_SIZE(nv17_gr_ctx_regs)]; @@ -402,214 +407,151 @@ struct nv10_gr_chan { }; -static inline struct nv10_gr_priv * -nv10_gr_priv(struct nv10_gr_chan *chan) -{ - return (void *)nv_object(chan)->engine; -} - /******************************************************************************* * Graphics object classes ******************************************************************************/ -#define PIPE_SAVE(priv, state, addr) \ +#define PIPE_SAVE(gr, state, addr) \ do { \ int __i; \ - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, addr); \ for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ - state[__i] = nv_rd32(priv, NV10_PGRAPH_PIPE_DATA); \ + state[__i] = nvkm_rd32(device, NV10_PGRAPH_PIPE_DATA); \ } while (0) -#define PIPE_RESTORE(priv, state, addr) \ +#define PIPE_RESTORE(gr, state, addr) \ do { \ int __i; \ - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, addr); \ for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, state[__i]); \ + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, state[__i]); \ } while (0) -static struct nvkm_oclass -nv10_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs }, /* clip */ - { 0x0030, &nv04_gr_ofuncs }, /* null */ - { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs }, /* rop */ - { 0x0044, &nv04_gr_ofuncs }, /* pattern */ - { 0x004a, &nv04_gr_ofuncs }, /* gdi */ - { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ - { 0x005f, &nv04_gr_ofuncs }, /* blit */ - { 0x0062, &nv04_gr_ofuncs }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs }, /* ifc */ - { 0x009f, &nv04_gr_ofuncs }, /* blit */ - { 0x0093, &nv04_gr_ofuncs }, /* surf3d */ - { 0x0094, &nv04_gr_ofuncs }, /* ttri */ - { 0x0095, &nv04_gr_ofuncs }, /* mtri */ - { 0x0056, &nv04_gr_ofuncs }, /* celcius */ - {}, -}; - -static struct nvkm_oclass -nv15_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs }, /* clip */ - { 0x0030, &nv04_gr_ofuncs }, /* null */ - { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs }, /* rop */ - { 0x0044, &nv04_gr_ofuncs }, /* pattern */ - { 0x004a, &nv04_gr_ofuncs }, /* gdi */ - { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ - { 0x005f, &nv04_gr_ofuncs }, /* blit */ - { 0x0062, &nv04_gr_ofuncs }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs }, /* ifc */ - { 0x009f, &nv04_gr_ofuncs }, /* blit */ - { 0x0093, &nv04_gr_ofuncs }, /* surf3d */ - { 0x0094, &nv04_gr_ofuncs }, /* ttri */ - { 0x0095, &nv04_gr_ofuncs }, /* mtri */ - { 0x0096, &nv04_gr_ofuncs }, /* celcius */ - {}, -}; - -static int -nv17_gr_mthd_lma_window(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static void +nv17_gr_mthd_lma_window(struct nv10_gr_chan *chan, u32 mthd, u32 data) { - struct nv10_gr_chan *chan = (void *)object->parent; - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nvkm_device *device = chan->object.engine->subdev.device; + struct nvkm_gr *gr = &chan->gr->base; struct pipe_state *pipe = &chan->pipe_state; u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; u32 xfmode0, xfmode1; - u32 data = *(u32 *)args; int i; chan->lma_window[(mthd - 0x1638) / 4] = data; if (mthd != 0x1644) - return 0; + return; - nv04_gr_idle(priv); + nv04_gr_idle(gr); - PIPE_SAVE(priv, pipe_0x0040, 0x0040); - PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200); + PIPE_SAVE(device, pipe_0x0040, 0x0040); + PIPE_SAVE(device, pipe->pipe_0x0200, 0x0200); - PIPE_RESTORE(priv, chan->lma_window, 0x6790); + PIPE_RESTORE(device, chan->lma_window, 0x6790); - nv04_gr_idle(priv); + nv04_gr_idle(gr); - xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0); - xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1); + xfmode0 = nvkm_rd32(device, NV10_PGRAPH_XFMODE0); + xfmode1 = nvkm_rd32(device, NV10_PGRAPH_XFMODE1); - PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400); - PIPE_SAVE(priv, pipe_0x64c0, 0x64c0); - PIPE_SAVE(priv, pipe_0x6ab0, 0x6ab0); - PIPE_SAVE(priv, pipe_0x6a80, 0x6a80); + PIPE_SAVE(device, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(device, pipe_0x64c0, 0x64c0); + PIPE_SAVE(device, pipe_0x6ab0, 0x6ab0); + PIPE_SAVE(device, pipe_0x6a80, 0x6a80); - nv04_gr_idle(priv); + nv04_gr_idle(gr); - nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000); - nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + nvkm_wr32(device, NV10_PGRAPH_XFMODE0, 0x10000000); + nvkm_wr32(device, NV10_PGRAPH_XFMODE1, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); for (i = 0; i < 4; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); for (i = 0; i < 4; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); for (i = 0; i < 3; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); for (i = 0; i < 3; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); - PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000008); - nv04_gr_idle(priv); + PIPE_RESTORE(device, pipe->pipe_0x0200, 0x0200); - PIPE_RESTORE(priv, pipe_0x0040, 0x0040); + nv04_gr_idle(gr); - nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0); - nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1); + PIPE_RESTORE(device, pipe_0x0040, 0x0040); - PIPE_RESTORE(priv, pipe_0x64c0, 0x64c0); - PIPE_RESTORE(priv, pipe_0x6ab0, 0x6ab0); - PIPE_RESTORE(priv, pipe_0x6a80, 0x6a80); - PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400); + nvkm_wr32(device, NV10_PGRAPH_XFMODE0, xfmode0); + nvkm_wr32(device, NV10_PGRAPH_XFMODE1, xfmode1); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + PIPE_RESTORE(device, pipe_0x64c0, 0x64c0); + PIPE_RESTORE(device, pipe_0x6ab0, 0x6ab0); + PIPE_RESTORE(device, pipe_0x6a80, 0x6a80); + PIPE_RESTORE(device, pipe->pipe_0x4400, 0x4400); - nv04_gr_idle(priv); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); - return 0; + nv04_gr_idle(gr); } -static int -nv17_gr_mthd_lma_enable(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static void +nv17_gr_mthd_lma_enable(struct nv10_gr_chan *chan, u32 mthd, u32 data) { - struct nv10_gr_chan *chan = (void *)object->parent; - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nvkm_device *device = chan->object.engine->subdev.device; + struct nvkm_gr *gr = &chan->gr->base; - nv04_gr_idle(priv); + nv04_gr_idle(gr); - nv_mask(priv, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100); - nv_mask(priv, 0x4006b0, 0x08000000, 0x08000000); - return 0; + nvkm_mask(device, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100); + nvkm_mask(device, 0x4006b0, 0x08000000, 0x08000000); } -static struct nvkm_omthds -nv17_celcius_omthds[] = { - { 0x1638, 0x1638, nv17_gr_mthd_lma_window }, - { 0x163c, 0x163c, nv17_gr_mthd_lma_window }, - { 0x1640, 0x1640, nv17_gr_mthd_lma_window }, - { 0x1644, 0x1644, nv17_gr_mthd_lma_window }, - { 0x1658, 0x1658, nv17_gr_mthd_lma_enable }, - {} -}; +static bool +nv17_gr_mthd_celcius(struct nv10_gr_chan *chan, u32 mthd, u32 data) +{ + void (*func)(struct nv10_gr_chan *, u32, u32); + switch (mthd) { + case 0x1638 ... 0x1644: + func = nv17_gr_mthd_lma_window; break; + case 0x1658: func = nv17_gr_mthd_lma_enable; break; + default: + return false; + } + func(chan, mthd, data); + return true; +} -static struct nvkm_oclass -nv17_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs }, /* clip */ - { 0x0030, &nv04_gr_ofuncs }, /* null */ - { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs }, /* rop */ - { 0x0044, &nv04_gr_ofuncs }, /* pattern */ - { 0x004a, &nv04_gr_ofuncs }, /* gdi */ - { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ - { 0x005f, &nv04_gr_ofuncs }, /* blit */ - { 0x0062, &nv04_gr_ofuncs }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs }, /* ifc */ - { 0x009f, &nv04_gr_ofuncs }, /* blit */ - { 0x0093, &nv04_gr_ofuncs }, /* surf3d */ - { 0x0094, &nv04_gr_ofuncs }, /* ttri */ - { 0x0095, &nv04_gr_ofuncs }, /* mtri */ - { 0x0099, &nv04_gr_ofuncs, nv17_celcius_omthds }, - {}, -}; +static bool +nv10_gr_mthd(struct nv10_gr_chan *chan, u8 class, u32 mthd, u32 data) +{ + bool (*func)(struct nv10_gr_chan *, u32, u32); + switch (class) { + case 0x99: func = nv17_gr_mthd_celcius; break; + default: + return false; + } + return func(chan, mthd, data); +} /******************************************************************************* * PGRAPH context ******************************************************************************/ static struct nv10_gr_chan * -nv10_gr_channel(struct nv10_gr_priv *priv) +nv10_gr_channel(struct nv10_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; struct nv10_gr_chan *chan = NULL; - if (nv_rd32(priv, 0x400144) & 0x00010000) { - int chid = nv_rd32(priv, 0x400148) >> 24; - if (chid < ARRAY_SIZE(priv->chan)) - chan = priv->chan[chid]; + if (nvkm_rd32(device, 0x400144) & 0x00010000) { + int chid = nvkm_rd32(device, 0x400148) >> 24; + if (chid < ARRAY_SIZE(gr->chan)) + chan = gr->chan[chid]; } return chan; } @@ -617,75 +559,78 @@ nv10_gr_channel(struct nv10_gr_priv *priv) static void nv10_gr_save_pipe(struct nv10_gr_chan *chan) { - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nv10_gr *gr = chan->gr; struct pipe_state *pipe = &chan->pipe_state; - - PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400); - PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200); - PIPE_SAVE(priv, pipe->pipe_0x6400, 0x6400); - PIPE_SAVE(priv, pipe->pipe_0x6800, 0x6800); - PIPE_SAVE(priv, pipe->pipe_0x6c00, 0x6c00); - PIPE_SAVE(priv, pipe->pipe_0x7000, 0x7000); - PIPE_SAVE(priv, pipe->pipe_0x7400, 0x7400); - PIPE_SAVE(priv, pipe->pipe_0x7800, 0x7800); - PIPE_SAVE(priv, pipe->pipe_0x0040, 0x0040); - PIPE_SAVE(priv, pipe->pipe_0x0000, 0x0000); + struct nvkm_device *device = gr->base.engine.subdev.device; + + PIPE_SAVE(gr, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(gr, pipe->pipe_0x0200, 0x0200); + PIPE_SAVE(gr, pipe->pipe_0x6400, 0x6400); + PIPE_SAVE(gr, pipe->pipe_0x6800, 0x6800); + PIPE_SAVE(gr, pipe->pipe_0x6c00, 0x6c00); + PIPE_SAVE(gr, pipe->pipe_0x7000, 0x7000); + PIPE_SAVE(gr, pipe->pipe_0x7400, 0x7400); + PIPE_SAVE(gr, pipe->pipe_0x7800, 0x7800); + PIPE_SAVE(gr, pipe->pipe_0x0040, 0x0040); + PIPE_SAVE(gr, pipe->pipe_0x0000, 0x0000); } static void nv10_gr_load_pipe(struct nv10_gr_chan *chan) { - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nv10_gr *gr = chan->gr; struct pipe_state *pipe = &chan->pipe_state; + struct nvkm_device *device = gr->base.engine.subdev.device; u32 xfmode0, xfmode1; int i; - nv04_gr_idle(priv); + nv04_gr_idle(&gr->base); /* XXX check haiku comments */ - xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0); - xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1); - nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000); - nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + xfmode0 = nvkm_rd32(device, NV10_PGRAPH_XFMODE0); + xfmode1 = nvkm_rd32(device, NV10_PGRAPH_XFMODE1); + nvkm_wr32(device, NV10_PGRAPH_XFMODE0, 0x10000000); + nvkm_wr32(device, NV10_PGRAPH_XFMODE1, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); for (i = 0; i < 4; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); for (i = 0; i < 4; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); for (i = 0; i < 3; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); for (i = 0; i < 3; i++) - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); - nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008); + nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000008); - PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200); - nv04_gr_idle(priv); + PIPE_RESTORE(gr, pipe->pipe_0x0200, 0x0200); + nv04_gr_idle(&gr->base); /* restore XFMODE */ - nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0); - nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1); - PIPE_RESTORE(priv, pipe->pipe_0x6400, 0x6400); - PIPE_RESTORE(priv, pipe->pipe_0x6800, 0x6800); - PIPE_RESTORE(priv, pipe->pipe_0x6c00, 0x6c00); - PIPE_RESTORE(priv, pipe->pipe_0x7000, 0x7000); - PIPE_RESTORE(priv, pipe->pipe_0x7400, 0x7400); - PIPE_RESTORE(priv, pipe->pipe_0x7800, 0x7800); - PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400); - PIPE_RESTORE(priv, pipe->pipe_0x0000, 0x0000); - PIPE_RESTORE(priv, pipe->pipe_0x0040, 0x0040); - nv04_gr_idle(priv); + nvkm_wr32(device, NV10_PGRAPH_XFMODE0, xfmode0); + nvkm_wr32(device, NV10_PGRAPH_XFMODE1, xfmode1); + PIPE_RESTORE(gr, pipe->pipe_0x6400, 0x6400); + PIPE_RESTORE(gr, pipe->pipe_0x6800, 0x6800); + PIPE_RESTORE(gr, pipe->pipe_0x6c00, 0x6c00); + PIPE_RESTORE(gr, pipe->pipe_0x7000, 0x7000); + PIPE_RESTORE(gr, pipe->pipe_0x7400, 0x7400); + PIPE_RESTORE(gr, pipe->pipe_0x7800, 0x7800); + PIPE_RESTORE(gr, pipe->pipe_0x4400, 0x4400); + PIPE_RESTORE(gr, pipe->pipe_0x0000, 0x0000); + PIPE_RESTORE(gr, pipe->pipe_0x0040, 0x0040); + nv04_gr_idle(&gr->base); } static void nv10_gr_create_pipe(struct nv10_gr_chan *chan) { - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nv10_gr *gr = chan->gr; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct pipe_state *pipe_state = &chan->pipe_state; u32 *pipe_state_addr; int i; @@ -698,7 +643,7 @@ nv10_gr_create_pipe(struct nv10_gr_chan *chan) u32 *__end_addr = pipe_state->pipe_##addr + \ ARRAY_SIZE(pipe_state->pipe_##addr); \ if (pipe_state_addr != __end_addr) \ - nv_error(priv, "incomplete pipe init for 0x%x : %p/%p\n", \ + nvkm_error(subdev, "incomplete pipe init for 0x%x : %p/%p\n", \ addr, pipe_state_addr, __end_addr); \ } while (0) #define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value @@ -838,33 +783,36 @@ nv10_gr_create_pipe(struct nv10_gr_chan *chan) } static int -nv10_gr_ctx_regs_find_offset(struct nv10_gr_priv *priv, int reg) +nv10_gr_ctx_regs_find_offset(struct nv10_gr *gr, int reg) { + struct nvkm_subdev *subdev = &gr->base.engine.subdev; int i; for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) { if (nv10_gr_ctx_regs[i] == reg) return i; } - nv_error(priv, "unknow offset nv10_ctx_regs %d\n", reg); + nvkm_error(subdev, "unknown offset nv10_ctx_regs %d\n", reg); return -1; } static int -nv17_gr_ctx_regs_find_offset(struct nv10_gr_priv *priv, int reg) +nv17_gr_ctx_regs_find_offset(struct nv10_gr *gr, int reg) { + struct nvkm_subdev *subdev = &gr->base.engine.subdev; int i; for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) { if (nv17_gr_ctx_regs[i] == reg) return i; } - nv_error(priv, "unknow offset nv17_ctx_regs %d\n", reg); + nvkm_error(subdev, "unknown offset nv17_ctx_regs %d\n", reg); return -1; } static void nv10_gr_load_dma_vtxbuf(struct nv10_gr_chan *chan, int chid, u32 inst) { - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nv10_gr *gr = chan->gr; + struct nvkm_device *device = gr->base.engine.subdev.device; u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; u32 ctx_user, ctx_switch[5]; int i, subchan = -1; @@ -876,7 +824,7 @@ nv10_gr_load_dma_vtxbuf(struct nv10_gr_chan *chan, int chid, u32 inst) /* Look for a celsius object */ for (i = 0; i < 8; i++) { - int class = nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; + int class = nvkm_rd32(device, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; if (class == 0x56 || class == 0x96 || class == 0x99) { subchan = i; @@ -888,159 +836,183 @@ nv10_gr_load_dma_vtxbuf(struct nv10_gr_chan *chan, int chid, u32 inst) return; /* Save the current ctx object */ - ctx_user = nv_rd32(priv, NV10_PGRAPH_CTX_USER); + ctx_user = nvkm_rd32(device, NV10_PGRAPH_CTX_USER); for (i = 0; i < 5; i++) - ctx_switch[i] = nv_rd32(priv, NV10_PGRAPH_CTX_SWITCH(i)); + ctx_switch[i] = nvkm_rd32(device, NV10_PGRAPH_CTX_SWITCH(i)); /* Save the FIFO state */ - st2 = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2); - st2_dl = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DL); - st2_dh = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DH); - fifo_ptr = nv_rd32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR); + st2 = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2); + st2_dl = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2_DL); + st2_dh = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2_DH); + fifo_ptr = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR); for (i = 0; i < ARRAY_SIZE(fifo); i++) - fifo[i] = nv_rd32(priv, 0x4007a0 + 4 * i); + fifo[i] = nvkm_rd32(device, 0x4007a0 + 4 * i); /* Switch to the celsius subchannel */ for (i = 0; i < 5; i++) - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), - nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(subchan, i))); - nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(i), + nvkm_rd32(device, NV10_PGRAPH_CTX_CACHE(subchan, i))); + nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); /* Inject NV10TCL_DMA_VTXBUF */ - nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, 0x2c000000 | chid << 20 | subchan << 16 | 0x18c); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, inst); - nv_mask(priv, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); - nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DL, inst); + nvkm_mask(device, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); + nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); /* Restore the FIFO state */ for (i = 0; i < ARRAY_SIZE(fifo); i++) - nv_wr32(priv, 0x4007a0 + 4 * i, fifo[i]); + nvkm_wr32(device, 0x4007a0 + 4 * i, fifo[i]); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, st2); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, st2); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); /* Restore the current ctx object */ for (i = 0; i < 5; i++) - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); - nv_wr32(priv, NV10_PGRAPH_CTX_USER, ctx_user); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); + nvkm_wr32(device, NV10_PGRAPH_CTX_USER, ctx_user); } static int nv10_gr_load_context(struct nv10_gr_chan *chan, int chid) { - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nv10_gr *gr = chan->gr; + struct nvkm_device *device = gr->base.engine.subdev.device; u32 inst; int i; for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) - nv_wr32(priv, nv10_gr_ctx_regs[i], chan->nv10[i]); + nvkm_wr32(device, nv10_gr_ctx_regs[i], chan->nv10[i]); - if (nv_device(priv)->card_type >= NV_11 && - nv_device(priv)->chipset >= 0x17) { + if (device->card_type >= NV_11 && device->chipset >= 0x17) { for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) - nv_wr32(priv, nv17_gr_ctx_regs[i], chan->nv17[i]); + nvkm_wr32(device, nv17_gr_ctx_regs[i], chan->nv17[i]); } nv10_gr_load_pipe(chan); - inst = nv_rd32(priv, NV10_PGRAPH_GLOBALSTATE1) & 0xffff; + inst = nvkm_rd32(device, NV10_PGRAPH_GLOBALSTATE1) & 0xffff; nv10_gr_load_dma_vtxbuf(chan, chid, inst); - nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100); - nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24); - nv_mask(priv, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24); + nvkm_mask(device, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000); return 0; } static int nv10_gr_unload_context(struct nv10_gr_chan *chan) { - struct nv10_gr_priv *priv = nv10_gr_priv(chan); + struct nv10_gr *gr = chan->gr; + struct nvkm_device *device = gr->base.engine.subdev.device; int i; for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) - chan->nv10[i] = nv_rd32(priv, nv10_gr_ctx_regs[i]); + chan->nv10[i] = nvkm_rd32(device, nv10_gr_ctx_regs[i]); - if (nv_device(priv)->card_type >= NV_11 && - nv_device(priv)->chipset >= 0x17) { + if (device->card_type >= NV_11 && device->chipset >= 0x17) { for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) - chan->nv17[i] = nv_rd32(priv, nv17_gr_ctx_regs[i]); + chan->nv17[i] = nvkm_rd32(device, nv17_gr_ctx_regs[i]); } nv10_gr_save_pipe(chan); - nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000000); - nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000000); + nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); return 0; } static void -nv10_gr_context_switch(struct nv10_gr_priv *priv) +nv10_gr_context_switch(struct nv10_gr *gr) { + struct nvkm_device *device = gr->base.engine.subdev.device; struct nv10_gr_chan *prev = NULL; struct nv10_gr_chan *next = NULL; - unsigned long flags; int chid; - spin_lock_irqsave(&priv->lock, flags); - nv04_gr_idle(priv); + nv04_gr_idle(&gr->base); /* If previous context is valid, we need to save it */ - prev = nv10_gr_channel(priv); + prev = nv10_gr_channel(gr); if (prev) nv10_gr_unload_context(prev); /* load context for next channel */ - chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; - next = priv->chan[chid]; + chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; + next = gr->chan[chid]; if (next) nv10_gr_load_context(next, chid); +} + +static int +nv10_gr_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nv10_gr_chan *chan = nv10_gr_chan(object); + struct nv10_gr *gr = chan->gr; + struct nvkm_device *device = gr->base.engine.subdev.device; + unsigned long flags; - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&gr->lock, flags); + nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + if (nv10_gr_channel(gr) == chan) + nv10_gr_unload_context(chan); + nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&gr->lock, flags); + return 0; +} + +static void * +nv10_gr_chan_dtor(struct nvkm_object *object) +{ + struct nv10_gr_chan *chan = nv10_gr_chan(object); + struct nv10_gr *gr = chan->gr; + unsigned long flags; + + spin_lock_irqsave(&gr->lock, flags); + gr->chan[chan->chid] = NULL; + spin_unlock_irqrestore(&gr->lock, flags); + return chan; } +static const struct nvkm_object_func +nv10_gr_chan = { + .dtor = nv10_gr_chan_dtor, + .fini = nv10_gr_chan_fini, +}; + #define NV_WRITE_CTX(reg, val) do { \ - int offset = nv10_gr_ctx_regs_find_offset(priv, reg); \ + int offset = nv10_gr_ctx_regs_find_offset(gr, reg); \ if (offset > 0) \ chan->nv10[offset] = val; \ } while (0) #define NV17_WRITE_CTX(reg, val) do { \ - int offset = nv17_gr_ctx_regs_find_offset(priv, reg); \ + int offset = nv17_gr_ctx_regs_find_offset(gr, reg); \ if (offset > 0) \ chan->nv17[offset] = val; \ } while (0) -static int -nv10_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv10_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nvkm_fifo_chan *fifo = (void *)parent; - struct nv10_gr_priv *priv = (void *)engine; + struct nv10_gr *gr = nv10_gr(base); struct nv10_gr_chan *chan; + struct nvkm_device *device = gr->base.engine.subdev.device; unsigned long flags; - int ret; - - ret = nvkm_object_create(parent, engine, oclass, 0, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - spin_lock_irqsave(&priv->lock, flags); - if (priv->chan[fifo->chid]) { - *pobject = nv_object(priv->chan[fifo->chid]); - atomic_inc(&(*pobject)->refcount); - spin_unlock_irqrestore(&priv->lock, flags); - nvkm_object_destroy(&chan->base); - return 1; - } + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv10_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; NV_WRITE_CTX(0x00400e88, 0x08000000); NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); @@ -1049,12 +1021,11 @@ nv10_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, NV_WRITE_CTX(0x00400e14, 0x00001000); NV_WRITE_CTX(0x00400e30, 0x00080008); NV_WRITE_CTX(0x00400e34, 0x00080008); - if (nv_device(priv)->card_type >= NV_11 && - nv_device(priv)->chipset >= 0x17) { + if (device->card_type >= NV_11 && device->chipset >= 0x17) { /* is it really needed ??? */ NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, - nv_rd32(priv, NV10_PGRAPH_DEBUG_4)); - NV17_WRITE_CTX(0x004006b0, nv_rd32(priv, 0x004006b0)); + nvkm_rd32(device, NV10_PGRAPH_DEBUG_4)); + NV17_WRITE_CTX(0x004006b0, nvkm_rd32(device, 0x004006b0)); NV17_WRITE_CTX(0x00400eac, 0x0fff0000); NV17_WRITE_CTX(0x00400eb0, 0x0fff0000); NV17_WRITE_CTX(0x00400ec0, 0x00000080); @@ -1064,74 +1035,32 @@ nv10_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, nv10_gr_create_pipe(chan); - priv->chan[fifo->chid] = chan; - chan->chid = fifo->chid; - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&gr->lock, flags); + gr->chan[chan->chid] = chan; + spin_unlock_irqrestore(&gr->lock, flags); return 0; } -static void -nv10_gr_context_dtor(struct nvkm_object *object) -{ - struct nv10_gr_priv *priv = (void *)object->engine; - struct nv10_gr_chan *chan = (void *)object; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - priv->chan[chan->chid] = NULL; - spin_unlock_irqrestore(&priv->lock, flags); - - nvkm_object_destroy(&chan->base); -} - -static int -nv10_gr_context_fini(struct nvkm_object *object, bool suspend) -{ - struct nv10_gr_priv *priv = (void *)object->engine; - struct nv10_gr_chan *chan = (void *)object; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (nv10_gr_channel(priv) == chan) - nv10_gr_unload_context(chan); - nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&priv->lock, flags); - - return nvkm_object_fini(&chan->base, suspend); -} - -static struct nvkm_oclass -nv10_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x10), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_gr_context_ctor, - .dtor = nv10_gr_context_dtor, - .init = nvkm_object_init, - .fini = nv10_gr_context_fini, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ -static void -nv10_gr_tile_prog(struct nvkm_engine *engine, int i) +void +nv10_gr_tile(struct nvkm_gr *base, int i, struct nvkm_fb_tile *tile) { - struct nvkm_fb_tile *tile = &nvkm_fb(engine)->tile.region[i]; - struct nvkm_fifo *pfifo = nvkm_fifo(engine); - struct nv10_gr_priv *priv = (void *)engine; + struct nv10_gr *gr = nv10_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + struct nvkm_fifo *fifo = device->fifo; unsigned long flags; - pfifo->pause(pfifo, &flags); - nv04_gr_idle(priv); + nvkm_fifo_pause(fifo, &flags); + nv04_gr_idle(&gr->base); - nv_wr32(priv, NV10_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(priv, NV10_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(priv, NV10_PGRAPH_TILE(i), tile->addr); + nvkm_wr32(device, NV10_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV10_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV10_PGRAPH_TILE(i), tile->addr); - pfifo->start(pfifo, &flags); + nvkm_fifo_start(fifo, &flags); } const struct nvkm_bitfield nv10_gr_intr_name[] = { @@ -1148,168 +1077,145 @@ const struct nvkm_bitfield nv10_gr_nstatus[] = { {} }; -static void -nv10_gr_intr(struct nvkm_subdev *subdev) +void +nv10_gr_intr(struct nvkm_gr *base) { - struct nv10_gr_priv *priv = (void *)subdev; - struct nv10_gr_chan *chan = NULL; - struct nvkm_namedb *namedb = NULL; - struct nvkm_handle *handle = NULL; - u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); - u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + struct nv10_gr *gr = nv10_gr(base); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); + u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); + u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); + u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); u32 chid = (addr & 0x01f00000) >> 20; u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff; + u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nvkm_rd32(device, 0x400160 + subc * 4) & 0xfff; u32 show = stat; + char msg[128], src[128], sta[128]; + struct nv10_gr_chan *chan; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - chan = priv->chan[chid]; - if (chan) - namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&gr->lock, flags); + chan = gr->chan[chid]; if (stat & NV_PGRAPH_INTR_ERROR) { if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { - handle = nvkm_namedb_get_class(namedb, class); - if (handle && !nv_call(handle->object, mthd, data)) + if (!nv10_gr_mthd(chan, class, mthd, data)) show &= ~NV_PGRAPH_INTR_ERROR; } } if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv10_gr_context_switch(priv); + nv10_gr_context_switch(gr); } - nv_wr32(priv, NV03_PGRAPH_INTR, stat); - nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + nvkm_wr32(device, NV03_PGRAPH_INTR, stat); + nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); - nvkm_bitfield_print(nv10_gr_intr_name, show); - pr_cont(" nsource:"); - nvkm_bitfield_print(nv04_gr_nsource, nsource); - pr_cont(" nstatus:"); - nvkm_bitfield_print(nv10_gr_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, nvkm_client_name(chan), subc, class, mthd, - data); + nvkm_snprintbf(msg, sizeof(msg), nv10_gr_intr_name, show); + nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); + nvkm_snprintbf(sta, sizeof(sta), nv10_gr_nstatus, nstatus); + nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " + "nstatus %08x [%s] ch %d [%s] subc %d " + "class %04x mthd %04x data %08x\n", + show, msg, nsource, src, nstatus, sta, chid, + chan ? chan->object.client->name : "unknown", + subc, class, mthd, data); } - nvkm_namedb_put(handle); + spin_unlock_irqrestore(&gr->lock, flags); } -static int -nv10_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv10_gr_init(struct nvkm_gr *base) { - struct nv10_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv10_gr_intr; - nv_engine(priv)->cclass = &nv10_gr_cclass; - - if (nv_device(priv)->chipset <= 0x10) - nv_engine(priv)->sclass = nv10_gr_sclass; - else - if (nv_device(priv)->chipset < 0x17 || - nv_device(priv)->card_type < NV_11) - nv_engine(priv)->sclass = nv15_gr_sclass; - else - nv_engine(priv)->sclass = nv17_gr_sclass; - - nv_engine(priv)->tile_prog = nv10_gr_tile_prog; - spin_lock_init(&priv->lock); - return 0; -} - -static void -nv10_gr_dtor(struct nvkm_object *object) -{ - struct nv10_gr_priv *priv = (void *)object; - nvkm_gr_destroy(&priv->base); -} - -static int -nv10_gr_init(struct nvkm_object *object) -{ - struct nvkm_engine *engine = nv_engine(object); - struct nvkm_fb *pfb = nvkm_fb(object); - struct nv10_gr_priv *priv = (void *)engine; - int ret, i; - - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700); - /* nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ - nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); - nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31)); - - if (nv_device(priv)->card_type >= NV_11 && - nv_device(priv)->chipset >= 0x17) { - nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000); - nv_wr32(priv, 0x400a10, 0x03ff3fb6); - nv_wr32(priv, 0x400838, 0x002f8684); - nv_wr32(priv, 0x40083c, 0x00115f3f); - nv_wr32(priv, 0x4006b0, 0x40000020); + struct nv10_gr *gr = nv10_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x00118700); + /* nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ + nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31)); + + if (device->card_type >= NV_11 && device->chipset >= 0x17) { + nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x1f000000); + nvkm_wr32(device, 0x400a10, 0x03ff3fb6); + nvkm_wr32(device, 0x400838, 0x002f8684); + nvkm_wr32(device, 0x40083c, 0x00115f3f); + nvkm_wr32(device, 0x4006b0, 0x40000020); } else { - nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00000000); } - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->tile.regions; i++) - engine->tile_prog(engine, i); - - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); - nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); - nv_wr32(priv, NV10_PGRAPH_STATE, 0xFFFFFFFF); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_STATE, 0xFFFFFFFF); - nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); - nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); + nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); + nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); return 0; } -static int -nv10_gr_fini(struct nvkm_object *object, bool suspend) +int +nv10_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device, + int index, struct nvkm_gr **pgr) { - struct nv10_gr_priv *priv = (void *)object; - return nvkm_gr_fini(&priv->base, suspend); + struct nv10_gr *gr; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + spin_lock_init(&gr->lock); + *pgr = &gr->base; + + return nvkm_gr_ctor(func, device, index, 0x00001000, true, &gr->base); } -struct nvkm_oclass -nv10_gr_oclass = { - .handle = NV_ENGINE(GR, 0x10), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_gr_ctor, - .dtor = nv10_gr_dtor, - .init = nv10_gr_init, - .fini = nv10_gr_fini, - }, +static const struct nvkm_gr_func +nv10_gr = { + .init = nv10_gr_init, + .intr = nv10_gr_intr, + .tile = nv10_gr_tile, + .chan_new = nv10_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* pattern */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x005f, &nv04_gr_object }, /* blit */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv04_gr_object }, /* blit */ + { -1, -1, 0x0093, &nv04_gr_object }, /* surf3d */ + { -1, -1, 0x0094, &nv04_gr_object }, /* ttri */ + { -1, -1, 0x0095, &nv04_gr_object }, /* mtri */ + { -1, -1, 0x0056, &nv04_gr_object }, /* celcius */ + {} + } }; + +int +nv10_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv10_gr_new_(&nv10_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h new file mode 100644 index 000000000..d7c3d86cc --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h @@ -0,0 +1,13 @@ +#ifndef __NV10_GR_H__ +#define __NV10_GR_H__ +#include "priv.h" + +int nv10_gr_new_(const struct nvkm_gr_func *, struct nvkm_device *, int index, + struct nvkm_gr **); +int nv10_gr_init(struct nvkm_gr *); +void nv10_gr_intr(struct nvkm_gr *); +void nv10_gr_tile(struct nvkm_gr *, int, struct nvkm_fb_tile *); + +int nv10_gr_chan_new(struct nvkm_gr *, struct nvkm_fifo_chan *, + const struct nvkm_oclass *, struct nvkm_object **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv15.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv15.c new file mode 100644 index 000000000..3e2c6856b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv15.c @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Matthieu CASTET + * All Rights Reserved. + * + * 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 (including the next + * paragr) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "nv10.h" + +static const struct nvkm_gr_func +nv15_gr = { + .init = nv10_gr_init, + .intr = nv10_gr_intr, + .tile = nv10_gr_tile, + .chan_new = nv10_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* pattern */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x005f, &nv04_gr_object }, /* blit */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv04_gr_object }, /* blit */ + { -1, -1, 0x0093, &nv04_gr_object }, /* surf3d */ + { -1, -1, 0x0094, &nv04_gr_object }, /* ttri */ + { -1, -1, 0x0095, &nv04_gr_object }, /* mtri */ + { -1, -1, 0x0096, &nv04_gr_object }, /* celcius */ + {} + } +}; + +int +nv15_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv10_gr_new_(&nv15_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv17.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv17.c new file mode 100644 index 000000000..12437d085 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv17.c @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Matthieu CASTET + * All Rights Reserved. + * + * 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 (including the next + * paragr) 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "nv10.h" + +static const struct nvkm_gr_func +nv17_gr = { + .init = nv10_gr_init, + .intr = nv10_gr_intr, + .tile = nv10_gr_tile, + .chan_new = nv10_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* pattern */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x005f, &nv04_gr_object }, /* blit */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv04_gr_object }, /* blit */ + { -1, -1, 0x0093, &nv04_gr_object }, /* surf3d */ + { -1, -1, 0x0094, &nv04_gr_object }, /* ttri */ + { -1, -1, 0x0095, &nv04_gr_object }, /* mtri */ + { -1, -1, 0x0099, &nv04_gr_object }, + {} + } +}; + +int +nv17_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv10_gr_new_(&nv17_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c index 1713ffb66..5caef65d3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c @@ -2,375 +2,374 @@ #include "regs.h" #include -#include -#include +#include #include +#include #include #include /******************************************************************************* - * Graphics object classes + * PGRAPH context ******************************************************************************/ -static struct nvkm_oclass -nv20_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv04_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv04_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv04_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv04_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv04_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs, NULL }, /* ifc */ - { 0x0096, &nv04_gr_ofuncs, NULL }, /* celcius */ - { 0x0097, &nv04_gr_ofuncs, NULL }, /* kelvin */ - { 0x009e, &nv04_gr_ofuncs, NULL }, /* swzsurf */ - { 0x009f, &nv04_gr_ofuncs, NULL }, /* imageblit */ - {}, -}; +int +nv20_gr_chan_init(struct nvkm_object *object) +{ + struct nv20_gr_chan *chan = nv20_gr_chan(object); + struct nv20_gr *gr = chan->gr; + u32 inst = nvkm_memory_addr(chan->inst); -/******************************************************************************* - * PGRAPH context - ******************************************************************************/ + nvkm_kmap(gr->ctxtab); + nvkm_wo32(gr->ctxtab, chan->chid * 4, inst >> 4); + nvkm_done(gr->ctxtab); + return 0; +} + +int +nv20_gr_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nv20_gr_chan *chan = nv20_gr_chan(object); + struct nv20_gr *gr = chan->gr; + struct nvkm_device *device = gr->base.engine.subdev.device; + u32 inst = nvkm_memory_addr(chan->inst); + int chid = -1; + + nvkm_mask(device, 0x400720, 0x00000001, 0x00000000); + if (nvkm_rd32(device, 0x400144) & 0x00010000) + chid = (nvkm_rd32(device, 0x400148) & 0x1f000000) >> 24; + if (chan->chid == chid) { + nvkm_wr32(device, 0x400784, inst >> 4); + nvkm_wr32(device, 0x400788, 0x00000002); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x400700)) + break; + ); + nvkm_wr32(device, 0x400144, 0x10000000); + nvkm_mask(device, 0x400148, 0xff000000, 0x1f000000); + } + nvkm_mask(device, 0x400720, 0x00000001, 0x00000001); + + nvkm_kmap(gr->ctxtab); + nvkm_wo32(gr->ctxtab, chan->chid * 4, 0x00000000); + nvkm_done(gr->ctxtab); + return 0; +} + +void * +nv20_gr_chan_dtor(struct nvkm_object *object) +{ + struct nv20_gr_chan *chan = nv20_gr_chan(object); + nvkm_memory_del(&chan->inst); + return chan; +} + +static const struct nvkm_object_func +nv20_gr_chan = { + .dtor = nv20_gr_chan_dtor, + .init = nv20_gr_chan_init, + .fini = nv20_gr_chan_fini, +}; static int -nv20_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv20_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { + struct nv20_gr *gr = nv20_gr(base); struct nv20_gr_chan *chan; int ret, i; - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, 0x37f0, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv20_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; + + ret = nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 0x37f0, 16, true, + &chan->inst); if (ret) return ret; - chan->chid = nvkm_fifo_chan(parent)->chid; - - nv_wo32(chan, 0x0000, 0x00000001 | (chan->chid << 24)); - nv_wo32(chan, 0x033c, 0xffff0000); - nv_wo32(chan, 0x03a0, 0x0fff0000); - nv_wo32(chan, 0x03a4, 0x0fff0000); - nv_wo32(chan, 0x047c, 0x00000101); - nv_wo32(chan, 0x0490, 0x00000111); - nv_wo32(chan, 0x04a8, 0x44400000); + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x0000, 0x00000001 | (chan->chid << 24)); + nvkm_wo32(chan->inst, 0x033c, 0xffff0000); + nvkm_wo32(chan->inst, 0x03a0, 0x0fff0000); + nvkm_wo32(chan->inst, 0x03a4, 0x0fff0000); + nvkm_wo32(chan->inst, 0x047c, 0x00000101); + nvkm_wo32(chan->inst, 0x0490, 0x00000111); + nvkm_wo32(chan->inst, 0x04a8, 0x44400000); for (i = 0x04d4; i <= 0x04e0; i += 4) - nv_wo32(chan, i, 0x00030303); + nvkm_wo32(chan->inst, i, 0x00030303); for (i = 0x04f4; i <= 0x0500; i += 4) - nv_wo32(chan, i, 0x00080000); + nvkm_wo32(chan->inst, i, 0x00080000); for (i = 0x050c; i <= 0x0518; i += 4) - nv_wo32(chan, i, 0x01012000); + nvkm_wo32(chan->inst, i, 0x01012000); for (i = 0x051c; i <= 0x0528; i += 4) - nv_wo32(chan, i, 0x000105b8); + nvkm_wo32(chan->inst, i, 0x000105b8); for (i = 0x052c; i <= 0x0538; i += 4) - nv_wo32(chan, i, 0x00080008); + nvkm_wo32(chan->inst, i, 0x00080008); for (i = 0x055c; i <= 0x0598; i += 4) - nv_wo32(chan, i, 0x07ff0000); - nv_wo32(chan, 0x05a4, 0x4b7fffff); - nv_wo32(chan, 0x05fc, 0x00000001); - nv_wo32(chan, 0x0604, 0x00004000); - nv_wo32(chan, 0x0610, 0x00000001); - nv_wo32(chan, 0x0618, 0x00040000); - nv_wo32(chan, 0x061c, 0x00010000); + nvkm_wo32(chan->inst, i, 0x07ff0000); + nvkm_wo32(chan->inst, 0x05a4, 0x4b7fffff); + nvkm_wo32(chan->inst, 0x05fc, 0x00000001); + nvkm_wo32(chan->inst, 0x0604, 0x00004000); + nvkm_wo32(chan->inst, 0x0610, 0x00000001); + nvkm_wo32(chan->inst, 0x0618, 0x00040000); + nvkm_wo32(chan->inst, 0x061c, 0x00010000); for (i = 0x1c1c; i <= 0x248c; i += 16) { - nv_wo32(chan, (i + 0), 0x10700ff9); - nv_wo32(chan, (i + 4), 0x0436086c); - nv_wo32(chan, (i + 8), 0x000c001b); + nvkm_wo32(chan->inst, (i + 0), 0x10700ff9); + nvkm_wo32(chan->inst, (i + 4), 0x0436086c); + nvkm_wo32(chan->inst, (i + 8), 0x000c001b); } - nv_wo32(chan, 0x281c, 0x3f800000); - nv_wo32(chan, 0x2830, 0x3f800000); - nv_wo32(chan, 0x285c, 0x40000000); - nv_wo32(chan, 0x2860, 0x3f800000); - nv_wo32(chan, 0x2864, 0x3f000000); - nv_wo32(chan, 0x286c, 0x40000000); - nv_wo32(chan, 0x2870, 0x3f800000); - nv_wo32(chan, 0x2878, 0xbf800000); - nv_wo32(chan, 0x2880, 0xbf800000); - nv_wo32(chan, 0x34a4, 0x000fe000); - nv_wo32(chan, 0x3530, 0x000003f8); - nv_wo32(chan, 0x3540, 0x002fe000); + nvkm_wo32(chan->inst, 0x281c, 0x3f800000); + nvkm_wo32(chan->inst, 0x2830, 0x3f800000); + nvkm_wo32(chan->inst, 0x285c, 0x40000000); + nvkm_wo32(chan->inst, 0x2860, 0x3f800000); + nvkm_wo32(chan->inst, 0x2864, 0x3f000000); + nvkm_wo32(chan->inst, 0x286c, 0x40000000); + nvkm_wo32(chan->inst, 0x2870, 0x3f800000); + nvkm_wo32(chan->inst, 0x2878, 0xbf800000); + nvkm_wo32(chan->inst, 0x2880, 0xbf800000); + nvkm_wo32(chan->inst, 0x34a4, 0x000fe000); + nvkm_wo32(chan->inst, 0x3530, 0x000003f8); + nvkm_wo32(chan->inst, 0x3540, 0x002fe000); for (i = 0x355c; i <= 0x3578; i += 4) - nv_wo32(chan, i, 0x001c527c); - return 0; -} - -int -nv20_gr_context_init(struct nvkm_object *object) -{ - struct nv20_gr_priv *priv = (void *)object->engine; - struct nv20_gr_chan *chan = (void *)object; - int ret; - - ret = nvkm_gr_context_init(&chan->base); - if (ret) - return ret; - - nv_wo32(priv->ctxtab, chan->chid * 4, nv_gpuobj(chan)->addr >> 4); + nvkm_wo32(chan->inst, i, 0x001c527c); + nvkm_done(chan->inst); return 0; } -int -nv20_gr_context_fini(struct nvkm_object *object, bool suspend) -{ - struct nv20_gr_priv *priv = (void *)object->engine; - struct nv20_gr_chan *chan = (void *)object; - int chid = -1; - - nv_mask(priv, 0x400720, 0x00000001, 0x00000000); - if (nv_rd32(priv, 0x400144) & 0x00010000) - chid = (nv_rd32(priv, 0x400148) & 0x1f000000) >> 24; - if (chan->chid == chid) { - nv_wr32(priv, 0x400784, nv_gpuobj(chan)->addr >> 4); - nv_wr32(priv, 0x400788, 0x00000002); - nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); - nv_wr32(priv, 0x400144, 0x10000000); - nv_mask(priv, 0x400148, 0xff000000, 0x1f000000); - } - nv_mask(priv, 0x400720, 0x00000001, 0x00000001); - - nv_wo32(priv->ctxtab, chan->chid * 4, 0x00000000); - return nvkm_gr_context_fini(&chan->base, suspend); -} - -static struct nvkm_oclass -nv20_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x20), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv20_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = nv20_gr_context_init, - .fini = nv20_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ void -nv20_gr_tile_prog(struct nvkm_engine *engine, int i) +nv20_gr_tile(struct nvkm_gr *base, int i, struct nvkm_fb_tile *tile) { - struct nvkm_fb_tile *tile = &nvkm_fb(engine)->tile.region[i]; - struct nvkm_fifo *pfifo = nvkm_fifo(engine); - struct nv20_gr_priv *priv = (void *)engine; + struct nv20_gr *gr = nv20_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + struct nvkm_fifo *fifo = device->fifo; unsigned long flags; - pfifo->pause(pfifo, &flags); - nv04_gr_idle(priv); + nvkm_fifo_pause(fifo, &flags); + nv04_gr_idle(&gr->base); - nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); + nvkm_wr32(device, NV20_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV20_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV20_PGRAPH_TILE(i), tile->addr); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->limit); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->pitch); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->addr); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->limit); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->pitch); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->addr); - if (nv_device(engine)->chipset != 0x34) { - nv_wr32(priv, NV20_PGRAPH_ZCOMP(i), tile->zcomp); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->zcomp); + if (device->chipset != 0x34) { + nvkm_wr32(device, NV20_PGRAPH_ZCOMP(i), tile->zcomp); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->zcomp); } - pfifo->start(pfifo, &flags); + nvkm_fifo_start(fifo, &flags); } void -nv20_gr_intr(struct nvkm_subdev *subdev) +nv20_gr_intr(struct nvkm_gr *base) { - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct nvkm_handle *handle; - struct nv20_gr_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); - u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + struct nv20_gr *gr = nv20_gr(base); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_fifo_chan *chan; + u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); + u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); + u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); + u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); u32 chid = (addr & 0x01f00000) >> 20; u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff; + u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nvkm_rd32(device, 0x400160 + subc * 4) & 0xfff; u32 show = stat; + char msg[128], src[128], sta[128]; + unsigned long flags; - engctx = nvkm_engctx_get(engine, chid); - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - handle = nvkm_handle_get_class(engctx, class); - if (handle && !nv_call(handle->object, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - nvkm_handle_put(handle); - } - } + chan = nvkm_fifo_chan_chid(device->fifo, chid, &flags); - nv_wr32(priv, NV03_PGRAPH_INTR, stat); - nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + nvkm_wr32(device, NV03_PGRAPH_INTR, stat); + nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); - nvkm_bitfield_print(nv10_gr_intr_name, show); - pr_cont(" nsource:"); - nvkm_bitfield_print(nv04_gr_nsource, nsource); - pr_cont(" nstatus:"); - nvkm_bitfield_print(nv10_gr_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, nvkm_client_name(engctx), subc, class, mthd, - data); + nvkm_snprintbf(msg, sizeof(msg), nv10_gr_intr_name, show); + nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); + nvkm_snprintbf(sta, sizeof(sta), nv10_gr_nstatus, nstatus); + nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " + "nstatus %08x [%s] ch %d [%s] subc %d " + "class %04x mthd %04x data %08x\n", + show, msg, nsource, src, nstatus, sta, chid, + chan ? chan->object.client->name : "unknown", + subc, class, mthd, data); } - nvkm_engctx_put(engctx); -} - -static int -nv20_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv20_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv20_gr_intr; - nv_engine(priv)->cclass = &nv20_gr_cclass; - nv_engine(priv)->sclass = nv20_gr_sclass; - nv_engine(priv)->tile_prog = nv20_gr_tile_prog; - return 0; + nvkm_fifo_chan_put(device->fifo, flags, &chan); } -void -nv20_gr_dtor(struct nvkm_object *object) +int +nv20_gr_oneinit(struct nvkm_gr *base) { - struct nv20_gr_priv *priv = (void *)object; - nvkm_gpuobj_ref(NULL, &priv->ctxtab); - nvkm_gr_destroy(&priv->base); + struct nv20_gr *gr = nv20_gr(base); + return nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 32 * 4, 16, + true, &gr->ctxtab); } int -nv20_gr_init(struct nvkm_object *object) +nv20_gr_init(struct nvkm_gr *base) { - struct nvkm_engine *engine = nv_engine(object); - struct nv20_gr_priv *priv = (void *)engine; - struct nvkm_fb *pfb = nvkm_fb(object); + struct nv20_gr *gr = nv20_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; u32 tmp, vramsz; - int ret, i; - - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; + int i; - nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); + nvkm_wr32(device, NV20_PGRAPH_CHANNEL_CTX_TABLE, + nvkm_memory_addr(gr->ctxtab) >> 4); - if (nv_device(priv)->chipset == 0x20) { - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x003d0000); + if (device->chipset == 0x20) { + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x003d0000); for (i = 0; i < 15; i++) - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, 0x00000000); - nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, 0x00000000); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x400700)) + break; + ); } else { - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x02c80000); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x02c80000); for (i = 0; i < 32; i++) - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, 0x00000000); - nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, 0x00000000); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x400700)) + break; + ); } - nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + nvkm_wr32(device, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700); - nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ - nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000); - nv_wr32(priv, 0x40009C , 0x00000040); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x00118700); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ + nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00000000); + nvkm_wr32(device, 0x40009C , 0x00000040); - if (nv_device(priv)->chipset >= 0x25) { - nv_wr32(priv, 0x400890, 0x00a8cfff); - nv_wr32(priv, 0x400610, 0x304B1FB6); - nv_wr32(priv, 0x400B80, 0x1cbd3883); - nv_wr32(priv, 0x400B84, 0x44000000); - nv_wr32(priv, 0x400098, 0x40000080); - nv_wr32(priv, 0x400B88, 0x000000ff); + if (device->chipset >= 0x25) { + nvkm_wr32(device, 0x400890, 0x00a8cfff); + nvkm_wr32(device, 0x400610, 0x304B1FB6); + nvkm_wr32(device, 0x400B80, 0x1cbd3883); + nvkm_wr32(device, 0x400B84, 0x44000000); + nvkm_wr32(device, 0x400098, 0x40000080); + nvkm_wr32(device, 0x400B88, 0x000000ff); } else { - nv_wr32(priv, 0x400880, 0x0008c7df); - nv_wr32(priv, 0x400094, 0x00000005); - nv_wr32(priv, 0x400B80, 0x45eae20e); - nv_wr32(priv, 0x400B84, 0x24000000); - nv_wr32(priv, 0x400098, 0x00000040); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00038); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000030); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E10038); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000030); + nvkm_wr32(device, 0x400880, 0x0008c7df); + nvkm_wr32(device, 0x400094, 0x00000005); + nvkm_wr32(device, 0x400B80, 0x45eae20e); + nvkm_wr32(device, 0x400B84, 0x24000000); + nvkm_wr32(device, 0x400098, 0x00000040); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00E00038); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000030); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00E10038); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000030); } - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->tile.regions; i++) - engine->tile_prog(engine, i); + nvkm_wr32(device, 0x4009a0, nvkm_rd32(device, 0x100324)); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, nvkm_rd32(device, 0x100324)); - nv_wr32(priv, 0x4009a0, nv_rd32(priv, 0x100324)); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA, nv_rd32(priv, 0x100324)); + nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nvkm_wr32(device, NV10_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); - - tmp = nv_rd32(priv, NV10_PGRAPH_SURFACE) & 0x0007ff00; - nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); - tmp = nv_rd32(priv, NV10_PGRAPH_SURFACE) | 0x00020100; - nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); + tmp = nvkm_rd32(device, NV10_PGRAPH_SURFACE) & 0x0007ff00; + nvkm_wr32(device, NV10_PGRAPH_SURFACE, tmp); + tmp = nvkm_rd32(device, NV10_PGRAPH_SURFACE) | 0x00020100; + nvkm_wr32(device, NV10_PGRAPH_SURFACE, tmp); /* begin RAM config */ - vramsz = nv_device_resource_len(nv_device(priv), 0) - 1; - nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , nv_rd32(priv, 0x100200)); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , nv_rd32(priv, 0x100204)); - nv_wr32(priv, 0x400820, 0); - nv_wr32(priv, 0x400824, 0); - nv_wr32(priv, 0x400864, vramsz - 1); - nv_wr32(priv, 0x400868, vramsz - 1); + vramsz = device->func->resource_size(device, 1) - 1; + nvkm_wr32(device, 0x4009A4, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x4009A8, nvkm_rd32(device, 0x100204)); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , nvkm_rd32(device, 0x100204)); + nvkm_wr32(device, 0x400820, 0); + nvkm_wr32(device, 0x400824, 0); + nvkm_wr32(device, 0x400864, vramsz - 1); + nvkm_wr32(device, 0x400868, vramsz - 1); /* interesting.. the below overwrites some of the tile setup above.. */ - nv_wr32(priv, 0x400B20, 0x00000000); - nv_wr32(priv, 0x400B04, 0xFFFFFFFF); + nvkm_wr32(device, 0x400B20, 0x00000000); + nvkm_wr32(device, 0x400B04, 0xFFFFFFFF); - nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); - nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); - nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); - nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); + nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); + nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); + nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); + nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); return 0; } -struct nvkm_oclass -nv20_gr_oclass = { - .handle = NV_ENGINE(GR, 0x20), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv20_gr_ctor, - .dtor = nv20_gr_dtor, - .init = nv20_gr_init, - .fini = _nvkm_gr_fini, - }, +void * +nv20_gr_dtor(struct nvkm_gr *base) +{ + struct nv20_gr *gr = nv20_gr(base); + nvkm_memory_del(&gr->ctxtab); + return gr; +} + +int +nv20_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device, + int index, struct nvkm_gr **pgr) +{ + struct nv20_gr *gr; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + *pgr = &gr->base; + + return nvkm_gr_ctor(func, device, index, 0x00001000, true, &gr->base); +} + +static const struct nvkm_gr_func +nv20_gr = { + .dtor = nv20_gr_dtor, + .oneinit = nv20_gr_oneinit, + .init = nv20_gr_init, + .intr = nv20_gr_intr, + .tile = nv20_gr_tile, + .chan_new = nv20_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x0096, &nv04_gr_object }, /* celcius */ + { -1, -1, 0x0097, &nv04_gr_object }, /* kelvin */ + { -1, -1, 0x009e, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ + {} + } }; + +int +nv20_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv20_gr_new_(&nv20_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h index ac4dc048f..cdf4501e3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h @@ -1,26 +1,33 @@ #ifndef __NV20_GR_H__ #define __NV20_GR_H__ -#include +#define nv20_gr(p) container_of((p), struct nv20_gr, base) +#include "priv.h" -struct nv20_gr_priv { +struct nv20_gr { struct nvkm_gr base; - struct nvkm_gpuobj *ctxtab; + struct nvkm_memory *ctxtab; }; -struct nv20_gr_chan { - struct nvkm_gr_chan base; - int chid; -}; +int nv20_gr_new_(const struct nvkm_gr_func *, struct nvkm_device *, + int, struct nvkm_gr **); +void *nv20_gr_dtor(struct nvkm_gr *); +int nv20_gr_oneinit(struct nvkm_gr *); +int nv20_gr_init(struct nvkm_gr *); +void nv20_gr_intr(struct nvkm_gr *); +void nv20_gr_tile(struct nvkm_gr *, int, struct nvkm_fb_tile *); -extern struct nvkm_oclass nv25_gr_sclass[]; -int nv20_gr_context_init(struct nvkm_object *); -int nv20_gr_context_fini(struct nvkm_object *, bool); +int nv30_gr_init(struct nvkm_gr *); -void nv20_gr_tile_prog(struct nvkm_engine *, int); -void nv20_gr_intr(struct nvkm_subdev *); +#define nv20_gr_chan(p) container_of((p), struct nv20_gr_chan, object) -void nv20_gr_dtor(struct nvkm_object *); -int nv20_gr_init(struct nvkm_object *); +struct nv20_gr_chan { + struct nvkm_object object; + struct nv20_gr *gr; + int chid; + struct nvkm_memory *inst; +}; -int nv30_gr_init(struct nvkm_object *); +void *nv20_gr_chan_dtor(struct nvkm_object *); +int nv20_gr_chan_init(struct nvkm_object *); +int nv20_gr_chan_fini(struct nvkm_object *, bool); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c index bc362519c..6c4a00819 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c @@ -1,158 +1,134 @@ #include "nv20.h" #include "regs.h" +#include #include +#include /******************************************************************************* - * Graphics object classes + * PGRAPH context ******************************************************************************/ -struct nvkm_oclass -nv25_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv04_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv04_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv04_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv04_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv04_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs, NULL }, /* ifc */ - { 0x0096, &nv04_gr_ofuncs, NULL }, /* celcius */ - { 0x009e, &nv04_gr_ofuncs, NULL }, /* swzsurf */ - { 0x009f, &nv04_gr_ofuncs, NULL }, /* imageblit */ - { 0x0597, &nv04_gr_ofuncs, NULL }, /* kelvin */ - {}, +static const struct nvkm_object_func +nv25_gr_chan = { + .dtor = nv20_gr_chan_dtor, + .init = nv20_gr_chan_init, + .fini = nv20_gr_chan_fini, }; -/******************************************************************************* - * PGRAPH context - ******************************************************************************/ - static int -nv25_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv25_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { + struct nv20_gr *gr = nv20_gr(base); struct nv20_gr_chan *chan; int ret, i; - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, 0x3724, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv25_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; + + ret = nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 0x3724, 16, true, + &chan->inst); if (ret) return ret; - chan->chid = nvkm_fifo_chan(parent)->chid; - - nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); - nv_wo32(chan, 0x035c, 0xffff0000); - nv_wo32(chan, 0x03c0, 0x0fff0000); - nv_wo32(chan, 0x03c4, 0x0fff0000); - nv_wo32(chan, 0x049c, 0x00000101); - nv_wo32(chan, 0x04b0, 0x00000111); - nv_wo32(chan, 0x04c8, 0x00000080); - nv_wo32(chan, 0x04cc, 0xffff0000); - nv_wo32(chan, 0x04d0, 0x00000001); - nv_wo32(chan, 0x04e4, 0x44400000); - nv_wo32(chan, 0x04fc, 0x4b800000); + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x0028, 0x00000001 | (chan->chid << 24)); + nvkm_wo32(chan->inst, 0x035c, 0xffff0000); + nvkm_wo32(chan->inst, 0x03c0, 0x0fff0000); + nvkm_wo32(chan->inst, 0x03c4, 0x0fff0000); + nvkm_wo32(chan->inst, 0x049c, 0x00000101); + nvkm_wo32(chan->inst, 0x04b0, 0x00000111); + nvkm_wo32(chan->inst, 0x04c8, 0x00000080); + nvkm_wo32(chan->inst, 0x04cc, 0xffff0000); + nvkm_wo32(chan->inst, 0x04d0, 0x00000001); + nvkm_wo32(chan->inst, 0x04e4, 0x44400000); + nvkm_wo32(chan->inst, 0x04fc, 0x4b800000); for (i = 0x0510; i <= 0x051c; i += 4) - nv_wo32(chan, i, 0x00030303); + nvkm_wo32(chan->inst, i, 0x00030303); for (i = 0x0530; i <= 0x053c; i += 4) - nv_wo32(chan, i, 0x00080000); + nvkm_wo32(chan->inst, i, 0x00080000); for (i = 0x0548; i <= 0x0554; i += 4) - nv_wo32(chan, i, 0x01012000); + nvkm_wo32(chan->inst, i, 0x01012000); for (i = 0x0558; i <= 0x0564; i += 4) - nv_wo32(chan, i, 0x000105b8); + nvkm_wo32(chan->inst, i, 0x000105b8); for (i = 0x0568; i <= 0x0574; i += 4) - nv_wo32(chan, i, 0x00080008); + nvkm_wo32(chan->inst, i, 0x00080008); for (i = 0x0598; i <= 0x05d4; i += 4) - nv_wo32(chan, i, 0x07ff0000); - nv_wo32(chan, 0x05e0, 0x4b7fffff); - nv_wo32(chan, 0x0620, 0x00000080); - nv_wo32(chan, 0x0624, 0x30201000); - nv_wo32(chan, 0x0628, 0x70605040); - nv_wo32(chan, 0x062c, 0xb0a09080); - nv_wo32(chan, 0x0630, 0xf0e0d0c0); - nv_wo32(chan, 0x0664, 0x00000001); - nv_wo32(chan, 0x066c, 0x00004000); - nv_wo32(chan, 0x0678, 0x00000001); - nv_wo32(chan, 0x0680, 0x00040000); - nv_wo32(chan, 0x0684, 0x00010000); + nvkm_wo32(chan->inst, i, 0x07ff0000); + nvkm_wo32(chan->inst, 0x05e0, 0x4b7fffff); + nvkm_wo32(chan->inst, 0x0620, 0x00000080); + nvkm_wo32(chan->inst, 0x0624, 0x30201000); + nvkm_wo32(chan->inst, 0x0628, 0x70605040); + nvkm_wo32(chan->inst, 0x062c, 0xb0a09080); + nvkm_wo32(chan->inst, 0x0630, 0xf0e0d0c0); + nvkm_wo32(chan->inst, 0x0664, 0x00000001); + nvkm_wo32(chan->inst, 0x066c, 0x00004000); + nvkm_wo32(chan->inst, 0x0678, 0x00000001); + nvkm_wo32(chan->inst, 0x0680, 0x00040000); + nvkm_wo32(chan->inst, 0x0684, 0x00010000); for (i = 0x1b04; i <= 0x2374; i += 16) { - nv_wo32(chan, (i + 0), 0x10700ff9); - nv_wo32(chan, (i + 4), 0x0436086c); - nv_wo32(chan, (i + 8), 0x000c001b); + nvkm_wo32(chan->inst, (i + 0), 0x10700ff9); + nvkm_wo32(chan->inst, (i + 4), 0x0436086c); + nvkm_wo32(chan->inst, (i + 8), 0x000c001b); } - nv_wo32(chan, 0x2704, 0x3f800000); - nv_wo32(chan, 0x2718, 0x3f800000); - nv_wo32(chan, 0x2744, 0x40000000); - nv_wo32(chan, 0x2748, 0x3f800000); - nv_wo32(chan, 0x274c, 0x3f000000); - nv_wo32(chan, 0x2754, 0x40000000); - nv_wo32(chan, 0x2758, 0x3f800000); - nv_wo32(chan, 0x2760, 0xbf800000); - nv_wo32(chan, 0x2768, 0xbf800000); - nv_wo32(chan, 0x308c, 0x000fe000); - nv_wo32(chan, 0x3108, 0x000003f8); - nv_wo32(chan, 0x3468, 0x002fe000); + nvkm_wo32(chan->inst, 0x2704, 0x3f800000); + nvkm_wo32(chan->inst, 0x2718, 0x3f800000); + nvkm_wo32(chan->inst, 0x2744, 0x40000000); + nvkm_wo32(chan->inst, 0x2748, 0x3f800000); + nvkm_wo32(chan->inst, 0x274c, 0x3f000000); + nvkm_wo32(chan->inst, 0x2754, 0x40000000); + nvkm_wo32(chan->inst, 0x2758, 0x3f800000); + nvkm_wo32(chan->inst, 0x2760, 0xbf800000); + nvkm_wo32(chan->inst, 0x2768, 0xbf800000); + nvkm_wo32(chan->inst, 0x308c, 0x000fe000); + nvkm_wo32(chan->inst, 0x3108, 0x000003f8); + nvkm_wo32(chan->inst, 0x3468, 0x002fe000); for (i = 0x3484; i <= 0x34a0; i += 4) - nv_wo32(chan, i, 0x001c527c); + nvkm_wo32(chan->inst, i, 0x001c527c); + nvkm_done(chan->inst); return 0; } -static struct nvkm_oclass -nv25_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x25), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv25_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = nv20_gr_context_init, - .fini = nv20_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ -static int -nv25_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv20_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); - if (ret) - return ret; +static const struct nvkm_gr_func +nv25_gr = { + .dtor = nv20_gr_dtor, + .oneinit = nv20_gr_oneinit, + .init = nv20_gr_init, + .intr = nv20_gr_intr, + .tile = nv20_gr_tile, + .chan_new = nv25_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x0096, &nv04_gr_object }, /* celcius */ + { -1, -1, 0x009e, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ + { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */ + {} + } +}; - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv20_gr_intr; - nv_engine(priv)->cclass = &nv25_gr_cclass; - nv_engine(priv)->sclass = nv25_gr_sclass; - nv_engine(priv)->tile_prog = nv20_gr_tile_prog; - return 0; +int +nv25_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv20_gr_new_(&nv25_gr, device, index, pgr); } - -struct nvkm_oclass -nv25_gr_oclass = { - .handle = NV_ENGINE(GR, 0x25), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv25_gr_ctor, - .dtor = nv20_gr_dtor, - .init = nv20_gr_init, - .fini = _nvkm_gr_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c index 22a5096e2..3cad26dbc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c @@ -1,125 +1,125 @@ #include "nv20.h" #include "regs.h" +#include #include +#include /******************************************************************************* * PGRAPH context ******************************************************************************/ +static const struct nvkm_object_func +nv2a_gr_chan = { + .dtor = nv20_gr_chan_dtor, + .init = nv20_gr_chan_init, + .fini = nv20_gr_chan_fini, +}; + static int -nv2a_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv2a_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { + struct nv20_gr *gr = nv20_gr(base); struct nv20_gr_chan *chan; int ret, i; - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, 0x36b0, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv2a_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; + + ret = nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 0x36b0, 16, true, + &chan->inst); if (ret) return ret; - chan->chid = nvkm_fifo_chan(parent)->chid; - - nv_wo32(chan, 0x0000, 0x00000001 | (chan->chid << 24)); - nv_wo32(chan, 0x033c, 0xffff0000); - nv_wo32(chan, 0x03a0, 0x0fff0000); - nv_wo32(chan, 0x03a4, 0x0fff0000); - nv_wo32(chan, 0x047c, 0x00000101); - nv_wo32(chan, 0x0490, 0x00000111); - nv_wo32(chan, 0x04a8, 0x44400000); + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x0000, 0x00000001 | (chan->chid << 24)); + nvkm_wo32(chan->inst, 0x033c, 0xffff0000); + nvkm_wo32(chan->inst, 0x03a0, 0x0fff0000); + nvkm_wo32(chan->inst, 0x03a4, 0x0fff0000); + nvkm_wo32(chan->inst, 0x047c, 0x00000101); + nvkm_wo32(chan->inst, 0x0490, 0x00000111); + nvkm_wo32(chan->inst, 0x04a8, 0x44400000); for (i = 0x04d4; i <= 0x04e0; i += 4) - nv_wo32(chan, i, 0x00030303); + nvkm_wo32(chan->inst, i, 0x00030303); for (i = 0x04f4; i <= 0x0500; i += 4) - nv_wo32(chan, i, 0x00080000); + nvkm_wo32(chan->inst, i, 0x00080000); for (i = 0x050c; i <= 0x0518; i += 4) - nv_wo32(chan, i, 0x01012000); + nvkm_wo32(chan->inst, i, 0x01012000); for (i = 0x051c; i <= 0x0528; i += 4) - nv_wo32(chan, i, 0x000105b8); + nvkm_wo32(chan->inst, i, 0x000105b8); for (i = 0x052c; i <= 0x0538; i += 4) - nv_wo32(chan, i, 0x00080008); + nvkm_wo32(chan->inst, i, 0x00080008); for (i = 0x055c; i <= 0x0598; i += 4) - nv_wo32(chan, i, 0x07ff0000); - nv_wo32(chan, 0x05a4, 0x4b7fffff); - nv_wo32(chan, 0x05fc, 0x00000001); - nv_wo32(chan, 0x0604, 0x00004000); - nv_wo32(chan, 0x0610, 0x00000001); - nv_wo32(chan, 0x0618, 0x00040000); - nv_wo32(chan, 0x061c, 0x00010000); + nvkm_wo32(chan->inst, i, 0x07ff0000); + nvkm_wo32(chan->inst, 0x05a4, 0x4b7fffff); + nvkm_wo32(chan->inst, 0x05fc, 0x00000001); + nvkm_wo32(chan->inst, 0x0604, 0x00004000); + nvkm_wo32(chan->inst, 0x0610, 0x00000001); + nvkm_wo32(chan->inst, 0x0618, 0x00040000); + nvkm_wo32(chan->inst, 0x061c, 0x00010000); for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ - nv_wo32(chan, (i + 0), 0x10700ff9); - nv_wo32(chan, (i + 4), 0x0436086c); - nv_wo32(chan, (i + 8), 0x000c001b); + nvkm_wo32(chan->inst, (i + 0), 0x10700ff9); + nvkm_wo32(chan->inst, (i + 4), 0x0436086c); + nvkm_wo32(chan->inst, (i + 8), 0x000c001b); } - nv_wo32(chan, 0x269c, 0x3f800000); - nv_wo32(chan, 0x26b0, 0x3f800000); - nv_wo32(chan, 0x26dc, 0x40000000); - nv_wo32(chan, 0x26e0, 0x3f800000); - nv_wo32(chan, 0x26e4, 0x3f000000); - nv_wo32(chan, 0x26ec, 0x40000000); - nv_wo32(chan, 0x26f0, 0x3f800000); - nv_wo32(chan, 0x26f8, 0xbf800000); - nv_wo32(chan, 0x2700, 0xbf800000); - nv_wo32(chan, 0x3024, 0x000fe000); - nv_wo32(chan, 0x30a0, 0x000003f8); - nv_wo32(chan, 0x33fc, 0x002fe000); + nvkm_wo32(chan->inst, 0x269c, 0x3f800000); + nvkm_wo32(chan->inst, 0x26b0, 0x3f800000); + nvkm_wo32(chan->inst, 0x26dc, 0x40000000); + nvkm_wo32(chan->inst, 0x26e0, 0x3f800000); + nvkm_wo32(chan->inst, 0x26e4, 0x3f000000); + nvkm_wo32(chan->inst, 0x26ec, 0x40000000); + nvkm_wo32(chan->inst, 0x26f0, 0x3f800000); + nvkm_wo32(chan->inst, 0x26f8, 0xbf800000); + nvkm_wo32(chan->inst, 0x2700, 0xbf800000); + nvkm_wo32(chan->inst, 0x3024, 0x000fe000); + nvkm_wo32(chan->inst, 0x30a0, 0x000003f8); + nvkm_wo32(chan->inst, 0x33fc, 0x002fe000); for (i = 0x341c; i <= 0x3438; i += 4) - nv_wo32(chan, i, 0x001c527c); + nvkm_wo32(chan->inst, i, 0x001c527c); + nvkm_done(chan->inst); return 0; } -static struct nvkm_oclass -nv2a_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x2a), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv2a_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = nv20_gr_context_init, - .fini = nv20_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ -static int -nv2a_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv20_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); - if (ret) - return ret; +static const struct nvkm_gr_func +nv2a_gr = { + .dtor = nv20_gr_dtor, + .oneinit = nv20_gr_oneinit, + .init = nv20_gr_init, + .intr = nv20_gr_intr, + .tile = nv20_gr_tile, + .chan_new = nv2a_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x0096, &nv04_gr_object }, /* celcius */ + { -1, -1, 0x009e, &nv04_gr_object }, /* swzsurf */ + { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ + { -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */ + {} + } +}; - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv20_gr_intr; - nv_engine(priv)->cclass = &nv2a_gr_cclass; - nv_engine(priv)->sclass = nv25_gr_sclass; - nv_engine(priv)->tile_prog = nv20_gr_tile_prog; - return 0; +int +nv2a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv20_gr_new_(&nv2a_gr, device, index, pgr); } - -struct nvkm_oclass -nv2a_gr_oclass = { - .handle = NV_ENGINE(GR, 0x2a), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv2a_gr_ctor, - .dtor = nv20_gr_dtor, - .init = nv20_gr_init, - .fini = _nvkm_gr_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c index dcc84eb54..69de8c625 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c @@ -1,231 +1,198 @@ #include "nv20.h" #include "regs.h" -#include +#include #include +#include #include /******************************************************************************* - * Graphics object classes + * PGRAPH context ******************************************************************************/ -static struct nvkm_oclass -nv30_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv04_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv04_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv04_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv04_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv04_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs, NULL }, /* ifc */ - { 0x009f, &nv04_gr_ofuncs, NULL }, /* imageblit */ - { 0x0362, &nv04_gr_ofuncs, NULL }, /* surf2d (nv30) */ - { 0x0389, &nv04_gr_ofuncs, NULL }, /* sifm (nv30) */ - { 0x038a, &nv04_gr_ofuncs, NULL }, /* ifc (nv30) */ - { 0x039e, &nv04_gr_ofuncs, NULL }, /* swzsurf (nv30) */ - { 0x0397, &nv04_gr_ofuncs, NULL }, /* rankine */ - {}, +static const struct nvkm_object_func +nv30_gr_chan = { + .dtor = nv20_gr_chan_dtor, + .init = nv20_gr_chan_init, + .fini = nv20_gr_chan_fini, }; -/******************************************************************************* - * PGRAPH context - ******************************************************************************/ - static int -nv30_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { + struct nv20_gr *gr = nv20_gr(base); struct nv20_gr_chan *chan; int ret, i; - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, 0x5f48, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv30_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; + + ret = nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 0x5f48, 16, true, + &chan->inst); if (ret) return ret; - chan->chid = nvkm_fifo_chan(parent)->chid; - - nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); - nv_wo32(chan, 0x0410, 0x00000101); - nv_wo32(chan, 0x0424, 0x00000111); - nv_wo32(chan, 0x0428, 0x00000060); - nv_wo32(chan, 0x0444, 0x00000080); - nv_wo32(chan, 0x0448, 0xffff0000); - nv_wo32(chan, 0x044c, 0x00000001); - nv_wo32(chan, 0x0460, 0x44400000); - nv_wo32(chan, 0x048c, 0xffff0000); + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x0028, 0x00000001 | (chan->chid << 24)); + nvkm_wo32(chan->inst, 0x0410, 0x00000101); + nvkm_wo32(chan->inst, 0x0424, 0x00000111); + nvkm_wo32(chan->inst, 0x0428, 0x00000060); + nvkm_wo32(chan->inst, 0x0444, 0x00000080); + nvkm_wo32(chan->inst, 0x0448, 0xffff0000); + nvkm_wo32(chan->inst, 0x044c, 0x00000001); + nvkm_wo32(chan->inst, 0x0460, 0x44400000); + nvkm_wo32(chan->inst, 0x048c, 0xffff0000); for (i = 0x04e0; i < 0x04e8; i += 4) - nv_wo32(chan, i, 0x0fff0000); - nv_wo32(chan, 0x04ec, 0x00011100); + nvkm_wo32(chan->inst, i, 0x0fff0000); + nvkm_wo32(chan->inst, 0x04ec, 0x00011100); for (i = 0x0508; i < 0x0548; i += 4) - nv_wo32(chan, i, 0x07ff0000); - nv_wo32(chan, 0x0550, 0x4b7fffff); - nv_wo32(chan, 0x058c, 0x00000080); - nv_wo32(chan, 0x0590, 0x30201000); - nv_wo32(chan, 0x0594, 0x70605040); - nv_wo32(chan, 0x0598, 0xb8a89888); - nv_wo32(chan, 0x059c, 0xf8e8d8c8); - nv_wo32(chan, 0x05b0, 0xb0000000); + nvkm_wo32(chan->inst, i, 0x07ff0000); + nvkm_wo32(chan->inst, 0x0550, 0x4b7fffff); + nvkm_wo32(chan->inst, 0x058c, 0x00000080); + nvkm_wo32(chan->inst, 0x0590, 0x30201000); + nvkm_wo32(chan->inst, 0x0594, 0x70605040); + nvkm_wo32(chan->inst, 0x0598, 0xb8a89888); + nvkm_wo32(chan->inst, 0x059c, 0xf8e8d8c8); + nvkm_wo32(chan->inst, 0x05b0, 0xb0000000); for (i = 0x0600; i < 0x0640; i += 4) - nv_wo32(chan, i, 0x00010588); + nvkm_wo32(chan->inst, i, 0x00010588); for (i = 0x0640; i < 0x0680; i += 4) - nv_wo32(chan, i, 0x00030303); + nvkm_wo32(chan->inst, i, 0x00030303); for (i = 0x06c0; i < 0x0700; i += 4) - nv_wo32(chan, i, 0x0008aae4); + nvkm_wo32(chan->inst, i, 0x0008aae4); for (i = 0x0700; i < 0x0740; i += 4) - nv_wo32(chan, i, 0x01012000); + nvkm_wo32(chan->inst, i, 0x01012000); for (i = 0x0740; i < 0x0780; i += 4) - nv_wo32(chan, i, 0x00080008); - nv_wo32(chan, 0x085c, 0x00040000); - nv_wo32(chan, 0x0860, 0x00010000); + nvkm_wo32(chan->inst, i, 0x00080008); + nvkm_wo32(chan->inst, 0x085c, 0x00040000); + nvkm_wo32(chan->inst, 0x0860, 0x00010000); for (i = 0x0864; i < 0x0874; i += 4) - nv_wo32(chan, i, 0x00040004); + nvkm_wo32(chan->inst, i, 0x00040004); for (i = 0x1f18; i <= 0x3088 ; i += 16) { - nv_wo32(chan, i + 0, 0x10700ff9); - nv_wo32(chan, i + 1, 0x0436086c); - nv_wo32(chan, i + 2, 0x000c001b); + nvkm_wo32(chan->inst, i + 0, 0x10700ff9); + nvkm_wo32(chan->inst, i + 1, 0x0436086c); + nvkm_wo32(chan->inst, i + 2, 0x000c001b); } for (i = 0x30b8; i < 0x30c8; i += 4) - nv_wo32(chan, i, 0x0000ffff); - nv_wo32(chan, 0x344c, 0x3f800000); - nv_wo32(chan, 0x3808, 0x3f800000); - nv_wo32(chan, 0x381c, 0x3f800000); - nv_wo32(chan, 0x3848, 0x40000000); - nv_wo32(chan, 0x384c, 0x3f800000); - nv_wo32(chan, 0x3850, 0x3f000000); - nv_wo32(chan, 0x3858, 0x40000000); - nv_wo32(chan, 0x385c, 0x3f800000); - nv_wo32(chan, 0x3864, 0xbf800000); - nv_wo32(chan, 0x386c, 0xbf800000); + nvkm_wo32(chan->inst, i, 0x0000ffff); + nvkm_wo32(chan->inst, 0x344c, 0x3f800000); + nvkm_wo32(chan->inst, 0x3808, 0x3f800000); + nvkm_wo32(chan->inst, 0x381c, 0x3f800000); + nvkm_wo32(chan->inst, 0x3848, 0x40000000); + nvkm_wo32(chan->inst, 0x384c, 0x3f800000); + nvkm_wo32(chan->inst, 0x3850, 0x3f000000); + nvkm_wo32(chan->inst, 0x3858, 0x40000000); + nvkm_wo32(chan->inst, 0x385c, 0x3f800000); + nvkm_wo32(chan->inst, 0x3864, 0xbf800000); + nvkm_wo32(chan->inst, 0x386c, 0xbf800000); + nvkm_done(chan->inst); return 0; } -static struct nvkm_oclass -nv30_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x30), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv30_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = nv20_gr_context_init, - .fini = nv20_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ -static int -nv30_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv20_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv20_gr_intr; - nv_engine(priv)->cclass = &nv30_gr_cclass; - nv_engine(priv)->sclass = nv30_gr_sclass; - nv_engine(priv)->tile_prog = nv20_gr_tile_prog; - return 0; -} - int -nv30_gr_init(struct nvkm_object *object) +nv30_gr_init(struct nvkm_gr *base) { - struct nvkm_engine *engine = nv_engine(object); - struct nv20_gr_priv *priv = (void *)engine; - struct nvkm_fb *pfb = nvkm_fb(object); - int ret, i; - - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); - - nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); - nv_wr32(priv, 0x400890, 0x01b463ff); - nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf2de0475); - nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); - nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); - nv_wr32(priv, 0x400B80, 0x1003d888); - nv_wr32(priv, 0x400B84, 0x0c000000); - nv_wr32(priv, 0x400098, 0x00000000); - nv_wr32(priv, 0x40009C, 0x0005ad00); - nv_wr32(priv, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ - nv_wr32(priv, 0x4000a0, 0x00000000); - nv_wr32(priv, 0x4000a4, 0x00000008); - nv_wr32(priv, 0x4008a8, 0xb784a400); - nv_wr32(priv, 0x400ba0, 0x002f8685); - nv_wr32(priv, 0x400ba4, 0x00231f3f); - nv_wr32(priv, 0x4008a4, 0x40000020); - - if (nv_device(priv)->chipset == 0x34) { - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00200201); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000008); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000032); - nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00004); - nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000002); + struct nv20_gr *gr = nv20_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, NV20_PGRAPH_CHANNEL_CTX_TABLE, + nvkm_memory_addr(gr->ctxtab) >> 4); + + nvkm_wr32(device, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nvkm_wr32(device, 0x400890, 0x01b463ff); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xf2de0475); + nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00008000); + nvkm_wr32(device, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); + nvkm_wr32(device, 0x400B80, 0x1003d888); + nvkm_wr32(device, 0x400B84, 0x0c000000); + nvkm_wr32(device, 0x400098, 0x00000000); + nvkm_wr32(device, 0x40009C, 0x0005ad00); + nvkm_wr32(device, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ + nvkm_wr32(device, 0x4000a0, 0x00000000); + nvkm_wr32(device, 0x4000a4, 0x00000008); + nvkm_wr32(device, 0x4008a8, 0xb784a400); + nvkm_wr32(device, 0x400ba0, 0x002f8685); + nvkm_wr32(device, 0x400ba4, 0x00231f3f); + nvkm_wr32(device, 0x4008a4, 0x40000020); + + if (device->chipset == 0x34) { + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00200201); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000008); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000032); + nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00E00004); + nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000002); } - nv_wr32(priv, 0x4000c0, 0x00000016); - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->tile.regions; i++) - engine->tile_prog(engine, i); + nvkm_wr32(device, 0x4000c0, 0x00000016); - nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(priv, 0x0040075c , 0x00000001); + nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nvkm_wr32(device, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nvkm_wr32(device, 0x0040075c , 0x00000001); /* begin RAM config */ - /* vramsz = pci_resource_len(priv->dev->pdev, 0) - 1; */ - nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); - if (nv_device(priv)->chipset != 0x34) { - nv_wr32(priv, 0x400750, 0x00EA0000); - nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x400750, 0x00EA0004); - nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100204)); + /* vramsz = pci_resource_len(gr->dev->pdev, 1) - 1; */ + nvkm_wr32(device, 0x4009A4, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x4009A8, nvkm_rd32(device, 0x100204)); + if (device->chipset != 0x34) { + nvkm_wr32(device, 0x400750, 0x00EA0000); + nvkm_wr32(device, 0x400754, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x400750, 0x00EA0004); + nvkm_wr32(device, 0x400754, nvkm_rd32(device, 0x100204)); } + return 0; } -struct nvkm_oclass -nv30_gr_oclass = { - .handle = NV_ENGINE(GR, 0x30), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv30_gr_ctor, - .dtor = nv20_gr_dtor, - .init = nv30_gr_init, - .fini = _nvkm_gr_fini, - }, +static const struct nvkm_gr_func +nv30_gr = { + .dtor = nv20_gr_dtor, + .oneinit = nv20_gr_oneinit, + .init = nv30_gr_init, + .intr = nv20_gr_intr, + .tile = nv20_gr_tile, + .chan_new = nv30_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ + { -1, -1, 0x0362, &nv04_gr_object }, /* surf2d (nv30) */ + { -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */ + { -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */ + { -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */ + { -1, -1, 0x0397, &nv04_gr_object }, /* rankine */ + {} + } }; + +int +nv30_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv20_gr_new_(&nv30_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c index 985b7f330..2207dac23 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c @@ -1,159 +1,135 @@ #include "nv20.h" #include "regs.h" +#include #include +#include /******************************************************************************* - * Graphics object classes + * PGRAPH context ******************************************************************************/ -static struct nvkm_oclass -nv34_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv04_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv04_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv04_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv04_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv04_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs, NULL }, /* ifc */ - { 0x009f, &nv04_gr_ofuncs, NULL }, /* imageblit */ - { 0x0362, &nv04_gr_ofuncs, NULL }, /* surf2d (nv30) */ - { 0x0389, &nv04_gr_ofuncs, NULL }, /* sifm (nv30) */ - { 0x038a, &nv04_gr_ofuncs, NULL }, /* ifc (nv30) */ - { 0x039e, &nv04_gr_ofuncs, NULL }, /* swzsurf (nv30) */ - { 0x0697, &nv04_gr_ofuncs, NULL }, /* rankine */ - {}, +static const struct nvkm_object_func +nv34_gr_chan = { + .dtor = nv20_gr_chan_dtor, + .init = nv20_gr_chan_init, + .fini = nv20_gr_chan_fini, }; -/******************************************************************************* - * PGRAPH context - ******************************************************************************/ - static int -nv34_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { + struct nv20_gr *gr = nv20_gr(base); struct nv20_gr_chan *chan; int ret, i; - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, 0x46dc, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv34_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; + + ret = nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 0x46dc, 16, true, + &chan->inst); if (ret) return ret; - chan->chid = nvkm_fifo_chan(parent)->chid; - - nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); - nv_wo32(chan, 0x040c, 0x01000101); - nv_wo32(chan, 0x0420, 0x00000111); - nv_wo32(chan, 0x0424, 0x00000060); - nv_wo32(chan, 0x0440, 0x00000080); - nv_wo32(chan, 0x0444, 0xffff0000); - nv_wo32(chan, 0x0448, 0x00000001); - nv_wo32(chan, 0x045c, 0x44400000); - nv_wo32(chan, 0x0480, 0xffff0000); + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x0028, 0x00000001 | (chan->chid << 24)); + nvkm_wo32(chan->inst, 0x040c, 0x01000101); + nvkm_wo32(chan->inst, 0x0420, 0x00000111); + nvkm_wo32(chan->inst, 0x0424, 0x00000060); + nvkm_wo32(chan->inst, 0x0440, 0x00000080); + nvkm_wo32(chan->inst, 0x0444, 0xffff0000); + nvkm_wo32(chan->inst, 0x0448, 0x00000001); + nvkm_wo32(chan->inst, 0x045c, 0x44400000); + nvkm_wo32(chan->inst, 0x0480, 0xffff0000); for (i = 0x04d4; i < 0x04dc; i += 4) - nv_wo32(chan, i, 0x0fff0000); - nv_wo32(chan, 0x04e0, 0x00011100); + nvkm_wo32(chan->inst, i, 0x0fff0000); + nvkm_wo32(chan->inst, 0x04e0, 0x00011100); for (i = 0x04fc; i < 0x053c; i += 4) - nv_wo32(chan, i, 0x07ff0000); - nv_wo32(chan, 0x0544, 0x4b7fffff); - nv_wo32(chan, 0x057c, 0x00000080); - nv_wo32(chan, 0x0580, 0x30201000); - nv_wo32(chan, 0x0584, 0x70605040); - nv_wo32(chan, 0x0588, 0xb8a89888); - nv_wo32(chan, 0x058c, 0xf8e8d8c8); - nv_wo32(chan, 0x05a0, 0xb0000000); + nvkm_wo32(chan->inst, i, 0x07ff0000); + nvkm_wo32(chan->inst, 0x0544, 0x4b7fffff); + nvkm_wo32(chan->inst, 0x057c, 0x00000080); + nvkm_wo32(chan->inst, 0x0580, 0x30201000); + nvkm_wo32(chan->inst, 0x0584, 0x70605040); + nvkm_wo32(chan->inst, 0x0588, 0xb8a89888); + nvkm_wo32(chan->inst, 0x058c, 0xf8e8d8c8); + nvkm_wo32(chan->inst, 0x05a0, 0xb0000000); for (i = 0x05f0; i < 0x0630; i += 4) - nv_wo32(chan, i, 0x00010588); + nvkm_wo32(chan->inst, i, 0x00010588); for (i = 0x0630; i < 0x0670; i += 4) - nv_wo32(chan, i, 0x00030303); + nvkm_wo32(chan->inst, i, 0x00030303); for (i = 0x06b0; i < 0x06f0; i += 4) - nv_wo32(chan, i, 0x0008aae4); + nvkm_wo32(chan->inst, i, 0x0008aae4); for (i = 0x06f0; i < 0x0730; i += 4) - nv_wo32(chan, i, 0x01012000); + nvkm_wo32(chan->inst, i, 0x01012000); for (i = 0x0730; i < 0x0770; i += 4) - nv_wo32(chan, i, 0x00080008); - nv_wo32(chan, 0x0850, 0x00040000); - nv_wo32(chan, 0x0854, 0x00010000); + nvkm_wo32(chan->inst, i, 0x00080008); + nvkm_wo32(chan->inst, 0x0850, 0x00040000); + nvkm_wo32(chan->inst, 0x0854, 0x00010000); for (i = 0x0858; i < 0x0868; i += 4) - nv_wo32(chan, i, 0x00040004); + nvkm_wo32(chan->inst, i, 0x00040004); for (i = 0x15ac; i <= 0x271c ; i += 16) { - nv_wo32(chan, i + 0, 0x10700ff9); - nv_wo32(chan, i + 1, 0x0436086c); - nv_wo32(chan, i + 2, 0x000c001b); + nvkm_wo32(chan->inst, i + 0, 0x10700ff9); + nvkm_wo32(chan->inst, i + 1, 0x0436086c); + nvkm_wo32(chan->inst, i + 2, 0x000c001b); } for (i = 0x274c; i < 0x275c; i += 4) - nv_wo32(chan, i, 0x0000ffff); - nv_wo32(chan, 0x2ae0, 0x3f800000); - nv_wo32(chan, 0x2e9c, 0x3f800000); - nv_wo32(chan, 0x2eb0, 0x3f800000); - nv_wo32(chan, 0x2edc, 0x40000000); - nv_wo32(chan, 0x2ee0, 0x3f800000); - nv_wo32(chan, 0x2ee4, 0x3f000000); - nv_wo32(chan, 0x2eec, 0x40000000); - nv_wo32(chan, 0x2ef0, 0x3f800000); - nv_wo32(chan, 0x2ef8, 0xbf800000); - nv_wo32(chan, 0x2f00, 0xbf800000); + nvkm_wo32(chan->inst, i, 0x0000ffff); + nvkm_wo32(chan->inst, 0x2ae0, 0x3f800000); + nvkm_wo32(chan->inst, 0x2e9c, 0x3f800000); + nvkm_wo32(chan->inst, 0x2eb0, 0x3f800000); + nvkm_wo32(chan->inst, 0x2edc, 0x40000000); + nvkm_wo32(chan->inst, 0x2ee0, 0x3f800000); + nvkm_wo32(chan->inst, 0x2ee4, 0x3f000000); + nvkm_wo32(chan->inst, 0x2eec, 0x40000000); + nvkm_wo32(chan->inst, 0x2ef0, 0x3f800000); + nvkm_wo32(chan->inst, 0x2ef8, 0xbf800000); + nvkm_wo32(chan->inst, 0x2f00, 0xbf800000); + nvkm_done(chan->inst); return 0; } -static struct nvkm_oclass -nv34_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x34), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv34_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = nv20_gr_context_init, - .fini = nv20_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ -static int -nv34_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv20_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); - if (ret) - return ret; +static const struct nvkm_gr_func +nv34_gr = { + .dtor = nv20_gr_dtor, + .oneinit = nv20_gr_oneinit, + .init = nv30_gr_init, + .intr = nv20_gr_intr, + .tile = nv20_gr_tile, + .chan_new = nv34_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ + { -1, -1, 0x0362, &nv04_gr_object }, /* surf2d (nv30) */ + { -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */ + { -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */ + { -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */ + { -1, -1, 0x0697, &nv04_gr_object }, /* rankine */ + {} + } +}; - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv20_gr_intr; - nv_engine(priv)->cclass = &nv34_gr_cclass; - nv_engine(priv)->sclass = nv34_gr_sclass; - nv_engine(priv)->tile_prog = nv20_gr_tile_prog; - return 0; +int +nv34_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv20_gr_new_(&nv34_gr, device, index, pgr); } - -struct nvkm_oclass -nv34_gr_oclass = { - .handle = NV_ENGINE(GR, 0x34), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv34_gr_ctor, - .dtor = nv20_gr_dtor, - .init = nv30_gr_init, - .fini = _nvkm_gr_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c index 707625f19..740df0f52 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c @@ -1,159 +1,135 @@ #include "nv20.h" #include "regs.h" +#include #include +#include /******************************************************************************* - * Graphics object classes + * PGRAPH context ******************************************************************************/ -static struct nvkm_oclass -nv35_gr_sclass[] = { - { 0x0012, &nv04_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv04_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv04_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv04_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv04_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv04_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv04_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv04_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv04_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv04_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv04_gr_ofuncs, NULL }, /* ifc */ - { 0x009f, &nv04_gr_ofuncs, NULL }, /* imageblit */ - { 0x0362, &nv04_gr_ofuncs, NULL }, /* surf2d (nv30) */ - { 0x0389, &nv04_gr_ofuncs, NULL }, /* sifm (nv30) */ - { 0x038a, &nv04_gr_ofuncs, NULL }, /* ifc (nv30) */ - { 0x039e, &nv04_gr_ofuncs, NULL }, /* swzsurf (nv30) */ - { 0x0497, &nv04_gr_ofuncs, NULL }, /* rankine */ - {}, +static const struct nvkm_object_func +nv35_gr_chan = { + .dtor = nv20_gr_chan_dtor, + .init = nv20_gr_chan_init, + .fini = nv20_gr_chan_fini, }; -/******************************************************************************* - * PGRAPH context - ******************************************************************************/ - static int -nv35_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv35_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { + struct nv20_gr *gr = nv20_gr(base); struct nv20_gr_chan *chan; int ret, i; - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, 0x577c, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv35_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->chid = fifoch->chid; + *pobject = &chan->object; + + ret = nvkm_memory_new(gr->base.engine.subdev.device, + NVKM_MEM_TARGET_INST, 0x577c, 16, true, + &chan->inst); if (ret) return ret; - chan->chid = nvkm_fifo_chan(parent)->chid; - - nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); - nv_wo32(chan, 0x040c, 0x00000101); - nv_wo32(chan, 0x0420, 0x00000111); - nv_wo32(chan, 0x0424, 0x00000060); - nv_wo32(chan, 0x0440, 0x00000080); - nv_wo32(chan, 0x0444, 0xffff0000); - nv_wo32(chan, 0x0448, 0x00000001); - nv_wo32(chan, 0x045c, 0x44400000); - nv_wo32(chan, 0x0488, 0xffff0000); + nvkm_kmap(chan->inst); + nvkm_wo32(chan->inst, 0x0028, 0x00000001 | (chan->chid << 24)); + nvkm_wo32(chan->inst, 0x040c, 0x00000101); + nvkm_wo32(chan->inst, 0x0420, 0x00000111); + nvkm_wo32(chan->inst, 0x0424, 0x00000060); + nvkm_wo32(chan->inst, 0x0440, 0x00000080); + nvkm_wo32(chan->inst, 0x0444, 0xffff0000); + nvkm_wo32(chan->inst, 0x0448, 0x00000001); + nvkm_wo32(chan->inst, 0x045c, 0x44400000); + nvkm_wo32(chan->inst, 0x0488, 0xffff0000); for (i = 0x04dc; i < 0x04e4; i += 4) - nv_wo32(chan, i, 0x0fff0000); - nv_wo32(chan, 0x04e8, 0x00011100); + nvkm_wo32(chan->inst, i, 0x0fff0000); + nvkm_wo32(chan->inst, 0x04e8, 0x00011100); for (i = 0x0504; i < 0x0544; i += 4) - nv_wo32(chan, i, 0x07ff0000); - nv_wo32(chan, 0x054c, 0x4b7fffff); - nv_wo32(chan, 0x0588, 0x00000080); - nv_wo32(chan, 0x058c, 0x30201000); - nv_wo32(chan, 0x0590, 0x70605040); - nv_wo32(chan, 0x0594, 0xb8a89888); - nv_wo32(chan, 0x0598, 0xf8e8d8c8); - nv_wo32(chan, 0x05ac, 0xb0000000); + nvkm_wo32(chan->inst, i, 0x07ff0000); + nvkm_wo32(chan->inst, 0x054c, 0x4b7fffff); + nvkm_wo32(chan->inst, 0x0588, 0x00000080); + nvkm_wo32(chan->inst, 0x058c, 0x30201000); + nvkm_wo32(chan->inst, 0x0590, 0x70605040); + nvkm_wo32(chan->inst, 0x0594, 0xb8a89888); + nvkm_wo32(chan->inst, 0x0598, 0xf8e8d8c8); + nvkm_wo32(chan->inst, 0x05ac, 0xb0000000); for (i = 0x0604; i < 0x0644; i += 4) - nv_wo32(chan, i, 0x00010588); + nvkm_wo32(chan->inst, i, 0x00010588); for (i = 0x0644; i < 0x0684; i += 4) - nv_wo32(chan, i, 0x00030303); + nvkm_wo32(chan->inst, i, 0x00030303); for (i = 0x06c4; i < 0x0704; i += 4) - nv_wo32(chan, i, 0x0008aae4); + nvkm_wo32(chan->inst, i, 0x0008aae4); for (i = 0x0704; i < 0x0744; i += 4) - nv_wo32(chan, i, 0x01012000); + nvkm_wo32(chan->inst, i, 0x01012000); for (i = 0x0744; i < 0x0784; i += 4) - nv_wo32(chan, i, 0x00080008); - nv_wo32(chan, 0x0860, 0x00040000); - nv_wo32(chan, 0x0864, 0x00010000); + nvkm_wo32(chan->inst, i, 0x00080008); + nvkm_wo32(chan->inst, 0x0860, 0x00040000); + nvkm_wo32(chan->inst, 0x0864, 0x00010000); for (i = 0x0868; i < 0x0878; i += 4) - nv_wo32(chan, i, 0x00040004); + nvkm_wo32(chan->inst, i, 0x00040004); for (i = 0x1f1c; i <= 0x308c ; i += 16) { - nv_wo32(chan, i + 0, 0x10700ff9); - nv_wo32(chan, i + 4, 0x0436086c); - nv_wo32(chan, i + 8, 0x000c001b); + nvkm_wo32(chan->inst, i + 0, 0x10700ff9); + nvkm_wo32(chan->inst, i + 4, 0x0436086c); + nvkm_wo32(chan->inst, i + 8, 0x000c001b); } for (i = 0x30bc; i < 0x30cc; i += 4) - nv_wo32(chan, i, 0x0000ffff); - nv_wo32(chan, 0x3450, 0x3f800000); - nv_wo32(chan, 0x380c, 0x3f800000); - nv_wo32(chan, 0x3820, 0x3f800000); - nv_wo32(chan, 0x384c, 0x40000000); - nv_wo32(chan, 0x3850, 0x3f800000); - nv_wo32(chan, 0x3854, 0x3f000000); - nv_wo32(chan, 0x385c, 0x40000000); - nv_wo32(chan, 0x3860, 0x3f800000); - nv_wo32(chan, 0x3868, 0xbf800000); - nv_wo32(chan, 0x3870, 0xbf800000); + nvkm_wo32(chan->inst, i, 0x0000ffff); + nvkm_wo32(chan->inst, 0x3450, 0x3f800000); + nvkm_wo32(chan->inst, 0x380c, 0x3f800000); + nvkm_wo32(chan->inst, 0x3820, 0x3f800000); + nvkm_wo32(chan->inst, 0x384c, 0x40000000); + nvkm_wo32(chan->inst, 0x3850, 0x3f800000); + nvkm_wo32(chan->inst, 0x3854, 0x3f000000); + nvkm_wo32(chan->inst, 0x385c, 0x40000000); + nvkm_wo32(chan->inst, 0x3860, 0x3f800000); + nvkm_wo32(chan->inst, 0x3868, 0xbf800000); + nvkm_wo32(chan->inst, 0x3870, 0xbf800000); + nvkm_done(chan->inst); return 0; } -static struct nvkm_oclass -nv35_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x35), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv35_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = nv20_gr_context_init, - .fini = nv20_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ -static int -nv35_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv20_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); - if (ret) - return ret; +static const struct nvkm_gr_func +nv35_gr = { + .dtor = nv20_gr_dtor, + .oneinit = nv20_gr_oneinit, + .init = nv30_gr_init, + .intr = nv20_gr_intr, + .tile = nv20_gr_tile, + .chan_new = nv35_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv04_gr_object }, /* null */ + { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ + { -1, -1, 0x0362, &nv04_gr_object }, /* surf2d (nv30) */ + { -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */ + { -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */ + { -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */ + { -1, -1, 0x0497, &nv04_gr_object }, /* rankine */ + {} + } +}; - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv20_gr_intr; - nv_engine(priv)->cclass = &nv35_gr_cclass; - nv_engine(priv)->sclass = nv35_gr_sclass; - nv_engine(priv)->tile_prog = nv20_gr_tile_prog; - return 0; +int +nv35_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv20_gr_new_(&nv35_gr, device, index, pgr); } - -struct nvkm_oclass -nv35_gr_oclass = { - .handle = NV_ENGINE(GR, 0x35), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv35_gr_ctor, - .dtor = nv20_gr_dtor, - .init = nv30_gr_init, - .fini = _nvkm_gr_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c index 7e1937980..05a895496 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c @@ -25,26 +25,15 @@ #include "regs.h" #include -#include +#include #include #include #include -struct nv40_gr_priv { - struct nvkm_gr base; - u32 size; -}; - -struct nv40_gr_chan { - struct nvkm_gr_chan base; -}; - -static u64 +u64 nv40_gr_units(struct nvkm_gr *gr) { - struct nv40_gr_priv *priv = (void *)gr; - - return nv_rd32(priv, 0x1540); + return nvkm_rd32(gr->engine.subdev.device, 0x1540); } /******************************************************************************* @@ -52,80 +41,29 @@ nv40_gr_units(struct nvkm_gr *gr) ******************************************************************************/ static int -nv40_gr_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv40_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_gpuobj *obj; - int ret; - - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, - 20, 16, 0, &obj); - *pobject = nv_object(obj); - if (ret) - return ret; - - nv_wo32(obj, 0x00, nv_mclass(obj)); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); + int ret = nvkm_gpuobj_new(object->engine->subdev.device, 20, align, + false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, object->oclass); + nvkm_wo32(*pgpuobj, 0x04, 0x00000000); + nvkm_wo32(*pgpuobj, 0x08, 0x00000000); #ifdef __BIG_ENDIAN - nv_mo32(obj, 0x08, 0x01000000, 0x01000000); + nvkm_mo32(*pgpuobj, 0x08, 0x01000000, 0x01000000); #endif - nv_wo32(obj, 0x0c, 0x00000000); - nv_wo32(obj, 0x10, 0x00000000); - return 0; + nvkm_wo32(*pgpuobj, 0x0c, 0x00000000); + nvkm_wo32(*pgpuobj, 0x10, 0x00000000); + nvkm_done(*pgpuobj); + } + return ret; } -static struct nvkm_ofuncs -nv40_gr_ofuncs = { - .ctor = nv40_gr_object_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, -}; - -static struct nvkm_oclass -nv40_gr_sclass[] = { - { 0x0012, &nv40_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv40_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv40_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv40_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv40_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv40_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv40_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv40_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv40_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv40_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv40_gr_ofuncs, NULL }, /* ifc */ - { 0x009f, &nv40_gr_ofuncs, NULL }, /* imageblit */ - { 0x3062, &nv40_gr_ofuncs, NULL }, /* surf2d (nv40) */ - { 0x3089, &nv40_gr_ofuncs, NULL }, /* sifm (nv40) */ - { 0x309e, &nv40_gr_ofuncs, NULL }, /* swzsurf (nv40) */ - { 0x4097, &nv40_gr_ofuncs, NULL }, /* curie */ - {}, -}; - -static struct nvkm_oclass -nv44_gr_sclass[] = { - { 0x0012, &nv40_gr_ofuncs, NULL }, /* beta1 */ - { 0x0019, &nv40_gr_ofuncs, NULL }, /* clip */ - { 0x0030, &nv40_gr_ofuncs, NULL }, /* null */ - { 0x0039, &nv40_gr_ofuncs, NULL }, /* m2mf */ - { 0x0043, &nv40_gr_ofuncs, NULL }, /* rop */ - { 0x0044, &nv40_gr_ofuncs, NULL }, /* patt */ - { 0x004a, &nv40_gr_ofuncs, NULL }, /* gdi */ - { 0x0062, &nv40_gr_ofuncs, NULL }, /* surf2d */ - { 0x0072, &nv40_gr_ofuncs, NULL }, /* beta4 */ - { 0x0089, &nv40_gr_ofuncs, NULL }, /* sifm */ - { 0x008a, &nv40_gr_ofuncs, NULL }, /* ifc */ - { 0x009f, &nv40_gr_ofuncs, NULL }, /* imageblit */ - { 0x3062, &nv40_gr_ofuncs, NULL }, /* surf2d (nv40) */ - { 0x3089, &nv40_gr_ofuncs, NULL }, /* sifm (nv40) */ - { 0x309e, &nv40_gr_ofuncs, NULL }, /* swzsurf (nv40) */ - { 0x4497, &nv40_gr_ofuncs, NULL }, /* curie */ - {}, +const struct nvkm_object_func +nv40_gr_object = { + .bind = nv40_gr_object_bind, }; /******************************************************************************* @@ -133,361 +71,335 @@ nv44_gr_sclass[] = { ******************************************************************************/ static int -nv40_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv40_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nv40_gr_priv *priv = (void *)engine; - struct nv40_gr_chan *chan; - int ret; - - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, priv->size, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - nv40_grctx_fill(nv_device(priv), nv_gpuobj(chan)); - nv_wo32(chan, 0x00000, nv_gpuobj(chan)->addr >> 4); - return 0; + struct nv40_gr_chan *chan = nv40_gr_chan(object); + struct nv40_gr *gr = chan->gr; + int ret = nvkm_gpuobj_new(gr->base.engine.subdev.device, gr->size, + align, true, parent, pgpuobj); + if (ret == 0) { + chan->inst = (*pgpuobj)->addr; + nvkm_kmap(*pgpuobj); + nv40_grctx_fill(gr->base.engine.subdev.device, *pgpuobj); + nvkm_wo32(*pgpuobj, 0x00000, chan->inst >> 4); + nvkm_done(*pgpuobj); + } + return ret; } static int -nv40_gr_context_fini(struct nvkm_object *object, bool suspend) +nv40_gr_chan_fini(struct nvkm_object *object, bool suspend) { - struct nv40_gr_priv *priv = (void *)object->engine; - struct nv40_gr_chan *chan = (void *)object; - u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; + struct nv40_gr_chan *chan = nv40_gr_chan(object); + struct nv40_gr *gr = chan->gr; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 inst = 0x01000000 | chan->inst >> 4; int ret = 0; - nv_mask(priv, 0x400720, 0x00000001, 0x00000000); + nvkm_mask(device, 0x400720, 0x00000001, 0x00000000); - if (nv_rd32(priv, 0x40032c) == inst) { + if (nvkm_rd32(device, 0x40032c) == inst) { if (suspend) { - nv_wr32(priv, 0x400720, 0x00000000); - nv_wr32(priv, 0x400784, inst); - nv_mask(priv, 0x400310, 0x00000020, 0x00000020); - nv_mask(priv, 0x400304, 0x00000001, 0x00000001); - if (!nv_wait(priv, 0x400300, 0x00000001, 0x00000000)) { - u32 insn = nv_rd32(priv, 0x400308); - nv_warn(priv, "ctxprog timeout 0x%08x\n", insn); + nvkm_wr32(device, 0x400720, 0x00000000); + nvkm_wr32(device, 0x400784, inst); + nvkm_mask(device, 0x400310, 0x00000020, 0x00000020); + nvkm_mask(device, 0x400304, 0x00000001, 0x00000001); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x400300) & 0x00000001)) + break; + ) < 0) { + u32 insn = nvkm_rd32(device, 0x400308); + nvkm_warn(subdev, "ctxprog timeout %08x\n", insn); ret = -EBUSY; } } - nv_mask(priv, 0x40032c, 0x01000000, 0x00000000); + nvkm_mask(device, 0x40032c, 0x01000000, 0x00000000); } - if (nv_rd32(priv, 0x400330) == inst) - nv_mask(priv, 0x400330, 0x01000000, 0x00000000); + if (nvkm_rd32(device, 0x400330) == inst) + nvkm_mask(device, 0x400330, 0x01000000, 0x00000000); - nv_mask(priv, 0x400720, 0x00000001, 0x00000001); + nvkm_mask(device, 0x400720, 0x00000001, 0x00000001); return ret; } -static struct nvkm_oclass -nv40_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = nv40_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, +static void * +nv40_gr_chan_dtor(struct nvkm_object *object) +{ + struct nv40_gr_chan *chan = nv40_gr_chan(object); + unsigned long flags; + spin_lock_irqsave(&chan->gr->base.engine.lock, flags); + list_del(&chan->head); + spin_unlock_irqrestore(&chan->gr->base.engine.lock, flags); + return chan; +} + +static const struct nvkm_object_func +nv40_gr_chan = { + .dtor = nv40_gr_chan_dtor, + .fini = nv40_gr_chan_fini, + .bind = nv40_gr_chan_bind, }; +int +nv40_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) +{ + struct nv40_gr *gr = nv40_gr(base); + struct nv40_gr_chan *chan; + unsigned long flags; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv40_gr_chan, oclass, &chan->object); + chan->gr = gr; + chan->fifo = fifoch; + *pobject = &chan->object; + + spin_lock_irqsave(&chan->gr->base.engine.lock, flags); + list_add(&chan->head, &gr->chan); + spin_unlock_irqrestore(&chan->gr->base.engine.lock, flags); + return 0; +} + /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ static void -nv40_gr_tile_prog(struct nvkm_engine *engine, int i) +nv40_gr_tile(struct nvkm_gr *base, int i, struct nvkm_fb_tile *tile) { - struct nvkm_fb_tile *tile = &nvkm_fb(engine)->tile.region[i]; - struct nvkm_fifo *pfifo = nvkm_fifo(engine); - struct nv40_gr_priv *priv = (void *)engine; + struct nv40_gr *gr = nv40_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + struct nvkm_fifo *fifo = device->fifo; unsigned long flags; - pfifo->pause(pfifo, &flags); - nv04_gr_idle(priv); + nvkm_fifo_pause(fifo, &flags); + nv04_gr_idle(&gr->base); - switch (nv_device(priv)->chipset) { + switch (device->chipset) { case 0x40: case 0x41: case 0x42: case 0x43: case 0x45: - case 0x4e: - nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); - nv_wr32(priv, NV40_PGRAPH_TSIZE1(i), tile->pitch); - nv_wr32(priv, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(priv, NV40_PGRAPH_TILE1(i), tile->addr); - switch (nv_device(priv)->chipset) { + nvkm_wr32(device, NV20_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV20_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV20_PGRAPH_TILE(i), tile->addr); + nvkm_wr32(device, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nvkm_wr32(device, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nvkm_wr32(device, NV40_PGRAPH_TILE1(i), tile->addr); + switch (device->chipset) { case 0x40: case 0x45: - nv_wr32(priv, NV20_PGRAPH_ZCOMP(i), tile->zcomp); - nv_wr32(priv, NV40_PGRAPH_ZCOMP1(i), tile->zcomp); + nvkm_wr32(device, NV20_PGRAPH_ZCOMP(i), tile->zcomp); + nvkm_wr32(device, NV40_PGRAPH_ZCOMP1(i), tile->zcomp); break; case 0x41: case 0x42: case 0x43: - nv_wr32(priv, NV41_PGRAPH_ZCOMP0(i), tile->zcomp); - nv_wr32(priv, NV41_PGRAPH_ZCOMP1(i), tile->zcomp); + nvkm_wr32(device, NV41_PGRAPH_ZCOMP0(i), tile->zcomp); + nvkm_wr32(device, NV41_PGRAPH_ZCOMP1(i), tile->zcomp); break; default: break; } break; - case 0x44: - case 0x4a: - nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); - break; - case 0x46: - case 0x4c: case 0x47: case 0x49: case 0x4b: - case 0x63: - case 0x67: - case 0x68: - nv_wr32(priv, NV47_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(priv, NV47_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(priv, NV47_PGRAPH_TILE(i), tile->addr); - nv_wr32(priv, NV40_PGRAPH_TSIZE1(i), tile->pitch); - nv_wr32(priv, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(priv, NV40_PGRAPH_TILE1(i), tile->addr); - switch (nv_device(priv)->chipset) { - case 0x47: - case 0x49: - case 0x4b: - nv_wr32(priv, NV47_PGRAPH_ZCOMP0(i), tile->zcomp); - nv_wr32(priv, NV47_PGRAPH_ZCOMP1(i), tile->zcomp); - break; - default: - break; - } + nvkm_wr32(device, NV47_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV47_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV47_PGRAPH_TILE(i), tile->addr); + nvkm_wr32(device, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nvkm_wr32(device, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nvkm_wr32(device, NV40_PGRAPH_TILE1(i), tile->addr); + nvkm_wr32(device, NV47_PGRAPH_ZCOMP0(i), tile->zcomp); + nvkm_wr32(device, NV47_PGRAPH_ZCOMP1(i), tile->zcomp); break; default: + WARN_ON(1); break; } - pfifo->start(pfifo, &flags); + nvkm_fifo_start(fifo, &flags); } -static void -nv40_gr_intr(struct nvkm_subdev *subdev) +void +nv40_gr_intr(struct nvkm_gr *base) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct nvkm_handle *handle = NULL; - struct nv40_gr_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); - u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); - u32 inst = nv_rd32(priv, 0x40032c) & 0x000fffff; - u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + struct nv40_gr *gr = nv40_gr(base); + struct nv40_gr_chan *temp, *chan = NULL; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); + u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); + u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); + u32 inst = nvkm_rd32(device, 0x40032c) & 0x000fffff; + u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xffff; + u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nvkm_rd32(device, 0x400160 + subc * 4) & 0xffff; u32 show = stat; - int chid; - - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); + char msg[128], src[128], sta[128]; + unsigned long flags; - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - handle = nvkm_handle_get_class(engctx, class); - if (handle && !nv_call(handle->object, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - nvkm_handle_put(handle); + spin_lock_irqsave(&gr->base.engine.lock, flags); + list_for_each_entry(temp, &gr->chan, head) { + if (temp->inst >> 4 == inst) { + chan = temp; + list_del(&chan->head); + list_add(&chan->head, &gr->chan); + break; } + } + if (stat & NV_PGRAPH_INTR_ERROR) { if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { - nv_mask(priv, 0x402000, 0, 0); + nvkm_mask(device, 0x402000, 0, 0); } } - nv_wr32(priv, NV03_PGRAPH_INTR, stat); - nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + nvkm_wr32(device, NV03_PGRAPH_INTR, stat); + nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); - nvkm_bitfield_print(nv10_gr_intr_name, show); - pr_cont(" nsource:"); - nvkm_bitfield_print(nv04_gr_nsource, nsource); - pr_cont(" nstatus:"); - nvkm_bitfield_print(nv10_gr_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [0x%08x %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 4, nvkm_client_name(engctx), subc, - class, mthd, data); + nvkm_snprintbf(msg, sizeof(msg), nv10_gr_intr_name, show); + nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); + nvkm_snprintbf(sta, sizeof(sta), nv10_gr_nstatus, nstatus); + nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " + "nstatus %08x [%s] ch %d [%08x %s] subc %d " + "class %04x mthd %04x data %08x\n", + show, msg, nsource, src, nstatus, sta, + chan ? chan->fifo->chid : -1, inst << 4, + chan ? chan->fifo->object.client->name : "unknown", + subc, class, mthd, data); } - nvkm_engctx_put(engctx); + spin_unlock_irqrestore(&gr->base.engine.lock, flags); } -static int -nv40_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv40_gr_init(struct nvkm_gr *base) { - struct nv40_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00001000; - nv_subdev(priv)->intr = nv40_gr_intr; - nv_engine(priv)->cclass = &nv40_gr_cclass; - if (nv44_gr_class(priv)) - nv_engine(priv)->sclass = nv44_gr_sclass; - else - nv_engine(priv)->sclass = nv40_gr_sclass; - nv_engine(priv)->tile_prog = nv40_gr_tile_prog; - - priv->base.units = nv40_gr_units; - return 0; -} - -static int -nv40_gr_init(struct nvkm_object *object) -{ - struct nvkm_engine *engine = nv_engine(object); - struct nvkm_fb *pfb = nvkm_fb(object); - struct nv40_gr_priv *priv = (void *)engine; + struct nv40_gr *gr = nv40_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; int ret, i, j; u32 vramsz; - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; - /* generate and upload context program */ - ret = nv40_grctx_init(nv_device(priv), &priv->size); + ret = nv40_grctx_init(device, &gr->size); if (ret) return ret; /* No context present currently */ - nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + nvkm_wr32(device, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); - nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(priv, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); + nvkm_wr32(device, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nvkm_wr32(device, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); - nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xe0de8055); - nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); - nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xe0de8055); + nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00008000); + nvkm_wr32(device, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); - nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100); - nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nvkm_wr32(device, NV10_PGRAPH_STATE , 0xFFFFFFFF); - j = nv_rd32(priv, 0x1540) & 0xff; + j = nvkm_rd32(device, 0x1540) & 0xff; if (j) { for (i = 0; !(j & 1); j >>= 1, i++) ; - nv_wr32(priv, 0x405000, i); + nvkm_wr32(device, 0x405000, i); } - if (nv_device(priv)->chipset == 0x40) { - nv_wr32(priv, 0x4009b0, 0x83280fff); - nv_wr32(priv, 0x4009b4, 0x000000a0); + if (device->chipset == 0x40) { + nvkm_wr32(device, 0x4009b0, 0x83280fff); + nvkm_wr32(device, 0x4009b4, 0x000000a0); } else { - nv_wr32(priv, 0x400820, 0x83280eff); - nv_wr32(priv, 0x400824, 0x000000a0); + nvkm_wr32(device, 0x400820, 0x83280eff); + nvkm_wr32(device, 0x400824, 0x000000a0); } - switch (nv_device(priv)->chipset) { + switch (device->chipset) { case 0x40: case 0x45: - nv_wr32(priv, 0x4009b8, 0x0078e366); - nv_wr32(priv, 0x4009bc, 0x0000014c); + nvkm_wr32(device, 0x4009b8, 0x0078e366); + nvkm_wr32(device, 0x4009bc, 0x0000014c); break; case 0x41: case 0x42: /* pciid also 0x00Cx */ /* case 0x0120: XXX (pciid) */ - nv_wr32(priv, 0x400828, 0x007596ff); - nv_wr32(priv, 0x40082c, 0x00000108); + nvkm_wr32(device, 0x400828, 0x007596ff); + nvkm_wr32(device, 0x40082c, 0x00000108); break; case 0x43: - nv_wr32(priv, 0x400828, 0x0072cb77); - nv_wr32(priv, 0x40082c, 0x00000108); + nvkm_wr32(device, 0x400828, 0x0072cb77); + nvkm_wr32(device, 0x40082c, 0x00000108); break; case 0x44: case 0x46: /* G72 */ case 0x4a: case 0x4c: /* G7x-based C51 */ case 0x4e: - nv_wr32(priv, 0x400860, 0); - nv_wr32(priv, 0x400864, 0); + nvkm_wr32(device, 0x400860, 0); + nvkm_wr32(device, 0x400864, 0); break; case 0x47: /* G70 */ case 0x49: /* G71 */ case 0x4b: /* G73 */ - nv_wr32(priv, 0x400828, 0x07830610); - nv_wr32(priv, 0x40082c, 0x0000016A); + nvkm_wr32(device, 0x400828, 0x07830610); + nvkm_wr32(device, 0x40082c, 0x0000016A); break; default: break; } - nv_wr32(priv, 0x400b38, 0x2ffff800); - nv_wr32(priv, 0x400b3c, 0x00006000); + nvkm_wr32(device, 0x400b38, 0x2ffff800); + nvkm_wr32(device, 0x400b3c, 0x00006000); /* Tiling related stuff. */ - switch (nv_device(priv)->chipset) { + switch (device->chipset) { case 0x44: case 0x4a: - nv_wr32(priv, 0x400bc4, 0x1003d888); - nv_wr32(priv, 0x400bbc, 0xb7a7b500); + nvkm_wr32(device, 0x400bc4, 0x1003d888); + nvkm_wr32(device, 0x400bbc, 0xb7a7b500); break; case 0x46: - nv_wr32(priv, 0x400bc4, 0x0000e024); - nv_wr32(priv, 0x400bbc, 0xb7a7b520); + nvkm_wr32(device, 0x400bc4, 0x0000e024); + nvkm_wr32(device, 0x400bbc, 0xb7a7b520); break; case 0x4c: case 0x4e: case 0x67: - nv_wr32(priv, 0x400bc4, 0x1003d888); - nv_wr32(priv, 0x400bbc, 0xb7a7b540); + nvkm_wr32(device, 0x400bc4, 0x1003d888); + nvkm_wr32(device, 0x400bbc, 0xb7a7b540); break; default: break; } - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->tile.regions; i++) - engine->tile_prog(engine, i); - /* begin RAM config */ - vramsz = nv_device_resource_len(nv_device(priv), 0) - 1; - switch (nv_device(priv)->chipset) { + vramsz = device->func->resource_size(device, 1) - 1; + switch (device->chipset) { case 0x40: - nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); - nv_wr32(priv, 0x4069A4, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x4069A8, nv_rd32(priv, 0x100204)); - nv_wr32(priv, 0x400820, 0); - nv_wr32(priv, 0x400824, 0); - nv_wr32(priv, 0x400864, vramsz); - nv_wr32(priv, 0x400868, vramsz); + nvkm_wr32(device, 0x4009A4, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x4009A8, nvkm_rd32(device, 0x100204)); + nvkm_wr32(device, 0x4069A4, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x4069A8, nvkm_rd32(device, 0x100204)); + nvkm_wr32(device, 0x400820, 0); + nvkm_wr32(device, 0x400824, 0); + nvkm_wr32(device, 0x400864, vramsz); + nvkm_wr32(device, 0x400868, vramsz); break; default: - switch (nv_device(priv)->chipset) { + switch (device->chipset) { case 0x41: case 0x42: case 0x43: @@ -495,33 +407,70 @@ nv40_gr_init(struct nvkm_object *object) case 0x4e: case 0x44: case 0x4a: - nv_wr32(priv, 0x4009F0, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x4009F4, nv_rd32(priv, 0x100204)); + nvkm_wr32(device, 0x4009F0, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x4009F4, nvkm_rd32(device, 0x100204)); break; default: - nv_wr32(priv, 0x400DF0, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x400DF4, nv_rd32(priv, 0x100204)); + nvkm_wr32(device, 0x400DF0, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x400DF4, nvkm_rd32(device, 0x100204)); break; } - nv_wr32(priv, 0x4069F0, nv_rd32(priv, 0x100200)); - nv_wr32(priv, 0x4069F4, nv_rd32(priv, 0x100204)); - nv_wr32(priv, 0x400840, 0); - nv_wr32(priv, 0x400844, 0); - nv_wr32(priv, 0x4008A0, vramsz); - nv_wr32(priv, 0x4008A4, vramsz); + nvkm_wr32(device, 0x4069F0, nvkm_rd32(device, 0x100200)); + nvkm_wr32(device, 0x4069F4, nvkm_rd32(device, 0x100204)); + nvkm_wr32(device, 0x400840, 0); + nvkm_wr32(device, 0x400844, 0); + nvkm_wr32(device, 0x4008A0, vramsz); + nvkm_wr32(device, 0x4008A4, vramsz); break; } return 0; } -struct nvkm_oclass -nv40_gr_oclass = { - .handle = NV_ENGINE(GR, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_gr_ctor, - .dtor = _nvkm_gr_dtor, - .init = nv40_gr_init, - .fini = _nvkm_gr_fini, - }, +int +nv40_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device, + int index, struct nvkm_gr **pgr) +{ + struct nv40_gr *gr; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + *pgr = &gr->base; + INIT_LIST_HEAD(&gr->chan); + + return nvkm_gr_ctor(func, device, index, 0x00001000, true, &gr->base); +} + +static const struct nvkm_gr_func +nv40_gr = { + .init = nv40_gr_init, + .intr = nv40_gr_intr, + .tile = nv40_gr_tile, + .units = nv40_gr_units, + .chan_new = nv40_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv40_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv40_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv40_gr_object }, /* null */ + { -1, -1, 0x0039, &nv40_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv40_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv40_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv40_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv40_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv40_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv40_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv40_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv40_gr_object }, /* imageblit */ + { -1, -1, 0x3062, &nv40_gr_object }, /* surf2d (nv40) */ + { -1, -1, 0x3089, &nv40_gr_object }, /* sifm (nv40) */ + { -1, -1, 0x309e, &nv40_gr_object }, /* swzsurf (nv40) */ + { -1, -1, 0x4097, &nv40_gr_object }, /* curie */ + {} + } }; + +int +nv40_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv40_gr_new_(&nv40_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h index d852bd6de..2812ed11f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h @@ -1,22 +1,45 @@ #ifndef __NV40_GR_H__ #define __NV40_GR_H__ -#include +#define nv40_gr(p) container_of((p), struct nv40_gr, base) +#include "priv.h" -#include -struct nvkm_gpuobj; +struct nv40_gr { + struct nvkm_gr base; + u32 size; + struct list_head chan; +}; + +int nv40_gr_new_(const struct nvkm_gr_func *, struct nvkm_device *, int index, + struct nvkm_gr **); +int nv40_gr_init(struct nvkm_gr *); +void nv40_gr_intr(struct nvkm_gr *); +u64 nv40_gr_units(struct nvkm_gr *); + +#define nv40_gr_chan(p) container_of((p), struct nv40_gr_chan, object) + +struct nv40_gr_chan { + struct nvkm_object object; + struct nv40_gr *gr; + struct nvkm_fifo_chan *fifo; + u32 inst; + struct list_head head; +}; + +int nv40_gr_chan_new(struct nvkm_gr *, struct nvkm_fifo_chan *, + const struct nvkm_oclass *, struct nvkm_object **); + +extern const struct nvkm_object_func nv40_gr_object; /* returns 1 if device is one of the nv4x using the 0x4497 object class, * helpful to determine a number of other hardware features */ static inline int -nv44_gr_class(void *priv) +nv44_gr_class(struct nvkm_device *device) { - struct nvkm_device *device = nv_device(priv); - if ((device->chipset & 0xf0) == 0x60) return 1; - return !(0x0baf & (1 << (device->chipset & 0x0f))); + return !(0x0aaf & (1 << (device->chipset & 0x0f))); } int nv40_grctx_init(struct nvkm_device *, u32 *size); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv44.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv44.c new file mode 100644 index 000000000..45ff80254 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv44.c @@ -0,0 +1,108 @@ +/* + * 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 "nv40.h" +#include "regs.h" + +#include +#include + +static void +nv44_gr_tile(struct nvkm_gr *base, int i, struct nvkm_fb_tile *tile) +{ + struct nv40_gr *gr = nv40_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; + struct nvkm_fifo *fifo = device->fifo; + unsigned long flags; + + nvkm_fifo_pause(fifo, &flags); + nv04_gr_idle(&gr->base); + + switch (device->chipset) { + case 0x44: + case 0x4a: + nvkm_wr32(device, NV20_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV20_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV20_PGRAPH_TILE(i), tile->addr); + break; + case 0x46: + case 0x4c: + case 0x63: + case 0x67: + case 0x68: + nvkm_wr32(device, NV47_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV47_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV47_PGRAPH_TILE(i), tile->addr); + nvkm_wr32(device, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nvkm_wr32(device, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nvkm_wr32(device, NV40_PGRAPH_TILE1(i), tile->addr); + break; + case 0x4e: + nvkm_wr32(device, NV20_PGRAPH_TSIZE(i), tile->pitch); + nvkm_wr32(device, NV20_PGRAPH_TLIMIT(i), tile->limit); + nvkm_wr32(device, NV20_PGRAPH_TILE(i), tile->addr); + nvkm_wr32(device, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nvkm_wr32(device, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nvkm_wr32(device, NV40_PGRAPH_TILE1(i), tile->addr); + break; + default: + WARN_ON(1); + break; + } + + nvkm_fifo_start(fifo, &flags); +} + +static const struct nvkm_gr_func +nv44_gr = { + .init = nv40_gr_init, + .intr = nv40_gr_intr, + .tile = nv44_gr_tile, + .units = nv40_gr_units, + .chan_new = nv40_gr_chan_new, + .sclass = { + { -1, -1, 0x0012, &nv40_gr_object }, /* beta1 */ + { -1, -1, 0x0019, &nv40_gr_object }, /* clip */ + { -1, -1, 0x0030, &nv40_gr_object }, /* null */ + { -1, -1, 0x0039, &nv40_gr_object }, /* m2mf */ + { -1, -1, 0x0043, &nv40_gr_object }, /* rop */ + { -1, -1, 0x0044, &nv40_gr_object }, /* patt */ + { -1, -1, 0x004a, &nv40_gr_object }, /* gdi */ + { -1, -1, 0x0062, &nv40_gr_object }, /* surf2d */ + { -1, -1, 0x0072, &nv40_gr_object }, /* beta4 */ + { -1, -1, 0x0089, &nv40_gr_object }, /* sifm */ + { -1, -1, 0x008a, &nv40_gr_object }, /* ifc */ + { -1, -1, 0x009f, &nv40_gr_object }, /* imageblit */ + { -1, -1, 0x3062, &nv40_gr_object }, /* surf2d (nv40) */ + { -1, -1, 0x3089, &nv40_gr_object }, /* sifm (nv40) */ + { -1, -1, 0x309e, &nv40_gr_object }, /* swzsurf (nv40) */ + { -1, -1, 0x4497, &nv40_gr_object }, /* curie */ + {} + } +}; + +int +nv44_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv40_gr_new_(&nv44_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c index 270d7cd63..b19b912d5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c @@ -24,27 +24,13 @@ #include "nv50.h" #include -#include -#include +#include #include -#include -struct nv50_gr_priv { - struct nvkm_gr base; - spinlock_t lock; - u32 size; -}; - -struct nv50_gr_chan { - struct nvkm_gr_chan base; -}; - -static u64 +u64 nv50_gr_units(struct nvkm_gr *gr) { - struct nv50_gr_priv *priv = (void *)gr; - - return nv_rd32(priv, 0x1540); + return nvkm_rd32(gr->engine.subdev.device, 0x1540); } /******************************************************************************* @@ -52,86 +38,25 @@ nv50_gr_units(struct nvkm_gr *gr) ******************************************************************************/ static int -nv50_gr_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_gpuobj *obj; - int ret; - - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, - 16, 16, 0, &obj); - *pobject = nv_object(obj); - if (ret) - return ret; - - nv_wo32(obj, 0x00, nv_mclass(obj)); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - return 0; + int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16, + align, false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, object->oclass); + nvkm_wo32(*pgpuobj, 0x04, 0x00000000); + nvkm_wo32(*pgpuobj, 0x08, 0x00000000); + nvkm_wo32(*pgpuobj, 0x0c, 0x00000000); + nvkm_done(*pgpuobj); + } + return ret; } -static struct nvkm_ofuncs -nv50_gr_ofuncs = { - .ctor = nv50_gr_object_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, -}; - -static struct nvkm_oclass -nv50_gr_sclass[] = { - { 0x0030, &nv50_gr_ofuncs }, - { 0x502d, &nv50_gr_ofuncs }, - { 0x5039, &nv50_gr_ofuncs }, - { 0x5097, &nv50_gr_ofuncs }, - { 0x50c0, &nv50_gr_ofuncs }, - {} -}; - -static struct nvkm_oclass -g84_gr_sclass[] = { - { 0x0030, &nv50_gr_ofuncs }, - { 0x502d, &nv50_gr_ofuncs }, - { 0x5039, &nv50_gr_ofuncs }, - { 0x50c0, &nv50_gr_ofuncs }, - { 0x8297, &nv50_gr_ofuncs }, - {} -}; - -static struct nvkm_oclass -gt200_gr_sclass[] = { - { 0x0030, &nv50_gr_ofuncs }, - { 0x502d, &nv50_gr_ofuncs }, - { 0x5039, &nv50_gr_ofuncs }, - { 0x50c0, &nv50_gr_ofuncs }, - { 0x8397, &nv50_gr_ofuncs }, - {} -}; - -static struct nvkm_oclass -gt215_gr_sclass[] = { - { 0x0030, &nv50_gr_ofuncs }, - { 0x502d, &nv50_gr_ofuncs }, - { 0x5039, &nv50_gr_ofuncs }, - { 0x50c0, &nv50_gr_ofuncs }, - { 0x8597, &nv50_gr_ofuncs }, - { 0x85c0, &nv50_gr_ofuncs }, - {} -}; - -static struct nvkm_oclass -mcp89_gr_sclass[] = { - { 0x0030, &nv50_gr_ofuncs }, - { 0x502d, &nv50_gr_ofuncs }, - { 0x5039, &nv50_gr_ofuncs }, - { 0x50c0, &nv50_gr_ofuncs }, - { 0x85c0, &nv50_gr_ofuncs }, - { 0x8697, &nv50_gr_ofuncs }, - {} +const struct nvkm_object_func +nv50_gr_object = { + .bind = nv50_gr_object_bind, }; /******************************************************************************* @@ -139,160 +64,43 @@ mcp89_gr_sclass[] = { ******************************************************************************/ static int -nv50_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nv50_gr_priv *priv = (void *)engine; - struct nv50_gr_chan *chan; - int ret; - - ret = nvkm_gr_context_create(parent, engine, oclass, NULL, priv->size, - 0, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - nv50_grctx_fill(nv_device(priv), nv_gpuobj(chan)); - return 0; + struct nv50_gr *gr = nv50_gr_chan(object)->gr; + int ret = nvkm_gpuobj_new(gr->base.engine.subdev.device, gr->size, + align, true, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nv50_grctx_fill(gr->base.engine.subdev.device, *pgpuobj); + nvkm_done(*pgpuobj); + } + return ret; } -static struct nvkm_oclass -nv50_gr_cclass = { - .handle = NV_ENGCTX(GR, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_gr_context_ctor, - .dtor = _nvkm_gr_context_dtor, - .init = _nvkm_gr_context_init, - .fini = _nvkm_gr_context_fini, - .rd32 = _nvkm_gr_context_rd32, - .wr32 = _nvkm_gr_context_wr32, - }, -}; - -/******************************************************************************* - * PGRAPH engine/subdev functions - ******************************************************************************/ - -static const struct nvkm_bitfield nv50_pgr_status[] = { - { 0x00000001, "BUSY" }, /* set when any bit is set */ - { 0x00000002, "DISPATCH" }, - { 0x00000004, "UNK2" }, - { 0x00000008, "UNK3" }, - { 0x00000010, "UNK4" }, - { 0x00000020, "UNK5" }, - { 0x00000040, "M2MF" }, - { 0x00000080, "UNK7" }, - { 0x00000100, "CTXPROG" }, - { 0x00000200, "VFETCH" }, - { 0x00000400, "CCACHE_PREGEOM" }, - { 0x00000800, "STRMOUT_VATTR_POSTGEOM" }, - { 0x00001000, "VCLIP" }, - { 0x00002000, "RATTR_APLANE" }, - { 0x00004000, "TRAST" }, - { 0x00008000, "CLIPID" }, - { 0x00010000, "ZCULL" }, - { 0x00020000, "ENG2D" }, - { 0x00040000, "RMASK" }, - { 0x00080000, "TPC_RAST" }, - { 0x00100000, "TPC_PROP" }, - { 0x00200000, "TPC_TEX" }, - { 0x00400000, "TPC_GEOM" }, - { 0x00800000, "TPC_MP" }, - { 0x01000000, "ROP" }, - {} -}; - -static const char *const nv50_pgr_vstatus_0[] = { - "VFETCH", "CCACHE", "PREGEOM", "POSTGEOM", "VATTR", "STRMOUT", "VCLIP", - NULL -}; - -static const char *const nv50_pgr_vstatus_1[] = { - "TPC_RAST", "TPC_PROP", "TPC_TEX", "TPC_GEOM", "TPC_MP", NULL -}; - -static const char *const nv50_pgr_vstatus_2[] = { - "RATTR", "APLANE", "TRAST", "CLIPID", "ZCULL", "ENG2D", "RMASK", - "ROP", NULL +static const struct nvkm_object_func +nv50_gr_chan = { + .bind = nv50_gr_chan_bind, }; -static void -nvkm_pgr_vstatus_print(struct nv50_gr_priv *priv, int r, - const char *const units[], u32 status) +int +nv50_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - int i; - - nv_error(priv, "PGRAPH_VSTATUS%d: 0x%08x", r, status); + struct nv50_gr *gr = nv50_gr(base); + struct nv50_gr_chan *chan; - for (i = 0; units[i] && status; i++) { - if ((status & 7) == 1) - pr_cont(" %s", units[i]); - status >>= 3; - } - if (status) - pr_cont(" (invalid: 0x%x)", status); - pr_cont("\n"); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv50_gr_chan, oclass, &chan->object); + chan->gr = gr; + *pobject = &chan->object; + return 0; } -static int -g84_gr_tlb_flush(struct nvkm_engine *engine) -{ - struct nvkm_timer *ptimer = nvkm_timer(engine); - struct nv50_gr_priv *priv = (void *)engine; - bool idle, timeout = false; - unsigned long flags; - u64 start; - u32 tmp; - - spin_lock_irqsave(&priv->lock, flags); - nv_mask(priv, 0x400500, 0x00000001, 0x00000000); - - start = ptimer->read(ptimer); - do { - idle = true; - - for (tmp = nv_rd32(priv, 0x400380); tmp && idle; tmp >>= 3) { - if ((tmp & 7) == 1) - idle = false; - } - - for (tmp = nv_rd32(priv, 0x400384); tmp && idle; tmp >>= 3) { - if ((tmp & 7) == 1) - idle = false; - } - - for (tmp = nv_rd32(priv, 0x400388); tmp && idle; tmp >>= 3) { - if ((tmp & 7) == 1) - idle = false; - } - } while (!idle && - !(timeout = ptimer->read(ptimer) - start > 2000000000)); - - if (timeout) { - nv_error(priv, "PGRAPH TLB flush idle timeout fail\n"); - - tmp = nv_rd32(priv, 0x400700); - nv_error(priv, "PGRAPH_STATUS : 0x%08x", tmp); - nvkm_bitfield_print(nv50_pgr_status, tmp); - pr_cont("\n"); - - nvkm_pgr_vstatus_print(priv, 0, nv50_pgr_vstatus_0, - nv_rd32(priv, 0x400380)); - nvkm_pgr_vstatus_print(priv, 1, nv50_pgr_vstatus_1, - nv_rd32(priv, 0x400384)); - nvkm_pgr_vstatus_print(priv, 2, nv50_pgr_vstatus_2, - nv_rd32(priv, 0x400388)); - } - - - nv_wr32(priv, 0x100c80, 0x00000001); - if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000)) - nv_error(priv, "vm flush timeout\n"); - nv_mask(priv, 0x400500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&priv->lock, flags); - return timeout ? -EBUSY : 0; -} +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ static const struct nvkm_bitfield nv50_mp_exec_errors[] = { { 0x01, "STACK_UNDERFLOW" }, @@ -427,157 +235,172 @@ static const struct nvkm_bitfield nv50_gr_trap_prop[] = { }; static void -nv50_priv_prop_trap(struct nv50_gr_priv *priv, - u32 ustatus_addr, u32 ustatus, u32 tp) +nv50_gr_prop_trap(struct nv50_gr *gr, u32 ustatus_addr, u32 ustatus, u32 tp) { - u32 e0c = nv_rd32(priv, ustatus_addr + 0x04); - u32 e10 = nv_rd32(priv, ustatus_addr + 0x08); - u32 e14 = nv_rd32(priv, ustatus_addr + 0x0c); - u32 e18 = nv_rd32(priv, ustatus_addr + 0x10); - u32 e1c = nv_rd32(priv, ustatus_addr + 0x14); - u32 e20 = nv_rd32(priv, ustatus_addr + 0x18); - u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 e0c = nvkm_rd32(device, ustatus_addr + 0x04); + u32 e10 = nvkm_rd32(device, ustatus_addr + 0x08); + u32 e14 = nvkm_rd32(device, ustatus_addr + 0x0c); + u32 e18 = nvkm_rd32(device, ustatus_addr + 0x10); + u32 e1c = nvkm_rd32(device, ustatus_addr + 0x14); + u32 e20 = nvkm_rd32(device, ustatus_addr + 0x18); + u32 e24 = nvkm_rd32(device, ustatus_addr + 0x1c); + char msg[128]; /* CUDA memory: l[], g[] or stack. */ if (ustatus & 0x00000080) { if (e18 & 0x80000000) { /* g[] read fault? */ - nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n", + nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n", tp, e14, e10 | ((e18 >> 24) & 0x1f)); e18 &= ~0x1f000000; } else if (e18 & 0xc) { /* g[] write fault? */ - nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n", + nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n", tp, e14, e10 | ((e18 >> 7) & 0x1f)); e18 &= ~0x00000f80; } else { - nv_error(priv, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n", + nvkm_error(subdev, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n", tp, e14, e10); } ustatus &= ~0x00000080; } if (ustatus) { - nv_error(priv, "TRAP_PROP - TP %d -", tp); - nvkm_bitfield_print(nv50_gr_trap_prop, ustatus); - pr_cont(" - Address %02x%08x\n", e14, e10); + nvkm_snprintbf(msg, sizeof(msg), nv50_gr_trap_prop, ustatus); + nvkm_error(subdev, "TRAP_PROP - TP %d - %08x [%s] - " + "Address %02x%08x\n", + tp, ustatus, msg, e14, e10); } - nv_error(priv, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nvkm_error(subdev, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", tp, e0c, e18, e1c, e20, e24); } static void -nv50_priv_mp_trap(struct nv50_gr_priv *priv, int tpid, int display) +nv50_gr_mp_trap(struct nv50_gr *gr, int tpid, int display) { - u32 units = nv_rd32(priv, 0x1540); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 units = nvkm_rd32(device, 0x1540); u32 addr, mp10, status, pc, oplow, ophigh; + char msg[128]; int i; int mps = 0; for (i = 0; i < 4; i++) { if (!(units & 1 << (i+24))) continue; - if (nv_device(priv)->chipset < 0xa0) + if (device->chipset < 0xa0) addr = 0x408200 + (tpid << 12) + (i << 7); else addr = 0x408100 + (tpid << 11) + (i << 7); - mp10 = nv_rd32(priv, addr + 0x10); - status = nv_rd32(priv, addr + 0x14); + mp10 = nvkm_rd32(device, addr + 0x10); + status = nvkm_rd32(device, addr + 0x14); if (!status) continue; if (display) { - nv_rd32(priv, addr + 0x20); - pc = nv_rd32(priv, addr + 0x24); - oplow = nv_rd32(priv, addr + 0x70); - ophigh = nv_rd32(priv, addr + 0x74); - nv_error(priv, "TRAP_MP_EXEC - " - "TP %d MP %d:", tpid, i); - nvkm_bitfield_print(nv50_mp_exec_errors, status); - pr_cont(" at %06x warp %d, opcode %08x %08x\n", - pc&0xffffff, pc >> 24, - oplow, ophigh); + nvkm_rd32(device, addr + 0x20); + pc = nvkm_rd32(device, addr + 0x24); + oplow = nvkm_rd32(device, addr + 0x70); + ophigh = nvkm_rd32(device, addr + 0x74); + nvkm_snprintbf(msg, sizeof(msg), + nv50_mp_exec_errors, status); + nvkm_error(subdev, "TRAP_MP_EXEC - TP %d MP %d: " + "%08x [%s] at %06x warp %d, " + "opcode %08x %08x\n", + tpid, i, status, msg, pc & 0xffffff, + pc >> 24, oplow, ophigh); } - nv_wr32(priv, addr + 0x10, mp10); - nv_wr32(priv, addr + 0x14, 0); + nvkm_wr32(device, addr + 0x10, mp10); + nvkm_wr32(device, addr + 0x14, 0); mps++; } if (!mps && display) - nv_error(priv, "TRAP_MP_EXEC - TP %d: " + nvkm_error(subdev, "TRAP_MP_EXEC - TP %d: " "No MPs claiming errors?\n", tpid); } static void -nv50_priv_tp_trap(struct nv50_gr_priv *priv, int type, u32 ustatus_old, +nv50_gr_tp_trap(struct nv50_gr *gr, int type, u32 ustatus_old, u32 ustatus_new, int display, const char *name) { + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 units = nvkm_rd32(device, 0x1540); int tps = 0; - u32 units = nv_rd32(priv, 0x1540); int i, r; + char msg[128]; u32 ustatus_addr, ustatus; for (i = 0; i < 16; i++) { if (!(units & (1 << i))) continue; - if (nv_device(priv)->chipset < 0xa0) + if (device->chipset < 0xa0) ustatus_addr = ustatus_old + (i << 12); else ustatus_addr = ustatus_new + (i << 11); - ustatus = nv_rd32(priv, ustatus_addr) & 0x7fffffff; + ustatus = nvkm_rd32(device, ustatus_addr) & 0x7fffffff; if (!ustatus) continue; tps++; switch (type) { case 6: /* texture error... unknown for now */ if (display) { - nv_error(priv, "magic set %d:\n", i); + nvkm_error(subdev, "magic set %d:\n", i); for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) - nv_error(priv, "\t0x%08x: 0x%08x\n", r, - nv_rd32(priv, r)); + nvkm_error(subdev, "\t%08x: %08x\n", r, + nvkm_rd32(device, r)); if (ustatus) { - nv_error(priv, "%s - TP%d:", name, i); - nvkm_bitfield_print(nv50_tex_traps, - ustatus); - pr_cont("\n"); + nvkm_snprintbf(msg, sizeof(msg), + nv50_tex_traps, ustatus); + nvkm_error(subdev, + "%s - TP%d: %08x [%s]\n", + name, i, ustatus, msg); ustatus = 0; } } break; case 7: /* MP error */ if (ustatus & 0x04030000) { - nv50_priv_mp_trap(priv, i, display); + nv50_gr_mp_trap(gr, i, display); ustatus &= ~0x04030000; } if (ustatus && display) { - nv_error(priv, "%s - TP%d:", name, i); - nvkm_bitfield_print(nv50_mpc_traps, ustatus); - pr_cont("\n"); + nvkm_snprintbf(msg, sizeof(msg), + nv50_mpc_traps, ustatus); + nvkm_error(subdev, "%s - TP%d: %08x [%s]\n", + name, i, ustatus, msg); ustatus = 0; } break; case 8: /* PROP error */ if (display) - nv50_priv_prop_trap( - priv, ustatus_addr, ustatus, i); + nv50_gr_prop_trap( + gr, ustatus_addr, ustatus, i); ustatus = 0; break; } if (ustatus) { if (display) - nv_error(priv, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); + nvkm_error(subdev, "%s - TP%d: Unhandled ustatus %08x\n", name, i, ustatus); } - nv_wr32(priv, ustatus_addr, 0xc0000000); + nvkm_wr32(device, ustatus_addr, 0xc0000000); } if (!tps && display) - nv_warn(priv, "%s - No TPs claiming errors?\n", name); + nvkm_warn(subdev, "%s - No TPs claiming errors?\n", name); } static int -nv50_gr_trap_handler(struct nv50_gr_priv *priv, u32 display, - int chid, u64 inst, struct nvkm_object *engctx) +nv50_gr_trap_handler(struct nv50_gr *gr, u32 display, + int chid, u64 inst, const char *name) { - u32 status = nv_rd32(priv, 0x400108); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 status = nvkm_rd32(device, 0x400108); u32 ustatus; + char msg[128]; if (!status && display) { - nv_error(priv, "TRAP: no units reporting traps?\n"); + nvkm_error(subdev, "TRAP: no units reporting traps?\n"); return 1; } @@ -585,71 +408,72 @@ nv50_gr_trap_handler(struct nv50_gr_priv *priv, u32 display, * COND, QUERY. If you get a trap from it, the command is still stuck * in DISPATCH and you need to do something about it. */ if (status & 0x001) { - ustatus = nv_rd32(priv, 0x400804) & 0x7fffffff; + ustatus = nvkm_rd32(device, 0x400804) & 0x7fffffff; if (!ustatus && display) { - nv_error(priv, "TRAP_DISPATCH - no ustatus?\n"); + nvkm_error(subdev, "TRAP_DISPATCH - no ustatus?\n"); } - nv_wr32(priv, 0x400500, 0x00000000); + nvkm_wr32(device, 0x400500, 0x00000000); /* Known to be triggered by screwed up NOTIFY and COND... */ if (ustatus & 0x00000001) { - u32 addr = nv_rd32(priv, 0x400808); + u32 addr = nvkm_rd32(device, 0x400808); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 datal = nv_rd32(priv, 0x40080c); - u32 datah = nv_rd32(priv, 0x400810); - u32 class = nv_rd32(priv, 0x400814); - u32 r848 = nv_rd32(priv, 0x400848); + u32 datal = nvkm_rd32(device, 0x40080c); + u32 datah = nvkm_rd32(device, 0x400810); + u32 class = nvkm_rd32(device, 0x400814); + u32 r848 = nvkm_rd32(device, 0x400848); - nv_error(priv, "TRAP DISPATCH_FAULT\n"); + nvkm_error(subdev, "TRAP DISPATCH_FAULT\n"); if (display && (addr & 0x80000000)) { - nv_error(priv, - "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x%08x 400808 0x%08x 400848 0x%08x\n", - chid, inst, - nvkm_client_name(engctx), subc, - class, mthd, datah, datal, addr, r848); + nvkm_error(subdev, + "ch %d [%010llx %s] subc %d " + "class %04x mthd %04x data %08x%08x " + "400808 %08x 400848 %08x\n", + chid, inst, name, subc, class, mthd, + datah, datal, addr, r848); } else if (display) { - nv_error(priv, "no stuck command?\n"); + nvkm_error(subdev, "no stuck command?\n"); } - nv_wr32(priv, 0x400808, 0); - nv_wr32(priv, 0x4008e8, nv_rd32(priv, 0x4008e8) & 3); - nv_wr32(priv, 0x400848, 0); + nvkm_wr32(device, 0x400808, 0); + nvkm_wr32(device, 0x4008e8, nvkm_rd32(device, 0x4008e8) & 3); + nvkm_wr32(device, 0x400848, 0); ustatus &= ~0x00000001; } if (ustatus & 0x00000002) { - u32 addr = nv_rd32(priv, 0x40084c); + u32 addr = nvkm_rd32(device, 0x40084c); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(priv, 0x40085c); - u32 class = nv_rd32(priv, 0x400814); + u32 data = nvkm_rd32(device, 0x40085c); + u32 class = nvkm_rd32(device, 0x400814); - nv_error(priv, "TRAP DISPATCH_QUERY\n"); + nvkm_error(subdev, "TRAP DISPATCH_QUERY\n"); if (display && (addr & 0x80000000)) { - nv_error(priv, - "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x 40084c 0x%08x\n", - chid, inst, - nvkm_client_name(engctx), subc, - class, mthd, data, addr); + nvkm_error(subdev, + "ch %d [%010llx %s] subc %d " + "class %04x mthd %04x data %08x " + "40084c %08x\n", chid, inst, name, + subc, class, mthd, data, addr); } else if (display) { - nv_error(priv, "no stuck command?\n"); + nvkm_error(subdev, "no stuck command?\n"); } - nv_wr32(priv, 0x40084c, 0); + nvkm_wr32(device, 0x40084c, 0); ustatus &= ~0x00000002; } if (ustatus && display) { - nv_error(priv, "TRAP_DISPATCH (unknown " - "0x%08x)\n", ustatus); + nvkm_error(subdev, "TRAP_DISPATCH " + "(unknown %08x)\n", ustatus); } - nv_wr32(priv, 0x400804, 0xc0000000); - nv_wr32(priv, 0x400108, 0x001); + nvkm_wr32(device, 0x400804, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x001); status &= ~0x001; if (!status) return 0; @@ -657,81 +481,91 @@ nv50_gr_trap_handler(struct nv50_gr_priv *priv, u32 display, /* M2MF: Memory to memory copy engine. */ if (status & 0x002) { - u32 ustatus = nv_rd32(priv, 0x406800) & 0x7fffffff; + u32 ustatus = nvkm_rd32(device, 0x406800) & 0x7fffffff; if (display) { - nv_error(priv, "TRAP_M2MF"); - nvkm_bitfield_print(nv50_gr_trap_m2mf, ustatus); - pr_cont("\n"); - nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n", - nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808), - nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810)); - + nvkm_snprintbf(msg, sizeof(msg), + nv50_gr_trap_m2mf, ustatus); + nvkm_error(subdev, "TRAP_M2MF %08x [%s]\n", + ustatus, msg); + nvkm_error(subdev, "TRAP_M2MF %08x %08x %08x %08x\n", + nvkm_rd32(device, 0x406804), + nvkm_rd32(device, 0x406808), + nvkm_rd32(device, 0x40680c), + nvkm_rd32(device, 0x406810)); } /* No sane way found yet -- just reset the bugger. */ - nv_wr32(priv, 0x400040, 2); - nv_wr32(priv, 0x400040, 0); - nv_wr32(priv, 0x406800, 0xc0000000); - nv_wr32(priv, 0x400108, 0x002); + nvkm_wr32(device, 0x400040, 2); + nvkm_wr32(device, 0x400040, 0); + nvkm_wr32(device, 0x406800, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x002); status &= ~0x002; } /* VFETCH: Fetches data from vertex buffers. */ if (status & 0x004) { - u32 ustatus = nv_rd32(priv, 0x400c04) & 0x7fffffff; + u32 ustatus = nvkm_rd32(device, 0x400c04) & 0x7fffffff; if (display) { - nv_error(priv, "TRAP_VFETCH"); - nvkm_bitfield_print(nv50_gr_trap_vfetch, ustatus); - pr_cont("\n"); - nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n", - nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08), - nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10)); + nvkm_snprintbf(msg, sizeof(msg), + nv50_gr_trap_vfetch, ustatus); + nvkm_error(subdev, "TRAP_VFETCH %08x [%s]\n", + ustatus, msg); + nvkm_error(subdev, "TRAP_VFETCH %08x %08x %08x %08x\n", + nvkm_rd32(device, 0x400c00), + nvkm_rd32(device, 0x400c08), + nvkm_rd32(device, 0x400c0c), + nvkm_rd32(device, 0x400c10)); } - nv_wr32(priv, 0x400c04, 0xc0000000); - nv_wr32(priv, 0x400108, 0x004); + nvkm_wr32(device, 0x400c04, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x004); status &= ~0x004; } /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ if (status & 0x008) { - ustatus = nv_rd32(priv, 0x401800) & 0x7fffffff; + ustatus = nvkm_rd32(device, 0x401800) & 0x7fffffff; if (display) { - nv_error(priv, "TRAP_STRMOUT"); - nvkm_bitfield_print(nv50_gr_trap_strmout, ustatus); - pr_cont("\n"); - nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n", - nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808), - nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810)); - + nvkm_snprintbf(msg, sizeof(msg), + nv50_gr_trap_strmout, ustatus); + nvkm_error(subdev, "TRAP_STRMOUT %08x [%s]\n", + ustatus, msg); + nvkm_error(subdev, "TRAP_STRMOUT %08x %08x %08x %08x\n", + nvkm_rd32(device, 0x401804), + nvkm_rd32(device, 0x401808), + nvkm_rd32(device, 0x40180c), + nvkm_rd32(device, 0x401810)); } /* No sane way found yet -- just reset the bugger. */ - nv_wr32(priv, 0x400040, 0x80); - nv_wr32(priv, 0x400040, 0); - nv_wr32(priv, 0x401800, 0xc0000000); - nv_wr32(priv, 0x400108, 0x008); + nvkm_wr32(device, 0x400040, 0x80); + nvkm_wr32(device, 0x400040, 0); + nvkm_wr32(device, 0x401800, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x008); status &= ~0x008; } /* CCACHE: Handles code and c[] caches and fills them. */ if (status & 0x010) { - ustatus = nv_rd32(priv, 0x405018) & 0x7fffffff; + ustatus = nvkm_rd32(device, 0x405018) & 0x7fffffff; if (display) { - nv_error(priv, "TRAP_CCACHE"); - nvkm_bitfield_print(nv50_gr_trap_ccache, ustatus); - pr_cont("\n"); - nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x" - " %08x %08x %08x\n", - nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004), - nv_rd32(priv, 0x405008), nv_rd32(priv, 0x40500c), - nv_rd32(priv, 0x405010), nv_rd32(priv, 0x405014), - nv_rd32(priv, 0x40501c)); - + nvkm_snprintbf(msg, sizeof(msg), + nv50_gr_trap_ccache, ustatus); + nvkm_error(subdev, "TRAP_CCACHE %08x [%s]\n", + ustatus, msg); + nvkm_error(subdev, "TRAP_CCACHE %08x %08x %08x %08x " + "%08x %08x %08x\n", + nvkm_rd32(device, 0x405000), + nvkm_rd32(device, 0x405004), + nvkm_rd32(device, 0x405008), + nvkm_rd32(device, 0x40500c), + nvkm_rd32(device, 0x405010), + nvkm_rd32(device, 0x405014), + nvkm_rd32(device, 0x40501c)); } - nv_wr32(priv, 0x405018, 0xc0000000); - nv_wr32(priv, 0x400108, 0x010); + nvkm_wr32(device, 0x405018, 0xc0000000); + nvkm_wr32(device, 0x400108, 0x010); status &= ~0x010; } @@ -739,239 +573,174 @@ nv50_gr_trap_handler(struct nv50_gr_priv *priv, u32 display, * remaining, so try to handle it anyway. Perhaps related to that * unknown DMA slot on tesla? */ if (status & 0x20) { - ustatus = nv_rd32(priv, 0x402000) & 0x7fffffff; + ustatus = nvkm_rd32(device, 0x402000) & 0x7fffffff; if (display) - nv_error(priv, "TRAP_UNKC04 0x%08x\n", ustatus); - nv_wr32(priv, 0x402000, 0xc0000000); + nvkm_error(subdev, "TRAP_UNKC04 %08x\n", ustatus); + nvkm_wr32(device, 0x402000, 0xc0000000); /* no status modifiction on purpose */ } /* TEXTURE: CUDA texturing units */ if (status & 0x040) { - nv50_priv_tp_trap(priv, 6, 0x408900, 0x408600, display, + nv50_gr_tp_trap(gr, 6, 0x408900, 0x408600, display, "TRAP_TEXTURE"); - nv_wr32(priv, 0x400108, 0x040); + nvkm_wr32(device, 0x400108, 0x040); status &= ~0x040; } /* MP: CUDA execution engines. */ if (status & 0x080) { - nv50_priv_tp_trap(priv, 7, 0x408314, 0x40831c, display, + nv50_gr_tp_trap(gr, 7, 0x408314, 0x40831c, display, "TRAP_MP"); - nv_wr32(priv, 0x400108, 0x080); + nvkm_wr32(device, 0x400108, 0x080); status &= ~0x080; } /* PROP: Handles TP-initiated uncached memory accesses: * l[], g[], stack, 2d surfaces, render targets. */ if (status & 0x100) { - nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display, + nv50_gr_tp_trap(gr, 8, 0x408e08, 0x408708, display, "TRAP_PROP"); - nv_wr32(priv, 0x400108, 0x100); + nvkm_wr32(device, 0x400108, 0x100); status &= ~0x100; } if (status) { if (display) - nv_error(priv, "TRAP: unknown 0x%08x\n", status); - nv_wr32(priv, 0x400108, status); + nvkm_error(subdev, "TRAP: unknown %08x\n", status); + nvkm_wr32(device, 0x400108, status); } return 1; } -static void -nv50_gr_intr(struct nvkm_subdev *subdev) +void +nv50_gr_intr(struct nvkm_gr *base) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct nvkm_handle *handle = NULL; - struct nv50_gr_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, 0x400100); - u32 inst = nv_rd32(priv, 0x40032c) & 0x0fffffff; - u32 addr = nv_rd32(priv, 0x400704); + struct nv50_gr *gr = nv50_gr(base); + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_fifo_chan *chan; + u32 stat = nvkm_rd32(device, 0x400100); + u32 inst = nvkm_rd32(device, 0x40032c) & 0x0fffffff; + u32 addr = nvkm_rd32(device, 0x400704); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(priv, 0x400708); - u32 class = nv_rd32(priv, 0x400814); + u32 data = nvkm_rd32(device, 0x400708); + u32 class = nvkm_rd32(device, 0x400814); u32 show = stat, show_bitfield = stat; - int chid; - - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); - - if (stat & 0x00000010) { - handle = nvkm_handle_get_class(engctx, class); - if (handle && !nv_call(handle->object, mthd, data)) - show &= ~0x00000010; - nvkm_handle_put(handle); + const struct nvkm_enum *en; + unsigned long flags; + const char *name = "unknown"; + char msg[128]; + int chid = -1; + + chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags); + if (chan) { + name = chan->object.client->name; + chid = chan->chid; } if (show & 0x00100000) { - u32 ecode = nv_rd32(priv, 0x400110); - nv_error(priv, "DATA_ERROR "); - nvkm_enum_print(nv50_data_error_names, ecode); - pr_cont("\n"); + u32 ecode = nvkm_rd32(device, 0x400110); + en = nvkm_enum_find(nv50_data_error_names, ecode); + nvkm_error(subdev, "DATA_ERROR %08x [%s]\n", + ecode, en ? en->name : ""); show_bitfield &= ~0x00100000; } if (stat & 0x00200000) { - if (!nv50_gr_trap_handler(priv, show, chid, (u64)inst << 12, - engctx)) + if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, name)) show &= ~0x00200000; show_bitfield &= ~0x00200000; } - nv_wr32(priv, 0x400100, stat); - nv_wr32(priv, 0x400500, 0x00010001); + nvkm_wr32(device, 0x400100, stat); + nvkm_wr32(device, 0x400500, 0x00010001); if (show) { show &= show_bitfield; - if (show) { - nv_error(priv, "%s", ""); - nvkm_bitfield_print(nv50_gr_intr_name, show); - pr_cont("\n"); - } - nv_error(priv, - "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, (u64)inst << 12, nvkm_client_name(engctx), - subc, class, mthd, data); + nvkm_snprintbf(msg, sizeof(msg), nv50_gr_intr_name, show); + nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] subc %d " + "class %04x mthd %04x data %08x\n", + stat, msg, chid, (u64)inst << 12, name, + subc, class, mthd, data); } - if (nv_rd32(priv, 0x400824) & (1 << 31)) - nv_wr32(priv, 0x400824, nv_rd32(priv, 0x400824) & ~(1 << 31)); + if (nvkm_rd32(device, 0x400824) & (1 << 31)) + nvkm_wr32(device, 0x400824, nvkm_rd32(device, 0x400824) & ~(1 << 31)); - nvkm_engctx_put(engctx); + nvkm_fifo_chan_put(device->fifo, flags, &chan); } -static int -nv50_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv50_gr_init(struct nvkm_gr *base) { - struct nv50_gr_priv *priv; - int ret; - - ret = nvkm_gr_create(parent, engine, oclass, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00201000; - nv_subdev(priv)->intr = nv50_gr_intr; - nv_engine(priv)->cclass = &nv50_gr_cclass; - - priv->base.units = nv50_gr_units; - - switch (nv_device(priv)->chipset) { - case 0x50: - nv_engine(priv)->sclass = nv50_gr_sclass; - break; - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - nv_engine(priv)->sclass = g84_gr_sclass; - break; - case 0xa0: - case 0xaa: - case 0xac: - nv_engine(priv)->sclass = gt200_gr_sclass; - break; - case 0xa3: - case 0xa5: - case 0xa8: - nv_engine(priv)->sclass = gt215_gr_sclass; - break; - case 0xaf: - nv_engine(priv)->sclass = mcp89_gr_sclass; - break; - - } - - /* unfortunate hw bug workaround... */ - if (nv_device(priv)->chipset != 0x50 && - nv_device(priv)->chipset != 0xac) - nv_engine(priv)->tlb_flush = g84_gr_tlb_flush; - - spin_lock_init(&priv->lock); - return 0; -} - -static int -nv50_gr_init(struct nvkm_object *object) -{ - struct nv50_gr_priv *priv = (void *)object; + struct nv50_gr *gr = nv50_gr(base); + struct nvkm_device *device = gr->base.engine.subdev.device; int ret, units, i; - ret = nvkm_gr_init(&priv->base); - if (ret) - return ret; - /* NV_PGRAPH_DEBUG_3_HW_CTX_SWITCH_ENABLED */ - nv_wr32(priv, 0x40008c, 0x00000004); + nvkm_wr32(device, 0x40008c, 0x00000004); /* reset/enable traps and interrupts */ - nv_wr32(priv, 0x400804, 0xc0000000); - nv_wr32(priv, 0x406800, 0xc0000000); - nv_wr32(priv, 0x400c04, 0xc0000000); - nv_wr32(priv, 0x401800, 0xc0000000); - nv_wr32(priv, 0x405018, 0xc0000000); - nv_wr32(priv, 0x402000, 0xc0000000); - - units = nv_rd32(priv, 0x001540); + nvkm_wr32(device, 0x400804, 0xc0000000); + nvkm_wr32(device, 0x406800, 0xc0000000); + nvkm_wr32(device, 0x400c04, 0xc0000000); + nvkm_wr32(device, 0x401800, 0xc0000000); + nvkm_wr32(device, 0x405018, 0xc0000000); + nvkm_wr32(device, 0x402000, 0xc0000000); + + units = nvkm_rd32(device, 0x001540); for (i = 0; i < 16; i++) { if (!(units & (1 << i))) continue; - if (nv_device(priv)->chipset < 0xa0) { - nv_wr32(priv, 0x408900 + (i << 12), 0xc0000000); - nv_wr32(priv, 0x408e08 + (i << 12), 0xc0000000); - nv_wr32(priv, 0x408314 + (i << 12), 0xc0000000); + if (device->chipset < 0xa0) { + nvkm_wr32(device, 0x408900 + (i << 12), 0xc0000000); + nvkm_wr32(device, 0x408e08 + (i << 12), 0xc0000000); + nvkm_wr32(device, 0x408314 + (i << 12), 0xc0000000); } else { - nv_wr32(priv, 0x408600 + (i << 11), 0xc0000000); - nv_wr32(priv, 0x408708 + (i << 11), 0xc0000000); - nv_wr32(priv, 0x40831c + (i << 11), 0xc0000000); + nvkm_wr32(device, 0x408600 + (i << 11), 0xc0000000); + nvkm_wr32(device, 0x408708 + (i << 11), 0xc0000000); + nvkm_wr32(device, 0x40831c + (i << 11), 0xc0000000); } } - nv_wr32(priv, 0x400108, 0xffffffff); - nv_wr32(priv, 0x400138, 0xffffffff); - nv_wr32(priv, 0x400100, 0xffffffff); - nv_wr32(priv, 0x40013c, 0xffffffff); - nv_wr32(priv, 0x400500, 0x00010001); + nvkm_wr32(device, 0x400108, 0xffffffff); + nvkm_wr32(device, 0x400138, 0xffffffff); + nvkm_wr32(device, 0x400100, 0xffffffff); + nvkm_wr32(device, 0x40013c, 0xffffffff); + nvkm_wr32(device, 0x400500, 0x00010001); /* upload context program, initialise ctxctl defaults */ - ret = nv50_grctx_init(nv_device(priv), &priv->size); + ret = nv50_grctx_init(device, &gr->size); if (ret) return ret; - nv_wr32(priv, 0x400824, 0x00000000); - nv_wr32(priv, 0x400828, 0x00000000); - nv_wr32(priv, 0x40082c, 0x00000000); - nv_wr32(priv, 0x400830, 0x00000000); - nv_wr32(priv, 0x40032c, 0x00000000); - nv_wr32(priv, 0x400330, 0x00000000); + nvkm_wr32(device, 0x400824, 0x00000000); + nvkm_wr32(device, 0x400828, 0x00000000); + nvkm_wr32(device, 0x40082c, 0x00000000); + nvkm_wr32(device, 0x400830, 0x00000000); + nvkm_wr32(device, 0x40032c, 0x00000000); + nvkm_wr32(device, 0x400330, 0x00000000); /* some unknown zcull magic */ - switch (nv_device(priv)->chipset & 0xf0) { + switch (device->chipset & 0xf0) { case 0x50: case 0x80: case 0x90: - nv_wr32(priv, 0x402ca8, 0x00000800); + nvkm_wr32(device, 0x402ca8, 0x00000800); break; case 0xa0: default: - if (nv_device(priv)->chipset == 0xa0 || - nv_device(priv)->chipset == 0xaa || - nv_device(priv)->chipset == 0xac) { - nv_wr32(priv, 0x402ca8, 0x00000802); + if (device->chipset == 0xa0 || + device->chipset == 0xaa || + device->chipset == 0xac) { + nvkm_wr32(device, 0x402ca8, 0x00000802); } else { - nv_wr32(priv, 0x402cc0, 0x00000000); - nv_wr32(priv, 0x402ca8, 0x00000002); + nvkm_wr32(device, 0x402cc0, 0x00000000); + nvkm_wr32(device, 0x402ca8, 0x00000002); } break; @@ -979,21 +748,47 @@ nv50_gr_init(struct nvkm_object *object) /* zero out zcull regions */ for (i = 0; i < 8; i++) { - nv_wr32(priv, 0x402c20 + (i * 0x10), 0x00000000); - nv_wr32(priv, 0x402c24 + (i * 0x10), 0x00000000); - nv_wr32(priv, 0x402c28 + (i * 0x10), 0x00000000); - nv_wr32(priv, 0x402c2c + (i * 0x10), 0x00000000); + nvkm_wr32(device, 0x402c20 + (i * 0x10), 0x00000000); + nvkm_wr32(device, 0x402c24 + (i * 0x10), 0x00000000); + nvkm_wr32(device, 0x402c28 + (i * 0x10), 0x00000000); + nvkm_wr32(device, 0x402c2c + (i * 0x10), 0x00000000); } + return 0; } -struct nvkm_oclass -nv50_gr_oclass = { - .handle = NV_ENGINE(GR, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_gr_ctor, - .dtor = _nvkm_gr_dtor, - .init = nv50_gr_init, - .fini = _nvkm_gr_fini, - }, +int +nv50_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device, + int index, struct nvkm_gr **pgr) +{ + struct nv50_gr *gr; + + if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) + return -ENOMEM; + spin_lock_init(&gr->lock); + *pgr = &gr->base; + + return nvkm_gr_ctor(func, device, index, 0x00201000, true, &gr->base); +} + +static const struct nvkm_gr_func +nv50_gr = { + .init = nv50_gr_init, + .intr = nv50_gr_intr, + .chan_new = nv50_gr_chan_new, + .units = nv50_gr_units, + .sclass = { + { -1, -1, 0x0030, &nv50_gr_object }, + { -1, -1, 0x502d, &nv50_gr_object }, + { -1, -1, 0x5039, &nv50_gr_object }, + { -1, -1, 0x5097, &nv50_gr_object }, + { -1, -1, 0x50c0, &nv50_gr_object }, + {} + } }; + +int +nv50_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return nv50_gr_new_(&nv50_gr, device, index, pgr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h index bcf786f6b..45eec83a5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h @@ -1,8 +1,34 @@ #ifndef __NV50_GR_H__ #define __NV50_GR_H__ -#include -struct nvkm_device; -struct nvkm_gpuobj; +#define nv50_gr(p) container_of((p), struct nv50_gr, base) +#include "priv.h" + +struct nv50_gr { + struct nvkm_gr base; + const struct nv50_gr_func *func; + spinlock_t lock; + u32 size; +}; + +int nv50_gr_new_(const struct nvkm_gr_func *, struct nvkm_device *, int index, + struct nvkm_gr **); +int nv50_gr_init(struct nvkm_gr *); +void nv50_gr_intr(struct nvkm_gr *); +u64 nv50_gr_units(struct nvkm_gr *); + +int g84_gr_tlb_flush(struct nvkm_gr *); + +#define nv50_gr_chan(p) container_of((p), struct nv50_gr_chan, object) + +struct nv50_gr_chan { + struct nvkm_object object; + struct nv50_gr *gr; +}; + +int nv50_gr_chan_new(struct nvkm_gr *, struct nvkm_fifo_chan *, + const struct nvkm_oclass *, struct nvkm_object **); + +extern const struct nvkm_object_func nv50_gr_object; int nv50_grctx_init(struct nvkm_device *, u32 *size); void nv50_grctx_fill(struct nvkm_device *, struct nvkm_gpuobj *); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h new file mode 100644 index 000000000..a234590be --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h @@ -0,0 +1,38 @@ +#ifndef __NVKM_GR_PRIV_H__ +#define __NVKM_GR_PRIV_H__ +#define nvkm_gr(p) container_of((p), struct nvkm_gr, engine) +#include +#include +struct nvkm_fb_tile; +struct nvkm_fifo_chan; + +int nvkm_gr_ctor(const struct nvkm_gr_func *, struct nvkm_device *, + int index, u32 pmc_enable, bool enable, + struct nvkm_gr *); + +bool nv04_gr_idle(struct nvkm_gr *); + +struct nvkm_gr_func { + void *(*dtor)(struct nvkm_gr *); + int (*oneinit)(struct nvkm_gr *); + int (*init)(struct nvkm_gr *); + void (*intr)(struct nvkm_gr *); + void (*tile)(struct nvkm_gr *, int region, struct nvkm_fb_tile *); + int (*tlb_flush)(struct nvkm_gr *); + int (*chan_new)(struct nvkm_gr *, struct nvkm_fifo_chan *, + const struct nvkm_oclass *, struct nvkm_object **); + int (*object_get)(struct nvkm_gr *, int, struct nvkm_sclass *); + /* Returns chipset-specific counts of units packed into an u64. + */ + u64 (*units)(struct nvkm_gr *); + struct nvkm_sclass sclass[]; +}; + +extern const struct nvkm_bitfield nv04_gr_nsource[]; +extern const struct nvkm_object_func nv04_gr_object; + +extern const struct nvkm_bitfield nv10_gr_intr_name[]; +extern const struct nvkm_bitfield nv10_gr_nstatus[]; + +extern const struct nvkm_enum nv50_data_error_names[]; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c index 0df889fa2..34ff0014a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c @@ -21,74 +21,24 @@ * * Authors: Ben Skeggs */ -#include - -struct g84_mpeg_priv { - struct nvkm_mpeg base; -}; - -struct g84_mpeg_chan { - struct nvkm_mpeg_chan base; -}; - -/******************************************************************************* - * MPEG object classes - ******************************************************************************/ - -static struct nvkm_oclass -g84_mpeg_sclass[] = { - { 0x8274, &nv50_mpeg_ofuncs }, - {} -}; - -/******************************************************************************* - * PMPEG context - ******************************************************************************/ - -static struct nvkm_oclass -g84_mpeg_cclass = { - .handle = NV_ENGCTX(MPEG, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_mpeg_context_ctor, - .dtor = _nvkm_mpeg_context_dtor, - .init = _nvkm_mpeg_context_init, - .fini = _nvkm_mpeg_context_fini, - .rd32 = _nvkm_mpeg_context_rd32, - .wr32 = _nvkm_mpeg_context_wr32, - }, +#include "priv.h" + +#include + +static const struct nvkm_engine_func +g84_mpeg = { + .init = nv50_mpeg_init, + .intr = nv50_mpeg_intr, + .cclass = &nv50_mpeg_cclass, + .sclass = { + { -1, -1, G82_MPEG, &nv31_mpeg_object }, + {} + } }; -/******************************************************************************* - * PMPEG engine/subdev functions - ******************************************************************************/ - -static int -g84_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +g84_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg) { - struct g84_mpeg_priv *priv; - int ret; - - ret = nvkm_mpeg_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000002; - nv_subdev(priv)->intr = nv50_mpeg_intr; - nv_engine(priv)->cclass = &g84_mpeg_cclass; - nv_engine(priv)->sclass = g84_mpeg_sclass; - return 0; + return nvkm_engine_new_(&g84_mpeg, device, index, 0x00000002, + true, pmpeg); } - -struct nvkm_oclass -g84_mpeg_oclass = { - .handle = NV_ENGINE(MPEG, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_mpeg_ctor, - .dtor = _nvkm_mpeg_dtor, - .init = nv50_mpeg_init, - .fini = _nvkm_mpeg_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c index b5bef0718..d4d8942b1 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c @@ -24,281 +24,271 @@ #include "nv31.h" #include -#include -#include -#include +#include #include #include +#include + +#include /******************************************************************************* * MPEG object classes ******************************************************************************/ static int -nv31_mpeg_object_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv31_mpeg_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_gpuobj *obj; - int ret; - - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, - 20, 16, 0, &obj); - *pobject = nv_object(obj); - if (ret) - return ret; - - nv_wo32(obj, 0x00, nv_mclass(obj)); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - return 0; + int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16, align, + false, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x00, object->oclass); + nvkm_wo32(*pgpuobj, 0x04, 0x00000000); + nvkm_wo32(*pgpuobj, 0x08, 0x00000000); + nvkm_wo32(*pgpuobj, 0x0c, 0x00000000); + nvkm_done(*pgpuobj); + } + return ret; } -static int -nv31_mpeg_mthd_dma(struct nvkm_object *object, u32 mthd, void *arg, u32 len) +const struct nvkm_object_func +nv31_mpeg_object = { + .bind = nv31_mpeg_object_bind, +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + +static void * +nv31_mpeg_chan_dtor(struct nvkm_object *object) { - struct nvkm_instmem *imem = nvkm_instmem(object); - struct nv31_mpeg_priv *priv = (void *)object->engine; - u32 inst = *(u32 *)arg << 4; - u32 dma0 = nv_ro32(imem, inst + 0); - u32 dma1 = nv_ro32(imem, inst + 4); - u32 dma2 = nv_ro32(imem, inst + 8); + struct nv31_mpeg_chan *chan = nv31_mpeg_chan(object); + struct nv31_mpeg *mpeg = chan->mpeg; + unsigned long flags; + + spin_lock_irqsave(&mpeg->engine.lock, flags); + if (mpeg->chan == chan) + mpeg->chan = NULL; + spin_unlock_irqrestore(&mpeg->engine.lock, flags); + return chan; +} + +static const struct nvkm_object_func +nv31_mpeg_chan = { + .dtor = nv31_mpeg_chan_dtor, +}; + +int +nv31_mpeg_chan_new(struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nv31_mpeg *mpeg = nv31_mpeg(oclass->engine); + struct nv31_mpeg_chan *chan; + unsigned long flags; + int ret = -EBUSY; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv31_mpeg_chan, oclass, &chan->object); + chan->mpeg = mpeg; + chan->fifo = fifoch; + *pobject = &chan->object; + + spin_lock_irqsave(&mpeg->engine.lock, flags); + if (!mpeg->chan) { + mpeg->chan = chan; + ret = 0; + } + spin_unlock_irqrestore(&mpeg->engine.lock, flags); + return ret; +} + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +void +nv31_mpeg_tile(struct nvkm_engine *engine, int i, struct nvkm_fb_tile *tile) +{ + struct nv31_mpeg *mpeg = nv31_mpeg(engine); + struct nvkm_device *device = mpeg->engine.subdev.device; + + nvkm_wr32(device, 0x00b008 + (i * 0x10), tile->pitch); + nvkm_wr32(device, 0x00b004 + (i * 0x10), tile->limit); + nvkm_wr32(device, 0x00b000 + (i * 0x10), tile->addr); +} + +static bool +nv31_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data) +{ + u32 inst = data << 4; + u32 dma0 = nvkm_rd32(device, 0x700000 + inst); + u32 dma1 = nvkm_rd32(device, 0x700004 + inst); + u32 dma2 = nvkm_rd32(device, 0x700008 + inst); u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); u32 size = dma1 + 1; /* only allow linear DMA objects */ if (!(dma0 & 0x00002000)) - return -EINVAL; + return false; if (mthd == 0x0190) { /* DMA_CMD */ - nv_mask(priv, 0x00b300, 0x00010000, (dma0 & 0x00030000) ? 0x00010000 : 0); - nv_wr32(priv, 0x00b334, base); - nv_wr32(priv, 0x00b324, size); + nvkm_mask(device, 0x00b300, 0x00010000, + (dma0 & 0x00030000) ? 0x00010000 : 0); + nvkm_wr32(device, 0x00b334, base); + nvkm_wr32(device, 0x00b324, size); } else if (mthd == 0x01a0) { /* DMA_DATA */ - nv_mask(priv, 0x00b300, 0x00020000, (dma0 & 0x00030000) ? 0x00020000 : 0); - nv_wr32(priv, 0x00b360, base); - nv_wr32(priv, 0x00b364, size); + nvkm_mask(device, 0x00b300, 0x00020000, + (dma0 & 0x00030000) ? 0x00020000 : 0); + nvkm_wr32(device, 0x00b360, base); + nvkm_wr32(device, 0x00b364, size); } else { /* DMA_IMAGE, VRAM only */ if (dma0 & 0x00030000) - return -EINVAL; + return false; - nv_wr32(priv, 0x00b370, base); - nv_wr32(priv, 0x00b374, size); + nvkm_wr32(device, 0x00b370, base); + nvkm_wr32(device, 0x00b374, size); } - return 0; + return true; } -struct nvkm_ofuncs -nv31_mpeg_ofuncs = { - .ctor = nv31_mpeg_object_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, -}; - -static struct nvkm_omthds -nv31_mpeg_omthds[] = { - { 0x0190, 0x0190, nv31_mpeg_mthd_dma }, - { 0x01a0, 0x01a0, nv31_mpeg_mthd_dma }, - { 0x01b0, 0x01b0, nv31_mpeg_mthd_dma }, - {} -}; - -struct nvkm_oclass -nv31_mpeg_sclass[] = { - { 0x3174, &nv31_mpeg_ofuncs, nv31_mpeg_omthds }, - {} -}; - -/******************************************************************************* - * PMPEG context - ******************************************************************************/ - -static int -nv31_mpeg_context_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static bool +nv31_mpeg_mthd(struct nv31_mpeg *mpeg, u32 mthd, u32 data) { - struct nv31_mpeg_priv *priv = (void *)engine; - struct nv31_mpeg_chan *chan; - unsigned long flags; - int ret; - - ret = nvkm_object_create(parent, engine, oclass, 0, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - spin_lock_irqsave(&nv_engine(priv)->lock, flags); - if (priv->chan) { - spin_unlock_irqrestore(&nv_engine(priv)->lock, flags); - nvkm_object_destroy(&chan->base); - *pobject = NULL; - return -EBUSY; + struct nvkm_device *device = mpeg->engine.subdev.device; + switch (mthd) { + case 0x190: + case 0x1a0: + case 0x1b0: + return mpeg->func->mthd_dma(device, mthd, data); + default: + break; } - priv->chan = chan; - spin_unlock_irqrestore(&nv_engine(priv)->lock, flags); - return 0; + return false; } static void -nv31_mpeg_context_dtor(struct nvkm_object *object) +nv31_mpeg_intr(struct nvkm_engine *engine) { - struct nv31_mpeg_priv *priv = (void *)object->engine; - struct nv31_mpeg_chan *chan = (void *)object; - unsigned long flags; - - spin_lock_irqsave(&nv_engine(priv)->lock, flags); - priv->chan = NULL; - spin_unlock_irqrestore(&nv_engine(priv)->lock, flags); - nvkm_object_destroy(&chan->base); -} - -struct nvkm_oclass -nv31_mpeg_cclass = { - .handle = NV_ENGCTX(MPEG, 0x31), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv31_mpeg_context_ctor, - .dtor = nv31_mpeg_context_dtor, - .init = nvkm_object_init, - .fini = nvkm_object_fini, - }, -}; - -/******************************************************************************* - * PMPEG engine/subdev functions - ******************************************************************************/ - -void -nv31_mpeg_tile_prog(struct nvkm_engine *engine, int i) -{ - struct nvkm_fb_tile *tile = &nvkm_fb(engine)->tile.region[i]; - struct nv31_mpeg_priv *priv = (void *)engine; - - nv_wr32(priv, 0x00b008 + (i * 0x10), tile->pitch); - nv_wr32(priv, 0x00b004 + (i * 0x10), tile->limit); - nv_wr32(priv, 0x00b000 + (i * 0x10), tile->addr); -} - -void -nv31_mpeg_intr(struct nvkm_subdev *subdev) -{ - struct nv31_mpeg_priv *priv = (void *)subdev; - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_handle *handle; - struct nvkm_object *engctx; - u32 stat = nv_rd32(priv, 0x00b100); - u32 type = nv_rd32(priv, 0x00b230); - u32 mthd = nv_rd32(priv, 0x00b234); - u32 data = nv_rd32(priv, 0x00b238); + struct nv31_mpeg *mpeg = nv31_mpeg(engine); + struct nvkm_subdev *subdev = &mpeg->engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x00b100); + u32 type = nvkm_rd32(device, 0x00b230); + u32 mthd = nvkm_rd32(device, 0x00b234); + u32 data = nvkm_rd32(device, 0x00b238); u32 show = stat; unsigned long flags; - spin_lock_irqsave(&nv_engine(priv)->lock, flags); - engctx = nv_object(priv->chan); + spin_lock_irqsave(&mpeg->engine.lock, flags); if (stat & 0x01000000) { /* happens on initial binding of the object */ if (type == 0x00000020 && mthd == 0x0000) { - nv_mask(priv, 0x00b308, 0x00000000, 0x00000000); + nvkm_mask(device, 0x00b308, 0x00000000, 0x00000000); show &= ~0x01000000; } - if (type == 0x00000010 && engctx) { - handle = nvkm_handle_get_class(engctx, 0x3174); - if (handle && !nv_call(handle->object, mthd, data)) + if (type == 0x00000010) { + if (!nv31_mpeg_mthd(mpeg, mthd, data)) show &= ~0x01000000; - nvkm_handle_put(handle); } } - nv_wr32(priv, 0x00b100, stat); - nv_wr32(priv, 0x00b230, 0x00000001); + nvkm_wr32(device, 0x00b100, stat); + nvkm_wr32(device, 0x00b230, 0x00000001); if (show) { - nv_error(priv, "ch %d [%s] 0x%08x 0x%08x 0x%08x 0x%08x\n", - pfifo->chid(pfifo, engctx), - nvkm_client_name(engctx), stat, type, mthd, data); + nvkm_error(subdev, "ch %d [%s] %08x %08x %08x %08x\n", + mpeg->chan ? mpeg->chan->fifo->chid : -1, + mpeg->chan ? mpeg->chan->object.client->name : + "unknown", stat, type, mthd, data); } - spin_unlock_irqrestore(&nv_engine(priv)->lock, flags); -} - -static int -nv31_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv31_mpeg_priv *priv; - int ret; - - ret = nvkm_mpeg_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000002; - nv_subdev(priv)->intr = nv31_mpeg_intr; - nv_engine(priv)->cclass = &nv31_mpeg_cclass; - nv_engine(priv)->sclass = nv31_mpeg_sclass; - nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; - return 0; + spin_unlock_irqrestore(&mpeg->engine.lock, flags); } int -nv31_mpeg_init(struct nvkm_object *object) +nv31_mpeg_init(struct nvkm_engine *mpeg) { - struct nvkm_engine *engine = nv_engine(object); - struct nv31_mpeg_priv *priv = (void *)object; - struct nvkm_fb *pfb = nvkm_fb(object); - int ret, i; - - ret = nvkm_mpeg_init(&priv->base); - if (ret) - return ret; + struct nvkm_subdev *subdev = &mpeg->subdev; + struct nvkm_device *device = subdev->device; /* VPE init */ - nv_wr32(priv, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - nv_wr32(priv, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - - for (i = 0; i < pfb->tile.regions; i++) - engine->tile_prog(engine, i); + nvkm_wr32(device, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ + nvkm_wr32(device, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ /* PMPEG init */ - nv_wr32(priv, 0x00b32c, 0x00000000); - nv_wr32(priv, 0x00b314, 0x00000100); - nv_wr32(priv, 0x00b220, 0x00000031); - nv_wr32(priv, 0x00b300, 0x02001ec1); - nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); - - nv_wr32(priv, 0x00b100, 0xffffffff); - nv_wr32(priv, 0x00b140, 0xffffffff); - - if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) { - nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200)); + nvkm_wr32(device, 0x00b32c, 0x00000000); + nvkm_wr32(device, 0x00b314, 0x00000100); + nvkm_wr32(device, 0x00b220, 0x00000031); + nvkm_wr32(device, 0x00b300, 0x02001ec1); + nvkm_mask(device, 0x00b32c, 0x00000001, 0x00000001); + + nvkm_wr32(device, 0x00b100, 0xffffffff); + nvkm_wr32(device, 0x00b140, 0xffffffff); + + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x00b200) & 0x00000001)) + break; + ) < 0) { + nvkm_error(subdev, "timeout %08x\n", + nvkm_rd32(device, 0x00b200)); return -EBUSY; } return 0; } -struct nvkm_oclass -nv31_mpeg_oclass = { - .handle = NV_ENGINE(MPEG, 0x31), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv31_mpeg_ctor, - .dtor = _nvkm_mpeg_dtor, - .init = nv31_mpeg_init, - .fini = _nvkm_mpeg_fini, - }, +static void * +nv31_mpeg_dtor(struct nvkm_engine *engine) +{ + return nv31_mpeg(engine); +} + +static const struct nvkm_engine_func +nv31_mpeg_ = { + .dtor = nv31_mpeg_dtor, + .init = nv31_mpeg_init, + .intr = nv31_mpeg_intr, + .tile = nv31_mpeg_tile, + .fifo.cclass = nv31_mpeg_chan_new, + .sclass = { + { -1, -1, NV31_MPEG, &nv31_mpeg_object }, + {} + } }; + +int +nv31_mpeg_new_(const struct nv31_mpeg_func *func, struct nvkm_device *device, + int index, struct nvkm_engine **pmpeg) +{ + struct nv31_mpeg *mpeg; + + if (!(mpeg = kzalloc(sizeof(*mpeg), GFP_KERNEL))) + return -ENOMEM; + mpeg->func = func; + *pmpeg = &mpeg->engine; + + return nvkm_engine_ctor(&nv31_mpeg_, device, index, 0x00000002, + true, &mpeg->engine); +} + +static const struct nv31_mpeg_func +nv31_mpeg = { + .mthd_dma = nv31_mpeg_mthd_dma, +}; + +int +nv31_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg) +{ + return nv31_mpeg_new_(&nv31_mpeg, device, index, pmpeg); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h index 782b796d7..d3bb34fcd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h @@ -1,13 +1,30 @@ #ifndef __NV31_MPEG_H__ #define __NV31_MPEG_H__ +#define nv31_mpeg(p) container_of((p), struct nv31_mpeg, engine) +#include "priv.h" #include -struct nv31_mpeg_chan { - struct nvkm_object base; +struct nv31_mpeg { + const struct nv31_mpeg_func *func; + struct nvkm_engine engine; + struct nv31_mpeg_chan *chan; }; -struct nv31_mpeg_priv { - struct nvkm_mpeg base; - struct nv31_mpeg_chan *chan; +int nv31_mpeg_new_(const struct nv31_mpeg_func *, struct nvkm_device *, + int index, struct nvkm_engine **); + +struct nv31_mpeg_func { + bool (*mthd_dma)(struct nvkm_device *, u32 mthd, u32 data); }; + +#define nv31_mpeg_chan(p) container_of((p), struct nv31_mpeg_chan, object) + +struct nv31_mpeg_chan { + struct nvkm_object object; + struct nv31_mpeg *mpeg; + struct nvkm_fifo_chan *fifo; +}; + +int nv31_mpeg_chan_new(struct nvkm_fifo_chan *, const struct nvkm_oclass *, + struct nvkm_object **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c index 9508bf9e1..16de5bd94 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c @@ -25,110 +25,53 @@ #include -/******************************************************************************* - * MPEG object classes - ******************************************************************************/ +#include -static int -nv40_mpeg_mthd_dma(struct nvkm_object *object, u32 mthd, void *arg, u32 len) +bool +nv40_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data) { - struct nvkm_instmem *imem = nvkm_instmem(object); - struct nv31_mpeg_priv *priv = (void *)object->engine; - u32 inst = *(u32 *)arg << 4; - u32 dma0 = nv_ro32(imem, inst + 0); - u32 dma1 = nv_ro32(imem, inst + 4); - u32 dma2 = nv_ro32(imem, inst + 8); + struct nvkm_instmem *imem = device->imem; + u32 inst = data << 4; + u32 dma0 = nvkm_instmem_rd32(imem, inst + 0); + u32 dma1 = nvkm_instmem_rd32(imem, inst + 4); + u32 dma2 = nvkm_instmem_rd32(imem, inst + 8); u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); u32 size = dma1 + 1; /* only allow linear DMA objects */ if (!(dma0 & 0x00002000)) - return -EINVAL; + return false; if (mthd == 0x0190) { /* DMA_CMD */ - nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000)); - nv_wr32(priv, 0x00b334, base); - nv_wr32(priv, 0x00b324, size); + nvkm_mask(device, 0x00b300, 0x00030000, (dma0 & 0x00030000)); + nvkm_wr32(device, 0x00b334, base); + nvkm_wr32(device, 0x00b324, size); } else if (mthd == 0x01a0) { /* DMA_DATA */ - nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); - nv_wr32(priv, 0x00b360, base); - nv_wr32(priv, 0x00b364, size); + nvkm_mask(device, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); + nvkm_wr32(device, 0x00b360, base); + nvkm_wr32(device, 0x00b364, size); } else { /* DMA_IMAGE, VRAM only */ if (dma0 & 0x00030000) - return -EINVAL; + return false; - nv_wr32(priv, 0x00b370, base); - nv_wr32(priv, 0x00b374, size); + nvkm_wr32(device, 0x00b370, base); + nvkm_wr32(device, 0x00b374, size); } - return 0; + return true; } -static struct nvkm_omthds -nv40_mpeg_omthds[] = { - { 0x0190, 0x0190, nv40_mpeg_mthd_dma }, - { 0x01a0, 0x01a0, nv40_mpeg_mthd_dma }, - { 0x01b0, 0x01b0, nv40_mpeg_mthd_dma }, - {} +static const struct nv31_mpeg_func +nv40_mpeg = { + .mthd_dma = nv40_mpeg_mthd_dma, }; -struct nvkm_oclass -nv40_mpeg_sclass[] = { - { 0x3174, &nv31_mpeg_ofuncs, nv40_mpeg_omthds }, - {} -}; - -/******************************************************************************* - * PMPEG engine/subdev functions - ******************************************************************************/ - -static void -nv40_mpeg_intr(struct nvkm_subdev *subdev) +int +nv40_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg) { - struct nv31_mpeg_priv *priv = (void *)subdev; - u32 stat; - - if ((stat = nv_rd32(priv, 0x00b100))) - nv31_mpeg_intr(subdev); - - if ((stat = nv_rd32(priv, 0x00b800))) { - nv_error(priv, "PMSRCH 0x%08x\n", stat); - nv_wr32(priv, 0x00b800, stat); - } + return nv31_mpeg_new_(&nv40_mpeg, device, index, pmpeg); } - -static int -nv40_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv31_mpeg_priv *priv; - int ret; - - ret = nvkm_mpeg_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000002; - nv_subdev(priv)->intr = nv40_mpeg_intr; - nv_engine(priv)->cclass = &nv31_mpeg_cclass; - nv_engine(priv)->sclass = nv40_mpeg_sclass; - nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; - return 0; -} - -struct nvkm_oclass -nv40_mpeg_oclass = { - .handle = NV_ENGINE(MPEG, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_mpeg_ctor, - .dtor = _nvkm_mpeg_dtor, - .init = nv31_mpeg_init, - .fini = _nvkm_mpeg_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c index 4720ac884..d433cfa4a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c @@ -21,165 +21,197 @@ * * Authors: Ben Skeggs */ -#include +#define nv44_mpeg(p) container_of((p), struct nv44_mpeg, engine) +#include "priv.h" #include -#include +#include #include -struct nv44_mpeg_priv { - struct nvkm_mpeg base; -}; +#include -struct nv44_mpeg_chan { - struct nvkm_mpeg_chan base; +struct nv44_mpeg { + struct nvkm_engine engine; + struct list_head chan; }; /******************************************************************************* * PMPEG context ******************************************************************************/ +#define nv44_mpeg_chan(p) container_of((p), struct nv44_mpeg_chan, object) + +struct nv44_mpeg_chan { + struct nvkm_object object; + struct nv44_mpeg *mpeg; + struct nvkm_fifo_chan *fifo; + struct list_head head; + u32 inst; +}; static int -nv44_mpeg_context_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv44_mpeg_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nv44_mpeg_chan *chan; - int ret; - - ret = nvkm_mpeg_context_create(parent, engine, oclass, NULL, 264 * 4, - 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - nv_wo32(&chan->base.base, 0x78, 0x02001ec1); - return 0; + struct nv44_mpeg_chan *chan = nv44_mpeg_chan(object); + int ret = nvkm_gpuobj_new(chan->object.engine->subdev.device, 264 * 4, + align, true, parent, pgpuobj); + if (ret == 0) { + chan->inst = (*pgpuobj)->addr; + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x78, 0x02001ec1); + nvkm_done(*pgpuobj); + } + return ret; } static int -nv44_mpeg_context_fini(struct nvkm_object *object, bool suspend) +nv44_mpeg_chan_fini(struct nvkm_object *object, bool suspend) { - struct nv44_mpeg_priv *priv = (void *)object->engine; - struct nv44_mpeg_chan *chan = (void *)object; - u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4; + struct nv44_mpeg_chan *chan = nv44_mpeg_chan(object); + struct nv44_mpeg *mpeg = chan->mpeg; + struct nvkm_device *device = mpeg->engine.subdev.device; + u32 inst = 0x80000000 | (chan->inst >> 4); - nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000); - if (nv_rd32(priv, 0x00b318) == inst) - nv_mask(priv, 0x00b318, 0x80000000, 0x00000000); - nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x00b32c, 0x00000001, 0x00000000); + if (nvkm_rd32(device, 0x00b318) == inst) + nvkm_mask(device, 0x00b318, 0x80000000, 0x00000000); + nvkm_mask(device, 0x00b32c, 0x00000001, 0x00000001); return 0; } -static struct nvkm_oclass -nv44_mpeg_cclass = { - .handle = NV_ENGCTX(MPEG, 0x44), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv44_mpeg_context_ctor, - .dtor = _nvkm_mpeg_context_dtor, - .init = _nvkm_mpeg_context_init, - .fini = nv44_mpeg_context_fini, - .rd32 = _nvkm_mpeg_context_rd32, - .wr32 = _nvkm_mpeg_context_wr32, - }, +static void * +nv44_mpeg_chan_dtor(struct nvkm_object *object) +{ + struct nv44_mpeg_chan *chan = nv44_mpeg_chan(object); + struct nv44_mpeg *mpeg = chan->mpeg; + unsigned long flags; + spin_lock_irqsave(&mpeg->engine.lock, flags); + list_del(&chan->head); + spin_unlock_irqrestore(&mpeg->engine.lock, flags); + return chan; +} + +static const struct nvkm_object_func +nv44_mpeg_chan = { + .dtor = nv44_mpeg_chan_dtor, + .fini = nv44_mpeg_chan_fini, + .bind = nv44_mpeg_chan_bind, }; +static int +nv44_mpeg_chan_new(struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nv44_mpeg *mpeg = nv44_mpeg(oclass->engine); + struct nv44_mpeg_chan *chan; + unsigned long flags; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nv44_mpeg_chan, oclass, &chan->object); + chan->mpeg = mpeg; + chan->fifo = fifoch; + *pobject = &chan->object; + + spin_lock_irqsave(&mpeg->engine.lock, flags); + list_add(&chan->head, &mpeg->chan); + spin_unlock_irqrestore(&mpeg->engine.lock, flags); + return 0; +} + /******************************************************************************* * PMPEG engine/subdev functions ******************************************************************************/ +static bool +nv44_mpeg_mthd(struct nvkm_device *device, u32 mthd, u32 data) +{ + switch (mthd) { + case 0x190: + case 0x1a0: + case 0x1b0: + return nv40_mpeg_mthd_dma(device, mthd, data); + default: + break; + } + return false; +} + static void -nv44_mpeg_intr(struct nvkm_subdev *subdev) +nv44_mpeg_intr(struct nvkm_engine *engine) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct nvkm_handle *handle; - struct nv44_mpeg_priv *priv = (void *)subdev; - u32 inst = nv_rd32(priv, 0x00b318) & 0x000fffff; - u32 stat = nv_rd32(priv, 0x00b100); - u32 type = nv_rd32(priv, 0x00b230); - u32 mthd = nv_rd32(priv, 0x00b234); - u32 data = nv_rd32(priv, 0x00b238); + struct nv44_mpeg *mpeg = nv44_mpeg(engine); + struct nvkm_subdev *subdev = &mpeg->engine.subdev; + struct nvkm_device *device = subdev->device; + struct nv44_mpeg_chan *temp, *chan = NULL; + unsigned long flags; + u32 inst = nvkm_rd32(device, 0x00b318) & 0x000fffff; + u32 stat = nvkm_rd32(device, 0x00b100); + u32 type = nvkm_rd32(device, 0x00b230); + u32 mthd = nvkm_rd32(device, 0x00b234); + u32 data = nvkm_rd32(device, 0x00b238); u32 show = stat; - int chid; - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); + spin_lock_irqsave(&mpeg->engine.lock, flags); + list_for_each_entry(temp, &mpeg->chan, head) { + if (temp->inst >> 4 == inst) { + chan = temp; + list_del(&chan->head); + list_add(&chan->head, &mpeg->chan); + break; + } + } if (stat & 0x01000000) { /* happens on initial binding of the object */ if (type == 0x00000020 && mthd == 0x0000) { - nv_mask(priv, 0x00b308, 0x00000000, 0x00000000); + nvkm_mask(device, 0x00b308, 0x00000000, 0x00000000); show &= ~0x01000000; } if (type == 0x00000010) { - handle = nvkm_handle_get_class(engctx, 0x3174); - if (handle && !nv_call(handle->object, mthd, data)) + if (!nv44_mpeg_mthd(subdev->device, mthd, data)) show &= ~0x01000000; - nvkm_handle_put(handle); } } - nv_wr32(priv, 0x00b100, stat); - nv_wr32(priv, 0x00b230, 0x00000001); + nvkm_wr32(device, 0x00b100, stat); + nvkm_wr32(device, 0x00b230, 0x00000001); if (show) { - nv_error(priv, - "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n", - chid, inst << 4, nvkm_client_name(engctx), stat, - type, mthd, data); + nvkm_error(subdev, "ch %d [%08x %s] %08x %08x %08x %08x\n", + chan ? chan->fifo->chid : -1, inst << 4, + chan ? chan->object.client->name : "unknown", + stat, type, mthd, data); } - nvkm_engctx_put(engctx); + spin_unlock_irqrestore(&mpeg->engine.lock, flags); } -static void -nv44_mpeg_me_intr(struct nvkm_subdev *subdev) -{ - struct nv44_mpeg_priv *priv = (void *)subdev; - u32 stat; - - if ((stat = nv_rd32(priv, 0x00b100))) - nv44_mpeg_intr(subdev); - - if ((stat = nv_rd32(priv, 0x00b800))) { - nv_error(priv, "PMSRCH 0x%08x\n", stat); - nv_wr32(priv, 0x00b800, stat); +static const struct nvkm_engine_func +nv44_mpeg = { + .init = nv31_mpeg_init, + .intr = nv44_mpeg_intr, + .tile = nv31_mpeg_tile, + .fifo.cclass = nv44_mpeg_chan_new, + .sclass = { + { -1, -1, NV31_MPEG, &nv31_mpeg_object }, + {} } -} +}; -static int -nv44_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv44_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg) { - struct nv44_mpeg_priv *priv; - int ret; - - ret = nvkm_mpeg_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00000002; - nv_subdev(priv)->intr = nv44_mpeg_me_intr; - nv_engine(priv)->cclass = &nv44_mpeg_cclass; - nv_engine(priv)->sclass = nv40_mpeg_sclass; - nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; - return 0; -} + struct nv44_mpeg *mpeg; -struct nvkm_oclass -nv44_mpeg_oclass = { - .handle = NV_ENGINE(MPEG, 0x44), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv44_mpeg_ctor, - .dtor = _nvkm_mpeg_dtor, - .init = nv31_mpeg_init, - .fini = _nvkm_mpeg_fini, - }, -}; + if (!(mpeg = kzalloc(sizeof(*mpeg), GFP_KERNEL))) + return -ENOMEM; + INIT_LIST_HEAD(&mpeg->chan); + *pmpeg = &mpeg->engine; + + return nvkm_engine_ctor(&nv44_mpeg, device, index, 0x00000002, + true, &mpeg->engine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c index b3463f373..c3a85dffc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c @@ -21,98 +21,35 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" -#include +#include #include -struct nv50_mpeg_priv { - struct nvkm_mpeg base; -}; - -struct nv50_mpeg_chan { - struct nvkm_mpeg_chan base; -}; - -/******************************************************************************* - * MPEG object classes - ******************************************************************************/ - -static int -nv50_mpeg_object_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_gpuobj *obj; - int ret; - - ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, - 16, 16, 0, &obj); - *pobject = nv_object(obj); - if (ret) - return ret; - - nv_wo32(obj, 0x00, nv_mclass(obj)); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - return 0; -} - -struct nvkm_ofuncs -nv50_mpeg_ofuncs = { - .ctor = nv50_mpeg_object_ctor, - .dtor = _nvkm_gpuobj_dtor, - .init = _nvkm_gpuobj_init, - .fini = _nvkm_gpuobj_fini, - .rd32 = _nvkm_gpuobj_rd32, - .wr32 = _nvkm_gpuobj_wr32, -}; - -static struct nvkm_oclass -nv50_mpeg_sclass[] = { - { 0x3174, &nv50_mpeg_ofuncs }, - {} -}; +#include /******************************************************************************* * PMPEG context ******************************************************************************/ -int -nv50_mpeg_context_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static int +nv50_mpeg_cclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_bar *bar = nvkm_bar(parent); - struct nv50_mpeg_chan *chan; - int ret; - - ret = nvkm_mpeg_context_create(parent, engine, oclass, NULL, 128 * 4, - 0, NVOBJ_FLAG_ZERO_ALLOC, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - nv_wo32(chan, 0x0070, 0x00801ec1); - nv_wo32(chan, 0x007c, 0x0000037c); - bar->flush(bar); - return 0; + int ret = nvkm_gpuobj_new(object->engine->subdev.device, 128 * 4, + align, true, parent, pgpuobj); + if (ret == 0) { + nvkm_kmap(*pgpuobj); + nvkm_wo32(*pgpuobj, 0x70, 0x00801ec1); + nvkm_wo32(*pgpuobj, 0x7c, 0x0000037c); + nvkm_done(*pgpuobj); + } + return ret; } -static struct nvkm_oclass +const struct nvkm_object_func nv50_mpeg_cclass = { - .handle = NV_ENGCTX(MPEG, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_mpeg_context_ctor, - .dtor = _nvkm_mpeg_context_dtor, - .init = _nvkm_mpeg_context_init, - .fini = _nvkm_mpeg_context_fini, - .rd32 = _nvkm_mpeg_context_rd32, - .wr32 = _nvkm_mpeg_context_wr32, - }, + .bind = nv50_mpeg_cclass_bind, }; /******************************************************************************* @@ -120,106 +57,79 @@ nv50_mpeg_cclass = { ******************************************************************************/ void -nv50_mpeg_intr(struct nvkm_subdev *subdev) +nv50_mpeg_intr(struct nvkm_engine *mpeg) { - struct nv50_mpeg_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, 0x00b100); - u32 type = nv_rd32(priv, 0x00b230); - u32 mthd = nv_rd32(priv, 0x00b234); - u32 data = nv_rd32(priv, 0x00b238); + struct nvkm_subdev *subdev = &mpeg->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x00b100); + u32 type = nvkm_rd32(device, 0x00b230); + u32 mthd = nvkm_rd32(device, 0x00b234); + u32 data = nvkm_rd32(device, 0x00b238); u32 show = stat; if (stat & 0x01000000) { /* happens on initial binding of the object */ if (type == 0x00000020 && mthd == 0x0000) { - nv_wr32(priv, 0x00b308, 0x00000100); + nvkm_wr32(device, 0x00b308, 0x00000100); show &= ~0x01000000; } } if (show) { - nv_info(priv, "0x%08x 0x%08x 0x%08x 0x%08x\n", - stat, type, mthd, data); - } - - nv_wr32(priv, 0x00b100, stat); - nv_wr32(priv, 0x00b230, 0x00000001); -} - -static void -nv50_vpe_intr(struct nvkm_subdev *subdev) -{ - struct nv50_mpeg_priv *priv = (void *)subdev; - - if (nv_rd32(priv, 0x00b100)) - nv50_mpeg_intr(subdev); - - if (nv_rd32(priv, 0x00b800)) { - u32 stat = nv_rd32(priv, 0x00b800); - nv_info(priv, "PMSRCH: 0x%08x\n", stat); - nv_wr32(priv, 0xb800, stat); + nvkm_info(subdev, "%08x %08x %08x %08x\n", + stat, type, mthd, data); } -} -static int -nv50_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_mpeg_priv *priv; - int ret; - - ret = nvkm_mpeg_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00400002; - nv_subdev(priv)->intr = nv50_vpe_intr; - nv_engine(priv)->cclass = &nv50_mpeg_cclass; - nv_engine(priv)->sclass = nv50_mpeg_sclass; - return 0; + nvkm_wr32(device, 0x00b100, stat); + nvkm_wr32(device, 0x00b230, 0x00000001); } int -nv50_mpeg_init(struct nvkm_object *object) +nv50_mpeg_init(struct nvkm_engine *mpeg) { - struct nv50_mpeg_priv *priv = (void *)object; - int ret; - - ret = nvkm_mpeg_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x00b32c, 0x00000000); - nv_wr32(priv, 0x00b314, 0x00000100); - nv_wr32(priv, 0x00b0e0, 0x0000001a); - - nv_wr32(priv, 0x00b220, 0x00000044); - nv_wr32(priv, 0x00b300, 0x00801ec1); - nv_wr32(priv, 0x00b390, 0x00000000); - nv_wr32(priv, 0x00b394, 0x00000000); - nv_wr32(priv, 0x00b398, 0x00000000); - nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); - - nv_wr32(priv, 0x00b100, 0xffffffff); - nv_wr32(priv, 0x00b140, 0xffffffff); - - if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) { - nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200)); + struct nvkm_subdev *subdev = &mpeg->subdev; + struct nvkm_device *device = subdev->device; + + nvkm_wr32(device, 0x00b32c, 0x00000000); + nvkm_wr32(device, 0x00b314, 0x00000100); + nvkm_wr32(device, 0x00b0e0, 0x0000001a); + + nvkm_wr32(device, 0x00b220, 0x00000044); + nvkm_wr32(device, 0x00b300, 0x00801ec1); + nvkm_wr32(device, 0x00b390, 0x00000000); + nvkm_wr32(device, 0x00b394, 0x00000000); + nvkm_wr32(device, 0x00b398, 0x00000000); + nvkm_mask(device, 0x00b32c, 0x00000001, 0x00000001); + + nvkm_wr32(device, 0x00b100, 0xffffffff); + nvkm_wr32(device, 0x00b140, 0xffffffff); + + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x00b200) & 0x00000001)) + break; + ) < 0) { + nvkm_error(subdev, "timeout %08x\n", + nvkm_rd32(device, 0x00b200)); return -EBUSY; } return 0; } -struct nvkm_oclass -nv50_mpeg_oclass = { - .handle = NV_ENGINE(MPEG, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_mpeg_ctor, - .dtor = _nvkm_mpeg_dtor, - .init = nv50_mpeg_init, - .fini = _nvkm_mpeg_fini, - }, +static const struct nvkm_engine_func +nv50_mpeg = { + .init = nv50_mpeg_init, + .intr = nv50_mpeg_intr, + .cclass = &nv50_mpeg_cclass, + .sclass = { + { -1, -1, NV31_MPEG, &nv31_mpeg_object }, + {} + } }; + +int +nv50_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg) +{ + return nvkm_engine_new_(&nv50_mpeg, device, index, 0x00400002, + true, pmpeg); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h new file mode 100644 index 000000000..d5753103f --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h @@ -0,0 +1,16 @@ +#ifndef __NVKM_MPEG_PRIV_H__ +#define __NVKM_MPEG_PRIV_H__ +#include +struct nvkm_fifo_chan; + +int nv31_mpeg_init(struct nvkm_engine *); +void nv31_mpeg_tile(struct nvkm_engine *, int, struct nvkm_fb_tile *); +extern const struct nvkm_object_func nv31_mpeg_object; + +bool nv40_mpeg_mthd_dma(struct nvkm_device *, u32, u32); + +int nv50_mpeg_init(struct nvkm_engine *); +void nv50_mpeg_intr(struct nvkm_engine *); + +extern const struct nvkm_object_func nv50_mpeg_cclass; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/Kbuild index c59c83a67..1a7151146 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/Kbuild @@ -1,3 +1,5 @@ +nvkm-y += nvkm/engine/mspdec/base.o nvkm-y += nvkm/engine/mspdec/g98.o +nvkm-y += nvkm/engine/mspdec/gt215.o nvkm-y += nvkm/engine/mspdec/gf100.o nvkm-y += nvkm/engine/mspdec/gk104.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/base.c new file mode 100644 index 000000000..80211f760 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/base.c @@ -0,0 +1,32 @@ +/* + * 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 + */ +#include "priv.h" + +int +nvkm_mspdec_new_(const struct nvkm_falcon_func *func, + struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_falcon_new_(func, device, index, true, 0x085000, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c index 217457779..1f1a99e92 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c @@ -21,89 +21,31 @@ * * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin */ -#include -#include +#include "priv.h" -struct g98_mspdec_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * MSPDEC object classes - ******************************************************************************/ - -static struct nvkm_oclass -g98_mspdec_sclass[] = { - { 0x88b2, &nvkm_object_ofuncs }, - { 0x85b2, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSPDEC context - ******************************************************************************/ - -static struct nvkm_oclass -g98_mspdec_cclass = { - .handle = NV_ENGCTX(MSPDEC, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSPDEC engine/subdev functions - ******************************************************************************/ +#include -static int -g98_mspdec_init(struct nvkm_object *object) +void +g98_mspdec_init(struct nvkm_falcon *mspdec) { - struct g98_mspdec_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x085010, 0x0000ffd2); - nv_wr32(priv, 0x08501c, 0x0000fff2); - return 0; + struct nvkm_device *device = mspdec->engine.subdev.device; + nvkm_wr32(device, 0x085010, 0x0000ffd2); + nvkm_wr32(device, 0x08501c, 0x0000fff2); } -static int -g98_mspdec_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct g98_mspdec_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x085000, true, - "PMSPDEC", "mspdec", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +g98_mspdec = { + .pmc_enable = 0x01020000, + .init = g98_mspdec_init, + .sclass = { + { -1, -1, G98_MSPDEC }, + {} + } +}; - nv_subdev(priv)->unit = 0x01020000; - nv_engine(priv)->cclass = &g98_mspdec_cclass; - nv_engine(priv)->sclass = g98_mspdec_sclass; - return 0; +int +g98_mspdec_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_mspdec_new_(&g98_mspdec, device, index, pengine); } - -struct nvkm_oclass -g98_mspdec_oclass = { - .handle = NV_ENGINE(MSPDEC, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g98_mspdec_ctor, - .dtor = _nvkm_falcon_dtor, - .init = g98_mspdec_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c index c814a5f65..371fd6c3c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c @@ -21,89 +21,31 @@ * * Authors: Maarten Lankhorst */ -#include -#include +#include "priv.h" -struct gf100_mspdec_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * MSPDEC object classes - ******************************************************************************/ - -static struct nvkm_oclass -gf100_mspdec_sclass[] = { - { 0x90b2, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSPDEC context - ******************************************************************************/ - -static struct nvkm_oclass -gf100_mspdec_cclass = { - .handle = NV_ENGCTX(MSPDEC, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSPDEC engine/subdev functions - ******************************************************************************/ +#include -static int -gf100_mspdec_init(struct nvkm_object *object) +void +gf100_mspdec_init(struct nvkm_falcon *mspdec) { - struct gf100_mspdec_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x085010, 0x0000fff2); - nv_wr32(priv, 0x08501c, 0x0000fff2); - return 0; + struct nvkm_device *device = mspdec->engine.subdev.device; + nvkm_wr32(device, 0x085010, 0x0000fff2); + nvkm_wr32(device, 0x08501c, 0x0000fff2); } -static int -gf100_mspdec_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_mspdec_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x085000, true, - "PMSPDEC", "mspdec", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +gf100_mspdec = { + .pmc_enable = 0x00020000, + .init = gf100_mspdec_init, + .sclass = { + { -1, -1, GF100_MSPDEC }, + {} + } +}; - nv_subdev(priv)->unit = 0x00020000; - nv_subdev(priv)->intr = nvkm_falcon_intr; - nv_engine(priv)->cclass = &gf100_mspdec_cclass; - nv_engine(priv)->sclass = gf100_mspdec_sclass; - return 0; +int +gf100_mspdec_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_mspdec_new_(&gf100_mspdec, device, index, pengine); } - -struct nvkm_oclass -gf100_mspdec_oclass = { - .handle = NV_ENGINE(MSPDEC, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_mspdec_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gf100_mspdec_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c index 979920650..de804a15b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c @@ -21,89 +21,23 @@ * * Authors: Ben Skeggs */ -#include -#include - -struct gk104_mspdec_priv { - struct nvkm_falcon base; +#include "priv.h" + +#include + +static const struct nvkm_falcon_func +gk104_mspdec = { + .pmc_enable = 0x00020000, + .init = gf100_mspdec_init, + .sclass = { + { -1, -1, GK104_MSPDEC }, + {} + } }; -/******************************************************************************* - * MSPDEC object classes - ******************************************************************************/ - -static struct nvkm_oclass -gk104_mspdec_sclass[] = { - { 0x95b2, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSPDEC context - ******************************************************************************/ - -static struct nvkm_oclass -gk104_mspdec_cclass = { - .handle = NV_ENGCTX(MSPDEC, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSPDEC engine/subdev functions - ******************************************************************************/ - -static int -gk104_mspdec_init(struct nvkm_object *object) +int +gk104_mspdec_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - struct gk104_mspdec_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x085010, 0x0000fff2); - nv_wr32(priv, 0x08501c, 0x0000fff2); - return 0; -} - -static int -gk104_mspdec_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk104_mspdec_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x085000, true, - "PMSPDEC", "mspdec", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00020000; - nv_subdev(priv)->intr = nvkm_falcon_intr; - nv_engine(priv)->cclass = &gk104_mspdec_cclass; - nv_engine(priv)->sclass = gk104_mspdec_sclass; - return 0; + return nvkm_mspdec_new_(&gk104_mspdec, device, index, pengine); } - -struct nvkm_oclass -gk104_mspdec_oclass = { - .handle = NV_ENGINE(MSPDEC, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_mspdec_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gk104_mspdec_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c new file mode 100644 index 000000000..835631713 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c @@ -0,0 +1,43 @@ +/* + * 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, Maarten Lankhorst, Ilia Mirkin + */ +#include "priv.h" + +#include + +static const struct nvkm_falcon_func +gt215_mspdec = { + .pmc_enable = 0x01020000, + .init = g98_mspdec_init, + .sclass = { + { -1, -1, GT212_MSPDEC }, + {} + } +}; + +int +gt215_mspdec_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_mspdec_new_(>215_mspdec, device, index, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h new file mode 100644 index 000000000..d518af4bc --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h @@ -0,0 +1,11 @@ +#ifndef __NVKM_MSPDEC_PRIV_H__ +#define __NVKM_MSPDEC_PRIV_H__ +#include + +int nvkm_mspdec_new_(const struct nvkm_falcon_func *, struct nvkm_device *, + int index, struct nvkm_engine **); + +void g98_mspdec_init(struct nvkm_falcon *); + +void gf100_mspdec_init(struct nvkm_falcon *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/Kbuild index 4576a9eee..3ea7eafb4 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/Kbuild @@ -1,2 +1,4 @@ +nvkm-y += nvkm/engine/msppp/base.o nvkm-y += nvkm/engine/msppp/g98.o +nvkm-y += nvkm/engine/msppp/gt215.o nvkm-y += nvkm/engine/msppp/gf100.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/base.c new file mode 100644 index 000000000..bfae5e60e --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/base.c @@ -0,0 +1,31 @@ +/* + * 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 + */ +#include "priv.h" + +int +nvkm_msppp_new_(const struct nvkm_falcon_func *func, struct nvkm_device *device, + int index, struct nvkm_engine **pengine) +{ + return nvkm_falcon_new_(func, device, index, true, 0x086000, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c index 7a602a2de..73f633ae2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c @@ -21,89 +21,31 @@ * * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin */ -#include -#include +#include "priv.h" -struct g98_msppp_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * MSPPP object classes - ******************************************************************************/ - -static struct nvkm_oclass -g98_msppp_sclass[] = { - { 0x88b3, &nvkm_object_ofuncs }, - { 0x85b3, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSPPP context - ******************************************************************************/ - -static struct nvkm_oclass -g98_msppp_cclass = { - .handle = NV_ENGCTX(MSPPP, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSPPP engine/subdev functions - ******************************************************************************/ +#include -static int -g98_msppp_init(struct nvkm_object *object) +void +g98_msppp_init(struct nvkm_falcon *msppp) { - struct g98_msppp_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x086010, 0x0000ffd2); - nv_wr32(priv, 0x08601c, 0x0000fff2); - return 0; + struct nvkm_device *device = msppp->engine.subdev.device; + nvkm_wr32(device, 0x086010, 0x0000ffd2); + nvkm_wr32(device, 0x08601c, 0x0000fff2); } -static int -g98_msppp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct g98_msppp_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x086000, true, - "PMSPPP", "msppp", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +g98_msppp = { + .pmc_enable = 0x00400002, + .init = g98_msppp_init, + .sclass = { + { -1, -1, G98_MSPPP }, + {} + } +}; - nv_subdev(priv)->unit = 0x00400002; - nv_engine(priv)->cclass = &g98_msppp_cclass; - nv_engine(priv)->sclass = g98_msppp_sclass; - return 0; +int +g98_msppp_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msppp_new_(&g98_msppp, device, index, pengine); } - -struct nvkm_oclass -g98_msppp_oclass = { - .handle = NV_ENGINE(MSPPP, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g98_msppp_ctor, - .dtor = _nvkm_falcon_dtor, - .init = g98_msppp_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c index 6047baee1..c42c0c07e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c @@ -21,89 +21,31 @@ * * Authors: Maarten Lankhorst */ -#include -#include +#include "priv.h" -struct gf100_msppp_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * MSPPP object classes - ******************************************************************************/ - -static struct nvkm_oclass -gf100_msppp_sclass[] = { - { 0x90b3, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSPPP context - ******************************************************************************/ - -static struct nvkm_oclass -gf100_msppp_cclass = { - .handle = NV_ENGCTX(MSPPP, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSPPP engine/subdev functions - ******************************************************************************/ +#include -static int -gf100_msppp_init(struct nvkm_object *object) +static void +gf100_msppp_init(struct nvkm_falcon *msppp) { - struct gf100_msppp_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x086010, 0x0000fff2); - nv_wr32(priv, 0x08601c, 0x0000fff2); - return 0; + struct nvkm_device *device = msppp->engine.subdev.device; + nvkm_wr32(device, 0x086010, 0x0000fff2); + nvkm_wr32(device, 0x08601c, 0x0000fff2); } -static int -gf100_msppp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_msppp_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x086000, true, - "PMSPPP", "msppp", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +gf100_msppp = { + .pmc_enable = 0x00000002, + .init = gf100_msppp_init, + .sclass = { + { -1, -1, GF100_MSPPP }, + {} + } +}; - nv_subdev(priv)->unit = 0x00000002; - nv_subdev(priv)->intr = nvkm_falcon_intr; - nv_engine(priv)->cclass = &gf100_msppp_cclass; - nv_engine(priv)->sclass = gf100_msppp_sclass; - return 0; +int +gf100_msppp_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msppp_new_(&gf100_msppp, device, index, pengine); } - -struct nvkm_oclass -gf100_msppp_oclass = { - .handle = NV_ENGINE(MSPPP, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_msppp_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gf100_msppp_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c new file mode 100644 index 000000000..00e7795f1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c @@ -0,0 +1,43 @@ +/* + * 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, Maarten Lankhorst, Ilia Mirkin + */ +#include "priv.h" + +#include + +static const struct nvkm_falcon_func +gt215_msppp = { + .pmc_enable = 0x00400002, + .init = g98_msppp_init, + .sclass = { + { -1, -1, GT212_MSPPP }, + {} + } +}; + +int +gt215_msppp_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msppp_new_(>215_msppp, device, index, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h new file mode 100644 index 000000000..37a91f9d9 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h @@ -0,0 +1,9 @@ +#ifndef __NVKM_MSPPP_PRIV_H__ +#define __NVKM_MSPPP_PRIV_H__ +#include + +int nvkm_msppp_new_(const struct nvkm_falcon_func *, struct nvkm_device *, + int index, struct nvkm_engine **); + +void g98_msppp_init(struct nvkm_falcon *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/Kbuild index 0c9811009..28c8ecd27 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/Kbuild @@ -1,3 +1,6 @@ +nvkm-y += nvkm/engine/msvld/base.o nvkm-y += nvkm/engine/msvld/g98.o +nvkm-y += nvkm/engine/msvld/gt215.o +nvkm-y += nvkm/engine/msvld/mcp89.o nvkm-y += nvkm/engine/msvld/gf100.o nvkm-y += nvkm/engine/msvld/gk104.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/base.c new file mode 100644 index 000000000..745bbb653 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/base.c @@ -0,0 +1,31 @@ +/* + * 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 + */ +#include "priv.h" + +int +nvkm_msvld_new_(const struct nvkm_falcon_func *func, struct nvkm_device *device, + int index, struct nvkm_engine **pengine) +{ + return nvkm_falcon_new_(func, device, index, true, 0x084000, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c index c8a6b4ef5..47e2929bf 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c @@ -21,90 +21,31 @@ * * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin */ -#include -#include +#include "priv.h" -struct g98_msvld_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * MSVLD object classes - ******************************************************************************/ - -static struct nvkm_oclass -g98_msvld_sclass[] = { - { 0x88b1, &nvkm_object_ofuncs }, - { 0x85b1, &nvkm_object_ofuncs }, - { 0x86b1, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSVLD context - ******************************************************************************/ - -static struct nvkm_oclass -g98_msvld_cclass = { - .handle = NV_ENGCTX(MSVLD, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSVLD engine/subdev functions - ******************************************************************************/ +#include -static int -g98_msvld_init(struct nvkm_object *object) +void +g98_msvld_init(struct nvkm_falcon *msvld) { - struct g98_msvld_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x084010, 0x0000ffd2); - nv_wr32(priv, 0x08401c, 0x0000fff2); - return 0; + struct nvkm_device *device = msvld->engine.subdev.device; + nvkm_wr32(device, 0x084010, 0x0000ffd2); + nvkm_wr32(device, 0x08401c, 0x0000fff2); } -static int -g98_msvld_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct g98_msvld_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x084000, true, - "PMSVLD", "msvld", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +g98_msvld = { + .pmc_enable = 0x04008000, + .init = g98_msvld_init, + .sclass = { + { -1, -1, G98_MSVLD }, + {} + } +}; - nv_subdev(priv)->unit = 0x04008000; - nv_engine(priv)->cclass = &g98_msvld_cclass; - nv_engine(priv)->sclass = g98_msvld_sclass; - return 0; +int +g98_msvld_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msvld_new_(&g98_msvld, device, index, pengine); } - -struct nvkm_oclass -g98_msvld_oclass = { - .handle = NV_ENGINE(MSVLD, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g98_msvld_ctor, - .dtor = _nvkm_falcon_dtor, - .init = g98_msvld_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c index b8d1e0f52..1ac581ba9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c @@ -21,89 +21,31 @@ * * Authors: Maarten Lankhorst */ -#include -#include +#include "priv.h" -struct gf100_msvld_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * MSVLD object classes - ******************************************************************************/ - -static struct nvkm_oclass -gf100_msvld_sclass[] = { - { 0x90b1, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSVLD context - ******************************************************************************/ - -static struct nvkm_oclass -gf100_msvld_cclass = { - .handle = NV_ENGCTX(MSVLD, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSVLD engine/subdev functions - ******************************************************************************/ +#include -static int -gf100_msvld_init(struct nvkm_object *object) +void +gf100_msvld_init(struct nvkm_falcon *msvld) { - struct gf100_msvld_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x084010, 0x0000fff2); - nv_wr32(priv, 0x08401c, 0x0000fff2); - return 0; + struct nvkm_device *device = msvld->engine.subdev.device; + nvkm_wr32(device, 0x084010, 0x0000fff2); + nvkm_wr32(device, 0x08401c, 0x0000fff2); } -static int -gf100_msvld_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_msvld_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x084000, true, - "PMSVLD", "msvld", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_falcon_func +gf100_msvld = { + .pmc_enable = 0x00008000, + .init = gf100_msvld_init, + .sclass = { + { -1, -1, GF100_MSVLD }, + {} + } +}; - nv_subdev(priv)->unit = 0x00008000; - nv_subdev(priv)->intr = nvkm_falcon_intr; - nv_engine(priv)->cclass = &gf100_msvld_cclass; - nv_engine(priv)->sclass = gf100_msvld_sclass; - return 0; +int +gf100_msvld_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msvld_new_(&gf100_msvld, device, index, pengine); } - -struct nvkm_oclass -gf100_msvld_oclass = { - .handle = NV_ENGINE(MSVLD, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_msvld_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gf100_msvld_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c index a0b092783..4bba16e0f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c @@ -21,89 +21,23 @@ * * Authors: Ben Skeggs */ -#include -#include - -struct gk104_msvld_priv { - struct nvkm_falcon base; +#include "priv.h" + +#include + +static const struct nvkm_falcon_func +gk104_msvld = { + .pmc_enable = 0x00008000, + .init = gf100_msvld_init, + .sclass = { + { -1, -1, GK104_MSVLD }, + {} + } }; -/******************************************************************************* - * MSVLD object classes - ******************************************************************************/ - -static struct nvkm_oclass -gk104_msvld_sclass[] = { - { 0x95b1, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PMSVLD context - ******************************************************************************/ - -static struct nvkm_oclass -gk104_msvld_cclass = { - .handle = NV_ENGCTX(MSVLD, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PMSVLD engine/subdev functions - ******************************************************************************/ - -static int -gk104_msvld_init(struct nvkm_object *object) +int +gk104_msvld_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - struct gk104_msvld_priv *priv = (void *)object; - int ret; - - ret = nvkm_falcon_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x084010, 0x0000fff2); - nv_wr32(priv, 0x08401c, 0x0000fff2); - return 0; -} - -static int -gk104_msvld_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk104_msvld_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x084000, true, - "PMSVLD", "msvld", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00008000; - nv_subdev(priv)->intr = nvkm_falcon_intr; - nv_engine(priv)->cclass = &gk104_msvld_cclass; - nv_engine(priv)->sclass = gk104_msvld_sclass; - return 0; + return nvkm_msvld_new_(&gk104_msvld, device, index, pengine); } - -struct nvkm_oclass -gk104_msvld_oclass = { - .handle = NV_ENGINE(MSVLD, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_msvld_ctor, - .dtor = _nvkm_falcon_dtor, - .init = gk104_msvld_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c new file mode 100644 index 000000000..e17cb5605 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c @@ -0,0 +1,43 @@ +/* + * 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, Maarten Lankhorst, Ilia Mirkin + */ +#include "priv.h" + +#include + +static const struct nvkm_falcon_func +gt215_msvld = { + .pmc_enable = 0x04008000, + .init = g98_msvld_init, + .sclass = { + { -1, -1, GT212_MSVLD }, + {} + } +}; + +int +gt215_msvld_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msvld_new_(>215_msvld, device, index, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c new file mode 100644 index 000000000..511800f6a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c @@ -0,0 +1,43 @@ +/* + * 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, Maarten Lankhorst, Ilia Mirkin + */ +#include "priv.h" + +#include + +static const struct nvkm_falcon_func +mcp89_msvld = { + .pmc_enable = 0x04008000, + .init = g98_msvld_init, + .sclass = { + { -1, -1, IGT21A_MSVLD }, + {} + } +}; + +int +mcp89_msvld_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) +{ + return nvkm_msvld_new_(&mcp89_msvld, device, index, pengine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h new file mode 100644 index 000000000..9dc1da67d --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h @@ -0,0 +1,11 @@ +#ifndef __NVKM_MSVLD_PRIV_H__ +#define __NVKM_MSVLD_PRIV_H__ +#include + +int nvkm_msvld_new_(const struct nvkm_falcon_func *, struct nvkm_device *, + int index, struct nvkm_engine **); + +void g98_msvld_init(struct nvkm_falcon *); + +void gf100_msvld_init(struct nvkm_falcon *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild index 413b6091e..1614d385f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild @@ -1,9 +1,10 @@ nvkm-y += nvkm/engine/pm/base.o -nvkm-y += nvkm/engine/pm/daemon.o nvkm-y += nvkm/engine/pm/nv40.o nvkm-y += nvkm/engine/pm/nv50.o nvkm-y += nvkm/engine/pm/g84.o +nvkm-y += nvkm/engine/pm/gt200.o nvkm-y += nvkm/engine/pm/gt215.o nvkm-y += nvkm/engine/pm/gf100.o +nvkm-y += nvkm/engine/pm/gf108.o +nvkm-y += nvkm/engine/pm/gf117.o nvkm-y += nvkm/engine/pm/gk104.o -nvkm-y += nvkm/engine/pm/gk110.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index 2006c4459..2721592d3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c @@ -24,368 +24,751 @@ #include "priv.h" #include -#include #include #include #include #include -#define QUAD_MASK 0x0f -#define QUAD_FREE 0x01 +static u8 +nvkm_pm_count_perfdom(struct nvkm_pm *pm) +{ + struct nvkm_perfdom *dom; + u8 domain_nr = 0; -static struct nvkm_perfsig * -nvkm_perfsig_find_(struct nvkm_perfdom *dom, const char *name, u32 size) + list_for_each_entry(dom, &pm->domains, head) + domain_nr++; + return domain_nr; +} + +static u16 +nvkm_perfdom_count_perfsig(struct nvkm_perfdom *dom) { - char path[64]; + u16 signal_nr = 0; int i; - if (name[0] != '/') { + if (dom) { for (i = 0; i < dom->signal_nr; i++) { - if ( dom->signal[i].name && - !strncmp(name, dom->signal[i].name, size)) - return &dom->signal[i]; - } - } else { - for (i = 0; i < dom->signal_nr; i++) { - snprintf(path, sizeof(path), "/%s/%02x", dom->name, i); - if (!strncmp(name, path, size)) - return &dom->signal[i]; + if (dom->signal[i].name) + signal_nr++; } } + return signal_nr; +} +static struct nvkm_perfdom * +nvkm_perfdom_find(struct nvkm_pm *pm, int di) +{ + struct nvkm_perfdom *dom; + int tmp = 0; + + list_for_each_entry(dom, &pm->domains, head) { + if (tmp++ == di) + return dom; + } return NULL; } struct nvkm_perfsig * -nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size, - struct nvkm_perfdom **pdom) +nvkm_perfsig_find(struct nvkm_pm *pm, u8 di, u8 si, struct nvkm_perfdom **pdom) { struct nvkm_perfdom *dom = *pdom; - struct nvkm_perfsig *sig; if (dom == NULL) { - list_for_each_entry(dom, &ppm->domains, head) { - sig = nvkm_perfsig_find_(dom, name, size); - if (sig) { - *pdom = dom; - return sig; - } - } + dom = nvkm_perfdom_find(pm, di); + if (dom == NULL) + return NULL; + *pdom = dom; + } + if (!dom->signal[si].name) return NULL; - } + return &dom->signal[si]; +} - return nvkm_perfsig_find_(dom, name, size); +static u8 +nvkm_perfsig_count_perfsrc(struct nvkm_perfsig *sig) +{ + u8 source_nr = 0, i; + + for (i = 0; i < ARRAY_SIZE(sig->source); i++) { + if (sig->source[i]) + source_nr++; + } + return source_nr; } -struct nvkm_perfctr * -nvkm_perfsig_wrap(struct nvkm_pm *ppm, const char *name, - struct nvkm_perfdom **pdom) +static struct nvkm_perfsrc * +nvkm_perfsrc_find(struct nvkm_pm *pm, struct nvkm_perfsig *sig, int si) { - struct nvkm_perfsig *sig; - struct nvkm_perfctr *ctr; + struct nvkm_perfsrc *src; + bool found = false; + int tmp = 1; /* Sources ID start from 1 */ + u8 i; + + for (i = 0; i < ARRAY_SIZE(sig->source) && sig->source[i]; i++) { + if (sig->source[i] == si) { + found = true; + break; + } + } - sig = nvkm_perfsig_find(ppm, name, strlen(name), pdom); - if (!sig) - return NULL; + if (found) { + list_for_each_entry(src, &pm->sources, head) { + if (tmp++ == si) + return src; + } + } - ctr = kzalloc(sizeof(*ctr), GFP_KERNEL); - if (ctr) { - ctr->signal[0] = sig; - ctr->logic_op = 0xaaaa; + return NULL; +} + +static int +nvkm_perfsrc_enable(struct nvkm_pm *pm, struct nvkm_perfctr *ctr) +{ + struct nvkm_subdev *subdev = &pm->engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_perfdom *dom = NULL; + struct nvkm_perfsig *sig; + struct nvkm_perfsrc *src; + u32 mask, value; + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8 && ctr->source[i][j]; j++) { + sig = nvkm_perfsig_find(pm, ctr->domain, + ctr->signal[i], &dom); + if (!sig) + return -EINVAL; + + src = nvkm_perfsrc_find(pm, sig, ctr->source[i][j]); + if (!src) + return -EINVAL; + + /* set enable bit if needed */ + mask = value = 0x00000000; + if (src->enable) + mask = value = 0x80000000; + mask |= (src->mask << src->shift); + value |= ((ctr->source[i][j] >> 32) << src->shift); + + /* enable the source */ + nvkm_mask(device, src->addr, mask, value); + nvkm_debug(subdev, + "enabled source %08x %08x %08x\n", + src->addr, mask, value); + } } + return 0; +} - return ctr; +static int +nvkm_perfsrc_disable(struct nvkm_pm *pm, struct nvkm_perfctr *ctr) +{ + struct nvkm_subdev *subdev = &pm->engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_perfdom *dom = NULL; + struct nvkm_perfsig *sig; + struct nvkm_perfsrc *src; + u32 mask; + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8 && ctr->source[i][j]; j++) { + sig = nvkm_perfsig_find(pm, ctr->domain, + ctr->signal[i], &dom); + if (!sig) + return -EINVAL; + + src = nvkm_perfsrc_find(pm, sig, ctr->source[i][j]); + if (!src) + return -EINVAL; + + /* unset enable bit if needed */ + mask = 0x00000000; + if (src->enable) + mask = 0x80000000; + mask |= (src->mask << src->shift); + + /* disable the source */ + nvkm_mask(device, src->addr, mask, 0); + nvkm_debug(subdev, "disabled source %08x %08x\n", + src->addr, mask); + } + } + return 0; } /******************************************************************************* - * Perfmon object classes + * Perfdom object classes ******************************************************************************/ static int -nvkm_perfctr_query(struct nvkm_object *object, void *data, u32 size) +nvkm_perfdom_init(struct nvkm_perfdom *dom, void *data, u32 size) { union { - struct nvif_perfctr_query_v0 v0; + struct nvif_perfdom_init none; } *args = data; - struct nvkm_device *device = nv_device(object); - struct nvkm_pm *ppm = (void *)object->engine; - struct nvkm_perfdom *dom = NULL, *chk; - const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false); - const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all); - const char *name; - int tmp = 0, di, si; + struct nvkm_object *object = &dom->object; + struct nvkm_pm *pm = dom->perfmon->pm; + int ret, i; + + nvif_ioctl(object, "perfdom init size %d\n", size); + if (nvif_unvers(args->none)) { + nvif_ioctl(object, "perfdom init\n"); + } else + return ret; + + for (i = 0; i < 4; i++) { + if (dom->ctr[i]) { + dom->func->init(pm, dom, dom->ctr[i]); + + /* enable sources */ + nvkm_perfsrc_enable(pm, dom->ctr[i]); + } + } + + /* start next batch of counters for sampling */ + dom->func->next(pm, dom); + return 0; +} + +static int +nvkm_perfdom_sample(struct nvkm_perfdom *dom, void *data, u32 size) +{ + union { + struct nvif_perfdom_sample none; + } *args = data; + struct nvkm_object *object = &dom->object; + struct nvkm_pm *pm = dom->perfmon->pm; int ret; - nv_ioctl(object, "perfctr query size %d\n", size); + nvif_ioctl(object, "perfdom sample size %d\n", size); + if (nvif_unvers(args->none)) { + nvif_ioctl(object, "perfdom sample\n"); + } else + return ret; + pm->sequence++; + + /* sample previous batch of counters */ + list_for_each_entry(dom, &pm->domains, head) + dom->func->next(pm, dom); + + return 0; +} + +static int +nvkm_perfdom_read(struct nvkm_perfdom *dom, void *data, u32 size) +{ + union { + struct nvif_perfdom_read_v0 v0; + } *args = data; + struct nvkm_object *object = &dom->object; + struct nvkm_pm *pm = dom->perfmon->pm; + int ret, i; + + nvif_ioctl(object, "perfdom read size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "perfctr query vers %d iter %08x\n", - args->v0.version, args->v0.iter); - di = (args->v0.iter & 0xff000000) >> 24; - si = (args->v0.iter & 0x00ffffff) - 1; + nvif_ioctl(object, "perfdom read vers %d\n", args->v0.version); } else return ret; - list_for_each_entry(chk, &ppm->domains, head) { - if (tmp++ == di) { - dom = chk; - break; - } + for (i = 0; i < 4; i++) { + if (dom->ctr[i]) + dom->func->read(pm, dom, dom->ctr[i]); } - if (dom == NULL || si >= (int)dom->signal_nr) - return -EINVAL; + if (!dom->clk) + return -EAGAIN; - if (si >= 0) { - if (raw || !(name = dom->signal[si].name)) { - snprintf(args->v0.name, sizeof(args->v0.name), - "/%s/%02x", dom->name, si); - } else { - strncpy(args->v0.name, name, sizeof(args->v0.name)); + for (i = 0; i < 4; i++) + if (dom->ctr[i]) + args->v0.ctr[i] = dom->ctr[i]->ctr; + args->v0.clk = dom->clk; + return 0; +} + +static int +nvkm_perfdom_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + struct nvkm_perfdom *dom = nvkm_perfdom(object); + switch (mthd) { + case NVIF_PERFDOM_V0_INIT: + return nvkm_perfdom_init(dom, data, size); + case NVIF_PERFDOM_V0_SAMPLE: + return nvkm_perfdom_sample(dom, data, size); + case NVIF_PERFDOM_V0_READ: + return nvkm_perfdom_read(dom, data, size); + default: + break; + } + return -EINVAL; +} + +static void * +nvkm_perfdom_dtor(struct nvkm_object *object) +{ + struct nvkm_perfdom *dom = nvkm_perfdom(object); + struct nvkm_pm *pm = dom->perfmon->pm; + int i; + + for (i = 0; i < 4; i++) { + struct nvkm_perfctr *ctr = dom->ctr[i]; + if (ctr) { + nvkm_perfsrc_disable(pm, ctr); + if (ctr->head.next) + list_del(&ctr->head); } + kfree(ctr); } - do { - while (++si < dom->signal_nr) { - if (all || dom->signal[si].name) { - args->v0.iter = (di << 24) | ++si; - return 0; - } + return dom; +} + +static int +nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot, u8 domain, + struct nvkm_perfsig *signal[4], u64 source[4][8], + u16 logic_op, struct nvkm_perfctr **pctr) +{ + struct nvkm_perfctr *ctr; + int i, j; + + if (!dom) + return -EINVAL; + + ctr = *pctr = kzalloc(sizeof(*ctr), GFP_KERNEL); + if (!ctr) + return -ENOMEM; + + ctr->domain = domain; + ctr->logic_op = logic_op; + ctr->slot = slot; + for (i = 0; i < 4; i++) { + if (signal[i]) { + ctr->signal[i] = signal[i] - dom->signal; + for (j = 0; j < 8; j++) + ctr->source[i][j] = source[i][j]; } - si = -1; - di = di + 1; - dom = list_entry(dom->head.next, typeof(*dom), head); - } while (&dom->head != &ppm->domains); + } + list_add_tail(&ctr->head, &dom->list); - args->v0.iter = 0xffffffff; return 0; } +static const struct nvkm_object_func +nvkm_perfdom = { + .dtor = nvkm_perfdom_dtor, + .mthd = nvkm_perfdom_mthd, +}; + static int -nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size) +nvkm_perfdom_new_(struct nvkm_perfmon *perfmon, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) { union { - struct nvif_perfctr_sample none; + struct nvif_perfdom_v0 v0; } *args = data; - struct nvkm_pm *ppm = (void *)object->engine; - struct nvkm_perfctr *ctr, *tmp; + struct nvkm_pm *pm = perfmon->pm; + struct nvkm_object *parent = oclass->parent; + struct nvkm_perfdom *sdom = NULL; + struct nvkm_perfctr *ctr[4] = {}; struct nvkm_perfdom *dom; + int c, s, m; int ret; - nv_ioctl(object, "perfctr sample size %d\n", size); - if (nvif_unvers(args->none)) { - nv_ioctl(object, "perfctr sample\n"); + nvif_ioctl(parent, "create perfdom size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(parent, "create perfdom vers %d dom %d mode %02x\n", + args->v0.version, args->v0.domain, args->v0.mode); } else return ret; - ppm->sequence++; - - list_for_each_entry(dom, &ppm->domains, head) { - /* sample previous batch of counters */ - if (dom->quad != QUAD_MASK) { - dom->func->next(ppm, dom); - tmp = NULL; - while (!list_empty(&dom->list)) { - ctr = list_first_entry(&dom->list, - typeof(*ctr), head); - if (ctr->slot < 0) break; - if ( tmp && tmp == ctr) break; - if (!tmp) tmp = ctr; - dom->func->read(ppm, dom, ctr); - ctr->slot = -1; - list_move_tail(&ctr->head, &dom->list); - } - } - dom->quad = QUAD_MASK; - - /* setup next batch of counters for sampling */ - list_for_each_entry(ctr, &dom->list, head) { - ctr->slot = ffs(dom->quad) - 1; - if (ctr->slot < 0) - break; - dom->quad &= ~(QUAD_FREE << ctr->slot); - dom->func->init(ppm, dom, ctr); + for (c = 0; c < ARRAY_SIZE(args->v0.ctr); c++) { + struct nvkm_perfsig *sig[4] = {}; + u64 src[4][8] = {}; + + for (s = 0; s < ARRAY_SIZE(args->v0.ctr[c].signal); s++) { + sig[s] = nvkm_perfsig_find(pm, args->v0.domain, + args->v0.ctr[c].signal[s], + &sdom); + if (args->v0.ctr[c].signal[s] && !sig[s]) + return -EINVAL; + + for (m = 0; m < 8; m++) { + src[s][m] = args->v0.ctr[c].source[s][m]; + if (src[s][m] && !nvkm_perfsrc_find(pm, sig[s], + src[s][m])) + return -EINVAL; + } } - if (dom->quad != QUAD_MASK) - dom->func->next(ppm, dom); + ret = nvkm_perfctr_new(sdom, c, args->v0.domain, sig, src, + args->v0.ctr[c].logic_op, &ctr[c]); + if (ret) + return ret; } + if (!sdom) + return -EINVAL; + + if (!(dom = kzalloc(sizeof(*dom), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nvkm_perfdom, oclass, &dom->object); + dom->perfmon = perfmon; + *pobject = &dom->object; + + dom->func = sdom->func; + dom->addr = sdom->addr; + dom->mode = args->v0.mode; + for (c = 0; c < ARRAY_SIZE(ctr); c++) + dom->ctr[c] = ctr[c]; return 0; } +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ static int -nvkm_perfctr_read(struct nvkm_object *object, void *data, u32 size) +nvkm_perfmon_mthd_query_domain(struct nvkm_perfmon *perfmon, + void *data, u32 size) { union { - struct nvif_perfctr_read_v0 v0; + struct nvif_perfmon_query_domain_v0 v0; } *args = data; - struct nvkm_perfctr *ctr = (void *)object; - int ret; + struct nvkm_object *object = &perfmon->object; + struct nvkm_pm *pm = perfmon->pm; + struct nvkm_perfdom *dom; + u8 domain_nr; + int di, ret; - nv_ioctl(object, "perfctr read size %d\n", size); + nvif_ioctl(object, "perfmon query domain size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(object, "perfctr read vers %d\n", args->v0.version); + nvif_ioctl(object, "perfmon domain vers %d iter %02x\n", + args->v0.version, args->v0.iter); + di = (args->v0.iter & 0xff) - 1; } else return ret; - if (!ctr->clk) - return -EAGAIN; + domain_nr = nvkm_pm_count_perfdom(pm); + if (di >= (int)domain_nr) + return -EINVAL; + + if (di >= 0) { + dom = nvkm_perfdom_find(pm, di); + if (dom == NULL) + return -EINVAL; + + args->v0.id = di; + args->v0.signal_nr = nvkm_perfdom_count_perfsig(dom); + strncpy(args->v0.name, dom->name, sizeof(args->v0.name)); + + /* Currently only global counters (PCOUNTER) are implemented + * but this will be different for local counters (MP). */ + args->v0.counter_nr = 4; + } - args->v0.clk = ctr->clk; - args->v0.ctr = ctr->ctr; + if (++di < domain_nr) { + args->v0.iter = ++di; + return 0; + } + + args->v0.iter = 0xff; return 0; } static int -nvkm_perfctr_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +nvkm_perfmon_mthd_query_signal(struct nvkm_perfmon *perfmon, + void *data, u32 size) { - switch (mthd) { - case NVIF_PERFCTR_V0_QUERY: - return nvkm_perfctr_query(object, data, size); - case NVIF_PERFCTR_V0_SAMPLE: - return nvkm_perfctr_sample(object, data, size); - case NVIF_PERFCTR_V0_READ: - return nvkm_perfctr_read(object, data, size); - default: - break; + union { + struct nvif_perfmon_query_signal_v0 v0; + } *args = data; + struct nvkm_object *object = &perfmon->object; + struct nvkm_pm *pm = perfmon->pm; + struct nvkm_device *device = pm->engine.subdev.device; + struct nvkm_perfdom *dom; + struct nvkm_perfsig *sig; + const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false); + const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all); + int ret, si; + + nvif_ioctl(object, "perfmon query signal size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nvif_ioctl(object, + "perfmon query signal vers %d dom %d iter %04x\n", + args->v0.version, args->v0.domain, args->v0.iter); + si = (args->v0.iter & 0xffff) - 1; + } else + return ret; + + dom = nvkm_perfdom_find(pm, args->v0.domain); + if (dom == NULL || si >= (int)dom->signal_nr) + return -EINVAL; + + if (si >= 0) { + sig = &dom->signal[si]; + if (raw || !sig->name) { + snprintf(args->v0.name, sizeof(args->v0.name), + "/%s/%02x", dom->name, si); + } else { + strncpy(args->v0.name, sig->name, + sizeof(args->v0.name)); + } + + args->v0.signal = si; + args->v0.source_nr = nvkm_perfsig_count_perfsrc(sig); } - return -EINVAL; -} -static void -nvkm_perfctr_dtor(struct nvkm_object *object) -{ - struct nvkm_perfctr *ctr = (void *)object; - if (ctr->head.next) - list_del(&ctr->head); - nvkm_object_destroy(&ctr->base); + while (++si < dom->signal_nr) { + if (all || dom->signal[si].name) { + args->v0.iter = ++si; + return 0; + } + } + + args->v0.iter = 0xffff; + return 0; } static int -nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_perfmon_mthd_query_source(struct nvkm_perfmon *perfmon, + void *data, u32 size) { union { - struct nvif_perfctr_v0 v0; + struct nvif_perfmon_query_source_v0 v0; } *args = data; - struct nvkm_pm *ppm = (void *)engine; + struct nvkm_object *object = &perfmon->object; + struct nvkm_pm *pm = perfmon->pm; struct nvkm_perfdom *dom = NULL; - struct nvkm_perfsig *sig[4] = {}; - struct nvkm_perfctr *ctr; - int ret, i; + struct nvkm_perfsig *sig; + struct nvkm_perfsrc *src; + u8 source_nr = 0; + int si, ret; - nv_ioctl(parent, "create perfctr size %d\n", size); + nvif_ioctl(object, "perfmon query source size %d\n", size); if (nvif_unpack(args->v0, 0, 0, false)) { - nv_ioctl(parent, "create perfctr vers %d logic_op %04x\n", - args->v0.version, args->v0.logic_op); + nvif_ioctl(object, + "perfmon source vers %d dom %d sig %02x iter %02x\n", + args->v0.version, args->v0.domain, args->v0.signal, + args->v0.iter); + si = (args->v0.iter & 0xff) - 1; } else return ret; - for (i = 0; i < ARRAY_SIZE(args->v0.name) && args->v0.name[i][0]; i++) { - sig[i] = nvkm_perfsig_find(ppm, args->v0.name[i], - strnlen(args->v0.name[i], - sizeof(args->v0.name[i])), - &dom); - if (!sig[i]) + sig = nvkm_perfsig_find(pm, args->v0.domain, args->v0.signal, &dom); + if (!sig) + return -EINVAL; + + source_nr = nvkm_perfsig_count_perfsrc(sig); + if (si >= (int)source_nr) + return -EINVAL; + + if (si >= 0) { + src = nvkm_perfsrc_find(pm, sig, sig->source[si]); + if (!src) return -EINVAL; + + args->v0.source = sig->source[si]; + args->v0.mask = src->mask; + strncpy(args->v0.name, src->name, sizeof(args->v0.name)); } - ret = nvkm_object_create(parent, engine, oclass, 0, &ctr); - *pobject = nv_object(ctr); - if (ret) - return ret; + if (++si < source_nr) { + args->v0.iter = ++si; + return 0; + } - ctr->slot = -1; - ctr->logic_op = args->v0.logic_op; - ctr->signal[0] = sig[0]; - ctr->signal[1] = sig[1]; - ctr->signal[2] = sig[2]; - ctr->signal[3] = sig[3]; - if (dom) - list_add_tail(&ctr->head, &dom->list); + args->v0.iter = 0xff; return 0; } -static struct nvkm_ofuncs -nvkm_perfctr_ofuncs = { - .ctor = nvkm_perfctr_ctor, - .dtor = nvkm_perfctr_dtor, - .init = nvkm_object_init, - .fini = nvkm_object_fini, - .mthd = nvkm_perfctr_mthd, -}; +static int +nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + struct nvkm_perfmon *perfmon = nvkm_perfmon(object); + switch (mthd) { + case NVIF_PERFMON_V0_QUERY_DOMAIN: + return nvkm_perfmon_mthd_query_domain(perfmon, data, size); + case NVIF_PERFMON_V0_QUERY_SIGNAL: + return nvkm_perfmon_mthd_query_signal(perfmon, data, size); + case NVIF_PERFMON_V0_QUERY_SOURCE: + return nvkm_perfmon_mthd_query_source(perfmon, data, size); + default: + break; + } + return -EINVAL; +} + +static int +nvkm_perfmon_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_perfmon *perfmon = nvkm_perfmon(oclass->parent); + return nvkm_perfdom_new_(perfmon, oclass, data, size, pobject); +} + +static int +nvkm_perfmon_child_get(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + if (index == 0) { + oclass->base.oclass = NVIF_IOCTL_NEW_V0_PERFDOM; + oclass->base.minver = 0; + oclass->base.maxver = 0; + oclass->ctor = nvkm_perfmon_child_new; + return 0; + } + return -EINVAL; +} + +static void * +nvkm_perfmon_dtor(struct nvkm_object *object) +{ + struct nvkm_perfmon *perfmon = nvkm_perfmon(object); + struct nvkm_pm *pm = perfmon->pm; + mutex_lock(&pm->engine.subdev.mutex); + if (pm->perfmon == &perfmon->object) + pm->perfmon = NULL; + mutex_unlock(&pm->engine.subdev.mutex); + return perfmon; +} -struct nvkm_oclass -nvkm_pm_sclass[] = { - { .handle = NVIF_IOCTL_NEW_V0_PERFCTR, - .ofuncs = &nvkm_perfctr_ofuncs, - }, - {}, +static const struct nvkm_object_func +nvkm_perfmon = { + .dtor = nvkm_perfmon_dtor, + .mthd = nvkm_perfmon_mthd, + .sclass = nvkm_perfmon_child_get, }; -/******************************************************************************* - * PPM context - ******************************************************************************/ -static void -nvkm_perfctx_dtor(struct nvkm_object *object) +static int +nvkm_perfmon_new(struct nvkm_pm *pm, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) { - struct nvkm_pm *ppm = (void *)object->engine; - mutex_lock(&nv_subdev(ppm)->mutex); - nvkm_engctx_destroy(&ppm->context->base); - ppm->context = NULL; - mutex_unlock(&nv_subdev(ppm)->mutex); + struct nvkm_perfmon *perfmon; + + if (!(perfmon = kzalloc(sizeof(*perfmon), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nvkm_perfmon, oclass, &perfmon->object); + perfmon->pm = pm; + *pobject = &perfmon->object; + return 0; } +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + static int -nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_pm_oclass_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) { - struct nvkm_pm *ppm = (void *)engine; - struct nvkm_perfctx *ctx; + struct nvkm_pm *pm = nvkm_pm(oclass->engine); int ret; - ret = nvkm_engctx_create(parent, engine, oclass, NULL, 0, 0, 0, &ctx); - *pobject = nv_object(ctx); + ret = nvkm_perfmon_new(pm, oclass, data, size, pobject); if (ret) return ret; - mutex_lock(&nv_subdev(ppm)->mutex); - if (ppm->context == NULL) - ppm->context = ctx; - mutex_unlock(&nv_subdev(ppm)->mutex); + mutex_lock(&pm->engine.subdev.mutex); + if (pm->perfmon == NULL) + pm->perfmon = *pobject; + ret = (pm->perfmon == *pobject) ? 0 : -EBUSY; + mutex_unlock(&pm->engine.subdev.mutex); + return ret; +} - if (ctx != ppm->context) - return -EBUSY; +static const struct nvkm_device_oclass +nvkm_pm_oclass = { + .base.oclass = NVIF_IOCTL_NEW_V0_PERFMON, + .base.minver = -1, + .base.maxver = -1, + .ctor = nvkm_pm_oclass_new, +}; - return 0; +static int +nvkm_pm_oclass_get(struct nvkm_oclass *oclass, int index, + const struct nvkm_device_oclass **class) +{ + if (index == 0) { + oclass->base = nvkm_pm_oclass.base; + *class = &nvkm_pm_oclass; + return index; + } + return 1; } -struct nvkm_oclass -nvkm_pm_cclass = { - .handle = NV_ENGCTX(PM, 0x00), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nvkm_perfctx_ctor, - .dtor = nvkm_perfctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - }, -}; +int +nvkm_perfsrc_new(struct nvkm_pm *pm, struct nvkm_perfsig *sig, + const struct nvkm_specsrc *spec) +{ + const struct nvkm_specsrc *ssrc; + const struct nvkm_specmux *smux; + struct nvkm_perfsrc *src; + u8 source_nr = 0; + + if (!spec) { + /* No sources are defined for this signal. */ + return 0; + } + + ssrc = spec; + while (ssrc->name) { + smux = ssrc->mux; + while (smux->name) { + bool found = false; + u8 source_id = 0; + u32 len; + + list_for_each_entry(src, &pm->sources, head) { + if (src->addr == ssrc->addr && + src->shift == smux->shift) { + found = true; + break; + } + source_id++; + } + + if (!found) { + src = kzalloc(sizeof(*src), GFP_KERNEL); + if (!src) + return -ENOMEM; + + src->addr = ssrc->addr; + src->mask = smux->mask; + src->shift = smux->shift; + src->enable = smux->enable; + + len = strlen(ssrc->name) + + strlen(smux->name) + 2; + src->name = kzalloc(len, GFP_KERNEL); + if (!src->name) { + kfree(src); + return -ENOMEM; + } + snprintf(src->name, len, "%s_%s", ssrc->name, + smux->name); + + list_add_tail(&src->head, &pm->sources); + } + + sig->source[source_nr++] = source_id + 1; + smux++; + } + ssrc++; + } + + return 0; +} -/******************************************************************************* - * PPM engine/subdev functions - ******************************************************************************/ int -nvkm_perfdom_new(struct nvkm_pm *ppm, const char *name, u32 mask, +nvkm_perfdom_new(struct nvkm_pm *pm, const char *name, u32 mask, u32 base, u32 size_unit, u32 size_domain, const struct nvkm_specdom *spec) { const struct nvkm_specdom *sdom; const struct nvkm_specsig *ssig; struct nvkm_perfdom *dom; - int i; + int ret, i; for (i = 0; i == 0 || mask; i++) { u32 addr = base + (i * size_unit); @@ -408,16 +791,20 @@ nvkm_perfdom_new(struct nvkm_pm *ppm, const char *name, u32 mask, "%s/%02x", name, (int)(sdom - spec)); } - list_add_tail(&dom->head, &ppm->domains); + list_add_tail(&dom->head, &pm->domains); INIT_LIST_HEAD(&dom->list); dom->func = sdom->func; dom->addr = addr; - dom->quad = QUAD_MASK; dom->signal_nr = sdom->signal_nr; ssig = (sdom++)->signal; while (ssig->name) { - dom->signal[ssig->signal].name = ssig->name; + struct nvkm_perfsig *sig = + &dom->signal[ssig->signal]; + sig->name = ssig->name; + ret = nvkm_perfsrc_new(pm, sig, ssig->source); + if (ret) + return ret; ssig++; } @@ -430,47 +817,49 @@ nvkm_perfdom_new(struct nvkm_pm *ppm, const char *name, u32 mask, return 0; } -int -_nvkm_pm_fini(struct nvkm_object *object, bool suspend) -{ - struct nvkm_pm *ppm = (void *)object; - return nvkm_engine_fini(&ppm->base, suspend); -} - -int -_nvkm_pm_init(struct nvkm_object *object) +static int +nvkm_pm_fini(struct nvkm_engine *engine, bool suspend) { - struct nvkm_pm *ppm = (void *)object; - return nvkm_engine_init(&ppm->base); + struct nvkm_pm *pm = nvkm_pm(engine); + if (pm->func->fini) + pm->func->fini(pm); + return 0; } -void -_nvkm_pm_dtor(struct nvkm_object *object) +static void * +nvkm_pm_dtor(struct nvkm_engine *engine) { - struct nvkm_pm *ppm = (void *)object; - struct nvkm_perfdom *dom, *tmp; + struct nvkm_pm *pm = nvkm_pm(engine); + struct nvkm_perfdom *dom, *next_dom; + struct nvkm_perfsrc *src, *next_src; - list_for_each_entry_safe(dom, tmp, &ppm->domains, head) { + list_for_each_entry_safe(dom, next_dom, &pm->domains, head) { list_del(&dom->head); kfree(dom); } - nvkm_engine_destroy(&ppm->base); + list_for_each_entry_safe(src, next_src, &pm->sources, head) { + list_del(&src->head); + kfree(src->name); + kfree(src); + } + + return pm; } +static const struct nvkm_engine_func +nvkm_pm = { + .dtor = nvkm_pm_dtor, + .fini = nvkm_pm_fini, + .base.sclass = nvkm_pm_oclass_get, +}; + int -nvkm_pm_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nvkm_pm_ctor(const struct nvkm_pm_func *func, struct nvkm_device *device, + int index, struct nvkm_pm *pm) { - struct nvkm_pm *ppm; - int ret; - - ret = nvkm_engine_create_(parent, engine, oclass, true, "PPM", - "pm", length, pobject); - ppm = *pobject; - if (ret) - return ret; - - INIT_LIST_HEAD(&ppm->domains); - return 0; + pm->func = func; + INIT_LIST_HEAD(&pm->domains); + INIT_LIST_HEAD(&pm->sources); + return nvkm_engine_ctor(&nvkm_pm, device, index, 0, true, &pm->engine); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/daemon.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/daemon.c deleted file mode 100644 index a7a5f3a3c..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/daemon.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2013 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 "priv.h" - -static void -pwr_perfctr_init(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, - struct nvkm_perfctr *ctr) -{ - u32 mask = 0x00000000; - u32 ctrl = 0x00000001; - int i; - - for (i = 0; i < ARRAY_SIZE(ctr->signal) && ctr->signal[i]; i++) - mask |= 1 << (ctr->signal[i] - dom->signal); - - nv_wr32(ppm, 0x10a504 + (ctr->slot * 0x10), mask); - nv_wr32(ppm, 0x10a50c + (ctr->slot * 0x10), ctrl); - nv_wr32(ppm, 0x10a50c + (ppm->last * 0x10), 0x00000003); -} - -static void -pwr_perfctr_read(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, - struct nvkm_perfctr *ctr) -{ - ctr->ctr = ppm->pwr[ctr->slot]; - ctr->clk = ppm->pwr[ppm->last]; -} - -static void -pwr_perfctr_next(struct nvkm_pm *ppm, struct nvkm_perfdom *dom) -{ - int i; - - for (i = 0; i <= ppm->last; i++) { - ppm->pwr[i] = nv_rd32(ppm, 0x10a508 + (i * 0x10)); - nv_wr32(ppm, 0x10a508 + (i * 0x10), 0x80000000); - } -} - -static const struct nvkm_funcdom -pwr_perfctr_func = { - .init = pwr_perfctr_init, - .read = pwr_perfctr_read, - .next = pwr_perfctr_next, -}; - -const struct nvkm_specdom -gt215_pm_pwr[] = { - { 0x20, (const struct nvkm_specsig[]) { - { 0x00, "pwr_gr_idle" }, - { 0x04, "pwr_bsp_idle" }, - { 0x05, "pwr_vp_idle" }, - { 0x06, "pwr_ppp_idle" }, - { 0x13, "pwr_ce0_idle" }, - {} - }, &pwr_perfctr_func }, - {} -}; - -const struct nvkm_specdom -gf100_pm_pwr[] = { - { 0x20, (const struct nvkm_specsig[]) { - { 0x00, "pwr_gr_idle" }, - { 0x04, "pwr_bsp_idle" }, - { 0x05, "pwr_vp_idle" }, - { 0x06, "pwr_ppp_idle" }, - { 0x13, "pwr_ce0_idle" }, - { 0x14, "pwr_ce1_idle" }, - {} - }, &pwr_perfctr_func }, - {} -}; - -const struct nvkm_specdom -gk104_pm_pwr[] = { - { 0x20, (const struct nvkm_specsig[]) { - { 0x00, "pwr_gr_idle" }, - { 0x04, "pwr_bsp_idle" }, - { 0x05, "pwr_vp_idle" }, - { 0x06, "pwr_ppp_idle" }, - { 0x13, "pwr_ce0_idle" }, - { 0x14, "pwr_ce1_idle" }, - { 0x15, "pwr_ce2_idle" }, - {} - }, &pwr_perfctr_func }, - {} -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c index d54c6705b..6e441ddaf 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c @@ -23,15 +23,121 @@ */ #include "nv40.h" +const struct nvkm_specsrc +g84_vfetch_sources[] = { + { 0x400c0c, (const struct nvkm_specmux[]) { + { 0x3, 0, "unk0" }, + {} + }, "pgraph_vfetch_unk0c" }, + {} +}; + +static const struct nvkm_specsrc +g84_prop_sources[] = { + { 0x408e50, (const struct nvkm_specmux[]) { + { 0x1f, 0, "sel", true }, + {} + }, "pgraph_tpc0_prop_pm_mux" }, + {} +}; + +static const struct nvkm_specsrc +g84_crop_sources[] = { + { 0x407008, (const struct nvkm_specmux[]) { + { 0xf, 0, "sel0", true }, + { 0x7, 16, "sel1", true }, + {} + }, "pgraph_rop0_crop_pm_mux" }, + {} +}; + +static const struct nvkm_specsrc +g84_tex_sources[] = { + { 0x408808, (const struct nvkm_specmux[]) { + { 0xfffff, 0, "unk0" }, + {} + }, "pgraph_tpc0_tex_unk08" }, + {} +}; + static const struct nvkm_specdom g84_pm[] = { { 0x20, (const struct nvkm_specsig[]) { {} }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { + { 0xf0, (const struct nvkm_specsig[]) { + { 0xbd, "pc01_gr_idle" }, + { 0x5e, "pc01_strmout_00" }, + { 0x5f, "pc01_strmout_01" }, + { 0xd2, "pc01_trast_00" }, + { 0xd3, "pc01_trast_01" }, + { 0xd4, "pc01_trast_02" }, + { 0xd5, "pc01_trast_03" }, + { 0xd8, "pc01_trast_04" }, + { 0xd9, "pc01_trast_05" }, + { 0x5c, "pc01_vattr_00" }, + { 0x5d, "pc01_vattr_01" }, + { 0x66, "pc01_vfetch_00", g84_vfetch_sources }, + { 0x67, "pc01_vfetch_01", g84_vfetch_sources }, + { 0x68, "pc01_vfetch_02", g84_vfetch_sources }, + { 0x69, "pc01_vfetch_03", g84_vfetch_sources }, + { 0x6a, "pc01_vfetch_04", g84_vfetch_sources }, + { 0x6b, "pc01_vfetch_05", g84_vfetch_sources }, + { 0x6c, "pc01_vfetch_06", g84_vfetch_sources }, + { 0x6d, "pc01_vfetch_07", g84_vfetch_sources }, + { 0x6e, "pc01_vfetch_08", g84_vfetch_sources }, + { 0x6f, "pc01_vfetch_09", g84_vfetch_sources }, + { 0x70, "pc01_vfetch_0a", g84_vfetch_sources }, + { 0x71, "pc01_vfetch_0b", g84_vfetch_sources }, + { 0x72, "pc01_vfetch_0c", g84_vfetch_sources }, + { 0x73, "pc01_vfetch_0d", g84_vfetch_sources }, + { 0x74, "pc01_vfetch_0e", g84_vfetch_sources }, + { 0x75, "pc01_vfetch_0f", g84_vfetch_sources }, + { 0x76, "pc01_vfetch_10", g84_vfetch_sources }, + { 0x77, "pc01_vfetch_11", g84_vfetch_sources }, + { 0x78, "pc01_vfetch_12", g84_vfetch_sources }, + { 0x79, "pc01_vfetch_13", g84_vfetch_sources }, + { 0x7a, "pc01_vfetch_14", g84_vfetch_sources }, + { 0x7b, "pc01_vfetch_15", g84_vfetch_sources }, + { 0x7c, "pc01_vfetch_16", g84_vfetch_sources }, + { 0x7d, "pc01_vfetch_17", g84_vfetch_sources }, + { 0x7e, "pc01_vfetch_18", g84_vfetch_sources }, + { 0x7f, "pc01_vfetch_19", g84_vfetch_sources }, + { 0x07, "pc01_zcull_00", nv50_zcull_sources }, + { 0x08, "pc01_zcull_01", nv50_zcull_sources }, + { 0x09, "pc01_zcull_02", nv50_zcull_sources }, + { 0x0a, "pc01_zcull_03", nv50_zcull_sources }, + { 0x0b, "pc01_zcull_04", nv50_zcull_sources }, + { 0x0c, "pc01_zcull_05", nv50_zcull_sources }, + { 0xa4, "pc01_unk00" }, + { 0xec, "pc01_trailer" }, {} }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { + { 0xa0, (const struct nvkm_specsig[]) { + { 0x30, "pc02_crop_00", g84_crop_sources }, + { 0x31, "pc02_crop_01", g84_crop_sources }, + { 0x32, "pc02_crop_02", g84_crop_sources }, + { 0x33, "pc02_crop_03", g84_crop_sources }, + { 0x00, "pc02_prop_00", g84_prop_sources }, + { 0x01, "pc02_prop_01", g84_prop_sources }, + { 0x02, "pc02_prop_02", g84_prop_sources }, + { 0x03, "pc02_prop_03", g84_prop_sources }, + { 0x04, "pc02_prop_04", g84_prop_sources }, + { 0x05, "pc02_prop_05", g84_prop_sources }, + { 0x06, "pc02_prop_06", g84_prop_sources }, + { 0x07, "pc02_prop_07", g84_prop_sources }, + { 0x48, "pc02_tex_00", g84_tex_sources }, + { 0x49, "pc02_tex_01", g84_tex_sources }, + { 0x4a, "pc02_tex_02", g84_tex_sources }, + { 0x4b, "pc02_tex_03", g84_tex_sources }, + { 0x1a, "pc02_tex_04", g84_tex_sources }, + { 0x1b, "pc02_tex_05", g84_tex_sources }, + { 0x1c, "pc02_tex_06", g84_tex_sources }, + { 0x44, "pc02_zrop_00", nv50_zrop_sources }, + { 0x45, "pc02_zrop_01", nv50_zrop_sources }, + { 0x46, "pc02_zrop_02", nv50_zrop_sources }, + { 0x47, "pc02_zrop_03", nv50_zrop_sources }, + { 0x8c, "pc02_trailer" }, {} }, &nv40_perfctr_func }, { 0x20, (const struct nvkm_specsig[]) { @@ -52,14 +158,8 @@ g84_pm[] = { {} }; -struct nvkm_oclass * -g84_pm_oclass = &(struct nv40_pm_oclass) { - .base.handle = NV_ENGINE(PM, 0x84), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = _nvkm_pm_fini, - }, - .doms = g84_pm, -}.base; +int +g84_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return nv40_pm_new_(g84_pm, device, index, ppm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c index 008fed73d..d2901e9a7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c @@ -23,62 +23,146 @@ */ #include "gf100.h" +const struct nvkm_specsrc +gf100_pbfb_sources[] = { + { 0x10f100, (const struct nvkm_specmux[]) { + { 0x1, 0, "unk0" }, + { 0x3f, 4, "unk4" }, + {} + }, "pbfb_broadcast_pm_unk100" }, + {} +}; + +const struct nvkm_specsrc +gf100_pmfb_sources[] = { + { 0x140028, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + { 0x7, 16, "unk16" }, + { 0x3, 24, "unk24" }, + { 0x2, 29, "unk29" }, + {} + }, "pmfb0_pm_unk28" }, + {} +}; + +static const struct nvkm_specsrc +gf100_l1_sources[] = { + { 0x5044a8, (const struct nvkm_specmux[]) { + { 0x3f, 0, "sel", true }, + {} + }, "pgraph_gpc0_tpc0_l1_pm_mux" }, + {} +}; + +static const struct nvkm_specsrc +gf100_tex_sources[] = { + { 0x5042c0, (const struct nvkm_specmux[]) { + { 0xf, 0, "sel0", true }, + { 0x7, 8, "sel1", true }, + {} + }, "pgraph_gpc0_tpc0_tex_pm_mux_c_d" }, + {} +}; + +static const struct nvkm_specsrc +gf100_unk400_sources[] = { + { 0x50440c, (const struct nvkm_specmux[]) { + { 0x3f, 0, "sel", true }, + {} + }, "pgraph_gpc0_tpc0_unk400_pm_mux" }, + {} +}; + static const struct nvkm_specdom gf100_pm_hub[] = { {} }; -static const struct nvkm_specdom +const struct nvkm_specdom gf100_pm_gpc[] = { + { 0xe0, (const struct nvkm_specsig[]) { + { 0x00, "gpc00_l1_00", gf100_l1_sources }, + { 0x01, "gpc00_l1_01", gf100_l1_sources }, + { 0x02, "gpc00_l1_02", gf100_l1_sources }, + { 0x03, "gpc00_l1_03", gf100_l1_sources }, + { 0x05, "gpc00_l1_04", gf100_l1_sources }, + { 0x06, "gpc00_l1_05", gf100_l1_sources }, + { 0x0a, "gpc00_tex_00", gf100_tex_sources }, + { 0x0b, "gpc00_tex_01", gf100_tex_sources }, + { 0x0c, "gpc00_tex_02", gf100_tex_sources }, + { 0x0d, "gpc00_tex_03", gf100_tex_sources }, + { 0x0e, "gpc00_tex_04", gf100_tex_sources }, + { 0x0f, "gpc00_tex_05", gf100_tex_sources }, + { 0x10, "gpc00_tex_06", gf100_tex_sources }, + { 0x11, "gpc00_tex_07", gf100_tex_sources }, + { 0x12, "gpc00_tex_08", gf100_tex_sources }, + { 0x26, "gpc00_unk400_00", gf100_unk400_sources }, + {} + }, &gf100_perfctr_func }, {} }; -static const struct nvkm_specdom +const struct nvkm_specdom gf100_pm_part[] = { + { 0xe0, (const struct nvkm_specsig[]) { + { 0x0f, "part00_pbfb_00", gf100_pbfb_sources }, + { 0x10, "part00_pbfb_01", gf100_pbfb_sources }, + { 0x21, "part00_pmfb_00", gf100_pmfb_sources }, + { 0x04, "part00_pmfb_01", gf100_pmfb_sources }, + { 0x00, "part00_pmfb_02", gf100_pmfb_sources }, + { 0x02, "part00_pmfb_03", gf100_pmfb_sources }, + { 0x01, "part00_pmfb_04", gf100_pmfb_sources }, + { 0x2e, "part00_pmfb_05", gf100_pmfb_sources }, + { 0x2f, "part00_pmfb_06", gf100_pmfb_sources }, + { 0x1b, "part00_pmfb_07", gf100_pmfb_sources }, + { 0x1c, "part00_pmfb_08", gf100_pmfb_sources }, + { 0x1d, "part00_pmfb_09", gf100_pmfb_sources }, + { 0x1e, "part00_pmfb_0a", gf100_pmfb_sources }, + { 0x1f, "part00_pmfb_0b", gf100_pmfb_sources }, + {} + }, &gf100_perfctr_func }, {} }; static void -gf100_perfctr_init(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, +gf100_perfctr_init(struct nvkm_pm *pm, struct nvkm_perfdom *dom, struct nvkm_perfctr *ctr) { - struct gf100_pm_priv *priv = (void *)ppm; - struct gf100_pm_cntr *cntr = (void *)ctr; + struct nvkm_device *device = pm->engine.subdev.device; u32 log = ctr->logic_op; u32 src = 0x00000000; int i; - for (i = 0; i < 4 && ctr->signal[i]; i++) - src |= (ctr->signal[i] - dom->signal) << (i * 8); + for (i = 0; i < 4; i++) + src |= ctr->signal[i] << (i * 8); - nv_wr32(priv, dom->addr + 0x09c, 0x00040002); - nv_wr32(priv, dom->addr + 0x100, 0x00000000); - nv_wr32(priv, dom->addr + 0x040 + (cntr->base.slot * 0x08), src); - nv_wr32(priv, dom->addr + 0x044 + (cntr->base.slot * 0x08), log); + nvkm_wr32(device, dom->addr + 0x09c, 0x00040002 | (dom->mode << 3)); + nvkm_wr32(device, dom->addr + 0x100, 0x00000000); + nvkm_wr32(device, dom->addr + 0x040 + (ctr->slot * 0x08), src); + nvkm_wr32(device, dom->addr + 0x044 + (ctr->slot * 0x08), log); } static void -gf100_perfctr_read(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, +gf100_perfctr_read(struct nvkm_pm *pm, struct nvkm_perfdom *dom, struct nvkm_perfctr *ctr) { - struct gf100_pm_priv *priv = (void *)ppm; - struct gf100_pm_cntr *cntr = (void *)ctr; - - switch (cntr->base.slot) { - case 0: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x08c); break; - case 1: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x088); break; - case 2: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x080); break; - case 3: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x090); break; + struct nvkm_device *device = pm->engine.subdev.device; + + switch (ctr->slot) { + case 0: ctr->ctr = nvkm_rd32(device, dom->addr + 0x08c); break; + case 1: ctr->ctr = nvkm_rd32(device, dom->addr + 0x088); break; + case 2: ctr->ctr = nvkm_rd32(device, dom->addr + 0x080); break; + case 3: ctr->ctr = nvkm_rd32(device, dom->addr + 0x090); break; } - cntr->base.clk = nv_rd32(priv, dom->addr + 0x070); + dom->clk = nvkm_rd32(device, dom->addr + 0x070); } static void -gf100_perfctr_next(struct nvkm_pm *ppm, struct nvkm_perfdom *dom) +gf100_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom) { - struct gf100_pm_priv *priv = (void *)ppm; - nv_wr32(priv, dom->addr + 0x06c, dom->signal_nr - 0x40 + 0x27); - nv_wr32(priv, dom->addr + 0x0ec, 0x00000011); + struct nvkm_device *device = pm->engine.subdev.device; + nvkm_wr32(device, dom->addr + 0x06c, dom->signal_nr - 0x40 + 0x27); + nvkm_wr32(device, dom->addr + 0x0ec, 0x00000011); } const struct nvkm_funcdom @@ -88,72 +172,72 @@ gf100_perfctr_func = { .next = gf100_perfctr_next, }; -int -gf100_pm_fini(struct nvkm_object *object, bool suspend) +static void +gf100_pm_fini(struct nvkm_pm *pm) { - struct gf100_pm_priv *priv = (void *)object; - nv_mask(priv, 0x000200, 0x10000000, 0x00000000); - nv_mask(priv, 0x000200, 0x10000000, 0x10000000); - return nvkm_pm_fini(&priv->base, suspend); + struct nvkm_device *device = pm->engine.subdev.device; + nvkm_mask(device, 0x000200, 0x10000000, 0x00000000); + nvkm_mask(device, 0x000200, 0x10000000, 0x10000000); } -static int -gf100_pm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_pm_func +gf100_pm_ = { + .fini = gf100_pm_fini, +}; + +int +gf100_pm_new_(const struct gf100_pm_func *func, struct nvkm_device *device, + int index, struct nvkm_pm **ppm) { - struct gf100_pm_priv *priv; + struct nvkm_pm *pm; u32 mask; int ret; - ret = nvkm_pm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(pm = *ppm = kzalloc(sizeof(*pm), GFP_KERNEL))) + return -ENOMEM; - ret = nvkm_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, gf100_pm_pwr); + ret = nvkm_pm_ctor(&gf100_pm_, device, index, pm); if (ret) return ret; /* HUB */ - ret = nvkm_perfdom_new(&priv->base, "hub", 0, 0x1b0000, 0, 0x200, - gf100_pm_hub); + ret = nvkm_perfdom_new(pm, "hub", 0, 0x1b0000, 0, 0x200, + func->doms_hub); if (ret) return ret; /* GPC */ - mask = (1 << nv_rd32(priv, 0x022430)) - 1; - mask &= ~nv_rd32(priv, 0x022504); - mask &= ~nv_rd32(priv, 0x022584); + mask = (1 << nvkm_rd32(device, 0x022430)) - 1; + mask &= ~nvkm_rd32(device, 0x022504); + mask &= ~nvkm_rd32(device, 0x022584); - ret = nvkm_perfdom_new(&priv->base, "gpc", mask, 0x180000, - 0x1000, 0x200, gf100_pm_gpc); + ret = nvkm_perfdom_new(pm, "gpc", mask, 0x180000, + 0x1000, 0x200, func->doms_gpc); if (ret) return ret; /* PART */ - mask = (1 << nv_rd32(priv, 0x022438)) - 1; - mask &= ~nv_rd32(priv, 0x022548); - mask &= ~nv_rd32(priv, 0x0225c8); + mask = (1 << nvkm_rd32(device, 0x022438)) - 1; + mask &= ~nvkm_rd32(device, 0x022548); + mask &= ~nvkm_rd32(device, 0x0225c8); - ret = nvkm_perfdom_new(&priv->base, "part", mask, 0x1a0000, - 0x1000, 0x200, gf100_pm_part); + ret = nvkm_perfdom_new(pm, "part", mask, 0x1a0000, + 0x1000, 0x200, func->doms_part); if (ret) return ret; - nv_engine(priv)->cclass = &nvkm_pm_cclass; - nv_engine(priv)->sclass = nvkm_pm_sclass; - priv->base.last = 7; return 0; } -struct nvkm_oclass -gf100_pm_oclass = { - .handle = NV_ENGINE(PM, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = gf100_pm_fini, - }, +static const struct gf100_pm_func +gf100_pm = { + .doms_gpc = gf100_pm_gpc, + .doms_hub = gf100_pm_hub, + .doms_part = gf100_pm_part, }; + +int +gf100_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return gf100_pm_new_(&gf100_pm, device, index, ppm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h index 6a01fc7fe..56d034485 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h @@ -2,14 +2,18 @@ #define __NVKM_PM_NVC0_H__ #include "priv.h" -struct gf100_pm_priv { - struct nvkm_pm base; +struct gf100_pm_func { + const struct nvkm_specdom *doms_hub; + const struct nvkm_specdom *doms_gpc; + const struct nvkm_specdom *doms_part; }; -struct gf100_pm_cntr { - struct nvkm_perfctr base; -}; +int gf100_pm_new_(const struct gf100_pm_func *, struct nvkm_device *, + int index, struct nvkm_pm **); extern const struct nvkm_funcdom gf100_perfctr_func; -int gf100_pm_fini(struct nvkm_object *, bool); +extern const struct nvkm_specdom gf100_pm_gpc[]; + +extern const struct nvkm_specsrc gf100_pbfb_sources[]; +extern const struct nvkm_specsrc gf100_pmfb_sources[]; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c new file mode 100644 index 000000000..49b24c98a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c @@ -0,0 +1,66 @@ +/* + * Copyright 2015 Samuel Pitoiset + * + * 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: Samuel Pitoiset + */ +#include "gf100.h" + +static const struct nvkm_specdom +gf108_pm_hub[] = { + {} +}; + +static const struct nvkm_specdom +gf108_pm_part[] = { + { 0xe0, (const struct nvkm_specsig[]) { + { 0x14, "part00_pbfb_00", gf100_pbfb_sources }, + { 0x15, "part00_pbfb_01", gf100_pbfb_sources }, + { 0x20, "part00_pbfb_02", gf100_pbfb_sources }, + { 0x21, "part00_pbfb_03", gf100_pbfb_sources }, + { 0x01, "part00_pmfb_00", gf100_pmfb_sources }, + { 0x04, "part00_pmfb_01", gf100_pmfb_sources }, + { 0x05, "part00_pmfb_02", gf100_pmfb_sources}, + { 0x07, "part00_pmfb_03", gf100_pmfb_sources }, + { 0x0d, "part00_pmfb_04", gf100_pmfb_sources }, + { 0x12, "part00_pmfb_05", gf100_pmfb_sources }, + { 0x13, "part00_pmfb_06", gf100_pmfb_sources }, + { 0x2c, "part00_pmfb_07", gf100_pmfb_sources }, + { 0x2d, "part00_pmfb_08", gf100_pmfb_sources }, + { 0x2e, "part00_pmfb_09", gf100_pmfb_sources }, + { 0x2f, "part00_pmfb_0a", gf100_pmfb_sources }, + { 0x30, "part00_pmfb_0b", gf100_pmfb_sources }, + {} + }, &gf100_perfctr_func }, + {} +}; + +static const struct gf100_pm_func +gf108_pm = { + .doms_gpc = gf100_pm_gpc, + .doms_hub = gf108_pm_hub, + .doms_part = gf108_pm_part, +}; + +int +gf108_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return gf100_pm_new_(&gf108_pm, device, index, ppm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c new file mode 100644 index 000000000..9170025fc --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Samuel Pitoiset + * + * 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: Samuel Pitoiset + */ +#include "gf100.h" + +static const struct nvkm_specsrc +gf117_pmfb_sources[] = { + { 0x140028, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + { 0x7, 16, "unk16" }, + { 0x3, 24, "unk24" }, + { 0x2, 28, "unk28" }, + {} + }, "pmfb0_pm_unk28" }, + { 0x14125c, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + {} + }, "pmfb0_subp0_pm_unk25c" }, + {} +}; + +static const struct nvkm_specdom +gf117_pm_hub[] = { + {} +}; + +static const struct nvkm_specdom +gf117_pm_part[] = { + { 0xe0, (const struct nvkm_specsig[]) { + { 0x00, "part00_pbfb_00", gf100_pbfb_sources }, + { 0x01, "part00_pbfb_01", gf100_pbfb_sources }, + { 0x12, "part00_pmfb_00", gf117_pmfb_sources }, + { 0x15, "part00_pmfb_01", gf117_pmfb_sources }, + { 0x16, "part00_pmfb_02", gf117_pmfb_sources }, + { 0x18, "part00_pmfb_03", gf117_pmfb_sources }, + { 0x1e, "part00_pmfb_04", gf117_pmfb_sources }, + { 0x23, "part00_pmfb_05", gf117_pmfb_sources }, + { 0x24, "part00_pmfb_06", gf117_pmfb_sources }, + { 0x0c, "part00_pmfb_07", gf117_pmfb_sources }, + { 0x0d, "part00_pmfb_08", gf117_pmfb_sources }, + { 0x0e, "part00_pmfb_09", gf117_pmfb_sources }, + { 0x0f, "part00_pmfb_0a", gf117_pmfb_sources }, + { 0x10, "part00_pmfb_0b", gf117_pmfb_sources }, + {} + }, &gf100_perfctr_func }, + {} +}; + +static const struct gf100_pm_func +gf117_pm = { + .doms_gpc = gf100_pm_gpc, + .doms_hub = gf117_pm_hub, + .doms_part = gf117_pm_part, +}; + +int +gf117_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return gf100_pm_new_(&gf117_pm, device, index, ppm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c index 75b9ff3d1..07f946d26 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c @@ -23,6 +23,52 @@ */ #include "gf100.h" +static const struct nvkm_specsrc +gk104_pmfb_sources[] = { + { 0x140028, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + { 0x7, 16, "unk16" }, + { 0x3, 24, "unk24" }, + { 0x2, 28, "unk28" }, + {} + }, "pmfb0_pm_unk28" }, + { 0x14125c, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + {} + }, "pmfb0_subp0_pm_unk25c" }, + { 0x14165c, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + {} + }, "pmfb0_subp1_pm_unk25c" }, + { 0x141a5c, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + {} + }, "pmfb0_subp2_pm_unk25c" }, + { 0x141e5c, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + {} + }, "pmfb0_subp3_pm_unk25c" }, + {} +}; + +static const struct nvkm_specsrc +gk104_tex_sources[] = { + { 0x5042c0, (const struct nvkm_specmux[]) { + { 0xf, 0, "sel0", true }, + { 0x7, 8, "sel1", true }, + {} + }, "pgraph_gpc0_tpc0_tex_pm_mux_c_d" }, + { 0x5042c8, (const struct nvkm_specmux[]) { + { 0x1f, 0, "sel", true }, + {} + }, "pgraph_gpc0_tpc0_tex_pm_unkc8" }, + { 0x5042b8, (const struct nvkm_specmux[]) { + { 0xff, 0, "sel", true }, + {} + }, "pgraph_gpc0_tpc0_tex_pm_unkb8" }, + {} +}; + static const struct nvkm_specdom gk104_pm_hub[] = { { 0x60, (const struct nvkm_specsig[]) { @@ -69,12 +115,51 @@ gk104_pm_gpc[] = { { 0xc7, "gpc00_user_0" }, {} }, &gf100_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &gf100_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + { 0x00, "gpc02_tex_00", gk104_tex_sources }, + { 0x01, "gpc02_tex_01", gk104_tex_sources }, + { 0x02, "gpc02_tex_02", gk104_tex_sources }, + { 0x03, "gpc02_tex_03", gk104_tex_sources }, + { 0x04, "gpc02_tex_04", gk104_tex_sources }, + { 0x05, "gpc02_tex_05", gk104_tex_sources }, + { 0x06, "gpc02_tex_06", gk104_tex_sources }, + { 0x07, "gpc02_tex_07", gk104_tex_sources }, + { 0x08, "gpc02_tex_08", gk104_tex_sources }, + { 0x0a, "gpc02_tex_0a", gk104_tex_sources }, + { 0x0b, "gpc02_tex_0b", gk104_tex_sources }, + { 0x0d, "gpc02_tex_0c", gk104_tex_sources }, + { 0x0c, "gpc02_tex_0d", gk104_tex_sources }, + { 0x0e, "gpc02_tex_0e", gk104_tex_sources }, + { 0x0f, "gpc02_tex_0f", gk104_tex_sources }, + { 0x10, "gpc02_tex_10", gk104_tex_sources }, + { 0x11, "gpc02_tex_11", gk104_tex_sources }, + { 0x12, "gpc02_tex_12", gk104_tex_sources }, + {} + }, &gf100_perfctr_func }, {} }; static const struct nvkm_specdom gk104_pm_part[] = { { 0x60, (const struct nvkm_specsig[]) { + { 0x00, "part00_pbfb_00", gf100_pbfb_sources }, + { 0x01, "part00_pbfb_01", gf100_pbfb_sources }, + { 0x0c, "part00_pmfb_00", gk104_pmfb_sources }, + { 0x0d, "part00_pmfb_01", gk104_pmfb_sources }, + { 0x0e, "part00_pmfb_02", gk104_pmfb_sources }, + { 0x0f, "part00_pmfb_03", gk104_pmfb_sources }, + { 0x10, "part00_pmfb_04", gk104_pmfb_sources }, + { 0x12, "part00_pmfb_05", gk104_pmfb_sources }, + { 0x15, "part00_pmfb_06", gk104_pmfb_sources }, + { 0x16, "part00_pmfb_07", gk104_pmfb_sources }, + { 0x18, "part00_pmfb_08", gk104_pmfb_sources }, + { 0x21, "part00_pmfb_09", gk104_pmfb_sources }, + { 0x25, "part00_pmfb_0a", gk104_pmfb_sources }, + { 0x26, "part00_pmfb_0b", gk104_pmfb_sources }, + { 0x27, "part00_pmfb_0c", gk104_pmfb_sources }, { 0x47, "part00_user_0" }, {} }, &gf100_perfctr_func }, @@ -85,64 +170,15 @@ gk104_pm_part[] = { {} }; -static int -gk104_pm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_pm_priv *priv; - u32 mask; - int ret; - - ret = nvkm_pm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - /* PDAEMON */ - ret = nvkm_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, gk104_pm_pwr); - if (ret) - return ret; - - /* HUB */ - ret = nvkm_perfdom_new(&priv->base, "hub", 0, 0x1b0000, 0, 0x200, - gk104_pm_hub); - if (ret) - return ret; - - /* GPC */ - mask = (1 << nv_rd32(priv, 0x022430)) - 1; - mask &= ~nv_rd32(priv, 0x022504); - mask &= ~nv_rd32(priv, 0x022584); - - ret = nvkm_perfdom_new(&priv->base, "gpc", mask, 0x180000, - 0x1000, 0x200, gk104_pm_gpc); - if (ret) - return ret; - - /* PART */ - mask = (1 << nv_rd32(priv, 0x022438)) - 1; - mask &= ~nv_rd32(priv, 0x022548); - mask &= ~nv_rd32(priv, 0x0225c8); - - ret = nvkm_perfdom_new(&priv->base, "part", mask, 0x1a0000, - 0x1000, 0x200, gk104_pm_part); - if (ret) - return ret; +static const struct gf100_pm_func +gk104_pm = { + .doms_gpc = gk104_pm_gpc, + .doms_hub = gk104_pm_hub, + .doms_part = gk104_pm_part, +}; - nv_engine(priv)->cclass = &nvkm_pm_cclass; - nv_engine(priv)->sclass = nvkm_pm_sclass; - priv->base.last = 7; - return 0; +int +gk104_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return gf100_pm_new_(&gk104_pm, device, index, ppm); } - -struct nvkm_oclass -gk104_pm_oclass = { - .handle = NV_ENGINE(PM, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = gf100_pm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c deleted file mode 100644 index 6820176e5..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013 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 "gf100.h" - -static int -gk110_pm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf100_pm_priv *priv; - int ret; - - ret = nvkm_pm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, gk104_pm_pwr); - if (ret) - return ret; - - nv_engine(priv)->cclass = &nvkm_pm_cclass; - nv_engine(priv)->sclass = nvkm_pm_sclass; - return 0; -} - -struct nvkm_oclass -gk110_pm_oclass = { - .handle = NV_ENGINE(PM, 0xf0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk110_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = gf100_pm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c new file mode 100644 index 000000000..5cf5dd536 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c @@ -0,0 +1,157 @@ +/* + * Copyright 2015 Nouveau project + * + * 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: Samuel Pitoiset + */ +#include "nv40.h" + +const struct nvkm_specsrc +gt200_crop_sources[] = { + { 0x407008, (const struct nvkm_specmux[]) { + { 0xf, 0, "sel0", true }, + { 0x1f, 16, "sel1", true }, + {} + }, "pgraph_rop0_crop_pm_mux" }, + {} +}; + +const struct nvkm_specsrc +gt200_prop_sources[] = { + { 0x408750, (const struct nvkm_specmux[]) { + { 0x3f, 0, "sel", true }, + {} + }, "pgraph_tpc0_prop_pm_mux" }, + {} +}; + +const struct nvkm_specsrc +gt200_tex_sources[] = { + { 0x408508, (const struct nvkm_specmux[]) { + { 0xfffff, 0, "unk0" }, + {} + }, "pgraph_tpc0_tex_unk08" }, + {} +}; + +static const struct nvkm_specdom +gt200_pm[] = { + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &nv40_perfctr_func }, + { 0xf0, (const struct nvkm_specsig[]) { + { 0xc9, "pc01_gr_idle" }, + { 0x84, "pc01_strmout_00" }, + { 0x85, "pc01_strmout_01" }, + { 0xde, "pc01_trast_00" }, + { 0xdf, "pc01_trast_01" }, + { 0xe0, "pc01_trast_02" }, + { 0xe1, "pc01_trast_03" }, + { 0xe4, "pc01_trast_04" }, + { 0xe5, "pc01_trast_05" }, + { 0x82, "pc01_vattr_00" }, + { 0x83, "pc01_vattr_01" }, + { 0x46, "pc01_vfetch_00", g84_vfetch_sources }, + { 0x47, "pc01_vfetch_01", g84_vfetch_sources }, + { 0x48, "pc01_vfetch_02", g84_vfetch_sources }, + { 0x49, "pc01_vfetch_03", g84_vfetch_sources }, + { 0x4a, "pc01_vfetch_04", g84_vfetch_sources }, + { 0x4b, "pc01_vfetch_05", g84_vfetch_sources }, + { 0x4c, "pc01_vfetch_06", g84_vfetch_sources }, + { 0x4d, "pc01_vfetch_07", g84_vfetch_sources }, + { 0x4e, "pc01_vfetch_08", g84_vfetch_sources }, + { 0x4f, "pc01_vfetch_09", g84_vfetch_sources }, + { 0x50, "pc01_vfetch_0a", g84_vfetch_sources }, + { 0x51, "pc01_vfetch_0b", g84_vfetch_sources }, + { 0x52, "pc01_vfetch_0c", g84_vfetch_sources }, + { 0x53, "pc01_vfetch_0d", g84_vfetch_sources }, + { 0x54, "pc01_vfetch_0e", g84_vfetch_sources }, + { 0x55, "pc01_vfetch_0f", g84_vfetch_sources }, + { 0x56, "pc01_vfetch_10", g84_vfetch_sources }, + { 0x57, "pc01_vfetch_11", g84_vfetch_sources }, + { 0x58, "pc01_vfetch_12", g84_vfetch_sources }, + { 0x59, "pc01_vfetch_13", g84_vfetch_sources }, + { 0x5a, "pc01_vfetch_14", g84_vfetch_sources }, + { 0x5b, "pc01_vfetch_15", g84_vfetch_sources }, + { 0x5c, "pc01_vfetch_16", g84_vfetch_sources }, + { 0x5d, "pc01_vfetch_17", g84_vfetch_sources }, + { 0x5e, "pc01_vfetch_18", g84_vfetch_sources }, + { 0x5f, "pc01_vfetch_19", g84_vfetch_sources }, + { 0x07, "pc01_zcull_00", nv50_zcull_sources }, + { 0x08, "pc01_zcull_01", nv50_zcull_sources }, + { 0x09, "pc01_zcull_02", nv50_zcull_sources }, + { 0x0a, "pc01_zcull_03", nv50_zcull_sources }, + { 0x0b, "pc01_zcull_04", nv50_zcull_sources }, + { 0x0c, "pc01_zcull_05", nv50_zcull_sources }, + + { 0xb0, "pc01_unk00" }, + { 0xec, "pc01_trailer" }, + {} + }, &nv40_perfctr_func }, + { 0xf0, (const struct nvkm_specsig[]) { + { 0x55, "pc02_crop_00", gt200_crop_sources }, + { 0x56, "pc02_crop_01", gt200_crop_sources }, + { 0x57, "pc02_crop_02", gt200_crop_sources }, + { 0x58, "pc02_crop_03", gt200_crop_sources }, + { 0x00, "pc02_prop_00", gt200_prop_sources }, + { 0x01, "pc02_prop_01", gt200_prop_sources }, + { 0x02, "pc02_prop_02", gt200_prop_sources }, + { 0x03, "pc02_prop_03", gt200_prop_sources }, + { 0x04, "pc02_prop_04", gt200_prop_sources }, + { 0x05, "pc02_prop_05", gt200_prop_sources }, + { 0x06, "pc02_prop_06", gt200_prop_sources }, + { 0x07, "pc02_prop_07", gt200_prop_sources }, + { 0x78, "pc02_tex_00", gt200_tex_sources }, + { 0x79, "pc02_tex_01", gt200_tex_sources }, + { 0x7a, "pc02_tex_02", gt200_tex_sources }, + { 0x7b, "pc02_tex_03", gt200_tex_sources }, + { 0x32, "pc02_tex_04", gt200_tex_sources }, + { 0x33, "pc02_tex_05", gt200_tex_sources }, + { 0x34, "pc02_tex_06", gt200_tex_sources }, + { 0x74, "pc02_zrop_00", nv50_zrop_sources }, + { 0x75, "pc02_zrop_01", nv50_zrop_sources }, + { 0x76, "pc02_zrop_02", nv50_zrop_sources }, + { 0x77, "pc02_zrop_03", nv50_zrop_sources }, + { 0xec, "pc02_trailer" }, + {} + }, &nv40_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &nv40_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &nv40_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &nv40_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &nv40_perfctr_func }, + { 0x20, (const struct nvkm_specsig[]) { + {} + }, &nv40_perfctr_func }, + {} +}; + +int +gt200_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return nv40_pm_new_(gt200_pm, device, index, ppm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c index d065bfc59..c9227ad41 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c @@ -23,15 +23,94 @@ */ #include "nv40.h" +static const struct nvkm_specsrc +gt215_zcull_sources[] = { + { 0x402ca4, (const struct nvkm_specmux[]) { + { 0x7fff, 0, "unk0" }, + { 0xff, 24, "unk24" }, + {} + }, "pgraph_zcull_pm_unka4" }, + {} +}; + static const struct nvkm_specdom gt215_pm[] = { { 0x20, (const struct nvkm_specsig[]) { {} }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { + { 0xf0, (const struct nvkm_specsig[]) { + { 0xcb, "pc01_gr_idle" }, + { 0x86, "pc01_strmout_00" }, + { 0x87, "pc01_strmout_01" }, + { 0xe0, "pc01_trast_00" }, + { 0xe1, "pc01_trast_01" }, + { 0xe2, "pc01_trast_02" }, + { 0xe3, "pc01_trast_03" }, + { 0xe6, "pc01_trast_04" }, + { 0xe7, "pc01_trast_05" }, + { 0x84, "pc01_vattr_00" }, + { 0x85, "pc01_vattr_01" }, + { 0x46, "pc01_vfetch_00", g84_vfetch_sources }, + { 0x47, "pc01_vfetch_01", g84_vfetch_sources }, + { 0x48, "pc01_vfetch_02", g84_vfetch_sources }, + { 0x49, "pc01_vfetch_03", g84_vfetch_sources }, + { 0x4a, "pc01_vfetch_04", g84_vfetch_sources }, + { 0x4b, "pc01_vfetch_05", g84_vfetch_sources }, + { 0x4c, "pc01_vfetch_06", g84_vfetch_sources }, + { 0x4d, "pc01_vfetch_07", g84_vfetch_sources }, + { 0x4e, "pc01_vfetch_08", g84_vfetch_sources }, + { 0x4f, "pc01_vfetch_09", g84_vfetch_sources }, + { 0x50, "pc01_vfetch_0a", g84_vfetch_sources }, + { 0x51, "pc01_vfetch_0b", g84_vfetch_sources }, + { 0x52, "pc01_vfetch_0c", g84_vfetch_sources }, + { 0x53, "pc01_vfetch_0d", g84_vfetch_sources }, + { 0x54, "pc01_vfetch_0e", g84_vfetch_sources }, + { 0x55, "pc01_vfetch_0f", g84_vfetch_sources }, + { 0x56, "pc01_vfetch_10", g84_vfetch_sources }, + { 0x57, "pc01_vfetch_11", g84_vfetch_sources }, + { 0x58, "pc01_vfetch_12", g84_vfetch_sources }, + { 0x59, "pc01_vfetch_13", g84_vfetch_sources }, + { 0x5a, "pc01_vfetch_14", g84_vfetch_sources }, + { 0x5b, "pc01_vfetch_15", g84_vfetch_sources }, + { 0x5c, "pc01_vfetch_16", g84_vfetch_sources }, + { 0x5d, "pc01_vfetch_17", g84_vfetch_sources }, + { 0x5e, "pc01_vfetch_18", g84_vfetch_sources }, + { 0x5f, "pc01_vfetch_19", g84_vfetch_sources }, + { 0x07, "pc01_zcull_00", gt215_zcull_sources }, + { 0x08, "pc01_zcull_01", gt215_zcull_sources }, + { 0x09, "pc01_zcull_02", gt215_zcull_sources }, + { 0x0a, "pc01_zcull_03", gt215_zcull_sources }, + { 0x0b, "pc01_zcull_04", gt215_zcull_sources }, + { 0x0c, "pc01_zcull_05", gt215_zcull_sources }, + { 0xb2, "pc01_unk00" }, + { 0xec, "pc01_trailer" }, {} }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { + { 0xe0, (const struct nvkm_specsig[]) { + { 0x64, "pc02_crop_00", gt200_crop_sources }, + { 0x65, "pc02_crop_01", gt200_crop_sources }, + { 0x66, "pc02_crop_02", gt200_crop_sources }, + { 0x67, "pc02_crop_03", gt200_crop_sources }, + { 0x00, "pc02_prop_00", gt200_prop_sources }, + { 0x01, "pc02_prop_01", gt200_prop_sources }, + { 0x02, "pc02_prop_02", gt200_prop_sources }, + { 0x03, "pc02_prop_03", gt200_prop_sources }, + { 0x04, "pc02_prop_04", gt200_prop_sources }, + { 0x05, "pc02_prop_05", gt200_prop_sources }, + { 0x06, "pc02_prop_06", gt200_prop_sources }, + { 0x07, "pc02_prop_07", gt200_prop_sources }, + { 0x80, "pc02_tex_00", gt200_tex_sources }, + { 0x81, "pc02_tex_01", gt200_tex_sources }, + { 0x82, "pc02_tex_02", gt200_tex_sources }, + { 0x83, "pc02_tex_03", gt200_tex_sources }, + { 0x3a, "pc02_tex_04", gt200_tex_sources }, + { 0x3b, "pc02_tex_05", gt200_tex_sources }, + { 0x3c, "pc02_tex_06", gt200_tex_sources }, + { 0x7c, "pc02_zrop_00", nv50_zrop_sources }, + { 0x7d, "pc02_zrop_01", nv50_zrop_sources }, + { 0x7e, "pc02_zrop_02", nv50_zrop_sources }, + { 0x7f, "pc02_zrop_03", nv50_zrop_sources }, + { 0xcc, "pc02_trailer" }, {} }, &nv40_perfctr_func }, { 0x20, (const struct nvkm_specsig[]) { @@ -52,32 +131,8 @@ gt215_pm[] = { {} }; -static int -gt215_pm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **object) +int +gt215_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) { - int ret = nv40_pm_ctor(parent, engine, oclass, data, size, object); - if (ret == 0) { - struct nv40_pm_priv *priv = (void *)*object; - ret = nvkm_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, - gt215_pm_pwr); - if (ret) - return ret; - - priv->base.last = 3; - } - return ret; + return nv40_pm_new_(gt215_pm, device, index, ppm); } - -struct nvkm_oclass * -gt215_pm_oclass = &(struct nv40_pm_oclass) { - .base.handle = NV_ENGINE(PM, 0xa3), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt215_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = _nvkm_pm_fini, - }, - .doms = gt215_pm, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c index ff22f06b2..4bef72a9d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c @@ -24,46 +24,44 @@ #include "nv40.h" static void -nv40_perfctr_init(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, +nv40_perfctr_init(struct nvkm_pm *pm, struct nvkm_perfdom *dom, struct nvkm_perfctr *ctr) { - struct nv40_pm_priv *priv = (void *)ppm; - struct nv40_pm_cntr *cntr = (void *)ctr; + struct nvkm_device *device = pm->engine.subdev.device; u32 log = ctr->logic_op; u32 src = 0x00000000; int i; - for (i = 0; i < 4 && ctr->signal[i]; i++) - src |= (ctr->signal[i] - dom->signal) << (i * 8); + for (i = 0; i < 4; i++) + src |= ctr->signal[i] << (i * 8); - nv_wr32(priv, 0x00a7c0 + dom->addr, 0x00000001); - nv_wr32(priv, 0x00a400 + dom->addr + (cntr->base.slot * 0x40), src); - nv_wr32(priv, 0x00a420 + dom->addr + (cntr->base.slot * 0x40), log); + nvkm_wr32(device, 0x00a7c0 + dom->addr, 0x00000001 | (dom->mode << 4)); + nvkm_wr32(device, 0x00a400 + dom->addr + (ctr->slot * 0x40), src); + nvkm_wr32(device, 0x00a420 + dom->addr + (ctr->slot * 0x40), log); } static void -nv40_perfctr_read(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, +nv40_perfctr_read(struct nvkm_pm *pm, struct nvkm_perfdom *dom, struct nvkm_perfctr *ctr) { - struct nv40_pm_priv *priv = (void *)ppm; - struct nv40_pm_cntr *cntr = (void *)ctr; + struct nvkm_device *device = pm->engine.subdev.device; - switch (cntr->base.slot) { - case 0: cntr->base.ctr = nv_rd32(priv, 0x00a700 + dom->addr); break; - case 1: cntr->base.ctr = nv_rd32(priv, 0x00a6c0 + dom->addr); break; - case 2: cntr->base.ctr = nv_rd32(priv, 0x00a680 + dom->addr); break; - case 3: cntr->base.ctr = nv_rd32(priv, 0x00a740 + dom->addr); break; + switch (ctr->slot) { + case 0: ctr->ctr = nvkm_rd32(device, 0x00a700 + dom->addr); break; + case 1: ctr->ctr = nvkm_rd32(device, 0x00a6c0 + dom->addr); break; + case 2: ctr->ctr = nvkm_rd32(device, 0x00a680 + dom->addr); break; + case 3: ctr->ctr = nvkm_rd32(device, 0x00a740 + dom->addr); break; } - cntr->base.clk = nv_rd32(priv, 0x00a600 + dom->addr); + dom->clk = nvkm_rd32(device, 0x00a600 + dom->addr); } static void -nv40_perfctr_next(struct nvkm_pm *ppm, struct nvkm_perfdom *dom) +nv40_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom) { - struct nv40_pm_priv *priv = (void *)ppm; - if (priv->sequence != ppm->sequence) { - nv_wr32(priv, 0x400084, 0x00000020); - priv->sequence = ppm->sequence; + struct nvkm_device *device = pm->engine.subdev.device; + if (pm->sequence != pm->sequence) { + nvkm_wr32(device, 0x400084, 0x00000020); + pm->sequence = pm->sequence; } } @@ -74,6 +72,28 @@ nv40_perfctr_func = { .next = nv40_perfctr_next, }; +static const struct nvkm_pm_func +nv40_pm_ = { +}; + +int +nv40_pm_new_(const struct nvkm_specdom *doms, struct nvkm_device *device, + int index, struct nvkm_pm **ppm) +{ + struct nv40_pm *pm; + int ret; + + if (!(pm = kzalloc(sizeof(*pm), GFP_KERNEL))) + return -ENOMEM; + *ppm = &pm->base; + + ret = nvkm_pm_ctor(&nv40_pm_, device, index, &pm->base); + if (ret) + return ret; + + return nvkm_perfdom_new(&pm->base, "pc", 0, 0, 0, 4, doms); +} + static const struct nvkm_specdom nv40_pm[] = { { 0x20, (const struct nvkm_specsig[]) { @@ -95,36 +115,7 @@ nv40_pm[] = { }; int -nv40_pm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv40_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) { - struct nv40_pm_oclass *mclass = (void *)oclass; - struct nv40_pm_priv *priv; - int ret; - - ret = nvkm_pm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - ret = nvkm_perfdom_new(&priv->base, "pm", 0, 0, 0, 4, mclass->doms); - if (ret) - return ret; - - nv_engine(priv)->cclass = &nvkm_pm_cclass; - nv_engine(priv)->sclass = nvkm_pm_sclass; - return 0; + return nv40_pm_new_(nv40_pm, device, index, ppm); } - -struct nvkm_oclass * -nv40_pm_oclass = &(struct nv40_pm_oclass) { - .base.handle = NV_ENGINE(PM, 0x40), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = _nvkm_pm_fini, - }, - .doms = nv40_pm, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h index 2338e1504..da481abe8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h @@ -1,24 +1,14 @@ #ifndef __NVKM_PM_NV40_H__ #define __NVKM_PM_NV40_H__ +#define nv40_pm(p) container_of((p), struct nv40_pm, base) #include "priv.h" -struct nv40_pm_oclass { - struct nvkm_oclass base; - const struct nvkm_specdom *doms; -}; - -struct nv40_pm_priv { +struct nv40_pm { struct nvkm_pm base; u32 sequence; }; -int nv40_pm_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **pobject); - -struct nv40_pm_cntr { - struct nvkm_perfctr base; -}; - +int nv40_pm_new_(const struct nvkm_specdom *, struct nvkm_device *, + int index, struct nvkm_pm **); extern const struct nvkm_funcdom nv40_perfctr_func; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c index 6af83b5d1..cc5a41d4c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c @@ -23,35 +23,153 @@ */ #include "nv40.h" +const struct nvkm_specsrc +nv50_zcull_sources[] = { + { 0x402ca4, (const struct nvkm_specmux[]) { + { 0x7fff, 0, "unk0" }, + {} + }, "pgraph_zcull_pm_unka4" }, + {} +}; + +const struct nvkm_specsrc +nv50_zrop_sources[] = { + { 0x40708c, (const struct nvkm_specmux[]) { + { 0xf, 0, "sel0", true }, + { 0xf, 16, "sel1", true }, + {} + }, "pgraph_rop0_zrop_pm_mux" }, + {} +}; + +static const struct nvkm_specsrc +nv50_prop_sources[] = { + { 0x40be50, (const struct nvkm_specmux[]) { + { 0x1f, 0, "sel", true }, + {} + }, "pgraph_tpc3_prop_pm_mux" }, + {} +}; + +static const struct nvkm_specsrc +nv50_crop_sources[] = { + { 0x407008, (const struct nvkm_specmux[]) { + { 0x7, 0, "sel0", true }, + { 0x7, 16, "sel1", true }, + {} + }, "pgraph_rop0_crop_pm_mux" }, + {} +}; + +static const struct nvkm_specsrc +nv50_tex_sources[] = { + { 0x40b808, (const struct nvkm_specmux[]) { + { 0x3fff, 0, "unk0" }, + {} + }, "pgraph_tpc3_tex_unk08" }, + {} +}; + +static const struct nvkm_specsrc +nv50_vfetch_sources[] = { + { 0x400c0c, (const struct nvkm_specmux[]) { + { 0x1, 0, "unk0" }, + {} + }, "pgraph_vfetch_unk0c" }, + {} +}; + static const struct nvkm_specdom nv50_pm[] = { - { 0x040, (const struct nvkm_specsig[]) { + { 0x20, (const struct nvkm_specsig[]) { {} }, &nv40_perfctr_func }, - { 0x100, (const struct nvkm_specsig[]) { - { 0xc8, "gr_idle" }, + { 0xf0, (const struct nvkm_specsig[]) { + { 0xc8, "pc01_gr_idle" }, + { 0x7f, "pc01_strmout_00" }, + { 0x80, "pc01_strmout_01" }, + { 0xdc, "pc01_trast_00" }, + { 0xdd, "pc01_trast_01" }, + { 0xde, "pc01_trast_02" }, + { 0xdf, "pc01_trast_03" }, + { 0xe2, "pc01_trast_04" }, + { 0xe3, "pc01_trast_05" }, + { 0x7c, "pc01_vattr_00" }, + { 0x7d, "pc01_vattr_01" }, + { 0x26, "pc01_vfetch_00", nv50_vfetch_sources }, + { 0x27, "pc01_vfetch_01", nv50_vfetch_sources }, + { 0x28, "pc01_vfetch_02", nv50_vfetch_sources }, + { 0x29, "pc01_vfetch_03", nv50_vfetch_sources }, + { 0x2a, "pc01_vfetch_04", nv50_vfetch_sources }, + { 0x2b, "pc01_vfetch_05", nv50_vfetch_sources }, + { 0x2c, "pc01_vfetch_06", nv50_vfetch_sources }, + { 0x2d, "pc01_vfetch_07", nv50_vfetch_sources }, + { 0x2e, "pc01_vfetch_08", nv50_vfetch_sources }, + { 0x2f, "pc01_vfetch_09", nv50_vfetch_sources }, + { 0x30, "pc01_vfetch_0a", nv50_vfetch_sources }, + { 0x31, "pc01_vfetch_0b", nv50_vfetch_sources }, + { 0x32, "pc01_vfetch_0c", nv50_vfetch_sources }, + { 0x33, "pc01_vfetch_0d", nv50_vfetch_sources }, + { 0x34, "pc01_vfetch_0e", nv50_vfetch_sources }, + { 0x35, "pc01_vfetch_0f", nv50_vfetch_sources }, + { 0x36, "pc01_vfetch_10", nv50_vfetch_sources }, + { 0x37, "pc01_vfetch_11", nv50_vfetch_sources }, + { 0x38, "pc01_vfetch_12", nv50_vfetch_sources }, + { 0x39, "pc01_vfetch_13", nv50_vfetch_sources }, + { 0x3a, "pc01_vfetch_14", nv50_vfetch_sources }, + { 0x3b, "pc01_vfetch_15", nv50_vfetch_sources }, + { 0x3c, "pc01_vfetch_16", nv50_vfetch_sources }, + { 0x3d, "pc01_vfetch_17", nv50_vfetch_sources }, + { 0x3e, "pc01_vfetch_18", nv50_vfetch_sources }, + { 0x3f, "pc01_vfetch_19", nv50_vfetch_sources }, + { 0x20, "pc01_zcull_00", nv50_zcull_sources }, + { 0x21, "pc01_zcull_01", nv50_zcull_sources }, + { 0x22, "pc01_zcull_02", nv50_zcull_sources }, + { 0x23, "pc01_zcull_03", nv50_zcull_sources }, + { 0x24, "pc01_zcull_04", nv50_zcull_sources }, + { 0x25, "pc01_zcull_05", nv50_zcull_sources }, + { 0xae, "pc01_unk00" }, + { 0xee, "pc01_trailer" }, {} }, &nv40_perfctr_func }, - { 0x100, (const struct nvkm_specsig[]) { + { 0xf0, (const struct nvkm_specsig[]) { + { 0x52, "pc02_crop_00", nv50_crop_sources }, + { 0x53, "pc02_crop_01", nv50_crop_sources }, + { 0x54, "pc02_crop_02", nv50_crop_sources }, + { 0x55, "pc02_crop_03", nv50_crop_sources }, + { 0x00, "pc02_prop_00", nv50_prop_sources }, + { 0x01, "pc02_prop_01", nv50_prop_sources }, + { 0x02, "pc02_prop_02", nv50_prop_sources }, + { 0x03, "pc02_prop_03", nv50_prop_sources }, + { 0x04, "pc02_prop_04", nv50_prop_sources }, + { 0x05, "pc02_prop_05", nv50_prop_sources }, + { 0x06, "pc02_prop_06", nv50_prop_sources }, + { 0x07, "pc02_prop_07", nv50_prop_sources }, + { 0x70, "pc02_tex_00", nv50_tex_sources }, + { 0x71, "pc02_tex_01", nv50_tex_sources }, + { 0x72, "pc02_tex_02", nv50_tex_sources }, + { 0x73, "pc02_tex_03", nv50_tex_sources }, + { 0x40, "pc02_tex_04", nv50_tex_sources }, + { 0x41, "pc02_tex_05", nv50_tex_sources }, + { 0x42, "pc02_tex_06", nv50_tex_sources }, + { 0x6c, "pc02_zrop_00", nv50_zrop_sources }, + { 0x6d, "pc02_zrop_01", nv50_zrop_sources }, + { 0x6e, "pc02_zrop_02", nv50_zrop_sources }, + { 0x6f, "pc02_zrop_03", nv50_zrop_sources }, + { 0xee, "pc02_trailer" }, {} }, &nv40_perfctr_func }, - { 0x020, (const struct nvkm_specsig[]) { + { 0x20, (const struct nvkm_specsig[]) { {} }, &nv40_perfctr_func }, - { 0x040, (const struct nvkm_specsig[]) { + { 0x20, (const struct nvkm_specsig[]) { {} }, &nv40_perfctr_func }, {} }; -struct nvkm_oclass * -nv50_pm_oclass = &(struct nv40_pm_oclass) { - .base.handle = NV_ENGINE(PM, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_pm_ctor, - .dtor = _nvkm_pm_dtor, - .init = _nvkm_pm_init, - .fini = _nvkm_pm_fini, - }, - .doms = nv50_pm, -}.base; +int +nv50_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) +{ + return nv40_pm_new_(nv50_pm, device, index, ppm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h index 1e6eff2a6..d7b81cbf8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h @@ -1,58 +1,85 @@ #ifndef __NVKM_PM_PRIV_H__ #define __NVKM_PM_PRIV_H__ +#define nvkm_pm(p) container_of((p), struct nvkm_pm, engine) #include +int nvkm_pm_ctor(const struct nvkm_pm_func *, struct nvkm_device *, + int index, struct nvkm_pm *); + +struct nvkm_pm_func { + void (*fini)(struct nvkm_pm *); +}; + struct nvkm_perfctr { - struct nvkm_object base; struct list_head head; - struct nvkm_perfsig *signal[4]; + u8 domain; + u8 signal[4]; + u64 source[4][8]; int slot; u32 logic_op; - u32 clk; u32 ctr; }; -extern struct nvkm_oclass nvkm_pm_sclass[]; +struct nvkm_specmux { + u32 mask; + u8 shift; + const char *name; + bool enable; +}; -#include +struct nvkm_specsrc { + u32 addr; + const struct nvkm_specmux *mux; + const char *name; +}; -struct nvkm_perfctx { - struct nvkm_engctx base; +struct nvkm_perfsrc { + struct list_head head; + char *name; + u32 addr; + u32 mask; + u8 shift; + bool enable; }; -extern struct nvkm_oclass nvkm_pm_cclass; +extern const struct nvkm_specsrc nv50_zcull_sources[]; +extern const struct nvkm_specsrc nv50_zrop_sources[]; +extern const struct nvkm_specsrc g84_vfetch_sources[]; +extern const struct nvkm_specsrc gt200_crop_sources[]; +extern const struct nvkm_specsrc gt200_prop_sources[]; +extern const struct nvkm_specsrc gt200_tex_sources[]; struct nvkm_specsig { u8 signal; const char *name; + const struct nvkm_specsrc *source; }; struct nvkm_perfsig { const char *name; + u8 source[8]; }; -struct nvkm_perfdom; -struct nvkm_perfctr * -nvkm_perfsig_wrap(struct nvkm_pm *, const char *, struct nvkm_perfdom **); - struct nvkm_specdom { u16 signal_nr; const struct nvkm_specsig *signal; const struct nvkm_funcdom *func; }; -extern const struct nvkm_specdom gt215_pm_pwr[]; -extern const struct nvkm_specdom gf100_pm_pwr[]; -extern const struct nvkm_specdom gk104_pm_pwr[]; +#define nvkm_perfdom(p) container_of((p), struct nvkm_perfdom, object) struct nvkm_perfdom { + struct nvkm_object object; + struct nvkm_perfmon *perfmon; struct list_head head; struct list_head list; const struct nvkm_funcdom *func; + struct nvkm_perfctr *ctr[4]; char name[32]; u32 addr; - u8 quad; - u32 signal_nr; + u8 mode; + u32 clk; + u16 signal_nr; struct nvkm_perfsig signal[]; }; @@ -67,24 +94,10 @@ struct nvkm_funcdom { int nvkm_perfdom_new(struct nvkm_pm *, const char *, u32, u32, u32, u32, const struct nvkm_specdom *); -#define nvkm_pm_create(p,e,o,d) \ - nvkm_pm_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_pm_dtor(p) ({ \ - struct nvkm_pm *c = (p); \ - _nvkm_pm_dtor(nv_object(c)); \ -}) -#define nvkm_pm_init(p) ({ \ - struct nvkm_pm *c = (p); \ - _nvkm_pm_init(nv_object(c)); \ -}) -#define nvkm_pm_fini(p,s) ({ \ - struct nvkm_pm *c = (p); \ - _nvkm_pm_fini(nv_object(c), (s)); \ -}) - -int nvkm_pm_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_pm_dtor(struct nvkm_object *); -int _nvkm_pm_init(struct nvkm_object *); -int _nvkm_pm_fini(struct nvkm_object *, bool); +#define nvkm_perfmon(p) container_of((p), struct nvkm_perfmon, object) + +struct nvkm_perfmon { + struct nvkm_object object; + struct nvkm_pm *pm; +}; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s index 06ee06071..66b147bd5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s @@ -1,5 +1,5 @@ /* - * fuc microcode for g98 psec engine + * fuc microcode for g98 sec engine * Copyright (C) 2010 Marcin KoÅ›cielnicki * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -.section #g98_psec_data +.section #g98_sec_data ctx_dma: ctx_dma_query: .b32 0 @@ -94,7 +94,7 @@ sec_dtable: .align 0x100 -.section #g98_psec_code +.section #g98_sec_code // $r0 is always set to 0 in our code - this allows some space savings. clear b32 $r0 diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h index 5d65c4fbb..eca62221f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h @@ -1,4 +1,4 @@ -uint32_t g98_psec_data[] = { +uint32_t g98_sec_data[] = { /* 0x0000: ctx_dma */ /* 0x0000: ctx_dma_query */ 0x00000000, @@ -150,7 +150,7 @@ uint32_t g98_psec_data[] = { 0x00000000, }; -uint32_t g98_psec_code[] = { +uint32_t g98_sec_code[] = { 0x17f004bd, 0x0010fe35, 0xf10004fe, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c index 9d5c1b8b1..995c2c5ec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c @@ -22,47 +22,14 @@ * Authors: Ben Skeggs */ #include -#include +#include #include "fuc/g98.fuc0s.h" #include #include -#include - -struct g98_sec_priv { - struct nvkm_falcon base; -}; - -/******************************************************************************* - * Crypt object classes - ******************************************************************************/ +#include -static struct nvkm_oclass -g98_sec_sclass[] = { - { 0x88b4, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PSEC context - ******************************************************************************/ - -static struct nvkm_oclass -g98_sec_cclass = { - .handle = NV_ENGCTX(SEC, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_falcon_context_ctor, - .dtor = _nvkm_falcon_context_dtor, - .init = _nvkm_falcon_context_init, - .fini = _nvkm_falcon_context_fini, - .rd32 = _nvkm_falcon_context_rd32, - .wr32 = _nvkm_falcon_context_wr32, - }, -}; - -/******************************************************************************* - * PSEC engine/subdev functions - ******************************************************************************/ +#include static const struct nvkm_enum g98_sec_isr_error_name[] = { { 0x0000, "ILLEGAL_MTHD" }, @@ -73,77 +40,44 @@ static const struct nvkm_enum g98_sec_isr_error_name[] = { }; static void -g98_sec_intr(struct nvkm_subdev *subdev) +g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan) { - struct nvkm_fifo *pfifo = nvkm_fifo(subdev); - struct nvkm_engine *engine = nv_engine(subdev); - struct nvkm_object *engctx; - struct g98_sec_priv *priv = (void *)subdev; - u32 disp = nv_rd32(priv, 0x08701c); - u32 stat = nv_rd32(priv, 0x087008) & disp & ~(disp >> 16); - u32 inst = nv_rd32(priv, 0x087050) & 0x3fffffff; - u32 ssta = nv_rd32(priv, 0x087040) & 0x0000ffff; - u32 addr = nv_rd32(priv, 0x087040) >> 16; + struct nvkm_subdev *subdev = &sec->engine.subdev; + struct nvkm_device *device = subdev->device; + u32 ssta = nvkm_rd32(device, 0x087040) & 0x0000ffff; + u32 addr = nvkm_rd32(device, 0x087040) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(priv, 0x087044); - int chid; - - engctx = nvkm_engctx_get(engine, inst); - chid = pfifo->chid(pfifo, engctx); - - if (stat & 0x00000040) { - nv_error(priv, "DISPATCH_ERROR ["); - nvkm_enum_print(g98_sec_isr_error_name, ssta); - pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n", - chid, (u64)inst << 12, nvkm_client_name(engctx), - subc, mthd, data); - nv_wr32(priv, 0x087004, 0x00000040); - stat &= ~0x00000040; - } + u32 data = nvkm_rd32(device, 0x087044); + const struct nvkm_enum *en = + nvkm_enum_find(g98_sec_isr_error_name, ssta); + + nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] " + "subc %d mthd %04x data %08x\n", ssta, + en ? en->name : "UNKNOWN", chan ? chan->chid : -1, + chan ? chan->inst->addr : 0, + chan ? chan->object.client->name : "unknown", + subc, mthd, data); +} - if (stat) { - nv_error(priv, "unhandled intr 0x%08x\n", stat); - nv_wr32(priv, 0x087004, stat); +static const struct nvkm_falcon_func +g98_sec = { + .code.data = g98_sec_code, + .code.size = sizeof(g98_sec_code), + .data.data = g98_sec_data, + .data.size = sizeof(g98_sec_data), + .pmc_enable = 0x00004000, + .intr = g98_sec_intr, + .sclass = { + { -1, -1, G98_SEC }, + {} } +}; - nvkm_engctx_put(engctx); -} - -static int -g98_sec_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +g98_sec_new(struct nvkm_device *device, int index, + struct nvkm_engine **pengine) { - struct g98_sec_priv *priv; - int ret; - - ret = nvkm_falcon_create(parent, engine, oclass, 0x087000, true, - "PSEC", "sec", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x00004000; - nv_subdev(priv)->intr = g98_sec_intr; - nv_engine(priv)->cclass = &g98_sec_cclass; - nv_engine(priv)->sclass = g98_sec_sclass; - nv_falcon(priv)->code.data = g98_psec_code; - nv_falcon(priv)->code.size = sizeof(g98_psec_code); - nv_falcon(priv)->data.data = g98_psec_data; - nv_falcon(priv)->data.size = sizeof(g98_psec_data); - return 0; + return nvkm_falcon_new_(&g98_sec, device, index, + true, 0x087000, pengine); } - -struct nvkm_oclass -g98_sec_oclass = { - .handle = NV_ENGINE(SEC, 0x98), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g98_sec_ctor, - .dtor = _nvkm_falcon_dtor, - .init = _nvkm_falcon_init, - .fini = _nvkm_falcon_fini, - .rd32 = _nvkm_falcon_rd32, - .wr32 = _nvkm_falcon_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild index bdc3a0590..1c291e6fc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild @@ -1,4 +1,9 @@ +nvkm-y += nvkm/engine/sw/base.o nvkm-y += nvkm/engine/sw/nv04.o nvkm-y += nvkm/engine/sw/nv10.o nvkm-y += nvkm/engine/sw/nv50.o nvkm-y += nvkm/engine/sw/gf100.o + +nvkm-y += nvkm/engine/sw/chan.o + +nvkm-y += nvkm/engine/sw/nvsw.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c new file mode 100644 index 000000000..53c1f7e75 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c @@ -0,0 +1,110 @@ +/* + * 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 + */ +#include "priv.h" +#include "chan.h" + +#include + +bool +nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data) +{ + struct nvkm_sw_chan *chan; + bool handled = false; + unsigned long flags; + + spin_lock_irqsave(&sw->engine.lock, flags); + list_for_each_entry(chan, &sw->chan, head) { + if (chan->fifo->chid == chid) { + handled = nvkm_sw_chan_mthd(chan, subc, mthd, data); + list_del(&chan->head); + list_add(&chan->head, &sw->chan); + break; + } + } + spin_unlock_irqrestore(&sw->engine.lock, flags); + return handled; +} + +static int +nvkm_sw_oclass_new(const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_sw_chan *chan = nvkm_sw_chan(oclass->parent); + const struct nvkm_sw_chan_sclass *sclass = oclass->engn; + return sclass->ctor(chan, oclass, data, size, pobject); +} + +static int +nvkm_sw_oclass_get(struct nvkm_oclass *oclass, int index) +{ + struct nvkm_sw *sw = nvkm_sw(oclass->engine); + int c = 0; + + while (sw->func->sclass[c].ctor) { + if (c++ == index) { + oclass->engn = &sw->func->sclass[index]; + oclass->base = sw->func->sclass[index].base; + oclass->base.ctor = nvkm_sw_oclass_new; + return index; + } + } + + return c; +} + +static int +nvkm_sw_cclass_get(struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nvkm_sw *sw = nvkm_sw(oclass->engine); + return sw->func->chan_new(sw, fifoch, oclass, pobject); +} + +static void * +nvkm_sw_dtor(struct nvkm_engine *engine) +{ + return nvkm_sw(engine); +} + +static const struct nvkm_engine_func +nvkm_sw = { + .dtor = nvkm_sw_dtor, + .fifo.cclass = nvkm_sw_cclass_get, + .fifo.sclass = nvkm_sw_oclass_get, +}; + +int +nvkm_sw_new_(const struct nvkm_sw_func *func, struct nvkm_device *device, + int index, struct nvkm_sw **psw) +{ + struct nvkm_sw *sw; + + if (!(sw = *psw = kzalloc(sizeof(*sw), GFP_KERNEL))) + return -ENOMEM; + INIT_LIST_HEAD(&sw->chan); + sw->func = func; + + return nvkm_engine_ctor(&nvkm_sw, device, index, 0, true, &sw->engine); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c new file mode 100644 index 000000000..d082f4f73 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -0,0 +1,111 @@ +/* + * 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 + */ +#include "chan.h" + +#include +#include + +#include +#include + +bool +nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data) +{ + switch (mthd) { + case 0x0000: + return true; + case 0x0500: + nvkm_event_send(&chan->event, 1, 0, NULL, 0); + return true; + default: + if (chan->func->mthd) + return chan->func->mthd(chan, subc, mthd, data); + break; + } + return false; +} + +static int +nvkm_sw_chan_event_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) +{ + union { + struct nvif_notify_uevent_req none; + } *req = data; + int ret; + + if (nvif_unvers(req->none)) { + notify->size = sizeof(struct nvif_notify_uevent_rep); + notify->types = 1; + notify->index = 0; + } + + return ret; +} + +static const struct nvkm_event_func +nvkm_sw_chan_event = { + .ctor = nvkm_sw_chan_event_ctor, +}; + +static void * +nvkm_sw_chan_dtor(struct nvkm_object *object) +{ + struct nvkm_sw_chan *chan = nvkm_sw_chan(object); + struct nvkm_sw *sw = chan->sw; + unsigned long flags; + void *data = chan; + + if (chan->func->dtor) + data = chan->func->dtor(chan); + nvkm_event_fini(&chan->event); + + spin_lock_irqsave(&sw->engine.lock, flags); + list_del(&chan->head); + spin_unlock_irqrestore(&sw->engine.lock, flags); + return data; +} + +static const struct nvkm_object_func +nvkm_sw_chan = { + .dtor = nvkm_sw_chan_dtor, +}; + +int +nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *func, struct nvkm_sw *sw, + struct nvkm_fifo_chan *fifo, const struct nvkm_oclass *oclass, + struct nvkm_sw_chan *chan) +{ + unsigned long flags; + + nvkm_object_ctor(&nvkm_sw_chan, oclass, &chan->object); + chan->func = func; + chan->sw = sw; + chan->fifo = fifo; + spin_lock_irqsave(&sw->engine.lock, flags); + list_add(&chan->head, &sw->chan); + spin_unlock_irqrestore(&sw->engine.lock, flags); + + return nvkm_event_init(&nvkm_sw_chan_event, 1, 1, &chan->event); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h new file mode 100644 index 000000000..6608bf6c6 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_SW_CHAN_H__ +#define __NVKM_SW_CHAN_H__ +#define nvkm_sw_chan(p) container_of((p), struct nvkm_sw_chan, object) +#include "priv.h" +#include + +struct nvkm_sw_chan { + const struct nvkm_sw_chan_func *func; + struct nvkm_object object; + struct nvkm_sw *sw; + struct nvkm_fifo_chan *fifo; + struct list_head head; + + struct nvkm_event event; +}; + +struct nvkm_sw_chan_func { + void *(*dtor)(struct nvkm_sw_chan *); + bool (*mthd)(struct nvkm_sw_chan *, int subc, u32 mthd, u32 data); +}; + +int nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *, struct nvkm_sw *, + struct nvkm_fifo_chan *, const struct nvkm_oclass *, + struct nvkm_sw_chan *); +bool nvkm_sw_chan_mthd(struct nvkm_sw_chan *, int subc, u32 mthd, u32 data); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c index 533d5d8ed..b01ef7eca 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c @@ -23,119 +23,133 @@ */ #include "nv50.h" +#include #include +#include +#include + +#include +#include /******************************************************************************* - * software object classes + * software context ******************************************************************************/ static int -gf100_sw_mthd_vblsem_offset(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +gf100_sw_chan_vblsem_release(struct nvkm_notify *notify) { - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - u64 data = *(u32 *)args; - if (mthd == 0x0400) { - chan->vblank.offset &= 0x00ffffffffULL; - chan->vblank.offset |= data << 32; - } else { - chan->vblank.offset &= 0xff00000000ULL; - chan->vblank.offset |= data; - } - return 0; + struct nv50_sw_chan *chan = + container_of(notify, typeof(*chan), vblank.notify[notify->index]); + struct nvkm_sw *sw = chan->base.sw; + struct nvkm_device *device = sw->engine.subdev.device; + u32 inst = chan->base.fifo->inst->addr >> 12; + + nvkm_wr32(device, 0x001718, 0x80000000 | inst); + nvkm_bar_flush(device->bar); + nvkm_wr32(device, 0x06000c, upper_32_bits(chan->vblank.offset)); + nvkm_wr32(device, 0x060010, lower_32_bits(chan->vblank.offset)); + nvkm_wr32(device, 0x060014, chan->vblank.value); + + return NVKM_NOTIFY_DROP; } -static int -gf100_sw_mthd_mp_control(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +static bool +gf100_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) { - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - struct nv50_sw_priv *priv = (void *)nv_object(chan)->engine; - u32 data = *(u32 *)args; - + struct nv50_sw_chan *chan = nv50_sw_chan(base); + struct nvkm_engine *engine = chan->base.object.engine; + struct nvkm_device *device = engine->subdev.device; switch (mthd) { - case 0x600: - nv_wr32(priv, 0x419e00, data); /* MP.PM_UNK000 */ - break; - case 0x644: - if (data & ~0x1ffffe) - return -EINVAL; - nv_wr32(priv, 0x419e44, data); /* MP.TRAP_WARP_ERROR_EN */ + case 0x0400: + chan->vblank.offset &= 0x00ffffffffULL; + chan->vblank.offset |= (u64)data << 32; + return true; + case 0x0404: + chan->vblank.offset &= 0xff00000000ULL; + chan->vblank.offset |= data; + return true; + case 0x0408: + chan->vblank.value = data; + return true; + case 0x040c: + if (data < device->disp->vblank.index_nr) { + nvkm_notify_get(&chan->vblank.notify[data]); + return true; + } break; - case 0x6ac: - nv_wr32(priv, 0x419eac, data); /* MP.PM_UNK0AC */ + case 0x600: /* MP.PM_UNK000 */ + nvkm_wr32(device, 0x419e00, data); + return true; + case 0x644: /* MP.TRAP_WARP_ERROR_EN */ + if (!(data & ~0x001ffffe)) { + nvkm_wr32(device, 0x419e44, data); + return true; + } break; + case 0x6ac: /* MP.PM_UNK0AC */ + nvkm_wr32(device, 0x419eac, data); + return true; default: - return -EINVAL; + break; } - return 0; + return false; } -static struct nvkm_omthds -gf100_sw_omthds[] = { - { 0x0400, 0x0400, gf100_sw_mthd_vblsem_offset }, - { 0x0404, 0x0404, gf100_sw_mthd_vblsem_offset }, - { 0x0408, 0x0408, nv50_sw_mthd_vblsem_value }, - { 0x040c, 0x040c, nv50_sw_mthd_vblsem_release }, - { 0x0500, 0x0500, nv50_sw_mthd_flip }, - { 0x0600, 0x0600, gf100_sw_mthd_mp_control }, - { 0x0644, 0x0644, gf100_sw_mthd_mp_control }, - { 0x06ac, 0x06ac, gf100_sw_mthd_mp_control }, - {} +static const struct nvkm_sw_chan_func +gf100_sw_chan = { + .dtor = nv50_sw_chan_dtor, + .mthd = gf100_sw_chan_mthd, }; -static struct nvkm_oclass -gf100_sw_sclass[] = { - { 0x906e, &nvkm_object_ofuncs, gf100_sw_omthds }, - {} -}; - -/******************************************************************************* - * software context - ******************************************************************************/ - static int -gf100_sw_vblsem_release(struct nvkm_notify *notify) +gf100_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) { - struct nv50_sw_chan *chan = - container_of(notify, typeof(*chan), vblank.notify[notify->index]); - struct nv50_sw_priv *priv = (void *)nv_object(chan)->engine; - struct nvkm_bar *bar = nvkm_bar(priv); + struct nvkm_disp *disp = sw->engine.subdev.device->disp; + struct nv50_sw_chan *chan; + int ret, i; - nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); - bar->flush(bar); - nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); - nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); - nv_wr32(priv, 0x060014, chan->vblank.value); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; - return NVKM_NOTIFY_DROP; -} + ret = nvkm_sw_chan_ctor(&gf100_sw_chan, sw, fifoch, oclass, + &chan->base); + if (ret) + return ret; -static struct nv50_sw_cclass -gf100_sw_cclass = { - .base.handle = NV_ENGCTX(SW, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_sw_context_ctor, - .dtor = nv50_sw_context_dtor, - .init = _nvkm_sw_context_init, - .fini = _nvkm_sw_context_fini, - }, - .vblank = gf100_sw_vblsem_release, -}; + for (i = 0; disp && i < disp->vblank.index_nr; i++) { + ret = nvkm_notify_init(NULL, &disp->vblank, + gf100_sw_chan_vblsem_release, false, + &(struct nvif_notify_head_req_v0) { + .head = i, + }, + sizeof(struct nvif_notify_head_req_v0), + sizeof(struct nvif_notify_head_rep_v0), + &chan->vblank.notify[i]); + if (ret) + return ret; + } + + return 0; +} /******************************************************************************* * software engine/subdev functions ******************************************************************************/ -struct nvkm_oclass * -gf100_sw_oclass = &(struct nv50_sw_oclass) { - .base.handle = NV_ENGINE(SW, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_sw_ctor, - .dtor = _nvkm_sw_dtor, - .init = _nvkm_sw_init, - .fini = _nvkm_sw_fini, - }, - .cclass = &gf100_sw_cclass.base, - .sclass = gf100_sw_sclass, -}.base; +static const struct nvkm_sw_func +gf100_sw = { + .chan_new = gf100_sw_chan_new, + .sclass = { + { nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_GF100 } }, + {} + } +}; + +int +gf100_sw_new(struct nvkm_device *device, int index, struct nvkm_sw **psw) +{ + return nvkm_sw_new_(&gf100_sw, device, index, psw); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c index 897024421..445217ffa 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c @@ -21,15 +21,18 @@ * * Authors: Ben Skeggs */ -#include -#include +#define nv04_sw_chan(p) container_of((p), struct nv04_sw_chan, base) +#include "priv.h" +#include "chan.h" +#include "nvsw.h" -struct nv04_sw_priv { - struct nvkm_sw base; -}; +#include +#include +#include struct nv04_sw_chan { struct nvkm_sw_chan base; + atomic_t ref; }; /******************************************************************************* @@ -37,103 +40,99 @@ struct nv04_sw_chan { ******************************************************************************/ static int -nv04_sw_set_ref(struct nvkm_object *object, u32 mthd, void *data, u32 size) +nv04_nvsw_mthd_get_ref(struct nvkm_nvsw *nvsw, void *data, u32 size) { - struct nvkm_object *channel = (void *)nv_engctx(object->parent); - struct nvkm_fifo_chan *fifo = (void *)channel->parent; - atomic_set(&fifo->refcnt, *(u32*)data); - return 0; + struct nv04_sw_chan *chan = nv04_sw_chan(nvsw->chan); + union { + struct nv04_nvsw_get_ref_v0 v0; + } *args = data; + int ret; + + if (nvif_unpack(args->v0, 0, 0, false)) { + args->v0.ref = atomic_read(&chan->ref); + } + + return ret; } static int -nv04_sw_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) +nv04_nvsw_mthd(struct nvkm_nvsw *nvsw, u32 mthd, void *data, u32 size) { - struct nv04_sw_chan *chan = (void *)nv_engctx(object->parent); - if (chan->base.flip) - return chan->base.flip(chan->base.flip_data); + switch (mthd) { + case NV04_NVSW_GET_REF: + return nv04_nvsw_mthd_get_ref(nvsw, data, size); + default: + break; + } return -EINVAL; } -static struct nvkm_omthds -nv04_sw_omthds[] = { - { 0x0150, 0x0150, nv04_sw_set_ref }, - { 0x0500, 0x0500, nv04_sw_flip }, - {} +static const struct nvkm_nvsw_func +nv04_nvsw = { + .mthd = nv04_nvsw_mthd, }; -static struct nvkm_oclass -nv04_sw_sclass[] = { - { 0x006e, &nvkm_object_ofuncs, nv04_sw_omthds }, - {} -}; +static int +nv04_nvsw_new(struct nvkm_sw_chan *chan, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + return nvkm_nvsw_new_(&nv04_nvsw, chan, oclass, data, size, pobject); +} /******************************************************************************* * software context ******************************************************************************/ -static int -nv04_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static bool +nv04_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) { - struct nv04_sw_chan *chan; - int ret; + struct nv04_sw_chan *chan = nv04_sw_chan(base); - ret = nvkm_sw_context_create(parent, engine, oclass, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; + switch (mthd) { + case 0x0150: + atomic_set(&chan->ref, data); + return true; + default: + break; + } - return 0; + return false; } -static struct nvkm_oclass -nv04_sw_cclass = { - .handle = NV_ENGCTX(SW, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_sw_context_ctor, - .dtor = _nvkm_sw_context_dtor, - .init = _nvkm_sw_context_init, - .fini = _nvkm_sw_context_fini, - }, +static const struct nvkm_sw_chan_func +nv04_sw_chan = { + .mthd = nv04_sw_chan_mthd, }; -/******************************************************************************* - * software engine/subdev functions - ******************************************************************************/ - -void -nv04_sw_intr(struct nvkm_subdev *subdev) -{ - nv_mask(subdev, 0x000100, 0x80000000, 0x00000000); -} - static int -nv04_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nv04_sw_priv *priv; - int ret; + struct nv04_sw_chan *chan; - ret = nvkm_sw_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + atomic_set(&chan->ref, 0); + *pobject = &chan->base.object; - nv_engine(priv)->cclass = &nv04_sw_cclass; - nv_engine(priv)->sclass = nv04_sw_sclass; - nv_subdev(priv)->intr = nv04_sw_intr; - return 0; + return nvkm_sw_chan_ctor(&nv04_sw_chan, sw, fifo, oclass, &chan->base); } -struct nvkm_oclass * -nv04_sw_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(SW, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_sw_ctor, - .dtor = _nvkm_sw_dtor, - .init = _nvkm_sw_init, - .fini = _nvkm_sw_fini, - }, +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static const struct nvkm_sw_func +nv04_sw = { + .chan_new = nv04_sw_chan_new, + .sclass = { + { nv04_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV04 } }, + {} + } }; + +int +nv04_sw_new(struct nvkm_device *device, int index, struct nvkm_sw **psw) +{ + return nvkm_sw_new_(&nv04_sw, device, index, psw); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c index c61153a3f..adf70d92b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c @@ -21,102 +21,48 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" +#include "chan.h" +#include "nvsw.h" -struct nv10_sw_priv { - struct nvkm_sw base; -}; - -struct nv10_sw_chan { - struct nvkm_sw_chan base; -}; +#include /******************************************************************************* - * software object classes + * software context ******************************************************************************/ -static int -nv10_sw_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) -{ - struct nv10_sw_chan *chan = (void *)nv_engctx(object->parent); - if (chan->base.flip) - return chan->base.flip(chan->base.flip_data); - return -EINVAL; -} - -static struct nvkm_omthds -nv10_sw_omthds[] = { - { 0x0500, 0x0500, nv10_sw_flip }, - {} -}; - -static struct nvkm_oclass -nv10_sw_sclass[] = { - { 0x016e, &nvkm_object_ofuncs, nv10_sw_omthds }, - {} +static const struct nvkm_sw_chan_func +nv10_sw_chan = { }; -/******************************************************************************* - * software context - ******************************************************************************/ - static int -nv10_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv10_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nv10_sw_chan *chan; - int ret; + struct nvkm_sw_chan *chan; - ret = nvkm_sw_context_create(parent, engine, oclass, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->object; - return 0; + return nvkm_sw_chan_ctor(&nv10_sw_chan, sw, fifo, oclass, chan); } -static struct nvkm_oclass -nv10_sw_cclass = { - .handle = NV_ENGCTX(SW, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_sw_context_ctor, - .dtor = _nvkm_sw_context_dtor, - .init = _nvkm_sw_context_init, - .fini = _nvkm_sw_context_fini, - }, -}; - /******************************************************************************* * software engine/subdev functions ******************************************************************************/ -static int -nv10_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv10_sw_priv *priv; - int ret; - - ret = nvkm_sw_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_sw_func +nv10_sw = { + .chan_new = nv10_sw_chan_new, + .sclass = { + { nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV10 } }, + {} + } +}; - nv_engine(priv)->cclass = &nv10_sw_cclass; - nv_engine(priv)->sclass = nv10_sw_sclass; - nv_subdev(priv)->intr = nv04_sw_intr; - return 0; +int +nv10_sw_new(struct nvkm_device *device, int index, struct nvkm_sw **psw) +{ + return nvkm_sw_new_(&nv10_sw, device, index, psw); } - -struct nvkm_oclass * -nv10_sw_oclass = &(struct nvkm_oclass) { - .handle = NV_ENGINE(SW, 0x10), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_sw_ctor, - .dtor = _nvkm_sw_dtor, - .init = _nvkm_sw_init, - .fini = _nvkm_sw_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c index 401fcd730..a381196af 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c @@ -23,153 +23,98 @@ */ #include "nv50.h" -#include -#include -#include +#include #include +#include #include #include - -/******************************************************************************* - * software object classes - ******************************************************************************/ - -static int -nv50_sw_mthd_dma_vblsem(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - struct nvkm_fifo_chan *fifo = (void *)nv_object(chan)->parent; - struct nvkm_handle *handle; - int ret = -EINVAL; - - handle = nvkm_namedb_get(nv_namedb(fifo), *(u32 *)args); - if (!handle) - return -ENOENT; - - if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { - struct nvkm_gpuobj *gpuobj = nv_gpuobj(handle->object); - chan->vblank.ctxdma = gpuobj->node->offset >> 4; - ret = 0; - } - nvkm_namedb_put(handle); - return ret; -} - -static int -nv50_sw_mthd_vblsem_offset(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - chan->vblank.offset = *(u32 *)args; - return 0; -} - -int -nv50_sw_mthd_vblsem_value(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - chan->vblank.value = *(u32 *)args; - return 0; -} - -int -nv50_sw_mthd_vblsem_release(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - u32 head = *(u32 *)args; - if (head >= nvkm_disp(chan)->vblank.index_nr) - return -EINVAL; - - nvkm_notify_get(&chan->vblank.notify[head]); - return 0; -} - -int -nv50_sw_mthd_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - if (chan->base.flip) - return chan->base.flip(chan->base.flip_data); - return -EINVAL; -} - -static struct nvkm_omthds -nv50_sw_omthds[] = { - { 0x018c, 0x018c, nv50_sw_mthd_dma_vblsem }, - { 0x0400, 0x0400, nv50_sw_mthd_vblsem_offset }, - { 0x0404, 0x0404, nv50_sw_mthd_vblsem_value }, - { 0x0408, 0x0408, nv50_sw_mthd_vblsem_release }, - { 0x0500, 0x0500, nv50_sw_mthd_flip }, - {} -}; - -static struct nvkm_oclass -nv50_sw_sclass[] = { - { 0x506e, &nvkm_object_ofuncs, nv50_sw_omthds }, - {} -}; +#include /******************************************************************************* * software context ******************************************************************************/ static int -nv50_sw_vblsem_release(struct nvkm_notify *notify) +nv50_sw_chan_vblsem_release(struct nvkm_notify *notify) { struct nv50_sw_chan *chan = container_of(notify, typeof(*chan), vblank.notify[notify->index]); - struct nv50_sw_priv *priv = (void *)nv_object(chan)->engine; - struct nvkm_bar *bar = nvkm_bar(priv); + struct nvkm_sw *sw = chan->base.sw; + struct nvkm_device *device = sw->engine.subdev.device; - nv_wr32(priv, 0x001704, chan->vblank.channel); - nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); - bar->flush(bar); + nvkm_wr32(device, 0x001704, chan->base.fifo->inst->addr >> 12); + nvkm_wr32(device, 0x001710, 0x80000000 | chan->vblank.ctxdma); + nvkm_bar_flush(device->bar); - if (nv_device(priv)->chipset == 0x50) { - nv_wr32(priv, 0x001570, chan->vblank.offset); - nv_wr32(priv, 0x001574, chan->vblank.value); + if (device->chipset == 0x50) { + nvkm_wr32(device, 0x001570, chan->vblank.offset); + nvkm_wr32(device, 0x001574, chan->vblank.value); } else { - nv_wr32(priv, 0x060010, chan->vblank.offset); - nv_wr32(priv, 0x060014, chan->vblank.value); + nvkm_wr32(device, 0x060010, chan->vblank.offset); + nvkm_wr32(device, 0x060014, chan->vblank.value); } return NVKM_NOTIFY_DROP; } -void -nv50_sw_context_dtor(struct nvkm_object *object) +static bool +nv50_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) { - struct nv50_sw_chan *chan = (void *)object; - int i; + struct nv50_sw_chan *chan = nv50_sw_chan(base); + struct nvkm_engine *engine = chan->base.object.engine; + struct nvkm_device *device = engine->subdev.device; + switch (mthd) { + case 0x018c: chan->vblank.ctxdma = data; return true; + case 0x0400: chan->vblank.offset = data; return true; + case 0x0404: chan->vblank.value = data; return true; + case 0x0408: + if (data < device->disp->vblank.index_nr) { + nvkm_notify_get(&chan->vblank.notify[data]); + return true; + } + break; + default: + break; + } + return false; +} +void * +nv50_sw_chan_dtor(struct nvkm_sw_chan *base) +{ + struct nv50_sw_chan *chan = nv50_sw_chan(base); + int i; for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++) nvkm_notify_fini(&chan->vblank.notify[i]); - - nvkm_sw_context_destroy(&chan->base); + return chan; } -int -nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_sw_chan_func +nv50_sw_chan = { + .dtor = nv50_sw_chan_dtor, + .mthd = nv50_sw_chan_mthd, +}; + +static int +nv50_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nvkm_disp *pdisp = nvkm_disp(parent); - struct nv50_sw_cclass *pclass = (void *)oclass; + struct nvkm_disp *disp = sw->engine.subdev.device->disp; struct nv50_sw_chan *chan; int ret, i; - ret = nvkm_sw_context_create(parent, engine, oclass, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nvkm_sw_chan_ctor(&nv50_sw_chan, sw, fifoch, oclass, &chan->base); if (ret) return ret; - for (i = 0; pdisp && i < pdisp->vblank.index_nr; i++) { - ret = nvkm_notify_init(NULL, &pdisp->vblank, pclass->vblank, - false, + for (i = 0; disp && i < disp->vblank.index_nr; i++) { + ret = nvkm_notify_init(NULL, &disp->vblank, + nv50_sw_chan_vblsem_release, false, &(struct nvif_notify_head_req_v0) { .head = i, }, @@ -180,55 +125,24 @@ nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, return ret; } - chan->vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; return 0; } -static struct nv50_sw_cclass -nv50_sw_cclass = { - .base.handle = NV_ENGCTX(SW, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_sw_context_ctor, - .dtor = nv50_sw_context_dtor, - .init = _nvkm_sw_context_init, - .fini = _nvkm_sw_context_fini, - }, - .vblank = nv50_sw_vblsem_release, -}; - /******************************************************************************* * software engine/subdev functions ******************************************************************************/ +static const struct nvkm_sw_func +nv50_sw = { + .chan_new = nv50_sw_chan_new, + .sclass = { + { nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV50 } }, + {} + } +}; + int -nv50_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_sw_new(struct nvkm_device *device, int index, struct nvkm_sw **psw) { - struct nv50_sw_oclass *pclass = (void *)oclass; - struct nv50_sw_priv *priv; - int ret; - - ret = nvkm_sw_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_engine(priv)->cclass = pclass->cclass; - nv_engine(priv)->sclass = pclass->sclass; - nv_subdev(priv)->intr = nv04_sw_intr; - return 0; + return nvkm_sw_new_(&nv50_sw, device, index, psw); } - -struct nvkm_oclass * -nv50_sw_oclass = &(struct nv50_sw_oclass) { - .base.handle = NV_ENGINE(SW, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_sw_ctor, - .dtor = _nvkm_sw_dtor, - .init = _nvkm_sw_init, - .fini = _nvkm_sw_fini, - }, - .cclass = &nv50_sw_cclass.base, - .sclass = nv50_sw_sclass, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h index d8adc1108..25cdfdef2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h @@ -1,45 +1,20 @@ #ifndef __NVKM_SW_NV50_H__ #define __NVKM_SW_NV50_H__ -#include +#define nv50_sw_chan(p) container_of((p), struct nv50_sw_chan, base) +#include "priv.h" +#include "chan.h" +#include "nvsw.h" #include -struct nv50_sw_oclass { - struct nvkm_oclass base; - struct nvkm_oclass *cclass; - struct nvkm_oclass *sclass; -}; - -struct nv50_sw_priv { - struct nvkm_sw base; -}; - -int nv50_sw_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - -struct nv50_sw_cclass { - struct nvkm_oclass base; - int (*vblank)(struct nvkm_notify *); -}; - struct nv50_sw_chan { struct nvkm_sw_chan base; struct { struct nvkm_notify notify[4]; - u32 channel; u32 ctxdma; u64 offset; u32 value; } vblank; }; -int nv50_sw_context_ctor(struct nvkm_object *, - struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv50_sw_context_dtor(struct nvkm_object *); - -int nv50_sw_mthd_vblsem_value(struct nvkm_object *, u32, void *, u32); -int nv50_sw_mthd_vblsem_release(struct nvkm_object *, u32, void *, u32); -int nv50_sw_mthd_flip(struct nvkm_object *, u32, void *, u32); +void *nv50_sw_chan_dtor(struct nvkm_sw_chan *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c new file mode 100644 index 000000000..66cf986b9 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c @@ -0,0 +1,85 @@ +/* + * 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 + */ +#include "nvsw.h" +#include "chan.h" + +#include + +static int +nvkm_nvsw_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) +{ + struct nvkm_nvsw *nvsw = nvkm_nvsw(object); + if (nvsw->func->mthd) + return nvsw->func->mthd(nvsw, mthd, data, size); + return -ENODEV; +} + +static int +nvkm_nvsw_ntfy_(struct nvkm_object *object, u32 mthd, + struct nvkm_event **pevent) +{ + struct nvkm_nvsw *nvsw = nvkm_nvsw(object); + switch (mthd) { + case NVSW_NTFY_UEVENT: + *pevent = &nvsw->chan->event; + return 0; + default: + break; + } + return -EINVAL; +} + +static const struct nvkm_object_func +nvkm_nvsw_ = { + .mthd = nvkm_nvsw_mthd_, + .ntfy = nvkm_nvsw_ntfy_, +}; + +int +nvkm_nvsw_new_(const struct nvkm_nvsw_func *func, struct nvkm_sw_chan *chan, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_nvsw *nvsw; + + if (!(nvsw = kzalloc(sizeof(*nvsw), GFP_KERNEL))) + return -ENOMEM; + *pobject = &nvsw->object; + + nvkm_object_ctor(&nvkm_nvsw_, oclass, &nvsw->object); + nvsw->func = func; + nvsw->chan = chan; + return 0; +} + +static const struct nvkm_nvsw_func +nvkm_nvsw = { +}; + +int +nvkm_nvsw_new(struct nvkm_sw_chan *chan, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + return nvkm_nvsw_new_(&nvkm_nvsw, chan, oclass, data, size, pobject); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h new file mode 100644 index 000000000..943ef4c10 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h @@ -0,0 +1,21 @@ +#ifndef __NVKM_NVSW_H__ +#define __NVKM_NVSW_H__ +#define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object) +#include "priv.h" + +struct nvkm_nvsw { + struct nvkm_object object; + const struct nvkm_nvsw_func *func; + struct nvkm_sw_chan *chan; +}; + +struct nvkm_nvsw_func { + int (*mthd)(struct nvkm_nvsw *, u32 mthd, void *data, u32 size); +}; + +int nvkm_nvsw_new_(const struct nvkm_nvsw_func *, struct nvkm_sw_chan *, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **pobject); +int nvkm_nvsw_new(struct nvkm_sw_chan *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **pobject); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h new file mode 100644 index 000000000..0ef1318dc --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h @@ -0,0 +1,21 @@ +#ifndef __NVKM_SW_PRIV_H__ +#define __NVKM_SW_PRIV_H__ +#define nvkm_sw(p) container_of((p), struct nvkm_sw, engine) +#include +struct nvkm_sw_chan; + +int nvkm_sw_new_(const struct nvkm_sw_func *, struct nvkm_device *, + int index, struct nvkm_sw **); + +struct nvkm_sw_chan_sclass { + int (*ctor)(struct nvkm_sw_chan *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + struct nvkm_sclass base; +}; + +struct nvkm_sw_func { + int (*chan_new)(struct nvkm_sw *, struct nvkm_fifo_chan *, + const struct nvkm_oclass *, struct nvkm_object **); + const struct nvkm_sw_chan_sclass sclass[]; +}; +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c index 45f4e186b..4188c77ac 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c @@ -22,72 +22,23 @@ * Authors: Ben Skeggs, Ilia Mirkin */ #include -#include -#include - -/******************************************************************************* - * VP object classes - ******************************************************************************/ - -static struct nvkm_oclass -g84_vp_sclass[] = { - { 0x7476, &nvkm_object_ofuncs }, - {}, -}; - -/******************************************************************************* - * PVP context - ******************************************************************************/ - -static struct nvkm_oclass -g84_vp_cclass = { - .handle = NV_ENGCTX(VP, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_xtensa_engctx_ctor, - .dtor = _nvkm_engctx_dtor, - .init = _nvkm_engctx_init, - .fini = _nvkm_engctx_fini, - .rd32 = _nvkm_engctx_rd32, - .wr32 = _nvkm_engctx_wr32, - }, +#include + +static const struct nvkm_xtensa_func +g84_vp = { + .pmc_enable = 0x01020000, + .fifo_val = 0x111, + .unkd28 = 0x9c544, + .sclass = { + { -1, -1, NV74_VP2 }, + {} + } }; -/******************************************************************************* - * PVP engine/subdev functions - ******************************************************************************/ - -static int -g84_vp_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +g84_vp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine) { - struct nvkm_xtensa *priv; - int ret; - - ret = nvkm_xtensa_create(parent, engine, oclass, 0xf000, true, - "PVP", "vp", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->unit = 0x01020000; - nv_engine(priv)->cclass = &g84_vp_cclass; - nv_engine(priv)->sclass = g84_vp_sclass; - priv->fifo_val = 0x111; - priv->unkd28 = 0x9c544; - return 0; + return nvkm_xtensa_new_(&g84_vp, device, index, + true, 0x00f000, pengine); } - -struct nvkm_oclass -g84_vp_oclass = { - .handle = NV_ENGINE(VP, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_vp_ctor, - .dtor = _nvkm_xtensa_dtor, - .init = _nvkm_xtensa_init, - .fini = _nvkm_xtensa_fini, - .rd32 = _nvkm_xtensa_rd32, - .wr32 = _nvkm_xtensa_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c index cea90df53..a3d4f5bce 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c @@ -20,153 +20,173 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include -#include -#include +#include +#include -u32 -_nvkm_xtensa_rd32(struct nvkm_object *object, u64 addr) +static int +nvkm_xtensa_oclass_get(struct nvkm_oclass *oclass, int index) { - struct nvkm_xtensa *xtensa = (void *)object; - return nv_rd32(xtensa, xtensa->addr + addr); -} + struct nvkm_xtensa *xtensa = nvkm_xtensa(oclass->engine); + int c = 0; -void -_nvkm_xtensa_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nvkm_xtensa *xtensa = (void *)object; - nv_wr32(xtensa, xtensa->addr + addr, data); + while (xtensa->func->sclass[c].oclass) { + if (c++ == index) { + oclass->base = xtensa->func->sclass[index]; + return index; + } + } + + return c; } -int -_nvkm_xtensa_engctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static int +nvkm_xtensa_cclass_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, + int align, struct nvkm_gpuobj **pgpuobj) { - struct nvkm_engctx *engctx; - int ret; - - ret = nvkm_engctx_create(parent, engine, oclass, NULL, 0x10000, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &engctx); - *pobject = nv_object(engctx); - return ret; + return nvkm_gpuobj_new(object->engine->subdev.device, 0x10000, align, + true, parent, pgpuobj); } -void -_nvkm_xtensa_intr(struct nvkm_subdev *subdev) +static const struct nvkm_object_func +nvkm_xtensa_cclass = { + .bind = nvkm_xtensa_cclass_bind, +}; + +static void +nvkm_xtensa_intr(struct nvkm_engine *engine) { - struct nvkm_xtensa *xtensa = (void *)subdev; - u32 unk104 = nv_ro32(xtensa, 0xd04); - u32 intr = nv_ro32(xtensa, 0xc20); - u32 chan = nv_ro32(xtensa, 0xc28); - u32 unk10c = nv_ro32(xtensa, 0xd0c); + struct nvkm_xtensa *xtensa = nvkm_xtensa(engine); + struct nvkm_subdev *subdev = &xtensa->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 base = xtensa->addr; + u32 unk104 = nvkm_rd32(device, base + 0xd04); + u32 intr = nvkm_rd32(device, base + 0xc20); + u32 chan = nvkm_rd32(device, base + 0xc28); + u32 unk10c = nvkm_rd32(device, base + 0xd0c); if (intr & 0x10) - nv_warn(xtensa, "Watchdog interrupt, engine hung.\n"); - nv_wo32(xtensa, 0xc20, intr); - intr = nv_ro32(xtensa, 0xc20); + nvkm_warn(subdev, "Watchdog interrupt, engine hung.\n"); + nvkm_wr32(device, base + 0xc20, intr); + intr = nvkm_rd32(device, base + 0xc20); if (unk104 == 0x10001 && unk10c == 0x200 && chan && !intr) { - nv_debug(xtensa, "Enabling FIFO_CTRL\n"); - nv_mask(xtensa, xtensa->addr + 0xd94, 0, xtensa->fifo_val); + nvkm_debug(subdev, "Enabling FIFO_CTRL\n"); + nvkm_mask(device, xtensa->addr + 0xd94, 0, xtensa->func->fifo_val); } } -int -nvkm_xtensa_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 addr, bool enable, - const char *iname, const char *fname, - int length, void **pobject) +static int +nvkm_xtensa_fini(struct nvkm_engine *engine, bool suspend) { - struct nvkm_xtensa *xtensa; - int ret; + struct nvkm_xtensa *xtensa = nvkm_xtensa(engine); + struct nvkm_device *device = xtensa->engine.subdev.device; + const u32 base = xtensa->addr; - ret = nvkm_engine_create_(parent, engine, oclass, enable, iname, - fname, length, pobject); - xtensa = *pobject; - if (ret) - return ret; + nvkm_wr32(device, base + 0xd84, 0); /* INTR_EN */ + nvkm_wr32(device, base + 0xd94, 0); /* FIFO_CTRL */ - nv_subdev(xtensa)->intr = _nvkm_xtensa_intr; - xtensa->addr = addr; + if (!suspend) + nvkm_memory_del(&xtensa->gpu_fw); return 0; } -int -_nvkm_xtensa_init(struct nvkm_object *object) +static int +nvkm_xtensa_init(struct nvkm_engine *engine) { - struct nvkm_device *device = nv_device(object); - struct nvkm_xtensa *xtensa = (void *)object; + struct nvkm_xtensa *xtensa = nvkm_xtensa(engine); + struct nvkm_subdev *subdev = &xtensa->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 base = xtensa->addr; const struct firmware *fw; char name[32]; int i, ret; + u64 addr, size; u32 tmp; - ret = nvkm_engine_init(&xtensa->base); - if (ret) - return ret; - if (!xtensa->gpu_fw) { snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x", xtensa->addr >> 12); - ret = request_firmware(&fw, name, nv_device_base(device)); + ret = request_firmware(&fw, name, device->dev); if (ret) { - nv_warn(xtensa, "unable to load firmware %s\n", name); + nvkm_warn(subdev, "unable to load firmware %s\n", name); return ret; } if (fw->size > 0x40000) { - nv_warn(xtensa, "firmware %s too large\n", name); + nvkm_warn(subdev, "firmware %s too large\n", name); release_firmware(fw); return -EINVAL; } - ret = nvkm_gpuobj_new(object, NULL, 0x40000, 0x1000, 0, + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + 0x40000, 0x1000, false, &xtensa->gpu_fw); if (ret) { release_firmware(fw); return ret; } - nv_debug(xtensa, "Loading firmware to address: 0x%llx\n", - xtensa->gpu_fw->addr); - + nvkm_kmap(xtensa->gpu_fw); for (i = 0; i < fw->size / 4; i++) - nv_wo32(xtensa->gpu_fw, i * 4, *((u32 *)fw->data + i)); + nvkm_wo32(xtensa->gpu_fw, i * 4, *((u32 *)fw->data + i)); + nvkm_done(xtensa->gpu_fw); release_firmware(fw); } - nv_wo32(xtensa, 0xd10, 0x1fffffff); /* ?? */ - nv_wo32(xtensa, 0xd08, 0x0fffffff); /* ?? */ + addr = nvkm_memory_addr(xtensa->gpu_fw); + size = nvkm_memory_size(xtensa->gpu_fw); - nv_wo32(xtensa, 0xd28, xtensa->unkd28); /* ?? */ - nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */ - nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */ + nvkm_wr32(device, base + 0xd10, 0x1fffffff); /* ?? */ + nvkm_wr32(device, base + 0xd08, 0x0fffffff); /* ?? */ - nv_wo32(xtensa, 0xcc0, xtensa->gpu_fw->addr >> 8); /* XT_REGION_BASE */ - nv_wo32(xtensa, 0xcc4, 0x1c); /* XT_REGION_SETUP */ - nv_wo32(xtensa, 0xcc8, xtensa->gpu_fw->size >> 8); /* XT_REGION_LIMIT */ + nvkm_wr32(device, base + 0xd28, xtensa->func->unkd28); /* ?? */ + nvkm_wr32(device, base + 0xc20, 0x3f); /* INTR */ + nvkm_wr32(device, base + 0xd84, 0x3f); /* INTR_EN */ - tmp = nv_rd32(xtensa, 0x0); - nv_wo32(xtensa, 0xde0, tmp); /* SCRATCH_H2X */ + nvkm_wr32(device, base + 0xcc0, addr >> 8); /* XT_REGION_BASE */ + nvkm_wr32(device, base + 0xcc4, 0x1c); /* XT_REGION_SETUP */ + nvkm_wr32(device, base + 0xcc8, size >> 8); /* XT_REGION_LIMIT */ - nv_wo32(xtensa, 0xce8, 0xf); /* XT_REGION_SETUP */ + tmp = nvkm_rd32(device, 0x0); + nvkm_wr32(device, base + 0xde0, tmp); /* SCRATCH_H2X */ - nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */ - nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */ + nvkm_wr32(device, base + 0xce8, 0xf); /* XT_REGION_SETUP */ + + nvkm_wr32(device, base + 0xc20, 0x3f); /* INTR */ + nvkm_wr32(device, base + 0xd84, 0x3f); /* INTR_EN */ return 0; } -int -_nvkm_xtensa_fini(struct nvkm_object *object, bool suspend) +static void * +nvkm_xtensa_dtor(struct nvkm_engine *engine) { - struct nvkm_xtensa *xtensa = (void *)object; + return nvkm_xtensa(engine); +} - nv_wo32(xtensa, 0xd84, 0); /* INTR_EN */ - nv_wo32(xtensa, 0xd94, 0); /* FIFO_CTRL */ +static const struct nvkm_engine_func +nvkm_xtensa = { + .dtor = nvkm_xtensa_dtor, + .init = nvkm_xtensa_init, + .fini = nvkm_xtensa_fini, + .intr = nvkm_xtensa_intr, + .fifo.sclass = nvkm_xtensa_oclass_get, + .cclass = &nvkm_xtensa_cclass, +}; - if (!suspend) - nvkm_gpuobj_ref(NULL, &xtensa->gpu_fw); +int +nvkm_xtensa_new_(const struct nvkm_xtensa_func *func, + struct nvkm_device *device, int index, bool enable, + u32 addr, struct nvkm_engine **pengine) +{ + struct nvkm_xtensa *xtensa; + + if (!(xtensa = kzalloc(sizeof(*xtensa), GFP_KERNEL))) + return -ENOMEM; + xtensa->func = func; + xtensa->addr = addr; + *pengine = &xtensa->engine; - return nvkm_engine_fini(&xtensa->base, suspend); + return nvkm_engine_ctor(&nvkm_xtensa, device, index, func->pmc_enable, + enable, &xtensa->engine); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild index a1bb3e487..ee2c38f50 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild @@ -13,6 +13,7 @@ include $(src)/nvkm/subdev/ltc/Kbuild include $(src)/nvkm/subdev/mc/Kbuild include $(src)/nvkm/subdev/mmu/Kbuild include $(src)/nvkm/subdev/mxm/Kbuild +include $(src)/nvkm/subdev/pci/Kbuild include $(src)/nvkm/subdev/pmu/Kbuild include $(src)/nvkm/subdev/therm/Kbuild include $(src)/nvkm/subdev/timer/Kbuild diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild index 1ab554a0b..1e138b337 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild @@ -1,4 +1,5 @@ nvkm-y += nvkm/subdev/bar/base.o nvkm-y += nvkm/subdev/bar/nv50.o +nvkm-y += nvkm/subdev/bar/g84.o nvkm-y += nvkm/subdev/bar/gf100.o nvkm-y += nvkm/subdev/bar/gk20a.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c index 3502d0012..a9433ad45 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c @@ -23,122 +23,61 @@ */ #include "priv.h" -#include -#include -#include - -struct nvkm_barobj { - struct nvkm_object base; - struct nvkm_vma vma; - void __iomem *iomem; -}; - -static int -nvkm_barobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +void +nvkm_bar_flush(struct nvkm_bar *bar) { - struct nvkm_device *device = nv_device(parent); - struct nvkm_bar *bar = nvkm_bar(device); - struct nvkm_mem *mem = data; - struct nvkm_barobj *barobj; - int ret; - - ret = nvkm_object_create(parent, engine, oclass, 0, &barobj); - *pobject = nv_object(barobj); - if (ret) - return ret; - - ret = bar->kmap(bar, mem, NV_MEM_ACCESS_RW, &barobj->vma); - if (ret) - return ret; - - barobj->iomem = ioremap(nv_device_resource_start(device, 3) + - (u32)barobj->vma.offset, mem->size << 12); - if (!barobj->iomem) { - nv_warn(bar, "PRAMIN ioremap failed\n"); - return -ENOMEM; - } - - return 0; + if (bar && bar->func->flush) + bar->func->flush(bar); } -static void -nvkm_barobj_dtor(struct nvkm_object *object) +struct nvkm_vm * +nvkm_bar_kmap(struct nvkm_bar *bar) { - struct nvkm_bar *bar = nvkm_bar(object); - struct nvkm_barobj *barobj = (void *)object; - if (barobj->vma.node) { - if (barobj->iomem) - iounmap(barobj->iomem); - bar->unmap(bar, &barobj->vma); - } - nvkm_object_destroy(&barobj->base); + /* disallow kmap() until after vm has been bootstrapped */ + if (bar && bar->func->kmap && bar->subdev.oneinit) + return bar->func->kmap(bar); + return NULL; } -static u32 -nvkm_barobj_rd32(struct nvkm_object *object, u64 addr) +int +nvkm_bar_umap(struct nvkm_bar *bar, u64 size, int type, struct nvkm_vma *vma) { - struct nvkm_barobj *barobj = (void *)object; - return ioread32_native(barobj->iomem + addr); + return bar->func->umap(bar, size, type, vma); } -static void -nvkm_barobj_wr32(struct nvkm_object *object, u64 addr, u32 data) +static int +nvkm_bar_oneinit(struct nvkm_subdev *subdev) { - struct nvkm_barobj *barobj = (void *)object; - iowrite32_native(data, barobj->iomem + addr); + struct nvkm_bar *bar = nvkm_bar(subdev); + return bar->func->oneinit(bar); } -static struct nvkm_oclass -nvkm_barobj_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nvkm_barobj_ctor, - .dtor = nvkm_barobj_dtor, - .init = nvkm_object_init, - .fini = nvkm_object_fini, - .rd32 = nvkm_barobj_rd32, - .wr32 = nvkm_barobj_wr32, - }, -}; - -int -nvkm_bar_alloc(struct nvkm_bar *bar, struct nvkm_object *parent, - struct nvkm_mem *mem, struct nvkm_object **pobject) +static int +nvkm_bar_init(struct nvkm_subdev *subdev) { - struct nvkm_object *gpuobj; - int ret = nvkm_object_ctor(parent, &parent->engine->subdev.object, - &nvkm_barobj_oclass, mem, 0, &gpuobj); - if (ret == 0) - *pobject = gpuobj; - return ret; + struct nvkm_bar *bar = nvkm_bar(subdev); + return bar->func->init(bar); } -int -nvkm_bar_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +static void * +nvkm_bar_dtor(struct nvkm_subdev *subdev) { - struct nvkm_bar *bar; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "BARCTL", - "bar", length, pobject); - bar = *pobject; - if (ret) - return ret; - - return 0; + struct nvkm_bar *bar = nvkm_bar(subdev); + return bar->func->dtor(bar); } -void -nvkm_bar_destroy(struct nvkm_bar *bar) -{ - nvkm_subdev_destroy(&bar->base); -} +static const struct nvkm_subdev_func +nvkm_bar = { + .dtor = nvkm_bar_dtor, + .oneinit = nvkm_bar_oneinit, + .init = nvkm_bar_init, +}; void -_nvkm_bar_dtor(struct nvkm_object *object) +nvkm_bar_ctor(const struct nvkm_bar_func *func, struct nvkm_device *device, + int index, struct nvkm_bar *bar) { - struct nvkm_bar *bar = (void *)object; - nvkm_bar_destroy(bar); + nvkm_subdev_ctor(&nvkm_bar, device, index, 0, &bar->subdev); + bar->func = func; + spin_lock_init(&bar->lock); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c new file mode 100644 index 000000000..ef717136c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c @@ -0,0 +1,56 @@ +/* + * 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 + */ +#include "nv50.h" + +#include + +void +g84_bar_flush(struct nvkm_bar *bar) +{ + struct nvkm_device *device = bar->subdev.device; + unsigned long flags; + spin_lock_irqsave(&bar->lock, flags); + nvkm_wr32(device, 0x070000, 0x00000001); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x070000) & 0x00000002)) + break; + ); + spin_unlock_irqrestore(&bar->lock, flags); +} + +static const struct nvkm_bar_func +g84_bar_func = { + .dtor = nv50_bar_dtor, + .oneinit = nv50_bar_oneinit, + .init = nv50_bar_init, + .kmap = nv50_bar_kmap, + .umap = nv50_bar_umap, + .flush = g84_bar_flush, +}; + +int +g84_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) +{ + return nv50_bar_new_(&g84_bar_func, device, index, 0x200, pbar); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c index 12a1aebd9..c794b2c2d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c @@ -21,101 +21,60 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "gf100.h" -#include #include #include #include -struct gf100_bar_priv_vm { - struct nvkm_gpuobj *mem; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; -}; - -struct gf100_bar_priv { - struct nvkm_bar base; - spinlock_t lock; - struct gf100_bar_priv_vm bar[2]; -}; - -static int -gf100_bar_kmap(struct nvkm_bar *bar, struct nvkm_mem *mem, u32 flags, - struct nvkm_vma *vma) -{ - struct gf100_bar_priv *priv = (void *)bar; - int ret; - - ret = nvkm_vm_get(priv->bar[0].vm, mem->size << 12, 12, flags, vma); - if (ret) - return ret; - - nvkm_vm_map(vma, mem); - return 0; -} - -static int -gf100_bar_umap(struct nvkm_bar *bar, struct nvkm_mem *mem, u32 flags, - struct nvkm_vma *vma) +static struct nvkm_vm * +gf100_bar_kmap(struct nvkm_bar *base) { - struct gf100_bar_priv *priv = (void *)bar; - int ret; - - ret = nvkm_vm_get(priv->bar[1].vm, mem->size << 12, - mem->page_shift, flags, vma); - if (ret) - return ret; - - nvkm_vm_map(vma, mem); - return 0; + return gf100_bar(base)->bar[0].vm; } -static void -gf100_bar_unmap(struct nvkm_bar *bar, struct nvkm_vma *vma) +int +gf100_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) { - nvkm_vm_unmap(vma); - nvkm_vm_put(vma); + struct gf100_bar *bar = gf100_bar(base); + return nvkm_vm_get(bar->bar[1].vm, size, type, NV_MEM_ACCESS_RW, vma); } static int -gf100_bar_ctor_vm(struct gf100_bar_priv *priv, struct gf100_bar_priv_vm *bar_vm, - int bar_nr) +gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm, + struct lock_class_key *key, int bar_nr) { - struct nvkm_device *device = nv_device(&priv->base); + struct nvkm_device *device = bar->base.subdev.device; struct nvkm_vm *vm; resource_size_t bar_len; int ret; - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false, &bar_vm->mem); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, - &bar_vm->pgd); + ret = nvkm_gpuobj_new(device, 0x8000, 0, false, NULL, &bar_vm->pgd); if (ret) return ret; - bar_len = nv_device_resource_len(device, bar_nr); + bar_len = device->func->resource_size(device, bar_nr); - ret = nvkm_vm_new(device, 0, bar_len, 0, &vm); + ret = nvkm_vm_new(device, 0, bar_len, 0, key, &vm); if (ret) return ret; - atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); + atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); /* * Bootstrap page table lookup. */ if (bar_nr == 3) { - ret = nvkm_gpuobj_new(nv_object(priv), NULL, - (bar_len >> 12) * 8, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, - &vm->pgt[0].obj[0]); - vm->pgt[0].refcount[0] = 1; - if (ret) + ret = nvkm_vm_boot(vm, bar_len); + if (ret) { + nvkm_vm_ref(NULL, &vm, NULL); return ret; + } } ret = nvkm_vm_ref(vm, &bar_vm->vm, bar_vm->pgd); @@ -123,97 +82,101 @@ gf100_bar_ctor_vm(struct gf100_bar_priv *priv, struct gf100_bar_priv_vm *bar_vm, if (ret) return ret; - nv_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr)); - nv_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr)); - nv_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1)); - nv_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1)); + nvkm_kmap(bar_vm->mem); + nvkm_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr)); + nvkm_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr)); + nvkm_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1)); + nvkm_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1)); + nvkm_done(bar_vm->mem); return 0; } int -gf100_bar_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_bar_oneinit(struct nvkm_bar *base) { - struct nvkm_device *device = nv_device(parent); - struct gf100_bar_priv *priv; - bool has_bar3 = nv_device_resource_len(device, 3) != 0; + static struct lock_class_key bar1_lock; + static struct lock_class_key bar3_lock; + struct gf100_bar *bar = gf100_bar(base); int ret; - ret = nvkm_bar_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - /* BAR3 */ - if (has_bar3) { - ret = gf100_bar_ctor_vm(priv, &priv->bar[0], 3); + if (bar->base.func->kmap) { + ret = gf100_bar_ctor_vm(bar, &bar->bar[0], &bar3_lock, 3); if (ret) return ret; } /* BAR1 */ - ret = gf100_bar_ctor_vm(priv, &priv->bar[1], 1); + ret = gf100_bar_ctor_vm(bar, &bar->bar[1], &bar1_lock, 1); if (ret) return ret; - if (has_bar3) { - priv->base.alloc = nvkm_bar_alloc; - priv->base.kmap = gf100_bar_kmap; - } - priv->base.umap = gf100_bar_umap; - priv->base.unmap = gf100_bar_unmap; - priv->base.flush = g84_bar_flush; - spin_lock_init(&priv->lock); return 0; } -void -gf100_bar_dtor(struct nvkm_object *object) +int +gf100_bar_init(struct nvkm_bar *base) { - struct gf100_bar_priv *priv = (void *)object; + struct gf100_bar *bar = gf100_bar(base); + struct nvkm_device *device = bar->base.subdev.device; + u32 addr; + + nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); + nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); - nvkm_vm_ref(NULL, &priv->bar[1].vm, priv->bar[1].pgd); - nvkm_gpuobj_ref(NULL, &priv->bar[1].pgd); - nvkm_gpuobj_ref(NULL, &priv->bar[1].mem); + addr = nvkm_memory_addr(bar->bar[1].mem) >> 12; + nvkm_wr32(device, 0x001704, 0x80000000 | addr); - if (priv->bar[0].vm) { - nvkm_gpuobj_ref(NULL, &priv->bar[0].vm->pgt[0].obj[0]); - nvkm_vm_ref(NULL, &priv->bar[0].vm, priv->bar[0].pgd); + if (bar->bar[0].mem) { + addr = nvkm_memory_addr(bar->bar[0].mem) >> 12; + nvkm_wr32(device, 0x001714, 0xc0000000 | addr); } - nvkm_gpuobj_ref(NULL, &priv->bar[0].pgd); - nvkm_gpuobj_ref(NULL, &priv->bar[0].mem); - nvkm_bar_destroy(&priv->base); + return 0; } -int -gf100_bar_init(struct nvkm_object *object) +void * +gf100_bar_dtor(struct nvkm_bar *base) { - struct gf100_bar_priv *priv = (void *)object; - int ret; + struct gf100_bar *bar = gf100_bar(base); - ret = nvkm_bar_init(&priv->base); - if (ret) - return ret; + nvkm_vm_ref(NULL, &bar->bar[1].vm, bar->bar[1].pgd); + nvkm_gpuobj_del(&bar->bar[1].pgd); + nvkm_memory_del(&bar->bar[1].mem); - nv_mask(priv, 0x000200, 0x00000100, 0x00000000); - nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + if (bar->bar[0].vm) { + nvkm_memory_del(&bar->bar[0].vm->pgt[0].mem[0]); + nvkm_vm_ref(NULL, &bar->bar[0].vm, bar->bar[0].pgd); + } + nvkm_gpuobj_del(&bar->bar[0].pgd); + nvkm_memory_del(&bar->bar[0].mem); + return bar; +} - nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); - if (priv->bar[0].mem) - nv_wr32(priv, 0x001714, - 0xc0000000 | priv->bar[0].mem->addr >> 12); +int +gf100_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device, + int index, struct nvkm_bar **pbar) +{ + struct gf100_bar *bar; + if (!(bar = kzalloc(sizeof(*bar), GFP_KERNEL))) + return -ENOMEM; + nvkm_bar_ctor(func, device, index, &bar->base); + *pbar = &bar->base; return 0; } -struct nvkm_oclass -gf100_bar_oclass = { - .handle = NV_SUBDEV(BAR, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_bar_ctor, - .dtor = gf100_bar_dtor, - .init = gf100_bar_init, - .fini = _nvkm_bar_fini, - }, +static const struct nvkm_bar_func +gf100_bar_func = { + .dtor = gf100_bar_dtor, + .oneinit = gf100_bar_oneinit, + .init = gf100_bar_init, + .kmap = gf100_bar_kmap, + .umap = gf100_bar_umap, + .flush = g84_bar_flush, }; + +int +gf100_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) +{ + return gf100_bar_new_(&gf100_bar_func, device, index, pbar); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h new file mode 100644 index 000000000..f7dea6964 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h @@ -0,0 +1,23 @@ +#ifndef __GF100_BAR_H__ +#define __GF100_BAR_H__ +#define gf100_bar(p) container_of((p), struct gf100_bar, base) +#include "priv.h" + +struct gf100_bar_vm { + struct nvkm_memory *mem; + struct nvkm_gpuobj *pgd; + struct nvkm_vm *vm; +}; + +struct gf100_bar { + struct nvkm_bar base; + struct gf100_bar_vm bar[2]; +}; + +int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, + int, struct nvkm_bar **); +void *gf100_bar_dtor(struct nvkm_bar *); +int gf100_bar_oneinit(struct nvkm_bar *); +int gf100_bar_init(struct nvkm_bar *); +int gf100_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c index 148f739a2..9232fab42 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c @@ -19,32 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include "priv.h" +#include "gf100.h" + +static const struct nvkm_bar_func +gk20a_bar_func = { + .dtor = gf100_bar_dtor, + .oneinit = gf100_bar_oneinit, + .init = gf100_bar_init, + .umap = gf100_bar_umap, + .flush = g84_bar_flush, +}; int -gk20a_bar_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gk20a_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) { - struct nvkm_bar *bar; - int ret; - - ret = gf100_bar_ctor(parent, engine, oclass, data, size, pobject); - if (ret) - return ret; - - bar = (struct nvkm_bar *)*pobject; - bar->iomap_uncached = true; - return 0; + int ret = gf100_bar_new_(&gk20a_bar_func, device, index, pbar); + if (ret == 0) + (*pbar)->iomap_uncached = true; + return ret; } - -struct nvkm_oclass -gk20a_bar_oclass = { - .handle = NV_SUBDEV(BAR, 0xea), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_bar_ctor, - .dtor = gf100_bar_dtor, - .init = gf100_bar_init, - .fini = _nvkm_bar_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c index 8548adb91..370dcd8ff 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c @@ -21,251 +21,196 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "nv50.h" -#include #include #include #include #include -struct nv50_bar_priv { - struct nvkm_bar base; - spinlock_t lock; - struct nvkm_gpuobj *mem; - struct nvkm_gpuobj *pad; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *bar1_vm; - struct nvkm_gpuobj *bar1; - struct nvkm_vm *bar3_vm; - struct nvkm_gpuobj *bar3; -}; - -static int -nv50_bar_kmap(struct nvkm_bar *bar, struct nvkm_mem *mem, u32 flags, - struct nvkm_vma *vma) -{ - struct nv50_bar_priv *priv = (void *)bar; - int ret; - - ret = nvkm_vm_get(priv->bar3_vm, mem->size << 12, 12, flags, vma); - if (ret) - return ret; - - nvkm_vm_map(vma, mem); - return 0; -} - -static int -nv50_bar_umap(struct nvkm_bar *bar, struct nvkm_mem *mem, u32 flags, - struct nvkm_vma *vma) +struct nvkm_vm * +nv50_bar_kmap(struct nvkm_bar *base) { - struct nv50_bar_priv *priv = (void *)bar; - int ret; - - ret = nvkm_vm_get(priv->bar1_vm, mem->size << 12, 12, flags, vma); - if (ret) - return ret; - - nvkm_vm_map(vma, mem); - return 0; + return nv50_bar(base)->bar3_vm; } -static void -nv50_bar_unmap(struct nvkm_bar *bar, struct nvkm_vma *vma) +int +nv50_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) { - nvkm_vm_unmap(vma); - nvkm_vm_put(vma); + struct nv50_bar *bar = nv50_bar(base); + return nvkm_vm_get(bar->bar1_vm, size, type, NV_MEM_ACCESS_RW, vma); } static void -nv50_bar_flush(struct nvkm_bar *bar) -{ - struct nv50_bar_priv *priv = (void *)bar; - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - nv_wr32(priv, 0x00330c, 0x00000001); - if (!nv_wait(priv, 0x00330c, 0x00000002, 0x00000000)) - nv_warn(priv, "flush timeout\n"); - spin_unlock_irqrestore(&priv->lock, flags); -} - -void -g84_bar_flush(struct nvkm_bar *bar) +nv50_bar_flush(struct nvkm_bar *base) { - struct nv50_bar_priv *priv = (void *)bar; + struct nv50_bar *bar = nv50_bar(base); + struct nvkm_device *device = bar->base.subdev.device; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - nv_wr32(bar, 0x070000, 0x00000001); - if (!nv_wait(priv, 0x070000, 0x00000002, 0x00000000)) - nv_warn(priv, "flush timeout\n"); - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&bar->base.lock, flags); + nvkm_wr32(device, 0x00330c, 0x00000001); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x00330c) & 0x00000002)) + break; + ); + spin_unlock_irqrestore(&bar->base.lock, flags); } -static int -nv50_bar_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv50_bar_oneinit(struct nvkm_bar *base) { - struct nvkm_device *device = nv_device(parent); - struct nvkm_object *heap; + struct nv50_bar *bar = nv50_bar(base); + struct nvkm_device *device = bar->base.subdev.device; + static struct lock_class_key bar1_lock; + static struct lock_class_key bar3_lock; struct nvkm_vm *vm; - struct nv50_bar_priv *priv; u64 start, limit; int ret; - ret = nvkm_bar_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); + ret = nvkm_gpuobj_new(device, 0x20000, 0, false, NULL, &bar->mem); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x20000, 0, - NVOBJ_FLAG_HEAP, &priv->mem); - heap = nv_object(priv->mem); + ret = nvkm_gpuobj_new(device, bar->pgd_addr, 0, false, bar->mem, + &bar->pad); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), heap, - (device->chipset == 0x50) ? 0x1400 : 0x0200, - 0, 0, &priv->pad); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), heap, 0x4000, 0, 0, &priv->pgd); + ret = nvkm_gpuobj_new(device, 0x4000, 0, false, bar->mem, &bar->pgd); if (ret) return ret; /* BAR3 */ start = 0x0100000000ULL; - limit = start + nv_device_resource_len(device, 3); + limit = start + device->func->resource_size(device, 3); - ret = nvkm_vm_new(device, start, limit, start, &vm); + ret = nvkm_vm_new(device, start, limit, start, &bar3_lock, &vm); if (ret) return ret; - atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); + atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); - ret = nvkm_gpuobj_new(nv_object(priv), heap, - ((limit-- - start) >> 12) * 8, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &vm->pgt[0].obj[0]); - vm->pgt[0].refcount[0] = 1; + ret = nvkm_vm_boot(vm, limit-- - start); if (ret) return ret; - ret = nvkm_vm_ref(vm, &priv->bar3_vm, priv->pgd); + ret = nvkm_vm_ref(vm, &bar->bar3_vm, bar->pgd); nvkm_vm_ref(NULL, &vm, NULL); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), heap, 24, 16, 0, &priv->bar3); + ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar3); if (ret) return ret; - nv_wo32(priv->bar3, 0x00, 0x7fc00000); - nv_wo32(priv->bar3, 0x04, lower_32_bits(limit)); - nv_wo32(priv->bar3, 0x08, lower_32_bits(start)); - nv_wo32(priv->bar3, 0x0c, upper_32_bits(limit) << 24 | - upper_32_bits(start)); - nv_wo32(priv->bar3, 0x10, 0x00000000); - nv_wo32(priv->bar3, 0x14, 0x00000000); + nvkm_kmap(bar->bar3); + nvkm_wo32(bar->bar3, 0x00, 0x7fc00000); + nvkm_wo32(bar->bar3, 0x04, lower_32_bits(limit)); + nvkm_wo32(bar->bar3, 0x08, lower_32_bits(start)); + nvkm_wo32(bar->bar3, 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nvkm_wo32(bar->bar3, 0x10, 0x00000000); + nvkm_wo32(bar->bar3, 0x14, 0x00000000); + nvkm_done(bar->bar3); /* BAR1 */ start = 0x0000000000ULL; - limit = start + nv_device_resource_len(device, 1); + limit = start + device->func->resource_size(device, 1); - ret = nvkm_vm_new(device, start, limit--, start, &vm); + ret = nvkm_vm_new(device, start, limit--, start, &bar1_lock, &vm); if (ret) return ret; - atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); + atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); - ret = nvkm_vm_ref(vm, &priv->bar1_vm, priv->pgd); + ret = nvkm_vm_ref(vm, &bar->bar1_vm, bar->pgd); nvkm_vm_ref(NULL, &vm, NULL); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), heap, 24, 16, 0, &priv->bar1); + ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar1); if (ret) return ret; - nv_wo32(priv->bar1, 0x00, 0x7fc00000); - nv_wo32(priv->bar1, 0x04, lower_32_bits(limit)); - nv_wo32(priv->bar1, 0x08, lower_32_bits(start)); - nv_wo32(priv->bar1, 0x0c, upper_32_bits(limit) << 24 | - upper_32_bits(start)); - nv_wo32(priv->bar1, 0x10, 0x00000000); - nv_wo32(priv->bar1, 0x14, 0x00000000); - - priv->base.alloc = nvkm_bar_alloc; - priv->base.kmap = nv50_bar_kmap; - priv->base.umap = nv50_bar_umap; - priv->base.unmap = nv50_bar_unmap; - if (device->chipset == 0x50) - priv->base.flush = nv50_bar_flush; - else - priv->base.flush = g84_bar_flush; - spin_lock_init(&priv->lock); + nvkm_kmap(bar->bar1); + nvkm_wo32(bar->bar1, 0x00, 0x7fc00000); + nvkm_wo32(bar->bar1, 0x04, lower_32_bits(limit)); + nvkm_wo32(bar->bar1, 0x08, lower_32_bits(start)); + nvkm_wo32(bar->bar1, 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nvkm_wo32(bar->bar1, 0x10, 0x00000000); + nvkm_wo32(bar->bar1, 0x14, 0x00000000); + nvkm_done(bar->bar1); return 0; } -static void -nv50_bar_dtor(struct nvkm_object *object) +int +nv50_bar_init(struct nvkm_bar *base) { - struct nv50_bar_priv *priv = (void *)object; - nvkm_gpuobj_ref(NULL, &priv->bar1); - nvkm_vm_ref(NULL, &priv->bar1_vm, priv->pgd); - nvkm_gpuobj_ref(NULL, &priv->bar3); - if (priv->bar3_vm) { - nvkm_gpuobj_ref(NULL, &priv->bar3_vm->pgt[0].obj[0]); - nvkm_vm_ref(NULL, &priv->bar3_vm, priv->pgd); - } - nvkm_gpuobj_ref(NULL, &priv->pgd); - nvkm_gpuobj_ref(NULL, &priv->pad); - nvkm_gpuobj_ref(NULL, &priv->mem); - nvkm_bar_destroy(&priv->base); -} - -static int -nv50_bar_init(struct nvkm_object *object) -{ - struct nv50_bar_priv *priv = (void *)object; - int ret, i; - - ret = nvkm_bar_init(&priv->base); - if (ret) - return ret; - - nv_mask(priv, 0x000200, 0x00000100, 0x00000000); - nv_mask(priv, 0x000200, 0x00000100, 0x00000100); - nv_wr32(priv, 0x100c80, 0x00060001); - if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000)) { - nv_error(priv, "vm flush timeout\n"); + struct nv50_bar *bar = nv50_bar(base); + struct nvkm_device *device = bar->base.subdev.device; + int i; + + nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); + nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); + nvkm_wr32(device, 0x100c80, 0x00060001); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) + break; + ) < 0) return -EBUSY; - } - nv_wr32(priv, 0x001704, 0x00000000 | priv->mem->addr >> 12); - nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12); - nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4); - nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4); + nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12); + nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12); + nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4); + nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar3->node->offset >> 4); for (i = 0; i < 8; i++) - nv_wr32(priv, 0x001900 + (i * 4), 0x00000000); + nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000); return 0; } -static int -nv50_bar_fini(struct nvkm_object *object, bool suspend) +void * +nv50_bar_dtor(struct nvkm_bar *base) { - struct nv50_bar_priv *priv = (void *)object; - return nvkm_bar_fini(&priv->base, suspend); + struct nv50_bar *bar = nv50_bar(base); + nvkm_gpuobj_del(&bar->bar1); + nvkm_vm_ref(NULL, &bar->bar1_vm, bar->pgd); + nvkm_gpuobj_del(&bar->bar3); + if (bar->bar3_vm) { + nvkm_memory_del(&bar->bar3_vm->pgt[0].mem[0]); + nvkm_vm_ref(NULL, &bar->bar3_vm, bar->pgd); + } + nvkm_gpuobj_del(&bar->pgd); + nvkm_gpuobj_del(&bar->pad); + nvkm_gpuobj_del(&bar->mem); + return bar; } -struct nvkm_oclass -nv50_bar_oclass = { - .handle = NV_SUBDEV(BAR, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_bar_ctor, - .dtor = nv50_bar_dtor, - .init = nv50_bar_init, - .fini = nv50_bar_fini, - }, +int +nv50_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device, + int index, u32 pgd_addr, struct nvkm_bar **pbar) +{ + struct nv50_bar *bar; + if (!(bar = kzalloc(sizeof(*bar), GFP_KERNEL))) + return -ENOMEM; + nvkm_bar_ctor(func, device, index, &bar->base); + bar->pgd_addr = pgd_addr; + *pbar = &bar->base; + return 0; +} + +static const struct nvkm_bar_func +nv50_bar_func = { + .dtor = nv50_bar_dtor, + .oneinit = nv50_bar_oneinit, + .init = nv50_bar_init, + .kmap = nv50_bar_kmap, + .umap = nv50_bar_umap, + .flush = nv50_bar_flush, }; + +int +nv50_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) +{ + return nv50_bar_new_(&nv50_bar_func, device, index, 0x1400, pbar); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h new file mode 100644 index 000000000..1eb764f22 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h @@ -0,0 +1,26 @@ +#ifndef __NV50_BAR_H__ +#define __NV50_BAR_H__ +#define nv50_bar(p) container_of((p), struct nv50_bar, base) +#include "priv.h" + +struct nv50_bar { + struct nvkm_bar base; + u32 pgd_addr; + struct nvkm_gpuobj *mem; + struct nvkm_gpuobj *pad; + struct nvkm_gpuobj *pgd; + struct nvkm_vm *bar1_vm; + struct nvkm_gpuobj *bar1; + struct nvkm_vm *bar3_vm; + struct nvkm_gpuobj *bar3; +}; + +int nv50_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, + int, u32 pgd_addr, struct nvkm_bar **); +void *nv50_bar_dtor(struct nvkm_bar *); +int nv50_bar_oneinit(struct nvkm_bar *); +int nv50_bar_init(struct nvkm_bar *); +struct nvkm_vm *nv50_bar_kmap(struct nvkm_bar *); +int nv50_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); +void nv50_bar_unmap(struct nvkm_bar *, struct nvkm_vma *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h index aa85f61b4..d834ef20d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h @@ -1,30 +1,19 @@ #ifndef __NVKM_BAR_PRIV_H__ #define __NVKM_BAR_PRIV_H__ +#define nvkm_bar(p) container_of((p), struct nvkm_bar, subdev) #include -#define nvkm_bar_create(p,e,o,d) \ - nvkm_bar_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_bar_init(p) \ - nvkm_subdev_init(&(p)->base) -#define nvkm_bar_fini(p,s) \ - nvkm_subdev_fini(&(p)->base, (s)) +void nvkm_bar_ctor(const struct nvkm_bar_func *, struct nvkm_device *, + int, struct nvkm_bar *); -int nvkm_bar_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void nvkm_bar_destroy(struct nvkm_bar *); - -void _nvkm_bar_dtor(struct nvkm_object *); -#define _nvkm_bar_init _nvkm_subdev_init -#define _nvkm_bar_fini _nvkm_subdev_fini - -int nvkm_bar_alloc(struct nvkm_bar *, struct nvkm_object *, - struct nvkm_mem *, struct nvkm_object **); +struct nvkm_bar_func { + void *(*dtor)(struct nvkm_bar *); + int (*oneinit)(struct nvkm_bar *); + int (*init)(struct nvkm_bar *); + struct nvkm_vm *(*kmap)(struct nvkm_bar *); + int (*umap)(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *); + void (*flush)(struct nvkm_bar *); +}; void g84_bar_flush(struct nvkm_bar *); - -int gf100_bar_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void gf100_bar_dtor(struct nvkm_object *); -int gf100_bar_init(struct nvkm_object *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0203.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0203.c index 08eb03fbc..43f0ba1fb 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0203.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0203.c @@ -33,14 +33,14 @@ nvbios_M0203Te(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'M', &bit_M)) { if (bit_M.version == 2 && bit_M.length > 0x04) - data = nv_ro16(bios, bit_M.offset + 0x03); + data = nvbios_rd16(bios, bit_M.offset + 0x03); if (data) { - *ver = nv_ro08(bios, data + 0x00); + *ver = nvbios_rd08(bios, data + 0x00); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, data + 0x01); - *len = nv_ro08(bios, data + 0x02); - *cnt = nv_ro08(bios, data + 0x03); + *hdr = nvbios_rd08(bios, data + 0x01); + *len = nvbios_rd08(bios, data + 0x02); + *cnt = nvbios_rd08(bios, data + 0x03); return data; default: break; @@ -59,8 +59,8 @@ nvbios_M0203Tp(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->type = nv_ro08(bios, data + 0x04); - info->pointer = nv_ro16(bios, data + 0x05); + info->type = nvbios_rd08(bios, data + 0x04); + info->pointer = nvbios_rd16(bios, data + 0x05); break; default: break; @@ -89,9 +89,9 @@ nvbios_M0203Ep(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->type = (nv_ro08(bios, data + 0x00) & 0x0f) >> 0; - info->strap = (nv_ro08(bios, data + 0x00) & 0xf0) >> 4; - info->group = (nv_ro08(bios, data + 0x01) & 0x0f) >> 0; + info->type = (nvbios_rd08(bios, data + 0x00) & 0x0f) >> 0; + info->strap = (nvbios_rd08(bios, data + 0x00) & 0xf0) >> 4; + info->group = (nvbios_rd08(bios, data + 0x01) & 0x0f) >> 0; return data; default: break; @@ -103,12 +103,13 @@ u32 nvbios_M0203Em(struct nvkm_bios *bios, u8 ramcfg, u8 *ver, u8 *hdr, struct nvbios_M0203E *info) { + struct nvkm_subdev *subdev = &bios->subdev; struct nvbios_M0203T M0203T; u8 cnt, len, idx = 0xff; u32 data; if (!nvbios_M0203Tp(bios, ver, hdr, &cnt, &len, &M0203T)) { - nv_warn(bios, "M0203T not found\n"); + nvkm_warn(subdev, "M0203T not found\n"); return 0x00000000; } @@ -119,7 +120,7 @@ nvbios_M0203Em(struct nvkm_bios *bios, u8 ramcfg, u8 *ver, u8 *hdr, continue; return data; default: - nv_warn(bios, "M0203T type %02x\n", M0203T.type); + nvkm_warn(subdev, "M0203T type %02x\n", M0203T.type); return 0x00000000; } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0205.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0205.c index e1a8ad5f3..293a6af1b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0205.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0205.c @@ -34,16 +34,16 @@ nvbios_M0205Te(struct nvkm_bios *bios, if (!bit_entry(bios, 'M', &bit_M)) { if (bit_M.version == 2 && bit_M.length > 0x08) - data = nv_ro32(bios, bit_M.offset + 0x05); + data = nvbios_rd32(bios, bit_M.offset + 0x05); if (data) { - *ver = nv_ro08(bios, data + 0x00); + *ver = nvbios_rd08(bios, data + 0x00); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, data + 0x01); - *len = nv_ro08(bios, data + 0x02); - *ssz = nv_ro08(bios, data + 0x03); - *snr = nv_ro08(bios, data + 0x04); - *cnt = nv_ro08(bios, data + 0x05); + *hdr = nvbios_rd08(bios, data + 0x01); + *len = nvbios_rd08(bios, data + 0x02); + *ssz = nvbios_rd08(bios, data + 0x03); + *snr = nvbios_rd08(bios, data + 0x04); + *cnt = nvbios_rd08(bios, data + 0x05); return data; default: break; @@ -63,7 +63,7 @@ nvbios_M0205Tp(struct nvkm_bios *bios, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->freq = nv_ro16(bios, data + 0x06); + info->freq = nvbios_rd16(bios, data + 0x06); break; default: break; @@ -96,7 +96,7 @@ nvbios_M0205Ep(struct nvkm_bios *bios, int idx, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->type = nv_ro08(bios, data + 0x00) & 0x0f; + info->type = nvbios_rd08(bios, data + 0x00) & 0x0f; return data; default: break; @@ -126,7 +126,7 @@ nvbios_M0205Sp(struct nvkm_bios *bios, int ent, int idx, u8 *ver, u8 *hdr, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->data = nv_ro08(bios, data + 0x00); + info->data = nvbios_rd08(bios, data + 0x00); return data; default: break; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0209.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0209.c index 3026920c3..95d49a526 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0209.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/M0209.c @@ -34,16 +34,16 @@ nvbios_M0209Te(struct nvkm_bios *bios, if (!bit_entry(bios, 'M', &bit_M)) { if (bit_M.version == 2 && bit_M.length > 0x0c) - data = nv_ro32(bios, bit_M.offset + 0x09); + data = nvbios_rd32(bios, bit_M.offset + 0x09); if (data) { - *ver = nv_ro08(bios, data + 0x00); + *ver = nvbios_rd08(bios, data + 0x00); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, data + 0x01); - *len = nv_ro08(bios, data + 0x02); - *ssz = nv_ro08(bios, data + 0x03); + *hdr = nvbios_rd08(bios, data + 0x01); + *len = nvbios_rd08(bios, data + 0x02); + *ssz = nvbios_rd08(bios, data + 0x03); *snr = 1; - *cnt = nv_ro08(bios, data + 0x04); + *cnt = nvbios_rd08(bios, data + 0x04); return data; default: break; @@ -78,12 +78,12 @@ nvbios_M0209Ep(struct nvkm_bios *bios, int idx, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->v00_40 = (nv_ro08(bios, data + 0x00) & 0x40) >> 6; - info->bits = nv_ro08(bios, data + 0x00) & 0x3f; - info->modulo = nv_ro08(bios, data + 0x01); - info->v02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6; - info->v02_07 = nv_ro08(bios, data + 0x02) & 0x07; - info->v03 = nv_ro08(bios, data + 0x03); + info->v00_40 = (nvbios_rd08(bios, data + 0x00) & 0x40) >> 6; + info->bits = nvbios_rd08(bios, data + 0x00) & 0x3f; + info->modulo = nvbios_rd08(bios, data + 0x01); + info->v02_40 = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6; + info->v02_07 = nvbios_rd08(bios, data + 0x02) & 0x07; + info->v03 = nvbios_rd08(bios, data + 0x03); return data; default: break; @@ -122,7 +122,7 @@ nvbios_M0209Sp(struct nvkm_bios *bios, int ent, int idx, u8 *ver, u8 *hdr, u32 mask = (1ULL << M0209E.bits) - 1; u16 off = bits / 8; u8 mod = bits % 8; - info->data[i] = nv_ro32(bios, data + off); + info->data[i] = nvbios_rd32(bios, data + off); info->data[i] = info->data[i] >> mod; info->data[i] = info->data[i] & mask; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/P0260.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/P0260.c index b72edcf84..3f7db3eb3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/P0260.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/P0260.c @@ -34,15 +34,15 @@ nvbios_P0260Te(struct nvkm_bios *bios, if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2 && bit_P.length > 0x63) - data = nv_ro32(bios, bit_P.offset + 0x60); + data = nvbios_rd32(bios, bit_P.offset + 0x60); if (data) { - *ver = nv_ro08(bios, data + 0); + *ver = nvbios_rd08(bios, data + 0); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, data + 1); - *cnt = nv_ro08(bios, data + 2); + *hdr = nvbios_rd08(bios, data + 1); + *cnt = nvbios_rd08(bios, data + 2); *len = 4; - *xnr = nv_ro08(bios, data + 3); + *xnr = nvbios_rd08(bios, data + 3); *xsz = 4; return data; default: @@ -72,7 +72,7 @@ nvbios_P0260Ep(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->data = nv_ro32(bios, data); + info->data = nvbios_rd32(bios, data); return data; default: break; @@ -98,7 +98,7 @@ nvbios_P0260Xp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x10: - info->data = nv_ro32(bios, data); + info->data = nvbios_rd32(bios, data); return data; default: break; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c index 8db204f92..79536897e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c @@ -52,6 +52,20 @@ nvbios_findstr(const u8 *data, int size, const char *str, int len) return 0; } +int +nvbios_memcmp(struct nvkm_bios *bios, u32 addr, const char *str, u32 len) +{ + unsigned char c1, c2; + + while (len--) { + c1 = nvbios_rd08(bios, addr++); + c2 = *(str++); + if (c1 != c2) + return c1 - c2; + } + return 0; +} + int nvbios_extend(struct nvkm_bios *bios, u32 length) { @@ -69,62 +83,29 @@ nvbios_extend(struct nvkm_bios *bios, u32 length) return 0; } -static u8 -nvkm_bios_rd08(struct nvkm_object *object, u64 addr) -{ - struct nvkm_bios *bios = (void *)object; - return bios->data[addr]; -} - -static u16 -nvkm_bios_rd16(struct nvkm_object *object, u64 addr) +static void * +nvkm_bios_dtor(struct nvkm_subdev *subdev) { - struct nvkm_bios *bios = (void *)object; - return get_unaligned_le16(&bios->data[addr]); -} - -static u32 -nvkm_bios_rd32(struct nvkm_object *object, u64 addr) -{ - struct nvkm_bios *bios = (void *)object; - return get_unaligned_le32(&bios->data[addr]); -} - -static void -nvkm_bios_wr08(struct nvkm_object *object, u64 addr, u8 data) -{ - struct nvkm_bios *bios = (void *)object; - bios->data[addr] = data; -} - -static void -nvkm_bios_wr16(struct nvkm_object *object, u64 addr, u16 data) -{ - struct nvkm_bios *bios = (void *)object; - put_unaligned_le16(data, &bios->data[addr]); + struct nvkm_bios *bios = nvkm_bios(subdev); + kfree(bios->data); + return bios; } -static void -nvkm_bios_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nvkm_bios *bios = (void *)object; - put_unaligned_le32(data, &bios->data[addr]); -} +static const struct nvkm_subdev_func +nvkm_bios = { + .dtor = nvkm_bios_dtor, +}; -static int -nvkm_bios_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nvkm_bios_new(struct nvkm_device *device, int index, struct nvkm_bios **pbios) { struct nvkm_bios *bios; struct bit_entry bit_i; int ret; - ret = nvkm_subdev_create(parent, engine, oclass, 0, - "VBIOS", "bios", &bios); - *pobject = nv_object(bios); - if (ret) - return ret; + if (!(bios = *pbios = kzalloc(sizeof(*bios), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_bios, device, index, 0, &bios->subdev); ret = nvbios_shadow(bios); if (ret) @@ -134,73 +115,33 @@ nvkm_bios_ctor(struct nvkm_object *parent, struct nvkm_object *engine, bios->bmp_offset = nvbios_findstr(bios->data, bios->size, "\xff\x7f""NV\0", 5); if (bios->bmp_offset) { - nv_info(bios, "BMP version %x.%x\n", - bmp_version(bios) >> 8, - bmp_version(bios) & 0xff); + nvkm_debug(&bios->subdev, "BMP version %x.%x\n", + bmp_version(bios) >> 8, + bmp_version(bios) & 0xff); } bios->bit_offset = nvbios_findstr(bios->data, bios->size, "\xff\xb8""BIT", 5); if (bios->bit_offset) - nv_info(bios, "BIT signature found\n"); + nvkm_debug(&bios->subdev, "BIT signature found\n"); /* determine the vbios version number */ if (!bit_entry(bios, 'i', &bit_i) && bit_i.length >= 4) { - bios->version.major = nv_ro08(bios, bit_i.offset + 3); - bios->version.chip = nv_ro08(bios, bit_i.offset + 2); - bios->version.minor = nv_ro08(bios, bit_i.offset + 1); - bios->version.micro = nv_ro08(bios, bit_i.offset + 0); - bios->version.patch = nv_ro08(bios, bit_i.offset + 4); + bios->version.major = nvbios_rd08(bios, bit_i.offset + 3); + bios->version.chip = nvbios_rd08(bios, bit_i.offset + 2); + bios->version.minor = nvbios_rd08(bios, bit_i.offset + 1); + bios->version.micro = nvbios_rd08(bios, bit_i.offset + 0); + bios->version.patch = nvbios_rd08(bios, bit_i.offset + 4); } else if (bmp_version(bios)) { - bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); - bios->version.chip = nv_ro08(bios, bios->bmp_offset + 12); - bios->version.minor = nv_ro08(bios, bios->bmp_offset + 11); - bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); + bios->version.major = nvbios_rd08(bios, bios->bmp_offset + 13); + bios->version.chip = nvbios_rd08(bios, bios->bmp_offset + 12); + bios->version.minor = nvbios_rd08(bios, bios->bmp_offset + 11); + bios->version.micro = nvbios_rd08(bios, bios->bmp_offset + 10); } - nv_info(bios, "version %02x.%02x.%02x.%02x.%02x\n", - bios->version.major, bios->version.chip, - bios->version.minor, bios->version.micro, bios->version.patch); - + nvkm_info(&bios->subdev, "version %02x.%02x.%02x.%02x.%02x\n", + bios->version.major, bios->version.chip, + bios->version.minor, bios->version.micro, bios->version.patch); return 0; } - -static void -nvkm_bios_dtor(struct nvkm_object *object) -{ - struct nvkm_bios *bios = (void *)object; - kfree(bios->data); - nvkm_subdev_destroy(&bios->base); -} - -static int -nvkm_bios_init(struct nvkm_object *object) -{ - struct nvkm_bios *bios = (void *)object; - return nvkm_subdev_init(&bios->base); -} - -static int -nvkm_bios_fini(struct nvkm_object *object, bool suspend) -{ - struct nvkm_bios *bios = (void *)object; - return nvkm_subdev_fini(&bios->base, suspend); -} - -struct nvkm_oclass -nvkm_bios_oclass = { - .handle = NV_SUBDEV(VBIOS, 0x00), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nvkm_bios_ctor, - .dtor = nvkm_bios_dtor, - .init = nvkm_bios_init, - .fini = nvkm_bios_fini, - .rd08 = nvkm_bios_rd08, - .rd16 = nvkm_bios_rd16, - .rd32 = nvkm_bios_rd32, - .wr08 = nvkm_bios_wr08, - .wr16 = nvkm_bios_wr16, - .wr32 = nvkm_bios_wr32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/bit.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/bit.c index eab540496..070ff33f8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/bit.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/bit.c @@ -28,18 +28,18 @@ int bit_entry(struct nvkm_bios *bios, u8 id, struct bit_entry *bit) { if (likely(bios->bit_offset)) { - u8 entries = nv_ro08(bios, bios->bit_offset + 10); + u8 entries = nvbios_rd08(bios, bios->bit_offset + 10); u32 entry = bios->bit_offset + 12; while (entries--) { - if (nv_ro08(bios, entry + 0) == id) { - bit->id = nv_ro08(bios, entry + 0); - bit->version = nv_ro08(bios, entry + 1); - bit->length = nv_ro16(bios, entry + 2); - bit->offset = nv_ro16(bios, entry + 4); + if (nvbios_rd08(bios, entry + 0) == id) { + bit->id = nvbios_rd08(bios, entry + 0); + bit->version = nvbios_rd08(bios, entry + 1); + bit->length = nvbios_rd16(bios, entry + 2); + bit->offset = nvbios_rd16(bios, entry + 4); return 0; } - entry += nv_ro08(bios, bios->bit_offset + 9); + entry += nvbios_rd08(bios, bios->bit_offset + 9); } return -ENOENT; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c index 12e958533..3756ec91a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c @@ -34,17 +34,17 @@ nvbios_boostTe(struct nvkm_bios *bios, if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2) - boost = nv_ro16(bios, bit_P.offset + 0x30); + boost = nvbios_rd16(bios, bit_P.offset + 0x30); if (boost) { - *ver = nv_ro08(bios, boost + 0); + *ver = nvbios_rd08(bios, boost + 0); switch (*ver) { case 0x11: - *hdr = nv_ro08(bios, boost + 1); - *cnt = nv_ro08(bios, boost + 5); - *len = nv_ro08(bios, boost + 2); - *snr = nv_ro08(bios, boost + 4); - *ssz = nv_ro08(bios, boost + 3); + *hdr = nvbios_rd08(bios, boost + 1); + *cnt = nvbios_rd08(bios, boost + 5); + *len = nvbios_rd08(bios, boost + 2); + *snr = nvbios_rd08(bios, boost + 4); + *ssz = nvbios_rd08(bios, boost + 3); return boost; default: break; @@ -78,9 +78,9 @@ nvbios_boostEp(struct nvkm_bios *bios, int idx, u16 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len); memset(info, 0x00, sizeof(*info)); if (data) { - info->pstate = (nv_ro16(bios, data + 0x00) & 0x01e0) >> 5; - info->min = nv_ro16(bios, data + 0x02) * 1000; - info->max = nv_ro16(bios, data + 0x04) * 1000; + info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5; + info->min = nvbios_rd16(bios, data + 0x02) * 1000; + info->max = nvbios_rd16(bios, data + 0x04) * 1000; } return data; } @@ -117,10 +117,10 @@ nvbios_boostSp(struct nvkm_bios *bios, int idx, data = nvbios_boostSe(bios, idx, data, ver, hdr, cnt, len); memset(info, 0x00, sizeof(*info)); if (data) { - info->domain = nv_ro08(bios, data + 0x00); - info->percent = nv_ro08(bios, data + 0x01); - info->min = nv_ro16(bios, data + 0x02) * 1000; - info->max = nv_ro16(bios, data + 0x04) * 1000; + info->domain = nvbios_rd08(bios, data + 0x00); + info->percent = nvbios_rd08(bios, data + 0x01); + info->min = nvbios_rd16(bios, data + 0x02) * 1000; + info->max = nvbios_rd16(bios, data + 0x04) * 1000; } return data; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/conn.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/conn.c index 706a1650a..276823426 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/conn.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/conn.c @@ -30,12 +30,12 @@ nvbios_connTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { u32 dcb = dcb_table(bios, ver, hdr, cnt, len); if (dcb && *ver >= 0x30 && *hdr >= 0x16) { - u32 data = nv_ro16(bios, dcb + 0x14); + u32 data = nvbios_rd16(bios, dcb + 0x14); if (data) { - *ver = nv_ro08(bios, data + 0); - *hdr = nv_ro08(bios, data + 1); - *cnt = nv_ro08(bios, data + 2); - *len = nv_ro08(bios, data + 3); + *ver = nvbios_rd08(bios, data + 0); + *hdr = nvbios_rd08(bios, data + 1); + *cnt = nvbios_rd08(bios, data + 2); + *len = nvbios_rd08(bios, data + 3); return data; } } @@ -77,18 +77,18 @@ nvbios_connEp(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, switch (!!data * *ver) { case 0x30: case 0x40: - info->type = nv_ro08(bios, data + 0x00); - info->location = nv_ro08(bios, data + 0x01) & 0x0f; - info->hpd = (nv_ro08(bios, data + 0x01) & 0x30) >> 4; - info->dp = (nv_ro08(bios, data + 0x01) & 0xc0) >> 6; + info->type = nvbios_rd08(bios, data + 0x00); + info->location = nvbios_rd08(bios, data + 0x01) & 0x0f; + info->hpd = (nvbios_rd08(bios, data + 0x01) & 0x30) >> 4; + info->dp = (nvbios_rd08(bios, data + 0x01) & 0xc0) >> 6; if (*len < 4) return data; - info->hpd |= (nv_ro08(bios, data + 0x02) & 0x03) << 2; - info->dp |= nv_ro08(bios, data + 0x02) & 0x0c; - info->di = (nv_ro08(bios, data + 0x02) & 0xf0) >> 4; - info->hpd |= (nv_ro08(bios, data + 0x03) & 0x07) << 4; - info->sr = (nv_ro08(bios, data + 0x03) & 0x08) >> 3; - info->lcdid = (nv_ro08(bios, data + 0x03) & 0x70) >> 4; + info->hpd |= (nvbios_rd08(bios, data + 0x02) & 0x03) << 2; + info->dp |= nvbios_rd08(bios, data + 0x02) & 0x0c; + info->di = (nvbios_rd08(bios, data + 0x02) & 0xf0) >> 4; + info->hpd |= (nvbios_rd08(bios, data + 0x03) & 0x07) << 4; + info->sr = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3; + info->lcdid = (nvbios_rd08(bios, data + 0x03) & 0x70) >> 4; return data; default: break; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c index 16f7ad8a4..32e01624a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c @@ -34,17 +34,17 @@ nvbios_cstepTe(struct nvkm_bios *bios, if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2) - cstep = nv_ro16(bios, bit_P.offset + 0x34); + cstep = nvbios_rd16(bios, bit_P.offset + 0x34); if (cstep) { - *ver = nv_ro08(bios, cstep + 0); + *ver = nvbios_rd08(bios, cstep + 0); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, cstep + 1); - *cnt = nv_ro08(bios, cstep + 3); - *len = nv_ro08(bios, cstep + 2); - *xnr = nv_ro08(bios, cstep + 5); - *xsz = nv_ro08(bios, cstep + 4); + *hdr = nvbios_rd08(bios, cstep + 1); + *cnt = nvbios_rd08(bios, cstep + 3); + *len = nvbios_rd08(bios, cstep + 2); + *xnr = nvbios_rd08(bios, cstep + 5); + *xsz = nvbios_rd08(bios, cstep + 4); return cstep; default: break; @@ -75,8 +75,8 @@ nvbios_cstepEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, u16 data = nvbios_cstepEe(bios, idx, ver, hdr); memset(info, 0x00, sizeof(*info)); if (data) { - info->pstate = (nv_ro16(bios, data + 0x00) & 0x01e0) >> 5; - info->index = nv_ro08(bios, data + 0x03); + info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5; + info->index = nvbios_rd08(bios, data + 0x03); } return data; } @@ -113,10 +113,10 @@ nvbios_cstepXp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, u16 data = nvbios_cstepXe(bios, idx, ver, hdr); memset(info, 0x00, sizeof(*info)); if (data) { - info->freq = nv_ro16(bios, data + 0x00) * 1000; - info->unkn[0] = nv_ro08(bios, data + 0x02); - info->unkn[1] = nv_ro08(bios, data + 0x03); - info->voltage = nv_ro08(bios, data + 0x04); + info->freq = nvbios_rd16(bios, data + 0x00) * 1000; + info->unkn[0] = nvbios_rd08(bios, data + 0x02); + info->unkn[1] = nvbios_rd08(bios, data + 0x03); + info->voltage = nvbios_rd08(bios, data + 0x04); } return data; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c index 8d78140f9..8304b806f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c @@ -24,38 +24,37 @@ #include #include -#include - u16 dcb_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { - struct nvkm_device *device = nv_device(bios); + struct nvkm_subdev *subdev = &bios->subdev; + struct nvkm_device *device = subdev->device; u16 dcb = 0x0000; if (device->card_type > NV_04) - dcb = nv_ro16(bios, 0x36); + dcb = nvbios_rd16(bios, 0x36); if (!dcb) { - nv_warn(bios, "DCB table not found\n"); + nvkm_warn(subdev, "DCB table not found\n"); return dcb; } - *ver = nv_ro08(bios, dcb); + *ver = nvbios_rd08(bios, dcb); if (*ver >= 0x42) { - nv_warn(bios, "DCB version 0x%02x unknown\n", *ver); + nvkm_warn(subdev, "DCB version 0x%02x unknown\n", *ver); return 0x0000; } else if (*ver >= 0x30) { - if (nv_ro32(bios, dcb + 6) == 0x4edcbdcb) { - *hdr = nv_ro08(bios, dcb + 1); - *cnt = nv_ro08(bios, dcb + 2); - *len = nv_ro08(bios, dcb + 3); + if (nvbios_rd32(bios, dcb + 6) == 0x4edcbdcb) { + *hdr = nvbios_rd08(bios, dcb + 1); + *cnt = nvbios_rd08(bios, dcb + 2); + *len = nvbios_rd08(bios, dcb + 3); return dcb; } } else if (*ver >= 0x20) { - if (nv_ro32(bios, dcb + 4) == 0x4edcbdcb) { - u16 i2c = nv_ro16(bios, dcb + 2); + if (nvbios_rd32(bios, dcb + 4) == 0x4edcbdcb) { + u16 i2c = nvbios_rd16(bios, dcb + 2); *hdr = 8; *cnt = (i2c - dcb) / 8; *len = 8; @@ -63,8 +62,8 @@ dcb_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) } } else if (*ver >= 0x15) { - if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) { - u16 i2c = nv_ro16(bios, dcb + 2); + if (!nvbios_memcmp(bios, dcb - 7, "DEV_REC", 7)) { + u16 i2c = nvbios_rd16(bios, dcb + 2); *hdr = 4; *cnt = (i2c - dcb) / 10; *len = 10; @@ -88,11 +87,11 @@ dcb_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) * * v1.1 (NV5+, maybe some NV4) is entirely unhelpful */ - nv_warn(bios, "DCB contains no useful data\n"); + nvkm_debug(subdev, "DCB contains no useful data\n"); return 0x0000; } - nv_warn(bios, "DCB header validation failed\n"); + nvkm_warn(subdev, "DCB header validation failed\n"); return 0x0000; } @@ -126,7 +125,7 @@ dcb_outp_parse(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, memset(outp, 0x00, sizeof(*outp)); if (dcb) { if (*ver >= 0x20) { - u32 conn = nv_ro32(bios, dcb + 0x00); + u32 conn = nvbios_rd32(bios, dcb + 0x00); outp->or = (conn & 0x0f000000) >> 24; outp->location = (conn & 0x00300000) >> 20; outp->bus = (conn & 0x000f0000) >> 16; @@ -140,7 +139,7 @@ dcb_outp_parse(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, } if (*ver >= 0x40) { - u32 conf = nv_ro32(bios, dcb + 0x04); + u32 conf = nvbios_rd32(bios, dcb + 0x04); switch (outp->type) { case DCB_OUTPUT_DP: switch (conf & 0x00e00000) { @@ -156,20 +155,19 @@ dcb_outp_parse(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, break; } - outp->dpconf.link_nr = (conf & 0x0f000000) >> 24; - if (*ver < 0x41) { - switch (outp->dpconf.link_nr) { - case 0x0f: - outp->dpconf.link_nr = 4; - break; - case 0x03: - outp->dpconf.link_nr = 2; - break; - case 0x01: - default: - outp->dpconf.link_nr = 1; - break; - } + switch ((conf & 0x0f000000) >> 24) { + case 0xf: + case 0x4: + outp->dpconf.link_nr = 4; + break; + case 0x3: + case 0x2: + outp->dpconf.link_nr = 2; + break; + case 0x1: + default: + outp->dpconf.link_nr = 1; + break; } /* fall-through... */ @@ -215,14 +213,14 @@ dcb_outp_foreach(struct nvkm_bios *bios, void *data, u16 outp; while ((outp = dcb_outp(bios, ++idx, &ver, &len))) { - if (nv_ro32(bios, outp) == 0x00000000) + if (nvbios_rd32(bios, outp) == 0x00000000) break; /* seen on an NV11 with DCB v1.5 */ - if (nv_ro32(bios, outp) == 0xffffffff) + if (nvbios_rd32(bios, outp) == 0xffffffff) break; /* seen on an NV17 with DCB v2.0 */ - if (nv_ro08(bios, outp) == DCB_OUTPUT_UNUSED) + if (nvbios_rd08(bios, outp) == DCB_OUTPUT_UNUSED) continue; - if (nv_ro08(bios, outp) == DCB_OUTPUT_EOL) + if (nvbios_rd08(bios, outp) == DCB_OUTPUT_EOL) break; ret = exec(bios, data, idx, outp); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c index 262c410b7..a5e92135c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c @@ -33,17 +33,17 @@ nvbios_disp_table(struct nvkm_bios *bios, if (!bit_entry(bios, 'U', &U)) { if (U.version == 1) { - u16 data = nv_ro16(bios, U.offset); + u16 data = nvbios_rd16(bios, U.offset); if (data) { - *ver = nv_ro08(bios, data + 0x00); + *ver = nvbios_rd08(bios, data + 0x00); switch (*ver) { case 0x20: case 0x21: case 0x22: - *hdr = nv_ro08(bios, data + 0x01); - *len = nv_ro08(bios, data + 0x02); - *cnt = nv_ro08(bios, data + 0x03); - *sub = nv_ro08(bios, data + 0x04); + *hdr = nvbios_rd08(bios, data + 0x01); + *len = nvbios_rd08(bios, data + 0x02); + *cnt = nvbios_rd08(bios, data + 0x03); + *sub = nvbios_rd08(bios, data + 0x04); return data; default: break; @@ -72,7 +72,7 @@ nvbios_disp_parse(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, u8 *sub, { u16 data = nvbios_disp_entry(bios, idx, ver, len, sub); if (data && *len >= 2) { - info->data = nv_ro16(bios, data + 0); + info->data = nvbios_rd16(bios, data + 0); return data; } return 0x0000; @@ -85,7 +85,7 @@ nvbios_outp_entry(struct nvkm_bios *bios, u8 idx, struct nvbios_disp info; u16 data = nvbios_disp_parse(bios, idx, ver, len, hdr, &info); if (data) { - *cnt = nv_ro08(bios, info.data + 0x05); + *cnt = nvbios_rd08(bios, info.data + 0x05); *len = 0x06; data = info.data; } @@ -98,15 +98,15 @@ nvbios_outp_parse(struct nvkm_bios *bios, u8 idx, { u16 data = nvbios_outp_entry(bios, idx, ver, hdr, cnt, len); if (data && *hdr >= 0x0a) { - info->type = nv_ro16(bios, data + 0x00); - info->mask = nv_ro32(bios, data + 0x02); + info->type = nvbios_rd16(bios, data + 0x00); + info->mask = nvbios_rd32(bios, data + 0x02); if (*ver <= 0x20) /* match any link */ info->mask |= 0x00c0; - info->script[0] = nv_ro16(bios, data + 0x06); - info->script[1] = nv_ro16(bios, data + 0x08); + info->script[0] = nvbios_rd16(bios, data + 0x06); + info->script[1] = nvbios_rd16(bios, data + 0x08); info->script[2] = 0x0000; if (*hdr >= 0x0c) - info->script[2] = nv_ro16(bios, data + 0x0a); + info->script[2] = nvbios_rd16(bios, data + 0x0a); return data; } return 0x0000; @@ -141,9 +141,9 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx, { u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len); if (data) { - info->match = nv_ro16(bios, data + 0x00); - info->clkcmp[0] = nv_ro16(bios, data + 0x02); - info->clkcmp[1] = nv_ro16(bios, data + 0x04); + info->match = nvbios_rd16(bios, data + 0x00); + info->clkcmp[0] = nvbios_rd16(bios, data + 0x02); + info->clkcmp[1] = nvbios_rd16(bios, data + 0x04); } return data; } @@ -164,8 +164,8 @@ u16 nvbios_oclk_match(struct nvkm_bios *bios, u16 cmp, u32 khz) { while (cmp) { - if (khz / 10 >= nv_ro16(bios, cmp + 0x00)) - return nv_ro16(bios, cmp + 0x02); + if (khz / 10 >= nvbios_rd16(bios, cmp + 0x00)) + return nvbios_rd16(bios, cmp + 0x02); cmp += 0x04; } return 0x0000; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c index 95970faae..053324763 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c @@ -32,17 +32,17 @@ nvbios_dp_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'd', &d)) { if (d.version == 1 && d.length >= 2) { - u16 data = nv_ro16(bios, d.offset); + u16 data = nvbios_rd16(bios, d.offset); if (data) { - *ver = nv_ro08(bios, data + 0x00); + *ver = nvbios_rd08(bios, data + 0x00); switch (*ver) { case 0x21: case 0x30: case 0x40: case 0x41: - *hdr = nv_ro08(bios, data + 0x01); - *len = nv_ro08(bios, data + 0x02); - *cnt = nv_ro08(bios, data + 0x03); + *hdr = nvbios_rd08(bios, data + 0x01); + *len = nvbios_rd08(bios, data + 0x02); + *cnt = nvbios_rd08(bios, data + 0x03); return data; default: break; @@ -60,17 +60,17 @@ nvbios_dpout_entry(struct nvkm_bios *bios, u8 idx, { u16 data = nvbios_dp_table(bios, ver, hdr, cnt, len); if (data && idx < *cnt) { - u16 outp = nv_ro16(bios, data + *hdr + idx * *len); + u16 outp = nvbios_rd16(bios, data + *hdr + idx * *len); switch (*ver * !!outp) { case 0x21: case 0x30: - *hdr = nv_ro08(bios, data + 0x04); - *len = nv_ro08(bios, data + 0x05); - *cnt = nv_ro08(bios, outp + 0x04); + *hdr = nvbios_rd08(bios, data + 0x04); + *len = nvbios_rd08(bios, data + 0x05); + *cnt = nvbios_rd08(bios, outp + 0x04); break; case 0x40: case 0x41: - *hdr = nv_ro08(bios, data + 0x04); + *hdr = nvbios_rd08(bios, data + 0x04); *cnt = 0; *len = 0; break; @@ -91,31 +91,31 @@ nvbios_dpout_parse(struct nvkm_bios *bios, u8 idx, u16 data = nvbios_dpout_entry(bios, idx, ver, hdr, cnt, len); memset(info, 0x00, sizeof(*info)); if (data && *ver) { - info->type = nv_ro16(bios, data + 0x00); - info->mask = nv_ro16(bios, data + 0x02); + info->type = nvbios_rd16(bios, data + 0x00); + info->mask = nvbios_rd16(bios, data + 0x02); switch (*ver) { case 0x21: case 0x30: - info->flags = nv_ro08(bios, data + 0x05); - info->script[0] = nv_ro16(bios, data + 0x06); - info->script[1] = nv_ro16(bios, data + 0x08); - info->lnkcmp = nv_ro16(bios, data + 0x0a); + info->flags = nvbios_rd08(bios, data + 0x05); + info->script[0] = nvbios_rd16(bios, data + 0x06); + info->script[1] = nvbios_rd16(bios, data + 0x08); + info->lnkcmp = nvbios_rd16(bios, data + 0x0a); if (*len >= 0x0f) { - info->script[2] = nv_ro16(bios, data + 0x0c); - info->script[3] = nv_ro16(bios, data + 0x0e); + info->script[2] = nvbios_rd16(bios, data + 0x0c); + info->script[3] = nvbios_rd16(bios, data + 0x0e); } if (*len >= 0x11) - info->script[4] = nv_ro16(bios, data + 0x10); + info->script[4] = nvbios_rd16(bios, data + 0x10); break; case 0x40: case 0x41: - info->flags = nv_ro08(bios, data + 0x04); - info->script[0] = nv_ro16(bios, data + 0x05); - info->script[1] = nv_ro16(bios, data + 0x07); - info->lnkcmp = nv_ro16(bios, data + 0x09); - info->script[2] = nv_ro16(bios, data + 0x0b); - info->script[3] = nv_ro16(bios, data + 0x0d); - info->script[4] = nv_ro16(bios, data + 0x0f); + info->flags = nvbios_rd08(bios, data + 0x04); + info->script[0] = nvbios_rd16(bios, data + 0x05); + info->script[1] = nvbios_rd16(bios, data + 0x07); + info->lnkcmp = nvbios_rd16(bios, data + 0x09); + info->script[2] = nvbios_rd16(bios, data + 0x0b); + info->script[3] = nvbios_rd16(bios, data + 0x0d); + info->script[4] = nvbios_rd16(bios, data + 0x0f); break; default: data = 0x0000; @@ -147,8 +147,9 @@ nvbios_dpcfg_entry(struct nvkm_bios *bios, u16 outp, u8 idx, if (*ver >= 0x40) { outp = nvbios_dp_table(bios, ver, hdr, cnt, len); *hdr = *hdr + (*len * * cnt); - *len = nv_ro08(bios, outp + 0x06); - *cnt = nv_ro08(bios, outp + 0x07); + *len = nvbios_rd08(bios, outp + 0x06); + *cnt = nvbios_rd08(bios, outp + 0x07) * + nvbios_rd08(bios, outp + 0x05); } if (idx < *cnt) @@ -167,17 +168,17 @@ nvbios_dpcfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx, if (data) { switch (*ver) { case 0x21: - info->dc = nv_ro08(bios, data + 0x02); - info->pe = nv_ro08(bios, data + 0x03); - info->tx_pu = nv_ro08(bios, data + 0x04); + info->dc = nvbios_rd08(bios, data + 0x02); + info->pe = nvbios_rd08(bios, data + 0x03); + info->tx_pu = nvbios_rd08(bios, data + 0x04); break; case 0x30: case 0x40: case 0x41: - info->pc = nv_ro08(bios, data + 0x00); - info->dc = nv_ro08(bios, data + 0x01); - info->pe = nv_ro08(bios, data + 0x02); - info->tx_pu = nv_ro08(bios, data + 0x03) & 0x0f; + info->pc = nvbios_rd08(bios, data + 0x00); + info->dc = nvbios_rd08(bios, data + 0x01); + info->pe = nvbios_rd08(bios, data + 0x02); + info->tx_pu = nvbios_rd08(bios, data + 0x03); break; default: data = 0x0000; @@ -196,17 +197,15 @@ nvbios_dpcfg_match(struct nvkm_bios *bios, u16 outp, u8 pc, u8 vs, u8 pe, u16 data; if (*ver >= 0x30) { - /*XXX: there's a second set of these on at least 4.1, that - * i've witnessed nvidia using instead of the first - * on gm204. figure out what/why - */ const u8 vsoff[] = { 0, 4, 7, 9 }; idx = (pc * 10) + vsoff[vs] + pe; + if (*ver >= 0x40 && *hdr >= 0x12) + idx += nvbios_rd08(bios, outp + 0x11) * 40; } else { while ((data = nvbios_dpcfg_entry(bios, outp, ++idx, ver, hdr, cnt, len))) { - if (nv_ro08(bios, data + 0x00) == vs && - nv_ro08(bios, data + 0x01) == pe) + if (nvbios_rd08(bios, data + 0x00) == vs && + nvbios_rd08(bios, data + 0x01) == pe) break; } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c index a8503a185..c9e6f6ff7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/extdev.c @@ -35,14 +35,14 @@ extdev_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) if (!dcb || (dcb_ver != 0x30 && dcb_ver != 0x40)) return 0x0000; - extdev = nv_ro16(bios, dcb + 18); + extdev = nvbios_rd16(bios, dcb + 18); if (!extdev) return 0x0000; - *ver = nv_ro08(bios, extdev + 0); - *hdr = nv_ro08(bios, extdev + 1); - *cnt = nv_ro08(bios, extdev + 2); - *len = nv_ro08(bios, extdev + 3); + *ver = nvbios_rd08(bios, extdev + 0); + *hdr = nvbios_rd08(bios, extdev + 1); + *cnt = nvbios_rd08(bios, extdev + 2); + *len = nvbios_rd08(bios, extdev + 3); return extdev + *hdr; } @@ -60,9 +60,9 @@ static void extdev_parse_entry(struct nvkm_bios *bios, u16 offset, struct nvbios_extdev_func *entry) { - entry->type = nv_ro08(bios, offset + 0); - entry->addr = nv_ro08(bios, offset + 1); - entry->bus = (nv_ro08(bios, offset + 2) >> 4) & 1; + entry->type = nvbios_rd08(bios, offset + 0); + entry->addr = nvbios_rd08(bios, offset + 1); + entry->bus = (nvbios_rd08(bios, offset + 2) >> 4) & 1; } int diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c index 8dba70d9d..80fed7e78 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c @@ -33,15 +33,15 @@ nvbios_fan_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2 && bit_P.length >= 0x5a) - fan = nv_ro16(bios, bit_P.offset + 0x58); + fan = nvbios_rd16(bios, bit_P.offset + 0x58); if (fan) { - *ver = nv_ro08(bios, fan + 0); + *ver = nvbios_rd08(bios, fan + 0); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, fan + 1); - *len = nv_ro08(bios, fan + 2); - *cnt = nv_ro08(bios, fan + 3); + *hdr = nvbios_rd08(bios, fan + 1); + *len = nvbios_rd08(bios, fan + 2); + *cnt = nvbios_rd08(bios, fan + 3); return fan; default: break; @@ -69,7 +69,7 @@ nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan) u16 data = nvbios_fan_entry(bios, 0, &ver, &hdr, &cnt, &len); if (data) { - u8 type = nv_ro08(bios, data + 0x00); + u8 type = nvbios_rd08(bios, data + 0x00); switch (type) { case 0: fan->type = NVBIOS_THERM_FAN_TOGGLE; @@ -83,10 +83,11 @@ nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan) fan->type = NVBIOS_THERM_FAN_UNK; } - fan->min_duty = nv_ro08(bios, data + 0x02); - fan->max_duty = nv_ro08(bios, data + 0x03); + fan->fan_mode = NVBIOS_THERM_FAN_LINEAR; + fan->min_duty = nvbios_rd08(bios, data + 0x02); + fan->max_duty = nvbios_rd08(bios, data + 0x03); - fan->pwm_freq = nv_ro32(bios, data + 0x0b) & 0xffffff; + fan->pwm_freq = nvbios_rd32(bios, data + 0x0b) & 0xffffff; } return data; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/gpio.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/gpio.c index 8ce154d88..2107b5584 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/gpio.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/gpio.c @@ -33,22 +33,22 @@ dcb_gpio_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) u16 dcb = dcb_table(bios, ver, hdr, cnt, len); if (dcb) { if (*ver >= 0x30 && *hdr >= 0x0c) - data = nv_ro16(bios, dcb + 0x0a); + data = nvbios_rd16(bios, dcb + 0x0a); else - if (*ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) - data = nv_ro16(bios, dcb - 0x0f); + if (*ver >= 0x22 && nvbios_rd08(bios, dcb - 1) >= 0x13) + data = nvbios_rd16(bios, dcb - 0x0f); if (data) { - *ver = nv_ro08(bios, data + 0x00); + *ver = nvbios_rd08(bios, data + 0x00); if (*ver < 0x30) { *hdr = 3; - *cnt = nv_ro08(bios, data + 0x02); - *len = nv_ro08(bios, data + 0x01); + *cnt = nvbios_rd08(bios, data + 0x02); + *len = nvbios_rd08(bios, data + 0x01); } else if (*ver <= 0x41) { - *hdr = nv_ro08(bios, data + 0x01); - *cnt = nv_ro08(bios, data + 0x02); - *len = nv_ro08(bios, data + 0x03); + *hdr = nvbios_rd08(bios, data + 0x01); + *cnt = nvbios_rd08(bios, data + 0x02); + *len = nvbios_rd08(bios, data + 0x03); } else { data = 0x0000; } @@ -81,7 +81,7 @@ dcb_gpio_parse(struct nvkm_bios *bios, int idx, int ent, u8 *ver, u8 *len, u16 data = dcb_gpio_entry(bios, idx, ent, ver, len); if (data) { if (*ver < 0x40) { - u16 info = nv_ro16(bios, data); + u16 info = nvbios_rd16(bios, data); *gpio = (struct dcb_gpio_func) { .line = (info & 0x001f) >> 0, .func = (info & 0x07e0) >> 5, @@ -91,7 +91,7 @@ dcb_gpio_parse(struct nvkm_bios *bios, int idx, int ent, u8 *ver, u8 *len, }; } else if (*ver < 0x41) { - u32 info = nv_ro32(bios, data); + u32 info = nvbios_rd32(bios, data); *gpio = (struct dcb_gpio_func) { .line = (info & 0x0000001f) >> 0, .func = (info & 0x0000ff00) >> 8, @@ -100,8 +100,8 @@ dcb_gpio_parse(struct nvkm_bios *bios, int idx, int ent, u8 *ver, u8 *len, .param = !!(info & 0x80000000), }; } else { - u32 info = nv_ro32(bios, data + 0); - u8 info1 = nv_ro32(bios, data + 4); + u32 info = nvbios_rd32(bios, data + 0); + u8 info1 = nvbios_rd32(bios, data + 4); *gpio = (struct dcb_gpio_func) { .line = (info & 0x0000003f) >> 0, .func = (info & 0x0000ff00) >> 8, @@ -131,8 +131,8 @@ dcb_gpio_match(struct nvkm_bios *bios, int idx, u8 func, u8 line, /* DCB 2.2, fixed TVDAC GPIO data */ if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) { if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) { - u8 conf = nv_ro08(bios, data - 5); - u8 addr = nv_ro08(bios, data - 4); + u8 conf = nvbios_rd08(bios, data - 5); + u8 addr = nvbios_rd08(bios, data - 4); if (conf & 0x01) { *gpio = (struct dcb_gpio_func) { .func = DCB_GPIO_TVDAC0, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c index c4e1f085e..0fc60be32 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/i2c.c @@ -32,21 +32,21 @@ dcb_i2c_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) u16 dcb = dcb_table(bios, ver, hdr, cnt, len); if (dcb) { if (*ver >= 0x15) - i2c = nv_ro16(bios, dcb + 2); + i2c = nvbios_rd16(bios, dcb + 2); if (*ver >= 0x30) - i2c = nv_ro16(bios, dcb + 4); + i2c = nvbios_rd16(bios, dcb + 4); } if (i2c && *ver >= 0x42) { - nv_warn(bios, "ccb %02x not supported\n", *ver); + nvkm_warn(&bios->subdev, "ccb %02x not supported\n", *ver); return 0x0000; } if (i2c && *ver >= 0x30) { - *ver = nv_ro08(bios, i2c + 0); - *hdr = nv_ro08(bios, i2c + 1); - *cnt = nv_ro08(bios, i2c + 2); - *len = nv_ro08(bios, i2c + 3); + *ver = nvbios_rd08(bios, i2c + 0); + *hdr = nvbios_rd08(bios, i2c + 1); + *cnt = nvbios_rd08(bios, i2c + 2); + *len = nvbios_rd08(bios, i2c + 3); } else { *ver = *ver; /* use DCB version */ *hdr = 0; @@ -70,13 +70,14 @@ dcb_i2c_entry(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len) int dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info) { + struct nvkm_subdev *subdev = &bios->subdev; u8 ver, len; u16 ent = dcb_i2c_entry(bios, idx, &ver, &len); if (ent) { if (ver >= 0x41) { - u32 ent_value = nv_ro32(bios, ent); - u8 i2c_port = (ent_value >> 27) & 0x1f; - u8 dpaux_port = (ent_value >> 22) & 0x1f; + u32 ent_value = nvbios_rd32(bios, ent); + u8 i2c_port = (ent_value >> 0) & 0x1f; + u8 dpaux_port = (ent_value >> 5) & 0x1f; /* value 0x1f means unused according to DCB 4.x spec */ if (i2c_port == 0x1f && dpaux_port == 0x1f) info->type = DCB_I2C_UNUSED; @@ -84,9 +85,9 @@ dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info) info->type = DCB_I2C_PMGR; } else if (ver >= 0x30) { - info->type = nv_ro08(bios, ent + 0x03); + info->type = nvbios_rd08(bios, ent + 0x03); } else { - info->type = nv_ro08(bios, ent + 0x03) & 0x07; + info->type = nvbios_rd08(bios, ent + 0x03) & 0x07; if (info->type == 0x07) info->type = DCB_I2C_UNUSED; } @@ -98,27 +99,27 @@ dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info) switch (info->type) { case DCB_I2C_NV04_BIT: - info->drive = nv_ro08(bios, ent + 0); - info->sense = nv_ro08(bios, ent + 1); + info->drive = nvbios_rd08(bios, ent + 0); + info->sense = nvbios_rd08(bios, ent + 1); return 0; case DCB_I2C_NV4E_BIT: - info->drive = nv_ro08(bios, ent + 1); + info->drive = nvbios_rd08(bios, ent + 1); return 0; case DCB_I2C_NVIO_BIT: - info->drive = nv_ro08(bios, ent + 0) & 0x0f; - if (nv_ro08(bios, ent + 1) & 0x01) - info->share = nv_ro08(bios, ent + 1) >> 1; + info->drive = nvbios_rd08(bios, ent + 0) & 0x0f; + if (nvbios_rd08(bios, ent + 1) & 0x01) + info->share = nvbios_rd08(bios, ent + 1) >> 1; return 0; case DCB_I2C_NVIO_AUX: - info->auxch = nv_ro08(bios, ent + 0) & 0x0f; - if (nv_ro08(bios, ent + 1) & 0x01) + info->auxch = nvbios_rd08(bios, ent + 0) & 0x0f; + if (nvbios_rd08(bios, ent + 1) & 0x01) info->share = info->auxch; return 0; case DCB_I2C_PMGR: - info->drive = (nv_ro16(bios, ent + 0) & 0x01f) >> 0; + info->drive = (nvbios_rd16(bios, ent + 0) & 0x01f) >> 0; if (info->drive == 0x1f) info->drive = DCB_I2C_UNUSED; - info->auxch = (nv_ro16(bios, ent + 0) & 0x3e0) >> 5; + info->auxch = (nvbios_rd16(bios, ent + 0) & 0x3e0) >> 5; if (info->auxch == 0x1f) info->auxch = DCB_I2C_UNUSED; info->share = info->auxch; @@ -126,7 +127,7 @@ dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info) case DCB_I2C_UNUSED: return 0; default: - nv_warn(bios, "unknown i2c type %d\n", info->type); + nvkm_warn(subdev, "unknown i2c type %d\n", info->type); info->type = DCB_I2C_UNUSED; return 0; } @@ -136,21 +137,21 @@ dcb_i2c_parse(struct nvkm_bios *bios, u8 idx, struct dcb_i2c_entry *info) /* BMP (from v4.0 has i2c info in the structure, it's in a * fixed location on earlier VBIOS */ - if (nv_ro08(bios, bios->bmp_offset + 5) < 4) + if (nvbios_rd08(bios, bios->bmp_offset + 5) < 4) ent = 0x0048; else ent = 0x0036 + bios->bmp_offset; if (idx == 0) { - info->drive = nv_ro08(bios, ent + 4); + info->drive = nvbios_rd08(bios, ent + 4); if (!info->drive) info->drive = 0x3f; - info->sense = nv_ro08(bios, ent + 5); + info->sense = nvbios_rd08(bios, ent + 5); if (!info->sense) info->sense = 0x3e; } else if (idx == 1) { - info->drive = nv_ro08(bios, ent + 6); + info->drive = nvbios_rd08(bios, ent + 6); if (!info->drive) info->drive = 0x37; - info->sense = nv_ro08(bios, ent + 7); + info->sense = nvbios_rd08(bios, ent + 7); if (!info->sense) info->sense = 0x36; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c index 1815540a0..74b14cf09 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/image.c @@ -29,20 +29,21 @@ static bool nvbios_imagen(struct nvkm_bios *bios, struct nvbios_image *image) { + struct nvkm_subdev *subdev = &bios->subdev; struct nvbios_pcirT pcir; struct nvbios_npdeT npde; u8 ver; u16 hdr; u32 data; - switch ((data = nv_ro16(bios, image->base + 0x00))) { + switch ((data = nvbios_rd16(bios, image->base + 0x00))) { case 0xaa55: case 0xbb77: case 0x4e56: /* NV */ break; default: - nv_debug(bios, "%08x: ROM signature (%04x) unknown\n", - image->base, data); + nvkm_debug(subdev, "%08x: ROM signature (%04x) unknown\n", + image->base, data); return false; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index f67cdae1e..a7d69ce7a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -31,18 +31,18 @@ #include #include -#include #include #include #include #include #define bioslog(lvl, fmt, args...) do { \ - nv_printk(init->bios, lvl, "0x%04x[%c]: "fmt, init->offset, \ - init_exec(init) ? '0' + (init->nested - 1) : ' ', ##args); \ + nvkm_printk(init->subdev, lvl, info, "0x%04x[%c]: "fmt, \ + init->offset, init_exec(init) ? \ + '0' + (init->nested - 1) : ' ', ##args); \ } while(0) #define cont(fmt, args...) do { \ - if (nv_subdev(init->bios)->debug >= NV_DBG_TRACE) \ + if (init->subdev->debug >= NV_DBG_TRACE) \ printk(fmt, ##args); \ } while(0) #define trace(fmt, args...) bioslog(TRACE, fmt, ##args) @@ -141,7 +141,7 @@ init_conn(struct nvbios_init *init) static inline u32 init_nvreg(struct nvbios_init *init, u32 reg) { - struct nvkm_devinit *devinit = nvkm_devinit(init->bios); + struct nvkm_devinit *devinit = init->bios->subdev.device->devinit; /* C51 (at least) sometimes has the lower bits set which the VBIOS * interprets to mean that access needs to go through certain IO @@ -154,7 +154,7 @@ init_nvreg(struct nvbios_init *init, u32 reg) /* GF8+ display scripts need register addresses mangled a bit to * select a specific CRTC/OR */ - if (nv_device(init->bios)->card_type >= NV_50) { + if (init->bios->subdev.device->card_type >= NV_50) { if (reg & 0x80000000) { reg += init_crtc(init) * 0x800; reg &= ~0x80000000; @@ -173,35 +173,36 @@ init_nvreg(struct nvbios_init *init, u32 reg) if (reg & ~0x00fffffc) warn("unknown bits in register 0x%08x\n", reg); - if (devinit->mmio) - reg = devinit->mmio(devinit, reg); - return reg; + return nvkm_devinit_mmio(devinit, reg); } static u32 init_rd32(struct nvbios_init *init, u32 reg) { + struct nvkm_device *device = init->bios->subdev.device; reg = init_nvreg(init, reg); if (reg != ~0 && init_exec(init)) - return nv_rd32(init->subdev, reg); + return nvkm_rd32(device, reg); return 0x00000000; } static void init_wr32(struct nvbios_init *init, u32 reg, u32 val) { + struct nvkm_device *device = init->bios->subdev.device; reg = init_nvreg(init, reg); if (reg != ~0 && init_exec(init)) - nv_wr32(init->subdev, reg, val); + nvkm_wr32(device, reg, val); } static u32 init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val) { + struct nvkm_device *device = init->bios->subdev.device; reg = init_nvreg(init, reg); if (reg != ~0 && init_exec(init)) { - u32 tmp = nv_rd32(init->subdev, reg); - nv_wr32(init->subdev, reg, (tmp & ~mask) | val); + u32 tmp = nvkm_rd32(device, reg); + nvkm_wr32(device, reg, (tmp & ~mask) | val); return tmp; } return 0x00000000; @@ -211,7 +212,7 @@ static u8 init_rdport(struct nvbios_init *init, u16 port) { if (init_exec(init)) - return nv_rdport(init->subdev, init->crtc, port); + return nvkm_rdport(init->subdev->device, init->crtc, port); return 0x00; } @@ -219,7 +220,7 @@ static void init_wrport(struct nvbios_init *init, u16 port, u8 value) { if (init_exec(init)) - nv_wrport(init->subdev, init->crtc, port, value); + nvkm_wrport(init->subdev->device, init->crtc, port, value); } static u8 @@ -228,7 +229,7 @@ init_rdvgai(struct nvbios_init *init, u16 port, u8 index) struct nvkm_subdev *subdev = init->subdev; if (init_exec(init)) { int head = init->crtc < 0 ? 0 : init->crtc; - return nv_rdvgai(subdev, head, port, index); + return nvkm_rdvgai(subdev->device, head, port, index); } return 0x00; } @@ -236,80 +237,86 @@ init_rdvgai(struct nvbios_init *init, u16 port, u8 index) static void init_wrvgai(struct nvbios_init *init, u16 port, u8 index, u8 value) { + struct nvkm_device *device = init->subdev->device; + /* force head 0 for updates to cr44, it only exists on first head */ - if (nv_device(init->subdev)->card_type < NV_50) { + if (device->card_type < NV_50) { if (port == 0x03d4 && index == 0x44) init->crtc = 0; } if (init_exec(init)) { int head = init->crtc < 0 ? 0 : init->crtc; - nv_wrvgai(init->subdev, head, port, index, value); + nvkm_wrvgai(device, head, port, index, value); } /* select head 1 if cr44 write selected it */ - if (nv_device(init->subdev)->card_type < NV_50) { + if (device->card_type < NV_50) { if (port == 0x03d4 && index == 0x44 && value == 3) init->crtc = 1; } } -static struct nvkm_i2c_port * +static struct i2c_adapter * init_i2c(struct nvbios_init *init, int index) { - struct nvkm_i2c *i2c = nvkm_i2c(init->bios); + struct nvkm_i2c *i2c = init->bios->subdev.device->i2c; + struct nvkm_i2c_bus *bus; if (index == 0xff) { - index = NV_I2C_DEFAULT(0); + index = NVKM_I2C_BUS_PRI; if (init->outp && init->outp->i2c_upper_default) - index = NV_I2C_DEFAULT(1); + index = NVKM_I2C_BUS_SEC; } else - if (index < 0) { - if (!init->outp) { - if (init_exec(init)) - error("script needs output for i2c\n"); - return NULL; - } - - if (index == -2 && init->outp->location) { - index = NV_I2C_TYPE_EXTAUX(init->outp->extdev); - return i2c->find_type(i2c, index); - } - - index = init->outp->i2c_index; - if (init->outp->type == DCB_OUTPUT_DP) - index += NV_I2C_AUX(0); + if (index == 0x80) { + index = NVKM_I2C_BUS_PRI; + } else + if (index == 0x81) { + index = NVKM_I2C_BUS_SEC; } - return i2c->find(i2c, index); + bus = nvkm_i2c_bus_find(i2c, index); + return bus ? &bus->i2c : NULL; } static int init_rdi2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg) { - struct nvkm_i2c_port *port = init_i2c(init, index); - if (port && init_exec(init)) - return nv_rdi2cr(port, addr, reg); + struct i2c_adapter *adap = init_i2c(init, index); + if (adap && init_exec(init)) + return nvkm_rdi2cr(adap, addr, reg); return -ENODEV; } static int init_wri2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg, u8 val) { - struct nvkm_i2c_port *port = init_i2c(init, index); - if (port && init_exec(init)) - return nv_wri2cr(port, addr, reg, val); + struct i2c_adapter *adap = init_i2c(init, index); + if (adap && init_exec(init)) + return nvkm_wri2cr(adap, addr, reg, val); return -ENODEV; } +static struct nvkm_i2c_aux * +init_aux(struct nvbios_init *init) +{ + struct nvkm_i2c *i2c = init->bios->subdev.device->i2c; + if (!init->outp) { + if (init_exec(init)) + error("script needs output for aux\n"); + return NULL; + } + return nvkm_i2c_aux_find(i2c, init->outp->i2c_index); +} + static u8 init_rdauxr(struct nvbios_init *init, u32 addr) { - struct nvkm_i2c_port *port = init_i2c(init, -2); + struct nvkm_i2c_aux *aux = init_aux(init); u8 data; - if (port && init_exec(init)) { - int ret = nv_rdaux(port, addr, &data, 1); + if (aux && init_exec(init)) { + int ret = nvkm_rdaux(aux, addr, &data, 1); if (ret == 0) return data; trace("auxch read failed with %d\n", ret); @@ -321,9 +328,9 @@ init_rdauxr(struct nvbios_init *init, u32 addr) static int init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) { - struct nvkm_i2c_port *port = init_i2c(init, -2); - if (port && init_exec(init)) { - int ret = nv_wraux(port, addr, &data, 1); + struct nvkm_i2c_aux *aux = init_aux(init); + if (aux && init_exec(init)) { + int ret = nvkm_wraux(aux, addr, &data, 1); if (ret) trace("auxch write failed with %d\n", ret); return ret; @@ -334,9 +341,9 @@ init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) static void init_prog_pll(struct nvbios_init *init, u32 id, u32 freq) { - struct nvkm_devinit *devinit = nvkm_devinit(init->bios); - if (devinit->pll_set && init_exec(init)) { - int ret = devinit->pll_set(devinit, id, freq); + struct nvkm_devinit *devinit = init->bios->subdev.device->devinit; + if (init_exec(init)) { + int ret = nvkm_devinit_pll_set(devinit, id, freq); if (ret) warn("failed to prog pll 0x%08x to %dkHz\n", id, freq); } @@ -371,7 +378,7 @@ init_table_(struct nvbios_init *init, u16 offset, const char *name) u16 len, data = init_table(bios, &len); if (data) { if (len >= offset + 2) { - data = nv_ro16(bios, data + offset); + data = nvbios_rd16(bios, data + offset); if (data) return data; @@ -407,12 +414,12 @@ init_script(struct nvkm_bios *bios, int index) return 0x0000; data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18); - return nv_ro16(bios, data + (index * 2)); + return nvbios_rd16(bios, data + (index * 2)); } data = init_script_table(&init); if (data) - return nv_ro16(bios, data + (index * 2)); + return nvbios_rd16(bios, data + (index * 2)); return 0x0000; } @@ -422,7 +429,7 @@ init_unknown_script(struct nvkm_bios *bios) { u16 len, data = init_table(bios, &len); if (data && len >= 16) - return nv_ro16(bios, data + 14); + return nvbios_rd16(bios, data + 14); return 0x0000; } @@ -454,9 +461,9 @@ init_xlat_(struct nvbios_init *init, u8 index, u8 offset) struct nvkm_bios *bios = init->bios; u16 table = init_xlat_table(init); if (table) { - u16 data = nv_ro16(bios, table + (index * 2)); + u16 data = nvbios_rd16(bios, table + (index * 2)); if (data) - return nv_ro08(bios, data + offset); + return nvbios_rd08(bios, data + offset); warn("xlat table pointer %d invalid\n", index); } return 0x00; @@ -472,9 +479,9 @@ init_condition_met(struct nvbios_init *init, u8 cond) struct nvkm_bios *bios = init->bios; u16 table = init_condition_table(init); if (table) { - u32 reg = nv_ro32(bios, table + (cond * 12) + 0); - u32 msk = nv_ro32(bios, table + (cond * 12) + 4); - u32 val = nv_ro32(bios, table + (cond * 12) + 8); + u32 reg = nvbios_rd32(bios, table + (cond * 12) + 0); + u32 msk = nvbios_rd32(bios, table + (cond * 12) + 4); + u32 val = nvbios_rd32(bios, table + (cond * 12) + 8); trace("\t[0x%02x] (R[0x%06x] & 0x%08x) == 0x%08x\n", cond, reg, msk, val); return (init_rd32(init, reg) & msk) == val; @@ -488,10 +495,10 @@ init_io_condition_met(struct nvbios_init *init, u8 cond) struct nvkm_bios *bios = init->bios; u16 table = init_io_condition_table(init); if (table) { - u16 port = nv_ro16(bios, table + (cond * 5) + 0); - u8 index = nv_ro08(bios, table + (cond * 5) + 2); - u8 mask = nv_ro08(bios, table + (cond * 5) + 3); - u8 value = nv_ro08(bios, table + (cond * 5) + 4); + u16 port = nvbios_rd16(bios, table + (cond * 5) + 0); + u8 index = nvbios_rd08(bios, table + (cond * 5) + 2); + u8 mask = nvbios_rd08(bios, table + (cond * 5) + 3); + u8 value = nvbios_rd08(bios, table + (cond * 5) + 4); trace("\t[0x%02x] (0x%04x[0x%02x] & 0x%02x) == 0x%02x\n", cond, port, index, mask, value); return (init_rdvgai(init, port, index) & mask) == value; @@ -505,15 +512,15 @@ init_io_flag_condition_met(struct nvbios_init *init, u8 cond) struct nvkm_bios *bios = init->bios; u16 table = init_io_flag_condition_table(init); if (table) { - u16 port = nv_ro16(bios, table + (cond * 9) + 0); - u8 index = nv_ro08(bios, table + (cond * 9) + 2); - u8 mask = nv_ro08(bios, table + (cond * 9) + 3); - u8 shift = nv_ro08(bios, table + (cond * 9) + 4); - u16 data = nv_ro16(bios, table + (cond * 9) + 5); - u8 dmask = nv_ro08(bios, table + (cond * 9) + 7); - u8 value = nv_ro08(bios, table + (cond * 9) + 8); + u16 port = nvbios_rd16(bios, table + (cond * 9) + 0); + u8 index = nvbios_rd08(bios, table + (cond * 9) + 2); + u8 mask = nvbios_rd08(bios, table + (cond * 9) + 3); + u8 shift = nvbios_rd08(bios, table + (cond * 9) + 4); + u16 data = nvbios_rd16(bios, table + (cond * 9) + 5); + u8 dmask = nvbios_rd08(bios, table + (cond * 9) + 7); + u8 value = nvbios_rd08(bios, table + (cond * 9) + 8); u8 ioval = (init_rdvgai(init, port, index) & mask) >> shift; - return (nv_ro08(bios, data + ioval) & dmask) == value; + return (nvbios_rd08(bios, data + ioval) & dmask) == value; } return false; } @@ -573,7 +580,7 @@ init_tmds_reg(struct nvbios_init *init, u8 tmds) static void init_reserved(struct nvbios_init *init) { - u8 opcode = nv_ro08(init->bios, init->offset); + u8 opcode = nvbios_rd08(init->bios, init->offset); u8 length, i; switch (opcode) { @@ -587,7 +594,7 @@ init_reserved(struct nvbios_init *init) trace("RESERVED 0x%02x\t", opcode); for (i = 1; i < length; i++) - cont(" 0x%02x", nv_ro08(init->bios, init->offset + i)); + cont(" 0x%02x", nvbios_rd08(init->bios, init->offset + i)); cont("\n"); init->offset += length; } @@ -611,12 +618,12 @@ static void init_io_restrict_prog(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 port = nv_ro16(bios, init->offset + 1); - u8 index = nv_ro08(bios, init->offset + 3); - u8 mask = nv_ro08(bios, init->offset + 4); - u8 shift = nv_ro08(bios, init->offset + 5); - u8 count = nv_ro08(bios, init->offset + 6); - u32 reg = nv_ro32(bios, init->offset + 7); + u16 port = nvbios_rd16(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 3); + u8 mask = nvbios_rd08(bios, init->offset + 4); + u8 shift = nvbios_rd08(bios, init->offset + 5); + u8 count = nvbios_rd08(bios, init->offset + 6); + u32 reg = nvbios_rd32(bios, init->offset + 7); u8 conf, i; trace("IO_RESTRICT_PROG\tR[0x%06x] = " @@ -626,7 +633,7 @@ init_io_restrict_prog(struct nvbios_init *init) conf = (init_rdvgai(init, port, index) & mask) >> shift; for (i = 0; i < count; i++) { - u32 data = nv_ro32(bios, init->offset); + u32 data = nvbios_rd32(bios, init->offset); if (i == conf) { trace("\t0x%08x *\n", data); @@ -648,7 +655,7 @@ static void init_repeat(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 count = nv_ro08(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 1); u16 repeat = init->repeat; trace("REPEAT\t0x%02x\n", count); @@ -674,13 +681,13 @@ static void init_io_restrict_pll(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 port = nv_ro16(bios, init->offset + 1); - u8 index = nv_ro08(bios, init->offset + 3); - u8 mask = nv_ro08(bios, init->offset + 4); - u8 shift = nv_ro08(bios, init->offset + 5); - s8 iofc = nv_ro08(bios, init->offset + 6); - u8 count = nv_ro08(bios, init->offset + 7); - u32 reg = nv_ro32(bios, init->offset + 8); + u16 port = nvbios_rd16(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 3); + u8 mask = nvbios_rd08(bios, init->offset + 4); + u8 shift = nvbios_rd08(bios, init->offset + 5); + s8 iofc = nvbios_rd08(bios, init->offset + 6); + u8 count = nvbios_rd08(bios, init->offset + 7); + u32 reg = nvbios_rd32(bios, init->offset + 8); u8 conf, i; trace("IO_RESTRICT_PLL\tR[0x%06x] =PLL= " @@ -690,7 +697,7 @@ init_io_restrict_pll(struct nvbios_init *init) conf = (init_rdvgai(init, port, index) & mask) >> shift; for (i = 0; i < count; i++) { - u32 freq = nv_ro16(bios, init->offset) * 10; + u32 freq = nvbios_rd16(bios, init->offset) * 10; if (i == conf) { trace("\t%dkHz *\n", freq); @@ -730,12 +737,12 @@ static void init_copy(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u8 shift = nv_ro08(bios, init->offset + 5); - u8 smask = nv_ro08(bios, init->offset + 6); - u16 port = nv_ro16(bios, init->offset + 7); - u8 index = nv_ro08(bios, init->offset + 9); - u8 mask = nv_ro08(bios, init->offset + 10); + u32 reg = nvbios_rd32(bios, init->offset + 1); + u8 shift = nvbios_rd08(bios, init->offset + 5); + u8 smask = nvbios_rd08(bios, init->offset + 6); + u16 port = nvbios_rd16(bios, init->offset + 7); + u8 index = nvbios_rd08(bios, init->offset + 9); + u8 mask = nvbios_rd08(bios, init->offset + 10); u8 data; trace("COPY\t0x%04x[0x%02x] &= 0x%02x |= " @@ -769,7 +776,7 @@ static void init_io_flag_condition(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 cond = nv_ro08(bios, init->offset + 1); + u8 cond = nvbios_rd08(bios, init->offset + 1); trace("IO_FLAG_CONDITION\t0x%02x\n", cond); init->offset += 2; @@ -787,8 +794,8 @@ init_dp_condition(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; struct nvbios_dpout info; - u8 cond = nv_ro08(bios, init->offset + 1); - u8 unkn = nv_ro08(bios, init->offset + 2); + u8 cond = nvbios_rd08(bios, init->offset + 1); + u8 unkn = nvbios_rd08(bios, init->offset + 2); u8 ver, hdr, cnt, len; u16 data; @@ -834,7 +841,7 @@ static void init_io_mask_or(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 1); u8 or = init_or(init); u8 data; @@ -853,7 +860,7 @@ static void init_io_or(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 1); u8 or = init_or(init); u8 data; @@ -872,8 +879,8 @@ static void init_andn_reg(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u32 mask = nv_ro32(bios, init->offset + 5); + u32 reg = nvbios_rd32(bios, init->offset + 1); + u32 mask = nvbios_rd32(bios, init->offset + 5); trace("ANDN_REG\tR[0x%06x] &= ~0x%08x\n", reg, mask); init->offset += 9; @@ -889,8 +896,8 @@ static void init_or_reg(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u32 mask = nv_ro32(bios, init->offset + 5); + u32 reg = nvbios_rd32(bios, init->offset + 1); + u32 mask = nvbios_rd32(bios, init->offset + 5); trace("OR_REG\tR[0x%06x] |= 0x%08x\n", reg, mask); init->offset += 9; @@ -906,19 +913,19 @@ static void init_idx_addr_latched(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 creg = nv_ro32(bios, init->offset + 1); - u32 dreg = nv_ro32(bios, init->offset + 5); - u32 mask = nv_ro32(bios, init->offset + 9); - u32 data = nv_ro32(bios, init->offset + 13); - u8 count = nv_ro08(bios, init->offset + 17); + u32 creg = nvbios_rd32(bios, init->offset + 1); + u32 dreg = nvbios_rd32(bios, init->offset + 5); + u32 mask = nvbios_rd32(bios, init->offset + 9); + u32 data = nvbios_rd32(bios, init->offset + 13); + u8 count = nvbios_rd08(bios, init->offset + 17); trace("INDEX_ADDRESS_LATCHED\tR[0x%06x] : R[0x%06x]\n", creg, dreg); trace("\tCTRL &= 0x%08x |= 0x%08x\n", mask, data); init->offset += 18; while (count--) { - u8 iaddr = nv_ro08(bios, init->offset + 0); - u8 idata = nv_ro08(bios, init->offset + 1); + u8 iaddr = nvbios_rd08(bios, init->offset + 0); + u8 idata = nvbios_rd08(bios, init->offset + 1); trace("\t[0x%02x] = 0x%02x\n", iaddr, idata); init->offset += 2; @@ -936,12 +943,12 @@ static void init_io_restrict_pll2(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 port = nv_ro16(bios, init->offset + 1); - u8 index = nv_ro08(bios, init->offset + 3); - u8 mask = nv_ro08(bios, init->offset + 4); - u8 shift = nv_ro08(bios, init->offset + 5); - u8 count = nv_ro08(bios, init->offset + 6); - u32 reg = nv_ro32(bios, init->offset + 7); + u16 port = nvbios_rd16(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 3); + u8 mask = nvbios_rd08(bios, init->offset + 4); + u8 shift = nvbios_rd08(bios, init->offset + 5); + u8 count = nvbios_rd08(bios, init->offset + 6); + u32 reg = nvbios_rd32(bios, init->offset + 7); u8 conf, i; trace("IO_RESTRICT_PLL2\t" @@ -951,7 +958,7 @@ init_io_restrict_pll2(struct nvbios_init *init) conf = (init_rdvgai(init, port, index) & mask) >> shift; for (i = 0; i < count; i++) { - u32 freq = nv_ro32(bios, init->offset); + u32 freq = nvbios_rd32(bios, init->offset); if (i == conf) { trace("\t%dkHz *\n", freq); init_prog_pll(init, reg, freq); @@ -971,8 +978,8 @@ static void init_pll2(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u32 freq = nv_ro32(bios, init->offset + 5); + u32 reg = nvbios_rd32(bios, init->offset + 1); + u32 freq = nvbios_rd32(bios, init->offset + 5); trace("PLL2\tR[0x%06x] =PLL= %dkHz\n", reg, freq); init->offset += 9; @@ -988,17 +995,17 @@ static void init_i2c_byte(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); - u8 addr = nv_ro08(bios, init->offset + 2) >> 1; - u8 count = nv_ro08(bios, init->offset + 3); + u8 index = nvbios_rd08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 2) >> 1; + u8 count = nvbios_rd08(bios, init->offset + 3); trace("I2C_BYTE\tI2C[0x%02x][0x%02x]\n", index, addr); init->offset += 4; while (count--) { - u8 reg = nv_ro08(bios, init->offset + 0); - u8 mask = nv_ro08(bios, init->offset + 1); - u8 data = nv_ro08(bios, init->offset + 2); + u8 reg = nvbios_rd08(bios, init->offset + 0); + u8 mask = nvbios_rd08(bios, init->offset + 1); + u8 data = nvbios_rd08(bios, init->offset + 2); int val; trace("\t[0x%02x] &= 0x%02x |= 0x%02x\n", reg, mask, data); @@ -1019,16 +1026,16 @@ static void init_zm_i2c_byte(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); - u8 addr = nv_ro08(bios, init->offset + 2) >> 1; - u8 count = nv_ro08(bios, init->offset + 3); + u8 index = nvbios_rd08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 2) >> 1; + u8 count = nvbios_rd08(bios, init->offset + 3); trace("ZM_I2C_BYTE\tI2C[0x%02x][0x%02x]\n", index, addr); init->offset += 4; while (count--) { - u8 reg = nv_ro08(bios, init->offset + 0); - u8 data = nv_ro08(bios, init->offset + 1); + u8 reg = nvbios_rd08(bios, init->offset + 0); + u8 data = nvbios_rd08(bios, init->offset + 1); trace("\t[0x%02x] = 0x%02x\n", reg, data); init->offset += 2; @@ -1045,28 +1052,28 @@ static void init_zm_i2c(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); - u8 addr = nv_ro08(bios, init->offset + 2) >> 1; - u8 count = nv_ro08(bios, init->offset + 3); + u8 index = nvbios_rd08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 2) >> 1; + u8 count = nvbios_rd08(bios, init->offset + 3); u8 data[256], i; trace("ZM_I2C\tI2C[0x%02x][0x%02x]\n", index, addr); init->offset += 4; for (i = 0; i < count; i++) { - data[i] = nv_ro08(bios, init->offset); + data[i] = nvbios_rd08(bios, init->offset); trace("\t0x%02x\n", data[i]); init->offset++; } if (init_exec(init)) { - struct nvkm_i2c_port *port = init_i2c(init, index); + struct i2c_adapter *adap = init_i2c(init, index); struct i2c_msg msg = { .addr = addr, .flags = 0, .len = count, .buf = data, }; int ret; - if (port && (ret = i2c_transfer(&port->adapter, &msg, 1)) != 1) + if (adap && (ret = i2c_transfer(adap, &msg, 1)) != 1) warn("i2c wr failed, %d\n", ret); } } @@ -1079,10 +1086,10 @@ static void init_tmds(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 tmds = nv_ro08(bios, init->offset + 1); - u8 addr = nv_ro08(bios, init->offset + 2); - u8 mask = nv_ro08(bios, init->offset + 3); - u8 data = nv_ro08(bios, init->offset + 4); + u8 tmds = nvbios_rd08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 2); + u8 mask = nvbios_rd08(bios, init->offset + 3); + u8 data = nvbios_rd08(bios, init->offset + 4); u32 reg = init_tmds_reg(init, tmds); trace("TMDS\tT[0x%02x][0x%02x] &= 0x%02x |= 0x%02x\n", @@ -1105,16 +1112,16 @@ static void init_zm_tmds_group(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 tmds = nv_ro08(bios, init->offset + 1); - u8 count = nv_ro08(bios, init->offset + 2); + u8 tmds = nvbios_rd08(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 2); u32 reg = init_tmds_reg(init, tmds); trace("TMDS_ZM_GROUP\tT[0x%02x]\n", tmds); init->offset += 3; while (count--) { - u8 addr = nv_ro08(bios, init->offset + 0); - u8 data = nv_ro08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 0); + u8 data = nvbios_rd08(bios, init->offset + 1); trace("\t[0x%02x] = 0x%02x\n", addr, data); init->offset += 2; @@ -1132,10 +1139,10 @@ static void init_cr_idx_adr_latch(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 addr0 = nv_ro08(bios, init->offset + 1); - u8 addr1 = nv_ro08(bios, init->offset + 2); - u8 base = nv_ro08(bios, init->offset + 3); - u8 count = nv_ro08(bios, init->offset + 4); + u8 addr0 = nvbios_rd08(bios, init->offset + 1); + u8 addr1 = nvbios_rd08(bios, init->offset + 2); + u8 base = nvbios_rd08(bios, init->offset + 3); + u8 count = nvbios_rd08(bios, init->offset + 4); u8 save0; trace("CR_INDEX_ADDR C[%02x] C[%02x]\n", addr0, addr1); @@ -1143,7 +1150,7 @@ init_cr_idx_adr_latch(struct nvbios_init *init) save0 = init_rdvgai(init, 0x03d4, addr0); while (count--) { - u8 data = nv_ro08(bios, init->offset); + u8 data = nvbios_rd08(bios, init->offset); trace("\t\t[0x%02x] = 0x%02x\n", base, data); init->offset += 1; @@ -1162,9 +1169,9 @@ static void init_cr(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 addr = nv_ro08(bios, init->offset + 1); - u8 mask = nv_ro08(bios, init->offset + 2); - u8 data = nv_ro08(bios, init->offset + 3); + u8 addr = nvbios_rd08(bios, init->offset + 1); + u8 mask = nvbios_rd08(bios, init->offset + 2); + u8 data = nvbios_rd08(bios, init->offset + 3); u8 val; trace("CR\t\tC[0x%02x] &= 0x%02x |= 0x%02x\n", addr, mask, data); @@ -1182,8 +1189,8 @@ static void init_zm_cr(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 addr = nv_ro08(bios, init->offset + 1); - u8 data = nv_ro08(bios, init->offset + 2); + u8 addr = nvbios_rd08(bios, init->offset + 1); + u8 data = nvbios_rd08(bios, init->offset + 2); trace("ZM_CR\tC[0x%02x] = 0x%02x\n", addr, data); init->offset += 3; @@ -1199,14 +1206,14 @@ static void init_zm_cr_group(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 count = nv_ro08(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 1); trace("ZM_CR_GROUP\n"); init->offset += 2; while (count--) { - u8 addr = nv_ro08(bios, init->offset + 0); - u8 data = nv_ro08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 0); + u8 data = nvbios_rd08(bios, init->offset + 1); trace("\t\tC[0x%02x] = 0x%02x\n", addr, data); init->offset += 2; @@ -1223,8 +1230,8 @@ static void init_condition_time(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 cond = nv_ro08(bios, init->offset + 1); - u8 retry = nv_ro08(bios, init->offset + 2); + u8 cond = nvbios_rd08(bios, init->offset + 1); + u8 retry = nvbios_rd08(bios, init->offset + 2); u8 wait = min((u16)retry * 50, 100); trace("CONDITION_TIME\t0x%02x 0x%02x\n", cond, retry); @@ -1250,7 +1257,7 @@ static void init_ltime(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 msec = nv_ro16(bios, init->offset + 1); + u16 msec = nvbios_rd16(bios, init->offset + 1); trace("LTIME\t0x%04x\n", msec); init->offset += 3; @@ -1267,14 +1274,14 @@ static void init_zm_reg_sequence(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 base = nv_ro32(bios, init->offset + 1); - u8 count = nv_ro08(bios, init->offset + 5); + u32 base = nvbios_rd32(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 5); trace("ZM_REG_SEQUENCE\t0x%02x\n", count); init->offset += 6; while (count--) { - u32 data = nv_ro32(bios, init->offset); + u32 data = nvbios_rd32(bios, init->offset); trace("\t\tR[0x%06x] = 0x%08x\n", base, data); init->offset += 4; @@ -1284,6 +1291,44 @@ init_zm_reg_sequence(struct nvbios_init *init) } } +/** + * INIT_PLL_INDIRECT - opcode 0x59 + * + */ +static void +init_pll_indirect(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u32 reg = nvbios_rd32(bios, init->offset + 1); + u16 addr = nvbios_rd16(bios, init->offset + 5); + u32 freq = (u32)nvbios_rd16(bios, addr) * 1000; + + trace("PLL_INDIRECT\tR[0x%06x] =PLL= VBIOS[%04x] = %dkHz\n", + reg, addr, freq); + init->offset += 7; + + init_prog_pll(init, reg, freq); +} + +/** + * INIT_ZM_REG_INDIRECT - opcode 0x5a + * + */ +static void +init_zm_reg_indirect(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u32 reg = nvbios_rd32(bios, init->offset + 1); + u16 addr = nvbios_rd16(bios, init->offset + 5); + u32 data = nvbios_rd32(bios, addr); + + trace("ZM_REG_INDIRECT\tR[0x%06x] = VBIOS[0x%04x] = 0x%08x\n", + reg, addr, data); + init->offset += 7; + + init_wr32(init, addr, data); +} + /** * INIT_SUB_DIRECT - opcode 0x5b * @@ -1292,7 +1337,7 @@ static void init_sub_direct(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 addr = nv_ro16(bios, init->offset + 1); + u16 addr = nvbios_rd16(bios, init->offset + 1); u16 save; trace("SUB_DIRECT\t0x%04x\n", addr); @@ -1318,7 +1363,7 @@ static void init_jump(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 offset = nv_ro16(bios, init->offset + 1); + u16 offset = nvbios_rd16(bios, init->offset + 1); trace("JUMP\t0x%04x\n", offset); @@ -1336,11 +1381,11 @@ static void init_i2c_if(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); - u8 addr = nv_ro08(bios, init->offset + 2); - u8 reg = nv_ro08(bios, init->offset + 3); - u8 mask = nv_ro08(bios, init->offset + 4); - u8 data = nv_ro08(bios, init->offset + 5); + u8 index = nvbios_rd08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 2); + u8 reg = nvbios_rd08(bios, init->offset + 3); + u8 mask = nvbios_rd08(bios, init->offset + 4); + u8 data = nvbios_rd08(bios, init->offset + 5); u8 value; trace("I2C_IF\tI2C[0x%02x][0x%02x][0x%02x] & 0x%02x == 0x%02x\n", @@ -1363,12 +1408,12 @@ static void init_copy_nv_reg(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 sreg = nv_ro32(bios, init->offset + 1); - u8 shift = nv_ro08(bios, init->offset + 5); - u32 smask = nv_ro32(bios, init->offset + 6); - u32 sxor = nv_ro32(bios, init->offset + 10); - u32 dreg = nv_ro32(bios, init->offset + 14); - u32 dmask = nv_ro32(bios, init->offset + 18); + u32 sreg = nvbios_rd32(bios, init->offset + 1); + u8 shift = nvbios_rd08(bios, init->offset + 5); + u32 smask = nvbios_rd32(bios, init->offset + 6); + u32 sxor = nvbios_rd32(bios, init->offset + 10); + u32 dreg = nvbios_rd32(bios, init->offset + 14); + u32 dmask = nvbios_rd32(bios, init->offset + 18); u32 data; trace("COPY_NV_REG\tR[0x%06x] &= 0x%08x |= " @@ -1389,9 +1434,9 @@ static void init_zm_index_io(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 port = nv_ro16(bios, init->offset + 1); - u8 index = nv_ro08(bios, init->offset + 3); - u8 data = nv_ro08(bios, init->offset + 4); + u16 port = nvbios_rd16(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 3); + u8 data = nvbios_rd08(bios, init->offset + 4); trace("ZM_INDEX_IO\tI[0x%04x][0x%02x] = 0x%02x\n", port, index, data); init->offset += 5; @@ -1406,14 +1451,14 @@ init_zm_index_io(struct nvbios_init *init) static void init_compute_mem(struct nvbios_init *init) { - struct nvkm_devinit *devinit = nvkm_devinit(init->bios); + struct nvkm_devinit *devinit = init->bios->subdev.device->devinit; trace("COMPUTE_MEM\n"); init->offset += 1; init_exec_force(init, true); - if (init_exec(init) && devinit->meminit) - devinit->meminit(devinit); + if (init_exec(init)) + nvkm_devinit_meminit(devinit); init_exec_force(init, false); } @@ -1425,9 +1470,9 @@ static void init_reset(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u32 data1 = nv_ro32(bios, init->offset + 5); - u32 data2 = nv_ro32(bios, init->offset + 9); + u32 reg = nvbios_rd32(bios, init->offset + 1); + u32 data1 = nvbios_rd32(bios, init->offset + 5); + u32 data2 = nvbios_rd32(bios, init->offset + 9); u32 savepci19; trace("RESET\tR[0x%08x] = 0x%08x, 0x%08x", reg, data1, data2); @@ -1475,14 +1520,14 @@ init_configure_mem(struct nvbios_init *init) mdata = init_configure_mem_clk(init); sdata = bmp_sdr_seq_table(bios); - if (nv_ro08(bios, mdata) & 0x01) + if (nvbios_rd08(bios, mdata) & 0x01) sdata = bmp_ddr_seq_table(bios); mdata += 6; /* skip to data */ data = init_rdvgai(init, 0x03c4, 0x01); init_wrvgai(init, 0x03c4, 0x01, data | 0x20); - for (; (addr = nv_ro32(bios, sdata)) != 0xffffffff; sdata += 4) { + for (; (addr = nvbios_rd32(bios, sdata)) != 0xffffffff; sdata += 4) { switch (addr) { case 0x10021c: /* CKE_NORMAL */ case 0x1002d0: /* CMD_REFRESH */ @@ -1490,7 +1535,7 @@ init_configure_mem(struct nvbios_init *init) data = 0x00000001; break; default: - data = nv_ro32(bios, mdata); + data = nvbios_rd32(bios, mdata); mdata += 4; if (data == 0xffffffff) continue; @@ -1525,12 +1570,12 @@ init_configure_clk(struct nvbios_init *init) mdata = init_configure_mem_clk(init); /* NVPLL */ - clock = nv_ro16(bios, mdata + 4) * 10; + clock = nvbios_rd16(bios, mdata + 4) * 10; init_prog_pll(init, 0x680500, clock); /* MPLL */ - clock = nv_ro16(bios, mdata + 2) * 10; - if (nv_ro08(bios, mdata) & 0x01) + clock = nvbios_rd16(bios, mdata + 2) * 10; + if (nvbios_rd08(bios, mdata) & 0x01) clock *= 2; init_prog_pll(init, 0x680504, clock); @@ -1571,9 +1616,9 @@ static void init_io(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 port = nv_ro16(bios, init->offset + 1); - u8 mask = nv_ro16(bios, init->offset + 3); - u8 data = nv_ro16(bios, init->offset + 4); + u16 port = nvbios_rd16(bios, init->offset + 1); + u8 mask = nvbios_rd16(bios, init->offset + 3); + u8 data = nvbios_rd16(bios, init->offset + 4); u8 value; trace("IO\t\tI[0x%04x] &= 0x%02x |= 0x%02x\n", port, mask, data); @@ -1583,7 +1628,7 @@ init_io(struct nvbios_init *init) * needed some day.. it's almost certainly wrong, but, it also * somehow makes things work... */ - if (nv_device(init->bios)->card_type >= NV_50 && + if (bios->subdev.device->card_type >= NV_50 && port == 0x03c3 && data == 0x01) { init_mask(init, 0x614100, 0xf0800000, 0x00800000); init_mask(init, 0x00e18c, 0x00020000, 0x00020000); @@ -1611,7 +1656,7 @@ static void init_sub(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); + u8 index = nvbios_rd08(bios, init->offset + 1); u16 addr, save; trace("SUB\t0x%02x\n", index); @@ -1638,8 +1683,8 @@ static void init_ram_condition(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 mask = nv_ro08(bios, init->offset + 1); - u8 value = nv_ro08(bios, init->offset + 2); + u8 mask = nvbios_rd08(bios, init->offset + 1); + u8 value = nvbios_rd08(bios, init->offset + 2); trace("RAM_CONDITION\t" "(R[0x100000] & 0x%02x) == 0x%02x\n", mask, value); @@ -1657,9 +1702,9 @@ static void init_nv_reg(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u32 mask = nv_ro32(bios, init->offset + 5); - u32 data = nv_ro32(bios, init->offset + 9); + u32 reg = nvbios_rd32(bios, init->offset + 1); + u32 mask = nvbios_rd32(bios, init->offset + 5); + u32 data = nvbios_rd32(bios, init->offset + 9); trace("NV_REG\tR[0x%06x] &= 0x%08x |= 0x%08x\n", reg, mask, data); init->offset += 13; @@ -1675,15 +1720,15 @@ static void init_macro(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 macro = nv_ro08(bios, init->offset + 1); + u8 macro = nvbios_rd08(bios, init->offset + 1); u16 table; trace("MACRO\t0x%02x\n", macro); table = init_macro_table(init); if (table) { - u32 addr = nv_ro32(bios, table + (macro * 8) + 0); - u32 data = nv_ro32(bios, table + (macro * 8) + 4); + u32 addr = nvbios_rd32(bios, table + (macro * 8) + 0); + u32 data = nvbios_rd32(bios, table + (macro * 8) + 4); trace("\t\tR[0x%06x] = 0x%08x\n", addr, data); init_wr32(init, addr, data); } @@ -1703,6 +1748,24 @@ init_resume(struct nvbios_init *init) init_exec_set(init, true); } +/** + * INIT_STRAP_CONDITION - opcode 0x73 + * + */ +static void +init_strap_condition(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u32 mask = nvbios_rd32(bios, init->offset + 1); + u32 value = nvbios_rd32(bios, init->offset + 5); + + trace("STRAP_CONDITION\t(R[0x101000] & 0x%08x) == 0x%08x\n", mask, value); + init->offset += 9; + + if ((init_rd32(init, 0x101000) & mask) != value) + init_exec_set(init, false); +} + /** * INIT_TIME - opcode 0x74 * @@ -1711,7 +1774,7 @@ static void init_time(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 usec = nv_ro16(bios, init->offset + 1); + u16 usec = nvbios_rd16(bios, init->offset + 1); trace("TIME\t0x%04x\n", usec); init->offset += 3; @@ -1732,7 +1795,7 @@ static void init_condition(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 cond = nv_ro08(bios, init->offset + 1); + u8 cond = nvbios_rd08(bios, init->offset + 1); trace("CONDITION\t0x%02x\n", cond); init->offset += 2; @@ -1749,7 +1812,7 @@ static void init_io_condition(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 cond = nv_ro08(bios, init->offset + 1); + u8 cond = nvbios_rd08(bios, init->offset + 1); trace("IO_CONDITION\t0x%02x\n", cond); init->offset += 2; @@ -1758,6 +1821,23 @@ init_io_condition(struct nvbios_init *init) init_exec_set(init, false); } +/** + * INIT_ZM_REG16 - opcode 0x77 + * + */ +static void +init_zm_reg16(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u32 addr = nvbios_rd32(bios, init->offset + 1); + u16 data = nvbios_rd16(bios, init->offset + 5); + + trace("ZM_REG\tR[0x%06x] = 0x%04x\n", addr, data); + init->offset += 7; + + init_wr32(init, addr, data); +} + /** * INIT_INDEX_IO - opcode 0x78 * @@ -1766,10 +1846,10 @@ static void init_index_io(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u16 port = nv_ro16(bios, init->offset + 1); - u8 index = nv_ro16(bios, init->offset + 3); - u8 mask = nv_ro08(bios, init->offset + 4); - u8 data = nv_ro08(bios, init->offset + 5); + u16 port = nvbios_rd16(bios, init->offset + 1); + u8 index = nvbios_rd16(bios, init->offset + 3); + u8 mask = nvbios_rd08(bios, init->offset + 4); + u8 data = nvbios_rd08(bios, init->offset + 5); u8 value; trace("INDEX_IO\tI[0x%04x][0x%02x] &= 0x%02x |= 0x%02x\n", @@ -1788,8 +1868,8 @@ static void init_pll(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 reg = nv_ro32(bios, init->offset + 1); - u32 freq = nv_ro16(bios, init->offset + 5) * 10; + u32 reg = nvbios_rd32(bios, init->offset + 1); + u32 freq = nvbios_rd16(bios, init->offset + 5) * 10; trace("PLL\tR[0x%06x] =PLL= %dkHz\n", reg, freq); init->offset += 7; @@ -1805,8 +1885,8 @@ static void init_zm_reg(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 addr = nv_ro32(bios, init->offset + 1); - u32 data = nv_ro32(bios, init->offset + 5); + u32 addr = nvbios_rd32(bios, init->offset + 1); + u32 data = nvbios_rd32(bios, init->offset + 5); trace("ZM_REG\tR[0x%06x] = 0x%08x\n", addr, data); init->offset += 9; @@ -1825,7 +1905,7 @@ static void init_ram_restrict_pll(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 type = nv_ro08(bios, init->offset + 1); + u8 type = nvbios_rd08(bios, init->offset + 1); u8 count = init_ram_restrict_group_count(init); u8 strap = init_ram_restrict(init); u8 cconf; @@ -1834,7 +1914,7 @@ init_ram_restrict_pll(struct nvbios_init *init) init->offset += 2; for (cconf = 0; cconf < count; cconf++) { - u32 freq = nv_ro32(bios, init->offset); + u32 freq = nvbios_rd32(bios, init->offset); if (cconf == strap) { trace("%dkHz *\n", freq); @@ -1854,13 +1934,13 @@ init_ram_restrict_pll(struct nvbios_init *init) static void init_gpio(struct nvbios_init *init) { - struct nvkm_gpio *gpio = nvkm_gpio(init->bios); + struct nvkm_gpio *gpio = init->bios->subdev.device->gpio; trace("GPIO\n"); init->offset += 1; - if (init_exec(init) && gpio && gpio->reset) - gpio->reset(gpio, DCB_GPIO_UNUSED); + if (init_exec(init)) + nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED); } /** @@ -1871,9 +1951,9 @@ static void init_ram_restrict_zm_reg_group(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 addr = nv_ro32(bios, init->offset + 1); - u8 incr = nv_ro08(bios, init->offset + 5); - u8 num = nv_ro08(bios, init->offset + 6); + u32 addr = nvbios_rd32(bios, init->offset + 1); + u8 incr = nvbios_rd08(bios, init->offset + 5); + u8 num = nvbios_rd08(bios, init->offset + 6); u8 count = init_ram_restrict_group_count(init); u8 index = init_ram_restrict(init); u8 i, j; @@ -1885,7 +1965,7 @@ init_ram_restrict_zm_reg_group(struct nvbios_init *init) for (i = 0; i < num; i++) { trace("\tR[0x%06x] = {\n", addr); for (j = 0; j < count; j++) { - u32 data = nv_ro32(bios, init->offset); + u32 data = nvbios_rd32(bios, init->offset); if (j == index) { trace("\t\t0x%08x *\n", data); @@ -1909,8 +1989,8 @@ static void init_copy_zm_reg(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 sreg = nv_ro32(bios, init->offset + 1); - u32 dreg = nv_ro32(bios, init->offset + 5); + u32 sreg = nvbios_rd32(bios, init->offset + 1); + u32 dreg = nvbios_rd32(bios, init->offset + 5); trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", dreg, sreg); init->offset += 9; @@ -1926,14 +2006,14 @@ static void init_zm_reg_group(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 addr = nv_ro32(bios, init->offset + 1); - u8 count = nv_ro08(bios, init->offset + 5); + u32 addr = nvbios_rd32(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 5); trace("ZM_REG_GROUP\tR[0x%06x] =\n", addr); init->offset += 6; while (count--) { - u32 data = nv_ro32(bios, init->offset); + u32 data = nvbios_rd32(bios, init->offset); trace("\t0x%08x\n", data); init_wr32(init, addr, data); init->offset += 4; @@ -1948,13 +2028,13 @@ static void init_xlat(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 saddr = nv_ro32(bios, init->offset + 1); - u8 sshift = nv_ro08(bios, init->offset + 5); - u8 smask = nv_ro08(bios, init->offset + 6); - u8 index = nv_ro08(bios, init->offset + 7); - u32 daddr = nv_ro32(bios, init->offset + 8); - u32 dmask = nv_ro32(bios, init->offset + 12); - u8 shift = nv_ro08(bios, init->offset + 16); + u32 saddr = nvbios_rd32(bios, init->offset + 1); + u8 sshift = nvbios_rd08(bios, init->offset + 5); + u8 smask = nvbios_rd08(bios, init->offset + 6); + u8 index = nvbios_rd08(bios, init->offset + 7); + u32 daddr = nvbios_rd32(bios, init->offset + 8); + u32 dmask = nvbios_rd32(bios, init->offset + 12); + u8 shift = nvbios_rd08(bios, init->offset + 16); u32 data; trace("INIT_XLAT\tR[0x%06x] &= 0x%08x |= " @@ -1976,9 +2056,9 @@ static void init_zm_mask_add(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 addr = nv_ro32(bios, init->offset + 1); - u32 mask = nv_ro32(bios, init->offset + 5); - u32 add = nv_ro32(bios, init->offset + 9); + u32 addr = nvbios_rd32(bios, init->offset + 1); + u32 mask = nvbios_rd32(bios, init->offset + 5); + u32 add = nvbios_rd32(bios, init->offset + 9); u32 data; trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add); @@ -1997,15 +2077,15 @@ static void init_auxch(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 addr = nv_ro32(bios, init->offset + 1); - u8 count = nv_ro08(bios, init->offset + 5); + u32 addr = nvbios_rd32(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 5); trace("AUXCH\tAUX[0x%08x] 0x%02x\n", addr, count); init->offset += 6; while (count--) { - u8 mask = nv_ro08(bios, init->offset + 0); - u8 data = nv_ro08(bios, init->offset + 1); + u8 mask = nvbios_rd08(bios, init->offset + 0); + u8 data = nvbios_rd08(bios, init->offset + 1); trace("\tAUX[0x%08x] &= 0x%02x |= 0x%02x\n", addr, mask, data); mask = init_rdauxr(init, addr) & mask; init_wrauxr(init, addr, mask | data); @@ -2021,14 +2101,14 @@ static void init_zm_auxch(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u32 addr = nv_ro32(bios, init->offset + 1); - u8 count = nv_ro08(bios, init->offset + 5); + u32 addr = nvbios_rd32(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 5); trace("ZM_AUXCH\tAUX[0x%08x] 0x%02x\n", addr, count); init->offset += 6; while (count--) { - u8 data = nv_ro08(bios, init->offset + 0); + u8 data = nvbios_rd08(bios, init->offset + 0); trace("\tAUX[0x%08x] = 0x%02x\n", addr, data); init_wrauxr(init, addr, data); init->offset += 1; @@ -2043,21 +2123,21 @@ static void init_i2c_long_if(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - u8 index = nv_ro08(bios, init->offset + 1); - u8 addr = nv_ro08(bios, init->offset + 2) >> 1; - u8 reglo = nv_ro08(bios, init->offset + 3); - u8 reghi = nv_ro08(bios, init->offset + 4); - u8 mask = nv_ro08(bios, init->offset + 5); - u8 data = nv_ro08(bios, init->offset + 6); - struct nvkm_i2c_port *port; + u8 index = nvbios_rd08(bios, init->offset + 1); + u8 addr = nvbios_rd08(bios, init->offset + 2) >> 1; + u8 reglo = nvbios_rd08(bios, init->offset + 3); + u8 reghi = nvbios_rd08(bios, init->offset + 4); + u8 mask = nvbios_rd08(bios, init->offset + 5); + u8 data = nvbios_rd08(bios, init->offset + 6); + struct i2c_adapter *adap; trace("I2C_LONG_IF\t" "I2C[0x%02x][0x%02x][0x%02x%02x] & 0x%02x == 0x%02x\n", index, addr, reglo, reghi, mask, data); init->offset += 7; - port = init_i2c(init, index); - if (port) { + adap = init_i2c(init, index); + if (adap) { u8 i[2] = { reghi, reglo }; u8 o[1] = {}; struct i2c_msg msg[] = { @@ -2066,7 +2146,7 @@ init_i2c_long_if(struct nvbios_init *init) }; int ret; - ret = i2c_transfer(&port->adapter, msg, 2); + ret = i2c_transfer(adap, msg, 2); if (ret == 2 && ((o[0] & mask) == data)) return; } @@ -2082,9 +2162,9 @@ static void init_gpio_ne(struct nvbios_init *init) { struct nvkm_bios *bios = init->bios; - struct nvkm_gpio *gpio = nvkm_gpio(bios); + struct nvkm_gpio *gpio = bios->subdev.device->gpio; struct dcb_gpio_func func; - u8 count = nv_ro08(bios, init->offset + 1); + u8 count = nvbios_rd08(bios, init->offset + 1); u8 idx = 0, ver, len; u16 data, i; @@ -2092,21 +2172,21 @@ init_gpio_ne(struct nvbios_init *init) init->offset += 2; for (i = init->offset; i < init->offset + count; i++) - cont("0x%02x ", nv_ro08(bios, i)); + cont("0x%02x ", nvbios_rd08(bios, i)); cont("\n"); while ((data = dcb_gpio_parse(bios, 0, idx++, &ver, &len, &func))) { if (func.func != DCB_GPIO_UNUSED) { for (i = init->offset; i < init->offset + count; i++) { - if (func.func == nv_ro08(bios, i)) + if (func.func == nvbios_rd08(bios, i)) break; } trace("\tFUNC[0x%02x]", func.func); if (i == (init->offset + count)) { cont(" *"); - if (init_exec(init) && gpio && gpio->reset) - gpio->reset(gpio, func.func); + if (init_exec(init)) + nvkm_gpio_reset(gpio, func.func); } cont("\n"); } @@ -2145,6 +2225,8 @@ static struct nvbios_init_opcode { [0x56] = { init_condition_time }, [0x57] = { init_ltime }, [0x58] = { init_zm_reg_sequence }, + [0x59] = { init_pll_indirect }, + [0x5a] = { init_zm_reg_indirect }, [0x5b] = { init_sub_direct }, [0x5c] = { init_jump }, [0x5e] = { init_i2c_if }, @@ -2162,9 +2244,11 @@ static struct nvbios_init_opcode { [0x6f] = { init_macro }, [0x71] = { init_done }, [0x72] = { init_resume }, + [0x73] = { init_strap_condition }, [0x74] = { init_time }, [0x75] = { init_condition }, [0x76] = { init_io_condition }, + [0x77] = { init_zm_reg16 }, [0x78] = { init_index_io }, [0x79] = { init_pll }, [0x7a] = { init_zm_reg }, @@ -2192,7 +2276,7 @@ nvbios_exec(struct nvbios_init *init) { init->nested++; while (init->offset) { - u8 opcode = nv_ro08(init->bios, init->offset); + u8 opcode = nvbios_rd08(init->bios, init->offset); if (opcode >= init_opcode_nr || !init_opcode[opcode].exec) { error("unknown opcode 0x%02x\n", opcode); return -EINVAL; @@ -2207,13 +2291,13 @@ nvbios_exec(struct nvbios_init *init) int nvbios_init(struct nvkm_subdev *subdev, bool execute) { - struct nvkm_bios *bios = nvkm_bios(subdev); + struct nvkm_bios *bios = subdev->device->bios; int ret = 0; int i = -1; u16 data; if (execute) - nv_info(bios, "running init tables\n"); + nvkm_debug(subdev, "running init tables\n"); while (!ret && (data = (init_script(bios, ++i)))) { struct nvbios_init init = { .subdev = subdev, diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c index c4087df4f..3ddf0939d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c @@ -28,17 +28,18 @@ u16 mxm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr) { + struct nvkm_subdev *subdev = &bios->subdev; struct bit_entry x; if (bit_entry(bios, 'x', &x)) { - nv_debug(bios, "BIT 'x' table not present\n"); + nvkm_debug(subdev, "BIT 'x' table not present\n"); return 0x0000; } *ver = x.version; *hdr = x.length; if (*ver != 1 || *hdr < 3) { - nv_warn(bios, "BIT 'x' table %d/%d unknown\n", *ver, *hdr); + nvkm_warn(subdev, "BIT 'x' table %d/%d unknown\n", *ver, *hdr); return 0x0000; } @@ -73,23 +74,24 @@ static u8 g98_sor_map[16] = { u8 mxm_sor_map(struct nvkm_bios *bios, u8 conn) { + struct nvkm_subdev *subdev = &bios->subdev; u8 ver, hdr; u16 mxm = mxm_table(bios, &ver, &hdr); if (mxm && hdr >= 6) { - u16 map = nv_ro16(bios, mxm + 4); + u16 map = nvbios_rd16(bios, mxm + 4); if (map) { - ver = nv_ro08(bios, map); + ver = nvbios_rd08(bios, map); if (ver == 0x10) { - if (conn < nv_ro08(bios, map + 3)) { - map += nv_ro08(bios, map + 1); + if (conn < nvbios_rd08(bios, map + 3)) { + map += nvbios_rd08(bios, map + 1); map += conn; - return nv_ro08(bios, map); + return nvbios_rd08(bios, map); } return 0x00; } - nv_warn(bios, "unknown sor map v%02x\n", ver); + nvkm_warn(subdev, "unknown sor map v%02x\n", ver); } } @@ -102,30 +104,31 @@ mxm_sor_map(struct nvkm_bios *bios, u8 conn) if (bios->version.chip == 0x98) return g98_sor_map[conn]; - nv_warn(bios, "missing sor map\n"); + nvkm_warn(subdev, "missing sor map\n"); return 0x00; } u8 mxm_ddc_map(struct nvkm_bios *bios, u8 port) { + struct nvkm_subdev *subdev = &bios->subdev; u8 ver, hdr; u16 mxm = mxm_table(bios, &ver, &hdr); if (mxm && hdr >= 8) { - u16 map = nv_ro16(bios, mxm + 6); + u16 map = nvbios_rd16(bios, mxm + 6); if (map) { - ver = nv_ro08(bios, map); + ver = nvbios_rd08(bios, map); if (ver == 0x10) { - if (port < nv_ro08(bios, map + 3)) { - map += nv_ro08(bios, map + 1); + if (port < nvbios_rd08(bios, map + 3)) { + map += nvbios_rd08(bios, map + 1); map += port; - return nv_ro08(bios, map); + return nvbios_rd08(bios, map); } return 0x00; } - nv_warn(bios, "unknown ddc map v%02x\n", ver); + nvkm_warn(subdev, "unknown ddc map v%02x\n", ver); } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/npde.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/npde.c index fd7dd718b..955df2963 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/npde.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/npde.c @@ -32,12 +32,13 @@ nvbios_npdeTe(struct nvkm_bios *bios, u32 base) u8 ver; u16 hdr; u32 data = nvbios_pcirTp(bios, base, &ver, &hdr, &pcir); if (data = (data + hdr + 0x0f) & ~0x0f, data) { - switch (nv_ro32(bios, data + 0x00)) { + switch (nvbios_rd32(bios, data + 0x00)) { case 0x4544504e: /* NPDE */ break; default: - nv_debug(bios, "%08x: NPDE signature (%08x) unknown\n", - data, nv_ro32(bios, data + 0x00)); + nvkm_debug(&bios->subdev, + "%08x: NPDE signature (%08x) unknown\n", + data, nvbios_rd32(bios, data + 0x00)); data = 0; break; } @@ -51,8 +52,8 @@ nvbios_npdeTp(struct nvkm_bios *bios, u32 base, struct nvbios_npdeT *info) u32 data = nvbios_npdeTe(bios, base); memset(info, 0x00, sizeof(*info)); if (data) { - info->image_size = nv_ro16(bios, data + 0x08) * 512; - info->last = nv_ro08(bios, data + 0x0a) & 0x80; + info->image_size = nvbios_rd16(bios, data + 0x08) * 512; + info->last = nvbios_rd08(bios, data + 0x0a) & 0x80; } return data; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pcir.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pcir.c index df5978753..67cb3aeb2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pcir.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pcir.c @@ -27,19 +27,20 @@ u32 nvbios_pcirTe(struct nvkm_bios *bios, u32 base, u8 *ver, u16 *hdr) { - u32 data = nv_ro16(bios, base + 0x18); + u32 data = nvbios_rd16(bios, base + 0x18); if (data) { data += base; - switch (nv_ro32(bios, data + 0x00)) { + switch (nvbios_rd32(bios, data + 0x00)) { case 0x52494350: /* PCIR */ case 0x53494752: /* RGIS */ case 0x5344504e: /* NPDS */ - *hdr = nv_ro16(bios, data + 0x0a); - *ver = nv_ro08(bios, data + 0x0c); + *hdr = nvbios_rd16(bios, data + 0x0a); + *ver = nvbios_rd08(bios, data + 0x0c); break; default: - nv_debug(bios, "%08x: PCIR signature (%08x) unknown\n", - data, nv_ro32(bios, data + 0x00)); + nvkm_debug(&bios->subdev, + "%08x: PCIR signature (%08x) unknown\n", + data, nvbios_rd32(bios, data + 0x00)); data = 0; break; } @@ -54,15 +55,15 @@ nvbios_pcirTp(struct nvkm_bios *bios, u32 base, u8 *ver, u16 *hdr, u32 data = nvbios_pcirTe(bios, base, ver, hdr); memset(info, 0x00, sizeof(*info)); if (data) { - info->vendor_id = nv_ro16(bios, data + 0x04); - info->device_id = nv_ro16(bios, data + 0x06); - info->class_code[0] = nv_ro08(bios, data + 0x0d); - info->class_code[1] = nv_ro08(bios, data + 0x0e); - info->class_code[2] = nv_ro08(bios, data + 0x0f); - info->image_size = nv_ro16(bios, data + 0x10) * 512; - info->image_rev = nv_ro16(bios, data + 0x12); - info->image_type = nv_ro08(bios, data + 0x14); - info->last = nv_ro08(bios, data + 0x15) & 0x80; + info->vendor_id = nvbios_rd16(bios, data + 0x04); + info->device_id = nvbios_rd16(bios, data + 0x06); + info->class_code[0] = nvbios_rd08(bios, data + 0x0d); + info->class_code[1] = nvbios_rd08(bios, data + 0x0e); + info->class_code[2] = nvbios_rd08(bios, data + 0x0f); + info->image_size = nvbios_rd16(bios, data + 0x10) * 512; + info->image_rev = nvbios_rd16(bios, data + 0x12); + info->image_type = nvbios_rd08(bios, data + 0x14); + info->last = nvbios_rd08(bios, data + 0x15) & 0x80; } return data; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c index 382ae9cdb..aa7e33b42 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c @@ -25,8 +25,6 @@ #include #include -#include - u16 nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz) @@ -36,22 +34,22 @@ nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version <= 2) { - perf = nv_ro16(bios, bit_P.offset + 0); + perf = nvbios_rd16(bios, bit_P.offset + 0); if (perf) { - *ver = nv_ro08(bios, perf + 0); - *hdr = nv_ro08(bios, perf + 1); + *ver = nvbios_rd08(bios, perf + 0); + *hdr = nvbios_rd08(bios, perf + 1); if (*ver >= 0x40 && *ver < 0x41) { - *cnt = nv_ro08(bios, perf + 5); - *len = nv_ro08(bios, perf + 2); - *snr = nv_ro08(bios, perf + 4); - *ssz = nv_ro08(bios, perf + 3); + *cnt = nvbios_rd08(bios, perf + 5); + *len = nvbios_rd08(bios, perf + 2); + *snr = nvbios_rd08(bios, perf + 4); + *ssz = nvbios_rd08(bios, perf + 3); return perf; } else if (*ver >= 0x20 && *ver < 0x40) { - *cnt = nv_ro08(bios, perf + 2); - *len = nv_ro08(bios, perf + 3); - *snr = nv_ro08(bios, perf + 4); - *ssz = nv_ro08(bios, perf + 5); + *cnt = nvbios_rd08(bios, perf + 2); + *len = nvbios_rd08(bios, perf + 3); + *snr = nvbios_rd08(bios, perf + 4); + *ssz = nvbios_rd08(bios, perf + 5); return perf; } } @@ -59,13 +57,13 @@ nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, } if (bios->bmp_offset) { - if (nv_ro08(bios, bios->bmp_offset + 6) >= 0x25) { - perf = nv_ro16(bios, bios->bmp_offset + 0x94); + if (nvbios_rd08(bios, bios->bmp_offset + 6) >= 0x25) { + perf = nvbios_rd16(bios, bios->bmp_offset + 0x94); if (perf) { - *hdr = nv_ro08(bios, perf + 0); - *ver = nv_ro08(bios, perf + 1); - *cnt = nv_ro08(bios, perf + 2); - *len = nv_ro08(bios, perf + 3); + *hdr = nvbios_rd08(bios, perf + 0); + *ver = nvbios_rd08(bios, perf + 1); + *cnt = nvbios_rd08(bios, perf + 2); + *len = nvbios_rd08(bios, perf + 3); *snr = 0; *ssz = 0; return perf; @@ -98,55 +96,55 @@ nvbios_perfEp(struct nvkm_bios *bios, int idx, { u16 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len); memset(info, 0x00, sizeof(*info)); - info->pstate = nv_ro08(bios, perf + 0x00); + info->pstate = nvbios_rd08(bios, perf + 0x00); switch (!!perf * *ver) { case 0x12: case 0x13: case 0x14: - info->core = nv_ro32(bios, perf + 0x01) * 10; - info->memory = nv_ro32(bios, perf + 0x05) * 20; - info->fanspeed = nv_ro08(bios, perf + 0x37); + info->core = nvbios_rd32(bios, perf + 0x01) * 10; + info->memory = nvbios_rd32(bios, perf + 0x05) * 20; + info->fanspeed = nvbios_rd08(bios, perf + 0x37); if (*hdr > 0x38) - info->voltage = nv_ro08(bios, perf + 0x38); + info->voltage = nvbios_rd08(bios, perf + 0x38); break; case 0x21: case 0x23: case 0x24: - info->fanspeed = nv_ro08(bios, perf + 0x04); - info->voltage = nv_ro08(bios, perf + 0x05); - info->shader = nv_ro16(bios, perf + 0x06) * 1000; + info->fanspeed = nvbios_rd08(bios, perf + 0x04); + info->voltage = nvbios_rd08(bios, perf + 0x05); + info->shader = nvbios_rd16(bios, perf + 0x06) * 1000; info->core = info->shader + (signed char) - nv_ro08(bios, perf + 0x08) * 1000; - switch (nv_device(bios)->chipset) { + nvbios_rd08(bios, perf + 0x08) * 1000; + switch (bios->subdev.device->chipset) { case 0x49: case 0x4b: - info->memory = nv_ro16(bios, perf + 0x0b) * 1000; + info->memory = nvbios_rd16(bios, perf + 0x0b) * 1000; break; default: - info->memory = nv_ro16(bios, perf + 0x0b) * 2000; + info->memory = nvbios_rd16(bios, perf + 0x0b) * 2000; break; } break; case 0x25: - info->fanspeed = nv_ro08(bios, perf + 0x04); - info->voltage = nv_ro08(bios, perf + 0x05); - info->core = nv_ro16(bios, perf + 0x06) * 1000; - info->shader = nv_ro16(bios, perf + 0x0a) * 1000; - info->memory = nv_ro16(bios, perf + 0x0c) * 1000; + info->fanspeed = nvbios_rd08(bios, perf + 0x04); + info->voltage = nvbios_rd08(bios, perf + 0x05); + info->core = nvbios_rd16(bios, perf + 0x06) * 1000; + info->shader = nvbios_rd16(bios, perf + 0x0a) * 1000; + info->memory = nvbios_rd16(bios, perf + 0x0c) * 1000; break; case 0x30: - info->script = nv_ro16(bios, perf + 0x02); + info->script = nvbios_rd16(bios, perf + 0x02); case 0x35: - info->fanspeed = nv_ro08(bios, perf + 0x06); - info->voltage = nv_ro08(bios, perf + 0x07); - info->core = nv_ro16(bios, perf + 0x08) * 1000; - info->shader = nv_ro16(bios, perf + 0x0a) * 1000; - info->memory = nv_ro16(bios, perf + 0x0c) * 1000; - info->vdec = nv_ro16(bios, perf + 0x10) * 1000; - info->disp = nv_ro16(bios, perf + 0x14) * 1000; + info->fanspeed = nvbios_rd08(bios, perf + 0x06); + info->voltage = nvbios_rd08(bios, perf + 0x07); + info->core = nvbios_rd16(bios, perf + 0x08) * 1000; + info->shader = nvbios_rd16(bios, perf + 0x0a) * 1000; + info->memory = nvbios_rd16(bios, perf + 0x0c) * 1000; + info->vdec = nvbios_rd16(bios, perf + 0x10) * 1000; + info->disp = nvbios_rd16(bios, perf + 0x14) * 1000; break; case 0x40: - info->voltage = nv_ro08(bios, perf + 0x02); + info->voltage = nvbios_rd08(bios, perf + 0x02); break; default: return 0x0000; @@ -175,7 +173,7 @@ nvbios_perfSp(struct nvkm_bios *bios, u32 perfE, int idx, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { case 0x40: - info->v40.freq = (nv_ro16(bios, data + 0x00) & 0x3fff) * 1000; + info->v40.freq = (nvbios_rd16(bios, data + 0x00) & 0x3fff) * 1000; break; default: break; @@ -193,7 +191,7 @@ nvbios_perf_fan_parse(struct nvkm_bios *bios, return -ENODEV; if (ver >= 0x20 && ver < 0x40 && hdr > 6) - fan->pwm_divisor = nv_ro16(bios, perf + 6); + fan->pwm_divisor = nvbios_rd16(bios, perf + 6); else fan->pwm_divisor = 0; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c index ebd402e19..125ec2ed6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c @@ -27,7 +27,6 @@ #include #include -#include struct pll_mapping { u8 type; @@ -84,20 +83,20 @@ pll_limits_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) struct bit_entry bit_C; if (!bit_entry(bios, 'C', &bit_C) && bit_C.length >= 10) { - u16 data = nv_ro16(bios, bit_C.offset + 8); + u16 data = nvbios_rd16(bios, bit_C.offset + 8); if (data) { - *ver = nv_ro08(bios, data + 0); - *hdr = nv_ro08(bios, data + 1); - *len = nv_ro08(bios, data + 2); - *cnt = nv_ro08(bios, data + 3); + *ver = nvbios_rd08(bios, data + 0); + *hdr = nvbios_rd08(bios, data + 1); + *len = nvbios_rd08(bios, data + 2); + *cnt = nvbios_rd08(bios, data + 3); return data; } } if (bmp_version(bios) >= 0x0524) { - u16 data = nv_ro16(bios, bios->bmp_offset + 142); + u16 data = nvbios_rd16(bios, bios->bmp_offset + 142); if (data) { - *ver = nv_ro08(bios, data + 0); + *ver = nvbios_rd08(bios, data + 0); *hdr = 1; *cnt = 1; *len = 0x18; @@ -112,7 +111,8 @@ pll_limits_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) static struct pll_mapping * pll_map(struct nvkm_bios *bios) { - switch (nv_device(bios)->card_type) { + struct nvkm_device *device = bios->subdev.device; + switch (device->card_type) { case NV_04: case NV_10: case NV_11: @@ -123,12 +123,12 @@ pll_map(struct nvkm_bios *bios) case NV_40: return nv40_pll_mapping; case NV_50: - if (nv_device(bios)->chipset == 0x50) + if (device->chipset == 0x50) return nv50_pll_mapping; else - if (nv_device(bios)->chipset < 0xa3 || - nv_device(bios)->chipset == 0xaa || - nv_device(bios)->chipset == 0xac) + if (device->chipset < 0xa3 || + device->chipset == 0xaa || + device->chipset == 0xac) return g84_pll_mapping; default: return NULL; @@ -146,8 +146,8 @@ pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) if (data && *ver >= 0x30) { data += hdr; while (cnt--) { - if (nv_ro32(bios, data + 3) == reg) { - *type = nv_ro08(bios, data + 0); + if (nvbios_rd32(bios, data + 3) == reg) { + *type = nvbios_rd08(bios, data + 0); return data; } data += *len; @@ -161,7 +161,7 @@ pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) u16 addr = (data += hdr); *type = map->type; while (cnt--) { - if (nv_ro32(bios, data) == map->reg) + if (nvbios_rd32(bios, data) == map->reg) return data; data += *len; } @@ -188,8 +188,8 @@ pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) if (data && *ver >= 0x30) { data += hdr; while (cnt--) { - if (nv_ro08(bios, data + 0) == type) { - *reg = nv_ro32(bios, data + 3); + if (nvbios_rd08(bios, data + 0) == type) { + *reg = nvbios_rd32(bios, data + 3); return data; } data += *len; @@ -203,7 +203,7 @@ pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) u16 addr = (data += hdr); *reg = map->reg; while (cnt--) { - if (nv_ro32(bios, data) == map->reg) + if (nvbios_rd32(bios, data) == map->reg) return data; data += *len; } @@ -222,6 +222,8 @@ pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) int nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info) { + struct nvkm_subdev *subdev = &bios->subdev; + struct nvkm_device *device = subdev->device; u8 ver, len; u32 reg = type; u16 data; @@ -245,12 +247,12 @@ nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info) break; case 0x10: case 0x11: - info->vco1.min_freq = nv_ro32(bios, data + 0); - info->vco1.max_freq = nv_ro32(bios, data + 4); - info->vco2.min_freq = nv_ro32(bios, data + 8); - info->vco2.max_freq = nv_ro32(bios, data + 12); - info->vco1.min_inputfreq = nv_ro32(bios, data + 16); - info->vco2.min_inputfreq = nv_ro32(bios, data + 20); + info->vco1.min_freq = nvbios_rd32(bios, data + 0); + info->vco1.max_freq = nvbios_rd32(bios, data + 4); + info->vco2.min_freq = nvbios_rd32(bios, data + 8); + info->vco2.max_freq = nvbios_rd32(bios, data + 12); + info->vco1.min_inputfreq = nvbios_rd32(bios, data + 16); + info->vco2.min_inputfreq = nvbios_rd32(bios, data + 20); info->vco1.max_inputfreq = INT_MAX; info->vco2.max_inputfreq = INT_MAX; @@ -291,82 +293,82 @@ nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info) break; case 0x20: case 0x21: - info->vco1.min_freq = nv_ro16(bios, data + 4) * 1000; - info->vco1.max_freq = nv_ro16(bios, data + 6) * 1000; - info->vco2.min_freq = nv_ro16(bios, data + 8) * 1000; - info->vco2.max_freq = nv_ro16(bios, data + 10) * 1000; - info->vco1.min_inputfreq = nv_ro16(bios, data + 12) * 1000; - info->vco2.min_inputfreq = nv_ro16(bios, data + 14) * 1000; - info->vco1.max_inputfreq = nv_ro16(bios, data + 16) * 1000; - info->vco2.max_inputfreq = nv_ro16(bios, data + 18) * 1000; - info->vco1.min_n = nv_ro08(bios, data + 20); - info->vco1.max_n = nv_ro08(bios, data + 21); - info->vco1.min_m = nv_ro08(bios, data + 22); - info->vco1.max_m = nv_ro08(bios, data + 23); - info->vco2.min_n = nv_ro08(bios, data + 24); - info->vco2.max_n = nv_ro08(bios, data + 25); - info->vco2.min_m = nv_ro08(bios, data + 26); - info->vco2.max_m = nv_ro08(bios, data + 27); - - info->max_p = nv_ro08(bios, data + 29); + info->vco1.min_freq = nvbios_rd16(bios, data + 4) * 1000; + info->vco1.max_freq = nvbios_rd16(bios, data + 6) * 1000; + info->vco2.min_freq = nvbios_rd16(bios, data + 8) * 1000; + info->vco2.max_freq = nvbios_rd16(bios, data + 10) * 1000; + info->vco1.min_inputfreq = nvbios_rd16(bios, data + 12) * 1000; + info->vco2.min_inputfreq = nvbios_rd16(bios, data + 14) * 1000; + info->vco1.max_inputfreq = nvbios_rd16(bios, data + 16) * 1000; + info->vco2.max_inputfreq = nvbios_rd16(bios, data + 18) * 1000; + info->vco1.min_n = nvbios_rd08(bios, data + 20); + info->vco1.max_n = nvbios_rd08(bios, data + 21); + info->vco1.min_m = nvbios_rd08(bios, data + 22); + info->vco1.max_m = nvbios_rd08(bios, data + 23); + info->vco2.min_n = nvbios_rd08(bios, data + 24); + info->vco2.max_n = nvbios_rd08(bios, data + 25); + info->vco2.min_m = nvbios_rd08(bios, data + 26); + info->vco2.max_m = nvbios_rd08(bios, data + 27); + + info->max_p = nvbios_rd08(bios, data + 29); info->max_p_usable = info->max_p; if (bios->version.chip < 0x60) info->max_p_usable = 0x6; - info->bias_p = nv_ro08(bios, data + 30); + info->bias_p = nvbios_rd08(bios, data + 30); if (len > 0x22) - info->refclk = nv_ro32(bios, data + 31); + info->refclk = nvbios_rd32(bios, data + 31); break; case 0x30: - data = nv_ro16(bios, data + 1); - - info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; - info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; - info->vco2.min_freq = nv_ro16(bios, data + 4) * 1000; - info->vco2.max_freq = nv_ro16(bios, data + 6) * 1000; - info->vco1.min_inputfreq = nv_ro16(bios, data + 8) * 1000; - info->vco2.min_inputfreq = nv_ro16(bios, data + 10) * 1000; - info->vco1.max_inputfreq = nv_ro16(bios, data + 12) * 1000; - info->vco2.max_inputfreq = nv_ro16(bios, data + 14) * 1000; - info->vco1.min_n = nv_ro08(bios, data + 16); - info->vco1.max_n = nv_ro08(bios, data + 17); - info->vco1.min_m = nv_ro08(bios, data + 18); - info->vco1.max_m = nv_ro08(bios, data + 19); - info->vco2.min_n = nv_ro08(bios, data + 20); - info->vco2.max_n = nv_ro08(bios, data + 21); - info->vco2.min_m = nv_ro08(bios, data + 22); - info->vco2.max_m = nv_ro08(bios, data + 23); - info->max_p_usable = info->max_p = nv_ro08(bios, data + 25); - info->bias_p = nv_ro08(bios, data + 27); - info->refclk = nv_ro32(bios, data + 28); + data = nvbios_rd16(bios, data + 1); + + info->vco1.min_freq = nvbios_rd16(bios, data + 0) * 1000; + info->vco1.max_freq = nvbios_rd16(bios, data + 2) * 1000; + info->vco2.min_freq = nvbios_rd16(bios, data + 4) * 1000; + info->vco2.max_freq = nvbios_rd16(bios, data + 6) * 1000; + info->vco1.min_inputfreq = nvbios_rd16(bios, data + 8) * 1000; + info->vco2.min_inputfreq = nvbios_rd16(bios, data + 10) * 1000; + info->vco1.max_inputfreq = nvbios_rd16(bios, data + 12) * 1000; + info->vco2.max_inputfreq = nvbios_rd16(bios, data + 14) * 1000; + info->vco1.min_n = nvbios_rd08(bios, data + 16); + info->vco1.max_n = nvbios_rd08(bios, data + 17); + info->vco1.min_m = nvbios_rd08(bios, data + 18); + info->vco1.max_m = nvbios_rd08(bios, data + 19); + info->vco2.min_n = nvbios_rd08(bios, data + 20); + info->vco2.max_n = nvbios_rd08(bios, data + 21); + info->vco2.min_m = nvbios_rd08(bios, data + 22); + info->vco2.max_m = nvbios_rd08(bios, data + 23); + info->max_p_usable = info->max_p = nvbios_rd08(bios, data + 25); + info->bias_p = nvbios_rd08(bios, data + 27); + info->refclk = nvbios_rd32(bios, data + 28); break; case 0x40: - info->refclk = nv_ro16(bios, data + 9) * 1000; - data = nv_ro16(bios, data + 1); - - info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; - info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; - info->vco1.min_inputfreq = nv_ro16(bios, data + 4) * 1000; - info->vco1.max_inputfreq = nv_ro16(bios, data + 6) * 1000; - info->vco1.min_m = nv_ro08(bios, data + 8); - info->vco1.max_m = nv_ro08(bios, data + 9); - info->vco1.min_n = nv_ro08(bios, data + 10); - info->vco1.max_n = nv_ro08(bios, data + 11); - info->min_p = nv_ro08(bios, data + 12); - info->max_p = nv_ro08(bios, data + 13); + info->refclk = nvbios_rd16(bios, data + 9) * 1000; + data = nvbios_rd16(bios, data + 1); + + info->vco1.min_freq = nvbios_rd16(bios, data + 0) * 1000; + info->vco1.max_freq = nvbios_rd16(bios, data + 2) * 1000; + info->vco1.min_inputfreq = nvbios_rd16(bios, data + 4) * 1000; + info->vco1.max_inputfreq = nvbios_rd16(bios, data + 6) * 1000; + info->vco1.min_m = nvbios_rd08(bios, data + 8); + info->vco1.max_m = nvbios_rd08(bios, data + 9); + info->vco1.min_n = nvbios_rd08(bios, data + 10); + info->vco1.max_n = nvbios_rd08(bios, data + 11); + info->min_p = nvbios_rd08(bios, data + 12); + info->max_p = nvbios_rd08(bios, data + 13); break; default: - nv_error(bios, "unknown pll limits version 0x%02x\n", ver); + nvkm_error(subdev, "unknown pll limits version 0x%02x\n", ver); return -EINVAL; } if (!info->refclk) { - info->refclk = nv_device(bios)->crystal; + info->refclk = device->crystal; if (bios->version.chip == 0x51) { - u32 sel_clk = nv_rd32(bios, 0x680524); + u32 sel_clk = nvkm_rd32(device, 0x680524); if ((info->reg == 0x680508 && sel_clk & 0x20) || (info->reg == 0x680520 && sel_clk & 0x80)) { - if (nv_rdvgac(bios, 0, 0x27) < 0xa3) + if (nvkm_rdvgac(device, 0, 0x27) < 0xa3) info->refclk = 200000; else info->refclk = 25000; @@ -380,8 +382,8 @@ nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info) * with an empty limit table (seen on nv18) */ if (!info->vco1.max_freq) { - info->vco1.max_freq = nv_ro32(bios, bios->bmp_offset + 67); - info->vco1.min_freq = nv_ro32(bios, bios->bmp_offset + 71); + info->vco1.max_freq = nvbios_rd32(bios, bios->bmp_offset + 67); + info->vco1.min_freq = nvbios_rd32(bios, bios->bmp_offset + 71); if (bmp_version(bios) < 0x0506) { info->vco1.max_freq = 256000; info->vco1.min_freq = 128000; @@ -393,7 +395,7 @@ nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info) info->vco1.max_n = 0xff; info->vco1.min_m = 0x1; - if (nv_device(bios)->crystal == 13500) { + if (device->crystal == 13500) { /* nv05 does this, nv11 doesn't, nv10 unknown */ if (bios->version.chip < 0x11) info->vco1.min_m = 0x7; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c index 20c5ce0cd..c268e5afe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c @@ -49,31 +49,18 @@ nvbios_pmuTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'p', &bit_p)) { if (bit_p.version == 2 && bit_p.length >= 4) - data = nv_ro32(bios, bit_p.offset + 0x00); + data = nvbios_rd32(bios, bit_p.offset + 0x00); if ((data = weirdo_pointer(bios, data))) { - *ver = nv_ro08(bios, data + 0x00); /* maybe? */ - *hdr = nv_ro08(bios, data + 0x01); - *len = nv_ro08(bios, data + 0x02); - *cnt = nv_ro08(bios, data + 0x03); + *ver = nvbios_rd08(bios, data + 0x00); /* maybe? */ + *hdr = nvbios_rd08(bios, data + 0x01); + *len = nvbios_rd08(bios, data + 0x02); + *cnt = nvbios_rd08(bios, data + 0x03); } } return data; } -u32 -nvbios_pmuTp(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, - struct nvbios_pmuT *info) -{ - u32 data = nvbios_pmuTe(bios, ver, hdr, cnt, len); - memset(info, 0x00, sizeof(*info)); - switch (!!data * *ver) { - default: - break; - } - return data; -} - u32 nvbios_pmuEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr) { @@ -95,8 +82,8 @@ nvbios_pmuEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, memset(info, 0x00, sizeof(*info)); switch (!!data * *ver) { default: - info->type = nv_ro08(bios, data + 0x00); - info->data = nv_ro32(bios, data + 0x02); + info->type = nvbios_rd08(bios, data + 0x00); + info->data = nvbios_rd32(bios, data + 0x02); break; } return data; @@ -112,21 +99,21 @@ nvbios_pmuRm(struct nvkm_bios *bios, u8 type, struct nvbios_pmuR *info) while ((data = nvbios_pmuEp(bios, idx++, &ver, &hdr, &pmuE))) { if ( pmuE.type == type && (data = weirdo_pointer(bios, pmuE.data))) { - info->init_addr_pmu = nv_ro32(bios, data + 0x08); - info->args_addr_pmu = nv_ro32(bios, data + 0x0c); + info->init_addr_pmu = nvbios_rd32(bios, data + 0x08); + info->args_addr_pmu = nvbios_rd32(bios, data + 0x0c); info->boot_addr = data + 0x30; - info->boot_addr_pmu = nv_ro32(bios, data + 0x10) + - nv_ro32(bios, data + 0x18); - info->boot_size = nv_ro32(bios, data + 0x1c) - - nv_ro32(bios, data + 0x18); + info->boot_addr_pmu = nvbios_rd32(bios, data + 0x10) + + nvbios_rd32(bios, data + 0x18); + info->boot_size = nvbios_rd32(bios, data + 0x1c) - + nvbios_rd32(bios, data + 0x18); info->code_addr = info->boot_addr + info->boot_size; info->code_addr_pmu = info->boot_addr_pmu + info->boot_size; - info->code_size = nv_ro32(bios, data + 0x20); + info->code_size = nvbios_rd32(bios, data + 0x20); info->data_addr = data + 0x30 + - nv_ro32(bios, data + 0x24); - info->data_addr_pmu = nv_ro32(bios, data + 0x28); - info->data_size = nv_ro32(bios, data + 0x2c); + nvbios_rd32(bios, data + 0x24); + info->data_addr_pmu = nvbios_rd32(bios, data + 0x28); + info->data_size = nvbios_rd32(bios, data + 0x2c); return true; } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h index 95e4fa153..212800ecd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h @@ -1,5 +1,6 @@ #ifndef __NVKM_BIOS_PRIV_H__ #define __NVKM_BIOS_PRIV_H__ +#define nvkm_bios(p) container_of((p), struct nvkm_bios, subdev) #include struct nvbios_source { @@ -7,7 +8,10 @@ struct nvbios_source { void *(*init)(struct nvkm_bios *, const char *); void (*fini)(void *); u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *); + u32 (*size)(void *); bool rw; + bool ignore_checksum; + bool no_pcir; }; int nvbios_extend(struct nvkm_bios *, u32 length); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/ramcfg.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/ramcfg.c index a17b22111..d5222af10 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/ramcfg.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/ramcfg.c @@ -29,7 +29,7 @@ static u8 nvbios_ramcfg_strap(struct nvkm_subdev *subdev) { - return (nv_rd32(subdev, 0x101000) & 0x0000003c) >> 2; + return (nvkm_rd32(subdev->device, 0x101000) & 0x0000003c) >> 2; } u8 @@ -39,9 +39,9 @@ nvbios_ramcfg_count(struct nvkm_bios *bios) if (!bit_entry(bios, 'M', &bit_M)) { if (bit_M.version == 1 && bit_M.length >= 5) - return nv_ro08(bios, bit_M.offset + 2); + return nvbios_rd08(bios, bit_M.offset + 2); if (bit_M.version == 2 && bit_M.length >= 3) - return nv_ro08(bios, bit_M.offset + 0); + return nvbios_rd08(bios, bit_M.offset + 0); } return 0x00; @@ -50,7 +50,7 @@ nvbios_ramcfg_count(struct nvkm_bios *bios) u8 nvbios_ramcfg_index(struct nvkm_subdev *subdev) { - struct nvkm_bios *bios = nvkm_bios(subdev); + struct nvkm_bios *bios = subdev->device->bios; u8 strap = nvbios_ramcfg_strap(subdev); u32 xlat = 0x00000000; struct bit_entry bit_M; @@ -59,7 +59,7 @@ nvbios_ramcfg_index(struct nvkm_subdev *subdev) if (!bit_entry(bios, 'M', &bit_M)) { if (bit_M.version == 1 && bit_M.length >= 5) - xlat = nv_ro16(bios, bit_M.offset + 3); + xlat = nvbios_rd16(bios, bit_M.offset + 3); if (bit_M.version == 2 && bit_M.length >= 3) { /*XXX: is M ever shorter than this? * if not - what is xlat used for now? @@ -68,11 +68,11 @@ nvbios_ramcfg_index(struct nvkm_subdev *subdev) if (bit_M.length >= 7 && nvbios_M0203Em(bios, strap, &ver, &hdr, &M0203E)) return M0203E.group; - xlat = nv_ro16(bios, bit_M.offset + 1); + xlat = nvbios_rd16(bios, bit_M.offset + 1); } } if (xlat) - strap = nv_ro08(bios, xlat + strap); + strap = nvbios_rd08(bios, xlat + strap); return strap; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index 8b17bb4b2..d0ae74547 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c @@ -34,18 +34,18 @@ nvbios_rammapTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2) - rammap = nv_ro16(bios, bit_P.offset + 4); + rammap = nvbios_rd16(bios, bit_P.offset + 4); if (rammap) { - *ver = nv_ro08(bios, rammap + 0); + *ver = nvbios_rd08(bios, rammap + 0); switch (*ver) { case 0x10: case 0x11: - *hdr = nv_ro08(bios, rammap + 1); - *cnt = nv_ro08(bios, rammap + 5); - *len = nv_ro08(bios, rammap + 2); - *snr = nv_ro08(bios, rammap + 4); - *ssz = nv_ro08(bios, rammap + 3); + *hdr = nvbios_rd08(bios, rammap + 1); + *cnt = nvbios_rd08(bios, rammap + 5); + *len = nvbios_rd08(bios, rammap + 2); + *snr = nvbios_rd08(bios, rammap + 4); + *ssz = nvbios_rd08(bios, rammap + 3); return rammap; default: break; @@ -72,6 +72,21 @@ nvbios_rammapEe(struct nvkm_bios *bios, int idx, return 0x0000; } +/* Pretend a performance mode is also a rammap entry, helps coalesce entries + * later on */ +u32 +nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, + struct nvbios_ramcfg *p) +{ + memset(p, 0x00, sizeof(*p)); + + p->rammap_00_16_20 = (nvbios_rd08(bios, data + 0x16) & 0x20) >> 5; + p->rammap_00_16_40 = (nvbios_rd08(bios, data + 0x16) & 0x40) >> 6; + p->rammap_00_17_02 = (nvbios_rd08(bios, data + 0x17) & 0x02) >> 1; + + return data; +} + u32 nvbios_rammapEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *p) @@ -82,18 +97,18 @@ nvbios_rammapEp(struct nvkm_bios *bios, int idx, p->rammap_hdr = *hdr; switch (!!data * *ver) { case 0x10: - p->rammap_min = nv_ro16(bios, data + 0x00); - p->rammap_max = nv_ro16(bios, data + 0x02); - p->rammap_10_04_02 = (nv_ro08(bios, data + 0x04) & 0x02) >> 1; - p->rammap_10_04_08 = (nv_ro08(bios, data + 0x04) & 0x08) >> 3; + p->rammap_min = nvbios_rd16(bios, data + 0x00); + p->rammap_max = nvbios_rd16(bios, data + 0x02); + p->rammap_10_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1; + p->rammap_10_04_08 = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3; break; case 0x11: - p->rammap_min = nv_ro16(bios, data + 0x00); - p->rammap_max = nv_ro16(bios, data + 0x02); - p->rammap_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0; - p->rammap_11_08_0c = (nv_ro08(bios, data + 0x08) & 0x0c) >> 2; - p->rammap_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4; - temp = nv_ro32(bios, data + 0x09); + p->rammap_min = nvbios_rd16(bios, data + 0x00); + p->rammap_max = nvbios_rd16(bios, data + 0x02); + p->rammap_11_08_01 = (nvbios_rd08(bios, data + 0x08) & 0x01) >> 0; + p->rammap_11_08_0c = (nvbios_rd08(bios, data + 0x08) & 0x0c) >> 2; + p->rammap_11_08_10 = (nvbios_rd08(bios, data + 0x08) & 0x10) >> 4; + temp = nvbios_rd32(bios, data + 0x09); p->rammap_11_09_01ff = (temp & 0x000001ff) >> 0; p->rammap_11_0a_03fe = (temp & 0x0003fe00) >> 9; p->rammap_11_0a_0400 = (temp & 0x00040000) >> 18; @@ -102,10 +117,10 @@ nvbios_rammapEp(struct nvkm_bios *bios, int idx, p->rammap_11_0b_0200 = (temp & 0x02000000) >> 25; p->rammap_11_0b_0400 = (temp & 0x04000000) >> 26; p->rammap_11_0b_0800 = (temp & 0x08000000) >> 27; - p->rammap_11_0d = nv_ro08(bios, data + 0x0d); - p->rammap_11_0e = nv_ro08(bios, data + 0x0e); - p->rammap_11_0f = nv_ro08(bios, data + 0x0f); - p->rammap_11_11_0c = (nv_ro08(bios, data + 0x11) & 0x0c) >> 2; + p->rammap_11_0d = nvbios_rd08(bios, data + 0x0d); + p->rammap_11_0e = nvbios_rd08(bios, data + 0x0e); + p->rammap_11_0f = nvbios_rd08(bios, data + 0x0f); + p->rammap_11_11_0c = (nvbios_rd08(bios, data + 0x11) & 0x0c) >> 2; break; default: data = 0; @@ -140,6 +155,37 @@ nvbios_rammapSe(struct nvkm_bios *bios, u32 data, return 0; } +u32 +nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, + struct nvbios_ramcfg *p) +{ + data += (idx * size); + + if (size < 11) + return 0x00000000; + + p->ramcfg_ver = 0; + p->ramcfg_timing = nvbios_rd08(bios, data + 0x01); + p->ramcfg_00_03_01 = (nvbios_rd08(bios, data + 0x03) & 0x01) >> 0; + p->ramcfg_00_03_02 = (nvbios_rd08(bios, data + 0x03) & 0x02) >> 1; + p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x03) & 0x04) >> 2; + p->ramcfg_00_03_08 = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3; + p->ramcfg_RON = (nvbios_rd08(bios, data + 0x03) & 0x10) >> 3; + p->ramcfg_FBVDDQ = (nvbios_rd08(bios, data + 0x03) & 0x80) >> 7; + p->ramcfg_00_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1; + p->ramcfg_00_04_04 = (nvbios_rd08(bios, data + 0x04) & 0x04) >> 2; + p->ramcfg_00_04_20 = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5; + p->ramcfg_00_05 = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0; + p->ramcfg_00_06 = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0; + p->ramcfg_00_07 = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0; + p->ramcfg_00_08 = (nvbios_rd08(bios, data + 0x08) & 0xff) >> 0; + p->ramcfg_00_09 = (nvbios_rd08(bios, data + 0x09) & 0xff) >> 0; + p->ramcfg_00_0a_0f = (nvbios_rd08(bios, data + 0x0a) & 0x0f) >> 0; + p->ramcfg_00_0a_f0 = (nvbios_rd08(bios, data + 0x0a) & 0xf0) >> 4; + + return data; +} + u32 nvbios_rammapSp(struct nvkm_bios *bios, u32 data, u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, @@ -150,58 +196,59 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data, p->ramcfg_hdr = *hdr; switch (!!data * *ver) { case 0x10: - p->ramcfg_timing = nv_ro08(bios, data + 0x01); - p->ramcfg_10_02_01 = (nv_ro08(bios, data + 0x02) & 0x01) >> 0; - p->ramcfg_10_02_02 = (nv_ro08(bios, data + 0x02) & 0x02) >> 1; - p->ramcfg_10_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2; - p->ramcfg_10_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3; - p->ramcfg_10_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4; - p->ramcfg_10_02_20 = (nv_ro08(bios, data + 0x02) & 0x20) >> 5; - p->ramcfg_10_DLLoff = (nv_ro08(bios, data + 0x02) & 0x40) >> 6; - p->ramcfg_10_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0; - p->ramcfg_10_04_01 = (nv_ro08(bios, data + 0x04) & 0x01) >> 0; - p->ramcfg_10_05 = (nv_ro08(bios, data + 0x05) & 0xff) >> 0; - p->ramcfg_10_06 = (nv_ro08(bios, data + 0x06) & 0xff) >> 0; - p->ramcfg_10_07 = (nv_ro08(bios, data + 0x07) & 0xff) >> 0; - p->ramcfg_10_08 = (nv_ro08(bios, data + 0x08) & 0xff) >> 0; - p->ramcfg_10_09_0f = (nv_ro08(bios, data + 0x09) & 0x0f) >> 0; - p->ramcfg_10_09_f0 = (nv_ro08(bios, data + 0x09) & 0xf0) >> 4; + p->ramcfg_timing = nvbios_rd08(bios, data + 0x01); + p->ramcfg_10_02_01 = (nvbios_rd08(bios, data + 0x02) & 0x01) >> 0; + p->ramcfg_10_02_02 = (nvbios_rd08(bios, data + 0x02) & 0x02) >> 1; + p->ramcfg_10_02_04 = (nvbios_rd08(bios, data + 0x02) & 0x04) >> 2; + p->ramcfg_10_02_08 = (nvbios_rd08(bios, data + 0x02) & 0x08) >> 3; + p->ramcfg_10_02_10 = (nvbios_rd08(bios, data + 0x02) & 0x10) >> 4; + p->ramcfg_10_02_20 = (nvbios_rd08(bios, data + 0x02) & 0x20) >> 5; + p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6; + p->ramcfg_10_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0; + p->ramcfg_10_04_01 = (nvbios_rd08(bios, data + 0x04) & 0x01) >> 0; + p->ramcfg_FBVDDQ = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3; + p->ramcfg_10_05 = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0; + p->ramcfg_10_06 = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0; + p->ramcfg_10_07 = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0; + p->ramcfg_10_08 = (nvbios_rd08(bios, data + 0x08) & 0xff) >> 0; + p->ramcfg_10_09_0f = (nvbios_rd08(bios, data + 0x09) & 0x0f) >> 0; + p->ramcfg_10_09_f0 = (nvbios_rd08(bios, data + 0x09) & 0xf0) >> 4; break; case 0x11: - p->ramcfg_timing = nv_ro08(bios, data + 0x00); - p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0; - p->ramcfg_11_01_02 = (nv_ro08(bios, data + 0x01) & 0x02) >> 1; - p->ramcfg_11_01_04 = (nv_ro08(bios, data + 0x01) & 0x04) >> 2; - p->ramcfg_11_01_08 = (nv_ro08(bios, data + 0x01) & 0x08) >> 3; - p->ramcfg_11_01_10 = (nv_ro08(bios, data + 0x01) & 0x10) >> 4; - p->ramcfg_11_01_20 = (nv_ro08(bios, data + 0x01) & 0x20) >> 5; - p->ramcfg_11_01_40 = (nv_ro08(bios, data + 0x01) & 0x40) >> 6; - p->ramcfg_11_01_80 = (nv_ro08(bios, data + 0x01) & 0x80) >> 7; - p->ramcfg_11_02_03 = (nv_ro08(bios, data + 0x02) & 0x03) >> 0; - p->ramcfg_11_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2; - p->ramcfg_11_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3; - p->ramcfg_11_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4; - p->ramcfg_11_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6; - p->ramcfg_11_02_80 = (nv_ro08(bios, data + 0x02) & 0x80) >> 7; - p->ramcfg_11_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0; - p->ramcfg_11_03_30 = (nv_ro08(bios, data + 0x03) & 0x30) >> 4; - p->ramcfg_11_03_c0 = (nv_ro08(bios, data + 0x03) & 0xc0) >> 6; - p->ramcfg_11_03_f0 = (nv_ro08(bios, data + 0x03) & 0xf0) >> 4; - p->ramcfg_11_04 = (nv_ro08(bios, data + 0x04) & 0xff) >> 0; - p->ramcfg_11_06 = (nv_ro08(bios, data + 0x06) & 0xff) >> 0; - p->ramcfg_11_07_02 = (nv_ro08(bios, data + 0x07) & 0x02) >> 1; - p->ramcfg_11_07_04 = (nv_ro08(bios, data + 0x07) & 0x04) >> 2; - p->ramcfg_11_07_08 = (nv_ro08(bios, data + 0x07) & 0x08) >> 3; - p->ramcfg_11_07_10 = (nv_ro08(bios, data + 0x07) & 0x10) >> 4; - p->ramcfg_11_07_40 = (nv_ro08(bios, data + 0x07) & 0x40) >> 6; - p->ramcfg_11_07_80 = (nv_ro08(bios, data + 0x07) & 0x80) >> 7; - p->ramcfg_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0; - p->ramcfg_11_08_02 = (nv_ro08(bios, data + 0x08) & 0x02) >> 1; - p->ramcfg_11_08_04 = (nv_ro08(bios, data + 0x08) & 0x04) >> 2; - p->ramcfg_11_08_08 = (nv_ro08(bios, data + 0x08) & 0x08) >> 3; - p->ramcfg_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4; - p->ramcfg_11_08_20 = (nv_ro08(bios, data + 0x08) & 0x20) >> 5; - p->ramcfg_11_09 = (nv_ro08(bios, data + 0x09) & 0xff) >> 0; + p->ramcfg_timing = nvbios_rd08(bios, data + 0x00); + p->ramcfg_11_01_01 = (nvbios_rd08(bios, data + 0x01) & 0x01) >> 0; + p->ramcfg_11_01_02 = (nvbios_rd08(bios, data + 0x01) & 0x02) >> 1; + p->ramcfg_11_01_04 = (nvbios_rd08(bios, data + 0x01) & 0x04) >> 2; + p->ramcfg_11_01_08 = (nvbios_rd08(bios, data + 0x01) & 0x08) >> 3; + p->ramcfg_11_01_10 = (nvbios_rd08(bios, data + 0x01) & 0x10) >> 4; + p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5; + p->ramcfg_11_01_40 = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6; + p->ramcfg_11_01_80 = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7; + p->ramcfg_11_02_03 = (nvbios_rd08(bios, data + 0x02) & 0x03) >> 0; + p->ramcfg_11_02_04 = (nvbios_rd08(bios, data + 0x02) & 0x04) >> 2; + p->ramcfg_11_02_08 = (nvbios_rd08(bios, data + 0x02) & 0x08) >> 3; + p->ramcfg_11_02_10 = (nvbios_rd08(bios, data + 0x02) & 0x10) >> 4; + p->ramcfg_11_02_40 = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6; + p->ramcfg_11_02_80 = (nvbios_rd08(bios, data + 0x02) & 0x80) >> 7; + p->ramcfg_11_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0; + p->ramcfg_11_03_30 = (nvbios_rd08(bios, data + 0x03) & 0x30) >> 4; + p->ramcfg_11_03_c0 = (nvbios_rd08(bios, data + 0x03) & 0xc0) >> 6; + p->ramcfg_11_03_f0 = (nvbios_rd08(bios, data + 0x03) & 0xf0) >> 4; + p->ramcfg_11_04 = (nvbios_rd08(bios, data + 0x04) & 0xff) >> 0; + p->ramcfg_11_06 = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0; + p->ramcfg_11_07_02 = (nvbios_rd08(bios, data + 0x07) & 0x02) >> 1; + p->ramcfg_11_07_04 = (nvbios_rd08(bios, data + 0x07) & 0x04) >> 2; + p->ramcfg_11_07_08 = (nvbios_rd08(bios, data + 0x07) & 0x08) >> 3; + p->ramcfg_11_07_10 = (nvbios_rd08(bios, data + 0x07) & 0x10) >> 4; + p->ramcfg_11_07_40 = (nvbios_rd08(bios, data + 0x07) & 0x40) >> 6; + p->ramcfg_11_07_80 = (nvbios_rd08(bios, data + 0x07) & 0x80) >> 7; + p->ramcfg_11_08_01 = (nvbios_rd08(bios, data + 0x08) & 0x01) >> 0; + p->ramcfg_11_08_02 = (nvbios_rd08(bios, data + 0x08) & 0x02) >> 1; + p->ramcfg_11_08_04 = (nvbios_rd08(bios, data + 0x08) & 0x04) >> 2; + p->ramcfg_11_08_08 = (nvbios_rd08(bios, data + 0x08) & 0x08) >> 3; + p->ramcfg_11_08_10 = (nvbios_rd08(bios, data + 0x08) & 0x10) >> 4; + p->ramcfg_11_08_20 = (nvbios_rd08(bios, data + 0x08) & 0x20) >> 5; + p->ramcfg_11_09 = (nvbios_rd08(bios, data + 0x09) & 0xff) >> 0; break; default: data = 0; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c index 8c2b7cba5..b2557e87a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c @@ -23,13 +23,11 @@ */ #include "priv.h" -#include #include #include #include struct shadow { - struct nvkm_oclass base; u32 skip; const struct nvbios_source *func; void *data; @@ -38,9 +36,8 @@ struct shadow { }; static bool -shadow_fetch(struct nvkm_bios *bios, u32 upto) +shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto) { - struct shadow *mthd = (void *)nv_object(bios)->oclass; const u32 limit = (upto + 3) & ~3; const u32 start = bios->size; void *data = mthd->data; @@ -48,68 +45,47 @@ shadow_fetch(struct nvkm_bios *bios, u32 upto) u32 read = mthd->func->read(data, start, limit - start, bios); bios->size = start + read; } - return bios->size >= limit; + return bios->size >= upto; } -static u8 -shadow_rd08(struct nvkm_object *object, u64 addr) -{ - struct nvkm_bios *bios = (void *)object; - if (shadow_fetch(bios, addr + 1)) - return bios->data[addr]; - return 0x00; -} - -static u16 -shadow_rd16(struct nvkm_object *object, u64 addr) -{ - struct nvkm_bios *bios = (void *)object; - if (shadow_fetch(bios, addr + 2)) - return get_unaligned_le16(&bios->data[addr]); - return 0x0000; -} - -static u32 -shadow_rd32(struct nvkm_object *object, u64 addr) -{ - struct nvkm_bios *bios = (void *)object; - if (shadow_fetch(bios, addr + 4)) - return get_unaligned_le32(&bios->data[addr]); - return 0x00000000; -} - -static struct nvkm_oclass -shadow_class = { - .handle = NV_SUBDEV(VBIOS, 0x00), - .ofuncs = &(struct nvkm_ofuncs) { - .rd08 = shadow_rd08, - .rd16 = shadow_rd16, - .rd32 = shadow_rd32, - }, -}; - static int -shadow_image(struct nvkm_bios *bios, int idx, struct shadow *mthd) +shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd) { + struct nvkm_subdev *subdev = &bios->subdev; struct nvbios_image image; int score = 1; - if (!nvbios_image(bios, idx, &image)) { - nv_debug(bios, "image %d invalid\n", idx); - return 0; + if (mthd->func->no_pcir) { + image.base = 0; + image.type = 0; + image.size = mthd->func->size(mthd->data); + image.last = 1; + } else { + if (!shadow_fetch(bios, mthd, offset + 0x1000)) { + nvkm_debug(subdev, "%08x: header fetch failed\n", + offset); + return 0; + } + + if (!nvbios_image(bios, idx, &image)) { + nvkm_debug(subdev, "image %d invalid\n", idx); + return 0; + } } - nv_debug(bios, "%08x: type %02x, %d bytes\n", - image.base, image.type, image.size); + nvkm_debug(subdev, "%08x: type %02x, %d bytes\n", + image.base, image.type, image.size); - if (!shadow_fetch(bios, image.size)) { - nv_debug(bios, "%08x: fetch failed\n", image.base); + if (!shadow_fetch(bios, mthd, image.size)) { + nvkm_debug(subdev, "%08x: fetch failed\n", image.base); return 0; } switch (image.type) { case 0x00: - if (nvbios_checksum(&bios->data[image.base], image.size)) { - nv_debug(bios, "%08x: checksum failed\n", image.base); + if (!mthd->func->ignore_checksum && + nvbios_checksum(&bios->data[image.base], image.size)) { + nvkm_debug(subdev, "%08x: checksum failed\n", + image.base); if (mthd->func->rw) score += 1; score += 1; @@ -123,28 +99,17 @@ shadow_image(struct nvkm_bios *bios, int idx, struct shadow *mthd) } if (!image.last) - score += shadow_image(bios, idx + 1, mthd); + score += shadow_image(bios, idx + 1, offset + image.size, mthd); return score; } -static int -shadow_score(struct nvkm_bios *bios, struct shadow *mthd) -{ - struct nvkm_oclass *oclass = nv_object(bios)->oclass; - int score; - nv_object(bios)->oclass = &mthd->base; - score = shadow_image(bios, 0, mthd); - nv_object(bios)->oclass = oclass; - return score; - -} - static int shadow_method(struct nvkm_bios *bios, struct shadow *mthd, const char *name) { const struct nvbios_source *func = mthd->func; + struct nvkm_subdev *subdev = &bios->subdev; if (func->name) { - nv_debug(bios, "trying %s...\n", name ? name : func->name); + nvkm_debug(subdev, "trying %s...\n", name ? name : func->name); if (func->init) { mthd->data = func->init(bios, name); if (IS_ERR(mthd->data)) { @@ -152,10 +117,10 @@ shadow_method(struct nvkm_bios *bios, struct shadow *mthd, const char *name) return 0; } } - mthd->score = shadow_score(bios, mthd); + mthd->score = shadow_image(bios, 0, 0, mthd); if (func->fini) func->fini(mthd->data); - nv_debug(bios, "scored %d\n", mthd->score); + nvkm_debug(subdev, "scored %d\n", mthd->score); mthd->data = bios->data; mthd->size = bios->size; bios->data = NULL; @@ -178,7 +143,7 @@ shadow_fw_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) static void * shadow_fw_init(struct nvkm_bios *bios, const char *name) { - struct device *dev = &nv_device(bios)->pdev->dev; + struct device *dev = bios->subdev.device->dev; const struct firmware *fw; int ret = request_firmware(&fw, name, dev); if (ret) @@ -198,22 +163,24 @@ shadow_fw = { int nvbios_shadow(struct nvkm_bios *bios) { + struct nvkm_subdev *subdev = &bios->subdev; + struct nvkm_device *device = subdev->device; struct shadow mthds[] = { - { shadow_class, 0, &nvbios_of }, - { shadow_class, 0, &nvbios_ramin }, - { shadow_class, 0, &nvbios_rom }, - { shadow_class, 0, &nvbios_acpi_fast }, - { shadow_class, 4, &nvbios_acpi_slow }, - { shadow_class, 1, &nvbios_pcirom }, - { shadow_class, 1, &nvbios_platform }, - { shadow_class } - }, *mthd = mthds, *best = NULL; + { 0, &nvbios_of }, + { 0, &nvbios_ramin }, + { 0, &nvbios_rom }, + { 0, &nvbios_acpi_fast }, + { 4, &nvbios_acpi_slow }, + { 1, &nvbios_pcirom }, + { 1, &nvbios_platform }, + {} + }, *mthd, *best = NULL; const char *optarg; char *source; int optlen; /* handle user-specified bios source */ - optarg = nvkm_stropt(nv_device(bios)->cfgopt, "NvBios", &optlen); + optarg = nvkm_stropt(device->cfgopt, "NvBios", &optlen); source = optarg ? kstrndup(optarg, optlen, GFP_KERNEL) : NULL; if (source) { /* try to match one of the built-in methods */ @@ -234,7 +201,7 @@ nvbios_shadow(struct nvkm_bios *bios) } if (!best->score) { - nv_error(bios, "%s invalid\n", source); + nvkm_error(subdev, "%s invalid\n", source); kfree(source); source = NULL; } @@ -259,12 +226,12 @@ nvbios_shadow(struct nvkm_bios *bios) } if (!best->score) { - nv_fatal(bios, "unable to locate usable image\n"); + nvkm_error(subdev, "unable to locate usable image\n"); return -EINVAL; } - nv_info(bios, "using image from %s\n", best->func ? - best->func->name : source); + nvkm_debug(subdev, "using image from %s\n", best->func ? + best->func->name : source); bios->data = best->data; bios->size = best->size; kfree(source); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c index f9d0eb564..8fecb5ff2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c @@ -22,14 +22,12 @@ */ #include "priv.h" -#include - #if defined(CONFIG_ACPI) && defined(CONFIG_X86) int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); -bool nouveau_acpi_rom_supported(struct pci_dev *pdev); +bool nouveau_acpi_rom_supported(struct device *); #else static inline bool -nouveau_acpi_rom_supported(struct pci_dev *pdev) +nouveau_acpi_rom_supported(struct device *dev) { return false; } @@ -90,7 +88,7 @@ acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios) static void * acpi_init(struct nvkm_bios *bios, const char *name) { - if (!nouveau_acpi_rom_supported(nv_device(bios)->pdev)) + if (!nouveau_acpi_rom_supported(bios->subdev.device->dev)) return ERR_PTR(-ENODEV); return NULL; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c index 4c19a7dba..4bf486b57 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c @@ -22,7 +22,7 @@ */ #include "priv.h" -#include +#include #if defined(__powerpc__) struct priv { @@ -34,17 +34,26 @@ static u32 of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { struct priv *priv = data; - if (offset + length <= priv->size) { + if (offset < priv->size) { + length = min_t(u32, length, priv->size - offset); memcpy_fromio(bios->data + offset, priv->data + offset, length); return length; } return 0; } +static u32 +of_size(void *data) +{ + struct priv *priv = data; + return priv->size; +} + static void * of_init(struct nvkm_bios *bios, const char *name) { - struct pci_dev *pdev = nv_device(bios)->pdev; + struct nvkm_device *device = bios->subdev.device; + struct pci_dev *pdev = device->func->pci(device)->pdev; struct device_node *dn; struct priv *priv; if (!(dn = pci_device_to_OF_node(pdev))) @@ -63,7 +72,10 @@ nvbios_of = { .init = of_init, .fini = (void(*)(void *))kfree, .read = of_read, + .size = of_size, .rw = false, + .ignore_checksum = true, + .no_pcir = true, }; #else const struct nvbios_source diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c index 1b045483d..9b91da09d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c @@ -22,7 +22,7 @@ */ #include "priv.h" -#include +#include struct priv { struct pci_dev *pdev; @@ -53,10 +53,16 @@ pcirom_fini(void *data) static void * pcirom_init(struct nvkm_bios *bios, const char *name) { - struct pci_dev *pdev = nv_device(bios)->pdev; + struct nvkm_device *device = bios->subdev.device; struct priv *priv = NULL; + struct pci_dev *pdev; int ret; + if (device->func->pci) + pdev = device->func->pci(device)->pdev; + else + return ERR_PTR(-ENODEV); + if (!(ret = pci_enable_rom(pdev))) { if (ret = -ENOMEM, (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) { @@ -85,10 +91,16 @@ nvbios_pcirom = { static void * platform_init(struct nvkm_bios *bios, const char *name) { - struct pci_dev *pdev = nv_device(bios)->pdev; + struct nvkm_device *device = bios->subdev.device; + struct pci_dev *pdev; struct priv *priv; int ret = -ENOMEM; + if (device->func->pci) + pdev = device->func->pci(device)->pdev; + else + return ERR_PTR(-ENODEV); + if ((priv = kmalloc(sizeof(*priv), GFP_KERNEL))) { if (ret = -ENODEV, (priv->rom = pci_platform_rom(pdev, &priv->size))) diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c index abe8ae4d3..0f537c228 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c @@ -22,8 +22,6 @@ */ #include "priv.h" -#include - struct priv { struct nvkm_bios *bios; u32 bar0; @@ -32,10 +30,11 @@ struct priv { static u32 pramin_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { + struct nvkm_device *device = bios->subdev.device; u32 i; if (offset + length <= 0x00100000) { for (i = offset; i < offset + length; i += 4) - *(u32 *)&bios->data[i] = nv_rd32(bios, 0x700000 + i); + *(u32 *)&bios->data[i] = nvkm_rd32(device, 0x700000 + i); return length; } return 0; @@ -46,7 +45,8 @@ pramin_fini(void *data) { struct priv *priv = data; if (priv) { - nv_wr32(priv->bios, 0x001700, priv->bar0); + struct nvkm_device *device = priv->bios->subdev.device; + nvkm_wr32(device, 0x001700, priv->bar0); kfree(priv); } } @@ -54,21 +54,23 @@ pramin_fini(void *data) static void * pramin_init(struct nvkm_bios *bios, const char *name) { + struct nvkm_subdev *subdev = &bios->subdev; + struct nvkm_device *device = subdev->device; struct priv *priv = NULL; u64 addr = 0; /* PRAMIN always potentially available prior to nv50 */ - if (nv_device(bios)->card_type < NV_50) + if (device->card_type < NV_50) return NULL; /* we can't get the bios image pointer without PDISP */ - if (nv_device(bios)->card_type >= GM100) - addr = nv_rd32(bios, 0x021c04); + if (device->card_type >= GM100) + addr = nvkm_rd32(device, 0x021c04); else - if (nv_device(bios)->card_type >= NV_C0) - addr = nv_rd32(bios, 0x022500); + if (device->card_type >= NV_C0) + addr = nvkm_rd32(device, 0x022500); if (addr & 0x00000001) { - nv_debug(bios, "... display disabled\n"); + nvkm_debug(subdev, "... display disabled\n"); return ERR_PTR(-ENODEV); } @@ -76,32 +78,32 @@ pramin_init(struct nvkm_bios *bios, const char *name) * important as we don't want to be touching vram on an * uninitialised board */ - addr = nv_rd32(bios, 0x619f04); + addr = nvkm_rd32(device, 0x619f04); if (!(addr & 0x00000008)) { - nv_debug(bios, "... not enabled\n"); + nvkm_debug(subdev, "... not enabled\n"); return ERR_PTR(-ENODEV); } if ( (addr & 0x00000003) != 1) { - nv_debug(bios, "... not in vram\n"); + nvkm_debug(subdev, "... not in vram\n"); return ERR_PTR(-ENODEV); } /* some alternate method inherited from xf86-video-nv... */ addr = (addr & 0xffffff00) << 8; if (!addr) { - addr = (u64)nv_rd32(bios, 0x001700) << 16; + addr = (u64)nvkm_rd32(device, 0x001700) << 16; addr += 0xf0000; } /* modify bar0 PRAMIN window to cover the bios image */ if (!(priv = kmalloc(sizeof(*priv), GFP_KERNEL))) { - nv_error(bios, "... out of memory\n"); + nvkm_error(subdev, "... out of memory\n"); return ERR_PTR(-ENOMEM); } priv->bios = bios; - priv->bar0 = nv_rd32(bios, 0x001700); - nv_wr32(bios, 0x001700, addr >> 16); + priv->bar0 = nvkm_rd32(device, 0x001700); + nvkm_wr32(device, 0x001700, addr >> 16); return priv; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c index 6ec3b2379..ffa4b3952 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c @@ -22,15 +22,16 @@ */ #include "priv.h" -#include +#include static u32 prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { + struct nvkm_device *device = data; u32 i; if (offset + length <= 0x00100000) { for (i = offset; i < offset + length; i += 4) - *(u32 *)&bios->data[i] = nv_rd32(bios, 0x300000 + i); + *(u32 *)&bios->data[i] = nvkm_rd32(device, 0x300000 + i); return length; } return 0; @@ -39,25 +40,18 @@ prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) static void prom_fini(void *data) { - struct nvkm_bios *bios = data; - if (nv_device(bios)->card_type < NV_50) - nv_mask(bios, 0x001850, 0x00000001, 0x00000001); - else - nv_mask(bios, 0x088050, 0x00000001, 0x00000001); + struct nvkm_device *device = data; + nvkm_pci_rom_shadow(device->pci, true); } static void * prom_init(struct nvkm_bios *bios, const char *name) { - if (nv_device(bios)->card_type < NV_50) { - if (nv_device(bios)->card_type == NV_40 && - nv_device(bios)->chipset >= 0x4c) - return ERR_PTR(-ENODEV); - nv_mask(bios, 0x001850, 0x00000001, 0x00000000); - } else { - nv_mask(bios, 0x088050, 0x00000001, 0x00000000); - } - return bios; + struct nvkm_device *device = bios->subdev.device; + if (device->card_type == NV_40 && device->chipset >= 0x4c) + return ERR_PTR(-ENODEV); + nvkm_pci_rom_shadow(device->pci, false); + return device; } const struct nvbios_source diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c index 249ff6d58..a54cfec05 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c @@ -25,8 +25,6 @@ #include #include -#include - static u16 therm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) { @@ -35,24 +33,24 @@ therm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 1) - therm = nv_ro16(bios, bit_P.offset + 12); + therm = nvbios_rd16(bios, bit_P.offset + 12); else if (bit_P.version == 2) - therm = nv_ro16(bios, bit_P.offset + 16); + therm = nvbios_rd16(bios, bit_P.offset + 16); else - nv_error(bios, - "unknown offset for thermal in BIT P %d\n", - bit_P.version); + nvkm_error(&bios->subdev, + "unknown offset for thermal in BIT P %d\n", + bit_P.version); } /* exit now if we haven't found the thermal table */ if (!therm) return 0x0000; - *ver = nv_ro08(bios, therm + 0); - *hdr = nv_ro08(bios, therm + 1); - *len = nv_ro08(bios, therm + 2); - *cnt = nv_ro08(bios, therm + 3); - return therm + nv_ro08(bios, therm + 1); + *ver = nvbios_rd08(bios, therm + 0); + *hdr = nvbios_rd08(bios, therm + 1); + *len = nvbios_rd08(bios, therm + 2); + *cnt = nvbios_rd08(bios, therm + 3); + return therm + nvbios_rd08(bios, therm + 1); } static u16 @@ -83,9 +81,9 @@ nvbios_therm_sensor_parse(struct nvkm_bios *bios, sensor_section = -1; i = 0; while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { - s16 value = nv_ro16(bios, entry + 1); + s16 value = nvbios_rd16(bios, entry + 1); - switch (nv_ro08(bios, entry + 0)) { + switch (nvbios_rd08(bios, entry + 0)) { case 0x0: thrs_section = value; if (value > 0) @@ -94,7 +92,7 @@ nvbios_therm_sensor_parse(struct nvkm_bios *bios, case 0x01: sensor_section++; if (sensor_section == 0) { - offset = ((s8) nv_ro08(bios, entry + 2)) / 2; + offset = ((s8) nvbios_rd08(bios, entry + 2)) / 2; sensor->offset_constant = offset; } break; @@ -165,9 +163,9 @@ nvbios_therm_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan) fan->nr_fan_trip = 0; fan->fan_mode = NVBIOS_THERM_FAN_OTHER; while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { - s16 value = nv_ro16(bios, entry + 1); + s16 value = nvbios_rd16(bios, entry + 1); - switch (nv_ro08(bios, entry + 0)) { + switch (nvbios_rd08(bios, entry + 0)) { case 0x22: fan->min_duty = value & 0xff; fan->max_duty = (value & 0xff00) >> 8; @@ -198,14 +196,14 @@ nvbios_therm_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan) case 0x46: if (fan->fan_mode > NVBIOS_THERM_FAN_LINEAR) fan->fan_mode = NVBIOS_THERM_FAN_LINEAR; - fan->linear_min_temp = nv_ro08(bios, entry + 1); - fan->linear_max_temp = nv_ro08(bios, entry + 2); + fan->linear_min_temp = nvbios_rd08(bios, entry + 1); + fan->linear_max_temp = nvbios_rd08(bios, entry + 2); break; } } /* starting from fermi, fan management is always linear */ - if (nv_device(bios)->card_type >= NV_C0 && + if (bios->subdev.device->card_type >= NV_C0 && fan->fan_mode == NVBIOS_THERM_FAN_OTHER) { fan->fan_mode = NVBIOS_THERM_FAN_LINEAR; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c index 763fd29a5..99f6432ac 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c @@ -34,27 +34,27 @@ nvbios_timingTe(struct nvkm_bios *bios, if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 1) - timing = nv_ro16(bios, bit_P.offset + 4); + timing = nvbios_rd16(bios, bit_P.offset + 4); else if (bit_P.version == 2) - timing = nv_ro16(bios, bit_P.offset + 8); + timing = nvbios_rd16(bios, bit_P.offset + 8); if (timing) { - *ver = nv_ro08(bios, timing + 0); + *ver = nvbios_rd08(bios, timing + 0); switch (*ver) { case 0x10: - *hdr = nv_ro08(bios, timing + 1); - *cnt = nv_ro08(bios, timing + 2); - *len = nv_ro08(bios, timing + 3); + *hdr = nvbios_rd08(bios, timing + 1); + *cnt = nvbios_rd08(bios, timing + 2); + *len = nvbios_rd08(bios, timing + 3); *snr = 0; *ssz = 0; return timing; case 0x20: - *hdr = nv_ro08(bios, timing + 1); - *cnt = nv_ro08(bios, timing + 5); - *len = nv_ro08(bios, timing + 2); - *snr = nv_ro08(bios, timing + 4); - *ssz = nv_ro08(bios, timing + 3); + *hdr = nvbios_rd08(bios, timing + 1); + *cnt = nvbios_rd08(bios, timing + 5); + *len = nvbios_rd08(bios, timing + 2); + *snr = nvbios_rd08(bios, timing + 4); + *ssz = nvbios_rd08(bios, timing + 3); return timing; default: break; @@ -90,18 +90,20 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx, p->timing_hdr = *hdr; switch (!!data * *ver) { case 0x10: - p->timing_10_WR = nv_ro08(bios, data + 0x00); - p->timing_10_WTR = nv_ro08(bios, data + 0x01); - p->timing_10_CL = nv_ro08(bios, data + 0x02); - p->timing_10_RC = nv_ro08(bios, data + 0x03); - p->timing_10_RFC = nv_ro08(bios, data + 0x05); - p->timing_10_RAS = nv_ro08(bios, data + 0x07); - p->timing_10_RP = nv_ro08(bios, data + 0x09); - p->timing_10_RCDRD = nv_ro08(bios, data + 0x0a); - p->timing_10_RCDWR = nv_ro08(bios, data + 0x0b); - p->timing_10_RRD = nv_ro08(bios, data + 0x0c); - p->timing_10_13 = nv_ro08(bios, data + 0x0d); - p->timing_10_ODT = nv_ro08(bios, data + 0x0e) & 0x07; + p->timing_10_WR = nvbios_rd08(bios, data + 0x00); + p->timing_10_WTR = nvbios_rd08(bios, data + 0x01); + p->timing_10_CL = nvbios_rd08(bios, data + 0x02); + p->timing_10_RC = nvbios_rd08(bios, data + 0x03); + p->timing_10_RFC = nvbios_rd08(bios, data + 0x05); + p->timing_10_RAS = nvbios_rd08(bios, data + 0x07); + p->timing_10_RP = nvbios_rd08(bios, data + 0x09); + p->timing_10_RCDRD = nvbios_rd08(bios, data + 0x0a); + p->timing_10_RCDWR = nvbios_rd08(bios, data + 0x0b); + p->timing_10_RRD = nvbios_rd08(bios, data + 0x0c); + p->timing_10_13 = nvbios_rd08(bios, data + 0x0d); + p->timing_10_ODT = nvbios_rd08(bios, data + 0x0e) & 0x07; + if (p->ramcfg_ver >= 0x10) + p->ramcfg_RON = nvbios_rd08(bios, data + 0x0e) & 0x07; p->timing_10_24 = 0xff; p->timing_10_21 = 0; @@ -112,45 +114,45 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx, switch (min_t(u8, *hdr, 25)) { case 25: - p->timing_10_24 = nv_ro08(bios, data + 0x18); + p->timing_10_24 = nvbios_rd08(bios, data + 0x18); case 24: case 23: case 22: - p->timing_10_21 = nv_ro08(bios, data + 0x15); + p->timing_10_21 = nvbios_rd08(bios, data + 0x15); case 21: - p->timing_10_20 = nv_ro08(bios, data + 0x14); + p->timing_10_20 = nvbios_rd08(bios, data + 0x14); case 20: - p->timing_10_CWL = nv_ro08(bios, data + 0x13); + p->timing_10_CWL = nvbios_rd08(bios, data + 0x13); case 19: - p->timing_10_18 = nv_ro08(bios, data + 0x12); + p->timing_10_18 = nvbios_rd08(bios, data + 0x12); case 18: case 17: - p->timing_10_16 = nv_ro08(bios, data + 0x10); + p->timing_10_16 = nvbios_rd08(bios, data + 0x10); } break; case 0x20: - p->timing[0] = nv_ro32(bios, data + 0x00); - p->timing[1] = nv_ro32(bios, data + 0x04); - p->timing[2] = nv_ro32(bios, data + 0x08); - p->timing[3] = nv_ro32(bios, data + 0x0c); - p->timing[4] = nv_ro32(bios, data + 0x10); - p->timing[5] = nv_ro32(bios, data + 0x14); - p->timing[6] = nv_ro32(bios, data + 0x18); - p->timing[7] = nv_ro32(bios, data + 0x1c); - p->timing[8] = nv_ro32(bios, data + 0x20); - p->timing[9] = nv_ro32(bios, data + 0x24); - p->timing[10] = nv_ro32(bios, data + 0x28); - p->timing_20_2e_03 = (nv_ro08(bios, data + 0x2e) & 0x03) >> 0; - p->timing_20_2e_30 = (nv_ro08(bios, data + 0x2e) & 0x30) >> 4; - p->timing_20_2e_c0 = (nv_ro08(bios, data + 0x2e) & 0xc0) >> 6; - p->timing_20_2f_03 = (nv_ro08(bios, data + 0x2f) & 0x03) >> 0; - temp = nv_ro16(bios, data + 0x2c); + p->timing[0] = nvbios_rd32(bios, data + 0x00); + p->timing[1] = nvbios_rd32(bios, data + 0x04); + p->timing[2] = nvbios_rd32(bios, data + 0x08); + p->timing[3] = nvbios_rd32(bios, data + 0x0c); + p->timing[4] = nvbios_rd32(bios, data + 0x10); + p->timing[5] = nvbios_rd32(bios, data + 0x14); + p->timing[6] = nvbios_rd32(bios, data + 0x18); + p->timing[7] = nvbios_rd32(bios, data + 0x1c); + p->timing[8] = nvbios_rd32(bios, data + 0x20); + p->timing[9] = nvbios_rd32(bios, data + 0x24); + p->timing[10] = nvbios_rd32(bios, data + 0x28); + p->timing_20_2e_03 = (nvbios_rd08(bios, data + 0x2e) & 0x03) >> 0; + p->timing_20_2e_30 = (nvbios_rd08(bios, data + 0x2e) & 0x30) >> 4; + p->timing_20_2e_c0 = (nvbios_rd08(bios, data + 0x2e) & 0xc0) >> 6; + p->timing_20_2f_03 = (nvbios_rd08(bios, data + 0x2f) & 0x03) >> 0; + temp = nvbios_rd16(bios, data + 0x2c); p->timing_20_2c_003f = (temp & 0x003f) >> 0; p->timing_20_2c_1fc0 = (temp & 0x1fc0) >> 6; - p->timing_20_30_07 = (nv_ro08(bios, data + 0x30) & 0x07) >> 0; - p->timing_20_30_f8 = (nv_ro08(bios, data + 0x30) & 0xf8) >> 3; - temp = nv_ro16(bios, data + 0x31); + p->timing_20_30_07 = (nvbios_rd08(bios, data + 0x30) & 0x07) >> 0; + p->timing_20_30_f8 = (nvbios_rd08(bios, data + 0x30) & 0xf8) >> 3; + temp = nvbios_rd16(bios, data + 0x31); p->timing_20_31_0007 = (temp & 0x0007) >> 0; p->timing_20_31_0078 = (temp & 0x0078) >> 3; p->timing_20_31_0780 = (temp & 0x0780) >> 7; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c index e95b69faa..2f13db745 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c @@ -33,15 +33,15 @@ nvbios_vmap_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2) { - vmap = nv_ro16(bios, bit_P.offset + 0x20); + vmap = nvbios_rd16(bios, bit_P.offset + 0x20); if (vmap) { - *ver = nv_ro08(bios, vmap + 0); + *ver = nvbios_rd08(bios, vmap + 0); switch (*ver) { case 0x10: case 0x20: - *hdr = nv_ro08(bios, vmap + 1); - *cnt = nv_ro08(bios, vmap + 3); - *len = nv_ro08(bios, vmap + 2); + *hdr = nvbios_rd08(bios, vmap + 1); + *cnt = nvbios_rd08(bios, vmap + 3); + *len = nvbios_rd08(bios, vmap + 2); return vmap; default: break; @@ -88,23 +88,23 @@ nvbios_vmap_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len, switch (!!vmap * *ver) { case 0x10: info->link = 0xff; - info->min = nv_ro32(bios, vmap + 0x00); - info->max = nv_ro32(bios, vmap + 0x04); - info->arg[0] = nv_ro32(bios, vmap + 0x08); - info->arg[1] = nv_ro32(bios, vmap + 0x0c); - info->arg[2] = nv_ro32(bios, vmap + 0x10); + info->min = nvbios_rd32(bios, vmap + 0x00); + info->max = nvbios_rd32(bios, vmap + 0x04); + info->arg[0] = nvbios_rd32(bios, vmap + 0x08); + info->arg[1] = nvbios_rd32(bios, vmap + 0x0c); + info->arg[2] = nvbios_rd32(bios, vmap + 0x10); break; case 0x20: - info->unk0 = nv_ro08(bios, vmap + 0x00); - info->link = nv_ro08(bios, vmap + 0x01); - info->min = nv_ro32(bios, vmap + 0x02); - info->max = nv_ro32(bios, vmap + 0x06); - info->arg[0] = nv_ro32(bios, vmap + 0x0a); - info->arg[1] = nv_ro32(bios, vmap + 0x0e); - info->arg[2] = nv_ro32(bios, vmap + 0x12); - info->arg[3] = nv_ro32(bios, vmap + 0x16); - info->arg[4] = nv_ro32(bios, vmap + 0x1a); - info->arg[5] = nv_ro32(bios, vmap + 0x1e); + info->unk0 = nvbios_rd08(bios, vmap + 0x00); + info->link = nvbios_rd08(bios, vmap + 0x01); + info->min = nvbios_rd32(bios, vmap + 0x02); + info->max = nvbios_rd32(bios, vmap + 0x06); + info->arg[0] = nvbios_rd32(bios, vmap + 0x0a); + info->arg[1] = nvbios_rd32(bios, vmap + 0x0e); + info->arg[2] = nvbios_rd32(bios, vmap + 0x12); + info->arg[3] = nvbios_rd32(bios, vmap + 0x16); + info->arg[4] = nvbios_rd32(bios, vmap + 0x1a); + info->arg[5] = nvbios_rd32(bios, vmap + 0x1e); break; } return vmap; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c index 8454ab7c4..6e0a33648 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c @@ -33,30 +33,30 @@ nvbios_volt_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) if (!bit_entry(bios, 'P', &bit_P)) { if (bit_P.version == 2) - volt = nv_ro16(bios, bit_P.offset + 0x0c); + volt = nvbios_rd16(bios, bit_P.offset + 0x0c); else if (bit_P.version == 1) - volt = nv_ro16(bios, bit_P.offset + 0x10); + volt = nvbios_rd16(bios, bit_P.offset + 0x10); if (volt) { - *ver = nv_ro08(bios, volt + 0); + *ver = nvbios_rd08(bios, volt + 0); switch (*ver) { case 0x12: *hdr = 5; - *cnt = nv_ro08(bios, volt + 2); - *len = nv_ro08(bios, volt + 1); + *cnt = nvbios_rd08(bios, volt + 2); + *len = nvbios_rd08(bios, volt + 1); return volt; case 0x20: - *hdr = nv_ro08(bios, volt + 1); - *cnt = nv_ro08(bios, volt + 2); - *len = nv_ro08(bios, volt + 3); + *hdr = nvbios_rd08(bios, volt + 1); + *cnt = nvbios_rd08(bios, volt + 2); + *len = nvbios_rd08(bios, volt + 3); return volt; case 0x30: case 0x40: case 0x50: - *hdr = nv_ro08(bios, volt + 1); - *cnt = nv_ro08(bios, volt + 3); - *len = nv_ro08(bios, volt + 2); + *hdr = nvbios_rd08(bios, volt + 1); + *cnt = nvbios_rd08(bios, volt + 3); + *len = nvbios_rd08(bios, volt + 2); return volt; } } @@ -73,28 +73,41 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, memset(info, 0x00, sizeof(*info)); switch (!!volt * *ver) { case 0x12: - info->vidmask = nv_ro08(bios, volt + 0x04); + info->type = NVBIOS_VOLT_GPIO; + info->vidmask = nvbios_rd08(bios, volt + 0x04); break; case 0x20: - info->vidmask = nv_ro08(bios, volt + 0x05); + info->type = NVBIOS_VOLT_GPIO; + info->vidmask = nvbios_rd08(bios, volt + 0x05); break; case 0x30: - info->vidmask = nv_ro08(bios, volt + 0x04); + info->type = NVBIOS_VOLT_GPIO; + info->vidmask = nvbios_rd08(bios, volt + 0x04); break; case 0x40: - info->base = nv_ro32(bios, volt + 0x04); - info->step = nv_ro16(bios, volt + 0x08); - info->vidmask = nv_ro08(bios, volt + 0x0b); + info->type = NVBIOS_VOLT_GPIO; + info->base = nvbios_rd32(bios, volt + 0x04); + info->step = nvbios_rd16(bios, volt + 0x08); + info->vidmask = nvbios_rd08(bios, volt + 0x0b); /*XXX*/ info->min = 0; info->max = info->base; break; case 0x50: - info->vidmask = nv_ro08(bios, volt + 0x06); - info->min = nv_ro32(bios, volt + 0x0a); - info->max = nv_ro32(bios, volt + 0x0e); - info->base = nv_ro32(bios, volt + 0x12) & 0x00ffffff; - info->step = nv_ro16(bios, volt + 0x16); + info->min = nvbios_rd32(bios, volt + 0x0a); + info->max = nvbios_rd32(bios, volt + 0x0e); + info->base = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff; + + /* offset 4 seems to be a flag byte */ + if (nvbios_rd32(bios, volt + 0x4) & 1) { + info->type = NVBIOS_VOLT_PWM; + info->pwm_freq = nvbios_rd32(bios, volt + 0x5) / 1000; + info->pwm_range = nvbios_rd32(bios, volt + 0x16); + } else { + info->type = NVBIOS_VOLT_GPIO; + info->vidmask = nvbios_rd08(bios, volt + 0x06); + info->step = nvbios_rd16(bios, volt + 0x16); + } break; } return volt; @@ -121,12 +134,12 @@ nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len, switch (!!volt * *ver) { case 0x12: case 0x20: - info->voltage = nv_ro08(bios, volt + 0x00) * 10000; - info->vid = nv_ro08(bios, volt + 0x01); + info->voltage = nvbios_rd08(bios, volt + 0x00) * 10000; + info->vid = nvbios_rd08(bios, volt + 0x01); break; case 0x30: - info->voltage = nv_ro08(bios, volt + 0x00) * 10000; - info->vid = nv_ro08(bios, volt + 0x01) >> 2; + info->voltage = nvbios_rd08(bios, volt + 0x00) * 10000; + info->vid = nvbios_rd08(bios, volt + 0x01) >> 2; break; case 0x40: case 0x50: diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/xpio.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/xpio.c index 63a5e1b5c..250fc42d8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/xpio.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bios/xpio.c @@ -30,12 +30,12 @@ dcb_xpiod_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) { u16 data = dcb_gpio_table(bios, ver, hdr, cnt, len); if (data && *ver >= 0x40 && *hdr >= 0x06) { - u16 xpio = nv_ro16(bios, data + 0x04); + u16 xpio = nvbios_rd16(bios, data + 0x04); if (xpio) { - *ver = nv_ro08(bios, data + 0x00); - *hdr = nv_ro08(bios, data + 0x01); - *cnt = nv_ro08(bios, data + 0x02); - *len = nv_ro08(bios, data + 0x03); + *ver = nvbios_rd08(bios, data + 0x00); + *hdr = nvbios_rd08(bios, data + 0x01); + *cnt = nvbios_rd08(bios, data + 0x02); + *len = nvbios_rd08(bios, data + 0x03); return xpio; } } @@ -48,12 +48,12 @@ dcb_xpio_table(struct nvkm_bios *bios, u8 idx, { u16 data = dcb_xpiod_table(bios, ver, hdr, cnt, len); if (data && idx < *cnt) { - u16 xpio = nv_ro16(bios, data + *hdr + (idx * *len)); + u16 xpio = nvbios_rd16(bios, data + *hdr + (idx * *len)); if (xpio) { - *ver = nv_ro08(bios, data + 0x00); - *hdr = nv_ro08(bios, data + 0x01); - *cnt = nv_ro08(bios, data + 0x02); - *len = nv_ro08(bios, data + 0x03); + *ver = nvbios_rd08(bios, data + 0x00); + *hdr = nvbios_rd08(bios, data + 0x01); + *cnt = nvbios_rd08(bios, data + 0x02); + *len = nvbios_rd08(bios, data + 0x03); return xpio; } } @@ -66,9 +66,9 @@ dcb_xpio_parse(struct nvkm_bios *bios, u8 idx, { u16 data = dcb_xpio_table(bios, idx, ver, hdr, cnt, len); if (data && *len >= 6) { - info->type = nv_ro08(bios, data + 0x04); - info->addr = nv_ro08(bios, data + 0x05); - info->flags = nv_ro08(bios, data + 0x06); + info->type = nvbios_rd08(bios, data + 0x04); + info->addr = nvbios_rd08(bios, data + 0x05); + info->flags = nvbios_rd08(bios, data + 0x06); } return 0x0000; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/Kbuild index 83d80b13f..5fa9e9183 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/Kbuild @@ -1,3 +1,4 @@ +nvkm-y += nvkm/subdev/bus/base.o nvkm-y += nvkm/subdev/bus/hwsq.o nvkm-y += nvkm/subdev/bus/nv04.o nvkm-y += nvkm/subdev/bus/nv31.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c new file mode 100644 index 000000000..dc5a10f18 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c @@ -0,0 +1,64 @@ +/* + * 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 + */ +#include "priv.h" + +static void +nvkm_bus_intr(struct nvkm_subdev *subdev) +{ + struct nvkm_bus *bus = nvkm_bus(subdev); + bus->func->intr(bus); +} + +static int +nvkm_bus_init(struct nvkm_subdev *subdev) +{ + struct nvkm_bus *bus = nvkm_bus(subdev); + bus->func->init(bus); + return 0; +} + +static void * +nvkm_bus_dtor(struct nvkm_subdev *subdev) +{ + return nvkm_bus(subdev); +} + +static const struct nvkm_subdev_func +nvkm_bus = { + .dtor = nvkm_bus_dtor, + .init = nvkm_bus_init, + .intr = nvkm_bus_intr, +}; + +int +nvkm_bus_new_(const struct nvkm_bus_func *func, struct nvkm_device *device, + int index, struct nvkm_bus **pbus) +{ + struct nvkm_bus *bus; + if (!(bus = *pbus = kzalloc(sizeof(*bus), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_bus, device, index, 0, &bus->subdev); + bus->func = func; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/g94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/g94.c index cbe699e82..9700b5c01 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/g94.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/g94.c @@ -22,37 +22,43 @@ * Authors: Martin Peres * Ben Skeggs */ -#include "nv04.h" +#include "priv.h" #include static int -g94_bus_hwsq_exec(struct nvkm_bus *pbus, u32 *data, u32 size) +g94_bus_hwsq_exec(struct nvkm_bus *bus, u32 *data, u32 size) { - struct nv50_bus_priv *priv = (void *)pbus; + struct nvkm_device *device = bus->subdev.device; int i; - nv_mask(pbus, 0x001098, 0x00000008, 0x00000000); - nv_wr32(pbus, 0x001304, 0x00000000); - nv_wr32(pbus, 0x001318, 0x00000000); + nvkm_mask(device, 0x001098, 0x00000008, 0x00000000); + nvkm_wr32(device, 0x001304, 0x00000000); + nvkm_wr32(device, 0x001318, 0x00000000); for (i = 0; i < size; i++) - nv_wr32(priv, 0x080000 + (i * 4), data[i]); - nv_mask(pbus, 0x001098, 0x00000018, 0x00000018); - nv_wr32(pbus, 0x00130c, 0x00000001); + nvkm_wr32(device, 0x080000 + (i * 4), data[i]); + nvkm_mask(device, 0x001098, 0x00000018, 0x00000018); + nvkm_wr32(device, 0x00130c, 0x00000001); - return nv_wait(pbus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x001308) & 0x00000100)) + break; + ) < 0) + return -ETIMEDOUT; + + return 0; } -struct nvkm_oclass * -g94_bus_oclass = &(struct nv04_bus_impl) { - .base.handle = NV_SUBDEV(BUS, 0x94), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_bus_ctor, - .dtor = _nvkm_bus_dtor, - .init = nv50_bus_init, - .fini = _nvkm_bus_fini, - }, +static const struct nvkm_bus_func +g94_bus = { + .init = nv50_bus_init, .intr = nv50_bus_intr, .hwsq_exec = g94_bus_hwsq_exec, .hwsq_size = 128, -}.base; +}; + +int +g94_bus_new(struct nvkm_device *device, int index, struct nvkm_bus **pbus) +{ + return nvkm_bus_new_(&g94_bus, device, index, pbus); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c index ebc63ba96..e0930d5fd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c @@ -22,59 +22,54 @@ * Authors: Martin Peres * Ben Skeggs */ -#include "nv04.h" +#include "priv.h" static void -gf100_bus_intr(struct nvkm_subdev *subdev) +gf100_bus_intr(struct nvkm_bus *bus) { - struct nvkm_bus *pbus = nvkm_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); + struct nvkm_subdev *subdev = &bus->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x001100) & nvkm_rd32(device, 0x001140); if (stat & 0x0000000e) { - u32 addr = nv_rd32(pbus, 0x009084); - u32 data = nv_rd32(pbus, 0x009088); + u32 addr = nvkm_rd32(device, 0x009084); + u32 data = nvkm_rd32(device, 0x009088); - nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x [ %s%s%s]\n", - (addr & 0x00000002) ? "write" : "read", data, - (addr & 0x00fffffc), - (stat & 0x00000002) ? "!ENGINE " : "", - (stat & 0x00000004) ? "IBUS " : "", - (stat & 0x00000008) ? "TIMEOUT " : ""); + nvkm_error(subdev, + "MMIO %s of %08x FAULT at %06x [ %s%s%s]\n", + (addr & 0x00000002) ? "write" : "read", data, + (addr & 0x00fffffc), + (stat & 0x00000002) ? "!ENGINE " : "", + (stat & 0x00000004) ? "IBUS " : "", + (stat & 0x00000008) ? "TIMEOUT " : ""); - nv_wr32(pbus, 0x009084, 0x00000000); - nv_wr32(pbus, 0x001100, (stat & 0x0000000e)); + nvkm_wr32(device, 0x009084, 0x00000000); + nvkm_wr32(device, 0x001100, (stat & 0x0000000e)); stat &= ~0x0000000e; } if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0x00000000); + nvkm_error(subdev, "intr %08x\n", stat); + nvkm_mask(device, 0x001140, stat, 0x00000000); } } -static int -gf100_bus_init(struct nvkm_object *object) +static void +gf100_bus_init(struct nvkm_bus *bus) { - struct nv04_bus_priv *priv = (void *)object; - int ret; - - ret = nvkm_bus_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x0000000e); - return 0; + struct nvkm_device *device = bus->subdev.device; + nvkm_wr32(device, 0x001100, 0xffffffff); + nvkm_wr32(device, 0x001140, 0x0000000e); } -struct nvkm_oclass * -gf100_bus_oclass = &(struct nv04_bus_impl) { - .base.handle = NV_SUBDEV(BUS, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_bus_ctor, - .dtor = _nvkm_bus_dtor, - .init = gf100_bus_init, - .fini = _nvkm_bus_fini, - }, +static const struct nvkm_bus_func +gf100_bus = { + .init = gf100_bus_init, .intr = gf100_bus_intr, -}.base; +}; + +int +gf100_bus_new(struct nvkm_device *device, int index, struct nvkm_bus **pbus) +{ + return nvkm_bus_new_(&gf100_bus, device, index, pbus); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c index 7622b4161..2a5668938 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c @@ -21,10 +21,10 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" struct nvkm_hwsq { - struct nvkm_bus *pbus; + struct nvkm_subdev *subdev; u32 addr; u32 data; struct { @@ -41,13 +41,13 @@ hwsq_cmd(struct nvkm_hwsq *hwsq, int size, u8 data[]) } int -nvkm_hwsq_init(struct nvkm_bus *pbus, struct nvkm_hwsq **phwsq) +nvkm_hwsq_init(struct nvkm_subdev *subdev, struct nvkm_hwsq **phwsq) { struct nvkm_hwsq *hwsq; hwsq = *phwsq = kmalloc(sizeof(*hwsq), GFP_KERNEL); if (hwsq) { - hwsq->pbus = pbus; + hwsq->subdev = subdev; hwsq->addr = ~0; hwsq->data = ~0; memset(hwsq->c.data, 0x7f, sizeof(hwsq->c.data)); @@ -63,21 +63,23 @@ nvkm_hwsq_fini(struct nvkm_hwsq **phwsq, bool exec) struct nvkm_hwsq *hwsq = *phwsq; int ret = 0, i; if (hwsq) { - struct nvkm_bus *pbus = hwsq->pbus; + struct nvkm_subdev *subdev = hwsq->subdev; + struct nvkm_bus *bus = subdev->device->bus; hwsq->c.size = (hwsq->c.size + 4) / 4; - if (hwsq->c.size <= pbus->hwsq_size) { + if (hwsq->c.size <= bus->func->hwsq_size) { if (exec) - ret = pbus->hwsq_exec(pbus, (u32 *)hwsq->c.data, - hwsq->c.size); + ret = bus->func->hwsq_exec(bus, + (u32 *)hwsq->c.data, + hwsq->c.size); if (ret) - nv_error(pbus, "hwsq exec failed: %d\n", ret); + nvkm_error(subdev, "hwsq exec failed: %d\n", ret); } else { - nv_error(pbus, "hwsq ucode too large\n"); + nvkm_error(subdev, "hwsq ucode too large\n"); ret = -ENOSPC; } for (i = 0; ret && i < hwsq->c.size; i++) - nv_error(pbus, "\t0x%08x\n", ((u32 *)hwsq->c.data)[i]); + nvkm_error(subdev, "\t%08x\n", ((u32 *)hwsq->c.data)[i]); *phwsq = NULL; kfree(hwsq); @@ -88,7 +90,7 @@ nvkm_hwsq_fini(struct nvkm_hwsq **phwsq, bool exec) void nvkm_hwsq_wr32(struct nvkm_hwsq *hwsq, u32 addr, u32 data) { - nv_debug(hwsq->pbus, "R[%06x] = 0x%08x\n", addr, data); + nvkm_debug(hwsq->subdev, "R[%06x] = %08x\n", addr, data); if (hwsq->data != data) { if ((data & 0xffff0000) != (hwsq->data & 0xffff0000)) { @@ -113,7 +115,7 @@ nvkm_hwsq_wr32(struct nvkm_hwsq *hwsq, u32 addr, u32 data) void nvkm_hwsq_setf(struct nvkm_hwsq *hwsq, u8 flag, int data) { - nv_debug(hwsq->pbus, " FLAG[%02x] = %d\n", flag, data); + nvkm_debug(hwsq->subdev, " FLAG[%02x] = %d\n", flag, data); flag += 0x80; if (data >= 0) flag += 0x20; @@ -125,10 +127,42 @@ nvkm_hwsq_setf(struct nvkm_hwsq *hwsq, u8 flag, int data) void nvkm_hwsq_wait(struct nvkm_hwsq *hwsq, u8 flag, u8 data) { - nv_debug(hwsq->pbus, " WAIT[%02x] = %d\n", flag, data); + nvkm_debug(hwsq->subdev, " WAIT[%02x] = %d\n", flag, data); hwsq_cmd(hwsq, 3, (u8[]){ 0x5f, flag, data }); } +void +nvkm_hwsq_wait_vblank(struct nvkm_hwsq *hwsq) +{ + struct nvkm_subdev *subdev = hwsq->subdev; + struct nvkm_device *device = subdev->device; + u32 heads, x, y, px = 0; + int i, head_sync; + + heads = nvkm_rd32(device, 0x610050); + for (i = 0; i < 2; i++) { + /* Heuristic: sync to head with biggest resolution */ + if (heads & (2 << (i << 3))) { + x = nvkm_rd32(device, 0x610b40 + (0x540 * i)); + y = (x & 0xffff0000) >> 16; + x &= 0x0000ffff; + if ((x * y) > px) { + px = (x * y); + head_sync = i; + } + } + } + + if (px == 0) { + nvkm_debug(subdev, "WAIT VBLANK !NO ACTIVE HEAD\n"); + return; + } + + nvkm_debug(subdev, "WAIT VBLANK HEAD%d\n", head_sync); + nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x0); + nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x1); +} + void nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec) { @@ -138,6 +172,6 @@ nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec) shift++; } - nv_debug(hwsq->pbus, " DELAY = %d ns\n", nsec); + nvkm_debug(hwsq->subdev, " DELAY = %d ns\n", nsec); hwsq_cmd(hwsq, 1, (u8[]){ 0x00 | (shift << 2) | usec }); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h index ebf709c27..54ec3b131 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h @@ -59,10 +59,9 @@ hwsq_reg(u32 addr) static inline int hwsq_init(struct hwsq *ram, struct nvkm_subdev *subdev) { - struct nvkm_bus *pbus = nvkm_bus(subdev); int ret; - ret = nvkm_hwsq_init(pbus, &ram->hwsq); + ret = nvkm_hwsq_init(subdev, &ram->hwsq); if (ret) return ret; @@ -85,8 +84,9 @@ hwsq_exec(struct hwsq *ram, bool exec) static inline u32 hwsq_rd32(struct hwsq *ram, struct hwsq_reg *reg) { + struct nvkm_device *device = ram->subdev->device; if (reg->sequence != ram->sequence) - reg->data = nv_rd32(ram->subdev, reg->addr); + reg->data = nvkm_rd32(device, reg->addr); return reg->data; } @@ -133,6 +133,12 @@ hwsq_wait(struct hwsq *ram, u8 flag, u8 data) nvkm_hwsq_wait(ram->hwsq, flag, data); } +static inline void +hwsq_wait_vblank(struct hwsq *ram) +{ + nvkm_hwsq_wait_vblank(ram->hwsq); +} + static inline void hwsq_nsec(struct hwsq *ram, u32 nsec) { diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c index 19c8e50ee..c80b96789 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c @@ -22,73 +22,55 @@ * Authors: Martin Peres * Ben Skeggs */ -#include "nv04.h" +#include "priv.h" + +#include + +#include static void -nv04_bus_intr(struct nvkm_subdev *subdev) +nv04_bus_intr(struct nvkm_bus *bus) { - struct nvkm_bus *pbus = nvkm_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); + struct nvkm_subdev *subdev = &bus->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x001100) & nvkm_rd32(device, 0x001140); if (stat & 0x00000001) { - nv_error(pbus, "BUS ERROR\n"); + nvkm_error(subdev, "BUS ERROR\n"); stat &= ~0x00000001; - nv_wr32(pbus, 0x001100, 0x00000001); + nvkm_wr32(device, 0x001100, 0x00000001); } if (stat & 0x00000110) { - subdev = nvkm_subdev(subdev, NVDEV_SUBDEV_GPIO); - if (subdev && subdev->intr) - subdev->intr(subdev); + struct nvkm_gpio *gpio = device->gpio; + if (gpio) + nvkm_subdev_intr(&gpio->subdev); stat &= ~0x00000110; - nv_wr32(pbus, 0x001100, 0x00000110); + nvkm_wr32(device, 0x001100, 0x00000110); } if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0x00000000); + nvkm_error(subdev, "intr %08x\n", stat); + nvkm_mask(device, 0x001140, stat, 0x00000000); } } -static int -nv04_bus_init(struct nvkm_object *object) +static void +nv04_bus_init(struct nvkm_bus *bus) { - struct nv04_bus_priv *priv = (void *)object; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x00000111); - - return nvkm_bus_init(&priv->base); + struct nvkm_device *device = bus->subdev.device; + nvkm_wr32(device, 0x001100, 0xffffffff); + nvkm_wr32(device, 0x001140, 0x00000111); } +static const struct nvkm_bus_func +nv04_bus = { + .init = nv04_bus_init, + .intr = nv04_bus_intr, +}; + int -nv04_bus_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_bus_new(struct nvkm_device *device, int index, struct nvkm_bus **pbus) { - struct nv04_bus_impl *impl = (void *)oclass; - struct nv04_bus_priv *priv; - int ret; - - ret = nvkm_bus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->intr = impl->intr; - priv->base.hwsq_exec = impl->hwsq_exec; - priv->base.hwsq_size = impl->hwsq_size; - return 0; + return nvkm_bus_new_(&nv04_bus, device, index, pbus); } - -struct nvkm_oclass * -nv04_bus_oclass = &(struct nv04_bus_impl) { - .base.handle = NV_SUBDEV(BUS, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_bus_ctor, - .dtor = _nvkm_bus_dtor, - .init = nv04_bus_init, - .fini = _nvkm_bus_fini, - }, - .intr = nv04_bus_intr, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.h deleted file mode 100644 index 3ddc8f91b..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __NVKM_BUS_NV04_H__ -#define __NVKM_BUS_NV04_H__ -#include - -struct nv04_bus_priv { - struct nvkm_bus base; -}; - -int nv04_bus_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -int nv50_bus_init(struct nvkm_object *); -void nv50_bus_intr(struct nvkm_subdev *); - -struct nv04_bus_impl { - struct nvkm_oclass base; - void (*intr)(struct nvkm_subdev *); - int (*hwsq_exec)(struct nvkm_bus *, u32 *, u32); - u32 hwsq_size; -}; -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c index c5739bce8..5153d89e1 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c @@ -22,70 +22,67 @@ * Authors: Martin Peres * Ben Skeggs */ -#include "nv04.h" +#include "priv.h" + +#include +#include static void -nv31_bus_intr(struct nvkm_subdev *subdev) +nv31_bus_intr(struct nvkm_bus *bus) { - struct nvkm_bus *pbus = nvkm_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); - u32 gpio = nv_rd32(pbus, 0x001104) & nv_rd32(pbus, 0x001144); + struct nvkm_subdev *subdev = &bus->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x001100) & nvkm_rd32(device, 0x001140); + u32 gpio = nvkm_rd32(device, 0x001104) & nvkm_rd32(device, 0x001144); if (gpio) { - subdev = nvkm_subdev(pbus, NVDEV_SUBDEV_GPIO); - if (subdev && subdev->intr) - subdev->intr(subdev); + struct nvkm_gpio *gpio = device->gpio; + if (gpio) + nvkm_subdev_intr(&gpio->subdev); } if (stat & 0x00000008) { /* NV41- */ - u32 addr = nv_rd32(pbus, 0x009084); - u32 data = nv_rd32(pbus, 0x009088); + u32 addr = nvkm_rd32(device, 0x009084); + u32 data = nvkm_rd32(device, 0x009088); - nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", - (addr & 0x00000002) ? "write" : "read", data, - (addr & 0x00fffffc)); + nvkm_error(subdev, "MMIO %s of %08x FAULT at %06x\n", + (addr & 0x00000002) ? "write" : "read", data, + (addr & 0x00fffffc)); stat &= ~0x00000008; - nv_wr32(pbus, 0x001100, 0x00000008); + nvkm_wr32(device, 0x001100, 0x00000008); } if (stat & 0x00070000) { - subdev = nvkm_subdev(pbus, NVDEV_SUBDEV_THERM); - if (subdev && subdev->intr) - subdev->intr(subdev); + struct nvkm_therm *therm = device->therm; + if (therm) + nvkm_subdev_intr(&therm->subdev); stat &= ~0x00070000; - nv_wr32(pbus, 0x001100, 0x00070000); + nvkm_wr32(device, 0x001100, 0x00070000); } if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0x00000000); + nvkm_error(subdev, "intr %08x\n", stat); + nvkm_mask(device, 0x001140, stat, 0x00000000); } } -static int -nv31_bus_init(struct nvkm_object *object) +static void +nv31_bus_init(struct nvkm_bus *bus) { - struct nv04_bus_priv *priv = (void *)object; - int ret; - - ret = nvkm_bus_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x00070008); - return 0; + struct nvkm_device *device = bus->subdev.device; + nvkm_wr32(device, 0x001100, 0xffffffff); + nvkm_wr32(device, 0x001140, 0x00070008); } -struct nvkm_oclass * -nv31_bus_oclass = &(struct nv04_bus_impl) { - .base.handle = NV_SUBDEV(BUS, 0x31), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_bus_ctor, - .dtor = _nvkm_bus_dtor, - .init = nv31_bus_init, - .fini = _nvkm_bus_fini, - }, +static const struct nvkm_bus_func +nv31_bus = { + .init = nv31_bus_init, .intr = nv31_bus_intr, -}.base; +}; + +int +nv31_bus_new(struct nvkm_device *device, int index, struct nvkm_bus **pbus) +{ + return nvkm_bus_new_(&nv31_bus, device, index, pbus); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c index 1987863d7..19e10fdc9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c @@ -22,83 +22,84 @@ * Authors: Martin Peres * Ben Skeggs */ -#include "nv04.h" +#include "priv.h" +#include #include static int -nv50_bus_hwsq_exec(struct nvkm_bus *pbus, u32 *data, u32 size) +nv50_bus_hwsq_exec(struct nvkm_bus *bus, u32 *data, u32 size) { - struct nv50_bus_priv *priv = (void *)pbus; + struct nvkm_device *device = bus->subdev.device; int i; - nv_mask(pbus, 0x001098, 0x00000008, 0x00000000); - nv_wr32(pbus, 0x001304, 0x00000000); + nvkm_mask(device, 0x001098, 0x00000008, 0x00000000); + nvkm_wr32(device, 0x001304, 0x00000000); for (i = 0; i < size; i++) - nv_wr32(priv, 0x001400 + (i * 4), data[i]); - nv_mask(pbus, 0x001098, 0x00000018, 0x00000018); - nv_wr32(pbus, 0x00130c, 0x00000003); + nvkm_wr32(device, 0x001400 + (i * 4), data[i]); + nvkm_mask(device, 0x001098, 0x00000018, 0x00000018); + nvkm_wr32(device, 0x00130c, 0x00000003); - return nv_wait(pbus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x001308) & 0x00000100)) + break; + ) < 0) + return -ETIMEDOUT; + + return 0; } void -nv50_bus_intr(struct nvkm_subdev *subdev) +nv50_bus_intr(struct nvkm_bus *bus) { - struct nvkm_bus *pbus = nvkm_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); + struct nvkm_subdev *subdev = &bus->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x001100) & nvkm_rd32(device, 0x001140); if (stat & 0x00000008) { - u32 addr = nv_rd32(pbus, 0x009084); - u32 data = nv_rd32(pbus, 0x009088); + u32 addr = nvkm_rd32(device, 0x009084); + u32 data = nvkm_rd32(device, 0x009088); - nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", - (addr & 0x00000002) ? "write" : "read", data, - (addr & 0x00fffffc)); + nvkm_error(subdev, "MMIO %s of %08x FAULT at %06x\n", + (addr & 0x00000002) ? "write" : "read", data, + (addr & 0x00fffffc)); stat &= ~0x00000008; - nv_wr32(pbus, 0x001100, 0x00000008); + nvkm_wr32(device, 0x001100, 0x00000008); } if (stat & 0x00010000) { - subdev = nvkm_subdev(pbus, NVDEV_SUBDEV_THERM); - if (subdev && subdev->intr) - subdev->intr(subdev); + struct nvkm_therm *therm = device->therm; + if (therm) + nvkm_subdev_intr(&therm->subdev); stat &= ~0x00010000; - nv_wr32(pbus, 0x001100, 0x00010000); + nvkm_wr32(device, 0x001100, 0x00010000); } if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0); + nvkm_error(subdev, "intr %08x\n", stat); + nvkm_mask(device, 0x001140, stat, 0); } } -int -nv50_bus_init(struct nvkm_object *object) +void +nv50_bus_init(struct nvkm_bus *bus) { - struct nv04_bus_priv *priv = (void *)object; - int ret; - - ret = nvkm_bus_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x00010008); - return 0; + struct nvkm_device *device = bus->subdev.device; + nvkm_wr32(device, 0x001100, 0xffffffff); + nvkm_wr32(device, 0x001140, 0x00010008); } -struct nvkm_oclass * -nv50_bus_oclass = &(struct nv04_bus_impl) { - .base.handle = NV_SUBDEV(BUS, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_bus_ctor, - .dtor = _nvkm_bus_dtor, - .init = nv50_bus_init, - .fini = _nvkm_bus_fini, - }, +static const struct nvkm_bus_func +nv50_bus = { + .init = nv50_bus_init, .intr = nv50_bus_intr, .hwsq_exec = nv50_bus_hwsq_exec, .hwsq_size = 64, -}.base; +}; + +int +nv50_bus_new(struct nvkm_device *device, int index, struct nvkm_bus **pbus) +{ + return nvkm_bus_new_(&nv50_bus, device, index, pbus); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h new file mode 100644 index 000000000..a130f2c64 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h @@ -0,0 +1,18 @@ +#ifndef __NVKM_BUS_PRIV_H__ +#define __NVKM_BUS_PRIV_H__ +#define nvkm_bus(p) container_of((p), struct nvkm_bus, subdev) +#include + +struct nvkm_bus_func { + void (*init)(struct nvkm_bus *); + void (*intr)(struct nvkm_bus *); + int (*hwsq_exec)(struct nvkm_bus *, u32 *, u32); + u32 hwsq_size; +}; + +int nvkm_bus_new_(const struct nvkm_bus_func *, struct nvkm_device *, int, + struct nvkm_bus **); + +void nv50_bus_init(struct nvkm_bus *); +void nv50_bus_intr(struct nvkm_bus *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild index 9c2f688c9..ed7717bcc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild @@ -8,5 +8,6 @@ nvkm-y += nvkm/subdev/clk/mcp77.o nvkm-y += nvkm/subdev/clk/gf100.o nvkm-y += nvkm/subdev/clk/gk104.o nvkm-y += nvkm/subdev/clk/gk20a.o + nvkm-y += nvkm/subdev/clk/pllnv04.o nvkm-y += nvkm/subdev/clk/pllgt215.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index 39a83d82e..dc8682c91 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -21,7 +21,8 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" + #include #include #include @@ -30,7 +31,6 @@ #include #include -#include #include /****************************************************************************** @@ -40,7 +40,7 @@ static u32 nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, u8 pstate, u8 domain, u32 input) { - struct nvkm_bios *bios = nvkm_bios(clk); + struct nvkm_bios *bios = clk->subdev.device->bios; struct nvbios_boostE boostE; u8 ver, hdr, cnt, len; u16 data; @@ -77,8 +77,10 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, static int nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) { - struct nvkm_therm *ptherm = nvkm_therm(clk); - struct nvkm_volt *volt = nvkm_volt(clk); + struct nvkm_subdev *subdev = &clk->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_therm *therm = device->therm; + struct nvkm_volt *volt = device->volt; struct nvkm_cstate *cstate; int ret; @@ -88,41 +90,41 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) cstate = &pstate->base; } - if (ptherm) { - ret = nvkm_therm_cstate(ptherm, pstate->fanspeed, +1); + if (therm) { + ret = nvkm_therm_cstate(therm, pstate->fanspeed, +1); if (ret && ret != -ENODEV) { - nv_error(clk, "failed to raise fan speed: %d\n", ret); + nvkm_error(subdev, "failed to raise fan speed: %d\n", ret); return ret; } } if (volt) { - ret = volt->set_id(volt, cstate->voltage, +1); + ret = nvkm_volt_set_id(volt, cstate->voltage, +1); if (ret && ret != -ENODEV) { - nv_error(clk, "failed to raise voltage: %d\n", ret); + nvkm_error(subdev, "failed to raise voltage: %d\n", ret); return ret; } } - ret = clk->calc(clk, cstate); + ret = clk->func->calc(clk, cstate); if (ret == 0) { - ret = clk->prog(clk); - clk->tidy(clk); + ret = clk->func->prog(clk); + clk->func->tidy(clk); } if (volt) { - ret = volt->set_id(volt, cstate->voltage, -1); + ret = nvkm_volt_set_id(volt, cstate->voltage, -1); if (ret && ret != -ENODEV) - nv_error(clk, "failed to lower voltage: %d\n", ret); + nvkm_error(subdev, "failed to lower voltage: %d\n", ret); } - if (ptherm) { - ret = nvkm_therm_cstate(ptherm, pstate->fanspeed, -1); + if (therm) { + ret = nvkm_therm_cstate(therm, pstate->fanspeed, -1); if (ret && ret != -ENODEV) - nv_error(clk, "failed to lower fan speed: %d\n", ret); + nvkm_error(subdev, "failed to lower fan speed: %d\n", ret); } - return 0; + return ret; } static void @@ -135,8 +137,8 @@ nvkm_cstate_del(struct nvkm_cstate *cstate) static int nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) { - struct nvkm_bios *bios = nvkm_bios(clk); - struct nvkm_domain *domain = clk->domains; + struct nvkm_bios *bios = clk->subdev.device->bios; + const struct nvkm_domain *domain = clk->domains; struct nvkm_cstate *cstate = NULL; struct nvbios_cstepX cstepX; u8 ver, hdr; @@ -172,7 +174,8 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) static int nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) { - struct nvkm_fb *pfb = nvkm_fb(clk); + struct nvkm_subdev *subdev = &clk->subdev; + struct nvkm_ram *ram = subdev->device->fb->ram; struct nvkm_pstate *pstate; int ret, idx = 0; @@ -181,17 +184,17 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) break; } - nv_debug(clk, "setting performance state %d\n", pstatei); + nvkm_debug(subdev, "setting performance state %d\n", pstatei); clk->pstate = pstatei; - if (pfb->ram && pfb->ram->calc) { + if (ram && ram->func->calc) { int khz = pstate->base.domain[nv_clk_src_mem]; do { - ret = pfb->ram->calc(pfb, khz); + ret = ram->func->calc(ram, khz); if (ret == 0) - ret = pfb->ram->prog(pfb); + ret = ram->func->prog(ram); } while (ret > 0); - pfb->ram->tidy(pfb); + ram->func->tidy(ram); } return nvkm_cstate_prog(clk, pstate, 0); @@ -201,31 +204,32 @@ static void nvkm_pstate_work(struct work_struct *work) { struct nvkm_clk *clk = container_of(work, typeof(*clk), work); + struct nvkm_subdev *subdev = &clk->subdev; int pstate; if (!atomic_xchg(&clk->waiting, 0)) return; clk->pwrsrc = power_supply_is_system_supplied(); - nv_trace(clk, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n", - clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc, - clk->astate, clk->tstate, clk->dstate); + nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n", + clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc, + clk->astate, clk->tstate, clk->dstate); pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc; if (clk->state_nr && pstate != -1) { pstate = (pstate < 0) ? clk->astate : pstate; - pstate = min(pstate, clk->state_nr - 1 - clk->tstate); + pstate = min(pstate, clk->state_nr - 1 + clk->tstate); pstate = max(pstate, clk->dstate); } else { pstate = clk->pstate = -1; } - nv_trace(clk, "-> %d\n", pstate); + nvkm_trace(subdev, "-> %d\n", pstate); if (pstate != clk->pstate) { int ret = nvkm_pstate_prog(clk, pstate); if (ret) { - nv_error(clk, "error setting pstate %d: %d\n", - pstate, ret); + nvkm_error(subdev, "error setting pstate %d: %d\n", + pstate, ret); } } @@ -246,8 +250,9 @@ nvkm_pstate_calc(struct nvkm_clk *clk, bool wait) static void nvkm_pstate_info(struct nvkm_clk *clk, struct nvkm_pstate *pstate) { - struct nvkm_domain *clock = clk->domains - 1; + const struct nvkm_domain *clock = clk->domains - 1; struct nvkm_cstate *cstate; + struct nvkm_subdev *subdev = &clk->subdev; char info[3][32] = { "", "", "" }; char name[4] = "--"; int i = -1; @@ -261,12 +266,12 @@ nvkm_pstate_info(struct nvkm_clk *clk, struct nvkm_pstate *pstate) if (hi == 0) continue; - nv_debug(clk, "%02x: %10d KHz\n", clock->name, lo); + nvkm_debug(subdev, "%02x: %10d KHz\n", clock->name, lo); list_for_each_entry(cstate, &pstate->list, head) { u32 freq = cstate->domain[clock->name]; lo = min(lo, freq); hi = max(hi, freq); - nv_debug(clk, "%10d KHz\n", freq); + nvkm_debug(subdev, "%10d KHz\n", freq); } if (clock->mname && ++i < ARRAY_SIZE(info)) { @@ -282,7 +287,7 @@ nvkm_pstate_info(struct nvkm_clk *clk, struct nvkm_pstate *pstate) } } - nv_info(clk, "%s: %s %s %s\n", name, info[0], info[1], info[2]); + nvkm_debug(subdev, "%s: %s %s %s\n", name, info[0], info[1], info[2]); } static void @@ -301,8 +306,8 @@ nvkm_pstate_del(struct nvkm_pstate *pstate) static int nvkm_pstate_new(struct nvkm_clk *clk, int idx) { - struct nvkm_bios *bios = nvkm_bios(clk); - struct nvkm_domain *domain = clk->domains - 1; + struct nvkm_bios *bios = clk->subdev.device->bios; + const struct nvkm_domain *domain = clk->domains - 1; struct nvkm_pstate *pstate; struct nvkm_cstate *cstate; struct nvbios_cstepE cstepE; @@ -471,32 +476,37 @@ nvkm_clk_pwrsrc(struct nvkm_notify *notify) *****************************************************************************/ int -_nvkm_clk_fini(struct nvkm_object *object, bool suspend) +nvkm_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +{ + return clk->func->read(clk, src); +} + +static int +nvkm_clk_fini(struct nvkm_subdev *subdev, bool suspend) { - struct nvkm_clk *clk = (void *)object; + struct nvkm_clk *clk = nvkm_clk(subdev); nvkm_notify_put(&clk->pwrsrc_ntfy); - return nvkm_subdev_fini(&clk->base, suspend); + flush_work(&clk->work); + if (clk->func->fini) + clk->func->fini(clk); + return 0; } -int -_nvkm_clk_init(struct nvkm_object *object) +static int +nvkm_clk_init(struct nvkm_subdev *subdev) { - struct nvkm_clk *clk = (void *)object; - struct nvkm_domain *clock = clk->domains; + struct nvkm_clk *clk = nvkm_clk(subdev); + const struct nvkm_domain *clock = clk->domains; int ret; - ret = nvkm_subdev_init(&clk->base); - if (ret) - return ret; - memset(&clk->bstate, 0x00, sizeof(clk->bstate)); INIT_LIST_HEAD(&clk->bstate.list); clk->bstate.pstate = 0xff; while (clock->name != nv_clk_src_max) { - ret = clk->read(clk, clock->name); + ret = nvkm_clk_read(clk, clock->name); if (ret < 0) { - nv_error(clk, "%02x freq unknown\n", clock->name); + nvkm_error(subdev, "%02x freq unknown\n", clock->name); return ret; } clk->bstate.base.domain[clock->name] = ret; @@ -505,6 +515,9 @@ _nvkm_clk_init(struct nvkm_object *object) nvkm_pstate_info(clk, &clk->bstate); + if (clk->func->init) + return clk->func->init(clk); + clk->astate = clk->state_nr - 1; clk->tstate = 0; clk->dstate = 0; @@ -513,61 +526,63 @@ _nvkm_clk_init(struct nvkm_object *object) return 0; } -void -_nvkm_clk_dtor(struct nvkm_object *object) +static void * +nvkm_clk_dtor(struct nvkm_subdev *subdev) { - struct nvkm_clk *clk = (void *)object; + struct nvkm_clk *clk = nvkm_clk(subdev); struct nvkm_pstate *pstate, *temp; nvkm_notify_fini(&clk->pwrsrc_ntfy); + /* Early return if the pstates have been provided statically */ + if (clk->func->pstates) + return clk; + list_for_each_entry_safe(pstate, temp, &clk->states, head) { nvkm_pstate_del(pstate); } - nvkm_subdev_destroy(&clk->base); + return clk; } +static const struct nvkm_subdev_func +nvkm_clk = { + .dtor = nvkm_clk_dtor, + .init = nvkm_clk_init, + .fini = nvkm_clk_fini, +}; + int -nvkm_clk_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, struct nvkm_domain *clocks, - struct nvkm_pstate *pstates, int nb_pstates, - bool allow_reclock, int length, void **object) +nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device, + int index, bool allow_reclock, struct nvkm_clk *clk) { - struct nvkm_device *device = nv_device(parent); - struct nvkm_clk *clk; int ret, idx, arglen; const char *mode; - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "CLK", - "clock", length, object); - clk = *object; - if (ret) - return ret; - + nvkm_subdev_ctor(&nvkm_clk, device, index, 0, &clk->subdev); + clk->func = func; INIT_LIST_HEAD(&clk->states); - clk->domains = clocks; + clk->domains = func->domains; clk->ustate_ac = -1; clk->ustate_dc = -1; + clk->allow_reclock = allow_reclock; INIT_WORK(&clk->work, nvkm_pstate_work); init_waitqueue_head(&clk->wait); atomic_set(&clk->waiting, 0); /* If no pstates are provided, try and fetch them from the BIOS */ - if (!pstates) { + if (!func->pstates) { idx = 0; do { ret = nvkm_pstate_new(clk, idx++); } while (ret == 0); } else { - for (idx = 0; idx < nb_pstates; idx++) - list_add_tail(&pstates[idx].head, &clk->states); - clk->state_nr = nb_pstates; + for (idx = 0; idx < func->nr_pstates; idx++) + list_add_tail(&func->pstates[idx].head, &clk->states); + clk->state_nr = func->nr_pstates; } - clk->allow_reclock = allow_reclock; - ret = nvkm_notify_init(NULL, &device->event, nvkm_clk_pwrsrc, true, NULL, 0, 0, &clk->pwrsrc_ntfy); if (ret) @@ -589,3 +604,12 @@ nvkm_clk_create_(struct nvkm_object *parent, struct nvkm_object *engine, return 0; } + +int +nvkm_clk_new_(const struct nvkm_clk_func *func, struct nvkm_device *device, + int index, bool allow_reclock, struct nvkm_clk **pclk) +{ + if (!(*pclk = kzalloc(sizeof(**pclk), GFP_KERNEL))) + return -ENOMEM; + return nvkm_clk_ctor(func, device, index, allow_reclock, *pclk); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c index 4c90b9769..f97e3ec19 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c @@ -23,25 +23,26 @@ */ #include "nv50.h" -static struct nvkm_domain -g84_domains[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_href , 0xff }, - { nv_clk_src_core , 0xff, 0, "core", 1000 }, - { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, - { nv_clk_src_mem , 0xff, 0, "memory", 1000 }, - { nv_clk_src_vdec , 0xff }, - { nv_clk_src_max } +static const struct nvkm_clk_func +g84_clk = { + .read = nv50_clk_read, + .calc = nv50_clk_calc, + .prog = nv50_clk_prog, + .tidy = nv50_clk_tidy, + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_core , 0xff, 0, "core", 1000 }, + { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, + { nv_clk_src_mem , 0xff, 0, "memory", 1000 }, + { nv_clk_src_vdec , 0xff }, + { nv_clk_src_max } + } }; -struct nvkm_oclass * -g84_clk_oclass = &(struct nv50_clk_oclass) { - .base.handle = NV_SUBDEV(CLK, 0x84), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, - .domains = g84_domains, -}.base; +int +g84_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) +{ + return nv50_clk_new_(&g84_clk, device, index, + (device->chipset >= 0x94), pclk); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c index 3d7330d54..a52b7e7fc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c @@ -21,10 +21,10 @@ * * Authors: Ben Skeggs */ -#include +#define gf100_clk(p) container_of((p), struct gf100_clk, base) +#include "priv.h" #include "pll.h" -#include #include #include #include @@ -38,29 +38,29 @@ struct gf100_clk_info { u32 coef; }; -struct gf100_clk_priv { +struct gf100_clk { struct nvkm_clk base; struct gf100_clk_info eng[16]; }; -static u32 read_div(struct gf100_clk_priv *, int, u32, u32); +static u32 read_div(struct gf100_clk *, int, u32, u32); static u32 -read_vco(struct gf100_clk_priv *priv, u32 dsrc) +read_vco(struct gf100_clk *clk, u32 dsrc) { - struct nvkm_clk *clk = &priv->base; - u32 ssrc = nv_rd32(priv, dsrc); + struct nvkm_device *device = clk->base.subdev.device; + u32 ssrc = nvkm_rd32(device, dsrc); if (!(ssrc & 0x00000100)) - return clk->read(clk, nv_clk_src_sppll0); - return clk->read(clk, nv_clk_src_sppll1); + return nvkm_clk_read(&clk->base, nv_clk_src_sppll0); + return nvkm_clk_read(&clk->base, nv_clk_src_sppll1); } static u32 -read_pll(struct gf100_clk_priv *priv, u32 pll) +read_pll(struct gf100_clk *clk, u32 pll) { - struct nvkm_clk *clk = &priv->base; - u32 ctrl = nv_rd32(priv, pll + 0x00); - u32 coef = nv_rd32(priv, pll + 0x04); + struct nvkm_device *device = clk->base.subdev.device; + u32 ctrl = nvkm_rd32(device, pll + 0x00); + u32 coef = nvkm_rd32(device, pll + 0x04); u32 P = (coef & 0x003f0000) >> 16; u32 N = (coef & 0x0000ff00) >> 8; u32 M = (coef & 0x000000ff) >> 0; @@ -72,20 +72,20 @@ read_pll(struct gf100_clk_priv *priv, u32 pll) switch (pll) { case 0x00e800: case 0x00e820: - sclk = nv_device(priv)->crystal; + sclk = device->crystal; P = 1; break; case 0x132000: - sclk = clk->read(clk, nv_clk_src_mpllsrc); + sclk = nvkm_clk_read(&clk->base, nv_clk_src_mpllsrc); break; case 0x132020: - sclk = clk->read(clk, nv_clk_src_mpllsrcref); + sclk = nvkm_clk_read(&clk->base, nv_clk_src_mpllsrcref); break; case 0x137000: case 0x137020: case 0x137040: case 0x1370e0: - sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140); + sclk = read_div(clk, (pll & 0xff) / 0x20, 0x137120, 0x137140); break; default: return 0; @@ -95,46 +95,48 @@ read_pll(struct gf100_clk_priv *priv, u32 pll) } static u32 -read_div(struct gf100_clk_priv *priv, int doff, u32 dsrc, u32 dctl) +read_div(struct gf100_clk *clk, int doff, u32 dsrc, u32 dctl) { - u32 ssrc = nv_rd32(priv, dsrc + (doff * 4)); - u32 sctl = nv_rd32(priv, dctl + (doff * 4)); + struct nvkm_device *device = clk->base.subdev.device; + u32 ssrc = nvkm_rd32(device, dsrc + (doff * 4)); + u32 sctl = nvkm_rd32(device, dctl + (doff * 4)); switch (ssrc & 0x00000003) { case 0: if ((ssrc & 0x00030000) != 0x00030000) - return nv_device(priv)->crystal; + return device->crystal; return 108000; case 2: return 100000; case 3: if (sctl & 0x80000000) { - u32 sclk = read_vco(priv, dsrc + (doff * 4)); + u32 sclk = read_vco(clk, dsrc + (doff * 4)); u32 sdiv = (sctl & 0x0000003f) + 2; return (sclk * 2) / sdiv; } - return read_vco(priv, dsrc + (doff * 4)); + return read_vco(clk, dsrc + (doff * 4)); default: return 0; } } static u32 -read_clk(struct gf100_clk_priv *priv, int clk) +read_clk(struct gf100_clk *clk, int idx) { - u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4)); - u32 ssel = nv_rd32(priv, 0x137100); + struct nvkm_device *device = clk->base.subdev.device; + u32 sctl = nvkm_rd32(device, 0x137250 + (idx * 4)); + u32 ssel = nvkm_rd32(device, 0x137100); u32 sclk, sdiv; - if (ssel & (1 << clk)) { - if (clk < 7) - sclk = read_pll(priv, 0x137000 + (clk * 0x20)); + if (ssel & (1 << idx)) { + if (idx < 7) + sclk = read_pll(clk, 0x137000 + (idx * 0x20)); else - sclk = read_pll(priv, 0x1370e0); + sclk = read_pll(clk, 0x1370e0); sdiv = ((sctl & 0x00003f00) >> 8) + 2; } else { - sclk = read_div(priv, clk, 0x137160, 0x1371d0); + sclk = read_div(clk, idx, 0x137160, 0x1371d0); sdiv = ((sctl & 0x0000003f) >> 0) + 2; } @@ -145,10 +147,11 @@ read_clk(struct gf100_clk_priv *priv, int clk) } static int -gf100_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +gf100_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct nvkm_device *device = nv_device(clk); - struct gf100_clk_priv *priv = (void *)clk; + struct gf100_clk *clk = gf100_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; switch (src) { case nv_clk_src_crystal: @@ -156,47 +159,47 @@ gf100_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) case nv_clk_src_href: return 100000; case nv_clk_src_sppll0: - return read_pll(priv, 0x00e800); + return read_pll(clk, 0x00e800); case nv_clk_src_sppll1: - return read_pll(priv, 0x00e820); + return read_pll(clk, 0x00e820); case nv_clk_src_mpllsrcref: - return read_div(priv, 0, 0x137320, 0x137330); + return read_div(clk, 0, 0x137320, 0x137330); case nv_clk_src_mpllsrc: - return read_pll(priv, 0x132020); + return read_pll(clk, 0x132020); case nv_clk_src_mpll: - return read_pll(priv, 0x132000); + return read_pll(clk, 0x132000); case nv_clk_src_mdiv: - return read_div(priv, 0, 0x137300, 0x137310); + return read_div(clk, 0, 0x137300, 0x137310); case nv_clk_src_mem: - if (nv_rd32(priv, 0x1373f0) & 0x00000002) - return clk->read(clk, nv_clk_src_mpll); - return clk->read(clk, nv_clk_src_mdiv); + if (nvkm_rd32(device, 0x1373f0) & 0x00000002) + return nvkm_clk_read(&clk->base, nv_clk_src_mpll); + return nvkm_clk_read(&clk->base, nv_clk_src_mdiv); case nv_clk_src_gpc: - return read_clk(priv, 0x00); + return read_clk(clk, 0x00); case nv_clk_src_rop: - return read_clk(priv, 0x01); + return read_clk(clk, 0x01); case nv_clk_src_hubk07: - return read_clk(priv, 0x02); + return read_clk(clk, 0x02); case nv_clk_src_hubk06: - return read_clk(priv, 0x07); + return read_clk(clk, 0x07); case nv_clk_src_hubk01: - return read_clk(priv, 0x08); + return read_clk(clk, 0x08); case nv_clk_src_copy: - return read_clk(priv, 0x09); + return read_clk(clk, 0x09); case nv_clk_src_daemon: - return read_clk(priv, 0x0c); + return read_clk(clk, 0x0c); case nv_clk_src_vdec: - return read_clk(priv, 0x0e); + return read_clk(clk, 0x0e); default: - nv_error(clk, "invalid clock source %d\n", src); + nvkm_error(subdev, "invalid clock source %d\n", src); return -EINVAL; } } static u32 -calc_div(struct gf100_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv) +calc_div(struct gf100_clk *clk, int idx, u32 ref, u32 freq, u32 *ddiv) { u32 div = min((ref * 2) / freq, (u32)65); if (div < 2) @@ -207,7 +210,7 @@ calc_div(struct gf100_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv) } static u32 -calc_src(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv) +calc_src(struct gf100_clk *clk, int idx, u32 freq, u32 *dsrc, u32 *ddiv) { u32 sclk; @@ -229,28 +232,29 @@ calc_src(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv) } /* otherwise, calculate the closest divider */ - sclk = read_vco(priv, 0x137160 + (clk * 4)); - if (clk < 7) - sclk = calc_div(priv, clk, sclk, freq, ddiv); + sclk = read_vco(clk, 0x137160 + (idx * 4)); + if (idx < 7) + sclk = calc_div(clk, idx, sclk, freq, ddiv); return sclk; } static u32 -calc_pll(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *coef) +calc_pll(struct gf100_clk *clk, int idx, u32 freq, u32 *coef) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvbios_pll limits; int N, M, P, ret; - ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); + ret = nvbios_pll_parse(bios, 0x137000 + (idx * 0x20), &limits); if (ret) return 0; - limits.refclk = read_div(priv, clk, 0x137120, 0x137140); + limits.refclk = read_div(clk, idx, 0x137120, 0x137140); if (!limits.refclk) return 0; - ret = gt215_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P); + ret = gt215_pll_calc(subdev, &limits, freq, &N, NULL, &M, &P); if (ret <= 0) return 0; @@ -259,10 +263,9 @@ calc_pll(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *coef) } static int -calc_clk(struct gf100_clk_priv *priv, - struct nvkm_cstate *cstate, int clk, int dom) +calc_clk(struct gf100_clk *clk, struct nvkm_cstate *cstate, int idx, int dom) { - struct gf100_clk_info *info = &priv->eng[clk]; + struct gf100_clk_info *info = &clk->eng[idx]; u32 freq = cstate->domain[dom]; u32 src0, div0, div1D, div1P = 0; u32 clk0, clk1 = 0; @@ -272,16 +275,16 @@ calc_clk(struct gf100_clk_priv *priv, return 0; /* first possible path, using only dividers */ - clk0 = calc_src(priv, clk, freq, &src0, &div0); - clk0 = calc_div(priv, clk, clk0, freq, &div1D); + clk0 = calc_src(clk, idx, freq, &src0, &div0); + clk0 = calc_div(clk, idx, clk0, freq, &div1D); /* see if we can get any closer using PLLs */ - if (clk0 != freq && (0x00004387 & (1 << clk))) { - if (clk <= 7) - clk1 = calc_pll(priv, clk, freq, &info->coef); + if (clk0 != freq && (0x00004387 & (1 << idx))) { + if (idx <= 7) + clk1 = calc_pll(clk, idx, freq, &info->coef); else clk1 = cstate->domain[nv_clk_src_hubk06]; - clk1 = calc_div(priv, clk, clk1, freq, &div1P); + clk1 = calc_div(clk, idx, clk1, freq, &div1P); } /* select the method which gets closest to target freq */ @@ -303,7 +306,7 @@ calc_clk(struct gf100_clk_priv *priv, info->mdiv |= 0x80000000; info->mdiv |= div1P << 8; } - info->ssel = (1 << clk); + info->ssel = (1 << idx); info->freq = clk1; } @@ -311,81 +314,96 @@ calc_clk(struct gf100_clk_priv *priv, } static int -gf100_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +gf100_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct gf100_clk_priv *priv = (void *)clk; + struct gf100_clk *clk = gf100_clk(base); int ret; - if ((ret = calc_clk(priv, cstate, 0x00, nv_clk_src_gpc)) || - (ret = calc_clk(priv, cstate, 0x01, nv_clk_src_rop)) || - (ret = calc_clk(priv, cstate, 0x02, nv_clk_src_hubk07)) || - (ret = calc_clk(priv, cstate, 0x07, nv_clk_src_hubk06)) || - (ret = calc_clk(priv, cstate, 0x08, nv_clk_src_hubk01)) || - (ret = calc_clk(priv, cstate, 0x09, nv_clk_src_copy)) || - (ret = calc_clk(priv, cstate, 0x0c, nv_clk_src_daemon)) || - (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec))) + if ((ret = calc_clk(clk, cstate, 0x00, nv_clk_src_gpc)) || + (ret = calc_clk(clk, cstate, 0x01, nv_clk_src_rop)) || + (ret = calc_clk(clk, cstate, 0x02, nv_clk_src_hubk07)) || + (ret = calc_clk(clk, cstate, 0x07, nv_clk_src_hubk06)) || + (ret = calc_clk(clk, cstate, 0x08, nv_clk_src_hubk01)) || + (ret = calc_clk(clk, cstate, 0x09, nv_clk_src_copy)) || + (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_daemon)) || + (ret = calc_clk(clk, cstate, 0x0e, nv_clk_src_vdec))) return ret; return 0; } static void -gf100_clk_prog_0(struct gf100_clk_priv *priv, int clk) +gf100_clk_prog_0(struct gf100_clk *clk, int idx) { - struct gf100_clk_info *info = &priv->eng[clk]; - if (clk < 7 && !info->ssel) { - nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); - nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc); + struct gf100_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; + if (idx < 7 && !info->ssel) { + nvkm_mask(device, 0x1371d0 + (idx * 0x04), 0x80003f3f, info->ddiv); + nvkm_wr32(device, 0x137160 + (idx * 0x04), info->dsrc); } } static void -gf100_clk_prog_1(struct gf100_clk_priv *priv, int clk) +gf100_clk_prog_1(struct gf100_clk *clk, int idx) { - nv_mask(priv, 0x137100, (1 << clk), 0x00000000); - nv_wait(priv, 0x137100, (1 << clk), 0x00000000); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, 0x137100, (1 << idx), 0x00000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x137100) & (1 << idx))) + break; + ); } static void -gf100_clk_prog_2(struct gf100_clk_priv *priv, int clk) +gf100_clk_prog_2(struct gf100_clk *clk, int idx) { - struct gf100_clk_info *info = &priv->eng[clk]; - const u32 addr = 0x137000 + (clk * 0x20); - if (clk <= 7) { - nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000); - nv_mask(priv, addr + 0x00, 0x00000001, 0x00000000); + struct gf100_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; + const u32 addr = 0x137000 + (idx * 0x20); + if (idx <= 7) { + nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000000); + nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000000); if (info->coef) { - nv_wr32(priv, addr + 0x04, info->coef); - nv_mask(priv, addr + 0x00, 0x00000001, 0x00000001); - nv_wait(priv, addr + 0x00, 0x00020000, 0x00020000); - nv_mask(priv, addr + 0x00, 0x00020004, 0x00000004); + nvkm_wr32(device, addr + 0x04, info->coef); + nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, addr + 0x00) & 0x00020000) + break; + ); + nvkm_mask(device, addr + 0x00, 0x00020004, 0x00000004); } } } static void -gf100_clk_prog_3(struct gf100_clk_priv *priv, int clk) +gf100_clk_prog_3(struct gf100_clk *clk, int idx) { - struct gf100_clk_info *info = &priv->eng[clk]; + struct gf100_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; if (info->ssel) { - nv_mask(priv, 0x137100, (1 << clk), info->ssel); - nv_wait(priv, 0x137100, (1 << clk), info->ssel); + nvkm_mask(device, 0x137100, (1 << idx), info->ssel); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x137100) & (1 << idx); + if (tmp == info->ssel) + break; + ); } } static void -gf100_clk_prog_4(struct gf100_clk_priv *priv, int clk) +gf100_clk_prog_4(struct gf100_clk *clk, int idx) { - struct gf100_clk_info *info = &priv->eng[clk]; - nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); + struct gf100_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, 0x137250 + (idx * 0x04), 0x00003f3f, info->mdiv); } static int -gf100_clk_prog(struct nvkm_clk *clk) +gf100_clk_prog(struct nvkm_clk *base) { - struct gf100_clk_priv *priv = (void *)clk; + struct gf100_clk *clk = gf100_clk(base); struct { - void (*exec)(struct gf100_clk_priv *, int); + void (*exec)(struct gf100_clk *, int); } stage[] = { { gf100_clk_prog_0 }, /* div programming */ { gf100_clk_prog_1 }, /* select div mode */ @@ -396,10 +414,10 @@ gf100_clk_prog(struct nvkm_clk *clk) int i, j; for (i = 0; i < ARRAY_SIZE(stage); i++) { - for (j = 0; j < ARRAY_SIZE(priv->eng); j++) { - if (!priv->eng[j].freq) + for (j = 0; j < ARRAY_SIZE(clk->eng); j++) { + if (!clk->eng[j].freq) continue; - stage[i].exec(priv, j); + stage[i].exec(clk, j); } } @@ -407,56 +425,42 @@ gf100_clk_prog(struct nvkm_clk *clk) } static void -gf100_clk_tidy(struct nvkm_clk *clk) +gf100_clk_tidy(struct nvkm_clk *base) { - struct gf100_clk_priv *priv = (void *)clk; - memset(priv->eng, 0x00, sizeof(priv->eng)); + struct gf100_clk *clk = gf100_clk(base); + memset(clk->eng, 0x00, sizeof(clk->eng)); } -static struct nvkm_domain -gf100_domain[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_href , 0xff }, - { nv_clk_src_hubk06 , 0x00 }, - { nv_clk_src_hubk01 , 0x01 }, - { nv_clk_src_copy , 0x02 }, - { nv_clk_src_gpc , 0x03, 0, "core", 2000 }, - { nv_clk_src_rop , 0x04 }, - { nv_clk_src_mem , 0x05, 0, "memory", 1000 }, - { nv_clk_src_vdec , 0x06 }, - { nv_clk_src_daemon , 0x0a }, - { nv_clk_src_hubk07 , 0x0b }, - { nv_clk_src_max } +static const struct nvkm_clk_func +gf100_clk = { + .read = gf100_clk_read, + .calc = gf100_clk_calc, + .prog = gf100_clk_prog, + .tidy = gf100_clk_tidy, + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_hubk06 , 0x00 }, + { nv_clk_src_hubk01 , 0x01 }, + { nv_clk_src_copy , 0x02 }, + { nv_clk_src_gpc , 0x03, 0, "core", 2000 }, + { nv_clk_src_rop , 0x04 }, + { nv_clk_src_mem , 0x05, 0, "memory", 1000 }, + { nv_clk_src_vdec , 0x06 }, + { nv_clk_src_daemon , 0x0a }, + { nv_clk_src_hubk07 , 0x0b }, + { nv_clk_src_max } + } }; -static int -gf100_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gf100_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct gf100_clk_priv *priv; - int ret; + struct gf100_clk *clk; - ret = nvkm_clk_create(parent, engine, oclass, gf100_domain, - NULL, 0, false, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + *pclk = &clk->base; - priv->base.read = gf100_clk_read; - priv->base.calc = gf100_clk_calc; - priv->base.prog = gf100_clk_prog; - priv->base.tidy = gf100_clk_tidy; - return 0; + return nvkm_clk_ctor(&gf100_clk, device, index, false, &clk->base); } - -struct nvkm_oclass -gf100_clk_oclass = { - .handle = NV_SUBDEV(CLK, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c index e9b2310bd..396f7e4da 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c @@ -21,10 +21,10 @@ * * Authors: Ben Skeggs */ -#include +#define gk104_clk(p) container_of((p), struct gk104_clk, base) +#include "priv.h" #include "pll.h" -#include #include #include #include @@ -38,28 +38,30 @@ struct gk104_clk_info { u32 coef; }; -struct gk104_clk_priv { +struct gk104_clk { struct nvkm_clk base; struct gk104_clk_info eng[16]; }; -static u32 read_div(struct gk104_clk_priv *, int, u32, u32); -static u32 read_pll(struct gk104_clk_priv *, u32); +static u32 read_div(struct gk104_clk *, int, u32, u32); +static u32 read_pll(struct gk104_clk *, u32); static u32 -read_vco(struct gk104_clk_priv *priv, u32 dsrc) +read_vco(struct gk104_clk *clk, u32 dsrc) { - u32 ssrc = nv_rd32(priv, dsrc); + struct nvkm_device *device = clk->base.subdev.device; + u32 ssrc = nvkm_rd32(device, dsrc); if (!(ssrc & 0x00000100)) - return read_pll(priv, 0x00e800); - return read_pll(priv, 0x00e820); + return read_pll(clk, 0x00e800); + return read_pll(clk, 0x00e820); } static u32 -read_pll(struct gk104_clk_priv *priv, u32 pll) +read_pll(struct gk104_clk *clk, u32 pll) { - u32 ctrl = nv_rd32(priv, pll + 0x00); - u32 coef = nv_rd32(priv, pll + 0x04); + struct nvkm_device *device = clk->base.subdev.device; + u32 ctrl = nvkm_rd32(device, pll + 0x00); + u32 coef = nvkm_rd32(device, pll + 0x04); u32 P = (coef & 0x003f0000) >> 16; u32 N = (coef & 0x0000ff00) >> 8; u32 M = (coef & 0x000000ff) >> 0; @@ -72,22 +74,22 @@ read_pll(struct gk104_clk_priv *priv, u32 pll) switch (pll) { case 0x00e800: case 0x00e820: - sclk = nv_device(priv)->crystal; + sclk = device->crystal; P = 1; break; case 0x132000: - sclk = read_pll(priv, 0x132020); + sclk = read_pll(clk, 0x132020); P = (coef & 0x10000000) ? 2 : 1; break; case 0x132020: - sclk = read_div(priv, 0, 0x137320, 0x137330); - fN = nv_rd32(priv, pll + 0x10) >> 16; + sclk = read_div(clk, 0, 0x137320, 0x137330); + fN = nvkm_rd32(device, pll + 0x10) >> 16; break; case 0x137000: case 0x137020: case 0x137040: case 0x1370e0: - sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140); + sclk = read_div(clk, (pll & 0xff) / 0x20, 0x137120, 0x137140); break; default: return 0; @@ -101,70 +103,73 @@ read_pll(struct gk104_clk_priv *priv, u32 pll) } static u32 -read_div(struct gk104_clk_priv *priv, int doff, u32 dsrc, u32 dctl) +read_div(struct gk104_clk *clk, int doff, u32 dsrc, u32 dctl) { - u32 ssrc = nv_rd32(priv, dsrc + (doff * 4)); - u32 sctl = nv_rd32(priv, dctl + (doff * 4)); + struct nvkm_device *device = clk->base.subdev.device; + u32 ssrc = nvkm_rd32(device, dsrc + (doff * 4)); + u32 sctl = nvkm_rd32(device, dctl + (doff * 4)); switch (ssrc & 0x00000003) { case 0: if ((ssrc & 0x00030000) != 0x00030000) - return nv_device(priv)->crystal; + return device->crystal; return 108000; case 2: return 100000; case 3: if (sctl & 0x80000000) { - u32 sclk = read_vco(priv, dsrc + (doff * 4)); + u32 sclk = read_vco(clk, dsrc + (doff * 4)); u32 sdiv = (sctl & 0x0000003f) + 2; return (sclk * 2) / sdiv; } - return read_vco(priv, dsrc + (doff * 4)); + return read_vco(clk, dsrc + (doff * 4)); default: return 0; } } static u32 -read_mem(struct gk104_clk_priv *priv) +read_mem(struct gk104_clk *clk) { - switch (nv_rd32(priv, 0x1373f4) & 0x0000000f) { - case 1: return read_pll(priv, 0x132020); - case 2: return read_pll(priv, 0x132000); + struct nvkm_device *device = clk->base.subdev.device; + switch (nvkm_rd32(device, 0x1373f4) & 0x0000000f) { + case 1: return read_pll(clk, 0x132020); + case 2: return read_pll(clk, 0x132000); default: return 0; } } static u32 -read_clk(struct gk104_clk_priv *priv, int clk) +read_clk(struct gk104_clk *clk, int idx) { - u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4)); + struct nvkm_device *device = clk->base.subdev.device; + u32 sctl = nvkm_rd32(device, 0x137250 + (idx * 4)); u32 sclk, sdiv; - if (clk < 7) { - u32 ssel = nv_rd32(priv, 0x137100); - if (ssel & (1 << clk)) { - sclk = read_pll(priv, 0x137000 + (clk * 0x20)); + if (idx < 7) { + u32 ssel = nvkm_rd32(device, 0x137100); + if (ssel & (1 << idx)) { + sclk = read_pll(clk, 0x137000 + (idx * 0x20)); sdiv = 1; } else { - sclk = read_div(priv, clk, 0x137160, 0x1371d0); + sclk = read_div(clk, idx, 0x137160, 0x1371d0); sdiv = 0; } } else { - u32 ssrc = nv_rd32(priv, 0x137160 + (clk * 0x04)); + u32 ssrc = nvkm_rd32(device, 0x137160 + (idx * 0x04)); if ((ssrc & 0x00000003) == 0x00000003) { - sclk = read_div(priv, clk, 0x137160, 0x1371d0); + sclk = read_div(clk, idx, 0x137160, 0x1371d0); if (ssrc & 0x00000100) { if (ssrc & 0x40000000) - sclk = read_pll(priv, 0x1370e0); + sclk = read_pll(clk, 0x1370e0); sdiv = 1; } else { sdiv = 0; } } else { - sclk = read_div(priv, clk, 0x137160, 0x1371d0); + sclk = read_div(clk, idx, 0x137160, 0x1371d0); sdiv = 0; } } @@ -181,10 +186,11 @@ read_clk(struct gk104_clk_priv *priv, int clk) } static int -gk104_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +gk104_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct nvkm_device *device = nv_device(clk); - struct gk104_clk_priv *priv = (void *)clk; + struct gk104_clk *clk = gk104_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; switch (src) { case nv_clk_src_crystal: @@ -192,29 +198,29 @@ gk104_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) case nv_clk_src_href: return 100000; case nv_clk_src_mem: - return read_mem(priv); + return read_mem(clk); case nv_clk_src_gpc: - return read_clk(priv, 0x00); + return read_clk(clk, 0x00); case nv_clk_src_rop: - return read_clk(priv, 0x01); + return read_clk(clk, 0x01); case nv_clk_src_hubk07: - return read_clk(priv, 0x02); + return read_clk(clk, 0x02); case nv_clk_src_hubk06: - return read_clk(priv, 0x07); + return read_clk(clk, 0x07); case nv_clk_src_hubk01: - return read_clk(priv, 0x08); + return read_clk(clk, 0x08); case nv_clk_src_daemon: - return read_clk(priv, 0x0c); + return read_clk(clk, 0x0c); case nv_clk_src_vdec: - return read_clk(priv, 0x0e); + return read_clk(clk, 0x0e); default: - nv_error(clk, "invalid clock source %d\n", src); + nvkm_error(subdev, "invalid clock source %d\n", src); return -EINVAL; } } static u32 -calc_div(struct gk104_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv) +calc_div(struct gk104_clk *clk, int idx, u32 ref, u32 freq, u32 *ddiv) { u32 div = min((ref * 2) / freq, (u32)65); if (div < 2) @@ -225,7 +231,7 @@ calc_div(struct gk104_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv) } static u32 -calc_src(struct gk104_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv) +calc_src(struct gk104_clk *clk, int idx, u32 freq, u32 *dsrc, u32 *ddiv) { u32 sclk; @@ -247,28 +253,29 @@ calc_src(struct gk104_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv) } /* otherwise, calculate the closest divider */ - sclk = read_vco(priv, 0x137160 + (clk * 4)); - if (clk < 7) - sclk = calc_div(priv, clk, sclk, freq, ddiv); + sclk = read_vco(clk, 0x137160 + (idx * 4)); + if (idx < 7) + sclk = calc_div(clk, idx, sclk, freq, ddiv); return sclk; } static u32 -calc_pll(struct gk104_clk_priv *priv, int clk, u32 freq, u32 *coef) +calc_pll(struct gk104_clk *clk, int idx, u32 freq, u32 *coef) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvbios_pll limits; int N, M, P, ret; - ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); + ret = nvbios_pll_parse(bios, 0x137000 + (idx * 0x20), &limits); if (ret) return 0; - limits.refclk = read_div(priv, clk, 0x137120, 0x137140); + limits.refclk = read_div(clk, idx, 0x137120, 0x137140); if (!limits.refclk) return 0; - ret = gt215_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P); + ret = gt215_pll_calc(subdev, &limits, freq, &N, NULL, &M, &P); if (ret <= 0) return 0; @@ -277,10 +284,10 @@ calc_pll(struct gk104_clk_priv *priv, int clk, u32 freq, u32 *coef) } static int -calc_clk(struct gk104_clk_priv *priv, - struct nvkm_cstate *cstate, int clk, int dom) +calc_clk(struct gk104_clk *clk, + struct nvkm_cstate *cstate, int idx, int dom) { - struct gk104_clk_info *info = &priv->eng[clk]; + struct gk104_clk_info *info = &clk->eng[idx]; u32 freq = cstate->domain[dom]; u32 src0, div0, div1D, div1P = 0; u32 clk0, clk1 = 0; @@ -290,16 +297,16 @@ calc_clk(struct gk104_clk_priv *priv, return 0; /* first possible path, using only dividers */ - clk0 = calc_src(priv, clk, freq, &src0, &div0); - clk0 = calc_div(priv, clk, clk0, freq, &div1D); + clk0 = calc_src(clk, idx, freq, &src0, &div0); + clk0 = calc_div(clk, idx, clk0, freq, &div1D); /* see if we can get any closer using PLLs */ - if (clk0 != freq && (0x0000ff87 & (1 << clk))) { - if (clk <= 7) - clk1 = calc_pll(priv, clk, freq, &info->coef); + if (clk0 != freq && (0x0000ff87 & (1 << idx))) { + if (idx <= 7) + clk1 = calc_pll(clk, idx, freq, &info->coef); else clk1 = cstate->domain[nv_clk_src_hubk06]; - clk1 = calc_div(priv, clk, clk1, freq, &div1P); + clk1 = calc_div(clk, idx, clk1, freq, &div1P); } /* select the method which gets closest to target freq */ @@ -320,7 +327,7 @@ calc_clk(struct gk104_clk_priv *priv, info->mdiv |= 0x80000000; info->mdiv |= div1P << 8; } - info->ssel = (1 << clk); + info->ssel = (1 << idx); info->dsrc = 0x40000100; info->freq = clk1; } @@ -329,98 +336,115 @@ calc_clk(struct gk104_clk_priv *priv, } static int -gk104_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +gk104_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct gk104_clk_priv *priv = (void *)clk; + struct gk104_clk *clk = gk104_clk(base); int ret; - if ((ret = calc_clk(priv, cstate, 0x00, nv_clk_src_gpc)) || - (ret = calc_clk(priv, cstate, 0x01, nv_clk_src_rop)) || - (ret = calc_clk(priv, cstate, 0x02, nv_clk_src_hubk07)) || - (ret = calc_clk(priv, cstate, 0x07, nv_clk_src_hubk06)) || - (ret = calc_clk(priv, cstate, 0x08, nv_clk_src_hubk01)) || - (ret = calc_clk(priv, cstate, 0x0c, nv_clk_src_daemon)) || - (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec))) + if ((ret = calc_clk(clk, cstate, 0x00, nv_clk_src_gpc)) || + (ret = calc_clk(clk, cstate, 0x01, nv_clk_src_rop)) || + (ret = calc_clk(clk, cstate, 0x02, nv_clk_src_hubk07)) || + (ret = calc_clk(clk, cstate, 0x07, nv_clk_src_hubk06)) || + (ret = calc_clk(clk, cstate, 0x08, nv_clk_src_hubk01)) || + (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_daemon)) || + (ret = calc_clk(clk, cstate, 0x0e, nv_clk_src_vdec))) return ret; return 0; } static void -gk104_clk_prog_0(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_0(struct gk104_clk *clk, int idx) { - struct gk104_clk_info *info = &priv->eng[clk]; + struct gk104_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; if (!info->ssel) { - nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x8000003f, info->ddiv); - nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc); + nvkm_mask(device, 0x1371d0 + (idx * 0x04), 0x8000003f, info->ddiv); + nvkm_wr32(device, 0x137160 + (idx * 0x04), info->dsrc); } } static void -gk104_clk_prog_1_0(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_1_0(struct gk104_clk *clk, int idx) { - nv_mask(priv, 0x137100, (1 << clk), 0x00000000); - nv_wait(priv, 0x137100, (1 << clk), 0x00000000); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, 0x137100, (1 << idx), 0x00000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x137100) & (1 << idx))) + break; + ); } static void -gk104_clk_prog_1_1(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_1_1(struct gk104_clk *clk, int idx) { - nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000000); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, 0x137160 + (idx * 0x04), 0x00000100, 0x00000000); } static void -gk104_clk_prog_2(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_2(struct gk104_clk *clk, int idx) { - struct gk104_clk_info *info = &priv->eng[clk]; - const u32 addr = 0x137000 + (clk * 0x20); - nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000); - nv_mask(priv, addr + 0x00, 0x00000001, 0x00000000); + struct gk104_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; + const u32 addr = 0x137000 + (idx * 0x20); + nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000000); + nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000000); if (info->coef) { - nv_wr32(priv, addr + 0x04, info->coef); - nv_mask(priv, addr + 0x00, 0x00000001, 0x00000001); - nv_wait(priv, addr + 0x00, 0x00020000, 0x00020000); - nv_mask(priv, addr + 0x00, 0x00020004, 0x00000004); + nvkm_wr32(device, addr + 0x04, info->coef); + nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, addr + 0x00) & 0x00020000) + break; + ); + nvkm_mask(device, addr + 0x00, 0x00020004, 0x00000004); } } static void -gk104_clk_prog_3(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_3(struct gk104_clk *clk, int idx) { - struct gk104_clk_info *info = &priv->eng[clk]; + struct gk104_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; if (info->ssel) - nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f00, info->mdiv); + nvkm_mask(device, 0x137250 + (idx * 0x04), 0x00003f00, info->mdiv); else - nv_mask(priv, 0x137250 + (clk * 0x04), 0x0000003f, info->mdiv); + nvkm_mask(device, 0x137250 + (idx * 0x04), 0x0000003f, info->mdiv); } static void -gk104_clk_prog_4_0(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_4_0(struct gk104_clk *clk, int idx) { - struct gk104_clk_info *info = &priv->eng[clk]; + struct gk104_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; if (info->ssel) { - nv_mask(priv, 0x137100, (1 << clk), info->ssel); - nv_wait(priv, 0x137100, (1 << clk), info->ssel); + nvkm_mask(device, 0x137100, (1 << idx), info->ssel); + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x137100) & (1 << idx); + if (tmp == info->ssel) + break; + ); } } static void -gk104_clk_prog_4_1(struct gk104_clk_priv *priv, int clk) +gk104_clk_prog_4_1(struct gk104_clk *clk, int idx) { - struct gk104_clk_info *info = &priv->eng[clk]; + struct gk104_clk_info *info = &clk->eng[idx]; + struct nvkm_device *device = clk->base.subdev.device; if (info->ssel) { - nv_mask(priv, 0x137160 + (clk * 0x04), 0x40000000, 0x40000000); - nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000100); + nvkm_mask(device, 0x137160 + (idx * 0x04), 0x40000000, 0x40000000); + nvkm_mask(device, 0x137160 + (idx * 0x04), 0x00000100, 0x00000100); } } static int -gk104_clk_prog(struct nvkm_clk *clk) +gk104_clk_prog(struct nvkm_clk *base) { - struct gk104_clk_priv *priv = (void *)clk; + struct gk104_clk *clk = gk104_clk(base); struct { u32 mask; - void (*exec)(struct gk104_clk_priv *, int); + void (*exec)(struct gk104_clk *, int); } stage[] = { { 0x007f, gk104_clk_prog_0 }, /* div programming */ { 0x007f, gk104_clk_prog_1_0 }, /* select div mode */ @@ -433,12 +457,12 @@ gk104_clk_prog(struct nvkm_clk *clk) int i, j; for (i = 0; i < ARRAY_SIZE(stage); i++) { - for (j = 0; j < ARRAY_SIZE(priv->eng); j++) { + for (j = 0; j < ARRAY_SIZE(clk->eng); j++) { if (!(stage[i].mask & (1 << j))) continue; - if (!priv->eng[j].freq) + if (!clk->eng[j].freq) continue; - stage[i].exec(priv, j); + stage[i].exec(clk, j); } } @@ -446,55 +470,41 @@ gk104_clk_prog(struct nvkm_clk *clk) } static void -gk104_clk_tidy(struct nvkm_clk *clk) +gk104_clk_tidy(struct nvkm_clk *base) { - struct gk104_clk_priv *priv = (void *)clk; - memset(priv->eng, 0x00, sizeof(priv->eng)); + struct gk104_clk *clk = gk104_clk(base); + memset(clk->eng, 0x00, sizeof(clk->eng)); } -static struct nvkm_domain -gk104_domain[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_href , 0xff }, - { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 }, - { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE }, - { nv_clk_src_rop , 0x02, NVKM_CLK_DOM_FLAG_CORE }, - { nv_clk_src_mem , 0x03, 0, "memory", 500 }, - { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE }, - { nv_clk_src_hubk01 , 0x05 }, - { nv_clk_src_vdec , 0x06 }, - { nv_clk_src_daemon , 0x07 }, - { nv_clk_src_max } +static const struct nvkm_clk_func +gk104_clk = { + .read = gk104_clk_read, + .calc = gk104_clk_calc, + .prog = gk104_clk_prog, + .tidy = gk104_clk_tidy, + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 }, + { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE }, + { nv_clk_src_rop , 0x02, NVKM_CLK_DOM_FLAG_CORE }, + { nv_clk_src_mem , 0x03, 0, "memory", 500 }, + { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE }, + { nv_clk_src_hubk01 , 0x05 }, + { nv_clk_src_vdec , 0x06 }, + { nv_clk_src_daemon , 0x07 }, + { nv_clk_src_max } + } }; -static int -gk104_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gk104_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct gk104_clk_priv *priv; - int ret; + struct gk104_clk *clk; - ret = nvkm_clk_create(parent, engine, oclass, gk104_domain, - NULL, 0, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + *pclk = &clk->base; - priv->base.read = gk104_clk_read; - priv->base.calc = gk104_clk_calc; - priv->base.prog = gk104_clk_prog; - priv->base.tidy = gk104_clk_tidy; - return 0; + return nvkm_clk_ctor(&gk104_clk, device, index, true, &clk->base); } - -struct nvkm_oclass -gk104_clk_oclass = { - .handle = NV_SUBDEV(CLK, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c index 65c532742..254094ab7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c @@ -22,14 +22,11 @@ * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c * */ -#include -#include - -#include +#define gk20a_clk(p) container_of((p), struct gk20a_clk, base) +#include "priv.h" -#ifdef __KERNEL__ -#include -#endif +#include +#include #define MHZ (1000 * 1000) @@ -117,41 +114,42 @@ static const struct gk20a_clk_pllg_params gk20a_pllg_params = { .min_pl = 1, .max_pl = 32, }; -struct gk20a_clk_priv { +struct gk20a_clk { struct nvkm_clk base; const struct gk20a_clk_pllg_params *params; u32 m, n, pl; u32 parent_rate; }; -#define to_gk20a_clk(base) container_of(base, struct gk20a_clk_priv, base) static void -gk20a_pllg_read_mnp(struct gk20a_clk_priv *priv) +gk20a_pllg_read_mnp(struct gk20a_clk *clk) { + struct nvkm_device *device = clk->base.subdev.device; u32 val; - val = nv_rd32(priv, GPCPLL_COEFF); - priv->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); - priv->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH); - priv->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH); + val = nvkm_rd32(device, GPCPLL_COEFF); + clk->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); + clk->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH); + clk->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH); } static u32 -gk20a_pllg_calc_rate(struct gk20a_clk_priv *priv) +gk20a_pllg_calc_rate(struct gk20a_clk *clk) { u32 rate; u32 divider; - rate = priv->parent_rate * priv->n; - divider = priv->m * pl_to_div[priv->pl]; + rate = clk->parent_rate * clk->n; + divider = clk->m * pl_to_div[clk->pl]; do_div(rate, divider); return rate / 2; } static int -gk20a_pllg_calc_mnp(struct gk20a_clk_priv *priv, unsigned long rate) +gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate) { + struct nvkm_subdev *subdev = &clk->base.subdev; u32 target_clk_f, ref_clk_f, target_freq; u32 min_vco_f, max_vco_f; u32 low_pl, high_pl, best_pl; @@ -163,13 +161,13 @@ gk20a_pllg_calc_mnp(struct gk20a_clk_priv *priv, unsigned long rate) u32 pl; target_clk_f = rate * 2 / MHZ; - ref_clk_f = priv->parent_rate / MHZ; + ref_clk_f = clk->parent_rate / MHZ; - max_vco_f = priv->params->max_vco; - min_vco_f = priv->params->min_vco; - best_m = priv->params->max_m; - best_n = priv->params->min_n; - best_pl = priv->params->min_pl; + max_vco_f = clk->params->max_vco; + min_vco_f = clk->params->min_vco; + best_m = clk->params->max_m; + best_n = clk->params->min_n; + best_pl = clk->params->min_pl; target_vco_f = target_clk_f + target_clk_f / 50; if (max_vco_f < target_vco_f) @@ -177,13 +175,13 @@ gk20a_pllg_calc_mnp(struct gk20a_clk_priv *priv, unsigned long rate) /* min_pl <= high_pl <= max_pl */ high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f; - high_pl = min(high_pl, priv->params->max_pl); - high_pl = max(high_pl, priv->params->min_pl); + high_pl = min(high_pl, clk->params->max_pl); + high_pl = max(high_pl, clk->params->min_pl); /* min_pl <= low_pl <= max_pl */ low_pl = min_vco_f / target_vco_f; - low_pl = min(low_pl, priv->params->max_pl); - low_pl = max(low_pl, priv->params->min_pl); + low_pl = min(low_pl, clk->params->max_pl); + low_pl = max(low_pl, clk->params->min_pl); /* Find Indices of high_pl and low_pl */ for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) { @@ -199,30 +197,30 @@ gk20a_pllg_calc_mnp(struct gk20a_clk_priv *priv, unsigned long rate) } } - nv_debug(priv, "low_PL %d(div%d), high_PL %d(div%d)", low_pl, - pl_to_div[low_pl], high_pl, pl_to_div[high_pl]); + nvkm_debug(subdev, "low_PL %d(div%d), high_PL %d(div%d)", low_pl, + pl_to_div[low_pl], high_pl, pl_to_div[high_pl]); /* Select lowest possible VCO */ for (pl = low_pl; pl <= high_pl; pl++) { target_vco_f = target_clk_f * pl_to_div[pl]; - for (m = priv->params->min_m; m <= priv->params->max_m; m++) { + for (m = clk->params->min_m; m <= clk->params->max_m; m++) { u_f = ref_clk_f / m; - if (u_f < priv->params->min_u) + if (u_f < clk->params->min_u) break; - if (u_f > priv->params->max_u) + if (u_f > clk->params->max_u) continue; n = (target_vco_f * m) / ref_clk_f; n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f; - if (n > priv->params->max_n) + if (n > clk->params->max_n) break; for (; n <= n2; n++) { - if (n < priv->params->min_n) + if (n < clk->params->min_n) continue; - if (n > priv->params->max_n) + if (n > clk->params->max_n) break; vco_f = ref_clk_f * n / m; @@ -250,71 +248,75 @@ found_match: WARN_ON(best_delta == ~0); if (best_delta != 0) - nv_debug(priv, "no best match for target @ %dMHz on gpc_pll", - target_clk_f); + nvkm_debug(subdev, + "no best match for target @ %dMHz on gpc_pll", + target_clk_f); - priv->m = best_m; - priv->n = best_n; - priv->pl = best_pl; + clk->m = best_m; + clk->n = best_n; + clk->pl = best_pl; - target_freq = gk20a_pllg_calc_rate(priv) / MHZ; + target_freq = gk20a_pllg_calc_rate(clk) / MHZ; - nv_debug(priv, "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n", - target_freq, priv->m, priv->n, priv->pl, pl_to_div[priv->pl]); + nvkm_debug(subdev, + "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n", + target_freq, clk->m, clk->n, clk->pl, pl_to_div[clk->pl]); return 0; } static int -gk20a_pllg_slide(struct gk20a_clk_priv *priv, u32 n) +gk20a_pllg_slide(struct gk20a_clk *clk, u32 n) { + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; u32 val; int ramp_timeout; /* get old coefficients */ - val = nv_rd32(priv, GPCPLL_COEFF); + val = nvkm_rd32(device, GPCPLL_COEFF); /* do nothing if NDIV is the same */ if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH))) return 0; /* setup */ - nv_mask(priv, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT, + nvkm_mask(device, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT, 0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT); - nv_mask(priv, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT, + nvkm_mask(device, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT, 0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT); /* pll slowdown mode */ - nv_mask(priv, GPCPLL_NDIV_SLOWDOWN, + nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN, BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT), BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT)); /* new ndiv ready for ramp */ - val = nv_rd32(priv, GPCPLL_COEFF); + val = nvkm_rd32(device, GPCPLL_COEFF); val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT); val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT; udelay(1); - nv_wr32(priv, GPCPLL_COEFF, val); + nvkm_wr32(device, GPCPLL_COEFF, val); /* dynamic ramp to new ndiv */ - val = nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN); + val = nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN); val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT; udelay(1); - nv_wr32(priv, GPCPLL_NDIV_SLOWDOWN, val); + nvkm_wr32(device, GPCPLL_NDIV_SLOWDOWN, val); for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) { udelay(1); - val = nv_rd32(priv, GPC_BCAST_NDIV_SLOWDOWN_DEBUG); + val = nvkm_rd32(device, GPC_BCAST_NDIV_SLOWDOWN_DEBUG); if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK) break; } /* exit slowdown mode */ - nv_mask(priv, GPCPLL_NDIV_SLOWDOWN, + nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN, BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) | BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0); - nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN); + nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN); if (ramp_timeout <= 0) { - nv_error(priv, "gpcpll dynamic ramp timeout\n"); + nvkm_error(subdev, "gpcpll dynamic ramp timeout\n"); return -ETIMEDOUT; } @@ -322,149 +324,147 @@ gk20a_pllg_slide(struct gk20a_clk_priv *priv, u32 n) } static void -_gk20a_pllg_enable(struct gk20a_clk_priv *priv) +_gk20a_pllg_enable(struct gk20a_clk *clk) { - nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE); - nv_rd32(priv, GPCPLL_CFG); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE); + nvkm_rd32(device, GPCPLL_CFG); } static void -_gk20a_pllg_disable(struct gk20a_clk_priv *priv) +_gk20a_pllg_disable(struct gk20a_clk *clk) { - nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0); - nv_rd32(priv, GPCPLL_CFG); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0); + nvkm_rd32(device, GPCPLL_CFG); } static int -_gk20a_pllg_program_mnp(struct gk20a_clk_priv *priv, bool allow_slide) +_gk20a_pllg_program_mnp(struct gk20a_clk *clk, bool allow_slide) { + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; u32 val, cfg; u32 m_old, pl_old, n_lo; /* get old coefficients */ - val = nv_rd32(priv, GPCPLL_COEFF); + val = nvkm_rd32(device, GPCPLL_COEFF); m_old = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); pl_old = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH); /* do NDIV slide if there is no change in M and PL */ - cfg = nv_rd32(priv, GPCPLL_CFG); - if (allow_slide && priv->m == m_old && priv->pl == pl_old && + cfg = nvkm_rd32(device, GPCPLL_CFG); + if (allow_slide && clk->m == m_old && clk->pl == pl_old && (cfg & GPCPLL_CFG_ENABLE)) { - return gk20a_pllg_slide(priv, priv->n); + return gk20a_pllg_slide(clk, clk->n); } /* slide down to NDIV_LO */ - n_lo = DIV_ROUND_UP(m_old * priv->params->min_vco, - priv->parent_rate / MHZ); + n_lo = DIV_ROUND_UP(m_old * clk->params->min_vco, + clk->parent_rate / MHZ); if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) { - int ret = gk20a_pllg_slide(priv, n_lo); + int ret = gk20a_pllg_slide(clk, n_lo); if (ret) return ret; } /* split FO-to-bypass jump in halfs by setting out divider 1:2 */ - nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK, + nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK, 0x2 << GPC2CLK_OUT_VCODIV_SHIFT); /* put PLL in bypass before programming it */ - val = nv_rd32(priv, SEL_VCO); + val = nvkm_rd32(device, SEL_VCO); val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT)); udelay(2); - nv_wr32(priv, SEL_VCO, val); + nvkm_wr32(device, SEL_VCO, val); /* get out from IDDQ */ - val = nv_rd32(priv, GPCPLL_CFG); + val = nvkm_rd32(device, GPCPLL_CFG); if (val & GPCPLL_CFG_IDDQ) { val &= ~GPCPLL_CFG_IDDQ; - nv_wr32(priv, GPCPLL_CFG, val); - nv_rd32(priv, GPCPLL_CFG); + nvkm_wr32(device, GPCPLL_CFG, val); + nvkm_rd32(device, GPCPLL_CFG); udelay(2); } - _gk20a_pllg_disable(priv); + _gk20a_pllg_disable(clk); - nv_debug(priv, "%s: m=%d n=%d pl=%d\n", __func__, priv->m, priv->n, - priv->pl); + nvkm_debug(subdev, "%s: m=%d n=%d pl=%d\n", __func__, + clk->m, clk->n, clk->pl); - n_lo = DIV_ROUND_UP(priv->m * priv->params->min_vco, - priv->parent_rate / MHZ); - val = priv->m << GPCPLL_COEFF_M_SHIFT; - val |= (allow_slide ? n_lo : priv->n) << GPCPLL_COEFF_N_SHIFT; - val |= priv->pl << GPCPLL_COEFF_P_SHIFT; - nv_wr32(priv, GPCPLL_COEFF, val); + n_lo = DIV_ROUND_UP(clk->m * clk->params->min_vco, + clk->parent_rate / MHZ); + val = clk->m << GPCPLL_COEFF_M_SHIFT; + val |= (allow_slide ? n_lo : clk->n) << GPCPLL_COEFF_N_SHIFT; + val |= clk->pl << GPCPLL_COEFF_P_SHIFT; + nvkm_wr32(device, GPCPLL_COEFF, val); - _gk20a_pllg_enable(priv); + _gk20a_pllg_enable(clk); - val = nv_rd32(priv, GPCPLL_CFG); + val = nvkm_rd32(device, GPCPLL_CFG); if (val & GPCPLL_CFG_LOCK_DET_OFF) { val &= ~GPCPLL_CFG_LOCK_DET_OFF; - nv_wr32(priv, GPCPLL_CFG, val); + nvkm_wr32(device, GPCPLL_CFG, val); } - if (!nvkm_timer_wait_eq(priv, 300000, GPCPLL_CFG, GPCPLL_CFG_LOCK, - GPCPLL_CFG_LOCK)) { - nv_error(priv, "%s: timeout waiting for pllg lock\n", __func__); + if (nvkm_usec(device, 300, + if (nvkm_rd32(device, GPCPLL_CFG) & GPCPLL_CFG_LOCK) + break; + ) < 0) return -ETIMEDOUT; - } /* switch to VCO mode */ - nv_mask(priv, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT)); + nvkm_mask(device, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT)); /* restore out divider 1:1 */ - val = nv_rd32(priv, GPC2CLK_OUT); + val = nvkm_rd32(device, GPC2CLK_OUT); val &= ~GPC2CLK_OUT_VCODIV_MASK; udelay(2); - nv_wr32(priv, GPC2CLK_OUT, val); + nvkm_wr32(device, GPC2CLK_OUT, val); /* slide up to new NDIV */ - return allow_slide ? gk20a_pllg_slide(priv, priv->n) : 0; + return allow_slide ? gk20a_pllg_slide(clk, clk->n) : 0; } static int -gk20a_pllg_program_mnp(struct gk20a_clk_priv *priv) +gk20a_pllg_program_mnp(struct gk20a_clk *clk) { int err; - err = _gk20a_pllg_program_mnp(priv, true); + err = _gk20a_pllg_program_mnp(clk, true); if (err) - err = _gk20a_pllg_program_mnp(priv, false); + err = _gk20a_pllg_program_mnp(clk, false); return err; } static void -gk20a_pllg_disable(struct gk20a_clk_priv *priv) +gk20a_pllg_disable(struct gk20a_clk *clk) { + struct nvkm_device *device = clk->base.subdev.device; u32 val; /* slide to VCO min */ - val = nv_rd32(priv, GPCPLL_CFG); + val = nvkm_rd32(device, GPCPLL_CFG); if (val & GPCPLL_CFG_ENABLE) { u32 coeff, m, n_lo; - coeff = nv_rd32(priv, GPCPLL_COEFF); + coeff = nvkm_rd32(device, GPCPLL_COEFF); m = (coeff >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); - n_lo = DIV_ROUND_UP(m * priv->params->min_vco, - priv->parent_rate / MHZ); - gk20a_pllg_slide(priv, n_lo); + n_lo = DIV_ROUND_UP(m * clk->params->min_vco, + clk->parent_rate / MHZ); + gk20a_pllg_slide(clk, n_lo); } /* put PLL in bypass before disabling it */ - nv_mask(priv, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0); + nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0); - _gk20a_pllg_disable(priv); + _gk20a_pllg_disable(clk); } #define GK20A_CLK_GPC_MDIV 1000 -static struct nvkm_domain -gk20a_domains[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV }, - { nv_clk_src_max } -}; - static struct nvkm_pstate gk20a_pstates[] = { { @@ -560,87 +560,99 @@ gk20a_pstates[] = { }; static int -gk20a_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +gk20a_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct gk20a_clk_priv *priv = (void *)clk; + struct gk20a_clk *clk = gk20a_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; switch (src) { case nv_clk_src_crystal: - return nv_device(clk)->crystal; + return device->crystal; case nv_clk_src_gpc: - gk20a_pllg_read_mnp(priv); - return gk20a_pllg_calc_rate(priv) / GK20A_CLK_GPC_MDIV; + gk20a_pllg_read_mnp(clk); + return gk20a_pllg_calc_rate(clk) / GK20A_CLK_GPC_MDIV; default: - nv_error(clk, "invalid clock source %d\n", src); + nvkm_error(subdev, "invalid clock source %d\n", src); return -EINVAL; } } static int -gk20a_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +gk20a_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct gk20a_clk_priv *priv = (void *)clk; + struct gk20a_clk *clk = gk20a_clk(base); - return gk20a_pllg_calc_mnp(priv, cstate->domain[nv_clk_src_gpc] * + return gk20a_pllg_calc_mnp(clk, cstate->domain[nv_clk_src_gpc] * GK20A_CLK_GPC_MDIV); } static int -gk20a_clk_prog(struct nvkm_clk *clk) +gk20a_clk_prog(struct nvkm_clk *base) { - struct gk20a_clk_priv *priv = (void *)clk; + struct gk20a_clk *clk = gk20a_clk(base); - return gk20a_pllg_program_mnp(priv); + return gk20a_pllg_program_mnp(clk); } static void -gk20a_clk_tidy(struct nvkm_clk *clk) +gk20a_clk_tidy(struct nvkm_clk *base) { } -static int -gk20a_clk_fini(struct nvkm_object *object, bool suspend) +static void +gk20a_clk_fini(struct nvkm_clk *base) { - struct gk20a_clk_priv *priv = (void *)object; - int ret; - - ret = nvkm_clk_fini(&priv->base, false); - - gk20a_pllg_disable(priv); - - return ret; + struct gk20a_clk *clk = gk20a_clk(base); + gk20a_pllg_disable(clk); } static int -gk20a_clk_init(struct nvkm_object *object) +gk20a_clk_init(struct nvkm_clk *base) { - struct gk20a_clk_priv *priv = (void *)object; + struct gk20a_clk *clk = gk20a_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; int ret; - nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL); - - ret = nvkm_clk_init(&priv->base); - if (ret) - return ret; + nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL); - ret = gk20a_clk_prog(&priv->base); + ret = gk20a_clk_prog(&clk->base); if (ret) { - nv_error(priv, "cannot initialize clock\n"); + nvkm_error(subdev, "cannot initialize clock\n"); return ret; } return 0; } -static int -gk20a_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_clk_func +gk20a_clk = { + .init = gk20a_clk_init, + .fini = gk20a_clk_fini, + .read = gk20a_clk_read, + .calc = gk20a_clk_calc, + .prog = gk20a_clk_prog, + .tidy = gk20a_clk_tidy, + .pstates = gk20a_pstates, + .nr_pstates = ARRAY_SIZE(gk20a_pstates), + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV }, + { nv_clk_src_max } + } +}; + +int +gk20a_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct gk20a_clk_priv *priv; - struct nouveau_platform_device *plat; - int ret; - int i; + struct nvkm_device_tegra *tdev = device->func->tegra(device); + struct gk20a_clk *clk; + int ret, i; + + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + *pclk = &clk->base; /* Finish initializing the pstates */ for (i = 0; i < ARRAY_SIZE(gk20a_pstates); i++) { @@ -648,33 +660,11 @@ gk20a_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, gk20a_pstates[i].pstate = i + 1; } - ret = nvkm_clk_create(parent, engine, oclass, gk20a_domains, - gk20a_pstates, ARRAY_SIZE(gk20a_pstates), - true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + clk->params = &gk20a_pllg_params; + clk->parent_rate = clk_get_rate(tdev->clk); - priv->params = &gk20a_pllg_params; - - plat = nv_device_to_platform(nv_device(parent)); - priv->parent_rate = clk_get_rate(plat->gpu->clk); - nv_info(priv, "parent clock rate: %d Mhz\n", priv->parent_rate / MHZ); - - priv->base.read = gk20a_clk_read; - priv->base.calc = gk20a_clk_calc; - priv->base.prog = gk20a_clk_prog; - priv->base.tidy = gk20a_clk_tidy; - return 0; + ret = nvkm_clk_ctor(&gk20a_clk, device, index, true, &clk->base); + nvkm_info(&clk->base.subdev, "parent clock rate: %d Mhz\n", + clk->parent_rate / MHZ); + return ret; } - -struct nvkm_oclass -gk20a_clk_oclass = { - .handle = NV_SUBDEV(CLK, 0xea), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_clk_ctor, - .dtor = _nvkm_subdev_dtor, - .init = gk20a_clk_init, - .fini = gk20a_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c index 822d32a28..c233e3f65 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c @@ -22,56 +22,58 @@ * Authors: Ben Skeggs * Roy Spliet */ +#define gt215_clk(p) container_of((p), struct gt215_clk, base) #include "gt215.h" #include "pll.h" -#include #include #include #include #include -struct gt215_clk_priv { +struct gt215_clk { struct nvkm_clk base; struct gt215_clk_info eng[nv_clk_src_max]; }; -static u32 read_clk(struct gt215_clk_priv *, int, bool); -static u32 read_pll(struct gt215_clk_priv *, int, u32); +static u32 read_clk(struct gt215_clk *, int, bool); +static u32 read_pll(struct gt215_clk *, int, u32); static u32 -read_vco(struct gt215_clk_priv *priv, int clk) +read_vco(struct gt215_clk *clk, int idx) { - u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4)); + struct nvkm_device *device = clk->base.subdev.device; + u32 sctl = nvkm_rd32(device, 0x4120 + (idx * 4)); switch (sctl & 0x00000030) { case 0x00000000: - return nv_device(priv)->crystal; + return device->crystal; case 0x00000020: - return read_pll(priv, 0x41, 0x00e820); + return read_pll(clk, 0x41, 0x00e820); case 0x00000030: - return read_pll(priv, 0x42, 0x00e8a0); + return read_pll(clk, 0x42, 0x00e8a0); default: return 0; } } static u32 -read_clk(struct gt215_clk_priv *priv, int clk, bool ignore_en) +read_clk(struct gt215_clk *clk, int idx, bool ignore_en) { + struct nvkm_device *device = clk->base.subdev.device; u32 sctl, sdiv, sclk; /* refclk for the 0xe8xx plls is a fixed frequency */ - if (clk >= 0x40) { - if (nv_device(priv)->chipset == 0xaf) { + if (idx >= 0x40) { + if (device->chipset == 0xaf) { /* no joke.. seriously.. sigh.. */ - return nv_rd32(priv, 0x00471c) * 1000; + return nvkm_rd32(device, 0x00471c) * 1000; } - return nv_device(priv)->crystal; + return device->crystal; } - sctl = nv_rd32(priv, 0x4120 + (clk * 4)); + sctl = nvkm_rd32(device, 0x4120 + (idx * 4)); if (!ignore_en && !(sctl & 0x00000100)) return 0; @@ -83,7 +85,7 @@ read_clk(struct gt215_clk_priv *priv, int clk, bool ignore_en) switch (sctl & 0x00003000) { case 0x00000000: if (!(sctl & 0x00000200)) - return nv_device(priv)->crystal; + return device->crystal; return 0; case 0x00002000: if (sctl & 0x00000040) @@ -94,7 +96,7 @@ read_clk(struct gt215_clk_priv *priv, int clk, bool ignore_en) if (!(sctl & 0x00000001)) return 0; - sclk = read_vco(priv, clk); + sclk = read_vco(clk, idx); sdiv = ((sctl & 0x003f0000) >> 16) + 2; return (sclk * 2) / sdiv; default: @@ -103,14 +105,15 @@ read_clk(struct gt215_clk_priv *priv, int clk, bool ignore_en) } static u32 -read_pll(struct gt215_clk_priv *priv, int clk, u32 pll) +read_pll(struct gt215_clk *clk, int idx, u32 pll) { - u32 ctrl = nv_rd32(priv, pll + 0); + struct nvkm_device *device = clk->base.subdev.device; + u32 ctrl = nvkm_rd32(device, pll + 0); u32 sclk = 0, P = 1, N = 1, M = 1; if (!(ctrl & 0x00000008)) { if (ctrl & 0x00000001) { - u32 coef = nv_rd32(priv, pll + 4); + u32 coef = nvkm_rd32(device, pll + 4); M = (coef & 0x000000ff) >> 0; N = (coef & 0x0000ff00) >> 8; P = (coef & 0x003f0000) >> 16; @@ -121,10 +124,10 @@ read_pll(struct gt215_clk_priv *priv, int clk, u32 pll) if ((pll & 0x00ff00) == 0x00e800) P = 1; - sclk = read_clk(priv, 0x00 + clk, false); + sclk = read_clk(clk, 0x00 + idx, false); } } else { - sclk = read_clk(priv, 0x10 + clk, false); + sclk = read_clk(clk, 0x10 + idx, false); } if (M * P) @@ -134,41 +137,43 @@ read_pll(struct gt215_clk_priv *priv, int clk, u32 pll) } static int -gt215_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +gt215_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct gt215_clk_priv *priv = (void *)clk; + struct gt215_clk *clk = gt215_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; u32 hsrc; switch (src) { case nv_clk_src_crystal: - return nv_device(priv)->crystal; + return device->crystal; case nv_clk_src_core: case nv_clk_src_core_intm: - return read_pll(priv, 0x00, 0x4200); + return read_pll(clk, 0x00, 0x4200); case nv_clk_src_shader: - return read_pll(priv, 0x01, 0x4220); + return read_pll(clk, 0x01, 0x4220); case nv_clk_src_mem: - return read_pll(priv, 0x02, 0x4000); + return read_pll(clk, 0x02, 0x4000); case nv_clk_src_disp: - return read_clk(priv, 0x20, false); + return read_clk(clk, 0x20, false); case nv_clk_src_vdec: - return read_clk(priv, 0x21, false); + return read_clk(clk, 0x21, false); case nv_clk_src_daemon: - return read_clk(priv, 0x25, false); + return read_clk(clk, 0x25, false); case nv_clk_src_host: - hsrc = (nv_rd32(priv, 0xc040) & 0x30000000) >> 28; + hsrc = (nvkm_rd32(device, 0xc040) & 0x30000000) >> 28; switch (hsrc) { case 0: - return read_clk(priv, 0x1d, false); + return read_clk(clk, 0x1d, false); case 2: case 3: return 277000; default: - nv_error(clk, "unknown HOST clock source %d\n", hsrc); + nvkm_error(subdev, "unknown HOST clock source %d\n", hsrc); return -EINVAL; } default: - nv_error(clk, "invalid clock source %d\n", src); + nvkm_error(subdev, "invalid clock source %d\n", src); return -EINVAL; } @@ -176,11 +181,12 @@ gt215_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) } int -gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, +gt215_clk_info(struct nvkm_clk *base, int idx, u32 khz, struct gt215_clk_info *info) { - struct gt215_clk_priv *priv = (void *)clock; - u32 oclk, sclk, sdiv, diff; + struct gt215_clk *clk = gt215_clk(base); + u32 oclk, sclk, sdiv; + s32 diff; info->clk = 0; @@ -195,7 +201,7 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, info->clk = 0x00002140; return khz; default: - sclk = read_vco(priv, clk); + sclk = read_vco(clk, idx); sdiv = min((sclk * 2) / khz, (u32)65); oclk = (sclk * 2) / sdiv; diff = ((khz + 3000) - oclk); @@ -223,11 +229,11 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, } int -gt215_pll_info(struct nvkm_clk *clock, int clk, u32 pll, u32 khz, +gt215_pll_info(struct nvkm_clk *base, int idx, u32 pll, u32 khz, struct gt215_clk_info *info) { - struct nvkm_bios *bios = nvkm_bios(clock); - struct gt215_clk_priv *priv = (void *)clock; + struct gt215_clk *clk = gt215_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; struct nvbios_pll limits; int P, N, M, diff; int ret; @@ -236,22 +242,22 @@ gt215_pll_info(struct nvkm_clk *clock, int clk, u32 pll, u32 khz, /* If we can get a within [-2, 3) MHz of a divider, we'll disable the * PLL and use the divider instead. */ - ret = gt215_clk_info(clock, clk, khz, info); + ret = gt215_clk_info(&clk->base, idx, khz, info); diff = khz - ret; if (!pll || (diff >= -2000 && diff < 3000)) { goto out; } /* Try with PLL */ - ret = nvbios_pll_parse(bios, pll, &limits); + ret = nvbios_pll_parse(subdev->device->bios, pll, &limits); if (ret) return ret; - ret = gt215_clk_info(clock, clk - 0x10, limits.refclk, info); + ret = gt215_clk_info(&clk->base, idx - 0x10, limits.refclk, info); if (ret != limits.refclk) return -EINVAL; - ret = gt215_pll_calc(nv_subdev(priv), &limits, khz, &N, NULL, &M, &P); + ret = gt215_pll_calc(subdev, &limits, khz, &N, NULL, &M, &P); if (ret >= 0) { info->pll = (P << 16) | (N << 8) | M; } @@ -262,22 +268,22 @@ out: } static int -calc_clk(struct gt215_clk_priv *priv, struct nvkm_cstate *cstate, - int clk, u32 pll, int idx) +calc_clk(struct gt215_clk *clk, struct nvkm_cstate *cstate, + int idx, u32 pll, int dom) { - int ret = gt215_pll_info(&priv->base, clk, pll, cstate->domain[idx], - &priv->eng[idx]); + int ret = gt215_pll_info(&clk->base, idx, pll, cstate->domain[dom], + &clk->eng[dom]); if (ret >= 0) return 0; return ret; } static int -calc_host(struct gt215_clk_priv *priv, struct nvkm_cstate *cstate) +calc_host(struct gt215_clk *clk, struct nvkm_cstate *cstate) { int ret = 0; u32 kHz = cstate->domain[nv_clk_src_host]; - struct gt215_clk_info *info = &priv->eng[nv_clk_src_host]; + struct gt215_clk_info *info = &clk->eng[nv_clk_src_host]; if (kHz == 277000) { info->clk = 0; @@ -287,7 +293,7 @@ calc_host(struct gt215_clk_priv *priv, struct nvkm_cstate *cstate) info->host_out = NVA3_HOST_CLK; - ret = gt215_clk_info(&priv->base, 0x1d, kHz, info); + ret = gt215_clk_info(&clk->base, 0x1d, kHz, info); if (ret >= 0) return 0; @@ -297,21 +303,33 @@ calc_host(struct gt215_clk_priv *priv, struct nvkm_cstate *cstate) int gt215_clk_pre(struct nvkm_clk *clk, unsigned long *flags) { - struct nvkm_fifo *pfifo = nvkm_fifo(clk); + struct nvkm_device *device = clk->subdev.device; + struct nvkm_fifo *fifo = device->fifo; /* halt and idle execution engines */ - nv_mask(clk, 0x020060, 0x00070000, 0x00000000); - nv_mask(clk, 0x002504, 0x00000001, 0x00000001); + nvkm_mask(device, 0x020060, 0x00070000, 0x00000000); + nvkm_mask(device, 0x002504, 0x00000001, 0x00000001); /* Wait until the interrupt handler is finished */ - if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000)) + if (nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x000100)) + break; + ) < 0) return -EBUSY; - if (pfifo) - pfifo->pause(pfifo, flags); + if (fifo) + nvkm_fifo_pause(fifo, flags); - if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010)) + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x002504) & 0x00000010) + break; + ) < 0) return -EIO; - if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f)) + + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x00251c) & 0x0000003f; + if (tmp == 0x0000003f) + break; + ) < 0) return -EIO; return 0; @@ -320,86 +338,94 @@ gt215_clk_pre(struct nvkm_clk *clk, unsigned long *flags) void gt215_clk_post(struct nvkm_clk *clk, unsigned long *flags) { - struct nvkm_fifo *pfifo = nvkm_fifo(clk); + struct nvkm_device *device = clk->subdev.device; + struct nvkm_fifo *fifo = device->fifo; - if (pfifo && flags) - pfifo->start(pfifo, flags); + if (fifo && flags) + nvkm_fifo_start(fifo, flags); - nv_mask(clk, 0x002504, 0x00000001, 0x00000000); - nv_mask(clk, 0x020060, 0x00070000, 0x00040000); + nvkm_mask(device, 0x002504, 0x00000001, 0x00000000); + nvkm_mask(device, 0x020060, 0x00070000, 0x00040000); } static void -disable_clk_src(struct gt215_clk_priv *priv, u32 src) +disable_clk_src(struct gt215_clk *clk, u32 src) { - nv_mask(priv, src, 0x00000100, 0x00000000); - nv_mask(priv, src, 0x00000001, 0x00000000); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, src, 0x00000100, 0x00000000); + nvkm_mask(device, src, 0x00000001, 0x00000000); } static void -prog_pll(struct gt215_clk_priv *priv, int clk, u32 pll, int idx) +prog_pll(struct gt215_clk *clk, int idx, u32 pll, int dom) { - struct gt215_clk_info *info = &priv->eng[idx]; - const u32 src0 = 0x004120 + (clk * 4); - const u32 src1 = 0x004160 + (clk * 4); + struct gt215_clk_info *info = &clk->eng[dom]; + struct nvkm_device *device = clk->base.subdev.device; + const u32 src0 = 0x004120 + (idx * 4); + const u32 src1 = 0x004160 + (idx * 4); const u32 ctrl = pll + 0; const u32 coef = pll + 4; u32 bypass; if (info->pll) { /* Always start from a non-PLL clock */ - bypass = nv_rd32(priv, ctrl) & 0x00000008; + bypass = nvkm_rd32(device, ctrl) & 0x00000008; if (!bypass) { - nv_mask(priv, src1, 0x00000101, 0x00000101); - nv_mask(priv, ctrl, 0x00000008, 0x00000008); + nvkm_mask(device, src1, 0x00000101, 0x00000101); + nvkm_mask(device, ctrl, 0x00000008, 0x00000008); udelay(20); } - nv_mask(priv, src0, 0x003f3141, 0x00000101 | info->clk); - nv_wr32(priv, coef, info->pll); - nv_mask(priv, ctrl, 0x00000015, 0x00000015); - nv_mask(priv, ctrl, 0x00000010, 0x00000000); - if (!nv_wait(priv, ctrl, 0x00020000, 0x00020000)) { - nv_mask(priv, ctrl, 0x00000010, 0x00000010); - nv_mask(priv, src0, 0x00000101, 0x00000000); + nvkm_mask(device, src0, 0x003f3141, 0x00000101 | info->clk); + nvkm_wr32(device, coef, info->pll); + nvkm_mask(device, ctrl, 0x00000015, 0x00000015); + nvkm_mask(device, ctrl, 0x00000010, 0x00000000); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, ctrl) & 0x00020000) + break; + ) < 0) { + nvkm_mask(device, ctrl, 0x00000010, 0x00000010); + nvkm_mask(device, src0, 0x00000101, 0x00000000); return; } - nv_mask(priv, ctrl, 0x00000010, 0x00000010); - nv_mask(priv, ctrl, 0x00000008, 0x00000000); - disable_clk_src(priv, src1); + nvkm_mask(device, ctrl, 0x00000010, 0x00000010); + nvkm_mask(device, ctrl, 0x00000008, 0x00000000); + disable_clk_src(clk, src1); } else { - nv_mask(priv, src1, 0x003f3141, 0x00000101 | info->clk); - nv_mask(priv, ctrl, 0x00000018, 0x00000018); + nvkm_mask(device, src1, 0x003f3141, 0x00000101 | info->clk); + nvkm_mask(device, ctrl, 0x00000018, 0x00000018); udelay(20); - nv_mask(priv, ctrl, 0x00000001, 0x00000000); - disable_clk_src(priv, src0); + nvkm_mask(device, ctrl, 0x00000001, 0x00000000); + disable_clk_src(clk, src0); } } static void -prog_clk(struct gt215_clk_priv *priv, int clk, int idx) +prog_clk(struct gt215_clk *clk, int idx, int dom) { - struct gt215_clk_info *info = &priv->eng[idx]; - nv_mask(priv, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | info->clk); + struct gt215_clk_info *info = &clk->eng[dom]; + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, 0x004120 + (idx * 4), 0x003f3141, 0x00000101 | info->clk); } static void -prog_host(struct gt215_clk_priv *priv) +prog_host(struct gt215_clk *clk) { - struct gt215_clk_info *info = &priv->eng[nv_clk_src_host]; - u32 hsrc = (nv_rd32(priv, 0xc040)); + struct gt215_clk_info *info = &clk->eng[nv_clk_src_host]; + struct nvkm_device *device = clk->base.subdev.device; + u32 hsrc = (nvkm_rd32(device, 0xc040)); switch (info->host_out) { case NVA3_HOST_277: if ((hsrc & 0x30000000) == 0) { - nv_wr32(priv, 0xc040, hsrc | 0x20000000); - disable_clk_src(priv, 0x4194); + nvkm_wr32(device, 0xc040, hsrc | 0x20000000); + disable_clk_src(clk, 0x4194); } break; case NVA3_HOST_CLK: - prog_clk(priv, 0x1d, nv_clk_src_host); + prog_clk(clk, 0x1d, nv_clk_src_host); if ((hsrc & 0x30000000) >= 0x20000000) { - nv_wr32(priv, 0xc040, hsrc & ~0x30000000); + nvkm_wr32(device, 0xc040, hsrc & ~0x30000000); } break; default: @@ -407,44 +433,45 @@ prog_host(struct gt215_clk_priv *priv) } /* This seems to be a clock gating factor on idle, always set to 64 */ - nv_wr32(priv, 0xc044, 0x3e); + nvkm_wr32(device, 0xc044, 0x3e); } static void -prog_core(struct gt215_clk_priv *priv, int idx) +prog_core(struct gt215_clk *clk, int dom) { - struct gt215_clk_info *info = &priv->eng[idx]; - u32 fb_delay = nv_rd32(priv, 0x10002c); + struct gt215_clk_info *info = &clk->eng[dom]; + struct nvkm_device *device = clk->base.subdev.device; + u32 fb_delay = nvkm_rd32(device, 0x10002c); if (fb_delay < info->fb_delay) - nv_wr32(priv, 0x10002c, info->fb_delay); + nvkm_wr32(device, 0x10002c, info->fb_delay); - prog_pll(priv, 0x00, 0x004200, idx); + prog_pll(clk, 0x00, 0x004200, dom); if (fb_delay > info->fb_delay) - nv_wr32(priv, 0x10002c, info->fb_delay); + nvkm_wr32(device, 0x10002c, info->fb_delay); } static int -gt215_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +gt215_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct gt215_clk_priv *priv = (void *)clk; - struct gt215_clk_info *core = &priv->eng[nv_clk_src_core]; + struct gt215_clk *clk = gt215_clk(base); + struct gt215_clk_info *core = &clk->eng[nv_clk_src_core]; int ret; - if ((ret = calc_clk(priv, cstate, 0x10, 0x4200, nv_clk_src_core)) || - (ret = calc_clk(priv, cstate, 0x11, 0x4220, nv_clk_src_shader)) || - (ret = calc_clk(priv, cstate, 0x20, 0x0000, nv_clk_src_disp)) || - (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec)) || - (ret = calc_host(priv, cstate))) + if ((ret = calc_clk(clk, cstate, 0x10, 0x4200, nv_clk_src_core)) || + (ret = calc_clk(clk, cstate, 0x11, 0x4220, nv_clk_src_shader)) || + (ret = calc_clk(clk, cstate, 0x20, 0x0000, nv_clk_src_disp)) || + (ret = calc_clk(clk, cstate, 0x21, 0x0000, nv_clk_src_vdec)) || + (ret = calc_host(clk, cstate))) return ret; /* XXX: Should be reading the highest bit in the VBIOS clock to decide * whether to use a PLL or not... but using a PLL defeats the purpose */ if (core->pll) { - ret = gt215_clk_info(clk, 0x10, + ret = gt215_clk_info(&clk->base, 0x10, cstate->domain[nv_clk_src_core_intm], - &priv->eng[nv_clk_src_core_intm]); + &clk->eng[nv_clk_src_core_intm]); if (ret < 0) return ret; } @@ -453,81 +480,67 @@ gt215_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) } static int -gt215_clk_prog(struct nvkm_clk *clk) +gt215_clk_prog(struct nvkm_clk *base) { - struct gt215_clk_priv *priv = (void *)clk; - struct gt215_clk_info *core = &priv->eng[nv_clk_src_core]; + struct gt215_clk *clk = gt215_clk(base); + struct gt215_clk_info *core = &clk->eng[nv_clk_src_core]; int ret = 0; unsigned long flags; unsigned long *f = &flags; - ret = gt215_clk_pre(clk, f); + ret = gt215_clk_pre(&clk->base, f); if (ret) goto out; if (core->pll) - prog_core(priv, nv_clk_src_core_intm); + prog_core(clk, nv_clk_src_core_intm); - prog_core(priv, nv_clk_src_core); - prog_pll(priv, 0x01, 0x004220, nv_clk_src_shader); - prog_clk(priv, 0x20, nv_clk_src_disp); - prog_clk(priv, 0x21, nv_clk_src_vdec); - prog_host(priv); + prog_core(clk, nv_clk_src_core); + prog_pll(clk, 0x01, 0x004220, nv_clk_src_shader); + prog_clk(clk, 0x20, nv_clk_src_disp); + prog_clk(clk, 0x21, nv_clk_src_vdec); + prog_host(clk); out: if (ret == -EBUSY) f = NULL; - gt215_clk_post(clk, f); + gt215_clk_post(&clk->base, f); return ret; } static void -gt215_clk_tidy(struct nvkm_clk *clk) +gt215_clk_tidy(struct nvkm_clk *base) { } -static struct nvkm_domain -gt215_domain[] = { - { nv_clk_src_crystal , 0xff }, - { nv_clk_src_core , 0x00, 0, "core", 1000 }, - { nv_clk_src_shader , 0x01, 0, "shader", 1000 }, - { nv_clk_src_mem , 0x02, 0, "memory", 1000 }, - { nv_clk_src_vdec , 0x03 }, - { nv_clk_src_disp , 0x04 }, - { nv_clk_src_host , 0x05 }, - { nv_clk_src_core_intm, 0x06 }, - { nv_clk_src_max } +static const struct nvkm_clk_func +gt215_clk = { + .read = gt215_clk_read, + .calc = gt215_clk_calc, + .prog = gt215_clk_prog, + .tidy = gt215_clk_tidy, + .domains = { + { nv_clk_src_crystal , 0xff }, + { nv_clk_src_core , 0x00, 0, "core", 1000 }, + { nv_clk_src_shader , 0x01, 0, "shader", 1000 }, + { nv_clk_src_mem , 0x02, 0, "memory", 1000 }, + { nv_clk_src_vdec , 0x03 }, + { nv_clk_src_disp , 0x04 }, + { nv_clk_src_host , 0x05 }, + { nv_clk_src_core_intm, 0x06 }, + { nv_clk_src_max } + } }; -static int -gt215_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gt215_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct gt215_clk_priv *priv; - int ret; + struct gt215_clk *clk; - ret = nvkm_clk_create(parent, engine, oclass, gt215_domain, - NULL, 0, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + *pclk = &clk->base; - priv->base.read = gt215_clk_read; - priv->base.calc = gt215_clk_calc; - priv->base.prog = gt215_clk_prog; - priv->base.tidy = gt215_clk_tidy; - return 0; + return nvkm_clk_ctor(>215_clk, device, index, true, &clk->base); } - -struct nvkm_oclass -gt215_clk_oclass = { - .handle = NV_SUBDEV(CLK, 0xa3), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt215_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h index b447d9cd4..8865b59fe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h @@ -1,6 +1,6 @@ #ifndef __NVKM_CLK_NVA3_H__ #define __NVKM_CLK_NVA3_H__ -#include +#include "priv.h" struct gt215_clk_info { u32 clk; @@ -13,6 +13,6 @@ struct gt215_clk_info { }; int gt215_pll_info(struct nvkm_clk *, int, u32, u32, struct gt215_clk_info *); -int gt215_clk_pre(struct nvkm_clk *clk, unsigned long *flags); -void gt215_clk_post(struct nvkm_clk *clk, unsigned long *flags); +int gt215_clk_pre(struct nvkm_clk *, unsigned long *flags); +void gt215_clk_post(struct nvkm_clk *, unsigned long *flags); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/mcp77.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/mcp77.c index c54417b14..1c21b8b53 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/mcp77.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/mcp77.c @@ -21,15 +21,15 @@ * * Authors: Ben Skeggs */ +#define mcp77_clk(p) container_of((p), struct mcp77_clk, base) #include "gt215.h" #include "pll.h" -#include #include #include #include -struct mcp77_clk_priv { +struct mcp77_clk { struct nvkm_clk base; enum nv_clk_src csrc, ssrc, vsrc; u32 cctrl, sctrl; @@ -39,27 +39,29 @@ struct mcp77_clk_priv { }; static u32 -read_div(struct nvkm_clk *clk) +read_div(struct mcp77_clk *clk) { - return nv_rd32(clk, 0x004600); + struct nvkm_device *device = clk->base.subdev.device; + return nvkm_rd32(device, 0x004600); } static u32 -read_pll(struct nvkm_clk *clk, u32 base) +read_pll(struct mcp77_clk *clk, u32 base) { - u32 ctrl = nv_rd32(clk, base + 0); - u32 coef = nv_rd32(clk, base + 4); - u32 ref = clk->read(clk, nv_clk_src_href); + struct nvkm_device *device = clk->base.subdev.device; + u32 ctrl = nvkm_rd32(device, base + 0); + u32 coef = nvkm_rd32(device, base + 4); + u32 ref = nvkm_clk_read(&clk->base, nv_clk_src_href); u32 post_div = 0; u32 clock = 0; int N1, M1; switch (base){ case 0x4020: - post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16); + post_div = 1 << ((nvkm_rd32(device, 0x4070) & 0x000f0000) >> 16); break; case 0x4028: - post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16; + post_div = (nvkm_rd32(device, 0x4040) & 0x000f0000) >> 16; break; default: break; @@ -76,59 +78,61 @@ read_pll(struct nvkm_clk *clk, u32 base) } static int -mcp77_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +mcp77_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct mcp77_clk_priv *priv = (void *)clk; - u32 mast = nv_rd32(clk, 0x00c054); + struct mcp77_clk *clk = mcp77_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; + u32 mast = nvkm_rd32(device, 0x00c054); u32 P = 0; switch (src) { case nv_clk_src_crystal: - return nv_device(priv)->crystal; + return device->crystal; case nv_clk_src_href: return 100000; /* PCIE reference clock */ case nv_clk_src_hclkm4: - return clk->read(clk, nv_clk_src_href) * 4; + return nvkm_clk_read(&clk->base, nv_clk_src_href) * 4; case nv_clk_src_hclkm2d3: - return clk->read(clk, nv_clk_src_href) * 2 / 3; + return nvkm_clk_read(&clk->base, nv_clk_src_href) * 2 / 3; case nv_clk_src_host: switch (mast & 0x000c0000) { - case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3); + case 0x00000000: return nvkm_clk_read(&clk->base, nv_clk_src_hclkm2d3); case 0x00040000: break; - case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4); - case 0x000c0000: return clk->read(clk, nv_clk_src_cclk); + case 0x00080000: return nvkm_clk_read(&clk->base, nv_clk_src_hclkm4); + case 0x000c0000: return nvkm_clk_read(&clk->base, nv_clk_src_cclk); } break; case nv_clk_src_core: - P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16; + P = (nvkm_rd32(device, 0x004028) & 0x00070000) >> 16; switch (mast & 0x00000003) { - case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P; + case 0x00000000: return nvkm_clk_read(&clk->base, nv_clk_src_crystal) >> P; case 0x00000001: return 0; - case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P; + case 0x00000002: return nvkm_clk_read(&clk->base, nv_clk_src_hclkm4) >> P; case 0x00000003: return read_pll(clk, 0x004028) >> P; } break; case nv_clk_src_cclk: if ((mast & 0x03000000) != 0x03000000) - return clk->read(clk, nv_clk_src_core); + return nvkm_clk_read(&clk->base, nv_clk_src_core); if ((mast & 0x00000200) == 0x00000000) - return clk->read(clk, nv_clk_src_core); + return nvkm_clk_read(&clk->base, nv_clk_src_core); switch (mast & 0x00000c00) { - case 0x00000000: return clk->read(clk, nv_clk_src_href); - case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4); - case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3); + case 0x00000000: return nvkm_clk_read(&clk->base, nv_clk_src_href); + case 0x00000400: return nvkm_clk_read(&clk->base, nv_clk_src_hclkm4); + case 0x00000800: return nvkm_clk_read(&clk->base, nv_clk_src_hclkm2d3); default: return 0; } case nv_clk_src_shader: - P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16; + P = (nvkm_rd32(device, 0x004020) & 0x00070000) >> 16; switch (mast & 0x00000030) { case 0x00000000: if (mast & 0x00000040) - return clk->read(clk, nv_clk_src_href) >> P; - return clk->read(clk, nv_clk_src_crystal) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_href) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_crystal) >> P; case 0x00000010: break; case 0x00000020: return read_pll(clk, 0x004028) >> P; case 0x00000030: return read_pll(clk, 0x004020) >> P; @@ -142,7 +146,7 @@ mcp77_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) switch (mast & 0x00400000) { case 0x00400000: - return clk->read(clk, nv_clk_src_core) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_core) >> P; break; default: return 500000 >> P; @@ -153,29 +157,28 @@ mcp77_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) break; } - nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); + nvkm_debug(subdev, "unknown clock source %d %08x\n", src, mast); return 0; } static u32 -calc_pll(struct mcp77_clk_priv *priv, u32 reg, +calc_pll(struct mcp77_clk *clk, u32 reg, u32 clock, int *N, int *M, int *P) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &clk->base.subdev; struct nvbios_pll pll; - struct nvkm_clk *clk = &priv->base; int ret; - ret = nvbios_pll_parse(bios, reg, &pll); + ret = nvbios_pll_parse(subdev->device->bios, reg, &pll); if (ret) return 0; pll.vco2.max_freq = 0; - pll.refclk = clk->read(clk, nv_clk_src_href); + pll.refclk = nvkm_clk_read(&clk->base, nv_clk_src_href); if (!pll.refclk) return 0; - return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P); + return nv04_pll_calc(subdev, &pll, clock, N, M, NULL, NULL, P); } static inline u32 @@ -197,26 +200,27 @@ calc_P(u32 src, u32 target, int *div) } static int -mcp77_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +mcp77_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct mcp77_clk_priv *priv = (void *)clk; + struct mcp77_clk *clk = mcp77_clk(base); const int shader = cstate->domain[nv_clk_src_shader]; const int core = cstate->domain[nv_clk_src_core]; const int vdec = cstate->domain[nv_clk_src_vdec]; + struct nvkm_subdev *subdev = &clk->base.subdev; u32 out = 0, clock = 0; int N, M, P1, P2 = 0; int divs = 0; /* cclk: find suitable source, disable PLL if we can */ - if (core < clk->read(clk, nv_clk_src_hclkm4)) - out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs); + if (core < nvkm_clk_read(&clk->base, nv_clk_src_hclkm4)) + out = calc_P(nvkm_clk_read(&clk->base, nv_clk_src_hclkm4), core, &divs); /* Calculate clock * 2, so shader clock can use it too */ - clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1); + clock = calc_pll(clk, 0x4028, (core << 1), &N, &M, &P1); if (abs(core - out) <= abs(core - (clock >> 1))) { - priv->csrc = nv_clk_src_hclkm4; - priv->cctrl = divs << 16; + clk->csrc = nv_clk_src_hclkm4; + clk->cctrl = divs << 16; } else { /* NVCTRL is actually used _after_ NVPOST, and after what we * call NVPLL. To make matters worse, NVPOST is an integer @@ -226,31 +230,31 @@ mcp77_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) P1 = 2; } - priv->csrc = nv_clk_src_core; - priv->ccoef = (N << 8) | M; + clk->csrc = nv_clk_src_core; + clk->ccoef = (N << 8) | M; - priv->cctrl = (P2 + 1) << 16; - priv->cpost = (1 << P1) << 16; + clk->cctrl = (P2 + 1) << 16; + clk->cpost = (1 << P1) << 16; } /* sclk: nvpll + divisor, href or spll */ out = 0; - if (shader == clk->read(clk, nv_clk_src_href)) { - priv->ssrc = nv_clk_src_href; + if (shader == nvkm_clk_read(&clk->base, nv_clk_src_href)) { + clk->ssrc = nv_clk_src_href; } else { - clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1); - if (priv->csrc == nv_clk_src_core) + clock = calc_pll(clk, 0x4020, shader, &N, &M, &P1); + if (clk->csrc == nv_clk_src_core) out = calc_P((core << 1), shader, &divs); if (abs(shader - out) <= abs(shader - clock) && (divs + P2) <= 7) { - priv->ssrc = nv_clk_src_core; - priv->sctrl = (divs + P2) << 16; + clk->ssrc = nv_clk_src_core; + clk->sctrl = (divs + P2) << 16; } else { - priv->ssrc = nv_clk_src_shader; - priv->scoef = (N << 8) | M; - priv->sctrl = P1 << 16; + clk->ssrc = nv_clk_src_shader; + clk->scoef = (N << 8) | M; + clk->sctrl = P1 << 16; } } @@ -258,172 +262,162 @@ mcp77_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) out = calc_P(core, vdec, &divs); clock = calc_P(500000, vdec, &P1); if(abs(vdec - out) <= abs(vdec - clock)) { - priv->vsrc = nv_clk_src_cclk; - priv->vdiv = divs << 16; + clk->vsrc = nv_clk_src_cclk; + clk->vdiv = divs << 16; } else { - priv->vsrc = nv_clk_src_vdec; - priv->vdiv = P1 << 16; + clk->vsrc = nv_clk_src_vdec; + clk->vdiv = P1 << 16; } /* Print strategy! */ - nv_debug(priv, "nvpll: %08x %08x %08x\n", - priv->ccoef, priv->cpost, priv->cctrl); - nv_debug(priv, " spll: %08x %08x %08x\n", - priv->scoef, priv->spost, priv->sctrl); - nv_debug(priv, " vdiv: %08x\n", priv->vdiv); - if (priv->csrc == nv_clk_src_hclkm4) - nv_debug(priv, "core: hrefm4\n"); + nvkm_debug(subdev, "nvpll: %08x %08x %08x\n", + clk->ccoef, clk->cpost, clk->cctrl); + nvkm_debug(subdev, " spll: %08x %08x %08x\n", + clk->scoef, clk->spost, clk->sctrl); + nvkm_debug(subdev, " vdiv: %08x\n", clk->vdiv); + if (clk->csrc == nv_clk_src_hclkm4) + nvkm_debug(subdev, "core: hrefm4\n"); else - nv_debug(priv, "core: nvpll\n"); + nvkm_debug(subdev, "core: nvpll\n"); - if (priv->ssrc == nv_clk_src_hclkm4) - nv_debug(priv, "shader: hrefm4\n"); - else if (priv->ssrc == nv_clk_src_core) - nv_debug(priv, "shader: nvpll\n"); + if (clk->ssrc == nv_clk_src_hclkm4) + nvkm_debug(subdev, "shader: hrefm4\n"); + else if (clk->ssrc == nv_clk_src_core) + nvkm_debug(subdev, "shader: nvpll\n"); else - nv_debug(priv, "shader: spll\n"); + nvkm_debug(subdev, "shader: spll\n"); - if (priv->vsrc == nv_clk_src_hclkm4) - nv_debug(priv, "vdec: 500MHz\n"); + if (clk->vsrc == nv_clk_src_hclkm4) + nvkm_debug(subdev, "vdec: 500MHz\n"); else - nv_debug(priv, "vdec: core\n"); + nvkm_debug(subdev, "vdec: core\n"); return 0; } static int -mcp77_clk_prog(struct nvkm_clk *clk) +mcp77_clk_prog(struct nvkm_clk *base) { - struct mcp77_clk_priv *priv = (void *)clk; + struct mcp77_clk *clk = mcp77_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; u32 pllmask = 0, mast; unsigned long flags; unsigned long *f = &flags; int ret = 0; - ret = gt215_clk_pre(clk, f); + ret = gt215_clk_pre(&clk->base, f); if (ret) goto out; /* First switch to safe clocks: href */ - mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640); + mast = nvkm_mask(device, 0xc054, 0x03400e70, 0x03400640); mast &= ~0x00400e73; mast |= 0x03000000; - switch (priv->csrc) { + switch (clk->csrc) { case nv_clk_src_hclkm4: - nv_mask(clk, 0x4028, 0x00070000, priv->cctrl); + nvkm_mask(device, 0x4028, 0x00070000, clk->cctrl); mast |= 0x00000002; break; case nv_clk_src_core: - nv_wr32(clk, 0x402c, priv->ccoef); - nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl); - nv_wr32(clk, 0x4040, priv->cpost); + nvkm_wr32(device, 0x402c, clk->ccoef); + nvkm_wr32(device, 0x4028, 0x80000000 | clk->cctrl); + nvkm_wr32(device, 0x4040, clk->cpost); pllmask |= (0x3 << 8); mast |= 0x00000003; break; default: - nv_warn(priv,"Reclocking failed: unknown core clock\n"); + nvkm_warn(subdev, "Reclocking failed: unknown core clock\n"); goto resume; } - switch (priv->ssrc) { + switch (clk->ssrc) { case nv_clk_src_href: - nv_mask(clk, 0x4020, 0x00070000, 0x00000000); + nvkm_mask(device, 0x4020, 0x00070000, 0x00000000); /* mast |= 0x00000000; */ break; case nv_clk_src_core: - nv_mask(clk, 0x4020, 0x00070000, priv->sctrl); + nvkm_mask(device, 0x4020, 0x00070000, clk->sctrl); mast |= 0x00000020; break; case nv_clk_src_shader: - nv_wr32(clk, 0x4024, priv->scoef); - nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl); - nv_wr32(clk, 0x4070, priv->spost); + nvkm_wr32(device, 0x4024, clk->scoef); + nvkm_wr32(device, 0x4020, 0x80000000 | clk->sctrl); + nvkm_wr32(device, 0x4070, clk->spost); pllmask |= (0x3 << 12); mast |= 0x00000030; break; default: - nv_warn(priv,"Reclocking failed: unknown sclk clock\n"); + nvkm_warn(subdev, "Reclocking failed: unknown sclk clock\n"); goto resume; } - if (!nv_wait(clk, 0x004080, pllmask, pllmask)) { - nv_warn(priv,"Reclocking failed: unstable PLLs\n"); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x004080) & pllmask; + if (tmp == pllmask) + break; + ) < 0) goto resume; - } - switch (priv->vsrc) { + switch (clk->vsrc) { case nv_clk_src_cclk: mast |= 0x00400000; default: - nv_wr32(clk, 0x4600, priv->vdiv); + nvkm_wr32(device, 0x4600, clk->vdiv); } - nv_wr32(clk, 0xc054, mast); + nvkm_wr32(device, 0xc054, mast); resume: /* Disable some PLLs and dividers when unused */ - if (priv->csrc != nv_clk_src_core) { - nv_wr32(clk, 0x4040, 0x00000000); - nv_mask(clk, 0x4028, 0x80000000, 0x00000000); + if (clk->csrc != nv_clk_src_core) { + nvkm_wr32(device, 0x4040, 0x00000000); + nvkm_mask(device, 0x4028, 0x80000000, 0x00000000); } - if (priv->ssrc != nv_clk_src_shader) { - nv_wr32(clk, 0x4070, 0x00000000); - nv_mask(clk, 0x4020, 0x80000000, 0x00000000); + if (clk->ssrc != nv_clk_src_shader) { + nvkm_wr32(device, 0x4070, 0x00000000); + nvkm_mask(device, 0x4020, 0x80000000, 0x00000000); } out: if (ret == -EBUSY) f = NULL; - gt215_clk_post(clk, f); + gt215_clk_post(&clk->base, f); return ret; } static void -mcp77_clk_tidy(struct nvkm_clk *clk) +mcp77_clk_tidy(struct nvkm_clk *base) { } -static struct nvkm_domain -mcp77_domains[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_href , 0xff }, - { nv_clk_src_core , 0xff, 0, "core", 1000 }, - { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, - { nv_clk_src_vdec , 0xff, 0, "vdec", 1000 }, - { nv_clk_src_max } +static const struct nvkm_clk_func +mcp77_clk = { + .read = mcp77_clk_read, + .calc = mcp77_clk_calc, + .prog = mcp77_clk_prog, + .tidy = mcp77_clk_tidy, + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_core , 0xff, 0, "core", 1000 }, + { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, + { nv_clk_src_vdec , 0xff, 0, "vdec", 1000 }, + { nv_clk_src_max } + } }; -static int -mcp77_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +mcp77_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct mcp77_clk_priv *priv; - int ret; + struct mcp77_clk *clk; - ret = nvkm_clk_create(parent, engine, oclass, mcp77_domains, - NULL, 0, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + *pclk = &clk->base; - priv->base.read = mcp77_clk_read; - priv->base.calc = mcp77_clk_calc; - priv->base.prog = mcp77_clk_prog; - priv->base.tidy = mcp77_clk_tidy; - return 0; + return nvkm_clk_ctor(&mcp77_clk, device, index, true, &clk->base); } - -struct nvkm_oclass * -mcp77_clk_oclass = &(struct nvkm_oclass) { - .handle = NV_SUBDEV(CLK, 0xaa), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = mcp77_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c index 63dbbb575..b280f85e8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c @@ -21,23 +21,19 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" #include "pll.h" #include #include #include -struct nv04_clk_priv { - struct nvkm_clk base; -}; - int nv04_clk_pll_calc(struct nvkm_clk *clock, struct nvbios_pll *info, int clk, struct nvkm_pll_vals *pv) { int N1, M1, N2, M2, P; - int ret = nv04_pll_calc(nv_subdev(clock), info, clk, &N1, &M1, &N2, &M2, &P); + int ret = nv04_pll_calc(&clock->subdev, info, clk, &N1, &M1, &N2, &M2, &P); if (ret) { pv->refclk = info->refclk; pv->N1 = N1; @@ -52,8 +48,9 @@ nv04_clk_pll_calc(struct nvkm_clk *clock, struct nvbios_pll *info, int nv04_clk_pll_prog(struct nvkm_clk *clk, u32 reg1, struct nvkm_pll_vals *pv) { - struct nvkm_devinit *devinit = nvkm_devinit(clk); - int cv = nvkm_bios(clk)->version.chip; + struct nvkm_device *device = clk->subdev.device; + struct nvkm_devinit *devinit = device->devinit; + int cv = device->bios->version.chip; if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || cv >= 0x40) { @@ -67,37 +64,20 @@ nv04_clk_pll_prog(struct nvkm_clk *clk, u32 reg1, struct nvkm_pll_vals *pv) return 0; } -static struct nvkm_domain -nv04_domain[] = { - { nv_clk_src_max } +static const struct nvkm_clk_func +nv04_clk = { + .domains = { + { nv_clk_src_max } + } }; -static int -nv04_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv04_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct nv04_clk_priv *priv; - int ret; - - ret = nvkm_clk_create(parent, engine, oclass, nv04_domain, - NULL, 0, false, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.pll_calc = nv04_clk_pll_calc; - priv->base.pll_prog = nv04_clk_pll_prog; - return 0; + int ret = nvkm_clk_new_(&nv04_clk, device, index, false, pclk); + if (ret == 0) { + (*pclk)->pll_calc = nv04_clk_pll_calc; + (*pclk)->pll_prog = nv04_clk_pll_prog; + } + return ret; } - -struct nvkm_oclass -nv04_clk_oclass = { - .handle = NV_SUBDEV(CLK, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c index ed838130c..2ab9b9b84 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c @@ -21,14 +21,14 @@ * * Authors: Ben Skeggs */ -#include +#define nv40_clk(p) container_of((p), struct nv40_clk, base) +#include "priv.h" #include "pll.h" -#include #include #include -struct nv40_clk_priv { +struct nv40_clk { struct nvkm_clk base; u32 ctrl; u32 npll_ctrl; @@ -36,64 +36,56 @@ struct nv40_clk_priv { u32 spll; }; -static struct nvkm_domain -nv40_domain[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_href , 0xff }, - { nv_clk_src_core , 0xff, 0, "core", 1000 }, - { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, - { nv_clk_src_mem , 0xff, 0, "memory", 1000 }, - { nv_clk_src_max } -}; - static u32 -read_pll_1(struct nv40_clk_priv *priv, u32 reg) +read_pll_1(struct nv40_clk *clk, u32 reg) { - u32 ctrl = nv_rd32(priv, reg + 0x00); + struct nvkm_device *device = clk->base.subdev.device; + u32 ctrl = nvkm_rd32(device, reg + 0x00); int P = (ctrl & 0x00070000) >> 16; int N = (ctrl & 0x0000ff00) >> 8; int M = (ctrl & 0x000000ff) >> 0; - u32 ref = 27000, clk = 0; + u32 ref = 27000, khz = 0; if (ctrl & 0x80000000) - clk = ref * N / M; + khz = ref * N / M; - return clk >> P; + return khz >> P; } static u32 -read_pll_2(struct nv40_clk_priv *priv, u32 reg) +read_pll_2(struct nv40_clk *clk, u32 reg) { - u32 ctrl = nv_rd32(priv, reg + 0x00); - u32 coef = nv_rd32(priv, reg + 0x04); + struct nvkm_device *device = clk->base.subdev.device; + u32 ctrl = nvkm_rd32(device, reg + 0x00); + u32 coef = nvkm_rd32(device, reg + 0x04); int N2 = (coef & 0xff000000) >> 24; int M2 = (coef & 0x00ff0000) >> 16; int N1 = (coef & 0x0000ff00) >> 8; int M1 = (coef & 0x000000ff) >> 0; int P = (ctrl & 0x00070000) >> 16; - u32 ref = 27000, clk = 0; + u32 ref = 27000, khz = 0; if ((ctrl & 0x80000000) && M1) { - clk = ref * N1 / M1; + khz = ref * N1 / M1; if ((ctrl & 0x40000100) == 0x40000000) { if (M2) - clk = clk * N2 / M2; + khz = khz * N2 / M2; else - clk = 0; + khz = 0; } } - return clk >> P; + return khz >> P; } static u32 -read_clk(struct nv40_clk_priv *priv, u32 src) +read_clk(struct nv40_clk *clk, u32 src) { switch (src) { case 3: - return read_pll_2(priv, 0x004000); + return read_pll_2(clk, 0x004000); case 2: - return read_pll_1(priv, 0x004008); + return read_pll_1(clk, 0x004008); default: break; } @@ -102,46 +94,48 @@ read_clk(struct nv40_clk_priv *priv, u32 src) } static int -nv40_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +nv40_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct nv40_clk_priv *priv = (void *)clk; - u32 mast = nv_rd32(priv, 0x00c040); + struct nv40_clk *clk = nv40_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; + u32 mast = nvkm_rd32(device, 0x00c040); switch (src) { case nv_clk_src_crystal: - return nv_device(priv)->crystal; + return device->crystal; case nv_clk_src_href: return 100000; /*XXX: PCIE/AGP differ*/ case nv_clk_src_core: - return read_clk(priv, (mast & 0x00000003) >> 0); + return read_clk(clk, (mast & 0x00000003) >> 0); case nv_clk_src_shader: - return read_clk(priv, (mast & 0x00000030) >> 4); + return read_clk(clk, (mast & 0x00000030) >> 4); case nv_clk_src_mem: - return read_pll_2(priv, 0x4020); + return read_pll_2(clk, 0x4020); default: break; } - nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); + nvkm_debug(subdev, "unknown clock source %d %08x\n", src, mast); return -EINVAL; } static int -nv40_clk_calc_pll(struct nv40_clk_priv *priv, u32 reg, u32 clk, +nv40_clk_calc_pll(struct nv40_clk *clk, u32 reg, u32 khz, int *N1, int *M1, int *N2, int *M2, int *log2P) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &clk->base.subdev; struct nvbios_pll pll; int ret; - ret = nvbios_pll_parse(bios, reg, &pll); + ret = nvbios_pll_parse(subdev->device->bios, reg, &pll); if (ret) return ret; - if (clk < pll.vco1.max_freq) + if (khz < pll.vco1.max_freq) pll.vco2.max_freq = 0; - ret = nv04_pll_calc(nv_subdev(priv), &pll, clk, N1, M1, N2, M2, log2P); + ret = nv04_pll_calc(subdev, &pll, khz, N1, M1, N2, M2, log2P); if (ret == 0) return -ERANGE; @@ -149,93 +143,90 @@ nv40_clk_calc_pll(struct nv40_clk_priv *priv, u32 reg, u32 clk, } static int -nv40_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +nv40_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct nv40_clk_priv *priv = (void *)clk; + struct nv40_clk *clk = nv40_clk(base); int gclk = cstate->domain[nv_clk_src_core]; int sclk = cstate->domain[nv_clk_src_shader]; int N1, M1, N2, M2, log2P; int ret; /* core/geometric clock */ - ret = nv40_clk_calc_pll(priv, 0x004000, gclk, + ret = nv40_clk_calc_pll(clk, 0x004000, gclk, &N1, &M1, &N2, &M2, &log2P); if (ret < 0) return ret; if (N2 == M2) { - priv->npll_ctrl = 0x80000100 | (log2P << 16); - priv->npll_coef = (N1 << 8) | M1; + clk->npll_ctrl = 0x80000100 | (log2P << 16); + clk->npll_coef = (N1 << 8) | M1; } else { - priv->npll_ctrl = 0xc0000000 | (log2P << 16); - priv->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; + clk->npll_ctrl = 0xc0000000 | (log2P << 16); + clk->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; } /* use the second pll for shader/rop clock, if it differs from core */ if (sclk && sclk != gclk) { - ret = nv40_clk_calc_pll(priv, 0x004008, sclk, + ret = nv40_clk_calc_pll(clk, 0x004008, sclk, &N1, &M1, NULL, NULL, &log2P); if (ret < 0) return ret; - priv->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; - priv->ctrl = 0x00000223; + clk->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; + clk->ctrl = 0x00000223; } else { - priv->spll = 0x00000000; - priv->ctrl = 0x00000333; + clk->spll = 0x00000000; + clk->ctrl = 0x00000333; } return 0; } static int -nv40_clk_prog(struct nvkm_clk *clk) +nv40_clk_prog(struct nvkm_clk *base) { - struct nv40_clk_priv *priv = (void *)clk; - nv_mask(priv, 0x00c040, 0x00000333, 0x00000000); - nv_wr32(priv, 0x004004, priv->npll_coef); - nv_mask(priv, 0x004000, 0xc0070100, priv->npll_ctrl); - nv_mask(priv, 0x004008, 0xc007ffff, priv->spll); + struct nv40_clk *clk = nv40_clk(base); + struct nvkm_device *device = clk->base.subdev.device; + nvkm_mask(device, 0x00c040, 0x00000333, 0x00000000); + nvkm_wr32(device, 0x004004, clk->npll_coef); + nvkm_mask(device, 0x004000, 0xc0070100, clk->npll_ctrl); + nvkm_mask(device, 0x004008, 0xc007ffff, clk->spll); mdelay(5); - nv_mask(priv, 0x00c040, 0x00000333, priv->ctrl); + nvkm_mask(device, 0x00c040, 0x00000333, clk->ctrl); return 0; } static void -nv40_clk_tidy(struct nvkm_clk *clk) +nv40_clk_tidy(struct nvkm_clk *obj) { } -static int -nv40_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_clk_func +nv40_clk = { + .read = nv40_clk_read, + .calc = nv40_clk_calc, + .prog = nv40_clk_prog, + .tidy = nv40_clk_tidy, + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_core , 0xff, 0, "core", 1000 }, + { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, + { nv_clk_src_mem , 0xff, 0, "memory", 1000 }, + { nv_clk_src_max } + } +}; + +int +nv40_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) { - struct nv40_clk_priv *priv; - int ret; + struct nv40_clk *clk; - ret = nvkm_clk_create(parent, engine, oclass, nv40_domain, - NULL, 0, true, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + clk->base.pll_calc = nv04_clk_pll_calc; + clk->base.pll_prog = nv04_clk_pll_prog; + *pclk = &clk->base; - priv->base.pll_calc = nv04_clk_pll_calc; - priv->base.pll_prog = nv04_clk_pll_prog; - priv->base.read = nv40_clk_read; - priv->base.calc = nv40_clk_calc; - priv->base.prog = nv40_clk_prog; - priv->base.tidy = nv40_clk_tidy; - return 0; + return nvkm_clk_ctor(&nv40_clk, device, index, true, &clk->base); } - -struct nvkm_oclass -nv40_clk_oclass = { - .handle = NV_SUBDEV(CLK, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c index 9b4ffd634..5841f2979 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c @@ -25,38 +25,39 @@ #include "pll.h" #include "seq.h" -#include #include #include static u32 -read_div(struct nv50_clk_priv *priv) +read_div(struct nv50_clk *clk) { - switch (nv_device(priv)->chipset) { + struct nvkm_device *device = clk->base.subdev.device; + switch (device->chipset) { case 0x50: /* it exists, but only has bit 31, not the dividers.. */ case 0x84: case 0x86: case 0x98: case 0xa0: - return nv_rd32(priv, 0x004700); + return nvkm_rd32(device, 0x004700); case 0x92: case 0x94: case 0x96: - return nv_rd32(priv, 0x004800); + return nvkm_rd32(device, 0x004800); default: return 0x00000000; } } static u32 -read_pll_src(struct nv50_clk_priv *priv, u32 base) +read_pll_src(struct nv50_clk *clk, u32 base) { - struct nvkm_clk *clk = &priv->base; - u32 coef, ref = clk->read(clk, nv_clk_src_crystal); - u32 rsel = nv_rd32(priv, 0x00e18c); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; + u32 coef, ref = nvkm_clk_read(&clk->base, nv_clk_src_crystal); + u32 rsel = nvkm_rd32(device, 0x00e18c); int P, N, M, id; - switch (nv_device(priv)->chipset) { + switch (device->chipset) { case 0x50: case 0xa0: switch (base) { @@ -65,11 +66,11 @@ read_pll_src(struct nv50_clk_priv *priv, u32 base) case 0x4008: id = !!(rsel & 0x00000008); break; case 0x4030: id = 0; break; default: - nv_error(priv, "ref: bad pll 0x%06x\n", base); + nvkm_error(subdev, "ref: bad pll %06x\n", base); return 0; } - coef = nv_rd32(priv, 0x00e81c + (id * 0x0c)); + coef = nvkm_rd32(device, 0x00e81c + (id * 0x0c)); ref *= (coef & 0x01000000) ? 2 : 4; P = (coef & 0x00070000) >> 16; N = ((coef & 0x0000ff00) >> 8) + 1; @@ -78,7 +79,7 @@ read_pll_src(struct nv50_clk_priv *priv, u32 base) case 0x84: case 0x86: case 0x92: - coef = nv_rd32(priv, 0x00e81c); + coef = nvkm_rd32(device, 0x00e81c); P = (coef & 0x00070000) >> 16; N = (coef & 0x0000ff00) >> 8; M = (coef & 0x000000ff) >> 0; @@ -86,26 +87,26 @@ read_pll_src(struct nv50_clk_priv *priv, u32 base) case 0x94: case 0x96: case 0x98: - rsel = nv_rd32(priv, 0x00c050); + rsel = nvkm_rd32(device, 0x00c050); switch (base) { case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; case 0x4030: rsel = 3; break; default: - nv_error(priv, "ref: bad pll 0x%06x\n", base); + nvkm_error(subdev, "ref: bad pll %06x\n", base); return 0; } switch (rsel) { case 0: id = 1; break; - case 1: return clk->read(clk, nv_clk_src_crystal); - case 2: return clk->read(clk, nv_clk_src_href); + case 1: return nvkm_clk_read(&clk->base, nv_clk_src_crystal); + case 2: return nvkm_clk_read(&clk->base, nv_clk_src_href); case 3: id = 0; break; } - coef = nv_rd32(priv, 0x00e81c + (id * 0x28)); - P = (nv_rd32(priv, 0x00e824 + (id * 0x28)) >> 16) & 7; + coef = nvkm_rd32(device, 0x00e81c + (id * 0x28)); + P = (nvkm_rd32(device, 0x00e824 + (id * 0x28)) >> 16) & 7; P += (coef & 0x00070000) >> 16; N = (coef & 0x0000ff00) >> 8; M = (coef & 0x000000ff) >> 0; @@ -121,10 +122,11 @@ read_pll_src(struct nv50_clk_priv *priv, u32 base) } static u32 -read_pll_ref(struct nv50_clk_priv *priv, u32 base) +read_pll_ref(struct nv50_clk *clk, u32 base) { - struct nvkm_clk *clk = &priv->base; - u32 src, mast = nv_rd32(priv, 0x00c040); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; + u32 src, mast = nvkm_rd32(device, 0x00c040); switch (base) { case 0x004028: @@ -140,33 +142,33 @@ read_pll_ref(struct nv50_clk_priv *priv, u32 base) src = !!(mast & 0x02000000); break; case 0x00e810: - return clk->read(clk, nv_clk_src_crystal); + return nvkm_clk_read(&clk->base, nv_clk_src_crystal); default: - nv_error(priv, "bad pll 0x%06x\n", base); + nvkm_error(subdev, "bad pll %06x\n", base); return 0; } if (src) - return clk->read(clk, nv_clk_src_href); + return nvkm_clk_read(&clk->base, nv_clk_src_href); - return read_pll_src(priv, base); + return read_pll_src(clk, base); } static u32 -read_pll(struct nv50_clk_priv *priv, u32 base) +read_pll(struct nv50_clk *clk, u32 base) { - struct nvkm_clk *clk = &priv->base; - u32 mast = nv_rd32(priv, 0x00c040); - u32 ctrl = nv_rd32(priv, base + 0); - u32 coef = nv_rd32(priv, base + 4); - u32 ref = read_pll_ref(priv, base); + struct nvkm_device *device = clk->base.subdev.device; + u32 mast = nvkm_rd32(device, 0x00c040); + u32 ctrl = nvkm_rd32(device, base + 0); + u32 coef = nvkm_rd32(device, base + 4); + u32 ref = read_pll_ref(clk, base); u32 freq = 0; int N1, N2, M1, M2; if (base == 0x004028 && (mast & 0x00100000)) { /* wtf, appears to only disable post-divider on gt200 */ - if (nv_device(priv)->chipset != 0xa0) - return clk->read(clk, nv_clk_src_dom6); + if (device->chipset != 0xa0) + return nvkm_clk_read(&clk->base, nv_clk_src_dom6); } N2 = (coef & 0xff000000) >> 24; @@ -186,71 +188,73 @@ read_pll(struct nv50_clk_priv *priv, u32 base) return freq; } -static int -nv50_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) +int +nv50_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { - struct nv50_clk_priv *priv = (void *)clk; - u32 mast = nv_rd32(priv, 0x00c040); + struct nv50_clk *clk = nv50_clk(base); + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; + u32 mast = nvkm_rd32(device, 0x00c040); u32 P = 0; switch (src) { case nv_clk_src_crystal: - return nv_device(priv)->crystal; + return device->crystal; case nv_clk_src_href: return 100000; /* PCIE reference clock */ case nv_clk_src_hclk: - return div_u64((u64)clk->read(clk, nv_clk_src_href) * 27778, 10000); + return div_u64((u64)nvkm_clk_read(&clk->base, nv_clk_src_href) * 27778, 10000); case nv_clk_src_hclkm3: - return clk->read(clk, nv_clk_src_hclk) * 3; + return nvkm_clk_read(&clk->base, nv_clk_src_hclk) * 3; case nv_clk_src_hclkm3d2: - return clk->read(clk, nv_clk_src_hclk) * 3 / 2; + return nvkm_clk_read(&clk->base, nv_clk_src_hclk) * 3 / 2; case nv_clk_src_host: switch (mast & 0x30000000) { - case 0x00000000: return clk->read(clk, nv_clk_src_href); + case 0x00000000: return nvkm_clk_read(&clk->base, nv_clk_src_href); case 0x10000000: break; case 0x20000000: /* !0x50 */ - case 0x30000000: return clk->read(clk, nv_clk_src_hclk); + case 0x30000000: return nvkm_clk_read(&clk->base, nv_clk_src_hclk); } break; case nv_clk_src_core: if (!(mast & 0x00100000)) - P = (nv_rd32(priv, 0x004028) & 0x00070000) >> 16; + P = (nvkm_rd32(device, 0x004028) & 0x00070000) >> 16; switch (mast & 0x00000003) { - case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P; - case 0x00000001: return clk->read(clk, nv_clk_src_dom6); - case 0x00000002: return read_pll(priv, 0x004020) >> P; - case 0x00000003: return read_pll(priv, 0x004028) >> P; + case 0x00000000: return nvkm_clk_read(&clk->base, nv_clk_src_crystal) >> P; + case 0x00000001: return nvkm_clk_read(&clk->base, nv_clk_src_dom6); + case 0x00000002: return read_pll(clk, 0x004020) >> P; + case 0x00000003: return read_pll(clk, 0x004028) >> P; } break; case nv_clk_src_shader: - P = (nv_rd32(priv, 0x004020) & 0x00070000) >> 16; + P = (nvkm_rd32(device, 0x004020) & 0x00070000) >> 16; switch (mast & 0x00000030) { case 0x00000000: if (mast & 0x00000080) - return clk->read(clk, nv_clk_src_host) >> P; - return clk->read(clk, nv_clk_src_crystal) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_host) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_crystal) >> P; case 0x00000010: break; - case 0x00000020: return read_pll(priv, 0x004028) >> P; - case 0x00000030: return read_pll(priv, 0x004020) >> P; + case 0x00000020: return read_pll(clk, 0x004028) >> P; + case 0x00000030: return read_pll(clk, 0x004020) >> P; } break; case nv_clk_src_mem: - P = (nv_rd32(priv, 0x004008) & 0x00070000) >> 16; - if (nv_rd32(priv, 0x004008) & 0x00000200) { + P = (nvkm_rd32(device, 0x004008) & 0x00070000) >> 16; + if (nvkm_rd32(device, 0x004008) & 0x00000200) { switch (mast & 0x0000c000) { case 0x00000000: - return clk->read(clk, nv_clk_src_crystal) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_crystal) >> P; case 0x00008000: case 0x0000c000: - return clk->read(clk, nv_clk_src_href) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_href) >> P; } } else { - return read_pll(priv, 0x004008) >> P; + return read_pll(clk, 0x004008) >> P; } break; case nv_clk_src_vdec: - P = (read_div(priv) & 0x00000700) >> 8; - switch (nv_device(priv)->chipset) { + P = (read_div(clk) & 0x00000700) >> 8; + switch (device->chipset) { case 0x84: case 0x86: case 0x92: @@ -259,51 +263,51 @@ nv50_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) case 0xa0: switch (mast & 0x00000c00) { case 0x00000000: - if (nv_device(priv)->chipset == 0xa0) /* wtf?? */ - return clk->read(clk, nv_clk_src_core) >> P; - return clk->read(clk, nv_clk_src_crystal) >> P; + if (device->chipset == 0xa0) /* wtf?? */ + return nvkm_clk_read(&clk->base, nv_clk_src_core) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_crystal) >> P; case 0x00000400: return 0; case 0x00000800: if (mast & 0x01000000) - return read_pll(priv, 0x004028) >> P; - return read_pll(priv, 0x004030) >> P; + return read_pll(clk, 0x004028) >> P; + return read_pll(clk, 0x004030) >> P; case 0x00000c00: - return clk->read(clk, nv_clk_src_core) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_core) >> P; } break; case 0x98: switch (mast & 0x00000c00) { case 0x00000000: - return clk->read(clk, nv_clk_src_core) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_core) >> P; case 0x00000400: return 0; case 0x00000800: - return clk->read(clk, nv_clk_src_hclkm3d2) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_hclkm3d2) >> P; case 0x00000c00: - return clk->read(clk, nv_clk_src_mem) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_mem) >> P; } break; } break; case nv_clk_src_dom6: - switch (nv_device(priv)->chipset) { + switch (device->chipset) { case 0x50: case 0xa0: - return read_pll(priv, 0x00e810) >> 2; + return read_pll(clk, 0x00e810) >> 2; case 0x84: case 0x86: case 0x92: case 0x94: case 0x96: case 0x98: - P = (read_div(priv) & 0x00000007) >> 0; + P = (read_div(clk) & 0x00000007) >> 0; switch (mast & 0x0c000000) { - case 0x00000000: return clk->read(clk, nv_clk_src_href); + case 0x00000000: return nvkm_clk_read(&clk->base, nv_clk_src_href); case 0x04000000: break; - case 0x08000000: return clk->read(clk, nv_clk_src_hclk); + case 0x08000000: return nvkm_clk_read(&clk->base, nv_clk_src_hclk); case 0x0c000000: - return clk->read(clk, nv_clk_src_hclkm3) >> P; + return nvkm_clk_read(&clk->base, nv_clk_src_hclkm3) >> P; } break; default: @@ -313,27 +317,27 @@ nv50_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) break; } - nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); + nvkm_debug(subdev, "unknown clock source %d %08x\n", src, mast); return -EINVAL; } static u32 -calc_pll(struct nv50_clk_priv *priv, u32 reg, u32 clk, int *N, int *M, int *P) +calc_pll(struct nv50_clk *clk, u32 reg, u32 idx, int *N, int *M, int *P) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &clk->base.subdev; struct nvbios_pll pll; int ret; - ret = nvbios_pll_parse(bios, reg, &pll); + ret = nvbios_pll_parse(subdev->device->bios, reg, &pll); if (ret) return 0; pll.vco2.max_freq = 0; - pll.refclk = read_pll_ref(priv, reg); + pll.refclk = read_pll_ref(clk, reg); if (!pll.refclk) return 0; - return nv04_pll_calc(nv_subdev(priv), &pll, clk, N, M, NULL, NULL, P); + return nv04_pll_calc(subdev, &pll, idx, N, M, NULL, NULL, P); } static inline u32 @@ -360,11 +364,13 @@ clk_same(u32 a, u32 b) return ((a / 1000) == (b / 1000)); } -static int -nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) +int +nv50_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { - struct nv50_clk_priv *priv = (void *)clk; - struct nv50_clk_hwsq *hwsq = &priv->hwsq; + struct nv50_clk *clk = nv50_clk(base); + struct nv50_clk_hwsq *hwsq = &clk->hwsq; + struct nvkm_subdev *subdev = &clk->base.subdev; + struct nvkm_device *device = subdev->device; const int shader = cstate->domain[nv_clk_src_shader]; const int core = cstate->domain[nv_clk_src_core]; const int vdec = cstate->domain[nv_clk_src_vdec]; @@ -375,7 +381,7 @@ nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) int freq, out; /* prepare a hwsq script from which we'll perform the reclock */ - out = clk_init(hwsq, nv_subdev(clk)); + out = clk_init(hwsq, subdev); if (out) return out; @@ -393,15 +399,15 @@ nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) freq = calc_div(core, vdec, &P1); /* see how close we can get using xpll/hclk as a source */ - if (nv_device(priv)->chipset != 0x98) - out = read_pll(priv, 0x004030); + if (device->chipset != 0x98) + out = read_pll(clk, 0x004030); else - out = clk->read(clk, nv_clk_src_hclkm3d2); + out = nvkm_clk_read(&clk->base, nv_clk_src_hclkm3d2); out = calc_div(out, vdec, &P2); /* select whichever gets us closest */ if (abs(vdec - freq) <= abs(vdec - out)) { - if (nv_device(priv)->chipset != 0x98) + if (device->chipset != 0x98) mastv |= 0x00000c00; divsv |= P1 << 8; } else { @@ -417,14 +423,14 @@ nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) * of the host clock frequency */ if (dom6) { - if (clk_same(dom6, clk->read(clk, nv_clk_src_href))) { + if (clk_same(dom6, nvkm_clk_read(&clk->base, nv_clk_src_href))) { mastv |= 0x00000000; } else - if (clk_same(dom6, clk->read(clk, nv_clk_src_hclk))) { + if (clk_same(dom6, nvkm_clk_read(&clk->base, nv_clk_src_hclk))) { mastv |= 0x08000000; } else { - freq = clk->read(clk, nv_clk_src_hclk) * 3; - freq = calc_div(freq, dom6, &P1); + freq = nvkm_clk_read(&clk->base, nv_clk_src_hclk) * 3; + calc_div(freq, dom6, &P1); mastv |= 0x0c000000; divsv |= P1; @@ -444,13 +450,13 @@ nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) /* core/shader: disconnect nvclk/sclk from their PLLs (nvclk to dom6, * sclk to hclk) before reprogramming */ - if (nv_device(priv)->chipset < 0x92) + if (device->chipset < 0x92) clk_mask(hwsq, mast, 0x001000b0, 0x00100080); else clk_mask(hwsq, mast, 0x000000b3, 0x00000081); /* core: for the moment at least, always use nvpll */ - freq = calc_pll(priv, 0x4028, core, &N, &M, &P1); + freq = calc_pll(clk, 0x4028, core, &N, &M, &P1); if (freq == 0) return -ERANGE; @@ -468,7 +474,7 @@ nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) clk_mask(hwsq, spll[0], 0xc03f0100, (P1 << 19) | (P1 << 16)); clk_mask(hwsq, mast, 0x00100033, 0x00000023); } else { - freq = calc_pll(priv, 0x4020, shader, &N, &M, &P1); + freq = calc_pll(clk, 0x4020, shader, &N, &M, &P1); if (freq == 0) return -ERANGE; @@ -485,77 +491,71 @@ nv50_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate) return 0; } -static int -nv50_clk_prog(struct nvkm_clk *clk) +int +nv50_clk_prog(struct nvkm_clk *base) { - struct nv50_clk_priv *priv = (void *)clk; - return clk_exec(&priv->hwsq, true); + struct nv50_clk *clk = nv50_clk(base); + return clk_exec(&clk->hwsq, true); } -static void -nv50_clk_tidy(struct nvkm_clk *clk) +void +nv50_clk_tidy(struct nvkm_clk *base) { - struct nv50_clk_priv *priv = (void *)clk; - clk_exec(&priv->hwsq, false); + struct nv50_clk *clk = nv50_clk(base); + clk_exec(&clk->hwsq, false); } int -nv50_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_clk_new_(const struct nvkm_clk_func *func, struct nvkm_device *device, + int index, bool allow_reclock, struct nvkm_clk **pclk) { - struct nv50_clk_oclass *pclass = (void *)oclass; - struct nv50_clk_priv *priv; + struct nv50_clk *clk; int ret; - ret = nvkm_clk_create(parent, engine, oclass, pclass->domains, - NULL, 0, false, &priv); - *pobject = nv_object(priv); + if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL))) + return -ENOMEM; + ret = nvkm_clk_ctor(func, device, index, allow_reclock, &clk->base); + *pclk = &clk->base; if (ret) return ret; - priv->hwsq.r_fifo = hwsq_reg(0x002504); - priv->hwsq.r_spll[0] = hwsq_reg(0x004020); - priv->hwsq.r_spll[1] = hwsq_reg(0x004024); - priv->hwsq.r_nvpll[0] = hwsq_reg(0x004028); - priv->hwsq.r_nvpll[1] = hwsq_reg(0x00402c); - switch (nv_device(priv)->chipset) { + clk->hwsq.r_fifo = hwsq_reg(0x002504); + clk->hwsq.r_spll[0] = hwsq_reg(0x004020); + clk->hwsq.r_spll[1] = hwsq_reg(0x004024); + clk->hwsq.r_nvpll[0] = hwsq_reg(0x004028); + clk->hwsq.r_nvpll[1] = hwsq_reg(0x00402c); + switch (device->chipset) { case 0x92: case 0x94: case 0x96: - priv->hwsq.r_divs = hwsq_reg(0x004800); + clk->hwsq.r_divs = hwsq_reg(0x004800); break; default: - priv->hwsq.r_divs = hwsq_reg(0x004700); + clk->hwsq.r_divs = hwsq_reg(0x004700); break; } - priv->hwsq.r_mast = hwsq_reg(0x00c040); - - priv->base.read = nv50_clk_read; - priv->base.calc = nv50_clk_calc; - priv->base.prog = nv50_clk_prog; - priv->base.tidy = nv50_clk_tidy; + clk->hwsq.r_mast = hwsq_reg(0x00c040); return 0; } -static struct nvkm_domain -nv50_domains[] = { - { nv_clk_src_crystal, 0xff }, - { nv_clk_src_href , 0xff }, - { nv_clk_src_core , 0xff, 0, "core", 1000 }, - { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, - { nv_clk_src_mem , 0xff, 0, "memory", 1000 }, - { nv_clk_src_max } +static const struct nvkm_clk_func +nv50_clk = { + .read = nv50_clk_read, + .calc = nv50_clk_calc, + .prog = nv50_clk_prog, + .tidy = nv50_clk_tidy, + .domains = { + { nv_clk_src_crystal, 0xff }, + { nv_clk_src_href , 0xff }, + { nv_clk_src_core , 0xff, 0, "core", 1000 }, + { nv_clk_src_shader , 0xff, 0, "shader", 1000 }, + { nv_clk_src_mem , 0xff, 0, "memory", 1000 }, + { nv_clk_src_max } + } }; -struct nvkm_oclass * -nv50_clk_oclass = &(struct nv50_clk_oclass) { - .base.handle = NV_SUBDEV(CLK, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_clk_ctor, - .dtor = _nvkm_clk_dtor, - .init = _nvkm_clk_init, - .fini = _nvkm_clk_fini, - }, - .domains = nv50_domains, -}.base; +int +nv50_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) +{ + return nv50_clk_new_(&nv50_clk, device, index, false, pclk); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h index 0ead76a32..d3c7fb6ef 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h @@ -1,7 +1,9 @@ -#ifndef __NVKM_CLK_NV50_H__ -#define __NVKM_CLK_NV50_H__ +#ifndef __NV50_CLK_H__ +#define __NV50_CLK_H__ +#define nv50_clk(p) container_of((p), struct nv50_clk, base) +#include "priv.h" + #include -#include struct nv50_clk_hwsq { struct hwsq base; @@ -12,17 +14,15 @@ struct nv50_clk_hwsq { struct hwsq_reg r_mast; }; -struct nv50_clk_priv { +struct nv50_clk { struct nvkm_clk base; struct nv50_clk_hwsq hwsq; }; -int nv50_clk_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - -struct nv50_clk_oclass { - struct nvkm_oclass base; - struct nvkm_domain *domains; -}; +int nv50_clk_new_(const struct nvkm_clk_func *, struct nvkm_device *, int, + bool, struct nvkm_clk **); +int nv50_clk_read(struct nvkm_clk *, enum nv_clk_src); +int nv50_clk_calc(struct nvkm_clk *, struct nvkm_cstate *); +int nv50_clk_prog(struct nvkm_clk *); +void nv50_clk_tidy(struct nvkm_clk *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllgt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllgt215.c index 783a3e78d..c6fccd600 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllgt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllgt215.c @@ -79,7 +79,7 @@ gt215_pll_calc(struct nvkm_subdev *subdev, struct nvbios_pll *info, } if (unlikely(best_err == ~0)) { - nv_error(subdev, "unable to find matching pll values\n"); + nvkm_error(subdev, "unable to find matching pll values\n"); return -EINVAL; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c index f2292895a..5ad67879e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c @@ -37,7 +37,7 @@ getMNP_single(struct nvkm_subdev *subdev, struct nvbios_pll *info, int clk, * "clk" parameter in kHz * returns calculated clock */ - struct nvkm_bios *bios = nvkm_bios(subdev); + struct nvkm_bios *bios = subdev->device->bios; int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq; int minM = info->vco1.min_m, maxM = info->vco1.max_m; int minN = info->vco1.min_n, maxN = info->vco1.max_n; @@ -136,7 +136,7 @@ getMNP_double(struct nvkm_subdev *subdev, struct nvbios_pll *info, int clk, * "clk" parameter in kHz * returns calculated clock */ - int chip_version = nvkm_bios(subdev)->version.chip; + int chip_version = subdev->device->bios->version.chip; int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq; int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq; int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq; @@ -240,6 +240,6 @@ nv04_pll_calc(struct nvkm_subdev *subdev, struct nvbios_pll *info, u32 freq, } if (!ret) - nv_error(subdev, "unable to compute acceptable pll values\n"); + nvkm_error(subdev, "unable to compute acceptable pll values\n"); return ret; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h new file mode 100644 index 000000000..51eafc00c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_CLK_PRIV_H__ +#define __NVKM_CLK_PRIV_H__ +#define nvkm_clk(p) container_of((p), struct nvkm_clk, subdev) +#include + +struct nvkm_clk_func { + int (*init)(struct nvkm_clk *); + void (*fini)(struct nvkm_clk *); + int (*read)(struct nvkm_clk *, enum nv_clk_src); + int (*calc)(struct nvkm_clk *, struct nvkm_cstate *); + int (*prog)(struct nvkm_clk *); + void (*tidy)(struct nvkm_clk *); + struct nvkm_pstate *pstates; + int nr_pstates; + struct nvkm_domain domains[]; +}; + +int nvkm_clk_ctor(const struct nvkm_clk_func *, struct nvkm_device *, int, + bool allow_reclock, struct nvkm_clk *); +int nvkm_clk_new_(const struct nvkm_clk_func *, struct nvkm_device *, int, + bool allow_reclock, struct nvkm_clk **); + +int nv04_clk_pll_calc(struct nvkm_clk *, struct nvbios_pll *, int clk, + struct nvkm_pll_vals *); +int nv04_clk_pll_prog(struct nvkm_clk *, u32 reg1, struct nvkm_pll_vals *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c index b0d7c5f40..5f25402f6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c @@ -23,74 +23,108 @@ */ #include "priv.h" -#include #include #include -int -_nvkm_devinit_fini(struct nvkm_object *object, bool suspend) +u32 +nvkm_devinit_mmio(struct nvkm_devinit *init, u32 addr) { - struct nvkm_devinit *devinit = (void *)object; + if (init->func->mmio) + addr = init->func->mmio(init, addr); + return addr; +} - /* force full reinit on resume */ - if (suspend) - devinit->post = true; +int +nvkm_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 khz) +{ + return init->func->pll_set(init, type, khz); +} - /* unlock the extended vga crtc regs */ - nv_lockvgac(devinit, false); +void +nvkm_devinit_meminit(struct nvkm_devinit *init) +{ + if (init->func->meminit) + init->func->meminit(init); +} - return nvkm_subdev_fini(&devinit->base, suspend); +u64 +nvkm_devinit_disable(struct nvkm_devinit *init) +{ + if (init && init->func->disable) + return init->func->disable(init); + return 0; } int -_nvkm_devinit_init(struct nvkm_object *object) +nvkm_devinit_post(struct nvkm_devinit *init, u64 *disable) { - struct nvkm_devinit_impl *impl = (void *)object->oclass; - struct nvkm_devinit *devinit = (void *)object; - int ret; + int ret = 0; + if (init && init->func->post) + ret = init->func->post(init, init->post); + *disable = nvkm_devinit_disable(init); + return ret; +} - ret = nvkm_subdev_init(&devinit->base); - if (ret) - return ret; +static int +nvkm_devinit_fini(struct nvkm_subdev *subdev, bool suspend) +{ + struct nvkm_devinit *init = nvkm_devinit(subdev); + /* force full reinit on resume */ + if (suspend) + init->post = true; + return 0; +} + +static int +nvkm_devinit_preinit(struct nvkm_subdev *subdev) +{ + struct nvkm_devinit *init = nvkm_devinit(subdev); - ret = impl->post(&devinit->base, devinit->post); - if (ret) - return ret; + if (init->func->preinit) + init->func->preinit(init); - if (impl->disable) - nv_device(devinit)->disable_mask |= impl->disable(devinit); + /* unlock the extended vga crtc regs */ + nvkm_lockvgac(subdev->device, false); return 0; } -void -_nvkm_devinit_dtor(struct nvkm_object *object) +static int +nvkm_devinit_init(struct nvkm_subdev *subdev) +{ + struct nvkm_devinit *init = nvkm_devinit(subdev); + if (init->func->init) + init->func->init(init); + return 0; +} + +static void * +nvkm_devinit_dtor(struct nvkm_subdev *subdev) { - struct nvkm_devinit *devinit = (void *)object; + struct nvkm_devinit *init = nvkm_devinit(subdev); + void *data = init; - /* lock crtc regs */ - nv_lockvgac(devinit, true); + if (init->func->dtor) + data = init->func->dtor(init); - nvkm_subdev_destroy(&devinit->base); + /* lock crtc regs */ + nvkm_lockvgac(subdev->device, true); + return data; } -int -nvkm_devinit_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int size, void **pobject) +static const struct nvkm_subdev_func +nvkm_devinit = { + .dtor = nvkm_devinit_dtor, + .preinit = nvkm_devinit_preinit, + .init = nvkm_devinit_init, + .fini = nvkm_devinit_fini, +}; + +void +nvkm_devinit_ctor(const struct nvkm_devinit_func *func, + struct nvkm_device *device, int index, + struct nvkm_devinit *init) { - struct nvkm_devinit_impl *impl = (void *)oclass; - struct nvkm_device *device = nv_device(parent); - struct nvkm_devinit *devinit; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "DEVINIT", - "init", size, pobject); - devinit = *pobject; - if (ret) - return ret; - - devinit->post = nvkm_boolopt(device->cfgopt, "NvForcePost", false); - devinit->meminit = impl->meminit; - devinit->pll_set = impl->pll_set; - devinit->mmio = impl->mmio; - return 0; + nvkm_subdev_ctor(&nvkm_devinit, device, index, 0, &init->subdev); + init->func = func; + init->post = nvkm_boolopt(device->cfgopt, "NvForcePost", false); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/fbmem.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/fbmem.h index 36684c3f9..6c5bbff12 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/fbmem.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/fbmem.h @@ -23,7 +23,6 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include #include #define NV04_PFB_DEBUG_0 0x00100080 @@ -48,8 +47,8 @@ static inline struct io_mapping * fbmem_init(struct nvkm_device *dev) { - return io_mapping_create_wc(nv_device_resource_start(dev, 1), - nv_device_resource_len(dev, 1)); + return io_mapping_create_wc(dev->func->resource_addr(dev, 1), + dev->func->resource_size(dev, 1)); } static inline void diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c index ca776ce75..e895289bf 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c @@ -27,40 +27,42 @@ #include static u64 -g84_devinit_disable(struct nvkm_devinit *devinit) +g84_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r001540 = nv_rd32(priv, 0x001540); - u32 r00154c = nv_rd32(priv, 0x00154c); + struct nvkm_device *device = init->subdev.device; + u32 r001540 = nvkm_rd32(device, 0x001540); + u32 r00154c = nvkm_rd32(device, 0x00154c); u64 disable = 0ULL; if (!(r001540 & 0x40000000)) { - disable |= (1ULL << NVDEV_ENGINE_MPEG); - disable |= (1ULL << NVDEV_ENGINE_VP); - disable |= (1ULL << NVDEV_ENGINE_BSP); - disable |= (1ULL << NVDEV_ENGINE_CIPHER); + disable |= (1ULL << NVKM_ENGINE_MPEG); + disable |= (1ULL << NVKM_ENGINE_VP); + disable |= (1ULL << NVKM_ENGINE_BSP); + disable |= (1ULL << NVKM_ENGINE_CIPHER); } if (!(r00154c & 0x00000004)) - disable |= (1ULL << NVDEV_ENGINE_DISP); + disable |= (1ULL << NVKM_ENGINE_DISP); if (!(r00154c & 0x00000020)) - disable |= (1ULL << NVDEV_ENGINE_BSP); + disable |= (1ULL << NVKM_ENGINE_BSP); if (!(r00154c & 0x00000040)) - disable |= (1ULL << NVDEV_ENGINE_CIPHER); + disable |= (1ULL << NVKM_ENGINE_CIPHER); return disable; } -struct nvkm_oclass * -g84_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x84), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +g84_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, .pll_set = nv50_devinit_pll_set, .disable = g84_devinit_disable, - .post = nvbios_init, -}.base; +}; + +int +g84_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(&g84_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c index d29bacee6..a9d45844d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c @@ -27,39 +27,41 @@ #include static u64 -g98_devinit_disable(struct nvkm_devinit *devinit) +g98_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r001540 = nv_rd32(priv, 0x001540); - u32 r00154c = nv_rd32(priv, 0x00154c); + struct nvkm_device *device = init->subdev.device; + u32 r001540 = nvkm_rd32(device, 0x001540); + u32 r00154c = nvkm_rd32(device, 0x00154c); u64 disable = 0ULL; if (!(r001540 & 0x40000000)) { - disable |= (1ULL << NVDEV_ENGINE_MSPDEC); - disable |= (1ULL << NVDEV_ENGINE_MSVLD); - disable |= (1ULL << NVDEV_ENGINE_MSPPP); + disable |= (1ULL << NVKM_ENGINE_MSPDEC); + disable |= (1ULL << NVKM_ENGINE_MSVLD); + disable |= (1ULL << NVKM_ENGINE_MSPPP); } if (!(r00154c & 0x00000004)) - disable |= (1ULL << NVDEV_ENGINE_DISP); + disable |= (1ULL << NVKM_ENGINE_DISP); if (!(r00154c & 0x00000020)) - disable |= (1ULL << NVDEV_ENGINE_MSVLD); + disable |= (1ULL << NVKM_ENGINE_MSVLD); if (!(r00154c & 0x00000040)) - disable |= (1ULL << NVDEV_ENGINE_SEC); + disable |= (1ULL << NVKM_ENGINE_SEC); return disable; } -struct nvkm_oclass * -g98_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x98), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +g98_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, .pll_set = nv50_devinit_pll_set, .disable = g98_devinit_disable, - .post = nvbios_init, -}.base; +}; + +int +g98_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(&g98_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c index c61102f70..22b0140e2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c @@ -29,19 +29,19 @@ #include int -gf100_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) +gf100_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) { - struct nv50_devinit_priv *priv = (void *)devinit; - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; struct nvbios_pll info; int N, fN, M, P; int ret; - ret = nvbios_pll_parse(bios, type, &info); + ret = nvbios_pll_parse(device->bios, type, &info); if (ret) return ret; - ret = gt215_pll_calc(nv_subdev(devinit), &info, freq, &N, &fN, &M, &P); + ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P); if (ret < 0) return ret; @@ -50,12 +50,12 @@ gf100_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) case PLL_VPLL1: case PLL_VPLL2: case PLL_VPLL3: - nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); - nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); - nv_wr32(priv, info.reg + 0x10, fN << 16); + nvkm_mask(device, info.reg + 0x0c, 0x00000000, 0x00000100); + nvkm_wr32(device, info.reg + 0x04, (P << 16) | (N << 8) | M); + nvkm_wr32(device, info.reg + 0x10, fN << 16); break; default: - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq); ret = -EINVAL; break; } @@ -64,64 +64,44 @@ gf100_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) } static u64 -gf100_devinit_disable(struct nvkm_devinit *devinit) +gf100_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r022500 = nv_rd32(priv, 0x022500); + struct nvkm_device *device = init->subdev.device; + u32 r022500 = nvkm_rd32(device, 0x022500); u64 disable = 0ULL; if (r022500 & 0x00000001) - disable |= (1ULL << NVDEV_ENGINE_DISP); + disable |= (1ULL << NVKM_ENGINE_DISP); if (r022500 & 0x00000002) { - disable |= (1ULL << NVDEV_ENGINE_MSPDEC); - disable |= (1ULL << NVDEV_ENGINE_MSPPP); + disable |= (1ULL << NVKM_ENGINE_MSPDEC); + disable |= (1ULL << NVKM_ENGINE_MSPPP); } if (r022500 & 0x00000004) - disable |= (1ULL << NVDEV_ENGINE_MSVLD); + disable |= (1ULL << NVKM_ENGINE_MSVLD); if (r022500 & 0x00000008) - disable |= (1ULL << NVDEV_ENGINE_MSENC); + disable |= (1ULL << NVKM_ENGINE_MSENC); if (r022500 & 0x00000100) - disable |= (1ULL << NVDEV_ENGINE_CE0); + disable |= (1ULL << NVKM_ENGINE_CE0); if (r022500 & 0x00000200) - disable |= (1ULL << NVDEV_ENGINE_CE1); + disable |= (1ULL << NVKM_ENGINE_CE1); return disable; } +static const struct nvkm_devinit_func +gf100_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, + .pll_set = gf100_devinit_pll_set, + .disable = gf100_devinit_disable, +}; + int -gf100_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) { - struct nvkm_devinit_impl *impl = (void *)oclass; - struct nv50_devinit_priv *priv; - u64 disable; - int ret; - - ret = nvkm_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - disable = impl->disable(&priv->base); - if (disable & (1ULL << NVDEV_ENGINE_DISP)) - priv->base.post = true; - - return 0; + return nv50_devinit_new_(&gf100_devinit, device, index, pinit); } - -struct nvkm_oclass * -gf100_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, - .pll_set = gf100_devinit_pll_set, - .disable = gf100_devinit_disable, - .post = nvbios_init, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c index 87ca0ece3..2be98bd78 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c @@ -27,33 +27,35 @@ #include u64 -gm107_devinit_disable(struct nvkm_devinit *devinit) +gm107_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r021c00 = nv_rd32(priv, 0x021c00); - u32 r021c04 = nv_rd32(priv, 0x021c04); + struct nvkm_device *device = init->subdev.device; + u32 r021c00 = nvkm_rd32(device, 0x021c00); + u32 r021c04 = nvkm_rd32(device, 0x021c04); u64 disable = 0ULL; if (r021c00 & 0x00000001) - disable |= (1ULL << NVDEV_ENGINE_CE0); + disable |= (1ULL << NVKM_ENGINE_CE0); if (r021c00 & 0x00000004) - disable |= (1ULL << NVDEV_ENGINE_CE2); + disable |= (1ULL << NVKM_ENGINE_CE2); if (r021c04 & 0x00000001) - disable |= (1ULL << NVDEV_ENGINE_DISP); + disable |= (1ULL << NVKM_ENGINE_DISP); return disable; } -struct nvkm_oclass * -gm107_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x07), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +gm107_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, .pll_set = gf100_devinit_pll_set, .disable = gm107_devinit_disable, - .post = nvbios_init, -}.base; +}; + +int +gm107_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(&gm107_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm204.c index 1076fcf0d..2b9c3f11b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm204.c @@ -28,69 +28,74 @@ #include static void -pmu_code(struct nv50_devinit_priv *priv, u32 pmu, u32 img, u32 len, bool sec) +pmu_code(struct nv50_devinit *init, u32 pmu, u32 img, u32 len, bool sec) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_device *device = init->base.subdev.device; + struct nvkm_bios *bios = device->bios; int i; - nv_wr32(priv, 0x10a180, 0x01000000 | (sec ? 0x10000000 : 0) | pmu); + nvkm_wr32(device, 0x10a180, 0x01000000 | (sec ? 0x10000000 : 0) | pmu); for (i = 0; i < len; i += 4) { if ((i & 0xff) == 0) - nv_wr32(priv, 0x10a188, (pmu + i) >> 8); - nv_wr32(priv, 0x10a184, nv_ro32(bios, img + i)); + nvkm_wr32(device, 0x10a188, (pmu + i) >> 8); + nvkm_wr32(device, 0x10a184, nvbios_rd32(bios, img + i)); } while (i & 0xff) { - nv_wr32(priv, 0x10a184, 0x00000000); + nvkm_wr32(device, 0x10a184, 0x00000000); i += 4; } } static void -pmu_data(struct nv50_devinit_priv *priv, u32 pmu, u32 img, u32 len) +pmu_data(struct nv50_devinit *init, u32 pmu, u32 img, u32 len) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_device *device = init->base.subdev.device; + struct nvkm_bios *bios = device->bios; int i; - nv_wr32(priv, 0x10a1c0, 0x01000000 | pmu); + nvkm_wr32(device, 0x10a1c0, 0x01000000 | pmu); for (i = 0; i < len; i += 4) - nv_wr32(priv, 0x10a1c4, nv_ro32(bios, img + i)); + nvkm_wr32(device, 0x10a1c4, nvbios_rd32(bios, img + i)); } static u32 -pmu_args(struct nv50_devinit_priv *priv, u32 argp, u32 argi) +pmu_args(struct nv50_devinit *init, u32 argp, u32 argi) { - nv_wr32(priv, 0x10a1c0, argp); - nv_wr32(priv, 0x10a1c0, nv_rd32(priv, 0x10a1c4) + argi); - return nv_rd32(priv, 0x10a1c4); + struct nvkm_device *device = init->base.subdev.device; + nvkm_wr32(device, 0x10a1c0, argp); + nvkm_wr32(device, 0x10a1c0, nvkm_rd32(device, 0x10a1c4) + argi); + return nvkm_rd32(device, 0x10a1c4); } static void -pmu_exec(struct nv50_devinit_priv *priv, u32 init_addr) +pmu_exec(struct nv50_devinit *init, u32 init_addr) { - nv_wr32(priv, 0x10a104, init_addr); - nv_wr32(priv, 0x10a10c, 0x00000000); - nv_wr32(priv, 0x10a100, 0x00000002); + struct nvkm_device *device = init->base.subdev.device; + nvkm_wr32(device, 0x10a104, init_addr); + nvkm_wr32(device, 0x10a10c, 0x00000000); + nvkm_wr32(device, 0x10a100, 0x00000002); } static int -pmu_load(struct nv50_devinit_priv *priv, u8 type, bool post, +pmu_load(struct nv50_devinit *init, u8 type, bool post, u32 *init_addr_pmu, u32 *args_addr_pmu) { - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &init->base.subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvbios_pmuR pmu; if (!nvbios_pmuRm(bios, type, &pmu)) { - nv_error(priv, "VBIOS PMU fuc %02x not found\n", type); + nvkm_error(subdev, "VBIOS PMU fuc %02x not found\n", type); return -EINVAL; } if (!post) return 0; - pmu_code(priv, pmu.boot_addr_pmu, pmu.boot_addr, pmu.boot_size, false); - pmu_code(priv, pmu.code_addr_pmu, pmu.code_addr, pmu.code_size, true); - pmu_data(priv, pmu.data_addr_pmu, pmu.data_addr, pmu.data_size); + pmu_code(init, pmu.boot_addr_pmu, pmu.boot_addr, pmu.boot_size, false); + pmu_code(init, pmu.code_addr_pmu, pmu.code_addr, pmu.code_size, true); + pmu_data(init, pmu.data_addr_pmu, pmu.data_addr, pmu.data_size); if (init_addr_pmu) { *init_addr_pmu = pmu.init_addr_pmu; @@ -98,75 +103,79 @@ pmu_load(struct nv50_devinit_priv *priv, u8 type, bool post, return 0; } - return pmu_exec(priv, pmu.init_addr_pmu), 0; + return pmu_exec(init, pmu.init_addr_pmu), 0; } static int -gm204_devinit_post(struct nvkm_subdev *subdev, bool post) +gm204_devinit_post(struct nvkm_devinit *base, bool post) { - struct nv50_devinit_priv *priv = (void *)nvkm_devinit(subdev); - struct nvkm_bios *bios = nvkm_bios(priv); + struct nv50_devinit *init = nv50_devinit(base); + struct nvkm_subdev *subdev = &init->base.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct bit_entry bit_I; - u32 init, args; + u32 exec, args; int ret; if (bit_entry(bios, 'I', &bit_I) || bit_I.version != 1 || bit_I.length < 0x1c) { - nv_error(priv, "VBIOS PMU init data not found\n"); + nvkm_error(subdev, "VBIOS PMU init data not found\n"); return -EINVAL; } /* reset PMU and load init table parser ucode */ if (post) { - nv_mask(priv, 0x000200, 0x00002000, 0x00000000); - nv_mask(priv, 0x000200, 0x00002000, 0x00002000); - nv_rd32(priv, 0x000200); - while (nv_rd32(priv, 0x10a10c) & 0x00000006) { + nvkm_mask(device, 0x000200, 0x00002000, 0x00000000); + nvkm_mask(device, 0x000200, 0x00002000, 0x00002000); + nvkm_rd32(device, 0x000200); + while (nvkm_rd32(device, 0x10a10c) & 0x00000006) { } } - ret = pmu_load(priv, 0x04, post, &init, &args); + ret = pmu_load(init, 0x04, post, &exec, &args); if (ret) return ret; /* upload first chunk of init data */ if (post) { - u32 pmu = pmu_args(priv, args + 0x08, 0x08); - u32 img = nv_ro16(bios, bit_I.offset + 0x14); - u32 len = nv_ro16(bios, bit_I.offset + 0x16); - pmu_data(priv, pmu, img, len); + u32 pmu = pmu_args(init, args + 0x08, 0x08); + u32 img = nvbios_rd16(bios, bit_I.offset + 0x14); + u32 len = nvbios_rd16(bios, bit_I.offset + 0x16); + pmu_data(init, pmu, img, len); } /* upload second chunk of init data */ if (post) { - u32 pmu = pmu_args(priv, args + 0x08, 0x10); - u32 img = nv_ro16(bios, bit_I.offset + 0x18); - u32 len = nv_ro16(bios, bit_I.offset + 0x1a); - pmu_data(priv, pmu, img, len); + u32 pmu = pmu_args(init, args + 0x08, 0x10); + u32 img = nvbios_rd16(bios, bit_I.offset + 0x18); + u32 len = nvbios_rd16(bios, bit_I.offset + 0x1a); + pmu_data(init, pmu, img, len); } /* execute init tables */ if (post) { - nv_wr32(priv, 0x10a040, 0x00005000); - pmu_exec(priv, init); - while (!(nv_rd32(priv, 0x10a040) & 0x00002000)) { + nvkm_wr32(device, 0x10a040, 0x00005000); + pmu_exec(init, exec); + while (!(nvkm_rd32(device, 0x10a040) & 0x00002000)) { } } /* load and execute some other ucode image (bios therm?) */ - return pmu_load(priv, 0x01, post, NULL, NULL); + return pmu_load(init, 0x01, post, NULL, NULL); } -struct nvkm_oclass * -gm204_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x07), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +gm204_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = gm204_devinit_post, .pll_set = gf100_devinit_pll_set, .disable = gm107_devinit_disable, - .post = gm204_devinit_post, -}.base; +}; + +int +gm204_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(&gm204_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c index 6a3e8d4ef..9a8522fa9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c @@ -29,32 +29,32 @@ #include int -gt215_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) +gt215_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) { - struct nv50_devinit_priv *priv = (void *)devinit; - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; struct nvbios_pll info; int N, fN, M, P; int ret; - ret = nvbios_pll_parse(bios, type, &info); + ret = nvbios_pll_parse(device->bios, type, &info); if (ret) return ret; - ret = gt215_pll_calc(nv_subdev(devinit), &info, freq, &N, &fN, &M, &P); + ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P); if (ret < 0) return ret; switch (info.type) { case PLL_VPLL0: case PLL_VPLL1: - nv_wr32(priv, info.reg + 0, 0x50000610); - nv_mask(priv, info.reg + 4, 0x003fffff, - (P << 16) | (M << 8) | N); - nv_wr32(priv, info.reg + 8, fN); + nvkm_wr32(device, info.reg + 0, 0x50000610); + nvkm_mask(device, info.reg + 4, 0x003fffff, + (P << 16) | (M << 8) | N); + nvkm_wr32(device, info.reg + 8, fN); break; default: - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq); ret = -EINVAL; break; } @@ -63,24 +63,24 @@ gt215_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) } static u64 -gt215_devinit_disable(struct nvkm_devinit *devinit) +gt215_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r001540 = nv_rd32(priv, 0x001540); - u32 r00154c = nv_rd32(priv, 0x00154c); + struct nvkm_device *device = init->subdev.device; + u32 r001540 = nvkm_rd32(device, 0x001540); + u32 r00154c = nvkm_rd32(device, 0x00154c); u64 disable = 0ULL; if (!(r001540 & 0x40000000)) { - disable |= (1ULL << NVDEV_ENGINE_MSPDEC); - disable |= (1ULL << NVDEV_ENGINE_MSPPP); + disable |= (1ULL << NVKM_ENGINE_MSPDEC); + disable |= (1ULL << NVKM_ENGINE_MSPPP); } if (!(r00154c & 0x00000004)) - disable |= (1ULL << NVDEV_ENGINE_DISP); + disable |= (1ULL << NVKM_ENGINE_DISP); if (!(r00154c & 0x00000020)) - disable |= (1ULL << NVDEV_ENGINE_MSVLD); + disable |= (1ULL << NVKM_ENGINE_MSVLD); if (!(r00154c & 0x00000200)) - disable |= (1ULL << NVDEV_ENGINE_CE0); + disable |= (1ULL << NVKM_ENGINE_CE0); return disable; } @@ -99,9 +99,10 @@ gt215_devinit_mmio_part[] = { }; static u32 -gt215_devinit_mmio(struct nvkm_devinit *devinit, u32 addr) +gt215_devinit_mmio(struct nvkm_devinit *base, u32 addr) { - struct nv50_devinit_priv *priv = (void *)devinit; + struct nv50_devinit *init = nv50_devinit(base); + struct nvkm_device *device = init->base.subdev.device; u32 *mmio = gt215_devinit_mmio_part; /* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP @@ -113,7 +114,7 @@ gt215_devinit_mmio(struct nvkm_devinit *devinit, u32 addr) * * the binary driver avoids touching these registers at all, however, * the video bios doesn't care and does what the scripts say. it's - * presumed that the io-port access to priv registers isn't effected + * presumed that the io-port access to init registers isn't effected * by the screw-up bug mentioned above. * * really, a new opcode should've been invented to handle these @@ -122,9 +123,9 @@ gt215_devinit_mmio(struct nvkm_devinit *devinit, u32 addr) while (mmio[0]) { if (addr >= mmio[0] && addr <= mmio[1]) { u32 part = (addr / mmio[2]) & 7; - if (!priv->r001540) - priv->r001540 = nv_rd32(priv, 0x001540); - if (part >= hweight8((priv->r001540 >> 16) & 0xff)) + if (!init->r001540) + init->r001540 = nvkm_rd32(device, 0x001540); + if (part >= hweight8((init->r001540 >> 16) & 0xff)) return ~0; return addr; } @@ -134,17 +135,19 @@ gt215_devinit_mmio(struct nvkm_devinit *devinit, u32 addr) return addr; } -struct nvkm_oclass * -gt215_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0xa3), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +gt215_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, + .mmio = gt215_devinit_mmio, .pll_set = gt215_devinit_pll_set, .disable = gt215_devinit_disable, - .mmio = gt215_devinit_mmio, - .post = nvbios_init, -}.base; +}; + +int +gt215_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(>215_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c index 55cf48bbc..ce4f718e9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c @@ -27,40 +27,42 @@ #include static u64 -mcp89_devinit_disable(struct nvkm_devinit *devinit) +mcp89_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r001540 = nv_rd32(priv, 0x001540); - u32 r00154c = nv_rd32(priv, 0x00154c); + struct nvkm_device *device = init->subdev.device; + u32 r001540 = nvkm_rd32(device, 0x001540); + u32 r00154c = nvkm_rd32(device, 0x00154c); u64 disable = 0; if (!(r001540 & 0x40000000)) { - disable |= (1ULL << NVDEV_ENGINE_MSPDEC); - disable |= (1ULL << NVDEV_ENGINE_MSPPP); + disable |= (1ULL << NVKM_ENGINE_MSPDEC); + disable |= (1ULL << NVKM_ENGINE_MSPPP); } if (!(r00154c & 0x00000004)) - disable |= (1ULL << NVDEV_ENGINE_DISP); + disable |= (1ULL << NVKM_ENGINE_DISP); if (!(r00154c & 0x00000020)) - disable |= (1ULL << NVDEV_ENGINE_MSVLD); + disable |= (1ULL << NVKM_ENGINE_MSVLD); if (!(r00154c & 0x00000040)) - disable |= (1ULL << NVDEV_ENGINE_VIC); + disable |= (1ULL << NVKM_ENGINE_VIC); if (!(r00154c & 0x00000200)) - disable |= (1ULL << NVDEV_ENGINE_CE0); + disable |= (1ULL << NVKM_ENGINE_CE0); return disable; } -struct nvkm_oclass * -mcp89_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0xaf), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +mcp89_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, .pll_set = gt215_devinit_pll_set, .disable = mcp89_devinit_disable, - .post = nvbios_init, -}.base; +}; + +int +mcp89_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(&mcp89_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c index 03a0da834..c8d455346 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c @@ -33,25 +33,26 @@ #include static void -nv04_devinit_meminit(struct nvkm_devinit *devinit) +nv04_devinit_meminit(struct nvkm_devinit *init) { - struct nv04_devinit_priv *priv = (void *)devinit; + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; u32 patt = 0xdeadbeef; struct io_mapping *fb; int i; /* Map the framebuffer aperture */ - fb = fbmem_init(nv_device(priv)); + fb = fbmem_init(device); if (!fb) { - nv_error(priv, "failed to map fb\n"); + nvkm_error(subdev, "failed to map fb\n"); return; } /* Sequencer and refresh off */ - nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); - nv_mask(priv, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); + nvkm_wrvgas(device, 0, 1, nvkm_rdvgas(device, 0, 1) | 0x20); + nvkm_mask(device, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); - nv_mask(priv, NV04_PFB_BOOT_0, ~0, + nvkm_mask(device, NV04_PFB_BOOT_0, ~0, NV04_PFB_BOOT_0_RAM_AMOUNT_16MB | NV04_PFB_BOOT_0_RAM_WIDTH_128 | NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT); @@ -62,49 +63,49 @@ nv04_devinit_meminit(struct nvkm_devinit *devinit) fbmem_poke(fb, 0x400000, patt + 1); if (fbmem_peek(fb, 0) == patt + 1) { - nv_mask(priv, NV04_PFB_BOOT_0, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT); - nv_mask(priv, NV04_PFB_DEBUG_0, + nvkm_mask(device, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); for (i = 0; i < 4; i++) fbmem_poke(fb, 4 * i, patt); if ((fbmem_peek(fb, 0xc) & 0xffff) != (patt & 0xffff)) - nv_mask(priv, NV04_PFB_BOOT_0, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_WIDTH_128 | NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); } else if ((fbmem_peek(fb, 0xc) & 0xffff0000) != (patt & 0xffff0000)) { - nv_mask(priv, NV04_PFB_BOOT_0, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_WIDTH_128 | NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); } else if (fbmem_peek(fb, 0) != patt) { if (fbmem_readback(fb, 0x800000, patt)) - nv_mask(priv, NV04_PFB_BOOT_0, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); else - nv_mask(priv, NV04_PFB_BOOT_0, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); - nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT); } else if (!fbmem_readback(fb, 0x800000, patt)) { - nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); } /* Refresh on, sequencer on */ - nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); - nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); + nvkm_mask(device, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + nvkm_wrvgas(device, 0, 1, nvkm_rdvgas(device, 0, 1) & ~0x20); fbmem_fini(fb); } @@ -139,11 +140,12 @@ powerctrl_1_shift(int chip_version, int reg) } void -setPLL_single(struct nvkm_devinit *devinit, u32 reg, +setPLL_single(struct nvkm_devinit *init, u32 reg, struct nvkm_pll_vals *pv) { - int chip_version = nvkm_bios(devinit)->version.chip; - uint32_t oldpll = nv_rd32(devinit, reg); + struct nvkm_device *device = init->subdev.device; + int chip_version = device->bios->version.chip; + uint32_t oldpll = nvkm_rd32(device, reg); int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; uint32_t saved_powerctrl_1 = 0; @@ -153,30 +155,30 @@ setPLL_single(struct nvkm_devinit *devinit, u32 reg, return; /* already set */ if (shift_powerctrl_1 >= 0) { - saved_powerctrl_1 = nv_rd32(devinit, 0x001584); - nv_wr32(devinit, 0x001584, + saved_powerctrl_1 = nvkm_rd32(device, 0x001584); + nvkm_wr32(device, 0x001584, (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | 1 << shift_powerctrl_1); } if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) /* upclock -- write new post divider first */ - nv_wr32(devinit, reg, pv->log2P << 16 | (oldpll & 0xffff)); + nvkm_wr32(device, reg, pv->log2P << 16 | (oldpll & 0xffff)); else /* downclock -- write new NM first */ - nv_wr32(devinit, reg, (oldpll & 0xffff0000) | pv->NM1); + nvkm_wr32(device, reg, (oldpll & 0xffff0000) | pv->NM1); if ((chip_version < 0x17 || chip_version == 0x1a) && chip_version != 0x11) /* wait a bit on older chips */ msleep(64); - nv_rd32(devinit, reg); + nvkm_rd32(device, reg); /* then write the other half as well */ - nv_wr32(devinit, reg, pll); + nvkm_wr32(device, reg, pll); if (shift_powerctrl_1 >= 0) - nv_wr32(devinit, 0x001584, saved_powerctrl_1); + nvkm_wr32(device, 0x001584, saved_powerctrl_1); } static uint32_t @@ -193,14 +195,15 @@ new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) } void -setPLL_double_highregs(struct nvkm_devinit *devinit, u32 reg1, +setPLL_double_highregs(struct nvkm_devinit *init, u32 reg1, struct nvkm_pll_vals *pv) { - int chip_version = nvkm_bios(devinit)->version.chip; + struct nvkm_device *device = init->subdev.device; + int chip_version = device->bios->version.chip; bool nv3035 = chip_version == 0x30 || chip_version == 0x35; uint32_t reg2 = reg1 + ((reg1 == 0x680520) ? 0x5c : 0x70); - uint32_t oldpll1 = nv_rd32(devinit, reg1); - uint32_t oldpll2 = !nv3035 ? nv_rd32(devinit, reg2) : 0; + uint32_t oldpll1 = nvkm_rd32(device, reg1); + uint32_t oldpll2 = !nv3035 ? nvkm_rd32(device, reg2) : 0; uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; uint32_t oldramdac580 = 0, ramdac580 = 0; @@ -215,7 +218,7 @@ setPLL_double_highregs(struct nvkm_devinit *devinit, u32 reg1, pll2 = 0; } if (chip_version > 0x40 && reg1 >= 0x680508) { /* !nv40 */ - oldramdac580 = nv_rd32(devinit, 0x680580); + oldramdac580 = nvkm_rd32(device, 0x680580); ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); if (oldramdac580 != ramdac580) oldpll1 = ~0; /* force mismatch */ @@ -231,8 +234,8 @@ setPLL_double_highregs(struct nvkm_devinit *devinit, u32 reg1, return; /* already set */ if (shift_powerctrl_1 >= 0) { - saved_powerctrl_1 = nv_rd32(devinit, 0x001584); - nv_wr32(devinit, 0x001584, + saved_powerctrl_1 = nvkm_rd32(device, 0x001584); + nvkm_wr32(device, 0x001584, (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | 1 << shift_powerctrl_1); } @@ -251,26 +254,26 @@ setPLL_double_highregs(struct nvkm_devinit *devinit, u32 reg1, shift_c040 += 2; } - savedc040 = nv_rd32(devinit, 0xc040); + savedc040 = nvkm_rd32(device, 0xc040); if (shift_c040 != 14) - nv_wr32(devinit, 0xc040, savedc040 & ~(3 << shift_c040)); + nvkm_wr32(device, 0xc040, savedc040 & ~(3 << shift_c040)); } if (oldramdac580 != ramdac580) - nv_wr32(devinit, 0x680580, ramdac580); + nvkm_wr32(device, 0x680580, ramdac580); if (!nv3035) - nv_wr32(devinit, reg2, pll2); - nv_wr32(devinit, reg1, pll1); + nvkm_wr32(device, reg2, pll2); + nvkm_wr32(device, reg1, pll1); if (shift_powerctrl_1 >= 0) - nv_wr32(devinit, 0x001584, saved_powerctrl_1); + nvkm_wr32(device, 0x001584, saved_powerctrl_1); if (chip_version >= 0x40) - nv_wr32(devinit, 0xc040, savedc040); + nvkm_wr32(device, 0xc040, savedc040); } void -setPLL_double_lowregs(struct nvkm_devinit *devinit, u32 NMNMreg, +setPLL_double_lowregs(struct nvkm_devinit *init, u32 NMNMreg, struct nvkm_pll_vals *pv) { /* When setting PLLs, there is a merry game of disabling and enabling @@ -280,10 +283,10 @@ setPLL_double_lowregs(struct nvkm_devinit *devinit, u32 NMNMreg, * combined herein. Without luck it deviates from each card's formula * so as to not work on any :) */ - + struct nvkm_device *device = init->subdev.device; uint32_t Preg = NMNMreg - 4; bool mpll = Preg == 0x4020; - uint32_t oldPval = nv_rd32(devinit, Preg); + uint32_t oldPval = nvkm_rd32(device, Preg); uint32_t NMNM = pv->NM2 << 16 | pv->NM1; uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | 0xc << 28 | pv->log2P << 16; @@ -292,7 +295,7 @@ setPLL_double_lowregs(struct nvkm_devinit *devinit, u32 NMNMreg, uint32_t maskc040 = ~(3 << 14), savedc040; bool single_stage = !pv->NM2 || pv->N2 == pv->M2; - if (nv_rd32(devinit, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) + if (nvkm_rd32(device, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) return; if (Preg == 0x4000) @@ -304,7 +307,7 @@ setPLL_double_lowregs(struct nvkm_devinit *devinit, u32 NMNMreg, struct nvbios_pll info; uint8_t Pval2; - if (nvbios_pll_parse(nvkm_bios(devinit), Preg, &info)) + if (nvbios_pll_parse(device->bios, Preg, &info)) return; Pval2 = pv->log2P + info.bias_p; @@ -312,47 +315,48 @@ setPLL_double_lowregs(struct nvkm_devinit *devinit, u32 NMNMreg, Pval2 = info.max_p; Pval |= 1 << 28 | Pval2 << 20; - saved4600 = nv_rd32(devinit, 0x4600); - nv_wr32(devinit, 0x4600, saved4600 | 8 << 28); + saved4600 = nvkm_rd32(device, 0x4600); + nvkm_wr32(device, 0x4600, saved4600 | 8 << 28); } if (single_stage) Pval |= mpll ? 1 << 12 : 1 << 8; - nv_wr32(devinit, Preg, oldPval | 1 << 28); - nv_wr32(devinit, Preg, Pval & ~(4 << 28)); + nvkm_wr32(device, Preg, oldPval | 1 << 28); + nvkm_wr32(device, Preg, Pval & ~(4 << 28)); if (mpll) { Pval |= 8 << 20; - nv_wr32(devinit, 0x4020, Pval & ~(0xc << 28)); - nv_wr32(devinit, 0x4038, Pval & ~(0xc << 28)); + nvkm_wr32(device, 0x4020, Pval & ~(0xc << 28)); + nvkm_wr32(device, 0x4038, Pval & ~(0xc << 28)); } - savedc040 = nv_rd32(devinit, 0xc040); - nv_wr32(devinit, 0xc040, savedc040 & maskc040); + savedc040 = nvkm_rd32(device, 0xc040); + nvkm_wr32(device, 0xc040, savedc040 & maskc040); - nv_wr32(devinit, NMNMreg, NMNM); + nvkm_wr32(device, NMNMreg, NMNM); if (NMNMreg == 0x4024) - nv_wr32(devinit, 0x403c, NMNM); + nvkm_wr32(device, 0x403c, NMNM); - nv_wr32(devinit, Preg, Pval); + nvkm_wr32(device, Preg, Pval); if (mpll) { Pval &= ~(8 << 20); - nv_wr32(devinit, 0x4020, Pval); - nv_wr32(devinit, 0x4038, Pval); - nv_wr32(devinit, 0x4600, saved4600); + nvkm_wr32(device, 0x4020, Pval); + nvkm_wr32(device, 0x4038, Pval); + nvkm_wr32(device, 0x4600, saved4600); } - nv_wr32(devinit, 0xc040, savedc040); + nvkm_wr32(device, 0xc040, savedc040); if (mpll) { - nv_wr32(devinit, 0x4020, Pval & ~(1 << 28)); - nv_wr32(devinit, 0x4038, Pval & ~(1 << 28)); + nvkm_wr32(device, 0x4020, Pval & ~(1 << 28)); + nvkm_wr32(device, 0x4038, Pval & ~(1 << 28)); } } int nv04_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) { - struct nvkm_bios *bios = nvkm_bios(devinit); + struct nvkm_subdev *subdev = &devinit->subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvkm_pll_vals pv; struct nvbios_pll info; int cv = bios->version.chip; @@ -363,8 +367,7 @@ nv04_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) if (ret) return ret; - ret = nv04_pll_calc(nv_subdev(devinit), &info, freq, - &N1, &M1, &N2, &M2, &P); + ret = nv04_pll_calc(subdev, &info, freq, &N1, &M1, &N2, &M2, &P); if (!ret) return -EINVAL; @@ -388,83 +391,76 @@ nv04_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) } int -nv04_devinit_fini(struct nvkm_object *object, bool suspend) +nv04_devinit_post(struct nvkm_devinit *init, bool execute) { - struct nv04_devinit_priv *priv = (void *)object; - int ret; + return nvbios_init(&init->subdev, execute); +} - /* make i2c busses accessible */ - nv_mask(priv, 0x000200, 0x00000001, 0x00000001); +void +nv04_devinit_preinit(struct nvkm_devinit *base) +{ + struct nv04_devinit *init = nv04_devinit(base); + struct nvkm_subdev *subdev = &init->base.subdev; + struct nvkm_device *device = subdev->device; - ret = nvkm_devinit_fini(&priv->base, suspend); - if (ret) - return ret; + /* make i2c busses accessible */ + nvkm_mask(device, 0x000200, 0x00000001, 0x00000001); /* unslave crtcs */ - if (priv->owner < 0) - priv->owner = nv_rdvgaowner(priv); - nv_wrvgaowner(priv, 0); - return 0; -} - -int -nv04_devinit_init(struct nvkm_object *object) -{ - struct nv04_devinit_priv *priv = (void *)object; - - if (!priv->base.post) { - u32 htotal = nv_rdvgac(priv, 0, 0x06); - htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x01) << 8; - htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x20) << 4; - htotal |= (nv_rdvgac(priv, 0, 0x25) & 0x01) << 10; - htotal |= (nv_rdvgac(priv, 0, 0x41) & 0x01) << 11; + if (init->owner < 0) + init->owner = nvkm_rdvgaowner(device); + nvkm_wrvgaowner(device, 0); + + if (!init->base.post) { + u32 htotal = nvkm_rdvgac(device, 0, 0x06); + htotal |= (nvkm_rdvgac(device, 0, 0x07) & 0x01) << 8; + htotal |= (nvkm_rdvgac(device, 0, 0x07) & 0x20) << 4; + htotal |= (nvkm_rdvgac(device, 0, 0x25) & 0x01) << 10; + htotal |= (nvkm_rdvgac(device, 0, 0x41) & 0x01) << 11; if (!htotal) { - nv_info(priv, "adaptor not initialised\n"); - priv->base.post = true; + nvkm_debug(subdev, "adaptor not initialised\n"); + init->base.post = true; } } - - return nvkm_devinit_init(&priv->base); } -void -nv04_devinit_dtor(struct nvkm_object *object) +void * +nv04_devinit_dtor(struct nvkm_devinit *base) { - struct nv04_devinit_priv *priv = (void *)object; - + struct nv04_devinit *init = nv04_devinit(base); /* restore vga owner saved at first init */ - nv_wrvgaowner(priv, priv->owner); - - nvkm_devinit_destroy(&priv->base); + nvkm_wrvgaowner(init->base.subdev.device, init->owner); + return init; } int -nv04_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_devinit_new_(const struct nvkm_devinit_func *func, + struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) { - struct nv04_devinit_priv *priv; - int ret; + struct nv04_devinit *init; - ret = nvkm_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(init = kzalloc(sizeof(*init), GFP_KERNEL))) + return -ENOMEM; + *pinit = &init->base; - priv->owner = -1; + nvkm_devinit_ctor(func, device, index, &init->base); + init->owner = -1; return 0; } -struct nvkm_oclass * -nv04_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_devinit_ctor, - .dtor = nv04_devinit_dtor, - .init = nv04_devinit_init, - .fini = nv04_devinit_fini, - }, +static const struct nvkm_devinit_func +nv04_devinit = { + .dtor = nv04_devinit_dtor, + .preinit = nv04_devinit_preinit, + .post = nv04_devinit_post, .meminit = nv04_devinit_meminit, .pll_set = nv04_devinit_pll_set, - .post = nvbios_init, -}.base; +}; + +int +nv04_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv04_devinit_new_(&nv04_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h index 7c63abf11..4a87c8c2b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h @@ -1,19 +1,19 @@ -#ifndef __NVKM_DEVINIT_NV04_H__ -#define __NVKM_DEVINIT_NV04_H__ +#ifndef __NV04_DEVINIT_H__ +#define __NV04_DEVINIT_H__ +#define nv04_devinit(p) container_of((p), struct nv04_devinit, base) #include "priv.h" struct nvkm_pll_vals; -struct nv04_devinit_priv { +struct nv04_devinit { struct nvkm_devinit base; int owner; }; -int nv04_devinit_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv04_devinit_dtor(struct nvkm_object *); -int nv04_devinit_init(struct nvkm_object *); -int nv04_devinit_fini(struct nvkm_object *, bool); +int nv04_devinit_new_(const struct nvkm_devinit_func *, struct nvkm_device *, + int, struct nvkm_devinit **); +void *nv04_devinit_dtor(struct nvkm_devinit *); +void nv04_devinit_preinit(struct nvkm_devinit *); +void nv04_devinit_fini(struct nvkm_devinit *); int nv04_devinit_pll_set(struct nvkm_devinit *, u32, u32); void setPLL_single(struct nvkm_devinit *, u32, struct nvkm_pll_vals *); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv05.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv05.c index def864921..9891eadca 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv05.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv05.c @@ -32,7 +32,7 @@ #include static void -nv05_devinit_meminit(struct nvkm_devinit *devinit) +nv05_devinit_meminit(struct nvkm_devinit *init) { static const u8 default_config_tab[][2] = { { 0x24, 0x00 }, @@ -44,8 +44,9 @@ nv05_devinit_meminit(struct nvkm_devinit *devinit) { 0x06, 0x00 }, { 0x00, 0x00 } }; - struct nv04_devinit_priv *priv = (void *)devinit; - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct io_mapping *fb; u32 patt = 0xdeadbeef; u16 data; @@ -53,88 +54,90 @@ nv05_devinit_meminit(struct nvkm_devinit *devinit) int i, v; /* Map the framebuffer aperture */ - fb = fbmem_init(nv_device(priv)); + fb = fbmem_init(device); if (!fb) { - nv_error(priv, "failed to map fb\n"); + nvkm_error(subdev, "failed to map fb\n"); return; } - strap = (nv_rd32(priv, 0x101000) & 0x0000003c) >> 2; + strap = (nvkm_rd32(device, 0x101000) & 0x0000003c) >> 2; if ((data = bmp_mem_init_table(bios))) { - ramcfg[0] = nv_ro08(bios, data + 2 * strap + 0); - ramcfg[1] = nv_ro08(bios, data + 2 * strap + 1); + ramcfg[0] = nvbios_rd08(bios, data + 2 * strap + 0); + ramcfg[1] = nvbios_rd08(bios, data + 2 * strap + 1); } else { ramcfg[0] = default_config_tab[strap][0]; ramcfg[1] = default_config_tab[strap][1]; } /* Sequencer off */ - nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); + nvkm_wrvgas(device, 0, 1, nvkm_rdvgas(device, 0, 1) | 0x20); - if (nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) + if (nvkm_rd32(device, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) goto out; - nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + nvkm_mask(device, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); /* If present load the hardcoded scrambling table */ if (data) { for (i = 0, data += 0x10; i < 8; i++, data += 4) { - u32 scramble = nv_ro32(bios, data); - nv_wr32(priv, NV04_PFB_SCRAMBLE(i), scramble); + u32 scramble = nvbios_rd32(bios, data); + nvkm_wr32(device, NV04_PFB_SCRAMBLE(i), scramble); } } /* Set memory type/width/length defaults depending on the straps */ - nv_mask(priv, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); + nvkm_mask(device, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); if (ramcfg[1] & 0x80) - nv_mask(priv, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); + nvkm_mask(device, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); - nv_mask(priv, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); - nv_mask(priv, NV04_PFB_CFG1, 0, 1); + nvkm_mask(device, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); + nvkm_mask(device, NV04_PFB_CFG1, 0, 1); /* Probe memory bus width */ for (i = 0; i < 4; i++) fbmem_poke(fb, 4 * i, patt); if (fbmem_peek(fb, 0xc) != patt) - nv_mask(priv, NV04_PFB_BOOT_0, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); /* Probe memory length */ - v = nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; + v = nvkm_rd32(device, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && (!fbmem_readback(fb, 0x1000000, ++patt) || !fbmem_readback(fb, 0, ++patt))) - nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && !fbmem_readback(fb, 0x800000, ++patt)) - nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); if (!fbmem_readback(fb, 0x400000, ++patt)) - nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + nvkm_mask(device, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); out: /* Sequencer on */ - nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); + nvkm_wrvgas(device, 0, 1, nvkm_rdvgas(device, 0, 1) & ~0x20); fbmem_fini(fb); } -struct nvkm_oclass * -nv05_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x05), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_devinit_ctor, - .dtor = nv04_devinit_dtor, - .init = nv04_devinit_init, - .fini = nv04_devinit_fini, - }, +static const struct nvkm_devinit_func +nv05_devinit = { + .dtor = nv04_devinit_dtor, + .preinit = nv04_devinit_preinit, + .post = nv04_devinit_post, .meminit = nv05_devinit_meminit, .pll_set = nv04_devinit_pll_set, - .post = nvbios_init, -}.base; +}; + +int +nv05_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv04_devinit_new_(&nv05_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv10.c index 7aabc1bf0..570822f83 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv10.c @@ -30,33 +30,33 @@ #include static void -nv10_devinit_meminit(struct nvkm_devinit *devinit) +nv10_devinit_meminit(struct nvkm_devinit *init) { - struct nv04_devinit_priv *priv = (void *)devinit; + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; static const int mem_width[] = { 0x10, 0x00, 0x20 }; int mem_width_count; uint32_t patt = 0xdeadbeef; struct io_mapping *fb; int i, j, k; - if (nv_device(priv)->card_type >= NV_11 && - nv_device(priv)->chipset >= 0x17) + if (device->card_type >= NV_11 && device->chipset >= 0x17) mem_width_count = 3; else mem_width_count = 2; /* Map the framebuffer aperture */ - fb = fbmem_init(nv_device(priv)); + fb = fbmem_init(device); if (!fb) { - nv_error(priv, "failed to map fb\n"); + nvkm_error(subdev, "failed to map fb\n"); return; } - nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); + nvkm_wr32(device, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); /* Probe memory bus width */ for (i = 0; i < mem_width_count; i++) { - nv_mask(priv, NV04_PFB_CFG0, 0x30, mem_width[i]); + nvkm_mask(device, NV04_PFB_CFG0, 0x30, mem_width[i]); for (j = 0; j < 4; j++) { for (k = 0; k < 4; k++) @@ -75,7 +75,7 @@ mem_width_found: /* Probe amount of installed memory */ for (i = 0; i < 4; i++) { - int off = nv_rd32(priv, 0x10020c) - 0x100000; + int off = nvkm_rd32(device, 0x10020c) - 0x100000; fbmem_poke(fb, off, patt); fbmem_poke(fb, 0, 0); @@ -90,22 +90,24 @@ mem_width_found: } /* IC missing - disable the upper half memory space. */ - nv_mask(priv, NV04_PFB_CFG0, 0x1000, 0); + nvkm_mask(device, NV04_PFB_CFG0, 0x1000, 0); amount_found: fbmem_fini(fb); } -struct nvkm_oclass * -nv10_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x10), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_devinit_ctor, - .dtor = nv04_devinit_dtor, - .init = nv04_devinit_init, - .fini = nv04_devinit_fini, - }, +static const struct nvkm_devinit_func +nv10_devinit = { + .dtor = nv04_devinit_dtor, + .preinit = nv04_devinit_preinit, + .post = nv04_devinit_post, .meminit = nv10_devinit_meminit, .pll_set = nv04_devinit_pll_set, - .post = nvbios_init, -}.base; +}; + +int +nv10_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv04_devinit_new_(&nv10_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv1a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv1a.c index 9f36fff5a..fefafec7e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv1a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv1a.c @@ -26,15 +26,17 @@ #include #include -struct nvkm_oclass * -nv1a_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x1a), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_devinit_ctor, - .dtor = nv04_devinit_dtor, - .init = nv04_devinit_init, - .fini = nv04_devinit_fini, - }, +static const struct nvkm_devinit_func +nv1a_devinit = { + .dtor = nv04_devinit_dtor, + .preinit = nv04_devinit_preinit, + .post = nv04_devinit_post, .pll_set = nv04_devinit_pll_set, - .post = nvbios_init, -}.base; +}; + +int +nv1a_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv04_devinit_new_(&nv1a_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv20.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv20.c index 02fcfd921..4ef04e0d8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv20.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv20.c @@ -30,48 +30,50 @@ #include static void -nv20_devinit_meminit(struct nvkm_devinit *devinit) +nv20_devinit_meminit(struct nvkm_devinit *init) { - struct nv04_devinit_priv *priv = (void *)devinit; - struct nvkm_device *device = nv_device(priv); + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900); uint32_t amount, off; struct io_mapping *fb; /* Map the framebuffer aperture */ - fb = fbmem_init(nv_device(priv)); + fb = fbmem_init(device); if (!fb) { - nv_error(priv, "failed to map fb\n"); + nvkm_error(subdev, "failed to map fb\n"); return; } - nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); + nvkm_wr32(device, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); /* Allow full addressing */ - nv_mask(priv, NV04_PFB_CFG0, 0, mask); + nvkm_mask(device, NV04_PFB_CFG0, 0, mask); - amount = nv_rd32(priv, 0x10020c); + amount = nvkm_rd32(device, 0x10020c); for (off = amount; off > 0x2000000; off -= 0x2000000) fbmem_poke(fb, off - 4, off); - amount = nv_rd32(priv, 0x10020c); + amount = nvkm_rd32(device, 0x10020c); if (amount != fbmem_peek(fb, amount - 4)) /* IC missing - disable the upper half memory space. */ - nv_mask(priv, NV04_PFB_CFG0, mask, 0); + nvkm_mask(device, NV04_PFB_CFG0, mask, 0); fbmem_fini(fb); } -struct nvkm_oclass * -nv20_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x20), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_devinit_ctor, - .dtor = nv04_devinit_dtor, - .init = nv04_devinit_init, - .fini = nv04_devinit_fini, - }, +static const struct nvkm_devinit_func +nv20_devinit = { + .dtor = nv04_devinit_dtor, + .preinit = nv04_devinit_preinit, + .post = nv04_devinit_post, .meminit = nv20_devinit_meminit, .pll_set = nv04_devinit_pll_set, - .post = nvbios_init, -}.base; +}; + +int +nv20_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv04_devinit_new_(&nv20_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c index 26b7cb13e..337c2c692 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c @@ -29,47 +29,48 @@ #include #include #include -#include #include int -nv50_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) +nv50_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) { - struct nv50_devinit_priv *priv = (void *)devinit; - struct nvkm_bios *bios = nvkm_bios(priv); + struct nvkm_subdev *subdev = &init->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct nvbios_pll info; int N1, M1, N2, M2, P; int ret; ret = nvbios_pll_parse(bios, type, &info); if (ret) { - nv_error(devinit, "failed to retrieve pll data, %d\n", ret); + nvkm_error(subdev, "failed to retrieve pll data, %d\n", ret); return ret; } - ret = nv04_pll_calc(nv_subdev(devinit), &info, freq, &N1, &M1, &N2, &M2, &P); + ret = nv04_pll_calc(subdev, &info, freq, &N1, &M1, &N2, &M2, &P); if (!ret) { - nv_error(devinit, "failed pll calculation\n"); + nvkm_error(subdev, "failed pll calculation\n"); return ret; } switch (info.type) { case PLL_VPLL0: case PLL_VPLL1: - nv_wr32(priv, info.reg + 0, 0x10000611); - nv_mask(priv, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1); - nv_mask(priv, info.reg + 8, 0x7fff00ff, (P << 28) | - (M2 << 16) | N2); + nvkm_wr32(device, info.reg + 0, 0x10000611); + nvkm_mask(device, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1); + nvkm_mask(device, info.reg + 8, 0x7fff00ff, (P << 28) | + (M2 << 16) | N2); break; case PLL_MEMORY: - nv_mask(priv, info.reg + 0, 0x01ff0000, (P << 22) | - (info.bias_p << 19) | - (P << 16)); - nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); + nvkm_mask(device, info.reg + 0, 0x01ff0000, + (P << 22) | + (info.bias_p << 19) | + (P << 16)); + nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1); break; default: - nv_mask(priv, info.reg + 0, 0x00070000, (P << 16)); - nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); + nvkm_mask(device, info.reg + 0, 0x00070000, (P << 16)); + nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1); break; } @@ -77,57 +78,68 @@ nv50_devinit_pll_set(struct nvkm_devinit *devinit, u32 type, u32 freq) } static u64 -nv50_devinit_disable(struct nvkm_devinit *devinit) +nv50_devinit_disable(struct nvkm_devinit *init) { - struct nv50_devinit_priv *priv = (void *)devinit; - u32 r001540 = nv_rd32(priv, 0x001540); + struct nvkm_device *device = init->subdev.device; + u32 r001540 = nvkm_rd32(device, 0x001540); u64 disable = 0ULL; if (!(r001540 & 0x40000000)) - disable |= (1ULL << NVDEV_ENGINE_MPEG); + disable |= (1ULL << NVKM_ENGINE_MPEG); return disable; } -int -nv50_devinit_init(struct nvkm_object *object) +void +nv50_devinit_preinit(struct nvkm_devinit *base) { - struct nvkm_bios *bios = nvkm_bios(object); - struct nvkm_ibus *ibus = nvkm_ibus(object); - struct nv50_devinit_priv *priv = (void *)object; - struct nvbios_outp info; - struct dcb_output outp; - u8 ver = 0xff, hdr, cnt, len; - int ret, i = 0; + struct nv50_devinit *init = nv50_devinit(base); + struct nvkm_subdev *subdev = &init->base.subdev; + struct nvkm_device *device = subdev->device; - if (!priv->base.post) { - if (!nv_rdvgac(priv, 0, 0x00) && - !nv_rdvgac(priv, 0, 0x1a)) { - nv_info(priv, "adaptor not initialised\n"); - priv->base.post = true; - } + /* our heuristics can't detect whether the board has had its + * devinit scripts executed or not if the display engine is + * missing, assume it's a secondary gpu which requires post + */ + if (!init->base.post) { + u64 disable = nvkm_devinit_disable(&init->base); + if (disable & (1ULL << NVKM_ENGINE_DISP)) + init->base.post = true; } - /* some boards appear to require certain priv register timeouts - * to be bumped before runing devinit scripts. not a clue why - * the vbios engineers didn't make the scripts just work... + /* magic to detect whether or not x86 vbios code has executed + * the devinit scripts to initialise the board */ - if (priv->base.post && ibus) - nv_ofuncs(ibus)->init(nv_object(ibus)); + if (!init->base.post) { + if (!nvkm_rdvgac(device, 0, 0x00) && + !nvkm_rdvgac(device, 0, 0x1a)) { + nvkm_debug(subdev, "adaptor not initialised\n"); + init->base.post = true; + } + } +} - ret = nvkm_devinit_init(&priv->base); - if (ret) - return ret; +void +nv50_devinit_init(struct nvkm_devinit *base) +{ + struct nv50_devinit *init = nv50_devinit(base); + struct nvkm_subdev *subdev = &init->base.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; + struct nvbios_outp info; + struct dcb_output outp; + u8 ver = 0xff, hdr, cnt, len; + int i = 0; /* if we ran the init tables, we have to execute the first script * pointer of each dcb entry's display encoder table in order * to properly initialise each encoder. */ - while (priv->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) { + while (init->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) { if (nvbios_outp_match(bios, outp.hasht, outp.hashm, &ver, &hdr, &cnt, &len, &info)) { - struct nvbios_init init = { - .subdev = nv_subdev(priv), + struct nvbios_init exec = { + .subdev = subdev, .bios = bios, .offset = info.script[0], .outp = &outp, @@ -135,40 +147,39 @@ nv50_devinit_init(struct nvkm_object *object) .execute = 1, }; - nvbios_exec(&init); + nvbios_exec(&exec); } i++; } - - return 0; } int -nv50_devinit_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_devinit_new_(const struct nvkm_devinit_func *func, + struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) { - struct nv50_devinit_priv *priv; - int ret; + struct nv50_devinit *init; - ret = nvkm_devinit_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(init = kzalloc(sizeof(*init), GFP_KERNEL))) + return -ENOMEM; + *pinit = &init->base; + nvkm_devinit_ctor(func, device, index, &init->base); return 0; } -struct nvkm_oclass * -nv50_devinit_oclass = &(struct nvkm_devinit_impl) { - .base.handle = NV_SUBDEV(DEVINIT, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_devinit_ctor, - .dtor = _nvkm_devinit_dtor, - .init = nv50_devinit_init, - .fini = _nvkm_devinit_fini, - }, +static const struct nvkm_devinit_func +nv50_devinit = { + .preinit = nv50_devinit_preinit, + .init = nv50_devinit_init, + .post = nv04_devinit_post, .pll_set = nv50_devinit_pll_set, .disable = nv50_devinit_disable, - .post = nvbios_init, -}.base; +}; + +int +nv50_devinit_new(struct nvkm_device *device, int index, + struct nvkm_devinit **pinit) +{ + return nv50_devinit_new_(&nv50_devinit, device, index, pinit); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h index 9243521c8..5de70a848 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h @@ -1,16 +1,17 @@ -#ifndef __NVKM_DEVINIT_NV50_H__ -#define __NVKM_DEVINIT_NV50_H__ +#ifndef __NV50_DEVINIT_H__ +#define __NV50_DEVINIT_H__ +#define nv50_devinit(p) container_of((p), struct nv50_devinit, base) #include "priv.h" -struct nv50_devinit_priv { +struct nv50_devinit { struct nvkm_devinit base; u32 r001540; }; -int nv50_devinit_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -int nv50_devinit_init(struct nvkm_object *); +int nv50_devinit_new_(const struct nvkm_devinit_func *, struct nvkm_device *, + int, struct nvkm_devinit **); +void nv50_devinit_preinit(struct nvkm_devinit *); +void nv50_devinit_init(struct nvkm_devinit *); int nv50_devinit_pll_set(struct nvkm_devinit *, u32, u32); int gt215_devinit_pll_set(struct nvkm_devinit *, u32, u32); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h index bb51a95d8..e1f6ae58f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h @@ -1,34 +1,21 @@ #ifndef __NVKM_DEVINIT_PRIV_H__ #define __NVKM_DEVINIT_PRIV_H__ +#define nvkm_devinit(p) container_of((p), struct nvkm_devinit, subdev) #include -struct nvkm_devinit_impl { - struct nvkm_oclass base; +struct nvkm_devinit_func { + void *(*dtor)(struct nvkm_devinit *); + void (*preinit)(struct nvkm_devinit *); + void (*init)(struct nvkm_devinit *); + int (*post)(struct nvkm_devinit *, bool post); + u32 (*mmio)(struct nvkm_devinit *, u32); void (*meminit)(struct nvkm_devinit *); int (*pll_set)(struct nvkm_devinit *, u32 type, u32 freq); u64 (*disable)(struct nvkm_devinit *); - u32 (*mmio)(struct nvkm_devinit *, u32); - int (*post)(struct nvkm_subdev *, bool); }; -#define nvkm_devinit_create(p,e,o,d) \ - nvkm_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_devinit_destroy(p) ({ \ - struct nvkm_devinit *d = (p); \ - _nvkm_devinit_dtor(nv_object(d)); \ -}) -#define nvkm_devinit_init(p) ({ \ - struct nvkm_devinit *d = (p); \ - _nvkm_devinit_init(nv_object(d)); \ -}) -#define nvkm_devinit_fini(p,s) ({ \ - struct nvkm_devinit *d = (p); \ - _nvkm_devinit_fini(nv_object(d), (s)); \ -}) +void nvkm_devinit_ctor(const struct nvkm_devinit_func *, struct nvkm_device *, + int index, struct nvkm_devinit *); -int nvkm_devinit_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_devinit_dtor(struct nvkm_object *); -int _nvkm_devinit_init(struct nvkm_object *); -int _nvkm_devinit_fini(struct nvkm_object *, bool suspend); +int nv04_devinit_post(struct nvkm_devinit *, bool); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild index d6be4c6c5..08105701a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild @@ -23,6 +23,8 @@ nvkm-y += nvkm/subdev/fb/gf100.o nvkm-y += nvkm/subdev/fb/gk104.o nvkm-y += nvkm/subdev/fb/gk20a.o nvkm-y += nvkm/subdev/fb/gm107.o + +nvkm-y += nvkm/subdev/fb/ram.o nvkm-y += nvkm/subdev/fb/ramnv04.o nvkm-y += nvkm/subdev/fb/ramnv10.o nvkm-y += nvkm/subdev/fb/ramnv1a.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 61fde43da..a719b9bec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -22,144 +22,151 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "ram.h" #include #include +#include +#include + +bool +nvkm_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype) +{ + return fb->func->memtype_valid(fb, memtype); +} + +void +nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) +{ + fb->func->tile.fini(fb, region, tile); +} + +void +nvkm_fb_tile_init(struct nvkm_fb *fb, int region, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *tile) +{ + fb->func->tile.init(fb, region, addr, size, pitch, flags, tile); +} + +void +nvkm_fb_tile_prog(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) +{ + struct nvkm_device *device = fb->subdev.device; + if (fb->func->tile.prog) { + fb->func->tile.prog(fb, region, tile); + if (device->gr) + nvkm_engine_tile(&device->gr->engine, region); + if (device->mpeg) + nvkm_engine_tile(device->mpeg, region); + } +} int nvkm_fb_bios_memtype(struct nvkm_bios *bios) { - const u8 ramcfg = (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2; + struct nvkm_subdev *subdev = &bios->subdev; + struct nvkm_device *device = subdev->device; + const u8 ramcfg = (nvkm_rd32(device, 0x101000) & 0x0000003c) >> 2; struct nvbios_M0203E M0203E; u8 ver, hdr; if (nvbios_M0203Em(bios, ramcfg, &ver, &hdr, &M0203E)) { switch (M0203E.type) { - case M0203E_TYPE_DDR2 : return NV_MEM_TYPE_DDR2; - case M0203E_TYPE_DDR3 : return NV_MEM_TYPE_DDR3; - case M0203E_TYPE_GDDR3: return NV_MEM_TYPE_GDDR3; - case M0203E_TYPE_GDDR5: return NV_MEM_TYPE_GDDR5; + case M0203E_TYPE_DDR2 : return NVKM_RAM_TYPE_DDR2; + case M0203E_TYPE_DDR3 : return NVKM_RAM_TYPE_DDR3; + case M0203E_TYPE_GDDR3: return NVKM_RAM_TYPE_GDDR3; + case M0203E_TYPE_GDDR5: return NVKM_RAM_TYPE_GDDR5; default: - nv_warn(bios, "M0203E type %02x\n", M0203E.type); - return NV_MEM_TYPE_UNKNOWN; + nvkm_warn(subdev, "M0203E type %02x\n", M0203E.type); + return NVKM_RAM_TYPE_UNKNOWN; } } - nv_warn(bios, "M0203E not matched!\n"); - return NV_MEM_TYPE_UNKNOWN; + nvkm_warn(subdev, "M0203E not matched!\n"); + return NVKM_RAM_TYPE_UNKNOWN; } -int -_nvkm_fb_fini(struct nvkm_object *object, bool suspend) +static void +nvkm_fb_intr(struct nvkm_subdev *subdev) { - struct nvkm_fb *pfb = (void *)object; - int ret; + struct nvkm_fb *fb = nvkm_fb(subdev); + if (fb->func->intr) + fb->func->intr(fb); +} - if (pfb->ram) { - ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend); - if (ret && suspend) +static int +nvkm_fb_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_fb *fb = nvkm_fb(subdev); + if (fb->func->ram_new) { + int ret = fb->func->ram_new(fb, &fb->ram); + if (ret) { + nvkm_error(subdev, "vram setup failed, %d\n", ret); return ret; + } } - - return nvkm_subdev_fini(&pfb->base, suspend); + return 0; } -int -_nvkm_fb_init(struct nvkm_object *object) +static int +nvkm_fb_init(struct nvkm_subdev *subdev) { - struct nvkm_fb *pfb = (void *)object; + struct nvkm_fb *fb = nvkm_fb(subdev); int ret, i; - ret = nvkm_subdev_init(&pfb->base); - if (ret) - return ret; - - if (pfb->ram) { - ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram)); + if (fb->ram) { + ret = nvkm_ram_init(fb->ram); if (ret) return ret; } - for (i = 0; i < pfb->tile.regions; i++) - pfb->tile.prog(pfb, i, &pfb->tile.region[i]); + for (i = 0; i < fb->tile.regions; i++) + fb->func->tile.prog(fb, i, &fb->tile.region[i]); + if (fb->func->init) + fb->func->init(fb); return 0; } -void -_nvkm_fb_dtor(struct nvkm_object *object) +static void * +nvkm_fb_dtor(struct nvkm_subdev *subdev) { - struct nvkm_fb *pfb = (void *)object; + struct nvkm_fb *fb = nvkm_fb(subdev); int i; - for (i = 0; i < pfb->tile.regions; i++) - pfb->tile.fini(pfb, i, &pfb->tile.region[i]); - nvkm_mm_fini(&pfb->tags); + for (i = 0; i < fb->tile.regions; i++) + fb->func->tile.fini(fb, i, &fb->tile.region[i]); - if (pfb->ram) { - nvkm_mm_fini(&pfb->vram); - nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram); - } + nvkm_ram_del(&fb->ram); - nvkm_subdev_destroy(&pfb->base); + if (fb->func->dtor) + return fb->func->dtor(fb); + return fb; } -int -nvkm_fb_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) -{ - struct nvkm_fb_impl *impl = (void *)oclass; - static const char *name[] = { - [NV_MEM_TYPE_UNKNOWN] = "unknown", - [NV_MEM_TYPE_STOLEN ] = "stolen system memory", - [NV_MEM_TYPE_SGRAM ] = "SGRAM", - [NV_MEM_TYPE_SDRAM ] = "SDRAM", - [NV_MEM_TYPE_DDR1 ] = "DDR1", - [NV_MEM_TYPE_DDR2 ] = "DDR2", - [NV_MEM_TYPE_DDR3 ] = "DDR3", - [NV_MEM_TYPE_GDDR2 ] = "GDDR2", - [NV_MEM_TYPE_GDDR3 ] = "GDDR3", - [NV_MEM_TYPE_GDDR4 ] = "GDDR4", - [NV_MEM_TYPE_GDDR5 ] = "GDDR5", - }; - struct nvkm_object *ram; - struct nvkm_fb *pfb; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PFB", "fb", - length, pobject); - pfb = *pobject; - if (ret) - return ret; - - pfb->memtype_valid = impl->memtype; - - if (!impl->ram) - return 0; - - ret = nvkm_object_ctor(nv_object(pfb), NULL, impl->ram, NULL, 0, &ram); - if (ret) { - nv_fatal(pfb, "error detecting memory configuration!!\n"); - return ret; - } - - pfb->ram = (void *)ram; +static const struct nvkm_subdev_func +nvkm_fb = { + .dtor = nvkm_fb_dtor, + .oneinit = nvkm_fb_oneinit, + .init = nvkm_fb_init, + .intr = nvkm_fb_intr, +}; - if (!nvkm_mm_initialised(&pfb->vram)) { - ret = nvkm_mm_init(&pfb->vram, 0, pfb->ram->size >> 12, 1); - if (ret) - return ret; - } - - if (!nvkm_mm_initialised(&pfb->tags)) { - ret = nvkm_mm_init(&pfb->tags, 0, pfb->ram->tags ? - ++pfb->ram->tags : 0, 1); - if (ret) - return ret; - } +void +nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device, + int index, struct nvkm_fb *fb) +{ + nvkm_subdev_ctor(&nvkm_fb, device, index, 0, &fb->subdev); + fb->func = func; + fb->tile.regions = fb->func->tile.regions; +} - nv_info(pfb, "RAM type: %s\n", name[pfb->ram->type]); - nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram->size >> 20)); - nv_info(pfb, " ZCOMP: %d tags\n", pfb->ram->tags); +int +nvkm_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, + int index, struct nvkm_fb **pfb) +{ + if (!(*pfb = kzalloc(sizeof(**pfb), GFP_KERNEL))) + return -ENOMEM; + nvkm_fb_ctor(func, device, index, *pfb); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c index 6c968d1e9..9c28392d0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c @@ -22,17 +22,16 @@ * Authors: Ben Skeggs */ #include "nv50.h" +#include "ram.h" -struct nvkm_oclass * -g84_fb_oclass = &(struct nv50_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x84), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fb_ctor, - .dtor = nv50_fb_dtor, - .init = nv50_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv50_fb_memtype_valid, - .base.ram = &nv50_ram_oclass, +static const struct nv50_fb_func +g84_fb = { + .ram_new = nv50_ram_new, .trap = 0x001d07ff, -}.base.base; +}; + +int +g84_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nv50_fb_new_(&g84_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index 15b462ae3..60ece0a8a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs * Roy Spliet */ -#include "priv.h" +#include "ram.h" struct ramxlat { int id; @@ -42,9 +42,9 @@ ramxlat(const struct ramxlat *xlat, int id) static const struct ramxlat ramgddr3_cl_lo[] = { - { 7, 7 }, { 8, 0 }, { 9, 1 }, { 10, 2 }, { 11, 3 }, + { 5, 5 }, { 7, 7 }, { 8, 0 }, { 9, 1 }, { 10, 2 }, { 11, 3 }, { 12, 8 }, /* the below are mentioned in some, but not all, gddr3 docs */ - { 12, 4 }, { 13, 5 }, { 14, 6 }, + { 13, 9 }, { 14, 6 }, /* XXX: Per Samsung docs, are these used? They overlap with Qimonda */ /* { 4, 4 }, { 5, 5 }, { 6, 6 }, { 12, 8 }, { 13, 9 }, { 14, 10 }, * { 15, 11 }, */ @@ -61,24 +61,25 @@ ramgddr3_cl_hi[] = { static const struct ramxlat ramgddr3_wr_lo[] = { { 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 }, - { 11, 0 }, + { 11, 0 }, { 13 , 1 }, /* the below are mentioned in some, but not all, gddr3 docs */ - { 4, 1 }, { 6, 3 }, { 12, 1 }, { 13 , 2 }, + { 4, 0 }, { 6, 3 }, { 12, 1 }, { -1 } }; int nvkm_gddr3_calc(struct nvkm_ram *ram) { - int CL, WR, CWL, DLL = 0, ODT = 0, hi; + int CL, WR, CWL, DLL = 0, ODT = 0, RON, hi; switch (ram->next->bios.timing_ver) { case 0x10: CWL = ram->next->bios.timing_10_CWL; CL = ram->next->bios.timing_10_CL; WR = ram->next->bios.timing_10_WR; - DLL = !ram->next->bios.ramcfg_10_DLLoff; + DLL = !ram->next->bios.ramcfg_DLLoff; ODT = ram->next->bios.timing_10_ODT; + RON = ram->next->bios.ramcfg_RON; break; case 0x20: CWL = (ram->next->bios.timing[1] & 0x00000f80) >> 7; @@ -86,14 +87,17 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; /* XXX: Get these values from the VBIOS instead */ DLL = !(ram->mr[1] & 0x1); - ODT = (ram->mr[1] & 0x004) >> 2 | - (ram->mr[1] & 0x040) >> 5 | - (ram->mr[1] & 0x200) >> 7; + RON = !(ram->mr[1] & 0x300) >> 8; break; default: return -ENOSYS; } + if (ram->next->bios.timing_ver == 0x20 || + ram->next->bios.ramcfg_timing == 0xff) { + ODT = (ram->mr[1] & 0xc) >> 2; + } + hi = ram->mr[2] & 0x1; CL = ramxlat(hi ? ramgddr3_cl_hi : ramgddr3_cl_lo, CL); WR = ramxlat(ramgddr3_wr_lo, WR); @@ -107,7 +111,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) ram->mr[1] &= ~0x3fc; ram->mr[1] |= (ODT & 0x03) << 2; - ram->mr[1] |= (ODT & 0x03) << 8; + ram->mr[1] |= (RON & 0x03) << 8; ram->mr[1] |= (WR & 0x03) << 4; ram->mr[1] |= (WR & 0x04) << 5; ram->mr[1] |= !DLL << 6; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c index f6f9eee1d..2cc074d39 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c @@ -21,7 +21,7 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ram.h" /* binary driver only executes this path if the condition (a) is true * for any configuration (combination of rammap+ramcfg+timing) that @@ -38,11 +38,12 @@ nvkm_gddr5_calc(struct nvkm_ram *ram, bool nuts) int WL, CL, WR, at[2], dt, ds; int rq = ram->freq < 1000000; /* XXX */ + xd = !ram->next->bios.ramcfg_DLLoff; + switch (ram->next->bios.ramcfg_ver) { case 0x11: pd = ram->next->bios.ramcfg_11_01_80; lf = ram->next->bios.ramcfg_11_01_40; - xd = !ram->next->bios.ramcfg_11_01_20; vh = ram->next->bios.ramcfg_11_02_10; vr = ram->next->bios.ramcfg_11_02_04; vo = ram->next->bios.ramcfg_11_06; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c index d51aa0237..008bb9849 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c @@ -22,101 +22,90 @@ * Authors: Ben Skeggs */ #include "gf100.h" - -#include +#include "ram.h" extern const u8 gf100_pte_storage_type_map[256]; bool -gf100_fb_memtype_valid(struct nvkm_fb *pfb, u32 tile_flags) +gf100_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags) { u8 memtype = (tile_flags & 0x0000ff00) >> 8; return likely((gf100_pte_storage_type_map[memtype] != 0xff)); } -static void -gf100_fb_intr(struct nvkm_subdev *subdev) +void +gf100_fb_intr(struct nvkm_fb *base) { - struct gf100_fb_priv *priv = (void *)subdev; - u32 intr = nv_rd32(priv, 0x000100); - if (intr & 0x08000000) { - nv_debug(priv, "PFFB intr\n"); - intr &= ~0x08000000; - } - if (intr & 0x00002000) { - nv_debug(priv, "PBFB intr\n"); - intr &= ~0x00002000; - } + struct gf100_fb *fb = gf100_fb(base); + struct nvkm_subdev *subdev = &fb->base.subdev; + struct nvkm_device *device = subdev->device; + u32 intr = nvkm_rd32(device, 0x000100); + if (intr & 0x08000000) + nvkm_debug(subdev, "PFFB intr\n"); + if (intr & 0x00002000) + nvkm_debug(subdev, "PBFB intr\n"); } -int -gf100_fb_init(struct nvkm_object *object) +void +gf100_fb_init(struct nvkm_fb *base) { - struct gf100_fb_priv *priv = (void *)object; - int ret; + struct gf100_fb *fb = gf100_fb(base); + struct nvkm_device *device = fb->base.subdev.device; - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; + if (fb->r100c10_page) + nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); - if (priv->r100c10_page) - nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); - - nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */ - return 0; + nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */ } -void -gf100_fb_dtor(struct nvkm_object *object) +void * +gf100_fb_dtor(struct nvkm_fb *base) { - struct nvkm_device *device = nv_device(object); - struct gf100_fb_priv *priv = (void *)object; + struct gf100_fb *fb = gf100_fb(base); + struct nvkm_device *device = fb->base.subdev.device; - if (priv->r100c10_page) { - dma_unmap_page(nv_device_base(device), priv->r100c10, PAGE_SIZE, + if (fb->r100c10_page) { + dma_unmap_page(device->dev, fb->r100c10, PAGE_SIZE, DMA_BIDIRECTIONAL); - __free_page(priv->r100c10_page); + __free_page(fb->r100c10_page); } - nvkm_fb_destroy(&priv->base); + return fb; } int -gf100_fb_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, + int index, struct nvkm_fb **pfb) { - struct nvkm_device *device = nv_device(parent); - struct gf100_fb_priv *priv; - int ret; - - ret = nvkm_fb_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (priv->r100c10_page) { - priv->r100c10 = dma_map_page(nv_device_base(device), - priv->r100c10_page, 0, PAGE_SIZE, - DMA_BIDIRECTIONAL); - if (dma_mapping_error(nv_device_base(device), priv->r100c10)) + struct gf100_fb *fb; + + if (!(fb = kzalloc(sizeof(*fb), GFP_KERNEL))) + return -ENOMEM; + nvkm_fb_ctor(func, device, index, &fb->base); + *pfb = &fb->base; + + fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (fb->r100c10_page) { + fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(device->dev, fb->r100c10)) return -EFAULT; } - nv_subdev(priv)->intr = gf100_fb_intr; return 0; } -struct nvkm_oclass * -gf100_fb_oclass = &(struct nvkm_fb_impl) { - .base.handle = NV_SUBDEV(FB, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_fb_ctor, - .dtor = gf100_fb_dtor, - .init = gf100_fb_init, - .fini = _nvkm_fb_fini, - }, - .memtype = gf100_fb_memtype_valid, - .ram = &gf100_ram_oclass, -}.base; +static const struct nvkm_fb_func +gf100_fb = { + .dtor = gf100_fb_dtor, + .init = gf100_fb_init, + .intr = gf100_fb_intr, + .ram_new = gf100_ram_new, + .memtype_valid = gf100_fb_memtype_valid, +}; + +int +gf100_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return gf100_fb_new_(&gf100_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h index 0af4da259..2160e5a39 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h @@ -1,28 +1,17 @@ #ifndef __NVKM_RAM_NVC0_H__ #define __NVKM_RAM_NVC0_H__ +#define gf100_fb(p) container_of((p), struct gf100_fb, base) #include "priv.h" -#include "nv50.h" -struct gf100_fb_priv { +struct gf100_fb { struct nvkm_fb base; struct page *r100c10_page; dma_addr_t r100c10; }; -int gf100_fb_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void gf100_fb_dtor(struct nvkm_object *); -int gf100_fb_init(struct nvkm_object *); -bool gf100_fb_memtype_valid(struct nvkm_fb *, u32); - -#define gf100_ram_create(p,e,o,m,d) \ - gf100_ram_create_((p), (e), (o), (m), sizeof(**d), (void **)d) -int gf100_ram_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u32, int, void **); -int gf100_ram_get(struct nvkm_fb *, u64, u32, u32, u32, - struct nvkm_mem **); -void gf100_ram_put(struct nvkm_fb *, struct nvkm_mem **); - -int gk104_ram_init(struct nvkm_object*); +int gf100_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, + int index, struct nvkm_fb **); +void *gf100_fb_dtor(struct nvkm_fb *); +void gf100_fb_init(struct nvkm_fb *); +void gf100_fb_intr(struct nvkm_fb *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c index 1c0831766..0edb3c316 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c @@ -22,16 +22,19 @@ * Authors: Ben Skeggs */ #include "gf100.h" +#include "ram.h" -struct nvkm_oclass * -gk104_fb_oclass = &(struct nvkm_fb_impl) { - .base.handle = NV_SUBDEV(FB, 0xe0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_fb_ctor, - .dtor = gf100_fb_dtor, - .init = gf100_fb_init, - .fini = _nvkm_fb_fini, - }, - .memtype = gf100_fb_memtype_valid, - .ram = &gk104_ram_oclass, -}.base; +static const struct nvkm_fb_func +gk104_fb = { + .dtor = gf100_fb_dtor, + .init = gf100_fb_init, + .intr = gf100_fb_intr, + .ram_new = gk104_ram_new, + .memtype_valid = gf100_fb_memtype_valid, +}; + +int +gk104_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return gf100_fb_new_(&gk104_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c index a5d7857d3..81447eb4c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c @@ -19,50 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include "gf100.h" +#include "priv.h" -struct gk20a_fb_priv { - struct nvkm_fb base; -}; - -static int -gk20a_fb_init(struct nvkm_object *object) +static void +gk20a_fb_init(struct nvkm_fb *fb) { - struct gk20a_fb_priv *priv = (void *)object; - int ret; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; - - nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */ - return 0; + struct nvkm_device *device = fb->subdev.device; + nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */ } -static int -gk20a_fb_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk20a_fb_priv *priv; - int ret; - - ret = nvkm_fb_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_fb_func +gk20a_fb = { + .init = gk20a_fb_init, + .memtype_valid = gf100_fb_memtype_valid, +}; - return 0; +int +gk20a_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&gk20a_fb, device, index, pfb); } - -struct nvkm_oclass * -gk20a_fb_oclass = &(struct nvkm_fb_impl) { - .base.handle = NV_SUBDEV(FB, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = gk20a_fb_init, - .fini = _nvkm_fb_fini, - }, - .memtype = gf100_fb_memtype_valid, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c index 843f9356b..2a91df865 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c @@ -22,16 +22,19 @@ * Authors: Ben Skeggs */ #include "gf100.h" +#include "ram.h" -struct nvkm_oclass * -gm107_fb_oclass = &(struct nvkm_fb_impl) { - .base.handle = NV_SUBDEV(FB, 0x07), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_fb_ctor, - .dtor = gf100_fb_dtor, - .init = gf100_fb_init, - .fini = _nvkm_fb_fini, - }, - .memtype = gf100_fb_memtype_valid, - .ram = &gm107_ram_oclass, -}.base; +static const struct nvkm_fb_func +gm107_fb = { + .dtor = gf100_fb_dtor, + .init = gf100_fb_init, + .intr = gf100_fb_intr, + .ram_new = gm107_ram_new, + .memtype_valid = gf100_fb_memtype_valid, +}; + +int +gm107_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return gf100_fb_new_(&gm107_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c index dd9b8a0a3..ebb30608d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c @@ -22,17 +22,16 @@ * Authors: Ben Skeggs */ #include "nv50.h" +#include "ram.h" -struct nvkm_oclass * -gt215_fb_oclass = &(struct nv50_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0xa3), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fb_ctor, - .dtor = nv50_fb_dtor, - .init = nv50_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv50_fb_memtype_valid, - .base.ram = >215_ram_oclass, +static const struct nv50_fb_func +gt215_fb = { + .ram_new = gt215_ram_new, .trap = 0x000d0fff, -}.base.base; +}; + +int +gt215_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nv50_fb_new_(>215_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp77.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp77.c index 7be4a47ef..73b3b86a2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp77.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp77.c @@ -22,17 +22,16 @@ * Authors: Ben Skeggs */ #include "nv50.h" +#include "ram.h" -struct nvkm_oclass * -mcp77_fb_oclass = &(struct nv50_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0xaa), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fb_ctor, - .dtor = nv50_fb_dtor, - .init = nv50_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv50_fb_memtype_valid, - .base.ram = &mcp77_ram_oclass, +static const struct nv50_fb_func +mcp77_fb = { + .ram_new = mcp77_ram_new, .trap = 0x001d07ff, -}.base.base; +}; + +int +mcp77_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nv50_fb_new_(&mcp77_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp89.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp89.c index 2d00656fa..6d11e32ec 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp89.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/mcp89.c @@ -22,17 +22,16 @@ * Authors: Ben Skeggs */ #include "nv50.h" +#include "ram.h" -struct nvkm_oclass * -mcp89_fb_oclass = &(struct nv50_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0xaf), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fb_ctor, - .dtor = nv50_fb_dtor, - .init = nv50_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv50_fb_memtype_valid, - .base.ram = &mcp77_ram_oclass, +static const struct nv50_fb_func +mcp89_fb = { + .ram_new = mcp77_ram_new, .trap = 0x089d1fff, -}.base.base; +}; + +int +mcp89_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nv50_fb_new_(&mcp89_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c index c063dec7d..8ff2e5db4 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c @@ -21,67 +21,39 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" #include "regsnv04.h" bool -nv04_fb_memtype_valid(struct nvkm_fb *pfb, u32 tile_flags) +nv04_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags) { if (!(tile_flags & 0xff00)) return true; - return false; } -static int -nv04_fb_init(struct nvkm_object *object) +static void +nv04_fb_init(struct nvkm_fb *fb) { - struct nv04_fb_priv *priv = (void *)object; - int ret; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; + struct nvkm_device *device = fb->subdev.device; /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows * nvidia reading PFB_CFG_0, then writing back its original value. * (which was 0x701114 in this case) */ - nv_wr32(priv, NV04_PFB_CFG0, 0x1114); - return 0; + nvkm_wr32(device, NV04_PFB_CFG0, 0x1114); } +static const struct nvkm_fb_func +nv04_fb = { + .init = nv04_fb_init, + .ram_new = nv04_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + int -nv04_fb_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) { - struct nv04_fb_impl *impl = (void *)oclass; - struct nv04_fb_priv *priv; - int ret; - - ret = nvkm_fb_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.tile.regions = impl->tile.regions; - priv->base.tile.init = impl->tile.init; - priv->base.tile.comp = impl->tile.comp; - priv->base.tile.fini = impl->tile.fini; - priv->base.tile.prog = impl->tile.prog; - return 0; + return nvkm_fb_new_(&nv04_fb, device, index, pfb); } - -struct nvkm_oclass * -nv04_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x04), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv04_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv04_ram_oclass, -}.base.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.h deleted file mode 100644 index caa0d03aa..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __NVKM_FB_NV04_H__ -#define __NVKM_FB_NV04_H__ -#include "priv.h" - -struct nv04_fb_priv { - struct nvkm_fb base; -}; - -int nv04_fb_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - -struct nv04_fb_impl { - struct nvkm_fb_impl base; - struct { - int regions; - void (*init)(struct nvkm_fb *, int i, u32 addr, u32 size, - u32 pitch, u32 flags, struct nvkm_fb_tile *); - void (*comp)(struct nvkm_fb *, int i, u32 size, u32 flags, - struct nvkm_fb_tile *); - void (*fini)(struct nvkm_fb *, int i, - struct nvkm_fb_tile *); - void (*prog)(struct nvkm_fb *, int i, - struct nvkm_fb_tile *); - } tile; -}; - -void nv10_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, - u32 pitch, u32 flags, struct nvkm_fb_tile *); -void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); -void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); - -void nv20_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, - u32 pitch, u32 flags, struct nvkm_fb_tile *); -void nv20_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); -void nv20_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); - -int nv30_fb_init(struct nvkm_object *); -void nv30_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, - u32 pitch, u32 flags, struct nvkm_fb_tile *); - -void nv40_fb_tile_comp(struct nvkm_fb *, int i, u32 size, u32 flags, - struct nvkm_fb_tile *); - -int nv41_fb_init(struct nvkm_object *); -void nv41_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); - -int nv44_fb_init(struct nvkm_object *); -void nv44_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); - -void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, - u32 pitch, u32 flags, struct nvkm_fb_tile *); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c index f3530e4a6..e8c44f5a3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c @@ -23,10 +23,11 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" void -nv10_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, +nv10_fb_tile_init(struct nvkm_fb *fb, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *tile) { tile->addr = 0x80000000 | addr; @@ -35,7 +36,7 @@ nv10_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, } void -nv10_fb_tile_fini(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) +nv10_fb_tile_fini(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) { tile->addr = 0; tile->limit = 0; @@ -44,27 +45,27 @@ nv10_fb_tile_fini(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) } void -nv10_fb_tile_prog(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) +nv10_fb_tile_prog(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) { - nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); - nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); - nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); - nv_rd32(pfb, 0x100240 + (i * 0x10)); + struct nvkm_device *device = fb->subdev.device; + nvkm_wr32(device, 0x100244 + (i * 0x10), tile->limit); + nvkm_wr32(device, 0x100248 + (i * 0x10), tile->pitch); + nvkm_wr32(device, 0x100240 + (i * 0x10), tile->addr); + nvkm_rd32(device, 0x100240 + (i * 0x10)); } -struct nvkm_oclass * -nv10_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x10), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = _nvkm_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv10_ram_oclass, +static const struct nvkm_fb_func +nv10_fb = { .tile.regions = 8, .tile.init = nv10_fb_tile_init, .tile.fini = nv10_fb_tile_fini, .tile.prog = nv10_fb_tile_prog, -}.base.base; + .ram_new = nv10_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv10_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv10_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c index 83bcb73ca..2ae0beb87 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c @@ -23,21 +23,21 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" -struct nvkm_oclass * -nv1a_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x1a), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = _nvkm_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv1a_ram_oclass, +static const struct nvkm_fb_func +nv1a_fb = { .tile.regions = 8, .tile.init = nv10_fb_tile_init, .tile.fini = nv10_fb_tile_fini, .tile.prog = nv10_fb_tile_prog, -}.base.base; + .ram_new = nv1a_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv1a_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv1a_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c index e37084b8d..126865dfe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c @@ -23,28 +23,29 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" void -nv20_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, +nv20_fb_tile_init(struct nvkm_fb *fb, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *tile) { tile->addr = 0x00000001 | addr; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; if (flags & 4) { - pfb->tile.comp(pfb, i, size, flags, tile); + fb->func->tile.comp(fb, i, size, flags, tile); tile->addr |= 2; } } static void -nv20_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, +nv20_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, struct nvkm_fb_tile *tile) { u32 tiles = DIV_ROUND_UP(size, 0x40); - u32 tags = round_up(tiles / pfb->ram->parts, 0x40); - if (!nvkm_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) { + u32 tags = round_up(tiles / fb->ram->parts, 0x40); + if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */ else tile->zcomp = 0x04000000; /* Z24S8 */ tile->zcomp |= tile->tag->offset; @@ -56,39 +57,39 @@ nv20_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, } void -nv20_fb_tile_fini(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) +nv20_fb_tile_fini(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) { tile->addr = 0; tile->limit = 0; tile->pitch = 0; tile->zcomp = 0; - nvkm_mm_free(&pfb->tags, &tile->tag); + nvkm_mm_free(&fb->ram->tags, &tile->tag); } void -nv20_fb_tile_prog(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) +nv20_fb_tile_prog(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) { - nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); - nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); - nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); - nv_rd32(pfb, 0x100240 + (i * 0x10)); - nv_wr32(pfb, 0x100300 + (i * 0x04), tile->zcomp); + struct nvkm_device *device = fb->subdev.device; + nvkm_wr32(device, 0x100244 + (i * 0x10), tile->limit); + nvkm_wr32(device, 0x100248 + (i * 0x10), tile->pitch); + nvkm_wr32(device, 0x100240 + (i * 0x10), tile->addr); + nvkm_rd32(device, 0x100240 + (i * 0x10)); + nvkm_wr32(device, 0x100300 + (i * 0x04), tile->zcomp); } -struct nvkm_oclass * -nv20_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x20), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = _nvkm_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv20_ram_oclass, +static const struct nvkm_fb_func +nv20_fb = { .tile.regions = 8, .tile.init = nv20_fb_tile_init, .tile.comp = nv20_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, -}.base.base; + .ram_new = nv20_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv20_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv20_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c index bc9f54f38..c56746d2a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c @@ -23,15 +23,16 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" static void -nv25_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, +nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, struct nvkm_fb_tile *tile) { u32 tiles = DIV_ROUND_UP(size, 0x40); - u32 tags = round_up(tiles / pfb->ram->parts, 0x40); - if (!nvkm_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) { + u32 tags = round_up(tiles / fb->ram->parts, 0x40); + if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */ else tile->zcomp = 0x00200000; /* Z24S8 */ tile->zcomp |= tile->tag->offset; @@ -41,20 +42,19 @@ nv25_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, } } -struct nvkm_oclass * -nv25_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x25), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = _nvkm_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv20_ram_oclass, +static const struct nvkm_fb_func +nv25_fb = { .tile.regions = 8, .tile.init = nv20_fb_tile_init, .tile.comp = nv25_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, -}.base.base; + .ram_new = nv20_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv25_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv25_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c index 09ebb9477..2a7c4831b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c @@ -23,20 +23,19 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" - -#include +#include "priv.h" +#include "ram.h" void -nv30_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, +nv30_fb_tile_init(struct nvkm_fb *fb, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *tile) { /* for performance, select alternate bank offset for zeta */ if (!(flags & 4)) { tile->addr = (0 << 4); } else { - if (pfb->tile.comp) /* z compression */ - pfb->tile.comp(pfb, i, size, flags, tile); + if (fb->func->tile.comp) /* z compression */ + fb->func->tile.comp(fb, i, size, flags, tile); tile->addr = (1 << 4); } @@ -47,12 +46,12 @@ nv30_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, } static void -nv30_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, +nv30_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, struct nvkm_fb_tile *tile) { u32 tiles = DIV_ROUND_UP(size, 0x40); - u32 tags = round_up(tiles / pfb->ram->parts, 0x40); - if (!nvkm_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) { + u32 tags = round_up(tiles / fb->ram->parts, 0x40); + if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */ else tile->zcomp |= 0x02000000; /* Z24S8 */ tile->zcomp |= ((tile->tag->offset ) >> 6); @@ -64,23 +63,24 @@ nv30_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, } static int -calc_bias(struct nv04_fb_priv *priv, int k, int i, int j) +calc_bias(struct nvkm_fb *fb, int k, int i, int j) { - struct nvkm_device *device = nv_device(priv); + struct nvkm_device *device = fb->subdev.device; int b = (device->chipset > 0x30 ? - nv_rd32(priv, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : + nvkm_rd32(device, 0x122c + 0x10 * k + 0x4 * j) >> + (4 * (i ^ 1)) : 0) & 0xf; return 2 * (b & 0x8 ? b - 0x10 : b); } static int -calc_ref(struct nv04_fb_priv *priv, int l, int k, int i) +calc_ref(struct nvkm_fb *fb, int l, int k, int i) { int j, x = 0; for (j = 0; j < 4; j++) { - int m = (l >> (8 * i) & 0xff) + calc_bias(priv, k, i, j); + int m = (l >> (8 * i) & 0xff) + calc_bias(fb, k, i, j); x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); } @@ -88,16 +88,11 @@ calc_ref(struct nv04_fb_priv *priv, int l, int k, int i) return x; } -int -nv30_fb_init(struct nvkm_object *object) +void +nv30_fb_init(struct nvkm_fb *fb) { - struct nvkm_device *device = nv_device(object); - struct nv04_fb_priv *priv = (void *)object; - int ret, i, j; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; + struct nvkm_device *device = fb->subdev.device; + int i, j; /* Init the memory timing regs at 0x10037c/0x1003ac */ if (device->chipset == 0x30 || @@ -105,36 +100,34 @@ nv30_fb_init(struct nvkm_object *object) device->chipset == 0x35) { /* Related to ROP count */ int n = (device->chipset == 0x31 ? 2 : 4); - int l = nv_rd32(priv, 0x1003d0); + int l = nvkm_rd32(device, 0x1003d0); for (i = 0; i < n; i++) { for (j = 0; j < 3; j++) - nv_wr32(priv, 0x10037c + 0xc * i + 0x4 * j, - calc_ref(priv, l, 0, j)); + nvkm_wr32(device, 0x10037c + 0xc * i + 0x4 * j, + calc_ref(fb, l, 0, j)); for (j = 0; j < 2; j++) - nv_wr32(priv, 0x1003ac + 0x8 * i + 0x4 * j, - calc_ref(priv, l, 1, j)); + nvkm_wr32(device, 0x1003ac + 0x8 * i + 0x4 * j, + calc_ref(fb, l, 1, j)); } } - - return 0; } -struct nvkm_oclass * -nv30_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x30), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv30_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv20_ram_oclass, +static const struct nvkm_fb_func +nv30_fb = { + .init = nv30_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, .tile.comp = nv30_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, -}.base.base; + .ram_new = nv20_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv30_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv30_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c index c01dc1839..1604b3789 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c @@ -23,15 +23,16 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" static void -nv35_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, +nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, struct nvkm_fb_tile *tile) { u32 tiles = DIV_ROUND_UP(size, 0x40); - u32 tags = round_up(tiles / pfb->ram->parts, 0x40); - if (!nvkm_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) { + u32 tags = round_up(tiles / fb->ram->parts, 0x40); + if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */ else tile->zcomp |= 0x08000000; /* Z24S8 */ tile->zcomp |= ((tile->tag->offset ) >> 6); @@ -42,20 +43,20 @@ nv35_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, } } -struct nvkm_oclass * -nv35_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x35), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv30_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv20_ram_oclass, +static const struct nvkm_fb_func +nv35_fb = { + .init = nv30_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, .tile.comp = nv35_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, -}.base.base; + .ram_new = nv20_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv35_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv35_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c index cad75a1ce..80cc0a6e3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c @@ -23,15 +23,16 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" static void -nv36_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, +nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, struct nvkm_fb_tile *tile) { u32 tiles = DIV_ROUND_UP(size, 0x40); - u32 tags = round_up(tiles / pfb->ram->parts, 0x40); - if (!nvkm_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) { + u32 tags = round_up(tiles / fb->ram->parts, 0x40); + if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */ else tile->zcomp |= 0x20000000; /* Z24S8 */ tile->zcomp |= ((tile->tag->offset ) >> 6); @@ -42,20 +43,20 @@ nv36_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, } } -struct nvkm_oclass * -nv36_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x36), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv30_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv20_ram_oclass, +static const struct nvkm_fb_func +nv36_fb = { + .init = nv30_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, .tile.comp = nv36_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, -}.base.base; + .ram_new = nv20_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv36_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv36_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c index dbe5c1910..deec46a31 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c @@ -23,16 +23,17 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" void -nv40_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, +nv40_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, struct nvkm_fb_tile *tile) { u32 tiles = DIV_ROUND_UP(size, 0x80); - u32 tags = round_up(tiles / pfb->ram->parts, 0x100); + u32 tags = round_up(tiles / fb->ram->parts, 0x100); if ( (flags & 2) && - !nvkm_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) { + !nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */ tile->zcomp |= ((tile->tag->offset ) >> 8); tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13; @@ -42,34 +43,26 @@ nv40_fb_tile_comp(struct nvkm_fb *pfb, int i, u32 size, u32 flags, } } -static int -nv40_fb_init(struct nvkm_object *object) +static void +nv40_fb_init(struct nvkm_fb *fb) { - struct nv04_fb_priv *priv = (void *)object; - int ret; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; - - nv_mask(priv, 0x10033c, 0x00008000, 0x00000000); - return 0; + nvkm_mask(fb->subdev.device, 0x10033c, 0x00008000, 0x00000000); } -struct nvkm_oclass * -nv40_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x40), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv40_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv40_ram_oclass, +static const struct nvkm_fb_func +nv40_fb = { + .init = nv40_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, .tile.comp = nv40_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, -}.base.base; + .ram_new = nv40_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv40_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv40_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.h deleted file mode 100644 index 602182661..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __NVKM_FB_NV40_H__ -#define __NVKM_FB_NV40_H__ -#include "priv.h" - -struct nv40_ram { - struct nvkm_ram base; - u32 ctrl; - u32 coef; -}; - -int nv40_ram_calc(struct nvkm_fb *, u32); -int nv40_ram_prog(struct nvkm_fb *); -void nv40_ram_tidy(struct nvkm_fb *); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c index d9e1a40a2..79e57dd5a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c @@ -23,46 +23,40 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" void -nv41_fb_tile_prog(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) +nv41_fb_tile_prog(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) { - nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit); - nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch); - nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr); - nv_rd32(pfb, 0x100600 + (i * 0x10)); - nv_wr32(pfb, 0x100700 + (i * 0x04), tile->zcomp); + struct nvkm_device *device = fb->subdev.device; + nvkm_wr32(device, 0x100604 + (i * 0x10), tile->limit); + nvkm_wr32(device, 0x100608 + (i * 0x10), tile->pitch); + nvkm_wr32(device, 0x100600 + (i * 0x10), tile->addr); + nvkm_rd32(device, 0x100600 + (i * 0x10)); + nvkm_wr32(device, 0x100700 + (i * 0x04), tile->zcomp); } -int -nv41_fb_init(struct nvkm_object *object) +void +nv41_fb_init(struct nvkm_fb *fb) { - struct nv04_fb_priv *priv = (void *)object; - int ret; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x100800, 0x00000001); - return 0; + nvkm_wr32(fb->subdev.device, 0x100800, 0x00000001); } -struct nvkm_oclass * -nv41_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x41), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv41_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv41_ram_oclass, +static const struct nvkm_fb_func +nv41_fb = { + .init = nv41_fb_init, .tile.regions = 12, .tile.init = nv30_fb_tile_init, .tile.comp = nv40_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv41_fb_tile_prog, -}.base.base; + .ram_new = nv41_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv41_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv41_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c index 20b97c83c..06246cce5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c @@ -23,10 +23,11 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" static void -nv44_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, +nv44_fb_tile_init(struct nvkm_fb *fb, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *tile) { tile->addr = 0x00000001; /* mode = vram */ @@ -36,42 +37,36 @@ nv44_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, } void -nv44_fb_tile_prog(struct nvkm_fb *pfb, int i, struct nvkm_fb_tile *tile) +nv44_fb_tile_prog(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) { - nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit); - nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch); - nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr); - nv_rd32(pfb, 0x100600 + (i * 0x10)); + struct nvkm_device *device = fb->subdev.device; + nvkm_wr32(device, 0x100604 + (i * 0x10), tile->limit); + nvkm_wr32(device, 0x100608 + (i * 0x10), tile->pitch); + nvkm_wr32(device, 0x100600 + (i * 0x10), tile->addr); + nvkm_rd32(device, 0x100600 + (i * 0x10)); } -int -nv44_fb_init(struct nvkm_object *object) +void +nv44_fb_init(struct nvkm_fb *fb) { - struct nv04_fb_priv *priv = (void *)object; - int ret; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x100850, 0x80000000); - nv_wr32(priv, 0x100800, 0x00000001); - return 0; + struct nvkm_device *device = fb->subdev.device; + nvkm_wr32(device, 0x100850, 0x80000000); + nvkm_wr32(device, 0x100800, 0x00000001); } -struct nvkm_oclass * -nv44_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x44), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv44_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv44_ram_oclass, +static const struct nvkm_fb_func +nv44_fb = { + .init = nv44_fb_init, .tile.regions = 12, .tile.init = nv44_fb_tile_init, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv44_fb_tile_prog, -}.base.base; + .ram_new = nv44_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv44_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv44_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c index 5bfac38cd..3598a1aa6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c @@ -23,10 +23,11 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" void -nv46_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, +nv46_fb_tile_init(struct nvkm_fb *fb, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *tile) { /* for performance, select alternate bank offset for zeta */ @@ -39,19 +40,19 @@ nv46_fb_tile_init(struct nvkm_fb *pfb, int i, u32 addr, u32 size, u32 pitch, tile->pitch = pitch; } -struct nvkm_oclass * -nv46_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x46), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv44_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv44_ram_oclass, +static const struct nvkm_fb_func +nv46_fb = { + .init = nv44_fb_init, .tile.regions = 15, .tile.init = nv46_fb_tile_init, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv44_fb_tile_prog, -}.base.base; + .ram_new = nv44_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv46_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv46_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c index d3b3988d1..c505e4429 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c @@ -23,22 +23,23 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" -struct nvkm_oclass * -nv47_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x47), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv41_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv41_ram_oclass, +static const struct nvkm_fb_func +nv47_fb = { + .init = nv41_fb_init, .tile.regions = 15, .tile.init = nv30_fb_tile_init, .tile.comp = nv40_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv41_fb_tile_prog, -}.base.base; + .ram_new = nv41_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv47_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv47_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c index 236e36c50..7b91b9f17 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c @@ -23,22 +23,23 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" -struct nvkm_oclass * -nv49_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x49), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv41_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv49_ram_oclass, +static const struct nvkm_fb_func +nv49_fb = { + .init = nv41_fb_init, .tile.regions = 15, .tile.init = nv30_fb_tile_init, .tile.comp = nv40_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv41_fb_tile_prog, -}.base.base; + .ram_new = nv49_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv49_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv49_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c index 1352b6a73..4e98210c1 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c @@ -23,21 +23,22 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#include "nv04.h" +#include "priv.h" +#include "ram.h" -struct nvkm_oclass * -nv4e_fb_oclass = &(struct nv04_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x4e), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_fb_ctor, - .dtor = _nvkm_fb_dtor, - .init = nv44_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv4e_ram_oclass, +static const struct nvkm_fb_func +nv4e_fb = { + .init = nv44_fb_init, .tile.regions = 12, .tile.init = nv46_fb_tile_init, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv44_fb_tile_prog, -}.base.base; + .ram_new = nv44_ram_new, + .memtype_valid = nv04_fb_memtype_valid, +}; + +int +nv4e_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nvkm_fb_new_(&nv4e_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c index 0480ce52a..f5edfadb5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c @@ -22,11 +22,11 @@ * Authors: Ben Skeggs */ #include "nv50.h" +#include "ram.h" #include -#include -#include #include +#include int nv50_fb_memtype[0x80] = { @@ -40,130 +40,139 @@ nv50_fb_memtype[0x80] = { 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 }; -bool -nv50_fb_memtype_valid(struct nvkm_fb *pfb, u32 memtype) +static int +nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram) +{ + struct nv50_fb *fb = nv50_fb(base); + return fb->func->ram_new(&fb->base, pram); +} + +static bool +nv50_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype) { return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0; } static const struct nvkm_enum vm_dispatch_subclients[] = { - { 0x00000000, "GRCTX", NULL }, - { 0x00000001, "NOTIFY", NULL }, - { 0x00000002, "QUERY", NULL }, - { 0x00000003, "COND", NULL }, - { 0x00000004, "M2M_IN", NULL }, - { 0x00000005, "M2M_OUT", NULL }, - { 0x00000006, "M2M_NOTIFY", NULL }, + { 0x00000000, "GRCTX" }, + { 0x00000001, "NOTIFY" }, + { 0x00000002, "QUERY" }, + { 0x00000003, "COND" }, + { 0x00000004, "M2M_IN" }, + { 0x00000005, "M2M_OUT" }, + { 0x00000006, "M2M_NOTIFY" }, {} }; static const struct nvkm_enum vm_ccache_subclients[] = { - { 0x00000000, "CB", NULL }, - { 0x00000001, "TIC", NULL }, - { 0x00000002, "TSC", NULL }, + { 0x00000000, "CB" }, + { 0x00000001, "TIC" }, + { 0x00000002, "TSC" }, {} }; static const struct nvkm_enum vm_prop_subclients[] = { - { 0x00000000, "RT0", NULL }, - { 0x00000001, "RT1", NULL }, - { 0x00000002, "RT2", NULL }, - { 0x00000003, "RT3", NULL }, - { 0x00000004, "RT4", NULL }, - { 0x00000005, "RT5", NULL }, - { 0x00000006, "RT6", NULL }, - { 0x00000007, "RT7", NULL }, - { 0x00000008, "ZETA", NULL }, - { 0x00000009, "LOCAL", NULL }, - { 0x0000000a, "GLOBAL", NULL }, - { 0x0000000b, "STACK", NULL }, - { 0x0000000c, "DST2D", NULL }, + { 0x00000000, "RT0" }, + { 0x00000001, "RT1" }, + { 0x00000002, "RT2" }, + { 0x00000003, "RT3" }, + { 0x00000004, "RT4" }, + { 0x00000005, "RT5" }, + { 0x00000006, "RT6" }, + { 0x00000007, "RT7" }, + { 0x00000008, "ZETA" }, + { 0x00000009, "LOCAL" }, + { 0x0000000a, "GLOBAL" }, + { 0x0000000b, "STACK" }, + { 0x0000000c, "DST2D" }, {} }; static const struct nvkm_enum vm_pfifo_subclients[] = { - { 0x00000000, "PUSHBUF", NULL }, - { 0x00000001, "SEMAPHORE", NULL }, + { 0x00000000, "PUSHBUF" }, + { 0x00000001, "SEMAPHORE" }, {} }; static const struct nvkm_enum vm_bar_subclients[] = { - { 0x00000000, "FB", NULL }, - { 0x00000001, "IN", NULL }, + { 0x00000000, "FB" }, + { 0x00000001, "IN" }, {} }; static const struct nvkm_enum vm_client[] = { - { 0x00000000, "STRMOUT", NULL }, + { 0x00000000, "STRMOUT" }, { 0x00000003, "DISPATCH", vm_dispatch_subclients }, - { 0x00000004, "PFIFO_WRITE", NULL }, + { 0x00000004, "PFIFO_WRITE" }, { 0x00000005, "CCACHE", vm_ccache_subclients }, - { 0x00000006, "PMSPPP", NULL }, - { 0x00000007, "CLIPID", NULL }, - { 0x00000008, "PFIFO_READ", NULL }, - { 0x00000009, "VFETCH", NULL }, - { 0x0000000a, "TEXTURE", NULL }, + { 0x00000006, "PMSPPP" }, + { 0x00000007, "CLIPID" }, + { 0x00000008, "PFIFO_READ" }, + { 0x00000009, "VFETCH" }, + { 0x0000000a, "TEXTURE" }, { 0x0000000b, "PROP", vm_prop_subclients }, - { 0x0000000c, "PVP", NULL }, - { 0x0000000d, "PBSP", NULL }, - { 0x0000000e, "PCRYPT", NULL }, - { 0x0000000f, "PCOUNTER", NULL }, - { 0x00000011, "PDAEMON", NULL }, + { 0x0000000c, "PVP" }, + { 0x0000000d, "PBSP" }, + { 0x0000000e, "PCRYPT" }, + { 0x0000000f, "PCOUNTER" }, + { 0x00000011, "PDAEMON" }, {} }; static const struct nvkm_enum vm_engine[] = { - { 0x00000000, "PGRAPH", NULL, NVDEV_ENGINE_GR }, - { 0x00000001, "PVP", NULL, NVDEV_ENGINE_VP }, - { 0x00000004, "PEEPHOLE", NULL }, - { 0x00000005, "PFIFO", vm_pfifo_subclients, NVDEV_ENGINE_FIFO }, + { 0x00000000, "PGRAPH" }, + { 0x00000001, "PVP" }, + { 0x00000004, "PEEPHOLE" }, + { 0x00000005, "PFIFO", vm_pfifo_subclients }, { 0x00000006, "BAR", vm_bar_subclients }, - { 0x00000008, "PMSPPP", NULL, NVDEV_ENGINE_MSPPP }, - { 0x00000008, "PMPEG", NULL, NVDEV_ENGINE_MPEG }, - { 0x00000009, "PBSP", NULL, NVDEV_ENGINE_BSP }, - { 0x0000000a, "PCRYPT", NULL, NVDEV_ENGINE_CIPHER }, - { 0x0000000b, "PCOUNTER", NULL }, - { 0x0000000c, "SEMAPHORE_BG", NULL }, - { 0x0000000d, "PCE0", NULL, NVDEV_ENGINE_CE0 }, - { 0x0000000e, "PDAEMON", NULL }, + { 0x00000008, "PMSPPP" }, + { 0x00000008, "PMPEG" }, + { 0x00000009, "PBSP" }, + { 0x0000000a, "PCRYPT" }, + { 0x0000000b, "PCOUNTER" }, + { 0x0000000c, "SEMAPHORE_BG" }, + { 0x0000000d, "PCE0" }, + { 0x0000000e, "PDAEMON" }, {} }; static const struct nvkm_enum vm_fault[] = { - { 0x00000000, "PT_NOT_PRESENT", NULL }, - { 0x00000001, "PT_TOO_SHORT", NULL }, - { 0x00000002, "PAGE_NOT_PRESENT", NULL }, - { 0x00000003, "PAGE_SYSTEM_ONLY", NULL }, - { 0x00000004, "PAGE_READ_ONLY", NULL }, - { 0x00000006, "NULL_DMAOBJ", NULL }, - { 0x00000007, "WRONG_MEMTYPE", NULL }, - { 0x0000000b, "VRAM_LIMIT", NULL }, - { 0x0000000f, "DMAOBJ_LIMIT", NULL }, + { 0x00000000, "PT_NOT_PRESENT" }, + { 0x00000001, "PT_TOO_SHORT" }, + { 0x00000002, "PAGE_NOT_PRESENT" }, + { 0x00000003, "PAGE_SYSTEM_ONLY" }, + { 0x00000004, "PAGE_READ_ONLY" }, + { 0x00000006, "NULL_DMAOBJ" }, + { 0x00000007, "WRONG_MEMTYPE" }, + { 0x0000000b, "VRAM_LIMIT" }, + { 0x0000000f, "DMAOBJ_LIMIT" }, {} }; static void -nv50_fb_intr(struct nvkm_subdev *subdev) +nv50_fb_intr(struct nvkm_fb *base) { - struct nvkm_device *device = nv_device(subdev); - struct nvkm_engine *engine; - struct nv50_fb_priv *priv = (void *)subdev; - const struct nvkm_enum *en, *cl; - struct nvkm_object *engctx = NULL; - u32 trap[6], idx, chan; + struct nv50_fb *fb = nv50_fb(base); + struct nvkm_subdev *subdev = &fb->base.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_fifo *fifo = device->fifo; + struct nvkm_fifo_chan *chan; + const struct nvkm_enum *en, *re, *cl, *sc; + u32 trap[6], idx, inst; u8 st0, st1, st2, st3; + unsigned long flags; int i; - idx = nv_rd32(priv, 0x100c90); + idx = nvkm_rd32(device, 0x100c90); if (!(idx & 0x80000000)) return; idx &= 0x00ffffff; for (i = 0; i < 6; i++) { - nv_wr32(priv, 0x100c90, idx | i << 24); - trap[i] = nv_rd32(priv, 0x100c94); + nvkm_wr32(device, 0x100c90, idx | i << 24); + trap[i] = nvkm_rd32(device, 0x100c94); } - nv_wr32(priv, 0x100c90, idx | 0x80000000); + nvkm_wr32(device, 0x100c90, idx | 0x80000000); /* decode status bits into something more useful */ if (device->chipset < 0xa3 || @@ -178,143 +187,103 @@ nv50_fb_intr(struct nvkm_subdev *subdev) st2 = (trap[0] & 0x00ff0000) >> 16; st3 = (trap[0] & 0xff000000) >> 24; } - chan = (trap[2] << 16) | trap[1]; + inst = ((trap[2] << 16) | trap[1]) << 12; en = nvkm_enum_find(vm_engine, st0); - - if (en && en->data2) { - const struct nvkm_enum *orig_en = en; - while (en->name && en->value == st0 && en->data2) { - engine = nvkm_engine(subdev, en->data2); - /*XXX: clean this up */ - if (!engine && en->data2 == NVDEV_ENGINE_BSP) - engine = nvkm_engine(subdev, NVDEV_ENGINE_MSVLD); - if (!engine && en->data2 == NVDEV_ENGINE_CIPHER) - engine = nvkm_engine(subdev, NVDEV_ENGINE_SEC); - if (!engine && en->data2 == NVDEV_ENGINE_VP) - engine = nvkm_engine(subdev, NVDEV_ENGINE_MSPDEC); - if (engine) { - engctx = nvkm_engctx_get(engine, chan); - if (engctx) - break; - } - en++; - } - if (!engctx) - en = orig_en; - } - - nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x [%s] ", - (trap[5] & 0x00000100) ? "read" : "write", - trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan, - nvkm_client_name(engctx)); - - nvkm_engctx_put(engctx); - - if (en) - pr_cont("%s/", en->name); - else - pr_cont("%02x/", st0); - + re = nvkm_enum_find(vm_fault , st1); cl = nvkm_enum_find(vm_client, st2); - if (cl) - pr_cont("%s/", cl->name); - else - pr_cont("%02x/", st2); - - if (cl && cl->data) cl = nvkm_enum_find(cl->data, st3); - else if (en && en->data) cl = nvkm_enum_find(en->data, st3); - else cl = NULL; - if (cl) - pr_cont("%s", cl->name); - else - pr_cont("%02x", st3); - - pr_cont(" reason: "); - en = nvkm_enum_find(vm_fault, st1); - if (en) - pr_cont("%s\n", en->name); - else - pr_cont("0x%08x\n", st1); + if (cl && cl->data) sc = nvkm_enum_find(cl->data, st3); + else if (en && en->data) sc = nvkm_enum_find(en->data, st3); + else sc = NULL; + + chan = nvkm_fifo_chan_inst(fifo, inst, &flags); + nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel %d [%08x %s] " + "engine %02x [%s] client %02x [%s] " + "subclient %02x [%s] reason %08x [%s]\n", + (trap[5] & 0x00000100) ? "read" : "write", + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, + chan ? chan->chid : -1, inst, + chan ? chan->object.client->name : "unknown", + st0, en ? en->name : "", + st2, cl ? cl->name : "", st3, sc ? sc->name : "", + st1, re ? re->name : ""); + nvkm_fifo_chan_put(fifo, flags, &chan); } -int -nv50_fb_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void +nv50_fb_init(struct nvkm_fb *base) { - struct nvkm_device *device = nv_device(parent); - struct nv50_fb_priv *priv; - int ret; - - ret = nvkm_fb_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + struct nv50_fb *fb = nv50_fb(base); + struct nvkm_device *device = fb->base.subdev.device; - priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (priv->r100c08_page) { - priv->r100c08 = dma_map_page(nv_device_base(device), - priv->r100c08_page, 0, PAGE_SIZE, - DMA_BIDIRECTIONAL); - if (dma_mapping_error(nv_device_base(device), priv->r100c08)) - return -EFAULT; - } else { - nv_warn(priv, "failed 0x100c08 page alloc\n"); - } + /* Not a clue what this is exactly. Without pointing it at a + * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) + * cause IOMMU "read from address 0" errors (rh#561267) + */ + nvkm_wr32(device, 0x100c08, fb->r100c08 >> 8); - nv_subdev(priv)->intr = nv50_fb_intr; - return 0; + /* This is needed to get meaningful information from 100c90 + * on traps. No idea what these values mean exactly. */ + nvkm_wr32(device, 0x100c90, fb->func->trap); } -void -nv50_fb_dtor(struct nvkm_object *object) +static void * +nv50_fb_dtor(struct nvkm_fb *base) { - struct nvkm_device *device = nv_device(object); - struct nv50_fb_priv *priv = (void *)object; + struct nv50_fb *fb = nv50_fb(base); + struct nvkm_device *device = fb->base.subdev.device; - if (priv->r100c08_page) { - dma_unmap_page(nv_device_base(device), priv->r100c08, PAGE_SIZE, + if (fb->r100c08_page) { + dma_unmap_page(device->dev, fb->r100c08, PAGE_SIZE, DMA_BIDIRECTIONAL); - __free_page(priv->r100c08_page); + __free_page(fb->r100c08_page); } - nvkm_fb_destroy(&priv->base); + return fb; } +static const struct nvkm_fb_func +nv50_fb_ = { + .dtor = nv50_fb_dtor, + .init = nv50_fb_init, + .intr = nv50_fb_intr, + .ram_new = nv50_fb_ram_new, + .memtype_valid = nv50_fb_memtype_valid, +}; + int -nv50_fb_init(struct nvkm_object *object) +nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device, + int index, struct nvkm_fb **pfb) { - struct nv50_fb_impl *impl = (void *)object->oclass; - struct nv50_fb_priv *priv = (void *)object; - int ret; - - ret = nvkm_fb_init(&priv->base); - if (ret) - return ret; - - /* Not a clue what this is exactly. Without pointing it at a - * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) - * cause IOMMU "read from address 0" errors (rh#561267) - */ - nv_wr32(priv, 0x100c08, priv->r100c08 >> 8); + struct nv50_fb *fb; + + if (!(fb = kzalloc(sizeof(*fb), GFP_KERNEL))) + return -ENOMEM; + nvkm_fb_ctor(&nv50_fb_, device, index, &fb->base); + fb->func = func; + *pfb = &fb->base; + + fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (fb->r100c08_page) { + fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(device->dev, fb->r100c08)) + return -EFAULT; + } else { + nvkm_warn(&fb->base.subdev, "failed 100c08 page alloc\n"); + } - /* This is needed to get meaningful information from 100c90 - * on traps. No idea what these values mean exactly. */ - nv_wr32(priv, 0x100c90, impl->trap); return 0; } -struct nvkm_oclass * -nv50_fb_oclass = &(struct nv50_fb_impl) { - .base.base.handle = NV_SUBDEV(FB, 0x50), - .base.base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fb_ctor, - .dtor = nv50_fb_dtor, - .init = nv50_fb_init, - .fini = _nvkm_fb_fini, - }, - .base.memtype = nv50_fb_memtype_valid, - .base.ram = &nv50_ram_oclass, +static const struct nv50_fb_func +nv50_fb = { + .ram_new = nv50_ram_new, .trap = 0x000707ff, -}.base.base; +}; + +int +nv50_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return nv50_fb_new_(&nv50_fb, device, index, pfb); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h index f3cde3f1f..faa88c8c6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h @@ -1,31 +1,21 @@ #ifndef __NVKM_FB_NV50_H__ #define __NVKM_FB_NV50_H__ +#define nv50_fb(p) container_of((p), struct nv50_fb, base) #include "priv.h" -struct nv50_fb_priv { +struct nv50_fb { + const struct nv50_fb_func *func; struct nvkm_fb base; struct page *r100c08_page; dma_addr_t r100c08; }; -int nv50_fb_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv50_fb_dtor(struct nvkm_object *); -int nv50_fb_init(struct nvkm_object *); - -struct nv50_fb_impl { - struct nvkm_fb_impl base; +struct nv50_fb_func { + int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); u32 trap; }; -#define nv50_ram_create(p,e,o,d) \ - nv50_ram_create_((p), (e), (o), sizeof(**d), (void **)d) -int nv50_ram_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -int nv50_ram_get(struct nvkm_fb *, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nvkm_mem **); -void nv50_ram_put(struct nvkm_fb *, struct nvkm_mem **); -void __nv50_ram_put(struct nvkm_fb *, struct nvkm_mem *); +int nv50_fb_new_(const struct nv50_fb_func *, struct nvkm_device *, int index, + struct nvkm_fb **pfb); extern int nv50_fb_memtype[0x80]; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index 485c4b648..62b9feb53 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -1,73 +1,62 @@ #ifndef __NVKM_FB_PRIV_H__ #define __NVKM_FB_PRIV_H__ +#define nvkm_fb(p) container_of((p), struct nvkm_fb, subdev) #include struct nvkm_bios; -#define nvkm_ram_create(p,e,o,d) \ - nvkm_object_create_((p), (e), (o), 0, sizeof(**d), (void **)d) -#define nvkm_ram_destroy(p) \ - nvkm_object_destroy(&(p)->base) -#define nvkm_ram_init(p) \ - nvkm_object_init(&(p)->base) -#define nvkm_ram_fini(p,s) \ - nvkm_object_fini(&(p)->base, (s)) +struct nvkm_fb_func { + void *(*dtor)(struct nvkm_fb *); + void (*init)(struct nvkm_fb *); + void (*intr)(struct nvkm_fb *); -#define nvkm_ram_create_(p,e,o,s,d) \ - nvkm_object_create_((p), (e), (o), 0, (s), (void **)d) -#define _nvkm_ram_dtor nvkm_object_destroy -#define _nvkm_ram_init nvkm_object_init -#define _nvkm_ram_fini nvkm_object_fini + struct { + int regions; + void (*init)(struct nvkm_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *); + void (*comp)(struct nvkm_fb *, int i, u32 size, u32 flags, + struct nvkm_fb_tile *); + void (*fini)(struct nvkm_fb *, int i, struct nvkm_fb_tile *); + void (*prog)(struct nvkm_fb *, int i, struct nvkm_fb_tile *); + } tile; -extern struct nvkm_oclass nv04_ram_oclass; -extern struct nvkm_oclass nv10_ram_oclass; -extern struct nvkm_oclass nv1a_ram_oclass; -extern struct nvkm_oclass nv20_ram_oclass; -extern struct nvkm_oclass nv40_ram_oclass; -extern struct nvkm_oclass nv41_ram_oclass; -extern struct nvkm_oclass nv44_ram_oclass; -extern struct nvkm_oclass nv49_ram_oclass; -extern struct nvkm_oclass nv4e_ram_oclass; -extern struct nvkm_oclass nv50_ram_oclass; -extern struct nvkm_oclass gt215_ram_oclass; -extern struct nvkm_oclass mcp77_ram_oclass; -extern struct nvkm_oclass gf100_ram_oclass; -extern struct nvkm_oclass gk104_ram_oclass; -extern struct nvkm_oclass gm107_ram_oclass; + int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); -int nvkm_sddr2_calc(struct nvkm_ram *ram); -int nvkm_sddr3_calc(struct nvkm_ram *ram); -int nvkm_gddr3_calc(struct nvkm_ram *ram); -int nvkm_gddr5_calc(struct nvkm_ram *ram, bool nuts); + bool (*memtype_valid)(struct nvkm_fb *, u32 memtype); +}; -#define nvkm_fb_create(p,e,c,d) \ - nvkm_fb_create_((p), (e), (c), sizeof(**d), (void **)d) -#define nvkm_fb_destroy(p) ({ \ - struct nvkm_fb *pfb = (p); \ - _nvkm_fb_dtor(nv_object(pfb)); \ -}) -#define nvkm_fb_init(p) ({ \ - struct nvkm_fb *pfb = (p); \ - _nvkm_fb_init(nv_object(pfb)); \ -}) -#define nvkm_fb_fini(p,s) ({ \ - struct nvkm_fb *pfb = (p); \ - _nvkm_fb_fini(nv_object(pfb), (s)); \ -}) +void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, + int index, struct nvkm_fb *); +int nvkm_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *device, + int index, struct nvkm_fb **); +int nvkm_fb_bios_memtype(struct nvkm_bios *); -int nvkm_fb_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_fb_dtor(struct nvkm_object *); -int _nvkm_fb_init(struct nvkm_object *); -int _nvkm_fb_fini(struct nvkm_object *, bool); +bool nv04_fb_memtype_valid(struct nvkm_fb *, u32 memtype); -struct nvkm_fb_impl { - struct nvkm_oclass base; - struct nvkm_oclass *ram; - bool (*memtype)(struct nvkm_fb *, u32); -}; +void nv10_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *); +void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); +void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); -bool nv04_fb_memtype_valid(struct nvkm_fb *, u32 memtype); -bool nv50_fb_memtype_valid(struct nvkm_fb *, u32 memtype); +void nv20_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *); +void nv20_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); +void nv20_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); + +void nv30_fb_init(struct nvkm_fb *); +void nv30_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *); + +void nv40_fb_tile_comp(struct nvkm_fb *, int i, u32 size, u32 flags, + struct nvkm_fb_tile *); + +void nv41_fb_init(struct nvkm_fb *); +void nv41_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); + +void nv44_fb_init(struct nvkm_fb *); +void nv44_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); + +void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nvkm_fb_tile *); -int nvkm_fb_bios_memtype(struct nvkm_bios *); +bool gf100_fb_memtype_valid(struct nvkm_fb *, u32); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c new file mode 100644 index 000000000..c17d559db --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c @@ -0,0 +1,100 @@ +/* + * 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 + */ +#include "ram.h" + +int +nvkm_ram_init(struct nvkm_ram *ram) +{ + if (ram->func->init) + return ram->func->init(ram); + return 0; +} + +void +nvkm_ram_del(struct nvkm_ram **pram) +{ + struct nvkm_ram *ram = *pram; + if (ram && !WARN_ON(!ram->func)) { + if (ram->func->dtor) + *pram = ram->func->dtor(ram); + nvkm_mm_fini(&ram->tags); + nvkm_mm_fini(&ram->vram); + kfree(*pram); + *pram = NULL; + } +} + +int +nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, + enum nvkm_ram_type type, u64 size, u32 tags, + struct nvkm_ram *ram) +{ + static const char *name[] = { + [NVKM_RAM_TYPE_UNKNOWN] = "of unknown memory type", + [NVKM_RAM_TYPE_STOLEN ] = "stolen system memory", + [NVKM_RAM_TYPE_SGRAM ] = "SGRAM", + [NVKM_RAM_TYPE_SDRAM ] = "SDRAM", + [NVKM_RAM_TYPE_DDR1 ] = "DDR1", + [NVKM_RAM_TYPE_DDR2 ] = "DDR2", + [NVKM_RAM_TYPE_DDR3 ] = "DDR3", + [NVKM_RAM_TYPE_GDDR2 ] = "GDDR2", + [NVKM_RAM_TYPE_GDDR3 ] = "GDDR3", + [NVKM_RAM_TYPE_GDDR4 ] = "GDDR4", + [NVKM_RAM_TYPE_GDDR5 ] = "GDDR5", + }; + struct nvkm_subdev *subdev = &fb->subdev; + int ret; + + nvkm_info(subdev, "%d MiB %s\n", (int)(size >> 20), name[type]); + ram->func = func; + ram->fb = fb; + ram->type = type; + ram->size = size; + + if (!nvkm_mm_initialised(&ram->vram)) { + ret = nvkm_mm_init(&ram->vram, 0, size >> NVKM_RAM_MM_SHIFT, 1); + if (ret) + return ret; + } + + if (!nvkm_mm_initialised(&ram->tags)) { + ret = nvkm_mm_init(&ram->tags, 0, tags ? ++tags : 0, 1); + if (ret) + return ret; + + nvkm_debug(subdev, "%d compression tags\n", tags); + } + + return 0; +} + +int +nvkm_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb, + enum nvkm_ram_type type, u64 size, u32 tags, + struct nvkm_ram **pram) +{ + if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL))) + return -ENOMEM; + return nvkm_ram_ctor(func, fb, type, size, tags, *pram); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h new file mode 100644 index 000000000..f816cbf2c --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -0,0 +1,50 @@ +#ifndef __NVKM_FB_RAM_PRIV_H__ +#define __NVKM_FB_RAM_PRIV_H__ +#include "priv.h" + +int nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, + enum nvkm_ram_type, u64 size, u32 tags, + struct nvkm_ram *); +int nvkm_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, + enum nvkm_ram_type, u64 size, u32 tags, + struct nvkm_ram **); +void nvkm_ram_del(struct nvkm_ram **); +int nvkm_ram_init(struct nvkm_ram *); + +extern const struct nvkm_ram_func nv04_ram_func; + +int nv50_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, + struct nvkm_ram *); +int nv50_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); +void nv50_ram_put(struct nvkm_ram *, struct nvkm_mem **); +void __nv50_ram_put(struct nvkm_ram *, struct nvkm_mem *); + +int gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, + u32, struct nvkm_ram *); +int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); +void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **); + +int gk104_ram_init(struct nvkm_ram *ram); + +/* RAM type-specific MR calculation routines */ +int nvkm_sddr2_calc(struct nvkm_ram *); +int nvkm_sddr3_calc(struct nvkm_ram *); +int nvkm_gddr3_calc(struct nvkm_ram *); +int nvkm_gddr5_calc(struct nvkm_ram *, bool nuts); + +int nv04_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv10_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv1a_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv20_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv40_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv41_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv44_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv49_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv4e_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int nv50_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gt215_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int mcp77_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gf100_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gk104_ram_new(struct nvkm_fb *, struct nvkm_ram **); +int gm107_ram_new(struct nvkm_fb *, struct nvkm_ram **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h index f343682b1..9ef9d6aa3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h @@ -1,10 +1,11 @@ #ifndef __NVKM_FBRAM_FUC_H__ #define __NVKM_FBRAM_FUC_H__ +#include #include struct ramfuc { struct nvkm_memx *memx; - struct nvkm_fb *pfb; + struct nvkm_fb *fb; int sequence; }; @@ -54,17 +55,14 @@ ramfuc_reg(u32 addr) } static inline int -ramfuc_init(struct ramfuc *ram, struct nvkm_fb *pfb) +ramfuc_init(struct ramfuc *ram, struct nvkm_fb *fb) { - struct nvkm_pmu *pmu = nvkm_pmu(pfb); - int ret; - - ret = nvkm_memx_init(pmu, &ram->memx); + int ret = nvkm_memx_init(fb->subdev.device->pmu, &ram->memx); if (ret) return ret; ram->sequence++; - ram->pfb = pfb; + ram->fb = fb; return 0; } @@ -72,9 +70,9 @@ static inline int ramfuc_exec(struct ramfuc *ram, bool exec) { int ret = 0; - if (ram->pfb) { + if (ram->fb) { ret = nvkm_memx_fini(&ram->memx, exec); - ram->pfb = NULL; + ram->fb = NULL; } return ret; } @@ -82,8 +80,9 @@ ramfuc_exec(struct ramfuc *ram, bool exec) static inline u32 ramfuc_rd32(struct ramfuc *ram, struct ramfuc_reg *reg) { + struct nvkm_device *device = ram->fb->subdev.device; if (reg->sequence != ram->sequence) - reg->data = nv_rd32(ram->pfb, reg->addr); + reg->data = nvkm_rd32(device, reg->addr); return reg->data; } @@ -144,11 +143,9 @@ ramfuc_train(struct ramfuc *ram) } static inline int -ramfuc_train_result(struct nvkm_fb *pfb, u32 *result, u32 rsize) +ramfuc_train_result(struct nvkm_fb *fb, u32 *result, u32 rsize) { - struct nvkm_pmu *pmu = nvkm_pmu(pfb); - - return nvkm_memx_train_result(pmu, result, rsize); + return nvkm_memx_train_result(fb->subdev.device->pmu, result, rsize); } static inline void diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index de9f39569..772425ca5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -21,10 +21,10 @@ * * Authors: Ben Skeggs */ -#include "gf100.h" +#define gf100_ram(p) container_of((p), struct gf100_ram, base) +#include "ram.h" #include "ramfuc.h" -#include #include #include #include @@ -108,9 +108,10 @@ static void gf100_ram_train(struct gf100_ramfuc *fuc, u32 magic) { struct gf100_ram *ram = container_of(fuc, typeof(*ram), fuc); - struct nvkm_fb *pfb = nvkm_fb(ram); - u32 part = nv_rd32(pfb, 0x022438), i; - u32 mask = nv_rd32(pfb, 0x022554); + struct nvkm_fb *fb = ram->base.fb; + struct nvkm_device *device = fb->subdev.device; + u32 part = nvkm_rd32(device, 0x022438), i; + u32 mask = nvkm_rd32(device, 0x022554); u32 addr = 0x110974; ram_wr32(fuc, 0x10f910, magic); @@ -124,12 +125,14 @@ gf100_ram_train(struct gf100_ramfuc *fuc, u32 magic) } static int -gf100_ram_calc(struct nvkm_fb *pfb, u32 freq) +gf100_ram_calc(struct nvkm_ram *base, u32 freq) { - struct nvkm_clk *clk = nvkm_clk(pfb); - struct nvkm_bios *bios = nvkm_bios(pfb); - struct gf100_ram *ram = (void *)pfb->ram; + struct gf100_ram *ram = gf100_ram(base); struct gf100_ramfuc *fuc = &ram->fuc; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_clk *clk = device->clk; + struct nvkm_bios *bios = device->bios; struct nvbios_ramcfg cfg; u8 ver, cnt, len, strap; struct { @@ -145,37 +148,37 @@ gf100_ram_calc(struct nvkm_fb *pfb, u32 freq) rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size, &cnt, &ramcfg.size, &cfg); if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { - nv_error(pfb, "invalid/missing rammap entry\n"); + nvkm_error(subdev, "invalid/missing rammap entry\n"); return -EINVAL; } /* locate specific data set for the attached memory */ - strap = nvbios_ramcfg_index(nv_subdev(pfb)); + strap = nvbios_ramcfg_index(subdev); if (strap >= cnt) { - nv_error(pfb, "invalid ramcfg strap\n"); + nvkm_error(subdev, "invalid ramcfg strap\n"); return -EINVAL; } ramcfg.data = rammap.data + rammap.size + (strap * ramcfg.size); if (!ramcfg.data || ver != 0x10 || ramcfg.size < 0x0e) { - nv_error(pfb, "invalid/missing ramcfg entry\n"); + nvkm_error(subdev, "invalid/missing ramcfg entry\n"); return -EINVAL; } /* lookup memory timings, if bios says they're present */ - strap = nv_ro08(bios, ramcfg.data + 0x01); + strap = nvbios_rd08(bios, ramcfg.data + 0x01); if (strap != 0xff) { timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size, &cnt, &len); if (!timing.data || ver != 0x10 || timing.size < 0x19) { - nv_error(pfb, "invalid/missing timing entry\n"); + nvkm_error(subdev, "invalid/missing timing entry\n"); return -EINVAL; } } else { timing.data = 0; } - ret = ram_init(fuc, pfb); + ret = ram_init(fuc, ram->base.fb); if (ret) return ret; @@ -184,9 +187,9 @@ gf100_ram_calc(struct nvkm_fb *pfb, u32 freq) /* determine target mclk configuration */ if (!(ram_rd32(fuc, 0x137300) & 0x00000100)) - ref = clk->read(clk, nv_clk_src_sppll0); + ref = nvkm_clk_read(clk, nv_clk_src_sppll0); else - ref = clk->read(clk, nv_clk_src_sppll1); + ref = nvkm_clk_read(clk, nv_clk_src_sppll1); div = max(min((ref * 2) / freq, (u32)65), (u32)2) - 2; out = (ref * 2) / (div + 2); mode = freq != out; @@ -210,10 +213,10 @@ gf100_ram_calc(struct nvkm_fb *pfb, u32 freq) if (mode == 1 && from == 0) { /* calculate refpll */ - ret = gt215_pll_calc(nv_subdev(pfb), &ram->refpll, - ram->mempll.refclk, &N1, NULL, &M1, &P); + ret = gt215_pll_calc(subdev, &ram->refpll, ram->mempll.refclk, + &N1, NULL, &M1, &P); if (ret <= 0) { - nv_error(pfb, "unable to calc refpll\n"); + nvkm_error(subdev, "unable to calc refpll\n"); return ret ? ret : -ERANGE; } @@ -225,10 +228,10 @@ gf100_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_wait(fuc, 0x137390, 0x00020000, 0x00020000, 64000); /* calculate mempll */ - ret = gt215_pll_calc(nv_subdev(pfb), &ram->mempll, freq, + ret = gt215_pll_calc(subdev, &ram->mempll, freq, &N1, NULL, &M1, &P); if (ret <= 0) { - nv_error(pfb, "unable to calc refpll\n"); + nvkm_error(subdev, "unable to calc refpll\n"); return ret ? ret : -ERANGE; } @@ -402,49 +405,48 @@ gf100_ram_calc(struct nvkm_fb *pfb, u32 freq) } static int -gf100_ram_prog(struct nvkm_fb *pfb) +gf100_ram_prog(struct nvkm_ram *base) { - struct nvkm_device *device = nv_device(pfb); - struct gf100_ram *ram = (void *)pfb->ram; - struct gf100_ramfuc *fuc = &ram->fuc; - ram_exec(fuc, nvkm_boolopt(device->cfgopt, "NvMemExec", true)); + struct gf100_ram *ram = gf100_ram(base); + struct nvkm_device *device = ram->base.fb->subdev.device; + ram_exec(&ram->fuc, nvkm_boolopt(device->cfgopt, "NvMemExec", true)); return 0; } static void -gf100_ram_tidy(struct nvkm_fb *pfb) +gf100_ram_tidy(struct nvkm_ram *base) { - struct gf100_ram *ram = (void *)pfb->ram; - struct gf100_ramfuc *fuc = &ram->fuc; - ram_exec(fuc, false); + struct gf100_ram *ram = gf100_ram(base); + ram_exec(&ram->fuc, false); } extern const u8 gf100_pte_storage_type_map[256]; void -gf100_ram_put(struct nvkm_fb *pfb, struct nvkm_mem **pmem) +gf100_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem) { - struct nvkm_ltc *ltc = nvkm_ltc(pfb); + struct nvkm_ltc *ltc = ram->fb->subdev.device->ltc; struct nvkm_mem *mem = *pmem; *pmem = NULL; if (unlikely(mem == NULL)) return; - mutex_lock(&pfb->base.mutex); + mutex_lock(&ram->fb->subdev.mutex); if (mem->tag) - ltc->tags_free(ltc, &mem->tag); - __nv50_ram_put(pfb, mem); - mutex_unlock(&pfb->base.mutex); + nvkm_ltc_tags_free(ltc, &mem->tag); + __nv50_ram_put(ram, mem); + mutex_unlock(&ram->fb->subdev.mutex); kfree(mem); } int -gf100_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, +gf100_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, u32 memtype, struct nvkm_mem **pmem) { - struct nvkm_mm *mm = &pfb->vram; + struct nvkm_ltc *ltc = ram->fb->subdev.device->ltc; + struct nvkm_mm *mm = &ram->vram; struct nvkm_mm_node *r; struct nvkm_mem *mem; int type = (memtype & 0x0ff); @@ -452,9 +454,9 @@ gf100_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, const bool comp = gf100_pte_storage_type_map[type] != type; int ret; - size >>= 12; - align >>= 12; - ncmin >>= 12; + size >>= NVKM_RAM_MM_SHIFT; + align >>= NVKM_RAM_MM_SHIFT; + ncmin >>= NVKM_RAM_MM_SHIFT; if (!ncmin) ncmin = size; @@ -465,14 +467,12 @@ gf100_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, INIT_LIST_HEAD(&mem->regions); mem->size = size; - mutex_lock(&pfb->base.mutex); + mutex_lock(&ram->fb->subdev.mutex); if (comp) { - struct nvkm_ltc *ltc = nvkm_ltc(pfb); - /* compression only works with lpages */ - if (align == (1 << (17 - 12))) { + if (align == (1 << (17 - NVKM_RAM_MM_SHIFT))) { int n = size >> 5; - ltc->tags_alloc(ltc, n, &mem->tag); + nvkm_ltc_tags_alloc(ltc, n, &mem->tag); } if (unlikely(!mem->tag)) @@ -486,178 +486,173 @@ gf100_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, else ret = nvkm_mm_head(mm, 0, 1, size, ncmin, align, &r); if (ret) { - mutex_unlock(&pfb->base.mutex); - pfb->ram->put(pfb, &mem); + mutex_unlock(&ram->fb->subdev.mutex); + ram->func->put(ram, &mem); return ret; } list_add_tail(&r->rl_entry, &mem->regions); size -= r->length; } while (size); - mutex_unlock(&pfb->base.mutex); + mutex_unlock(&ram->fb->subdev.mutex); r = list_first_entry(&mem->regions, struct nvkm_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; + mem->offset = (u64)r->offset << NVKM_RAM_MM_SHIFT; *pmem = mem; return 0; } -int -gf100_ram_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 maskaddr, int size, - void **pobject) +static int +gf100_ram_init(struct nvkm_ram *base) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_bios *bios = nvkm_bios(pfb); - struct nvkm_ram *ram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 parts = nv_rd32(pfb, 0x022438); - u32 pmask = nv_rd32(pfb, maskaddr); - u32 bsize = nv_rd32(pfb, 0x10f20c); - u32 offset, length; - bool uniform = true; - int ret, part; + static const u8 train0[] = { + 0x00, 0xff, 0x55, 0xaa, 0x33, 0xcc, + 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, + }; + static const u32 train1[] = { + 0x00000000, 0xffffffff, + 0x55555555, 0xaaaaaaaa, + 0x33333333, 0xcccccccc, + 0xf0f0f0f0, 0x0f0f0f0f, + 0x00ff00ff, 0xff00ff00, + 0x0000ffff, 0xffff0000, + }; + struct gf100_ram *ram = gf100_ram(base); + struct nvkm_device *device = ram->base.fb->subdev.device; + int i; - ret = nvkm_ram_create_(parent, engine, oclass, size, pobject); - ram = *pobject; - if (ret) - return ret; + switch (ram->base.type) { + case NVKM_RAM_TYPE_GDDR5: + break; + default: + return 0; + } - nv_debug(pfb, "0x100800: 0x%08x\n", nv_rd32(pfb, 0x100800)); - nv_debug(pfb, "parts 0x%08x mask 0x%08x\n", parts, pmask); + /* prepare for ddr link training, and load training patterns */ + for (i = 0; i < 0x30; i++) { + nvkm_wr32(device, 0x10f968, 0x00000000 | (i << 8)); + nvkm_wr32(device, 0x10f96c, 0x00000000 | (i << 8)); + nvkm_wr32(device, 0x10f920, 0x00000100 | train0[i % 12]); + nvkm_wr32(device, 0x10f924, 0x00000100 | train0[i % 12]); + nvkm_wr32(device, 0x10f918, train1[i % 12]); + nvkm_wr32(device, 0x10f91c, train1[i % 12]); + nvkm_wr32(device, 0x10f920, 0x00000000 | train0[i % 12]); + nvkm_wr32(device, 0x10f924, 0x00000000 | train0[i % 12]); + nvkm_wr32(device, 0x10f918, train1[i % 12]); + nvkm_wr32(device, 0x10f91c, train1[i % 12]); + } - ram->type = nvkm_fb_bios_memtype(bios); - ram->ranks = (nv_rd32(pfb, 0x10f200) & 0x00000004) ? 2 : 1; + return 0; +} + +static const struct nvkm_ram_func +gf100_ram_func = { + .init = gf100_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gf100_ram_calc, + .prog = gf100_ram_prog, + .tidy = gf100_ram_tidy, +}; + +int +gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, + u32 maskaddr, struct nvkm_ram *ram) +{ + struct nvkm_subdev *subdev = &fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; + const u32 rsvd_head = ( 256 * 1024); /* vga memory */ + const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ + u32 parts = nvkm_rd32(device, 0x022438); + u32 pmask = nvkm_rd32(device, maskaddr); + u64 bsize = (u64)nvkm_rd32(device, 0x10f20c) << 20; + u64 psize, size = 0; + enum nvkm_ram_type type = nvkm_fb_bios_memtype(bios); + bool uniform = true; + int ret, i; + + nvkm_debug(subdev, "100800: %08x\n", nvkm_rd32(device, 0x100800)); + nvkm_debug(subdev, "parts %08x mask %08x\n", parts, pmask); /* read amount of vram attached to each memory controller */ - for (part = 0; part < parts; part++) { - if (!(pmask & (1 << part))) { - u32 psize = nv_rd32(pfb, 0x11020c + (part * 0x1000)); - if (psize != bsize) { - if (psize < bsize) - bsize = psize; - uniform = false; - } - - nv_debug(pfb, "%d: mem_amount 0x%08x\n", part, psize); - ram->size += (u64)psize << 20; + for (i = 0; i < parts; i++) { + if (pmask & (1 << i)) + continue; + + psize = (u64)nvkm_rd32(device, 0x11020c + (i * 0x1000)) << 20; + if (psize != bsize) { + if (psize < bsize) + bsize = psize; + uniform = false; } + + nvkm_debug(subdev, "%d: %d MiB\n", i, (u32)(psize >> 20)); + size += psize; } + ret = nvkm_ram_ctor(func, fb, type, size, 0, ram); + if (ret) + return ret; + + nvkm_mm_fini(&ram->vram); + /* if all controllers have the same amount attached, there's no holes */ if (uniform) { - offset = rsvd_head; - length = (ram->size >> 12) - rsvd_head - rsvd_tail; - ret = nvkm_mm_init(&pfb->vram, offset, length, 1); + ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + (size - rsvd_head - rsvd_tail) >> + NVKM_RAM_MM_SHIFT, 1); + if (ret) + return ret; } else { /* otherwise, address lowest common amount from 0GiB */ - ret = nvkm_mm_init(&pfb->vram, rsvd_head, - (bsize << 8) * parts - rsvd_head, 1); + ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + ((bsize * parts) - rsvd_head) >> + NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; /* and the rest starting from (8GiB + common_size) */ - offset = (0x0200000000ULL >> 12) + (bsize << 8); - length = (ram->size >> 12) - ((bsize * parts) << 8) - rsvd_tail; - - ret = nvkm_mm_init(&pfb->vram, offset, length, 1); + ret = nvkm_mm_init(&ram->vram, (0x0200000000ULL + bsize) >> + NVKM_RAM_MM_SHIFT, + (size - (bsize * parts) - rsvd_tail) >> + NVKM_RAM_MM_SHIFT, 1); if (ret) - nvkm_mm_fini(&pfb->vram); - } - - if (ret) - return ret; - - ram->get = gf100_ram_get; - ram->put = gf100_ram_put; - return 0; -} - -static int -gf100_ram_init(struct nvkm_object *object) -{ - struct nvkm_fb *pfb = (void *)object->parent; - struct gf100_ram *ram = (void *)object; - int ret, i; - - ret = nvkm_ram_init(&ram->base); - if (ret) - return ret; - - /* prepare for ddr link training, and load training patterns */ - switch (ram->base.type) { - case NV_MEM_TYPE_GDDR5: { - static const u8 train0[] = { - 0x00, 0xff, 0x55, 0xaa, 0x33, 0xcc, - 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, - }; - static const u32 train1[] = { - 0x00000000, 0xffffffff, - 0x55555555, 0xaaaaaaaa, - 0x33333333, 0xcccccccc, - 0xf0f0f0f0, 0x0f0f0f0f, - 0x00ff00ff, 0xff00ff00, - 0x0000ffff, 0xffff0000, - }; - - for (i = 0; i < 0x30; i++) { - nv_wr32(pfb, 0x10f968, 0x00000000 | (i << 8)); - nv_wr32(pfb, 0x10f96c, 0x00000000 | (i << 8)); - nv_wr32(pfb, 0x10f920, 0x00000100 | train0[i % 12]); - nv_wr32(pfb, 0x10f924, 0x00000100 | train0[i % 12]); - nv_wr32(pfb, 0x10f918, train1[i % 12]); - nv_wr32(pfb, 0x10f91c, train1[i % 12]); - nv_wr32(pfb, 0x10f920, 0x00000000 | train0[i % 12]); - nv_wr32(pfb, 0x10f924, 0x00000000 | train0[i % 12]); - nv_wr32(pfb, 0x10f918, train1[i % 12]); - nv_wr32(pfb, 0x10f91c, train1[i % 12]); - } - } break; - default: - break; + return ret; } + ram->ranks = (nvkm_rd32(device, 0x10f200) & 0x00000004) ? 2 : 1; return 0; } -static int -gf100_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_bios *bios = nvkm_bios(parent); + struct nvkm_subdev *subdev = &fb->subdev; + struct nvkm_bios *bios = subdev->device->bios; struct gf100_ram *ram; int ret; - ret = gf100_ram_create(parent, engine, oclass, 0x022554, &ram); - *pobject = nv_object(ram); + if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; + *pram = &ram->base; + + ret = gf100_ram_ctor(&gf100_ram_func, fb, 0x022554, &ram->base); if (ret) return ret; ret = nvbios_pll_parse(bios, 0x0c, &ram->refpll); if (ret) { - nv_error(ram, "mclk refpll data not found\n"); + nvkm_error(subdev, "mclk refpll data not found\n"); return ret; } ret = nvbios_pll_parse(bios, 0x04, &ram->mempll); if (ret) { - nv_error(ram, "mclk pll data not found\n"); + nvkm_error(subdev, "mclk pll data not found\n"); return ret; } - switch (ram->base.type) { - case NV_MEM_TYPE_GDDR5: - ram->base.calc = gf100_ram_calc; - ram->base.prog = gf100_ram_prog; - ram->base.tidy = gf100_ram_tidy; - break; - default: - nv_warn(ram, "reclocking of this ram type unsupported\n"); - return 0; - } - ram->fuc.r_0x10fe20 = ramfuc_reg(0x10fe20); ram->fuc.r_0x10fe24 = ramfuc_reg(0x10fe24); ram->fuc.r_0x137320 = ramfuc_reg(0x137320); @@ -718,14 +713,3 @@ gf100_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->fuc.r_0x13d8f4 = ramfuc_reg(0x13d8f4); return 0; } - -struct nvkm_oclass -gf100_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_ram_ctor, - .dtor = _nvkm_ram_dtor, - .init = gf100_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 1ef15c3e6..9df45030f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -21,10 +21,10 @@ * * Authors: Ben Skeggs */ +#define gk104_ram(p) container_of((p), struct gk104_ram, base) +#include "ram.h" #include "ramfuc.h" -#include "gf100.h" -#include #include #include #include @@ -229,8 +229,9 @@ static void gk104_ram_nuts(struct gk104_ram *ram, struct ramfuc_reg *reg, u32 _mask, u32 _data, u32 _copy) { - struct gk104_fb_priv *priv = (void *)nvkm_fb(ram); + struct nvkm_fb *fb = ram->base.fb; struct ramfuc *fuc = &ram->fuc.base; + struct nvkm_device *device = fb->subdev.device; u32 addr = 0x110000 + (reg->addr & 0xfff); u32 mask = _mask | _copy; u32 data = (_data & _mask) | (reg->data & _copy); @@ -238,7 +239,7 @@ gk104_ram_nuts(struct gk104_ram *ram, struct ramfuc_reg *reg, for (i = 0; i < 16; i++, addr += 0x1000) { if (ram->pnuts & (1 << i)) { - u32 prev = nv_rd32(priv, addr); + u32 prev = nvkm_rd32(device, addr); u32 next = (prev & ~mask) | data; nvkm_memx_wr32(fuc->memx, addr, next); } @@ -248,9 +249,8 @@ gk104_ram_nuts(struct gk104_ram *ram, struct ramfuc_reg *reg, gk104_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c)) static int -gk104_ram_calc_gddr5(struct nvkm_fb *pfb, u32 freq) +gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq) { - struct gk104_ram *ram = (void *)pfb->ram; struct gk104_ramfuc *fuc = &ram->fuc; struct nvkm_ram_data *next = ram->base.next; int vc = !next->bios.ramcfg_11_02_08; @@ -673,10 +673,28 @@ gk104_ram_calc_gddr5(struct nvkm_fb *pfb, u32 freq) * DDR3 ******************************************************************************/ +static void +nvkm_sddr3_dll_reset(struct gk104_ramfuc *fuc) +{ + ram_nuke(fuc, mr[0]); + ram_mask(fuc, mr[0], 0x100, 0x100); + ram_mask(fuc, mr[0], 0x100, 0x000); +} + +static void +nvkm_sddr3_dll_disable(struct gk104_ramfuc *fuc) +{ + u32 mr1_old = ram_rd32(fuc, mr[1]); + + if (!(mr1_old & 0x1)) { + ram_mask(fuc, mr[1], 0x1, 0x1); + ram_nsec(fuc, 1000); + } +} + static int -gk104_ram_calc_sddr3(struct nvkm_fb *pfb, u32 freq) +gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) { - struct gk104_ram *ram = (void *)pfb->ram; struct gk104_ramfuc *fuc = &ram->fuc; const u32 rcoef = (( ram->P1 << 16) | (ram->N1 << 8) | ram->M1); const u32 runk0 = ram->fN1 << 16; @@ -703,6 +721,10 @@ gk104_ram_calc_sddr3(struct nvkm_fb *pfb, u32 freq) ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000); ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ + + if (next->bios.ramcfg_DLLoff) + nvkm_sddr3_dll_disable(fuc); + ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */ ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); @@ -880,17 +902,20 @@ gk104_ram_calc_sddr3(struct nvkm_fb *pfb, u32 freq) ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */ ram_nsec(fuc, 1000); - ram_nuke(fuc, mr[0]); - ram_mask(fuc, mr[0], 0x100, 0x100); - ram_mask(fuc, mr[0], 0x100, 0x000); + if (!next->bios.ramcfg_DLLoff) { + ram_mask(fuc, mr[1], 0x1, 0x0); + nvkm_sddr3_dll_reset(fuc); + } - ram_mask(fuc, mr[2], 0xfff, ram->base.mr[2]); + ram_mask(fuc, mr[2], 0x00000fff, ram->base.mr[2]); + ram_mask(fuc, mr[1], 0xffffffff, ram->base.mr[1]); ram_wr32(fuc, mr[0], ram->base.mr[0]); ram_nsec(fuc, 1000); - ram_nuke(fuc, mr[0]); - ram_mask(fuc, mr[0], 0x100, 0x100); - ram_mask(fuc, mr[0], 0x100, 0x000); + if (!next->bios.ramcfg_DLLoff) { + nvkm_sddr3_dll_reset(fuc); + ram_nsec(fuc, 1000); + } if (vc == 0 && ram_have(fuc, gpio2E)) { u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]); @@ -926,9 +951,9 @@ gk104_ram_calc_sddr3(struct nvkm_fb *pfb, u32 freq) ******************************************************************************/ static int -gk104_ram_calc_data(struct nvkm_fb *pfb, u32 khz, struct nvkm_ram_data *data) +gk104_ram_calc_data(struct gk104_ram *ram, u32 khz, struct nvkm_ram_data *data) { - struct gk104_ram *ram = (void *)pfb->ram; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; struct nvkm_ram_data *cfg; u32 mhz = khz / 1000; @@ -941,19 +966,80 @@ gk104_ram_calc_data(struct nvkm_fb *pfb, u32 khz, struct nvkm_ram_data *data) } } - nv_error(ram, "ramcfg data for %dMHz not found\n", mhz); + nvkm_error(subdev, "ramcfg data for %dMHz not found\n", mhz); return -EINVAL; } static int -gk104_ram_calc_xits(struct nvkm_fb *pfb, struct nvkm_ram_data *next) +gk104_calc_pll_output(int fN, int M, int N, int P, int clk) +{ + return ((clk * N) + (((u16)(fN + 4096) * clk) >> 13)) / (M * P); +} + +static int +gk104_pll_calc_hiclk(int target_khz, int crystal, + int *N1, int *fN1, int *M1, int *P1, + int *N2, int *M2, int *P2) +{ + int best_clk = 0, best_err = target_khz, p_ref, n_ref; + bool upper = false; + + *M1 = 1; + /* M has to be 1, otherwise it gets unstable */ + *M2 = 1; + /* can be 1 or 2, sticking with 1 for simplicity */ + *P2 = 1; + + for (p_ref = 0x7; p_ref >= 0x5; --p_ref) { + for (n_ref = 0x25; n_ref <= 0x2b; ++n_ref) { + int cur_N, cur_clk, cur_err; + + cur_clk = gk104_calc_pll_output(0, 1, n_ref, p_ref, crystal); + cur_N = target_khz / cur_clk; + cur_err = target_khz + - gk104_calc_pll_output(0xf000, 1, cur_N, 1, cur_clk); + + /* we found a better combination */ + if (cur_err < best_err) { + best_err = cur_err; + best_clk = cur_clk; + *N2 = cur_N; + *N1 = n_ref; + *P1 = p_ref; + upper = false; + } + + cur_N += 1; + cur_err = gk104_calc_pll_output(0xf000, 1, cur_N, 1, cur_clk) + - target_khz; + if (cur_err < best_err) { + best_err = cur_err; + best_clk = cur_clk; + *N2 = cur_N; + *N1 = n_ref; + *P1 = p_ref; + upper = true; + } + } + } + + /* adjust fN to get closer to the target clock */ + *fN1 = (u16)((((best_err / *N2 * *P2) * (*P1 * *M1)) << 13) / crystal); + if (upper) + *fN1 = (u16)(1 - *fN1); + + return gk104_calc_pll_output(*fN1, 1, *N1, *P1, crystal); +} + +static int +gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next) { - struct gk104_ram *ram = (void *)pfb->ram; struct gk104_ramfuc *fuc = &ram->fuc; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; int refclk, i; int ret; - ret = ram_init(fuc, pfb); + ret = ram_init(fuc, ram->base.fb); if (ret) return ret; @@ -969,31 +1055,24 @@ gk104_ram_calc_xits(struct nvkm_fb *pfb, struct nvkm_ram_data *next) * kepler boards, no idea how/why they're chosen. */ refclk = next->freq; - if (ram->mode == 2) - refclk = fuc->mempll.refclk; - - /* calculate refpll coefficients */ - ret = gt215_pll_calc(nv_subdev(pfb), &fuc->refpll, refclk, &ram->N1, - &ram->fN1, &ram->M1, &ram->P1); - fuc->mempll.refclk = ret; - if (ret <= 0) { - nv_error(pfb, "unable to calc refpll\n"); - return -EINVAL; - } - - /* calculate mempll coefficients, if we're using it */ if (ram->mode == 2) { - /* post-divider doesn't work... the reg takes the values but - * appears to completely ignore it. there *is* a bit at - * bit 28 that appears to divide the clock by 2 if set. - */ - fuc->mempll.min_p = 1; - fuc->mempll.max_p = 2; - - ret = gt215_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq, - &ram->N2, NULL, &ram->M2, &ram->P2); + ret = gk104_pll_calc_hiclk(next->freq, subdev->device->crystal, + &ram->N1, &ram->fN1, &ram->M1, &ram->P1, + &ram->N2, &ram->M2, &ram->P2); + fuc->mempll.refclk = ret; if (ret <= 0) { - nv_error(pfb, "unable to calc mempll\n"); + nvkm_error(subdev, "unable to calc plls\n"); + return -EINVAL; + } + nvkm_debug(subdev, "sucessfully calced PLLs for clock %i kHz" + " (refclock: %i kHz)\n", next->freq, ret); + } else { + /* calculate refpll coefficients */ + ret = gt215_pll_calc(subdev, &fuc->refpll, refclk, &ram->N1, + &ram->fN1, &ram->M1, &ram->P1); + fuc->mempll.refclk = ret; + if (ret <= 0) { + nvkm_error(subdev, "unable to calc refpll\n"); return -EINVAL; } } @@ -1005,15 +1084,15 @@ gk104_ram_calc_xits(struct nvkm_fb *pfb, struct nvkm_ram_data *next) ram->base.freq = next->freq; switch (ram->base.type) { - case NV_MEM_TYPE_DDR3: + case NVKM_RAM_TYPE_DDR3: ret = nvkm_sddr3_calc(&ram->base); if (ret == 0) - ret = gk104_ram_calc_sddr3(pfb, next->freq); + ret = gk104_ram_calc_sddr3(ram, next->freq); break; - case NV_MEM_TYPE_GDDR5: + case NVKM_RAM_TYPE_GDDR5: ret = nvkm_gddr5_calc(&ram->base, ram->pnuts != 0); if (ret == 0) - ret = gk104_ram_calc_gddr5(pfb, next->freq); + ret = gk104_ram_calc_gddr5(ram, next->freq); break; default: ret = -ENOSYS; @@ -1024,21 +1103,22 @@ gk104_ram_calc_xits(struct nvkm_fb *pfb, struct nvkm_ram_data *next) } static int -gk104_ram_calc(struct nvkm_fb *pfb, u32 freq) +gk104_ram_calc(struct nvkm_ram *base, u32 freq) { - struct nvkm_clk *clk = nvkm_clk(pfb); - struct gk104_ram *ram = (void *)pfb->ram; + struct gk104_ram *ram = gk104_ram(base); + struct nvkm_clk *clk = ram->base.fb->subdev.device->clk; struct nvkm_ram_data *xits = &ram->base.xition; struct nvkm_ram_data *copy; int ret; if (ram->base.next == NULL) { - ret = gk104_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem), + ret = gk104_ram_calc_data(ram, + nvkm_clk_read(clk, nv_clk_src_mem), &ram->base.former); if (ret) return ret; - ret = gk104_ram_calc_data(pfb, freq, &ram->base.target); + ret = gk104_ram_calc_data(ram, freq, &ram->base.target); if (ret) return ret; @@ -1062,13 +1142,13 @@ gk104_ram_calc(struct nvkm_fb *pfb, u32 freq) ram->base.next = &ram->base.target; } - return gk104_ram_calc_xits(pfb, ram->base.next); + return gk104_ram_calc_xits(ram, ram->base.next); } static void -gk104_ram_prog_0(struct nvkm_fb *pfb, u32 freq) +gk104_ram_prog_0(struct gk104_ram *ram, u32 freq) { - struct gk104_ram *ram = (void *)pfb->ram; + struct nvkm_device *device = ram->base.fb->subdev.device; struct nvkm_ram_data *cfg; u32 mhz = freq / 1000; u32 mask, data; @@ -1090,31 +1170,31 @@ gk104_ram_prog_0(struct nvkm_fb *pfb, u32 freq) data |= cfg->bios.rammap_11_09_01ff; mask |= 0x000001ff; } - nv_mask(pfb, 0x10f468, mask, data); + nvkm_mask(device, 0x10f468, mask, data); if (mask = 0, data = 0, ram->diff.rammap_11_0a_0400) { data |= cfg->bios.rammap_11_0a_0400; mask |= 0x00000001; } - nv_mask(pfb, 0x10f420, mask, data); + nvkm_mask(device, 0x10f420, mask, data); if (mask = 0, data = 0, ram->diff.rammap_11_0a_0800) { data |= cfg->bios.rammap_11_0a_0800; mask |= 0x00000001; } - nv_mask(pfb, 0x10f430, mask, data); + nvkm_mask(device, 0x10f430, mask, data); if (mask = 0, data = 0, ram->diff.rammap_11_0b_01f0) { data |= cfg->bios.rammap_11_0b_01f0; mask |= 0x0000001f; } - nv_mask(pfb, 0x10f400, mask, data); + nvkm_mask(device, 0x10f400, mask, data); if (mask = 0, data = 0, ram->diff.rammap_11_0b_0200) { data |= cfg->bios.rammap_11_0b_0200 << 9; mask |= 0x00000200; } - nv_mask(pfb, 0x10f410, mask, data); + nvkm_mask(device, 0x10f410, mask, data); if (mask = 0, data = 0, ram->diff.rammap_11_0d) { data |= cfg->bios.rammap_11_0d << 16; @@ -1124,7 +1204,7 @@ gk104_ram_prog_0(struct nvkm_fb *pfb, u32 freq) data |= cfg->bios.rammap_11_0f << 8; mask |= 0x0000ff00; } - nv_mask(pfb, 0x10f440, mask, data); + nvkm_mask(device, 0x10f440, mask, data); if (mask = 0, data = 0, ram->diff.rammap_11_0e) { data |= cfg->bios.rammap_11_0e << 8; @@ -1138,15 +1218,15 @@ gk104_ram_prog_0(struct nvkm_fb *pfb, u32 freq) data |= cfg->bios.rammap_11_0b_0400 << 5; mask |= 0x00000020; } - nv_mask(pfb, 0x10f444, mask, data); + nvkm_mask(device, 0x10f444, mask, data); } static int -gk104_ram_prog(struct nvkm_fb *pfb) +gk104_ram_prog(struct nvkm_ram *base) { - struct nvkm_device *device = nv_device(pfb); - struct gk104_ram *ram = (void *)pfb->ram; + struct gk104_ram *ram = gk104_ram(base); struct gk104_ramfuc *fuc = &ram->fuc; + struct nvkm_device *device = ram->base.fb->subdev.device; struct nvkm_ram_data *next = ram->base.next; if (!nvkm_boolopt(device->cfgopt, "NvMemExec", true)) { @@ -1154,20 +1234,19 @@ gk104_ram_prog(struct nvkm_fb *pfb) return (ram->base.next == &ram->base.xition); } - gk104_ram_prog_0(pfb, 1000); + gk104_ram_prog_0(ram, 1000); ram_exec(fuc, true); - gk104_ram_prog_0(pfb, next->freq); + gk104_ram_prog_0(ram, next->freq); return (ram->base.next == &ram->base.xition); } static void -gk104_ram_tidy(struct nvkm_fb *pfb) +gk104_ram_tidy(struct nvkm_ram *base) { - struct gk104_ram *ram = (void *)pfb->ram; - struct gk104_ramfuc *fuc = &ram->fuc; + struct gk104_ram *ram = gk104_ram(base); ram->base.next = NULL; - ram_exec(fuc, false); + ram_exec(&ram->fuc, false); } struct gk104_ram_train { @@ -1183,10 +1262,10 @@ struct gk104_ram_train { }; static int -gk104_ram_train_type(struct nvkm_fb *pfb, int i, u8 ramcfg, +gk104_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg, struct gk104_ram_train *train) { - struct nvkm_bios *bios = nvkm_bios(pfb); + struct nvkm_bios *bios = ram->fb->subdev.device->bios; struct nvbios_M0205E M0205E; struct nvbios_M0205S M0205S; struct nvbios_M0209E M0209E; @@ -1244,33 +1323,35 @@ gk104_ram_train_type(struct nvkm_fb *pfb, int i, u8 ramcfg, } static int -gk104_ram_train_init_0(struct nvkm_fb *pfb, struct gk104_ram_train *train) +gk104_ram_train_init_0(struct nvkm_ram *ram, struct gk104_ram_train *train) { + struct nvkm_subdev *subdev = &ram->fb->subdev; + struct nvkm_device *device = subdev->device; int i, j; if ((train->mask & 0x03d3) != 0x03d3) { - nv_warn(pfb, "missing link training data\n"); + nvkm_warn(subdev, "missing link training data\n"); return -EINVAL; } for (i = 0; i < 0x30; i++) { for (j = 0; j < 8; j += 4) { - nv_wr32(pfb, 0x10f968 + j, 0x00000000 | (i << 8)); - nv_wr32(pfb, 0x10f920 + j, 0x00000000 | + nvkm_wr32(device, 0x10f968 + j, 0x00000000 | (i << 8)); + nvkm_wr32(device, 0x10f920 + j, 0x00000000 | train->type08.data[i] << 4 | train->type06.data[i]); - nv_wr32(pfb, 0x10f918 + j, train->type00.data[i]); - nv_wr32(pfb, 0x10f920 + j, 0x00000100 | + nvkm_wr32(device, 0x10f918 + j, train->type00.data[i]); + nvkm_wr32(device, 0x10f920 + j, 0x00000100 | train->type09.data[i] << 4 | train->type07.data[i]); - nv_wr32(pfb, 0x10f918 + j, train->type01.data[i]); + nvkm_wr32(device, 0x10f918 + j, train->type01.data[i]); } } for (j = 0; j < 8; j += 4) { for (i = 0; i < 0x100; i++) { - nv_wr32(pfb, 0x10f968 + j, i); - nv_wr32(pfb, 0x10f900 + j, train->type04.data[i]); + nvkm_wr32(device, 0x10f968 + j, i); + nvkm_wr32(device, 0x10f900 + j, train->type04.data[i]); } } @@ -1278,23 +1359,24 @@ gk104_ram_train_init_0(struct nvkm_fb *pfb, struct gk104_ram_train *train) } static int -gk104_ram_train_init(struct nvkm_fb *pfb) +gk104_ram_train_init(struct nvkm_ram *ram) { - u8 ramcfg = nvbios_ramcfg_index(nv_subdev(pfb)); + u8 ramcfg = nvbios_ramcfg_index(&ram->fb->subdev); struct gk104_ram_train *train; - int ret = -ENOMEM, i; + int ret, i; - if ((train = kzalloc(sizeof(*train), GFP_KERNEL))) { - for (i = 0; i < 0x100; i++) { - ret = gk104_ram_train_type(pfb, i, ramcfg, train); - if (ret && ret != -ENOENT) - break; - } + if (!(train = kzalloc(sizeof(*train), GFP_KERNEL))) + return -ENOMEM; + + for (i = 0; i < 0x100; i++) { + ret = gk104_ram_train_type(ram, i, ramcfg, train); + if (ret && ret != -ENOENT) + break; } - switch (pfb->ram->type) { - case NV_MEM_TYPE_GDDR5: - ret = gk104_ram_train_init_0(pfb, train); + switch (ram->type) { + case NVKM_RAM_TYPE_GDDR5: + ret = gk104_ram_train_init_0(ram, train); break; default: ret = 0; @@ -1306,18 +1388,14 @@ gk104_ram_train_init(struct nvkm_fb *pfb) } int -gk104_ram_init(struct nvkm_object *object) +gk104_ram_init(struct nvkm_ram *ram) { - struct nvkm_fb *pfb = (void *)object->parent; - struct gk104_ram *ram = (void *)object; - struct nvkm_bios *bios = nvkm_bios(pfb); + struct nvkm_subdev *subdev = &ram->fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; u8 ver, hdr, cnt, len, snr, ssz; u32 data, save; - int ret, i; - - ret = nvkm_ram_init(&ram->base); - if (ret) - return ret; + int i; /* run a bunch of tables from rammap table. there's actually * individual pointers for each rammap entry too, but, nvidia @@ -1334,33 +1412,32 @@ gk104_ram_init(struct nvkm_object *object) if (!data || hdr < 0x15) return -EINVAL; - cnt = nv_ro08(bios, data + 0x14); /* guess at count */ - data = nv_ro32(bios, data + 0x10); /* guess u32... */ - save = nv_rd32(pfb, 0x10f65c) & 0x000000f0; + cnt = nvbios_rd08(bios, data + 0x14); /* guess at count */ + data = nvbios_rd32(bios, data + 0x10); /* guess u32... */ + save = nvkm_rd32(device, 0x10f65c) & 0x000000f0; for (i = 0; i < cnt; i++, data += 4) { if (i != save >> 4) { - nv_mask(pfb, 0x10f65c, 0x000000f0, i << 4); + nvkm_mask(device, 0x10f65c, 0x000000f0, i << 4); nvbios_exec(&(struct nvbios_init) { - .subdev = nv_subdev(pfb), + .subdev = subdev, .bios = bios, - .offset = nv_ro32(bios, data), + .offset = nvbios_rd32(bios, data), .execute = 1, }); } } - nv_mask(pfb, 0x10f65c, 0x000000f0, save); - nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000); - nv_wr32(pfb, 0x10ecc0, 0xffffffff); - nv_mask(pfb, 0x10f160, 0x00000010, 0x00000010); + nvkm_mask(device, 0x10f65c, 0x000000f0, save); + nvkm_mask(device, 0x10f584, 0x11000000, 0x00000000); + nvkm_wr32(device, 0x10ecc0, 0xffffffff); + nvkm_mask(device, 0x10f160, 0x00000010, 0x00000010); - return gk104_ram_train_init(pfb); + return gk104_ram_train_init(ram); } static int gk104_ram_ctor_data(struct gk104_ram *ram, u8 ramcfg, int i) { - struct nvkm_fb *pfb = (void *)nv_object(ram)->parent; - struct nvkm_bios *bios = nvkm_bios(pfb); + struct nvkm_bios *bios = ram->base.fb->subdev.device->bios; struct nvkm_ram_data *cfg; struct nvbios_ramcfg *d = &ram->diff; struct nvbios_ramcfg *p, *n; @@ -1426,63 +1503,64 @@ done: return ret; } -static void -gk104_ram_dtor(struct nvkm_object *object) +static void * +gk104_ram_dtor(struct nvkm_ram *base) { - struct gk104_ram *ram = (void *)object; + struct gk104_ram *ram = gk104_ram(base); struct nvkm_ram_data *cfg, *tmp; list_for_each_entry_safe(cfg, tmp, &ram->cfg, head) { kfree(cfg); } - nvkm_ram_destroy(&ram->base); + return ram; } -static int -gk104_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_ram_func +gk104_ram_func = { + .dtor = gk104_ram_dtor, + .init = gk104_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, + .calc = gk104_ram_calc, + .prog = gk104_ram_prog, + .tidy = gk104_ram_tidy, +}; + +int +gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_bios *bios = nvkm_bios(pfb); - struct nvkm_gpio *gpio = nvkm_gpio(pfb); + struct nvkm_subdev *subdev = &fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; + struct nvkm_gpio *gpio = device->gpio; struct dcb_gpio_func func; struct gk104_ram *ram; int ret, i; - u8 ramcfg = nvbios_ramcfg_index(nv_subdev(pfb)); + u8 ramcfg = nvbios_ramcfg_index(subdev); u32 tmp; - ret = gf100_ram_create(parent, engine, oclass, 0x022554, &ram); - *pobject = nv_object(ram); + if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; + *pram = &ram->base; + + ret = gf100_ram_ctor(&gk104_ram_func, fb, 0x022554, &ram->base); if (ret) return ret; INIT_LIST_HEAD(&ram->cfg); - switch (ram->base.type) { - case NV_MEM_TYPE_DDR3: - case NV_MEM_TYPE_GDDR5: - ram->base.calc = gk104_ram_calc; - ram->base.prog = gk104_ram_prog; - ram->base.tidy = gk104_ram_tidy; - break; - default: - nv_warn(pfb, "reclocking of this RAM type is unsupported\n"); - break; - } - /* calculate a mask of differently configured memory partitions, * because, of course reclocking wasn't complicated enough * already without having to treat some of them differently to * the others.... */ - ram->parts = nv_rd32(pfb, 0x022438); - ram->pmask = nv_rd32(pfb, 0x022554); + ram->parts = nvkm_rd32(device, 0x022438); + ram->pmask = nvkm_rd32(device, 0x022554); ram->pnuts = 0; for (i = 0, tmp = 0; i < ram->parts; i++) { if (!(ram->pmask & (1 << i))) { - u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000)); + u32 cfg1 = nvkm_rd32(device, 0x110204 + (i * 0x1000)); if (tmp && tmp != cfg1) { ram->pnuts |= (1 << i); continue; @@ -1505,7 +1583,7 @@ gk104_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, for (i = 0; !ret; i++) { ret = gk104_ram_ctor_data(ram, ramcfg, i); if (ret && ret != -ENOENT) { - nv_error(pfb, "failed to parse ramcfg data\n"); + nvkm_error(subdev, "failed to parse ramcfg data\n"); return ret; } } @@ -1513,25 +1591,25 @@ gk104_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, /* parse bios data for both pll's */ ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll); if (ret) { - nv_error(pfb, "mclk refpll data not found\n"); + nvkm_error(subdev, "mclk refpll data not found\n"); return ret; } ret = nvbios_pll_parse(bios, 0x04, &ram->fuc.mempll); if (ret) { - nv_error(pfb, "mclk pll data not found\n"); + nvkm_error(subdev, "mclk pll data not found\n"); return ret; } /* lookup memory voltage gpios */ - ret = gpio->find(gpio, 0, 0x18, DCB_GPIO_UNUSED, &func); + ret = nvkm_gpio_find(gpio, 0, 0x18, DCB_GPIO_UNUSED, &func); if (ret == 0) { ram->fuc.r_gpioMV = ramfuc_reg(0x00d610 + (func.line * 0x04)); ram->fuc.r_funcMV[0] = (func.log[0] ^ 2) << 12; ram->fuc.r_funcMV[1] = (func.log[1] ^ 2) << 12; } - ret = gpio->find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); + ret = nvkm_gpio_find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); if (ret == 0) { ram->fuc.r_gpio2E = ramfuc_reg(0x00d610 + (func.line * 0x04)); ram->fuc.r_func2E[0] = (func.log[0] ^ 2) << 12; @@ -1588,7 +1666,7 @@ gk104_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->fuc.r_0x10f914 = ramfuc_reg(0x10f914); switch (ram->base.type) { - case NV_MEM_TYPE_GDDR5: + case NVKM_RAM_TYPE_GDDR5: ram->fuc.r_mr[0] = ramfuc_reg(0x10f300); ram->fuc.r_mr[1] = ramfuc_reg(0x10f330); ram->fuc.r_mr[2] = ramfuc_reg(0x10f334); @@ -1600,8 +1678,9 @@ gk104_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->fuc.r_mr[8] = ramfuc_reg(0x10f354); ram->fuc.r_mr[15] = ramfuc_reg(0x10f34c); break; - case NV_MEM_TYPE_DDR3: + case NVKM_RAM_TYPE_DDR3: ram->fuc.r_mr[0] = ramfuc_reg(0x10f300); + ram->fuc.r_mr[1] = ramfuc_reg(0x10f304); ram->fuc.r_mr[2] = ramfuc_reg(0x10f320); break; default: @@ -1626,14 +1705,3 @@ gk104_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->fuc.r_0x100750 = ramfuc_reg(0x100750); return 0; } - -struct nvkm_oclass -gk104_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_ram_ctor, - .dtor = gk104_ram_dtor, - .init = gk104_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c index a298b39f5..43d807f6c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c @@ -21,35 +21,20 @@ * * Authors: Ben Skeggs */ -#include "gf100.h" +#include "ram.h" -struct gm107_ram { - struct nvkm_ram base; +static const struct nvkm_ram_func +gm107_ram_func = { + .init = gk104_ram_init, + .get = gf100_ram_get, + .put = gf100_ram_put, }; -static int -gm107_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gm107_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct gm107_ram *ram; - int ret; + if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL))) + return -ENOMEM; - ret = gf100_ram_create(parent, engine, oclass, 0x021c14, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; - - return 0; + return gf100_ram_ctor(&gm107_ram_func, fb, 0x021c14, *pram); } - -struct nvkm_oclass -gm107_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm107_ram_ctor, - .dtor = _nvkm_ram_dtor, - .init = gk104_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c index 24176401b..d15ea886d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c @@ -22,11 +22,10 @@ * Authors: Ben Skeggs * Roy Spliet */ - +#define gt215_ram(p) container_of((p), struct gt215_ram, base) +#include "ram.h" #include "ramfuc.h" -#include "nv50.h" -#include #include #include #include @@ -35,9 +34,6 @@ #include #include -/* XXX: Remove when memx gains GPIO support */ -extern int nv50_gpio_location(int line, u32 *reg, u32 *shift); - struct gt215_ramfuc { struct ramfuc base; struct ramfuc_reg r_0x001610; @@ -76,7 +72,7 @@ struct gt215_ramfuc { struct ramfuc_reg r_0x111400; struct ramfuc_reg r_0x611200; struct ramfuc_reg r_mr[4]; - struct ramfuc_reg r_gpioFBVREF; + struct ramfuc_reg r_gpio[4]; }; struct gt215_ltrain { @@ -154,14 +150,14 @@ gt215_link_train_calc(u32 *vals, struct gt215_ltrain *train) * Link training for (at least) DDR3 */ int -gt215_link_train(struct nvkm_fb *pfb) +gt215_link_train(struct gt215_ram *ram) { - struct nvkm_bios *bios = nvkm_bios(pfb); - struct gt215_ram *ram = (void *)pfb->ram; - struct nvkm_clk *clk = nvkm_clk(pfb); struct gt215_ltrain *train = &ram->ltrain; - struct nvkm_device *device = nv_device(pfb); struct gt215_ramfuc *fuc = &ram->fuc; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; + struct nvkm_clk *clk = device->clk; u32 *result, r1700; int ret, i; struct nvbios_M0205T M0205T = { 0 }; @@ -182,27 +178,29 @@ gt215_link_train(struct nvkm_fb *pfb) /* Clock speeds for training and back */ nvbios_M0205Tp(bios, &ver, &hdr, &cnt, &len, &snr, &ssz, &M0205T); - if (M0205T.freq == 0) + if (M0205T.freq == 0) { + kfree(result); return -ENOENT; + } - clk_current = clk->read(clk, nv_clk_src_mem); + clk_current = nvkm_clk_read(clk, nv_clk_src_mem); ret = gt215_clk_pre(clk, f); if (ret) goto out; /* First: clock up/down */ - ret = ram->base.calc(pfb, (u32) M0205T.freq * 1000); + ret = ram->base.func->calc(&ram->base, (u32) M0205T.freq * 1000); if (ret) goto out; /* Do this *after* calc, eliminates write in script */ - nv_wr32(pfb, 0x111400, 0x00000000); + nvkm_wr32(device, 0x111400, 0x00000000); /* XXX: Magic writes that improve train reliability? */ - nv_mask(pfb, 0x100674, 0x0000ffff, 0x00000000); - nv_mask(pfb, 0x1005e4, 0x0000ffff, 0x00000000); - nv_mask(pfb, 0x100b0c, 0x000000ff, 0x00000000); - nv_wr32(pfb, 0x100c04, 0x00000400); + nvkm_mask(device, 0x100674, 0x0000ffff, 0x00000000); + nvkm_mask(device, 0x1005e4, 0x0000ffff, 0x00000000); + nvkm_mask(device, 0x100b0c, 0x000000ff, 0x00000000); + nvkm_wr32(device, 0x100c04, 0x00000400); /* Now the training script */ r1700 = ram_rd32(fuc, 0x001700); @@ -235,22 +233,22 @@ gt215_link_train(struct nvkm_fb *pfb) ram_exec(fuc, true); - ram->base.calc(pfb, clk_current); + ram->base.func->calc(&ram->base, clk_current); ram_exec(fuc, true); /* Post-processing, avoids flicker */ - nv_mask(pfb, 0x616308, 0x10, 0x10); - nv_mask(pfb, 0x616b08, 0x10, 0x10); + nvkm_mask(device, 0x616308, 0x10, 0x10); + nvkm_mask(device, 0x616b08, 0x10, 0x10); gt215_clk_post(clk, f); - ram_train_result(pfb, result, 64); + ram_train_result(ram->base.fb, result, 64); for (i = 0; i < 64; i++) - nv_debug(pfb, "Train: %08x", result[i]); + nvkm_debug(subdev, "Train: %08x", result[i]); gt215_link_train_calc(result, train); - nv_debug(pfb, "Train: %08x %08x %08x", train->r_100720, - train->r_1111e0, train->r_111400); + nvkm_debug(subdev, "Train: %08x %08x %08x", train->r_100720, + train->r_1111e0, train->r_111400); kfree(result); @@ -265,11 +263,12 @@ out: train->state = NVA3_TRAIN_UNSUPPORTED; gt215_clk_post(clk, f); + kfree(result); return ret; } int -gt215_link_train_init(struct nvkm_fb *pfb) +gt215_link_train_init(struct gt215_ram *ram) { static const u32 pattern[16] = { 0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee, @@ -277,9 +276,9 @@ gt215_link_train_init(struct nvkm_fb *pfb) 0x33333333, 0x55555555, 0x77777777, 0x66666666, 0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb, }; - struct nvkm_bios *bios = nvkm_bios(pfb); - struct gt215_ram *ram = (void *)pfb->ram; struct gt215_ltrain *train = &ram->ltrain; + struct nvkm_device *device = ram->base.fb->subdev.device; + struct nvkm_bios *bios = device->bios; struct nvkm_mem *mem; struct nvbios_M0205E M0205E; u8 ver, hdr, cnt, len; @@ -298,48 +297,47 @@ gt215_link_train_init(struct nvkm_fb *pfb) train->state = NVA3_TRAIN_ONCE; - ret = pfb->ram->get(pfb, 0x8000, 0x10000, 0, 0x800, &ram->ltrain.mem); + ret = ram->base.func->get(&ram->base, 0x8000, 0x10000, 0, 0x800, + &ram->ltrain.mem); if (ret) return ret; mem = ram->ltrain.mem; - nv_wr32(pfb, 0x100538, 0x10000000 | (mem->offset >> 16)); - nv_wr32(pfb, 0x1005a8, 0x0000ffff); - nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001); + nvkm_wr32(device, 0x100538, 0x10000000 | (mem->offset >> 16)); + nvkm_wr32(device, 0x1005a8, 0x0000ffff); + nvkm_mask(device, 0x10f800, 0x00000001, 0x00000001); for (i = 0; i < 0x30; i++) { - nv_wr32(pfb, 0x10f8c0, (i << 8) | i); - nv_wr32(pfb, 0x10f900, pattern[i % 16]); + nvkm_wr32(device, 0x10f8c0, (i << 8) | i); + nvkm_wr32(device, 0x10f900, pattern[i % 16]); } for (i = 0; i < 0x30; i++) { - nv_wr32(pfb, 0x10f8e0, (i << 8) | i); - nv_wr32(pfb, 0x10f920, pattern[i % 16]); + nvkm_wr32(device, 0x10f8e0, (i << 8) | i); + nvkm_wr32(device, 0x10f920, pattern[i % 16]); } /* And upload the pattern */ - r001700 = nv_rd32(pfb, 0x1700); - nv_wr32(pfb, 0x1700, mem->offset >> 16); + r001700 = nvkm_rd32(device, 0x1700); + nvkm_wr32(device, 0x1700, mem->offset >> 16); for (i = 0; i < 16; i++) - nv_wr32(pfb, 0x700000 + (i << 2), pattern[i]); + nvkm_wr32(device, 0x700000 + (i << 2), pattern[i]); for (i = 0; i < 16; i++) - nv_wr32(pfb, 0x700100 + (i << 2), pattern[i]); - nv_wr32(pfb, 0x1700, r001700); + nvkm_wr32(device, 0x700100 + (i << 2), pattern[i]); + nvkm_wr32(device, 0x1700, r001700); - train->r_100720 = nv_rd32(pfb, 0x100720); - train->r_1111e0 = nv_rd32(pfb, 0x1111e0); - train->r_111400 = nv_rd32(pfb, 0x111400); + train->r_100720 = nvkm_rd32(device, 0x100720); + train->r_1111e0 = nvkm_rd32(device, 0x1111e0); + train->r_111400 = nvkm_rd32(device, 0x111400); return 0; } void -gt215_link_train_fini(struct nvkm_fb *pfb) +gt215_link_train_fini(struct gt215_ram *ram) { - struct gt215_ram *ram = (void *)pfb->ram; - if (ram->ltrain.mem) - pfb->ram->put(pfb, &ram->ltrain.mem); + ram->base.func->put(&ram->base, &ram->ltrain.mem); } /* @@ -347,24 +345,25 @@ gt215_link_train_fini(struct nvkm_fb *pfb) */ #define T(t) cfg->timing_10_##t static int -gt215_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing) +gt215_ram_timing_calc(struct gt215_ram *ram, u32 *timing) { - struct gt215_ram *ram = (void *)pfb->ram; struct nvbios_ramcfg *cfg = &ram->base.target.bios; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; int tUNK_base, tUNK_40_0, prevCL; u32 cur2, cur3, cur7, cur8; - cur2 = nv_rd32(pfb, 0x100228); - cur3 = nv_rd32(pfb, 0x10022c); - cur7 = nv_rd32(pfb, 0x10023c); - cur8 = nv_rd32(pfb, 0x100240); + cur2 = nvkm_rd32(device, 0x100228); + cur3 = nvkm_rd32(device, 0x10022c); + cur7 = nvkm_rd32(device, 0x10023c); + cur8 = nvkm_rd32(device, 0x100240); switch ((!T(CWL)) * ram->base.type) { - case NV_MEM_TYPE_DDR2: + case NVKM_RAM_TYPE_DDR2: T(CWL) = T(CL) - 1; break; - case NV_MEM_TYPE_GDDR3: + case NVKM_RAM_TYPE_GDDR3: T(CWL) = ((cur2 & 0xff000000) >> 24) + 1; break; } @@ -402,8 +401,8 @@ gt215_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing) timing[8] = cur8 & 0xffffff00; switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: - case NV_MEM_TYPE_GDDR3: + case NVKM_RAM_TYPE_DDR2: + case NVKM_RAM_TYPE_GDDR3: tUNK_40_0 = prevCL - (cur8 & 0xff); if (tUNK_40_0 > 0) timing[8] |= T(CL); @@ -412,11 +411,11 @@ gt215_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing) break; } - nv_debug(pfb, "Entry: 220: %08x %08x %08x %08x\n", - timing[0], timing[1], timing[2], timing[3]); - nv_debug(pfb, " 230: %08x %08x %08x %08x\n", - timing[4], timing[5], timing[6], timing[7]); - nv_debug(pfb, " 240: %08x\n", timing[8]); + nvkm_debug(subdev, "Entry: 220: %08x %08x %08x %08x\n", + timing[0], timing[1], timing[2], timing[3]); + nvkm_debug(subdev, " 230: %08x %08x %08x %08x\n", + timing[4], timing[5], timing[6], timing[7]); + nvkm_debug(subdev, " 240: %08x\n", timing[8]); return 0; } #undef T @@ -464,36 +463,42 @@ gt215_ram_lock_pll(struct gt215_ramfuc *fuc, struct gt215_clk_info *mclk) } static void -gt215_ram_fbvref(struct gt215_ramfuc *fuc, u32 val) +gt215_ram_gpio(struct gt215_ramfuc *fuc, u8 tag, u32 val) { - struct nvkm_gpio *gpio = nvkm_gpio(fuc->base.pfb); + struct nvkm_gpio *gpio = fuc->base.fb->subdev.device->gpio; struct dcb_gpio_func func; u32 reg, sh, gpio_val; int ret; - if (gpio->get(gpio, 0, 0x2e, DCB_GPIO_UNUSED) != val) { - ret = gpio->find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); + if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) { + ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func); if (ret) return; - nv50_gpio_location(func.line, ®, &sh); - gpio_val = ram_rd32(fuc, gpioFBVREF); + reg = func.line >> 3; + sh = (func.line & 0x7) << 2; + gpio_val = ram_rd32(fuc, gpio[reg]); if (gpio_val & (8 << sh)) val = !val; + if (!(func.log[1] & 1)) + val = !val; - ram_mask(fuc, gpioFBVREF, (0x3 << sh), ((val | 0x2) << sh)); + ram_mask(fuc, gpio[reg], (0x3 << sh), ((val | 0x2) << sh)); ram_nsec(fuc, 20000); } } static int -gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) +gt215_ram_calc(struct nvkm_ram *base, u32 freq) { - struct nvkm_bios *bios = nvkm_bios(pfb); - struct gt215_ram *ram = (void *)pfb->ram; + struct gt215_ram *ram = gt215_ram(base); struct gt215_ramfuc *fuc = &ram->fuc; struct gt215_ltrain *train = &ram->ltrain; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct gt215_clk_info mclk; + struct nvkm_gpio *gpio = device->gpio; struct nvkm_ram_data *next; u8 ver, hdr, cnt, len, strap; u32 data; @@ -508,28 +513,27 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) ram->base.next = next; if (ram->ltrain.state == NVA3_TRAIN_ONCE) - gt215_link_train(pfb); + gt215_link_train(ram); /* lookup memory config data relevant to the target frequency */ - i = 0; data = nvbios_rammapEm(bios, freq / 1000, &ver, &hdr, &cnt, &len, &next->bios); if (!data || ver != 0x10 || hdr < 0x05) { - nv_error(pfb, "invalid/missing rammap entry\n"); + nvkm_error(subdev, "invalid/missing rammap entry\n"); return -EINVAL; } /* locate specific data set for the attached memory */ - strap = nvbios_ramcfg_index(nv_subdev(pfb)); + strap = nvbios_ramcfg_index(subdev); if (strap >= cnt) { - nv_error(pfb, "invalid ramcfg strap\n"); + nvkm_error(subdev, "invalid ramcfg strap\n"); return -EINVAL; } data = nvbios_rammapSp(bios, data, ver, hdr, cnt, len, strap, &ver, &hdr, &next->bios); if (!data || ver != 0x10 || hdr < 0x09) { - nv_error(pfb, "invalid/missing ramcfg entry\n"); + nvkm_error(subdev, "invalid/missing ramcfg entry\n"); return -EINVAL; } @@ -539,20 +543,20 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) &ver, &hdr, &cnt, &len, &next->bios); if (!data || ver != 0x10 || hdr < 0x17) { - nv_error(pfb, "invalid/missing timing entry\n"); + nvkm_error(subdev, "invalid/missing timing entry\n"); return -EINVAL; } } - ret = gt215_pll_info(nvkm_clk(pfb), 0x12, 0x4000, freq, &mclk); + ret = gt215_pll_info(device->clk, 0x12, 0x4000, freq, &mclk); if (ret < 0) { - nv_error(pfb, "failed mclk calculation\n"); + nvkm_error(subdev, "failed mclk calculation\n"); return ret; } - gt215_ram_timing_calc(pfb, timing); + gt215_ram_timing_calc(ram, timing); - ret = ram_init(fuc, pfb); + ret = ram_init(fuc, ram->base.fb); if (ret) return ret; @@ -562,13 +566,13 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) ram->base.mr[2] = ram_rd32(fuc, mr[2]); switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: + case NVKM_RAM_TYPE_DDR2: ret = nvkm_sddr2_calc(&ram->base); break; - case NV_MEM_TYPE_DDR3: + case NVKM_RAM_TYPE_DDR3: ret = nvkm_sddr3_calc(&ram->base); break; - case NV_MEM_TYPE_GDDR3: + case NVKM_RAM_TYPE_GDDR3: ret = nvkm_gddr3_calc(&ram->base); break; default: @@ -579,7 +583,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) if (ret) return ret; - /* XXX: where the fuck does 750MHz come from? */ + /* XXX: 750MHz seems rather arbitrary */ if (freq <= 750000) { r004018 = 0x10000000; r100760 = 0x22222222; @@ -590,7 +594,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) r100da0 = 0x00000000; } - if (!next->bios.ramcfg_10_DLLoff) + if (!next->bios.ramcfg_DLLoff) r004018 |= 0x00004000; /* pll2pll requires to switch to a safe clock first */ @@ -623,24 +627,24 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_nsec(fuc, 2000); if (!next->bios.ramcfg_10_02_10) { - if (ram->base.type == NV_MEM_TYPE_GDDR3) + if (ram->base.type == NVKM_RAM_TYPE_GDDR3) ram_mask(fuc, 0x111100, 0x04020000, 0x00020000); else ram_mask(fuc, 0x111100, 0x04020000, 0x04020000); } /* If we're disabling the DLL, do it now */ - switch (next->bios.ramcfg_10_DLLoff * ram->base.type) { - case NV_MEM_TYPE_DDR3: + switch (next->bios.ramcfg_DLLoff * ram->base.type) { + case NVKM_RAM_TYPE_DDR3: nvkm_sddr3_dll_disable(fuc, ram->base.mr); break; - case NV_MEM_TYPE_GDDR3: + case NVKM_RAM_TYPE_GDDR3: nvkm_gddr3_dll_disable(fuc, ram->base.mr); break; } - if (fuc->r_gpioFBVREF.addr && next->bios.timing_10_ODT) - gt215_ram_fbvref(fuc, 0); + if (next->bios.timing_10_ODT) + gt215_ram_gpio(fuc, 0x2e, 1); /* Brace RAM for impact */ ram_wr32(fuc, 0x1002d4, 0x00000001); @@ -650,9 +654,26 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_wr32(fuc, 0x1002dc, 0x00000001); ram_nsec(fuc, 2000); - if (nv_device(pfb)->chipset == 0xa3 && freq <= 500000) + if (device->chipset == 0xa3 && freq <= 500000) ram_mask(fuc, 0x100700, 0x00000006, 0x00000006); + /* Alter FBVDD/Q, apparently must be done with PLL disabled, thus + * set it to bypass */ + if (nvkm_gpio_get(gpio, 0, 0x18, DCB_GPIO_UNUSED) == + next->bios.ramcfg_FBVDDQ) { + data = ram_rd32(fuc, 0x004000) & 0x9; + + if (data == 0x1) + ram_mask(fuc, 0x004000, 0x8, 0x8); + if (data & 0x1) + ram_mask(fuc, 0x004000, 0x1, 0x0); + + gt215_ram_gpio(fuc, 0x18, !next->bios.ramcfg_FBVDDQ); + + if (data & 0x1) + ram_mask(fuc, 0x004000, 0x1, 0x1); + } + /* Fiddle with clocks */ /* There's 4 scenario's * pll->pll: first switch to a 324MHz clock, set up new PLL, switch @@ -708,7 +729,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_mask(fuc, 0x1007e0, 0x22222222, r100760); } - if (nv_device(pfb)->chipset == 0xa3 && freq > 500000) { + if (device->chipset == 0xa3 && freq > 500000) { ram_mask(fuc, 0x100700, 0x00000006, 0x00000000); } @@ -750,39 +771,43 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100; r111100 = ram_rd32(fuc, 0x111100) & ~0x3a800000; - if (next->bios.ramcfg_10_02_04) { - switch (ram->base.type) { - case NV_MEM_TYPE_DDR3: - if (nv_device(pfb)->chipset != 0xa8) - r111100 |= 0x00000004; - /* no break */ - case NV_MEM_TYPE_DDR2: - r111100 |= 0x08000000; - break; - default: - break; - } - } else { - switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: - r111100 |= 0x1a800000; + /* NVA8 seems to skip various bits related to ramcfg_10_02_04 */ + if (device->chipset == 0xa8) { + r111100 |= 0x08000000; + if (!next->bios.ramcfg_10_02_04) unk714 |= 0x00000010; - break; - case NV_MEM_TYPE_DDR3: - if (nv_device(pfb)->chipset == 0xa8) { - r111100 |= 0x08000000; - } else { - r111100 &= ~0x00000004; + } else { + if (next->bios.ramcfg_10_02_04) { + switch (ram->base.type) { + case NVKM_RAM_TYPE_DDR2: + case NVKM_RAM_TYPE_DDR3: + r111100 &= ~0x00000020; + if (next->bios.ramcfg_10_02_10) + r111100 |= 0x08000004; + else + r111100 |= 0x00000024; + break; + default: + break; + } + } else { + switch (ram->base.type) { + case NVKM_RAM_TYPE_DDR2: + case NVKM_RAM_TYPE_DDR3: + r111100 &= ~0x00000024; r111100 |= 0x12800000; + + if (next->bios.ramcfg_10_02_10) + r111100 |= 0x08000000; + unk714 |= 0x00000010; + break; + case NVKM_RAM_TYPE_GDDR3: + r111100 |= 0x30000000; + unk714 |= 0x00000020; + break; + default: + break; } - unk714 |= 0x00000010; - break; - case NV_MEM_TYPE_GDDR3: - r111100 |= 0x30000000; - unk714 |= 0x00000020; - break; - default: - break; } } @@ -806,20 +831,20 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_mask(fuc, 0x100718, 0xffffffff, unk718); ram_mask(fuc, 0x111100, 0xffffffff, r111100); - if (fuc->r_gpioFBVREF.addr && !next->bios.timing_10_ODT) - gt215_ram_fbvref(fuc, 1); + if (!next->bios.timing_10_ODT) + gt215_ram_gpio(fuc, 0x2e, 0); /* Reset DLL */ - if (!next->bios.ramcfg_10_DLLoff) + if (!next->bios.ramcfg_DLLoff) nvkm_sddr2_dll_reset(fuc); - if (ram->base.type == NV_MEM_TYPE_GDDR3) { + if (ram->base.type == NVKM_RAM_TYPE_GDDR3) { ram_nsec(fuc, 31000); } else { ram_nsec(fuc, 14000); } - if (ram->base.type == NV_MEM_TYPE_DDR3) { + if (ram->base.type == NVKM_RAM_TYPE_DDR3) { ram_wr32(fuc, 0x100264, 0x1); ram_nsec(fuc, 2000); } @@ -855,24 +880,24 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) } static int -gt215_ram_prog(struct nvkm_fb *pfb) +gt215_ram_prog(struct nvkm_ram *base) { - struct nvkm_device *device = nv_device(pfb); - struct gt215_ram *ram = (void *)pfb->ram; + struct gt215_ram *ram = gt215_ram(base); struct gt215_ramfuc *fuc = &ram->fuc; + struct nvkm_device *device = ram->base.fb->subdev.device; bool exec = nvkm_boolopt(device->cfgopt, "NvMemExec", true); if (exec) { - nv_mask(pfb, 0x001534, 0x2, 0x2); + nvkm_mask(device, 0x001534, 0x2, 0x2); ram_exec(fuc, true); /* Post-processing, avoids flicker */ - nv_mask(pfb, 0x002504, 0x1, 0x0); - nv_mask(pfb, 0x001534, 0x2, 0x0); + nvkm_mask(device, 0x002504, 0x1, 0x0); + nvkm_mask(device, 0x001534, 0x2, 0x0); - nv_mask(pfb, 0x616308, 0x10, 0x10); - nv_mask(pfb, 0x616b08, 0x10, 0x10); + nvkm_mask(device, 0x616308, 0x10, 0x10); + nvkm_mask(device, 0x616b08, 0x10, 0x10); } else { ram_exec(fuc, false); } @@ -880,69 +905,53 @@ gt215_ram_prog(struct nvkm_fb *pfb) } static void -gt215_ram_tidy(struct nvkm_fb *pfb) +gt215_ram_tidy(struct nvkm_ram *base) { - struct gt215_ram *ram = (void *)pfb->ram; - struct gt215_ramfuc *fuc = &ram->fuc; - ram_exec(fuc, false); + struct gt215_ram *ram = gt215_ram(base); + ram_exec(&ram->fuc, false); } static int -gt215_ram_init(struct nvkm_object *object) +gt215_ram_init(struct nvkm_ram *base) { - struct nvkm_fb *pfb = (void *)object->parent; - struct gt215_ram *ram = (void *)object; - int ret; - - ret = nvkm_ram_init(&ram->base); - if (ret) - return ret; - - gt215_link_train_init(pfb); + struct gt215_ram *ram = gt215_ram(base); + gt215_link_train_init(ram); return 0; } -static int -gt215_ram_fini(struct nvkm_object *object, bool suspend) +static void * +gt215_ram_dtor(struct nvkm_ram *base) { - struct nvkm_fb *pfb = (void *)object->parent; - - if (!suspend) - gt215_link_train_fini(pfb); - - return 0; + struct gt215_ram *ram = gt215_ram(base); + gt215_link_train_fini(ram); + return ram; } -static int -gt215_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 datasize, - struct nvkm_object **pobject) +static const struct nvkm_ram_func +gt215_ram_func = { + .dtor = gt215_ram_dtor, + .init = gt215_ram_init, + .get = nv50_ram_get, + .put = nv50_ram_put, + .calc = gt215_ram_calc, + .prog = gt215_ram_prog, + .tidy = gt215_ram_tidy, +}; + +int +gt215_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_gpio *gpio = nvkm_gpio(pfb); - struct dcb_gpio_func func; struct gt215_ram *ram; int ret, i; - u32 reg, shift; - ret = nv50_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); + if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; + *pram = &ram->base; + + ret = nv50_ram_ctor(>215_ram_func, fb, &ram->base); if (ret) return ret; - switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: - case NV_MEM_TYPE_DDR3: - case NV_MEM_TYPE_GDDR3: - ram->base.calc = gt215_ram_calc; - ram->base.prog = gt215_ram_prog; - ram->base.tidy = gt215_ram_tidy; - break; - default: - nv_warn(ram, "reclocking of this ram type unsupported\n"); - return 0; - } - ram->fuc.r_0x001610 = ramfuc_reg(0x001610); ram->fuc.r_0x001700 = ramfuc_reg(0x001700); ram->fuc.r_0x002504 = ramfuc_reg(0x002504); @@ -991,22 +1000,10 @@ gt215_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->fuc.r_mr[2] = ramfuc_reg(0x1002e0); ram->fuc.r_mr[3] = ramfuc_reg(0x1002e4); } - - ret = gpio->find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); - if (ret == 0) { - nv50_gpio_location(func.line, ®, &shift); - ram->fuc.r_gpioFBVREF = ramfuc_reg(reg); - } + ram->fuc.r_gpio[0] = ramfuc_reg(0x00e104); + ram->fuc.r_gpio[1] = ramfuc_reg(0x00e108); + ram->fuc.r_gpio[2] = ramfuc_reg(0x00e120); + ram->fuc.r_gpio[3] = ramfuc_reg(0x00e124); return 0; } - -struct nvkm_oclass -gt215_ram_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt215_ram_ctor, - .dtor = _nvkm_ram_dtor, - .init = gt215_ram_init, - .fini = gt215_ram_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c index abc18e89a..0a0e44b75 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c @@ -21,81 +21,67 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#define mcp77_ram(p) container_of((p), struct mcp77_ram, base) +#include "ram.h" -struct mcp77_ram_priv { +struct mcp77_ram { struct nvkm_ram base; u64 poller_base; }; static int -mcp77_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 datasize, - struct nvkm_object **pobject) +mcp77_ram_init(struct nvkm_ram *base) { - u32 rsvd_head = ( 256 * 1024); /* vga memory */ - u32 rsvd_tail = (1024 * 1024); /* vbios etc */ - struct nvkm_fb *pfb = nvkm_fb(parent); - struct mcp77_ram_priv *priv; - int ret; - - ret = nvkm_ram_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.type = NV_MEM_TYPE_STOLEN; - priv->base.stolen = (u64)nv_rd32(pfb, 0x100e10) << 12; - priv->base.size = (u64)nv_rd32(pfb, 0x100e14) << 12; + struct mcp77_ram *ram = mcp77_ram(base); + struct nvkm_device *device = ram->base.fb->subdev.device; + u32 dniso = ((ram->base.size - (ram->poller_base + 0x00)) >> 5) - 1; + u32 hostnb = ((ram->base.size - (ram->poller_base + 0x20)) >> 5) - 1; + u32 flush = ((ram->base.size - (ram->poller_base + 0x40)) >> 5) - 1; - rsvd_tail += 0x1000; - priv->poller_base = priv->base.size - rsvd_tail; - - ret = nvkm_mm_init(&pfb->vram, rsvd_head >> 12, - (priv->base.size - (rsvd_head + rsvd_tail)) >> 12, - 1); - if (ret) - return ret; - - priv->base.get = nv50_ram_get; - priv->base.put = nv50_ram_put; + /* Enable NISO poller for various clients and set their associated + * read address, only for MCP77/78 and MCP79/7A. (fd#25701) + */ + nvkm_wr32(device, 0x100c18, dniso); + nvkm_mask(device, 0x100c14, 0x00000000, 0x00000001); + nvkm_wr32(device, 0x100c1c, hostnb); + nvkm_mask(device, 0x100c14, 0x00000000, 0x00000002); + nvkm_wr32(device, 0x100c24, flush); + nvkm_mask(device, 0x100c14, 0x00000000, 0x00010000); return 0; } -static int -mcp77_ram_init(struct nvkm_object *object) +static const struct nvkm_ram_func +mcp77_ram_func = { + .init = mcp77_ram_init, + .get = nv50_ram_get, + .put = nv50_ram_put, +}; + +int +mcp77_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(object); - struct mcp77_ram_priv *priv = (void *)object; + struct nvkm_device *device = fb->subdev.device; + u32 rsvd_head = ( 256 * 1024); /* vga memory */ + u32 rsvd_tail = (1024 * 1024) + 0x1000; /* vbios etc + poller mem */ + u64 base = (u64)nvkm_rd32(device, 0x100e10) << 12; + u64 size = (u64)nvkm_rd32(device, 0x100e14) << 12; + struct mcp77_ram *ram; int ret; - u64 dniso, hostnb, flush; - ret = nvkm_ram_init(&priv->base); + if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; + *pram = &ram->base; + + ret = nvkm_ram_ctor(&mcp77_ram_func, fb, NVKM_RAM_TYPE_STOLEN, + size, 0, &ram->base); if (ret) return ret; - dniso = ((priv->base.size - (priv->poller_base + 0x00)) >> 5) - 1; - hostnb = ((priv->base.size - (priv->poller_base + 0x20)) >> 5) - 1; - flush = ((priv->base.size - (priv->poller_base + 0x40)) >> 5) - 1; + ram->poller_base = size - rsvd_tail; + ram->base.stolen = base; + nvkm_mm_fini(&ram->base.vram); - /* Enable NISO poller for various clients and set their associated - * read address, only for MCP77/78 and MCP79/7A. (fd#25701) - */ - nv_wr32(pfb, 0x100c18, dniso); - nv_mask(pfb, 0x100c14, 0x00000000, 0x00000001); - nv_wr32(pfb, 0x100c1c, hostnb); - nv_mask(pfb, 0x100c14, 0x00000000, 0x00000002); - nv_wr32(pfb, 0x100c24, flush); - nv_mask(pfb, 0x100c14, 0x00000000, 0x00010000); - return 0; + return nvkm_mm_init(&ram->base.vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + (size - rsvd_head - rsvd_tail) >> + NVKM_RAM_MM_SHIFT, 1); } - -struct nvkm_oclass -mcp77_ram_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = mcp77_ram_ctor, - .dtor = _nvkm_ram_dtor, - .init = mcp77_ram_init, - .fini = _nvkm_ram_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c index 855de1617..6f053a03d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c @@ -21,59 +21,45 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ram.h" #include "regsnv04.h" -static int -nv04_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ram *ram; - u32 boot0 = nv_rd32(pfb, NV04_PFB_BOOT_0); - int ret; +const struct nvkm_ram_func +nv04_ram_func = { +}; - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; +int +nv04_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + struct nvkm_device *device = fb->subdev.device; + u32 boot0 = nvkm_rd32(device, NV04_PFB_BOOT_0); + u64 size; + enum nvkm_ram_type type; if (boot0 & 0x00000100) { - ram->size = ((boot0 >> 12) & 0xf) * 2 + 2; - ram->size *= 1024 * 1024; + size = ((boot0 >> 12) & 0xf) * 2 + 2; + size *= 1024 * 1024; } else { switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: - ram->size = 32 * 1024 * 1024; + size = 32 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: - ram->size = 16 * 1024 * 1024; + size = 16 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: - ram->size = 8 * 1024 * 1024; + size = 8 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: - ram->size = 4 * 1024 * 1024; + size = 4 * 1024 * 1024; break; } } if ((boot0 & 0x00000038) <= 0x10) - ram->type = NV_MEM_TYPE_SGRAM; + type = NVKM_RAM_TYPE_SGRAM; else - ram->type = NV_MEM_TYPE_SDRAM; + type = NVKM_RAM_TYPE_SDRAM; - return 0; + return nvkm_ram_new_(&nv04_ram_func, fb, type, size, 0, pram); } - -struct nvkm_oclass -nv04_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c index 3b8a1eda5..dfd155c98 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c @@ -21,39 +21,20 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ram.h" -static int -nv10_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv10_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ram *ram; - u32 cfg0 = nv_rd32(pfb, 0x100200); - int ret; - - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; + struct nvkm_device *device = fb->subdev.device; + u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; + u32 cfg0 = nvkm_rd32(device, 0x100200); + enum nvkm_ram_type type; if (cfg0 & 0x00000001) - ram->type = NV_MEM_TYPE_DDR1; + type = NVKM_RAM_TYPE_DDR1; else - ram->type = NV_MEM_TYPE_SDRAM; + type = NVKM_RAM_TYPE_SDRAM; - ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; - return 0; + return nvkm_ram_new_(&nv04_ram_func, fb, type, size, 0, pram); } - -struct nvkm_oclass -nv10_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c index fbae05db4..3c6a8710e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c @@ -21,33 +21,21 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ram.h" -#include - -static int -nv1a_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv1a_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ram *ram; struct pci_dev *bridge; u32 mem, mib; - int ret; bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); if (!bridge) { - nv_fatal(pfb, "no bridge device\n"); + nvkm_error(&fb->subdev, "no bridge device\n"); return -ENODEV; } - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; - - if (nv_device(pfb)->chipset == 0x1a) { + if (fb->subdev.device->chipset == 0x1a) { pci_read_config_dword(bridge, 0x7c, &mem); mib = ((mem >> 6) & 31) + 1; } else { @@ -55,18 +43,6 @@ nv1a_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, mib = ((mem >> 4) & 127) + 1; } - ram->type = NV_MEM_TYPE_STOLEN; - ram->size = mib * 1024 * 1024; - return 0; + return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_STOLEN, + mib * 1024 * 1024, 0, pram); } - -struct nvkm_oclass -nv1a_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv1a_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c index d9e7187bd..747e47c10 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c @@ -21,42 +21,29 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ram.h" -static int -nv20_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv20_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ram *ram; - u32 pbus1218 = nv_rd32(pfb, 0x001218); + struct nvkm_device *device = fb->subdev.device; + u32 pbus1218 = nvkm_rd32(device, 0x001218); + u32 size = (nvkm_rd32(device, 0x10020c) & 0xff000000); + u32 tags = nvkm_rd32(device, 0x100320); + enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); + switch (pbus1218 & 0x00000300) { + case 0x00000000: type = NVKM_RAM_TYPE_SDRAM; break; + case 0x00000100: type = NVKM_RAM_TYPE_DDR1 ; break; + case 0x00000200: type = NVKM_RAM_TYPE_GDDR3; break; + case 0x00000300: type = NVKM_RAM_TYPE_GDDR2; break; + } + + ret = nvkm_ram_new_(&nv04_ram_func, fb, type, size, tags, pram); if (ret) return ret; - switch (pbus1218 & 0x00000300) { - case 0x00000000: ram->type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: ram->type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: ram->type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: ram->type = NV_MEM_TYPE_GDDR2; break; - } - ram->size = (nv_rd32(pfb, 0x10020c) & 0xff000000); - ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; - ram->tags = nv_rd32(pfb, 0x100320); + (*pram)->parts = (nvkm_rd32(device, 0x100200) & 0x00000003) + 1; return 0; } - -struct nvkm_oclass -nv20_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv20_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c index 3d31fa45c..56f8cffc2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c @@ -21,9 +21,8 @@ * * Authors: Ben Skeggs */ -#include "nv40.h" +#include "ramnv40.h" -#include #include #include #include @@ -31,23 +30,23 @@ #include #include -int -nv40_ram_calc(struct nvkm_fb *pfb, u32 freq) +static int +nv40_ram_calc(struct nvkm_ram *base, u32 freq) { - struct nvkm_bios *bios = nvkm_bios(pfb); - struct nv40_ram *ram = (void *)pfb->ram; + struct nv40_ram *ram = nv40_ram(base); + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvbios_pll pll; int N1, M1, N2, M2; int log2P, ret; ret = nvbios_pll_parse(bios, 0x04, &pll); if (ret) { - nv_error(pfb, "mclk pll data not found\n"); + nvkm_error(subdev, "mclk pll data not found\n"); return ret; } - ret = nv04_pll_calc(nv_subdev(pfb), &pll, freq, - &N1, &M1, &N2, &M2, &log2P); + ret = nv04_pll_calc(subdev, &pll, freq, &N1, &M1, &N2, &M2, &log2P); if (ret < 0) return ret; @@ -64,11 +63,13 @@ nv40_ram_calc(struct nvkm_fb *pfb, u32 freq) return 0; } -int -nv40_ram_prog(struct nvkm_fb *pfb) +static int +nv40_ram_prog(struct nvkm_ram *base) { - struct nvkm_bios *bios = nvkm_bios(pfb); - struct nv40_ram *ram = (void *)pfb->ram; + struct nv40_ram *ram = nv40_ram(base); + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_bios *bios = device->bios; struct bit_entry M; u32 crtc_mask = 0; u8 sr1[2]; @@ -76,12 +77,12 @@ nv40_ram_prog(struct nvkm_fb *pfb) /* determine which CRTCs are active, fetch VGA_SR1 for each */ for (i = 0; i < 2; i++) { - u32 vbl = nv_rd32(pfb, 0x600808 + (i * 0x2000)); + u32 vbl = nvkm_rd32(device, 0x600808 + (i * 0x2000)); u32 cnt = 0; do { - if (vbl != nv_rd32(pfb, 0x600808 + (i * 0x2000))) { - nv_wr08(pfb, 0x0c03c4 + (i * 0x2000), 0x01); - sr1[i] = nv_rd08(pfb, 0x0c03c5 + (i * 0x2000)); + if (vbl != nvkm_rd32(device, 0x600808 + (i * 0x2000))) { + nvkm_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); + sr1[i] = nvkm_rd08(device, 0x0c03c5 + (i * 0x2000)); if (!(sr1[i] & 0x20)) crtc_mask |= (1 << i); break; @@ -94,55 +95,66 @@ nv40_ram_prog(struct nvkm_fb *pfb) for (i = 0; i < 2; i++) { if (!(crtc_mask & (1 << i))) continue; - nv_wait(pfb, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); - nv_wait(pfb, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); - nv_wr08(pfb, 0x0c03c4 + (i * 0x2000), 0x01); - nv_wr08(pfb, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); + + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x600808 + (i * 0x2000)); + if (!(tmp & 0x00010000)) + break; + ); + + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x600808 + (i * 0x2000)); + if ( (tmp & 0x00010000)) + break; + ); + + nvkm_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); + nvkm_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); } /* prepare ram for reclocking */ - nv_wr32(pfb, 0x1002d4, 0x00000001); /* precharge */ - nv_wr32(pfb, 0x1002d0, 0x00000001); /* refresh */ - nv_wr32(pfb, 0x1002d0, 0x00000001); /* refresh */ - nv_mask(pfb, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ - nv_wr32(pfb, 0x1002dc, 0x00000001); /* enable self-refresh */ + nvkm_wr32(device, 0x1002d4, 0x00000001); /* precharge */ + nvkm_wr32(device, 0x1002d0, 0x00000001); /* refresh */ + nvkm_wr32(device, 0x1002d0, 0x00000001); /* refresh */ + nvkm_mask(device, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ + nvkm_wr32(device, 0x1002dc, 0x00000001); /* enable self-refresh */ /* change the PLL of each memory partition */ - nv_mask(pfb, 0x00c040, 0x0000c000, 0x00000000); - switch (nv_device(pfb)->chipset) { + nvkm_mask(device, 0x00c040, 0x0000c000, 0x00000000); + switch (device->chipset) { case 0x40: case 0x45: case 0x41: case 0x42: case 0x47: - nv_mask(pfb, 0x004044, 0xc0771100, ram->ctrl); - nv_mask(pfb, 0x00402c, 0xc0771100, ram->ctrl); - nv_wr32(pfb, 0x004048, ram->coef); - nv_wr32(pfb, 0x004030, ram->coef); + nvkm_mask(device, 0x004044, 0xc0771100, ram->ctrl); + nvkm_mask(device, 0x00402c, 0xc0771100, ram->ctrl); + nvkm_wr32(device, 0x004048, ram->coef); + nvkm_wr32(device, 0x004030, ram->coef); case 0x43: case 0x49: case 0x4b: - nv_mask(pfb, 0x004038, 0xc0771100, ram->ctrl); - nv_wr32(pfb, 0x00403c, ram->coef); + nvkm_mask(device, 0x004038, 0xc0771100, ram->ctrl); + nvkm_wr32(device, 0x00403c, ram->coef); default: - nv_mask(pfb, 0x004020, 0xc0771100, ram->ctrl); - nv_wr32(pfb, 0x004024, ram->coef); + nvkm_mask(device, 0x004020, 0xc0771100, ram->ctrl); + nvkm_wr32(device, 0x004024, ram->coef); break; } udelay(100); - nv_mask(pfb, 0x00c040, 0x0000c000, 0x0000c000); + nvkm_mask(device, 0x00c040, 0x0000c000, 0x0000c000); /* re-enable normal operation of memory controller */ - nv_wr32(pfb, 0x1002dc, 0x00000000); - nv_mask(pfb, 0x100210, 0x80000000, 0x80000000); + nvkm_wr32(device, 0x1002dc, 0x00000000); + nvkm_mask(device, 0x100210, 0x80000000, 0x80000000); udelay(100); /* execute memory reset script from vbios */ if (!bit_entry(bios, 'M', &M)) { struct nvbios_init init = { - .subdev = nv_subdev(pfb), + .subdev = subdev, .bios = bios, - .offset = nv_ro16(bios, M.offset + 0x00), + .offset = nvbios_rd16(bios, M.offset + 0x00), .execute = 1, }; @@ -155,58 +167,64 @@ nv40_ram_prog(struct nvkm_fb *pfb) for (i = 0; i < 2; i++) { if (!(crtc_mask & (1 << i))) continue; - nv_wait(pfb, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); - nv_wr08(pfb, 0x0c03c4 + (i * 0x2000), 0x01); - nv_wr08(pfb, 0x0c03c5 + (i * 0x2000), sr1[i]); + + nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x600808 + (i * 0x2000)); + if ( (tmp & 0x00010000)) + break; + ); + + nvkm_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); + nvkm_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i]); } return 0; } -void -nv40_ram_tidy(struct nvkm_fb *pfb) +static void +nv40_ram_tidy(struct nvkm_ram *base) { } -static int -nv40_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_ram_func +nv40_ram_func = { + .calc = nv40_ram_calc, + .prog = nv40_ram_prog, + .tidy = nv40_ram_tidy, +}; + +int +nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type type, u64 size, + u32 tags, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); struct nv40_ram *ram; - u32 pbus1218 = nv_rd32(pfb, 0x001218); - int ret; + if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; + *pram = &ram->base; + return nvkm_ram_ctor(&nv40_ram_func, fb, type, size, tags, &ram->base); +} - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; +int +nv40_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) +{ + struct nvkm_device *device = fb->subdev.device; + u32 pbus1218 = nvkm_rd32(device, 0x001218); + u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; + u32 tags = nvkm_rd32(device, 0x100320); + enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; + int ret; switch (pbus1218 & 0x00000300) { - case 0x00000000: ram->base.type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: ram->base.type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: ram->base.type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: ram->base.type = NV_MEM_TYPE_DDR2; break; + case 0x00000000: type = NVKM_RAM_TYPE_SDRAM; break; + case 0x00000100: type = NVKM_RAM_TYPE_DDR1 ; break; + case 0x00000200: type = NVKM_RAM_TYPE_GDDR3; break; + case 0x00000300: type = NVKM_RAM_TYPE_DDR2 ; break; } - ram->base.size = nv_rd32(pfb, 0x10020c) & 0xff000000; - ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; - ram->base.tags = nv_rd32(pfb, 0x100320); - ram->base.calc = nv40_ram_calc; - ram->base.prog = nv40_ram_prog; - ram->base.tidy = nv40_ram_tidy; + ret = nv40_ram_new_(fb, type, size, tags, pram); + if (ret) + return ret; + + (*pram)->parts = (nvkm_rd32(device, 0x100200) & 0x00000003) + 1; return 0; } - - -struct nvkm_oclass -nv40_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h new file mode 100644 index 000000000..8a0524566 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h @@ -0,0 +1,14 @@ +#ifndef __NV40_FB_RAM_H__ +#define __NV40_FB_RAM_H__ +#define nv40_ram(p) container_of((p), struct nv40_ram, base) +#include "ram.h" + +struct nv40_ram { + struct nvkm_ram base; + u32 ctrl; + u32 coef; +}; + +int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type, u64, u32, + struct nvkm_ram **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c index 33c612b13..114828be2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c @@ -21,46 +21,29 @@ * * Authors: Ben Skeggs */ -#include "nv40.h" +#include "ramnv40.h" -static int -nv41_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv41_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nv40_ram *ram; - u32 pfb474 = nv_rd32(pfb, 0x100474); + struct nvkm_device *device = fb->subdev.device; + u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; + u32 tags = nvkm_rd32(device, 0x100320); + u32 fb474 = nvkm_rd32(device, 0x100474); + enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); + if (fb474 & 0x00000004) + type = NVKM_RAM_TYPE_GDDR3; + if (fb474 & 0x00000002) + type = NVKM_RAM_TYPE_DDR2; + if (fb474 & 0x00000001) + type = NVKM_RAM_TYPE_DDR1; + + ret = nv40_ram_new_(fb, type, size, tags, pram); if (ret) return ret; - if (pfb474 & 0x00000004) - ram->base.type = NV_MEM_TYPE_GDDR3; - if (pfb474 & 0x00000002) - ram->base.type = NV_MEM_TYPE_DDR2; - if (pfb474 & 0x00000001) - ram->base.type = NV_MEM_TYPE_DDR1; - - ram->base.size = nv_rd32(pfb, 0x10020c) & 0xff000000; - ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; - ram->base.tags = nv_rd32(pfb, 0x100320); - ram->base.calc = nv40_ram_calc; - ram->base.prog = nv40_ram_prog; - ram->base.tidy = nv40_ram_tidy; + (*pram)->parts = (nvkm_rd32(device, 0x100200) & 0x00000003) + 1; return 0; } - -struct nvkm_oclass -nv41_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv41_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c index f575a7246..bc56fbf1c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c @@ -21,44 +21,22 @@ * * Authors: Ben Skeggs */ -#include "nv40.h" +#include "ramnv40.h" -static int -nv44_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv44_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nv40_ram *ram; - u32 pfb474 = nv_rd32(pfb, 0x100474); - int ret; + struct nvkm_device *device = fb->subdev.device; + u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; + u32 fb474 = nvkm_rd32(device, 0x100474); + enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; + if (fb474 & 0x00000004) + type = NVKM_RAM_TYPE_GDDR3; + if (fb474 & 0x00000002) + type = NVKM_RAM_TYPE_DDR2; + if (fb474 & 0x00000001) + type = NVKM_RAM_TYPE_DDR1; - if (pfb474 & 0x00000004) - ram->base.type = NV_MEM_TYPE_GDDR3; - if (pfb474 & 0x00000002) - ram->base.type = NV_MEM_TYPE_DDR2; - if (pfb474 & 0x00000001) - ram->base.type = NV_MEM_TYPE_DDR1; - - ram->base.size = nv_rd32(pfb, 0x10020c) & 0xff000000; - ram->base.calc = nv40_ram_calc; - ram->base.prog = nv40_ram_prog; - ram->base.tidy = nv40_ram_tidy; - return 0; + return nv40_ram_new_(fb, type, size, 0, pram); } - -struct nvkm_oclass -nv44_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv44_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c index 51b44cdb2..c01f4b102 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c @@ -21,46 +21,29 @@ * * Authors: Ben Skeggs */ -#include "nv40.h" +#include "ramnv40.h" -static int -nv49_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv49_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nv40_ram *ram; - u32 pfb914 = nv_rd32(pfb, 0x100914); + struct nvkm_device *device = fb->subdev.device; + u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; + u32 tags = nvkm_rd32(device, 0x100320); + u32 fb914 = nvkm_rd32(device, 0x100914); + enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; - - switch (pfb914 & 0x00000003) { - case 0x00000000: ram->base.type = NV_MEM_TYPE_DDR1; break; - case 0x00000001: ram->base.type = NV_MEM_TYPE_DDR2; break; - case 0x00000002: ram->base.type = NV_MEM_TYPE_GDDR3; break; + switch (fb914 & 0x00000003) { + case 0x00000000: type = NVKM_RAM_TYPE_DDR1 ; break; + case 0x00000001: type = NVKM_RAM_TYPE_DDR2 ; break; + case 0x00000002: type = NVKM_RAM_TYPE_GDDR3; break; case 0x00000003: break; } - ram->base.size = nv_rd32(pfb, 0x10020c) & 0xff000000; - ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; - ram->base.tags = nv_rd32(pfb, 0x100320); - ram->base.calc = nv40_ram_calc; - ram->base.prog = nv40_ram_prog; - ram->base.tidy = nv40_ram_tidy; + ret = nv40_ram_new_(fb, type, size, tags, pram); + if (ret) + return ret; + + (*pram)->parts = (nvkm_rd32(device, 0x100200) & 0x00000003) + 1; return 0; } - -struct nvkm_oclass -nv49_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv49_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c index f3ed1c60d..fa3c2e062 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c @@ -21,34 +21,13 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ram.h" -static int -nv4e_ram_create(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv4e_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ram *ram; - int ret; - - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; - - ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; - ram->type = NV_MEM_TYPE_STOLEN; - return 0; + struct nvkm_device *device = fb->subdev.device; + u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; + return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_UNKNOWN, + size, 0, pram); } - -struct nvkm_oclass -nv4e_ram_oclass = { - .handle = 0, - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv4e_ram_create, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index d2c81dd63..87bde8ff2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c @@ -21,16 +21,19 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#define nv50_ram(p) container_of((p), struct nv50_ram, base) +#include "ram.h" #include "ramseq.h" +#include "nv50.h" -#include #include #include #include #include +#include #include #include +#include struct nv50_ramseq { struct hwsq base; @@ -38,16 +41,26 @@ struct nv50_ramseq { struct hwsq_reg r_0x004008; struct hwsq_reg r_0x00400c; struct hwsq_reg r_0x00c040; + struct hwsq_reg r_0x100200; struct hwsq_reg r_0x100210; + struct hwsq_reg r_0x10021c; struct hwsq_reg r_0x1002d0; struct hwsq_reg r_0x1002d4; struct hwsq_reg r_0x1002dc; - struct hwsq_reg r_0x100da0[8]; + struct hwsq_reg r_0x10053c; + struct hwsq_reg r_0x1005a0; + struct hwsq_reg r_0x1005a4; + struct hwsq_reg r_0x100710; + struct hwsq_reg r_0x100714; + struct hwsq_reg r_0x100718; + struct hwsq_reg r_0x10071c; + struct hwsq_reg r_0x100da0; struct hwsq_reg r_0x100e20; struct hwsq_reg r_0x100e24; struct hwsq_reg r_0x611200; struct hwsq_reg r_timing[9]; struct hwsq_reg r_mr[4]; + struct hwsq_reg r_gpio[4]; }; struct nv50_ram { @@ -55,71 +68,256 @@ struct nv50_ram { struct nv50_ramseq hwsq; }; -#define QFX5800NVA0 1 +#define T(t) cfg->timing_10_##t +static int +nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing) +{ + struct nvbios_ramcfg *cfg = &ram->base.target.bios; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; + u32 cur2, cur4, cur7, cur8; + u8 unkt3b; + + cur2 = nvkm_rd32(device, 0x100228); + cur4 = nvkm_rd32(device, 0x100230); + cur7 = nvkm_rd32(device, 0x10023c); + cur8 = nvkm_rd32(device, 0x100240); + + switch ((!T(CWL)) * ram->base.type) { + case NVKM_RAM_TYPE_DDR2: + T(CWL) = T(CL) - 1; + break; + case NVKM_RAM_TYPE_GDDR3: + T(CWL) = ((cur2 & 0xff000000) >> 24) + 1; + break; + } + + /* XXX: N=1 is not proper statistics */ + if (device->chipset == 0xa0) { + unkt3b = 0x19 + ram->base.next->bios.rammap_00_16_40; + timing[6] = (0x2d + T(CL) - T(CWL) + + ram->base.next->bios.rammap_00_16_40) << 16 | + T(CWL) << 8 | + (0x2f + T(CL) - T(CWL)); + } else { + unkt3b = 0x16; + timing[6] = (0x2b + T(CL) - T(CWL)) << 16 | + max_t(s8, T(CWL) - 2, 1) << 8 | + (0x2e + T(CL) - T(CWL)); + } + + timing[0] = (T(RP) << 24 | T(RAS) << 16 | T(RFC) << 8 | T(RC)); + timing[1] = (T(WR) + 1 + T(CWL)) << 24 | + max_t(u8, T(18), 1) << 16 | + (T(WTR) + 1 + T(CWL)) << 8 | + (3 + T(CL) - T(CWL)); + timing[2] = (T(CWL) - 1) << 24 | + (T(RRD) << 16) | + (T(RCDWR) << 8) | + T(RCDRD); + timing[3] = (unkt3b - 2 + T(CL)) << 24 | + unkt3b << 16 | + (T(CL) - 1) << 8 | + (T(CL) - 1); + timing[4] = (cur4 & 0xffff0000) | + T(13) << 8 | + T(13); + timing[5] = T(RFC) << 24 | + max_t(u8, T(RCDRD), T(RCDWR)) << 16 | + T(RP); + /* Timing 6 is already done above */ + timing[7] = (cur7 & 0xff00ffff) | (T(CL) - 1) << 16; + timing[8] = (cur8 & 0xffffff00); + + /* XXX: P.version == 1 only has DDR2 and GDDR3? */ + if (ram->base.type == NVKM_RAM_TYPE_DDR2) { + timing[5] |= (T(CL) + 3) << 8; + timing[8] |= (T(CL) - 4); + } else + if (ram->base.type == NVKM_RAM_TYPE_GDDR3) { + timing[5] |= (T(CL) + 2) << 8; + timing[8] |= (T(CL) - 2); + } + + nvkm_debug(subdev, " 220: %08x %08x %08x %08x\n", + timing[0], timing[1], timing[2], timing[3]); + nvkm_debug(subdev, " 230: %08x %08x %08x %08x\n", + timing[4], timing[5], timing[6], timing[7]); + nvkm_debug(subdev, " 240: %08x\n", timing[8]); + return 0; +} + +static int +nv50_ram_timing_read(struct nv50_ram *ram, u32 *timing) +{ + unsigned int i; + struct nvbios_ramcfg *cfg = &ram->base.target.bios; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_device *device = subdev->device; + + for (i = 0; i <= 8; i++) + timing[i] = nvkm_rd32(device, 0x100220 + (i * 4)); + + /* Derive the bare minimum for the MR calculation to succeed */ + cfg->timing_ver = 0x10; + T(CL) = (timing[3] & 0xff) + 1; + + switch (ram->base.type) { + case NVKM_RAM_TYPE_DDR2: + T(CWL) = T(CL) - 1; + break; + case NVKM_RAM_TYPE_GDDR3: + T(CWL) = ((timing[2] & 0xff000000) >> 24) + 1; + break; + default: + return -ENOSYS; + break; + } + + T(WR) = ((timing[1] >> 24) & 0xff) - 1 - T(CWL); + + return 0; +} +#undef T + +static void +nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq) +{ + ram_mask(hwsq, mr[0], 0x100, 0x100); + ram_mask(hwsq, mr[0], 0x100, 0x000); + ram_nsec(hwsq, 24000); +} + +static void +nv50_ram_gpio(struct nv50_ramseq *hwsq, u8 tag, u32 val) +{ + struct nvkm_gpio *gpio = hwsq->base.subdev->device->gpio; + struct dcb_gpio_func func; + u32 reg, sh, gpio_val; + int ret; + + if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) { + ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func); + if (ret) + return; + + reg = func.line >> 3; + sh = (func.line & 0x7) << 2; + gpio_val = ram_rd32(hwsq, gpio[reg]); + + if (gpio_val & (8 << sh)) + val = !val; + if (!(func.log[1] & 1)) + val = !val; + + ram_mask(hwsq, gpio[reg], (0x3 << sh), ((val | 0x2) << sh)); + ram_nsec(hwsq, 20000); + } +} static int -nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) +nv50_ram_calc(struct nvkm_ram *base, u32 freq) { - struct nvkm_bios *bios = nvkm_bios(pfb); - struct nv50_ram *ram = (void *)pfb->ram; + struct nv50_ram *ram = nv50_ram(base); struct nv50_ramseq *hwsq = &ram->hwsq; + struct nvkm_subdev *subdev = &ram->base.fb->subdev; + struct nvkm_bios *bios = subdev->device->bios; struct nvbios_perfE perfE; struct nvbios_pll mpll; - struct { - u32 data; - u8 size; - } ramcfg, timing; - u8 ver, hdr, cnt, len, strap; + struct nvkm_ram_data *next; + u8 ver, hdr, cnt, len, strap, size; + u32 data; + u32 r100da0, r004008, unk710, unk714, unk718, unk71c; int N1, M1, N2, M2, P; int ret, i; + u32 timing[9]; + + next = &ram->base.target; + next->freq = freq; + ram->base.next = next; /* lookup closest matching performance table entry for frequency */ i = 0; do { - ramcfg.data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, - &ramcfg.size, &perfE); - if (!ramcfg.data || (ver < 0x25 || ver >= 0x40) || - (ramcfg.size < 2)) { - nv_error(pfb, "invalid/missing perftab entry\n"); + data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, + &size, &perfE); + if (!data || (ver < 0x25 || ver >= 0x40) || + (size < 2)) { + nvkm_error(subdev, "invalid/missing perftab entry\n"); return -EINVAL; } } while (perfE.memory < freq); + nvbios_rammapEp_from_perf(bios, data, hdr, &next->bios); + /* locate specific data set for the attached memory */ - strap = nvbios_ramcfg_index(nv_subdev(pfb)); + strap = nvbios_ramcfg_index(subdev); if (strap >= cnt) { - nv_error(pfb, "invalid ramcfg strap\n"); + nvkm_error(subdev, "invalid ramcfg strap\n"); return -EINVAL; } - ramcfg.data += hdr + (strap * ramcfg.size); + data = nvbios_rammapSp_from_perf(bios, data + hdr, size, strap, + &next->bios); + if (!data) { + nvkm_error(subdev, "invalid/missing rammap entry "); + return -EINVAL; + } /* lookup memory timings, if bios says they're present */ - strap = nv_ro08(bios, ramcfg.data + 0x01); - if (strap != 0xff) { - timing.data = nvbios_timingEe(bios, strap, &ver, &hdr, - &cnt, &len); - if (!timing.data || ver != 0x10 || hdr < 0x12) { - nv_error(pfb, "invalid/missing timing entry " + if (next->bios.ramcfg_timing != 0xff) { + data = nvbios_timingEp(bios, next->bios.ramcfg_timing, + &ver, &hdr, &cnt, &len, &next->bios); + if (!data || ver != 0x10 || hdr < 0x12) { + nvkm_error(subdev, "invalid/missing timing entry " "%02x %04x %02x %02x\n", - strap, timing.data, ver, hdr); + strap, data, ver, hdr); return -EINVAL; } + nv50_ram_timing_calc(ram, timing); } else { - timing.data = 0; + nv50_ram_timing_read(ram, timing); } - ret = ram_init(hwsq, nv_subdev(pfb)); + ret = ram_init(hwsq, subdev); if (ret) return ret; - ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */ - ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */ + /* Determine ram-specific MR values */ + ram->base.mr[0] = ram_rd32(hwsq, mr[0]); + ram->base.mr[1] = ram_rd32(hwsq, mr[1]); + ram->base.mr[2] = ram_rd32(hwsq, mr[2]); + + switch (ram->base.type) { + case NVKM_RAM_TYPE_GDDR3: + ret = nvkm_gddr3_calc(&ram->base); + break; + default: + ret = -ENOSYS; + break; + } + + if (ret) { + nvkm_error(subdev, "Could not calculate MR\n"); + return ret; + } + + if (subdev->device->chipset <= 0x96 && !next->bios.ramcfg_00_03_02) + ram_mask(hwsq, 0x100710, 0x00000200, 0x00000000); + + /* Always disable this bit during reclock */ + ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000); + + ram_wait_vblank(hwsq); ram_wr32(hwsq, 0x611200, 0x00003300); ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */ ram_nsec(hwsq, 8000); ram_setf(hwsq, 0x10, 0x00); /* disable fb */ ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ + ram_nsec(hwsq, 2000); + + if (next->bios.timing_10_ODT) + nv50_ram_gpio(hwsq, 0x2e, 1); ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */ ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ @@ -129,97 +327,174 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) ret = nvbios_pll_parse(bios, 0x004008, &mpll); mpll.vco2.max_freq = 0; - if (ret == 0) { - ret = nv04_pll_calc(nv_subdev(pfb), &mpll, freq, + if (ret >= 0) { + ret = nv04_pll_calc(subdev, &mpll, freq, &N1, &M1, &N2, &M2, &P); - if (ret == 0) + if (ret <= 0) ret = -EINVAL; } if (ret < 0) return ret; + /* XXX: 750MHz seems rather arbitrary */ + if (freq <= 750000) { + r100da0 = 0x00000010; + r004008 = 0x90000000; + } else { + r100da0 = 0x00000000; + r004008 = 0x80000000; + } + + r004008 |= (mpll.bias_p << 19) | (P << 22) | (P << 16); + ram_mask(hwsq, 0x00c040, 0xc000c000, 0x0000c000); - ram_mask(hwsq, 0x004008, 0x00000200, 0x00000200); + /* XXX: Is rammap_00_16_40 the DLL bit we've seen in GT215? Why does + * it have a different rammap bit from DLLoff? */ + ram_mask(hwsq, 0x004008, 0x00004200, 0x00000200 | + next->bios.rammap_00_16_40 << 14); ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); - ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) | - (P << 22) | (P << 16)); -#if QFX5800NVA0 - for (i = 0; i < 8; i++) - ram_mask(hwsq, 0x100da0[i], 0x00000000, 0x00000000); /*XXX*/ -#endif - ram_nsec(hwsq, 96000); /*XXX*/ + ram_mask(hwsq, 0x004008, 0x91ff0000, r004008); + + /* XXX: GDDR3 only? */ + if (subdev->device->chipset >= 0x92) + ram_wr32(hwsq, 0x100da0, r100da0); + + nv50_ram_gpio(hwsq, 0x18, !next->bios.ramcfg_FBVDDQ); + ram_nsec(hwsq, 64000); /*XXX*/ + ram_nsec(hwsq, 32000); /*XXX*/ + ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000); ram_wr32(hwsq, 0x1002dc, 0x00000000); /* disable self-refresh */ + ram_wr32(hwsq, 0x1002d4, 0x00000001); /* disable self-refresh */ ram_wr32(hwsq, 0x100210, 0x80000000); /* enable auto-refresh */ ram_nsec(hwsq, 12000); switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: + case NVKM_RAM_TYPE_DDR2: ram_nuke(hwsq, mr[0]); /* force update */ ram_mask(hwsq, mr[0], 0x000, 0x000); break; - case NV_MEM_TYPE_GDDR3: - ram_mask(hwsq, mr[2], 0x000, 0x000); + case NVKM_RAM_TYPE_GDDR3: + ram_nuke(hwsq, mr[1]); /* force update */ + ram_wr32(hwsq, mr[1], ram->base.mr[1]); ram_nuke(hwsq, mr[0]); /* force update */ - ram_mask(hwsq, mr[0], 0x000, 0x000); + ram_wr32(hwsq, mr[0], ram->base.mr[0]); break; default: break; } - ram_mask(hwsq, timing[3], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[1], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[6], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[7], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[8], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[2], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[4], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[5], 0x00000000, 0x00000000); /*XXX*/ - - ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ - -#if QFX5800NVA0 - ram_nuke(hwsq, 0x100e24); - ram_mask(hwsq, 0x100e24, 0x00000000, 0x00000000); - ram_nuke(hwsq, 0x100e20); - ram_mask(hwsq, 0x100e20, 0x00000000, 0x00000000); -#endif + ram_mask(hwsq, timing[3], 0xffffffff, timing[3]); + ram_mask(hwsq, timing[1], 0xffffffff, timing[1]); + ram_mask(hwsq, timing[6], 0xffffffff, timing[6]); + ram_mask(hwsq, timing[7], 0xffffffff, timing[7]); + ram_mask(hwsq, timing[8], 0xffffffff, timing[8]); + ram_mask(hwsq, timing[0], 0xffffffff, timing[0]); + ram_mask(hwsq, timing[2], 0xffffffff, timing[2]); + ram_mask(hwsq, timing[4], 0xffffffff, timing[4]); + ram_mask(hwsq, timing[5], 0xffffffff, timing[5]); + + if (!next->bios.ramcfg_00_03_02) + ram_mask(hwsq, 0x10021c, 0x00010000, 0x00000000); + ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 << 12); + + /* XXX: A lot of this could be "chipset"/"ram type" specific stuff */ + unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000100; + unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020; + unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100; + unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100; + if (subdev->device->chipset <= 0x96) { + unk710 &= ~0x0000006e; + unk714 &= ~0x00000100; + + if (!next->bios.ramcfg_00_03_08) + unk710 |= 0x00000060; + if (!next->bios.ramcfg_FBVDDQ) + unk714 |= 0x00000100; + if ( next->bios.ramcfg_00_04_04) + unk710 |= 0x0000000e; + } else { + unk710 &= ~0x00000001; - ram_mask(hwsq, mr[0], 0x100, 0x100); - ram_mask(hwsq, mr[0], 0x100, 0x000); + if (!next->bios.ramcfg_00_03_08) + unk710 |= 0x00000001; + } + + if ( next->bios.ramcfg_00_03_01) + unk71c |= 0x00000100; + if ( next->bios.ramcfg_00_03_02) + unk710 |= 0x00000100; + if (!next->bios.ramcfg_00_03_08) + unk714 |= 0x00000020; + if ( next->bios.ramcfg_00_04_04) + unk714 |= 0x70000000; + if ( next->bios.ramcfg_00_04_20) + unk718 |= 0x00000100; + + ram_mask(hwsq, 0x100714, 0xffffffff, unk714); + ram_mask(hwsq, 0x10071c, 0xffffffff, unk71c); + ram_mask(hwsq, 0x100718, 0xffffffff, unk718); + ram_mask(hwsq, 0x100710, 0xffffffff, unk710); + + /* XXX: G94 does not even test these regs in trace. Harmless we do it, + * but why is it omitted? */ + if (next->bios.rammap_00_16_20) { + ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 | + next->bios.ramcfg_00_06 << 8 | + next->bios.ramcfg_00_05); + ram_wr32(hwsq, 0x1005a4, next->bios.ramcfg_00_09 << 8 | + next->bios.ramcfg_00_08); + ram_mask(hwsq, 0x10053c, 0x00001000, 0x00000000); + } else { + ram_mask(hwsq, 0x10053c, 0x00001000, 0x00001000); + } + ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]); + + if (!next->bios.timing_10_ODT) + nv50_ram_gpio(hwsq, 0x2e, 0); + + /* Reset DLL */ + if (!next->bios.ramcfg_DLLoff) + nvkm_sddr2_dll_reset(hwsq); ram_setf(hwsq, 0x10, 0x01); /* enable fb */ ram_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */ ram_wr32(hwsq, 0x611200, 0x00003330); ram_wr32(hwsq, 0x002504, 0x00000000); /* un-block fifo */ + + if (next->bios.rammap_00_17_02) + ram_mask(hwsq, 0x100200, 0x00000800, 0x00000800); + if (!next->bios.rammap_00_16_40) + ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000); + if (next->bios.ramcfg_00_03_02) + ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000); + if (subdev->device->chipset <= 0x96 && next->bios.ramcfg_00_03_02) + ram_mask(hwsq, 0x100710, 0x00000200, 0x00000200); + return 0; } static int -nv50_ram_prog(struct nvkm_fb *pfb) +nv50_ram_prog(struct nvkm_ram *base) { - struct nvkm_device *device = nv_device(pfb); - struct nv50_ram *ram = (void *)pfb->ram; - struct nv50_ramseq *hwsq = &ram->hwsq; - - ram_exec(hwsq, nvkm_boolopt(device->cfgopt, "NvMemExec", true)); + struct nv50_ram *ram = nv50_ram(base); + struct nvkm_device *device = ram->base.fb->subdev.device; + ram_exec(&ram->hwsq, nvkm_boolopt(device->cfgopt, "NvMemExec", true)); return 0; } static void -nv50_ram_tidy(struct nvkm_fb *pfb) +nv50_ram_tidy(struct nvkm_ram *base) { - struct nv50_ram *ram = (void *)pfb->ram; - struct nv50_ramseq *hwsq = &ram->hwsq; - ram_exec(hwsq, false); + struct nv50_ram *ram = nv50_ram(base); + ram_exec(&ram->hwsq, false); } void -__nv50_ram_put(struct nvkm_fb *pfb, struct nvkm_mem *mem) +__nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem *mem) { struct nvkm_mm_node *this; @@ -227,14 +502,14 @@ __nv50_ram_put(struct nvkm_fb *pfb, struct nvkm_mem *mem) this = list_first_entry(&mem->regions, typeof(*this), rl_entry); list_del(&this->rl_entry); - nvkm_mm_free(&pfb->vram, &this); + nvkm_mm_free(&ram->vram, &this); } - nvkm_mm_free(&pfb->tags, &mem->tag); + nvkm_mm_free(&ram->tags, &mem->tag); } void -nv50_ram_put(struct nvkm_fb *pfb, struct nvkm_mem **pmem) +nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem) { struct nvkm_mem *mem = *pmem; @@ -242,19 +517,19 @@ nv50_ram_put(struct nvkm_fb *pfb, struct nvkm_mem **pmem) if (unlikely(mem == NULL)) return; - mutex_lock(&pfb->base.mutex); - __nv50_ram_put(pfb, mem); - mutex_unlock(&pfb->base.mutex); + mutex_lock(&ram->fb->subdev.mutex); + __nv50_ram_put(ram, mem); + mutex_unlock(&ram->fb->subdev.mutex); kfree(mem); } int -nv50_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, +nv50_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, u32 memtype, struct nvkm_mem **pmem) { - struct nvkm_mm *heap = &pfb->vram; - struct nvkm_mm *tags = &pfb->tags; + struct nvkm_mm *heap = &ram->vram; + struct nvkm_mm *tags = &ram->tags; struct nvkm_mm_node *r; struct nvkm_mem *mem; int comp = (memtype & 0x300) >> 8; @@ -262,17 +537,17 @@ nv50_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, int back = (memtype & 0x800); int min, max, ret; - max = (size >> 12); - min = ncmin ? (ncmin >> 12) : max; - align >>= 12; + max = (size >> NVKM_RAM_MM_SHIFT); + min = ncmin ? (ncmin >> NVKM_RAM_MM_SHIFT) : max; + align >>= NVKM_RAM_MM_SHIFT; mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) return -ENOMEM; - mutex_lock(&pfb->base.mutex); + mutex_lock(&ram->fb->subdev.mutex); if (comp) { - if (align == 16) { + if (align == (1 << (16 - NVKM_RAM_MM_SHIFT))) { int n = (max >> 4) * comp; ret = nvkm_mm_head(tags, 0, 1, n, n, 1, &mem->tag); @@ -295,34 +570,45 @@ nv50_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, else ret = nvkm_mm_head(heap, 0, type, max, min, align, &r); if (ret) { - mutex_unlock(&pfb->base.mutex); - pfb->ram->put(pfb, &mem); + mutex_unlock(&ram->fb->subdev.mutex); + ram->func->put(ram, &mem); return ret; } list_add_tail(&r->rl_entry, &mem->regions); max -= r->length; } while (max); - mutex_unlock(&pfb->base.mutex); + mutex_unlock(&ram->fb->subdev.mutex); r = list_first_entry(&mem->regions, struct nvkm_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; + mem->offset = (u64)r->offset << NVKM_RAM_MM_SHIFT; *pmem = mem; return 0; } +static const struct nvkm_ram_func +nv50_ram_func = { + .get = nv50_ram_get, + .put = nv50_ram_put, + .calc = nv50_ram_calc, + .prog = nv50_ram_prog, + .tidy = nv50_ram_tidy, +}; + static u32 -nv50_fb_vram_rblock(struct nvkm_fb *pfb, struct nvkm_ram *ram) +nv50_fb_vram_rblock(struct nvkm_ram *ram) { + struct nvkm_subdev *subdev = &ram->fb->subdev; + struct nvkm_device *device = subdev->device; int colbits, rowbitsa, rowbitsb, banks; u64 rowsize, predicted; u32 r0, r4, rt, rblock_size; - r0 = nv_rd32(pfb, 0x100200); - r4 = nv_rd32(pfb, 0x100204); - rt = nv_rd32(pfb, 0x100250); - nv_debug(pfb, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", - r0, r4, rt, nv_rd32(pfb, 0x001540)); + r0 = nvkm_rd32(device, 0x100200); + r4 = nvkm_rd32(device, 0x100204); + rt = nvkm_rd32(device, 0x100250); + nvkm_debug(subdev, "memcfg %08x %08x %08x %08x\n", + r0, r4, rt, nvkm_rd32(device, 0x001540)); colbits = (r4 & 0x0000f000) >> 12; rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; @@ -335,103 +621,94 @@ nv50_fb_vram_rblock(struct nvkm_fb *pfb, struct nvkm_ram *ram) predicted += rowsize << rowbitsb; if (predicted != ram->size) { - nv_warn(pfb, "memory controller reports %d MiB VRAM\n", - (u32)(ram->size >> 20)); + nvkm_warn(subdev, "memory controller reports %d MiB VRAM\n", + (u32)(ram->size >> 20)); } rblock_size = rowsize; if (rt & 1) rblock_size *= 3; - nv_debug(pfb, "rblock %d bytes\n", rblock_size); + nvkm_debug(subdev, "rblock %d bytes\n", rblock_size); return rblock_size; } int -nv50_ram_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nv50_ram_ctor(const struct nvkm_ram_func *func, + struct nvkm_fb *fb, struct nvkm_ram *ram) { - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - struct nvkm_bios *bios = nvkm_bios(parent); - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ram *ram; + struct nvkm_device *device = fb->subdev.device; + struct nvkm_bios *bios = device->bios; + const u32 rsvd_head = ( 256 * 1024); /* vga memory */ + const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ + u64 size = nvkm_rd32(device, 0x10020c); + u32 tags = nvkm_rd32(device, 0x100320); + enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; - ret = nvkm_ram_create_(parent, engine, oclass, length, pobject); - ram = *pobject; - if (ret) - return ret; - - ram->size = nv_rd32(pfb, 0x10020c); - ram->size = (ram->size & 0xffffff00) | ((ram->size & 0x000000ff) << 32); - - ram->part_mask = (nv_rd32(pfb, 0x001540) & 0x00ff0000) >> 16; - ram->parts = hweight8(ram->part_mask); - - switch (nv_rd32(pfb, 0x100714) & 0x00000007) { - case 0: ram->type = NV_MEM_TYPE_DDR1; break; + switch (nvkm_rd32(device, 0x100714) & 0x00000007) { + case 0: type = NVKM_RAM_TYPE_DDR1; break; case 1: - if (nvkm_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3) - ram->type = NV_MEM_TYPE_DDR3; + if (nvkm_fb_bios_memtype(bios) == NVKM_RAM_TYPE_DDR3) + type = NVKM_RAM_TYPE_DDR3; else - ram->type = NV_MEM_TYPE_DDR2; + type = NVKM_RAM_TYPE_DDR2; break; - case 2: ram->type = NV_MEM_TYPE_GDDR3; break; - case 3: ram->type = NV_MEM_TYPE_GDDR4; break; - case 4: ram->type = NV_MEM_TYPE_GDDR5; break; + case 2: type = NVKM_RAM_TYPE_GDDR3; break; + case 3: type = NVKM_RAM_TYPE_GDDR4; break; + case 4: type = NVKM_RAM_TYPE_GDDR5; break; default: break; } - ret = nvkm_mm_init(&pfb->vram, rsvd_head, (ram->size >> 12) - - (rsvd_head + rsvd_tail), - nv50_fb_vram_rblock(pfb, ram) >> 12); + size = (size & 0x000000ff) << 32 | (size & 0xffffff00); + + ret = nvkm_ram_ctor(func, fb, type, size, tags, ram); if (ret) return ret; - ram->ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1; - ram->tags = nv_rd32(pfb, 0x100320); - ram->get = nv50_ram_get; - ram->put = nv50_ram_put; - return 0; + ram->part_mask = (nvkm_rd32(device, 0x001540) & 0x00ff0000) >> 16; + ram->parts = hweight8(ram->part_mask); + ram->ranks = (nvkm_rd32(device, 0x100200) & 0x4) ? 2 : 1; + nvkm_mm_fini(&ram->vram); + + return nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, + nv50_fb_vram_rblock(ram) >> NVKM_RAM_MM_SHIFT); } -static int -nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 datasize, - struct nvkm_object **pobject) +int +nv50_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { struct nv50_ram *ram; int ret, i; - ret = nv50_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); + if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) + return -ENOMEM; + *pram = &ram->base; + + ret = nv50_ram_ctor(&nv50_ram_func, fb, &ram->base); if (ret) return ret; - switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: - case NV_MEM_TYPE_GDDR3: - ram->base.calc = nv50_ram_calc; - ram->base.prog = nv50_ram_prog; - ram->base.tidy = nv50_ram_tidy; - break; - default: - nv_warn(ram, "reclocking of this ram type unsupported\n"); - return 0; - } - ram->hwsq.r_0x002504 = hwsq_reg(0x002504); ram->hwsq.r_0x00c040 = hwsq_reg(0x00c040); ram->hwsq.r_0x004008 = hwsq_reg(0x004008); ram->hwsq.r_0x00400c = hwsq_reg(0x00400c); + ram->hwsq.r_0x100200 = hwsq_reg(0x100200); ram->hwsq.r_0x100210 = hwsq_reg(0x100210); + ram->hwsq.r_0x10021c = hwsq_reg(0x10021c); ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0); ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4); ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc); - for (i = 0; i < 8; i++) - ram->hwsq.r_0x100da0[i] = hwsq_reg(0x100da0 + (i * 0x04)); + ram->hwsq.r_0x10053c = hwsq_reg(0x10053c); + ram->hwsq.r_0x1005a0 = hwsq_reg(0x1005a0); + ram->hwsq.r_0x1005a4 = hwsq_reg(0x1005a4); + ram->hwsq.r_0x100710 = hwsq_reg(0x100710); + ram->hwsq.r_0x100714 = hwsq_reg(0x100714); + ram->hwsq.r_0x100718 = hwsq_reg(0x100718); + ram->hwsq.r_0x10071c = hwsq_reg(0x10071c); + ram->hwsq.r_0x100da0 = hwsq_stride(0x100da0, 4, ram->base.part_mask); ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20); ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24); ram->hwsq.r_0x611200 = hwsq_reg(0x611200); @@ -451,15 +728,10 @@ nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4); } + ram->hwsq.r_gpio[0] = hwsq_reg(0x00e104); + ram->hwsq.r_gpio[1] = hwsq_reg(0x00e108); + ram->hwsq.r_gpio[2] = hwsq_reg(0x00e120); + ram->hwsq.r_gpio[3] = hwsq_reg(0x00e124); + return 0; } - -struct nvkm_oclass -nv50_ram_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_ram_ctor, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h index 0f1f97ccd..8df7306d5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h @@ -11,5 +11,6 @@ #define ram_mask(s,r,m,d) hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d)) #define ram_setf(s,f,d) hwsq_setf(&(s)->base, (f), (d)) #define ram_wait(s,f,d) hwsq_wait(&(s)->base, (f), (d)) +#define ram_wait_vblank(s) hwsq_wait_vblank(&(s)->base) #define ram_nsec(s,n) hwsq_nsec(&(s)->base, (n)) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c index afab42df2..b9f1ffdfc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c @@ -65,7 +65,7 @@ nvkm_sddr2_calc(struct nvkm_ram *ram) case 0x10: CL = ram->next->bios.timing_10_CL; WR = ram->next->bios.timing_10_WR; - DLL = !ram->next->bios.ramcfg_10_DLLoff; + DLL = !ram->next->bios.ramcfg_DLLoff; ODT = ram->next->bios.timing_10_ODT & 3; break; case 0x20: @@ -76,6 +76,12 @@ nvkm_sddr2_calc(struct nvkm_ram *ram) return -ENOSYS; } + if (ram->next->bios.timing_ver == 0x20 || + ram->next->bios.ramcfg_timing == 0xff) { + ODT = (ram->mr[1] & 0x004) >> 2 | + (ram->mr[1] & 0x040) >> 5; + } + CL = ramxlat(ramddr2_cl, CL); WR = ramxlat(ramddr2_wr, WR); if (CL < 0 || WR < 0) diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c index 10844355c..26900333b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c @@ -53,7 +53,7 @@ static const struct ramxlat ramddr3_wr[] = { { 5, 1 }, { 6, 2 }, { 7, 3 }, { 8, 4 }, { 10, 5 }, { 12, 6 }, /* the below are mentioned in some, but not all, ddr3 docs */ - { 14, 7 }, { 16, 0 }, + { 14, 7 }, { 15, 7 }, { 16, 0 }, { -1 } }; @@ -61,7 +61,7 @@ static const struct ramxlat ramddr3_cwl[] = { { 5, 0 }, { 6, 1 }, { 7, 2 }, { 8, 3 }, /* the below are mentioned in some, but not all, ddr3 docs */ - { 9, 4 }, + { 9, 4 }, { 10, 5 }, { -1 } }; @@ -70,6 +70,8 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) { int CWL, CL, WR, DLL = 0, ODT = 0; + DLL = !ram->next->bios.ramcfg_DLLoff; + switch (ram->next->bios.timing_ver) { case 0x10: if (ram->next->bios.timing_hdr < 0x17) { @@ -79,7 +81,6 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) CWL = ram->next->bios.timing_10_CWL; CL = ram->next->bios.timing_10_CL; WR = ram->next->bios.timing_10_WR; - DLL = !ram->next->bios.ramcfg_10_DLLoff; ODT = ram->next->bios.timing_10_ODT; break; case 0x20: @@ -87,7 +88,6 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) CL = (ram->next->bios.timing[1] & 0x0000001f) >> 0; WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; /* XXX: Get these values from the VBIOS instead */ - DLL = !(ram->mr[1] & 0x1); ODT = (ram->mr[1] & 0x004) >> 2 | (ram->mr[1] & 0x040) >> 5 | (ram->mr[1] & 0x200) >> 7; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c index b7b7193bb..f4144979a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c @@ -21,31 +21,34 @@ * * Authors: Martin Peres */ -#include +#include "priv.h" -int -_nvkm_fuse_init(struct nvkm_object *object) +u32 +nvkm_fuse_read(struct nvkm_fuse *fuse, u32 addr) { - struct nvkm_fuse *fuse = (void *)object; - return nvkm_subdev_init(&fuse->base); + return fuse->func->read(fuse, addr); } -void -_nvkm_fuse_dtor(struct nvkm_object *object) +static void * +nvkm_fuse_dtor(struct nvkm_subdev *subdev) { - struct nvkm_fuse *fuse = (void *)object; - nvkm_subdev_destroy(&fuse->base); + return nvkm_fuse(subdev); } +static const struct nvkm_subdev_func +nvkm_fuse = { + .dtor = nvkm_fuse_dtor, +}; + int -nvkm_fuse_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nvkm_fuse_new_(const struct nvkm_fuse_func *func, struct nvkm_device *device, + int index, struct nvkm_fuse **pfuse) { struct nvkm_fuse *fuse; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "FUSE", - "fuse", length, pobject); - fuse = *pobject; - return ret; + if (!(fuse = *pfuse = kzalloc(sizeof(*fuse), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_fuse, device, index, 0, &fuse->subdev); + fuse->func = func; + spin_lock_init(&fuse->lock); + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gf100.c index 393ef3a0f..13671fedc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gf100.c @@ -23,56 +23,31 @@ */ #include "priv.h" -struct gf100_fuse_priv { - struct nvkm_fuse base; - - spinlock_t fuse_enable_lock; -}; - static u32 -gf100_fuse_rd32(struct nvkm_object *object, u64 addr) +gf100_fuse_read(struct nvkm_fuse *fuse, u32 addr) { - struct gf100_fuse_priv *priv = (void *)object; + struct nvkm_device *device = fuse->subdev.device; unsigned long flags; u32 fuse_enable, unk, val; /* racy if another part of nvkm start writing to these regs */ - spin_lock_irqsave(&priv->fuse_enable_lock, flags); - fuse_enable = nv_mask(priv, 0x22400, 0x800, 0x800); - unk = nv_mask(priv, 0x21000, 0x1, 0x1); - val = nv_rd32(priv, 0x21100 + addr); - nv_wr32(priv, 0x21000, unk); - nv_wr32(priv, 0x22400, fuse_enable); - spin_unlock_irqrestore(&priv->fuse_enable_lock, flags); + spin_lock_irqsave(&fuse->lock, flags); + fuse_enable = nvkm_mask(device, 0x022400, 0x800, 0x800); + unk = nvkm_mask(device, 0x021000, 0x1, 0x1); + val = nvkm_rd32(device, 0x021100 + addr); + nvkm_wr32(device, 0x021000, unk); + nvkm_wr32(device, 0x022400, fuse_enable); + spin_unlock_irqrestore(&fuse->lock, flags); return val; } +static const struct nvkm_fuse_func +gf100_fuse = { + .read = gf100_fuse_read, +}; -static int -gf100_fuse_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gf100_fuse_new(struct nvkm_device *device, int index, struct nvkm_fuse **pfuse) { - struct gf100_fuse_priv *priv; - int ret; - - ret = nvkm_fuse_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - spin_lock_init(&priv->fuse_enable_lock); - return 0; + return nvkm_fuse_new_(&gf100_fuse, device, index, pfuse); } - -struct nvkm_oclass -gf100_fuse_oclass = { - .handle = NV_SUBDEV(FUSE, 0xC0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_fuse_ctor, - .dtor = _nvkm_fuse_dtor, - .init = _nvkm_fuse_init, - .fini = _nvkm_fuse_fini, - .rd32 = gf100_fuse_rd32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c index 0b256aa49..9aff4ea04 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c @@ -23,40 +23,20 @@ */ #include "priv.h" -struct gm107_fuse_priv { - struct nvkm_fuse base; -}; - static u32 -gm107_fuse_rd32(struct nvkm_object *object, u64 addr) +gm107_fuse_read(struct nvkm_fuse *fuse, u32 addr) { - struct gf100_fuse_priv *priv = (void *)object; - return nv_rd32(priv, 0x21100 + addr); + struct nvkm_device *device = fuse->subdev.device; + return nvkm_rd32(device, 0x021100 + addr); } +static const struct nvkm_fuse_func +gm107_fuse = { + .read = gm107_fuse_read, +}; -static int -gm107_fuse_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +gm107_fuse_new(struct nvkm_device *device, int index, struct nvkm_fuse **pfuse) { - struct gm107_fuse_priv *priv; - int ret; - - ret = nvkm_fuse_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - - return ret; + return nvkm_fuse_new_(&gm107_fuse, device, index, pfuse); } - -struct nvkm_oclass -gm107_fuse_oclass = { - .handle = NV_SUBDEV(FUSE, 0x117), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm107_fuse_ctor, - .dtor = _nvkm_fuse_dtor, - .init = _nvkm_fuse_init, - .fini = _nvkm_fuse_fini, - .rd32 = gm107_fuse_rd32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/nv50.c index 0d2afc426..514c193db 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/nv50.c @@ -23,54 +23,29 @@ */ #include "priv.h" -struct nv50_fuse_priv { - struct nvkm_fuse base; - - spinlock_t fuse_enable_lock; -}; - static u32 -nv50_fuse_rd32(struct nvkm_object *object, u64 addr) +nv50_fuse_read(struct nvkm_fuse *fuse, u32 addr) { - struct nv50_fuse_priv *priv = (void *)object; + struct nvkm_device *device = fuse->subdev.device; unsigned long flags; u32 fuse_enable, val; /* racy if another part of nvkm start writing to this reg */ - spin_lock_irqsave(&priv->fuse_enable_lock, flags); - fuse_enable = nv_mask(priv, 0x1084, 0x800, 0x800); - val = nv_rd32(priv, 0x21000 + addr); - nv_wr32(priv, 0x1084, fuse_enable); - spin_unlock_irqrestore(&priv->fuse_enable_lock, flags); + spin_lock_irqsave(&fuse->lock, flags); + fuse_enable = nvkm_mask(device, 0x001084, 0x800, 0x800); + val = nvkm_rd32(device, 0x021000 + addr); + nvkm_wr32(device, 0x001084, fuse_enable); + spin_unlock_irqrestore(&fuse->lock, flags); return val; } +static const struct nvkm_fuse_func +nv50_fuse = { + .read = &nv50_fuse_read, +}; -static int -nv50_fuse_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv50_fuse_new(struct nvkm_device *device, int index, struct nvkm_fuse **pfuse) { - struct nv50_fuse_priv *priv; - int ret; - - ret = nvkm_fuse_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - spin_lock_init(&priv->fuse_enable_lock); - return 0; + return nvkm_fuse_new_(&nv50_fuse, device, index, pfuse); } - -struct nvkm_oclass -nv50_fuse_oclass = { - .handle = NV_SUBDEV(FUSE, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_fuse_ctor, - .dtor = _nvkm_fuse_dtor, - .init = _nvkm_fuse_init, - .fini = _nvkm_fuse_fini, - .rd32 = nv50_fuse_rd32, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h index 7e050f789..b0390b540 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h @@ -1,7 +1,12 @@ #ifndef __NVKM_FUSE_PRIV_H__ #define __NVKM_FUSE_PRIV_H__ +#define nvkm_fuse(p) container_of((p), struct nvkm_fuse, subdev) #include -int _nvkm_fuse_init(struct nvkm_object *object); -void _nvkm_fuse_dtor(struct nvkm_object *object); +struct nvkm_fuse_func { + u32 (*read)(struct nvkm_fuse *, u32 addr); +}; + +int nvkm_fuse_new_(const struct nvkm_fuse_func *, struct nvkm_device *, + int index, struct nvkm_fuse **); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/Kbuild index ea42a9ed1..e52c5e87f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/Kbuild @@ -2,5 +2,5 @@ nvkm-y += nvkm/subdev/gpio/base.o nvkm-y += nvkm/subdev/gpio/nv10.o nvkm-y += nvkm/subdev/gpio/nv50.o nvkm-y += nvkm/subdev/gpio/g94.o -nvkm-y += nvkm/subdev/gpio/gf110.o +nvkm-y += nvkm/subdev/gpio/gf119.o nvkm-y += nvkm/subdev/gpio/gk104.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c index dea58161b..d45ec99f0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c @@ -23,28 +23,33 @@ */ #include "priv.h" -#include #include static int nvkm_gpio_drive(struct nvkm_gpio *gpio, int idx, int line, int dir, int out) { - const struct nvkm_gpio_impl *impl = (void *)nv_object(gpio)->oclass; - return impl->drive ? impl->drive(gpio, line, dir, out) : -ENODEV; + return gpio->func->drive(gpio, line, dir, out); } static int nvkm_gpio_sense(struct nvkm_gpio *gpio, int idx, int line) { - const struct nvkm_gpio_impl *impl = (void *)nv_object(gpio)->oclass; - return impl->sense ? impl->sense(gpio, line) : -ENODEV; + return gpio->func->sense(gpio, line); } -static int +void +nvkm_gpio_reset(struct nvkm_gpio *gpio, u8 func) +{ + if (gpio->func->reset) + gpio->func->reset(gpio, func); +} + +int nvkm_gpio_find(struct nvkm_gpio *gpio, int idx, u8 tag, u8 line, struct dcb_gpio_func *func) { - struct nvkm_bios *bios = nvkm_bios(gpio); + struct nvkm_device *device = gpio->subdev.device; + struct nvkm_bios *bios = device->bios; u8 ver, len; u16 data; @@ -56,11 +61,11 @@ nvkm_gpio_find(struct nvkm_gpio *gpio, int idx, u8 tag, u8 line, return 0; /* Apple iMac G4 NV18 */ - if (nv_device_match(nv_object(gpio), 0x0189, 0x10de, 0x0010)) { + if (device->quirk && device->quirk->tv_gpio) { if (tag == DCB_GPIO_TVDAC0) { *func = (struct dcb_gpio_func) { .func = DCB_GPIO_TVDAC0, - .line = 4, + .line = device->quirk->tv_gpio, .log[0] = 0, .log[1] = 1, }; @@ -71,7 +76,7 @@ nvkm_gpio_find(struct nvkm_gpio *gpio, int idx, u8 tag, u8 line, return -ENOENT; } -static int +int nvkm_gpio_set(struct nvkm_gpio *gpio, int idx, u8 tag, u8 line, int state) { struct dcb_gpio_func func; @@ -87,7 +92,7 @@ nvkm_gpio_set(struct nvkm_gpio *gpio, int idx, u8 tag, u8 line, int state) return ret; } -static int +int nvkm_gpio_get(struct nvkm_gpio *gpio, int idx, u8 tag, u8 line) { struct dcb_gpio_func func; @@ -107,16 +112,14 @@ static void nvkm_gpio_intr_fini(struct nvkm_event *event, int type, int index) { struct nvkm_gpio *gpio = container_of(event, typeof(*gpio), event); - const struct nvkm_gpio_impl *impl = (void *)nv_object(gpio)->oclass; - impl->intr_mask(gpio, type, 1 << index, 0); + gpio->func->intr_mask(gpio, type, 1 << index, 0); } static void nvkm_gpio_intr_init(struct nvkm_event *event, int type, int index) { struct nvkm_gpio *gpio = container_of(event, typeof(*gpio), event); - const struct nvkm_gpio_impl *impl = (void *)nv_object(gpio)->oclass; - impl->intr_mask(gpio, type, 1 << index, 1 << index); + gpio->func->intr_mask(gpio, type, 1 << index, 1 << index); } static int @@ -133,16 +136,22 @@ nvkm_gpio_intr_ctor(struct nvkm_object *object, void *data, u32 size, return -EINVAL; } +static const struct nvkm_event_func +nvkm_gpio_intr_func = { + .ctor = nvkm_gpio_intr_ctor, + .init = nvkm_gpio_intr_init, + .fini = nvkm_gpio_intr_fini, +}; + static void nvkm_gpio_intr(struct nvkm_subdev *subdev) { struct nvkm_gpio *gpio = nvkm_gpio(subdev); - const struct nvkm_gpio_impl *impl = (void *)nv_object(gpio)->oclass; u32 hi, lo, i; - impl->intr_stat(gpio, &hi, &lo); + gpio->func->intr_stat(gpio, &hi, &lo); - for (i = 0; (hi | lo) && i < impl->lines; i++) { + for (i = 0; (hi | lo) && i < gpio->func->lines; i++) { struct nvkm_gpio_ntfy_rep rep = { .mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) | (NVKM_GPIO_LO * !!(lo & (1 << i))), @@ -151,24 +160,15 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev) } } -static const struct nvkm_event_func -nvkm_gpio_intr_func = { - .ctor = nvkm_gpio_intr_ctor, - .init = nvkm_gpio_intr_init, - .fini = nvkm_gpio_intr_fini, -}; - -int -_nvkm_gpio_fini(struct nvkm_object *object, bool suspend) +static int +nvkm_gpio_fini(struct nvkm_subdev *subdev, bool suspend) { - const struct nvkm_gpio_impl *impl = (void *)object->oclass; - struct nvkm_gpio *gpio = nvkm_gpio(object); - u32 mask = (1 << impl->lines) - 1; - - impl->intr_mask(gpio, NVKM_GPIO_TOGGLED, mask, 0); - impl->intr_stat(gpio, &mask, &mask); + struct nvkm_gpio *gpio = nvkm_gpio(subdev); + u32 mask = (1 << gpio->func->lines) - 1; - return nvkm_subdev_fini(&gpio->base, suspend); + gpio->func->intr_mask(gpio, NVKM_GPIO_TOGGLED, mask, 0); + gpio->func->intr_stat(gpio, &mask, &mask); + return 0; } static struct dmi_system_id gpio_reset_ids[] = { @@ -182,70 +182,43 @@ static struct dmi_system_id gpio_reset_ids[] = { { } }; -int -_nvkm_gpio_init(struct nvkm_object *object) +static int +nvkm_gpio_init(struct nvkm_subdev *subdev) { - struct nvkm_gpio *gpio = nvkm_gpio(object); - int ret; - - ret = nvkm_subdev_init(&gpio->base); - if (ret) - return ret; - - if (gpio->reset && dmi_check_system(gpio_reset_ids)) - gpio->reset(gpio, DCB_GPIO_UNUSED); - - return ret; + struct nvkm_gpio *gpio = nvkm_gpio(subdev); + if (dmi_check_system(gpio_reset_ids)) + nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED); + return 0; } -void -_nvkm_gpio_dtor(struct nvkm_object *object) +static void * +nvkm_gpio_dtor(struct nvkm_subdev *subdev) { - struct nvkm_gpio *gpio = (void *)object; + struct nvkm_gpio *gpio = nvkm_gpio(subdev); nvkm_event_fini(&gpio->event); - nvkm_subdev_destroy(&gpio->base); + return gpio; } -int -nvkm_gpio_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) -{ - const struct nvkm_gpio_impl *impl = (void *)oclass; - struct nvkm_gpio *gpio; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "GPIO", - "gpio", length, pobject); - gpio = *pobject; - if (ret) - return ret; - - gpio->find = nvkm_gpio_find; - gpio->set = nvkm_gpio_set; - gpio->get = nvkm_gpio_get; - gpio->reset = impl->reset; - - ret = nvkm_event_init(&nvkm_gpio_intr_func, 2, impl->lines, - &gpio->event); - if (ret) - return ret; - - nv_subdev(gpio)->intr = nvkm_gpio_intr; - return 0; -} +static const struct nvkm_subdev_func +nvkm_gpio = { + .dtor = nvkm_gpio_dtor, + .init = nvkm_gpio_init, + .fini = nvkm_gpio_fini, + .intr = nvkm_gpio_intr, +}; int -_nvkm_gpio_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_gpio_new_(const struct nvkm_gpio_func *func, struct nvkm_device *device, + int index, struct nvkm_gpio **pgpio) { struct nvkm_gpio *gpio; - int ret; - ret = nvkm_gpio_create(parent, engine, oclass, &gpio); - *pobject = nv_object(gpio); - if (ret) - return ret; + if (!(gpio = *pgpio = kzalloc(sizeof(*gpio), GFP_KERNEL))) + return -ENOMEM; - return 0; + nvkm_subdev_ctor(&nvkm_gpio, device, index, 0, &gpio->subdev); + gpio->func = func; + + return nvkm_event_init(&nvkm_gpio_intr_func, 2, func->lines, + &gpio->event); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/g94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/g94.c index 12b3e01fc..6dcda55fb 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/g94.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/g94.c @@ -26,21 +26,23 @@ void g94_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo) { - u32 intr0 = nv_rd32(gpio, 0x00e054); - u32 intr1 = nv_rd32(gpio, 0x00e074); - u32 stat0 = nv_rd32(gpio, 0x00e050) & intr0; - u32 stat1 = nv_rd32(gpio, 0x00e070) & intr1; + struct nvkm_device *device = gpio->subdev.device; + u32 intr0 = nvkm_rd32(device, 0x00e054); + u32 intr1 = nvkm_rd32(device, 0x00e074); + u32 stat0 = nvkm_rd32(device, 0x00e050) & intr0; + u32 stat1 = nvkm_rd32(device, 0x00e070) & intr1; *lo = (stat1 & 0xffff0000) | (stat0 >> 16); *hi = (stat1 << 16) | (stat0 & 0x0000ffff); - nv_wr32(gpio, 0x00e054, intr0); - nv_wr32(gpio, 0x00e074, intr1); + nvkm_wr32(device, 0x00e054, intr0); + nvkm_wr32(device, 0x00e074, intr1); } void g94_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data) { - u32 inte0 = nv_rd32(gpio, 0x00e050); - u32 inte1 = nv_rd32(gpio, 0x00e070); + struct nvkm_device *device = gpio->subdev.device; + u32 inte0 = nvkm_rd32(device, 0x00e050); + u32 inte1 = nvkm_rd32(device, 0x00e070); if (type & NVKM_GPIO_LO) inte0 = (inte0 & ~(mask << 16)) | (data << 16); if (type & NVKM_GPIO_HI) @@ -51,23 +53,22 @@ g94_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data) inte1 = (inte1 & ~(mask << 16)) | (data << 16); if (type & NVKM_GPIO_HI) inte1 = (inte1 & ~mask) | data; - nv_wr32(gpio, 0x00e050, inte0); - nv_wr32(gpio, 0x00e070, inte1); + nvkm_wr32(device, 0x00e050, inte0); + nvkm_wr32(device, 0x00e070, inte1); } -struct nvkm_oclass * -g94_gpio_oclass = &(struct nvkm_gpio_impl) { - .base.handle = NV_SUBDEV(GPIO, 0x94), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_gpio_ctor, - .dtor = _nvkm_gpio_dtor, - .init = _nvkm_gpio_init, - .fini = _nvkm_gpio_fini, - }, +static const struct nvkm_gpio_func +g94_gpio = { .lines = 32, .intr_stat = g94_gpio_intr_stat, .intr_mask = g94_gpio_intr_mask, .drive = nv50_gpio_drive, .sense = nv50_gpio_sense, .reset = nv50_gpio_reset, -}.base; +}; + +int +g94_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio) +{ + return nvkm_gpio_new_(&g94_gpio, device, index, pgpio); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf110.c deleted file mode 100644 index 2c3bb255d..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf110.c +++ /dev/null @@ -1,84 +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 "priv.h" - -void -gf110_gpio_reset(struct nvkm_gpio *gpio, u8 match) -{ - struct nvkm_bios *bios = nvkm_bios(gpio); - u8 ver, len; - u16 entry; - int ent = -1; - - while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { - u32 data = nv_ro32(bios, entry); - u8 line = (data & 0x0000003f); - u8 defs = !!(data & 0x00000080); - u8 func = (data & 0x0000ff00) >> 8; - u8 unk0 = (data & 0x00ff0000) >> 16; - u8 unk1 = (data & 0x1f000000) >> 24; - - if ( func == DCB_GPIO_UNUSED || - (match != DCB_GPIO_UNUSED && match != func)) - continue; - - gpio->set(gpio, 0, func, line, defs); - - nv_mask(gpio, 0x00d610 + (line * 4), 0xff, unk0); - if (unk1--) - nv_mask(gpio, 0x00d740 + (unk1 * 4), 0xff, line); - } -} - -int -gf110_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out) -{ - u32 data = ((dir ^ 1) << 13) | (out << 12); - nv_mask(gpio, 0x00d610 + (line * 4), 0x00003000, data); - nv_mask(gpio, 0x00d604, 0x00000001, 0x00000001); /* update? */ - return 0; -} - -int -gf110_gpio_sense(struct nvkm_gpio *gpio, int line) -{ - return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); -} - -struct nvkm_oclass * -gf110_gpio_oclass = &(struct nvkm_gpio_impl) { - .base.handle = NV_SUBDEV(GPIO, 0xd0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_gpio_ctor, - .dtor = _nvkm_gpio_dtor, - .init = _nvkm_gpio_init, - .fini = _nvkm_gpio_fini, - }, - .lines = 32, - .intr_stat = g94_gpio_intr_stat, - .intr_mask = g94_gpio_intr_mask, - .drive = gf110_gpio_drive, - .sense = gf110_gpio_sense, - .reset = gf110_gpio_reset, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf119.c new file mode 100644 index 000000000..bb7400dfa --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gf119.c @@ -0,0 +1,86 @@ +/* + * 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 "priv.h" + +void +gf119_gpio_reset(struct nvkm_gpio *gpio, u8 match) +{ + struct nvkm_device *device = gpio->subdev.device; + struct nvkm_bios *bios = device->bios; + u8 ver, len; + u16 entry; + int ent = -1; + + while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { + u32 data = nvbios_rd32(bios, entry); + u8 line = (data & 0x0000003f); + u8 defs = !!(data & 0x00000080); + u8 func = (data & 0x0000ff00) >> 8; + u8 unk0 = (data & 0x00ff0000) >> 16; + u8 unk1 = (data & 0x1f000000) >> 24; + + if ( func == DCB_GPIO_UNUSED || + (match != DCB_GPIO_UNUSED && match != func)) + continue; + + nvkm_gpio_set(gpio, 0, func, line, defs); + + nvkm_mask(device, 0x00d610 + (line * 4), 0xff, unk0); + if (unk1--) + nvkm_mask(device, 0x00d740 + (unk1 * 4), 0xff, line); + } +} + +int +gf119_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out) +{ + struct nvkm_device *device = gpio->subdev.device; + u32 data = ((dir ^ 1) << 13) | (out << 12); + nvkm_mask(device, 0x00d610 + (line * 4), 0x00003000, data); + nvkm_mask(device, 0x00d604, 0x00000001, 0x00000001); /* update? */ + return 0; +} + +int +gf119_gpio_sense(struct nvkm_gpio *gpio, int line) +{ + struct nvkm_device *device = gpio->subdev.device; + return !!(nvkm_rd32(device, 0x00d610 + (line * 4)) & 0x00004000); +} + +static const struct nvkm_gpio_func +gf119_gpio = { + .lines = 32, + .intr_stat = g94_gpio_intr_stat, + .intr_mask = g94_gpio_intr_mask, + .drive = gf119_gpio_drive, + .sense = gf119_gpio_sense, + .reset = gf119_gpio_reset, +}; + +int +gf119_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio) +{ + return nvkm_gpio_new_(&gf119_gpio, device, index, pgpio); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c index 42fd2faaa..3f45afd17 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c @@ -26,21 +26,23 @@ static void gk104_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo) { - u32 intr0 = nv_rd32(gpio, 0x00dc00); - u32 intr1 = nv_rd32(gpio, 0x00dc80); - u32 stat0 = nv_rd32(gpio, 0x00dc08) & intr0; - u32 stat1 = nv_rd32(gpio, 0x00dc88) & intr1; + struct nvkm_device *device = gpio->subdev.device; + u32 intr0 = nvkm_rd32(device, 0x00dc00); + u32 intr1 = nvkm_rd32(device, 0x00dc80); + u32 stat0 = nvkm_rd32(device, 0x00dc08) & intr0; + u32 stat1 = nvkm_rd32(device, 0x00dc88) & intr1; *lo = (stat1 & 0xffff0000) | (stat0 >> 16); *hi = (stat1 << 16) | (stat0 & 0x0000ffff); - nv_wr32(gpio, 0x00dc00, intr0); - nv_wr32(gpio, 0x00dc80, intr1); + nvkm_wr32(device, 0x00dc00, intr0); + nvkm_wr32(device, 0x00dc80, intr1); } void gk104_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data) { - u32 inte0 = nv_rd32(gpio, 0x00dc08); - u32 inte1 = nv_rd32(gpio, 0x00dc88); + struct nvkm_device *device = gpio->subdev.device; + u32 inte0 = nvkm_rd32(device, 0x00dc08); + u32 inte1 = nvkm_rd32(device, 0x00dc88); if (type & NVKM_GPIO_LO) inte0 = (inte0 & ~(mask << 16)) | (data << 16); if (type & NVKM_GPIO_HI) @@ -51,23 +53,22 @@ gk104_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data) inte1 = (inte1 & ~(mask << 16)) | (data << 16); if (type & NVKM_GPIO_HI) inte1 = (inte1 & ~mask) | data; - nv_wr32(gpio, 0x00dc08, inte0); - nv_wr32(gpio, 0x00dc88, inte1); + nvkm_wr32(device, 0x00dc08, inte0); + nvkm_wr32(device, 0x00dc88, inte1); } -struct nvkm_oclass * -gk104_gpio_oclass = &(struct nvkm_gpio_impl) { - .base.handle = NV_SUBDEV(GPIO, 0xe0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_gpio_ctor, - .dtor = _nvkm_gpio_dtor, - .init = _nvkm_gpio_init, - .fini = _nvkm_gpio_fini, - }, +static const struct nvkm_gpio_func +gk104_gpio = { .lines = 32, .intr_stat = gk104_gpio_intr_stat, .intr_mask = gk104_gpio_intr_mask, - .drive = gf110_gpio_drive, - .sense = gf110_gpio_sense, - .reset = gf110_gpio_reset, -}.base; + .drive = gf119_gpio_drive, + .sense = gf119_gpio_sense, + .reset = gf119_gpio_reset, +}; + +int +gk104_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio) +{ + return nvkm_gpio_new_(&gk104_gpio, device, index, pgpio); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c index 2b2951542..ae3499b48 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv10.c @@ -28,19 +28,20 @@ static int nv10_gpio_sense(struct nvkm_gpio *gpio, int line) { + struct nvkm_device *device = gpio->subdev.device; if (line < 2) { line = line * 16; - line = nv_rd32(gpio, 0x600818) >> line; + line = nvkm_rd32(device, 0x600818) >> line; return !!(line & 0x0100); } else if (line < 10) { line = (line - 2) * 4; - line = nv_rd32(gpio, 0x60081c) >> line; + line = nvkm_rd32(device, 0x60081c) >> line; return !!(line & 0x04); } else if (line < 14) { line = (line - 10) * 4; - line = nv_rd32(gpio, 0x600850) >> line; + line = nvkm_rd32(device, 0x600850) >> line; return !!(line & 0x04); } @@ -50,6 +51,7 @@ nv10_gpio_sense(struct nvkm_gpio *gpio, int line) static int nv10_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out) { + struct nvkm_device *device = gpio->subdev.device; u32 reg, mask, data; if (line < 2) { @@ -73,43 +75,44 @@ nv10_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out) return -EINVAL; } - nv_mask(gpio, reg, mask << line, data << line); + nvkm_mask(device, reg, mask << line, data << line); return 0; } static void nv10_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo) { - u32 intr = nv_rd32(gpio, 0x001104); - u32 stat = nv_rd32(gpio, 0x001144) & intr; + struct nvkm_device *device = gpio->subdev.device; + u32 intr = nvkm_rd32(device, 0x001104); + u32 stat = nvkm_rd32(device, 0x001144) & intr; *lo = (stat & 0xffff0000) >> 16; *hi = (stat & 0x0000ffff); - nv_wr32(gpio, 0x001104, intr); + nvkm_wr32(device, 0x001104, intr); } static void nv10_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data) { - u32 inte = nv_rd32(gpio, 0x001144); + struct nvkm_device *device = gpio->subdev.device; + u32 inte = nvkm_rd32(device, 0x001144); if (type & NVKM_GPIO_LO) inte = (inte & ~(mask << 16)) | (data << 16); if (type & NVKM_GPIO_HI) inte = (inte & ~mask) | data; - nv_wr32(gpio, 0x001144, inte); + nvkm_wr32(device, 0x001144, inte); } -struct nvkm_oclass * -nv10_gpio_oclass = &(struct nvkm_gpio_impl) { - .base.handle = NV_SUBDEV(GPIO, 0x10), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_gpio_ctor, - .dtor = _nvkm_gpio_dtor, - .init = _nvkm_gpio_init, - .fini = _nvkm_gpio_fini, - }, +static const struct nvkm_gpio_func +nv10_gpio = { .lines = 16, .intr_stat = nv10_gpio_intr_stat, .intr_mask = nv10_gpio_intr_mask, .drive = nv10_gpio_drive, .sense = nv10_gpio_sense, -}.base; +}; + +int +nv10_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio) +{ + return nvkm_gpio_new_(&nv10_gpio, device, index, pgpio); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c index 6a031035b..73923fd5f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c @@ -26,14 +26,15 @@ void nv50_gpio_reset(struct nvkm_gpio *gpio, u8 match) { - struct nvkm_bios *bios = nvkm_bios(gpio); + struct nvkm_device *device = gpio->subdev.device; + struct nvkm_bios *bios = device->bios; u8 ver, len; u16 entry; int ent = -1; while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { static const u32 regs[] = { 0xe100, 0xe28c }; - u32 data = nv_ro32(bios, entry); + u32 data = nvbios_rd32(bios, entry); u8 line = (data & 0x0000001f); u8 func = (data & 0x0000ff00) >> 8; u8 defs = !!(data & 0x01000000); @@ -47,13 +48,13 @@ nv50_gpio_reset(struct nvkm_gpio *gpio, u8 match) (match != DCB_GPIO_UNUSED && match != func)) continue; - gpio->set(gpio, 0, func, line, defs); + nvkm_gpio_set(gpio, 0, func, line, defs); - nv_mask(gpio, reg, 0x00010001 << lsh, val << lsh); + nvkm_mask(device, reg, 0x00010001 << lsh, val << lsh); } } -int +static int nv50_gpio_location(int line, u32 *reg, u32 *shift) { const u32 nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; @@ -69,60 +70,63 @@ nv50_gpio_location(int line, u32 *reg, u32 *shift) int nv50_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out) { + struct nvkm_device *device = gpio->subdev.device; u32 reg, shift; if (nv50_gpio_location(line, ®, &shift)) return -EINVAL; - nv_mask(gpio, reg, 3 << shift, (((dir ^ 1) << 1) | out) << shift); + nvkm_mask(device, reg, 3 << shift, (((dir ^ 1) << 1) | out) << shift); return 0; } int nv50_gpio_sense(struct nvkm_gpio *gpio, int line) { + struct nvkm_device *device = gpio->subdev.device; u32 reg, shift; if (nv50_gpio_location(line, ®, &shift)) return -EINVAL; - return !!(nv_rd32(gpio, reg) & (4 << shift)); + return !!(nvkm_rd32(device, reg) & (4 << shift)); } static void nv50_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo) { - u32 intr = nv_rd32(gpio, 0x00e054); - u32 stat = nv_rd32(gpio, 0x00e050) & intr; + struct nvkm_device *device = gpio->subdev.device; + u32 intr = nvkm_rd32(device, 0x00e054); + u32 stat = nvkm_rd32(device, 0x00e050) & intr; *lo = (stat & 0xffff0000) >> 16; *hi = (stat & 0x0000ffff); - nv_wr32(gpio, 0x00e054, intr); + nvkm_wr32(device, 0x00e054, intr); } static void nv50_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data) { - u32 inte = nv_rd32(gpio, 0x00e050); + struct nvkm_device *device = gpio->subdev.device; + u32 inte = nvkm_rd32(device, 0x00e050); if (type & NVKM_GPIO_LO) inte = (inte & ~(mask << 16)) | (data << 16); if (type & NVKM_GPIO_HI) inte = (inte & ~mask) | data; - nv_wr32(gpio, 0x00e050, inte); + nvkm_wr32(device, 0x00e050, inte); } -struct nvkm_oclass * -nv50_gpio_oclass = &(struct nvkm_gpio_impl) { - .base.handle = NV_SUBDEV(GPIO, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_gpio_ctor, - .dtor = _nvkm_gpio_dtor, - .init = _nvkm_gpio_init, - .fini = _nvkm_gpio_fini, - }, +static const struct nvkm_gpio_func +nv50_gpio = { .lines = 16, .intr_stat = nv50_gpio_intr_stat, .intr_mask = nv50_gpio_intr_mask, .drive = nv50_gpio_drive, .sense = nv50_gpio_sense, .reset = nv50_gpio_reset, -}.base; +}; + +int +nv50_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio) +{ + return nvkm_gpio_new_(&nv50_gpio, device, index, pgpio); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h index 382f8d44e..371bcdbbe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h @@ -1,33 +1,9 @@ #ifndef __NVKM_GPIO_PRIV_H__ #define __NVKM_GPIO_PRIV_H__ +#define nvkm_gpio(p) container_of((p), struct nvkm_gpio, subdev) #include -#define nvkm_gpio_create(p,e,o,d) \ - nvkm_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_gpio_destroy(p) ({ \ - struct nvkm_gpio *gpio = (p); \ - _nvkm_gpio_dtor(nv_object(gpio)); \ -}) -#define nvkm_gpio_init(p) ({ \ - struct nvkm_gpio *gpio = (p); \ - _nvkm_gpio_init(nv_object(gpio)); \ -}) -#define nvkm_gpio_fini(p,s) ({ \ - struct nvkm_gpio *gpio = (p); \ - _nvkm_gpio_fini(nv_object(gpio), (s)); \ -}) - -int nvkm_gpio_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -int _nvkm_gpio_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void _nvkm_gpio_dtor(struct nvkm_object *); -int _nvkm_gpio_init(struct nvkm_object *); -int _nvkm_gpio_fini(struct nvkm_object *, bool); - -struct nvkm_gpio_impl { - struct nvkm_oclass base; +struct nvkm_gpio_func { int lines; /* read and ack pending interrupts, returning only data @@ -51,6 +27,9 @@ struct nvkm_gpio_impl { void (*reset)(struct nvkm_gpio *, u8); }; +int nvkm_gpio_new_(const struct nvkm_gpio_func *, struct nvkm_device *, + int index, struct nvkm_gpio **); + void nv50_gpio_reset(struct nvkm_gpio *, u8); int nv50_gpio_drive(struct nvkm_gpio *, int, int, int); int nv50_gpio_sense(struct nvkm_gpio *, int); @@ -58,7 +37,7 @@ int nv50_gpio_sense(struct nvkm_gpio *, int); void g94_gpio_intr_stat(struct nvkm_gpio *, u32 *, u32 *); void g94_gpio_intr_mask(struct nvkm_gpio *, u32, u32, u32); -void gf110_gpio_reset(struct nvkm_gpio *, u8); -int gf110_gpio_drive(struct nvkm_gpio *, int, int, int); -int gf110_gpio_sense(struct nvkm_gpio *, int); +void gf119_gpio_reset(struct nvkm_gpio *, u8); +int gf119_gpio_drive(struct nvkm_gpio *, int, int, int); +int gf119_gpio_sense(struct nvkm_gpio *, int); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild index d68307409..1f730613c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild @@ -1,16 +1,30 @@ nvkm-y += nvkm/subdev/i2c/base.o -nvkm-y += nvkm/subdev/i2c/anx9805.o -nvkm-y += nvkm/subdev/i2c/aux.o -nvkm-y += nvkm/subdev/i2c/bit.o -nvkm-y += nvkm/subdev/i2c/pad.o -nvkm-y += nvkm/subdev/i2c/padnv04.o -nvkm-y += nvkm/subdev/i2c/padg94.o -nvkm-y += nvkm/subdev/i2c/padgm204.o nvkm-y += nvkm/subdev/i2c/nv04.o nvkm-y += nvkm/subdev/i2c/nv4e.o nvkm-y += nvkm/subdev/i2c/nv50.o nvkm-y += nvkm/subdev/i2c/g94.o -nvkm-y += nvkm/subdev/i2c/gf110.o nvkm-y += nvkm/subdev/i2c/gf117.o +nvkm-y += nvkm/subdev/i2c/gf119.o nvkm-y += nvkm/subdev/i2c/gk104.o nvkm-y += nvkm/subdev/i2c/gm204.o + +nvkm-y += nvkm/subdev/i2c/pad.o +nvkm-y += nvkm/subdev/i2c/padnv04.o +nvkm-y += nvkm/subdev/i2c/padnv4e.o +nvkm-y += nvkm/subdev/i2c/padnv50.o +nvkm-y += nvkm/subdev/i2c/padg94.o +nvkm-y += nvkm/subdev/i2c/padgf119.o +nvkm-y += nvkm/subdev/i2c/padgm204.o + +nvkm-y += nvkm/subdev/i2c/bus.o +nvkm-y += nvkm/subdev/i2c/busnv04.o +nvkm-y += nvkm/subdev/i2c/busnv4e.o +nvkm-y += nvkm/subdev/i2c/busnv50.o +nvkm-y += nvkm/subdev/i2c/busgf119.o +nvkm-y += nvkm/subdev/i2c/bit.o + +nvkm-y += nvkm/subdev/i2c/aux.o +nvkm-y += nvkm/subdev/i2c/auxg94.o +nvkm-y += nvkm/subdev/i2c/auxgm204.o + +nvkm-y += nvkm/subdev/i2c/anx9805.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c index d17dd1cf3..b7b01c3f7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c @@ -21,272 +21,258 @@ * * Authors: Ben Skeggs */ -#include "port.h" +#define anx9805_pad(p) container_of((p), struct anx9805_pad, base) +#define anx9805_bus(p) container_of((p), struct anx9805_bus, base) +#define anx9805_aux(p) container_of((p), struct anx9805_aux, base) +#include "aux.h" +#include "bus.h" + +struct anx9805_pad { + struct nvkm_i2c_pad base; + struct nvkm_i2c_bus *bus; + u8 addr; +}; -struct anx9805_i2c_port { - struct nvkm_i2c_port base; - u32 addr; - u32 ctrl; +struct anx9805_bus { + struct nvkm_i2c_bus base; + struct anx9805_pad *pad; + u8 addr; }; static int -anx9805_train(struct nvkm_i2c_port *port, int link_nr, int link_bw, bool enh) +anx9805_bus_xfer(struct nvkm_i2c_bus *base, struct i2c_msg *msgs, int num) { - struct anx9805_i2c_port *chan = (void *)port; - struct nvkm_i2c_port *mast = (void *)nv_object(chan)->parent; - u8 tmp, i; - - DBG("ANX9805 train %d 0x%02x %d\n", link_nr, link_bw, enh); + struct anx9805_bus *bus = anx9805_bus(base); + struct anx9805_pad *pad = bus->pad; + struct i2c_adapter *adap = &pad->bus->i2c; + struct i2c_msg *msg = msgs; + int ret = -ETIMEDOUT; + int i, j, cnt = num; + u8 seg = 0x00, off = 0x00, tmp; - nv_wri2cr(mast, chan->addr, 0xa0, link_bw); - nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00)); - nv_wri2cr(mast, chan->addr, 0xa2, 0x01); - nv_wri2cr(mast, chan->addr, 0xa8, 0x01); + tmp = nvkm_rdi2cr(adap, pad->addr, 0x07) & ~0x10; + nvkm_wri2cr(adap, pad->addr, 0x07, tmp | 0x10); + nvkm_wri2cr(adap, pad->addr, 0x07, tmp); + nvkm_wri2cr(adap, bus->addr, 0x43, 0x05); + mdelay(5); - i = 0; - while ((tmp = nv_rdi2cr(mast, chan->addr, 0xa8)) & 0x01) { - mdelay(5); - if (i++ == 100) { - nv_error(port, "link training timed out\n"); - return -ETIMEDOUT; + while (cnt--) { + if ( (msg->flags & I2C_M_RD) && msg->addr == 0x50) { + nvkm_wri2cr(adap, bus->addr, 0x40, msg->addr << 1); + nvkm_wri2cr(adap, bus->addr, 0x41, seg); + nvkm_wri2cr(adap, bus->addr, 0x42, off); + nvkm_wri2cr(adap, bus->addr, 0x44, msg->len); + nvkm_wri2cr(adap, bus->addr, 0x45, 0x00); + nvkm_wri2cr(adap, bus->addr, 0x43, 0x01); + for (i = 0; i < msg->len; i++) { + j = 0; + while (nvkm_rdi2cr(adap, bus->addr, 0x46) & 0x10) { + mdelay(5); + if (j++ == 32) + goto done; + } + msg->buf[i] = nvkm_rdi2cr(adap, bus->addr, 0x47); + } + } else + if (!(msg->flags & I2C_M_RD)) { + if (msg->addr == 0x50 && msg->len == 0x01) { + off = msg->buf[0]; + } else + if (msg->addr == 0x30 && msg->len == 0x01) { + seg = msg->buf[0]; + } else + goto done; + } else { + goto done; } + msg++; } - if (tmp & 0x70) { - nv_error(port, "link training failed: 0x%02x\n", tmp); - return -EIO; + ret = num; +done: + nvkm_wri2cr(adap, bus->addr, 0x43, 0x00); + return ret; +} + +static const struct nvkm_i2c_bus_func +anx9805_bus_func = { + .xfer = anx9805_bus_xfer, +}; + +static int +anx9805_bus_new(struct nvkm_i2c_pad *base, int id, u8 drive, + struct nvkm_i2c_bus **pbus) +{ + struct anx9805_pad *pad = anx9805_pad(base); + struct anx9805_bus *bus; + int ret; + + if (!(bus = kzalloc(sizeof(*bus), GFP_KERNEL))) + return -ENOMEM; + *pbus = &bus->base; + bus->pad = pad; + + ret = nvkm_i2c_bus_ctor(&anx9805_bus_func, &pad->base, id, &bus->base); + if (ret) + return ret; + + switch (pad->addr) { + case 0x39: bus->addr = 0x3d; break; + case 0x3b: bus->addr = 0x3f; break; + default: + return -ENOSYS; } - return 1; + return 0; } +struct anx9805_aux { + struct nvkm_i2c_aux base; + struct anx9805_pad *pad; + u8 addr; +}; + static int -anx9805_aux(struct nvkm_i2c_port *port, bool retry, - u8 type, u32 addr, u8 *data, u8 size) +anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry, + u8 type, u32 addr, u8 *data, u8 size) { - struct anx9805_i2c_port *chan = (void *)port; - struct nvkm_i2c_port *mast = (void *)nv_object(chan)->parent; + struct anx9805_aux *aux = anx9805_aux(base); + struct anx9805_pad *pad = aux->pad; + struct i2c_adapter *adap = &pad->bus->i2c; int i, ret = -ETIMEDOUT; u8 buf[16] = {}; u8 tmp; - DBG("%02x %05x %d\n", type, addr, size); + AUX_DBG(&aux->base, "%02x %05x %d", type, addr, size); - tmp = nv_rdi2cr(mast, chan->ctrl, 0x07) & ~0x04; - nv_wri2cr(mast, chan->ctrl, 0x07, tmp | 0x04); - nv_wri2cr(mast, chan->ctrl, 0x07, tmp); - nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); + tmp = nvkm_rdi2cr(adap, pad->addr, 0x07) & ~0x04; + nvkm_wri2cr(adap, pad->addr, 0x07, tmp | 0x04); + nvkm_wri2cr(adap, pad->addr, 0x07, tmp); + nvkm_wri2cr(adap, pad->addr, 0xf7, 0x01); - nv_wri2cr(mast, chan->addr, 0xe4, 0x80); + nvkm_wri2cr(adap, aux->addr, 0xe4, 0x80); if (!(type & 1)) { memcpy(buf, data, size); - DBG("%16ph", buf); + AUX_DBG(&aux->base, "%16ph", buf); for (i = 0; i < size; i++) - nv_wri2cr(mast, chan->addr, 0xf0 + i, buf[i]); + nvkm_wri2cr(adap, aux->addr, 0xf0 + i, buf[i]); } - nv_wri2cr(mast, chan->addr, 0xe5, ((size - 1) << 4) | type); - nv_wri2cr(mast, chan->addr, 0xe6, (addr & 0x000ff) >> 0); - nv_wri2cr(mast, chan->addr, 0xe7, (addr & 0x0ff00) >> 8); - nv_wri2cr(mast, chan->addr, 0xe8, (addr & 0xf0000) >> 16); - nv_wri2cr(mast, chan->addr, 0xe9, 0x01); + nvkm_wri2cr(adap, aux->addr, 0xe5, ((size - 1) << 4) | type); + nvkm_wri2cr(adap, aux->addr, 0xe6, (addr & 0x000ff) >> 0); + nvkm_wri2cr(adap, aux->addr, 0xe7, (addr & 0x0ff00) >> 8); + nvkm_wri2cr(adap, aux->addr, 0xe8, (addr & 0xf0000) >> 16); + nvkm_wri2cr(adap, aux->addr, 0xe9, 0x01); i = 0; - while ((tmp = nv_rdi2cr(mast, chan->addr, 0xe9)) & 0x01) { + while ((tmp = nvkm_rdi2cr(adap, aux->addr, 0xe9)) & 0x01) { mdelay(5); if (i++ == 32) goto done; } - if ((tmp = nv_rdi2cr(mast, chan->ctrl, 0xf7)) & 0x01) { + if ((tmp = nvkm_rdi2cr(adap, pad->addr, 0xf7)) & 0x01) { ret = -EIO; goto done; } if (type & 1) { for (i = 0; i < size; i++) - buf[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); - DBG("%16ph", buf); + buf[i] = nvkm_rdi2cr(adap, aux->addr, 0xf0 + i); + AUX_DBG(&aux->base, "%16ph", buf); memcpy(data, buf, size); } ret = 0; done: - nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); + nvkm_wri2cr(adap, pad->addr, 0xf7, 0x01); return ret; } -static const struct nvkm_i2c_func -anx9805_aux_func = { - .aux = anx9805_aux, - .lnk_ctl = anx9805_train, -}; - static int -anx9805_aux_chan_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +anx9805_aux_lnk_ctl(struct nvkm_i2c_aux *base, + int link_nr, int link_bw, bool enh) { - struct nvkm_i2c_port *mast = (void *)parent; - struct anx9805_i2c_port *chan; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_aux_algo, &anx9805_aux_func, - &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - switch ((oclass->handle & 0xff00) >> 8) { - case 0x0d: - chan->addr = 0x38; - chan->ctrl = 0x39; - break; - case 0x0e: - chan->addr = 0x3c; - chan->ctrl = 0x3b; - break; - default: - BUG_ON(1); - } - - if (mast->adapter.algo == &i2c_bit_algo) { - struct i2c_algo_bit_data *algo = mast->adapter.algo_data; - algo->udelay = max(algo->udelay, 40); - } - - return 0; -} - -static struct nvkm_ofuncs -anx9805_aux_ofuncs = { - .ctor = anx9805_aux_chan_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, -}; + struct anx9805_aux *aux = anx9805_aux(base); + struct anx9805_pad *pad = aux->pad; + struct i2c_adapter *adap = &pad->bus->i2c; + u8 tmp, i; -static int -anx9805_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct anx9805_i2c_port *port = adap->algo_data; - struct nvkm_i2c_port *mast = (void *)nv_object(port)->parent; - struct i2c_msg *msg = msgs; - int ret = -ETIMEDOUT; - int i, j, cnt = num; - u8 seg = 0x00, off = 0x00, tmp; + AUX_DBG(&aux->base, "ANX9805 train %d %02x %d", + link_nr, link_bw, enh); - tmp = nv_rdi2cr(mast, port->ctrl, 0x07) & ~0x10; - nv_wri2cr(mast, port->ctrl, 0x07, tmp | 0x10); - nv_wri2cr(mast, port->ctrl, 0x07, tmp); - nv_wri2cr(mast, port->addr, 0x43, 0x05); - mdelay(5); + nvkm_wri2cr(adap, aux->addr, 0xa0, link_bw); + nvkm_wri2cr(adap, aux->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00)); + nvkm_wri2cr(adap, aux->addr, 0xa2, 0x01); + nvkm_wri2cr(adap, aux->addr, 0xa8, 0x01); - while (cnt--) { - if ( (msg->flags & I2C_M_RD) && msg->addr == 0x50) { - nv_wri2cr(mast, port->addr, 0x40, msg->addr << 1); - nv_wri2cr(mast, port->addr, 0x41, seg); - nv_wri2cr(mast, port->addr, 0x42, off); - nv_wri2cr(mast, port->addr, 0x44, msg->len); - nv_wri2cr(mast, port->addr, 0x45, 0x00); - nv_wri2cr(mast, port->addr, 0x43, 0x01); - for (i = 0; i < msg->len; i++) { - j = 0; - while (nv_rdi2cr(mast, port->addr, 0x46) & 0x10) { - mdelay(5); - if (j++ == 32) - goto done; - } - msg->buf[i] = nv_rdi2cr(mast, port->addr, 0x47); - } - } else - if (!(msg->flags & I2C_M_RD)) { - if (msg->addr == 0x50 && msg->len == 0x01) { - off = msg->buf[0]; - } else - if (msg->addr == 0x30 && msg->len == 0x01) { - seg = msg->buf[0]; - } else - goto done; - } else { - goto done; + i = 0; + while ((tmp = nvkm_rdi2cr(adap, aux->addr, 0xa8)) & 0x01) { + mdelay(5); + if (i++ == 100) { + AUX_ERR(&aux->base, "link training timeout"); + return -ETIMEDOUT; } - msg++; } - ret = num; -done: - nv_wri2cr(mast, port->addr, 0x43, 0x00); - return ret; -} + if (tmp & 0x70) { + AUX_ERR(&aux->base, "link training failed"); + return -EIO; + } -static u32 -anx9805_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return 0; } -static const struct i2c_algorithm -anx9805_i2c_algo = { - .master_xfer = anx9805_xfer, - .functionality = anx9805_func -}; - -static const struct nvkm_i2c_func -anx9805_i2c_func = { +static const struct nvkm_i2c_aux_func +anx9805_aux_func = { + .xfer = anx9805_aux_xfer, + .lnk_ctl = anx9805_aux_lnk_ctl, }; static int -anx9805_ddc_port_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +anx9805_aux_new(struct nvkm_i2c_pad *base, int id, u8 drive, + struct nvkm_i2c_aux **pbus) { - struct nvkm_i2c_port *mast = (void *)parent; - struct anx9805_i2c_port *port; + struct anx9805_pad *pad = anx9805_pad(base); + struct anx9805_aux *aux; int ret; - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &anx9805_i2c_algo, &anx9805_i2c_func, &port); - *pobject = nv_object(port); + if (!(aux = kzalloc(sizeof(*aux), GFP_KERNEL))) + return -ENOMEM; + *pbus = &aux->base; + aux->pad = pad; + + ret = nvkm_i2c_aux_ctor(&anx9805_aux_func, &pad->base, id, &aux->base); if (ret) return ret; - switch ((oclass->handle & 0xff00) >> 8) { - case 0x0d: - port->addr = 0x3d; - port->ctrl = 0x39; - break; - case 0x0e: - port->addr = 0x3f; - port->ctrl = 0x3b; - break; + switch (pad->addr) { + case 0x39: aux->addr = 0x38; break; + case 0x3b: aux->addr = 0x3c; break; default: - BUG_ON(1); - } - - if (mast->adapter.algo == &i2c_bit_algo) { - struct i2c_algo_bit_data *algo = mast->adapter.algo_data; - algo->udelay = max(algo->udelay, 40); + return -ENOSYS; } return 0; } -static struct nvkm_ofuncs -anx9805_ddc_ofuncs = { - .ctor = anx9805_ddc_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, +static const struct nvkm_i2c_pad_func +anx9805_pad_func = { + .bus_new_4 = anx9805_bus_new, + .aux_new_6 = anx9805_aux_new, }; -struct nvkm_oclass -nvkm_anx9805_sclass[] = { - { .handle = NV_I2C_TYPE_EXTDDC(0x0d), .ofuncs = &anx9805_ddc_ofuncs }, - { .handle = NV_I2C_TYPE_EXTAUX(0x0d), .ofuncs = &anx9805_aux_ofuncs }, - { .handle = NV_I2C_TYPE_EXTDDC(0x0e), .ofuncs = &anx9805_ddc_ofuncs }, - { .handle = NV_I2C_TYPE_EXTAUX(0x0e), .ofuncs = &anx9805_aux_ofuncs }, - {} -}; +int +anx9805_pad_new(struct nvkm_i2c_bus *bus, int id, u8 addr, + struct nvkm_i2c_pad **ppad) +{ + struct anx9805_pad *pad; + + if (!(pad = kzalloc(sizeof(*pad), GFP_KERNEL))) + return -ENOMEM; + *ppad = &pad->base; + + nvkm_i2c_pad_ctor(&anx9805_pad_func, bus->pad->i2c, id, &pad->base); + pad->bus = bus; + pad->addr = addr; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c index 1c18860f8..f0851d57d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c @@ -21,50 +21,17 @@ * * Authors: Ben Skeggs */ -#include "priv.h" - -int -nv_rdaux(struct nvkm_i2c_port *port, u32 addr, u8 *data, u8 size) -{ - struct nvkm_i2c *i2c = nvkm_i2c(port); - if (port->func->aux) { - int ret = i2c->acquire(port, 0); - if (ret == 0) { - ret = port->func->aux(port, true, 9, addr, data, size); - i2c->release(port); - } - return ret; - } - return -ENODEV; -} - -int -nv_wraux(struct nvkm_i2c_port *port, u32 addr, u8 *data, u8 size) -{ - struct nvkm_i2c *i2c = nvkm_i2c(port); - if (port->func->aux) { - int ret = i2c->acquire(port, 0); - if (ret == 0) { - ret = port->func->aux(port, true, 8, addr, data, size); - i2c->release(port); - } - return ret; - } - return -ENODEV; -} +#include "aux.h" +#include "pad.h" static int -aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { - struct nvkm_i2c_port *port = adap->algo_data; - struct nvkm_i2c *i2c = nvkm_i2c(port); + struct nvkm_i2c_aux *aux = container_of(adap, typeof(*aux), i2c); struct i2c_msg *msg = msgs; int ret, mcnt = num; - if (!port->func->aux) - return -ENODEV; - - ret = i2c->acquire(port, 0); + ret = nvkm_i2c_aux_acquire(aux); if (ret) return ret; @@ -84,9 +51,9 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (mcnt || remaining > 16) cmd |= 4; /* MOT */ - ret = port->func->aux(port, true, cmd, msg->addr, ptr, cnt); + ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, cnt); if (ret < 0) { - i2c->release(port); + nvkm_i2c_aux_release(aux); return ret; } @@ -97,17 +64,111 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) msg++; } - i2c->release(port); + nvkm_i2c_aux_release(aux); return num; } static u32 -aux_func(struct i2c_adapter *adap) +nvkm_i2c_aux_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } -const struct i2c_algorithm nvkm_i2c_aux_algo = { - .master_xfer = aux_xfer, - .functionality = aux_func +const struct i2c_algorithm +nvkm_i2c_aux_i2c_algo = { + .master_xfer = nvkm_i2c_aux_i2c_xfer, + .functionality = nvkm_i2c_aux_i2c_func }; + +void +nvkm_i2c_aux_monitor(struct nvkm_i2c_aux *aux, bool monitor) +{ + struct nvkm_i2c_pad *pad = aux->pad; + AUX_TRACE(aux, "monitor: %s", monitor ? "yes" : "no"); + if (monitor) + nvkm_i2c_pad_mode(pad, NVKM_I2C_PAD_AUX); + else + nvkm_i2c_pad_mode(pad, NVKM_I2C_PAD_OFF); +} + +void +nvkm_i2c_aux_release(struct nvkm_i2c_aux *aux) +{ + struct nvkm_i2c_pad *pad = aux->pad; + AUX_TRACE(aux, "release"); + nvkm_i2c_pad_release(pad); + mutex_unlock(&aux->mutex); +} + +int +nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *aux) +{ + struct nvkm_i2c_pad *pad = aux->pad; + int ret; + AUX_TRACE(aux, "acquire"); + mutex_lock(&aux->mutex); + ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_AUX); + if (ret) + mutex_unlock(&aux->mutex); + return ret; +} + +int +nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *aux, bool retry, u8 type, + u32 addr, u8 *data, u8 size) +{ + return aux->func->xfer(aux, retry, type, addr, data, size); +} + +int +nvkm_i2c_aux_lnk_ctl(struct nvkm_i2c_aux *aux, int nr, int bw, bool ef) +{ + if (aux->func->lnk_ctl) + return aux->func->lnk_ctl(aux, nr, bw, ef); + return -ENODEV; +} + +void +nvkm_i2c_aux_del(struct nvkm_i2c_aux **paux) +{ + struct nvkm_i2c_aux *aux = *paux; + if (aux && !WARN_ON(!aux->func)) { + AUX_TRACE(aux, "dtor"); + list_del(&aux->head); + i2c_del_adapter(&aux->i2c); + kfree(*paux); + *paux = NULL; + } +} + +int +nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *func, + struct nvkm_i2c_pad *pad, int id, + struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = pad->i2c->subdev.device; + + aux->func = func; + aux->pad = pad; + aux->id = id; + mutex_init(&aux->mutex); + list_add_tail(&aux->head, &pad->i2c->aux); + AUX_TRACE(aux, "ctor"); + + snprintf(aux->i2c.name, sizeof(aux->i2c.name), "nvkm-%s-aux-%04x", + dev_name(device->dev), id); + aux->i2c.owner = THIS_MODULE; + aux->i2c.dev.parent = device->dev; + aux->i2c.algo = &nvkm_i2c_aux_i2c_algo; + return i2c_add_adapter(&aux->i2c); +} + +int +nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *func, + struct nvkm_i2c_pad *pad, int id, + struct nvkm_i2c_aux **paux) +{ + if (!(*paux = kzalloc(sizeof(**paux), GFP_KERNEL))) + return -ENOMEM; + return nvkm_i2c_aux_ctor(func, pad, id, *paux); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h new file mode 100644 index 000000000..35a892e4a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h @@ -0,0 +1,30 @@ +#ifndef __NVKM_I2C_AUX_H__ +#define __NVKM_I2C_AUX_H__ +#include "pad.h" + +struct nvkm_i2c_aux_func { + int (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type, + u32 addr, u8 *data, u8 size); + int (*lnk_ctl)(struct nvkm_i2c_aux *, int link_nr, int link_bw, + bool enhanced_framing); +}; + +int nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *, + int id, struct nvkm_i2c_aux *); +int nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *, + int id, struct nvkm_i2c_aux **); +void nvkm_i2c_aux_del(struct nvkm_i2c_aux **); +int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, + u32 addr, u8 *data, u8 size); + +int g94_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **); +int gm204_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **); + +#define AUX_MSG(b,l,f,a...) do { \ + struct nvkm_i2c_aux *_aux = (b); \ + nvkm_##l(&_aux->pad->i2c->subdev, "aux %04x: "f"\n", _aux->id, ##a); \ +} while(0) +#define AUX_ERR(b,f,a...) AUX_MSG((b), error, f, ##a) +#define AUX_DBG(b,f,a...) AUX_MSG((b), debug, f, ##a) +#define AUX_TRACE(b,f,a...) AUX_MSG((b), trace, f, ##a) +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c new file mode 100644 index 000000000..954f5b76b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c @@ -0,0 +1,181 @@ +/* + * 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 busions 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 + */ +#define g94_i2c_aux(p) container_of((p), struct g94_i2c_aux, base) +#include "aux.h" + +struct g94_i2c_aux { + struct nvkm_i2c_aux base; + int ch; +}; + +static void +g94_i2c_aux_fini(struct g94_i2c_aux *aux) +{ + struct nvkm_device *device = aux->base.pad->i2c->subdev.device; + nvkm_mask(device, 0x00e4e4 + (aux->ch * 0x50), 0x00310000, 0x00000000); +} + +static int +g94_i2c_aux_init(struct g94_i2c_aux *aux) +{ + struct nvkm_device *device = aux->base.pad->i2c->subdev.device; + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; + + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { + ctrl = nvkm_rd32(device, 0x00e4e4 + (aux->ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR(&aux->base, "begin idle timeout %08x", ctrl); + return -EBUSY; + } + } while (ctrl & 0x03010000); + + /* set some magic, and wait up to 1ms for it to appear */ + nvkm_mask(device, 0x00e4e4 + (aux->ch * 0x50), 0x00300000, ureq); + timeout = 1000; + do { + ctrl = nvkm_rd32(device, 0x00e4e4 + (aux->ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR(&aux->base, "magic wait %08x", ctrl); + g94_i2c_aux_fini(aux); + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); + + return 0; +} + +static int +g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, + u8 type, u32 addr, u8 *data, u8 size) +{ + struct g94_i2c_aux *aux = g94_i2c_aux(obj); + struct nvkm_device *device = aux->base.pad->i2c->subdev.device; + const u32 base = aux->ch * 0x50; + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; + + AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, size); + + ret = g94_i2c_aux_init(aux); + if (ret < 0) + goto out; + + stat = nvkm_rd32(device, 0x00e4e8 + base); + if (!(stat & 0x10000000)) { + AUX_TRACE(&aux->base, "sink not detected"); + ret = -ENXIO; + goto out; + } + + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { + AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]); + nvkm_wr32(device, 0x00e4c0 + base + i, xbuf[i / 4]); + } + } + + ctrl = nvkm_rd32(device, 0x00e4e4 + base); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nvkm_wr32(device, 0x00e4e0 + base, addr); + + /* (maybe) retry transaction a number of times on failure... */ + for (retries = 0; !ret && retries < 32; retries++) { + /* reset, and delay a while if this is a retry */ + nvkm_wr32(device, 0x00e4e4 + base, 0x80000000 | ctrl); + nvkm_wr32(device, 0x00e4e4 + base, 0x00000000 | ctrl); + if (retries) + udelay(400); + + /* transaction request, wait up to 1ms for it to complete */ + nvkm_wr32(device, 0x00e4e4 + base, 0x00010000 | ctrl); + + timeout = 1000; + do { + ctrl = nvkm_rd32(device, 0x00e4e4 + base); + udelay(1); + if (!timeout--) { + AUX_ERR(&aux->base, "timeout %08x", ctrl); + ret = -EIO; + goto out; + } + } while (ctrl & 0x00010000); + ret = 1; + + /* read status, and check if transaction completed ok */ + stat = nvkm_mask(device, 0x00e4e8 + base, 0, 0); + if ((stat & 0x000f0000) == 0x00080000 || + (stat & 0x000f0000) == 0x00020000) + ret = retry ? 0 : 1; + if ((stat & 0x00000100)) + ret = -ETIMEDOUT; + if ((stat & 0x00000e00)) + ret = -EIO; + + AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat); + } + + if (type & 1) { + for (i = 0; i < 16; i += 4) { + xbuf[i / 4] = nvkm_rd32(device, 0x00e4d0 + base + i); + AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]); + } + memcpy(data, xbuf, size); + } + +out: + g94_i2c_aux_fini(aux); + return ret < 0 ? ret : (stat & 0x000f0000) >> 16; +} + +static const struct nvkm_i2c_aux_func +g94_i2c_aux_func = { + .xfer = g94_i2c_aux_xfer, +}; + +int +g94_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive, + struct nvkm_i2c_aux **paux) +{ + struct g94_i2c_aux *aux; + + if (!(aux = kzalloc(sizeof(*aux), GFP_KERNEL))) + return -ENOMEM; + *paux = &aux->base; + + nvkm_i2c_aux_ctor(&g94_i2c_aux_func, pad, index, &aux->base); + aux->ch = drive; + aux->base.intr = 1 << aux->ch; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c new file mode 100644 index 000000000..bed231b56 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm204.c @@ -0,0 +1,181 @@ +/* + * 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 busions 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 + */ +#define gm204_i2c_aux(p) container_of((p), struct gm204_i2c_aux, base) +#include "aux.h" + +struct gm204_i2c_aux { + struct nvkm_i2c_aux base; + int ch; +}; + +static void +gm204_i2c_aux_fini(struct gm204_i2c_aux *aux) +{ + struct nvkm_device *device = aux->base.pad->i2c->subdev.device; + nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00310000, 0x00000000); +} + +static int +gm204_i2c_aux_init(struct gm204_i2c_aux *aux) +{ + struct nvkm_device *device = aux->base.pad->i2c->subdev.device; + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; + + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { + ctrl = nvkm_rd32(device, 0x00d954 + (aux->ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR(&aux->base, "begin idle timeout %08x", ctrl); + return -EBUSY; + } + } while (ctrl & 0x03010000); + + /* set some magic, and wait up to 1ms for it to appear */ + nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00300000, ureq); + timeout = 1000; + do { + ctrl = nvkm_rd32(device, 0x00d954 + (aux->ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR(&aux->base, "magic wait %08x", ctrl); + gm204_i2c_aux_fini(aux); + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); + + return 0; +} + +static int +gm204_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, + u8 type, u32 addr, u8 *data, u8 size) +{ + struct gm204_i2c_aux *aux = gm204_i2c_aux(obj); + struct nvkm_device *device = aux->base.pad->i2c->subdev.device; + const u32 base = aux->ch * 0x50; + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; + + AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, size); + + ret = gm204_i2c_aux_init(aux); + if (ret < 0) + goto out; + + stat = nvkm_rd32(device, 0x00d958 + base); + if (!(stat & 0x10000000)) { + AUX_TRACE(&aux->base, "sink not detected"); + ret = -ENXIO; + goto out; + } + + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { + AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]); + nvkm_wr32(device, 0x00d930 + base + i, xbuf[i / 4]); + } + } + + ctrl = nvkm_rd32(device, 0x00d954 + base); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nvkm_wr32(device, 0x00d950 + base, addr); + + /* (maybe) retry transaction a number of times on failure... */ + for (retries = 0; !ret && retries < 32; retries++) { + /* reset, and delay a while if this is a retry */ + nvkm_wr32(device, 0x00d954 + base, 0x80000000 | ctrl); + nvkm_wr32(device, 0x00d954 + base, 0x00000000 | ctrl); + if (retries) + udelay(400); + + /* transaction request, wait up to 1ms for it to complete */ + nvkm_wr32(device, 0x00d954 + base, 0x00010000 | ctrl); + + timeout = 1000; + do { + ctrl = nvkm_rd32(device, 0x00d954 + base); + udelay(1); + if (!timeout--) { + AUX_ERR(&aux->base, "timeout %08x", ctrl); + ret = -EIO; + goto out; + } + } while (ctrl & 0x00010000); + ret = 1; + + /* read status, and check if transaction completed ok */ + stat = nvkm_mask(device, 0x00d958 + base, 0, 0); + if ((stat & 0x000f0000) == 0x00080000 || + (stat & 0x000f0000) == 0x00020000) + ret = retry ? 0 : 1; + if ((stat & 0x00000100)) + ret = -ETIMEDOUT; + if ((stat & 0x00000e00)) + ret = -EIO; + + AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat); + } + + if (type & 1) { + for (i = 0; i < 16; i += 4) { + xbuf[i / 4] = nvkm_rd32(device, 0x00d940 + base + i); + AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]); + } + memcpy(data, xbuf, size); + } + +out: + gm204_i2c_aux_fini(aux); + return ret < 0 ? ret : (stat & 0x000f0000) >> 16; +} + +static const struct nvkm_i2c_aux_func +gm204_i2c_aux_func = { + .xfer = gm204_i2c_aux_xfer, +}; + +int +gm204_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive, + struct nvkm_i2c_aux **paux) +{ + struct gm204_i2c_aux *aux; + + if (!(aux = kzalloc(sizeof(*aux), GFP_KERNEL))) + return -ENOMEM; + *paux = &aux->base; + + nvkm_i2c_aux_ctor(&gm204_i2c_aux_func, pad, index, &aux->base); + aux->ch = drive; + aux->base.intr = 1 << aux->ch; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 9200f122c..243a71ff0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -22,328 +22,91 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "aux.h" +#include "bus.h" #include "pad.h" -#include #include #include #include #include +#include -/****************************************************************************** - * interface to linux i2c bit-banging algorithm - *****************************************************************************/ - -#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT -#define CSTMSEL true -#else -#define CSTMSEL false -#endif - -static int -nvkm_i2c_pre_xfer(struct i2c_adapter *adap) +static struct nvkm_i2c_pad * +nvkm_i2c_pad_find(struct nvkm_i2c *i2c, int id) { - struct i2c_algo_bit_data *bit = adap->algo_data; - struct nvkm_i2c_port *port = bit->data; - return nvkm_i2c(port)->acquire(port, bit->timeout); -} + struct nvkm_i2c_pad *pad; -static void -nvkm_i2c_post_xfer(struct i2c_adapter *adap) -{ - struct i2c_algo_bit_data *bit = adap->algo_data; - struct nvkm_i2c_port *port = bit->data; - return nvkm_i2c(port)->release(port); -} - -static void -nvkm_i2c_setscl(void *data, int state) -{ - struct nvkm_i2c_port *port = data; - port->func->drive_scl(port, state); -} - -static void -nvkm_i2c_setsda(void *data, int state) -{ - struct nvkm_i2c_port *port = data; - port->func->drive_sda(port, state); -} - -static int -nvkm_i2c_getscl(void *data) -{ - struct nvkm_i2c_port *port = data; - return port->func->sense_scl(port); -} - -static int -nvkm_i2c_getsda(void *data) -{ - struct nvkm_i2c_port *port = data; - return port->func->sense_sda(port); -} - -/****************************************************************************** - * base i2c "port" class implementation - *****************************************************************************/ - -int -_nvkm_i2c_port_fini(struct nvkm_object *object, bool suspend) -{ - struct nvkm_i2c_port *port = (void *)object; - struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); - nv_ofuncs(pad)->fini(nv_object(pad), suspend); - return nvkm_object_fini(&port->base, suspend); -} - -void -_nvkm_i2c_port_dtor(struct nvkm_object *object) -{ - struct nvkm_i2c_port *port = (void *)object; - i2c_del_adapter(&port->adapter); - nvkm_object_destroy(&port->base); -} - -int -nvkm_i2c_port_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u8 index, - const struct i2c_algorithm *algo, - const struct nvkm_i2c_func *func, - int size, void **pobject) -{ - struct nvkm_device *device = nv_device(parent); - struct nvkm_i2c *i2c = nvkm_i2c(parent); - struct nvkm_i2c_port *port; - int ret; - - ret = nvkm_object_create_(parent, engine, oclass, 0, size, pobject); - port = *pobject; - if (ret) - return ret; - - snprintf(port->adapter.name, sizeof(port->adapter.name), - "nvkm-%s-%d", device->name, index); - port->adapter.owner = THIS_MODULE; - port->adapter.dev.parent = nv_device_base(device); - port->index = index; - port->aux = -1; - port->func = func; - mutex_init(&port->mutex); - - if ( algo == &nvkm_i2c_bit_algo && - !nvkm_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) { - struct i2c_algo_bit_data *bit; - - bit = kzalloc(sizeof(*bit), GFP_KERNEL); - if (!bit) - return -ENOMEM; - - bit->udelay = 10; - bit->timeout = usecs_to_jiffies(2200); - bit->data = port; - bit->pre_xfer = nvkm_i2c_pre_xfer; - bit->post_xfer = nvkm_i2c_post_xfer; - bit->setsda = nvkm_i2c_setsda; - bit->setscl = nvkm_i2c_setscl; - bit->getsda = nvkm_i2c_getsda; - bit->getscl = nvkm_i2c_getscl; - - port->adapter.algo_data = bit; - ret = i2c_bit_add_bus(&port->adapter); - } else { - port->adapter.algo_data = port; - port->adapter.algo = algo; - ret = i2c_add_adapter(&port->adapter); + list_for_each_entry(pad, &i2c->pad, head) { + if (pad->id == id) + return pad; } - if (ret == 0) - list_add_tail(&port->head, &i2c->ports); - return ret; + return NULL; } -/****************************************************************************** - * base i2c subdev class implementation - *****************************************************************************/ - -static struct nvkm_i2c_port * -nvkm_i2c_find(struct nvkm_i2c *i2c, u8 index) +struct nvkm_i2c_bus * +nvkm_i2c_bus_find(struct nvkm_i2c *i2c, int id) { - struct nvkm_bios *bios = nvkm_bios(i2c); - struct nvkm_i2c_port *port; + struct nvkm_bios *bios = i2c->subdev.device->bios; + struct nvkm_i2c_bus *bus; - if (index == NV_I2C_DEFAULT(0) || - index == NV_I2C_DEFAULT(1)) { + if (id == NVKM_I2C_BUS_PRI || id == NVKM_I2C_BUS_SEC) { u8 ver, hdr, cnt, len; u16 i2c = dcb_i2c_table(bios, &ver, &hdr, &cnt, &len); if (i2c && ver >= 0x30) { - u8 auxidx = nv_ro08(bios, i2c + 4); - if (index == NV_I2C_DEFAULT(0)) - index = (auxidx & 0x0f) >> 0; + u8 auxidx = nvbios_rd08(bios, i2c + 4); + if (id == NVKM_I2C_BUS_PRI) + id = NVKM_I2C_BUS_CCB((auxidx & 0x0f) >> 0); else - index = (auxidx & 0xf0) >> 4; + id = NVKM_I2C_BUS_CCB((auxidx & 0xf0) >> 4); } else { - index = 2; + id = NVKM_I2C_BUS_CCB(2); } } - list_for_each_entry(port, &i2c->ports, head) { - if (port->index == index) - return port; + list_for_each_entry(bus, &i2c->bus, head) { + if (bus->id == id) + return bus; } return NULL; } -static struct nvkm_i2c_port * -nvkm_i2c_find_type(struct nvkm_i2c *i2c, u16 type) +struct nvkm_i2c_aux * +nvkm_i2c_aux_find(struct nvkm_i2c *i2c, int id) { - struct nvkm_i2c_port *port; + struct nvkm_i2c_aux *aux; - list_for_each_entry(port, &i2c->ports, head) { - if (nv_hclass(port) == type) - return port; + list_for_each_entry(aux, &i2c->aux, head) { + if (aux->id == id) + return aux; } return NULL; } static void -nvkm_i2c_release_pad(struct nvkm_i2c_port *port) -{ - struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); - struct nvkm_i2c *i2c = nvkm_i2c(port); - - if (atomic_dec_and_test(&nv_object(pad)->usecount)) { - nv_ofuncs(pad)->fini(nv_object(pad), false); - wake_up_all(&i2c->wait); - } -} - -static int -nvkm_i2c_try_acquire_pad(struct nvkm_i2c_port *port) -{ - struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); - - if (atomic_add_return(1, &nv_object(pad)->usecount) != 1) { - struct nvkm_object *owner = (void *)pad->port; - do { - if (owner == (void *)port) - return 0; - owner = owner->parent; - } while(owner); - nvkm_i2c_release_pad(port); - return -EBUSY; - } - - pad->next = port; - nv_ofuncs(pad)->init(nv_object(pad)); - return 0; -} - -static int -nvkm_i2c_acquire_pad(struct nvkm_i2c_port *port, unsigned long timeout) -{ - struct nvkm_i2c *i2c = nvkm_i2c(port); - - if (timeout) { - if (wait_event_timeout(i2c->wait, - nvkm_i2c_try_acquire_pad(port) == 0, - timeout) == 0) - return -EBUSY; - } else { - wait_event(i2c->wait, nvkm_i2c_try_acquire_pad(port) == 0); - } - - return 0; -} - -static void -nvkm_i2c_release(struct nvkm_i2c_port *port) -__releases(pad->mutex) -{ - nvkm_i2c(port)->release_pad(port); - mutex_unlock(&port->mutex); -} - -static int -nvkm_i2c_acquire(struct nvkm_i2c_port *port, unsigned long timeout) -__acquires(pad->mutex) -{ - int ret; - mutex_lock(&port->mutex); - if ((ret = nvkm_i2c(port)->acquire_pad(port, timeout))) - mutex_unlock(&port->mutex); - return ret; -} - -static int -nvkm_i2c_identify(struct nvkm_i2c *i2c, int index, const char *what, - struct nvkm_i2c_board_info *info, - bool (*match)(struct nvkm_i2c_port *, - struct i2c_board_info *, void *), void *data) -{ - struct nvkm_i2c_port *port = nvkm_i2c_find(i2c, index); - int i; - - if (!port) { - nv_debug(i2c, "no bus when probing %s on %d\n", what, index); - return -ENODEV; - } - - nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index); - for (i = 0; info[i].dev.addr; i++) { - u8 orig_udelay = 0; - - if ((port->adapter.algo == &i2c_bit_algo) && - (info[i].udelay != 0)) { - struct i2c_algo_bit_data *algo = port->adapter.algo_data; - nv_debug(i2c, "using custom udelay %d instead of %d\n", - info[i].udelay, algo->udelay); - orig_udelay = algo->udelay; - algo->udelay = info[i].udelay; - } - - if (nv_probe_i2c(port, info[i].dev.addr) && - (!match || match(port, &info[i].dev, data))) { - nv_info(i2c, "detected %s: %s\n", what, - info[i].dev.type); - return i; - } - - if (orig_udelay) { - struct i2c_algo_bit_data *algo = port->adapter.algo_data; - algo->udelay = orig_udelay; - } - } - - nv_debug(i2c, "no devices found.\n"); - return -ENODEV; -} - -static void -nvkm_i2c_intr_fini(struct nvkm_event *event, int type, int index) +nvkm_i2c_intr_fini(struct nvkm_event *event, int type, int id) { struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event); - struct nvkm_i2c_port *port = i2c->find(i2c, index); - const struct nvkm_i2c_impl *impl = (void *)nv_object(i2c)->oclass; - if (port && port->aux >= 0) - impl->aux_mask(i2c, type, 1 << port->aux, 0); + struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id); + if (aux) + i2c->func->aux_mask(i2c, type, aux->intr, 0); } static void -nvkm_i2c_intr_init(struct nvkm_event *event, int type, int index) +nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id) { struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event); - struct nvkm_i2c_port *port = i2c->find(i2c, index); - const struct nvkm_i2c_impl *impl = (void *)nv_object(i2c)->oclass; - if (port && port->aux >= 0) - impl->aux_mask(i2c, type, 1 << port->aux, 1 << port->aux); + struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id); + if (aux) + i2c->func->aux_mask(i2c, type, aux->intr, aux->intr); } static int nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) + struct nvkm_notify *notify) { struct nvkm_i2c_ntfy_req *req = data; if (!WARN_ON(size != sizeof(*req))) { @@ -355,38 +118,6 @@ nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size, return -EINVAL; } -static void -nvkm_i2c_intr(struct nvkm_subdev *subdev) -{ - struct nvkm_i2c_impl *impl = (void *)nv_oclass(subdev); - struct nvkm_i2c *i2c = nvkm_i2c(subdev); - struct nvkm_i2c_port *port; - u32 hi, lo, rq, tx, e; - - if (impl->aux_stat) { - impl->aux_stat(i2c, &hi, &lo, &rq, &tx); - if (hi || lo || rq || tx) { - list_for_each_entry(port, &i2c->ports, head) { - if (e = 0, port->aux < 0) - continue; - - if (hi & (1 << port->aux)) e |= NVKM_I2C_PLUG; - if (lo & (1 << port->aux)) e |= NVKM_I2C_UNPLUG; - if (rq & (1 << port->aux)) e |= NVKM_I2C_IRQ; - if (tx & (1 << port->aux)) e |= NVKM_I2C_DONE; - if (e) { - struct nvkm_i2c_ntfy_rep rep = { - .mask = e, - }; - nvkm_event_send(&i2c->event, rep.mask, - port->index, &rep, - sizeof(rep)); - } - } - } - } -} - static const struct nvkm_event_func nvkm_i2c_intr_func = { .ctor = nvkm_i2c_intr_ctor, @@ -394,229 +125,272 @@ nvkm_i2c_intr_func = { .fini = nvkm_i2c_intr_fini, }; -int -_nvkm_i2c_fini(struct nvkm_object *object, bool suspend) +static void +nvkm_i2c_intr(struct nvkm_subdev *subdev) { - struct nvkm_i2c_impl *impl = (void *)nv_oclass(object); - struct nvkm_i2c *i2c = (void *)object; - struct nvkm_i2c_port *port; - u32 mask; - int ret; + struct nvkm_i2c *i2c = nvkm_i2c(subdev); + struct nvkm_i2c_aux *aux; + u32 hi, lo, rq, tx; + + if (!i2c->func->aux_stat) + return; + + i2c->func->aux_stat(i2c, &hi, &lo, &rq, &tx); + if (!hi && !lo && !rq && !tx) + return; - list_for_each_entry(port, &i2c->ports, head) { - ret = nv_ofuncs(port)->fini(nv_object(port), suspend); - if (ret && suspend) - goto fail; + list_for_each_entry(aux, &i2c->aux, head) { + u32 mask = 0; + if (hi & aux->intr) mask |= NVKM_I2C_PLUG; + if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG; + if (rq & aux->intr) mask |= NVKM_I2C_IRQ; + if (tx & aux->intr) mask |= NVKM_I2C_DONE; + if (mask) { + struct nvkm_i2c_ntfy_rep rep = { + .mask = mask, + }; + nvkm_event_send(&i2c->event, rep.mask, aux->id, + &rep, sizeof(rep)); + } } +} + +static int +nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend) +{ + struct nvkm_i2c *i2c = nvkm_i2c(subdev); + struct nvkm_i2c_pad *pad; + u32 mask; - if ((mask = (1 << impl->aux) - 1), impl->aux_stat) { - impl->aux_mask(i2c, NVKM_I2C_ANY, mask, 0); - impl->aux_stat(i2c, &mask, &mask, &mask, &mask); + if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) { + i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0); + i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask); } - return nvkm_subdev_fini(&i2c->base, suspend); -fail: - list_for_each_entry_continue_reverse(port, &i2c->ports, head) { - nv_ofuncs(port)->init(nv_object(port)); + list_for_each_entry(pad, &i2c->pad, head) { + nvkm_i2c_pad_fini(pad); } - return ret; + return 0; } -int -_nvkm_i2c_init(struct nvkm_object *object) +static int +nvkm_i2c_init(struct nvkm_subdev *subdev) { - struct nvkm_i2c *i2c = (void *)object; - struct nvkm_i2c_port *port; - int ret; - - ret = nvkm_subdev_init(&i2c->base); - if (ret == 0) { - list_for_each_entry(port, &i2c->ports, head) { - ret = nv_ofuncs(port)->init(nv_object(port)); - if (ret) - goto fail; - } + struct nvkm_i2c *i2c = nvkm_i2c(subdev); + struct nvkm_i2c_bus *bus; + struct nvkm_i2c_pad *pad; + + list_for_each_entry(pad, &i2c->pad, head) { + nvkm_i2c_pad_init(pad); } - return ret; -fail: - list_for_each_entry_continue_reverse(port, &i2c->ports, head) { - nv_ofuncs(port)->fini(nv_object(port), false); + list_for_each_entry(bus, &i2c->bus, head) { + nvkm_i2c_bus_init(bus); } - return ret; + return 0; } -void -_nvkm_i2c_dtor(struct nvkm_object *object) +static void * +nvkm_i2c_dtor(struct nvkm_subdev *subdev) { - struct nvkm_i2c *i2c = (void *)object; - struct nvkm_i2c_port *port, *temp; + struct nvkm_i2c *i2c = nvkm_i2c(subdev); nvkm_event_fini(&i2c->event); - list_for_each_entry_safe(port, temp, &i2c->ports, head) { - nvkm_object_ref(NULL, (struct nvkm_object **)&port); + while (!list_empty(&i2c->aux)) { + struct nvkm_i2c_aux *aux = + list_first_entry(&i2c->aux, typeof(*aux), head); + nvkm_i2c_aux_del(&aux); } - nvkm_subdev_destroy(&i2c->base); -} - -static struct nvkm_oclass * -nvkm_i2c_extdev_sclass[] = { - nvkm_anx9805_sclass, -}; + while (!list_empty(&i2c->bus)) { + struct nvkm_i2c_bus *bus = + list_first_entry(&i2c->bus, typeof(*bus), head); + nvkm_i2c_bus_del(&bus); + } -static void -nvkm_i2c_create_port(struct nvkm_i2c *i2c, int index, u8 type, - struct dcb_i2c_entry *info) -{ - const struct nvkm_i2c_impl *impl = (void *)nv_oclass(i2c); - struct nvkm_oclass *oclass; - struct nvkm_object *parent; - struct nvkm_object *object; - int ret, pad; - - if (info->share != DCB_I2C_UNUSED) { - pad = info->share; - oclass = impl->pad_s; - } else { - if (type != DCB_I2C_NVIO_AUX) - pad = 0x100 + info->drive; - else - pad = 0x100 + info->auxch; - oclass = impl->pad_x; + while (!list_empty(&i2c->pad)) { + struct nvkm_i2c_pad *pad = + list_first_entry(&i2c->pad, typeof(*pad), head); + nvkm_i2c_pad_del(&pad); } - ret = nvkm_object_ctor(nv_object(i2c), NULL, oclass, - NULL, pad, &parent); - if (ret < 0) - return; + return i2c; +} - oclass = impl->sclass; - do { - ret = -EINVAL; - if (oclass->handle == type) { - ret = nvkm_object_ctor(parent, NULL, oclass, - info, index, &object); - } - } while (ret && (++oclass)->handle); +static const struct nvkm_subdev_func +nvkm_i2c = { + .dtor = nvkm_i2c_dtor, + .init = nvkm_i2c_init, + .fini = nvkm_i2c_fini, + .intr = nvkm_i2c_intr, +}; - nvkm_object_ref(NULL, &parent); +static const struct nvkm_i2c_drv { + u8 bios; + u8 addr; + int (*pad_new)(struct nvkm_i2c_bus *, int id, u8 addr, + struct nvkm_i2c_pad **); } +nvkm_i2c_drv[] = { + { 0x0d, 0x39, anx9805_pad_new }, + { 0x0e, 0x3b, anx9805_pad_new }, + {} +}; int -nvkm_i2c_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, + int index, struct nvkm_i2c **pi2c) { - struct nvkm_bios *bios = nvkm_bios(parent); + struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c; - struct nvkm_object *object; - struct dcb_i2c_entry info; - int ret, i, j, index = -1; - struct dcb_output outp; - u8 ver, hdr; - u32 data; - - ret = nvkm_subdev_create(parent, engine, oclass, 0, "I2C", "i2c", &i2c); - *pobject = nv_object(i2c); - if (ret) - return ret; - - nv_subdev(i2c)->intr = nvkm_i2c_intr; - i2c->find = nvkm_i2c_find; - i2c->find_type = nvkm_i2c_find_type; - i2c->acquire_pad = nvkm_i2c_acquire_pad; - i2c->release_pad = nvkm_i2c_release_pad; - i2c->acquire = nvkm_i2c_acquire; - i2c->release = nvkm_i2c_release; - i2c->identify = nvkm_i2c_identify; - init_waitqueue_head(&i2c->wait); - INIT_LIST_HEAD(&i2c->ports); - - while (!dcb_i2c_parse(bios, ++index, &info)) { - switch (info.type) { - case DCB_I2C_NV04_BIT: - case DCB_I2C_NV4E_BIT: - case DCB_I2C_NVIO_BIT: - nvkm_i2c_create_port(i2c, NV_I2C_PORT(index), - info.type, &info); - break; - case DCB_I2C_NVIO_AUX: - nvkm_i2c_create_port(i2c, NV_I2C_AUX(index), - info.type, &info); - break; - case DCB_I2C_PMGR: - if (info.drive != DCB_I2C_UNUSED) { - nvkm_i2c_create_port(i2c, NV_I2C_PORT(index), - DCB_I2C_NVIO_BIT, &info); - } - if (info.auxch != DCB_I2C_UNUSED) { - nvkm_i2c_create_port(i2c, NV_I2C_AUX(index), - DCB_I2C_NVIO_AUX, &info); - } - break; - case DCB_I2C_UNUSED: - default: + struct dcb_i2c_entry ccbE; + struct dcb_output dcbE; + u8 ver, hdr; + int ret, i; + + if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_i2c, device, index, 0, &i2c->subdev); + i2c->func = func; + INIT_LIST_HEAD(&i2c->pad); + INIT_LIST_HEAD(&i2c->bus); + INIT_LIST_HEAD(&i2c->aux); + + i = -1; + while (!dcb_i2c_parse(bios, ++i, &ccbE)) { + struct nvkm_i2c_pad *pad = NULL; + struct nvkm_i2c_bus *bus = NULL; + struct nvkm_i2c_aux *aux = NULL; + + nvkm_debug(&i2c->subdev, "ccb %02x: type %02x drive %02x " + "sense %02x share %02x auxch %02x\n", i, ccbE.type, + ccbE.drive, ccbE.sense, ccbE.share, ccbE.auxch); + + if (ccbE.share != DCB_I2C_UNUSED) { + const int id = NVKM_I2C_PAD_HYBRID(ccbE.share); + if (!(pad = nvkm_i2c_pad_find(i2c, id))) + ret = func->pad_s_new(i2c, id, &pad); + else + ret = 0; + } else { + ret = func->pad_x_new(i2c, NVKM_I2C_PAD_CCB(i), &pad); + } + + if (ret) { + nvkm_error(&i2c->subdev, "ccb %02x pad, %d\n", i, ret); + nvkm_i2c_pad_del(&pad); + continue; + } + + if (pad->func->bus_new_0 && ccbE.type == DCB_I2C_NV04_BIT) { + ret = pad->func->bus_new_0(pad, NVKM_I2C_BUS_CCB(i), + ccbE.drive, + ccbE.sense, &bus); + } else + if (pad->func->bus_new_4 && + ( ccbE.type == DCB_I2C_NV4E_BIT || + ccbE.type == DCB_I2C_NVIO_BIT || + (ccbE.type == DCB_I2C_PMGR && + ccbE.drive != DCB_I2C_UNUSED))) { + ret = pad->func->bus_new_4(pad, NVKM_I2C_BUS_CCB(i), + ccbE.drive, &bus); + } + + if (ret) { + nvkm_error(&i2c->subdev, "ccb %02x bus, %d\n", i, ret); + nvkm_i2c_bus_del(&bus); + } + + if (pad->func->aux_new_6 && + ( ccbE.type == DCB_I2C_NVIO_AUX || + (ccbE.type == DCB_I2C_PMGR && + ccbE.auxch != DCB_I2C_UNUSED))) { + ret = pad->func->aux_new_6(pad, NVKM_I2C_BUS_CCB(i), + ccbE.auxch, &aux); + } else { + ret = 0; + } + + if (ret) { + nvkm_error(&i2c->subdev, "ccb %02x aux, %d\n", i, ret); + nvkm_i2c_aux_del(&aux); + } + + if (ccbE.type != DCB_I2C_UNUSED && !bus && !aux) { + nvkm_warn(&i2c->subdev, "ccb %02x was ignored\n", i); continue; } } - /* in addition to the busses specified in the i2c table, there - * may be ddc/aux channels hiding behind external tmds/dp/etc - * transmitters. - */ - index = NV_I2C_EXT(0); i = -1; - while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &outp))) { - if (!outp.location || !outp.extdev) + while (dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE)) { + const struct nvkm_i2c_drv *drv = nvkm_i2c_drv; + struct nvkm_i2c_bus *bus; + struct nvkm_i2c_pad *pad; + + /* internal outputs handled by native i2c busses (above) */ + if (!dcbE.location) continue; - switch (outp.type) { - case DCB_OUTPUT_TMDS: - info.type = NV_I2C_TYPE_EXTDDC(outp.extdev); - break; - case DCB_OUTPUT_DP: - info.type = NV_I2C_TYPE_EXTAUX(outp.extdev); - break; - default: + /* we need an i2c bus to talk to the external encoder */ + bus = nvkm_i2c_bus_find(i2c, dcbE.i2c_index); + if (!bus) { + nvkm_debug(&i2c->subdev, "dcb %02x no bus\n", i); continue; } - ret = -ENODEV; - j = -1; - while (ret && ++j < ARRAY_SIZE(nvkm_i2c_extdev_sclass)) { - parent = nv_object(i2c->find(i2c, outp.i2c_index)); - oclass = nvkm_i2c_extdev_sclass[j]; - do { - if (oclass->handle != info.type) - continue; - ret = nvkm_object_ctor(parent, NULL, oclass, - NULL, index++, &object); - } while (ret && (++oclass)->handle); + /* ... and a driver for it */ + while (drv->pad_new) { + if (drv->bios == dcbE.extdev) + break; + drv++; } - } - ret = nvkm_event_init(&nvkm_i2c_intr_func, 4, index, &i2c->event); - if (ret) - return ret; - - return 0; -} + if (!drv->pad_new) { + nvkm_debug(&i2c->subdev, "dcb %02x drv %02x unknown\n", + i, dcbE.extdev); + continue; + } -int -_nvkm_i2c_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_i2c *i2c; - int ret; + /* find/create an instance of the driver */ + pad = nvkm_i2c_pad_find(i2c, NVKM_I2C_PAD_EXT(dcbE.extdev)); + if (!pad) { + const int id = NVKM_I2C_PAD_EXT(dcbE.extdev); + ret = drv->pad_new(bus, id, drv->addr, &pad); + if (ret) { + nvkm_error(&i2c->subdev, "dcb %02x pad, %d\n", + i, ret); + nvkm_i2c_pad_del(&pad); + continue; + } + } - ret = nvkm_i2c_create(parent, engine, oclass, &i2c); - *pobject = nv_object(i2c); - if (ret) - return ret; + /* create any i2c bus / aux channel required by the output */ + if (pad->func->aux_new_6 && dcbE.type == DCB_OUTPUT_DP) { + const int id = NVKM_I2C_AUX_EXT(dcbE.extdev); + struct nvkm_i2c_aux *aux = NULL; + ret = pad->func->aux_new_6(pad, id, 0, &aux); + if (ret) { + nvkm_error(&i2c->subdev, "dcb %02x aux, %d\n", + i, ret); + nvkm_i2c_aux_del(&aux); + } + } else + if (pad->func->bus_new_4) { + const int id = NVKM_I2C_BUS_EXT(dcbE.extdev); + struct nvkm_i2c_bus *bus = NULL; + ret = pad->func->bus_new_4(pad, id, 0, &bus); + if (ret) { + nvkm_error(&i2c->subdev, "dcb %02x bus, %d\n", + i, ret); + nvkm_i2c_bus_del(&bus); + } + } + } - return 0; + return nvkm_event_init(&nvkm_i2c_intr_func, 4, i, &i2c->event); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c index 861a453d2..cdce11bba 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c @@ -9,7 +9,7 @@ * 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. + * all copies or substantial busions 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, @@ -21,7 +21,7 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "bus.h" #ifdef CONFIG_NOUVEAU_I2C_INTERNAL #define T_TIMEOUT 2200000 @@ -29,205 +29,188 @@ #define T_HOLD 5000 static inline void -i2c_drive_scl(struct nvkm_i2c_port *port, int state) +nvkm_i2c_drive_scl(struct nvkm_i2c_bus *bus, int state) { - port->func->drive_scl(port, state); + bus->func->drive_scl(bus, state); } static inline void -i2c_drive_sda(struct nvkm_i2c_port *port, int state) +nvkm_i2c_drive_sda(struct nvkm_i2c_bus *bus, int state) { - port->func->drive_sda(port, state); + bus->func->drive_sda(bus, state); } static inline int -i2c_sense_scl(struct nvkm_i2c_port *port) +nvkm_i2c_sense_scl(struct nvkm_i2c_bus *bus) { - return port->func->sense_scl(port); + return bus->func->sense_scl(bus); } static inline int -i2c_sense_sda(struct nvkm_i2c_port *port) +nvkm_i2c_sense_sda(struct nvkm_i2c_bus *bus) { - return port->func->sense_sda(port); + return bus->func->sense_sda(bus); } static void -i2c_delay(struct nvkm_i2c_port *port, u32 nsec) +nvkm_i2c_delay(struct nvkm_i2c_bus *bus, u32 nsec) { udelay((nsec + 500) / 1000); } static bool -i2c_raise_scl(struct nvkm_i2c_port *port) +nvkm_i2c_raise_scl(struct nvkm_i2c_bus *bus) { u32 timeout = T_TIMEOUT / T_RISEFALL; - i2c_drive_scl(port, 1); + nvkm_i2c_drive_scl(bus, 1); do { - i2c_delay(port, T_RISEFALL); - } while (!i2c_sense_scl(port) && --timeout); + nvkm_i2c_delay(bus, T_RISEFALL); + } while (!nvkm_i2c_sense_scl(bus) && --timeout); return timeout != 0; } static int -i2c_start(struct nvkm_i2c_port *port) +i2c_start(struct nvkm_i2c_bus *bus) { int ret = 0; - if (!i2c_sense_scl(port) || - !i2c_sense_sda(port)) { - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 1); - if (!i2c_raise_scl(port)) + if (!nvkm_i2c_sense_scl(bus) || + !nvkm_i2c_sense_sda(bus)) { + nvkm_i2c_drive_scl(bus, 0); + nvkm_i2c_drive_sda(bus, 1); + if (!nvkm_i2c_raise_scl(bus)) ret = -EBUSY; } - i2c_drive_sda(port, 0); - i2c_delay(port, T_HOLD); - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); + nvkm_i2c_drive_sda(bus, 0); + nvkm_i2c_delay(bus, T_HOLD); + nvkm_i2c_drive_scl(bus, 0); + nvkm_i2c_delay(bus, T_HOLD); return ret; } static void -i2c_stop(struct nvkm_i2c_port *port) +i2c_stop(struct nvkm_i2c_bus *bus) { - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 0); - i2c_delay(port, T_RISEFALL); - - i2c_drive_scl(port, 1); - i2c_delay(port, T_HOLD); - i2c_drive_sda(port, 1); - i2c_delay(port, T_HOLD); + nvkm_i2c_drive_scl(bus, 0); + nvkm_i2c_drive_sda(bus, 0); + nvkm_i2c_delay(bus, T_RISEFALL); + + nvkm_i2c_drive_scl(bus, 1); + nvkm_i2c_delay(bus, T_HOLD); + nvkm_i2c_drive_sda(bus, 1); + nvkm_i2c_delay(bus, T_HOLD); } static int -i2c_bitw(struct nvkm_i2c_port *port, int sda) +i2c_bitw(struct nvkm_i2c_bus *bus, int sda) { - i2c_drive_sda(port, sda); - i2c_delay(port, T_RISEFALL); + nvkm_i2c_drive_sda(bus, sda); + nvkm_i2c_delay(bus, T_RISEFALL); - if (!i2c_raise_scl(port)) + if (!nvkm_i2c_raise_scl(bus)) return -ETIMEDOUT; - i2c_delay(port, T_HOLD); + nvkm_i2c_delay(bus, T_HOLD); - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); + nvkm_i2c_drive_scl(bus, 0); + nvkm_i2c_delay(bus, T_HOLD); return 0; } static int -i2c_bitr(struct nvkm_i2c_port *port) +i2c_bitr(struct nvkm_i2c_bus *bus) { int sda; - i2c_drive_sda(port, 1); - i2c_delay(port, T_RISEFALL); + nvkm_i2c_drive_sda(bus, 1); + nvkm_i2c_delay(bus, T_RISEFALL); - if (!i2c_raise_scl(port)) + if (!nvkm_i2c_raise_scl(bus)) return -ETIMEDOUT; - i2c_delay(port, T_HOLD); + nvkm_i2c_delay(bus, T_HOLD); - sda = i2c_sense_sda(port); + sda = nvkm_i2c_sense_sda(bus); - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); + nvkm_i2c_drive_scl(bus, 0); + nvkm_i2c_delay(bus, T_HOLD); return sda; } static int -i2c_get_byte(struct nvkm_i2c_port *port, u8 *byte, bool last) +nvkm_i2c_get_byte(struct nvkm_i2c_bus *bus, u8 *byte, bool last) { int i, bit; *byte = 0; for (i = 7; i >= 0; i--) { - bit = i2c_bitr(port); + bit = i2c_bitr(bus); if (bit < 0) return bit; *byte |= bit << i; } - return i2c_bitw(port, last ? 1 : 0); + return i2c_bitw(bus, last ? 1 : 0); } static int -i2c_put_byte(struct nvkm_i2c_port *port, u8 byte) +nvkm_i2c_put_byte(struct nvkm_i2c_bus *bus, u8 byte) { int i, ret; for (i = 7; i >= 0; i--) { - ret = i2c_bitw(port, !!(byte & (1 << i))); + ret = i2c_bitw(bus, !!(byte & (1 << i))); if (ret < 0) return ret; } - ret = i2c_bitr(port); + ret = i2c_bitr(bus); if (ret == 1) /* nack */ ret = -EIO; return ret; } static int -i2c_addr(struct nvkm_i2c_port *port, struct i2c_msg *msg) +i2c_addr(struct nvkm_i2c_bus *bus, struct i2c_msg *msg) { u32 addr = msg->addr << 1; if (msg->flags & I2C_M_RD) addr |= 1; - return i2c_put_byte(port, addr); + return nvkm_i2c_put_byte(bus, addr); } -static int -i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +int +nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *bus, struct i2c_msg *msgs, int num) { - struct nvkm_i2c_port *port = adap->algo_data; struct i2c_msg *msg = msgs; int ret = 0, mcnt = num; - ret = nvkm_i2c(port)->acquire(port, nsecs_to_jiffies(T_TIMEOUT)); - if (ret) - return ret; - while (!ret && mcnt--) { u8 remaining = msg->len; u8 *ptr = msg->buf; - ret = i2c_start(port); + ret = i2c_start(bus); if (ret == 0) - ret = i2c_addr(port, msg); + ret = i2c_addr(bus, msg); if (msg->flags & I2C_M_RD) { while (!ret && remaining--) - ret = i2c_get_byte(port, ptr++, !remaining); + ret = nvkm_i2c_get_byte(bus, ptr++, !remaining); } else { while (!ret && remaining--) - ret = i2c_put_byte(port, *ptr++); + ret = nvkm_i2c_put_byte(bus, *ptr++); } msg++; } - i2c_stop(port); - nvkm_i2c(port)->release(port); + i2c_stop(bus); return (ret < 0) ? ret : num; } #else -static int -i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +int +nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *bus, struct i2c_msg *msgs, int num) { return -ENODEV; } #endif - -static u32 -i2c_bit_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -const struct i2c_algorithm nvkm_i2c_bit_algo = { - .master_xfer = i2c_bit_xfer, - .functionality = i2c_bit_func -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c new file mode 100644 index 000000000..807a2b67b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c @@ -0,0 +1,245 @@ +/* + * 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 + */ +#include "bus.h" +#include "pad.h" + +#include + +/******************************************************************************* + * i2c-algo-bit + ******************************************************************************/ +static int +nvkm_i2c_bus_pre_xfer(struct i2c_adapter *adap) +{ + struct nvkm_i2c_bus *bus = container_of(adap, typeof(*bus), i2c); + return nvkm_i2c_bus_acquire(bus); +} + +static void +nvkm_i2c_bus_post_xfer(struct i2c_adapter *adap) +{ + struct nvkm_i2c_bus *bus = container_of(adap, typeof(*bus), i2c); + return nvkm_i2c_bus_release(bus); +} + +static void +nvkm_i2c_bus_setscl(void *data, int state) +{ + struct nvkm_i2c_bus *bus = data; + bus->func->drive_scl(bus, state); +} + +static void +nvkm_i2c_bus_setsda(void *data, int state) +{ + struct nvkm_i2c_bus *bus = data; + bus->func->drive_sda(bus, state); +} + +static int +nvkm_i2c_bus_getscl(void *data) +{ + struct nvkm_i2c_bus *bus = data; + return bus->func->sense_scl(bus); +} + +static int +nvkm_i2c_bus_getsda(void *data) +{ + struct nvkm_i2c_bus *bus = data; + return bus->func->sense_sda(bus); +} + +/******************************************************************************* + * !i2c-algo-bit (off-chip i2c bus / hw i2c / internal bit-banging algo) + ******************************************************************************/ +static int +nvkm_i2c_bus_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct nvkm_i2c_bus *bus = container_of(adap, typeof(*bus), i2c); + int ret; + + ret = nvkm_i2c_bus_acquire(bus); + if (ret) + return ret; + + ret = bus->func->xfer(bus, msgs, num); + nvkm_i2c_bus_release(bus); + return ret; +} + +static u32 +nvkm_i2c_bus_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm +nvkm_i2c_bus_algo = { + .master_xfer = nvkm_i2c_bus_xfer, + .functionality = nvkm_i2c_bus_func, +}; + +/******************************************************************************* + * nvkm_i2c_bus base + ******************************************************************************/ +void +nvkm_i2c_bus_init(struct nvkm_i2c_bus *bus) +{ + BUS_TRACE(bus, "init"); + if (bus->func->init) + bus->func->init(bus); +} + +void +nvkm_i2c_bus_release(struct nvkm_i2c_bus *bus) +{ + struct nvkm_i2c_pad *pad = bus->pad; + BUS_TRACE(bus, "release"); + nvkm_i2c_pad_release(pad); + mutex_unlock(&bus->mutex); +} + +int +nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *bus) +{ + struct nvkm_i2c_pad *pad = bus->pad; + int ret; + BUS_TRACE(bus, "acquire"); + mutex_lock(&bus->mutex); + ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_I2C); + if (ret) + mutex_unlock(&bus->mutex); + return ret; +} + +int +nvkm_i2c_bus_probe(struct nvkm_i2c_bus *bus, const char *what, + struct nvkm_i2c_bus_probe *info, + bool (*match)(struct nvkm_i2c_bus *, + struct i2c_board_info *, void *), void *data) +{ + int i; + + BUS_DBG(bus, "probing %ss", what); + for (i = 0; info[i].dev.addr; i++) { + u8 orig_udelay = 0; + + if ((bus->i2c.algo == &i2c_bit_algo) && (info[i].udelay != 0)) { + struct i2c_algo_bit_data *algo = bus->i2c.algo_data; + BUS_DBG(bus, "%dms delay instead of %dms", + info[i].udelay, algo->udelay); + orig_udelay = algo->udelay; + algo->udelay = info[i].udelay; + } + + if (nvkm_probe_i2c(&bus->i2c, info[i].dev.addr) && + (!match || match(bus, &info[i].dev, data))) { + BUS_DBG(bus, "detected %s: %s", + what, info[i].dev.type); + return i; + } + + if (orig_udelay) { + struct i2c_algo_bit_data *algo = bus->i2c.algo_data; + algo->udelay = orig_udelay; + } + } + + BUS_DBG(bus, "no devices found."); + return -ENODEV; +} + +void +nvkm_i2c_bus_del(struct nvkm_i2c_bus **pbus) +{ + struct nvkm_i2c_bus *bus = *pbus; + if (bus && !WARN_ON(!bus->func)) { + BUS_TRACE(bus, "dtor"); + list_del(&bus->head); + i2c_del_adapter(&bus->i2c); + kfree(bus->i2c.algo_data); + kfree(*pbus); + *pbus = NULL; + } +} + +int +nvkm_i2c_bus_ctor(const struct nvkm_i2c_bus_func *func, + struct nvkm_i2c_pad *pad, int id, + struct nvkm_i2c_bus *bus) +{ + struct nvkm_device *device = pad->i2c->subdev.device; + struct i2c_algo_bit_data *bit; +#ifndef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT + const bool internal = false; +#else + const bool internal = true; +#endif + int ret; + + bus->func = func; + bus->pad = pad; + bus->id = id; + mutex_init(&bus->mutex); + list_add_tail(&bus->head, &pad->i2c->bus); + BUS_TRACE(bus, "ctor"); + + snprintf(bus->i2c.name, sizeof(bus->i2c.name), "nvkm-%s-bus-%04x", + dev_name(device->dev), id); + bus->i2c.owner = THIS_MODULE; + bus->i2c.dev.parent = device->dev; + + if ( bus->func->drive_scl && + !nvkm_boolopt(device->cfgopt, "NvI2C", internal)) { + if (!(bit = kzalloc(sizeof(*bit), GFP_KERNEL))) + return -ENOMEM; + bit->udelay = 10; + bit->timeout = usecs_to_jiffies(2200); + bit->data = bus; + bit->pre_xfer = nvkm_i2c_bus_pre_xfer; + bit->post_xfer = nvkm_i2c_bus_post_xfer; + bit->setscl = nvkm_i2c_bus_setscl; + bit->setsda = nvkm_i2c_bus_setsda; + bit->getscl = nvkm_i2c_bus_getscl; + bit->getsda = nvkm_i2c_bus_getsda; + bus->i2c.algo_data = bit; + ret = i2c_bit_add_bus(&bus->i2c); + } else { + bus->i2c.algo = &nvkm_i2c_bus_algo; + ret = i2c_add_adapter(&bus->i2c); + } + + return ret; +} + +int +nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func *func, + struct nvkm_i2c_pad *pad, int id, + struct nvkm_i2c_bus **pbus) +{ + if (!(*pbus = kzalloc(sizeof(**pbus), GFP_KERNEL))) + return -ENOMEM; + return nvkm_i2c_bus_ctor(func, pad, id, *pbus); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h new file mode 100644 index 000000000..e1be14c23 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h @@ -0,0 +1,37 @@ +#ifndef __NVKM_I2C_BUS_H__ +#define __NVKM_I2C_BUS_H__ +#include "pad.h" + +struct nvkm_i2c_bus_func { + void (*init)(struct nvkm_i2c_bus *); + void (*drive_scl)(struct nvkm_i2c_bus *, int state); + void (*drive_sda)(struct nvkm_i2c_bus *, int state); + int (*sense_scl)(struct nvkm_i2c_bus *); + int (*sense_sda)(struct nvkm_i2c_bus *); + int (*xfer)(struct nvkm_i2c_bus *, struct i2c_msg *, int num); +}; + +int nvkm_i2c_bus_ctor(const struct nvkm_i2c_bus_func *, struct nvkm_i2c_pad *, + int id, struct nvkm_i2c_bus *); +int nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func *, struct nvkm_i2c_pad *, + int id, struct nvkm_i2c_bus **); +void nvkm_i2c_bus_del(struct nvkm_i2c_bus **); +void nvkm_i2c_bus_init(struct nvkm_i2c_bus *); + +int nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *, struct i2c_msg *, int); + +int nv04_i2c_bus_new(struct nvkm_i2c_pad *, int, u8, u8, + struct nvkm_i2c_bus **); + +int nv4e_i2c_bus_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_bus **); +int nv50_i2c_bus_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_bus **); +int gf119_i2c_bus_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_bus **); + +#define BUS_MSG(b,l,f,a...) do { \ + struct nvkm_i2c_bus *_bus = (b); \ + nvkm_##l(&_bus->pad->i2c->subdev, "bus %04x: "f"\n", _bus->id, ##a); \ +} while(0) +#define BUS_ERR(b,f,a...) BUS_MSG((b), error, f, ##a) +#define BUS_DBG(b,f,a...) BUS_MSG((b), debug, f, ##a) +#define BUS_TRACE(b,f,a...) BUS_MSG((b), trace, f, ##a) +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c new file mode 100644 index 000000000..96bbdda0f --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busgf119.c @@ -0,0 +1,95 @@ +/* + * 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 busions 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 + */ +#define gf119_i2c_bus(p) container_of((p), struct gf119_i2c_bus, base) +#include "bus.h" + +struct gf119_i2c_bus { + struct nvkm_i2c_bus base; + u32 addr; +}; + +static void +gf119_i2c_bus_drive_scl(struct nvkm_i2c_bus *base, int state) +{ + struct gf119_i2c_bus *bus = gf119_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + nvkm_mask(device, bus->addr, 0x00000001, state ? 0x00000001 : 0); +} + +static void +gf119_i2c_bus_drive_sda(struct nvkm_i2c_bus *base, int state) +{ + struct gf119_i2c_bus *bus = gf119_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + nvkm_mask(device, bus->addr, 0x00000002, state ? 0x00000002 : 0); +} + +static int +gf119_i2c_bus_sense_scl(struct nvkm_i2c_bus *base) +{ + struct gf119_i2c_bus *bus = gf119_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rd32(device, bus->addr) & 0x00000010); +} + +static int +gf119_i2c_bus_sense_sda(struct nvkm_i2c_bus *base) +{ + struct gf119_i2c_bus *bus = gf119_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rd32(device, bus->addr) & 0x00000020); +} + +static void +gf119_i2c_bus_init(struct nvkm_i2c_bus *base) +{ + struct gf119_i2c_bus *bus = gf119_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + nvkm_wr32(device, bus->addr, 0x00000007); +} + +static const struct nvkm_i2c_bus_func +gf119_i2c_bus_func = { + .init = gf119_i2c_bus_init, + .drive_scl = gf119_i2c_bus_drive_scl, + .drive_sda = gf119_i2c_bus_drive_sda, + .sense_scl = gf119_i2c_bus_sense_scl, + .sense_sda = gf119_i2c_bus_sense_sda, + .xfer = nvkm_i2c_bit_xfer, +}; + +int +gf119_i2c_bus_new(struct nvkm_i2c_pad *pad, int id, u8 drive, + struct nvkm_i2c_bus **pbus) +{ + struct gf119_i2c_bus *bus; + + if (!(bus = kzalloc(sizeof(*bus), GFP_KERNEL))) + return -ENOMEM; + *pbus = &bus->base; + + nvkm_i2c_bus_ctor(&gf119_i2c_bus_func, pad, id, &bus->base); + bus->addr = 0x00d014 + (drive * 0x20); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c new file mode 100644 index 000000000..a58db1592 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv04.c @@ -0,0 +1,96 @@ +/* + * 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 busions 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 + */ +#define nv04_i2c_bus(p) container_of((p), struct nv04_i2c_bus, base) +#include "bus.h" + +#include + +struct nv04_i2c_bus { + struct nvkm_i2c_bus base; + u8 drive; + u8 sense; +}; + +static void +nv04_i2c_bus_drive_scl(struct nvkm_i2c_bus *base, int state) +{ + struct nv04_i2c_bus *bus = nv04_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + u8 val = nvkm_rdvgac(device, 0, bus->drive); + if (state) val |= 0x20; + else val &= 0xdf; + nvkm_wrvgac(device, 0, bus->drive, val | 0x01); +} + +static void +nv04_i2c_bus_drive_sda(struct nvkm_i2c_bus *base, int state) +{ + struct nv04_i2c_bus *bus = nv04_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + u8 val = nvkm_rdvgac(device, 0, bus->drive); + if (state) val |= 0x10; + else val &= 0xef; + nvkm_wrvgac(device, 0, bus->drive, val | 0x01); +} + +static int +nv04_i2c_bus_sense_scl(struct nvkm_i2c_bus *base) +{ + struct nv04_i2c_bus *bus = nv04_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rdvgac(device, 0, bus->sense) & 0x04); +} + +static int +nv04_i2c_bus_sense_sda(struct nvkm_i2c_bus *base) +{ + struct nv04_i2c_bus *bus = nv04_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rdvgac(device, 0, bus->sense) & 0x08); +} + +static const struct nvkm_i2c_bus_func +nv04_i2c_bus_func = { + .drive_scl = nv04_i2c_bus_drive_scl, + .drive_sda = nv04_i2c_bus_drive_sda, + .sense_scl = nv04_i2c_bus_sense_scl, + .sense_sda = nv04_i2c_bus_sense_sda, + .xfer = nvkm_i2c_bit_xfer, +}; + +int +nv04_i2c_bus_new(struct nvkm_i2c_pad *pad, int id, u8 drive, u8 sense, + struct nvkm_i2c_bus **pbus) +{ + struct nv04_i2c_bus *bus; + + if (!(bus = kzalloc(sizeof(*bus), GFP_KERNEL))) + return -ENOMEM; + *pbus = &bus->base; + + nvkm_i2c_bus_ctor(&nv04_i2c_bus_func, pad, id, &bus->base); + bus->drive = drive; + bus->sense = sense; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c new file mode 100644 index 000000000..cdd73dcb1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv4e.c @@ -0,0 +1,86 @@ +/* + * 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 busions 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 + */ +#define nv4e_i2c_bus(p) container_of((p), struct nv4e_i2c_bus, base) +#include "bus.h" + +struct nv4e_i2c_bus { + struct nvkm_i2c_bus base; + u32 addr; +}; + +static void +nv4e_i2c_bus_drive_scl(struct nvkm_i2c_bus *base, int state) +{ + struct nv4e_i2c_bus *bus = nv4e_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + nvkm_mask(device, bus->addr, 0x2f, state ? 0x21 : 0x01); +} + +static void +nv4e_i2c_bus_drive_sda(struct nvkm_i2c_bus *base, int state) +{ + struct nv4e_i2c_bus *bus = nv4e_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + nvkm_mask(device, bus->addr, 0x1f, state ? 0x11 : 0x01); +} + +static int +nv4e_i2c_bus_sense_scl(struct nvkm_i2c_bus *base) +{ + struct nv4e_i2c_bus *bus = nv4e_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rd32(device, bus->addr) & 0x00040000); +} + +static int +nv4e_i2c_bus_sense_sda(struct nvkm_i2c_bus *base) +{ + struct nv4e_i2c_bus *bus = nv4e_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rd32(device, bus->addr) & 0x00080000); +} + +static const struct nvkm_i2c_bus_func +nv4e_i2c_bus_func = { + .drive_scl = nv4e_i2c_bus_drive_scl, + .drive_sda = nv4e_i2c_bus_drive_sda, + .sense_scl = nv4e_i2c_bus_sense_scl, + .sense_sda = nv4e_i2c_bus_sense_sda, + .xfer = nvkm_i2c_bit_xfer, +}; + +int +nv4e_i2c_bus_new(struct nvkm_i2c_pad *pad, int id, u8 drive, + struct nvkm_i2c_bus **pbus) +{ + struct nv4e_i2c_bus *bus; + + if (!(bus = kzalloc(sizeof(*bus), GFP_KERNEL))) + return -ENOMEM; + *pbus = &bus->base; + + nvkm_i2c_bus_ctor(&nv4e_i2c_bus_func, pad, id, &bus->base); + bus->addr = 0x600800 + drive; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c new file mode 100644 index 000000000..8db839938 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/busnv50.c @@ -0,0 +1,113 @@ +/* + * 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 busions 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 + */ +#define nv50_i2c_bus(p) container_of((p), struct nv50_i2c_bus, base) +#include "bus.h" + +#include + +struct nv50_i2c_bus { + struct nvkm_i2c_bus base; + u32 addr; + u32 data; +}; + +static void +nv50_i2c_bus_drive_scl(struct nvkm_i2c_bus *base, int state) +{ + struct nv50_i2c_bus *bus = nv50_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + if (state) bus->data |= 0x01; + else bus->data &= 0xfe; + nvkm_wr32(device, bus->addr, bus->data); +} + +static void +nv50_i2c_bus_drive_sda(struct nvkm_i2c_bus *base, int state) +{ + struct nv50_i2c_bus *bus = nv50_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + if (state) bus->data |= 0x02; + else bus->data &= 0xfd; + nvkm_wr32(device, bus->addr, bus->data); +} + +static int +nv50_i2c_bus_sense_scl(struct nvkm_i2c_bus *base) +{ + struct nv50_i2c_bus *bus = nv50_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rd32(device, bus->addr) & 0x00000001); +} + +static int +nv50_i2c_bus_sense_sda(struct nvkm_i2c_bus *base) +{ + struct nv50_i2c_bus *bus = nv50_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + return !!(nvkm_rd32(device, bus->addr) & 0x00000002); +} + +static void +nv50_i2c_bus_init(struct nvkm_i2c_bus *base) +{ + struct nv50_i2c_bus *bus = nv50_i2c_bus(base); + struct nvkm_device *device = bus->base.pad->i2c->subdev.device; + nvkm_wr32(device, bus->addr, (bus->data = 0x00000007)); +} + +static const struct nvkm_i2c_bus_func +nv50_i2c_bus_func = { + .init = nv50_i2c_bus_init, + .drive_scl = nv50_i2c_bus_drive_scl, + .drive_sda = nv50_i2c_bus_drive_sda, + .sense_scl = nv50_i2c_bus_sense_scl, + .sense_sda = nv50_i2c_bus_sense_sda, + .xfer = nvkm_i2c_bit_xfer, +}; + +int +nv50_i2c_bus_new(struct nvkm_i2c_pad *pad, int id, u8 drive, + struct nvkm_i2c_bus **pbus) +{ + static const u32 addr[] = { + 0x00e138, 0x00e150, 0x00e168, 0x00e180, + 0x00e254, 0x00e274, 0x00e764, 0x00e780, + 0x00e79c, 0x00e7b8 + }; + struct nv50_i2c_bus *bus; + + if (drive >= ARRAY_SIZE(addr)) { + nvkm_warn(&pad->i2c->subdev, "bus %d unknown\n", drive); + return -ENODEV; + } + + if (!(bus = kzalloc(sizeof(*bus), GFP_KERNEL))) + return -ENOMEM; + *pbus = &bus->base; + + nvkm_i2c_bus_ctor(&nv50_i2c_bus_func, pad, id, &bus->base); + bus->addr = addr[drive]; + bus->data = 0x00000007; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c index 2a2dd47b9..bb2a31d88 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/g94.c @@ -21,26 +21,29 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "pad.h" void g94_aux_stat(struct nvkm_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) { - u32 intr = nv_rd32(i2c, 0x00e06c); - u32 stat = nv_rd32(i2c, 0x00e068) & intr, i; + struct nvkm_device *device = i2c->subdev.device; + u32 intr = nvkm_rd32(device, 0x00e06c); + u32 stat = nvkm_rd32(device, 0x00e068) & intr, i; for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { if ((stat & (1 << (i * 4)))) *hi |= 1 << i; if ((stat & (2 << (i * 4)))) *lo |= 1 << i; if ((stat & (4 << (i * 4)))) *rq |= 1 << i; if ((stat & (8 << (i * 4)))) *tx |= 1 << i; } - nv_wr32(i2c, 0x00e06c, intr); + nvkm_wr32(device, 0x00e06c, intr); } void g94_aux_mask(struct nvkm_i2c *i2c, u32 type, u32 mask, u32 data) { - u32 temp = nv_rd32(i2c, 0x00e068), i; + struct nvkm_device *device = i2c->subdev.device; + u32 temp = nvkm_rd32(device, 0x00e068), i; for (i = 0; i < 8; i++) { if (mask & (1 << i)) { if (!(data & (1 << i))) { @@ -50,230 +53,20 @@ g94_aux_mask(struct nvkm_i2c *i2c, u32 type, u32 mask, u32 data) temp |= type << (i * 4); } } - nv_wr32(i2c, 0x00e068, temp); -} - -#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) -#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) - -static void -auxch_fini(struct nvkm_i2c *aux, int ch) -{ - nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); -} - -static int -auxch_init(struct nvkm_i2c *aux, int ch) -{ - const u32 unksel = 1; /* nfi which to use, or if it matters.. */ - const u32 ureq = unksel ? 0x00100000 : 0x00200000; - const u32 urep = unksel ? 0x01000000 : 0x02000000; - u32 ctrl, timeout; - - /* wait up to 1ms for any previous transaction to be done... */ - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("begin idle timeout 0x%08x\n", ctrl); - return -EBUSY; - } - } while (ctrl & 0x03010000); - - /* set some magic, and wait up to 1ms for it to appear */ - nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("magic wait 0x%08x\n", ctrl); - auxch_fini(aux, ch); - return -EBUSY; - } - } while ((ctrl & 0x03000000) != urep); - - return 0; -} - -int -g94_aux(struct nvkm_i2c_port *base, bool retry, - u8 type, u32 addr, u8 *data, u8 size) -{ - struct nvkm_i2c *aux = nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - u32 ctrl, stat, timeout, retries; - u32 xbuf[4] = {}; - int ch = port->addr; - int ret, i; - - AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - - ret = auxch_init(aux, ch); - if (ret) - goto out; - - stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); - if (!(stat & 0x10000000)) { - AUX_DBG("sink not detected\n"); - ret = -ENXIO; - goto out; - } - - if (!(type & 1)) { - memcpy(xbuf, data, size); - for (i = 0; i < 16; i += 4) { - AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); - nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); - } - } - - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - ctrl &= ~0x0001f0ff; - ctrl |= type << 12; - ctrl |= size - 1; - nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); - - /* (maybe) retry transaction a number of times on failure... */ - for (retries = 0; !ret && retries < 32; retries++) { - /* reset, and delay a while if this is a retry */ - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); - if (retries) - udelay(400); - - /* transaction request, wait up to 1ms for it to complete */ - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); - - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("tx req timeout 0x%08x\n", ctrl); - ret = -EIO; - goto out; - } - } while (ctrl & 0x00010000); - ret = 1; - - /* read status, and check if transaction completed ok */ - stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); - if ((stat & 0x000f0000) == 0x00080000 || - (stat & 0x000f0000) == 0x00020000) - ret = retry ? 0 : 1; - if ((stat & 0x00000100)) - ret = -ETIMEDOUT; - if ((stat & 0x00000e00)) - ret = -EIO; - - AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); - } - - if (type & 1) { - for (i = 0; i < 16; i += 4) { - xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); - AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); - } - memcpy(data, xbuf, size); - } - -out: - auxch_fini(aux, ch); - return ret < 0 ? ret : (stat & 0x000f0000) >> 16; + nvkm_wr32(device, 0x00e068, temp); } static const struct nvkm_i2c_func -g94_i2c_func = { - .drive_scl = nv50_i2c_drive_scl, - .drive_sda = nv50_i2c_drive_sda, - .sense_scl = nv50_i2c_sense_scl, - .sense_sda = nv50_i2c_sense_sda, -}; - -static int -g94_i2c_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_bit_algo, &g94_i2c_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - if (info->drive >= nv50_i2c_addr_nr) - return -EINVAL; - - port->state = 7; - port->addr = nv50_i2c_addr[info->drive]; - return 0; -} - -static const struct nvkm_i2c_func -g94_aux_func = { - .aux = g94_aux, +g94_i2c = { + .pad_x_new = g94_i2c_pad_x_new, + .pad_s_new = g94_i2c_pad_s_new, + .aux = 4, + .aux_stat = g94_aux_stat, + .aux_mask = g94_aux_mask, }; int -g94_aux_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +g94_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) { - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_aux_algo, &g94_aux_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->base.aux = info->auxch; - port->addr = info->auxch; - return 0; + return nvkm_i2c_new_(&g94_i2c, device, index, pi2c); } - -static struct nvkm_oclass -g94_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g94_i2c_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g94_aux_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - {} -}; - -struct nvkm_oclass * -g94_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0x94), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = g94_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, - .pad_s = &g94_i2c_pad_oclass, - .aux = 4, - .aux_stat = g94_aux_stat, - .aux_mask = g94_aux_mask, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c deleted file mode 100644 index 4d4ac6638..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf110.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "nv50.h" - -static int -gf110_i2c_sense_scl(struct nvkm_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000010); -} - -static int -gf110_i2c_sense_sda(struct nvkm_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000020); -} - -static const struct nvkm_i2c_func -gf110_i2c_func = { - .drive_scl = nv50_i2c_drive_scl, - .drive_sda = nv50_i2c_drive_sda, - .sense_scl = gf110_i2c_sense_scl, - .sense_sda = gf110_i2c_sense_sda, -}; - -int -gf110_i2c_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_bit_algo, &gf110_i2c_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->state = 0x00000007; - port->addr = 0x00d014 + (info->drive * 0x20); - return 0; -} - -struct nvkm_oclass -gf110_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf110_i2c_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g94_aux_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - {} -}; - -struct nvkm_oclass * -gf110_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0xd0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = gf110_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, - .pad_s = &g94_i2c_pad_oclass, - .aux = 4, - .aux_stat = g94_aux_stat, - .aux_mask = g94_aux_mask, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c index e290b40f2..ae4aad3fc 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf117.c @@ -21,18 +21,16 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "pad.h" -struct nvkm_oclass * -gf117_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0xd7), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = gf110_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, - .pad_s = &nv04_i2c_pad_oclass, -}.base; +static const struct nvkm_i2c_func +gf117_i2c = { + .pad_x_new = gf119_i2c_pad_x_new, +}; + +int +gf117_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) +{ + return nvkm_i2c_new_(&gf117_i2c, device, index, pi2c); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf119.c new file mode 100644 index 000000000..6f2b02af4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gf119.c @@ -0,0 +1,40 @@ +/* + * 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 "priv.h" +#include "pad.h" + +static const struct nvkm_i2c_func +gf119_i2c = { + .pad_x_new = gf119_i2c_pad_x_new, + .pad_s_new = gf119_i2c_pad_s_new, + .aux = 4, + .aux_stat = g94_aux_stat, + .aux_mask = g94_aux_mask, +}; + +int +gf119_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) +{ + return nvkm_i2c_new_(&gf119_i2c, device, index, pi2c); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c index 1a464903a..f9f6bf4b6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk104.c @@ -21,26 +21,29 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "pad.h" void gk104_aux_stat(struct nvkm_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) { - u32 intr = nv_rd32(i2c, 0x00dc60); - u32 stat = nv_rd32(i2c, 0x00dc68) & intr, i; + struct nvkm_device *device = i2c->subdev.device; + u32 intr = nvkm_rd32(device, 0x00dc60); + u32 stat = nvkm_rd32(device, 0x00dc68) & intr, i; for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { if ((stat & (1 << (i * 4)))) *hi |= 1 << i; if ((stat & (2 << (i * 4)))) *lo |= 1 << i; if ((stat & (4 << (i * 4)))) *rq |= 1 << i; if ((stat & (8 << (i * 4)))) *tx |= 1 << i; } - nv_wr32(i2c, 0x00dc60, intr); + nvkm_wr32(device, 0x00dc60, intr); } void gk104_aux_mask(struct nvkm_i2c *i2c, u32 type, u32 mask, u32 data) { - u32 temp = nv_rd32(i2c, 0x00dc68), i; + struct nvkm_device *device = i2c->subdev.device; + u32 temp = nvkm_rd32(device, 0x00dc68), i; for (i = 0; i < 8; i++) { if (mask & (1 << i)) { if (!(data & (1 << i))) { @@ -50,22 +53,20 @@ gk104_aux_mask(struct nvkm_i2c *i2c, u32 type, u32 mask, u32 data) temp |= type << (i * 4); } } - nv_wr32(i2c, 0x00dc68, temp); + nvkm_wr32(device, 0x00dc68, temp); } -struct nvkm_oclass * -gk104_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0xe0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = gf110_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, - .pad_s = &g94_i2c_pad_oclass, +static const struct nvkm_i2c_func +gk104_i2c = { + .pad_x_new = gf119_i2c_pad_x_new, + .pad_s_new = gf119_i2c_pad_s_new, .aux = 4, .aux_stat = gk104_aux_stat, .aux_mask = gk104_aux_mask, -}.base; +}; + +int +gk104_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) +{ + return nvkm_i2c_new_(&gk104_i2c, device, index, pi2c); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c index ab64237b3..ff9f7d62f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c @@ -21,199 +21,20 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" - -#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) -#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) - -static void -auxch_fini(struct nvkm_i2c *aux, int ch) -{ - nv_mask(aux, 0x00d954 + (ch * 0x50), 0x00310000, 0x00000000); -} - -static int -auxch_init(struct nvkm_i2c *aux, int ch) -{ - const u32 unksel = 1; /* nfi which to use, or if it matters.. */ - const u32 ureq = unksel ? 0x00100000 : 0x00200000; - const u32 urep = unksel ? 0x01000000 : 0x02000000; - u32 ctrl, timeout; - - /* wait up to 1ms for any previous transaction to be done... */ - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("begin idle timeout 0x%08x\n", ctrl); - return -EBUSY; - } - } while (ctrl & 0x03010000); - - /* set some magic, and wait up to 1ms for it to appear */ - nv_mask(aux, 0x00d954 + (ch * 0x50), 0x00300000, ureq); - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("magic wait 0x%08x\n", ctrl); - auxch_fini(aux, ch); - return -EBUSY; - } - } while ((ctrl & 0x03000000) != urep); - - return 0; -} - -int -gm204_aux(struct nvkm_i2c_port *base, bool retry, - u8 type, u32 addr, u8 *data, u8 size) -{ - struct nvkm_i2c *aux = nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - u32 ctrl, stat, timeout, retries; - u32 xbuf[4] = {}; - int ch = port->addr; - int ret, i; - - AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - - ret = auxch_init(aux, ch); - if (ret) - goto out; - - stat = nv_rd32(aux, 0x00d958 + (ch * 0x50)); - if (!(stat & 0x10000000)) { - AUX_DBG("sink not detected\n"); - ret = -ENXIO; - goto out; - } - - if (!(type & 1)) { - memcpy(xbuf, data, size); - for (i = 0; i < 16; i += 4) { - AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); - nv_wr32(aux, 0x00d930 + (ch * 0x50) + i, xbuf[i / 4]); - } - } - - ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); - ctrl &= ~0x0001f0ff; - ctrl |= type << 12; - ctrl |= size - 1; - nv_wr32(aux, 0x00d950 + (ch * 0x50), addr); - - /* (maybe) retry transaction a number of times on failure... */ - for (retries = 0; !ret && retries < 32; retries++) { - /* reset, and delay a while if this is a retry */ - nv_wr32(aux, 0x00d954 + (ch * 0x50), 0x80000000 | ctrl); - nv_wr32(aux, 0x00d954 + (ch * 0x50), 0x00000000 | ctrl); - if (retries) - udelay(400); - - /* transaction request, wait up to 1ms for it to complete */ - nv_wr32(aux, 0x00d954 + (ch * 0x50), 0x00010000 | ctrl); - - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("tx req timeout 0x%08x\n", ctrl); - ret = -EIO; - goto out; - } - } while (ctrl & 0x00010000); - ret = 1; - - /* read status, and check if transaction completed ok */ - stat = nv_mask(aux, 0x00d958 + (ch * 0x50), 0, 0); - if ((stat & 0x000f0000) == 0x00080000 || - (stat & 0x000f0000) == 0x00020000) - ret = retry ? 0 : 1; - if ((stat & 0x00000100)) - ret = -ETIMEDOUT; - if ((stat & 0x00000e00)) - ret = -EIO; - - AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); - } - - if (type & 1) { - for (i = 0; i < 16; i += 4) { - xbuf[i / 4] = nv_rd32(aux, 0x00d940 + (ch * 0x50) + i); - AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); - } - memcpy(data, xbuf, size); - } - -out: - auxch_fini(aux, ch); - return ret < 0 ? ret : (stat & 0x000f0000) >> 16; -} +#include "priv.h" +#include "pad.h" static const struct nvkm_i2c_func -gm204_aux_func = { - .aux = gm204_aux, +gm204_i2c = { + .pad_x_new = gf119_i2c_pad_x_new, + .pad_s_new = gm204_i2c_pad_s_new, + .aux = 8, + .aux_stat = gk104_aux_stat, + .aux_mask = gk104_aux_mask, }; int -gm204_aux_port_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +gm204_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) { - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_aux_algo, &gm204_aux_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->base.aux = info->auxch; - port->addr = info->auxch; - return 0; + return nvkm_i2c_new_(&gm204_i2c, device, index, pi2c); } - -struct nvkm_oclass -gm204_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf110_i2c_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_aux_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - {} -}; - -struct nvkm_oclass * -gm204_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0x24), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = gm204_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, - .pad_s = &gm204_i2c_pad_oclass, - .aux = 8, - .aux_stat = gk104_aux_stat, - .aux_mask = gk104_aux_mask, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c index 4cdf1c489..18776f493 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv04.c @@ -22,107 +22,15 @@ * Authors: Ben Skeggs */ #include "priv.h" - -#include - -struct nv04_i2c_priv { - struct nvkm_i2c base; -}; - -struct nv04_i2c_port { - struct nvkm_i2c_port base; - u8 drive; - u8 sense; -}; - -static void -nv04_i2c_drive_scl(struct nvkm_i2c_port *base, int state) -{ - struct nv04_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv04_i2c_port *port = (void *)base; - u8 val = nv_rdvgac(priv, 0, port->drive); - if (state) val |= 0x20; - else val &= 0xdf; - nv_wrvgac(priv, 0, port->drive, val | 0x01); -} - -static void -nv04_i2c_drive_sda(struct nvkm_i2c_port *base, int state) -{ - struct nv04_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv04_i2c_port *port = (void *)base; - u8 val = nv_rdvgac(priv, 0, port->drive); - if (state) val |= 0x10; - else val &= 0xef; - nv_wrvgac(priv, 0, port->drive, val | 0x01); -} - -static int -nv04_i2c_sense_scl(struct nvkm_i2c_port *base) -{ - struct nv04_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv04_i2c_port *port = (void *)base; - return !!(nv_rdvgac(priv, 0, port->sense) & 0x04); -} - -static int -nv04_i2c_sense_sda(struct nvkm_i2c_port *base) -{ - struct nv04_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv04_i2c_port *port = (void *)base; - return !!(nv_rdvgac(priv, 0, port->sense) & 0x08); -} +#include "pad.h" static const struct nvkm_i2c_func -nv04_i2c_func = { - .drive_scl = nv04_i2c_drive_scl, - .drive_sda = nv04_i2c_drive_sda, - .sense_scl = nv04_i2c_sense_scl, - .sense_sda = nv04_i2c_sense_sda, +nv04_i2c = { + .pad_x_new = nv04_i2c_pad_new, }; -static int -nv04_i2c_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +int +nv04_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) { - struct dcb_i2c_entry *info = data; - struct nv04_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_bit_algo, &nv04_i2c_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->drive = info->drive; - port->sense = info->sense; - return 0; + return nvkm_i2c_new_(&nv04_i2c, device, index, pi2c); } - -static struct nvkm_oclass -nv04_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV04_BIT), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_i2c_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - {} -}; - -struct nvkm_oclass * -nv04_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = nv04_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c index 046fe5e2e..6b762f7ce 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv4e.c @@ -22,99 +22,15 @@ * Authors: Ben Skeggs */ #include "priv.h" - -#include - -struct nv4e_i2c_priv { - struct nvkm_i2c base; -}; - -struct nv4e_i2c_port { - struct nvkm_i2c_port base; - u32 addr; -}; - -static void -nv4e_i2c_drive_scl(struct nvkm_i2c_port *base, int state) -{ - struct nv4e_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv4e_i2c_port *port = (void *)base; - nv_mask(priv, port->addr, 0x2f, state ? 0x21 : 0x01); -} - -static void -nv4e_i2c_drive_sda(struct nvkm_i2c_port *base, int state) -{ - struct nv4e_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv4e_i2c_port *port = (void *)base; - nv_mask(priv, port->addr, 0x1f, state ? 0x11 : 0x01); -} - -static int -nv4e_i2c_sense_scl(struct nvkm_i2c_port *base) -{ - struct nv4e_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv4e_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00040000); -} - -static int -nv4e_i2c_sense_sda(struct nvkm_i2c_port *base) -{ - struct nv4e_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv4e_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00080000); -} +#include "pad.h" static const struct nvkm_i2c_func -nv4e_i2c_func = { - .drive_scl = nv4e_i2c_drive_scl, - .drive_sda = nv4e_i2c_drive_sda, - .sense_scl = nv4e_i2c_sense_scl, - .sense_sda = nv4e_i2c_sense_sda, +nv4e_i2c = { + .pad_x_new = nv4e_i2c_pad_new, }; -static int -nv4e_i2c_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +int +nv4e_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) { - struct dcb_i2c_entry *info = data; - struct nv4e_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_bit_algo, &nv4e_i2c_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->addr = 0x600800 + info->drive; - return 0; + return nvkm_i2c_new_(&nv4e_i2c, device, index, pi2c); } - -static struct nvkm_oclass -nv4e_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV4E_BIT), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv4e_i2c_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = _nvkm_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - {} -}; - -struct nvkm_oclass * -nv4e_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0x4e), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = nv4e_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c index fba5b26a5..75640ab97 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.c @@ -21,113 +21,16 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" - -void -nv50_i2c_drive_scl(struct nvkm_i2c_port *base, int state) -{ - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - if (state) port->state |= 0x01; - else port->state &= 0xfe; - nv_wr32(priv, port->addr, port->state); -} - -void -nv50_i2c_drive_sda(struct nvkm_i2c_port *base, int state) -{ - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - if (state) port->state |= 0x02; - else port->state &= 0xfd; - nv_wr32(priv, port->addr, port->state); -} - -int -nv50_i2c_sense_scl(struct nvkm_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000001); -} - -int -nv50_i2c_sense_sda(struct nvkm_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(base); - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000002); -} +#include "priv.h" +#include "pad.h" static const struct nvkm_i2c_func -nv50_i2c_func = { - .drive_scl = nv50_i2c_drive_scl, - .drive_sda = nv50_i2c_drive_sda, - .sense_scl = nv50_i2c_sense_scl, - .sense_sda = nv50_i2c_sense_sda, -}; - -const u32 nv50_i2c_addr[] = { - 0x00e138, 0x00e150, 0x00e168, 0x00e180, - 0x00e254, 0x00e274, 0x00e764, 0x00e780, - 0x00e79c, 0x00e7b8 +nv50_i2c = { + .pad_x_new = nv50_i2c_pad_new, }; -const int nv50_i2c_addr_nr = ARRAY_SIZE(nv50_i2c_addr); - -static int -nv50_i2c_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nvkm_i2c_port_create(parent, engine, oclass, index, - &nvkm_i2c_bit_algo, &nv50_i2c_func, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - if (info->drive >= nv50_i2c_addr_nr) - return -EINVAL; - - port->state = 0x00000007; - port->addr = nv50_i2c_addr[info->drive]; - return 0; -} int -nv50_i2c_port_init(struct nvkm_object *object) +nv50_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c) { - struct nv50_i2c_priv *priv = (void *)nvkm_i2c(object); - struct nv50_i2c_port *port = (void *)object; - nv_wr32(priv, port->addr, port->state); - return nvkm_i2c_port_init(&port->base); + return nvkm_i2c_new_(&nv50_i2c, device, index, pi2c); } - -static struct nvkm_oclass -nv50_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_i2c_port_ctor, - .dtor = _nvkm_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nvkm_i2c_port_fini, - }, - }, - {} -}; - -struct nvkm_oclass * -nv50_i2c_oclass = &(struct nvkm_i2c_impl) { - .base.handle = NV_SUBDEV(I2C, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_ctor, - .dtor = _nvkm_i2c_dtor, - .init = _nvkm_i2c_init, - .fini = _nvkm_i2c_fini, - }, - .sclass = nv50_i2c_sclass, - .pad_x = &nv04_i2c_pad_oclass, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h deleted file mode 100644 index b3139e721..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/nv50.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __NV50_I2C_H__ -#define __NV50_I2C_H__ -#include "priv.h" - -struct nv50_i2c_priv { - struct nvkm_i2c base; -}; - -struct nv50_i2c_port { - struct nvkm_i2c_port base; - u32 addr; - u32 state; -}; - -extern const u32 nv50_i2c_addr[]; -extern const int nv50_i2c_addr_nr; -int nv50_i2c_port_init(struct nvkm_object *); -int nv50_i2c_sense_scl(struct nvkm_i2c_port *); -int nv50_i2c_sense_sda(struct nvkm_i2c_port *); -void nv50_i2c_drive_scl(struct nvkm_i2c_port *, int state); -void nv50_i2c_drive_sda(struct nvkm_i2c_port *, int state); - -int g94_aux_port_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void g94_i2c_acquire(struct nvkm_i2c_port *); -void g94_i2c_release(struct nvkm_i2c_port *); - -int gf110_i2c_port_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c index a242eeb67..2c5fcb9c5 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.c @@ -1,5 +1,5 @@ /* - * Copyright 2014 Red Hat Inc. + * 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"), @@ -19,65 +19,98 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * Authors: Ben Skeggs + * Authors: Ben Skeggs */ #include "pad.h" -int -_nvkm_i2c_pad_fini(struct nvkm_object *object, bool suspend) +static void +nvkm_i2c_pad_mode_locked(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode) { - struct nvkm_i2c_pad *pad = (void *)object; - DBG("-> NULL\n"); - pad->port = NULL; - return nvkm_object_fini(&pad->base, suspend); + PAD_TRACE(pad, "-> %s", (mode == NVKM_I2C_PAD_AUX) ? "aux" : + (mode == NVKM_I2C_PAD_I2C) ? "i2c" : "off"); + if (pad->func->mode) + pad->func->mode(pad, mode); } -int -_nvkm_i2c_pad_init(struct nvkm_object *object) +void +nvkm_i2c_pad_mode(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode) { - struct nvkm_i2c_pad *pad = (void *)object; - DBG("-> PORT:%02x\n", pad->next->index); - pad->port = pad->next; - return nvkm_object_init(&pad->base); + PAD_TRACE(pad, "mode %d", mode); + mutex_lock(&pad->mutex); + nvkm_i2c_pad_mode_locked(pad, mode); + pad->mode = mode; + mutex_unlock(&pad->mutex); } -int -nvkm_i2c_pad_create_(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, int index, - int size, void **pobject) +void +nvkm_i2c_pad_release(struct nvkm_i2c_pad *pad) { - struct nvkm_i2c *i2c = nvkm_i2c(parent); - struct nvkm_i2c_port *port; - struct nvkm_i2c_pad *pad; - int ret; + PAD_TRACE(pad, "release"); + if (pad->mode == NVKM_I2C_PAD_OFF) + nvkm_i2c_pad_mode_locked(pad, pad->mode); + mutex_unlock(&pad->mutex); +} - list_for_each_entry(port, &i2c->ports, head) { - pad = nvkm_i2c_pad(port); - if (pad->index == index) { - atomic_inc(&nv_object(pad)->refcount); - *pobject = pad; - return 1; +int +nvkm_i2c_pad_acquire(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode) +{ + PAD_TRACE(pad, "acquire"); + mutex_lock(&pad->mutex); + if (pad->mode != mode) { + if (pad->mode != NVKM_I2C_PAD_OFF) { + mutex_unlock(&pad->mutex); + return -EBUSY; } + nvkm_i2c_pad_mode_locked(pad, mode); } + return 0; +} + +void +nvkm_i2c_pad_fini(struct nvkm_i2c_pad *pad) +{ + PAD_TRACE(pad, "fini"); + nvkm_i2c_pad_mode_locked(pad, NVKM_I2C_PAD_OFF); +} - ret = nvkm_object_create_(parent, engine, oclass, 0, size, pobject); - pad = *pobject; - if (ret) - return ret; +void +nvkm_i2c_pad_init(struct nvkm_i2c_pad *pad) +{ + PAD_TRACE(pad, "init"); + nvkm_i2c_pad_mode_locked(pad, pad->mode); +} - pad->index = index; - return 0; +void +nvkm_i2c_pad_del(struct nvkm_i2c_pad **ppad) +{ + struct nvkm_i2c_pad *pad = *ppad; + if (pad) { + PAD_TRACE(pad, "dtor"); + list_del(&pad->head); + kfree(pad); + pad = NULL; + } +} + +void +nvkm_i2c_pad_ctor(const struct nvkm_i2c_pad_func *func, struct nvkm_i2c *i2c, + int id, struct nvkm_i2c_pad *pad) +{ + pad->func = func; + pad->i2c = i2c; + pad->id = id; + pad->mode = NVKM_I2C_PAD_OFF; + mutex_init(&pad->mutex); + list_add_tail(&pad->head, &i2c->pad); + PAD_TRACE(pad, "ctor"); } int -_nvkm_i2c_pad_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) +nvkm_i2c_pad_new_(const struct nvkm_i2c_pad_func *func, struct nvkm_i2c *i2c, + int id, struct nvkm_i2c_pad **ppad) { - struct nvkm_i2c_pad *pad; - int ret; - ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); - *pobject = nv_object(pad); - return ret; + if (!(*ppad = kzalloc(sizeof(**ppad), GFP_KERNEL))) + return -ENOMEM; + nvkm_i2c_pad_ctor(func, i2c, id, *ppad); + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h index f3422cc6f..9eeb99294 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h @@ -1,56 +1,67 @@ #ifndef __NVKM_I2C_PAD_H__ #define __NVKM_I2C_PAD_H__ -#include "priv.h" +#include struct nvkm_i2c_pad { - struct nvkm_object base; - int index; - struct nvkm_i2c_port *port; - struct nvkm_i2c_port *next; + const struct nvkm_i2c_pad_func *func; + struct nvkm_i2c *i2c; +#define NVKM_I2C_PAD_HYBRID(n) /* 'n' is hw pad index */ (n) +#define NVKM_I2C_PAD_CCB(n) /* 'n' is ccb index */ ((n) + 0x100) +#define NVKM_I2C_PAD_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x200) + int id; + + enum nvkm_i2c_pad_mode { + NVKM_I2C_PAD_OFF, + NVKM_I2C_PAD_I2C, + NVKM_I2C_PAD_AUX, + } mode; + struct mutex mutex; + struct list_head head; +}; + +struct nvkm_i2c_pad_func { + int (*bus_new_0)(struct nvkm_i2c_pad *, int id, u8 drive, u8 sense, + struct nvkm_i2c_bus **); + int (*bus_new_4)(struct nvkm_i2c_pad *, int id, u8 drive, + struct nvkm_i2c_bus **); + + int (*aux_new_6)(struct nvkm_i2c_pad *, int id, u8 drive, + struct nvkm_i2c_aux **); + + void (*mode)(struct nvkm_i2c_pad *, enum nvkm_i2c_pad_mode); }; -static inline struct nvkm_i2c_pad * -nvkm_i2c_pad(struct nvkm_i2c_port *port) -{ - struct nvkm_object *pad = nv_object(port); - while (!nv_iclass(pad->parent, NV_SUBDEV_CLASS)) - pad = pad->parent; - return (void *)pad; -} - -#define nvkm_i2c_pad_create(p,e,o,i,d) \ - nvkm_i2c_pad_create_((p), (e), (o), (i), sizeof(**d), (void **)d) -#define nvkm_i2c_pad_destroy(p) ({ \ - struct nvkm_i2c_pad *_p = (p); \ - _nvkm_i2c_pad_dtor(nv_object(_p)); \ -}) -#define nvkm_i2c_pad_init(p) ({ \ - struct nvkm_i2c_pad *_p = (p); \ - _nvkm_i2c_pad_init(nv_object(_p)); \ -}) -#define nvkm_i2c_pad_fini(p,s) ({ \ - struct nvkm_i2c_pad *_p = (p); \ - _nvkm_i2c_pad_fini(nv_object(_p), (s)); \ -}) - -int nvkm_i2c_pad_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int index, int, void **); - -int _nvkm_i2c_pad_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -#define _nvkm_i2c_pad_dtor nvkm_object_destroy -int _nvkm_i2c_pad_init(struct nvkm_object *); -int _nvkm_i2c_pad_fini(struct nvkm_object *, bool); - -#ifndef MSG -#define MSG(l,f,a...) do { \ - struct nvkm_i2c_pad *_pad = (void *)pad; \ - nv_##l(_pad, "PAD:%c:%02x: "f, \ - _pad->index >= 0x100 ? 'X' : 'S', \ - _pad->index >= 0x100 ? _pad->index - 0x100 : _pad->index, ##a); \ +void nvkm_i2c_pad_ctor(const struct nvkm_i2c_pad_func *, struct nvkm_i2c *, + int id, struct nvkm_i2c_pad *); +int nvkm_i2c_pad_new_(const struct nvkm_i2c_pad_func *, struct nvkm_i2c *, + int id, struct nvkm_i2c_pad **); +void nvkm_i2c_pad_del(struct nvkm_i2c_pad **); +void nvkm_i2c_pad_init(struct nvkm_i2c_pad *); +void nvkm_i2c_pad_fini(struct nvkm_i2c_pad *); +void nvkm_i2c_pad_mode(struct nvkm_i2c_pad *, enum nvkm_i2c_pad_mode); +int nvkm_i2c_pad_acquire(struct nvkm_i2c_pad *, enum nvkm_i2c_pad_mode); +void nvkm_i2c_pad_release(struct nvkm_i2c_pad *); + +void g94_i2c_pad_mode(struct nvkm_i2c_pad *, enum nvkm_i2c_pad_mode); + +int nv04_i2c_pad_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int nv4e_i2c_pad_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int nv50_i2c_pad_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int g94_i2c_pad_x_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int gf119_i2c_pad_x_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int gm204_i2c_pad_x_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); + +int g94_i2c_pad_s_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int gf119_i2c_pad_s_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); +int gm204_i2c_pad_s_new(struct nvkm_i2c *, int, struct nvkm_i2c_pad **); + +int anx9805_pad_new(struct nvkm_i2c_bus *, int, u8, struct nvkm_i2c_pad **); + +#define PAD_MSG(p,l,f,a...) do { \ + struct nvkm_i2c_pad *_pad = (p); \ + nvkm_##l(&_pad->i2c->subdev, "pad %04x: "f"\n", _pad->id, ##a); \ } while(0) -#define DBG(f,a...) MSG(debug, f, ##a) -#define ERR(f,a...) MSG(error, f, ##a) -#endif +#define PAD_ERR(p,f,a...) PAD_MSG((p), error, f, ##a) +#define PAD_DBG(p,f,a...) PAD_MSG((p), debug, f, ##a) +#define PAD_TRACE(p,f,a...) PAD_MSG((p), trace, f, ##a) #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c index e9832f7a7..5904bc5f2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c @@ -22,64 +22,55 @@ * Authors: Ben Skeggs */ #include "pad.h" +#include "aux.h" +#include "bus.h" -struct g94_i2c_pad { - struct nvkm_i2c_pad base; - int addr; -}; - -static int -g94_i2c_pad_fini(struct nvkm_object *object, bool suspend) -{ - struct nvkm_i2c *i2c = (void *)nvkm_i2c(object); - struct g94_i2c_pad *pad = (void *)object; - nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000001); - return nvkm_i2c_pad_fini(&pad->base, suspend); -} - -static int -g94_i2c_pad_init(struct nvkm_object *object) +void +g94_i2c_pad_mode(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode) { - struct nvkm_i2c *i2c = (void *)nvkm_i2c(object); - struct g94_i2c_pad *pad = (void *)object; + struct nvkm_subdev *subdev = &pad->i2c->subdev; + struct nvkm_device *device = subdev->device; + const u32 base = (pad->id - NVKM_I2C_PAD_HYBRID(0)) * 0x50; - switch (nv_oclass(pad->base.next)->handle) { - case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX): - nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x00000002); + switch (mode) { + case NVKM_I2C_PAD_OFF: + nvkm_mask(device, 0x00e50c + base, 0x00000001, 0x00000001); + break; + case NVKM_I2C_PAD_I2C: + nvkm_mask(device, 0x00e500 + base, 0x0000c003, 0x0000c001); + nvkm_mask(device, 0x00e50c + base, 0x00000001, 0x00000000); + break; + case NVKM_I2C_PAD_AUX: + nvkm_mask(device, 0x00e500 + base, 0x0000c003, 0x00000002); + nvkm_mask(device, 0x00e50c + base, 0x00000001, 0x00000000); break; - case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT): default: - nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x0000c001); + WARN_ON(1); break; } - - nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000000); - return nvkm_i2c_pad_init(&pad->base); } -static int -g94_i2c_pad_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) -{ - struct g94_i2c_pad *pad; - int ret; - - ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); - *pobject = nv_object(pad); - if (ret) - return ret; +static const struct nvkm_i2c_pad_func +g94_i2c_pad_s_func = { + .bus_new_4 = nv50_i2c_bus_new, + .aux_new_6 = g94_i2c_aux_new, + .mode = g94_i2c_pad_mode, +}; - pad->addr = index * 0x50;; - return 0; +int +g94_i2c_pad_s_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&g94_i2c_pad_s_func, i2c, id, ppad); } -struct nvkm_oclass -g94_i2c_pad_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g94_i2c_pad_ctor, - .dtor = _nvkm_i2c_pad_dtor, - .init = g94_i2c_pad_init, - .fini = g94_i2c_pad_fini, - }, +static const struct nvkm_i2c_pad_func +g94_i2c_pad_x_func = { + .bus_new_4 = nv50_i2c_bus_new, + .aux_new_6 = g94_i2c_aux_new, }; + +int +g94_i2c_pad_x_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&g94_i2c_pad_x_func, i2c, id, ppad); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c new file mode 100644 index 000000000..d53212f1a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "pad.h" +#include "aux.h" +#include "bus.h" + +static const struct nvkm_i2c_pad_func +gf119_i2c_pad_s_func = { + .bus_new_4 = gf119_i2c_bus_new, + .aux_new_6 = g94_i2c_aux_new, + .mode = g94_i2c_pad_mode, +}; + +int +gf119_i2c_pad_s_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&gf119_i2c_pad_s_func, i2c, id, ppad); +} + +static const struct nvkm_i2c_pad_func +gf119_i2c_pad_x_func = { + .bus_new_4 = gf119_i2c_bus_new, + .aux_new_6 = g94_i2c_aux_new, +}; + +int +gf119_i2c_pad_x_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&gf119_i2c_pad_x_func, i2c, id, ppad); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c index be5904054..24a4d760c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm204.c @@ -22,64 +22,55 @@ * Authors: Ben Skeggs */ #include "pad.h" +#include "aux.h" +#include "bus.h" -struct gm204_i2c_pad { - struct nvkm_i2c_pad base; - int addr; -}; - -static int -gm204_i2c_pad_fini(struct nvkm_object *object, bool suspend) -{ - struct nvkm_i2c *i2c = (void *)nvkm_i2c(object); - struct gm204_i2c_pad *pad = (void *)object; - nv_mask(i2c, 0x00d97c + pad->addr, 0x00000001, 0x00000001); - return nvkm_i2c_pad_fini(&pad->base, suspend); -} - -static int -gm204_i2c_pad_init(struct nvkm_object *object) +static void +gm204_i2c_pad_mode(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode) { - struct nvkm_i2c *i2c = (void *)nvkm_i2c(object); - struct gm204_i2c_pad *pad = (void *)object; + struct nvkm_subdev *subdev = &pad->i2c->subdev; + struct nvkm_device *device = subdev->device; + const u32 base = (pad->id - NVKM_I2C_PAD_HYBRID(0)) * 0x50; - switch (nv_oclass(pad->base.next)->handle) { - case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX): - nv_mask(i2c, 0x00d970 + pad->addr, 0x0000c003, 0x00000002); + switch (mode) { + case NVKM_I2C_PAD_OFF: + nvkm_mask(device, 0x00d97c + base, 0x00000001, 0x00000001); + break; + case NVKM_I2C_PAD_I2C: + nvkm_mask(device, 0x00d970 + base, 0x0000c003, 0x0000c001); + nvkm_mask(device, 0x00d97c + base, 0x00000001, 0x00000000); + break; + case NVKM_I2C_PAD_AUX: + nvkm_mask(device, 0x00d970 + base, 0x0000c003, 0x00000002); + nvkm_mask(device, 0x00d97c + base, 0x00000001, 0x00000000); break; - case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT): default: - nv_mask(i2c, 0x00d970 + pad->addr, 0x0000c003, 0x0000c001); + WARN_ON(1); break; } - - nv_mask(i2c, 0x00d97c + pad->addr, 0x00000001, 0x00000000); - return nvkm_i2c_pad_init(&pad->base); } -static int -gm204_i2c_pad_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 index, - struct nvkm_object **pobject) -{ - struct gm204_i2c_pad *pad; - int ret; - - ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); - *pobject = nv_object(pad); - if (ret) - return ret; +static const struct nvkm_i2c_pad_func +gm204_i2c_pad_s_func = { + .bus_new_4 = gf119_i2c_bus_new, + .aux_new_6 = gm204_i2c_aux_new, + .mode = gm204_i2c_pad_mode, +}; - pad->addr = index * 0x50;; - return 0; +int +gm204_i2c_pad_s_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&gm204_i2c_pad_s_func, i2c, id, ppad); } -struct nvkm_oclass -gm204_i2c_pad_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm204_i2c_pad_ctor, - .dtor = _nvkm_i2c_pad_dtor, - .init = gm204_i2c_pad_init, - .fini = gm204_i2c_pad_fini, - }, +static const struct nvkm_i2c_pad_func +gm204_i2c_pad_x_func = { + .bus_new_4 = gf119_i2c_bus_new, + .aux_new_6 = gm204_i2c_aux_new, }; + +int +gm204_i2c_pad_x_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&gm204_i2c_pad_x_func, i2c, id, ppad); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c index 22c7daaad..310046ad9 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv04.c @@ -22,13 +22,15 @@ * Authors: Ben Skeggs */ #include "pad.h" +#include "bus.h" -struct nvkm_oclass -nv04_i2c_pad_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_i2c_pad_ctor, - .dtor = _nvkm_i2c_pad_dtor, - .init = _nvkm_i2c_pad_init, - .fini = _nvkm_i2c_pad_fini, - }, +static const struct nvkm_i2c_pad_func +nv04_i2c_pad_func = { + .bus_new_0 = nv04_i2c_bus_new, }; + +int +nv04_i2c_pad_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&nv04_i2c_pad_func, i2c, id, ppad); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c new file mode 100644 index 000000000..dda6fc0b0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv4e.c @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "pad.h" +#include "bus.h" + +static const struct nvkm_i2c_pad_func +nv4e_i2c_pad_func = { + .bus_new_4 = nv4e_i2c_bus_new, +}; + +int +nv4e_i2c_pad_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&nv4e_i2c_pad_func, i2c, id, ppad); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c new file mode 100644 index 000000000..a03f25b19 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padnv50.c @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "pad.h" +#include "bus.h" + +static const struct nvkm_i2c_pad_func +nv50_i2c_pad_func = { + .bus_new_4 = nv50_i2c_bus_new, +}; + +int +nv50_i2c_pad_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad) +{ + return nvkm_i2c_pad_new_(&nv50_i2c_pad_func, i2c, id, ppad); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h deleted file mode 100644 index 586f53dad..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/port.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __NVKM_I2C_PORT_H__ -#define __NVKM_I2C_PORT_H__ -#include "priv.h" - -#ifndef MSG -#define MSG(l,f,a...) do { \ - struct nvkm_i2c_port *_port = (void *)port; \ - nv_##l(_port, "PORT:%02x: "f, _port->index, ##a); \ -} while(0) -#define DBG(f,a...) MSG(debug, f, ##a) -#define ERR(f,a...) MSG(error, f, ##a) -#endif -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h index 6586e1567..bf655a66e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h @@ -1,69 +1,14 @@ #ifndef __NVKM_I2C_PRIV_H__ #define __NVKM_I2C_PRIV_H__ +#define nvkm_i2c(p) container_of((p), struct nvkm_i2c, subdev) #include -extern struct nvkm_oclass nv04_i2c_pad_oclass; -extern struct nvkm_oclass g94_i2c_pad_oclass; -extern struct nvkm_oclass gm204_i2c_pad_oclass; +int nvkm_i2c_new_(const struct nvkm_i2c_func *, struct nvkm_device *, + int index, struct nvkm_i2c **); -#define nvkm_i2c_port_create(p,e,o,i,a,f,d) \ - nvkm_i2c_port_create_((p), (e), (o), (i), (a), (f), \ - sizeof(**d), (void **)d) -#define nvkm_i2c_port_destroy(p) ({ \ - struct nvkm_i2c_port *port = (p); \ - _nvkm_i2c_port_dtor(nv_object(i2c)); \ -}) -#define nvkm_i2c_port_init(p) \ - nvkm_object_init(&(p)->base) -#define nvkm_i2c_port_fini(p,s) \ - nvkm_object_fini(&(p)->base, (s)) - -int nvkm_i2c_port_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, u8, - const struct i2c_algorithm *, - const struct nvkm_i2c_func *, - int, void **); -void _nvkm_i2c_port_dtor(struct nvkm_object *); -#define _nvkm_i2c_port_init nvkm_object_init -int _nvkm_i2c_port_fini(struct nvkm_object *, bool); - -#define nvkm_i2c_create(p,e,o,d) \ - nvkm_i2c_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_i2c_destroy(p) ({ \ - struct nvkm_i2c *i2c = (p); \ - _nvkm_i2c_dtor(nv_object(i2c)); \ -}) -#define nvkm_i2c_init(p) ({ \ - struct nvkm_i2c *i2c = (p); \ - _nvkm_i2c_init(nv_object(i2c)); \ -}) -#define nvkm_i2c_fini(p,s) ({ \ - struct nvkm_i2c *i2c = (p); \ - _nvkm_i2c_fini(nv_object(i2c), (s)); \ -}) - -int nvkm_i2c_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -int _nvkm_i2c_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void _nvkm_i2c_dtor(struct nvkm_object *); -int _nvkm_i2c_init(struct nvkm_object *); -int _nvkm_i2c_fini(struct nvkm_object *, bool); - -extern struct nvkm_oclass nvkm_anx9805_sclass[]; -extern struct nvkm_oclass gf110_i2c_sclass[]; - -extern const struct i2c_algorithm nvkm_i2c_bit_algo; -extern const struct i2c_algorithm nvkm_i2c_aux_algo; - -struct nvkm_i2c_impl { - struct nvkm_oclass base; - - /* supported i2c port classes */ - struct nvkm_oclass *sclass; - struct nvkm_oclass *pad_x; - struct nvkm_oclass *pad_s; +struct nvkm_i2c_func { + int (*pad_x_new)(struct nvkm_i2c *, int id, struct nvkm_i2c_pad **); + int (*pad_s_new)(struct nvkm_i2c *, int id, struct nvkm_i2c_pad **); /* number of native dp aux channels present */ int aux; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild index a0b12d272..de888fa62 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild @@ -1,3 +1,4 @@ nvkm-y += nvkm/subdev/ibus/gf100.o +nvkm-y += nvkm/subdev/ibus/gf117.o nvkm-y += nvkm/subdev/ibus/gk104.o nvkm-y += nvkm/subdev/ibus/gk20a.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c index 8e578f802..72d6330d2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c @@ -21,57 +21,56 @@ * * Authors: Ben Skeggs */ -#include - -struct gf100_ibus_priv { - struct nvkm_ibus base; -}; +#include "priv.h" static void -gf100_ibus_intr_hub(struct gf100_ibus_priv *priv, int i) +gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i) { - u32 addr = nv_rd32(priv, 0x122120 + (i * 0x0400)); - u32 data = nv_rd32(priv, 0x122124 + (i * 0x0400)); - u32 stat = nv_rd32(priv, 0x122128 + (i * 0x0400)); - nv_error(priv, "HUB%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); - nv_mask(priv, 0x122128 + (i * 0x0400), 0x00000200, 0x00000000); + struct nvkm_device *device = ibus->device; + u32 addr = nvkm_rd32(device, 0x122120 + (i * 0x0400)); + u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0400)); + u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0400)); + nvkm_error(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat); + nvkm_mask(device, 0x122128 + (i * 0x0400), 0x00000200, 0x00000000); } static void -gf100_ibus_intr_rop(struct gf100_ibus_priv *priv, int i) +gf100_ibus_intr_rop(struct nvkm_subdev *ibus, int i) { - u32 addr = nv_rd32(priv, 0x124120 + (i * 0x0400)); - u32 data = nv_rd32(priv, 0x124124 + (i * 0x0400)); - u32 stat = nv_rd32(priv, 0x124128 + (i * 0x0400)); - nv_error(priv, "ROP%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); - nv_mask(priv, 0x124128 + (i * 0x0400), 0x00000200, 0x00000000); + struct nvkm_device *device = ibus->device; + u32 addr = nvkm_rd32(device, 0x124120 + (i * 0x0400)); + u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0400)); + u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0400)); + nvkm_error(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat); + nvkm_mask(device, 0x124128 + (i * 0x0400), 0x00000200, 0x00000000); } static void -gf100_ibus_intr_gpc(struct gf100_ibus_priv *priv, int i) +gf100_ibus_intr_gpc(struct nvkm_subdev *ibus, int i) { - u32 addr = nv_rd32(priv, 0x128120 + (i * 0x0400)); - u32 data = nv_rd32(priv, 0x128124 + (i * 0x0400)); - u32 stat = nv_rd32(priv, 0x128128 + (i * 0x0400)); - nv_error(priv, "GPC%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); - nv_mask(priv, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000); + struct nvkm_device *device = ibus->device; + u32 addr = nvkm_rd32(device, 0x128120 + (i * 0x0400)); + u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0400)); + u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0400)); + nvkm_error(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat); + nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000); } -static void -gf100_ibus_intr(struct nvkm_subdev *subdev) +void +gf100_ibus_intr(struct nvkm_subdev *ibus) { - struct gf100_ibus_priv *priv = (void *)subdev; - u32 intr0 = nv_rd32(priv, 0x121c58); - u32 intr1 = nv_rd32(priv, 0x121c5c); - u32 hubnr = nv_rd32(priv, 0x121c70); - u32 ropnr = nv_rd32(priv, 0x121c74); - u32 gpcnr = nv_rd32(priv, 0x121c78); + struct nvkm_device *device = ibus->device; + u32 intr0 = nvkm_rd32(device, 0x121c58); + u32 intr1 = nvkm_rd32(device, 0x121c5c); + u32 hubnr = nvkm_rd32(device, 0x121c70); + u32 ropnr = nvkm_rd32(device, 0x121c74); + u32 gpcnr = nvkm_rd32(device, 0x121c78); u32 i; for (i = 0; (intr0 & 0x0000ff00) && i < hubnr; i++) { u32 stat = 0x00000100 << i; if (intr0 & stat) { - gf100_ibus_intr_hub(priv, i); + gf100_ibus_intr_hub(ibus, i); intr0 &= ~stat; } } @@ -79,7 +78,7 @@ gf100_ibus_intr(struct nvkm_subdev *subdev) for (i = 0; (intr0 & 0xffff0000) && i < ropnr; i++) { u32 stat = 0x00010000 << i; if (intr0 & stat) { - gf100_ibus_intr_rop(priv, i); + gf100_ibus_intr_rop(ibus, i); intr0 &= ~stat; } } @@ -87,36 +86,37 @@ gf100_ibus_intr(struct nvkm_subdev *subdev) for (i = 0; intr1 && i < gpcnr; i++) { u32 stat = 0x00000001 << i; if (intr1 & stat) { - gf100_ibus_intr_gpc(priv, i); + gf100_ibus_intr_gpc(ibus, i); intr1 &= ~stat; } } } static int -gf100_ibus_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_ibus_init(struct nvkm_subdev *ibus) { - struct gf100_ibus_priv *priv; - int ret; - - ret = nvkm_ibus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->intr = gf100_ibus_intr; + struct nvkm_device *device = ibus->device; + nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800); + nvkm_wr32(device, 0x12232c, 0x00100064); + nvkm_wr32(device, 0x122330, 0x00100064); + nvkm_wr32(device, 0x122334, 0x00100064); + nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100); return 0; } -struct nvkm_oclass -gf100_ibus_oclass = { - .handle = NV_SUBDEV(IBUS, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_ibus_ctor, - .dtor = _nvkm_ibus_dtor, - .init = _nvkm_ibus_init, - .fini = _nvkm_ibus_fini, - }, +static const struct nvkm_subdev_func +gf100_ibus = { + .init = gf100_ibus_init, + .intr = gf100_ibus_intr, }; + +int +gf100_ibus_new(struct nvkm_device *device, int index, + struct nvkm_subdev **pibus) +{ + struct nvkm_subdev *ibus; + if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&gf100_ibus, device, index, 0, ibus); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c new file mode 100644 index 000000000..f69f263c5 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Samuel Pitosiet + * + * 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: Samuel Pitoiset + */ +#include "priv.h" + +static int +gf117_ibus_init(struct nvkm_subdev *ibus) +{ + struct nvkm_device *device = ibus->device; + nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800); + nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100); + nvkm_mask(device, 0x1223b0, 0x0003ffff, 0x00000fff); + return 0; +} + +static const struct nvkm_subdev_func +gf117_ibus = { + .init = gf117_ibus_init, + .intr = gf100_ibus_intr, +}; + +int +gf117_ibus_new(struct nvkm_device *device, int index, + struct nvkm_subdev **pibus) +{ + struct nvkm_subdev *ibus; + if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&gf117_ibus, device, index, 0, ibus); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c index 7b6e9a6cd..ba33609f6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c @@ -23,55 +23,54 @@ */ #include -struct gk104_ibus_priv { - struct nvkm_ibus base; -}; - static void -gk104_ibus_intr_hub(struct gk104_ibus_priv *priv, int i) +gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i) { - u32 addr = nv_rd32(priv, 0x122120 + (i * 0x0800)); - u32 data = nv_rd32(priv, 0x122124 + (i * 0x0800)); - u32 stat = nv_rd32(priv, 0x122128 + (i * 0x0800)); - nv_error(priv, "HUB%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); - nv_mask(priv, 0x122128 + (i * 0x0800), 0x00000200, 0x00000000); + struct nvkm_device *device = ibus->device; + u32 addr = nvkm_rd32(device, 0x122120 + (i * 0x0800)); + u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0800)); + u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0800)); + nvkm_error(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat); + nvkm_mask(device, 0x122128 + (i * 0x0800), 0x00000200, 0x00000000); } static void -gk104_ibus_intr_rop(struct gk104_ibus_priv *priv, int i) +gk104_ibus_intr_rop(struct nvkm_subdev *ibus, int i) { - u32 addr = nv_rd32(priv, 0x124120 + (i * 0x0800)); - u32 data = nv_rd32(priv, 0x124124 + (i * 0x0800)); - u32 stat = nv_rd32(priv, 0x124128 + (i * 0x0800)); - nv_error(priv, "ROP%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); - nv_mask(priv, 0x124128 + (i * 0x0800), 0x00000200, 0x00000000); + struct nvkm_device *device = ibus->device; + u32 addr = nvkm_rd32(device, 0x124120 + (i * 0x0800)); + u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0800)); + u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0800)); + nvkm_error(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat); + nvkm_mask(device, 0x124128 + (i * 0x0800), 0x00000200, 0x00000000); } static void -gk104_ibus_intr_gpc(struct gk104_ibus_priv *priv, int i) +gk104_ibus_intr_gpc(struct nvkm_subdev *ibus, int i) { - u32 addr = nv_rd32(priv, 0x128120 + (i * 0x0800)); - u32 data = nv_rd32(priv, 0x128124 + (i * 0x0800)); - u32 stat = nv_rd32(priv, 0x128128 + (i * 0x0800)); - nv_error(priv, "GPC%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); - nv_mask(priv, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000); + struct nvkm_device *device = ibus->device; + u32 addr = nvkm_rd32(device, 0x128120 + (i * 0x0800)); + u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0800)); + u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0800)); + nvkm_error(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat); + nvkm_mask(device, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000); } static void -gk104_ibus_intr(struct nvkm_subdev *subdev) +gk104_ibus_intr(struct nvkm_subdev *ibus) { - struct gk104_ibus_priv *priv = (void *)subdev; - u32 intr0 = nv_rd32(priv, 0x120058); - u32 intr1 = nv_rd32(priv, 0x12005c); - u32 hubnr = nv_rd32(priv, 0x120070); - u32 ropnr = nv_rd32(priv, 0x120074); - u32 gpcnr = nv_rd32(priv, 0x120078); + struct nvkm_device *device = ibus->device; + u32 intr0 = nvkm_rd32(device, 0x120058); + u32 intr1 = nvkm_rd32(device, 0x12005c); + u32 hubnr = nvkm_rd32(device, 0x120070); + u32 ropnr = nvkm_rd32(device, 0x120074); + u32 gpcnr = nvkm_rd32(device, 0x120078); u32 i; for (i = 0; (intr0 & 0x0000ff00) && i < hubnr; i++) { u32 stat = 0x00000100 << i; if (intr0 & stat) { - gk104_ibus_intr_hub(priv, i); + gk104_ibus_intr_hub(ibus, i); intr0 &= ~stat; } } @@ -79,7 +78,7 @@ gk104_ibus_intr(struct nvkm_subdev *subdev) for (i = 0; (intr0 & 0xffff0000) && i < ropnr; i++) { u32 stat = 0x00010000 << i; if (intr0 & stat) { - gk104_ibus_intr_rop(priv, i); + gk104_ibus_intr_rop(ibus, i); intr0 &= ~stat; } } @@ -87,53 +86,40 @@ gk104_ibus_intr(struct nvkm_subdev *subdev) for (i = 0; intr1 && i < gpcnr; i++) { u32 stat = 0x00000001 << i; if (intr1 & stat) { - gk104_ibus_intr_gpc(priv, i); + gk104_ibus_intr_gpc(ibus, i); intr1 &= ~stat; } } } static int -gk104_ibus_init(struct nvkm_object *object) +gk104_ibus_init(struct nvkm_subdev *ibus) { - struct gk104_ibus_priv *priv = (void *)object; - int ret = nvkm_ibus_init(&priv->base); - if (ret == 0) { - nv_mask(priv, 0x122318, 0x0003ffff, 0x00001000); - nv_mask(priv, 0x12231c, 0x0003ffff, 0x00000200); - nv_mask(priv, 0x122310, 0x0003ffff, 0x00000800); - nv_mask(priv, 0x122348, 0x0003ffff, 0x00000100); - nv_mask(priv, 0x1223b0, 0x0003ffff, 0x00000fff); - nv_mask(priv, 0x122348, 0x0003ffff, 0x00000200); - nv_mask(priv, 0x122358, 0x0003ffff, 0x00002880); - } - return ret; + struct nvkm_device *device = ibus->device; + nvkm_mask(device, 0x122318, 0x0003ffff, 0x00001000); + nvkm_mask(device, 0x12231c, 0x0003ffff, 0x00000200); + nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800); + nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100); + nvkm_mask(device, 0x1223b0, 0x0003ffff, 0x00000fff); + nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000200); + nvkm_mask(device, 0x122358, 0x0003ffff, 0x00002880); + return 0; } -static int -gk104_ibus_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk104_ibus_priv *priv; - int ret; - - ret = nvkm_ibus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_subdev_func +gk104_ibus = { + .preinit = gk104_ibus_init, + .init = gk104_ibus_init, + .intr = gk104_ibus_intr, +}; - nv_subdev(priv)->intr = gk104_ibus_intr; +int +gk104_ibus_new(struct nvkm_device *device, int index, + struct nvkm_subdev **pibus) +{ + struct nvkm_subdev *ibus; + if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&gk104_ibus, device, index, 0, ibus); return 0; } - -struct nvkm_oclass -gk104_ibus_oclass = { - .handle = NV_SUBDEV(IBUS, 0xe0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk104_ibus_ctor, - .dtor = _nvkm_ibus_dtor, - .init = gk104_ibus_init, - .fini = _nvkm_ibus_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c index c0fdb89e7..3484079e8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c @@ -22,81 +22,68 @@ #include #include -struct gk20a_ibus_priv { - struct nvkm_ibus base; -}; - static void -gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv) +gk20a_ibus_init_ibus_ring(struct nvkm_subdev *ibus) { - nv_mask(priv, 0x137250, 0x3f, 0); + struct nvkm_device *device = ibus->device; + nvkm_mask(device, 0x137250, 0x3f, 0); - nv_mask(priv, 0x000200, 0x20, 0); + nvkm_mask(device, 0x000200, 0x20, 0); usleep_range(20, 30); - nv_mask(priv, 0x000200, 0x20, 0x20); - - nv_wr32(priv, 0x12004c, 0x4); - nv_wr32(priv, 0x122204, 0x2); - nv_rd32(priv, 0x122204); + nvkm_mask(device, 0x000200, 0x20, 0x20); + + nvkm_wr32(device, 0x12004c, 0x4); + nvkm_wr32(device, 0x122204, 0x2); + nvkm_rd32(device, 0x122204); + + /* + * Bug: increase clock timeout to avoid operation failure at high + * gpcclk rate. + */ + nvkm_wr32(device, 0x122354, 0x800); + nvkm_wr32(device, 0x128328, 0x800); + nvkm_wr32(device, 0x124320, 0x800); } static void -gk20a_ibus_intr(struct nvkm_subdev *subdev) +gk20a_ibus_intr(struct nvkm_subdev *ibus) { - struct gk20a_ibus_priv *priv = (void *)subdev; - u32 status0 = nv_rd32(priv, 0x120058); + struct nvkm_device *device = ibus->device; + u32 status0 = nvkm_rd32(device, 0x120058); if (status0 & 0x7) { - nv_debug(priv, "resetting priv ring\n"); - gk20a_ibus_init_priv_ring(priv); + nvkm_debug(ibus, "resetting ibus ring\n"); + gk20a_ibus_init_ibus_ring(ibus); } /* Acknowledge interrupt */ - nv_mask(priv, 0x12004c, 0x2, 0x2); - - if (!nv_wait(subdev, 0x12004c, 0x3f, 0x00)) - nv_warn(priv, "timeout waiting for ringmaster ack\n"); + nvkm_mask(device, 0x12004c, 0x2, 0x2); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x12004c) & 0x0000003f)) + break; + ); } static int -gk20a_ibus_init(struct nvkm_object *object) +gk20a_ibus_init(struct nvkm_subdev *ibus) { - struct gk20a_ibus_priv *priv = (void *)object; - int ret; - - ret = _nvkm_ibus_init(object); - if (ret) - return ret; - - gk20a_ibus_init_priv_ring(priv); - + gk20a_ibus_init_ibus_ring(ibus); return 0; } -static int -gk20a_ibus_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk20a_ibus_priv *priv; - int ret; - - ret = nvkm_ibus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_subdev_func +gk20a_ibus = { + .init = gk20a_ibus_init, + .intr = gk20a_ibus_intr, +}; - nv_subdev(priv)->intr = gk20a_ibus_intr; +int +gk20a_ibus_new(struct nvkm_device *device, int index, + struct nvkm_subdev **pibus) +{ + struct nvkm_subdev *ibus; + if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&gk20a_ibus, device, index, 0, ibus); return 0; } - -struct nvkm_oclass -gk20a_ibus_oclass = { - .handle = NV_SUBDEV(IBUS, 0xea), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_ibus_ctor, - .dtor = _nvkm_ibus_dtor, - .init = gk20a_ibus_init, - .fini = _nvkm_ibus_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h new file mode 100644 index 000000000..48e1b6365 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h @@ -0,0 +1,7 @@ +#ifndef __NVKM_IBUS_PRIV_H__ +#define __NVKM_IBUS_PRIV_H__ + +#include + +void gf100_ibus_intr(struct nvkm_subdev *); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c index d16358cc6..1d7dd3829 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c @@ -23,124 +23,296 @@ */ #include "priv.h" -#include +#include +#include /****************************************************************************** * instmem object base implementation *****************************************************************************/ +#define nvkm_instobj(p) container_of((p), struct nvkm_instobj, memory) -void -_nvkm_instobj_dtor(struct nvkm_object *object) +struct nvkm_instobj { + struct nvkm_memory memory; + struct nvkm_memory *parent; + struct nvkm_instmem *imem; + struct list_head head; + u32 *suspend; + void __iomem *map; +}; + +static enum nvkm_memory_target +nvkm_instobj_target(struct nvkm_memory *memory) +{ + memory = nvkm_instobj(memory)->parent; + return nvkm_memory_target(memory); +} + +static u64 +nvkm_instobj_addr(struct nvkm_memory *memory) +{ + memory = nvkm_instobj(memory)->parent; + return nvkm_memory_addr(memory); +} + +static u64 +nvkm_instobj_size(struct nvkm_memory *memory) +{ + memory = nvkm_instobj(memory)->parent; + return nvkm_memory_size(memory); +} + +static void +nvkm_instobj_release(struct nvkm_memory *memory) +{ + struct nvkm_instobj *iobj = nvkm_instobj(memory); + nvkm_bar_flush(iobj->imem->subdev.device->bar); +} + +static void __iomem * +nvkm_instobj_acquire(struct nvkm_memory *memory) +{ + return nvkm_instobj(memory)->map; +} + +static u32 +nvkm_instobj_rd32(struct nvkm_memory *memory, u64 offset) +{ + return ioread32_native(nvkm_instobj(memory)->map + offset); +} + +static void +nvkm_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) { - struct nvkm_instmem *imem = nvkm_instmem(object); - struct nvkm_instobj *iobj = (void *)object; + iowrite32_native(data, nvkm_instobj(memory)->map + offset); +} + +static void +nvkm_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) +{ + memory = nvkm_instobj(memory)->parent; + nvkm_memory_map(memory, vma, offset); +} - mutex_lock(&nv_subdev(imem)->mutex); +static void * +nvkm_instobj_dtor(struct nvkm_memory *memory) +{ + struct nvkm_instobj *iobj = nvkm_instobj(memory); + spin_lock(&iobj->imem->lock); list_del(&iobj->head); - mutex_unlock(&nv_subdev(imem)->mutex); + spin_unlock(&iobj->imem->lock); + nvkm_memory_del(&iobj->parent); + return iobj; +} + +const struct nvkm_memory_func +nvkm_instobj_func = { + .dtor = nvkm_instobj_dtor, + .target = nvkm_instobj_target, + .addr = nvkm_instobj_addr, + .size = nvkm_instobj_size, + .acquire = nvkm_instobj_acquire, + .release = nvkm_instobj_release, + .rd32 = nvkm_instobj_rd32, + .wr32 = nvkm_instobj_wr32, + .map = nvkm_instobj_map, +}; + +static void +nvkm_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm) +{ + memory = nvkm_instobj(memory)->parent; + nvkm_memory_boot(memory, vm); +} + +static void +nvkm_instobj_release_slow(struct nvkm_memory *memory) +{ + struct nvkm_instobj *iobj = nvkm_instobj(memory); + nvkm_instobj_release(memory); + nvkm_done(iobj->parent); +} + +static void __iomem * +nvkm_instobj_acquire_slow(struct nvkm_memory *memory) +{ + struct nvkm_instobj *iobj = nvkm_instobj(memory); + iobj->map = nvkm_kmap(iobj->parent); + if (iobj->map) + memory->func = &nvkm_instobj_func; + return iobj->map; +} + +static u32 +nvkm_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset) +{ + struct nvkm_instobj *iobj = nvkm_instobj(memory); + return nvkm_ro32(iobj->parent, offset); +} - return nvkm_object_destroy(&iobj->base); +static void +nvkm_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data) +{ + struct nvkm_instobj *iobj = nvkm_instobj(memory); + return nvkm_wo32(iobj->parent, offset, data); } +const struct nvkm_memory_func +nvkm_instobj_func_slow = { + .dtor = nvkm_instobj_dtor, + .target = nvkm_instobj_target, + .addr = nvkm_instobj_addr, + .size = nvkm_instobj_size, + .boot = nvkm_instobj_boot, + .acquire = nvkm_instobj_acquire_slow, + .release = nvkm_instobj_release_slow, + .rd32 = nvkm_instobj_rd32_slow, + .wr32 = nvkm_instobj_wr32_slow, + .map = nvkm_instobj_map, +}; + int -nvkm_instobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, + struct nvkm_memory **pmemory) { - struct nvkm_instmem *imem = nvkm_instmem(parent); + struct nvkm_memory *memory = NULL; struct nvkm_instobj *iobj; + u32 offset; int ret; - ret = nvkm_object_create_(parent, engine, oclass, NV_MEMOBJ_CLASS, - length, pobject); - iobj = *pobject; + ret = imem->func->memory_new(imem, size, align, zero, &memory); if (ret) - return ret; + goto done; - mutex_lock(&imem->base.mutex); - list_add(&iobj->head, &imem->list); - mutex_unlock(&imem->base.mutex); - return 0; + if (!imem->func->persistent) { + if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + + nvkm_memory_ctor(&nvkm_instobj_func_slow, &iobj->memory); + iobj->parent = memory; + iobj->imem = imem; + spin_lock(&iobj->imem->lock); + list_add_tail(&iobj->head, &imem->list); + spin_unlock(&iobj->imem->lock); + memory = &iobj->memory; + } + + if (!imem->func->zero && zero) { + void __iomem *map = nvkm_kmap(memory); + if (unlikely(!map)) { + for (offset = 0; offset < size; offset += 4) + nvkm_wo32(memory, offset, 0x00000000); + } else { + memset_io(map, 0x00, size); + } + nvkm_done(memory); + } + +done: + if (ret) + nvkm_memory_del(&memory); + *pmemory = memory; + return ret; } /****************************************************************************** * instmem subdev base implementation *****************************************************************************/ -static int -nvkm_instmem_alloc(struct nvkm_instmem *imem, struct nvkm_object *parent, - u32 size, u32 align, struct nvkm_object **pobject) +u32 +nvkm_instmem_rd32(struct nvkm_instmem *imem, u32 addr) { - struct nvkm_instmem_impl *impl = (void *)imem->base.object.oclass; - struct nvkm_instobj_args args = { .size = size, .align = align }; - return nvkm_object_ctor(parent, &parent->engine->subdev.object, - impl->instobj, &args, sizeof(args), pobject); + return imem->func->rd32(imem, addr); } -int -_nvkm_instmem_fini(struct nvkm_object *object, bool suspend) +void +nvkm_instmem_wr32(struct nvkm_instmem *imem, u32 addr, u32 data) +{ + return imem->func->wr32(imem, addr, data); +} + +static int +nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend) { - struct nvkm_instmem *imem = (void *)object; + struct nvkm_instmem *imem = nvkm_instmem(subdev); struct nvkm_instobj *iobj; - int i, ret = 0; + int i; + + if (imem->func->fini) + imem->func->fini(imem); if (suspend) { - mutex_lock(&imem->base.mutex); list_for_each_entry(iobj, &imem->list, head) { - iobj->suspend = vmalloc(iobj->size); - if (!iobj->suspend) { - ret = -ENOMEM; - break; - } - - for (i = 0; i < iobj->size; i += 4) - iobj->suspend[i / 4] = nv_ro32(iobj, i); + struct nvkm_memory *memory = iobj->parent; + u64 size = nvkm_memory_size(memory); + + iobj->suspend = vmalloc(size); + if (!iobj->suspend) + return -ENOMEM; + + for (i = 0; i < size; i += 4) + iobj->suspend[i / 4] = nvkm_ro32(memory, i); } - mutex_unlock(&imem->base.mutex); - if (ret) - return ret; } - return nvkm_subdev_fini(&imem->base, suspend); + return 0; } -int -_nvkm_instmem_init(struct nvkm_object *object) +static int +nvkm_instmem_oneinit(struct nvkm_subdev *subdev) { - struct nvkm_instmem *imem = (void *)object; - struct nvkm_instobj *iobj; - int ret, i; + struct nvkm_instmem *imem = nvkm_instmem(subdev); + if (imem->func->oneinit) + return imem->func->oneinit(imem); + return 0; +} - ret = nvkm_subdev_init(&imem->base); - if (ret) - return ret; +static int +nvkm_instmem_init(struct nvkm_subdev *subdev) +{ + struct nvkm_instmem *imem = nvkm_instmem(subdev); + struct nvkm_instobj *iobj; + int i; - mutex_lock(&imem->base.mutex); list_for_each_entry(iobj, &imem->list, head) { if (iobj->suspend) { - for (i = 0; i < iobj->size; i += 4) - nv_wo32(iobj, i, iobj->suspend[i / 4]); + struct nvkm_memory *memory = iobj->parent; + u64 size = nvkm_memory_size(memory); + for (i = 0; i < size; i += 4) + nvkm_wo32(memory, i, iobj->suspend[i / 4]); vfree(iobj->suspend); iobj->suspend = NULL; } } - mutex_unlock(&imem->base.mutex); + return 0; } -int -nvkm_instmem_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +static void * +nvkm_instmem_dtor(struct nvkm_subdev *subdev) { - struct nvkm_instmem *imem; - int ret; + struct nvkm_instmem *imem = nvkm_instmem(subdev); + if (imem->func->dtor) + return imem->func->dtor(imem); + return imem; +} - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "INSTMEM", - "instmem", length, pobject); - imem = *pobject; - if (ret) - return ret; +static const struct nvkm_subdev_func +nvkm_instmem = { + .dtor = nvkm_instmem_dtor, + .oneinit = nvkm_instmem_oneinit, + .init = nvkm_instmem_init, + .fini = nvkm_instmem_fini, +}; +void +nvkm_instmem_ctor(const struct nvkm_instmem_func *func, + struct nvkm_device *device, int index, + struct nvkm_instmem *imem) +{ + nvkm_subdev_ctor(&nvkm_instmem, device, index, 0, &imem->subdev); + imem->func = func; + spin_lock_init(&imem->lock); INIT_LIST_HEAD(&imem->list); - imem->alloc = nvkm_instmem_alloc; - return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c index dd0994d9e..14107b5b7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c @@ -23,418 +23,607 @@ /* * GK20A does not have dedicated video memory, and to accurately represent this * fact Nouveau will not create a RAM device for it. Therefore its instmem - * implementation must be done directly on top of system memory, while providing - * coherent read and write operations. + * implementation must be done directly on top of system memory, while + * preserving coherency for read and write operations. * * Instmem can be allocated through two means: - * 1) If an IOMMU mapping has been probed, the IOMMU API is used to make memory + * 1) If an IOMMU unit has been probed, the IOMMU API is used to make memory * pages contiguous to the GPU. This is the preferred way. - * 2) If no IOMMU mapping is probed, the DMA API is used to allocate physically + * 2) If no IOMMU unit is probed, the DMA API is used to allocate physically * contiguous memory. * - * In both cases CPU read and writes are performed using PRAMIN (i.e. using the - * GPU path) to ensure these operations are coherent for the GPU. This allows us - * to use more "relaxed" allocation parameters when using the DMA API, since we - * never need a kernel mapping. + * In both cases CPU read and writes are performed by creating a write-combined + * mapping. The GPU L2 cache must thus be flushed/invalidated when required. To + * be conservative we do this every time we acquire or release an instobj, but + * ideally L2 management should be handled at a higher level. + * + * To improve performance, CPU mappings are not removed upon instobj release. + * Instead they are placed into a LRU list to be recycled when the mapped space + * goes beyond a certain threshold. At the moment this limit is 1MB. */ +#include "priv.h" -#include +#include #include -#include - -#ifdef __KERNEL__ -#include -#include -#include -#endif +#include +#include +#include -#include "priv.h" +struct gk20a_instobj { + struct nvkm_memory memory; + struct nvkm_mem mem; + struct gk20a_instmem *imem; -struct gk20a_instobj_priv { - struct nvkm_instobj base; - /* Must be second member here - see nouveau_gpuobj_map_vm() */ - struct nvkm_mem *mem; - /* Pointed by mem */ - struct nvkm_mem _mem; + /* CPU mapping */ + u32 *vaddr; + struct list_head vaddr_node; }; +#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory) /* * Used for objects allocated using the DMA API */ struct gk20a_instobj_dma { - struct gk20a_instobj_priv base; + struct gk20a_instobj base; - void *cpuaddr; + u32 *cpuaddr; dma_addr_t handle; struct nvkm_mm_node r; }; +#define gk20a_instobj_dma(p) \ + container_of(gk20a_instobj(p), struct gk20a_instobj_dma, base) /* * Used for objects flattened using the IOMMU API */ struct gk20a_instobj_iommu { - struct gk20a_instobj_priv base; + struct gk20a_instobj base; - /* array of base.mem->size pages */ + /* will point to the higher half of pages */ + dma_addr_t *dma_addrs; + /* array of base.mem->size pages (+ dma_addr_ts) */ struct page *pages[]; }; +#define gk20a_instobj_iommu(p) \ + container_of(gk20a_instobj(p), struct gk20a_instobj_iommu, base) -struct gk20a_instmem_priv { +struct gk20a_instmem { struct nvkm_instmem base; + + /* protects vaddr_* and gk20a_instobj::vaddr* */ spinlock_t lock; - u64 addr; + + /* CPU mappings LRU */ + unsigned int vaddr_use; + unsigned int vaddr_max; + struct list_head vaddr_lru; /* Only used if IOMMU if present */ struct mutex *mm_mutex; struct nvkm_mm *mm; struct iommu_domain *domain; unsigned long iommu_pgshift; + u16 iommu_bit; /* Only used by DMA API */ struct dma_attrs attrs; + + void __iomem * (*cpu_map)(struct nvkm_memory *); }; +#define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base) + +static enum nvkm_memory_target +gk20a_instobj_target(struct nvkm_memory *memory) +{ + return NVKM_MEM_TARGET_HOST; +} + +static u64 +gk20a_instobj_addr(struct nvkm_memory *memory) +{ + return gk20a_instobj(memory)->mem.offset; +} + +static u64 +gk20a_instobj_size(struct nvkm_memory *memory) +{ + return (u64)gk20a_instobj(memory)->mem.size << 12; +} + +static void __iomem * +gk20a_instobj_cpu_map_dma(struct nvkm_memory *memory) +{ +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) + struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory); + struct device *dev = node->base.imem->base.subdev.device->dev; + int npages = nvkm_memory_size(memory) >> 12; + struct page *pages[npages]; + int i; + + /* we shouldn't see a gk20a on anything but arm/arm64 anyways */ + /* phys_to_page does not exist on all platforms... */ + pages[0] = pfn_to_page(dma_to_phys(dev, node->handle) >> PAGE_SHIFT); + for (i = 1; i < npages; i++) + pages[i] = pages[0] + i; + + return vmap(pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); +#else + BUG(); + return NULL; +#endif +} + +static void __iomem * +gk20a_instobj_cpu_map_iommu(struct nvkm_memory *memory) +{ + struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory); + int npages = nvkm_memory_size(memory) >> 12; + + return vmap(node->pages, npages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); +} /* - * Use PRAMIN to read/write data and avoid coherency issues. - * PRAMIN uses the GPU path and ensures data will always be coherent. - * - * A dynamic mapping based solution would be desirable in the future, but - * the issue remains of how to maintain coherency efficiently. On ARM it is - * not easy (if possible at all?) to create uncached temporary mappings. + * Must be called while holding gk20a_instmem_lock */ +static void +gk20a_instmem_vaddr_gc(struct gk20a_instmem *imem, const u64 size) +{ + while (imem->vaddr_use + size > imem->vaddr_max) { + struct gk20a_instobj *obj; + + /* no candidate that can be unmapped, abort... */ + if (list_empty(&imem->vaddr_lru)) + break; + + obj = list_first_entry(&imem->vaddr_lru, struct gk20a_instobj, + vaddr_node); + list_del(&obj->vaddr_node); + vunmap(obj->vaddr); + obj->vaddr = NULL; + imem->vaddr_use -= nvkm_memory_size(&obj->memory); + nvkm_debug(&imem->base.subdev, "(GC) vaddr used: %x/%x\n", + imem->vaddr_use, imem->vaddr_max); -static u32 -gk20a_instobj_rd32(struct nvkm_object *object, u64 offset) + } +} + +static void __iomem * +gk20a_instobj_acquire(struct nvkm_memory *memory) { - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(object); - struct gk20a_instobj_priv *node = (void *)object; + struct gk20a_instobj *node = gk20a_instobj(memory); + struct gk20a_instmem *imem = node->imem; + struct nvkm_ltc *ltc = imem->base.subdev.device->ltc; + const u64 size = nvkm_memory_size(memory); unsigned long flags; - u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; - u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; - u32 data; - - spin_lock_irqsave(&priv->lock, flags); - if (unlikely(priv->addr != base)) { - nv_wr32(priv, 0x001700, base >> 16); - priv->addr = base; + + nvkm_ltc_flush(ltc); + + spin_lock_irqsave(&imem->lock, flags); + + if (node->vaddr) { + /* remove us from the LRU list since we cannot be unmapped */ + list_del(&node->vaddr_node); + + goto out; + } + + /* try to free some address space if we reached the limit */ + gk20a_instmem_vaddr_gc(imem, size); + + node->vaddr = imem->cpu_map(memory); + + if (!node->vaddr) { + nvkm_error(&imem->base.subdev, "cannot map instobj - " + "this is not going to end well...\n"); + goto out; } - data = nv_rd32(priv, 0x700000 + addr); - spin_unlock_irqrestore(&priv->lock, flags); - return data; + + imem->vaddr_use += size; + nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", + imem->vaddr_use, imem->vaddr_max); + +out: + spin_unlock_irqrestore(&imem->lock, flags); + + return node->vaddr; } static void -gk20a_instobj_wr32(struct nvkm_object *object, u64 offset, u32 data) +gk20a_instobj_release(struct nvkm_memory *memory) { - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(object); - struct gk20a_instobj_priv *node = (void *)object; + struct gk20a_instobj *node = gk20a_instobj(memory); + struct gk20a_instmem *imem = node->imem; + struct nvkm_ltc *ltc = imem->base.subdev.device->ltc; unsigned long flags; - u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; - u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; - spin_lock_irqsave(&priv->lock, flags); - if (unlikely(priv->addr != base)) { - nv_wr32(priv, 0x001700, base >> 16); - priv->addr = base; - } - nv_wr32(priv, 0x700000 + addr, data); - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&imem->lock, flags); + + /* add ourselves to the LRU list so our CPU mapping can be freed */ + list_add_tail(&node->vaddr_node, &imem->vaddr_lru); + + spin_unlock_irqrestore(&imem->lock, flags); + + wmb(); + nvkm_ltc_invalidate(ltc); +} + +static u32 +gk20a_instobj_rd32(struct nvkm_memory *memory, u64 offset) +{ + struct gk20a_instobj *node = gk20a_instobj(memory); + + return node->vaddr[offset / 4]; } static void -gk20a_instobj_dtor_dma(struct gk20a_instobj_priv *_node) +gk20a_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) { - struct gk20a_instobj_dma *node = (void *)_node; - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node); - struct device *dev = nv_device_base(nv_device(priv)); + struct gk20a_instobj *node = gk20a_instobj(memory); - if (unlikely(!node->cpuaddr)) - return; + node->vaddr[offset / 4] = data; +} - dma_free_attrs(dev, _node->mem->size << PAGE_SHIFT, node->cpuaddr, - node->handle, &priv->attrs); +static void +gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) +{ + struct gk20a_instobj *node = gk20a_instobj(memory); + + nvkm_vm_map_at(vma, offset, &node->mem); } +/* + * Clear the CPU mapping of an instobj if it exists + */ static void -gk20a_instobj_dtor_iommu(struct gk20a_instobj_priv *_node) +gk20a_instobj_dtor(struct gk20a_instobj *node) +{ + struct gk20a_instmem *imem = node->imem; + struct gk20a_instobj *obj; + unsigned long flags; + + spin_lock_irqsave(&imem->lock, flags); + + if (!node->vaddr) + goto out; + + list_for_each_entry(obj, &imem->vaddr_lru, vaddr_node) { + if (obj == node) { + list_del(&obj->vaddr_node); + break; + } + } + vunmap(node->vaddr); + node->vaddr = NULL; + imem->vaddr_use -= nvkm_memory_size(&node->memory); + nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", + imem->vaddr_use, imem->vaddr_max); + +out: + spin_unlock_irqrestore(&imem->lock, flags); +} + +static void * +gk20a_instobj_dtor_dma(struct nvkm_memory *memory) +{ + struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory); + struct gk20a_instmem *imem = node->base.imem; + struct device *dev = imem->base.subdev.device->dev; + + gk20a_instobj_dtor(&node->base); + + if (unlikely(!node->cpuaddr)) + goto out; + + dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->cpuaddr, + node->handle, &imem->attrs); + +out: + return node; +} + +static void * +gk20a_instobj_dtor_iommu(struct nvkm_memory *memory) { - struct gk20a_instobj_iommu *node = (void *)_node; - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node); + struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory); + struct gk20a_instmem *imem = node->base.imem; + struct device *dev = imem->base.subdev.device->dev; struct nvkm_mm_node *r; int i; - if (unlikely(list_empty(&_node->mem->regions))) - return; + gk20a_instobj_dtor(&node->base); - r = list_first_entry(&_node->mem->regions, struct nvkm_mm_node, + if (unlikely(list_empty(&node->base.mem.regions))) + goto out; + + r = list_first_entry(&node->base.mem.regions, struct nvkm_mm_node, rl_entry); - /* clear bit 34 to unmap pages */ - r->offset &= ~BIT(34 - priv->iommu_pgshift); + /* clear IOMMU bit to unmap pages */ + r->offset &= ~BIT(imem->iommu_bit - imem->iommu_pgshift); /* Unmap pages from GPU address space and free them */ - for (i = 0; i < _node->mem->size; i++) { - iommu_unmap(priv->domain, - (r->offset + i) << priv->iommu_pgshift, PAGE_SIZE); + for (i = 0; i < node->base.mem.size; i++) { + iommu_unmap(imem->domain, + (r->offset + i) << imem->iommu_pgshift, PAGE_SIZE); + dma_unmap_page(dev, node->dma_addrs[i], PAGE_SIZE, + DMA_BIDIRECTIONAL); __free_page(node->pages[i]); } /* Release area from GPU address space */ - mutex_lock(priv->mm_mutex); - nvkm_mm_free(priv->mm, &r); - mutex_unlock(priv->mm_mutex); -} + mutex_lock(imem->mm_mutex); + nvkm_mm_free(imem->mm, &r); + mutex_unlock(imem->mm_mutex); -static void -gk20a_instobj_dtor(struct nvkm_object *object) -{ - struct gk20a_instobj_priv *node = (void *)object; - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node); +out: + return node; +} - if (priv->domain) - gk20a_instobj_dtor_iommu(node); - else - gk20a_instobj_dtor_dma(node); +static const struct nvkm_memory_func +gk20a_instobj_func_dma = { + .dtor = gk20a_instobj_dtor_dma, + .target = gk20a_instobj_target, + .addr = gk20a_instobj_addr, + .size = gk20a_instobj_size, + .acquire = gk20a_instobj_acquire, + .release = gk20a_instobj_release, + .rd32 = gk20a_instobj_rd32, + .wr32 = gk20a_instobj_wr32, + .map = gk20a_instobj_map, +}; - nvkm_instobj_destroy(&node->base); -} +static const struct nvkm_memory_func +gk20a_instobj_func_iommu = { + .dtor = gk20a_instobj_dtor_iommu, + .target = gk20a_instobj_target, + .addr = gk20a_instobj_addr, + .size = gk20a_instobj_size, + .acquire = gk20a_instobj_acquire, + .release = gk20a_instobj_release, + .rd32 = gk20a_instobj_rd32, + .wr32 = gk20a_instobj_wr32, + .map = gk20a_instobj_map, +}; static int -gk20a_instobj_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 npages, u32 align, - struct gk20a_instobj_priv **_node) +gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align, + struct gk20a_instobj **_node) { struct gk20a_instobj_dma *node; - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent); - struct device *dev = nv_device_base(nv_device(parent)); - int ret; + struct nvkm_subdev *subdev = &imem->base.subdev; + struct device *dev = subdev->device->dev; - ret = nvkm_instobj_create_(parent, engine, oclass, sizeof(*node), - (void **)&node); + if (!(node = kzalloc(sizeof(*node), GFP_KERNEL))) + return -ENOMEM; *_node = &node->base; - if (ret) - return ret; + + nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory); node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, &node->handle, GFP_KERNEL, - &priv->attrs); + &imem->attrs); if (!node->cpuaddr) { - nv_error(priv, "cannot allocate DMA memory\n"); + nvkm_error(subdev, "cannot allocate DMA memory\n"); return -ENOMEM; } /* alignment check */ if (unlikely(node->handle & (align - 1))) - nv_warn(priv, "memory not aligned as requested: %pad (0x%x)\n", - &node->handle, align); + nvkm_warn(subdev, + "memory not aligned as requested: %pad (0x%x)\n", + &node->handle, align); /* present memory for being mapped using small pages */ node->r.type = 12; node->r.offset = node->handle >> 12; node->r.length = (npages << PAGE_SHIFT) >> 12; - node->base._mem.offset = node->handle; + node->base.mem.offset = node->handle; - INIT_LIST_HEAD(&node->base._mem.regions); - list_add_tail(&node->r.rl_entry, &node->base._mem.regions); + INIT_LIST_HEAD(&node->base.mem.regions); + list_add_tail(&node->r.rl_entry, &node->base.mem.regions); return 0; } static int -gk20a_instobj_ctor_iommu(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, u32 npages, u32 align, - struct gk20a_instobj_priv **_node) +gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, + struct gk20a_instobj **_node) { struct gk20a_instobj_iommu *node; - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent); + struct nvkm_subdev *subdev = &imem->base.subdev; + struct device *dev = subdev->device->dev; struct nvkm_mm_node *r; int ret; int i; - ret = nvkm_instobj_create_(parent, engine, oclass, - sizeof(*node) + sizeof(node->pages[0]) * npages, - (void **)&node); + /* + * despite their variable size, instmem allocations are small enough + * (< 1 page) to be handled by kzalloc + */ + if (!(node = kzalloc(sizeof(*node) + ((sizeof(node->pages[0]) + + sizeof(*node->dma_addrs)) * npages), GFP_KERNEL))) + return -ENOMEM; *_node = &node->base; - if (ret) - return ret; + node->dma_addrs = (void *)(node->pages + npages); + + nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory); /* Allocate backing memory */ for (i = 0; i < npages; i++) { struct page *p = alloc_page(GFP_KERNEL); + dma_addr_t dma_adr; if (p == NULL) { ret = -ENOMEM; goto free_pages; } node->pages[i] = p; + dma_adr = dma_map_page(dev, p, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, dma_adr)) { + nvkm_error(subdev, "DMA mapping error!\n"); + ret = -ENOMEM; + goto free_pages; + } + node->dma_addrs[i] = dma_adr; } - mutex_lock(priv->mm_mutex); + mutex_lock(imem->mm_mutex); /* Reserve area from GPU address space */ - ret = nvkm_mm_head(priv->mm, 0, 1, npages, npages, - align >> priv->iommu_pgshift, &r); - mutex_unlock(priv->mm_mutex); + ret = nvkm_mm_head(imem->mm, 0, 1, npages, npages, + align >> imem->iommu_pgshift, &r); + mutex_unlock(imem->mm_mutex); if (ret) { - nv_error(priv, "virtual space is full!\n"); + nvkm_error(subdev, "IOMMU space is full!\n"); goto free_pages; } /* Map into GPU address space */ for (i = 0; i < npages; i++) { - struct page *p = node->pages[i]; - u32 offset = (r->offset + i) << priv->iommu_pgshift; + u32 offset = (r->offset + i) << imem->iommu_pgshift; - ret = iommu_map(priv->domain, offset, page_to_phys(p), + ret = iommu_map(imem->domain, offset, node->dma_addrs[i], PAGE_SIZE, IOMMU_READ | IOMMU_WRITE); if (ret < 0) { - nv_error(priv, "IOMMU mapping failure: %d\n", ret); + nvkm_error(subdev, "IOMMU mapping failure: %d\n", ret); while (i-- > 0) { offset -= PAGE_SIZE; - iommu_unmap(priv->domain, offset, PAGE_SIZE); + iommu_unmap(imem->domain, offset, PAGE_SIZE); } goto release_area; } } - /* Bit 34 tells that an address is to be resolved through the IOMMU */ - r->offset |= BIT(34 - priv->iommu_pgshift); + /* IOMMU bit tells that an address is to be resolved through the IOMMU */ + r->offset |= BIT(imem->iommu_bit - imem->iommu_pgshift); - node->base._mem.offset = ((u64)r->offset) << priv->iommu_pgshift; + node->base.mem.offset = ((u64)r->offset) << imem->iommu_pgshift; - INIT_LIST_HEAD(&node->base._mem.regions); - list_add_tail(&r->rl_entry, &node->base._mem.regions); + INIT_LIST_HEAD(&node->base.mem.regions); + list_add_tail(&r->rl_entry, &node->base.mem.regions); return 0; release_area: - mutex_lock(priv->mm_mutex); - nvkm_mm_free(priv->mm, &r); - mutex_unlock(priv->mm_mutex); + mutex_lock(imem->mm_mutex); + nvkm_mm_free(imem->mm, &r); + mutex_unlock(imem->mm_mutex); free_pages: - for (i = 0; i < npages && node->pages[i] != NULL; i++) + for (i = 0; i < npages && node->pages[i] != NULL; i++) { + dma_addr_t dma_addr = node->dma_addrs[i]; + if (dma_addr) + dma_unmap_page(dev, dma_addr, PAGE_SIZE, + DMA_BIDIRECTIONAL); __free_page(node->pages[i]); + } return ret; } static int -gk20a_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 _size, - struct nvkm_object **pobject) +gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, + struct nvkm_memory **pmemory) { - struct nvkm_instobj_args *args = data; - struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent); - struct gk20a_instobj_priv *node; - u32 size, align; + struct gk20a_instmem *imem = gk20a_instmem(base); + struct nvkm_subdev *subdev = &imem->base.subdev; + struct gk20a_instobj *node = NULL; int ret; - nv_debug(parent, "%s (%s): size: %x align: %x\n", __func__, - priv->domain ? "IOMMU" : "DMA", args->size, args->align); + nvkm_debug(subdev, "%s (%s): size: %x align: %x\n", __func__, + imem->domain ? "IOMMU" : "DMA", size, align); /* Round size and align to page bounds */ - size = max(roundup(args->size, PAGE_SIZE), PAGE_SIZE); - align = max(roundup(args->align, PAGE_SIZE), PAGE_SIZE); + size = max(roundup(size, PAGE_SIZE), PAGE_SIZE); + align = max(roundup(align, PAGE_SIZE), PAGE_SIZE); - if (priv->domain) - ret = gk20a_instobj_ctor_iommu(parent, engine, oclass, - size >> PAGE_SHIFT, align, &node); + if (imem->domain) + ret = gk20a_instobj_ctor_iommu(imem, size >> PAGE_SHIFT, + align, &node); else - ret = gk20a_instobj_ctor_dma(parent, engine, oclass, - size >> PAGE_SHIFT, align, &node); - *pobject = nv_object(node); + ret = gk20a_instobj_ctor_dma(imem, size >> PAGE_SHIFT, + align, &node); + *pmemory = node ? &node->memory : NULL; if (ret) return ret; - node->mem = &node->_mem; + node->imem = imem; /* present memory for being mapped using small pages */ - node->mem->size = size >> 12; - node->mem->memtype = 0; - node->mem->page_shift = 12; - - node->base.addr = node->mem->offset; - node->base.size = size; + node->mem.size = size >> 12; + node->mem.memtype = 0; + node->mem.page_shift = 12; - nv_debug(parent, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n", - size, align, node->mem->offset); + nvkm_debug(subdev, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n", + size, align, node->mem.offset); return 0; } -static struct nvkm_instobj_impl -gk20a_instobj_oclass = { - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_instobj_ctor, - .dtor = gk20a_instobj_dtor, - .init = _nvkm_instobj_init, - .fini = _nvkm_instobj_fini, - .rd32 = gk20a_instobj_rd32, - .wr32 = gk20a_instobj_wr32, - }, -}; +static void * +gk20a_instmem_dtor(struct nvkm_instmem *base) +{ + struct gk20a_instmem *imem = gk20a_instmem(base); + /* perform some sanity checks... */ + if (!list_empty(&imem->vaddr_lru)) + nvkm_warn(&base->subdev, "instobj LRU not empty!\n"); + if (imem->vaddr_use != 0) + nvkm_warn(&base->subdev, "instobj vmap area not empty! " + "0x%x bytes still mapped\n", imem->vaddr_use); -static int -gk20a_instmem_fini(struct nvkm_object *object, bool suspend) -{ - struct gk20a_instmem_priv *priv = (void *)object; - priv->addr = ~0ULL; - return nvkm_instmem_fini(&priv->base, suspend); + return imem; } -static int -gk20a_instmem_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk20a_instmem_priv *priv; - struct nouveau_platform_device *plat; - int ret; - - ret = nvkm_instmem_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - spin_lock_init(&priv->lock); +static const struct nvkm_instmem_func +gk20a_instmem = { + .dtor = gk20a_instmem_dtor, + .memory_new = gk20a_instobj_new, + .persistent = true, + .zero = false, +}; - plat = nv_device_to_platform(nv_device(parent)); - if (plat->gpu->iommu.domain) { - priv->domain = plat->gpu->iommu.domain; - priv->mm = plat->gpu->iommu.mm; - priv->iommu_pgshift = plat->gpu->iommu.pgshift; - priv->mm_mutex = &plat->gpu->iommu.mutex; +int +gk20a_instmem_new(struct nvkm_device *device, int index, + struct nvkm_instmem **pimem) +{ + struct nvkm_device_tegra *tdev = device->func->tegra(device); + struct gk20a_instmem *imem; - nv_info(priv, "using IOMMU\n"); + if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) + return -ENOMEM; + nvkm_instmem_ctor(&gk20a_instmem, device, index, &imem->base); + spin_lock_init(&imem->lock); + *pimem = &imem->base; + + /* do not allow more than 1MB of CPU-mapped instmem */ + imem->vaddr_use = 0; + imem->vaddr_max = 0x100000; + INIT_LIST_HEAD(&imem->vaddr_lru); + + if (tdev->iommu.domain) { + imem->mm_mutex = &tdev->iommu.mutex; + imem->mm = &tdev->iommu.mm; + imem->domain = tdev->iommu.domain; + imem->iommu_pgshift = tdev->iommu.pgshift; + imem->cpu_map = gk20a_instobj_cpu_map_iommu; + imem->iommu_bit = tdev->func->iommu_bit; + + nvkm_info(&imem->base.subdev, "using IOMMU\n"); } else { - init_dma_attrs(&priv->attrs); - /* - * We will access instmem through PRAMIN and thus do not need a - * consistent CPU pointer or kernel mapping - */ - dma_set_attr(DMA_ATTR_NON_CONSISTENT, &priv->attrs); - dma_set_attr(DMA_ATTR_WEAK_ORDERING, &priv->attrs); - dma_set_attr(DMA_ATTR_WRITE_COMBINE, &priv->attrs); - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &priv->attrs); - - nv_info(priv, "using DMA API\n"); + init_dma_attrs(&imem->attrs); + /* We will access the memory through our own mapping */ + dma_set_attr(DMA_ATTR_NON_CONSISTENT, &imem->attrs); + dma_set_attr(DMA_ATTR_WEAK_ORDERING, &imem->attrs); + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &imem->attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem->attrs); + imem->cpu_map = gk20a_instobj_cpu_map_dma; + + nvkm_info(&imem->base.subdev, "using DMA API\n"); } return 0; } - -struct nvkm_oclass * -gk20a_instmem_oclass = &(struct nvkm_instmem_impl) { - .base.handle = NV_SUBDEV(INSTMEM, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_instmem_ctor, - .dtor = _nvkm_instmem_dtor, - .init = _nvkm_instmem_init, - .fini = gk20a_instmem_fini, - }, - .instobj = &gk20a_instobj_oclass.base, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c index 282143f49..6133c8bb2 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c @@ -21,173 +21,207 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#define nv04_instmem(p) container_of((p), struct nv04_instmem, base) +#include "priv.h" +#include #include +struct nv04_instmem { + struct nvkm_instmem base; + struct nvkm_mm heap; +}; + /****************************************************************************** * instmem object implementation *****************************************************************************/ +#define nv04_instobj(p) container_of((p), struct nv04_instobj, memory) -static u32 -nv04_instobj_rd32(struct nvkm_object *object, u64 addr) +struct nv04_instobj { + struct nvkm_memory memory; + struct nv04_instmem *imem; + struct nvkm_mm_node *node; +}; + +static enum nvkm_memory_target +nv04_instobj_target(struct nvkm_memory *memory) { - struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); - struct nv04_instobj_priv *node = (void *)object; - return nv_ro32(priv, node->mem->offset + addr); + return NVKM_MEM_TARGET_INST; } -static void -nv04_instobj_wr32(struct nvkm_object *object, u64 addr, u32 data) +static u64 +nv04_instobj_addr(struct nvkm_memory *memory) +{ + return nv04_instobj(memory)->node->offset; +} + +static u64 +nv04_instobj_size(struct nvkm_memory *memory) +{ + return nv04_instobj(memory)->node->length; +} + +static void __iomem * +nv04_instobj_acquire(struct nvkm_memory *memory) { - struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); - struct nv04_instobj_priv *node = (void *)object; - nv_wo32(priv, node->mem->offset + addr, data); + struct nv04_instobj *iobj = nv04_instobj(memory); + struct nvkm_device *device = iobj->imem->base.subdev.device; + return device->pri + 0x700000 + iobj->node->offset; } static void -nv04_instobj_dtor(struct nvkm_object *object) +nv04_instobj_release(struct nvkm_memory *memory) { - struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); - struct nv04_instobj_priv *node = (void *)object; - struct nvkm_subdev *subdev = (void *)priv; +} - mutex_lock(&subdev->mutex); - nvkm_mm_free(&priv->heap, &node->mem); - mutex_unlock(&subdev->mutex); +static u32 +nv04_instobj_rd32(struct nvkm_memory *memory, u64 offset) +{ + struct nv04_instobj *iobj = nv04_instobj(memory); + struct nvkm_device *device = iobj->imem->base.subdev.device; + return nvkm_rd32(device, 0x700000 + iobj->node->offset + offset); +} - nvkm_instobj_destroy(&node->base); +static void +nv04_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) +{ + struct nv04_instobj *iobj = nv04_instobj(memory); + struct nvkm_device *device = iobj->imem->base.subdev.device; + nvkm_wr32(device, 0x700000 + iobj->node->offset + offset, data); } +static void * +nv04_instobj_dtor(struct nvkm_memory *memory) +{ + struct nv04_instobj *iobj = nv04_instobj(memory); + mutex_lock(&iobj->imem->base.subdev.mutex); + nvkm_mm_free(&iobj->imem->heap, &iobj->node); + mutex_unlock(&iobj->imem->base.subdev.mutex); + return iobj; +} + +static const struct nvkm_memory_func +nv04_instobj_func = { + .dtor = nv04_instobj_dtor, + .target = nv04_instobj_target, + .size = nv04_instobj_size, + .addr = nv04_instobj_addr, + .acquire = nv04_instobj_acquire, + .release = nv04_instobj_release, + .rd32 = nv04_instobj_rd32, + .wr32 = nv04_instobj_wr32, +}; + static int -nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, + struct nvkm_memory **pmemory) { - struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent); - struct nv04_instobj_priv *node; - struct nvkm_instobj_args *args = data; - struct nvkm_subdev *subdev = (void *)priv; + struct nv04_instmem *imem = nv04_instmem(base); + struct nv04_instobj *iobj; int ret; - if (!args->align) - args->align = 1; + if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) + return -ENOMEM; + *pmemory = &iobj->memory; - ret = nvkm_instobj_create(parent, engine, oclass, &node); - *pobject = nv_object(node); - if (ret) - return ret; - - mutex_lock(&subdev->mutex); - ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size, - args->align, &node->mem); - mutex_unlock(&subdev->mutex); - if (ret) - return ret; + nvkm_memory_ctor(&nv04_instobj_func, &iobj->memory); + iobj->imem = imem; - node->base.addr = node->mem->offset; - node->base.size = node->mem->length; - return 0; + mutex_lock(&imem->base.subdev.mutex); + ret = nvkm_mm_head(&imem->heap, 0, 1, size, size, + align ? align : 1, &iobj->node); + mutex_unlock(&imem->base.subdev.mutex); + return ret; } -struct nvkm_instobj_impl -nv04_instobj_oclass = { - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_instobj_ctor, - .dtor = nv04_instobj_dtor, - .init = _nvkm_instobj_init, - .fini = _nvkm_instobj_fini, - .rd32 = nv04_instobj_rd32, - .wr32 = nv04_instobj_wr32, - }, -}; - /****************************************************************************** * instmem subdev implementation *****************************************************************************/ static u32 -nv04_instmem_rd32(struct nvkm_object *object, u64 addr) +nv04_instmem_rd32(struct nvkm_instmem *imem, u32 addr) { - return nv_rd32(object, 0x700000 + addr); + return nvkm_rd32(imem->subdev.device, 0x700000 + addr); } static void -nv04_instmem_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - return nv_wr32(object, 0x700000 + addr, data); -} - -void -nv04_instmem_dtor(struct nvkm_object *object) +nv04_instmem_wr32(struct nvkm_instmem *imem, u32 addr, u32 data) { - struct nv04_instmem_priv *priv = (void *)object; - nvkm_gpuobj_ref(NULL, &priv->ramfc); - nvkm_gpuobj_ref(NULL, &priv->ramro); - nvkm_ramht_ref(NULL, &priv->ramht); - nvkm_gpuobj_ref(NULL, &priv->vbios); - nvkm_mm_fini(&priv->heap); - if (priv->iomem) - iounmap(priv->iomem); - nvkm_instmem_destroy(&priv->base); + nvkm_wr32(imem->subdev.device, 0x700000 + addr, data); } static int -nv04_instmem_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_instmem_oneinit(struct nvkm_instmem *base) { - struct nv04_instmem_priv *priv; + struct nv04_instmem *imem = nv04_instmem(base); + struct nvkm_device *device = imem->base.subdev.device; int ret; - ret = nvkm_instmem_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - /* PRAMIN aperture maps over the end of VRAM, reserve it */ - priv->base.reserved = 512 * 1024; + imem->base.reserved = 512 * 1024; - ret = nvkm_mm_init(&priv->heap, 0, priv->base.reserved, 1); + ret = nvkm_mm_init(&imem->heap, 0, imem->base.reserved, 1); if (ret) return ret; /* 0x00000-0x10000: reserve for probable vbios image */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x10000, 0, 0, - &priv->vbios); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x10000, 0, false, + &imem->base.vbios); if (ret) return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nvkm_ramht_new(nv_object(priv), NULL, 0x08000, 0, &priv->ramht); + ret = nvkm_ramht_new(device, 0x08000, 0, NULL, &imem->base.ramht); if (ret) return ret; /* 0x18000-0x18800: reserve for RAMFC (enough for 32 nv30 channels) */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x00800, 0, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x00800, 0, true, + &imem->base.ramfc); if (ret) return ret; /* 0x18800-0x18a00: reserve for RAMRO */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x00200, 0, 0, - &priv->ramro); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x00200, 0, false, + &imem->base.ramro); if (ret) return ret; return 0; } -struct nvkm_oclass * -nv04_instmem_oclass = &(struct nvkm_instmem_impl) { - .base.handle = NV_SUBDEV(INSTMEM, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_instmem_ctor, - .dtor = nv04_instmem_dtor, - .init = _nvkm_instmem_init, - .fini = _nvkm_instmem_fini, - .rd32 = nv04_instmem_rd32, - .wr32 = nv04_instmem_wr32, - }, - .instobj = &nv04_instobj_oclass.base, -}.base; +static void * +nv04_instmem_dtor(struct nvkm_instmem *base) +{ + struct nv04_instmem *imem = nv04_instmem(base); + nvkm_memory_del(&imem->base.ramfc); + nvkm_memory_del(&imem->base.ramro); + nvkm_ramht_del(&imem->base.ramht); + nvkm_memory_del(&imem->base.vbios); + nvkm_mm_fini(&imem->heap); + return imem; +} + +static const struct nvkm_instmem_func +nv04_instmem = { + .dtor = nv04_instmem_dtor, + .oneinit = nv04_instmem_oneinit, + .rd32 = nv04_instmem_rd32, + .wr32 = nv04_instmem_wr32, + .memory_new = nv04_instobj_new, + .persistent = false, + .zero = false, +}; + +int +nv04_instmem_new(struct nvkm_device *device, int index, + struct nvkm_instmem **pimem) +{ + struct nv04_instmem *imem; + + if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) + return -ENOMEM; + nvkm_instmem_ctor(&nv04_instmem, device, index, &imem->base); + *pimem = &imem->base; + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.h deleted file mode 100644 index 42b6c9280..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __NV04_INSTMEM_H__ -#define __NV04_INSTMEM_H__ -#include "priv.h" - -#include - -extern struct nvkm_instobj_impl nv04_instobj_oclass; - -struct nv04_instmem_priv { - struct nvkm_instmem base; - - void __iomem *iomem; - struct nvkm_mm heap; - - struct nvkm_gpuobj *vbios; - struct nvkm_ramht *ramht; - struct nvkm_gpuobj *ramro; - struct nvkm_gpuobj *ramfc; -}; - -static inline struct nv04_instmem_priv * -nv04_instmem(void *obj) -{ - return (void *)nvkm_instmem(obj); -} - -struct nv04_instobj_priv { - struct nvkm_instobj base; - struct nvkm_mm_node *mem; -}; - -void nv04_instmem_dtor(struct nvkm_object *); - -int nv04_instmem_alloc(struct nvkm_instmem *, struct nvkm_object *, - u32 size, u32 align, struct nvkm_object **pobject); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c index b42b8588f..c0543875e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c @@ -21,116 +21,239 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#define nv40_instmem(p) container_of((p), struct nv40_instmem, base) +#include "priv.h" +#include #include #include +struct nv40_instmem { + struct nvkm_instmem base; + struct nvkm_mm heap; + void __iomem *iomem; +}; + /****************************************************************************** - * instmem subdev implementation + * instmem object implementation *****************************************************************************/ +#define nv40_instobj(p) container_of((p), struct nv40_instobj, memory) + +struct nv40_instobj { + struct nvkm_memory memory; + struct nv40_instmem *imem; + struct nvkm_mm_node *node; +}; + +static enum nvkm_memory_target +nv40_instobj_target(struct nvkm_memory *memory) +{ + return NVKM_MEM_TARGET_INST; +} + +static u64 +nv40_instobj_addr(struct nvkm_memory *memory) +{ + return nv40_instobj(memory)->node->offset; +} + +static u64 +nv40_instobj_size(struct nvkm_memory *memory) +{ + return nv40_instobj(memory)->node->length; +} + +static void __iomem * +nv40_instobj_acquire(struct nvkm_memory *memory) +{ + struct nv40_instobj *iobj = nv40_instobj(memory); + return iobj->imem->iomem + iobj->node->offset; +} + +static void +nv40_instobj_release(struct nvkm_memory *memory) +{ +} static u32 -nv40_instmem_rd32(struct nvkm_object *object, u64 addr) +nv40_instobj_rd32(struct nvkm_memory *memory, u64 offset) { - struct nv04_instmem_priv *priv = (void *)object; - return ioread32_native(priv->iomem + addr); + struct nv40_instobj *iobj = nv40_instobj(memory); + return ioread32_native(iobj->imem->iomem + iobj->node->offset + offset); } static void -nv40_instmem_wr32(struct nvkm_object *object, u64 addr, u32 data) +nv40_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) +{ + struct nv40_instobj *iobj = nv40_instobj(memory); + iowrite32_native(data, iobj->imem->iomem + iobj->node->offset + offset); +} + +static void * +nv40_instobj_dtor(struct nvkm_memory *memory) { - struct nv04_instmem_priv *priv = (void *)object; - iowrite32_native(data, priv->iomem + addr); + struct nv40_instobj *iobj = nv40_instobj(memory); + mutex_lock(&iobj->imem->base.subdev.mutex); + nvkm_mm_free(&iobj->imem->heap, &iobj->node); + mutex_unlock(&iobj->imem->base.subdev.mutex); + return iobj; } +static const struct nvkm_memory_func +nv40_instobj_func = { + .dtor = nv40_instobj_dtor, + .target = nv40_instobj_target, + .size = nv40_instobj_size, + .addr = nv40_instobj_addr, + .acquire = nv40_instobj_acquire, + .release = nv40_instobj_release, + .rd32 = nv40_instobj_rd32, + .wr32 = nv40_instobj_wr32, +}; + static int -nv40_instmem_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv40_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, + struct nvkm_memory **pmemory) { - struct nvkm_device *device = nv_device(parent); - struct nv04_instmem_priv *priv; - int ret, bar, vs; + struct nv40_instmem *imem = nv40_instmem(base); + struct nv40_instobj *iobj; + int ret; - ret = nvkm_instmem_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; + if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) + return -ENOMEM; + *pmemory = &iobj->memory; - /* map bar */ - if (nv_device_resource_len(device, 2)) - bar = 2; - else - bar = 3; + nvkm_memory_ctor(&nv40_instobj_func, &iobj->memory); + iobj->imem = imem; - priv->iomem = ioremap(nv_device_resource_start(device, bar), - nv_device_resource_len(device, bar)); - if (!priv->iomem) { - nv_error(priv, "unable to map PRAMIN BAR\n"); - return -EFAULT; - } + mutex_lock(&imem->base.subdev.mutex); + ret = nvkm_mm_head(&imem->heap, 0, 1, size, size, + align ? align : 1, &iobj->node); + mutex_unlock(&imem->base.subdev.mutex); + return ret; +} + +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ + +static u32 +nv40_instmem_rd32(struct nvkm_instmem *base, u32 addr) +{ + return ioread32_native(nv40_instmem(base)->iomem + addr); +} + +static void +nv40_instmem_wr32(struct nvkm_instmem *base, u32 addr, u32 data) +{ + iowrite32_native(data, nv40_instmem(base)->iomem + addr); +} + +static int +nv40_instmem_oneinit(struct nvkm_instmem *base) +{ + struct nv40_instmem *imem = nv40_instmem(base); + struct nvkm_device *device = imem->base.subdev.device; + int ret, vs; /* PRAMIN aperture maps over the end of vram, reserve enough space * to fit graphics contexts for every channel, the magics come * from engine/gr/nv40.c */ - vs = hweight8((nv_rd32(priv, 0x001540) & 0x0000ff00) >> 8); - if (device->chipset == 0x40) priv->base.reserved = 0x6aa0 * vs; - else if (device->chipset < 0x43) priv->base.reserved = 0x4f00 * vs; - else if (nv44_gr_class(priv)) priv->base.reserved = 0x4980 * vs; - else priv->base.reserved = 0x4a40 * vs; - priv->base.reserved += 16 * 1024; - priv->base.reserved *= 32; /* per-channel */ - priv->base.reserved += 512 * 1024; /* pci(e)gart table */ - priv->base.reserved += 512 * 1024; /* object storage */ - - priv->base.reserved = round_up(priv->base.reserved, 4096); - - ret = nvkm_mm_init(&priv->heap, 0, priv->base.reserved, 1); + vs = hweight8((nvkm_rd32(device, 0x001540) & 0x0000ff00) >> 8); + if (device->chipset == 0x40) imem->base.reserved = 0x6aa0 * vs; + else if (device->chipset < 0x43) imem->base.reserved = 0x4f00 * vs; + else if (nv44_gr_class(device)) imem->base.reserved = 0x4980 * vs; + else imem->base.reserved = 0x4a40 * vs; + imem->base.reserved += 16 * 1024; + imem->base.reserved *= 32; /* per-channel */ + imem->base.reserved += 512 * 1024; /* pci(e)gart table */ + imem->base.reserved += 512 * 1024; /* object storage */ + imem->base.reserved = round_up(imem->base.reserved, 4096); + + ret = nvkm_mm_init(&imem->heap, 0, imem->base.reserved, 1); if (ret) return ret; /* 0x00000-0x10000: reserve for probable vbios image */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x10000, 0, 0, - &priv->vbios); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x10000, 0, false, + &imem->base.vbios); if (ret) return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nvkm_ramht_new(nv_object(priv), NULL, 0x08000, 0, &priv->ramht); + ret = nvkm_ramht_new(device, 0x08000, 0, NULL, &imem->base.ramht); if (ret) return ret; /* 0x18000-0x18200: reserve for RAMRO * 0x18200-0x20000: padding */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x08000, 0, 0, - &priv->ramro); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x08000, 0, false, + &imem->base.ramro); if (ret) return ret; /* 0x20000-0x21000: reserve for RAMFC * 0x21000-0x40000: padding and some unknown crap */ - ret = nvkm_gpuobj_new(nv_object(priv), NULL, 0x20000, 0, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x20000, 0, true, + &imem->base.ramfc); if (ret) return ret; return 0; } -struct nvkm_oclass * -nv40_instmem_oclass = &(struct nvkm_instmem_impl) { - .base.handle = NV_SUBDEV(INSTMEM, 0x40), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_instmem_ctor, - .dtor = nv04_instmem_dtor, - .init = _nvkm_instmem_init, - .fini = _nvkm_instmem_fini, - .rd32 = nv40_instmem_rd32, - .wr32 = nv40_instmem_wr32, - }, - .instobj = &nv04_instobj_oclass.base, -}.base; +static void * +nv40_instmem_dtor(struct nvkm_instmem *base) +{ + struct nv40_instmem *imem = nv40_instmem(base); + nvkm_memory_del(&imem->base.ramfc); + nvkm_memory_del(&imem->base.ramro); + nvkm_ramht_del(&imem->base.ramht); + nvkm_memory_del(&imem->base.vbios); + nvkm_mm_fini(&imem->heap); + if (imem->iomem) + iounmap(imem->iomem); + return imem; +} + +static const struct nvkm_instmem_func +nv40_instmem = { + .dtor = nv40_instmem_dtor, + .oneinit = nv40_instmem_oneinit, + .rd32 = nv40_instmem_rd32, + .wr32 = nv40_instmem_wr32, + .memory_new = nv40_instobj_new, + .persistent = false, + .zero = false, +}; + +int +nv40_instmem_new(struct nvkm_device *device, int index, + struct nvkm_instmem **pimem) +{ + struct nv40_instmem *imem; + int bar; + + if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) + return -ENOMEM; + nvkm_instmem_ctor(&nv40_instmem, device, index, &imem->base); + *pimem = &imem->base; + + /* map bar */ + if (device->func->resource_size(device, 2)) + bar = 2; + else + bar = 3; + + imem->iomem = ioremap(device->func->resource_addr(device, bar), + device->func->resource_size(device, bar)); + if (!imem->iomem) { + nvkm_error(&imem->base.subdev, "unable to map PRAMIN BAR\n"); + return -EFAULT; + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index 8404143f9..6d512c062 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -21,149 +21,229 @@ * * Authors: Ben Skeggs */ +#define nv50_instmem(p) container_of((p), struct nv50_instmem, base) #include "priv.h" +#include +#include #include +#include -struct nv50_instmem_priv { +struct nv50_instmem { struct nvkm_instmem base; + unsigned long lock_flags; spinlock_t lock; u64 addr; }; -struct nv50_instobj_priv { - struct nvkm_instobj base; - struct nvkm_mem *mem; -}; - /****************************************************************************** * instmem object implementation *****************************************************************************/ +#define nv50_instobj(p) container_of((p), struct nv50_instobj, memory) -static u32 -nv50_instobj_rd32(struct nvkm_object *object, u64 offset) +struct nv50_instobj { + struct nvkm_memory memory; + struct nv50_instmem *imem; + struct nvkm_mem *mem; + struct nvkm_vma bar; + void *map; +}; + +static enum nvkm_memory_target +nv50_instobj_target(struct nvkm_memory *memory) +{ + return NVKM_MEM_TARGET_VRAM; +} + +static u64 +nv50_instobj_addr(struct nvkm_memory *memory) +{ + return nv50_instobj(memory)->mem->offset; +} + +static u64 +nv50_instobj_size(struct nvkm_memory *memory) +{ + return (u64)nv50_instobj(memory)->mem->size << NVKM_RAM_MM_SHIFT; +} + +static void +nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm) +{ + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nvkm_subdev *subdev = &iobj->imem->base.subdev; + struct nvkm_device *device = subdev->device; + u64 size = nvkm_memory_size(memory); + void __iomem *map; + int ret; + + iobj->map = ERR_PTR(-ENOMEM); + + ret = nvkm_vm_get(vm, size, 12, NV_MEM_ACCESS_RW, &iobj->bar); + if (ret == 0) { + map = ioremap(device->func->resource_addr(device, 3) + + (u32)iobj->bar.offset, size); + if (map) { + nvkm_memory_map(memory, &iobj->bar, 0); + iobj->map = map; + } else { + nvkm_warn(subdev, "PRAMIN ioremap failed\n"); + nvkm_vm_put(&iobj->bar); + } + } else { + nvkm_warn(subdev, "PRAMIN exhausted\n"); + } +} + +static void +nv50_instobj_release(struct nvkm_memory *memory) { - struct nv50_instmem_priv *priv = (void *)nvkm_instmem(object); - struct nv50_instobj_priv *node = (void *)object; + struct nv50_instmem *imem = nv50_instobj(memory)->imem; + spin_unlock_irqrestore(&imem->lock, imem->lock_flags); +} + +static void __iomem * +nv50_instobj_acquire(struct nvkm_memory *memory) +{ + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nv50_instmem *imem = iobj->imem; + struct nvkm_bar *bar = imem->base.subdev.device->bar; + struct nvkm_vm *vm; unsigned long flags; - u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; - u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; + + if (!iobj->map && (vm = nvkm_bar_kmap(bar))) + nvkm_memory_boot(memory, vm); + if (!IS_ERR_OR_NULL(iobj->map)) + return iobj->map; + + spin_lock_irqsave(&imem->lock, flags); + imem->lock_flags = flags; + return NULL; +} + +static u32 +nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset) +{ + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nv50_instmem *imem = iobj->imem; + struct nvkm_device *device = imem->base.subdev.device; + u64 base = (iobj->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (iobj->mem->offset + offset) & 0x000000fffffULL; u32 data; - spin_lock_irqsave(&priv->lock, flags); - if (unlikely(priv->addr != base)) { - nv_wr32(priv, 0x001700, base >> 16); - priv->addr = base; + if (unlikely(imem->addr != base)) { + nvkm_wr32(device, 0x001700, base >> 16); + imem->addr = base; } - data = nv_rd32(priv, 0x700000 + addr); - spin_unlock_irqrestore(&priv->lock, flags); + data = nvkm_rd32(device, 0x700000 + addr); return data; } static void -nv50_instobj_wr32(struct nvkm_object *object, u64 offset, u32 data) +nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) { - struct nv50_instmem_priv *priv = (void *)nvkm_instmem(object); - struct nv50_instobj_priv *node = (void *)object; - unsigned long flags; - u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; - u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; - - spin_lock_irqsave(&priv->lock, flags); - if (unlikely(priv->addr != base)) { - nv_wr32(priv, 0x001700, base >> 16); - priv->addr = base; + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nv50_instmem *imem = iobj->imem; + struct nvkm_device *device = imem->base.subdev.device; + u64 base = (iobj->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (iobj->mem->offset + offset) & 0x000000fffffULL; + + if (unlikely(imem->addr != base)) { + nvkm_wr32(device, 0x001700, base >> 16); + imem->addr = base; } - nv_wr32(priv, 0x700000 + addr, data); - spin_unlock_irqrestore(&priv->lock, flags); + nvkm_wr32(device, 0x700000 + addr, data); } static void -nv50_instobj_dtor(struct nvkm_object *object) +nv50_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) { - struct nv50_instobj_priv *node = (void *)object; - struct nvkm_fb *pfb = nvkm_fb(object); - pfb->ram->put(pfb, &node->mem); - nvkm_instobj_destroy(&node->base); + struct nv50_instobj *iobj = nv50_instobj(memory); + nvkm_vm_map_at(vma, offset, iobj->mem); } +static void * +nv50_instobj_dtor(struct nvkm_memory *memory) +{ + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nvkm_ram *ram = iobj->imem->base.subdev.device->fb->ram; + if (!IS_ERR_OR_NULL(iobj->map)) { + nvkm_vm_put(&iobj->bar); + iounmap(iobj->map); + } + ram->func->put(ram, &iobj->mem); + return iobj; +} + +static const struct nvkm_memory_func +nv50_instobj_func = { + .dtor = nv50_instobj_dtor, + .target = nv50_instobj_target, + .size = nv50_instobj_size, + .addr = nv50_instobj_addr, + .boot = nv50_instobj_boot, + .acquire = nv50_instobj_acquire, + .release = nv50_instobj_release, + .rd32 = nv50_instobj_rd32, + .wr32 = nv50_instobj_wr32, + .map = nv50_instobj_map, +}; + static int -nv50_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, + struct nvkm_memory **pmemory) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_instobj_args *args = data; - struct nv50_instobj_priv *node; + struct nv50_instmem *imem = nv50_instmem(base); + struct nv50_instobj *iobj; + struct nvkm_ram *ram = imem->base.subdev.device->fb->ram; int ret; - args->size = max((args->size + 4095) & ~4095, (u32)4096); - args->align = max((args->align + 4095) & ~4095, (u32)4096); + if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) + return -ENOMEM; + *pmemory = &iobj->memory; - ret = nvkm_instobj_create(parent, engine, oclass, &node); - *pobject = nv_object(node); - if (ret) - return ret; + nvkm_memory_ctor(&nv50_instobj_func, &iobj->memory); + iobj->imem = imem; + + size = max((size + 4095) & ~4095, (u32)4096); + align = max((align + 4095) & ~4095, (u32)4096); - ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem); + ret = ram->func->get(ram, size, align, 0, 0x800, &iobj->mem); if (ret) return ret; - node->base.addr = node->mem->offset; - node->base.size = node->mem->size << 12; - node->mem->page_shift = 12; + iobj->mem->page_shift = 12; return 0; } -static struct nvkm_instobj_impl -nv50_instobj_oclass = { - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_instobj_ctor, - .dtor = nv50_instobj_dtor, - .init = _nvkm_instobj_init, - .fini = _nvkm_instobj_fini, - .rd32 = nv50_instobj_rd32, - .wr32 = nv50_instobj_wr32, - }, -}; - /****************************************************************************** * instmem subdev implementation *****************************************************************************/ -static int -nv50_instmem_fini(struct nvkm_object *object, bool suspend) +static void +nv50_instmem_fini(struct nvkm_instmem *base) { - struct nv50_instmem_priv *priv = (void *)object; - priv->addr = ~0ULL; - return nvkm_instmem_fini(&priv->base, suspend); + nv50_instmem(base)->addr = ~0ULL; } -static int -nv50_instmem_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_instmem_priv *priv; - int ret; +static const struct nvkm_instmem_func +nv50_instmem = { + .fini = nv50_instmem_fini, + .memory_new = nv50_instobj_new, + .persistent = false, + .zero = false, +}; - ret = nvkm_instmem_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +int +nv50_instmem_new(struct nvkm_device *device, int index, + struct nvkm_instmem **pimem) +{ + struct nv50_instmem *imem; - spin_lock_init(&priv->lock); + if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) + return -ENOMEM; + nvkm_instmem_ctor(&nv50_instmem, device, index, &imem->base); + spin_lock_init(&imem->lock); + *pimem = &imem->base; return 0; } - -struct nvkm_oclass * -nv50_instmem_oclass = &(struct nvkm_instmem_impl) { - .base.handle = NV_SUBDEV(INSTMEM, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_instmem_ctor, - .dtor = _nvkm_instmem_dtor, - .init = _nvkm_instmem_init, - .fini = nv50_instmem_fini, - }, - .instobj = &nv50_instobj_oclass.base, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h index b10e292e5..ace447186 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h @@ -1,54 +1,20 @@ #ifndef __NVKM_INSTMEM_PRIV_H__ #define __NVKM_INSTMEM_PRIV_H__ +#define nvkm_instmem(p) container_of((p), struct nvkm_instmem, subdev) #include -struct nvkm_instobj_impl { - struct nvkm_oclass base; +struct nvkm_instmem_func { + void *(*dtor)(struct nvkm_instmem *); + int (*oneinit)(struct nvkm_instmem *); + void (*fini)(struct nvkm_instmem *); + u32 (*rd32)(struct nvkm_instmem *, u32 addr); + void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data); + int (*memory_new)(struct nvkm_instmem *, u32 size, u32 align, + bool zero, struct nvkm_memory **); + bool persistent; + bool zero; }; -struct nvkm_instobj_args { - u32 size; - u32 align; -}; - -#define nvkm_instobj_create(p,e,o,d) \ - nvkm_instobj_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_instobj_destroy(p) ({ \ - struct nvkm_instobj *iobj = (p); \ - _nvkm_instobj_dtor(nv_object(iobj)); \ -}) -#define nvkm_instobj_init(p) \ - nvkm_object_init(&(p)->base) -#define nvkm_instobj_fini(p,s) \ - nvkm_object_fini(&(p)->base, (s)) - -int nvkm_instobj_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_instobj_dtor(struct nvkm_object *); -#define _nvkm_instobj_init nvkm_object_init -#define _nvkm_instobj_fini nvkm_object_fini - -struct nvkm_instmem_impl { - struct nvkm_oclass base; - struct nvkm_oclass *instobj; -}; - -#define nvkm_instmem_create(p,e,o,d) \ - nvkm_instmem_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_instmem_destroy(p) \ - nvkm_subdev_destroy(&(p)->base) -#define nvkm_instmem_init(p) ({ \ - struct nvkm_instmem *imem = (p); \ - _nvkm_instmem_init(nv_object(imem)); \ -}) -#define nvkm_instmem_fini(p,s) ({ \ - struct nvkm_instmem *imem = (p); \ - _nvkm_instmem_fini(nv_object(imem), (s)); \ -}) - -int nvkm_instmem_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -#define _nvkm_instmem_dtor _nvkm_subdev_dtor -int _nvkm_instmem_init(struct nvkm_object *); -int _nvkm_instmem_fini(struct nvkm_object *, bool); +void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *, + int index, struct nvkm_instmem *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c index 2fb87fbfd..85b1464c0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c @@ -23,102 +23,124 @@ */ #include "priv.h" -static int +#include + +int nvkm_ltc_tags_alloc(struct nvkm_ltc *ltc, u32 n, struct nvkm_mm_node **pnode) { - struct nvkm_ltc_priv *priv = (void *)ltc; - int ret; - - ret = nvkm_mm_head(&priv->tags, 0, 1, n, n, 1, pnode); + int ret = nvkm_mm_head(<c->tags, 0, 1, n, n, 1, pnode); if (ret) *pnode = NULL; - return ret; } -static void +void nvkm_ltc_tags_free(struct nvkm_ltc *ltc, struct nvkm_mm_node **pnode) { - struct nvkm_ltc_priv *priv = (void *)ltc; - nvkm_mm_free(&priv->tags, pnode); + nvkm_mm_free(<c->tags, pnode); } -static void +void nvkm_ltc_tags_clear(struct nvkm_ltc *ltc, u32 first, u32 count) { - const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc); - struct nvkm_ltc_priv *priv = (void *)ltc; const u32 limit = first + count - 1; - BUG_ON((first > limit) || (limit >= priv->num_tags)); + BUG_ON((first > limit) || (limit >= ltc->num_tags)); - impl->cbc_clear(priv, first, limit); - impl->cbc_wait(priv); + ltc->func->cbc_clear(ltc, first, limit); + ltc->func->cbc_wait(ltc); } -static int +int nvkm_ltc_zbc_color_get(struct nvkm_ltc *ltc, int index, const u32 color[4]) { - const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc); - struct nvkm_ltc_priv *priv = (void *)ltc; - memcpy(priv->zbc_color[index], color, sizeof(priv->zbc_color[index])); - impl->zbc_clear_color(priv, index, color); + memcpy(ltc->zbc_color[index], color, sizeof(ltc->zbc_color[index])); + ltc->func->zbc_clear_color(ltc, index, color); return index; } -static int +int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *ltc, int index, const u32 depth) { - const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc); - struct nvkm_ltc_priv *priv = (void *)ltc; - priv->zbc_depth[index] = depth; - impl->zbc_clear_depth(priv, index, depth); + ltc->zbc_depth[index] = depth; + ltc->func->zbc_clear_depth(ltc, index, depth); return index; } -int -_nvkm_ltc_init(struct nvkm_object *object) +void +nvkm_ltc_invalidate(struct nvkm_ltc *ltc) { - const struct nvkm_ltc_impl *impl = (void *)nv_oclass(object); - struct nvkm_ltc_priv *priv = (void *)object; - int ret, i; + if (ltc->func->invalidate) + ltc->func->invalidate(ltc); +} - ret = nvkm_subdev_init(&priv->base.base); - if (ret) - return ret; +void +nvkm_ltc_flush(struct nvkm_ltc *ltc) +{ + if (ltc->func->flush) + ltc->func->flush(ltc); +} - for (i = priv->base.zbc_min; i <= priv->base.zbc_max; i++) { - impl->zbc_clear_color(priv, i, priv->zbc_color[i]); - impl->zbc_clear_depth(priv, i, priv->zbc_depth[i]); +static void +nvkm_ltc_intr(struct nvkm_subdev *subdev) +{ + struct nvkm_ltc *ltc = nvkm_ltc(subdev); + ltc->func->intr(ltc); +} + +static int +nvkm_ltc_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_ltc *ltc = nvkm_ltc(subdev); + return ltc->func->oneinit(ltc); +} + +static int +nvkm_ltc_init(struct nvkm_subdev *subdev) +{ + struct nvkm_ltc *ltc = nvkm_ltc(subdev); + int i; + + for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) { + ltc->func->zbc_clear_color(ltc, i, ltc->zbc_color[i]); + ltc->func->zbc_clear_depth(ltc, i, ltc->zbc_depth[i]); } + ltc->func->init(ltc); return 0; } +static void * +nvkm_ltc_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_ltc *ltc = nvkm_ltc(subdev); + struct nvkm_ram *ram = ltc->subdev.device->fb->ram; + nvkm_mm_fini(<c->tags); + if (ram) + nvkm_mm_free(&ram->vram, <c->tag_ram); + return ltc; +} + +static const struct nvkm_subdev_func +nvkm_ltc = { + .dtor = nvkm_ltc_dtor, + .oneinit = nvkm_ltc_oneinit, + .init = nvkm_ltc_init, + .intr = nvkm_ltc_intr, +}; + int -nvkm_ltc_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nvkm_ltc_new_(const struct nvkm_ltc_func *func, struct nvkm_device *device, + int index, struct nvkm_ltc **pltc) { - const struct nvkm_ltc_impl *impl = (void *)oclass; - struct nvkm_ltc_priv *priv; - int ret; + struct nvkm_ltc *ltc; - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PLTCG", - "l2c", length, pobject); - priv = *pobject; - if (ret) - return ret; - - memset(priv->zbc_color, 0x00, sizeof(priv->zbc_color)); - memset(priv->zbc_depth, 0x00, sizeof(priv->zbc_depth)); - - priv->base.base.intr = impl->intr; - priv->base.tags_alloc = nvkm_ltc_tags_alloc; - priv->base.tags_free = nvkm_ltc_tags_free; - priv->base.tags_clear = nvkm_ltc_tags_clear; - priv->base.zbc_min = 1; /* reserve 0 for disabled */ - priv->base.zbc_max = min(impl->zbc, NVKM_LTC_MAX_ZBC_CNT) - 1; - priv->base.zbc_color_get = nvkm_ltc_zbc_color_get; - priv->base.zbc_depth_get = nvkm_ltc_zbc_depth_get; + if (!(ltc = *pltc = kzalloc(sizeof(*ltc), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_ltc, device, index, 0, <c->subdev); + ltc->func = func; + ltc->zbc_min = 1; /* reserve 0 for disabled */ + ltc->zbc_max = min(func->zbc, NVKM_LTC_MAX_ZBC_CNT) - 1; return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c index 7fb5ea031..fb0de83da 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c @@ -28,38 +28,47 @@ #include void -gf100_ltc_cbc_clear(struct nvkm_ltc_priv *priv, u32 start, u32 limit) +gf100_ltc_cbc_clear(struct nvkm_ltc *ltc, u32 start, u32 limit) { - nv_wr32(priv, 0x17e8cc, start); - nv_wr32(priv, 0x17e8d0, limit); - nv_wr32(priv, 0x17e8c8, 0x00000004); + struct nvkm_device *device = ltc->subdev.device; + nvkm_wr32(device, 0x17e8cc, start); + nvkm_wr32(device, 0x17e8d0, limit); + nvkm_wr32(device, 0x17e8c8, 0x00000004); } void -gf100_ltc_cbc_wait(struct nvkm_ltc_priv *priv) +gf100_ltc_cbc_wait(struct nvkm_ltc *ltc) { + struct nvkm_device *device = ltc->subdev.device; int c, s; - for (c = 0; c < priv->ltc_nr; c++) { - for (s = 0; s < priv->lts_nr; s++) - nv_wait(priv, 0x1410c8 + c * 0x2000 + s * 0x400, ~0, 0); + for (c = 0; c < ltc->ltc_nr; c++) { + for (s = 0; s < ltc->lts_nr; s++) { + const u32 addr = 0x1410c8 + (c * 0x2000) + (s * 0x400); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, addr)) + break; + ); + } } } void -gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4]) +gf100_ltc_zbc_clear_color(struct nvkm_ltc *ltc, int i, const u32 color[4]) { - nv_mask(priv, 0x17ea44, 0x0000000f, i); - nv_wr32(priv, 0x17ea48, color[0]); - nv_wr32(priv, 0x17ea4c, color[1]); - nv_wr32(priv, 0x17ea50, color[2]); - nv_wr32(priv, 0x17ea54, color[3]); + struct nvkm_device *device = ltc->subdev.device; + nvkm_mask(device, 0x17ea44, 0x0000000f, i); + nvkm_wr32(device, 0x17ea48, color[0]); + nvkm_wr32(device, 0x17ea4c, color[1]); + nvkm_wr32(device, 0x17ea50, color[2]); + nvkm_wr32(device, 0x17ea54, color[3]); } void -gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth) +gf100_ltc_zbc_clear_depth(struct nvkm_ltc *ltc, int i, const u32 depth) { - nv_mask(priv, 0x17ea44, 0x0000000f, i); - nv_wr32(priv, 0x17ea58, depth); + struct nvkm_device *device = ltc->subdev.device; + nvkm_mask(device, 0x17ea44, 0x0000000f, i); + nvkm_wr32(device, 0x17ea58, depth); } static const struct nvkm_bitfield @@ -81,88 +90,90 @@ gf100_ltc_lts_intr_name[] = { }; static void -gf100_ltc_lts_intr(struct nvkm_ltc_priv *priv, int ltc, int lts) +gf100_ltc_lts_intr(struct nvkm_ltc *ltc, int c, int s) { - u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400); - u32 intr = nv_rd32(priv, base + 0x020); + struct nvkm_subdev *subdev = <c->subdev; + struct nvkm_device *device = subdev->device; + u32 base = 0x141000 + (c * 0x2000) + (s * 0x400); + u32 intr = nvkm_rd32(device, base + 0x020); u32 stat = intr & 0x0000ffff; + char msg[128]; if (stat) { - nv_info(priv, "LTC%d_LTS%d:", ltc, lts); - nvkm_bitfield_print(gf100_ltc_lts_intr_name, stat); - pr_cont("\n"); + nvkm_snprintbf(msg, sizeof(msg), gf100_ltc_lts_intr_name, stat); + nvkm_error(subdev, "LTC%d_LTS%d: %08x [%s]\n", c, s, stat, msg); } - nv_wr32(priv, base + 0x020, intr); + nvkm_wr32(device, base + 0x020, intr); } void -gf100_ltc_intr(struct nvkm_subdev *subdev) +gf100_ltc_intr(struct nvkm_ltc *ltc) { - struct nvkm_ltc_priv *priv = (void *)subdev; + struct nvkm_device *device = ltc->subdev.device; u32 mask; - mask = nv_rd32(priv, 0x00017c); + mask = nvkm_rd32(device, 0x00017c); while (mask) { - u32 lts, ltc = __ffs(mask); - for (lts = 0; lts < priv->lts_nr; lts++) - gf100_ltc_lts_intr(priv, ltc, lts); - mask &= ~(1 << ltc); + u32 s, c = __ffs(mask); + for (s = 0; s < ltc->lts_nr; s++) + gf100_ltc_lts_intr(ltc, c, s); + mask &= ~(1 << c); } } -static int -gf100_ltc_init(struct nvkm_object *object) +void +gf100_ltc_invalidate(struct nvkm_ltc *ltc) { - struct nvkm_ltc_priv *priv = (void *)object; - u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001); - int ret; + struct nvkm_device *device = ltc->subdev.device; + s64 taken; - ret = nvkm_ltc_init(priv); - if (ret) - return ret; + nvkm_wr32(device, 0x70004, 0x00000001); + taken = nvkm_wait_msec(device, 2, 0x70004, 0x00000003, 0x00000000); + if (taken < 0) + nvkm_warn(<c->subdev, "LTC invalidate timeout\n"); - nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ - nv_wr32(priv, 0x17e8d8, priv->ltc_nr); - nv_wr32(priv, 0x17e8d4, priv->tag_base); - nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); - return 0; + if (taken > 0) + nvkm_debug(<c->subdev, "LTC invalidate took %lld ns\n", taken); } void -gf100_ltc_dtor(struct nvkm_object *object) +gf100_ltc_flush(struct nvkm_ltc *ltc) { - struct nvkm_fb *pfb = nvkm_fb(object); - struct nvkm_ltc_priv *priv = (void *)object; + struct nvkm_device *device = ltc->subdev.device; + s64 taken; - nvkm_mm_fini(&priv->tags); - if (pfb->ram) - nvkm_mm_free(&pfb->vram, &priv->tag_ram); + nvkm_wr32(device, 0x70010, 0x00000001); + taken = nvkm_wait_msec(device, 2, 0x70010, 0x00000003, 0x00000000); + if (taken < 0) + nvkm_warn(<c->subdev, "LTC flush timeout\n"); - nvkm_ltc_destroy(priv); + if (taken > 0) + nvkm_debug(<c->subdev, "LTC flush took %lld ns\n", taken); } /* TODO: Figure out tag memory details and drop the over-cautious allocation. */ int -gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv) +gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) { + struct nvkm_ram *ram = ltc->subdev.device->fb->ram; u32 tag_size, tag_margin, tag_align; int ret; /* No VRAM, no tags for now. */ - if (!pfb->ram) { - priv->num_tags = 0; + if (!ram) { + ltc->num_tags = 0; goto mm_init; } /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ - priv->num_tags = (pfb->ram->size >> 17) / 4; - if (priv->num_tags > (1 << 17)) - priv->num_tags = 1 << 17; /* we have 17 bits in PTE */ - priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */ + ltc->num_tags = (ram->size >> 17) / 4; + if (ltc->num_tags > (1 << 17)) + ltc->num_tags = 1 << 17; /* we have 17 bits in PTE */ + ltc->num_tags = (ltc->num_tags + 63) & ~63; /* round up to 64 */ - tag_align = priv->ltc_nr * 0x800; + tag_align = ltc->ltc_nr * 0x800; tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align; /* 4 part 4 sub: 0x2000 bytes for 56 tags */ @@ -173,72 +184,73 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv) * * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %. */ - tag_size = (priv->num_tags / 64) * 0x6000 + tag_margin; + tag_size = (ltc->num_tags / 64) * 0x6000 + tag_margin; tag_size += tag_align; tag_size = (tag_size + 0xfff) >> 12; /* round up */ - ret = nvkm_mm_tail(&pfb->vram, 1, 1, tag_size, tag_size, 1, - &priv->tag_ram); + ret = nvkm_mm_tail(&ram->vram, 1, 1, tag_size, tag_size, 1, + <c->tag_ram); if (ret) { - priv->num_tags = 0; + ltc->num_tags = 0; } else { - u64 tag_base = ((u64)priv->tag_ram->offset << 12) + tag_margin; + u64 tag_base = ((u64)ltc->tag_ram->offset << 12) + tag_margin; tag_base += tag_align - 1; - ret = do_div(tag_base, tag_align); + do_div(tag_base, tag_align); - priv->tag_base = tag_base; + ltc->tag_base = tag_base; } mm_init: - ret = nvkm_mm_init(&priv->tags, 0, priv->num_tags, 1); - return ret; + return nvkm_mm_init(<c->tags, 0, ltc->num_tags, 1); } int -gf100_ltc_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +gf100_ltc_oneinit(struct nvkm_ltc *ltc) { - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ltc_priv *priv; - u32 parts, mask; - int ret, i; - - ret = nvkm_ltc_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - parts = nv_rd32(priv, 0x022438); - mask = nv_rd32(priv, 0x022554); + struct nvkm_device *device = ltc->subdev.device; + const u32 parts = nvkm_rd32(device, 0x022438); + const u32 mask = nvkm_rd32(device, 0x022554); + const u32 slice = nvkm_rd32(device, 0x17e8dc) >> 28; + int i; + for (i = 0; i < parts; i++) { if (!(mask & (1 << i))) - priv->ltc_nr++; + ltc->ltc_nr++; } - priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28; + ltc->lts_nr = slice; - ret = gf100_ltc_init_tag_ram(pfb, priv); - if (ret) - return ret; + return gf100_ltc_oneinit_tag_ram(ltc); +} + +static void +gf100_ltc_init(struct nvkm_ltc *ltc) +{ + struct nvkm_device *device = ltc->subdev.device; + u32 lpg128 = !(nvkm_rd32(device, 0x100c80) & 0x00000001); - nv_subdev(priv)->intr = gf100_ltc_intr; - return 0; + nvkm_mask(device, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ + nvkm_wr32(device, 0x17e8d8, ltc->ltc_nr); + nvkm_wr32(device, 0x17e8d4, ltc->tag_base); + nvkm_mask(device, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); } -struct nvkm_oclass * -gf100_ltc_oclass = &(struct nvkm_ltc_impl) { - .base.handle = NV_SUBDEV(LTC, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_ltc_ctor, - .dtor = gf100_ltc_dtor, - .init = gf100_ltc_init, - .fini = _nvkm_ltc_fini, - }, +static const struct nvkm_ltc_func +gf100_ltc = { + .oneinit = gf100_ltc_oneinit, + .init = gf100_ltc_init, .intr = gf100_ltc_intr, .cbc_clear = gf100_ltc_cbc_clear, .cbc_wait = gf100_ltc_cbc_wait, .zbc = 16, .zbc_clear_color = gf100_ltc_zbc_clear_color, .zbc_clear_depth = gf100_ltc_zbc_clear_depth, -}.base; + .invalidate = gf100_ltc_invalidate, + .flush = gf100_ltc_flush, +}; + +int +gf100_ltc_new(struct nvkm_device *device, int index, struct nvkm_ltc **pltc) +{ + return nvkm_ltc_new_(&gf100_ltc, device, index, pltc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c index d53959b5e..b4f6e0034 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c @@ -23,37 +23,34 @@ */ #include "priv.h" -static int -gk104_ltc_init(struct nvkm_object *object) +static void +gk104_ltc_init(struct nvkm_ltc *ltc) { - struct nvkm_ltc_priv *priv = (void *)object; - u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001); - int ret; + struct nvkm_device *device = ltc->subdev.device; + u32 lpg128 = !(nvkm_rd32(device, 0x100c80) & 0x00000001); - ret = nvkm_ltc_init(priv); - if (ret) - return ret; - - nv_wr32(priv, 0x17e8d8, priv->ltc_nr); - nv_wr32(priv, 0x17e000, priv->ltc_nr); - nv_wr32(priv, 0x17e8d4, priv->tag_base); - nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); - return 0; + nvkm_wr32(device, 0x17e8d8, ltc->ltc_nr); + nvkm_wr32(device, 0x17e000, ltc->ltc_nr); + nvkm_wr32(device, 0x17e8d4, ltc->tag_base); + nvkm_mask(device, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); } -struct nvkm_oclass * -gk104_ltc_oclass = &(struct nvkm_ltc_impl) { - .base.handle = NV_SUBDEV(LTC, 0xe4), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_ltc_ctor, - .dtor = gf100_ltc_dtor, - .init = gk104_ltc_init, - .fini = _nvkm_ltc_fini, - }, +static const struct nvkm_ltc_func +gk104_ltc = { + .oneinit = gf100_ltc_oneinit, + .init = gk104_ltc_init, .intr = gf100_ltc_intr, .cbc_clear = gf100_ltc_cbc_clear, .cbc_wait = gf100_ltc_cbc_wait, .zbc = 16, .zbc_clear_color = gf100_ltc_zbc_clear_color, .zbc_clear_depth = gf100_ltc_zbc_clear_depth, -}.base; + .invalidate = gf100_ltc_invalidate, + .flush = gf100_ltc_flush, +}; + +int +gk104_ltc_new(struct nvkm_device *device, int index, struct nvkm_ltc **pltc) +{ + return nvkm_ltc_new_(&gk104_ltc, device, index, pltc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c index 6b3f6f4ce..3043bbfd7 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c @@ -27,127 +27,123 @@ #include static void -gm107_ltc_cbc_clear(struct nvkm_ltc_priv *priv, u32 start, u32 limit) +gm107_ltc_cbc_clear(struct nvkm_ltc *ltc, u32 start, u32 limit) { - nv_wr32(priv, 0x17e270, start); - nv_wr32(priv, 0x17e274, limit); - nv_wr32(priv, 0x17e26c, 0x00000004); + struct nvkm_device *device = ltc->subdev.device; + nvkm_wr32(device, 0x17e270, start); + nvkm_wr32(device, 0x17e274, limit); + nvkm_wr32(device, 0x17e26c, 0x00000004); } static void -gm107_ltc_cbc_wait(struct nvkm_ltc_priv *priv) +gm107_ltc_cbc_wait(struct nvkm_ltc *ltc) { + struct nvkm_device *device = ltc->subdev.device; int c, s; - for (c = 0; c < priv->ltc_nr; c++) { - for (s = 0; s < priv->lts_nr; s++) - nv_wait(priv, 0x14046c + c * 0x2000 + s * 0x200, ~0, 0); + for (c = 0; c < ltc->ltc_nr; c++) { + for (s = 0; s < ltc->lts_nr; s++) { + const u32 addr = 0x14046c + (c * 0x2000) + (s * 0x200); + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, addr)) + break; + ); + } } } static void -gm107_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4]) +gm107_ltc_zbc_clear_color(struct nvkm_ltc *ltc, int i, const u32 color[4]) { - nv_mask(priv, 0x17e338, 0x0000000f, i); - nv_wr32(priv, 0x17e33c, color[0]); - nv_wr32(priv, 0x17e340, color[1]); - nv_wr32(priv, 0x17e344, color[2]); - nv_wr32(priv, 0x17e348, color[3]); + struct nvkm_device *device = ltc->subdev.device; + nvkm_mask(device, 0x17e338, 0x0000000f, i); + nvkm_wr32(device, 0x17e33c, color[0]); + nvkm_wr32(device, 0x17e340, color[1]); + nvkm_wr32(device, 0x17e344, color[2]); + nvkm_wr32(device, 0x17e348, color[3]); } static void -gm107_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth) +gm107_ltc_zbc_clear_depth(struct nvkm_ltc *ltc, int i, const u32 depth) { - nv_mask(priv, 0x17e338, 0x0000000f, i); - nv_wr32(priv, 0x17e34c, depth); + struct nvkm_device *device = ltc->subdev.device; + nvkm_mask(device, 0x17e338, 0x0000000f, i); + nvkm_wr32(device, 0x17e34c, depth); } static void -gm107_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts) +gm107_ltc_lts_isr(struct nvkm_ltc *ltc, int c, int s) { - u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400); - u32 stat = nv_rd32(priv, base + 0x00c); + struct nvkm_subdev *subdev = <c->subdev; + struct nvkm_device *device = subdev->device; + u32 base = 0x140000 + (c * 0x2000) + (s * 0x400); + u32 stat = nvkm_rd32(device, base + 0x00c); if (stat) { - nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat); - nv_wr32(priv, base + 0x00c, stat); + nvkm_error(subdev, "LTC%d_LTS%d: %08x\n", c, s, stat); + nvkm_wr32(device, base + 0x00c, stat); } } static void -gm107_ltc_intr(struct nvkm_subdev *subdev) +gm107_ltc_intr(struct nvkm_ltc *ltc) { - struct nvkm_ltc_priv *priv = (void *)subdev; + struct nvkm_device *device = ltc->subdev.device; u32 mask; - mask = nv_rd32(priv, 0x00017c); + mask = nvkm_rd32(device, 0x00017c); while (mask) { - u32 lts, ltc = __ffs(mask); - for (lts = 0; lts < priv->lts_nr; lts++) - gm107_ltc_lts_isr(priv, ltc, lts); - mask &= ~(1 << ltc); + u32 s, c = __ffs(mask); + for (s = 0; s < ltc->lts_nr; s++) + gm107_ltc_lts_isr(ltc, c, s); + mask &= ~(1 << c); } } static int -gm107_ltc_init(struct nvkm_object *object) +gm107_ltc_oneinit(struct nvkm_ltc *ltc) { - struct nvkm_ltc_priv *priv = (void *)object; - u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001); - int ret; - - ret = nvkm_ltc_init(priv); - if (ret) - return ret; - - nv_wr32(priv, 0x17e27c, priv->ltc_nr); - nv_wr32(priv, 0x17e278, priv->tag_base); - nv_mask(priv, 0x17e264, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); - return 0; -} + struct nvkm_device *device = ltc->subdev.device; + const u32 parts = nvkm_rd32(device, 0x022438); + const u32 mask = nvkm_rd32(device, 0x021c14); + const u32 slice = nvkm_rd32(device, 0x17e280) >> 28; + int i; -static int -gm107_ltc_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_fb *pfb = nvkm_fb(parent); - struct nvkm_ltc_priv *priv; - u32 parts, mask; - int ret, i; - - ret = nvkm_ltc_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - parts = nv_rd32(priv, 0x022438); - mask = nv_rd32(priv, 0x021c14); for (i = 0; i < parts; i++) { if (!(mask & (1 << i))) - priv->ltc_nr++; + ltc->ltc_nr++; } - priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28; + ltc->lts_nr = slice; + + return gf100_ltc_oneinit_tag_ram(ltc); +} - ret = gf100_ltc_init_tag_ram(pfb, priv); - if (ret) - return ret; +static void +gm107_ltc_init(struct nvkm_ltc *ltc) +{ + struct nvkm_device *device = ltc->subdev.device; + u32 lpg128 = !(nvkm_rd32(device, 0x100c80) & 0x00000001); - return 0; + nvkm_wr32(device, 0x17e27c, ltc->ltc_nr); + nvkm_wr32(device, 0x17e278, ltc->tag_base); + nvkm_mask(device, 0x17e264, 0x00000002, lpg128 ? 0x00000002 : 0x00000000); } -struct nvkm_oclass * -gm107_ltc_oclass = &(struct nvkm_ltc_impl) { - .base.handle = NV_SUBDEV(LTC, 0xff), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm107_ltc_ctor, - .dtor = gf100_ltc_dtor, - .init = gm107_ltc_init, - .fini = _nvkm_ltc_fini, - }, +static const struct nvkm_ltc_func +gm107_ltc = { + .oneinit = gm107_ltc_oneinit, + .init = gm107_ltc_init, .intr = gm107_ltc_intr, .cbc_clear = gm107_ltc_cbc_clear, .cbc_wait = gm107_ltc_cbc_wait, .zbc = 16, .zbc_clear_color = gm107_ltc_zbc_clear_color, .zbc_clear_depth = gm107_ltc_zbc_clear_depth, -}.base; + .invalidate = gf100_ltc_invalidate, + .flush = gf100_ltc_flush, +}; + +int +gm107_ltc_new(struct nvkm_device *device, int index, struct nvkm_ltc **pltc) +{ + return nvkm_ltc_new_(&gm107_ltc, device, index, pltc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h index 09537d7b6..4e3755b82 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h @@ -1,69 +1,34 @@ #ifndef __NVKM_LTC_PRIV_H__ #define __NVKM_LTC_PRIV_H__ +#define nvkm_ltc(p) container_of((p), struct nvkm_ltc, subdev) #include -#include -struct nvkm_fb; +int nvkm_ltc_new_(const struct nvkm_ltc_func *, struct nvkm_device *, + int index, struct nvkm_ltc **); -struct nvkm_ltc_priv { - struct nvkm_ltc base; - u32 ltc_nr; - u32 lts_nr; +struct nvkm_ltc_func { + int (*oneinit)(struct nvkm_ltc *); + void (*init)(struct nvkm_ltc *); + void (*intr)(struct nvkm_ltc *); - u32 num_tags; - u32 tag_base; - struct nvkm_mm tags; - struct nvkm_mm_node *tag_ram; - - u32 zbc_color[NVKM_LTC_MAX_ZBC_CNT][4]; - u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; -}; - -#define nvkm_ltc_create(p,e,o,d) \ - nvkm_ltc_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_ltc_destroy(p) ({ \ - struct nvkm_ltc_priv *_priv = (p); \ - _nvkm_ltc_dtor(nv_object(_priv)); \ -}) -#define nvkm_ltc_init(p) ({ \ - struct nvkm_ltc_priv *_priv = (p); \ - _nvkm_ltc_init(nv_object(_priv)); \ -}) -#define nvkm_ltc_fini(p,s) ({ \ - struct nvkm_ltc_priv *_priv = (p); \ - _nvkm_ltc_fini(nv_object(_priv), (s)); \ -}) - -int nvkm_ltc_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); - -#define _nvkm_ltc_dtor _nvkm_subdev_dtor -int _nvkm_ltc_init(struct nvkm_object *); -#define _nvkm_ltc_fini _nvkm_subdev_fini - -int gf100_ltc_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void gf100_ltc_dtor(struct nvkm_object *); -int gf100_ltc_init_tag_ram(struct nvkm_fb *, struct nvkm_ltc_priv *); -int gf100_ltc_tags_alloc(struct nvkm_ltc *, u32, struct nvkm_mm_node **); -void gf100_ltc_tags_free(struct nvkm_ltc *, struct nvkm_mm_node **); - -struct nvkm_ltc_impl { - struct nvkm_oclass base; - void (*intr)(struct nvkm_subdev *); - - void (*cbc_clear)(struct nvkm_ltc_priv *, u32 start, u32 limit); - void (*cbc_wait)(struct nvkm_ltc_priv *); + void (*cbc_clear)(struct nvkm_ltc *, u32 start, u32 limit); + void (*cbc_wait)(struct nvkm_ltc *); int zbc; - void (*zbc_clear_color)(struct nvkm_ltc_priv *, int, const u32[4]); - void (*zbc_clear_depth)(struct nvkm_ltc_priv *, int, const u32); + void (*zbc_clear_color)(struct nvkm_ltc *, int, const u32[4]); + void (*zbc_clear_depth)(struct nvkm_ltc *, int, const u32); + + void (*invalidate)(struct nvkm_ltc *); + void (*flush)(struct nvkm_ltc *); }; -void gf100_ltc_intr(struct nvkm_subdev *); -void gf100_ltc_cbc_clear(struct nvkm_ltc_priv *, u32, u32); -void gf100_ltc_cbc_wait(struct nvkm_ltc_priv *); -void gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *, int, const u32[4]); -void gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *, int, const u32); +int gf100_ltc_oneinit(struct nvkm_ltc *); +int gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *); +void gf100_ltc_intr(struct nvkm_ltc *); +void gf100_ltc_cbc_clear(struct nvkm_ltc *, u32, u32); +void gf100_ltc_cbc_wait(struct nvkm_ltc *); +void gf100_ltc_zbc_clear_color(struct nvkm_ltc *, int, const u32[4]); +void gf100_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32); +void gf100_ltc_invalidate(struct nvkm_ltc *); +void gf100_ltc_flush(struct nvkm_ltc *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild index 721643f04..bef325dcb 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild @@ -1,11 +1,7 @@ nvkm-y += nvkm/subdev/mc/base.o nvkm-y += nvkm/subdev/mc/nv04.o -nvkm-y += nvkm/subdev/mc/nv40.o nvkm-y += nvkm/subdev/mc/nv44.o -nvkm-y += nvkm/subdev/mc/nv4c.o nvkm-y += nvkm/subdev/mc/nv50.o -nvkm-y += nvkm/subdev/mc/g94.o nvkm-y += nvkm/subdev/mc/g98.o nvkm-y += nvkm/subdev/mc/gf100.o -nvkm-y += nvkm/subdev/mc/gf106.o nvkm-y += nvkm/subdev/mc/gk20a.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c index 5b051a266..954fbbe56 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c @@ -23,147 +23,101 @@ */ #include "priv.h" -#include #include -static inline void -nvkm_mc_unk260(struct nvkm_mc *pmc, u32 data) +void +nvkm_mc_unk260(struct nvkm_mc *mc, u32 data) { - const struct nvkm_mc_oclass *impl = (void *)nv_oclass(pmc); - if (impl->unk260) - impl->unk260(pmc, data); + if (mc->func->unk260) + mc->func->unk260(mc, data); } -static inline u32 -nvkm_mc_intr_mask(struct nvkm_mc *pmc) +void +nvkm_mc_intr_unarm(struct nvkm_mc *mc) { - u32 intr = nv_rd32(pmc, 0x000100); - if (intr == 0xffffffff) /* likely fallen off the bus */ - intr = 0x00000000; - return intr; + return mc->func->intr_unarm(mc); } -static irqreturn_t -nvkm_mc_intr(int irq, void *arg) +void +nvkm_mc_intr_rearm(struct nvkm_mc *mc) { - struct nvkm_mc *pmc = arg; - const struct nvkm_mc_oclass *oclass = (void *)nv_object(pmc)->oclass; - const struct nvkm_mc_intr *map = oclass->intr; - struct nvkm_subdev *unit; - u32 intr; + return mc->func->intr_rearm(mc); +} - nv_wr32(pmc, 0x000140, 0x00000000); - nv_rd32(pmc, 0x000140); - intr = nvkm_mc_intr_mask(pmc); - if (pmc->use_msi) - oclass->msi_rearm(pmc); +static u32 +nvkm_mc_intr_mask(struct nvkm_mc *mc) +{ + u32 intr = mc->func->intr_mask(mc); + if (WARN_ON_ONCE(intr == 0xffffffff)) + intr = 0; /* likely fallen off the bus */ + return intr; +} - if (intr) { - u32 stat = intr = nvkm_mc_intr_mask(pmc); - while (map->stat) { - if (intr & map->stat) { - unit = nvkm_subdev(pmc, map->unit); - if (unit && unit->intr) - unit->intr(unit); - stat &= ~map->stat; - } - map++; +void +nvkm_mc_intr(struct nvkm_mc *mc, bool *handled) +{ + struct nvkm_device *device = mc->subdev.device; + struct nvkm_subdev *subdev; + const struct nvkm_mc_intr *map = mc->func->intr; + u32 stat, intr; + + stat = intr = nvkm_mc_intr_mask(mc); + while (map->stat) { + if (intr & map->stat) { + subdev = nvkm_device_subdev(device, map->unit); + if (subdev) + nvkm_subdev_intr(subdev); + stat &= ~map->stat; } - - if (stat) - nv_error(pmc, "unknown intr 0x%08x\n", stat); + map++; } - nv_wr32(pmc, 0x000140, 0x00000001); - return intr ? IRQ_HANDLED : IRQ_NONE; + if (stat) + nvkm_error(&mc->subdev, "intr %08x\n", stat); + *handled = intr != 0; } -int -_nvkm_mc_fini(struct nvkm_object *object, bool suspend) +static int +nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend) { - struct nvkm_mc *pmc = (void *)object; - nv_wr32(pmc, 0x000140, 0x00000000); - return nvkm_subdev_fini(&pmc->base, suspend); + struct nvkm_mc *mc = nvkm_mc(subdev); + nvkm_mc_intr_unarm(mc); + return 0; } -int -_nvkm_mc_init(struct nvkm_object *object) +static int +nvkm_mc_init(struct nvkm_subdev *subdev) { - struct nvkm_mc *pmc = (void *)object; - int ret = nvkm_subdev_init(&pmc->base); - if (ret) - return ret; - nv_wr32(pmc, 0x000140, 0x00000001); + struct nvkm_mc *mc = nvkm_mc(subdev); + if (mc->func->init) + mc->func->init(mc); + nvkm_mc_intr_rearm(mc); return 0; } -void -_nvkm_mc_dtor(struct nvkm_object *object) +static void * +nvkm_mc_dtor(struct nvkm_subdev *subdev) { - struct nvkm_device *device = nv_device(object); - struct nvkm_mc *pmc = (void *)object; - free_irq(pmc->irq, pmc); - if (pmc->use_msi) - pci_disable_msi(device->pdev); - nvkm_subdev_destroy(&pmc->base); + return nvkm_mc(subdev); } +static const struct nvkm_subdev_func +nvkm_mc = { + .dtor = nvkm_mc_dtor, + .init = nvkm_mc_init, + .fini = nvkm_mc_fini, +}; + int -nvkm_mc_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *bclass, int length, void **pobject) +nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device, + int index, struct nvkm_mc **pmc) { - const struct nvkm_mc_oclass *oclass = (void *)bclass; - struct nvkm_device *device = nv_device(parent); - struct nvkm_mc *pmc; - int ret; - - ret = nvkm_subdev_create_(parent, engine, bclass, 0, "PMC", - "master", length, pobject); - pmc = *pobject; - if (ret) - return ret; - - pmc->unk260 = nvkm_mc_unk260; - - if (nv_device_is_pci(device)) { - switch (device->pdev->device & 0x0ff0) { - case 0x00f0: - case 0x02e0: - /* BR02? NFI how these would be handled yet exactly */ - break; - default: - switch (device->chipset) { - case 0xaa: - /* reported broken, nv also disable it */ - break; - default: - pmc->use_msi = true; - break; - } - } - - pmc->use_msi = nvkm_boolopt(device->cfgopt, "NvMSI", - pmc->use_msi); - - if (pmc->use_msi && oclass->msi_rearm) { - pmc->use_msi = pci_enable_msi(device->pdev) == 0; - if (pmc->use_msi) { - nv_info(pmc, "MSI interrupts enabled\n"); - oclass->msi_rearm(pmc); - } - } else { - pmc->use_msi = false; - } - } - - ret = nv_device_get_irq(device, true); - if (ret < 0) - return ret; - pmc->irq = ret; + struct nvkm_mc *mc; - ret = request_irq(pmc->irq, nvkm_mc_intr, IRQF_SHARED, "nvkm", pmc); - if (ret < 0) - return ret; + if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev); + mc->func = func; return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c deleted file mode 100644 index f042e7d83..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.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 "nv04.h" - -struct nvkm_oclass * -g94_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x94), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv50_mc_init, - .fini = _nvkm_mc_fini, - }, - .intr = nv50_mc_intr, - .msi_rearm = nv40_mc_msi_rearm, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c index 8ab7f1272..7344ad659 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c @@ -21,38 +21,40 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" static const struct nvkm_mc_intr g98_mc_intr[] = { - { 0x04000000, NVDEV_ENGINE_DISP }, /* DISP first, so pageflip timestamps work */ - { 0x00000001, NVDEV_ENGINE_MSPPP }, - { 0x00000100, NVDEV_ENGINE_FIFO }, - { 0x00001000, NVDEV_ENGINE_GR }, - { 0x00004000, NVDEV_ENGINE_SEC }, /* NV84:NVA3 */ - { 0x00008000, NVDEV_ENGINE_MSVLD }, - { 0x00020000, NVDEV_ENGINE_MSPDEC }, - { 0x00040000, NVDEV_SUBDEV_PMU }, /* NVA3:NVC0 */ - { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ - { 0x00100000, NVDEV_SUBDEV_TIMER }, - { 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */ - { 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */ - { 0x00400000, NVDEV_ENGINE_CE0 }, /* NVA3- */ - { 0x10000000, NVDEV_SUBDEV_BUS }, - { 0x80000000, NVDEV_ENGINE_SW }, - { 0x0042d101, NVDEV_SUBDEV_FB }, + { 0x04000000, NVKM_ENGINE_DISP }, /* DISP first, so pageflip timestamps work */ + { 0x00000001, NVKM_ENGINE_MSPPP }, + { 0x00000100, NVKM_ENGINE_FIFO }, + { 0x00001000, NVKM_ENGINE_GR }, + { 0x00004000, NVKM_ENGINE_SEC }, /* NV84:NVA3 */ + { 0x00008000, NVKM_ENGINE_MSVLD }, + { 0x00020000, NVKM_ENGINE_MSPDEC }, + { 0x00040000, NVKM_SUBDEV_PMU }, /* NVA3:NVC0 */ + { 0x00080000, NVKM_SUBDEV_THERM }, /* NVA3:NVC0 */ + { 0x00100000, NVKM_SUBDEV_TIMER }, + { 0x00200000, NVKM_SUBDEV_GPIO }, /* PMGR->GPIO */ + { 0x00200000, NVKM_SUBDEV_I2C }, /* PMGR->I2C/AUX */ + { 0x00400000, NVKM_ENGINE_CE0 }, /* NVA3- */ + { 0x10000000, NVKM_SUBDEV_BUS }, + { 0x80000000, NVKM_ENGINE_SW }, + { 0x0042d101, NVKM_SUBDEV_FB }, {}, }; -struct nvkm_oclass * -g98_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x98), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv50_mc_init, - .fini = _nvkm_mc_fini, - }, +static const struct nvkm_mc_func +g98_mc = { + .init = nv50_mc_init, .intr = g98_mc_intr, - .msi_rearm = nv40_mc_msi_rearm, -}.base; + .intr_unarm = nv04_mc_intr_unarm, + .intr_rearm = nv04_mc_intr_rearm, + .intr_mask = nv04_mc_intr_mask, +}; + +int +g98_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) +{ + return nvkm_mc_new_(&g98_mc, device, index, pmc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c index 2425984b0..122fe69e8 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c @@ -21,56 +21,77 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" const struct nvkm_mc_intr gf100_mc_intr[] = { - { 0x04000000, NVDEV_ENGINE_DISP }, /* DISP first, so pageflip timestamps work. */ - { 0x00000001, NVDEV_ENGINE_MSPPP }, - { 0x00000020, NVDEV_ENGINE_CE0 }, - { 0x00000040, NVDEV_ENGINE_CE1 }, - { 0x00000080, NVDEV_ENGINE_CE2 }, - { 0x00000100, NVDEV_ENGINE_FIFO }, - { 0x00001000, NVDEV_ENGINE_GR }, - { 0x00002000, NVDEV_SUBDEV_FB }, - { 0x00008000, NVDEV_ENGINE_MSVLD }, - { 0x00040000, NVDEV_SUBDEV_THERM }, - { 0x00020000, NVDEV_ENGINE_MSPDEC }, - { 0x00100000, NVDEV_SUBDEV_TIMER }, - { 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */ - { 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */ - { 0x01000000, NVDEV_SUBDEV_PMU }, - { 0x02000000, NVDEV_SUBDEV_LTC }, - { 0x08000000, NVDEV_SUBDEV_FB }, - { 0x10000000, NVDEV_SUBDEV_BUS }, - { 0x40000000, NVDEV_SUBDEV_IBUS }, - { 0x80000000, NVDEV_ENGINE_SW }, + { 0x04000000, NVKM_ENGINE_DISP }, /* DISP first, so pageflip timestamps work. */ + { 0x00000001, NVKM_ENGINE_MSPPP }, + { 0x00000020, NVKM_ENGINE_CE0 }, + { 0x00000040, NVKM_ENGINE_CE1 }, + { 0x00000080, NVKM_ENGINE_CE2 }, + { 0x00000100, NVKM_ENGINE_FIFO }, + { 0x00001000, NVKM_ENGINE_GR }, + { 0x00002000, NVKM_SUBDEV_FB }, + { 0x00008000, NVKM_ENGINE_MSVLD }, + { 0x00040000, NVKM_SUBDEV_THERM }, + { 0x00020000, NVKM_ENGINE_MSPDEC }, + { 0x00100000, NVKM_SUBDEV_TIMER }, + { 0x00200000, NVKM_SUBDEV_GPIO }, /* PMGR->GPIO */ + { 0x00200000, NVKM_SUBDEV_I2C }, /* PMGR->I2C/AUX */ + { 0x01000000, NVKM_SUBDEV_PMU }, + { 0x02000000, NVKM_SUBDEV_LTC }, + { 0x08000000, NVKM_SUBDEV_FB }, + { 0x10000000, NVKM_SUBDEV_BUS }, + { 0x40000000, NVKM_SUBDEV_IBUS }, + { 0x80000000, NVKM_ENGINE_SW }, {}, }; -static void -gf100_mc_msi_rearm(struct nvkm_mc *pmc) +void +gf100_mc_intr_unarm(struct nvkm_mc *mc) +{ + struct nvkm_device *device = mc->subdev.device; + nvkm_wr32(device, 0x000140, 0x00000000); + nvkm_wr32(device, 0x000144, 0x00000000); + nvkm_rd32(device, 0x000140); +} + +void +gf100_mc_intr_rearm(struct nvkm_mc *mc) +{ + struct nvkm_device *device = mc->subdev.device; + nvkm_wr32(device, 0x000140, 0x00000001); + nvkm_wr32(device, 0x000144, 0x00000001); +} + +u32 +gf100_mc_intr_mask(struct nvkm_mc *mc) { - struct nv04_mc_priv *priv = (void *)pmc; - nv_wr32(priv, 0x088704, 0x00000000); + struct nvkm_device *device = mc->subdev.device; + u32 intr0 = nvkm_rd32(device, 0x000100); + u32 intr1 = nvkm_rd32(device, 0x000104); + return intr0 | intr1; } void -gf100_mc_unk260(struct nvkm_mc *pmc, u32 data) +gf100_mc_unk260(struct nvkm_mc *mc, u32 data) { - nv_wr32(pmc, 0x000260, data); + nvkm_wr32(mc->subdev.device, 0x000260, data); } -struct nvkm_oclass * -gf100_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv50_mc_init, - .fini = _nvkm_mc_fini, - }, +static const struct nvkm_mc_func +gf100_mc = { + .init = nv50_mc_init, .intr = gf100_mc_intr, - .msi_rearm = gf100_mc_msi_rearm, + .intr_unarm = gf100_mc_intr_unarm, + .intr_rearm = gf100_mc_intr_rearm, + .intr_mask = gf100_mc_intr_mask, .unk260 = gf100_mc_unk260, -}.base; +}; + +int +gf100_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) +{ + return nvkm_mc_new_(&gf100_mc, device, index, pmc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c deleted file mode 100644 index 8d2a8f457..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c +++ /dev/null @@ -1,38 +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 "nv04.h" - -struct nvkm_oclass * -gf106_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0xc3), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv50_mc_init, - .fini = _nvkm_mc_fini, - }, - .intr = gf100_mc_intr, - .msi_rearm = nv40_mc_msi_rearm, - .unk260 = gf100_mc_unk260, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c index 43b277429..d92efb33b 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c @@ -21,17 +21,19 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" -struct nvkm_oclass * -gk20a_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv50_mc_init, - .fini = _nvkm_mc_fini, - }, +static const struct nvkm_mc_func +gk20a_mc = { + .init = nv50_mc_init, .intr = gf100_mc_intr, - .msi_rearm = nv40_mc_msi_rearm, -}.base; + .intr_unarm = gf100_mc_intr_unarm, + .intr_rearm = gf100_mc_intr_rearm, + .intr_mask = gf100_mc_intr_mask, +}; + +int +gk20a_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) +{ + return nvkm_mc_new_(&gk20a_mc, device, index, pmc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c index 32713827b..d282ec155 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c @@ -21,58 +21,63 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" const struct nvkm_mc_intr nv04_mc_intr[] = { - { 0x00000001, NVDEV_ENGINE_MPEG }, /* NV17- MPEG/ME */ - { 0x00000100, NVDEV_ENGINE_FIFO }, - { 0x00001000, NVDEV_ENGINE_GR }, - { 0x00010000, NVDEV_ENGINE_DISP }, - { 0x00020000, NVDEV_ENGINE_VP }, /* NV40- */ - { 0x00100000, NVDEV_SUBDEV_TIMER }, - { 0x01000000, NVDEV_ENGINE_DISP }, /* NV04- PCRTC0 */ - { 0x02000000, NVDEV_ENGINE_DISP }, /* NV11- PCRTC1 */ - { 0x10000000, NVDEV_SUBDEV_BUS }, - { 0x80000000, NVDEV_ENGINE_SW }, + { 0x00000001, NVKM_ENGINE_MPEG }, /* NV17- MPEG/ME */ + { 0x00000100, NVKM_ENGINE_FIFO }, + { 0x00001000, NVKM_ENGINE_GR }, + { 0x00010000, NVKM_ENGINE_DISP }, + { 0x00020000, NVKM_ENGINE_VP }, /* NV40- */ + { 0x00100000, NVKM_SUBDEV_TIMER }, + { 0x01000000, NVKM_ENGINE_DISP }, /* NV04- PCRTC0 */ + { 0x02000000, NVKM_ENGINE_DISP }, /* NV11- PCRTC1 */ + { 0x10000000, NVKM_SUBDEV_BUS }, + { 0x80000000, NVKM_ENGINE_SW }, {} }; -int -nv04_mc_init(struct nvkm_object *object) +void +nv04_mc_intr_unarm(struct nvkm_mc *mc) { - struct nv04_mc_priv *priv = (void *)object; - - nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ - nv_wr32(priv, 0x001850, 0x00000001); /* disable rom access */ - - return nvkm_mc_init(&priv->base); + struct nvkm_device *device = mc->subdev.device; + nvkm_wr32(device, 0x000140, 0x00000000); + nvkm_rd32(device, 0x000140); } -int -nv04_mc_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +void +nv04_mc_intr_rearm(struct nvkm_mc *mc) { - struct nv04_mc_priv *priv; - int ret; + struct nvkm_device *device = mc->subdev.device; + nvkm_wr32(device, 0x000140, 0x00000001); +} - ret = nvkm_mc_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +u32 +nv04_mc_intr_mask(struct nvkm_mc *mc) +{ + return nvkm_rd32(mc->subdev.device, 0x000100); +} - return 0; +void +nv04_mc_init(struct nvkm_mc *mc) +{ + struct nvkm_device *device = mc->subdev.device; + nvkm_wr32(device, 0x000200, 0xffffffff); /* everything enabled */ + nvkm_wr32(device, 0x001850, 0x00000001); /* disable rom access */ } -struct nvkm_oclass * -nv04_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x04), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv04_mc_init, - .fini = _nvkm_mc_fini, - }, +static const struct nvkm_mc_func +nv04_mc = { + .init = nv04_mc_init, .intr = nv04_mc_intr, -}.base; + .intr_unarm = nv04_mc_intr_unarm, + .intr_rearm = nv04_mc_intr_rearm, + .intr_mask = nv04_mc_intr_mask, +}; + +int +nv04_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) +{ + return nvkm_mc_new_(&nv04_mc, device, index, pmc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.h deleted file mode 100644 index 411de3d08..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __NVKM_MC_NV04_H__ -#define __NVKM_MC_NV04_H__ -#include "priv.h" - -struct nv04_mc_priv { - struct nvkm_mc base; -}; - -int nv04_mc_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); - -extern const struct nvkm_mc_intr nv04_mc_intr[]; -int nv04_mc_init(struct nvkm_object *); -void nv40_mc_msi_rearm(struct nvkm_mc *); -int nv44_mc_init(struct nvkm_object *object); -int nv50_mc_init(struct nvkm_object *); -extern const struct nvkm_mc_intr nv50_mc_intr[]; -extern const struct nvkm_mc_intr gf100_mc_intr[]; -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c deleted file mode 100644 index b7613059d..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c +++ /dev/null @@ -1,44 +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 "nv04.h" - -void -nv40_mc_msi_rearm(struct nvkm_mc *pmc) -{ - struct nv04_mc_priv *priv = (void *)pmc; - nv_wr08(priv, 0x088068, 0xff); -} - -struct nvkm_oclass * -nv40_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x40), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv04_mc_init, - .fini = _nvkm_mc_fini, - }, - .intr = nv04_mc_intr, - .msi_rearm = nv40_mc_msi_rearm, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c index 2c7f7c701..9a3ac9965 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c @@ -21,33 +21,33 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" -int -nv44_mc_init(struct nvkm_object *object) +void +nv44_mc_init(struct nvkm_mc *mc) { - struct nv04_mc_priv *priv = (void *)object; - u32 tmp = nv_rd32(priv, 0x10020c); - - nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ + struct nvkm_device *device = mc->subdev.device; + u32 tmp = nvkm_rd32(device, 0x10020c); - nv_wr32(priv, 0x001700, tmp); - nv_wr32(priv, 0x001704, 0); - nv_wr32(priv, 0x001708, 0); - nv_wr32(priv, 0x00170c, tmp); + nvkm_wr32(device, 0x000200, 0xffffffff); /* everything enabled */ - return nvkm_mc_init(&priv->base); + nvkm_wr32(device, 0x001700, tmp); + nvkm_wr32(device, 0x001704, 0); + nvkm_wr32(device, 0x001708, 0); + nvkm_wr32(device, 0x00170c, tmp); } -struct nvkm_oclass * -nv44_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x44), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv44_mc_init, - .fini = _nvkm_mc_fini, - }, +static const struct nvkm_mc_func +nv44_mc = { + .init = nv44_mc_init, .intr = nv04_mc_intr, - .msi_rearm = nv40_mc_msi_rearm, -}.base; + .intr_unarm = nv04_mc_intr_unarm, + .intr_rearm = nv04_mc_intr_rearm, + .intr_mask = nv04_mc_intr_mask, +}; + +int +nv44_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) +{ + return nvkm_mc_new_(&nv44_mc, device, index, pmc); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c deleted file mode 100644 index c0aac7e20..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 Ilia Mirkin - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ilia Mirkin - */ -#include "nv04.h" - -struct nvkm_oclass * -nv4c_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x4c), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv44_mc_init, - .fini = _nvkm_mc_fini, - }, - .intr = nv04_mc_intr, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c index 40e3019e1..5f27d7b8f 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c @@ -21,52 +21,44 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" - -#include +#include "priv.h" const struct nvkm_mc_intr nv50_mc_intr[] = { - { 0x04000000, NVDEV_ENGINE_DISP }, /* DISP before FIFO, so pageflip-timestamping works! */ - { 0x00000001, NVDEV_ENGINE_MPEG }, - { 0x00000100, NVDEV_ENGINE_FIFO }, - { 0x00001000, NVDEV_ENGINE_GR }, - { 0x00004000, NVDEV_ENGINE_CIPHER }, /* NV84- */ - { 0x00008000, NVDEV_ENGINE_BSP }, /* NV84- */ - { 0x00020000, NVDEV_ENGINE_VP }, /* NV84- */ - { 0x00100000, NVDEV_SUBDEV_TIMER }, - { 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */ - { 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */ - { 0x10000000, NVDEV_SUBDEV_BUS }, - { 0x80000000, NVDEV_ENGINE_SW }, - { 0x0002d101, NVDEV_SUBDEV_FB }, + { 0x04000000, NVKM_ENGINE_DISP }, /* DISP before FIFO, so pageflip-timestamping works! */ + { 0x00000001, NVKM_ENGINE_MPEG }, + { 0x00000100, NVKM_ENGINE_FIFO }, + { 0x00001000, NVKM_ENGINE_GR }, + { 0x00004000, NVKM_ENGINE_CIPHER }, /* NV84- */ + { 0x00008000, NVKM_ENGINE_BSP }, /* NV84- */ + { 0x00020000, NVKM_ENGINE_VP }, /* NV84- */ + { 0x00100000, NVKM_SUBDEV_TIMER }, + { 0x00200000, NVKM_SUBDEV_GPIO }, /* PMGR->GPIO */ + { 0x00200000, NVKM_SUBDEV_I2C }, /* PMGR->I2C/AUX */ + { 0x10000000, NVKM_SUBDEV_BUS }, + { 0x80000000, NVKM_ENGINE_SW }, + { 0x0002d101, NVKM_SUBDEV_FB }, {}, }; -static void -nv50_mc_msi_rearm(struct nvkm_mc *pmc) +void +nv50_mc_init(struct nvkm_mc *mc) { - struct nvkm_device *device = nv_device(pmc); - pci_write_config_byte(device->pdev, 0x68, 0xff); + struct nvkm_device *device = mc->subdev.device; + nvkm_wr32(device, 0x000200, 0xffffffff); /* everything on */ } +static const struct nvkm_mc_func +nv50_mc = { + .init = nv50_mc_init, + .intr = nv50_mc_intr, + .intr_unarm = nv04_mc_intr_unarm, + .intr_rearm = nv04_mc_intr_rearm, + .intr_mask = nv04_mc_intr_mask, +}; + int -nv50_mc_init(struct nvkm_object *object) +nv50_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) { - struct nv04_mc_priv *priv = (void *)object; - nv_wr32(priv, 0x000200, 0xffffffff); /* everything on */ - return nvkm_mc_init(&priv->base); + return nvkm_mc_new_(&nv50_mc, device, index, pmc); } - -struct nvkm_oclass * -nv50_mc_oclass = &(struct nvkm_mc_oclass) { - .base.handle = NV_SUBDEV(MC, 0x50), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mc_ctor, - .dtor = _nvkm_mc_dtor, - .init = nv50_mc_init, - .fini = _nvkm_mc_fini, - }, - .intr = nv50_mc_intr, - .msi_rearm = nv50_mc_msi_rearm, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h index d2cad07af..307f6c692 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h @@ -1,36 +1,42 @@ #ifndef __NVKM_MC_PRIV_H__ #define __NVKM_MC_PRIV_H__ +#define nvkm_mc(p) container_of((p), struct nvkm_mc, subdev) #include -#define nvkm_mc_create(p,e,o,d) \ - nvkm_mc_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_mc_destroy(p) ({ \ - struct nvkm_mc *pmc = (p); _nvkm_mc_dtor(nv_object(pmc)); \ -}) -#define nvkm_mc_init(p) ({ \ - struct nvkm_mc *pmc = (p); _nvkm_mc_init(nv_object(pmc)); \ -}) -#define nvkm_mc_fini(p,s) ({ \ - struct nvkm_mc *pmc = (p); _nvkm_mc_fini(nv_object(pmc), (s)); \ -}) - -int nvkm_mc_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); -void _nvkm_mc_dtor(struct nvkm_object *); -int _nvkm_mc_init(struct nvkm_object *); -int _nvkm_mc_fini(struct nvkm_object *, bool); +int nvkm_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *, + int index, struct nvkm_mc **); struct nvkm_mc_intr { u32 stat; u32 unit; }; -struct nvkm_mc_oclass { - struct nvkm_oclass base; +struct nvkm_mc_func { + void (*init)(struct nvkm_mc *); const struct nvkm_mc_intr *intr; - void (*msi_rearm)(struct nvkm_mc *); + /* disable reporting of interrupts to host */ + void (*intr_unarm)(struct nvkm_mc *); + /* enable reporting of interrupts to host */ + void (*intr_rearm)(struct nvkm_mc *); + /* retrieve pending interrupt mask (NV_PMC_INTR) */ + u32 (*intr_mask)(struct nvkm_mc *); void (*unk260)(struct nvkm_mc *, u32); }; +void nv04_mc_init(struct nvkm_mc *); +extern const struct nvkm_mc_intr nv04_mc_intr[]; +void nv04_mc_intr_unarm(struct nvkm_mc *); +void nv04_mc_intr_rearm(struct nvkm_mc *); +u32 nv04_mc_intr_mask(struct nvkm_mc *); + +void nv44_mc_init(struct nvkm_mc *); + +void nv50_mc_init(struct nvkm_mc *); +extern const struct nvkm_mc_intr nv50_mc_intr[]; + +extern const struct nvkm_mc_intr gf100_mc_intr[]; +void gf100_mc_intr_unarm(struct nvkm_mc *); +void gf100_mc_intr_rearm(struct nvkm_mc *); +u32 gf100_mc_intr_mask(struct nvkm_mc *); void gf100_mc_unk260(struct nvkm_mc *, u32); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c index 277b6ec04..e04a2296e 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c @@ -21,10 +21,10 @@ * * Authors: Ben Skeggs */ -#include -#include +#include "priv.h" #include +#include void nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node) @@ -32,12 +32,12 @@ nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node) struct nvkm_vm *vm = vma->vm; struct nvkm_mmu *mmu = vm->mmu; struct nvkm_mm_node *r; - int big = vma->node->type != mmu->spg_shift; + int big = vma->node->type != mmu->func->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; - u32 pde = (offset >> mmu->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->pgt_bits - bits); + u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; + u32 max = 1 << (mmu->func->pgt_bits - bits); u32 end, len; delta = 0; @@ -46,14 +46,14 @@ nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node) u32 num = r->length >> bits; while (num) { - struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big]; + struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; end = (pte + num); if (unlikely(end >= max)) end = max; len = end - pte; - mmu->map(vma, pgt, node, pte, len, phys, delta); + mmu->func->map(vma, pgt, node, pte, len, phys, delta); num -= len; pte += len; @@ -67,7 +67,7 @@ nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node) } } - mmu->flush(vm); + mmu->func->flush(vm); } static void @@ -76,20 +76,20 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length, { struct nvkm_vm *vm = vma->vm; struct nvkm_mmu *mmu = vm->mmu; - int big = vma->node->type != mmu->spg_shift; + int big = vma->node->type != mmu->func->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> mmu->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->pgt_bits - bits); + u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; + u32 max = 1 << (mmu->func->pgt_bits - bits); unsigned m, sglen; u32 end, len; int i; struct scatterlist *sg; for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) { - struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big]; + struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; sglen = sg_dma_len(sg) >> PAGE_SHIFT; end = pte + sglen; @@ -100,7 +100,7 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length, for (m = 0; m < len; m++) { dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - mmu->map_sg(vma, pgt, mem, pte, 1, &addr); + mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr); num--; pte++; @@ -115,7 +115,7 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length, for (; m < sglen; m++) { dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - mmu->map_sg(vma, pgt, mem, pte, 1, &addr); + mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr); num--; pte++; if (num == 0) @@ -125,7 +125,7 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length, } finish: - mmu->flush(vm); + mmu->func->flush(vm); } static void @@ -135,24 +135,24 @@ nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length, struct nvkm_vm *vm = vma->vm; struct nvkm_mmu *mmu = vm->mmu; dma_addr_t *list = mem->pages; - int big = vma->node->type != mmu->spg_shift; + int big = vma->node->type != mmu->func->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> mmu->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->pgt_bits - bits); + u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; + u32 max = 1 << (mmu->func->pgt_bits - bits); u32 end, len; while (num) { - struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big]; + struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; end = (pte + num); if (unlikely(end >= max)) end = max; len = end - pte; - mmu->map_sg(vma, pgt, mem, pte, len, list); + mmu->func->map_sg(vma, pgt, mem, pte, len, list); num -= len; pte += len; @@ -163,7 +163,7 @@ nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length, } } - mmu->flush(vm); + mmu->func->flush(vm); } void @@ -183,24 +183,24 @@ nvkm_vm_unmap_at(struct nvkm_vma *vma, u64 delta, u64 length) { struct nvkm_vm *vm = vma->vm; struct nvkm_mmu *mmu = vm->mmu; - int big = vma->node->type != mmu->spg_shift; + int big = vma->node->type != mmu->func->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> mmu->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->pgt_bits - bits); + u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; + u32 max = 1 << (mmu->func->pgt_bits - bits); u32 end, len; while (num) { - struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big]; + struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; end = (pte + num); if (unlikely(end >= max)) end = max; len = end - pte; - mmu->unmap(pgt, pte, len); + mmu->func->unmap(vma, pgt, pte, len); num -= len; pte += len; @@ -210,7 +210,7 @@ nvkm_vm_unmap_at(struct nvkm_vma *vma, u64 delta, u64 length) } } - mmu->flush(vm); + mmu->func->flush(vm); } void @@ -225,7 +225,7 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde) struct nvkm_mmu *mmu = vm->mmu; struct nvkm_vm_pgd *vpgd; struct nvkm_vm_pgt *vpgt; - struct nvkm_gpuobj *pgt; + struct nvkm_memory *pgt; u32 pde; for (pde = fpde; pde <= lpde; pde++) { @@ -233,16 +233,14 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde) if (--vpgt->refcount[big]) continue; - pgt = vpgt->obj[big]; - vpgt->obj[big] = NULL; + pgt = vpgt->mem[big]; + vpgt->mem[big] = NULL; list_for_each_entry(vpgd, &vm->pgd_list, head) { - mmu->map_pgt(vpgd->obj, pde, vpgt->obj); + mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem); } - mutex_unlock(&nv_subdev(mmu)->mutex); - nvkm_gpuobj_ref(NULL, &pgt); - mutex_lock(&nv_subdev(mmu)->mutex); + nvkm_memory_del(&pgt); } } @@ -252,34 +250,23 @@ nvkm_vm_map_pgt(struct nvkm_vm *vm, u32 pde, u32 type) struct nvkm_mmu *mmu = vm->mmu; struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; struct nvkm_vm_pgd *vpgd; - struct nvkm_gpuobj *pgt; - int big = (type != mmu->spg_shift); + int big = (type != mmu->func->spg_shift); u32 pgt_size; int ret; - pgt_size = (1 << (mmu->pgt_bits + 12)) >> type; + pgt_size = (1 << (mmu->func->pgt_bits + 12)) >> type; pgt_size *= 8; - mutex_unlock(&nv_subdev(mmu)->mutex); - ret = nvkm_gpuobj_new(nv_object(vm->mmu), NULL, pgt_size, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &pgt); - mutex_lock(&nv_subdev(mmu)->mutex); + ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST, + pgt_size, 0x1000, true, &vpgt->mem[big]); if (unlikely(ret)) return ret; - /* someone beat us to filling the PDE while we didn't have the lock */ - if (unlikely(vpgt->refcount[big]++)) { - mutex_unlock(&nv_subdev(mmu)->mutex); - nvkm_gpuobj_ref(NULL, &pgt); - mutex_lock(&nv_subdev(mmu)->mutex); - return 0; - } - - vpgt->obj[big] = pgt; list_for_each_entry(vpgd, &vm->pgd_list, head) { - mmu->map_pgt(vpgd->obj, pde, vpgt->obj); + mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem); } + vpgt->refcount[big]++; return 0; } @@ -293,20 +280,20 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access, u32 fpde, lpde, pde; int ret; - mutex_lock(&nv_subdev(mmu)->mutex); + mutex_lock(&vm->mutex); ret = nvkm_mm_head(&vm->mm, 0, page_shift, msize, msize, align, &vma->node); if (unlikely(ret != 0)) { - mutex_unlock(&nv_subdev(mmu)->mutex); + mutex_unlock(&vm->mutex); return ret; } - fpde = (vma->node->offset >> mmu->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> mmu->pgt_bits; + fpde = (vma->node->offset >> mmu->func->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits; for (pde = fpde; pde <= lpde; pde++) { struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; - int big = (vma->node->type != mmu->spg_shift); + int big = (vma->node->type != mmu->func->spg_shift); if (likely(vpgt->refcount[big])) { vpgt->refcount[big]++; @@ -318,11 +305,11 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access, if (pde != fpde) nvkm_vm_unmap_pgt(vm, big, fpde, pde - 1); nvkm_mm_free(&vm->mm, &vma->node); - mutex_unlock(&nv_subdev(mmu)->mutex); + mutex_unlock(&vm->mutex); return ret; } } - mutex_unlock(&nv_subdev(mmu)->mutex); + mutex_unlock(&vm->mutex); vma->vm = NULL; nvkm_vm_ref(vm, &vma->vm, NULL); @@ -334,27 +321,49 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access, void nvkm_vm_put(struct nvkm_vma *vma) { - struct nvkm_vm *vm = vma->vm; - struct nvkm_mmu *mmu = vm->mmu; + struct nvkm_mmu *mmu; + struct nvkm_vm *vm; u32 fpde, lpde; if (unlikely(vma->node == NULL)) return; - fpde = (vma->node->offset >> mmu->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> mmu->pgt_bits; + vm = vma->vm; + mmu = vm->mmu; + + fpde = (vma->node->offset >> mmu->func->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits; - mutex_lock(&nv_subdev(mmu)->mutex); - nvkm_vm_unmap_pgt(vm, vma->node->type != mmu->spg_shift, fpde, lpde); + mutex_lock(&vm->mutex); + nvkm_vm_unmap_pgt(vm, vma->node->type != mmu->func->spg_shift, fpde, lpde); nvkm_mm_free(&vm->mm, &vma->node); - mutex_unlock(&nv_subdev(mmu)->mutex); + mutex_unlock(&vm->mutex); nvkm_vm_ref(NULL, &vma->vm, NULL); } +int +nvkm_vm_boot(struct nvkm_vm *vm, u64 size) +{ + struct nvkm_mmu *mmu = vm->mmu; + struct nvkm_memory *pgt; + int ret; + + ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST, + (size >> mmu->func->spg_shift) * 8, 0x1000, true, &pgt); + if (ret == 0) { + vm->pgt[0].refcount[0] = 1; + vm->pgt[0].mem[0] = pgt; + nvkm_memory_boot(pgt, vm); + } + + return ret; +} + int nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, - u32 block, struct nvkm_vm **pvm) + u32 block, struct lock_class_key *key, struct nvkm_vm **pvm) { + static struct lock_class_key _key; struct nvkm_vm *vm; u64 mm_length = (offset + length) - mm_offset; int ret; @@ -363,11 +372,12 @@ nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, if (!vm) return -ENOMEM; + __mutex_init(&vm->mutex, "&vm->mutex", key ? key : &_key); INIT_LIST_HEAD(&vm->pgd_list); vm->mmu = mmu; kref_init(&vm->refcount); - vm->fpde = offset >> (mmu->pgt_bits + 12); - vm->lpde = (offset + length - 1) >> (mmu->pgt_bits + 12); + vm->fpde = offset >> (mmu->func->pgt_bits + 12); + vm->lpde = (offset + length - 1) >> (mmu->func->pgt_bits + 12); vm->pgt = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt)); if (!vm->pgt) { @@ -390,10 +400,12 @@ nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, int nvkm_vm_new(struct nvkm_device *device, u64 offset, u64 length, u64 mm_offset, - struct nvkm_vm **pvm) + struct lock_class_key *key, struct nvkm_vm **pvm) { - struct nvkm_mmu *mmu = nvkm_mmu(device); - return mmu->create(mmu, offset, length, mm_offset, pvm); + struct nvkm_mmu *mmu = device->mmu; + if (!mmu->func->create) + return -EINVAL; + return mmu->func->create(mmu, offset, length, mm_offset, key, pvm); } static int @@ -410,38 +422,33 @@ nvkm_vm_link(struct nvkm_vm *vm, struct nvkm_gpuobj *pgd) if (!vpgd) return -ENOMEM; - nvkm_gpuobj_ref(pgd, &vpgd->obj); + vpgd->obj = pgd; - mutex_lock(&nv_subdev(mmu)->mutex); + mutex_lock(&vm->mutex); for (i = vm->fpde; i <= vm->lpde; i++) - mmu->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); + mmu->func->map_pgt(pgd, i, vm->pgt[i - vm->fpde].mem); list_add(&vpgd->head, &vm->pgd_list); - mutex_unlock(&nv_subdev(mmu)->mutex); + mutex_unlock(&vm->mutex); return 0; } static void nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd) { - struct nvkm_mmu *mmu = vm->mmu; struct nvkm_vm_pgd *vpgd, *tmp; - struct nvkm_gpuobj *pgd = NULL; if (!mpgd) return; - mutex_lock(&nv_subdev(mmu)->mutex); + mutex_lock(&vm->mutex); list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { if (vpgd->obj == mpgd) { - pgd = vpgd->obj; list_del(&vpgd->head); kfree(vpgd); break; } } - mutex_unlock(&nv_subdev(mmu)->mutex); - - nvkm_gpuobj_ref(NULL, &pgd); + mutex_unlock(&vm->mutex); } static void @@ -478,3 +485,58 @@ nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_gpuobj *pgd) *ptr = ref; return 0; } + +static int +nvkm_mmu_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_mmu *mmu = nvkm_mmu(subdev); + if (mmu->func->oneinit) + return mmu->func->oneinit(mmu); + return 0; +} + +static int +nvkm_mmu_init(struct nvkm_subdev *subdev) +{ + struct nvkm_mmu *mmu = nvkm_mmu(subdev); + if (mmu->func->init) + mmu->func->init(mmu); + return 0; +} + +static void * +nvkm_mmu_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_mmu *mmu = nvkm_mmu(subdev); + if (mmu->func->dtor) + return mmu->func->dtor(mmu); + return mmu; +} + +static const struct nvkm_subdev_func +nvkm_mmu = { + .dtor = nvkm_mmu_dtor, + .oneinit = nvkm_mmu_oneinit, + .init = nvkm_mmu_init, +}; + +void +nvkm_mmu_ctor(const struct nvkm_mmu_func *func, struct nvkm_device *device, + int index, struct nvkm_mmu *mmu) +{ + nvkm_subdev_ctor(&nvkm_mmu, device, index, 0, &mmu->subdev); + mmu->func = func; + mmu->limit = func->limit; + mmu->dma_bits = func->dma_bits; + mmu->lpg_shift = func->lpg_shift; +} + +int +nvkm_mmu_new_(const struct nvkm_mmu_func *func, struct nvkm_device *device, + int index, struct nvkm_mmu **pmmu) +{ + if (!(*pmmu = kzalloc(sizeof(**pmmu), GFP_KERNEL))) + return -ENOMEM; + nvkm_mmu_ctor(func, device, index, *pmmu); + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c index 294cda37f..7ac507c92 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c @@ -21,19 +21,14 @@ * * Authors: Ben Skeggs */ -#include -#include +#include "priv.h" + #include #include #include #include -struct gf100_mmu_priv { - struct nvkm_mmu base; -}; - - /* Map from compressed to corresponding uncompressed storage type. * The value 0xff represents an invalid storage type. */ @@ -75,17 +70,19 @@ const u8 gf100_pte_storage_type_map[256] = static void -gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_gpuobj *pgt[2]) +gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_memory *pgt[2]) { u32 pde[2] = { 0, 0 }; if (pgt[0]) - pde[1] = 0x00000001 | (pgt[0]->addr >> 8); + pde[1] = 0x00000001 | (nvkm_memory_addr(pgt[0]) >> 8); if (pgt[1]) - pde[0] = 0x00000001 | (pgt[1]->addr >> 8); + pde[0] = 0x00000001 | (nvkm_memory_addr(pgt[1]) >> 8); - nv_wo32(pgd, (index * 8) + 0, pde[0]); - nv_wo32(pgd, (index * 8) + 4, pde[1]); + nvkm_kmap(pgd); + nvkm_wo32(pgd, (index * 8) + 0, pde[0]); + nvkm_wo32(pgd, (index * 8) + 4, pde[1]); + nvkm_done(pgd); } static inline u64 @@ -103,7 +100,7 @@ gf100_vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target) } static void -gf100_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +gf100_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { u64 next = 1 << (vma->node->type - 8); @@ -112,126 +109,113 @@ gf100_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, pte <<= 3; if (mem->tag) { - struct nvkm_ltc *ltc = nvkm_ltc(vma->vm->mmu); + struct nvkm_ltc *ltc = vma->vm->mmu->subdev.device->ltc; u32 tag = mem->tag->offset + (delta >> 17); phys |= (u64)tag << (32 + 12); next |= (u64)1 << (32 + 12); - ltc->tags_clear(ltc, tag, cnt); + nvkm_ltc_tags_clear(ltc, tag, cnt); } + nvkm_kmap(pgt); while (cnt--) { - nv_wo32(pgt, pte + 0, lower_32_bits(phys)); - nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + nvkm_wo32(pgt, pte + 0, lower_32_bits(phys)); + nvkm_wo32(pgt, pte + 4, upper_32_bits(phys)); phys += next; pte += 8; } + nvkm_done(pgt); } static void -gf100_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +gf100_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5; /* compressed storage types are invalid for system memory */ u32 memtype = gf100_pte_storage_type_map[mem->memtype & 0xff]; + nvkm_kmap(pgt); pte <<= 3; while (cnt--) { u64 phys = gf100_vm_addr(vma, *list++, memtype, target); - nv_wo32(pgt, pte + 0, lower_32_bits(phys)); - nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + nvkm_wo32(pgt, pte + 0, lower_32_bits(phys)); + nvkm_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; } + nvkm_done(pgt); } static void -gf100_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt) +gf100_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) { + nvkm_kmap(pgt); pte <<= 3; while (cnt--) { - nv_wo32(pgt, pte + 0, 0x00000000); - nv_wo32(pgt, pte + 4, 0x00000000); + nvkm_wo32(pgt, pte + 0, 0x00000000); + nvkm_wo32(pgt, pte + 4, 0x00000000); pte += 8; } + nvkm_done(pgt); } static void gf100_vm_flush(struct nvkm_vm *vm) { - struct gf100_mmu_priv *priv = (void *)vm->mmu; - struct nvkm_bar *bar = nvkm_bar(priv); + struct nvkm_mmu *mmu = vm->mmu; + struct nvkm_device *device = mmu->subdev.device; struct nvkm_vm_pgd *vpgd; u32 type; - bar->flush(bar); - type = 0x00000001; /* PAGE_ALL */ - if (atomic_read(&vm->engref[NVDEV_SUBDEV_BAR])) + if (atomic_read(&vm->engref[NVKM_SUBDEV_BAR])) type |= 0x00000004; /* HUB_ONLY */ - mutex_lock(&nv_subdev(priv)->mutex); + mutex_lock(&mmu->subdev.mutex); list_for_each_entry(vpgd, &vm->pgd_list, head) { /* looks like maybe a "free flush slots" counter, the * faster you write to 0x100cbc to more it decreases */ - if (!nv_wait_ne(priv, 0x100c80, 0x00ff0000, 0x00000000)) { - nv_error(priv, "vm timeout 0: 0x%08x %d\n", - nv_rd32(priv, 0x100c80), type); - } + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100c80) & 0x00ff0000) + break; + ); - nv_wr32(priv, 0x100cb8, vpgd->obj->addr >> 8); - nv_wr32(priv, 0x100cbc, 0x80000000 | type); + nvkm_wr32(device, 0x100cb8, vpgd->obj->addr >> 8); + nvkm_wr32(device, 0x100cbc, 0x80000000 | type); /* wait for flush to be queued? */ - if (!nv_wait(priv, 0x100c80, 0x00008000, 0x00008000)) { - nv_error(priv, "vm timeout 1: 0x%08x %d\n", - nv_rd32(priv, 0x100c80), type); - } + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100c80) & 0x00008000) + break; + ); } - mutex_unlock(&nv_subdev(priv)->mutex); + mutex_unlock(&mmu->subdev.mutex); } static int gf100_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, - struct nvkm_vm **pvm) + struct lock_class_key *key, struct nvkm_vm **pvm) { - return nvkm_vm_create(mmu, offset, length, mm_offset, 4096, pvm); + return nvkm_vm_create(mmu, offset, length, mm_offset, 4096, key, pvm); } -static int -gf100_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_mmu_func +gf100_mmu = { + .limit = (1ULL << 40), + .dma_bits = 40, + .pgt_bits = 27 - 12, + .spg_shift = 12, + .lpg_shift = 17, + .create = gf100_vm_create, + .map_pgt = gf100_vm_map_pgt, + .map = gf100_vm_map, + .map_sg = gf100_vm_map_sg, + .unmap = gf100_vm_unmap, + .flush = gf100_vm_flush, +}; + +int +gf100_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) { - struct gf100_mmu_priv *priv; - int ret; - - ret = nvkm_mmu_create(parent, engine, oclass, "VM", "vm", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.limit = 1ULL << 40; - priv->base.dma_bits = 40; - priv->base.pgt_bits = 27 - 12; - priv->base.spg_shift = 12; - priv->base.lpg_shift = 17; - priv->base.create = gf100_vm_create; - priv->base.map_pgt = gf100_vm_map_pgt; - priv->base.map = gf100_vm_map; - priv->base.map_sg = gf100_vm_map_sg; - priv->base.unmap = gf100_vm_unmap; - priv->base.flush = gf100_vm_flush; - return 0; + return nvkm_mmu_new_(&gf100_mmu, device, index, pmmu); } - -struct nvkm_oclass -gf100_mmu_oclass = { - .handle = NV_SUBDEV(MMU, 0xc0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_mmu_ctor, - .dtor = _nvkm_mmu_dtor, - .init = _nvkm_mmu_init, - .fini = _nvkm_mmu_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c index fe93ea271..37927c3fd 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c @@ -23,7 +23,6 @@ */ #include "nv04.h" -#include #include #define NV04_PDMA_SIZE (128 * 1024 * 1024) @@ -34,30 +33,34 @@ ******************************************************************************/ static void -nv04_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +nv04_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { pte = 0x00008 + (pte * 4); + nvkm_kmap(pgt); while (cnt) { u32 page = PAGE_SIZE / NV04_PDMA_PAGE; u32 phys = (u32)*list++; while (cnt && page--) { - nv_wo32(pgt, pte, phys | 3); + nvkm_wo32(pgt, pte, phys | 3); phys += NV04_PDMA_PAGE; pte += 4; cnt -= 1; } } + nvkm_done(pgt); } static void -nv04_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt) +nv04_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) { pte = 0x00008 + (pte * 4); + nvkm_kmap(pgt); while (cnt--) { - nv_wo32(pgt, pte, 0x00000000); + nvkm_wo32(pgt, pte, 0x00000000); pte += 4; } + nvkm_done(pgt); } static void @@ -65,87 +68,82 @@ nv04_vm_flush(struct nvkm_vm *vm) { } -/******************************************************************************* - * VM object - ******************************************************************************/ - -int -nv04_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mmstart, - struct nvkm_vm **pvm) -{ - return -EINVAL; -} - /******************************************************************************* * MMU subdev ******************************************************************************/ static int -nv04_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_mmu_oneinit(struct nvkm_mmu *base) { - struct nv04_mmu_priv *priv; - struct nvkm_gpuobj *dma; + struct nv04_mmu *mmu = nv04_mmu(base); + struct nvkm_device *device = mmu->base.subdev.device; + struct nvkm_memory *dma; int ret; - ret = nvkm_mmu_create(parent, engine, oclass, "PCIGART", - "pcigart", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.create = nv04_vm_create; - priv->base.limit = NV04_PDMA_SIZE; - priv->base.dma_bits = 32; - priv->base.pgt_bits = 32 - 12; - priv->base.spg_shift = 12; - priv->base.lpg_shift = 12; - priv->base.map_sg = nv04_vm_map_sg; - priv->base.unmap = nv04_vm_unmap; - priv->base.flush = nv04_vm_flush; - - ret = nvkm_vm_create(&priv->base, 0, NV04_PDMA_SIZE, 0, 4096, - &priv->vm); + ret = nvkm_vm_create(&mmu->base, 0, NV04_PDMA_SIZE, 0, 4096, NULL, + &mmu->vm); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), NULL, + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, (NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + 8, - 16, NVOBJ_FLAG_ZERO_ALLOC, - &priv->vm->pgt[0].obj[0]); - dma = priv->vm->pgt[0].obj[0]; - priv->vm->pgt[0].refcount[0] = 1; + 16, true, &dma); + mmu->vm->pgt[0].mem[0] = dma; + mmu->vm->pgt[0].refcount[0] = 1; if (ret) return ret; - nv_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */ - nv_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1); + nvkm_kmap(dma); + nvkm_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */ + nvkm_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1); + nvkm_done(dma); return 0; } -void -nv04_mmu_dtor(struct nvkm_object *object) +void * +nv04_mmu_dtor(struct nvkm_mmu *base) { - struct nv04_mmu_priv *priv = (void *)object; - if (priv->vm) { - nvkm_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]); - nvkm_vm_ref(NULL, &priv->vm, NULL); + struct nv04_mmu *mmu = nv04_mmu(base); + struct nvkm_device *device = mmu->base.subdev.device; + if (mmu->vm) { + nvkm_memory_del(&mmu->vm->pgt[0].mem[0]); + nvkm_vm_ref(NULL, &mmu->vm, NULL); } - if (priv->nullp) { - pci_free_consistent(nv_device(priv)->pdev, 16 * 1024, - priv->nullp, priv->null); + if (mmu->nullp) { + dma_free_coherent(device->dev, 16 * 1024, + mmu->nullp, mmu->null); } - nvkm_mmu_destroy(&priv->base); + return mmu; +} + +int +nv04_mmu_new_(const struct nvkm_mmu_func *func, struct nvkm_device *device, + int index, struct nvkm_mmu **pmmu) +{ + struct nv04_mmu *mmu; + if (!(mmu = kzalloc(sizeof(*mmu), GFP_KERNEL))) + return -ENOMEM; + *pmmu = &mmu->base; + nvkm_mmu_ctor(func, device, index, &mmu->base); + return 0; } -struct nvkm_oclass -nv04_mmu_oclass = { - .handle = NV_SUBDEV(MMU, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_mmu_ctor, - .dtor = nv04_mmu_dtor, - .init = _nvkm_mmu_init, - .fini = _nvkm_mmu_fini, - }, +const struct nvkm_mmu_func +nv04_mmu = { + .oneinit = nv04_mmu_oneinit, + .dtor = nv04_mmu_dtor, + .limit = NV04_PDMA_SIZE, + .dma_bits = 32, + .pgt_bits = 32 - 12, + .spg_shift = 12, + .lpg_shift = 12, + .map_sg = nv04_vm_map_sg, + .unmap = nv04_vm_unmap, + .flush = nv04_vm_flush, }; + +int +nv04_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + return nv04_mmu_new_(&nv04_mmu, device, index, pmmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h index 7bf6f4b38..363e33b29 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h @@ -1,19 +1,18 @@ #ifndef __NV04_MMU_PRIV__ #define __NV04_MMU_PRIV__ +#define nv04_mmu(p) container_of((p), struct nv04_mmu, base) +#include "priv.h" -#include - -struct nv04_mmu_priv { +struct nv04_mmu { struct nvkm_mmu base; struct nvkm_vm *vm; dma_addr_t null; void *nullp; }; -static inline struct nv04_mmu_priv * -nv04_mmu(void *obj) -{ - return (void *)nvkm_mmu(obj); -} +int nv04_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *, + int index, struct nvkm_mmu **); +void *nv04_mmu_dtor(struct nvkm_mmu *); +extern const struct nvkm_mmu_func nv04_mmu; #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c index 61ee3ab11..c6a26f907 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c @@ -23,7 +23,6 @@ */ #include "nv04.h" -#include #include #include #include @@ -36,45 +35,50 @@ ******************************************************************************/ static void -nv41_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +nv41_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { pte = pte * 4; + nvkm_kmap(pgt); while (cnt) { u32 page = PAGE_SIZE / NV41_GART_PAGE; u64 phys = (u64)*list++; while (cnt && page--) { - nv_wo32(pgt, pte, (phys >> 7) | 1); + nvkm_wo32(pgt, pte, (phys >> 7) | 1); phys += NV41_GART_PAGE; pte += 4; cnt -= 1; } } + nvkm_done(pgt); } static void -nv41_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt) +nv41_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) { pte = pte * 4; + nvkm_kmap(pgt); while (cnt--) { - nv_wo32(pgt, pte, 0x00000000); + nvkm_wo32(pgt, pte, 0x00000000); pte += 4; } + nvkm_done(pgt); } static void nv41_vm_flush(struct nvkm_vm *vm) { - struct nv04_mmu_priv *priv = (void *)vm->mmu; - - mutex_lock(&nv_subdev(priv)->mutex); - nv_wr32(priv, 0x100810, 0x00000022); - if (!nv_wait(priv, 0x100810, 0x00000020, 0x00000020)) { - nv_warn(priv, "flush timeout, 0x%08x\n", - nv_rd32(priv, 0x100810)); - } - nv_wr32(priv, 0x100810, 0x00000000); - mutex_unlock(&nv_subdev(priv)->mutex); + struct nv04_mmu *mmu = nv04_mmu(vm->mmu); + struct nvkm_device *device = mmu->base.subdev.device; + + mutex_lock(&mmu->base.subdev.mutex); + nvkm_wr32(device, 0x100810, 0x00000022); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100810) & 0x00000020) + break; + ); + nvkm_wr32(device, 0x100810, 0x00000000); + mutex_unlock(&mmu->base.subdev.mutex); } /******************************************************************************* @@ -82,76 +86,56 @@ nv41_vm_flush(struct nvkm_vm *vm) ******************************************************************************/ static int -nv41_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv41_mmu_oneinit(struct nvkm_mmu *base) { - struct nvkm_device *device = nv_device(parent); - struct nv04_mmu_priv *priv; + struct nv04_mmu *mmu = nv04_mmu(base); + struct nvkm_device *device = mmu->base.subdev.device; int ret; - if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || - !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) { - return nvkm_object_ctor(parent, engine, &nv04_mmu_oclass, - data, size, pobject); - } - - ret = nvkm_mmu_create(parent, engine, oclass, "PCIEGART", - "pciegart", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.create = nv04_vm_create; - priv->base.limit = NV41_GART_SIZE; - priv->base.dma_bits = 39; - priv->base.pgt_bits = 32 - 12; - priv->base.spg_shift = 12; - priv->base.lpg_shift = 12; - priv->base.map_sg = nv41_vm_map_sg; - priv->base.unmap = nv41_vm_unmap; - priv->base.flush = nv41_vm_flush; - - ret = nvkm_vm_create(&priv->base, 0, NV41_GART_SIZE, 0, 4096, - &priv->vm); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(nv_object(priv), NULL, - (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, - &priv->vm->pgt[0].obj[0]); - priv->vm->pgt[0].refcount[0] = 1; + ret = nvkm_vm_create(&mmu->base, 0, NV41_GART_SIZE, 0, 4096, NULL, + &mmu->vm); if (ret) return ret; - return 0; + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16, true, + &mmu->vm->pgt[0].mem[0]); + mmu->vm->pgt[0].refcount[0] = 1; + return ret; } -static int -nv41_mmu_init(struct nvkm_object *object) +static void +nv41_mmu_init(struct nvkm_mmu *base) { - struct nv04_mmu_priv *priv = (void *)object; - struct nvkm_gpuobj *dma = priv->vm->pgt[0].obj[0]; - int ret; - - ret = nvkm_mmu_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x100800, dma->addr | 0x00000002); - nv_mask(priv, 0x10008c, 0x00000100, 0x00000100); - nv_wr32(priv, 0x100820, 0x00000000); - return 0; + struct nv04_mmu *mmu = nv04_mmu(base); + struct nvkm_device *device = mmu->base.subdev.device; + struct nvkm_memory *dma = mmu->vm->pgt[0].mem[0]; + nvkm_wr32(device, 0x100800, 0x00000002 | nvkm_memory_addr(dma)); + nvkm_mask(device, 0x10008c, 0x00000100, 0x00000100); + nvkm_wr32(device, 0x100820, 0x00000000); } -struct nvkm_oclass -nv41_mmu_oclass = { - .handle = NV_SUBDEV(MMU, 0x41), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv41_mmu_ctor, - .dtor = nv04_mmu_dtor, - .init = nv41_mmu_init, - .fini = _nvkm_mmu_fini, - }, +static const struct nvkm_mmu_func +nv41_mmu = { + .dtor = nv04_mmu_dtor, + .oneinit = nv41_mmu_oneinit, + .init = nv41_mmu_init, + .limit = NV41_GART_SIZE, + .dma_bits = 39, + .pgt_bits = 32 - 12, + .spg_shift = 12, + .lpg_shift = 12, + .map_sg = nv41_vm_map_sg, + .unmap = nv41_vm_unmap, + .flush = nv41_vm_flush, }; + +int +nv41_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + if (device->type == NVKM_DEVICE_AGP || + !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) + return nv04_mmu_new(device, index, pmmu); + + return nv04_mmu_new_(&nv41_mmu, device, index, pmmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c index b90ded188..a648c2395 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c @@ -23,7 +23,6 @@ */ #include "nv04.h" -#include #include #include #include @@ -36,16 +35,16 @@ ******************************************************************************/ static void -nv44_vm_fill(struct nvkm_gpuobj *pgt, dma_addr_t null, +nv44_vm_fill(struct nvkm_memory *pgt, dma_addr_t null, dma_addr_t *list, u32 pte, u32 cnt) { u32 base = (pte << 2) & ~0x0000000f; u32 tmp[4]; - tmp[0] = nv_ro32(pgt, base + 0x0); - tmp[1] = nv_ro32(pgt, base + 0x4); - tmp[2] = nv_ro32(pgt, base + 0x8); - tmp[3] = nv_ro32(pgt, base + 0xc); + tmp[0] = nvkm_ro32(pgt, base + 0x0); + tmp[1] = nvkm_ro32(pgt, base + 0x4); + tmp[2] = nvkm_ro32(pgt, base + 0x8); + tmp[3] = nvkm_ro32(pgt, base + 0xc); while (cnt--) { u32 addr = list ? (*list++ >> 12) : (null >> 12); @@ -75,24 +74,25 @@ nv44_vm_fill(struct nvkm_gpuobj *pgt, dma_addr_t null, } } - nv_wo32(pgt, base + 0x0, tmp[0]); - nv_wo32(pgt, base + 0x4, tmp[1]); - nv_wo32(pgt, base + 0x8, tmp[2]); - nv_wo32(pgt, base + 0xc, tmp[3] | 0x40000000); + nvkm_wo32(pgt, base + 0x0, tmp[0]); + nvkm_wo32(pgt, base + 0x4, tmp[1]); + nvkm_wo32(pgt, base + 0x8, tmp[2]); + nvkm_wo32(pgt, base + 0xc, tmp[3] | 0x40000000); } static void -nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { - struct nv04_mmu_priv *priv = (void *)vma->vm->mmu; + struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu); u32 tmp[4]; int i; + nvkm_kmap(pgt); if (pte & 3) { u32 max = 4 - (pte & 3); u32 part = (cnt > max) ? max : cnt; - nv44_vm_fill(pgt, priv->null, list, pte, part); + nv44_vm_fill(pgt, mmu->null, list, pte, part); pte += part; list += part; cnt -= part; @@ -101,51 +101,57 @@ nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, while (cnt >= 4) { for (i = 0; i < 4; i++) tmp[i] = *list++ >> 12; - nv_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27); - nv_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22); - nv_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17); - nv_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000); + nvkm_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27); + nvkm_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22); + nvkm_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17); + nvkm_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000); cnt -= 4; } if (cnt) - nv44_vm_fill(pgt, priv->null, list, pte, cnt); + nv44_vm_fill(pgt, mmu->null, list, pte, cnt); + nvkm_done(pgt); } static void -nv44_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt) +nv44_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) { - struct nv04_mmu_priv *priv = (void *)nvkm_mmu(pgt); + struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu); + nvkm_kmap(pgt); if (pte & 3) { u32 max = 4 - (pte & 3); u32 part = (cnt > max) ? max : cnt; - nv44_vm_fill(pgt, priv->null, NULL, pte, part); + nv44_vm_fill(pgt, mmu->null, NULL, pte, part); pte += part; cnt -= part; } while (cnt >= 4) { - nv_wo32(pgt, pte++ * 4, 0x00000000); - nv_wo32(pgt, pte++ * 4, 0x00000000); - nv_wo32(pgt, pte++ * 4, 0x00000000); - nv_wo32(pgt, pte++ * 4, 0x00000000); + nvkm_wo32(pgt, pte++ * 4, 0x00000000); + nvkm_wo32(pgt, pte++ * 4, 0x00000000); + nvkm_wo32(pgt, pte++ * 4, 0x00000000); + nvkm_wo32(pgt, pte++ * 4, 0x00000000); cnt -= 4; } if (cnt) - nv44_vm_fill(pgt, priv->null, NULL, pte, cnt); + nv44_vm_fill(pgt, mmu->null, NULL, pte, cnt); + nvkm_done(pgt); } static void nv44_vm_flush(struct nvkm_vm *vm) { - struct nv04_mmu_priv *priv = (void *)vm->mmu; - nv_wr32(priv, 0x100814, priv->base.limit - NV44_GART_PAGE); - nv_wr32(priv, 0x100808, 0x00000020); - if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001)) - nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808)); - nv_wr32(priv, 0x100808, 0x00000000); + struct nv04_mmu *mmu = nv04_mmu(vm->mmu); + struct nvkm_device *device = mmu->base.subdev.device; + nvkm_wr32(device, 0x100814, mmu->base.limit - NV44_GART_PAGE); + nvkm_wr32(device, 0x100808, 0x00000020); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100808) & 0x00000001) + break; + ); + nvkm_wr32(device, 0x100808, 0x00000000); } /******************************************************************************* @@ -153,95 +159,78 @@ nv44_vm_flush(struct nvkm_vm *vm) ******************************************************************************/ static int -nv44_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv44_mmu_oneinit(struct nvkm_mmu *base) { - struct nvkm_device *device = nv_device(parent); - struct nv04_mmu_priv *priv; + struct nv04_mmu *mmu = nv04_mmu(base); + struct nvkm_device *device = mmu->base.subdev.device; int ret; - if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || - !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) { - return nvkm_object_ctor(parent, engine, &nv04_mmu_oclass, - data, size, pobject); - } - - ret = nvkm_mmu_create(parent, engine, oclass, "PCIEGART", - "pciegart", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.create = nv04_vm_create; - priv->base.limit = NV44_GART_SIZE; - priv->base.dma_bits = 39; - priv->base.pgt_bits = 32 - 12; - priv->base.spg_shift = 12; - priv->base.lpg_shift = 12; - priv->base.map_sg = nv44_vm_map_sg; - priv->base.unmap = nv44_vm_unmap; - priv->base.flush = nv44_vm_flush; - - priv->nullp = pci_alloc_consistent(device->pdev, 16 * 1024, &priv->null); - if (!priv->nullp) { - nv_error(priv, "unable to allocate dummy pages\n"); - return -ENOMEM; + mmu->nullp = dma_alloc_coherent(device->dev, 16 * 1024, + &mmu->null, GFP_KERNEL); + if (!mmu->nullp) { + nvkm_warn(&mmu->base.subdev, "unable to allocate dummy pages\n"); + mmu->null = 0; } - ret = nvkm_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096, - &priv->vm); + ret = nvkm_vm_create(&mmu->base, 0, NV44_GART_SIZE, 0, 4096, NULL, + &mmu->vm); if (ret) return ret; - ret = nvkm_gpuobj_new(nv_object(priv), NULL, + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, (NV44_GART_SIZE / NV44_GART_PAGE) * 4, - 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC, - &priv->vm->pgt[0].obj[0]); - priv->vm->pgt[0].refcount[0] = 1; - if (ret) - return ret; - - return 0; + 512 * 1024, true, + &mmu->vm->pgt[0].mem[0]); + mmu->vm->pgt[0].refcount[0] = 1; + return ret; } -static int -nv44_mmu_init(struct nvkm_object *object) +static void +nv44_mmu_init(struct nvkm_mmu *base) { - struct nv04_mmu_priv *priv = (void *)object; - struct nvkm_gpuobj *gart = priv->vm->pgt[0].obj[0]; + struct nv04_mmu *mmu = nv04_mmu(base); + struct nvkm_device *device = mmu->base.subdev.device; + struct nvkm_memory *gart = mmu->vm->pgt[0].mem[0]; u32 addr; - int ret; - - ret = nvkm_mmu_init(&priv->base); - if (ret) - return ret; /* calculate vram address of this PRAMIN block, object must be * allocated on 512KiB alignment, and not exceed a total size * of 512KiB for this to work correctly */ - addr = nv_rd32(priv, 0x10020c); - addr -= ((gart->addr >> 19) + 1) << 19; - - nv_wr32(priv, 0x100850, 0x80000000); - nv_wr32(priv, 0x100818, priv->null); - nv_wr32(priv, 0x100804, NV44_GART_SIZE); - nv_wr32(priv, 0x100850, 0x00008000); - nv_mask(priv, 0x10008c, 0x00000200, 0x00000200); - nv_wr32(priv, 0x100820, 0x00000000); - nv_wr32(priv, 0x10082c, 0x00000001); - nv_wr32(priv, 0x100800, addr | 0x00000010); - return 0; + addr = nvkm_rd32(device, 0x10020c); + addr -= ((nvkm_memory_addr(gart) >> 19) + 1) << 19; + + nvkm_wr32(device, 0x100850, 0x80000000); + nvkm_wr32(device, 0x100818, mmu->null); + nvkm_wr32(device, 0x100804, NV44_GART_SIZE); + nvkm_wr32(device, 0x100850, 0x00008000); + nvkm_mask(device, 0x10008c, 0x00000200, 0x00000200); + nvkm_wr32(device, 0x100820, 0x00000000); + nvkm_wr32(device, 0x10082c, 0x00000001); + nvkm_wr32(device, 0x100800, addr | 0x00000010); } -struct nvkm_oclass -nv44_mmu_oclass = { - .handle = NV_SUBDEV(MMU, 0x44), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv44_mmu_ctor, - .dtor = nv04_mmu_dtor, - .init = nv44_mmu_init, - .fini = _nvkm_mmu_fini, - }, +static const struct nvkm_mmu_func +nv44_mmu = { + .dtor = nv04_mmu_dtor, + .oneinit = nv44_mmu_oneinit, + .init = nv44_mmu_init, + .limit = NV44_GART_SIZE, + .dma_bits = 39, + .pgt_bits = 32 - 12, + .spg_shift = 12, + .lpg_shift = 12, + .map_sg = nv44_vm_map_sg, + .unmap = nv44_vm_unmap, + .flush = nv44_vm_flush, }; + +int +nv44_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + if (device->type == NVKM_DEVICE_AGP || + !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) + return nv04_mmu_new(device, index, pmmu); + + return nv04_mmu_new_(&nv44_mmu, device, index, pmmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c index b83550fa7..a1f8d65f0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c @@ -21,31 +21,28 @@ * * Authors: Ben Skeggs */ -#include -#include -#include -#include +#include "priv.h" -#include #include - -struct nv50_mmu_priv { - struct nvkm_mmu base; -}; +#include +#include +#include static void -nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_gpuobj *pgt[2]) +nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2]) { u64 phys = 0xdeadcafe00000000ULL; u32 coverage = 0; if (pgt[0]) { - phys = 0x00000003 | pgt[0]->addr; /* present, 4KiB pages */ - coverage = (pgt[0]->size >> 3) << 12; + /* present, 4KiB pages */ + phys = 0x00000003 | nvkm_memory_addr(pgt[0]); + coverage = (nvkm_memory_size(pgt[0]) >> 3) << 12; } else if (pgt[1]) { - phys = 0x00000001 | pgt[1]->addr; /* present */ - coverage = (pgt[1]->size >> 3) << 16; + /* present, 64KiB pages */ + phys = 0x00000001 | nvkm_memory_addr(pgt[1]); + coverage = (nvkm_memory_size(pgt[1]) >> 3) << 16; } if (phys & 1) { @@ -57,8 +54,10 @@ nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_gpuobj *pgt[2]) phys |= 0x20; } - nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); - nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); + nvkm_kmap(pgd); + nvkm_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); + nvkm_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); + nvkm_done(pgd); } static inline u64 @@ -75,17 +74,18 @@ vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target) } static void -nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +nv50_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { + struct nvkm_ram *ram = vma->vm->mmu->subdev.device->fb->ram; u32 comp = (mem->memtype & 0x180) >> 7; u32 block, target; int i; /* IGPs don't have real VRAM, re-target to stolen system memory */ target = 0; - if (nvkm_fb(vma->vm->mmu)->ram->stolen) { - phys += nvkm_fb(vma->vm->mmu)->ram->stolen; + if (ram->stolen) { + phys += ram->stolen; target = 3; } @@ -93,6 +93,7 @@ nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, pte <<= 3; cnt <<= 3; + nvkm_kmap(pgt); while (cnt) { u32 offset_h = upper_32_bits(phys); u32 offset_l = lower_32_bits(phys); @@ -113,129 +114,118 @@ nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, } while (block) { - nv_wo32(pgt, pte + 0, offset_l); - nv_wo32(pgt, pte + 4, offset_h); + nvkm_wo32(pgt, pte + 0, offset_l); + nvkm_wo32(pgt, pte + 4, offset_h); pte += 8; block -= 8; } } + nvkm_done(pgt); } static void -nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt, +nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2; pte <<= 3; + nvkm_kmap(pgt); while (cnt--) { u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target); - nv_wo32(pgt, pte + 0, lower_32_bits(phys)); - nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + nvkm_wo32(pgt, pte + 0, lower_32_bits(phys)); + nvkm_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; } + nvkm_done(pgt); } static void -nv50_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt) +nv50_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) { pte <<= 3; + nvkm_kmap(pgt); while (cnt--) { - nv_wo32(pgt, pte + 0, 0x00000000); - nv_wo32(pgt, pte + 4, 0x00000000); + nvkm_wo32(pgt, pte + 0, 0x00000000); + nvkm_wo32(pgt, pte + 4, 0x00000000); pte += 8; } + nvkm_done(pgt); } static void nv50_vm_flush(struct nvkm_vm *vm) { - struct nv50_mmu_priv *priv = (void *)vm->mmu; - struct nvkm_bar *bar = nvkm_bar(priv); - struct nvkm_engine *engine; + struct nvkm_mmu *mmu = vm->mmu; + struct nvkm_subdev *subdev = &mmu->subdev; + struct nvkm_device *device = subdev->device; int i, vme; - bar->flush(bar); - - mutex_lock(&nv_subdev(priv)->mutex); - for (i = 0; i < NVDEV_SUBDEV_NR; i++) { + mutex_lock(&subdev->mutex); + for (i = 0; i < NVKM_SUBDEV_NR; i++) { if (!atomic_read(&vm->engref[i])) continue; /* unfortunate hw bug workaround... */ - engine = nvkm_engine(priv, i); - if (engine && engine->tlb_flush) { - engine->tlb_flush(engine); - continue; + if (i == NVKM_ENGINE_GR && device->gr) { + int ret = nvkm_gr_tlb_flush(device->gr); + if (ret != -ENODEV) + continue; } switch (i) { - case NVDEV_ENGINE_GR : vme = 0x00; break; - case NVDEV_ENGINE_VP : - case NVDEV_ENGINE_MSPDEC: vme = 0x01; break; - case NVDEV_SUBDEV_BAR : vme = 0x06; break; - case NVDEV_ENGINE_MSPPP : - case NVDEV_ENGINE_MPEG : vme = 0x08; break; - case NVDEV_ENGINE_BSP : - case NVDEV_ENGINE_MSVLD : vme = 0x09; break; - case NVDEV_ENGINE_CIPHER: - case NVDEV_ENGINE_SEC : vme = 0x0a; break; - case NVDEV_ENGINE_CE0 : vme = 0x0d; break; + case NVKM_ENGINE_GR : vme = 0x00; break; + case NVKM_ENGINE_VP : + case NVKM_ENGINE_MSPDEC: vme = 0x01; break; + case NVKM_SUBDEV_BAR : vme = 0x06; break; + case NVKM_ENGINE_MSPPP : + case NVKM_ENGINE_MPEG : vme = 0x08; break; + case NVKM_ENGINE_BSP : + case NVKM_ENGINE_MSVLD : vme = 0x09; break; + case NVKM_ENGINE_CIPHER: + case NVKM_ENGINE_SEC : vme = 0x0a; break; + case NVKM_ENGINE_CE0 : vme = 0x0d; break; default: continue; } - nv_wr32(priv, 0x100c80, (vme << 16) | 1); - if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000)) - nv_error(priv, "vm flush timeout: engine %d\n", vme); + nvkm_wr32(device, 0x100c80, (vme << 16) | 1); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) + break; + ) < 0) + nvkm_error(subdev, "vm flush timeout: engine %d\n", vme); } - mutex_unlock(&nv_subdev(priv)->mutex); + mutex_unlock(&subdev->mutex); } static int -nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, - u64 mm_offset, struct nvkm_vm **pvm) +nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, + struct lock_class_key *key, struct nvkm_vm **pvm) { - u32 block = (1 << (mmu->pgt_bits + 12)); + u32 block = (1 << (mmu->func->pgt_bits + 12)); if (block > length) block = length; - return nvkm_vm_create(mmu, offset, length, mm_offset, block, pvm); + return nvkm_vm_create(mmu, offset, length, mm_offset, block, key, pvm); } -static int -nv50_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_mmu_func +nv50_mmu = { + .limit = (1ULL << 40), + .dma_bits = 40, + .pgt_bits = 29 - 12, + .spg_shift = 12, + .lpg_shift = 16, + .create = nv50_vm_create, + .map_pgt = nv50_vm_map_pgt, + .map = nv50_vm_map, + .map_sg = nv50_vm_map_sg, + .unmap = nv50_vm_unmap, + .flush = nv50_vm_flush, +}; + +int +nv50_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) { - struct nv50_mmu_priv *priv; - int ret; - - ret = nvkm_mmu_create(parent, engine, oclass, "VM", "vm", &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.limit = 1ULL << 40; - priv->base.dma_bits = 40; - priv->base.pgt_bits = 29 - 12; - priv->base.spg_shift = 12; - priv->base.lpg_shift = 16; - priv->base.create = nv50_vm_create; - priv->base.map_pgt = nv50_vm_map_pgt; - priv->base.map = nv50_vm_map; - priv->base.map_sg = nv50_vm_map_sg; - priv->base.unmap = nv50_vm_unmap; - priv->base.flush = nv50_vm_flush; - return 0; + return nvkm_mmu_new_(&nv50_mmu, device, index, pmmu); } - -struct nvkm_oclass -nv50_mmu_oclass = { - .handle = NV_SUBDEV(MMU, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_mmu_ctor, - .dtor = _nvkm_mmu_dtor, - .init = _nvkm_mmu_init, - .fini = _nvkm_mmu_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h new file mode 100644 index 000000000..27cedc60b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h @@ -0,0 +1,39 @@ +#ifndef __NVKM_MMU_PRIV_H__ +#define __NVKM_MMU_PRIV_H__ +#define nvkm_mmu(p) container_of((p), struct nvkm_mmu, subdev) +#include + +void nvkm_mmu_ctor(const struct nvkm_mmu_func *, struct nvkm_device *, + int index, struct nvkm_mmu *); +int nvkm_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *, + int index, struct nvkm_mmu **); + +struct nvkm_mmu_func { + void *(*dtor)(struct nvkm_mmu *); + int (*oneinit)(struct nvkm_mmu *); + void (*init)(struct nvkm_mmu *); + + u64 limit; + u8 dma_bits; + u32 pgt_bits; + u8 spg_shift; + u8 lpg_shift; + + int (*create)(struct nvkm_mmu *, u64 offset, u64 length, u64 mm_offset, + struct lock_class_key *, struct nvkm_vm **); + + void (*map_pgt)(struct nvkm_gpuobj *pgd, u32 pde, + struct nvkm_memory *pgt[2]); + void (*map)(struct nvkm_vma *, struct nvkm_memory *, + struct nvkm_mem *, u32 pte, u32 cnt, + u64 phys, u64 delta); + void (*map_sg)(struct nvkm_vma *, struct nvkm_memory *, + struct nvkm_mem *, u32 pte, u32 cnt, dma_addr_t *); + void (*unmap)(struct nvkm_vma *, struct nvkm_memory *pgt, + u32 pte, u32 cnt); + void (*flush)(struct nvkm_vm *); +}; + +int nvkm_vm_create(struct nvkm_mmu *, u64, u64, u64, u32, + struct lock_class_key *, struct nvkm_vm **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c index 0ca9dcabb..9700a7625 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c @@ -23,14 +23,13 @@ */ #include "mxms.h" -#include #include #include #include #include static bool -mxm_shadow_rom_fetch(struct nvkm_i2c_port *i2c, u8 addr, +mxm_shadow_rom_fetch(struct nvkm_i2c_bus *bus, u8 addr, u8 offset, u8 size, u8 *data) { struct i2c_msg msgs[] = { @@ -38,27 +37,28 @@ mxm_shadow_rom_fetch(struct nvkm_i2c_port *i2c, u8 addr, { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, }, }; - return i2c_transfer(&i2c->adapter, msgs, 2) == 2; + return i2c_transfer(&bus->i2c, msgs, 2) == 2; } static bool mxm_shadow_rom(struct nvkm_mxm *mxm, u8 version) { - struct nvkm_bios *bios = nvkm_bios(mxm); - struct nvkm_i2c *i2c = nvkm_i2c(mxm); - struct nvkm_i2c_port *port = NULL; + struct nvkm_device *device = mxm->subdev.device; + struct nvkm_bios *bios = device->bios; + struct nvkm_i2c *i2c = device->i2c; + struct nvkm_i2c_bus *bus = NULL; u8 i2cidx, mxms[6], addr, size; i2cidx = mxm_ddc_map(bios, 1 /* LVDS_DDC */) & 0x0f; if (i2cidx < 0x0f) - port = i2c->find(i2c, i2cidx); - if (!port) + bus = nvkm_i2c_bus_find(i2c, i2cidx); + if (!bus) return false; addr = 0x54; - if (!mxm_shadow_rom_fetch(port, addr, 0, 6, mxms)) { + if (!mxm_shadow_rom_fetch(bus, addr, 0, 6, mxms)) { addr = 0x56; - if (!mxm_shadow_rom_fetch(port, addr, 0, 6, mxms)) + if (!mxm_shadow_rom_fetch(bus, addr, 0, 6, mxms)) return false; } @@ -67,7 +67,7 @@ mxm_shadow_rom(struct nvkm_mxm *mxm, u8 version) mxm->mxms = kmalloc(size, GFP_KERNEL); if (mxm->mxms && - mxm_shadow_rom_fetch(port, addr, 0, size, mxm->mxms)) + mxm_shadow_rom_fetch(bus, addr, 0, size, mxm->mxms)) return true; kfree(mxm->mxms); @@ -79,7 +79,8 @@ mxm_shadow_rom(struct nvkm_mxm *mxm, u8 version) static bool mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version) { - struct nvkm_device *device = nv_device(mxm); + struct nvkm_subdev *subdev = &mxm->subdev; + struct nvkm_device *device = subdev->device; static char muid[] = { 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 @@ -94,7 +95,7 @@ mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version) acpi_handle handle; int rev; - handle = ACPI_HANDLE(nv_device_base(device)); + handle = ACPI_HANDLE(device->dev); if (!handle) return false; @@ -106,7 +107,7 @@ mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version) rev = (version & 0xf0) << 4 | (version & 0x0f); obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4); if (!obj) { - nv_debug(mxm, "DSM MXMS failed\n"); + nvkm_debug(subdev, "DSM MXMS failed\n"); return false; } @@ -114,7 +115,8 @@ mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version) mxm->mxms = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); } else if (obj->type == ACPI_TYPE_INTEGER) { - nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); + nvkm_debug(subdev, "DSM MXMS returned 0x%llx\n", + obj->integer.value); } ACPI_FREE(obj); @@ -129,6 +131,7 @@ mxm_shadow_dsm(struct nvkm_mxm *mxm, u8 version) static u8 wmi_wmmx_mxmi(struct nvkm_mxm *mxm, u8 version) { + struct nvkm_subdev *subdev = &mxm->subdev; u32 mxmi_args[] = { 0x494D584D /* MXMI */, version, 0 }; struct acpi_buffer args = { sizeof(mxmi_args), mxmi_args }; struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -137,18 +140,18 @@ wmi_wmmx_mxmi(struct nvkm_mxm *mxm, u8 version) status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); if (ACPI_FAILURE(status)) { - nv_debug(mxm, "WMMX MXMI returned %d\n", status); + nvkm_debug(subdev, "WMMX MXMI returned %d\n", status); return 0x00; } obj = retn.pointer; if (obj->type == ACPI_TYPE_INTEGER) { version = obj->integer.value; - nv_debug(mxm, "WMMX MXMI version %d.%d\n", - (version >> 4), version & 0x0f); + nvkm_debug(subdev, "WMMX MXMI version %d.%d\n", + (version >> 4), version & 0x0f); } else { version = 0; - nv_debug(mxm, "WMMX MXMI returned non-integer\n"); + nvkm_debug(subdev, "WMMX MXMI returned non-integer\n"); } kfree(obj); @@ -158,6 +161,7 @@ wmi_wmmx_mxmi(struct nvkm_mxm *mxm, u8 version) static bool mxm_shadow_wmi(struct nvkm_mxm *mxm, u8 version) { + struct nvkm_subdev *subdev = &mxm->subdev; u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 }; struct acpi_buffer args = { sizeof(mxms_args), mxms_args }; struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -165,7 +169,7 @@ mxm_shadow_wmi(struct nvkm_mxm *mxm, u8 version) acpi_status status; if (!wmi_has_guid(WMI_WMMX_GUID)) { - nv_debug(mxm, "WMMX GUID not found\n"); + nvkm_debug(subdev, "WMMX GUID not found\n"); return false; } @@ -177,7 +181,7 @@ mxm_shadow_wmi(struct nvkm_mxm *mxm, u8 version) status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); if (ACPI_FAILURE(status)) { - nv_debug(mxm, "WMMX MXMS returned %d\n", status); + nvkm_debug(subdev, "WMMX MXMS returned %d\n", status); return false; } @@ -211,7 +215,7 @@ mxm_shadow(struct nvkm_mxm *mxm, u8 version) { struct mxm_shadow_h *shadow = _mxm_shadow; do { - nv_debug(mxm, "checking %s\n", shadow->name); + nvkm_debug(&mxm->subdev, "checking %s\n", shadow->name); if (shadow->exec(mxm, version)) { if (mxms_valid(mxm)) return 0; @@ -222,33 +226,33 @@ mxm_shadow(struct nvkm_mxm *mxm, u8 version) return -ENOENT; } +static const struct nvkm_subdev_func +nvkm_mxm = { +}; + int -nvkm_mxm_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +nvkm_mxm_new_(struct nvkm_device *device, int index, struct nvkm_mxm **pmxm) { - struct nvkm_device *device = nv_device(parent); - struct nvkm_bios *bios = nvkm_bios(device); + struct nvkm_bios *bios = device->bios; struct nvkm_mxm *mxm; u8 ver, len; u16 data; - int ret; - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "MXM", "mxm", - length, pobject); - mxm = *pobject; - if (ret) - return ret; + if (!(mxm = *pmxm = kzalloc(sizeof(*mxm), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_mxm, device, index, 0, &mxm->subdev); data = mxm_table(bios, &ver, &len); - if (!data || !(ver = nv_ro08(bios, data))) { - nv_debug(mxm, "no VBIOS data, nothing to do\n"); + if (!data || !(ver = nvbios_rd08(bios, data))) { + nvkm_debug(&mxm->subdev, "no VBIOS data, nothing to do\n"); return 0; } - nv_info(mxm, "BIOS version %d.%d\n", ver >> 4, ver & 0x0f); + nvkm_info(&mxm->subdev, "BIOS version %d.%d\n", ver >> 4, ver & 0x0f); if (mxm_shadow(mxm, ver)) { - nv_info(mxm, "failed to locate valid SIS\n"); + nvkm_warn(&mxm->subdev, "failed to locate valid SIS\n"); #if 0 /* we should, perhaps, fall back to some kind of limited * mode here if the x86 vbios hasn't already done the @@ -261,8 +265,8 @@ nvkm_mxm_create_(struct nvkm_object *parent, struct nvkm_object *engine, #endif } - nv_info(mxm, "MXMS Version %d.%d\n", - mxms_version(mxm) >> 8, mxms_version(mxm) & 0xff); + nvkm_debug(&mxm->subdev, "MXMS Version %d.%d\n", + mxms_version(mxm) >> 8, mxms_version(mxm) & 0xff); mxms_foreach(mxm, 0, NULL, NULL); if (nvkm_boolopt(device->cfgopt, "NvMXMDCB", true)) diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c index a9b1d63fe..45a2f8e78 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c @@ -47,7 +47,7 @@ mxms_version(struct nvkm_mxm *mxm) break; } - nv_debug(mxm, "unknown version %d.%d\n", mxms[4], mxms[5]); + nvkm_debug(&mxm->subdev, "unknown version %d.%d\n", mxms[4], mxms[5]); return 0x0000; } @@ -71,7 +71,7 @@ mxms_checksum(struct nvkm_mxm *mxm) while (size--) sum += *mxms++; if (sum) { - nv_debug(mxm, "checksum invalid\n"); + nvkm_debug(&mxm->subdev, "checksum invalid\n"); return false; } return true; @@ -82,7 +82,7 @@ mxms_valid(struct nvkm_mxm *mxm) { u8 *mxms = mxms_data(mxm); if (*(u32 *)mxms != 0x5f4d584d) { - nv_debug(mxm, "signature invalid\n"); + nvkm_debug(&mxm->subdev, "signature invalid\n"); return false; } @@ -96,6 +96,7 @@ bool mxms_foreach(struct nvkm_mxm *mxm, u8 types, bool (*exec)(struct nvkm_mxm *, u8 *, void *), void *info) { + struct nvkm_subdev *subdev = &mxm->subdev; u8 *mxms = mxms_data(mxm); u8 *desc = mxms + mxms_headerlen(mxm); u8 *fini = desc + mxms_structlen(mxm) - 1; @@ -140,29 +141,28 @@ mxms_foreach(struct nvkm_mxm *mxm, u8 types, entries = desc[1] & 0x07; break; default: - nv_debug(mxm, "unknown descriptor type %d\n", type); + nvkm_debug(subdev, "unknown descriptor type %d\n", type); return false; } - if (nv_subdev(mxm)->debug >= NV_DBG_DEBUG && (exec == NULL)) { - static const char * mxms_desc_name[] = { + if (mxm->subdev.debug >= NV_DBG_DEBUG && (exec == NULL)) { + static const char * mxms_desc[] = { "ODS", "SCCS", "TS", "IPS", "GSD", "VSS", "BCS", "FCS", }; u8 *dump = desc; + char data[32], *ptr; int i, j; - nv_debug(mxm, "%4s: ", mxms_desc_name[type]); - for (j = headerlen - 1; j >= 0; j--) - pr_cont("%02x", dump[j]); - pr_cont("\n"); + for (j = headerlen - 1, ptr = data; j >= 0; j--) + ptr += sprintf(ptr, "%02x", dump[j]); dump += headerlen; + nvkm_debug(subdev, "%4s: %s\n", mxms_desc[type], data); for (i = 0; i < entries; i++, dump += recordlen) { - nv_debug(mxm, " "); - for (j = recordlen - 1; j >= 0; j--) - pr_cont("%02x", dump[j]); - pr_cont("\n"); + for (j = recordlen - 1, ptr = data; j >= 0; j--) + ptr += sprintf(ptr, "%02x", dump[j]); + nvkm_debug(subdev, " %s\n", data); } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h index 4ef804012..333e0c015 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h @@ -1,6 +1,6 @@ #ifndef __NVMXM_MXMS_H__ #define __NVMXM_MXMS_H__ -#include +#include "priv.h" struct mxms_odev { u8 outp_type; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c index f20e4ca87..db14fad2d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c @@ -28,10 +28,6 @@ #include #include -struct nv50_mxm_priv { - struct nvkm_mxm base; -}; - struct context { u32 *outp; struct mxms_odev desc; @@ -53,7 +49,7 @@ mxm_match_tmds_partner(struct nvkm_mxm *mxm, u8 *data, void *info) static bool mxm_match_dcb(struct nvkm_mxm *mxm, u8 *data, void *info) { - struct nvkm_bios *bios = nvkm_bios(mxm); + struct nvkm_bios *bios = mxm->subdev.device->bios; struct context *ctx = info; u64 desc = *(u64 *)data; @@ -107,8 +103,8 @@ mxm_dcb_sanitise_entry(struct nvkm_bios *bios, void *data, int idx, u16 pdcb) * if one isn't found, disable it. */ if (mxms_foreach(mxm, 0x01, mxm_match_dcb, &ctx)) { - nv_debug(mxm, "disable %d: 0x%08x 0x%08x\n", - idx, ctx.outp[0], ctx.outp[1]); + nvkm_debug(&mxm->subdev, "disable %d: %08x %08x\n", + idx, ctx.outp[0], ctx.outp[1]); ctx.outp[0] |= 0x0000000f; return 0; } @@ -180,20 +176,22 @@ mxm_dcb_sanitise_entry(struct nvkm_bios *bios, void *data, int idx, u16 pdcb) static bool mxm_show_unmatched(struct nvkm_mxm *mxm, u8 *data, void *info) { + struct nvkm_subdev *subdev = &mxm->subdev; u64 desc = *(u64 *)data; if ((desc & 0xf0) != 0xf0) - nv_info(mxm, "unmatched output device 0x%016llx\n", desc); + nvkm_info(subdev, "unmatched output device %016llx\n", desc); return true; } static void mxm_dcb_sanitise(struct nvkm_mxm *mxm) { - struct nvkm_bios *bios = nvkm_bios(mxm); + struct nvkm_subdev *subdev = &mxm->subdev; + struct nvkm_bios *bios = subdev->device->bios; u8 ver, hdr, cnt, len; u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); if (dcb == 0x0000 || ver != 0x40) { - nv_debug(mxm, "unsupported DCB version\n"); + nvkm_debug(subdev, "unsupported DCB version\n"); return; } @@ -201,31 +199,20 @@ mxm_dcb_sanitise(struct nvkm_mxm *mxm) mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL); } -static int -nv50_mxm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv50_mxm_new(struct nvkm_device *device, int index, struct nvkm_subdev **pmxm) { - struct nv50_mxm_priv *priv; + struct nvkm_mxm *mxm; int ret; - ret = nvkm_mxm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); + ret = nvkm_mxm_new_(device, index, &mxm); + if (mxm) + *pmxm = &mxm->subdev; if (ret) return ret; - if (priv->base.action & MXM_SANITISE_DCB) - mxm_dcb_sanitise(&priv->base); + if (mxm->action & MXM_SANITISE_DCB) + mxm_dcb_sanitise(mxm); + return 0; } - -struct nvkm_oclass -nv50_mxm_oclass = { - .handle = NV_SUBDEV(MXM, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_mxm_ctor, - .dtor = _nvkm_mxm_dtor, - .init = _nvkm_mxm_init, - .fini = _nvkm_mxm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h new file mode 100644 index 000000000..7d970157a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h @@ -0,0 +1,15 @@ +#ifndef __NVKM_MXM_PRIV_H__ +#define __NVKM_MXM_PRIV_H__ +#define nvkm_mxm(p) container_of((p), struct nvkm_mxm, subdev) +#include + +#define MXM_SANITISE_DCB 0x00000001 + +struct nvkm_mxm { + struct nvkm_subdev subdev; + u32 action; + u8 *mxms; +}; + +int nvkm_mxm_new_(struct nvkm_device *, int index, struct nvkm_mxm **); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild new file mode 100644 index 000000000..4476ef75a --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild @@ -0,0 +1,9 @@ +nvkm-y += nvkm/subdev/pci/agp.o +nvkm-y += nvkm/subdev/pci/base.o +nvkm-y += nvkm/subdev/pci/nv04.o +nvkm-y += nvkm/subdev/pci/nv40.o +nvkm-y += nvkm/subdev/pci/nv46.o +nvkm-y += nvkm/subdev/pci/nv4c.o +nvkm-y += nvkm/subdev/pci/g84.o +nvkm-y += nvkm/subdev/pci/g94.o +nvkm-y += nvkm/subdev/pci/gf100.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c new file mode 100644 index 000000000..385a90f91 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c @@ -0,0 +1,175 @@ +/* + * Copyright 2015 Nouveau Project + * + * 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 "agp.h" +#ifdef __NVKM_PCI_AGP_H__ +#include + +struct nvkm_device_agp_quirk { + u16 hostbridge_vendor; + u16 hostbridge_device; + u16 chip_vendor; + u16 chip_device; + int mode; +}; + +static const struct nvkm_device_agp_quirk +nvkm_device_agp_quirks[] = { + /* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */ + { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, + /* SiS 761 does not support AGP cards, use PCI mode */ + { PCI_VENDOR_ID_SI, 0x0761, PCI_ANY_ID, PCI_ANY_ID, 0 }, + {}, +}; + +void +nvkm_agp_fini(struct nvkm_pci *pci) +{ + if (pci->agp.acquired) { + agp_backend_release(pci->agp.bridge); + pci->agp.acquired = false; + } +} + +/* Ensure AGP controller is in a consistent state in case we need to + * execute the VBIOS DEVINIT scripts. + */ +void +nvkm_agp_preinit(struct nvkm_pci *pci) +{ + struct nvkm_device *device = pci->subdev.device; + u32 mode = nvkm_pci_rd32(pci, 0x004c); + u32 save[2]; + + /* First of all, disable fast writes, otherwise if it's already + * enabled in the AGP bridge and we disable the card's AGP + * controller we might be locking ourselves out of it. + */ + if ((mode | pci->agp.mode) & PCI_AGP_COMMAND_FW) { + mode = pci->agp.mode & ~PCI_AGP_COMMAND_FW; + agp_enable(pci->agp.bridge, mode); + } + + /* clear busmaster bit, and disable AGP */ + save[0] = nvkm_pci_rd32(pci, 0x0004); + nvkm_pci_wr32(pci, 0x0004, save[0] & ~0x00000004); + nvkm_pci_wr32(pci, 0x004c, 0x00000000); + + /* reset PGRAPH, PFIFO and PTIMER */ + save[1] = nvkm_mask(device, 0x000200, 0x00011100, 0x00000000); + nvkm_mask(device, 0x000200, 0x00011100, save[1]); + + /* and restore busmaster bit (gives effect of resetting AGP) */ + nvkm_pci_wr32(pci, 0x0004, save[0]); +} + +int +nvkm_agp_init(struct nvkm_pci *pci) +{ + if (!agp_backend_acquire(pci->pdev)) { + nvkm_error(&pci->subdev, "failed to acquire agp\n"); + return -ENODEV; + } + + agp_enable(pci->agp.bridge, pci->agp.mode); + pci->agp.acquired = true; + return 0; +} + +void +nvkm_agp_dtor(struct nvkm_pci *pci) +{ + arch_phys_wc_del(pci->agp.mtrr); +} + +void +nvkm_agp_ctor(struct nvkm_pci *pci) +{ + const struct nvkm_device_agp_quirk *quirk = nvkm_device_agp_quirks; + struct nvkm_subdev *subdev = &pci->subdev; + struct nvkm_device *device = subdev->device; + struct agp_kern_info info; + int mode = -1; + +#ifdef __powerpc__ + /* Disable AGP by default on all PowerPC machines for now -- At + * least some UniNorth-2 AGP bridges are known to be broken: + * DMA from the host to the card works just fine, but writeback + * from the card to the host goes straight to memory + * untranslated bypassing that GATT somehow, making them quite + * painful to deal with... + */ + mode = 0; +#endif + mode = nvkm_longopt(device->cfgopt, "NvAGP", mode); + + /* acquire bridge temporarily, so that we can copy its info */ + if (!(pci->agp.bridge = agp_backend_acquire(pci->pdev))) { + nvkm_warn(subdev, "failed to acquire agp\n"); + return; + } + agp_copy_info(pci->agp.bridge, &info); + agp_backend_release(pci->agp.bridge); + + pci->agp.mode = info.mode; + pci->agp.base = info.aper_base; + pci->agp.size = info.aper_size * 1024 * 1024; + pci->agp.cma = info.cant_use_aperture; + pci->agp.mtrr = -1; + + /* determine if bridge + chipset combination needs a workaround */ + while (quirk->hostbridge_vendor) { + if (info.device->vendor == quirk->hostbridge_vendor && + info.device->device == quirk->hostbridge_device && + (quirk->chip_vendor == (u16)PCI_ANY_ID || + pci->pdev->vendor == quirk->chip_vendor) && + (quirk->chip_device == (u16)PCI_ANY_ID || + pci->pdev->device == quirk->chip_device)) { + nvkm_info(subdev, "forcing default agp mode to %dX, " + "use NvAGP= to override\n", + quirk->mode); + mode = quirk->mode; + break; + } + quirk++; + } + + /* apply quirk / user-specified mode */ + if (mode >= 1) { + if (pci->agp.mode & 0x00000008) + mode /= 4; /* AGPv3 */ + pci->agp.mode &= ~0x00000007; + pci->agp.mode |= (mode & 0x7); + } else + if (mode == 0) { + pci->agp.bridge = NULL; + return; + } + + /* fast writes appear to be broken on nv18, they make the card + * lock up randomly. + */ + if (device->chipset == 0x18) + pci->agp.mode &= ~PCI_AGP_COMMAND_FW; + + pci->agp.mtrr = arch_phys_wc_add(pci->agp.base, pci->agp.size); +} +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h new file mode 100644 index 000000000..df2dd0836 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h @@ -0,0 +1,18 @@ +#include "priv.h" +#if defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)) +#ifndef __NVKM_PCI_AGP_H__ +#define __NVKM_PCI_AGP_H__ + +void nvkm_agp_ctor(struct nvkm_pci *); +void nvkm_agp_dtor(struct nvkm_pci *); +void nvkm_agp_preinit(struct nvkm_pci *); +int nvkm_agp_init(struct nvkm_pci *); +void nvkm_agp_fini(struct nvkm_pci *); +#endif +#else +static inline void nvkm_agp_ctor(struct nvkm_pci *pci) {} +static inline void nvkm_agp_dtor(struct nvkm_pci *pci) {} +static inline void nvkm_agp_preinit(struct nvkm_pci *pci) {} +static inline int nvkm_agp_init(struct nvkm_pci *pci) { return -ENOSYS; } +static inline void nvkm_agp_fini(struct nvkm_pci *pci) {} +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c new file mode 100644 index 000000000..d671dcfaf --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c @@ -0,0 +1,193 @@ +/* + * 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 + */ +#include "priv.h" +#include "agp.h" + +#include +#include +#include + +u32 +nvkm_pci_rd32(struct nvkm_pci *pci, u16 addr) +{ + return pci->func->rd32(pci, addr); +} + +void +nvkm_pci_wr08(struct nvkm_pci *pci, u16 addr, u8 data) +{ + pci->func->wr08(pci, addr, data); +} + +void +nvkm_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data) +{ + pci->func->wr32(pci, addr, data); +} + +u32 +nvkm_pci_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32 value) +{ + u32 data = pci->func->rd32(pci, addr); + pci->func->wr32(pci, addr, (data & ~mask) | value); + return data; +} + +void +nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) +{ + u32 data = nvkm_pci_rd32(pci, 0x0050); + if (shadow) + data |= 0x00000001; + else + data &= ~0x00000001; + nvkm_pci_wr32(pci, 0x0050, data); +} + +static irqreturn_t +nvkm_pci_intr(int irq, void *arg) +{ + struct nvkm_pci *pci = arg; + struct nvkm_mc *mc = pci->subdev.device->mc; + bool handled = false; + if (likely(mc)) { + nvkm_mc_intr_unarm(mc); + if (pci->msi) + pci->func->msi_rearm(pci); + nvkm_mc_intr(mc, &handled); + nvkm_mc_intr_rearm(mc); + } + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static int +nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) +{ + struct nvkm_pci *pci = nvkm_pci(subdev); + + if (pci->irq >= 0) { + free_irq(pci->irq, pci); + pci->irq = -1; + }; + + if (pci->agp.bridge) + nvkm_agp_fini(pci); + + return 0; +} + +static int +nvkm_pci_preinit(struct nvkm_subdev *subdev) +{ + struct nvkm_pci *pci = nvkm_pci(subdev); + if (pci->agp.bridge) + nvkm_agp_preinit(pci); + return 0; +} + +static int +nvkm_pci_init(struct nvkm_subdev *subdev) +{ + struct nvkm_pci *pci = nvkm_pci(subdev); + struct pci_dev *pdev = pci->pdev; + int ret; + + if (pci->agp.bridge) { + ret = nvkm_agp_init(pci); + if (ret) + return ret; + } + + if (pci->func->init) + pci->func->init(pci); + + ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); + if (ret) + return ret; + + pci->irq = pdev->irq; + return ret; +} + +static void * +nvkm_pci_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_pci *pci = nvkm_pci(subdev); + nvkm_agp_dtor(pci); + if (pci->msi) + pci_disable_msi(pci->pdev); + return nvkm_pci(subdev); +} + +static const struct nvkm_subdev_func +nvkm_pci_func = { + .dtor = nvkm_pci_dtor, + .preinit = nvkm_pci_preinit, + .init = nvkm_pci_init, + .fini = nvkm_pci_fini, +}; + +int +nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device, + int index, struct nvkm_pci **ppci) +{ + struct nvkm_pci *pci; + + if (!(pci = *ppci = kzalloc(sizeof(**ppci), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_pci_func, device, index, 0, &pci->subdev); + pci->func = func; + pci->pdev = device->func->pci(device)->pdev; + pci->irq = -1; + + if (device->type == NVKM_DEVICE_AGP) + nvkm_agp_ctor(pci); + + switch (pci->pdev->device & 0x0ff0) { + case 0x00f0: + case 0x02e0: + /* BR02? NFI how these would be handled yet exactly */ + break; + default: + switch (device->chipset) { + case 0xaa: + /* reported broken, nv also disable it */ + break; + default: + pci->msi = true; + break; + } + } + + pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi); + if (pci->msi && func->msi_rearm) { + pci->msi = pci_enable_msi(pci->pdev) == 0; + if (pci->msi) + nvkm_debug(&pci->subdev, "MSI enabled\n"); + } else { + pci->msi = false; + } + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c new file mode 100644 index 000000000..3faa6bfb8 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c @@ -0,0 +1,64 @@ +/* + * 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 + */ +#include "priv.h" + +#include + +void +g84_pci_init(struct nvkm_pci *pci) +{ + /* The following only concerns PCIe cards. */ + if (!pci_is_pcie(pci->pdev)) + return; + + /* Tag field is 8-bit long, regardless of EXT_TAG. + * However, if EXT_TAG is disabled, only the lower 5 bits of the tag + * field should be used, limiting the number of request to 32. + * + * Apparently, 0x041c stores some limit on the number of requests + * possible, so if EXT_TAG is disabled, limit that requests number to + * 32 + * + * Fixes fdo#86537 + */ + if (nvkm_pci_rd32(pci, 0x007c) & 0x00000020) + nvkm_pci_mask(pci, 0x0080, 0x00000100, 0x00000100); + else + nvkm_pci_mask(pci, 0x041c, 0x00000060, 0x00000000); +} + +static const struct nvkm_pci_func +g84_pci_func = { + .init = g84_pci_init, + .rd32 = nv40_pci_rd32, + .wr08 = nv40_pci_wr08, + .wr32 = nv40_pci_wr32, + .msi_rearm = nv46_pci_msi_rearm, +}; + +int +g84_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&g84_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c new file mode 100644 index 000000000..cd311ee31 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c @@ -0,0 +1,39 @@ +/* + * 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 + */ +#include "priv.h" + +static const struct nvkm_pci_func +g94_pci_func = { + .init = g84_pci_init, + .rd32 = nv40_pci_rd32, + .wr08 = nv40_pci_wr08, + .wr32 = nv40_pci_wr32, + .msi_rearm = nv40_pci_msi_rearm, +}; + +int +g94_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&g94_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c new file mode 100644 index 000000000..25e1ae708 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c @@ -0,0 +1,45 @@ +/* + * 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 + */ +#include "priv.h" + +static void +gf100_pci_msi_rearm(struct nvkm_pci *pci) +{ + nvkm_pci_wr08(pci, 0x0704, 0xff); +} + +static const struct nvkm_pci_func +gf100_pci_func = { + .init = g84_pci_init, + .rd32 = nv40_pci_rd32, + .wr08 = nv40_pci_wr08, + .wr32 = nv40_pci_wr32, + .msi_rearm = gf100_pci_msi_rearm, +}; + +int +gf100_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&gf100_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv04.c new file mode 100644 index 000000000..5b1ed42cb --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv04.c @@ -0,0 +1,58 @@ +/* + * 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 + */ +#include "priv.h" + +static u32 +nv04_pci_rd32(struct nvkm_pci *pci, u16 addr) +{ + struct nvkm_device *device = pci->subdev.device; + return nvkm_rd32(device, 0x001800 + addr); +} + +static void +nv04_pci_wr08(struct nvkm_pci *pci, u16 addr, u8 data) +{ + struct nvkm_device *device = pci->subdev.device; + nvkm_wr08(device, 0x001800 + addr, data); +} + +static void +nv04_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data) +{ + struct nvkm_device *device = pci->subdev.device; + nvkm_wr32(device, 0x001800 + addr, data); +} + +static const struct nvkm_pci_func +nv04_pci_func = { + .rd32 = nv04_pci_rd32, + .wr08 = nv04_pci_wr08, + .wr32 = nv04_pci_wr32, +}; + +int +nv04_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&nv04_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c new file mode 100644 index 000000000..6eb417765 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c @@ -0,0 +1,65 @@ +/* + * 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 + */ +#include "priv.h" + +u32 +nv40_pci_rd32(struct nvkm_pci *pci, u16 addr) +{ + struct nvkm_device *device = pci->subdev.device; + return nvkm_rd32(device, 0x088000 + addr); +} + +void +nv40_pci_wr08(struct nvkm_pci *pci, u16 addr, u8 data) +{ + struct nvkm_device *device = pci->subdev.device; + nvkm_wr08(device, 0x088000 + addr, data); +} + +void +nv40_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data) +{ + struct nvkm_device *device = pci->subdev.device; + nvkm_wr32(device, 0x088000 + addr, data); +} + +void +nv40_pci_msi_rearm(struct nvkm_pci *pci) +{ + nvkm_pci_wr08(pci, 0x0068, 0xff); +} + +static const struct nvkm_pci_func +nv40_pci_func = { + .rd32 = nv40_pci_rd32, + .wr08 = nv40_pci_wr08, + .wr32 = nv40_pci_wr32, + .msi_rearm = nv40_pci_msi_rearm, +}; + +int +nv40_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&nv40_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c new file mode 100644 index 000000000..fc617e4c0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c @@ -0,0 +1,51 @@ +/* + * 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 + */ +#include "priv.h" + +#include + +/* MSI re-arm through the PRI appears to be broken on NV46/NV50/G84/G86/G92, + * so we access it via alternate PCI config space mechanisms. + */ +void +nv46_pci_msi_rearm(struct nvkm_pci *pci) +{ + struct nvkm_device *device = pci->subdev.device; + struct pci_dev *pdev = device->func->pci(device)->pdev; + pci_write_config_byte(pdev, 0x68, 0xff); +} + +static const struct nvkm_pci_func +nv46_pci_func = { + .rd32 = nv40_pci_rd32, + .wr08 = nv40_pci_wr08, + .wr32 = nv40_pci_wr32, + .msi_rearm = nv46_pci_msi_rearm, +}; + +int +nv46_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&nv46_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv4c.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv4c.c new file mode 100644 index 000000000..1f1b26b5f --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv4c.c @@ -0,0 +1,37 @@ +/* + * 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 + */ +#include "priv.h" + +static const struct nvkm_pci_func +nv4c_pci_func = { + .rd32 = nv40_pci_rd32, + .wr08 = nv40_pci_wr08, + .wr32 = nv40_pci_wr32, +}; + +int +nv4c_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) +{ + return nvkm_pci_new_(&nv4c_pci_func, device, index, ppci); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h new file mode 100644 index 000000000..cf46d38d0 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h @@ -0,0 +1,25 @@ +#ifndef __NVKM_PCI_PRIV_H__ +#define __NVKM_PCI_PRIV_H__ +#define nvkm_pci(p) container_of((p), struct nvkm_pci, subdev) +#include + +int nvkm_pci_new_(const struct nvkm_pci_func *, struct nvkm_device *, + int index, struct nvkm_pci **); + +struct nvkm_pci_func { + void (*init)(struct nvkm_pci *); + u32 (*rd32)(struct nvkm_pci *, u16 addr); + void (*wr08)(struct nvkm_pci *, u16 addr, u8 data); + void (*wr32)(struct nvkm_pci *, u16 addr, u32 data); + void (*msi_rearm)(struct nvkm_pci *); +}; + +u32 nv40_pci_rd32(struct nvkm_pci *, u16); +void nv40_pci_wr08(struct nvkm_pci *, u16, u8); +void nv40_pci_wr32(struct nvkm_pci *, u16, u32); +void nv40_pci_msi_rearm(struct nvkm_pci *); + +void nv46_pci_msi_rearm(struct nvkm_pci *); + +void g84_pci_init(struct nvkm_pci *pci); +#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild index 7081d6a9b..88b643b86 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild @@ -2,8 +2,9 @@ nvkm-y += nvkm/subdev/pmu/base.o nvkm-y += nvkm/subdev/pmu/memx.o nvkm-y += nvkm/subdev/pmu/gt215.o nvkm-y += nvkm/subdev/pmu/gf100.o -nvkm-y += nvkm/subdev/pmu/gf110.o +nvkm-y += nvkm/subdev/pmu/gf119.o nvkm-y += nvkm/subdev/pmu/gk104.o nvkm-y += nvkm/subdev/pmu/gk110.o nvkm-y += nvkm/subdev/pmu/gk208.o nvkm-y += nvkm/subdev/pmu/gk20a.o +nvkm-y += nvkm/subdev/pmu/gm107.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 054b2d2ee..d95eb8659 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -28,21 +28,25 @@ void nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable) { - const struct nvkm_pmu_impl *impl = (void *)nv_oclass(pmu); - if (impl->pgob) - impl->pgob(pmu, enable); + if (pmu && pmu->func->pgob) + pmu->func->pgob(pmu, enable); } -static int +int nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2], u32 process, u32 message, u32 data0, u32 data1) { - struct nvkm_subdev *subdev = nv_subdev(pmu); + struct nvkm_subdev *subdev = &pmu->subdev; + struct nvkm_device *device = subdev->device; u32 addr; /* wait for a free slot in the fifo */ - addr = nv_rd32(pmu, 0x10a4a0); - if (!nv_wait_ne(pmu, 0x10a4b0, 0xffffffff, addr ^ 8)) + addr = nvkm_rd32(device, 0x10a4a0); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x10a4b0); + if (tmp != (addr ^ 8)) + break; + ) < 0) return -EBUSY; /* we currently only support a single process at a time waiting @@ -57,20 +61,20 @@ nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2], /* acquire data segment access */ do { - nv_wr32(pmu, 0x10a580, 0x00000001); - } while (nv_rd32(pmu, 0x10a580) != 0x00000001); + nvkm_wr32(device, 0x10a580, 0x00000001); + } while (nvkm_rd32(device, 0x10a580) != 0x00000001); /* write the packet */ - nv_wr32(pmu, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) + + nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) + pmu->send.base)); - nv_wr32(pmu, 0x10a1c4, process); - nv_wr32(pmu, 0x10a1c4, message); - nv_wr32(pmu, 0x10a1c4, data0); - nv_wr32(pmu, 0x10a1c4, data1); - nv_wr32(pmu, 0x10a4a0, (addr + 1) & 0x0f); + nvkm_wr32(device, 0x10a1c4, process); + nvkm_wr32(device, 0x10a1c4, message); + nvkm_wr32(device, 0x10a1c4, data0); + nvkm_wr32(device, 0x10a1c4, data1); + nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f); /* release data segment access */ - nv_wr32(pmu, 0x10a580, 0x00000000); + nvkm_wr32(device, 0x10a580, 0x00000000); /* wait for reply, if requested */ if (reply) { @@ -87,29 +91,31 @@ static void nvkm_pmu_recv(struct work_struct *work) { struct nvkm_pmu *pmu = container_of(work, struct nvkm_pmu, recv.work); + struct nvkm_subdev *subdev = &pmu->subdev; + struct nvkm_device *device = subdev->device; u32 process, message, data0, data1; /* nothing to do if GET == PUT */ - u32 addr = nv_rd32(pmu, 0x10a4cc); - if (addr == nv_rd32(pmu, 0x10a4c8)) + u32 addr = nvkm_rd32(device, 0x10a4cc); + if (addr == nvkm_rd32(device, 0x10a4c8)) return; /* acquire data segment access */ do { - nv_wr32(pmu, 0x10a580, 0x00000002); - } while (nv_rd32(pmu, 0x10a580) != 0x00000002); + nvkm_wr32(device, 0x10a580, 0x00000002); + } while (nvkm_rd32(device, 0x10a580) != 0x00000002); /* read the packet */ - nv_wr32(pmu, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) + + nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) + pmu->recv.base)); - process = nv_rd32(pmu, 0x10a1c4); - message = nv_rd32(pmu, 0x10a1c4); - data0 = nv_rd32(pmu, 0x10a1c4); - data1 = nv_rd32(pmu, 0x10a1c4); - nv_wr32(pmu, 0x10a4cc, (addr + 1) & 0x0f); + process = nvkm_rd32(device, 0x10a1c4); + message = nvkm_rd32(device, 0x10a1c4); + data0 = nvkm_rd32(device, 0x10a1c4); + data1 = nvkm_rd32(device, 0x10a1c4); + nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f); /* release data segment access */ - nv_wr32(pmu, 0x10a580, 0x00000000); + nvkm_wr32(device, 0x10a580, 0x00000000); /* wake process if it's waiting on a synchronous reply */ if (pmu->recv.process) { @@ -126,143 +132,149 @@ nvkm_pmu_recv(struct work_struct *work) /* right now there's no other expected responses from the engine, * so assume that any unexpected message is an error. */ - nv_warn(pmu, "%c%c%c%c 0x%08x 0x%08x 0x%08x 0x%08x\n", - (char)((process & 0x000000ff) >> 0), - (char)((process & 0x0000ff00) >> 8), - (char)((process & 0x00ff0000) >> 16), - (char)((process & 0xff000000) >> 24), - process, message, data0, data1); + nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n", + (char)((process & 0x000000ff) >> 0), + (char)((process & 0x0000ff00) >> 8), + (char)((process & 0x00ff0000) >> 16), + (char)((process & 0xff000000) >> 24), + process, message, data0, data1); } static void nvkm_pmu_intr(struct nvkm_subdev *subdev) { - struct nvkm_pmu *pmu = (void *)subdev; - u32 disp = nv_rd32(pmu, 0x10a01c); - u32 intr = nv_rd32(pmu, 0x10a008) & disp & ~(disp >> 16); + struct nvkm_pmu *pmu = nvkm_pmu(subdev); + struct nvkm_device *device = pmu->subdev.device; + u32 disp = nvkm_rd32(device, 0x10a01c); + u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16); if (intr & 0x00000020) { - u32 stat = nv_rd32(pmu, 0x10a16c); + u32 stat = nvkm_rd32(device, 0x10a16c); if (stat & 0x80000000) { - nv_error(pmu, "UAS fault at 0x%06x addr 0x%08x\n", - stat & 0x00ffffff, nv_rd32(pmu, 0x10a168)); - nv_wr32(pmu, 0x10a16c, 0x00000000); + nvkm_error(subdev, "UAS fault at %06x addr %08x\n", + stat & 0x00ffffff, + nvkm_rd32(device, 0x10a168)); + nvkm_wr32(device, 0x10a16c, 0x00000000); intr &= ~0x00000020; } } if (intr & 0x00000040) { schedule_work(&pmu->recv.work); - nv_wr32(pmu, 0x10a004, 0x00000040); + nvkm_wr32(device, 0x10a004, 0x00000040); intr &= ~0x00000040; } if (intr & 0x00000080) { - nv_info(pmu, "wr32 0x%06x 0x%08x\n", nv_rd32(pmu, 0x10a7a0), - nv_rd32(pmu, 0x10a7a4)); - nv_wr32(pmu, 0x10a004, 0x00000080); + nvkm_info(subdev, "wr32 %06x %08x\n", + nvkm_rd32(device, 0x10a7a0), + nvkm_rd32(device, 0x10a7a4)); + nvkm_wr32(device, 0x10a004, 0x00000080); intr &= ~0x00000080; } if (intr) { - nv_error(pmu, "intr 0x%08x\n", intr); - nv_wr32(pmu, 0x10a004, intr); + nvkm_error(subdev, "intr %08x\n", intr); + nvkm_wr32(device, 0x10a004, intr); } } -int -_nvkm_pmu_fini(struct nvkm_object *object, bool suspend) +static int +nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) { - struct nvkm_pmu *pmu = (void *)object; + struct nvkm_pmu *pmu = nvkm_pmu(subdev); + struct nvkm_device *device = pmu->subdev.device; - nv_wr32(pmu, 0x10a014, 0x00000060); + nvkm_wr32(device, 0x10a014, 0x00000060); flush_work(&pmu->recv.work); - - return nvkm_subdev_fini(&pmu->base, suspend); + return 0; } -int -_nvkm_pmu_init(struct nvkm_object *object) +static int +nvkm_pmu_init(struct nvkm_subdev *subdev) { - const struct nvkm_pmu_impl *impl = (void *)object->oclass; - struct nvkm_pmu *pmu = (void *)object; - int ret, i; - - ret = nvkm_subdev_init(&pmu->base); - if (ret) - return ret; - - nv_subdev(pmu)->intr = nvkm_pmu_intr; - pmu->message = nvkm_pmu_send; - pmu->pgob = nvkm_pmu_pgob; + struct nvkm_pmu *pmu = nvkm_pmu(subdev); + struct nvkm_device *device = pmu->subdev.device; + int i; /* prevent previous ucode from running, wait for idle, reset */ - nv_wr32(pmu, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */ - nv_wait(pmu, 0x10a04c, 0xffffffff, 0x00000000); - nv_mask(pmu, 0x000200, 0x00002000, 0x00000000); - nv_mask(pmu, 0x000200, 0x00002000, 0x00002000); - nv_rd32(pmu, 0x000200); - nv_wait(pmu, 0x10a10c, 0x00000006, 0x00000000); + nvkm_wr32(device, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */ + nvkm_msec(device, 2000, + if (!nvkm_rd32(device, 0x10a04c)) + break; + ); + nvkm_mask(device, 0x000200, 0x00002000, 0x00000000); + nvkm_mask(device, 0x000200, 0x00002000, 0x00002000); + nvkm_rd32(device, 0x000200); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) + break; + ); /* upload data segment */ - nv_wr32(pmu, 0x10a1c0, 0x01000000); - for (i = 0; i < impl->data.size / 4; i++) - nv_wr32(pmu, 0x10a1c4, impl->data.data[i]); + nvkm_wr32(device, 0x10a1c0, 0x01000000); + for (i = 0; i < pmu->func->data.size / 4; i++) + nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]); /* upload code segment */ - nv_wr32(pmu, 0x10a180, 0x01000000); - for (i = 0; i < impl->code.size / 4; i++) { + nvkm_wr32(device, 0x10a180, 0x01000000); + for (i = 0; i < pmu->func->code.size / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(pmu, 0x10a188, i >> 6); - nv_wr32(pmu, 0x10a184, impl->code.data[i]); + nvkm_wr32(device, 0x10a188, i >> 6); + nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]); } /* start it running */ - nv_wr32(pmu, 0x10a10c, 0x00000000); - nv_wr32(pmu, 0x10a104, 0x00000000); - nv_wr32(pmu, 0x10a100, 0x00000002); + nvkm_wr32(device, 0x10a10c, 0x00000000); + nvkm_wr32(device, 0x10a104, 0x00000000); + nvkm_wr32(device, 0x10a100, 0x00000002); /* wait for valid host->pmu ring configuration */ - if (!nv_wait_ne(pmu, 0x10a4d0, 0xffffffff, 0x00000000)) + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x10a4d0)) + break; + ) < 0) return -EBUSY; - pmu->send.base = nv_rd32(pmu, 0x10a4d0) & 0x0000ffff; - pmu->send.size = nv_rd32(pmu, 0x10a4d0) >> 16; + pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff; + pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16; /* wait for valid pmu->host ring configuration */ - if (!nv_wait_ne(pmu, 0x10a4dc, 0xffffffff, 0x00000000)) + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x10a4dc)) + break; + ) < 0) return -EBUSY; - pmu->recv.base = nv_rd32(pmu, 0x10a4dc) & 0x0000ffff; - pmu->recv.size = nv_rd32(pmu, 0x10a4dc) >> 16; + pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff; + pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16; - nv_wr32(pmu, 0x10a010, 0x000000e0); + nvkm_wr32(device, 0x10a010, 0x000000e0); return 0; } -int -nvkm_pmu_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) +static void * +nvkm_pmu_dtor(struct nvkm_subdev *subdev) { - struct nvkm_pmu *pmu; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PMU", - "pmu", length, pobject); - pmu = *pobject; - if (ret) - return ret; - - INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); - init_waitqueue_head(&pmu->recv.wait); - return 0; + return nvkm_pmu(subdev); } +static const struct nvkm_subdev_func +nvkm_pmu = { + .dtor = nvkm_pmu_dtor, + .init = nvkm_pmu_init, + .fini = nvkm_pmu_fini, + .intr = nvkm_pmu_intr, +}; + int -_nvkm_pmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nvkm_pmu_new_(const struct nvkm_pmu_func *func, struct nvkm_device *device, + int index, struct nvkm_pmu **ppmu) { struct nvkm_pmu *pmu; - int ret = nvkm_pmu_create(parent, engine, oclass, &pmu); - *pobject = nv_object(pmu); - return ret; + if (!(pmu = *ppmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_pmu, device, index, 0, &pmu->subdev); + pmu->func = func; + INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); + init_waitqueue_head(&pmu->recv.wait); + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4 b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4 deleted file mode 100644 index ae9c3f18a..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4 +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013 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 - */ - -#define NVKM_PPWR_CHIPSET GF119 -#define HW_TICKS_PER_US 324 - -//#define NVKM_FALCON_PC24 -#define NVKM_FALCON_UNSHIFTED_IO -//#define NVKM_FALCON_MMIO_UAS -//#define NVKM_FALCON_MMIO_TRAP - -#include "macros.fuc" - -.section #gf110_pmu_data -#define INCLUDE_PROC -#include "kernel.fuc" -#include "arith.fuc" -#include "host.fuc" -#include "memx.fuc" -#include "perf.fuc" -#include "i2c_.fuc" -#include "test.fuc" -#include "idle.fuc" -#undef INCLUDE_PROC - -#define INCLUDE_DATA -#include "kernel.fuc" -#include "arith.fuc" -#include "host.fuc" -#include "memx.fuc" -#include "perf.fuc" -#include "i2c_.fuc" -#include "test.fuc" -#include "idle.fuc" -#undef INCLUDE_DATA -.align 256 - -.section #gf110_pmu_code -#define INCLUDE_CODE -#include "kernel.fuc" -#include "arith.fuc" -#include "host.fuc" -#include "memx.fuc" -#include "perf.fuc" -#include "i2c_.fuc" -#include "test.fuc" -#include "idle.fuc" -#undef INCLUDE_CODE -.align 256 diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4.h deleted file mode 100644 index a0c499e45..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf110.fuc4.h +++ /dev/null @@ -1,1795 +0,0 @@ -uint32_t gf110_pmu_data[] = { -/* 0x0000: proc_kern */ - 0x52544e49, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -/* 0x0058: proc_list_head */ - 0x54534f48, - 0x0000049d, - 0x00000446, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x584d454d, - 0x0000068b, - 0x0000067d, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x46524550, - 0x0000068f, - 0x0000068d, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x5f433249, - 0x00000aaa, - 0x0000094d, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x54534554, - 0x00000acd, - 0x00000aac, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x454c4449, - 0x00000ad9, - 0x00000ad7, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -/* 0x0268: proc_list_tail */ -/* 0x0268: time_prev */ - 0x00000000, -/* 0x026c: time_next */ - 0x00000000, -/* 0x0270: fifo_queue */ - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -/* 0x02f0: rfifo_queue */ - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -/* 0x0370: memx_func_head */ - 0x00000001, - 0x00000000, - 0x000004d3, -/* 0x037c: memx_func_next */ - 0x00000002, - 0x00000000, - 0x00000554, - 0x00000003, - 0x00000002, - 0x000005d8, - 0x00040004, - 0x00000000, - 0x000005f4, - 0x00010005, - 0x00000000, - 0x0000060e, - 0x00010006, - 0x00000000, - 0x000005d3, - 0x00000007, - 0x00000000, - 0x00000619, -/* 0x03c4: memx_func_tail */ -/* 0x03c4: memx_ts_start */ - 0x00000000, -/* 0x03c8: memx_ts_end */ - 0x00000000, -/* 0x03cc: memx_data_head */ - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -/* 0x0bcc: memx_data_tail */ -/* 0x0bcc: memx_train_head */ - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -/* 0x0ccc: memx_train_tail */ -/* 0x0ccc: i2c_scl_map */ - 0x00000400, - 0x00000800, - 0x00001000, - 0x00002000, - 0x00004000, - 0x00008000, - 0x00010000, - 0x00020000, - 0x00040000, - 0x00080000, -/* 0x0cf4: i2c_sda_map */ - 0x00100000, - 0x00200000, - 0x00400000, - 0x00800000, - 0x01000000, - 0x02000000, - 0x04000000, - 0x08000000, - 0x10000000, - 0x20000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -uint32_t gf110_pmu_code[] = { - 0x034d0ef5, -/* 0x0004: rd32 */ - 0x07a007f1, - 0xbd000ed0, - 0x01d7f004, - 0xf101d3f0, - 0xd007ac07, - 0x04bd000d, -/* 0x001c: rd32_wait */ - 0x07acd7f1, - 0xf100ddcf, - 0xf47000d4, - 0xd7f1f51b, - 0xddcf07a4, -/* 0x0033: wr32 */ - 0xf100f800, - 0xd007a007, - 0x04bd000e, - 0x07a407f1, - 0xbd000dd0, - 0x02d7f004, - 0xf0f0d5f0, - 0x07f101d3, - 0x0dd007ac, -/* 0x0057: wr32_wait */ - 0xf104bd00, - 0xcf07acd7, - 0xd4f100dd, - 0x1bf47000, -/* 0x0067: nsec */ - 0xf900f8f5, - 0xf080f990, - 0x88cf2c87, -/* 0x0071: nsec_loop */ - 0x2c97f000, - 0xbb0099cf, - 0x9eb80298, - 0xf41ef406, - 0x90fc80fc, -/* 0x0086: wait */ - 0x90f900f8, - 0x87f080f9, - 0x0088cf2c, -/* 0x0090: wait_loop */ - 0xf402eeb9, - 0xdab90421, - 0x04adfd02, - 0xf406acb8, - 0x97f0120b, - 0x0099cf2c, - 0xb80298bb, - 0x1ef4069b, -/* 0x00b1: wait_done */ - 0xfc80fce2, -/* 0x00b7: intr_watchdog */ - 0x9800f890, - 0x96b003e9, - 0x2a0bf400, - 0xbb9a0a98, - 0x1cf4029a, - 0x01d7f00f, - 0x028c21f5, - 0x0ef494bd, -/* 0x00d5: intr_watchdog_next_time */ - 0x9b0a9815, - 0xf400a6b0, - 0x9ab8090b, - 0x061cf406, -/* 0x00e4: intr_watchdog_next_time_set */ -/* 0x00e7: intr_watchdog_next_proc */ - 0x809b0980, - 0xe0b603e9, - 0x68e6b158, - 0xc61bf402, -/* 0x00f6: intr */ - 0x00f900f8, - 0x80f904bd, - 0xa0f990f9, - 0xc0f9b0f9, - 0xe0f9d0f9, - 0xf7f0f0f9, - 0x0188fe00, - 0x87f180f9, - 0x88cf05d0, - 0x0180b600, - 0x05d007f1, - 0xbd0008d0, - 0x0887f004, - 0xc40088cf, - 0x0bf40289, - 0x9b008020, - 0xf458e7f0, - 0x0998b721, - 0x0096b09b, - 0xf00e0bf4, - 0x09d03407, - 0x8004bd00, -/* 0x014e: intr_skip_watchdog */ - 0x89e49a09, - 0x0bf40800, - 0x8897f13c, - 0x0099cf06, - 0xf4029ac4, - 0xc7f1260b, - 0xcccf04c0, - 0xf1c0f900, - 0xf14f48e7, - 0xf05453e3, - 0x21f500d7, - 0xc0fc02f1, - 0x04c007f1, - 0xbd000cd0, -/* 0x0185: intr_subintr_skip_fifo */ - 0x8807f104, - 0x0009d006, -/* 0x018e: intr_skip_subintr */ - 0x89c404bd, - 0x070bf420, - 0xffbfa4f1, -/* 0x0198: intr_skip_pause */ - 0xf44089c4, - 0xa4f1070b, -/* 0x01a2: intr_skip_user0 */ - 0x07f0ffbf, - 0x0008d004, - 0x80fc04bd, - 0xfc0088fe, - 0xfce0fcf0, - 0xfcc0fcd0, - 0xfca0fcb0, - 0xfc80fc90, - 0x0032f400, -/* 0x01c6: ticks_from_ns */ - 0xc0f901f8, - 0xd7f1b0f9, - 0xd3f00144, - 0xb321f500, - 0xe8ccec03, - 0x00b4b003, - 0xec120bf4, - 0xf103e8ee, - 0xf00144d7, - 0x21f500d3, -/* 0x01ee: ticks_from_ns_quit */ - 0xceb903b3, - 0xfcb0fc02, -/* 0x01f7: ticks_from_us */ - 0xf900f8c0, - 0xf1b0f9c0, - 0xf00144d7, - 0x21f500d3, - 0xceb903b3, - 0x00b4b002, - 0xbd050bf4, -/* 0x0211: ticks_from_us_quit */ - 0xfcb0fce4, -/* 0x0217: ticks_to_us */ - 0xf100f8c0, - 0xf00144d7, - 0xedff00d3, -/* 0x0223: timer */ - 0xf900f8ec, - 0xf480f990, - 0xf8981032, - 0x0086b003, - 0xbd531cf4, - 0x3807f084, - 0xbd0008d0, - 0x3487f004, - 0x980088cf, - 0x98bb9a09, - 0x00e9bb02, - 0xf003fe80, - 0x88cf0887, - 0x0284f000, - 0xf0201bf4, - 0x88cf3487, - 0x06e0b800, - 0xb8090bf4, - 0x1cf406e8, -/* 0x026d: timer_reset */ - 0x3407f00e, - 0xbd000ed0, - 0x9a0e8004, -/* 0x0278: timer_enable */ - 0xf00187f0, - 0x08d03807, -/* 0x0283: timer_done */ - 0xf404bd00, - 0x80fc1031, - 0x00f890fc, -/* 0x028c: send_proc */ - 0x90f980f9, - 0x9805e898, - 0x86f004e9, - 0x0689b804, - 0xc42a0bf4, - 0x88940398, - 0x1880b604, - 0x98008ebb, - 0x8a8000fa, - 0x018d8000, - 0x80028c80, - 0x90b6038b, - 0x0794f001, - 0xf404e980, -/* 0x02c6: send_done */ - 0x90fc0231, - 0x00f880fc, -/* 0x02cc: find */ - 0x87f080f9, - 0x0131f458, -/* 0x02d4: find_loop */ - 0xb8008a98, - 0x0bf406ae, - 0x5880b610, - 0x026886b1, - 0xf4f01bf4, -/* 0x02ea: find_done */ - 0x8eb90132, - 0xf880fc02, -/* 0x02f1: send */ - 0xcc21f500, - 0x9701f402, -/* 0x02fa: recv */ - 0x90f900f8, - 0xe89880f9, - 0x04e99805, - 0xb80132f4, - 0x0bf40689, - 0x0389c43d, - 0xf00180b6, - 0xe8800784, - 0x02ea9805, - 0x8ffef0f9, - 0xb9f0f901, - 0x999402ef, - 0x00e9bb04, - 0x9818e0b6, - 0xec9803eb, - 0x01ed9802, - 0xf900ee98, - 0xfef0fca5, - 0x31f400f8, -/* 0x0347: recv_done */ - 0xfcf0fc01, - 0xf890fc80, -/* 0x034d: init */ - 0x0817f100, - 0x0011cf01, - 0x010911e7, - 0xfe0814b6, - 0x17f10014, - 0x13f000e0, - 0x1c07f000, - 0xbd0001d0, - 0xff17f004, - 0xd01407f0, - 0x04bd0001, - 0xf10217f0, - 0xf0080015, - 0x01d01007, - 0xf104bd00, - 0xf000f617, - 0x10fe0013, - 0x1031f400, - 0xf00117f0, - 0x01d03807, - 0xf004bd00, -/* 0x03a2: init_proc */ - 0xf19858f7, - 0x0016b001, - 0xf9fa0bf4, - 0x58f0b615, -/* 0x03b3: mulu32_32_64 */ - 0xf9f20ef4, - 0xf920f910, - 0x9540f930, - 0xd29510e1, - 0xbdc4bd10, - 0xc0edffb4, - 0xb9301dff, - 0x34f10234, - 0x34b6ffff, - 0x1045b610, - 0xbb00c3bb, - 0xe2ff01b4, - 0x0234b930, - 0xffff34f1, - 0xb61034b6, - 0xc3bb1045, - 0x01b4bb00, - 0xbb3012ff, - 0x40fc00b3, - 0x20fc30fc, - 0x00f810fc, -/* 0x0404: host_send */ - 0x04b017f1, - 0xf10011cf, - 0xcf04a027, - 0x12b80022, - 0x2f0bf406, - 0x94071ec4, - 0xe0b704ee, - 0xeb980270, - 0x02ec9803, - 0x9801ed98, - 0x21f500ee, - 0x10b602f1, - 0x0f1ec401, - 0x04b007f1, - 0xbd000ed0, - 0xc30ef404, -/* 0x0444: host_send_done */ -/* 0x0446: host_recv */ - 0x17f100f8, - 0x13f14e49, - 0xe1b85254, - 0xb30bf406, -/* 0x0454: host_recv_wait */ - 0x04cc17f1, - 0xf10011cf, - 0xcf04c827, - 0x16f00022, - 0x0612b808, - 0xc4ec0bf4, - 0x34b60723, - 0xf030b704, - 0x033b8002, - 0x80023c80, - 0x3e80013d, - 0x0120b600, - 0xf10f24f0, - 0xd004c807, - 0x04bd0002, - 0xf04027f0, - 0x02d00007, - 0xf804bd00, -/* 0x049d: host_init */ - 0x8017f100, - 0x1014b600, - 0x027015f1, - 0x04d007f1, - 0xbd0001d0, - 0x8017f104, - 0x1014b600, - 0x02f015f1, - 0x04dc07f1, - 0xbd0001d0, - 0x0117f004, - 0x04c407f1, - 0xbd0001d0, -/* 0x04d3: memx_func_enter */ - 0xf100f804, - 0xf1162067, - 0xf1f55d77, - 0xb9ffff73, - 0x21f4026e, - 0x02d8b904, - 0xf90487fd, - 0xfc80f960, - 0xf4e0fcd0, - 0x77f13321, - 0x73f1fffe, - 0x6eb9ffff, - 0x0421f402, - 0xfd02d8b9, - 0x60f90487, - 0xd0fc80f9, - 0x21f4e0fc, - 0xf067f133, - 0x026eb926, - 0xb90421f4, - 0x87fd02d8, - 0xf960f904, - 0xfcd0fc80, - 0x3321f4e0, - 0xf10467f0, - 0xd007e007, - 0x04bd0006, -/* 0x053c: memx_func_enter_wait */ - 0x07c067f1, - 0xf00066cf, - 0x0bf40464, - 0x2c67f0f6, - 0x800066cf, - 0x00f8f106, -/* 0x0554: memx_func_leave */ - 0xcf2c67f0, - 0x06800066, - 0x0467f0f2, - 0x07e407f1, - 0xbd0006d0, -/* 0x0569: memx_func_leave_wait */ - 0xc067f104, - 0x0066cf07, - 0xf40464f0, - 0x67f1f61b, - 0x77f126f0, - 0x73f00001, - 0x026eb900, - 0xb90421f4, - 0x87fd02d8, - 0xf960f905, - 0xfcd0fc80, - 0x3321f4e0, - 0x162067f1, - 0xf4026eb9, - 0xd8b90421, - 0x0587fd02, - 0x80f960f9, - 0xe0fcd0fc, - 0xf13321f4, - 0xf00aa277, - 0x6eb90073, - 0x0421f402, - 0xfd02d8b9, - 0x60f90587, - 0xd0fc80f9, - 0x21f4e0fc, -/* 0x05d3: memx_func_wait_vblank */ - 0xb600f833, - 0x00f80410, -/* 0x05d8: memx_func_wr32 */ - 0x98001698, - 0x10b60115, - 0xf960f908, - 0xfcd0fc50, - 0x3321f4e0, - 0xf40242b6, - 0x00f8e91b, -/* 0x05f4: memx_func_wait */ - 0xcf2c87f0, - 0x1e980088, - 0x011d9800, - 0x98021c98, - 0x10b6031b, - 0x8621f410, -/* 0x060e: memx_func_delay */ - 0x1e9800f8, - 0x0410b600, - 0xf86721f4, -/* 0x0619: memx_func_train */ -/* 0x061b: memx_exec */ - 0xf900f800, - 0xb9d0f9e0, - 0xb2b902c1, -/* 0x0625: memx_exec_next */ - 0x00139802, - 0xe70410b6, - 0xe701f034, - 0xb601e033, - 0x30f00132, - 0xde35980c, - 0x12b855f9, - 0xe41ef406, - 0x98f10b98, - 0xcbbbf20c, - 0xc4b7f102, - 0x00bbcf07, - 0xe0fcd0fc, - 0x02f121f5, -/* 0x065e: memx_info */ - 0xc67000f8, - 0x0e0bf401, -/* 0x0664: memx_info_data */ - 0x03ccc7f1, - 0x0800b7f1, -/* 0x066f: memx_info_train */ - 0xf10b0ef4, - 0xf10bccc7, -/* 0x0677: memx_info_send */ - 0xf50100b7, - 0xf802f121, -/* 0x067d: memx_recv */ - 0x01d6b000, - 0xb09b0bf4, - 0x0bf400d6, -/* 0x068b: memx_init */ - 0xf800f8d8, -/* 0x068d: perf_recv */ -/* 0x068f: perf_init */ - 0xf800f800, -/* 0x0691: i2c_drive_scl */ - 0x0036b000, - 0xf10e0bf4, - 0xd007e007, - 0x04bd0001, -/* 0x06a2: i2c_drive_scl_lo */ - 0x07f100f8, - 0x01d007e4, - 0xf804bd00, -/* 0x06ad: i2c_drive_sda */ - 0x0036b000, - 0xf10e0bf4, - 0xd007e007, - 0x04bd0002, -/* 0x06be: i2c_drive_sda_lo */ - 0x07f100f8, - 0x02d007e4, - 0xf804bd00, -/* 0x06c9: i2c_sense_scl */ - 0x0132f400, - 0x07c437f1, - 0xfd0033cf, - 0x0bf40431, - 0x0131f406, -/* 0x06dc: i2c_sense_scl_done */ -/* 0x06de: i2c_sense_sda */ - 0x32f400f8, - 0xc437f101, - 0x0033cf07, - 0xf40432fd, - 0x31f4060b, -/* 0x06f1: i2c_sense_sda_done */ -/* 0x06f3: i2c_raise_scl */ - 0xf900f801, - 0x9847f140, - 0x0137f008, - 0x069121f5, -/* 0x0700: i2c_raise_scl_wait */ - 0x03e8e7f1, - 0xf56721f4, - 0xf406c921, - 0x42b60901, - 0xef1bf401, -/* 0x0714: i2c_raise_scl_done */ - 0x00f840fc, -/* 0x0718: i2c_start */ - 0x06c921f5, - 0xf50d11f4, - 0xf406de21, - 0x0ef40611, -/* 0x0729: i2c_start_rep */ - 0x0037f030, - 0x069121f5, - 0xf50137f0, - 0xbb06ad21, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x06f321f5, - 0xf40464b6, -/* 0x0756: i2c_start_send */ - 0x37f01f11, - 0xad21f500, - 0x88e7f106, - 0x6721f413, - 0xf50037f0, - 0xf1069121, - 0xf41388e7, -/* 0x0772: i2c_start_out */ - 0x00f86721, -/* 0x0774: i2c_stop */ - 0xf50037f0, - 0xf0069121, - 0x21f50037, - 0xe7f106ad, - 0x21f403e8, - 0x0137f067, - 0x069121f5, - 0x1388e7f1, - 0xf06721f4, - 0x21f50137, - 0xe7f106ad, - 0x21f41388, -/* 0x07a7: i2c_bitw */ - 0xf500f867, - 0xf106ad21, - 0xf403e8e7, - 0x76bb6721, - 0x0465b600, - 0x659450f9, - 0x0256bb04, - 0x75fd50bd, - 0xf550fc04, - 0xb606f321, - 0x11f40464, - 0x88e7f118, - 0x6721f413, - 0xf50037f0, - 0xf1069121, - 0xf41388e7, -/* 0x07e6: i2c_bitw_out */ - 0x00f86721, -/* 0x07e8: i2c_bitr */ - 0xf50137f0, - 0xf106ad21, - 0xf403e8e7, - 0x76bb6721, - 0x0465b600, - 0x659450f9, - 0x0256bb04, - 0x75fd50bd, - 0xf550fc04, - 0xb606f321, - 0x11f40464, - 0xde21f51b, - 0x0037f006, - 0x069121f5, - 0x1388e7f1, - 0xf06721f4, - 0x31f4013c, -/* 0x082d: i2c_bitr_done */ -/* 0x082f: i2c_get_byte */ - 0xf000f801, - 0x47f00057, -/* 0x0835: i2c_get_byte_next */ - 0x0154b608, - 0xb60076bb, - 0x50f90465, - 0xbb046594, - 0x50bd0256, - 0xfc0475fd, - 0xe821f550, - 0x0464b607, - 0xfd2b11f4, - 0x42b60553, - 0xd81bf401, - 0xbb0137f0, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x07a721f5, -/* 0x087f: i2c_get_byte_done */ - 0xf80464b6, -/* 0x0881: i2c_put_byte */ - 0x0847f000, -/* 0x0884: i2c_put_byte_next */ - 0xff0142b6, - 0x76bb3854, - 0x0465b600, - 0x659450f9, - 0x0256bb04, - 0x75fd50bd, - 0xf550fc04, - 0xb607a721, - 0x11f40464, - 0x0046b034, - 0xbbd81bf4, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x07e821f5, - 0xf40464b6, - 0x76bb0f11, - 0x0136b000, - 0xf4061bf4, -/* 0x08da: i2c_put_byte_done */ - 0x00f80132, -/* 0x08dc: i2c_addr */ - 0xb60076bb, - 0x50f90465, - 0xbb046594, - 0x50bd0256, - 0xfc0475fd, - 0x1821f550, - 0x0464b607, - 0xe72911f4, - 0xb6012ec3, - 0x53fd0134, - 0x0076bb05, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0x21f550fc, - 0x64b60881, -/* 0x0921: i2c_addr_done */ -/* 0x0923: i2c_acquire_addr */ - 0xc700f804, - 0xe4b6f8ce, - 0x14e0b705, -/* 0x092f: i2c_acquire */ - 0xf500f8d0, - 0xf4092321, - 0xd9f00421, - 0x3321f403, -/* 0x093e: i2c_release */ - 0x21f500f8, - 0x21f40923, - 0x03daf004, - 0xf83321f4, -/* 0x094d: i2c_recv */ - 0x0132f400, - 0xb6f8c1c7, - 0x16b00214, - 0x3a1ff528, - 0xf413a001, - 0x0032980c, - 0x0ccc13a0, - 0xf4003198, - 0xd0f90231, - 0xd0f9e0f9, - 0x000067f1, - 0x100063f1, - 0xbb016792, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x092f21f5, - 0xfc0464b6, - 0x00d6b0d0, - 0x00b31bf5, - 0xbb0057f0, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x08dc21f5, - 0xf50464b6, - 0xc700d011, - 0x76bbe0c5, - 0x0465b600, - 0x659450f9, - 0x0256bb04, - 0x75fd50bd, - 0xf550fc04, - 0xb6088121, - 0x11f50464, - 0x57f000ad, - 0x0076bb01, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0x21f550fc, - 0x64b608dc, - 0x8a11f504, - 0x0076bb00, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0x21f550fc, - 0x64b6082f, - 0x6a11f404, - 0xbbe05bcb, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x077421f5, - 0xb90464b6, - 0x74bd025b, -/* 0x0a53: i2c_recv_not_rd08 */ - 0xb0430ef4, - 0x1bf401d6, - 0x0057f03d, - 0x08dc21f5, - 0xc73311f4, - 0x21f5e0c5, - 0x11f40881, - 0x0057f029, - 0x08dc21f5, - 0xc71f11f4, - 0x21f5e0b5, - 0x11f40881, - 0x7421f515, - 0xc774bd07, - 0x1bf408c5, - 0x0232f409, -/* 0x0a93: i2c_recv_not_wr08 */ -/* 0x0a93: i2c_recv_done */ - 0xc7030ef4, - 0x21f5f8ce, - 0xe0fc093e, - 0x12f4d0fc, - 0x027cb90a, - 0x02f121f5, -/* 0x0aa8: i2c_recv_exit */ -/* 0x0aaa: i2c_init */ - 0x00f800f8, -/* 0x0aac: test_recv */ - 0x05d817f1, - 0xb60011cf, - 0x07f10110, - 0x01d005d8, - 0xf104bd00, - 0xf1d900e7, - 0xf5134fe3, - 0xf8022321, -/* 0x0acd: test_init */ - 0x00e7f100, - 0x2321f508, -/* 0x0ad7: idle_recv */ - 0xf800f802, -/* 0x0ad9: idle */ - 0x0031f400, - 0x05d417f1, - 0xb60011cf, - 0x07f10110, - 0x01d005d4, -/* 0x0aef: idle_loop */ - 0xf004bd00, - 0x32f45817, -/* 0x0af5: idle_proc */ -/* 0x0af5: idle_proc_exec */ - 0xb910f902, - 0x21f5021e, - 0x10fc02fa, - 0xf40911f4, - 0x0ef40231, -/* 0x0b09: idle_proc_next */ - 0x5810b6ef, - 0xf4061fb8, - 0x02f4e61b, - 0x0028f4dd, - 0x00c10ef4, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4 b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4 new file mode 100644 index 000000000..2f28c7e26 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4 @@ -0,0 +1,70 @@ +/* + * Copyright 2013 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 + */ + +#define NVKM_PPWR_CHIPSET GF119 +#define HW_TICKS_PER_US 324 + +//#define NVKM_FALCON_PC24 +#define NVKM_FALCON_UNSHIFTED_IO +//#define NVKM_FALCON_MMIO_UAS +//#define NVKM_FALCON_MMIO_TRAP + +#include "macros.fuc" + +.section #gf119_pmu_data +#define INCLUDE_PROC +#include "kernel.fuc" +#include "arith.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_PROC + +#define INCLUDE_DATA +#include "kernel.fuc" +#include "arith.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_DATA +.align 256 + +.section #gf119_pmu_code +#define INCLUDE_CODE +#include "kernel.fuc" +#include "arith.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_CODE +.align 256 diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h new file mode 100644 index 000000000..31552af9b --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h @@ -0,0 +1,1795 @@ +uint32_t gf119_pmu_data[] = { +/* 0x0000: proc_kern */ + 0x52544e49, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0058: proc_list_head */ + 0x54534f48, + 0x0000049d, + 0x00000446, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x584d454d, + 0x0000068b, + 0x0000067d, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x46524550, + 0x0000068f, + 0x0000068d, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x5f433249, + 0x00000aaa, + 0x0000094d, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x54534554, + 0x00000acd, + 0x00000aac, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x454c4449, + 0x00000ad9, + 0x00000ad7, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ + 0x00000000, +/* 0x026c: time_next */ + 0x00000000, +/* 0x0270: fifo_queue */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x02f0: rfifo_queue */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0370: memx_func_head */ + 0x00000001, + 0x00000000, + 0x000004d3, +/* 0x037c: memx_func_next */ + 0x00000002, + 0x00000000, + 0x00000554, + 0x00000003, + 0x00000002, + 0x000005d8, + 0x00040004, + 0x00000000, + 0x000005f4, + 0x00010005, + 0x00000000, + 0x0000060e, + 0x00010006, + 0x00000000, + 0x000005d3, + 0x00000007, + 0x00000000, + 0x00000619, +/* 0x03c4: memx_func_tail */ +/* 0x03c4: memx_ts_start */ + 0x00000000, +/* 0x03c8: memx_ts_end */ + 0x00000000, +/* 0x03cc: memx_data_head */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0bcc: memx_data_tail */ +/* 0x0bcc: memx_train_head */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0ccc: memx_train_tail */ +/* 0x0ccc: i2c_scl_map */ + 0x00000400, + 0x00000800, + 0x00001000, + 0x00002000, + 0x00004000, + 0x00008000, + 0x00010000, + 0x00020000, + 0x00040000, + 0x00080000, +/* 0x0cf4: i2c_sda_map */ + 0x00100000, + 0x00200000, + 0x00400000, + 0x00800000, + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +uint32_t gf119_pmu_code[] = { + 0x034d0ef5, +/* 0x0004: rd32 */ + 0x07a007f1, + 0xbd000ed0, + 0x01d7f004, + 0xf101d3f0, + 0xd007ac07, + 0x04bd000d, +/* 0x001c: rd32_wait */ + 0x07acd7f1, + 0xf100ddcf, + 0xf47000d4, + 0xd7f1f51b, + 0xddcf07a4, +/* 0x0033: wr32 */ + 0xf100f800, + 0xd007a007, + 0x04bd000e, + 0x07a407f1, + 0xbd000dd0, + 0x02d7f004, + 0xf0f0d5f0, + 0x07f101d3, + 0x0dd007ac, +/* 0x0057: wr32_wait */ + 0xf104bd00, + 0xcf07acd7, + 0xd4f100dd, + 0x1bf47000, +/* 0x0067: nsec */ + 0xf900f8f5, + 0xf080f990, + 0x88cf2c87, +/* 0x0071: nsec_loop */ + 0x2c97f000, + 0xbb0099cf, + 0x9eb80298, + 0xf41ef406, + 0x90fc80fc, +/* 0x0086: wait */ + 0x90f900f8, + 0x87f080f9, + 0x0088cf2c, +/* 0x0090: wait_loop */ + 0xf402eeb9, + 0xdab90421, + 0x04adfd02, + 0xf406acb8, + 0x97f0120b, + 0x0099cf2c, + 0xb80298bb, + 0x1ef4069b, +/* 0x00b1: wait_done */ + 0xfc80fce2, +/* 0x00b7: intr_watchdog */ + 0x9800f890, + 0x96b003e9, + 0x2a0bf400, + 0xbb9a0a98, + 0x1cf4029a, + 0x01d7f00f, + 0x028c21f5, + 0x0ef494bd, +/* 0x00d5: intr_watchdog_next_time */ + 0x9b0a9815, + 0xf400a6b0, + 0x9ab8090b, + 0x061cf406, +/* 0x00e4: intr_watchdog_next_time_set */ +/* 0x00e7: intr_watchdog_next_proc */ + 0x809b0980, + 0xe0b603e9, + 0x68e6b158, + 0xc61bf402, +/* 0x00f6: intr */ + 0x00f900f8, + 0x80f904bd, + 0xa0f990f9, + 0xc0f9b0f9, + 0xe0f9d0f9, + 0xf7f0f0f9, + 0x0188fe00, + 0x87f180f9, + 0x88cf05d0, + 0x0180b600, + 0x05d007f1, + 0xbd0008d0, + 0x0887f004, + 0xc40088cf, + 0x0bf40289, + 0x9b008020, + 0xf458e7f0, + 0x0998b721, + 0x0096b09b, + 0xf00e0bf4, + 0x09d03407, + 0x8004bd00, +/* 0x014e: intr_skip_watchdog */ + 0x89e49a09, + 0x0bf40800, + 0x8897f13c, + 0x0099cf06, + 0xf4029ac4, + 0xc7f1260b, + 0xcccf04c0, + 0xf1c0f900, + 0xf14f48e7, + 0xf05453e3, + 0x21f500d7, + 0xc0fc02f1, + 0x04c007f1, + 0xbd000cd0, +/* 0x0185: intr_subintr_skip_fifo */ + 0x8807f104, + 0x0009d006, +/* 0x018e: intr_skip_subintr */ + 0x89c404bd, + 0x070bf420, + 0xffbfa4f1, +/* 0x0198: intr_skip_pause */ + 0xf44089c4, + 0xa4f1070b, +/* 0x01a2: intr_skip_user0 */ + 0x07f0ffbf, + 0x0008d004, + 0x80fc04bd, + 0xfc0088fe, + 0xfce0fcf0, + 0xfcc0fcd0, + 0xfca0fcb0, + 0xfc80fc90, + 0x0032f400, +/* 0x01c6: ticks_from_ns */ + 0xc0f901f8, + 0xd7f1b0f9, + 0xd3f00144, + 0xb321f500, + 0xe8ccec03, + 0x00b4b003, + 0xec120bf4, + 0xf103e8ee, + 0xf00144d7, + 0x21f500d3, +/* 0x01ee: ticks_from_ns_quit */ + 0xceb903b3, + 0xfcb0fc02, +/* 0x01f7: ticks_from_us */ + 0xf900f8c0, + 0xf1b0f9c0, + 0xf00144d7, + 0x21f500d3, + 0xceb903b3, + 0x00b4b002, + 0xbd050bf4, +/* 0x0211: ticks_from_us_quit */ + 0xfcb0fce4, +/* 0x0217: ticks_to_us */ + 0xf100f8c0, + 0xf00144d7, + 0xedff00d3, +/* 0x0223: timer */ + 0xf900f8ec, + 0xf480f990, + 0xf8981032, + 0x0086b003, + 0xbd531cf4, + 0x3807f084, + 0xbd0008d0, + 0x3487f004, + 0x980088cf, + 0x98bb9a09, + 0x00e9bb02, + 0xf003fe80, + 0x88cf0887, + 0x0284f000, + 0xf0201bf4, + 0x88cf3487, + 0x06e0b800, + 0xb8090bf4, + 0x1cf406e8, +/* 0x026d: timer_reset */ + 0x3407f00e, + 0xbd000ed0, + 0x9a0e8004, +/* 0x0278: timer_enable */ + 0xf00187f0, + 0x08d03807, +/* 0x0283: timer_done */ + 0xf404bd00, + 0x80fc1031, + 0x00f890fc, +/* 0x028c: send_proc */ + 0x90f980f9, + 0x9805e898, + 0x86f004e9, + 0x0689b804, + 0xc42a0bf4, + 0x88940398, + 0x1880b604, + 0x98008ebb, + 0x8a8000fa, + 0x018d8000, + 0x80028c80, + 0x90b6038b, + 0x0794f001, + 0xf404e980, +/* 0x02c6: send_done */ + 0x90fc0231, + 0x00f880fc, +/* 0x02cc: find */ + 0x87f080f9, + 0x0131f458, +/* 0x02d4: find_loop */ + 0xb8008a98, + 0x0bf406ae, + 0x5880b610, + 0x026886b1, + 0xf4f01bf4, +/* 0x02ea: find_done */ + 0x8eb90132, + 0xf880fc02, +/* 0x02f1: send */ + 0xcc21f500, + 0x9701f402, +/* 0x02fa: recv */ + 0x90f900f8, + 0xe89880f9, + 0x04e99805, + 0xb80132f4, + 0x0bf40689, + 0x0389c43d, + 0xf00180b6, + 0xe8800784, + 0x02ea9805, + 0x8ffef0f9, + 0xb9f0f901, + 0x999402ef, + 0x00e9bb04, + 0x9818e0b6, + 0xec9803eb, + 0x01ed9802, + 0xf900ee98, + 0xfef0fca5, + 0x31f400f8, +/* 0x0347: recv_done */ + 0xfcf0fc01, + 0xf890fc80, +/* 0x034d: init */ + 0x0817f100, + 0x0011cf01, + 0x010911e7, + 0xfe0814b6, + 0x17f10014, + 0x13f000e0, + 0x1c07f000, + 0xbd0001d0, + 0xff17f004, + 0xd01407f0, + 0x04bd0001, + 0xf10217f0, + 0xf0080015, + 0x01d01007, + 0xf104bd00, + 0xf000f617, + 0x10fe0013, + 0x1031f400, + 0xf00117f0, + 0x01d03807, + 0xf004bd00, +/* 0x03a2: init_proc */ + 0xf19858f7, + 0x0016b001, + 0xf9fa0bf4, + 0x58f0b615, +/* 0x03b3: mulu32_32_64 */ + 0xf9f20ef4, + 0xf920f910, + 0x9540f930, + 0xd29510e1, + 0xbdc4bd10, + 0xc0edffb4, + 0xb9301dff, + 0x34f10234, + 0x34b6ffff, + 0x1045b610, + 0xbb00c3bb, + 0xe2ff01b4, + 0x0234b930, + 0xffff34f1, + 0xb61034b6, + 0xc3bb1045, + 0x01b4bb00, + 0xbb3012ff, + 0x40fc00b3, + 0x20fc30fc, + 0x00f810fc, +/* 0x0404: host_send */ + 0x04b017f1, + 0xf10011cf, + 0xcf04a027, + 0x12b80022, + 0x2f0bf406, + 0x94071ec4, + 0xe0b704ee, + 0xeb980270, + 0x02ec9803, + 0x9801ed98, + 0x21f500ee, + 0x10b602f1, + 0x0f1ec401, + 0x04b007f1, + 0xbd000ed0, + 0xc30ef404, +/* 0x0444: host_send_done */ +/* 0x0446: host_recv */ + 0x17f100f8, + 0x13f14e49, + 0xe1b85254, + 0xb30bf406, +/* 0x0454: host_recv_wait */ + 0x04cc17f1, + 0xf10011cf, + 0xcf04c827, + 0x16f00022, + 0x0612b808, + 0xc4ec0bf4, + 0x34b60723, + 0xf030b704, + 0x033b8002, + 0x80023c80, + 0x3e80013d, + 0x0120b600, + 0xf10f24f0, + 0xd004c807, + 0x04bd0002, + 0xf04027f0, + 0x02d00007, + 0xf804bd00, +/* 0x049d: host_init */ + 0x8017f100, + 0x1014b600, + 0x027015f1, + 0x04d007f1, + 0xbd0001d0, + 0x8017f104, + 0x1014b600, + 0x02f015f1, + 0x04dc07f1, + 0xbd0001d0, + 0x0117f004, + 0x04c407f1, + 0xbd0001d0, +/* 0x04d3: memx_func_enter */ + 0xf100f804, + 0xf1162067, + 0xf1f55d77, + 0xb9ffff73, + 0x21f4026e, + 0x02d8b904, + 0xf90487fd, + 0xfc80f960, + 0xf4e0fcd0, + 0x77f13321, + 0x73f1fffe, + 0x6eb9ffff, + 0x0421f402, + 0xfd02d8b9, + 0x60f90487, + 0xd0fc80f9, + 0x21f4e0fc, + 0xf067f133, + 0x026eb926, + 0xb90421f4, + 0x87fd02d8, + 0xf960f904, + 0xfcd0fc80, + 0x3321f4e0, + 0xf10467f0, + 0xd007e007, + 0x04bd0006, +/* 0x053c: memx_func_enter_wait */ + 0x07c067f1, + 0xf00066cf, + 0x0bf40464, + 0x2c67f0f6, + 0x800066cf, + 0x00f8f106, +/* 0x0554: memx_func_leave */ + 0xcf2c67f0, + 0x06800066, + 0x0467f0f2, + 0x07e407f1, + 0xbd0006d0, +/* 0x0569: memx_func_leave_wait */ + 0xc067f104, + 0x0066cf07, + 0xf40464f0, + 0x67f1f61b, + 0x77f126f0, + 0x73f00001, + 0x026eb900, + 0xb90421f4, + 0x87fd02d8, + 0xf960f905, + 0xfcd0fc80, + 0x3321f4e0, + 0x162067f1, + 0xf4026eb9, + 0xd8b90421, + 0x0587fd02, + 0x80f960f9, + 0xe0fcd0fc, + 0xf13321f4, + 0xf00aa277, + 0x6eb90073, + 0x0421f402, + 0xfd02d8b9, + 0x60f90587, + 0xd0fc80f9, + 0x21f4e0fc, +/* 0x05d3: memx_func_wait_vblank */ + 0xb600f833, + 0x00f80410, +/* 0x05d8: memx_func_wr32 */ + 0x98001698, + 0x10b60115, + 0xf960f908, + 0xfcd0fc50, + 0x3321f4e0, + 0xf40242b6, + 0x00f8e91b, +/* 0x05f4: memx_func_wait */ + 0xcf2c87f0, + 0x1e980088, + 0x011d9800, + 0x98021c98, + 0x10b6031b, + 0x8621f410, +/* 0x060e: memx_func_delay */ + 0x1e9800f8, + 0x0410b600, + 0xf86721f4, +/* 0x0619: memx_func_train */ +/* 0x061b: memx_exec */ + 0xf900f800, + 0xb9d0f9e0, + 0xb2b902c1, +/* 0x0625: memx_exec_next */ + 0x00139802, + 0xe70410b6, + 0xe701f034, + 0xb601e033, + 0x30f00132, + 0xde35980c, + 0x12b855f9, + 0xe41ef406, + 0x98f10b98, + 0xcbbbf20c, + 0xc4b7f102, + 0x00bbcf07, + 0xe0fcd0fc, + 0x02f121f5, +/* 0x065e: memx_info */ + 0xc67000f8, + 0x0e0bf401, +/* 0x0664: memx_info_data */ + 0x03ccc7f1, + 0x0800b7f1, +/* 0x066f: memx_info_train */ + 0xf10b0ef4, + 0xf10bccc7, +/* 0x0677: memx_info_send */ + 0xf50100b7, + 0xf802f121, +/* 0x067d: memx_recv */ + 0x01d6b000, + 0xb09b0bf4, + 0x0bf400d6, +/* 0x068b: memx_init */ + 0xf800f8d8, +/* 0x068d: perf_recv */ +/* 0x068f: perf_init */ + 0xf800f800, +/* 0x0691: i2c_drive_scl */ + 0x0036b000, + 0xf10e0bf4, + 0xd007e007, + 0x04bd0001, +/* 0x06a2: i2c_drive_scl_lo */ + 0x07f100f8, + 0x01d007e4, + 0xf804bd00, +/* 0x06ad: i2c_drive_sda */ + 0x0036b000, + 0xf10e0bf4, + 0xd007e007, + 0x04bd0002, +/* 0x06be: i2c_drive_sda_lo */ + 0x07f100f8, + 0x02d007e4, + 0xf804bd00, +/* 0x06c9: i2c_sense_scl */ + 0x0132f400, + 0x07c437f1, + 0xfd0033cf, + 0x0bf40431, + 0x0131f406, +/* 0x06dc: i2c_sense_scl_done */ +/* 0x06de: i2c_sense_sda */ + 0x32f400f8, + 0xc437f101, + 0x0033cf07, + 0xf40432fd, + 0x31f4060b, +/* 0x06f1: i2c_sense_sda_done */ +/* 0x06f3: i2c_raise_scl */ + 0xf900f801, + 0x9847f140, + 0x0137f008, + 0x069121f5, +/* 0x0700: i2c_raise_scl_wait */ + 0x03e8e7f1, + 0xf56721f4, + 0xf406c921, + 0x42b60901, + 0xef1bf401, +/* 0x0714: i2c_raise_scl_done */ + 0x00f840fc, +/* 0x0718: i2c_start */ + 0x06c921f5, + 0xf50d11f4, + 0xf406de21, + 0x0ef40611, +/* 0x0729: i2c_start_rep */ + 0x0037f030, + 0x069121f5, + 0xf50137f0, + 0xbb06ad21, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x06f321f5, + 0xf40464b6, +/* 0x0756: i2c_start_send */ + 0x37f01f11, + 0xad21f500, + 0x88e7f106, + 0x6721f413, + 0xf50037f0, + 0xf1069121, + 0xf41388e7, +/* 0x0772: i2c_start_out */ + 0x00f86721, +/* 0x0774: i2c_stop */ + 0xf50037f0, + 0xf0069121, + 0x21f50037, + 0xe7f106ad, + 0x21f403e8, + 0x0137f067, + 0x069121f5, + 0x1388e7f1, + 0xf06721f4, + 0x21f50137, + 0xe7f106ad, + 0x21f41388, +/* 0x07a7: i2c_bitw */ + 0xf500f867, + 0xf106ad21, + 0xf403e8e7, + 0x76bb6721, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb606f321, + 0x11f40464, + 0x88e7f118, + 0x6721f413, + 0xf50037f0, + 0xf1069121, + 0xf41388e7, +/* 0x07e6: i2c_bitw_out */ + 0x00f86721, +/* 0x07e8: i2c_bitr */ + 0xf50137f0, + 0xf106ad21, + 0xf403e8e7, + 0x76bb6721, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb606f321, + 0x11f40464, + 0xde21f51b, + 0x0037f006, + 0x069121f5, + 0x1388e7f1, + 0xf06721f4, + 0x31f4013c, +/* 0x082d: i2c_bitr_done */ +/* 0x082f: i2c_get_byte */ + 0xf000f801, + 0x47f00057, +/* 0x0835: i2c_get_byte_next */ + 0x0154b608, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xe821f550, + 0x0464b607, + 0xfd2b11f4, + 0x42b60553, + 0xd81bf401, + 0xbb0137f0, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x07a721f5, +/* 0x087f: i2c_get_byte_done */ + 0xf80464b6, +/* 0x0881: i2c_put_byte */ + 0x0847f000, +/* 0x0884: i2c_put_byte_next */ + 0xff0142b6, + 0x76bb3854, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb607a721, + 0x11f40464, + 0x0046b034, + 0xbbd81bf4, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x07e821f5, + 0xf40464b6, + 0x76bb0f11, + 0x0136b000, + 0xf4061bf4, +/* 0x08da: i2c_put_byte_done */ + 0x00f80132, +/* 0x08dc: i2c_addr */ + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x1821f550, + 0x0464b607, + 0xe72911f4, + 0xb6012ec3, + 0x53fd0134, + 0x0076bb05, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b60881, +/* 0x0921: i2c_addr_done */ +/* 0x0923: i2c_acquire_addr */ + 0xc700f804, + 0xe4b6f8ce, + 0x14e0b705, +/* 0x092f: i2c_acquire */ + 0xf500f8d0, + 0xf4092321, + 0xd9f00421, + 0x3321f403, +/* 0x093e: i2c_release */ + 0x21f500f8, + 0x21f40923, + 0x03daf004, + 0xf83321f4, +/* 0x094d: i2c_recv */ + 0x0132f400, + 0xb6f8c1c7, + 0x16b00214, + 0x3a1ff528, + 0xf413a001, + 0x0032980c, + 0x0ccc13a0, + 0xf4003198, + 0xd0f90231, + 0xd0f9e0f9, + 0x000067f1, + 0x100063f1, + 0xbb016792, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x092f21f5, + 0xfc0464b6, + 0x00d6b0d0, + 0x00b31bf5, + 0xbb0057f0, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x08dc21f5, + 0xf50464b6, + 0xc700d011, + 0x76bbe0c5, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6088121, + 0x11f50464, + 0x57f000ad, + 0x0076bb01, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b608dc, + 0x8a11f504, + 0x0076bb00, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b6082f, + 0x6a11f404, + 0xbbe05bcb, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x077421f5, + 0xb90464b6, + 0x74bd025b, +/* 0x0a53: i2c_recv_not_rd08 */ + 0xb0430ef4, + 0x1bf401d6, + 0x0057f03d, + 0x08dc21f5, + 0xc73311f4, + 0x21f5e0c5, + 0x11f40881, + 0x0057f029, + 0x08dc21f5, + 0xc71f11f4, + 0x21f5e0b5, + 0x11f40881, + 0x7421f515, + 0xc774bd07, + 0x1bf408c5, + 0x0232f409, +/* 0x0a93: i2c_recv_not_wr08 */ +/* 0x0a93: i2c_recv_done */ + 0xc7030ef4, + 0x21f5f8ce, + 0xe0fc093e, + 0x12f4d0fc, + 0x027cb90a, + 0x02f121f5, +/* 0x0aa8: i2c_recv_exit */ +/* 0x0aaa: i2c_init */ + 0x00f800f8, +/* 0x0aac: test_recv */ + 0x05d817f1, + 0xb60011cf, + 0x07f10110, + 0x01d005d8, + 0xf104bd00, + 0xf1d900e7, + 0xf5134fe3, + 0xf8022321, +/* 0x0acd: test_init */ + 0x00e7f100, + 0x2321f508, +/* 0x0ad7: idle_recv */ + 0xf800f802, +/* 0x0ad9: idle */ + 0x0031f400, + 0x05d417f1, + 0xb60011cf, + 0x07f10110, + 0x01d005d4, +/* 0x0aef: idle_loop */ + 0xf004bd00, + 0x32f45817, +/* 0x0af5: idle_proc */ +/* 0x0af5: idle_proc_exec */ + 0xb910f902, + 0x21f5021e, + 0x10fc02fa, + 0xf40911f4, + 0x0ef40231, +/* 0x0b09: idle_proc_next */ + 0x5810b6ef, + 0xf4061fb8, + 0x02f4e61b, + 0x0028f4dd, + 0x00c10ef4, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c index 78a4ea010..aeb8ccd89 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c @@ -24,17 +24,16 @@ #include "priv.h" #include "fuc/gf100.fuc3.h" -struct nvkm_oclass * -gf100_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0xc0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = _nvkm_pmu_init, - .fini = _nvkm_pmu_fini, - }, +static const struct nvkm_pmu_func +gf100_pmu = { .code.data = gf100_pmu_code, .code.size = sizeof(gf100_pmu_code), .data.data = gf100_pmu_data, .data.size = sizeof(gf100_pmu_data), -}.base; +}; + +int +gf100_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gf100_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf110.c deleted file mode 100644 index 6b3a23839..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf110.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2013 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 "priv.h" -#include "fuc/gf110.fuc4.h" - -struct nvkm_oclass * -gf110_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0xd0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = _nvkm_pmu_init, - .fini = _nvkm_pmu_fini, - }, - .code.data = gf110_pmu_code, - .code.size = sizeof(gf110_pmu_code), - .data.data = gf110_pmu_data, - .data.size = sizeof(gf110_pmu_data), -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c new file mode 100644 index 000000000..fbc88d8ec --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c @@ -0,0 +1,39 @@ +/* + * Copyright 2013 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 "priv.h" +#include "fuc/gf119.fuc4.h" + +static const struct nvkm_pmu_func +gf119_pmu = { + .code.data = gf119_pmu_code, + .code.size = sizeof(gf119_pmu_code), + .data.data = gf119_pmu_data, + .data.size = sizeof(gf119_pmu_data), +}; + +int +gf119_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gf119_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c index 28fdb8ea9..86f9f3b13 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c @@ -21,47 +21,99 @@ * * Authors: Ben Skeggs */ -#define gf110_pmu_code gk104_pmu_code -#define gf110_pmu_data gk104_pmu_data +#define gf119_pmu_code gk104_pmu_code +#define gf119_pmu_data gk104_pmu_data #include "priv.h" -#include "fuc/gf110.fuc4.h" +#include "fuc/gf119.fuc4.h" + +#include +#include +#include + +static void +magic_(struct nvkm_device *device, u32 ctrl, int size) +{ + nvkm_wr32(device, 0x00c800, 0x00000000); + nvkm_wr32(device, 0x00c808, 0x00000000); + nvkm_wr32(device, 0x00c800, ctrl); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x00c800) & 0x40000000) { + while (size--) + nvkm_wr32(device, 0x00c804, 0x00000000); + break; + } + ); + nvkm_wr32(device, 0x00c800, 0x00000000); +} + +static void +magic(struct nvkm_device *device, u32 ctrl) +{ + magic_(device, 0x8000a41f | ctrl, 6); + magic_(device, 0x80000421 | ctrl, 1); +} static void gk104_pmu_pgob(struct nvkm_pmu *pmu, bool enable) { - nv_mask(pmu, 0x000200, 0x00001000, 0x00000000); - nv_rd32(pmu, 0x000200); - nv_mask(pmu, 0x000200, 0x08000000, 0x08000000); + struct nvkm_device *device = pmu->subdev.device; + + if (!(nvkm_fuse_read(device->fuse, 0x31c) & 0x00000001)) + return; + + nvkm_mask(device, 0x000200, 0x00001000, 0x00000000); + nvkm_rd32(device, 0x000200); + nvkm_mask(device, 0x000200, 0x08000000, 0x08000000); msleep(50); - nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000002); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000); + nvkm_mask(device, 0x10a78c, 0x00000002, 0x00000002); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000000); - nv_mask(pmu, 0x020004, 0xc0000000, enable ? 0xc0000000 : 0x40000000); + nvkm_mask(device, 0x020004, 0xc0000000, enable ? 0xc0000000 : 0x40000000); msleep(50); - nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000000); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000); + nvkm_mask(device, 0x10a78c, 0x00000002, 0x00000000); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000000); + + nvkm_mask(device, 0x000200, 0x08000000, 0x00000000); + nvkm_mask(device, 0x000200, 0x00001000, 0x00001000); + nvkm_rd32(device, 0x000200); - nv_mask(pmu, 0x000200, 0x08000000, 0x00000000); - nv_mask(pmu, 0x000200, 0x00001000, 0x00001000); - nv_rd32(pmu, 0x000200); + if (nvkm_boolopt(device->cfgopt, "War00C800_0", true)) { + switch (device->chipset) { + case 0xe4: + magic(device, 0x04000000); + magic(device, 0x06000000); + magic(device, 0x0c000000); + magic(device, 0x0e000000); + break; + case 0xe6: + magic(device, 0x02000000); + magic(device, 0x04000000); + magic(device, 0x0a000000); + break; + case 0xe7: + magic(device, 0x02000000); + break; + default: + break; + } + } } -struct nvkm_oclass * -gk104_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0xe4), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = _nvkm_pmu_init, - .fini = _nvkm_pmu_fini, - }, +static const struct nvkm_pmu_func +gk104_pmu = { .code.data = gk104_pmu_code, .code.size = sizeof(gk104_pmu_code), .data.data = gk104_pmu_data, .data.size = sizeof(gk104_pmu_data), .pgob = gk104_pmu_pgob, -}.base; +}; + +int +gk104_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gk104_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c index 89bb94b0a..ae255247c 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c @@ -21,16 +21,17 @@ * * Authors: Ben Skeggs */ -#define gf110_pmu_code gk110_pmu_code -#define gf110_pmu_data gk110_pmu_data +#define gf119_pmu_code gk110_pmu_code +#define gf119_pmu_data gk110_pmu_data #include "priv.h" -#include "fuc/gf110.fuc4.h" +#include "fuc/gf119.fuc4.h" #include void gk110_pmu_pgob(struct nvkm_pmu *pmu, bool enable) { + struct nvkm_device *device = pmu->subdev.device; static const struct { u32 addr; u32 data; @@ -54,42 +55,44 @@ gk110_pmu_pgob(struct nvkm_pmu *pmu, bool enable) }; int i; - nv_mask(pmu, 0x000200, 0x00001000, 0x00000000); - nv_rd32(pmu, 0x000200); - nv_mask(pmu, 0x000200, 0x08000000, 0x08000000); + nvkm_mask(device, 0x000200, 0x00001000, 0x00000000); + nvkm_rd32(device, 0x000200); + nvkm_mask(device, 0x000200, 0x08000000, 0x08000000); msleep(50); - nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000002); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000); + nvkm_mask(device, 0x10a78c, 0x00000002, 0x00000002); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000000); - nv_mask(pmu, 0x0206b4, 0x00000000, 0x00000000); + nvkm_mask(device, 0x0206b4, 0x00000000, 0x00000000); for (i = 0; i < ARRAY_SIZE(magic); i++) { - nv_wr32(pmu, magic[i].addr, magic[i].data); - nv_wait(pmu, magic[i].addr, 0x80000000, 0x00000000); + nvkm_wr32(device, magic[i].addr, magic[i].data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, magic[i].addr) & 0x80000000)) + break; + ); } - nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000000); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001); - nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000); + nvkm_mask(device, 0x10a78c, 0x00000002, 0x00000000); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000001); + nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000000); - nv_mask(pmu, 0x000200, 0x08000000, 0x00000000); - nv_mask(pmu, 0x000200, 0x00001000, 0x00001000); - nv_rd32(pmu, 0x000200); + nvkm_mask(device, 0x000200, 0x08000000, 0x00000000); + nvkm_mask(device, 0x000200, 0x00001000, 0x00001000); + nvkm_rd32(device, 0x000200); } -struct nvkm_oclass * -gk110_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0xf0), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = _nvkm_pmu_init, - .fini = _nvkm_pmu_fini, - }, +static const struct nvkm_pmu_func +gk110_pmu = { .code.data = gk110_pmu_code, .code.size = sizeof(gk110_pmu_code), .data.data = gk110_pmu_data, .data.size = sizeof(gk110_pmu_data), .pgob = gk110_pmu_pgob, -}.base; +}; + +int +gk110_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gk110_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c index b14134ef9..3b4917637 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c @@ -24,18 +24,17 @@ #include "priv.h" #include "fuc/gk208.fuc5.h" -struct nvkm_oclass * -gk208_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0x00), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = _nvkm_pmu_init, - .fini = _nvkm_pmu_fini, - }, +static const struct nvkm_pmu_func +gk208_pmu = { .code.data = gk208_pmu_code, .code.size = sizeof(gk208_pmu_code), .data.data = gk208_pmu_data, .data.size = sizeof(gk208_pmu_data), .pgob = gk110_pmu_pgob, -}.base; +}; + +int +gk208_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gk208_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c index 594f746e6..6689d0290 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +#define gk20a_pmu(p) container_of((p), struct gk20a_pmu, base.subdev) #include "priv.h" #include @@ -35,7 +36,7 @@ struct gk20a_pmu_dvfs_data { unsigned int avg_load; }; -struct gk20a_pmu_priv { +struct gk20a_pmu { struct nvkm_pmu base; struct nvkm_alarm alarm; struct gk20a_pmu_dvfs_data *data; @@ -48,28 +49,28 @@ struct gk20a_pmu_dvfs_dev_status { }; static int -gk20a_pmu_dvfs_target(struct gk20a_pmu_priv *priv, int *state) +gk20a_pmu_dvfs_target(struct gk20a_pmu *pmu, int *state) { - struct nvkm_clk *clk = nvkm_clk(priv); + struct nvkm_clk *clk = pmu->base.subdev.device->clk; return nvkm_clk_astate(clk, *state, 0, false); } static int -gk20a_pmu_dvfs_get_cur_state(struct gk20a_pmu_priv *priv, int *state) +gk20a_pmu_dvfs_get_cur_state(struct gk20a_pmu *pmu, int *state) { - struct nvkm_clk *clk = nvkm_clk(priv); + struct nvkm_clk *clk = pmu->base.subdev.device->clk; *state = clk->pstate; return 0; } static int -gk20a_pmu_dvfs_get_target_state(struct gk20a_pmu_priv *priv, +gk20a_pmu_dvfs_get_target_state(struct gk20a_pmu *pmu, int *state, int load) { - struct gk20a_pmu_dvfs_data *data = priv->data; - struct nvkm_clk *clk = nvkm_clk(priv); + struct gk20a_pmu_dvfs_data *data = pmu->data; + struct nvkm_clk *clk = pmu->base.subdev.device->clk; int cur_level, level; /* For GK20A, the performance level is directly mapped to pstate */ @@ -84,7 +85,8 @@ gk20a_pmu_dvfs_get_target_state(struct gk20a_pmu_priv *priv, level = min(clk->state_nr - 1, level); } - nv_trace(priv, "cur level = %d, new level = %d\n", cur_level, level); + nvkm_trace(&pmu->base.subdev, "cur level = %d, new level = %d\n", + cur_level, level); *state = level; @@ -95,30 +97,35 @@ gk20a_pmu_dvfs_get_target_state(struct gk20a_pmu_priv *priv, } static int -gk20a_pmu_dvfs_get_dev_status(struct gk20a_pmu_priv *priv, +gk20a_pmu_dvfs_get_dev_status(struct gk20a_pmu *pmu, struct gk20a_pmu_dvfs_dev_status *status) { - status->busy = nv_rd32(priv, 0x10a508 + (BUSY_SLOT * 0x10)); - status->total= nv_rd32(priv, 0x10a508 + (CLK_SLOT * 0x10)); + struct nvkm_device *device = pmu->base.subdev.device; + status->busy = nvkm_rd32(device, 0x10a508 + (BUSY_SLOT * 0x10)); + status->total= nvkm_rd32(device, 0x10a508 + (CLK_SLOT * 0x10)); return 0; } static void -gk20a_pmu_dvfs_reset_dev_status(struct gk20a_pmu_priv *priv) +gk20a_pmu_dvfs_reset_dev_status(struct gk20a_pmu *pmu) { - nv_wr32(priv, 0x10a508 + (BUSY_SLOT * 0x10), 0x80000000); - nv_wr32(priv, 0x10a508 + (CLK_SLOT * 0x10), 0x80000000); + struct nvkm_device *device = pmu->base.subdev.device; + nvkm_wr32(device, 0x10a508 + (BUSY_SLOT * 0x10), 0x80000000); + nvkm_wr32(device, 0x10a508 + (CLK_SLOT * 0x10), 0x80000000); } static void gk20a_pmu_dvfs_work(struct nvkm_alarm *alarm) { - struct gk20a_pmu_priv *priv = - container_of(alarm, struct gk20a_pmu_priv, alarm); - struct gk20a_pmu_dvfs_data *data = priv->data; + struct gk20a_pmu *pmu = + container_of(alarm, struct gk20a_pmu, alarm); + struct gk20a_pmu_dvfs_data *data = pmu->data; struct gk20a_pmu_dvfs_dev_status status; - struct nvkm_clk *clk = nvkm_clk(priv); - struct nvkm_volt *volt = nvkm_volt(priv); + struct nvkm_subdev *subdev = &pmu->base.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_clk *clk = device->clk; + struct nvkm_timer *tmr = device->timer; + struct nvkm_volt *volt = device->volt; u32 utilization = 0; int state, ret; @@ -129,9 +136,9 @@ gk20a_pmu_dvfs_work(struct nvkm_alarm *alarm) if (!clk || !volt) goto resched; - ret = gk20a_pmu_dvfs_get_dev_status(priv, &status); + ret = gk20a_pmu_dvfs_get_dev_status(pmu, &status); if (ret) { - nv_warn(priv, "failed to get device status\n"); + nvkm_warn(subdev, "failed to get device status\n"); goto resched; } @@ -140,56 +147,52 @@ gk20a_pmu_dvfs_work(struct nvkm_alarm *alarm) data->avg_load = (data->p_smooth * data->avg_load) + utilization; data->avg_load /= data->p_smooth + 1; - nv_trace(priv, "utilization = %d %%, avg_load = %d %%\n", - utilization, data->avg_load); + nvkm_trace(subdev, "utilization = %d %%, avg_load = %d %%\n", + utilization, data->avg_load); - ret = gk20a_pmu_dvfs_get_cur_state(priv, &state); + ret = gk20a_pmu_dvfs_get_cur_state(pmu, &state); if (ret) { - nv_warn(priv, "failed to get current state\n"); + nvkm_warn(subdev, "failed to get current state\n"); goto resched; } - if (gk20a_pmu_dvfs_get_target_state(priv, &state, data->avg_load)) { - nv_trace(priv, "set new state to %d\n", state); - gk20a_pmu_dvfs_target(priv, &state); + if (gk20a_pmu_dvfs_get_target_state(pmu, &state, data->avg_load)) { + nvkm_trace(subdev, "set new state to %d\n", state); + gk20a_pmu_dvfs_target(pmu, &state); } resched: - gk20a_pmu_dvfs_reset_dev_status(priv); - nvkm_timer_alarm(priv, 100000000, alarm); + gk20a_pmu_dvfs_reset_dev_status(pmu); + nvkm_timer_alarm(tmr, 100000000, alarm); } static int -gk20a_pmu_fini(struct nvkm_object *object, bool suspend) +gk20a_pmu_fini(struct nvkm_subdev *subdev, bool suspend) { - struct nvkm_pmu *pmu = (void *)object; - struct gk20a_pmu_priv *priv = (void *)pmu; - - nvkm_timer_alarm_cancel(priv, &priv->alarm); + struct gk20a_pmu *pmu = gk20a_pmu(subdev); + nvkm_timer_alarm_cancel(subdev->device->timer, &pmu->alarm); + return 0; +} - return nvkm_subdev_fini(&pmu->base, suspend); +static void * +gk20a_pmu_dtor(struct nvkm_subdev *subdev) +{ + return gk20a_pmu(subdev); } static int -gk20a_pmu_init(struct nvkm_object *object) +gk20a_pmu_init(struct nvkm_subdev *subdev) { - struct nvkm_pmu *pmu = (void *)object; - struct gk20a_pmu_priv *priv = (void *)pmu; - int ret; - - ret = nvkm_subdev_init(&pmu->base); - if (ret) - return ret; - - pmu->pgob = nvkm_pmu_pgob; + struct gk20a_pmu *pmu = gk20a_pmu(subdev); + struct nvkm_device *device = pmu->base.subdev.device; /* init pwr perf counter */ - nv_wr32(pmu, 0x10a504 + (BUSY_SLOT * 0x10), 0x00200001); - nv_wr32(pmu, 0x10a50c + (BUSY_SLOT * 0x10), 0x00000002); - nv_wr32(pmu, 0x10a50c + (CLK_SLOT * 0x10), 0x00000003); + nvkm_wr32(device, 0x10a504 + (BUSY_SLOT * 0x10), 0x00200001); + nvkm_wr32(device, 0x10a50c + (BUSY_SLOT * 0x10), 0x00000002); + nvkm_wr32(device, 0x10a50c + (CLK_SLOT * 0x10), 0x00000003); - nvkm_timer_alarm(pmu, 2000000000, &priv->alarm); - return ret; + nvkm_timer_alarm(device->timer, 2000000000, &pmu->alarm); + return 0; } static struct gk20a_pmu_dvfs_data @@ -199,32 +202,26 @@ gk20a_dvfs_data= { .p_smooth = 1, }; -static int -gk20a_pmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gk20a_pmu_priv *priv; - int ret; +static const struct nvkm_subdev_func +gk20a_pmu = { + .init = gk20a_pmu_init, + .fini = gk20a_pmu_fini, + .dtor = gk20a_pmu_dtor, +}; - ret = nvkm_pmu_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +int +gk20a_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + static const struct nvkm_pmu_func func = {}; + struct gk20a_pmu *pmu; - priv->data = &gk20a_dvfs_data; + if (!(pmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) + return -ENOMEM; + pmu->base.func = &func; + *ppmu = &pmu->base; - nvkm_alarm_init(&priv->alarm, gk20a_pmu_dvfs_work); + nvkm_subdev_ctor(&gk20a_pmu, device, index, 0, &pmu->base.subdev); + pmu->data = &gk20a_dvfs_data; + nvkm_alarm_init(&pmu->alarm, gk20a_pmu_dvfs_work); return 0; } - -struct nvkm_oclass * -gk20a_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0xea), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = gk20a_pmu_init, - .fini = gk20a_pmu_fini, - }, -}.base; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c new file mode 100644 index 000000000..31b8692b4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c @@ -0,0 +1,41 @@ +/* + * Copyright 2013 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 "priv.h" +#define gk208_pmu_code gm107_pmu_code +#define gk208_pmu_data gm107_pmu_data +#include "fuc/gk208.fuc5.h" + +static const struct nvkm_pmu_func +gm107_pmu = { + .code.data = gm107_pmu_code, + .code.size = sizeof(gm107_pmu_code), + .data.data = gm107_pmu_data, + .data.size = sizeof(gm107_pmu_data), +}; + +int +gm107_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gm107_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index 30aaeb21d..8ba7fa4ca 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -24,26 +24,25 @@ #include "priv.h" #include "fuc/gt215.fuc3.h" -static int -gt215_pmu_init(struct nvkm_object *object) +static void +gt215_pmu_reset(struct nvkm_pmu *pmu) { - struct nvkm_pmu *pmu = (void *)object; - nv_mask(pmu, 0x022210, 0x00000001, 0x00000000); - nv_mask(pmu, 0x022210, 0x00000001, 0x00000001); - return nvkm_pmu_init(pmu); + struct nvkm_device *device = pmu->subdev.device; + nvkm_mask(device, 0x022210, 0x00000001, 0x00000000); + nvkm_mask(device, 0x022210, 0x00000001, 0x00000001); } -struct nvkm_oclass * -gt215_pmu_oclass = &(struct nvkm_pmu_impl) { - .base.handle = NV_SUBDEV(PMU, 0xa3), - .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = _nvkm_pmu_ctor, - .dtor = _nvkm_pmu_dtor, - .init = gt215_pmu_init, - .fini = _nvkm_pmu_fini, - }, +static const struct nvkm_pmu_func +gt215_pmu = { + .reset = gt215_pmu_reset, .code.data = gt215_pmu_code, .code.size = sizeof(gt215_pmu_code), .data.data = gt215_pmu_data, .data.size = sizeof(gt215_pmu_data), -}.base; +}; + +int +gt215_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(>215_pmu, device, index, ppmu); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c index b75c5b885..e6f741682 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c @@ -2,8 +2,6 @@ #define __NVKM_PMU_MEMX_H__ #include "priv.h" -#include - struct nvkm_memx { struct nvkm_pmu *pmu; u32 base; @@ -18,13 +16,13 @@ struct nvkm_memx { static void memx_out(struct nvkm_memx *memx) { - struct nvkm_pmu *pmu = memx->pmu; + struct nvkm_device *device = memx->pmu->subdev.device; int i; if (memx->c.mthd) { - nv_wr32(pmu, 0x10a1c4, (memx->c.size << 16) | memx->c.mthd); + nvkm_wr32(device, 0x10a1c4, (memx->c.size << 16) | memx->c.mthd); for (i = 0; i < memx->c.size; i++) - nv_wr32(pmu, 0x10a1c4, memx->c.data[i]); + nvkm_wr32(device, 0x10a1c4, memx->c.data[i]); memx->c.mthd = 0; memx->c.size = 0; } @@ -44,12 +42,13 @@ memx_cmd(struct nvkm_memx *memx, u32 mthd, u32 size, u32 data[]) int nvkm_memx_init(struct nvkm_pmu *pmu, struct nvkm_memx **pmemx) { + struct nvkm_device *device = pmu->subdev.device; struct nvkm_memx *memx; u32 reply[2]; int ret; - ret = pmu->message(pmu, reply, PROC_MEMX, MEMX_MSG_INFO, - MEMX_INFO_DATA, 0); + ret = nvkm_pmu_send(pmu, reply, PROC_MEMX, MEMX_MSG_INFO, + MEMX_INFO_DATA, 0); if (ret) return ret; @@ -62,9 +61,9 @@ nvkm_memx_init(struct nvkm_pmu *pmu, struct nvkm_memx **pmemx) /* acquire data segment access */ do { - nv_wr32(pmu, 0x10a580, 0x00000003); - } while (nv_rd32(pmu, 0x10a580) != 0x00000003); - nv_wr32(pmu, 0x10a1c0, 0x01000000 | memx->base); + nvkm_wr32(device, 0x10a580, 0x00000003); + } while (nvkm_rd32(device, 0x10a580) != 0x00000003); + nvkm_wr32(device, 0x10a1c0, 0x01000000 | memx->base); return 0; } @@ -73,23 +72,25 @@ nvkm_memx_fini(struct nvkm_memx **pmemx, bool exec) { struct nvkm_memx *memx = *pmemx; struct nvkm_pmu *pmu = memx->pmu; + struct nvkm_subdev *subdev = &pmu->subdev; + struct nvkm_device *device = subdev->device; u32 finish, reply[2]; /* flush the cache... */ memx_out(memx); /* release data segment access */ - finish = nv_rd32(pmu, 0x10a1c0) & 0x00ffffff; - nv_wr32(pmu, 0x10a580, 0x00000000); + finish = nvkm_rd32(device, 0x10a1c0) & 0x00ffffff; + nvkm_wr32(device, 0x10a580, 0x00000000); /* call MEMX process to execute the script, and wait for reply */ if (exec) { - pmu->message(pmu, reply, PROC_MEMX, MEMX_MSG_EXEC, - memx->base, finish); + nvkm_pmu_send(pmu, reply, PROC_MEMX, MEMX_MSG_EXEC, + memx->base, finish); } - nv_debug(memx->pmu, "Exec took %uns, PMU_IN %08x\n", - reply[0], reply[1]); + nvkm_debug(subdev, "Exec took %uns, PMU_IN %08x\n", + reply[0], reply[1]); kfree(memx); return 0; } @@ -97,7 +98,7 @@ nvkm_memx_fini(struct nvkm_memx **pmemx, bool exec) void nvkm_memx_wr32(struct nvkm_memx *memx, u32 addr, u32 data) { - nv_debug(memx->pmu, "R[%06x] = 0x%08x\n", addr, data); + nvkm_debug(&memx->pmu->subdev, "R[%06x] = %08x\n", addr, data); memx_cmd(memx, MEMX_WR32, 2, (u32[]){ addr, data }); } @@ -105,8 +106,8 @@ void nvkm_memx_wait(struct nvkm_memx *memx, u32 addr, u32 mask, u32 data, u32 nsec) { - nv_debug(memx->pmu, "R[%06x] & 0x%08x == 0x%08x, %d us\n", - addr, mask, data, nsec); + nvkm_debug(&memx->pmu->subdev, "R[%06x] & %08x == %08x, %d us\n", + addr, mask, data, nsec); memx_cmd(memx, MEMX_WAIT, 4, (u32[]){ addr, mask, data, nsec }); memx_out(memx); /* fuc can't handle multiple */ } @@ -114,7 +115,7 @@ nvkm_memx_wait(struct nvkm_memx *memx, void nvkm_memx_nsec(struct nvkm_memx *memx, u32 nsec) { - nv_debug(memx->pmu, " DELAY = %d ns\n", nsec); + nvkm_debug(&memx->pmu->subdev, " DELAY = %d ns\n", nsec); memx_cmd(memx, MEMX_DELAY, 1, (u32[]){ nsec }); memx_out(memx); /* fuc can't handle multiple */ } @@ -122,16 +123,17 @@ nvkm_memx_nsec(struct nvkm_memx *memx, u32 nsec) void nvkm_memx_wait_vblank(struct nvkm_memx *memx) { - struct nvkm_pmu *pmu = memx->pmu; + struct nvkm_subdev *subdev = &memx->pmu->subdev; + struct nvkm_device *device = subdev->device; u32 heads, x, y, px = 0; int i, head_sync; - if (nv_device(pmu)->chipset < 0xd0) { - heads = nv_rd32(pmu, 0x610050); + if (device->chipset < 0xd0) { + heads = nvkm_rd32(device, 0x610050); for (i = 0; i < 2; i++) { /* Heuristic: sync to head with biggest resolution */ if (heads & (2 << (i << 3))) { - x = nv_rd32(pmu, 0x610b40 + (0x540 * i)); + x = nvkm_rd32(device, 0x610b40 + (0x540 * i)); y = (x & 0xffff0000) >> 16; x &= 0x0000ffff; if ((x * y) > px) { @@ -143,11 +145,11 @@ nvkm_memx_wait_vblank(struct nvkm_memx *memx) } if (px == 0) { - nv_debug(memx->pmu, "WAIT VBLANK !NO ACTIVE HEAD\n"); + nvkm_debug(subdev, "WAIT VBLANK !NO ACTIVE HEAD\n"); return; } - nv_debug(memx->pmu, "WAIT VBLANK HEAD%d\n", head_sync); + nvkm_debug(subdev, "WAIT VBLANK HEAD%d\n", head_sync); memx_cmd(memx, MEMX_VBLANK, 1, (u32[]){ head_sync }); memx_out(memx); /* fuc can't handle multiple */ } @@ -155,18 +157,19 @@ nvkm_memx_wait_vblank(struct nvkm_memx *memx) void nvkm_memx_train(struct nvkm_memx *memx) { - nv_debug(memx->pmu, " MEM TRAIN\n"); + nvkm_debug(&memx->pmu->subdev, " MEM TRAIN\n"); memx_cmd(memx, MEMX_TRAIN, 0, NULL); } int nvkm_memx_train_result(struct nvkm_pmu *pmu, u32 *res, int rsize) { + struct nvkm_device *device = pmu->subdev.device; u32 reply[2], base, size, i; int ret; - ret = pmu->message(pmu, reply, PROC_MEMX, MEMX_MSG_INFO, - MEMX_INFO_TRAIN, 0); + ret = nvkm_pmu_send(pmu, reply, PROC_MEMX, MEMX_MSG_INFO, + MEMX_INFO_TRAIN, 0); if (ret) return ret; @@ -176,10 +179,10 @@ nvkm_memx_train_result(struct nvkm_pmu *pmu, u32 *res, int rsize) return -ENOMEM; /* read the packet */ - nv_wr32(pmu, 0x10a1c0, 0x02000000 | base); + nvkm_wr32(device, 0x10a1c0, 0x02000000 | base); for (i = 0; i < size; i++) - res[i] = nv_rd32(pmu, 0x10a1c4); + res[i] = nvkm_rd32(device, 0x10a1c4); return 0; } @@ -187,14 +190,14 @@ nvkm_memx_train_result(struct nvkm_pmu *pmu, u32 *res, int rsize) void nvkm_memx_block(struct nvkm_memx *memx) { - nv_debug(memx->pmu, " HOST BLOCKED\n"); + nvkm_debug(&memx->pmu->subdev, " HOST BLOCKED\n"); memx_cmd(memx, MEMX_ENTER, 0, NULL); } void nvkm_memx_unblock(struct nvkm_memx *memx) { - nv_debug(memx->pmu, " HOST UNBLOCKED\n"); + nvkm_debug(&memx->pmu->subdev, " HOST UNBLOCKED\n"); memx_cmd(memx, MEMX_LEAVE, 0, NULL); } #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 799e7c8b8..f38c88fae 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -1,38 +1,20 @@ #ifndef __NVKM_PMU_PRIV_H__ #define __NVKM_PMU_PRIV_H__ +#define nvkm_pmu(p) container_of((p), struct nvkm_pmu, subdev) #include #include -#define nvkm_pmu_create(p, e, o, d) \ - nvkm_pmu_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nvkm_pmu_destroy(p) \ - nvkm_subdev_destroy(&(p)->base) -#define nvkm_pmu_init(p) ({ \ - struct nvkm_pmu *_pmu = (p); \ - _nvkm_pmu_init(nv_object(_pmu)); \ -}) -#define nvkm_pmu_fini(p,s) ({ \ - struct nvkm_pmu *_pmu = (p); \ - _nvkm_pmu_fini(nv_object(_pmu), (s)); \ -}) +int nvkm_pmu_new_(const struct nvkm_pmu_func *, struct nvkm_device *, + int index, struct nvkm_pmu **); -int nvkm_pmu_create_(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, int, void **); +struct nvkm_pmu_func { + void (*reset)(struct nvkm_pmu *); -int _nvkm_pmu_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -#define _nvkm_pmu_dtor _nvkm_subdev_dtor -int _nvkm_pmu_init(struct nvkm_object *); -int _nvkm_pmu_fini(struct nvkm_object *, bool); -void nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable); - -struct nvkm_pmu_impl { - struct nvkm_oclass base; struct { u32 *data; u32 size; } code; + struct { u32 *data; u32 size; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild index 5837cf129..135758ba3 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild @@ -9,5 +9,5 @@ nvkm-y += nvkm/subdev/therm/nv40.o nvkm-y += nvkm/subdev/therm/nv50.o nvkm-y += nvkm/subdev/therm/g84.o nvkm-y += nvkm/subdev/therm/gt215.o -nvkm-y += nvkm/subdev/therm/gf110.o +nvkm-y += nvkm/subdev/therm/gf119.o nvkm-y += nvkm/subdev/therm/gm107.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index ec327cb64..949dc6101 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -23,21 +23,26 @@ */ #include "priv.h" -#include +int +nvkm_therm_temp_get(struct nvkm_therm *therm) +{ + if (therm->func->temp_get) + return therm->func->temp_get(therm); + return -ENODEV; +} static int nvkm_therm_update_trip(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_trip_point *trip = priv->fan->bios.trip, + struct nvbios_therm_trip_point *trip = therm->fan->bios.trip, *cur_trip = NULL, - *last_trip = priv->last_trip; - u8 temp = therm->temp_get(therm); + *last_trip = therm->last_trip; + u8 temp = therm->func->temp_get(therm); u16 duty, i; /* look for the trip point corresponding to the current temperature */ cur_trip = NULL; - for (i = 0; i < priv->fan->bios.nr_fan_trip; i++) { + for (i = 0; i < therm->fan->bios.nr_fan_trip; i++) { if (temp >= trip[i].temp) cur_trip = &trip[i]; } @@ -49,10 +54,10 @@ nvkm_therm_update_trip(struct nvkm_therm *therm) if (cur_trip) { duty = cur_trip->fan_duty; - priv->last_trip = cur_trip; + therm->last_trip = cur_trip; } else { duty = 0; - priv->last_trip = NULL; + therm->last_trip = NULL; } return duty; @@ -61,51 +66,50 @@ nvkm_therm_update_trip(struct nvkm_therm *therm) static int nvkm_therm_update_linear(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - u8 linear_min_temp = priv->fan->bios.linear_min_temp; - u8 linear_max_temp = priv->fan->bios.linear_max_temp; - u8 temp = therm->temp_get(therm); + u8 linear_min_temp = therm->fan->bios.linear_min_temp; + u8 linear_max_temp = therm->fan->bios.linear_max_temp; + u8 temp = therm->func->temp_get(therm); u16 duty; /* handle the non-linear part first */ if (temp < linear_min_temp) - return priv->fan->bios.min_duty; + return therm->fan->bios.min_duty; else if (temp > linear_max_temp) - return priv->fan->bios.max_duty; + return therm->fan->bios.max_duty; /* we are in the linear zone */ duty = (temp - linear_min_temp); - duty *= (priv->fan->bios.max_duty - priv->fan->bios.min_duty); + duty *= (therm->fan->bios.max_duty - therm->fan->bios.min_duty); duty /= (linear_max_temp - linear_min_temp); - duty += priv->fan->bios.min_duty; + duty += therm->fan->bios.min_duty; return duty; } static void nvkm_therm_update(struct nvkm_therm *therm, int mode) { - struct nvkm_timer *ptimer = nvkm_timer(therm); - struct nvkm_therm_priv *priv = (void *)therm; + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_timer *tmr = subdev->device->timer; unsigned long flags; bool immd = true; bool poll = true; int duty = -1; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&therm->lock, flags); if (mode < 0) - mode = priv->mode; - priv->mode = mode; + mode = therm->mode; + therm->mode = mode; switch (mode) { case NVKM_THERM_CTRL_MANUAL: - ptimer->alarm_cancel(ptimer, &priv->alarm); + nvkm_timer_alarm_cancel(tmr, &therm->alarm); duty = nvkm_therm_fan_get(therm); if (duty < 0) duty = 100; poll = false; break; case NVKM_THERM_CTRL_AUTO: - switch(priv->fan->bios.fan_mode) { + switch(therm->fan->bios.fan_mode) { case NVBIOS_THERM_FAN_TRIP: duty = nvkm_therm_update_trip(therm); break; @@ -113,8 +117,8 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) duty = nvkm_therm_update_linear(therm); break; case NVBIOS_THERM_FAN_OTHER: - if (priv->cstate) - duty = priv->cstate; + if (therm->cstate) + duty = therm->cstate; poll = false; break; } @@ -122,29 +126,29 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) break; case NVKM_THERM_CTRL_NONE: default: - ptimer->alarm_cancel(ptimer, &priv->alarm); + nvkm_timer_alarm_cancel(tmr, &therm->alarm); poll = false; } - if (list_empty(&priv->alarm.head) && poll) - ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); - spin_unlock_irqrestore(&priv->lock, flags); + if (list_empty(&therm->alarm.head) && poll) + nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm); + spin_unlock_irqrestore(&therm->lock, flags); if (duty >= 0) { - nv_debug(therm, "FAN target request: %d%%\n", duty); + nvkm_debug(subdev, "FAN target request: %d%%\n", duty); nvkm_therm_fan_set(therm, immd, duty); } } int -nvkm_therm_cstate(struct nvkm_therm *ptherm, int fan, int dir) +nvkm_therm_cstate(struct nvkm_therm *therm, int fan, int dir) { - struct nvkm_therm_priv *priv = (void *)ptherm; - if (!dir || (dir < 0 && fan < priv->cstate) || - (dir > 0 && fan > priv->cstate)) { - nv_debug(ptherm, "default fan speed -> %d%%\n", fan); - priv->cstate = fan; - nvkm_therm_update(ptherm, -1); + struct nvkm_subdev *subdev = &therm->subdev; + if (!dir || (dir < 0 && fan < therm->cstate) || + (dir > 0 && fan > therm->cstate)) { + nvkm_debug(subdev, "default fan speed -> %d%%\n", fan); + therm->cstate = fan; + nvkm_therm_update(therm, -1); } return 0; } @@ -152,16 +156,16 @@ nvkm_therm_cstate(struct nvkm_therm *ptherm, int fan, int dir) static void nvkm_therm_alarm(struct nvkm_alarm *alarm) { - struct nvkm_therm_priv *priv = - container_of(alarm, struct nvkm_therm_priv, alarm); - nvkm_therm_update(&priv->base, -1); + struct nvkm_therm *therm = + container_of(alarm, struct nvkm_therm, alarm); + nvkm_therm_update(therm, -1); } int nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_device *device = nv_device(therm); + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; static const char *name[] = { "disabled", "manual", @@ -171,51 +175,49 @@ nvkm_therm_fan_mode(struct nvkm_therm *therm, int mode) /* The default PPWR ucode on fermi interferes with fan management */ if ((mode >= ARRAY_SIZE(name)) || (mode != NVKM_THERM_CTRL_NONE && device->card_type >= NV_C0 && - !nvkm_subdev(device, NVDEV_SUBDEV_PMU))) + !device->pmu)) return -EINVAL; /* do not allow automatic fan management if the thermal sensor is * not available */ - if (mode == NVKM_THERM_CTRL_AUTO && therm->temp_get(therm) < 0) + if (mode == NVKM_THERM_CTRL_AUTO && + therm->func->temp_get(therm) < 0) return -EINVAL; - if (priv->mode == mode) + if (therm->mode == mode) return 0; - nv_info(therm, "fan management: %s\n", name[mode]); + nvkm_debug(subdev, "fan management: %s\n", name[mode]); nvkm_therm_update(therm, mode); return 0; } int -nvkm_therm_attr_get(struct nvkm_therm *therm, - enum nvkm_therm_attr_type type) +nvkm_therm_attr_get(struct nvkm_therm *therm, enum nvkm_therm_attr_type type) { - struct nvkm_therm_priv *priv = (void *)therm; - switch (type) { case NVKM_THERM_ATTR_FAN_MIN_DUTY: - return priv->fan->bios.min_duty; + return therm->fan->bios.min_duty; case NVKM_THERM_ATTR_FAN_MAX_DUTY: - return priv->fan->bios.max_duty; + return therm->fan->bios.max_duty; case NVKM_THERM_ATTR_FAN_MODE: - return priv->mode; + return therm->mode; case NVKM_THERM_ATTR_THRS_FAN_BOOST: - return priv->bios_sensor.thrs_fan_boost.temp; + return therm->bios_sensor.thrs_fan_boost.temp; case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST: - return priv->bios_sensor.thrs_fan_boost.hysteresis; + return therm->bios_sensor.thrs_fan_boost.hysteresis; case NVKM_THERM_ATTR_THRS_DOWN_CLK: - return priv->bios_sensor.thrs_down_clock.temp; + return therm->bios_sensor.thrs_down_clock.temp; case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST: - return priv->bios_sensor.thrs_down_clock.hysteresis; + return therm->bios_sensor.thrs_down_clock.hysteresis; case NVKM_THERM_ATTR_THRS_CRITICAL: - return priv->bios_sensor.thrs_critical.temp; + return therm->bios_sensor.thrs_critical.temp; case NVKM_THERM_ATTR_THRS_CRITICAL_HYST: - return priv->bios_sensor.thrs_critical.hysteresis; + return therm->bios_sensor.thrs_critical.hysteresis; case NVKM_THERM_ATTR_THRS_SHUTDOWN: - return priv->bios_sensor.thrs_shutdown.temp; + return therm->bios_sensor.thrs_shutdown.temp; case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST: - return priv->bios_sensor.thrs_shutdown.hysteresis; + return therm->bios_sensor.thrs_shutdown.hysteresis; } return -EINVAL; @@ -225,143 +227,156 @@ int nvkm_therm_attr_set(struct nvkm_therm *therm, enum nvkm_therm_attr_type type, int value) { - struct nvkm_therm_priv *priv = (void *)therm; - switch (type) { case NVKM_THERM_ATTR_FAN_MIN_DUTY: if (value < 0) value = 0; - if (value > priv->fan->bios.max_duty) - value = priv->fan->bios.max_duty; - priv->fan->bios.min_duty = value; + if (value > therm->fan->bios.max_duty) + value = therm->fan->bios.max_duty; + therm->fan->bios.min_duty = value; return 0; case NVKM_THERM_ATTR_FAN_MAX_DUTY: if (value < 0) value = 0; - if (value < priv->fan->bios.min_duty) - value = priv->fan->bios.min_duty; - priv->fan->bios.max_duty = value; + if (value < therm->fan->bios.min_duty) + value = therm->fan->bios.min_duty; + therm->fan->bios.max_duty = value; return 0; case NVKM_THERM_ATTR_FAN_MODE: return nvkm_therm_fan_mode(therm, value); case NVKM_THERM_ATTR_THRS_FAN_BOOST: - priv->bios_sensor.thrs_fan_boost.temp = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_fan_boost.temp = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST: - priv->bios_sensor.thrs_fan_boost.hysteresis = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_fan_boost.hysteresis = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_DOWN_CLK: - priv->bios_sensor.thrs_down_clock.temp = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_down_clock.temp = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST: - priv->bios_sensor.thrs_down_clock.hysteresis = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_down_clock.hysteresis = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_CRITICAL: - priv->bios_sensor.thrs_critical.temp = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_critical.temp = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_CRITICAL_HYST: - priv->bios_sensor.thrs_critical.hysteresis = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_critical.hysteresis = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_SHUTDOWN: - priv->bios_sensor.thrs_shutdown.temp = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_shutdown.temp = value; + therm->func->program_alarms(therm); return 0; case NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST: - priv->bios_sensor.thrs_shutdown.hysteresis = value; - priv->sensor.program_alarms(therm); + therm->bios_sensor.thrs_shutdown.hysteresis = value; + therm->func->program_alarms(therm); return 0; } return -EINVAL; } -int -_nvkm_therm_init(struct nvkm_object *object) +static void +nvkm_therm_intr(struct nvkm_subdev *subdev) { - struct nvkm_therm *therm = (void *)object; - struct nvkm_therm_priv *priv = (void *)therm; - int ret; - - ret = nvkm_subdev_init(&therm->base); - if (ret) - return ret; - - if (priv->suspend >= 0) { - /* restore the pwm value only when on manual or auto mode */ - if (priv->suspend > 0) - nvkm_therm_fan_set(therm, true, priv->fan->percent); - - nvkm_therm_fan_mode(therm, priv->suspend); - } - nvkm_therm_sensor_init(therm); - nvkm_therm_fan_init(therm); - return 0; + struct nvkm_therm *therm = nvkm_therm(subdev); + if (therm->func->intr) + therm->func->intr(therm); } -int -_nvkm_therm_fini(struct nvkm_object *object, bool suspend) +static int +nvkm_therm_fini(struct nvkm_subdev *subdev, bool suspend) { - struct nvkm_therm *therm = (void *)object; - struct nvkm_therm_priv *priv = (void *)therm; + struct nvkm_therm *therm = nvkm_therm(subdev); + + if (therm->func->fini) + therm->func->fini(therm); nvkm_therm_fan_fini(therm, suspend); nvkm_therm_sensor_fini(therm, suspend); + if (suspend) { - priv->suspend = priv->mode; - priv->mode = NVKM_THERM_CTRL_NONE; + therm->suspend = therm->mode; + therm->mode = NVKM_THERM_CTRL_NONE; } - return nvkm_subdev_fini(&therm->base, suspend); -} - -int -nvkm_therm_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) -{ - struct nvkm_therm_priv *priv; - int ret; - - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "PTHERM", - "therm", length, pobject); - priv = *pobject; - if (ret) - return ret; - - nvkm_alarm_init(&priv->alarm, nvkm_therm_alarm); - spin_lock_init(&priv->lock); - spin_lock_init(&priv->sensor.alarm_program_lock); - - priv->base.fan_get = nvkm_therm_fan_user_get; - priv->base.fan_set = nvkm_therm_fan_user_set; - priv->base.fan_sense = nvkm_therm_fan_sense; - priv->base.attr_get = nvkm_therm_attr_get; - priv->base.attr_set = nvkm_therm_attr_set; - priv->mode = priv->suspend = -1; /* undefined */ return 0; } -int -nvkm_therm_preinit(struct nvkm_therm *therm) +static int +nvkm_therm_oneinit(struct nvkm_subdev *subdev) { + struct nvkm_therm *therm = nvkm_therm(subdev); nvkm_therm_sensor_ctor(therm); nvkm_therm_ic_ctor(therm); nvkm_therm_fan_ctor(therm); - nvkm_therm_fan_mode(therm, NVKM_THERM_CTRL_AUTO); nvkm_therm_sensor_preinit(therm); return 0; } -void -_nvkm_therm_dtor(struct nvkm_object *object) +static int +nvkm_therm_init(struct nvkm_subdev *subdev) +{ + struct nvkm_therm *therm = nvkm_therm(subdev); + + therm->func->init(therm); + + if (therm->suspend >= 0) { + /* restore the pwm value only when on manual or auto mode */ + if (therm->suspend > 0) + nvkm_therm_fan_set(therm, true, therm->fan->percent); + + nvkm_therm_fan_mode(therm, therm->suspend); + } + + nvkm_therm_sensor_init(therm); + nvkm_therm_fan_init(therm); + return 0; +} + +static void * +nvkm_therm_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_therm *therm = nvkm_therm(subdev); + kfree(therm->fan); + return therm; +} + +static const struct nvkm_subdev_func +nvkm_therm = { + .dtor = nvkm_therm_dtor, + .oneinit = nvkm_therm_oneinit, + .init = nvkm_therm_init, + .fini = nvkm_therm_fini, + .intr = nvkm_therm_intr, +}; + +int +nvkm_therm_new_(const struct nvkm_therm_func *func, struct nvkm_device *device, + int index, struct nvkm_therm **ptherm) { - struct nvkm_therm_priv *priv = (void *)object; - kfree(priv->fan); - nvkm_subdev_destroy(&priv->base.base); + struct nvkm_therm *therm; + + if (!(therm = *ptherm = kzalloc(sizeof(*therm), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_therm, device, index, 0, &therm->subdev); + therm->func = func; + + nvkm_alarm_init(&therm->alarm, nvkm_therm_alarm); + spin_lock_init(&therm->lock); + spin_lock_init(&therm->sensor.alarm_program_lock); + + therm->fan_get = nvkm_therm_fan_user_get; + therm->fan_set = nvkm_therm_fan_user_set; + therm->attr_get = nvkm_therm_attr_get; + therm->attr_set = nvkm_therm_attr_set; + therm->mode = therm->suspend = -1; /* undefined */ + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c index 434fa745c..91198d793 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c @@ -32,8 +32,8 @@ static int nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) { struct nvkm_therm *therm = fan->parent; - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_timer *ptimer = nvkm_timer(priv); + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_timer *tmr = subdev->device->timer; unsigned long flags; int ret = 0; int duty; @@ -45,7 +45,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) target = max_t(u8, target, fan->bios.min_duty); target = min_t(u8, target, fan->bios.max_duty); if (fan->percent != target) { - nv_debug(therm, "FAN target: %d\n", target); + nvkm_debug(subdev, "FAN target: %d\n", target); fan->percent = target; } @@ -70,7 +70,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) duty = target; } - nv_debug(therm, "FAN update: %d\n", duty); + nvkm_debug(subdev, "FAN update: %d\n", duty); ret = fan->set(therm, duty); if (ret) { spin_unlock_irqrestore(&fan->lock, flags); @@ -95,7 +95,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) else delay = bump_period; - ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm); + nvkm_timer_alarm(tmr, delay * 1000 * 1000, &fan->alarm); } return ret; @@ -111,48 +111,51 @@ nvkm_fan_alarm(struct nvkm_alarm *alarm) int nvkm_therm_fan_get(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - return priv->fan->get(therm); + return therm->fan->get(therm); } int nvkm_therm_fan_set(struct nvkm_therm *therm, bool immediate, int percent) { - struct nvkm_therm_priv *priv = (void *)therm; - return nvkm_fan_update(priv->fan, immediate, percent); + return nvkm_fan_update(therm->fan, immediate, percent); } int nvkm_therm_fan_sense(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_timer *ptimer = nvkm_timer(therm); - struct nvkm_gpio *gpio = nvkm_gpio(therm); + struct nvkm_device *device = therm->subdev.device; + struct nvkm_timer *tmr = device->timer; + struct nvkm_gpio *gpio = device->gpio; u32 cycles, cur, prev; u64 start, end, tach; - if (priv->fan->tach.func == DCB_GPIO_UNUSED) + if (therm->func->fan_sense) + return therm->func->fan_sense(therm); + + if (therm->fan->tach.func == DCB_GPIO_UNUSED) return -ENODEV; /* Time a complete rotation and extrapolate to RPM: * When the fan spins, it changes the value of GPIO FAN_SENSE. * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation. */ - start = ptimer->read(ptimer); - prev = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line); + start = nvkm_timer_read(tmr); + prev = nvkm_gpio_get(gpio, 0, therm->fan->tach.func, + therm->fan->tach.line); cycles = 0; do { usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ - cur = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line); + cur = nvkm_gpio_get(gpio, 0, therm->fan->tach.func, + therm->fan->tach.line); if (prev != cur) { if (!start) - start = ptimer->read(ptimer); + start = nvkm_timer_read(tmr); cycles++; prev = cur; } - } while (cycles < 5 && ptimer->read(ptimer) - start < 250000000); - end = ptimer->read(ptimer); + } while (cycles < 5 && nvkm_timer_read(tmr) - start < 250000000); + end = nvkm_timer_read(tmr); if (cycles == 5) { tach = (u64)60000000000ULL; @@ -171,9 +174,7 @@ nvkm_therm_fan_user_get(struct nvkm_therm *therm) int nvkm_therm_fan_user_set(struct nvkm_therm *therm, int percent) { - struct nvkm_therm_priv *priv = (void *)therm; - - if (priv->mode != NVKM_THERM_CTRL_MANUAL) + if (therm->mode != NVKM_THERM_CTRL_MANUAL) return -EINVAL; return nvkm_therm_fan_set(therm, true, percent); @@ -182,29 +183,25 @@ nvkm_therm_fan_user_set(struct nvkm_therm *therm, int percent) static void nvkm_therm_fan_set_defaults(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - - priv->fan->bios.pwm_freq = 0; - priv->fan->bios.min_duty = 0; - priv->fan->bios.max_duty = 100; - priv->fan->bios.bump_period = 500; - priv->fan->bios.slow_down_period = 2000; - priv->fan->bios.linear_min_temp = 40; - priv->fan->bios.linear_max_temp = 85; + therm->fan->bios.pwm_freq = 0; + therm->fan->bios.min_duty = 0; + therm->fan->bios.max_duty = 100; + therm->fan->bios.bump_period = 500; + therm->fan->bios.slow_down_period = 2000; + therm->fan->bios.linear_min_temp = 40; + therm->fan->bios.linear_max_temp = 85; } static void nvkm_therm_fan_safety_checks(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; + if (therm->fan->bios.min_duty > 100) + therm->fan->bios.min_duty = 100; + if (therm->fan->bios.max_duty > 100) + therm->fan->bios.max_duty = 100; - if (priv->fan->bios.min_duty > 100) - priv->fan->bios.min_duty = 100; - if (priv->fan->bios.max_duty > 100) - priv->fan->bios.max_duty = 100; - - if (priv->fan->bios.min_duty > priv->fan->bios.max_duty) - priv->fan->bios.min_duty = priv->fan->bios.max_duty; + if (therm->fan->bios.min_duty > therm->fan->bios.max_duty) + therm->fan->bios.min_duty = therm->fan->bios.max_duty; } int @@ -216,29 +213,28 @@ nvkm_therm_fan_init(struct nvkm_therm *therm) int nvkm_therm_fan_fini(struct nvkm_therm *therm, bool suspend) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_timer *ptimer = nvkm_timer(therm); - + struct nvkm_timer *tmr = therm->subdev.device->timer; if (suspend) - ptimer->alarm_cancel(ptimer, &priv->fan->alarm); + nvkm_timer_alarm_cancel(tmr, &therm->fan->alarm); return 0; } int nvkm_therm_fan_ctor(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_gpio *gpio = nvkm_gpio(therm); - struct nvkm_bios *bios = nvkm_bios(therm); + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_gpio *gpio = device->gpio; + struct nvkm_bios *bios = device->bios; struct dcb_gpio_func func; int ret; /* attempt to locate a drivable fan, and determine control method */ - ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); + ret = nvkm_gpio_find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); if (ret == 0) { /* FIXME: is this really the place to perform such checks ? */ if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) { - nv_debug(therm, "GPIO_FAN is in input mode\n"); + nvkm_debug(subdev, "GPIO_FAN is in input mode\n"); ret = -EINVAL; } else { ret = nvkm_fanpwm_create(therm, &func); @@ -254,28 +250,29 @@ nvkm_therm_fan_ctor(struct nvkm_therm *therm) return ret; } - nv_info(therm, "FAN control: %s\n", priv->fan->type); + nvkm_debug(subdev, "FAN control: %s\n", therm->fan->type); /* read the current speed, it is useful when resuming */ - priv->fan->percent = nvkm_therm_fan_get(therm); + therm->fan->percent = nvkm_therm_fan_get(therm); /* attempt to detect a tachometer connection */ - ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); + ret = nvkm_gpio_find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, + &therm->fan->tach); if (ret) - priv->fan->tach.func = DCB_GPIO_UNUSED; + therm->fan->tach.func = DCB_GPIO_UNUSED; /* initialise fan bump/slow update handling */ - priv->fan->parent = therm; - nvkm_alarm_init(&priv->fan->alarm, nvkm_fan_alarm); - spin_lock_init(&priv->fan->lock); + therm->fan->parent = therm; + nvkm_alarm_init(&therm->fan->alarm, nvkm_fan_alarm); + spin_lock_init(&therm->fan->lock); /* other random init... */ nvkm_therm_fan_set_defaults(therm); - nvbios_perf_fan_parse(bios, &priv->fan->perf); - if (!nvbios_fan_parse(bios, &priv->fan->bios)) { - nv_debug(therm, "parsing the fan table failed\n"); - if (nvbios_therm_fan_parse(bios, &priv->fan->bios)) - nv_error(therm, "parsing both fan tables failed\n"); + nvbios_perf_fan_parse(bios, &therm->fan->perf); + if (!nvbios_fan_parse(bios, &therm->fan->bios)) { + nvkm_debug(subdev, "parsing the fan table failed\n"); + if (nvbios_therm_fan_parse(bios, &therm->fan->bios)) + nvkm_error(subdev, "parsing both fan tables failed\n"); } nvkm_therm_fan_safety_checks(therm); return 0; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c index 534e5970e..8ae300f91 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fannil.c @@ -38,11 +38,10 @@ nvkm_fannil_set(struct nvkm_therm *therm, int percent) int nvkm_fannil_create(struct nvkm_therm *therm) { - struct nvkm_therm_priv *tpriv = (void *)therm; struct nvkm_fan *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); - tpriv->fan = priv; + therm->fan = priv; if (!priv) return -ENOMEM; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c index bde5ceaeb..340f37a29 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c @@ -24,13 +24,12 @@ */ #include "priv.h" -#include #include #include #include #include -struct nvkm_fanpwm_priv { +struct nvkm_fanpwm { struct nvkm_fan base; struct dcb_gpio_func func; }; @@ -38,76 +37,74 @@ struct nvkm_fanpwm_priv { static int nvkm_fanpwm_get(struct nvkm_therm *therm) { - struct nvkm_therm_priv *tpriv = (void *)therm; - struct nvkm_fanpwm_priv *priv = (void *)tpriv->fan; - struct nvkm_gpio *gpio = nvkm_gpio(therm); - int card_type = nv_device(therm)->card_type; + struct nvkm_fanpwm *fan = (void *)therm->fan; + struct nvkm_device *device = therm->subdev.device; + struct nvkm_gpio *gpio = device->gpio; + int card_type = device->card_type; u32 divs, duty; int ret; - ret = therm->pwm_get(therm, priv->func.line, &divs, &duty); + ret = therm->func->pwm_get(therm, fan->func.line, &divs, &duty); if (ret == 0 && divs) { divs = max(divs, duty); - if (card_type <= NV_40 || (priv->func.log[0] & 1)) + if (card_type <= NV_40 || (fan->func.log[0] & 1)) duty = divs - duty; return (duty * 100) / divs; } - return gpio->get(gpio, 0, priv->func.func, priv->func.line) * 100; + return nvkm_gpio_get(gpio, 0, fan->func.func, fan->func.line) * 100; } static int nvkm_fanpwm_set(struct nvkm_therm *therm, int percent) { - struct nvkm_therm_priv *tpriv = (void *)therm; - struct nvkm_fanpwm_priv *priv = (void *)tpriv->fan; - int card_type = nv_device(therm)->card_type; + struct nvkm_fanpwm *fan = (void *)therm->fan; + int card_type = therm->subdev.device->card_type; u32 divs, duty; int ret; - divs = priv->base.perf.pwm_divisor; - if (priv->base.bios.pwm_freq) { + divs = fan->base.perf.pwm_divisor; + if (fan->base.bios.pwm_freq) { divs = 1; - if (therm->pwm_clock) - divs = therm->pwm_clock(therm, priv->func.line); - divs /= priv->base.bios.pwm_freq; + if (therm->func->pwm_clock) + divs = therm->func->pwm_clock(therm, fan->func.line); + divs /= fan->base.bios.pwm_freq; } duty = ((divs * percent) + 99) / 100; - if (card_type <= NV_40 || (priv->func.log[0] & 1)) + if (card_type <= NV_40 || (fan->func.log[0] & 1)) duty = divs - duty; - ret = therm->pwm_set(therm, priv->func.line, divs, duty); + ret = therm->func->pwm_set(therm, fan->func.line, divs, duty); if (ret == 0) - ret = therm->pwm_ctrl(therm, priv->func.line, true); + ret = therm->func->pwm_ctrl(therm, fan->func.line, true); return ret; } int nvkm_fanpwm_create(struct nvkm_therm *therm, struct dcb_gpio_func *func) { - struct nvkm_device *device = nv_device(therm); - struct nvkm_therm_priv *tpriv = (void *)therm; - struct nvkm_bios *bios = nvkm_bios(therm); - struct nvkm_fanpwm_priv *priv; - struct nvbios_therm_fan fan; + struct nvkm_device *device = therm->subdev.device; + struct nvkm_bios *bios = device->bios; + struct nvkm_fanpwm *fan; + struct nvbios_therm_fan info = {}; u32 divs, duty; - nvbios_fan_parse(bios, &fan); + nvbios_fan_parse(bios, &info); if (!nvkm_boolopt(device->cfgopt, "NvFanPWM", func->param) || - !therm->pwm_ctrl || fan.type == NVBIOS_THERM_FAN_TOGGLE || - therm->pwm_get(therm, func->line, &divs, &duty) == -ENODEV) + !therm->func->pwm_ctrl || info.type == NVBIOS_THERM_FAN_TOGGLE || + therm->func->pwm_get(therm, func->line, &divs, &duty) == -ENODEV) return -ENODEV; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - tpriv->fan = &priv->base; - if (!priv) + fan = kzalloc(sizeof(*fan), GFP_KERNEL); + therm->fan = &fan->base; + if (!fan) return -ENOMEM; - priv->base.type = "PWM"; - priv->base.get = nvkm_fanpwm_get; - priv->base.set = nvkm_fanpwm_set; - priv->func = *func; + fan->base.type = "PWM"; + fan->base.get = nvkm_fanpwm_get; + fan->base.set = nvkm_fanpwm_set; + fan->func = *func; return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c index 4ce041e81..59701b7a6 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c @@ -26,7 +26,7 @@ #include #include -struct nvkm_fantog_priv { +struct nvkm_fantog { struct nvkm_fan base; struct nvkm_alarm alarm; spinlock_t lock; @@ -36,83 +36,81 @@ struct nvkm_fantog_priv { }; static void -nvkm_fantog_update(struct nvkm_fantog_priv *priv, int percent) +nvkm_fantog_update(struct nvkm_fantog *fan, int percent) { - struct nvkm_therm_priv *tpriv = (void *)priv->base.parent; - struct nvkm_timer *ptimer = nvkm_timer(tpriv); - struct nvkm_gpio *gpio = nvkm_gpio(tpriv); + struct nvkm_therm *therm = fan->base.parent; + struct nvkm_device *device = therm->subdev.device; + struct nvkm_timer *tmr = device->timer; + struct nvkm_gpio *gpio = device->gpio; unsigned long flags; int duty; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&fan->lock, flags); if (percent < 0) - percent = priv->percent; - priv->percent = percent; + percent = fan->percent; + fan->percent = percent; - duty = !gpio->get(gpio, 0, DCB_GPIO_FAN, 0xff); - gpio->set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); + duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff); + nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); - if (list_empty(&priv->alarm.head) && percent != (duty * 100)) { - u64 next_change = (percent * priv->period_us) / 100; + if (list_empty(&fan->alarm.head) && percent != (duty * 100)) { + u64 next_change = (percent * fan->period_us) / 100; if (!duty) - next_change = priv->period_us - next_change; - ptimer->alarm(ptimer, next_change * 1000, &priv->alarm); + next_change = fan->period_us - next_change; + nvkm_timer_alarm(tmr, next_change * 1000, &fan->alarm); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&fan->lock, flags); } static void nvkm_fantog_alarm(struct nvkm_alarm *alarm) { - struct nvkm_fantog_priv *priv = - container_of(alarm, struct nvkm_fantog_priv, alarm); - nvkm_fantog_update(priv, -1); + struct nvkm_fantog *fan = + container_of(alarm, struct nvkm_fantog, alarm); + nvkm_fantog_update(fan, -1); } static int nvkm_fantog_get(struct nvkm_therm *therm) { - struct nvkm_therm_priv *tpriv = (void *)therm; - struct nvkm_fantog_priv *priv = (void *)tpriv->fan; - return priv->percent; + struct nvkm_fantog *fan = (void *)therm->fan; + return fan->percent; } static int nvkm_fantog_set(struct nvkm_therm *therm, int percent) { - struct nvkm_therm_priv *tpriv = (void *)therm; - struct nvkm_fantog_priv *priv = (void *)tpriv->fan; - if (therm->pwm_ctrl) - therm->pwm_ctrl(therm, priv->func.line, false); - nvkm_fantog_update(priv, percent); + struct nvkm_fantog *fan = (void *)therm->fan; + if (therm->func->pwm_ctrl) + therm->func->pwm_ctrl(therm, fan->func.line, false); + nvkm_fantog_update(fan, percent); return 0; } int nvkm_fantog_create(struct nvkm_therm *therm, struct dcb_gpio_func *func) { - struct nvkm_therm_priv *tpriv = (void *)therm; - struct nvkm_fantog_priv *priv; + struct nvkm_fantog *fan; int ret; - if (therm->pwm_ctrl) { - ret = therm->pwm_ctrl(therm, func->line, false); + if (therm->func->pwm_ctrl) { + ret = therm->func->pwm_ctrl(therm, func->line, false); if (ret) return ret; } - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - tpriv->fan = &priv->base; - if (!priv) + fan = kzalloc(sizeof(*fan), GFP_KERNEL); + therm->fan = &fan->base; + if (!fan) return -ENOMEM; - priv->base.type = "toggle"; - priv->base.get = nvkm_fantog_get; - priv->base.set = nvkm_fantog_set; - nvkm_alarm_init(&priv->alarm, nvkm_fantog_alarm); - priv->period_us = 100000; /* 10Hz */ - priv->percent = 100; - priv->func = *func; - spin_lock_init(&priv->lock); + fan->base.type = "toggle"; + fan->base.get = nvkm_fantog_get; + fan->base.set = nvkm_fantog_set; + nvkm_alarm_init(&fan->alarm, nvkm_fantog_alarm); + fan->period_us = 100000; /* 10Hz */ + fan->percent = 100; + fan->func = *func; + spin_lock_init(&fan->lock); return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c index 85b5d0c18..86e81930d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/g84.c @@ -26,17 +26,13 @@ #include -struct g84_therm_priv { - struct nvkm_therm_priv base; -}; - int g84_temp_get(struct nvkm_therm *therm) { - struct nvkm_fuse *fuse = nvkm_fuse(therm); + struct nvkm_device *device = therm->subdev.device; - if (nv_ro32(fuse, 0x1a8) == 1) - return nv_rd32(therm, 0x20400); + if (nvkm_fuse_read(device->fuse, 0x1a8) == 1) + return nvkm_rd32(device, 0x20400); else return -ENODEV; } @@ -44,12 +40,12 @@ g84_temp_get(struct nvkm_therm *therm) void g84_sensor_setup(struct nvkm_therm *therm) { - struct nvkm_fuse *fuse = nvkm_fuse(therm); + struct nvkm_device *device = therm->subdev.device; /* enable temperature reading for cards with insane defaults */ - if (nv_ro32(fuse, 0x1a8) == 1) { - nv_mask(therm, 0x20008, 0x80008000, 0x80000000); - nv_mask(therm, 0x2000c, 0x80000003, 0x00000000); + if (nvkm_fuse_read(device->fuse, 0x1a8) == 1) { + nvkm_mask(device, 0x20008, 0x80008000, 0x80000000); + nvkm_mask(device, 0x2000c, 0x80000003, 0x00000000); mdelay(20); /* wait for the temperature to stabilize */ } } @@ -57,36 +53,40 @@ g84_sensor_setup(struct nvkm_therm *therm) static void g84_therm_program_alarms(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; unsigned long flags; - spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); + spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags); /* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */ - nv_wr32(therm, 0x20000, 0x000003ff); + nvkm_wr32(device, 0x20000, 0x000003ff); /* shutdown: The computer should be shutdown when reached */ - nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis); - nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp); + nvkm_wr32(device, 0x20484, sensor->thrs_shutdown.hysteresis); + nvkm_wr32(device, 0x20480, sensor->thrs_shutdown.temp); /* THRS_1 : fan boost*/ - nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp); + nvkm_wr32(device, 0x204c4, sensor->thrs_fan_boost.temp); /* THRS_2 : critical */ - nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp); + nvkm_wr32(device, 0x204c0, sensor->thrs_critical.temp); /* THRS_4 : down clock */ - nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp); - spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); - - nv_debug(therm, - "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", - sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis, - sensor->thrs_down_clock.temp, - sensor->thrs_down_clock.hysteresis, - sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis, - sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis); + nvkm_wr32(device, 0x20414, sensor->thrs_down_clock.temp); + spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); + + nvkm_debug(subdev, + "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", + sensor->thrs_fan_boost.temp, + sensor->thrs_fan_boost.hysteresis, + sensor->thrs_down_clock.temp, + sensor->thrs_down_clock.hysteresis, + sensor->thrs_critical.temp, + sensor->thrs_critical.hysteresis, + sensor->thrs_shutdown.temp, + sensor->thrs_shutdown.hysteresis); } @@ -97,24 +97,25 @@ g84_therm_threshold_hyst_emulation(struct nvkm_therm *therm, const struct nvbios_therm_threshold *thrs, enum nvkm_therm_thrs thrs_name) { + struct nvkm_device *device = therm->subdev.device; enum nvkm_therm_thrs_direction direction; enum nvkm_therm_thrs_state prev_state, new_state; int temp, cur; prev_state = nvkm_therm_sensor_get_threshold_state(therm, thrs_name); - temp = nv_rd32(therm, thrs_reg); + temp = nvkm_rd32(device, thrs_reg); /* program the next threshold */ if (temp == thrs->temp) { - nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis); + nvkm_wr32(device, thrs_reg, thrs->temp - thrs->hysteresis); new_state = NVKM_THERM_THRS_HIGHER; } else { - nv_wr32(therm, thrs_reg, thrs->temp); + nvkm_wr32(device, thrs_reg, thrs->temp); new_state = NVKM_THERM_THRS_LOWER; } /* fix the state (in case someone reprogrammed the alarms) */ - cur = therm->temp_get(therm); + cur = therm->func->temp_get(therm); if (new_state == NVKM_THERM_THRS_LOWER && cur > thrs->temp) new_state = NVKM_THERM_THRS_HIGHER; else if (new_state == NVKM_THERM_THRS_HIGHER && @@ -135,17 +136,17 @@ g84_therm_threshold_hyst_emulation(struct nvkm_therm *therm, } static void -g84_therm_intr(struct nvkm_subdev *subdev) +g84_therm_intr(struct nvkm_therm *therm) { - struct nvkm_therm *therm = nvkm_therm(subdev); - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; unsigned long flags; uint32_t intr; - spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); + spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags); - intr = nv_rd32(therm, 0x20100) & 0x3ff; + intr = nvkm_rd32(device, 0x20100) & 0x3ff; /* THRS_4: downclock */ if (intr & 0x002) { @@ -180,87 +181,66 @@ g84_therm_intr(struct nvkm_subdev *subdev) } if (intr) - nv_error(therm, "unhandled intr 0x%08x\n", intr); + nvkm_error(subdev, "intr %08x\n", intr); /* ACK everything */ - nv_wr32(therm, 0x20100, 0xffffffff); - nv_wr32(therm, 0x1100, 0x10000); /* PBUS */ + nvkm_wr32(device, 0x20100, 0xffffffff); + nvkm_wr32(device, 0x1100, 0x10000); /* PBUS */ - spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); + spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); } -static int -g84_therm_init(struct nvkm_object *object) +void +g84_therm_fini(struct nvkm_therm *therm) { - struct g84_therm_priv *priv = (void *)object; - int ret; + struct nvkm_device *device = therm->subdev.device; - ret = nvkm_therm_init(&priv->base.base); - if (ret) - return ret; + /* Disable PTherm IRQs */ + nvkm_wr32(device, 0x20000, 0x00000000); - g84_sensor_setup(&priv->base.base); - return 0; + /* ACK all PTherm IRQs */ + nvkm_wr32(device, 0x20100, 0xffffffff); + nvkm_wr32(device, 0x1100, 0x10000); /* PBUS */ } -static int -g84_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void +g84_therm_init(struct nvkm_therm *therm) { - struct g84_therm_priv *priv; - int ret; - - ret = nvkm_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; - priv->base.base.pwm_get = nv50_fan_pwm_get; - priv->base.base.pwm_set = nv50_fan_pwm_set; - priv->base.base.pwm_clock = nv50_fan_pwm_clock; - priv->base.base.temp_get = g84_temp_get; - priv->base.sensor.program_alarms = g84_therm_program_alarms; - nv_subdev(priv)->intr = g84_therm_intr; - - /* init the thresholds */ - nvkm_therm_sensor_set_threshold_state(&priv->base.base, - NVKM_THERM_THRS_SHUTDOWN, - NVKM_THERM_THRS_LOWER); - nvkm_therm_sensor_set_threshold_state(&priv->base.base, - NVKM_THERM_THRS_FANBOOST, - NVKM_THERM_THRS_LOWER); - nvkm_therm_sensor_set_threshold_state(&priv->base.base, - NVKM_THERM_THRS_CRITICAL, - NVKM_THERM_THRS_LOWER); - nvkm_therm_sensor_set_threshold_state(&priv->base.base, - NVKM_THERM_THRS_DOWNCLOCK, - NVKM_THERM_THRS_LOWER); - - return nvkm_therm_preinit(&priv->base.base); + g84_sensor_setup(therm); } +static const struct nvkm_therm_func +g84_therm = { + .init = g84_therm_init, + .fini = g84_therm_fini, + .intr = g84_therm_intr, + .pwm_ctrl = nv50_fan_pwm_ctrl, + .pwm_get = nv50_fan_pwm_get, + .pwm_set = nv50_fan_pwm_set, + .pwm_clock = nv50_fan_pwm_clock, + .temp_get = g84_temp_get, + .program_alarms = g84_therm_program_alarms, +}; + int -g84_therm_fini(struct nvkm_object *object, bool suspend) +g84_therm_new(struct nvkm_device *device, int index, struct nvkm_therm **ptherm) { - /* Disable PTherm IRQs */ - nv_wr32(object, 0x20000, 0x00000000); + struct nvkm_therm *therm; + int ret; - /* ACK all PTherm IRQs */ - nv_wr32(object, 0x20100, 0xffffffff); - nv_wr32(object, 0x1100, 0x10000); /* PBUS */ + ret = nvkm_therm_new_(&g84_therm, device, index, &therm); + *ptherm = therm; + if (ret) + return ret; - return _nvkm_therm_fini(object, suspend); + /* init the thresholds */ + nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_SHUTDOWN, + NVKM_THERM_THRS_LOWER); + nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_FANBOOST, + NVKM_THERM_THRS_LOWER); + nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_CRITICAL, + NVKM_THERM_THRS_LOWER); + nvkm_therm_sensor_set_threshold_state(therm, NVKM_THERM_THRS_DOWNCLOCK, + NVKM_THERM_THRS_LOWER); + return 0; } - -struct nvkm_oclass -g84_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0x84), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = g84_therm_ctor, - .dtor = _nvkm_therm_dtor, - .init = g84_therm_init, - .fini = g84_therm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c deleted file mode 100644 index 46b7e656a..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf110.c +++ /dev/null @@ -1,174 +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 "priv.h" - -#include - -struct gf110_therm_priv { - struct nvkm_therm_priv base; -}; - -static int -pwm_info(struct nvkm_therm *therm, int line) -{ - u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04)); - - switch (gpio & 0x000000c0) { - case 0x00000000: /* normal mode, possibly pwm forced off by us */ - case 0x00000040: /* nvio special */ - switch (gpio & 0x0000001f) { - case 0x00: return 2; - case 0x19: return 1; - case 0x1c: return 0; - case 0x1e: return 2; - default: - break; - } - default: - break; - } - - nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio); - return -ENODEV; -} - -static int -gf110_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) -{ - u32 data = enable ? 0x00000040 : 0x00000000; - int indx = pwm_info(therm, line); - if (indx < 0) - return indx; - else if (indx < 2) - nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); - /* nothing to do for indx == 2, it seems hardwired to PTHERM */ - return 0; -} - -static int -gf110_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) -{ - int indx = pwm_info(therm, line); - if (indx < 0) - return indx; - else if (indx < 2) { - if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { - *divs = nv_rd32(therm, 0x00e114 + (indx * 8)); - *duty = nv_rd32(therm, 0x00e118 + (indx * 8)); - return 0; - } - } else if (indx == 2) { - *divs = nv_rd32(therm, 0x0200d8) & 0x1fff; - *duty = nv_rd32(therm, 0x0200dc) & 0x1fff; - return 0; - } - - return -EINVAL; -} - -static int -gf110_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) -{ - int indx = pwm_info(therm, line); - if (indx < 0) - return indx; - else if (indx < 2) { - nv_wr32(therm, 0x00e114 + (indx * 8), divs); - nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); - } else if (indx == 2) { - nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */ - nv_wr32(therm, 0x0200dc, duty | 0x40000000); - } - return 0; -} - -static int -gf110_fan_pwm_clock(struct nvkm_therm *therm, int line) -{ - int indx = pwm_info(therm, line); - if (indx < 0) - return 0; - else if (indx < 2) - return (nv_device(therm)->crystal * 1000) / 20; - else - return nv_device(therm)->crystal * 1000 / 10; -} - -int -gf110_therm_init(struct nvkm_object *object) -{ - struct gf110_therm_priv *priv = (void *)object; - int ret; - - ret = nvkm_therm_init(&priv->base.base); - if (ret) - return ret; - - /* enable fan tach, count revolutions per-second */ - nv_mask(priv, 0x00e720, 0x00000003, 0x00000002); - if (priv->base.fan->tach.func != DCB_GPIO_UNUSED) { - nv_mask(priv, 0x00d79c, 0x000000ff, priv->base.fan->tach.line); - nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000); - nv_mask(priv, 0x00e720, 0x00000001, 0x00000001); - } - nv_mask(priv, 0x00e720, 0x00000002, 0x00000000); - - return 0; -} - -static int -gf110_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gf110_therm_priv *priv; - int ret; - - ret = nvkm_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - g84_sensor_setup(&priv->base.base); - - priv->base.base.pwm_ctrl = gf110_fan_pwm_ctrl; - priv->base.base.pwm_get = gf110_fan_pwm_get; - priv->base.base.pwm_set = gf110_fan_pwm_set; - priv->base.base.pwm_clock = gf110_fan_pwm_clock; - priv->base.base.temp_get = g84_temp_get; - priv->base.base.fan_sense = gt215_therm_fan_sense; - priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling; - return nvkm_therm_preinit(&priv->base.base); -} - -struct nvkm_oclass -gf110_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0xd0), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf110_therm_ctor, - .dtor = _nvkm_therm_dtor, - .init = gf110_therm_init, - .fini = g84_therm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c new file mode 100644 index 000000000..06dcfd6ee --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c @@ -0,0 +1,153 @@ +/* + * 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 "priv.h" + +static int +pwm_info(struct nvkm_therm *therm, int line) +{ + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; + u32 gpio = nvkm_rd32(device, 0x00d610 + (line * 0x04)); + + switch (gpio & 0x000000c0) { + case 0x00000000: /* normal mode, possibly pwm forced off by us */ + case 0x00000040: /* nvio special */ + switch (gpio & 0x0000001f) { + case 0x00: return 2; + case 0x19: return 1; + case 0x1c: return 0; + case 0x1e: return 2; + default: + break; + } + default: + break; + } + + nvkm_error(subdev, "GPIO %d unknown PWM: %08x\n", line, gpio); + return -ENODEV; +} + +static int +gf119_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) +{ + struct nvkm_device *device = therm->subdev.device; + u32 data = enable ? 0x00000040 : 0x00000000; + int indx = pwm_info(therm, line); + if (indx < 0) + return indx; + else if (indx < 2) + nvkm_mask(device, 0x00d610 + (line * 0x04), 0x000000c0, data); + /* nothing to do for indx == 2, it seems hardwired to PTHERM */ + return 0; +} + +static int +gf119_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) +{ + struct nvkm_device *device = therm->subdev.device; + int indx = pwm_info(therm, line); + if (indx < 0) + return indx; + else if (indx < 2) { + if (nvkm_rd32(device, 0x00d610 + (line * 0x04)) & 0x00000040) { + *divs = nvkm_rd32(device, 0x00e114 + (indx * 8)); + *duty = nvkm_rd32(device, 0x00e118 + (indx * 8)); + return 0; + } + } else if (indx == 2) { + *divs = nvkm_rd32(device, 0x0200d8) & 0x1fff; + *duty = nvkm_rd32(device, 0x0200dc) & 0x1fff; + return 0; + } + + return -EINVAL; +} + +static int +gf119_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) +{ + struct nvkm_device *device = therm->subdev.device; + int indx = pwm_info(therm, line); + if (indx < 0) + return indx; + else if (indx < 2) { + nvkm_wr32(device, 0x00e114 + (indx * 8), divs); + nvkm_wr32(device, 0x00e118 + (indx * 8), duty | 0x80000000); + } else if (indx == 2) { + nvkm_mask(device, 0x0200d8, 0x1fff, divs); /* keep the high bits */ + nvkm_wr32(device, 0x0200dc, duty | 0x40000000); + } + return 0; +} + +static int +gf119_fan_pwm_clock(struct nvkm_therm *therm, int line) +{ + struct nvkm_device *device = therm->subdev.device; + int indx = pwm_info(therm, line); + if (indx < 0) + return 0; + else if (indx < 2) + return (device->crystal * 1000) / 20; + else + return device->crystal * 1000 / 10; +} + +void +gf119_therm_init(struct nvkm_therm *therm) +{ + struct nvkm_device *device = therm->subdev.device; + + g84_sensor_setup(therm); + + /* enable fan tach, count revolutions per-second */ + nvkm_mask(device, 0x00e720, 0x00000003, 0x00000002); + if (therm->fan->tach.func != DCB_GPIO_UNUSED) { + nvkm_mask(device, 0x00d79c, 0x000000ff, therm->fan->tach.line); + nvkm_wr32(device, 0x00e724, device->crystal * 1000); + nvkm_mask(device, 0x00e720, 0x00000001, 0x00000001); + } + nvkm_mask(device, 0x00e720, 0x00000002, 0x00000000); +} + +static const struct nvkm_therm_func +gf119_therm = { + .init = gf119_therm_init, + .fini = g84_therm_fini, + .pwm_ctrl = gf119_fan_pwm_ctrl, + .pwm_get = gf119_fan_pwm_get, + .pwm_set = gf119_fan_pwm_set, + .pwm_clock = gf119_fan_pwm_clock, + .temp_get = g84_temp_get, + .fan_sense = gt215_therm_fan_sense, + .program_alarms = nvkm_therm_program_alarms_polling, +}; + +int +gf119_therm_new(struct nvkm_device *device, int index, + struct nvkm_therm **ptherm) +{ + return nvkm_therm_new_(&gf119_therm, device, index, ptherm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c index 2fd110f09..86848ece4 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gm107.c @@ -23,12 +23,6 @@ */ #include "priv.h" -#include - -struct gm107_therm_priv { - struct nvkm_therm_priv base; -}; - static int gm107_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) { @@ -39,55 +33,43 @@ gm107_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) static int gm107_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) { - *divs = nv_rd32(therm, 0x10eb20) & 0x1fff; - *duty = nv_rd32(therm, 0x10eb24) & 0x1fff; + struct nvkm_device *device = therm->subdev.device; + *divs = nvkm_rd32(device, 0x10eb20) & 0x1fff; + *duty = nvkm_rd32(device, 0x10eb24) & 0x1fff; return 0; } static int gm107_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) { - nv_mask(therm, 0x10eb10, 0x1fff, divs); /* keep the high bits */ - nv_wr32(therm, 0x10eb14, duty | 0x80000000); + struct nvkm_device *device = therm->subdev.device; + nvkm_mask(device, 0x10eb10, 0x1fff, divs); /* keep the high bits */ + nvkm_wr32(device, 0x10eb14, duty | 0x80000000); return 0; } static int gm107_fan_pwm_clock(struct nvkm_therm *therm, int line) { - return nv_device(therm)->crystal * 1000; + return therm->subdev.device->crystal * 1000; } -static int -gm107_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gm107_therm_priv *priv; - int ret; - - ret = nvkm_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_therm_func +gm107_therm = { + .init = gf119_therm_init, + .fini = g84_therm_fini, + .pwm_ctrl = gm107_fan_pwm_ctrl, + .pwm_get = gm107_fan_pwm_get, + .pwm_set = gm107_fan_pwm_set, + .pwm_clock = gm107_fan_pwm_clock, + .temp_get = g84_temp_get, + .fan_sense = gt215_therm_fan_sense, + .program_alarms = nvkm_therm_program_alarms_polling, +}; - priv->base.base.pwm_ctrl = gm107_fan_pwm_ctrl; - priv->base.base.pwm_get = gm107_fan_pwm_get; - priv->base.base.pwm_set = gm107_fan_pwm_set; - priv->base.base.pwm_clock = gm107_fan_pwm_clock; - priv->base.base.temp_get = g84_temp_get; - priv->base.base.fan_sense = gt215_therm_fan_sense; - priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling; - return nvkm_therm_preinit(&priv->base.base); +int +gm107_therm_new(struct nvkm_device *device, int index, + struct nvkm_therm **ptherm) +{ + return nvkm_therm_new_(&gm107_therm, device, index, ptherm); } - -struct nvkm_oclass -gm107_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0x117), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gm107_therm_ctor, - .dtor = _nvkm_therm_dtor, - .init = gf110_therm_init, - .fini = g84_therm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c index e99be2033..c08097f2a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c @@ -23,78 +23,53 @@ */ #include "priv.h" -#include #include -struct gt215_therm_priv { - struct nvkm_therm_priv base; -}; - int gt215_therm_fan_sense(struct nvkm_therm *therm) { - u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff; - u32 ctrl = nv_rd32(therm, 0x00e720); + struct nvkm_device *device = therm->subdev.device; + u32 tach = nvkm_rd32(device, 0x00e728) & 0x0000ffff; + u32 ctrl = nvkm_rd32(device, 0x00e720); if (ctrl & 0x00000001) return tach * 60 / 2; return -ENODEV; } -static int -gt215_therm_init(struct nvkm_object *object) +static void +gt215_therm_init(struct nvkm_therm *therm) { - struct gt215_therm_priv *priv = (void *)object; - struct dcb_gpio_func *tach = &priv->base.fan->tach; - int ret; - - ret = nvkm_therm_init(&priv->base.base); - if (ret) - return ret; + struct nvkm_device *device = therm->subdev.device; + struct dcb_gpio_func *tach = &therm->fan->tach; - g84_sensor_setup(&priv->base.base); + g84_sensor_setup(therm); /* enable fan tach, count revolutions per-second */ - nv_mask(priv, 0x00e720, 0x00000003, 0x00000002); + nvkm_mask(device, 0x00e720, 0x00000003, 0x00000002); if (tach->func != DCB_GPIO_UNUSED) { - nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000); - nv_mask(priv, 0x00e720, 0x001f0000, tach->line << 16); - nv_mask(priv, 0x00e720, 0x00000001, 0x00000001); + nvkm_wr32(device, 0x00e724, device->crystal * 1000); + nvkm_mask(device, 0x00e720, 0x001f0000, tach->line << 16); + nvkm_mask(device, 0x00e720, 0x00000001, 0x00000001); } - nv_mask(priv, 0x00e720, 0x00000002, 0x00000000); - - return 0; + nvkm_mask(device, 0x00e720, 0x00000002, 0x00000000); } -static int -gt215_therm_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct gt215_therm_priv *priv; - int ret; - - ret = nvkm_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; +static const struct nvkm_therm_func +gt215_therm = { + .init = gt215_therm_init, + .fini = g84_therm_fini, + .pwm_ctrl = nv50_fan_pwm_ctrl, + .pwm_get = nv50_fan_pwm_get, + .pwm_set = nv50_fan_pwm_set, + .pwm_clock = nv50_fan_pwm_clock, + .temp_get = g84_temp_get, + .fan_sense = gt215_therm_fan_sense, + .program_alarms = nvkm_therm_program_alarms_polling, +}; - priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; - priv->base.base.pwm_get = nv50_fan_pwm_get; - priv->base.base.pwm_set = nv50_fan_pwm_set; - priv->base.base.pwm_clock = nv50_fan_pwm_clock; - priv->base.base.temp_get = g84_temp_get; - priv->base.base.fan_sense = gt215_therm_fan_sense; - priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling; - return nvkm_therm_preinit(&priv->base.base); +int +gt215_therm_new(struct nvkm_device *device, int index, + struct nvkm_therm **ptherm) +{ + return nvkm_therm_new_(>215_therm, device, index, ptherm); } - -struct nvkm_oclass -gt215_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0xa3), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gt215_therm_ctor, - .dtor = _nvkm_therm_dtor, - .init = gt215_therm_init, - .fini = g84_therm_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c index 09fc4605e..6e0ddc1bb 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/ic.c @@ -27,16 +27,16 @@ #include static bool -probe_monitoring_device(struct nvkm_i2c_port *i2c, +probe_monitoring_device(struct nvkm_i2c_bus *bus, struct i2c_board_info *info, void *data) { - struct nvkm_therm_priv *priv = data; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + struct nvkm_therm *therm = data; + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; struct i2c_client *client; request_module("%s%s", I2C_MODULE_PREFIX, info->type); - client = i2c_new_device(&i2c->adapter, info); + client = i2c_new_device(&bus->i2c, info); if (!client) return false; @@ -46,15 +46,15 @@ probe_monitoring_device(struct nvkm_i2c_port *i2c, return false; } - nv_info(priv, - "Found an %s at address 0x%x (controlled by lm_sensors, " - "temp offset %+i C)\n", - info->type, info->addr, sensor->offset_constant); - priv->ic = client; + nvkm_debug(&therm->subdev, + "Found an %s at address 0x%x (controlled by lm_sensors, " + "temp offset %+i C)\n", + info->type, info->addr, sensor->offset_constant); + therm->ic = client; return true; } -static struct nvkm_i2c_board_info +static struct nvkm_i2c_bus_probe nv_board_infos[] = { { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 }, { { I2C_BOARD_INFO("w83781d", 0x2d) }, 0 }, @@ -82,38 +82,43 @@ nv_board_infos[] = { void nvkm_therm_ic_ctor(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_bios *bios = nvkm_bios(therm); - struct nvkm_i2c *i2c = nvkm_i2c(therm); + struct nvkm_device *device = therm->subdev.device; + struct nvkm_bios *bios = device->bios; + struct nvkm_i2c *i2c = device->i2c; + struct nvkm_i2c_bus *bus; struct nvbios_extdev_func extdev_entry; + bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI); + if (!bus) + return; + if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { - struct nvkm_i2c_board_info board[] = { + struct nvkm_i2c_bus_probe board[] = { { { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 0}, { } }; - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - board, probe_monitoring_device, therm); - if (priv->ic) + nvkm_i2c_bus_probe(bus, "monitoring device", board, + probe_monitoring_device, therm); + if (therm->ic) return; } if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) { - struct nvkm_i2c_board_info board[] = { + struct nvkm_i2c_bus_probe board[] = { { { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, 20 }, { } }; - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - board, probe_monitoring_device, therm); - if (priv->ic) + nvkm_i2c_bus_probe(bus, "monitoring device", board, + probe_monitoring_device, therm); + if (therm->ic) return; } /* The vbios doesn't provide the address of an exisiting monitoring device. Let's try our static list. */ - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - nv_board_infos, probe_monitoring_device, therm); + nvkm_i2c_bus_probe(bus, "monitoring device", nv_board_infos, + probe_monitoring_device, therm); } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c index 8496fffd4..6326fdc5a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c @@ -24,26 +24,17 @@ */ #include "priv.h" -#include - -struct nv40_therm_priv { - struct nvkm_therm_priv base; -}; - enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 }; static enum nv40_sensor_style nv40_sensor_style(struct nvkm_therm *therm) { - struct nvkm_device *device = nv_device(therm); - - switch (device->chipset) { + switch (therm->subdev.device->chipset) { case 0x43: case 0x44: case 0x4a: case 0x47: return OLD_STYLE; - case 0x46: case 0x49: case 0x4b: @@ -61,18 +52,19 @@ nv40_sensor_style(struct nvkm_therm *therm) static int nv40_sensor_setup(struct nvkm_therm *therm) { + struct nvkm_device *device = therm->subdev.device; enum nv40_sensor_style style = nv40_sensor_style(therm); /* enable ADC readout and disable the ALARM threshold */ if (style == NEW_STYLE) { - nv_mask(therm, 0x15b8, 0x80000000, 0); - nv_wr32(therm, 0x15b0, 0x80003fff); + nvkm_mask(device, 0x15b8, 0x80000000, 0); + nvkm_wr32(device, 0x15b0, 0x80003fff); mdelay(20); /* wait for the temperature to stabilize */ - return nv_rd32(therm, 0x15b4) & 0x3fff; + return nvkm_rd32(device, 0x15b4) & 0x3fff; } else if (style == OLD_STYLE) { - nv_wr32(therm, 0x15b0, 0xff); + nvkm_wr32(device, 0x15b0, 0xff); mdelay(20); /* wait for the temperature to stabilize */ - return nv_rd32(therm, 0x15b4) & 0xff; + return nvkm_rd32(device, 0x15b4) & 0xff; } else return -ENODEV; } @@ -80,17 +72,17 @@ nv40_sensor_setup(struct nvkm_therm *therm) static int nv40_temp_get(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + struct nvkm_device *device = therm->subdev.device; + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; enum nv40_sensor_style style = nv40_sensor_style(therm); int core_temp; if (style == NEW_STYLE) { - nv_wr32(therm, 0x15b0, 0x80003fff); - core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; + nvkm_wr32(device, 0x15b0, 0x80003fff); + core_temp = nvkm_rd32(device, 0x15b4) & 0x3fff; } else if (style == OLD_STYLE) { - nv_wr32(therm, 0x15b0, 0xff); - core_temp = nv_rd32(therm, 0x15b4) & 0xff; + nvkm_wr32(device, 0x15b0, 0xff); + core_temp = nvkm_rd32(device, 0x15b4) & 0xff; } else return -ENODEV; @@ -113,11 +105,13 @@ nv40_temp_get(struct nvkm_therm *therm) static int nv40_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) { + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; u32 mask = enable ? 0x80000000 : 0x0000000; - if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask); - else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask); + if (line == 2) nvkm_mask(device, 0x0010f0, 0x80000000, mask); + else if (line == 9) nvkm_mask(device, 0x0015f4, 0x80000000, mask); else { - nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); + nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line); return -ENODEV; } return 0; @@ -126,8 +120,10 @@ nv40_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) static int nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) { + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; if (line == 2) { - u32 reg = nv_rd32(therm, 0x0010f0); + u32 reg = nvkm_rd32(device, 0x0010f0); if (reg & 0x80000000) { *duty = (reg & 0x7fff0000) >> 16; *divs = (reg & 0x00007fff); @@ -135,14 +131,14 @@ nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) } } else if (line == 9) { - u32 reg = nv_rd32(therm, 0x0015f4); + u32 reg = nvkm_rd32(device, 0x0015f4); if (reg & 0x80000000) { - *divs = nv_rd32(therm, 0x0015f8); + *divs = nvkm_rd32(device, 0x0015f8); *duty = (reg & 0x7fffffff); return 0; } } else { - nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); + nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line); return -ENODEV; } @@ -152,14 +148,16 @@ nv40_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) static int nv40_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) { + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; if (line == 2) { - nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs); + nvkm_mask(device, 0x0010f0, 0x7fff7fff, (duty << 16) | divs); } else if (line == 9) { - nv_wr32(therm, 0x0015f8, divs); - nv_mask(therm, 0x0015f4, 0x7fffffff, duty); + nvkm_wr32(device, 0x0015f8, divs); + nvkm_mask(device, 0x0015f4, 0x7fffffff, duty); } else { - nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); + nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", line); return -ENODEV; } @@ -167,59 +165,40 @@ nv40_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) } void -nv40_therm_intr(struct nvkm_subdev *subdev) +nv40_therm_intr(struct nvkm_therm *therm) { - struct nvkm_therm *therm = nvkm_therm(subdev); - uint32_t stat = nv_rd32(therm, 0x1100); + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_device *device = subdev->device; + uint32_t stat = nvkm_rd32(device, 0x1100); /* traitement */ /* ack all IRQs */ - nv_wr32(therm, 0x1100, 0x70000); + nvkm_wr32(device, 0x1100, 0x70000); - nv_error(therm, "THERM received an IRQ: stat = %x\n", stat); + nvkm_error(subdev, "THERM received an IRQ: stat = %x\n", stat); } -static int -nv40_therm_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static void +nv40_therm_init(struct nvkm_therm *therm) { - struct nv40_therm_priv *priv; - int ret; - - ret = nvkm_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.pwm_ctrl = nv40_fan_pwm_ctrl; - priv->base.base.pwm_get = nv40_fan_pwm_get; - priv->base.base.pwm_set = nv40_fan_pwm_set; - priv->base.base.temp_get = nv40_temp_get; - priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling; - nv_subdev(priv)->intr = nv40_therm_intr; - return nvkm_therm_preinit(&priv->base.base); -} - -static int -nv40_therm_init(struct nvkm_object *object) -{ - struct nvkm_therm *therm = (void *)object; - nv40_sensor_setup(therm); - - return _nvkm_therm_init(object); } -struct nvkm_oclass -nv40_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_therm_ctor, - .dtor = _nvkm_therm_dtor, - .init = nv40_therm_init, - .fini = _nvkm_therm_fini, - }, +static const struct nvkm_therm_func +nv40_therm = { + .init = nv40_therm_init, + .intr = nv40_therm_intr, + .pwm_ctrl = nv40_fan_pwm_ctrl, + .pwm_get = nv40_fan_pwm_get, + .pwm_set = nv40_fan_pwm_set, + .temp_get = nv40_temp_get, + .program_alarms = nvkm_therm_program_alarms_polling, }; + +int +nv40_therm_new(struct nvkm_device *device, int index, + struct nvkm_therm **ptherm) +{ + return nvkm_therm_new_(&nv40_therm, device, index, ptherm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c index 1ef59e892..9b57b433d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv50.c @@ -24,15 +24,11 @@ */ #include "priv.h" -#include - -struct nv50_therm_priv { - struct nvkm_therm_priv base; -}; - static int pwm_info(struct nvkm_therm *therm, int *line, int *ctrl, int *indx) { + struct nvkm_subdev *subdev = &therm->subdev; + if (*line == 0x04) { *ctrl = 0x00e100; *line = 4; @@ -48,7 +44,7 @@ pwm_info(struct nvkm_therm *therm, int *line, int *ctrl, int *indx) *line = 0; *indx = 0; } else { - nv_error(therm, "unknown pwm ctrl for gpio %d\n", *line); + nvkm_error(subdev, "unknown pwm ctrl for gpio %d\n", *line); return -ENODEV; } @@ -58,23 +54,25 @@ pwm_info(struct nvkm_therm *therm, int *line, int *ctrl, int *indx) int nv50_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) { + struct nvkm_device *device = therm->subdev.device; u32 data = enable ? 0x00000001 : 0x00000000; int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); if (ret == 0) - nv_mask(therm, ctrl, 0x00010001 << line, data << line); + nvkm_mask(device, ctrl, 0x00010001 << line, data << line); return ret; } int nv50_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) { + struct nvkm_device *device = therm->subdev.device; int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); if (ret) return ret; - if (nv_rd32(therm, ctrl) & (1 << line)) { - *divs = nv_rd32(therm, 0x00e114 + (id * 8)); - *duty = nv_rd32(therm, 0x00e118 + (id * 8)); + if (nvkm_rd32(device, ctrl) & (1 << line)) { + *divs = nvkm_rd32(device, 0x00e114 + (id * 8)); + *duty = nvkm_rd32(device, 0x00e118 + (id * 8)); return 0; } @@ -84,36 +82,36 @@ nv50_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) int nv50_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) { + struct nvkm_device *device = therm->subdev.device; int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); if (ret) return ret; - nv_wr32(therm, 0x00e114 + (id * 8), divs); - nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); + nvkm_wr32(device, 0x00e114 + (id * 8), divs); + nvkm_wr32(device, 0x00e118 + (id * 8), duty | 0x80000000); return 0; } int nv50_fan_pwm_clock(struct nvkm_therm *therm, int line) { - int chipset = nv_device(therm)->chipset; - int crystal = nv_device(therm)->crystal; + struct nvkm_device *device = therm->subdev.device; int pwm_clock; /* determine the PWM source clock */ - if (chipset > 0x50 && chipset < 0x94) { - u8 pwm_div = nv_rd32(therm, 0x410c); - if (nv_rd32(therm, 0xc040) & 0x800000) { + if (device->chipset > 0x50 && device->chipset < 0x94) { + u8 pwm_div = nvkm_rd32(device, 0x410c); + if (nvkm_rd32(device, 0xc040) & 0x800000) { /* Use the HOST clock (100 MHz) * Where does this constant(2.4) comes from? */ pwm_clock = (100000000 >> pwm_div) * 10 / 24; } else { /* Where does this constant(20) comes from? */ - pwm_clock = (crystal * 1000) >> pwm_div; + pwm_clock = (device->crystal * 1000) >> pwm_div; pwm_clock /= 20; } } else { - pwm_clock = (crystal * 1000) / 20; + pwm_clock = (device->crystal * 1000) / 20; } return pwm_clock; @@ -122,18 +120,19 @@ nv50_fan_pwm_clock(struct nvkm_therm *therm, int line) static void nv50_sensor_setup(struct nvkm_therm *therm) { - nv_mask(therm, 0x20010, 0x40000000, 0x0); + struct nvkm_device *device = therm->subdev.device; + nvkm_mask(device, 0x20010, 0x40000000, 0x0); mdelay(20); /* wait for the temperature to stabilize */ } static int nv50_temp_get(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + struct nvkm_device *device = therm->subdev.device; + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; int core_temp; - core_temp = nv_rd32(therm, 0x20014) & 0x3fff; + core_temp = nvkm_rd32(device, 0x20014) & 0x3fff; /* if the slope or the offset is unset, do no use the sensor */ if (!sensor->slope_div || !sensor->slope_mult || @@ -151,48 +150,27 @@ nv50_temp_get(struct nvkm_therm *therm) return core_temp; } -static int -nv50_therm_ctor(struct nvkm_object *parent, - struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nv50_therm_priv *priv; - int ret; - - ret = nvkm_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; - priv->base.base.pwm_get = nv50_fan_pwm_get; - priv->base.base.pwm_set = nv50_fan_pwm_set; - priv->base.base.pwm_clock = nv50_fan_pwm_clock; - priv->base.base.temp_get = nv50_temp_get; - priv->base.sensor.program_alarms = nvkm_therm_program_alarms_polling; - nv_subdev(priv)->intr = nv40_therm_intr; - - return nvkm_therm_preinit(&priv->base.base); -} - -static int -nv50_therm_init(struct nvkm_object *object) +static void +nv50_therm_init(struct nvkm_therm *therm) { - struct nvkm_therm *therm = (void *)object; - nv50_sensor_setup(therm); - - return _nvkm_therm_init(object); } -struct nvkm_oclass -nv50_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0x50), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv50_therm_ctor, - .dtor = _nvkm_therm_dtor, - .init = nv50_therm_init, - .fini = _nvkm_therm_fini, - }, +static const struct nvkm_therm_func +nv50_therm = { + .init = nv50_therm_init, + .intr = nv40_therm_intr, + .pwm_ctrl = nv50_fan_pwm_ctrl, + .pwm_get = nv50_fan_pwm_get, + .pwm_set = nv50_fan_pwm_set, + .pwm_clock = nv50_fan_pwm_clock, + .temp_get = nv50_temp_get, + .program_alarms = nvkm_therm_program_alarms_polling, }; + +int +nv50_therm_new(struct nvkm_device *device, int index, + struct nvkm_therm **ptherm) +{ + return nvkm_therm_new_(&nv50_therm, device, index, ptherm); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h index 916a149ef..235a5d8da 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h @@ -1,5 +1,6 @@ #ifndef __NVTHERM_PRIV_H__ #define __NVTHERM_PRIV_H__ +#define nvkm_therm(p) container_of((p), struct nvkm_therm, subdev) /* * Copyright 2012 The Nouveau community * @@ -28,8 +29,9 @@ #include #include #include -#include -#include + +int nvkm_therm_new_(const struct nvkm_therm_func *, struct nvkm_device *, + int index, struct nvkm_therm **); struct nvkm_fan { struct nvkm_therm *parent; @@ -48,59 +50,6 @@ struct nvkm_fan { struct dcb_gpio_func tach; }; -enum nvkm_therm_thrs_direction { - NVKM_THERM_THRS_FALLING = 0, - NVKM_THERM_THRS_RISING = 1 -}; - -enum nvkm_therm_thrs_state { - NVKM_THERM_THRS_LOWER = 0, - NVKM_THERM_THRS_HIGHER = 1 -}; - -enum nvkm_therm_thrs { - NVKM_THERM_THRS_FANBOOST = 0, - NVKM_THERM_THRS_DOWNCLOCK = 1, - NVKM_THERM_THRS_CRITICAL = 2, - NVKM_THERM_THRS_SHUTDOWN = 3, - NVKM_THERM_THRS_NR -}; - -struct nvkm_therm_priv { - struct nvkm_therm base; - - /* automatic thermal management */ - struct nvkm_alarm alarm; - spinlock_t lock; - struct nvbios_therm_trip_point *last_trip; - int mode; - int cstate; - int suspend; - - /* bios */ - struct nvbios_therm_sensor bios_sensor; - - /* fan priv */ - struct nvkm_fan *fan; - - /* alarms priv */ - struct { - spinlock_t alarm_program_lock; - struct nvkm_alarm therm_poll_alarm; - enum nvkm_therm_thrs_state alarm_state[NVKM_THERM_THRS_NR]; - void (*program_alarms)(struct nvkm_therm *); - } sensor; - - /* what should be done if the card overheats */ - struct { - void (*downclock)(struct nvkm_therm *, bool active); - void (*pause)(struct nvkm_therm *, bool active); - } emergency; - - /* ic */ - struct i2c_client *ic; -}; - int nvkm_therm_fan_mode(struct nvkm_therm *, int mode); int nvkm_therm_attr_get(struct nvkm_therm *, enum nvkm_therm_attr_type); int nvkm_therm_attr_set(struct nvkm_therm *, enum nvkm_therm_attr_type, int); @@ -117,8 +66,6 @@ int nvkm_therm_fan_set(struct nvkm_therm *, bool now, int percent); int nvkm_therm_fan_user_get(struct nvkm_therm *); int nvkm_therm_fan_user_set(struct nvkm_therm *, int percent); -int nvkm_therm_fan_sense(struct nvkm_therm *); - int nvkm_therm_preinit(struct nvkm_therm *); int nvkm_therm_sensor_init(struct nvkm_therm *); @@ -134,18 +81,37 @@ void nvkm_therm_sensor_event(struct nvkm_therm *, enum nvkm_therm_thrs, enum nvkm_therm_thrs_direction); void nvkm_therm_program_alarms_polling(struct nvkm_therm *); -void nv40_therm_intr(struct nvkm_subdev *); +struct nvkm_therm_func { + void (*init)(struct nvkm_therm *); + void (*fini)(struct nvkm_therm *); + void (*intr)(struct nvkm_therm *); + + int (*pwm_ctrl)(struct nvkm_therm *, int line, bool); + int (*pwm_get)(struct nvkm_therm *, int line, u32 *, u32 *); + int (*pwm_set)(struct nvkm_therm *, int line, u32, u32); + int (*pwm_clock)(struct nvkm_therm *, int line); + + int (*temp_get)(struct nvkm_therm *); + + int (*fan_sense)(struct nvkm_therm *); + + void (*program_alarms)(struct nvkm_therm *); +}; + +void nv40_therm_intr(struct nvkm_therm *); + int nv50_fan_pwm_ctrl(struct nvkm_therm *, int, bool); int nv50_fan_pwm_get(struct nvkm_therm *, int, u32 *, u32 *); int nv50_fan_pwm_set(struct nvkm_therm *, int, u32, u32); int nv50_fan_pwm_clock(struct nvkm_therm *, int); + int g84_temp_get(struct nvkm_therm *); void g84_sensor_setup(struct nvkm_therm *); -int g84_therm_fini(struct nvkm_object *, bool suspend); +void g84_therm_fini(struct nvkm_therm *); int gt215_therm_fan_sense(struct nvkm_therm *); -int gf110_therm_init(struct nvkm_object *); +void gf119_therm_init(struct nvkm_therm *); int nvkm_fanpwm_create(struct nvkm_therm *, struct dcb_gpio_func *); int nvkm_fantog_create(struct nvkm_therm *, struct dcb_gpio_func *); diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c index aa13744f3..b9703c02d 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c @@ -26,29 +26,25 @@ static void nvkm_therm_temp_set_defaults(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; + therm->bios_sensor.offset_constant = 0; - priv->bios_sensor.offset_constant = 0; + therm->bios_sensor.thrs_fan_boost.temp = 90; + therm->bios_sensor.thrs_fan_boost.hysteresis = 3; - priv->bios_sensor.thrs_fan_boost.temp = 90; - priv->bios_sensor.thrs_fan_boost.hysteresis = 3; + therm->bios_sensor.thrs_down_clock.temp = 95; + therm->bios_sensor.thrs_down_clock.hysteresis = 3; - priv->bios_sensor.thrs_down_clock.temp = 95; - priv->bios_sensor.thrs_down_clock.hysteresis = 3; + therm->bios_sensor.thrs_critical.temp = 105; + therm->bios_sensor.thrs_critical.hysteresis = 5; - priv->bios_sensor.thrs_critical.temp = 105; - priv->bios_sensor.thrs_critical.hysteresis = 5; - - priv->bios_sensor.thrs_shutdown.temp = 135; - priv->bios_sensor.thrs_shutdown.hysteresis = 5; /*not that it matters */ + therm->bios_sensor.thrs_shutdown.temp = 135; + therm->bios_sensor.thrs_shutdown.hysteresis = 5; /*not that it matters */ } - static void nvkm_therm_temp_safety_checks(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *s = &priv->bios_sensor; + struct nvbios_therm_sensor *s = &therm->bios_sensor; /* enforce a minimum hysteresis on thresholds */ s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); @@ -63,8 +59,7 @@ nvkm_therm_sensor_set_threshold_state(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs, enum nvkm_therm_thrs_state st) { - struct nvkm_therm_priv *priv = (void *)therm; - priv->sensor.alarm_state[thrs] = st; + therm->sensor.alarm_state[thrs] = st; } /* must be called with alarm_program_lock taken ! */ @@ -72,8 +67,7 @@ enum nvkm_therm_thrs_state nvkm_therm_sensor_get_threshold_state(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs) { - struct nvkm_therm_priv *priv = (void *)therm; - return priv->sensor.alarm_state[thrs]; + return therm->sensor.alarm_state[thrs]; } static void @@ -87,22 +81,23 @@ void nvkm_therm_sensor_event(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs, enum nvkm_therm_thrs_direction dir) { - struct nvkm_therm_priv *priv = (void *)therm; + struct nvkm_subdev *subdev = &therm->subdev; bool active; const char *thresolds[] = { "fanboost", "downclock", "critical", "shutdown" }; - int temperature = therm->temp_get(therm); + int temperature = therm->func->temp_get(therm); if (thrs < 0 || thrs > 3) return; if (dir == NVKM_THERM_THRS_FALLING) - nv_info(therm, "temperature (%i C) went below the '%s' threshold\n", - temperature, thresolds[thrs]); + nvkm_info(subdev, + "temperature (%i C) went below the '%s' threshold\n", + temperature, thresolds[thrs]); else - nv_info(therm, "temperature (%i C) hit the '%s' threshold\n", - temperature, thresolds[thrs]); + nvkm_info(subdev, "temperature (%i C) hit the '%s' threshold\n", + temperature, thresolds[thrs]); active = (dir == NVKM_THERM_THRS_RISING); switch (thrs) { @@ -113,12 +108,12 @@ nvkm_therm_sensor_event(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs, } break; case NVKM_THERM_THRS_DOWNCLOCK: - if (priv->emergency.downclock) - priv->emergency.downclock(therm, active); + if (therm->emergency.downclock) + therm->emergency.downclock(therm, active); break; case NVKM_THERM_THRS_CRITICAL: - if (priv->emergency.pause) - priv->emergency.pause(therm, active); + if (therm->emergency.pause) + therm->emergency.pause(therm, active); break; case NVKM_THERM_THRS_SHUTDOWN: if (active) { @@ -145,7 +140,7 @@ nvkm_therm_threshold_hyst_polling(struct nvkm_therm *therm, { enum nvkm_therm_thrs_direction direction; enum nvkm_therm_thrs_state prev_state, new_state; - int temp = therm->temp_get(therm); + int temp = therm->func->temp_get(therm); prev_state = nvkm_therm_sensor_get_threshold_state(therm, thrs_name); @@ -166,19 +161,19 @@ nvkm_therm_threshold_hyst_polling(struct nvkm_therm *therm, static void alarm_timer_callback(struct nvkm_alarm *alarm) { - struct nvkm_therm_priv *priv = - container_of(alarm, struct nvkm_therm_priv, sensor.therm_poll_alarm); - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - struct nvkm_timer *ptimer = nvkm_timer(priv); - struct nvkm_therm *therm = &priv->base; + struct nvkm_therm *therm = + container_of(alarm, struct nvkm_therm, sensor.therm_poll_alarm); + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; + struct nvkm_timer *tmr = therm->subdev.device->timer; unsigned long flags; - spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); + spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags); nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, NVKM_THERM_THRS_FANBOOST); - nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_down_clock, + nvkm_therm_threshold_hyst_polling(therm, + &sensor->thrs_down_clock, NVKM_THERM_THRS_DOWNCLOCK); nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_critical, @@ -187,46 +182,45 @@ alarm_timer_callback(struct nvkm_alarm *alarm) nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown, NVKM_THERM_THRS_SHUTDOWN); - spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); + spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); /* schedule the next poll in one second */ - if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head)) - ptimer->alarm(ptimer, 1000000000ULL, alarm); + if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head)) + nvkm_timer_alarm(tmr, 1000000000ULL, alarm); } void nvkm_therm_program_alarms_polling(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - - nv_debug(therm, - "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", - sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis, - sensor->thrs_down_clock.temp, - sensor->thrs_down_clock.hysteresis, - sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis, - sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis); - - alarm_timer_callback(&priv->sensor.therm_poll_alarm); + struct nvbios_therm_sensor *sensor = &therm->bios_sensor; + + nvkm_debug(&therm->subdev, + "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", + sensor->thrs_fan_boost.temp, + sensor->thrs_fan_boost.hysteresis, + sensor->thrs_down_clock.temp, + sensor->thrs_down_clock.hysteresis, + sensor->thrs_critical.temp, + sensor->thrs_critical.hysteresis, + sensor->thrs_shutdown.temp, + sensor->thrs_shutdown.hysteresis); + + alarm_timer_callback(&therm->sensor.therm_poll_alarm); } int nvkm_therm_sensor_init(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - priv->sensor.program_alarms(therm); + therm->func->program_alarms(therm); return 0; } int nvkm_therm_sensor_fini(struct nvkm_therm *therm, bool suspend) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_timer *ptimer = nvkm_timer(therm); - + struct nvkm_timer *tmr = therm->subdev.device->timer; if (suspend) - ptimer->alarm_cancel(ptimer, &priv->sensor.therm_poll_alarm); + nvkm_timer_alarm_cancel(tmr, &therm->sensor.therm_poll_alarm); return 0; } @@ -235,24 +229,24 @@ nvkm_therm_sensor_preinit(struct nvkm_therm *therm) { const char *sensor_avail = "yes"; - if (therm->temp_get(therm) < 0) + if (therm->func->temp_get(therm) < 0) sensor_avail = "no"; - nv_info(therm, "internal sensor: %s\n", sensor_avail); + nvkm_debug(&therm->subdev, "internal sensor: %s\n", sensor_avail); } int nvkm_therm_sensor_ctor(struct nvkm_therm *therm) { - struct nvkm_therm_priv *priv = (void *)therm; - struct nvkm_bios *bios = nvkm_bios(therm); + struct nvkm_subdev *subdev = &therm->subdev; + struct nvkm_bios *bios = subdev->device->bios; - nvkm_alarm_init(&priv->sensor.therm_poll_alarm, alarm_timer_callback); + nvkm_alarm_init(&therm->sensor.therm_poll_alarm, alarm_timer_callback); nvkm_therm_temp_set_defaults(therm); if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, - &priv->bios_sensor)) - nv_error(therm, "nvbios_therm_sensor_parse failed\n"); + &therm->bios_sensor)) + nvkm_error(subdev, "nvbios_therm_sensor_parse failed\n"); nvkm_therm_temp_safety_checks(therm); return 0; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/Kbuild index d1d38b4ba..e436f0ffe 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/Kbuild @@ -1,3 +1,5 @@ nvkm-y += nvkm/subdev/timer/base.o nvkm-y += nvkm/subdev/timer/nv04.o +nvkm-y += nvkm/subdev/timer/nv40.o +nvkm-y += nvkm/subdev/timer/nv41.o nvkm-y += nvkm/subdev/timer/gk20a.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index d894061ce..d4dae1f12 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -21,73 +21,131 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" -bool -nvkm_timer_wait_eq(void *obj, u64 nsec, u32 addr, u32 mask, u32 data) +u64 +nvkm_timer_read(struct nvkm_timer *tmr) { - struct nvkm_timer *ptimer = nvkm_timer(obj); - u64 time0; - - time0 = ptimer->read(ptimer); - do { - if (nv_iclass(obj, NV_SUBDEV_CLASS)) { - if ((nv_rd32(obj, addr) & mask) == data) - return true; - } else { - if ((nv_ro32(obj, addr) & mask) == data) - return true; - } - } while (ptimer->read(ptimer) - time0 < nsec); + return tmr->func->read(tmr); +} + +void +nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) +{ + struct nvkm_alarm *alarm, *atemp; + unsigned long flags; + LIST_HEAD(exec); + + /* move any due alarms off the pending list */ + spin_lock_irqsave(&tmr->lock, flags); + list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) { + if (alarm->timestamp <= nvkm_timer_read(tmr)) + list_move_tail(&alarm->head, &exec); + } - return false; + /* reschedule interrupt for next alarm time */ + if (!list_empty(&tmr->alarms)) { + alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head); + tmr->func->alarm_init(tmr, alarm->timestamp); + } else { + tmr->func->alarm_fini(tmr); + } + spin_unlock_irqrestore(&tmr->lock, flags); + + /* execute any pending alarm handlers */ + list_for_each_entry_safe(alarm, atemp, &exec, head) { + list_del_init(&alarm->head); + alarm->func(alarm); + } } -bool -nvkm_timer_wait_ne(void *obj, u64 nsec, u32 addr, u32 mask, u32 data) +void +nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) { - struct nvkm_timer *ptimer = nvkm_timer(obj); - u64 time0; - - time0 = ptimer->read(ptimer); - do { - if (nv_iclass(obj, NV_SUBDEV_CLASS)) { - if ((nv_rd32(obj, addr) & mask) != data) - return true; - } else { - if ((nv_ro32(obj, addr) & mask) != data) - return true; + struct nvkm_alarm *list; + unsigned long flags; + + alarm->timestamp = nvkm_timer_read(tmr) + nsec; + + /* append new alarm to list, in soonest-alarm-first order */ + spin_lock_irqsave(&tmr->lock, flags); + if (!nsec) { + if (!list_empty(&alarm->head)) + list_del(&alarm->head); + } else { + list_for_each_entry(list, &tmr->alarms, head) { + if (list->timestamp > alarm->timestamp) + break; } - } while (ptimer->read(ptimer) - time0 < nsec); + list_add_tail(&alarm->head, &list->head); + } + spin_unlock_irqrestore(&tmr->lock, flags); - return false; + /* process pending alarms */ + nvkm_timer_alarm_trigger(tmr); } -bool -nvkm_timer_wait_cb(void *obj, u64 nsec, bool (*func)(void *), void *data) +void +nvkm_timer_alarm_cancel(struct nvkm_timer *tmr, struct nvkm_alarm *alarm) { - struct nvkm_timer *ptimer = nvkm_timer(obj); - u64 time0; + unsigned long flags; + spin_lock_irqsave(&tmr->lock, flags); + list_del_init(&alarm->head); + spin_unlock_irqrestore(&tmr->lock, flags); +} - time0 = ptimer->read(ptimer); - do { - if (func(data) == true) - return true; - } while (ptimer->read(ptimer) - time0 < nsec); +static void +nvkm_timer_intr(struct nvkm_subdev *subdev) +{ + struct nvkm_timer *tmr = nvkm_timer(subdev); + tmr->func->intr(tmr); +} - return false; +static int +nvkm_timer_fini(struct nvkm_subdev *subdev, bool suspend) +{ + struct nvkm_timer *tmr = nvkm_timer(subdev); + tmr->func->alarm_fini(tmr); + return 0; } -void -nvkm_timer_alarm(void *obj, u32 nsec, struct nvkm_alarm *alarm) +static int +nvkm_timer_init(struct nvkm_subdev *subdev) { - struct nvkm_timer *ptimer = nvkm_timer(obj); - ptimer->alarm(ptimer, nsec, alarm); + struct nvkm_timer *tmr = nvkm_timer(subdev); + if (tmr->func->init) + tmr->func->init(tmr); + tmr->func->time(tmr, ktime_to_ns(ktime_get())); + nvkm_timer_alarm_trigger(tmr); + return 0; } -void -nvkm_timer_alarm_cancel(void *obj, struct nvkm_alarm *alarm) +static void * +nvkm_timer_dtor(struct nvkm_subdev *subdev) { - struct nvkm_timer *ptimer = nvkm_timer(obj); - ptimer->alarm_cancel(ptimer, alarm); + return nvkm_timer(subdev); +} + +static const struct nvkm_subdev_func +nvkm_timer = { + .dtor = nvkm_timer_dtor, + .init = nvkm_timer_init, + .fini = nvkm_timer_fini, + .intr = nvkm_timer_intr, +}; + +int +nvkm_timer_new_(const struct nvkm_timer_func *func, struct nvkm_device *device, + int index, struct nvkm_timer **ptmr) +{ + struct nvkm_timer *tmr; + + if (!(tmr = *ptmr = kzalloc(sizeof(*tmr), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_timer, device, index, 0, &tmr->subdev); + tmr->func = func; + INIT_LIST_HEAD(&tmr->alarms); + spin_lock_init(&tmr->lock); + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c index 80e38063d..9ed5f6491 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c @@ -21,36 +21,19 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" -static int -gk20a_timer_init(struct nvkm_object *object) -{ - struct nv04_timer_priv *priv = (void *)object; - u32 hi = upper_32_bits(priv->suspend_time); - u32 lo = lower_32_bits(priv->suspend_time); - int ret; - - ret = nvkm_timer_init(&priv->base); - if (ret) - return ret; - - nv_debug(priv, "time low : 0x%08x\n", lo); - nv_debug(priv, "time high : 0x%08x\n", hi); +static const struct nvkm_timer_func +gk20a_timer = { + .intr = nv04_timer_intr, + .read = nv04_timer_read, + .time = nv04_timer_time, + .alarm_init = nv04_timer_alarm_init, + .alarm_fini = nv04_timer_alarm_fini, +}; - /* restore the time before suspend */ - nv_wr32(priv, NV04_PTIMER_TIME_1, hi); - nv_wr32(priv, NV04_PTIMER_TIME_0, lo); - return 0; +int +gk20a_timer_new(struct nvkm_device *device, int index, struct nvkm_timer **ptmr) +{ + return nvkm_timer_new_(&gk20a_timer, device, index, ptmr); } - -struct nvkm_oclass -gk20a_timer_oclass = { - .handle = NV_SUBDEV(TIMER, 0xff), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_timer_ctor, - .dtor = nv04_timer_dtor, - .init = gk20a_timer_init, - .fini = nv04_timer_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c index 6b7facbe5..7b9ce87f0 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c @@ -21,165 +21,92 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "priv.h" +#include "regsnv04.h" -#include - -static u64 -nv04_timer_read(struct nvkm_timer *ptimer) +void +nv04_timer_time(struct nvkm_timer *tmr, u64 time) { - struct nv04_timer_priv *priv = (void *)ptimer; - u32 hi, lo; + struct nvkm_subdev *subdev = &tmr->subdev; + struct nvkm_device *device = subdev->device; + u32 hi = upper_32_bits(time); + u32 lo = lower_32_bits(time); - do { - hi = nv_rd32(priv, NV04_PTIMER_TIME_1); - lo = nv_rd32(priv, NV04_PTIMER_TIME_0); - } while (hi != nv_rd32(priv, NV04_PTIMER_TIME_1)); + nvkm_debug(subdev, "time low : %08x\n", lo); + nvkm_debug(subdev, "time high : %08x\n", hi); - return ((u64)hi << 32 | lo); + nvkm_wr32(device, NV04_PTIMER_TIME_1, hi); + nvkm_wr32(device, NV04_PTIMER_TIME_0, lo); } -static void -nv04_timer_alarm_trigger(struct nvkm_timer *ptimer) +u64 +nv04_timer_read(struct nvkm_timer *tmr) { - struct nv04_timer_priv *priv = (void *)ptimer; - struct nvkm_alarm *alarm, *atemp; - unsigned long flags; - LIST_HEAD(exec); - - /* move any due alarms off the pending list */ - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry_safe(alarm, atemp, &priv->alarms, head) { - if (alarm->timestamp <= ptimer->read(ptimer)) - list_move_tail(&alarm->head, &exec); - } + struct nvkm_device *device = tmr->subdev.device; + u32 hi, lo; - /* reschedule interrupt for next alarm time */ - if (!list_empty(&priv->alarms)) { - alarm = list_first_entry(&priv->alarms, typeof(*alarm), head); - nv_wr32(priv, NV04_PTIMER_ALARM_0, alarm->timestamp); - nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000001); - } else { - nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); - } - spin_unlock_irqrestore(&priv->lock, flags); + do { + hi = nvkm_rd32(device, NV04_PTIMER_TIME_1); + lo = nvkm_rd32(device, NV04_PTIMER_TIME_0); + } while (hi != nvkm_rd32(device, NV04_PTIMER_TIME_1)); - /* execute any pending alarm handlers */ - list_for_each_entry_safe(alarm, atemp, &exec, head) { - list_del_init(&alarm->head); - alarm->func(alarm); - } + return ((u64)hi << 32 | lo); } -static void -nv04_timer_alarm(struct nvkm_timer *ptimer, u64 time, struct nvkm_alarm *alarm) +void +nv04_timer_alarm_fini(struct nvkm_timer *tmr) { - struct nv04_timer_priv *priv = (void *)ptimer; - struct nvkm_alarm *list; - unsigned long flags; - - alarm->timestamp = ptimer->read(ptimer) + time; - - /* append new alarm to list, in soonest-alarm-first order */ - spin_lock_irqsave(&priv->lock, flags); - if (!time) { - if (!list_empty(&alarm->head)) - list_del(&alarm->head); - } else { - list_for_each_entry(list, &priv->alarms, head) { - if (list->timestamp > alarm->timestamp) - break; - } - list_add_tail(&alarm->head, &list->head); - } - spin_unlock_irqrestore(&priv->lock, flags); - - /* process pending alarms */ - nv04_timer_alarm_trigger(ptimer); + struct nvkm_device *device = tmr->subdev.device; + nvkm_wr32(device, NV04_PTIMER_INTR_EN_0, 0x00000000); } -static void -nv04_timer_alarm_cancel(struct nvkm_timer *ptimer, struct nvkm_alarm *alarm) +void +nv04_timer_alarm_init(struct nvkm_timer *tmr, u32 time) { - struct nv04_timer_priv *priv = (void *)ptimer; - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - list_del_init(&alarm->head); - spin_unlock_irqrestore(&priv->lock, flags); + struct nvkm_device *device = tmr->subdev.device; + nvkm_wr32(device, NV04_PTIMER_ALARM_0, time); + nvkm_wr32(device, NV04_PTIMER_INTR_EN_0, 0x00000001); } -static void -nv04_timer_intr(struct nvkm_subdev *subdev) +void +nv04_timer_intr(struct nvkm_timer *tmr) { - struct nv04_timer_priv *priv = (void *)subdev; - u32 stat = nv_rd32(priv, NV04_PTIMER_INTR_0); + struct nvkm_subdev *subdev = &tmr->subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0); if (stat & 0x00000001) { - nv04_timer_alarm_trigger(&priv->base); - nv_wr32(priv, NV04_PTIMER_INTR_0, 0x00000001); + nvkm_timer_alarm_trigger(tmr); + nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001); stat &= ~0x00000001; } if (stat) { - nv_error(priv, "unknown stat 0x%08x\n", stat); - nv_wr32(priv, NV04_PTIMER_INTR_0, stat); + nvkm_error(subdev, "intr %08x\n", stat); + nvkm_wr32(device, NV04_PTIMER_INTR_0, stat); } } -int -nv04_timer_fini(struct nvkm_object *object, bool suspend) -{ - struct nv04_timer_priv *priv = (void *)object; - if (suspend) - priv->suspend_time = nv04_timer_read(&priv->base); - nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); - return nvkm_timer_fini(&priv->base, suspend); -} - -static int -nv04_timer_init(struct nvkm_object *object) +static void +nv04_timer_init(struct nvkm_timer *tmr) { - struct nvkm_device *device = nv_device(object); - struct nv04_timer_priv *priv = (void *)object; - u32 m = 1, f, n, d, lo, hi; - int ret; - - ret = nvkm_timer_init(&priv->base); - if (ret) - return ret; + struct nvkm_subdev *subdev = &tmr->subdev; + struct nvkm_device *device = subdev->device; + u32 f = 0; /*XXX: nvclk */ + u32 n, d; /* aim for 31.25MHz, which gives us nanosecond timestamps */ d = 1000000 / 32; - - /* determine base clock for timer source */ -#if 0 /*XXX*/ - if (device->chipset < 0x40) { - n = nvkm_hw_get_clock(device, PLL_CORE); - } else -#endif - if (device->chipset <= 0x40) { - /*XXX: figure this out */ - f = -1; - n = 0; - } else { - f = device->crystal; - n = f; - while (n < (d * 2)) { - n += (n / m); - m++; - } - - nv_wr32(priv, 0x009220, m - 1); - } - - if (!n) { - nv_warn(priv, "unknown input clock freq\n"); - if (!nv_rd32(priv, NV04_PTIMER_NUMERATOR) || - !nv_rd32(priv, NV04_PTIMER_DENOMINATOR)) { - nv_wr32(priv, NV04_PTIMER_NUMERATOR, 1); - nv_wr32(priv, NV04_PTIMER_DENOMINATOR, 1); + n = f; + + if (!f) { + n = nvkm_rd32(device, NV04_PTIMER_NUMERATOR); + d = nvkm_rd32(device, NV04_PTIMER_DENOMINATOR); + if (!n || !d) { + n = 1; + d = 1; } - return 0; + nvkm_warn(subdev, "unknown input clock freq\n"); } /* reduce ratio to acceptable values */ @@ -198,65 +125,27 @@ nv04_timer_init(struct nvkm_object *object) d >>= 1; } - /* restore the time before suspend */ - lo = priv->suspend_time; - hi = (priv->suspend_time >> 32); + nvkm_debug(subdev, "input frequency : %dHz\n", f); + nvkm_debug(subdev, "numerator : %08x\n", n); + nvkm_debug(subdev, "denominator : %08x\n", d); + nvkm_debug(subdev, "timer frequency : %dHz\n", f * d / n); - nv_debug(priv, "input frequency : %dHz\n", f); - nv_debug(priv, "input multiplier: %d\n", m); - nv_debug(priv, "numerator : 0x%08x\n", n); - nv_debug(priv, "denominator : 0x%08x\n", d); - nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); - nv_debug(priv, "time low : 0x%08x\n", lo); - nv_debug(priv, "time high : 0x%08x\n", hi); - - nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); - nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); - nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); - nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); - nv_wr32(priv, NV04_PTIMER_TIME_1, hi); - nv_wr32(priv, NV04_PTIMER_TIME_0, lo); - return 0; + nvkm_wr32(device, NV04_PTIMER_NUMERATOR, n); + nvkm_wr32(device, NV04_PTIMER_DENOMINATOR, d); } -void -nv04_timer_dtor(struct nvkm_object *object) -{ - struct nv04_timer_priv *priv = (void *)object; - return nvkm_timer_destroy(&priv->base); -} +static const struct nvkm_timer_func +nv04_timer = { + .init = nv04_timer_init, + .intr = nv04_timer_intr, + .read = nv04_timer_read, + .time = nv04_timer_time, + .alarm_init = nv04_timer_alarm_init, + .alarm_fini = nv04_timer_alarm_fini, +}; int -nv04_timer_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_timer_new(struct nvkm_device *device, int index, struct nvkm_timer **ptmr) { - struct nv04_timer_priv *priv; - int ret; - - ret = nvkm_timer_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.intr = nv04_timer_intr; - priv->base.read = nv04_timer_read; - priv->base.alarm = nv04_timer_alarm; - priv->base.alarm_cancel = nv04_timer_alarm_cancel; - priv->suspend_time = 0; - - INIT_LIST_HEAD(&priv->alarms); - spin_lock_init(&priv->lock); - return 0; + return nvkm_timer_new_(&nv04_timer, device, index, ptmr); } - -struct nvkm_oclass -nv04_timer_oclass = { - .handle = NV_SUBDEV(TIMER, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_timer_ctor, - .dtor = nv04_timer_dtor, - .init = nv04_timer_init, - .fini = nv04_timer_fini, - } -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h deleted file mode 100644 index 89996a982..000000000 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __NVKM_TIMER_NV04_H__ -#define __NVKM_TIMER_NV04_H__ -#include "priv.h" - -#define NV04_PTIMER_INTR_0 0x009100 -#define NV04_PTIMER_INTR_EN_0 0x009140 -#define NV04_PTIMER_NUMERATOR 0x009200 -#define NV04_PTIMER_DENOMINATOR 0x009210 -#define NV04_PTIMER_TIME_0 0x009400 -#define NV04_PTIMER_TIME_1 0x009410 -#define NV04_PTIMER_ALARM_0 0x009420 - -struct nv04_timer_priv { - struct nvkm_timer base; - struct list_head alarms; - spinlock_t lock; - u64 suspend_time; -}; - -int nv04_timer_ctor(struct nvkm_object *, struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv04_timer_dtor(struct nvkm_object *); -int nv04_timer_fini(struct nvkm_object *, bool); -#endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv40.c new file mode 100644 index 000000000..bb99a152f --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv40.c @@ -0,0 +1,88 @@ +/* + * 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 "priv.h" +#include "regsnv04.h" + +static void +nv40_timer_init(struct nvkm_timer *tmr) +{ + struct nvkm_subdev *subdev = &tmr->subdev; + struct nvkm_device *device = subdev->device; + u32 f = 0; /*XXX: figure this out */ + u32 n, d; + + /* aim for 31.25MHz, which gives us nanosecond timestamps */ + d = 1000000 / 32; + n = f; + + if (!f) { + n = nvkm_rd32(device, NV04_PTIMER_NUMERATOR); + d = nvkm_rd32(device, NV04_PTIMER_DENOMINATOR); + if (!n || !d) { + n = 1; + d = 1; + } + nvkm_warn(subdev, "unknown input clock freq\n"); + } + + /* reduce ratio to acceptable values */ + while (((n % 5) == 0) && ((d % 5) == 0)) { + n /= 5; + d /= 5; + } + + while (((n % 2) == 0) && ((d % 2) == 0)) { + n /= 2; + d /= 2; + } + + while (n > 0xffff || d > 0xffff) { + n >>= 1; + d >>= 1; + } + + nvkm_debug(subdev, "input frequency : %dHz\n", f); + nvkm_debug(subdev, "numerator : %08x\n", n); + nvkm_debug(subdev, "denominator : %08x\n", d); + nvkm_debug(subdev, "timer frequency : %dHz\n", f * d / n); + + nvkm_wr32(device, NV04_PTIMER_NUMERATOR, n); + nvkm_wr32(device, NV04_PTIMER_DENOMINATOR, d); +} + +static const struct nvkm_timer_func +nv40_timer = { + .init = nv40_timer_init, + .intr = nv04_timer_intr, + .read = nv04_timer_read, + .time = nv04_timer_time, + .alarm_init = nv04_timer_alarm_init, + .alarm_fini = nv04_timer_alarm_fini, +}; + +int +nv40_timer_new(struct nvkm_device *device, int index, struct nvkm_timer **ptmr) +{ + return nvkm_timer_new_(&nv40_timer, device, index, ptmr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv41.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv41.c new file mode 100644 index 000000000..3cf9ec1b1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv41.c @@ -0,0 +1,85 @@ +/* + * 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 "priv.h" +#include "regsnv04.h" + +static void +nv41_timer_init(struct nvkm_timer *tmr) +{ + struct nvkm_subdev *subdev = &tmr->subdev; + struct nvkm_device *device = subdev->device; + u32 f = device->crystal; + u32 m = 1, n, d; + + /* aim for 31.25MHz, which gives us nanosecond timestamps */ + d = 1000000 / 32; + n = f; + + while (n < (d * 2)) { + n += (n / m); + m++; + } + + /* reduce ratio to acceptable values */ + while (((n % 5) == 0) && ((d % 5) == 0)) { + n /= 5; + d /= 5; + } + + while (((n % 2) == 0) && ((d % 2) == 0)) { + n /= 2; + d /= 2; + } + + while (n > 0xffff || d > 0xffff) { + n >>= 1; + d >>= 1; + } + + nvkm_debug(subdev, "input frequency : %dHz\n", f); + nvkm_debug(subdev, "input multiplier: %d\n", m); + nvkm_debug(subdev, "numerator : %08x\n", n); + nvkm_debug(subdev, "denominator : %08x\n", d); + nvkm_debug(subdev, "timer frequency : %dHz\n", (f * m) * d / n); + + nvkm_wr32(device, 0x009220, m - 1); + nvkm_wr32(device, NV04_PTIMER_NUMERATOR, n); + nvkm_wr32(device, NV04_PTIMER_DENOMINATOR, d); +} + +static const struct nvkm_timer_func +nv41_timer = { + .init = nv41_timer_init, + .intr = nv04_timer_intr, + .read = nv04_timer_read, + .time = nv04_timer_time, + .alarm_init = nv04_timer_alarm_init, + .alarm_fini = nv04_timer_alarm_fini, +}; + +int +nv41_timer_new(struct nvkm_device *device, int index, struct nvkm_timer **ptmr) +{ + return nvkm_timer_new_(&nv41_timer, device, index, ptmr); +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h index 08e29a3da..f820ca2ae 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h @@ -1,4 +1,26 @@ #ifndef __NVKM_TIMER_PRIV_H__ #define __NVKM_TIMER_PRIV_H__ +#define nvkm_timer(p) container_of((p), struct nvkm_timer, subdev) #include + +int nvkm_timer_new_(const struct nvkm_timer_func *, struct nvkm_device *, + int index, struct nvkm_timer **); + +struct nvkm_timer_func { + void (*init)(struct nvkm_timer *); + void (*intr)(struct nvkm_timer *); + u64 (*read)(struct nvkm_timer *); + void (*time)(struct nvkm_timer *, u64 time); + void (*alarm_init)(struct nvkm_timer *, u32 time); + void (*alarm_fini)(struct nvkm_timer *); +}; + +void nvkm_timer_alarm_trigger(struct nvkm_timer *); + +void nv04_timer_fini(struct nvkm_timer *); +void nv04_timer_intr(struct nvkm_timer *); +void nv04_timer_time(struct nvkm_timer *, u64); +u64 nv04_timer_read(struct nvkm_timer *); +void nv04_timer_alarm_init(struct nvkm_timer *, u32); +void nv04_timer_alarm_fini(struct nvkm_timer *); #endif diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h new file mode 100644 index 000000000..10bef85b4 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h @@ -0,0 +1,7 @@ +#define NV04_PTIMER_INTR_0 0x009100 +#define NV04_PTIMER_INTR_EN_0 0x009140 +#define NV04_PTIMER_NUMERATOR 0x009200 +#define NV04_PTIMER_DENOMINATOR 0x009210 +#define NV04_PTIMER_TIME_0 0x009400 +#define NV04_PTIMER_TIME_1 0x009410 +#define NV04_PTIMER_ALARM_0 0x009420 diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild index 6b46ff421..b035c6e28 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild @@ -1,4 +1,5 @@ nvkm-y += nvkm/subdev/volt/base.o nvkm-y += nvkm/subdev/volt/gpio.o nvkm-y += nvkm/subdev/volt/nv40.o +nvkm-y += nvkm/subdev/volt/gk104.o nvkm-y += nvkm/subdev/volt/gk20a.o diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 39f15803f..50b5649ad 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -21,49 +21,54 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" + #include #include #include -static int +int nvkm_volt_get(struct nvkm_volt *volt) { - if (volt->vid_get) { - int ret = volt->vid_get(volt), i; - if (ret >= 0) { - for (i = 0; i < volt->vid_nr; i++) { - if (volt->vid[i].vid == ret) - return volt->vid[i].uv; - } - ret = -EINVAL; + int ret, i; + + if (volt->func->volt_get) + return volt->func->volt_get(volt); + + ret = volt->func->vid_get(volt); + if (ret >= 0) { + for (i = 0; i < volt->vid_nr; i++) { + if (volt->vid[i].vid == ret) + return volt->vid[i].uv; } - return ret; + ret = -EINVAL; } - return -ENODEV; + return ret; } static int nvkm_volt_set(struct nvkm_volt *volt, u32 uv) { - if (volt->vid_set) { - int i, ret = -EINVAL; - for (i = 0; i < volt->vid_nr; i++) { - if (volt->vid[i].uv == uv) { - ret = volt->vid_set(volt, volt->vid[i].vid); - nv_debug(volt, "set %duv: %d\n", uv, ret); - break; - } + struct nvkm_subdev *subdev = &volt->subdev; + int i, ret = -EINVAL; + + if (volt->func->volt_set) + return volt->func->volt_set(volt, uv); + + for (i = 0; i < volt->vid_nr; i++) { + if (volt->vid[i].uv == uv) { + ret = volt->func->vid_set(volt, volt->vid[i].vid); + nvkm_debug(subdev, "set %duv: %d\n", uv, ret); + break; } - return ret; } - return -ENODEV; + return ret; } static int nvkm_volt_map(struct nvkm_volt *volt, u8 id) { - struct nvkm_bios *bios = nvkm_bios(volt); + struct nvkm_bios *bios = volt->subdev.device->bios; struct nvbios_vmap_entry info; u8 ver, len; u16 vmap; @@ -82,10 +87,15 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id) return id ? id * 10000 : -ENODEV; } -static int +int nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) { - int ret = nvkm_volt_map(volt, id); + int ret; + + if (volt->func->set_id) + return volt->func->set_id(volt, id, condition); + + ret = nvkm_volt_map(volt, id); if (ret >= 0) { int prev = nvkm_volt_get(volt); if (!condition || prev < 0 || @@ -134,51 +144,41 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) } } -int -_nvkm_volt_init(struct nvkm_object *object) +static int +nvkm_volt_init(struct nvkm_subdev *subdev) { - struct nvkm_volt *volt = (void *)object; - int ret; - - ret = nvkm_subdev_init(&volt->base); - if (ret) - return ret; - - ret = volt->get(volt); + struct nvkm_volt *volt = nvkm_volt(subdev); + int ret = nvkm_volt_get(volt); if (ret < 0) { if (ret != -ENODEV) - nv_debug(volt, "current voltage unknown\n"); + nvkm_debug(subdev, "current voltage unknown\n"); return 0; } - - nv_info(volt, "GPU voltage: %duv\n", ret); + nvkm_debug(subdev, "current voltage: %duv\n", ret); return 0; } -void -_nvkm_volt_dtor(struct nvkm_object *object) +static void * +nvkm_volt_dtor(struct nvkm_subdev *subdev) { - struct nvkm_volt *volt = (void *)object; - nvkm_subdev_destroy(&volt->base); + return nvkm_volt(subdev); } -int -nvkm_volt_create_(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, int length, void **pobject) -{ - struct nvkm_bios *bios = nvkm_bios(parent); - struct nvkm_volt *volt; - int ret, i; +static const struct nvkm_subdev_func +nvkm_volt = { + .dtor = nvkm_volt_dtor, + .init = nvkm_volt_init, +}; - ret = nvkm_subdev_create_(parent, engine, oclass, 0, "VOLT", - "voltage", length, pobject); - volt = *pobject; - if (ret) - return ret; +void +nvkm_volt_ctor(const struct nvkm_volt_func *func, struct nvkm_device *device, + int index, struct nvkm_volt *volt) +{ + struct nvkm_bios *bios = device->bios; + int i; - volt->get = nvkm_volt_get; - volt->set = nvkm_volt_set; - volt->set_id = nvkm_volt_set_id; + nvkm_subdev_ctor(&nvkm_volt, device, index, 0, &volt->subdev); + volt->func = func; /* Assuming the non-bios device should build the voltage table later */ if (bios) @@ -186,19 +186,18 @@ nvkm_volt_create_(struct nvkm_object *parent, struct nvkm_object *engine, if (volt->vid_nr) { for (i = 0; i < volt->vid_nr; i++) { - nv_debug(volt, "VID %02x: %duv\n", - volt->vid[i].vid, volt->vid[i].uv); - } - - /*XXX: this is an assumption.. there probably exists boards - * out there with i2c-connected voltage controllers too.. - */ - ret = nvkm_voltgpio_init(volt); - if (ret == 0) { - volt->vid_get = nvkm_voltgpio_get; - volt->vid_set = nvkm_voltgpio_set; + nvkm_debug(&volt->subdev, "VID %02x: %duv\n", + volt->vid[i].vid, volt->vid[i].uv); } } +} - return ret; +int +nvkm_volt_new_(const struct nvkm_volt_func *func, struct nvkm_device *device, + int index, struct nvkm_volt **pvolt) +{ + if (!(*pvolt = kzalloc(sizeof(**pvolt), GFP_KERNEL))) + return -ENOMEM; + nvkm_volt_ctor(func, device, index, *pvolt); + return 0; } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c new file mode 100644 index 000000000..b735173a1 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c @@ -0,0 +1,119 @@ +/* + * Copyright 2015 Martin Peres + * + * 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: Martin Peres + */ +#include "priv.h" + +#include +#include +#include +#include + +#define gk104_volt(p) container_of((p), struct gk104_volt, base) +struct gk104_volt { + struct nvkm_volt base; + struct nvbios_volt bios; +}; + +int +gk104_volt_get(struct nvkm_volt *base) +{ + struct nvbios_volt *bios = &gk104_volt(base)->bios; + struct nvkm_device *device = base->subdev.device; + u32 div, duty; + + div = nvkm_rd32(device, 0x20340); + duty = nvkm_rd32(device, 0x20344); + + return bios->base + bios->pwm_range * duty / div; +} + +int +gk104_volt_set(struct nvkm_volt *base, u32 uv) +{ + struct nvbios_volt *bios = &gk104_volt(base)->bios; + struct nvkm_device *device = base->subdev.device; + u32 div, duty; + + /* the blob uses this crystal frequency, let's use it too. */ + div = 27648000 / bios->pwm_freq; + duty = (uv - bios->base) * div / bios->pwm_range; + + nvkm_wr32(device, 0x20340, div); + nvkm_wr32(device, 0x20344, 0x80000000 | duty); + + return 0; +} + +static const struct nvkm_volt_func +gk104_volt_pwm = { + .volt_get = gk104_volt_get, + .volt_set = gk104_volt_set, +}, gk104_volt_gpio = { + .vid_get = nvkm_voltgpio_get, + .vid_set = nvkm_voltgpio_set, +}; + +int +gk104_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) +{ + const struct nvkm_volt_func *volt_func = &gk104_volt_gpio; + struct dcb_gpio_func gpio; + struct nvbios_volt bios; + struct gk104_volt *volt; + u8 ver, hdr, cnt, len; + const char *mode; + + if (!nvbios_volt_parse(device->bios, &ver, &hdr, &cnt, &len, &bios)) + return 0; + + if (!nvkm_gpio_find(device->gpio, 0, DCB_GPIO_VID_PWM, 0xff, &gpio) && + bios.type == NVBIOS_VOLT_PWM) { + volt_func = &gk104_volt_pwm; + } + + if (!(volt = kzalloc(sizeof(*volt), GFP_KERNEL))) + return -ENOMEM; + nvkm_volt_ctor(volt_func, device, index, &volt->base); + *pvolt = &volt->base; + volt->bios = bios; + + /* now that we have a subdev, we can show an error if we found through + * the voltage table that we were supposed to use the PWN mode but we + * did not find the right GPIO for it. + */ + if (bios.type == NVBIOS_VOLT_PWM && volt_func != &gk104_volt_pwm) { + nvkm_error(&volt->base.subdev, + "Type mismatch between the voltage table type and " + "the GPIO table. Fallback to GPIO mode.\n"); + } + + if (volt_func == &gk104_volt_gpio) { + nvkm_voltgpio_init(&volt->base); + mode = "GPIO"; + } else + mode = "PWM"; + + nvkm_debug(&volt->base.subdev, "Using %s mode\n", mode); + + return 0; +} diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c index 871fd5101..fd56c6476 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c @@ -19,10 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include -#ifdef __KERNEL__ -#include -#endif +#define gk20a_volt(p) container_of((p), struct gk20a_volt, base) +#include "priv.h" + +#include struct cvb_coef { int c0; @@ -33,7 +33,7 @@ struct cvb_coef { int c5; }; -struct gk20a_volt_priv { +struct gk20a_volt { struct nvkm_volt base; struct regulator *vdd; }; @@ -101,43 +101,45 @@ gk20a_volt_calc_voltage(const struct cvb_coef *coef, int speedo) } static int -gk20a_volt_vid_get(struct nvkm_volt *volt) +gk20a_volt_vid_get(struct nvkm_volt *base) { - struct gk20a_volt_priv *priv = (void *)volt; + struct gk20a_volt *volt = gk20a_volt(base); int i, uv; - uv = regulator_get_voltage(priv->vdd); + uv = regulator_get_voltage(volt->vdd); - for (i = 0; i < volt->vid_nr; i++) - if (volt->vid[i].uv >= uv) + for (i = 0; i < volt->base.vid_nr; i++) + if (volt->base.vid[i].uv >= uv) return i; return -EINVAL; } static int -gk20a_volt_vid_set(struct nvkm_volt *volt, u8 vid) +gk20a_volt_vid_set(struct nvkm_volt *base, u8 vid) { - struct gk20a_volt_priv *priv = (void *)volt; + struct gk20a_volt *volt = gk20a_volt(base); + struct nvkm_subdev *subdev = &volt->base.subdev; - nv_debug(volt, "set voltage as %duv\n", volt->vid[vid].uv); - return regulator_set_voltage(priv->vdd, volt->vid[vid].uv, 1200000); + nvkm_debug(subdev, "set voltage as %duv\n", volt->base.vid[vid].uv); + return regulator_set_voltage(volt->vdd, volt->base.vid[vid].uv, 1200000); } static int -gk20a_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) +gk20a_volt_set_id(struct nvkm_volt *base, u8 id, int condition) { - struct gk20a_volt_priv *priv = (void *)volt; - int prev_uv = regulator_get_voltage(priv->vdd); - int target_uv = volt->vid[id].uv; + struct gk20a_volt *volt = gk20a_volt(base); + struct nvkm_subdev *subdev = &volt->base.subdev; + int prev_uv = regulator_get_voltage(volt->vdd); + int target_uv = volt->base.vid[id].uv; int ret; - nv_debug(volt, "prev=%d, target=%d, condition=%d\n", - prev_uv, target_uv, condition); + nvkm_debug(subdev, "prev=%d, target=%d, condition=%d\n", + prev_uv, target_uv, condition); if (!condition || (condition < 0 && target_uv < prev_uv) || (condition > 0 && target_uv > prev_uv)) { - ret = gk20a_volt_vid_set(volt, volt->vid[id].vid); + ret = gk20a_volt_vid_set(&volt->base, volt->base.vid[id].vid); } else { ret = 0; } @@ -145,53 +147,42 @@ gk20a_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) return ret; } -static int -gk20a_volt_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +static const struct nvkm_volt_func +gk20a_volt = { + .vid_get = gk20a_volt_vid_get, + .vid_set = gk20a_volt_vid_set, + .set_id = gk20a_volt_set_id, +}; + +int +gk20a_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) { - struct gk20a_volt_priv *priv; - struct nvkm_volt *volt; - struct nouveau_platform_device *plat; - int i, ret, uv; - - ret = nvkm_volt_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - volt = &priv->base; - - plat = nv_device_to_platform(nv_device(parent)); - - uv = regulator_get_voltage(plat->gpu->vdd); - nv_info(priv, "The default voltage is %duV\n", uv); - - priv->vdd = plat->gpu->vdd; - priv->base.vid_get = gk20a_volt_vid_get; - priv->base.vid_set = gk20a_volt_vid_set; - priv->base.set_id = gk20a_volt_set_id; - - volt->vid_nr = ARRAY_SIZE(gk20a_cvb_coef); - nv_debug(priv, "%s - vid_nr = %d\n", __func__, volt->vid_nr); - for (i = 0; i < volt->vid_nr; i++) { - volt->vid[i].vid = i; - volt->vid[i].uv = gk20a_volt_calc_voltage(&gk20a_cvb_coef[i], - plat->gpu_speedo); - nv_debug(priv, "%2d: vid=%d, uv=%d\n", i, volt->vid[i].vid, - volt->vid[i].uv); + struct nvkm_device_tegra *tdev = device->func->tegra(device); + struct gk20a_volt *volt; + int i, uv; + + if (!(volt = kzalloc(sizeof(*volt), GFP_KERNEL))) + return -ENOMEM; + + nvkm_volt_ctor(&gk20a_volt, device, index, &volt->base); + *pvolt = &volt->base; + + uv = regulator_get_voltage(tdev->vdd); + nvkm_info(&volt->base.subdev, "The default voltage is %duV\n", uv); + + volt->vdd = tdev->vdd; + + volt->base.vid_nr = ARRAY_SIZE(gk20a_cvb_coef); + nvkm_debug(&volt->base.subdev, "%s - vid_nr = %d\n", __func__, + volt->base.vid_nr); + for (i = 0; i < volt->base.vid_nr; i++) { + volt->base.vid[i].vid = i; + volt->base.vid[i].uv = + gk20a_volt_calc_voltage(&gk20a_cvb_coef[i], + tdev->gpu_speedo); + nvkm_debug(&volt->base.subdev, "%2d: vid=%d, uv=%d\n", i, + volt->base.vid[i].vid, volt->base.vid[i].uv); } return 0; } - -struct nvkm_oclass -gk20a_volt_oclass = { - .handle = NV_SUBDEV(VOLT, 0xea), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_volt_ctor, - .dtor = _nvkm_volt_dtor, - .init = _nvkm_volt_init, - .fini = _nvkm_volt_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c index b778deb32..d2bac1d77 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c @@ -34,13 +34,13 @@ static const u8 tags[] = { int nvkm_voltgpio_get(struct nvkm_volt *volt) { - struct nvkm_gpio *gpio = nvkm_gpio(volt); + struct nvkm_gpio *gpio = volt->subdev.device->gpio; u8 vid = 0; int i; for (i = 0; i < ARRAY_SIZE(tags); i++) { if (volt->vid_mask & (1 << i)) { - int ret = gpio->get(gpio, 0, tags[i], 0xff); + int ret = nvkm_gpio_get(gpio, 0, tags[i], 0xff); if (ret < 0) return ret; vid |= ret << i; @@ -53,12 +53,12 @@ nvkm_voltgpio_get(struct nvkm_volt *volt) int nvkm_voltgpio_set(struct nvkm_volt *volt, u8 vid) { - struct nvkm_gpio *gpio = nvkm_gpio(volt); + struct nvkm_gpio *gpio = volt->subdev.device->gpio; int i; for (i = 0; i < ARRAY_SIZE(tags); i++, vid >>= 1) { if (volt->vid_mask & (1 << i)) { - int ret = gpio->set(gpio, 0, tags[i], 0xff, vid & 1); + int ret = nvkm_gpio_set(gpio, 0, tags[i], 0xff, vid & 1); if (ret < 0) return ret; } @@ -70,7 +70,8 @@ nvkm_voltgpio_set(struct nvkm_volt *volt, u8 vid) int nvkm_voltgpio_init(struct nvkm_volt *volt) { - struct nvkm_gpio *gpio = nvkm_gpio(volt); + struct nvkm_subdev *subdev = &volt->subdev; + struct nvkm_gpio *gpio = subdev->device->gpio; struct dcb_gpio_func func; int i; @@ -82,11 +83,11 @@ nvkm_voltgpio_init(struct nvkm_volt *volt) */ for (i = 0; i < ARRAY_SIZE(tags); i++) { if (volt->vid_mask & (1 << i)) { - int ret = gpio->find(gpio, 0, tags[i], 0xff, &func); + int ret = nvkm_gpio_find(gpio, 0, tags[i], 0xff, &func); if (ret) { if (ret != -ENOENT) return ret; - nv_debug(volt, "VID bit %d has no GPIO\n", i); + nvkm_debug(subdev, "VID bit %d has no GPIO\n", i); volt->vid_mask &= ~(1 << i); } } diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/nv40.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/nv40.c index 0ac5a3f8c..23409387a 100644 --- a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/nv40.c +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/nv40.c @@ -21,35 +21,24 @@ * * Authors: Ben Skeggs */ -#include +#include "priv.h" -struct nv40_volt_priv { - struct nvkm_volt base; +static const struct nvkm_volt_func +nv40_volt = { + .vid_get = nvkm_voltgpio_get, + .vid_set = nvkm_voltgpio_set, }; -static int -nv40_volt_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +int +nv40_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) { - struct nv40_volt_priv *priv; + struct nvkm_volt *volt; int ret; - ret = nvkm_volt_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); + ret = nvkm_volt_new_(&nv40_volt, device, index, &volt); + *pvolt = volt; if (ret) return ret; - return 0; + return nvkm_voltgpio_init(volt); } - -struct nvkm_oclass -nv40_volt_oclass = { - .handle = NV_SUBDEV(VOLT, 0x40), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv40_volt_ctor, - .dtor = _nvkm_volt_dtor, - .init = _nvkm_volt_init, - .fini = _nvkm_volt_fini, - }, -}; diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h new file mode 100644 index 000000000..d5140d991 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_VOLT_PRIV_H__ +#define __NVKM_VOLT_PRIV_H__ +#define nvkm_volt(p) container_of((p), struct nvkm_volt, subdev) +#include + +void nvkm_volt_ctor(const struct nvkm_volt_func *, struct nvkm_device *, + int index, struct nvkm_volt *); +int nvkm_volt_new_(const struct nvkm_volt_func *, struct nvkm_device *, + int index, struct nvkm_volt **); + +struct nvkm_volt_func { + int (*volt_get)(struct nvkm_volt *); + int (*volt_set)(struct nvkm_volt *, u32 uv); + int (*vid_get)(struct nvkm_volt *); + int (*vid_set)(struct nvkm_volt *, u8 vid); + int (*set_id)(struct nvkm_volt *, u8 id, int condition); +}; + +int nvkm_voltgpio_init(struct nvkm_volt *); +int nvkm_voltgpio_get(struct nvkm_volt *); +int nvkm_voltgpio_set(struct nvkm_volt *, u8); + +int nvkm_voltpwm_init(struct nvkm_volt *volt); +int nvkm_voltpwm_get(struct nvkm_volt *volt); +int nvkm_voltpwm_set(struct nvkm_volt *volt, u32 uv); +#endif -- cgit 1.2.3-korg