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 "chan.h" 25 #include "chid.h" 26 #include "runl.h" 27 28 #include "nv50.h" 29 #include "channv50.h" 30 31 #include <core/gpuobj.h> 32 33 #include <nvif/class.h> 34 35 static const struct nvkm_chan_func 36 nv50_chan = { 37 }; 38 39 static const struct nvkm_engn_func 40 nv50_engn = { 41 }; 42 43 const struct nvkm_engn_func 44 nv50_engn_sw = { 45 }; 46 47 static void 48 nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo) 49 { 50 struct nvkm_device *device = fifo->base.engine.subdev.device; 51 struct nvkm_memory *cur; 52 int i, p; 53 54 cur = fifo->runlist[fifo->cur_runlist]; 55 fifo->cur_runlist = !fifo->cur_runlist; 56 57 nvkm_kmap(cur); 58 for (i = 0, p = 0; i < fifo->base.nr; i++) { 59 if (nvkm_rd32(device, 0x002600 + (i * 4)) & 0x80000000) 60 nvkm_wo32(cur, p++ * 4, i); 61 } 62 nvkm_done(cur); 63 64 nvkm_wr32(device, 0x0032f4, nvkm_memory_addr(cur) >> 12); 65 nvkm_wr32(device, 0x0032ec, p); 66 nvkm_wr32(device, 0x002500, 0x00000101); 67 } 68 69 void 70 nv50_fifo_runlist_update(struct nv50_fifo *fifo) 71 { 72 mutex_lock(&fifo->base.mutex); 73 nv50_fifo_runlist_update_locked(fifo); 74 mutex_unlock(&fifo->base.mutex); 75 } 76 77 const struct nvkm_runl_func 78 nv50_runl = { 79 }; 80 81 void 82 nv50_fifo_init(struct nvkm_fifo *base) 83 { 84 struct nv50_fifo *fifo = nv50_fifo(base); 85 struct nvkm_device *device = fifo->base.engine.subdev.device; 86 int i; 87 88 nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); 89 nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); 90 nvkm_wr32(device, 0x00250c, 0x6f3cfc34); 91 nvkm_wr32(device, 0x002044, 0x01003fff); 92 93 nvkm_wr32(device, 0x002100, 0xffffffff); 94 nvkm_wr32(device, 0x002140, 0xbfffffff); 95 96 for (i = 0; i < 128; i++) 97 nvkm_wr32(device, 0x002600 + (i * 4), 0x00000000); 98 nv50_fifo_runlist_update_locked(fifo); 99 100 nvkm_wr32(device, 0x003200, 0x00000001); 101 nvkm_wr32(device, 0x003250, 0x00000001); 102 nvkm_wr32(device, 0x002500, 0x00000001); 103 } 104 105 int 106 nv50_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr) 107 { 108 /* CHID 0 is unusable (some kind of PIO channel?), 127 is "channel invalid". */ 109 return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 1, nr - 2, &fifo->chid); 110 } 111 112 int 113 nv50_fifo_chid_nr(struct nvkm_fifo *fifo) 114 { 115 return 128; 116 } 117 118 int 119 nv50_fifo_oneinit(struct nvkm_fifo *base) 120 { 121 struct nv50_fifo *fifo = nv50_fifo(base); 122 struct nvkm_device *device = fifo->base.engine.subdev.device; 123 int ret; 124 125 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, 126 false, &fifo->runlist[0]); 127 if (ret) 128 return ret; 129 130 return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000, 131 false, &fifo->runlist[1]); 132 } 133 134 void * 135 nv50_fifo_dtor(struct nvkm_fifo *base) 136 { 137 struct nv50_fifo *fifo = nv50_fifo(base); 138 nvkm_memory_unref(&fifo->runlist[1]); 139 nvkm_memory_unref(&fifo->runlist[0]); 140 return fifo; 141 } 142 143 int 144 nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, 145 enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) 146 { 147 struct nv50_fifo *fifo; 148 int ret; 149 150 if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) 151 return -ENOMEM; 152 *pfifo = &fifo->base; 153 154 ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base); 155 if (ret) 156 return ret; 157 158 return 0; 159 } 160 161 static const struct nvkm_fifo_func 162 nv50_fifo = { 163 .dtor = nv50_fifo_dtor, 164 .oneinit = nv50_fifo_oneinit, 165 .chid_nr = nv50_fifo_chid_nr, 166 .chid_ctor = nv50_fifo_chid_ctor, 167 .runl_ctor = nv04_fifo_runl_ctor, 168 .init = nv50_fifo_init, 169 .intr = nv04_fifo_intr, 170 .engine_id = nv04_fifo_engine_id, 171 .pause = nv04_fifo_pause, 172 .start = nv04_fifo_start, 173 .runl = &nv50_runl, 174 .engn = &nv50_engn, 175 .engn_sw = &nv50_engn_sw, 176 .cgrp = {{ }, &nv04_cgrp }, 177 .chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan, .oclass = &nv50_fifo_gpfifo_oclass }, 178 }; 179 180 int 181 nv50_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 182 struct nvkm_fifo **pfifo) 183 { 184 return nv50_fifo_new_(&nv50_fifo, device, type, inst, pfifo); 185 } 186