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 "nv40.h" 25 #include "regs.h" 26 27 #include <core/client.h> 28 #include <core/handle.h> 29 #include <subdev/fb.h> 30 #include <subdev/timer.h> 31 #include <engine/fifo.h> 32 33 struct nv40_gr { 34 struct nvkm_gr base; 35 u32 size; 36 }; 37 38 struct nv40_gr_chan { 39 struct nvkm_gr_chan base; 40 }; 41 42 static u64 43 nv40_gr_units(struct nvkm_gr *gr) 44 { 45 return nv_rd32(gr, 0x1540); 46 } 47 48 /******************************************************************************* 49 * Graphics object classes 50 ******************************************************************************/ 51 52 static int 53 nv40_gr_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 54 struct nvkm_oclass *oclass, void *data, u32 size, 55 struct nvkm_object **pobject) 56 { 57 struct nvkm_gpuobj *obj; 58 int ret; 59 60 ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, 61 20, 16, 0, &obj); 62 *pobject = nv_object(obj); 63 if (ret) 64 return ret; 65 66 nv_wo32(obj, 0x00, nv_mclass(obj)); 67 nv_wo32(obj, 0x04, 0x00000000); 68 nv_wo32(obj, 0x08, 0x00000000); 69 #ifdef __BIG_ENDIAN 70 nv_mo32(obj, 0x08, 0x01000000, 0x01000000); 71 #endif 72 nv_wo32(obj, 0x0c, 0x00000000); 73 nv_wo32(obj, 0x10, 0x00000000); 74 return 0; 75 } 76 77 static struct nvkm_ofuncs 78 nv40_gr_ofuncs = { 79 .ctor = nv40_gr_object_ctor, 80 .dtor = _nvkm_gpuobj_dtor, 81 .init = _nvkm_gpuobj_init, 82 .fini = _nvkm_gpuobj_fini, 83 .rd32 = _nvkm_gpuobj_rd32, 84 .wr32 = _nvkm_gpuobj_wr32, 85 }; 86 87 static struct nvkm_oclass 88 nv40_gr_sclass[] = { 89 { 0x0012, &nv40_gr_ofuncs, NULL }, /* beta1 */ 90 { 0x0019, &nv40_gr_ofuncs, NULL }, /* clip */ 91 { 0x0030, &nv40_gr_ofuncs, NULL }, /* null */ 92 { 0x0039, &nv40_gr_ofuncs, NULL }, /* m2mf */ 93 { 0x0043, &nv40_gr_ofuncs, NULL }, /* rop */ 94 { 0x0044, &nv40_gr_ofuncs, NULL }, /* patt */ 95 { 0x004a, &nv40_gr_ofuncs, NULL }, /* gdi */ 96 { 0x0062, &nv40_gr_ofuncs, NULL }, /* surf2d */ 97 { 0x0072, &nv40_gr_ofuncs, NULL }, /* beta4 */ 98 { 0x0089, &nv40_gr_ofuncs, NULL }, /* sifm */ 99 { 0x008a, &nv40_gr_ofuncs, NULL }, /* ifc */ 100 { 0x009f, &nv40_gr_ofuncs, NULL }, /* imageblit */ 101 { 0x3062, &nv40_gr_ofuncs, NULL }, /* surf2d (nv40) */ 102 { 0x3089, &nv40_gr_ofuncs, NULL }, /* sifm (nv40) */ 103 { 0x309e, &nv40_gr_ofuncs, NULL }, /* swzsurf (nv40) */ 104 { 0x4097, &nv40_gr_ofuncs, NULL }, /* curie */ 105 {}, 106 }; 107 108 static struct nvkm_oclass 109 nv44_gr_sclass[] = { 110 { 0x0012, &nv40_gr_ofuncs, NULL }, /* beta1 */ 111 { 0x0019, &nv40_gr_ofuncs, NULL }, /* clip */ 112 { 0x0030, &nv40_gr_ofuncs, NULL }, /* null */ 113 { 0x0039, &nv40_gr_ofuncs, NULL }, /* m2mf */ 114 { 0x0043, &nv40_gr_ofuncs, NULL }, /* rop */ 115 { 0x0044, &nv40_gr_ofuncs, NULL }, /* patt */ 116 { 0x004a, &nv40_gr_ofuncs, NULL }, /* gdi */ 117 { 0x0062, &nv40_gr_ofuncs, NULL }, /* surf2d */ 118 { 0x0072, &nv40_gr_ofuncs, NULL }, /* beta4 */ 119 { 0x0089, &nv40_gr_ofuncs, NULL }, /* sifm */ 120 { 0x008a, &nv40_gr_ofuncs, NULL }, /* ifc */ 121 { 0x009f, &nv40_gr_ofuncs, NULL }, /* imageblit */ 122 { 0x3062, &nv40_gr_ofuncs, NULL }, /* surf2d (nv40) */ 123 { 0x3089, &nv40_gr_ofuncs, NULL }, /* sifm (nv40) */ 124 { 0x309e, &nv40_gr_ofuncs, NULL }, /* swzsurf (nv40) */ 125 { 0x4497, &nv40_gr_ofuncs, NULL }, /* curie */ 126 {}, 127 }; 128 129 /******************************************************************************* 130 * PGRAPH context 131 ******************************************************************************/ 132 133 static int 134 nv40_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 135 struct nvkm_oclass *oclass, void *data, u32 size, 136 struct nvkm_object **pobject) 137 { 138 struct nv40_gr *gr = (void *)engine; 139 struct nv40_gr_chan *chan; 140 int ret; 141 142 ret = nvkm_gr_context_create(parent, engine, oclass, NULL, gr->size, 143 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); 144 *pobject = nv_object(chan); 145 if (ret) 146 return ret; 147 148 nv40_grctx_fill(nv_device(gr), nv_gpuobj(chan)); 149 nv_wo32(chan, 0x00000, nv_gpuobj(chan)->addr >> 4); 150 return 0; 151 } 152 153 static int 154 nv40_gr_context_fini(struct nvkm_object *object, bool suspend) 155 { 156 struct nv40_gr *gr = (void *)object->engine; 157 struct nv40_gr_chan *chan = (void *)object; 158 u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; 159 int ret = 0; 160 161 nv_mask(gr, 0x400720, 0x00000001, 0x00000000); 162 163 if (nv_rd32(gr, 0x40032c) == inst) { 164 if (suspend) { 165 nv_wr32(gr, 0x400720, 0x00000000); 166 nv_wr32(gr, 0x400784, inst); 167 nv_mask(gr, 0x400310, 0x00000020, 0x00000020); 168 nv_mask(gr, 0x400304, 0x00000001, 0x00000001); 169 if (!nv_wait(gr, 0x400300, 0x00000001, 0x00000000)) { 170 u32 insn = nv_rd32(gr, 0x400308); 171 nv_warn(gr, "ctxprog timeout 0x%08x\n", insn); 172 ret = -EBUSY; 173 } 174 } 175 176 nv_mask(gr, 0x40032c, 0x01000000, 0x00000000); 177 } 178 179 if (nv_rd32(gr, 0x400330) == inst) 180 nv_mask(gr, 0x400330, 0x01000000, 0x00000000); 181 182 nv_mask(gr, 0x400720, 0x00000001, 0x00000001); 183 return ret; 184 } 185 186 static struct nvkm_oclass 187 nv40_gr_cclass = { 188 .handle = NV_ENGCTX(GR, 0x40), 189 .ofuncs = &(struct nvkm_ofuncs) { 190 .ctor = nv40_gr_context_ctor, 191 .dtor = _nvkm_gr_context_dtor, 192 .init = _nvkm_gr_context_init, 193 .fini = nv40_gr_context_fini, 194 .rd32 = _nvkm_gr_context_rd32, 195 .wr32 = _nvkm_gr_context_wr32, 196 }, 197 }; 198 199 /******************************************************************************* 200 * PGRAPH engine/subdev functions 201 ******************************************************************************/ 202 203 static void 204 nv40_gr_tile_prog(struct nvkm_engine *engine, int i) 205 { 206 struct nvkm_fb_tile *tile = &nvkm_fb(engine)->tile.region[i]; 207 struct nvkm_fifo *fifo = nvkm_fifo(engine); 208 struct nv40_gr *gr = (void *)engine; 209 unsigned long flags; 210 211 fifo->pause(fifo, &flags); 212 nv04_gr_idle(gr); 213 214 switch (nv_device(gr)->chipset) { 215 case 0x40: 216 case 0x41: 217 case 0x42: 218 case 0x43: 219 case 0x45: 220 case 0x4e: 221 nv_wr32(gr, NV20_PGRAPH_TSIZE(i), tile->pitch); 222 nv_wr32(gr, NV20_PGRAPH_TLIMIT(i), tile->limit); 223 nv_wr32(gr, NV20_PGRAPH_TILE(i), tile->addr); 224 nv_wr32(gr, NV40_PGRAPH_TSIZE1(i), tile->pitch); 225 nv_wr32(gr, NV40_PGRAPH_TLIMIT1(i), tile->limit); 226 nv_wr32(gr, NV40_PGRAPH_TILE1(i), tile->addr); 227 switch (nv_device(gr)->chipset) { 228 case 0x40: 229 case 0x45: 230 nv_wr32(gr, NV20_PGRAPH_ZCOMP(i), tile->zcomp); 231 nv_wr32(gr, NV40_PGRAPH_ZCOMP1(i), tile->zcomp); 232 break; 233 case 0x41: 234 case 0x42: 235 case 0x43: 236 nv_wr32(gr, NV41_PGRAPH_ZCOMP0(i), tile->zcomp); 237 nv_wr32(gr, NV41_PGRAPH_ZCOMP1(i), tile->zcomp); 238 break; 239 default: 240 break; 241 } 242 break; 243 case 0x44: 244 case 0x4a: 245 nv_wr32(gr, NV20_PGRAPH_TSIZE(i), tile->pitch); 246 nv_wr32(gr, NV20_PGRAPH_TLIMIT(i), tile->limit); 247 nv_wr32(gr, NV20_PGRAPH_TILE(i), tile->addr); 248 break; 249 case 0x46: 250 case 0x4c: 251 case 0x47: 252 case 0x49: 253 case 0x4b: 254 case 0x63: 255 case 0x67: 256 case 0x68: 257 nv_wr32(gr, NV47_PGRAPH_TSIZE(i), tile->pitch); 258 nv_wr32(gr, NV47_PGRAPH_TLIMIT(i), tile->limit); 259 nv_wr32(gr, NV47_PGRAPH_TILE(i), tile->addr); 260 nv_wr32(gr, NV40_PGRAPH_TSIZE1(i), tile->pitch); 261 nv_wr32(gr, NV40_PGRAPH_TLIMIT1(i), tile->limit); 262 nv_wr32(gr, NV40_PGRAPH_TILE1(i), tile->addr); 263 switch (nv_device(gr)->chipset) { 264 case 0x47: 265 case 0x49: 266 case 0x4b: 267 nv_wr32(gr, NV47_PGRAPH_ZCOMP0(i), tile->zcomp); 268 nv_wr32(gr, NV47_PGRAPH_ZCOMP1(i), tile->zcomp); 269 break; 270 default: 271 break; 272 } 273 break; 274 default: 275 break; 276 } 277 278 fifo->start(fifo, &flags); 279 } 280 281 static void 282 nv40_gr_intr(struct nvkm_subdev *subdev) 283 { 284 struct nvkm_fifo *fifo = nvkm_fifo(subdev); 285 struct nvkm_engine *engine = nv_engine(subdev); 286 struct nvkm_object *engctx; 287 struct nvkm_handle *handle = NULL; 288 struct nv40_gr *gr = (void *)subdev; 289 u32 stat = nv_rd32(gr, NV03_PGRAPH_INTR); 290 u32 nsource = nv_rd32(gr, NV03_PGRAPH_NSOURCE); 291 u32 nstatus = nv_rd32(gr, NV03_PGRAPH_NSTATUS); 292 u32 inst = nv_rd32(gr, 0x40032c) & 0x000fffff; 293 u32 addr = nv_rd32(gr, NV04_PGRAPH_TRAPPED_ADDR); 294 u32 subc = (addr & 0x00070000) >> 16; 295 u32 mthd = (addr & 0x00001ffc); 296 u32 data = nv_rd32(gr, NV04_PGRAPH_TRAPPED_DATA); 297 u32 class = nv_rd32(gr, 0x400160 + subc * 4) & 0xffff; 298 u32 show = stat; 299 int chid; 300 301 engctx = nvkm_engctx_get(engine, inst); 302 chid = fifo->chid(fifo, engctx); 303 304 if (stat & NV_PGRAPH_INTR_ERROR) { 305 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { 306 handle = nvkm_handle_get_class(engctx, class); 307 if (handle && !nv_call(handle->object, mthd, data)) 308 show &= ~NV_PGRAPH_INTR_ERROR; 309 nvkm_handle_put(handle); 310 } 311 312 if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { 313 nv_mask(gr, 0x402000, 0, 0); 314 } 315 } 316 317 nv_wr32(gr, NV03_PGRAPH_INTR, stat); 318 nv_wr32(gr, NV04_PGRAPH_FIFO, 0x00000001); 319 320 if (show) { 321 nv_error(gr, "%s", ""); 322 nvkm_bitfield_print(nv10_gr_intr_name, show); 323 pr_cont(" nsource:"); 324 nvkm_bitfield_print(nv04_gr_nsource, nsource); 325 pr_cont(" nstatus:"); 326 nvkm_bitfield_print(nv10_gr_nstatus, nstatus); 327 pr_cont("\n"); 328 nv_error(gr, 329 "ch %d [0x%08x %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 330 chid, inst << 4, nvkm_client_name(engctx), subc, 331 class, mthd, data); 332 } 333 334 nvkm_engctx_put(engctx); 335 } 336 337 static int 338 nv40_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 339 struct nvkm_oclass *oclass, void *data, u32 size, 340 struct nvkm_object **pobject) 341 { 342 struct nv40_gr *gr; 343 int ret; 344 345 ret = nvkm_gr_create(parent, engine, oclass, true, &gr); 346 *pobject = nv_object(gr); 347 if (ret) 348 return ret; 349 350 nv_subdev(gr)->unit = 0x00001000; 351 nv_subdev(gr)->intr = nv40_gr_intr; 352 nv_engine(gr)->cclass = &nv40_gr_cclass; 353 if (nv44_gr_class(gr)) 354 nv_engine(gr)->sclass = nv44_gr_sclass; 355 else 356 nv_engine(gr)->sclass = nv40_gr_sclass; 357 nv_engine(gr)->tile_prog = nv40_gr_tile_prog; 358 359 gr->base.units = nv40_gr_units; 360 return 0; 361 } 362 363 static int 364 nv40_gr_init(struct nvkm_object *object) 365 { 366 struct nvkm_engine *engine = nv_engine(object); 367 struct nvkm_fb *fb = nvkm_fb(object); 368 struct nv40_gr *gr = (void *)engine; 369 int ret, i, j; 370 u32 vramsz; 371 372 ret = nvkm_gr_init(&gr->base); 373 if (ret) 374 return ret; 375 376 /* generate and upload context program */ 377 ret = nv40_grctx_init(nv_device(gr), &gr->size); 378 if (ret) 379 return ret; 380 381 /* No context present currently */ 382 nv_wr32(gr, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); 383 384 nv_wr32(gr, NV03_PGRAPH_INTR , 0xFFFFFFFF); 385 nv_wr32(gr, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); 386 387 nv_wr32(gr, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); 388 nv_wr32(gr, NV04_PGRAPH_DEBUG_0, 0x00000000); 389 nv_wr32(gr, NV04_PGRAPH_DEBUG_1, 0x401287c0); 390 nv_wr32(gr, NV04_PGRAPH_DEBUG_3, 0xe0de8055); 391 nv_wr32(gr, NV10_PGRAPH_DEBUG_4, 0x00008000); 392 nv_wr32(gr, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); 393 394 nv_wr32(gr, NV10_PGRAPH_CTX_CONTROL, 0x10010100); 395 nv_wr32(gr, NV10_PGRAPH_STATE , 0xFFFFFFFF); 396 397 j = nv_rd32(gr, 0x1540) & 0xff; 398 if (j) { 399 for (i = 0; !(j & 1); j >>= 1, i++) 400 ; 401 nv_wr32(gr, 0x405000, i); 402 } 403 404 if (nv_device(gr)->chipset == 0x40) { 405 nv_wr32(gr, 0x4009b0, 0x83280fff); 406 nv_wr32(gr, 0x4009b4, 0x000000a0); 407 } else { 408 nv_wr32(gr, 0x400820, 0x83280eff); 409 nv_wr32(gr, 0x400824, 0x000000a0); 410 } 411 412 switch (nv_device(gr)->chipset) { 413 case 0x40: 414 case 0x45: 415 nv_wr32(gr, 0x4009b8, 0x0078e366); 416 nv_wr32(gr, 0x4009bc, 0x0000014c); 417 break; 418 case 0x41: 419 case 0x42: /* pciid also 0x00Cx */ 420 /* case 0x0120: XXX (pciid) */ 421 nv_wr32(gr, 0x400828, 0x007596ff); 422 nv_wr32(gr, 0x40082c, 0x00000108); 423 break; 424 case 0x43: 425 nv_wr32(gr, 0x400828, 0x0072cb77); 426 nv_wr32(gr, 0x40082c, 0x00000108); 427 break; 428 case 0x44: 429 case 0x46: /* G72 */ 430 case 0x4a: 431 case 0x4c: /* G7x-based C51 */ 432 case 0x4e: 433 nv_wr32(gr, 0x400860, 0); 434 nv_wr32(gr, 0x400864, 0); 435 break; 436 case 0x47: /* G70 */ 437 case 0x49: /* G71 */ 438 case 0x4b: /* G73 */ 439 nv_wr32(gr, 0x400828, 0x07830610); 440 nv_wr32(gr, 0x40082c, 0x0000016A); 441 break; 442 default: 443 break; 444 } 445 446 nv_wr32(gr, 0x400b38, 0x2ffff800); 447 nv_wr32(gr, 0x400b3c, 0x00006000); 448 449 /* Tiling related stuff. */ 450 switch (nv_device(gr)->chipset) { 451 case 0x44: 452 case 0x4a: 453 nv_wr32(gr, 0x400bc4, 0x1003d888); 454 nv_wr32(gr, 0x400bbc, 0xb7a7b500); 455 break; 456 case 0x46: 457 nv_wr32(gr, 0x400bc4, 0x0000e024); 458 nv_wr32(gr, 0x400bbc, 0xb7a7b520); 459 break; 460 case 0x4c: 461 case 0x4e: 462 case 0x67: 463 nv_wr32(gr, 0x400bc4, 0x1003d888); 464 nv_wr32(gr, 0x400bbc, 0xb7a7b540); 465 break; 466 default: 467 break; 468 } 469 470 /* Turn all the tiling regions off. */ 471 for (i = 0; i < fb->tile.regions; i++) 472 engine->tile_prog(engine, i); 473 474 /* begin RAM config */ 475 vramsz = nv_device_resource_len(nv_device(gr), 1) - 1; 476 switch (nv_device(gr)->chipset) { 477 case 0x40: 478 nv_wr32(gr, 0x4009A4, nv_rd32(gr, 0x100200)); 479 nv_wr32(gr, 0x4009A8, nv_rd32(gr, 0x100204)); 480 nv_wr32(gr, 0x4069A4, nv_rd32(gr, 0x100200)); 481 nv_wr32(gr, 0x4069A8, nv_rd32(gr, 0x100204)); 482 nv_wr32(gr, 0x400820, 0); 483 nv_wr32(gr, 0x400824, 0); 484 nv_wr32(gr, 0x400864, vramsz); 485 nv_wr32(gr, 0x400868, vramsz); 486 break; 487 default: 488 switch (nv_device(gr)->chipset) { 489 case 0x41: 490 case 0x42: 491 case 0x43: 492 case 0x45: 493 case 0x4e: 494 case 0x44: 495 case 0x4a: 496 nv_wr32(gr, 0x4009F0, nv_rd32(gr, 0x100200)); 497 nv_wr32(gr, 0x4009F4, nv_rd32(gr, 0x100204)); 498 break; 499 default: 500 nv_wr32(gr, 0x400DF0, nv_rd32(gr, 0x100200)); 501 nv_wr32(gr, 0x400DF4, nv_rd32(gr, 0x100204)); 502 break; 503 } 504 nv_wr32(gr, 0x4069F0, nv_rd32(gr, 0x100200)); 505 nv_wr32(gr, 0x4069F4, nv_rd32(gr, 0x100204)); 506 nv_wr32(gr, 0x400840, 0); 507 nv_wr32(gr, 0x400844, 0); 508 nv_wr32(gr, 0x4008A0, vramsz); 509 nv_wr32(gr, 0x4008A4, vramsz); 510 break; 511 } 512 513 return 0; 514 } 515 516 struct nvkm_oclass 517 nv40_gr_oclass = { 518 .handle = NV_ENGINE(GR, 0x40), 519 .ofuncs = &(struct nvkm_ofuncs) { 520 .ctor = nv40_gr_ctor, 521 .dtor = _nvkm_gr_dtor, 522 .init = nv40_gr_init, 523 .fini = _nvkm_gr_fini, 524 }, 525 }; 526