1 /* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 #include "priv.h" 25 #include "cgrp.h" 26 #include "chan.h" 27 #include "runl.h" 28 29 #include <core/ramht.h> 30 #include <subdev/timer.h> 31 32 #include <nvif/class.h> 33 34 static void 35 g84_chan_bind(struct nvkm_chan *chan) 36 { 37 struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; 38 39 nvkm_wr32(device, 0x002600 + (chan->id * 4), chan->ramfc->addr >> 8); 40 } 41 42 static int 43 g84_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv) 44 { 45 struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device; 46 const u32 limit2 = ilog2(length / 8); 47 int ret; 48 49 ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->inst, &chan->eng); 50 if (ret) 51 return ret; 52 53 ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->inst, &chan->pgd); 54 if (ret) 55 return ret; 56 57 ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->inst, &chan->cache); 58 if (ret) 59 return ret; 60 61 ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->inst, &chan->ramfc); 62 if (ret) 63 return ret; 64 65 ret = nvkm_ramht_new(device, 0x8000, 16, chan->inst, &chan->ramht); 66 if (ret) 67 return ret; 68 69 nvkm_kmap(chan->ramfc); 70 nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078); 71 nvkm_wo32(chan->ramfc, 0x44, 0x01003fff); 72 nvkm_wo32(chan->ramfc, 0x48, chan->push->node->offset >> 4); 73 nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(offset)); 74 nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(offset) | (limit2 << 16)); 75 nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff); 76 nvkm_wo32(chan->ramfc, 0x78, 0x00000000); 77 nvkm_wo32(chan->ramfc, 0x7c, 0x30000000 | devm); 78 nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | 79 (4 << 24) /* SEARCH_FULL */ | 80 (chan->ramht->gpuobj->node->offset >> 4)); 81 nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10); 82 nvkm_wo32(chan->ramfc, 0x98, chan->inst->addr >> 12); 83 nvkm_done(chan->ramfc); 84 return 0; 85 } 86 87 static const struct nvkm_chan_func_ramfc 88 g84_chan_ramfc = { 89 .write = g84_chan_ramfc_write, 90 .ctxdma = true, 91 .devm = 0xfff, 92 }; 93 94 const struct nvkm_chan_func 95 g84_chan = { 96 .inst = &nv50_chan_inst, 97 .userd = &nv50_chan_userd, 98 .ramfc = &g84_chan_ramfc, 99 .bind = g84_chan_bind, 100 .unbind = nv50_chan_unbind, 101 .start = nv50_chan_start, 102 .stop = nv50_chan_stop, 103 }; 104 105 static void 106 g84_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan) 107 { 108 struct nvkm_subdev *subdev = &chan->cgrp->runl->fifo->engine.subdev; 109 struct nvkm_device *device = subdev->device; 110 u64 start = 0, limit = 0; 111 u32 flags = 0, ptr0, save; 112 113 switch (engn->engine->subdev.type) { 114 case NVKM_ENGINE_GR : ptr0 = 0x0020; break; 115 case NVKM_ENGINE_VP : 116 case NVKM_ENGINE_MSPDEC: ptr0 = 0x0040; break; 117 case NVKM_ENGINE_MPEG : 118 case NVKM_ENGINE_MSPPP : ptr0 = 0x0060; break; 119 case NVKM_ENGINE_BSP : 120 case NVKM_ENGINE_MSVLD : ptr0 = 0x0080; break; 121 case NVKM_ENGINE_CIPHER: 122 case NVKM_ENGINE_SEC : ptr0 = 0x00a0; break; 123 case NVKM_ENGINE_CE : ptr0 = 0x00c0; break; 124 default: 125 WARN_ON(1); 126 return; 127 } 128 129 if (!cctx) { 130 save = nvkm_mask(device, 0x002520, 0x0000003f, BIT(engn->id - 1)); 131 nvkm_wr32(device, 0x0032fc, chan->inst->addr >> 12); 132 nvkm_msec(device, 2000, 133 if (nvkm_rd32(device, 0x0032fc) != 0xffffffff) 134 break; 135 ); 136 nvkm_wr32(device, 0x002520, save); 137 } else { 138 flags = 0x00190000; 139 start = cctx->vctx->inst->addr; 140 limit = start + cctx->vctx->inst->size - 1; 141 } 142 143 nvkm_kmap(chan->eng); 144 nvkm_wo32(chan->eng, ptr0 + 0x00, flags); 145 nvkm_wo32(chan->eng, ptr0 + 0x04, lower_32_bits(limit)); 146 nvkm_wo32(chan->eng, ptr0 + 0x08, lower_32_bits(start)); 147 nvkm_wo32(chan->eng, ptr0 + 0x0c, upper_32_bits(limit) << 24 | 148 lower_32_bits(start)); 149 nvkm_wo32(chan->eng, ptr0 + 0x10, 0x00000000); 150 nvkm_wo32(chan->eng, ptr0 + 0x14, 0x00000000); 151 nvkm_done(chan->eng); 152 } 153 154 const struct nvkm_engn_func 155 g84_engn = { 156 .bind = g84_ectx_bind, 157 .ramht_add = nv50_eobj_ramht_add, 158 .ramht_del = nv50_eobj_ramht_del, 159 }; 160 161 static void 162 g84_fifo_nonstall_block(struct nvkm_event *event, int type, int index) 163 { 164 struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); 165 unsigned long flags; 166 167 spin_lock_irqsave(&fifo->lock, flags); 168 nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x40000000, 0x00000000); 169 spin_unlock_irqrestore(&fifo->lock, flags); 170 } 171 172 static void 173 g84_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) 174 { 175 struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); 176 unsigned long flags; 177 178 spin_lock_irqsave(&fifo->lock, flags); 179 nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x40000000, 0x40000000); 180 spin_unlock_irqrestore(&fifo->lock, flags); 181 } 182 183 const struct nvkm_event_func 184 g84_fifo_nonstall = { 185 .init = g84_fifo_nonstall_allow, 186 .fini = g84_fifo_nonstall_block, 187 }; 188 189 static int 190 g84_fifo_runl_ctor(struct nvkm_fifo *fifo) 191 { 192 struct nvkm_runl *runl; 193 194 runl = nvkm_runl_new(fifo, 0, 0, 0); 195 if (IS_ERR(runl)) 196 return PTR_ERR(runl); 197 198 nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0); 199 nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0); 200 nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_GR, 0); 201 nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MPEG, 0); 202 nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_ME, 0); 203 nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_VP, 0); 204 nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_CIPHER, 0); 205 nvkm_runl_add(runl, 6, fifo->func->engn, NVKM_ENGINE_BSP, 0); 206 return 0; 207 } 208 209 static const struct nvkm_fifo_func 210 g84_fifo = { 211 .chid_nr = nv50_fifo_chid_nr, 212 .chid_ctor = nv50_fifo_chid_ctor, 213 .runl_ctor = g84_fifo_runl_ctor, 214 .init = nv50_fifo_init, 215 .intr = nv04_fifo_intr, 216 .pause = nv04_fifo_pause, 217 .start = nv04_fifo_start, 218 .nonstall = &g84_fifo_nonstall, 219 .runl = &nv50_runl, 220 .engn = &g84_engn, 221 .engn_sw = &nv50_engn_sw, 222 .cgrp = {{ }, &nv04_cgrp }, 223 .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan }, 224 }; 225 226 int 227 g84_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 228 struct nvkm_fifo **pfifo) 229 { 230 return nvkm_fifo_new_(&g84_fifo, device, type, inst, pfifo); 231 } 232