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