1/* $NetBSD: nouveau_nvkm_engine_gr_nv20.c,v 1.3 2021/12/18 23:45:36 riastradh Exp $ */ 2 3// SPDX-License-Identifier: MIT 4#include <sys/cdefs.h> 5__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_engine_gr_nv20.c,v 1.3 2021/12/18 23:45:36 riastradh Exp $"); 6 7#include "nv20.h" 8#include "regs.h" 9 10#include <core/client.h> 11#include <core/gpuobj.h> 12#include <engine/fifo.h> 13#include <engine/fifo/chan.h> 14#include <subdev/fb.h> 15#include <subdev/timer.h> 16 17/******************************************************************************* 18 * PGRAPH context 19 ******************************************************************************/ 20 21int 22nv20_gr_chan_init(struct nvkm_object *object) 23{ 24 struct nv20_gr_chan *chan = nv20_gr_chan(object); 25 struct nv20_gr *gr = chan->gr; 26 u32 inst = nvkm_memory_addr(chan->inst); 27 28 nvkm_kmap(gr->ctxtab); 29 nvkm_wo32(gr->ctxtab, chan->chid * 4, inst >> 4); 30 nvkm_done(gr->ctxtab); 31 return 0; 32} 33 34int 35nv20_gr_chan_fini(struct nvkm_object *object, bool suspend) 36{ 37 struct nv20_gr_chan *chan = nv20_gr_chan(object); 38 struct nv20_gr *gr = chan->gr; 39 struct nvkm_device *device = gr->base.engine.subdev.device; 40 u32 inst = nvkm_memory_addr(chan->inst); 41 int chid = -1; 42 43 nvkm_mask(device, 0x400720, 0x00000001, 0x00000000); 44 if (nvkm_rd32(device, 0x400144) & 0x00010000) 45 chid = (nvkm_rd32(device, 0x400148) & 0x1f000000) >> 24; 46 if (chan->chid == chid) { 47 nvkm_wr32(device, 0x400784, inst >> 4); 48 nvkm_wr32(device, 0x400788, 0x00000002); 49 nvkm_msec(device, 2000, 50 if (!nvkm_rd32(device, 0x400700)) 51 break; 52 ); 53 nvkm_wr32(device, 0x400144, 0x10000000); 54 nvkm_mask(device, 0x400148, 0xff000000, 0x1f000000); 55 } 56 nvkm_mask(device, 0x400720, 0x00000001, 0x00000001); 57 58 nvkm_kmap(gr->ctxtab); 59 nvkm_wo32(gr->ctxtab, chan->chid * 4, 0x00000000); 60 nvkm_done(gr->ctxtab); 61 return 0; 62} 63 64void * 65nv20_gr_chan_dtor(struct nvkm_object *object) 66{ 67 struct nv20_gr_chan *chan = nv20_gr_chan(object); 68 nvkm_memory_unref(&chan->inst); 69 return chan; 70} 71 72static const struct nvkm_object_func 73nv20_gr_chan = { 74 .dtor = nv20_gr_chan_dtor, 75 .init = nv20_gr_chan_init, 76 .fini = nv20_gr_chan_fini, 77}; 78 79static int 80nv20_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, 81 const struct nvkm_oclass *oclass, struct nvkm_object **pobject) 82{ 83 struct nv20_gr *gr = nv20_gr(base); 84 struct nv20_gr_chan *chan; 85 int ret, i; 86 87 if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) 88 return -ENOMEM; 89 nvkm_object_ctor(&nv20_gr_chan, oclass, &chan->object); 90 chan->gr = gr; 91 chan->chid = fifoch->chid; 92 *pobject = &chan->object; 93 94 ret = nvkm_memory_new(gr->base.engine.subdev.device, 95 NVKM_MEM_TARGET_INST, 0x37f0, 16, true, 96 &chan->inst); 97 if (ret) 98 return ret; 99 100 nvkm_kmap(chan->inst); 101 nvkm_wo32(chan->inst, 0x0000, 0x00000001 | (chan->chid << 24)); 102 nvkm_wo32(chan->inst, 0x033c, 0xffff0000); 103 nvkm_wo32(chan->inst, 0x03a0, 0x0fff0000); 104 nvkm_wo32(chan->inst, 0x03a4, 0x0fff0000); 105 nvkm_wo32(chan->inst, 0x047c, 0x00000101); 106 nvkm_wo32(chan->inst, 0x0490, 0x00000111); 107 nvkm_wo32(chan->inst, 0x04a8, 0x44400000); 108 for (i = 0x04d4; i <= 0x04e0; i += 4) 109 nvkm_wo32(chan->inst, i, 0x00030303); 110 for (i = 0x04f4; i <= 0x0500; i += 4) 111 nvkm_wo32(chan->inst, i, 0x00080000); 112 for (i = 0x050c; i <= 0x0518; i += 4) 113 nvkm_wo32(chan->inst, i, 0x01012000); 114 for (i = 0x051c; i <= 0x0528; i += 4) 115 nvkm_wo32(chan->inst, i, 0x000105b8); 116 for (i = 0x052c; i <= 0x0538; i += 4) 117 nvkm_wo32(chan->inst, i, 0x00080008); 118 for (i = 0x055c; i <= 0x0598; i += 4) 119 nvkm_wo32(chan->inst, i, 0x07ff0000); 120 nvkm_wo32(chan->inst, 0x05a4, 0x4b7fffff); 121 nvkm_wo32(chan->inst, 0x05fc, 0x00000001); 122 nvkm_wo32(chan->inst, 0x0604, 0x00004000); 123 nvkm_wo32(chan->inst, 0x0610, 0x00000001); 124 nvkm_wo32(chan->inst, 0x0618, 0x00040000); 125 nvkm_wo32(chan->inst, 0x061c, 0x00010000); 126 for (i = 0x1c1c; i <= 0x248c; i += 16) { 127 nvkm_wo32(chan->inst, (i + 0), 0x10700ff9); 128 nvkm_wo32(chan->inst, (i + 4), 0x0436086c); 129 nvkm_wo32(chan->inst, (i + 8), 0x000c001b); 130 } 131 nvkm_wo32(chan->inst, 0x281c, 0x3f800000); 132 nvkm_wo32(chan->inst, 0x2830, 0x3f800000); 133 nvkm_wo32(chan->inst, 0x285c, 0x40000000); 134 nvkm_wo32(chan->inst, 0x2860, 0x3f800000); 135 nvkm_wo32(chan->inst, 0x2864, 0x3f000000); 136 nvkm_wo32(chan->inst, 0x286c, 0x40000000); 137 nvkm_wo32(chan->inst, 0x2870, 0x3f800000); 138 nvkm_wo32(chan->inst, 0x2878, 0xbf800000); 139 nvkm_wo32(chan->inst, 0x2880, 0xbf800000); 140 nvkm_wo32(chan->inst, 0x34a4, 0x000fe000); 141 nvkm_wo32(chan->inst, 0x3530, 0x000003f8); 142 nvkm_wo32(chan->inst, 0x3540, 0x002fe000); 143 for (i = 0x355c; i <= 0x3578; i += 4) 144 nvkm_wo32(chan->inst, i, 0x001c527c); 145 nvkm_done(chan->inst); 146 return 0; 147} 148 149/******************************************************************************* 150 * PGRAPH engine/subdev functions 151 ******************************************************************************/ 152 153void 154nv20_gr_tile(struct nvkm_gr *base, int i, struct nvkm_fb_tile *tile) 155{ 156 struct nv20_gr *gr = nv20_gr(base); 157 struct nvkm_device *device = gr->base.engine.subdev.device; 158 struct nvkm_fifo *fifo = device->fifo; 159 unsigned long flags; 160 161 nvkm_fifo_pause(fifo, &flags); 162 nv04_gr_idle(&gr->base); 163 164 nvkm_wr32(device, NV20_PGRAPH_TLIMIT(i), tile->limit); 165 nvkm_wr32(device, NV20_PGRAPH_TSIZE(i), tile->pitch); 166 nvkm_wr32(device, NV20_PGRAPH_TILE(i), tile->addr); 167 168 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); 169 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->limit); 170 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); 171 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->pitch); 172 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); 173 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->addr); 174 175 if (device->chipset != 0x34) { 176 nvkm_wr32(device, NV20_PGRAPH_ZCOMP(i), tile->zcomp); 177 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); 178 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, tile->zcomp); 179 } 180 181 nvkm_fifo_start(fifo, &flags); 182} 183 184void 185nv20_gr_intr(struct nvkm_gr *base) 186{ 187 struct nv20_gr *gr = nv20_gr(base); 188 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 189 struct nvkm_device *device = subdev->device; 190 struct nvkm_fifo_chan *chan; 191 u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); 192 u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); 193 u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); 194 u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); 195 u32 chid = (addr & 0x01f00000) >> 20; 196 u32 subc = (addr & 0x00070000) >> 16; 197 u32 mthd = (addr & 0x00001ffc); 198 u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); 199 u32 class = nvkm_rd32(device, 0x400160 + subc * 4) & 0xfff; 200 u32 show = stat; 201 char msg[128], src[128], sta[128]; 202 unsigned long flags; 203 204 chan = nvkm_fifo_chan_chid(device->fifo, chid, &flags); 205 206 nvkm_wr32(device, NV03_PGRAPH_INTR, stat); 207 nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); 208 209 if (show) { 210 nvkm_snprintbf(msg, sizeof(msg), nv10_gr_intr_name, show); 211 nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); 212 nvkm_snprintbf(sta, sizeof(sta), nv10_gr_nstatus, nstatus); 213 nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " 214 "nstatus %08x [%s] ch %d [%s] subc %d " 215 "class %04x mthd %04x data %08x\n", 216 show, msg, nsource, src, nstatus, sta, chid, 217 chan ? chan->object.client->name : "unknown", 218 subc, class, mthd, data); 219 } 220 221 nvkm_fifo_chan_put(device->fifo, flags, &chan); 222} 223 224int 225nv20_gr_oneinit(struct nvkm_gr *base) 226{ 227 struct nv20_gr *gr = nv20_gr(base); 228 return nvkm_memory_new(gr->base.engine.subdev.device, 229 NVKM_MEM_TARGET_INST, 32 * 4, 16, 230 true, &gr->ctxtab); 231} 232 233int 234nv20_gr_init(struct nvkm_gr *base) 235{ 236 struct nv20_gr *gr = nv20_gr(base); 237 struct nvkm_device *device = gr->base.engine.subdev.device; 238 u32 tmp, vramsz; 239 int i; 240 241 nvkm_wr32(device, NV20_PGRAPH_CHANNEL_CTX_TABLE, 242 nvkm_memory_addr(gr->ctxtab) >> 4); 243 244 if (device->chipset == 0x20) { 245 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x003d0000); 246 for (i = 0; i < 15; i++) 247 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, 0x00000000); 248 nvkm_msec(device, 2000, 249 if (!nvkm_rd32(device, 0x400700)) 250 break; 251 ); 252 } else { 253 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x02c80000); 254 for (i = 0; i < 32; i++) 255 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, 0x00000000); 256 nvkm_msec(device, 2000, 257 if (!nvkm_rd32(device, 0x400700)) 258 break; 259 ); 260 } 261 262 nvkm_wr32(device, NV03_PGRAPH_INTR , 0xFFFFFFFF); 263 nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 264 265 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); 266 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000); 267 nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x00118700); 268 nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ 269 nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00000000); 270 nvkm_wr32(device, 0x40009C , 0x00000040); 271 272 if (device->chipset >= 0x25) { 273 nvkm_wr32(device, 0x400890, 0x00a8cfff); 274 nvkm_wr32(device, 0x400610, 0x304B1FB6); 275 nvkm_wr32(device, 0x400B80, 0x1cbd3883); 276 nvkm_wr32(device, 0x400B84, 0x44000000); 277 nvkm_wr32(device, 0x400098, 0x40000080); 278 nvkm_wr32(device, 0x400B88, 0x000000ff); 279 280 } else { 281 nvkm_wr32(device, 0x400880, 0x0008c7df); 282 nvkm_wr32(device, 0x400094, 0x00000005); 283 nvkm_wr32(device, 0x400B80, 0x45eae20e); 284 nvkm_wr32(device, 0x400B84, 0x24000000); 285 nvkm_wr32(device, 0x400098, 0x00000040); 286 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00E00038); 287 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000030); 288 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00E10038); 289 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , 0x00000030); 290 } 291 292 nvkm_wr32(device, 0x4009a0, nvkm_rd32(device, 0x100324)); 293 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); 294 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA, nvkm_rd32(device, 0x100324)); 295 296 nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000100); 297 nvkm_wr32(device, NV10_PGRAPH_STATE , 0xFFFFFFFF); 298 299 tmp = nvkm_rd32(device, NV10_PGRAPH_SURFACE) & 0x0007ff00; 300 nvkm_wr32(device, NV10_PGRAPH_SURFACE, tmp); 301 tmp = nvkm_rd32(device, NV10_PGRAPH_SURFACE) | 0x00020100; 302 nvkm_wr32(device, NV10_PGRAPH_SURFACE, tmp); 303 304 /* begin RAM config */ 305 vramsz = device->func->resource_size(device, 1) - 1; 306 nvkm_wr32(device, 0x4009A4, nvkm_rd32(device, 0x100200)); 307 nvkm_wr32(device, 0x4009A8, nvkm_rd32(device, 0x100204)); 308 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); 309 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , nvkm_rd32(device, 0x100200)); 310 nvkm_wr32(device, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); 311 nvkm_wr32(device, NV10_PGRAPH_RDI_DATA , nvkm_rd32(device, 0x100204)); 312 nvkm_wr32(device, 0x400820, 0); 313 nvkm_wr32(device, 0x400824, 0); 314 nvkm_wr32(device, 0x400864, vramsz - 1); 315 nvkm_wr32(device, 0x400868, vramsz - 1); 316 317 /* interesting.. the below overwrites some of the tile setup above.. */ 318 nvkm_wr32(device, 0x400B20, 0x00000000); 319 nvkm_wr32(device, 0x400B04, 0xFFFFFFFF); 320 321 nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); 322 nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); 323 nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); 324 nvkm_wr32(device, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); 325 return 0; 326} 327 328void * 329nv20_gr_dtor(struct nvkm_gr *base) 330{ 331 struct nv20_gr *gr = nv20_gr(base); 332 nvkm_memory_unref(&gr->ctxtab); 333 return gr; 334} 335 336int 337nv20_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device, 338 int index, struct nvkm_gr **pgr) 339{ 340 struct nv20_gr *gr; 341 342 if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) 343 return -ENOMEM; 344 *pgr = &gr->base; 345 346 return nvkm_gr_ctor(func, device, index, true, &gr->base); 347} 348 349static const struct nvkm_gr_func 350nv20_gr = { 351 .dtor = nv20_gr_dtor, 352 .oneinit = nv20_gr_oneinit, 353 .init = nv20_gr_init, 354 .intr = nv20_gr_intr, 355 .tile = nv20_gr_tile, 356 .chan_new = nv20_gr_chan_new, 357 .sclass = { 358 { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */ 359 { -1, -1, 0x0019, &nv04_gr_object }, /* clip */ 360 { -1, -1, 0x0030, &nv04_gr_object }, /* null */ 361 { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */ 362 { -1, -1, 0x0043, &nv04_gr_object }, /* rop */ 363 { -1, -1, 0x0044, &nv04_gr_object }, /* patt */ 364 { -1, -1, 0x004a, &nv04_gr_object }, /* gdi */ 365 { -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */ 366 { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */ 367 { -1, -1, 0x0089, &nv04_gr_object }, /* sifm */ 368 { -1, -1, 0x008a, &nv04_gr_object }, /* ifc */ 369 { -1, -1, 0x0096, &nv04_gr_object }, /* celcius */ 370 { -1, -1, 0x0097, &nv04_gr_object }, /* kelvin */ 371 { -1, -1, 0x009e, &nv04_gr_object }, /* swzsurf */ 372 { -1, -1, 0x009f, &nv04_gr_object }, /* imageblit */ 373 {} 374 } 375}; 376 377int 378nv20_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) 379{ 380 return nv20_gr_new_(&nv20_gr, device, index, pgr); 381} 382