1 /* $NetBSD: nouveau_nvkm_engine_fifo_chang84.c,v 1.4 2021/12/18 23:45:35 riastradh Exp $ */ 2 3 /* 4 * Copyright 2012 Red Hat Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: Ben Skeggs 25 */ 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_engine_fifo_chang84.c,v 1.4 2021/12/18 23:45:35 riastradh Exp $"); 28 29 #include "channv50.h" 30 31 #include <core/client.h> 32 #include <core/ramht.h> 33 #include <subdev/mmu.h> 34 #include <subdev/timer.h> 35 36 #include <nvif/cl826e.h> 37 38 static int 39 g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type, 40 struct nvkm_event **pevent) 41 { 42 switch (type) { 43 case NV826E_V0_NTFY_NON_STALL_INTERRUPT: 44 *pevent = &chan->fifo->uevent; 45 return 0; 46 default: 47 break; 48 } 49 return -EINVAL; 50 } 51 52 static int 53 g84_fifo_chan_engine(struct nvkm_engine *engine) 54 { 55 switch (engine->subdev.index) { 56 case NVKM_ENGINE_GR : return 0; 57 case NVKM_ENGINE_MPEG : 58 case NVKM_ENGINE_MSPPP : return 1; 59 case NVKM_ENGINE_CE0 : return 2; 60 case NVKM_ENGINE_VP : 61 case NVKM_ENGINE_MSPDEC: return 3; 62 case NVKM_ENGINE_CIPHER: 63 case NVKM_ENGINE_SEC : return 4; 64 case NVKM_ENGINE_BSP : 65 case NVKM_ENGINE_MSVLD : return 5; 66 default: 67 WARN_ON(1); 68 return 0; 69 } 70 } 71 72 static int 73 g84_fifo_chan_engine_addr(struct nvkm_engine *engine) 74 { 75 switch (engine->subdev.index) { 76 case NVKM_ENGINE_DMAOBJ: 77 case NVKM_ENGINE_SW : return -1; 78 case NVKM_ENGINE_GR : return 0x0020; 79 case NVKM_ENGINE_VP : 80 case NVKM_ENGINE_MSPDEC: return 0x0040; 81 case NVKM_ENGINE_MPEG : 82 case NVKM_ENGINE_MSPPP : return 0x0060; 83 case NVKM_ENGINE_BSP : 84 case NVKM_ENGINE_MSVLD : return 0x0080; 85 case NVKM_ENGINE_CIPHER: 86 case NVKM_ENGINE_SEC : return 0x00a0; 87 case NVKM_ENGINE_CE0 : return 0x00c0; 88 default: 89 WARN_ON(1); 90 return -1; 91 } 92 } 93 94 static int 95 g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base, 96 struct nvkm_engine *engine, bool suspend) 97 { 98 struct nv50_fifo_chan *chan = nv50_fifo_chan(base); 99 struct nv50_fifo *fifo = chan->fifo; 100 struct nvkm_subdev *subdev = &fifo->base.engine.subdev; 101 struct nvkm_device *device = subdev->device; 102 u32 engn, save; 103 int offset; 104 bool done; 105 106 offset = g84_fifo_chan_engine_addr(engine); 107 if (offset < 0) 108 return 0; 109 110 engn = g84_fifo_chan_engine(engine); 111 save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn); 112 nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12); 113 done = nvkm_msec(device, 2000, 114 if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) 115 break; 116 ) >= 0; 117 nvkm_wr32(device, 0x002520, save); 118 if (!done) { 119 nvkm_error(subdev, "channel %d [%s] unload timeout\n", 120 chan->base.chid, chan->base.object.client->name); 121 if (suspend) 122 return -EBUSY; 123 } 124 125 nvkm_kmap(chan->eng); 126 nvkm_wo32(chan->eng, offset + 0x00, 0x00000000); 127 nvkm_wo32(chan->eng, offset + 0x04, 0x00000000); 128 nvkm_wo32(chan->eng, offset + 0x08, 0x00000000); 129 nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000); 130 nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); 131 nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); 132 nvkm_done(chan->eng); 133 return 0; 134 } 135 136 137 static int 138 g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base, 139 struct nvkm_engine *engine) 140 { 141 struct nv50_fifo_chan *chan = nv50_fifo_chan(base); 142 struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index]; 143 u64 limit, start; 144 int offset; 145 146 offset = g84_fifo_chan_engine_addr(engine); 147 if (offset < 0) 148 return 0; 149 limit = engn->addr + engn->size - 1; 150 start = engn->addr; 151 152 nvkm_kmap(chan->eng); 153 nvkm_wo32(chan->eng, offset + 0x00, 0x00190000); 154 nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit)); 155 nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start)); 156 nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 | 157 upper_32_bits(start)); 158 nvkm_wo32(chan->eng, offset + 0x10, 0x00000000); 159 nvkm_wo32(chan->eng, offset + 0x14, 0x00000000); 160 nvkm_done(chan->eng); 161 return 0; 162 } 163 164 static int 165 g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base, 166 struct nvkm_engine *engine, 167 struct nvkm_object *object) 168 { 169 struct nv50_fifo_chan *chan = nv50_fifo_chan(base); 170 int engn = engine->subdev.index; 171 172 if (g84_fifo_chan_engine_addr(engine) < 0) 173 return 0; 174 175 return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]); 176 } 177 178 static int 179 g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base, 180 struct nvkm_object *object) 181 { 182 struct nv50_fifo_chan *chan = nv50_fifo_chan(base); 183 u32 handle = object->handle; 184 u32 context; 185 186 switch (object->engine->subdev.index) { 187 case NVKM_ENGINE_DMAOBJ: 188 case NVKM_ENGINE_SW : context = 0x00000000; break; 189 case NVKM_ENGINE_GR : context = 0x00100000; break; 190 case NVKM_ENGINE_MPEG : 191 case NVKM_ENGINE_MSPPP : context = 0x00200000; break; 192 case NVKM_ENGINE_ME : 193 case NVKM_ENGINE_CE0 : context = 0x00300000; break; 194 case NVKM_ENGINE_VP : 195 case NVKM_ENGINE_MSPDEC: context = 0x00400000; break; 196 case NVKM_ENGINE_CIPHER: 197 case NVKM_ENGINE_SEC : 198 case NVKM_ENGINE_VIC : context = 0x00500000; break; 199 case NVKM_ENGINE_BSP : 200 case NVKM_ENGINE_MSVLD : context = 0x00600000; break; 201 default: 202 WARN_ON(1); 203 return -EINVAL; 204 } 205 206 return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context); 207 } 208 209 static void 210 g84_fifo_chan_init(struct nvkm_fifo_chan *base) 211 { 212 struct nv50_fifo_chan *chan = nv50_fifo_chan(base); 213 struct nv50_fifo *fifo = chan->fifo; 214 struct nvkm_device *device = fifo->base.engine.subdev.device; 215 u64 addr = chan->ramfc->addr >> 8; 216 u32 chid = chan->base.chid; 217 218 nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr); 219 nv50_fifo_runlist_update(fifo); 220 } 221 222 static const struct nvkm_fifo_chan_func 223 g84_fifo_chan_func = { 224 .dtor = nv50_fifo_chan_dtor, 225 .init = g84_fifo_chan_init, 226 .fini = nv50_fifo_chan_fini, 227 .ntfy = g84_fifo_chan_ntfy, 228 .engine_ctor = g84_fifo_chan_engine_ctor, 229 .engine_dtor = nv50_fifo_chan_engine_dtor, 230 .engine_init = g84_fifo_chan_engine_init, 231 .engine_fini = g84_fifo_chan_engine_fini, 232 .object_ctor = g84_fifo_chan_object_ctor, 233 .object_dtor = nv50_fifo_chan_object_dtor, 234 }; 235 236 int 237 g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, 238 const struct nvkm_oclass *oclass, 239 struct nv50_fifo_chan *chan) 240 { 241 struct nvkm_device *device = fifo->base.engine.subdev.device; 242 int ret; 243 244 if (!vmm) 245 return -EINVAL; 246 247 ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base, 248 0x10000, 0x1000, false, vmm, push, 249 (1ULL << NVKM_ENGINE_BSP) | 250 (1ULL << NVKM_ENGINE_CE0) | 251 (1ULL << NVKM_ENGINE_CIPHER) | 252 (1ULL << NVKM_ENGINE_DMAOBJ) | 253 (1ULL << NVKM_ENGINE_GR) | 254 (1ULL << NVKM_ENGINE_ME) | 255 (1ULL << NVKM_ENGINE_MPEG) | 256 (1ULL << NVKM_ENGINE_MSPDEC) | 257 (1ULL << NVKM_ENGINE_MSPPP) | 258 (1ULL << NVKM_ENGINE_MSVLD) | 259 (1ULL << NVKM_ENGINE_SEC) | 260 (1ULL << NVKM_ENGINE_SW) | 261 (1ULL << NVKM_ENGINE_VIC) | 262 (1ULL << NVKM_ENGINE_VP), 263 0, 0xc00000, 0x2000, oclass, &chan->base); 264 chan->fifo = fifo; 265 if (ret) 266 return ret; 267 268 ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst, 269 &chan->eng); 270 if (ret) 271 return ret; 272 273 ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst, 274 &chan->pgd); 275 if (ret) 276 return ret; 277 278 ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst, 279 &chan->cache); 280 if (ret) 281 return ret; 282 283 ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst, 284 &chan->ramfc); 285 if (ret) 286 return ret; 287 288 return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); 289 } 290