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