1 /* 2 * Copyright 2007 Stephane Marchesin 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragr) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 #include <engine/gr.h> 25 #include "regs.h" 26 27 #include <core/client.h> 28 #include <core/handle.h> 29 #include <engine/fifo.h> 30 #include <subdev/instmem.h> 31 #include <subdev/timer.h> 32 33 static u32 34 nv04_gr_ctx_regs[] = { 35 0x0040053c, 36 0x00400544, 37 0x00400540, 38 0x00400548, 39 NV04_PGRAPH_CTX_SWITCH1, 40 NV04_PGRAPH_CTX_SWITCH2, 41 NV04_PGRAPH_CTX_SWITCH3, 42 NV04_PGRAPH_CTX_SWITCH4, 43 NV04_PGRAPH_CTX_CACHE1, 44 NV04_PGRAPH_CTX_CACHE2, 45 NV04_PGRAPH_CTX_CACHE3, 46 NV04_PGRAPH_CTX_CACHE4, 47 0x00400184, 48 0x004001a4, 49 0x004001c4, 50 0x004001e4, 51 0x00400188, 52 0x004001a8, 53 0x004001c8, 54 0x004001e8, 55 0x0040018c, 56 0x004001ac, 57 0x004001cc, 58 0x004001ec, 59 0x00400190, 60 0x004001b0, 61 0x004001d0, 62 0x004001f0, 63 0x00400194, 64 0x004001b4, 65 0x004001d4, 66 0x004001f4, 67 0x00400198, 68 0x004001b8, 69 0x004001d8, 70 0x004001f8, 71 0x0040019c, 72 0x004001bc, 73 0x004001dc, 74 0x004001fc, 75 0x00400174, 76 NV04_PGRAPH_DMA_START_0, 77 NV04_PGRAPH_DMA_START_1, 78 NV04_PGRAPH_DMA_LENGTH, 79 NV04_PGRAPH_DMA_MISC, 80 NV04_PGRAPH_DMA_PITCH, 81 NV04_PGRAPH_BOFFSET0, 82 NV04_PGRAPH_BBASE0, 83 NV04_PGRAPH_BLIMIT0, 84 NV04_PGRAPH_BOFFSET1, 85 NV04_PGRAPH_BBASE1, 86 NV04_PGRAPH_BLIMIT1, 87 NV04_PGRAPH_BOFFSET2, 88 NV04_PGRAPH_BBASE2, 89 NV04_PGRAPH_BLIMIT2, 90 NV04_PGRAPH_BOFFSET3, 91 NV04_PGRAPH_BBASE3, 92 NV04_PGRAPH_BLIMIT3, 93 NV04_PGRAPH_BOFFSET4, 94 NV04_PGRAPH_BBASE4, 95 NV04_PGRAPH_BLIMIT4, 96 NV04_PGRAPH_BOFFSET5, 97 NV04_PGRAPH_BBASE5, 98 NV04_PGRAPH_BLIMIT5, 99 NV04_PGRAPH_BPITCH0, 100 NV04_PGRAPH_BPITCH1, 101 NV04_PGRAPH_BPITCH2, 102 NV04_PGRAPH_BPITCH3, 103 NV04_PGRAPH_BPITCH4, 104 NV04_PGRAPH_SURFACE, 105 NV04_PGRAPH_STATE, 106 NV04_PGRAPH_BSWIZZLE2, 107 NV04_PGRAPH_BSWIZZLE5, 108 NV04_PGRAPH_BPIXEL, 109 NV04_PGRAPH_NOTIFY, 110 NV04_PGRAPH_PATT_COLOR0, 111 NV04_PGRAPH_PATT_COLOR1, 112 NV04_PGRAPH_PATT_COLORRAM+0x00, 113 NV04_PGRAPH_PATT_COLORRAM+0x04, 114 NV04_PGRAPH_PATT_COLORRAM+0x08, 115 NV04_PGRAPH_PATT_COLORRAM+0x0c, 116 NV04_PGRAPH_PATT_COLORRAM+0x10, 117 NV04_PGRAPH_PATT_COLORRAM+0x14, 118 NV04_PGRAPH_PATT_COLORRAM+0x18, 119 NV04_PGRAPH_PATT_COLORRAM+0x1c, 120 NV04_PGRAPH_PATT_COLORRAM+0x20, 121 NV04_PGRAPH_PATT_COLORRAM+0x24, 122 NV04_PGRAPH_PATT_COLORRAM+0x28, 123 NV04_PGRAPH_PATT_COLORRAM+0x2c, 124 NV04_PGRAPH_PATT_COLORRAM+0x30, 125 NV04_PGRAPH_PATT_COLORRAM+0x34, 126 NV04_PGRAPH_PATT_COLORRAM+0x38, 127 NV04_PGRAPH_PATT_COLORRAM+0x3c, 128 NV04_PGRAPH_PATT_COLORRAM+0x40, 129 NV04_PGRAPH_PATT_COLORRAM+0x44, 130 NV04_PGRAPH_PATT_COLORRAM+0x48, 131 NV04_PGRAPH_PATT_COLORRAM+0x4c, 132 NV04_PGRAPH_PATT_COLORRAM+0x50, 133 NV04_PGRAPH_PATT_COLORRAM+0x54, 134 NV04_PGRAPH_PATT_COLORRAM+0x58, 135 NV04_PGRAPH_PATT_COLORRAM+0x5c, 136 NV04_PGRAPH_PATT_COLORRAM+0x60, 137 NV04_PGRAPH_PATT_COLORRAM+0x64, 138 NV04_PGRAPH_PATT_COLORRAM+0x68, 139 NV04_PGRAPH_PATT_COLORRAM+0x6c, 140 NV04_PGRAPH_PATT_COLORRAM+0x70, 141 NV04_PGRAPH_PATT_COLORRAM+0x74, 142 NV04_PGRAPH_PATT_COLORRAM+0x78, 143 NV04_PGRAPH_PATT_COLORRAM+0x7c, 144 NV04_PGRAPH_PATT_COLORRAM+0x80, 145 NV04_PGRAPH_PATT_COLORRAM+0x84, 146 NV04_PGRAPH_PATT_COLORRAM+0x88, 147 NV04_PGRAPH_PATT_COLORRAM+0x8c, 148 NV04_PGRAPH_PATT_COLORRAM+0x90, 149 NV04_PGRAPH_PATT_COLORRAM+0x94, 150 NV04_PGRAPH_PATT_COLORRAM+0x98, 151 NV04_PGRAPH_PATT_COLORRAM+0x9c, 152 NV04_PGRAPH_PATT_COLORRAM+0xa0, 153 NV04_PGRAPH_PATT_COLORRAM+0xa4, 154 NV04_PGRAPH_PATT_COLORRAM+0xa8, 155 NV04_PGRAPH_PATT_COLORRAM+0xac, 156 NV04_PGRAPH_PATT_COLORRAM+0xb0, 157 NV04_PGRAPH_PATT_COLORRAM+0xb4, 158 NV04_PGRAPH_PATT_COLORRAM+0xb8, 159 NV04_PGRAPH_PATT_COLORRAM+0xbc, 160 NV04_PGRAPH_PATT_COLORRAM+0xc0, 161 NV04_PGRAPH_PATT_COLORRAM+0xc4, 162 NV04_PGRAPH_PATT_COLORRAM+0xc8, 163 NV04_PGRAPH_PATT_COLORRAM+0xcc, 164 NV04_PGRAPH_PATT_COLORRAM+0xd0, 165 NV04_PGRAPH_PATT_COLORRAM+0xd4, 166 NV04_PGRAPH_PATT_COLORRAM+0xd8, 167 NV04_PGRAPH_PATT_COLORRAM+0xdc, 168 NV04_PGRAPH_PATT_COLORRAM+0xe0, 169 NV04_PGRAPH_PATT_COLORRAM+0xe4, 170 NV04_PGRAPH_PATT_COLORRAM+0xe8, 171 NV04_PGRAPH_PATT_COLORRAM+0xec, 172 NV04_PGRAPH_PATT_COLORRAM+0xf0, 173 NV04_PGRAPH_PATT_COLORRAM+0xf4, 174 NV04_PGRAPH_PATT_COLORRAM+0xf8, 175 NV04_PGRAPH_PATT_COLORRAM+0xfc, 176 NV04_PGRAPH_PATTERN, 177 0x0040080c, 178 NV04_PGRAPH_PATTERN_SHAPE, 179 0x00400600, 180 NV04_PGRAPH_ROP3, 181 NV04_PGRAPH_CHROMA, 182 NV04_PGRAPH_BETA_AND, 183 NV04_PGRAPH_BETA_PREMULT, 184 NV04_PGRAPH_CONTROL0, 185 NV04_PGRAPH_CONTROL1, 186 NV04_PGRAPH_CONTROL2, 187 NV04_PGRAPH_BLEND, 188 NV04_PGRAPH_STORED_FMT, 189 NV04_PGRAPH_SOURCE_COLOR, 190 0x00400560, 191 0x00400568, 192 0x00400564, 193 0x0040056c, 194 0x00400400, 195 0x00400480, 196 0x00400404, 197 0x00400484, 198 0x00400408, 199 0x00400488, 200 0x0040040c, 201 0x0040048c, 202 0x00400410, 203 0x00400490, 204 0x00400414, 205 0x00400494, 206 0x00400418, 207 0x00400498, 208 0x0040041c, 209 0x0040049c, 210 0x00400420, 211 0x004004a0, 212 0x00400424, 213 0x004004a4, 214 0x00400428, 215 0x004004a8, 216 0x0040042c, 217 0x004004ac, 218 0x00400430, 219 0x004004b0, 220 0x00400434, 221 0x004004b4, 222 0x00400438, 223 0x004004b8, 224 0x0040043c, 225 0x004004bc, 226 0x00400440, 227 0x004004c0, 228 0x00400444, 229 0x004004c4, 230 0x00400448, 231 0x004004c8, 232 0x0040044c, 233 0x004004cc, 234 0x00400450, 235 0x004004d0, 236 0x00400454, 237 0x004004d4, 238 0x00400458, 239 0x004004d8, 240 0x0040045c, 241 0x004004dc, 242 0x00400460, 243 0x004004e0, 244 0x00400464, 245 0x004004e4, 246 0x00400468, 247 0x004004e8, 248 0x0040046c, 249 0x004004ec, 250 0x00400470, 251 0x004004f0, 252 0x00400474, 253 0x004004f4, 254 0x00400478, 255 0x004004f8, 256 0x0040047c, 257 0x004004fc, 258 0x00400534, 259 0x00400538, 260 0x00400514, 261 0x00400518, 262 0x0040051c, 263 0x00400520, 264 0x00400524, 265 0x00400528, 266 0x0040052c, 267 0x00400530, 268 0x00400d00, 269 0x00400d40, 270 0x00400d80, 271 0x00400d04, 272 0x00400d44, 273 0x00400d84, 274 0x00400d08, 275 0x00400d48, 276 0x00400d88, 277 0x00400d0c, 278 0x00400d4c, 279 0x00400d8c, 280 0x00400d10, 281 0x00400d50, 282 0x00400d90, 283 0x00400d14, 284 0x00400d54, 285 0x00400d94, 286 0x00400d18, 287 0x00400d58, 288 0x00400d98, 289 0x00400d1c, 290 0x00400d5c, 291 0x00400d9c, 292 0x00400d20, 293 0x00400d60, 294 0x00400da0, 295 0x00400d24, 296 0x00400d64, 297 0x00400da4, 298 0x00400d28, 299 0x00400d68, 300 0x00400da8, 301 0x00400d2c, 302 0x00400d6c, 303 0x00400dac, 304 0x00400d30, 305 0x00400d70, 306 0x00400db0, 307 0x00400d34, 308 0x00400d74, 309 0x00400db4, 310 0x00400d38, 311 0x00400d78, 312 0x00400db8, 313 0x00400d3c, 314 0x00400d7c, 315 0x00400dbc, 316 0x00400590, 317 0x00400594, 318 0x00400598, 319 0x0040059c, 320 0x004005a8, 321 0x004005ac, 322 0x004005b0, 323 0x004005b4, 324 0x004005c0, 325 0x004005c4, 326 0x004005c8, 327 0x004005cc, 328 0x004005d0, 329 0x004005d4, 330 0x004005d8, 331 0x004005dc, 332 0x004005e0, 333 NV04_PGRAPH_PASSTHRU_0, 334 NV04_PGRAPH_PASSTHRU_1, 335 NV04_PGRAPH_PASSTHRU_2, 336 NV04_PGRAPH_DVD_COLORFMT, 337 NV04_PGRAPH_SCALED_FORMAT, 338 NV04_PGRAPH_MISC24_0, 339 NV04_PGRAPH_MISC24_1, 340 NV04_PGRAPH_MISC24_2, 341 0x00400500, 342 0x00400504, 343 NV04_PGRAPH_VALID1, 344 NV04_PGRAPH_VALID2, 345 NV04_PGRAPH_DEBUG_3 346 }; 347 348 struct nv04_gr { 349 struct nvkm_gr base; 350 struct nv04_gr_chan *chan[16]; 351 spinlock_t lock; 352 }; 353 354 struct nv04_gr_chan { 355 struct nvkm_object base; 356 int chid; 357 u32 nv04[ARRAY_SIZE(nv04_gr_ctx_regs)]; 358 }; 359 360 361 static inline struct nv04_gr * 362 nv04_gr(struct nv04_gr_chan *chan) 363 { 364 return (void *)nv_object(chan)->engine; 365 } 366 367 /******************************************************************************* 368 * Graphics object classes 369 ******************************************************************************/ 370 371 /* 372 * Software methods, why they are needed, and how they all work: 373 * 374 * NV04 and NV05 keep most of the state in PGRAPH context itself, but some 375 * 2d engine settings are kept inside the grobjs themselves. The grobjs are 376 * 3 words long on both. grobj format on NV04 is: 377 * 378 * word 0: 379 * - bits 0-7: class 380 * - bit 12: color key active 381 * - bit 13: clip rect active 382 * - bit 14: if set, destination surface is swizzled and taken from buffer 5 383 * [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken 384 * from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or 385 * NV03_CONTEXT_SURFACE_DST]. 386 * - bits 15-17: 2d operation [aka patch config] 387 * - bit 24: patch valid [enables rendering using this object] 388 * - bit 25: surf3d valid [for tex_tri and multitex_tri only] 389 * word 1: 390 * - bits 0-1: mono format 391 * - bits 8-13: color format 392 * - bits 16-31: DMA_NOTIFY instance 393 * word 2: 394 * - bits 0-15: DMA_A instance 395 * - bits 16-31: DMA_B instance 396 * 397 * On NV05 it's: 398 * 399 * word 0: 400 * - bits 0-7: class 401 * - bit 12: color key active 402 * - bit 13: clip rect active 403 * - bit 14: if set, destination surface is swizzled and taken from buffer 5 404 * [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken 405 * from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or 406 * NV03_CONTEXT_SURFACE_DST]. 407 * - bits 15-17: 2d operation [aka patch config] 408 * - bits 20-22: dither mode 409 * - bit 24: patch valid [enables rendering using this object] 410 * - bit 25: surface_dst/surface_color/surf2d/surf3d valid 411 * - bit 26: surface_src/surface_zeta valid 412 * - bit 27: pattern valid 413 * - bit 28: rop valid 414 * - bit 29: beta1 valid 415 * - bit 30: beta4 valid 416 * word 1: 417 * - bits 0-1: mono format 418 * - bits 8-13: color format 419 * - bits 16-31: DMA_NOTIFY instance 420 * word 2: 421 * - bits 0-15: DMA_A instance 422 * - bits 16-31: DMA_B instance 423 * 424 * NV05 will set/unset the relevant valid bits when you poke the relevant 425 * object-binding methods with object of the proper type, or with the NULL 426 * type. It'll only allow rendering using the grobj if all needed objects 427 * are bound. The needed set of objects depends on selected operation: for 428 * example rop object is needed by ROP_AND, but not by SRCCOPY_AND. 429 * 430 * NV04 doesn't have these methods implemented at all, and doesn't have the 431 * relevant bits in grobj. Instead, it'll allow rendering whenever bit 24 432 * is set. So we have to emulate them in software, internally keeping the 433 * same bits as NV05 does. Since grobjs are aligned to 16 bytes on nv04, 434 * but the last word isn't actually used for anything, we abuse it for this 435 * purpose. 436 * 437 * Actually, NV05 can optionally check bit 24 too, but we disable this since 438 * there's no use for it. 439 * 440 * For unknown reasons, NV04 implements surf3d binding in hardware as an 441 * exception. Also for unknown reasons, NV04 doesn't implement the clipping 442 * methods on the surf3d object, so we have to emulate them too. 443 */ 444 445 static void 446 nv04_gr_set_ctx1(struct nvkm_object *obj, u32 mask, u32 value) 447 { 448 struct nvkm_gpuobj *object = container_of(obj, typeof(*object), object); 449 struct nv04_gr *gr = (void *)object->object.engine; 450 struct nvkm_device *device = gr->base.engine.subdev.device; 451 int subc = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; 452 u32 tmp; 453 454 nvkm_kmap(object); 455 tmp = nvkm_ro32(object, 0x00); 456 tmp &= ~mask; 457 tmp |= value; 458 nvkm_wo32(object, 0x00, tmp); 459 nvkm_done(object); 460 461 nvkm_wr32(device, NV04_PGRAPH_CTX_SWITCH1, tmp); 462 nvkm_wr32(device, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); 463 } 464 465 static void 466 nv04_gr_set_ctx_val(struct nvkm_object *obj, u32 mask, u32 value) 467 { 468 struct nvkm_gpuobj *object = container_of(obj, typeof(*object), object); 469 int class, op, valid = 1; 470 u32 tmp, ctx1; 471 472 nvkm_kmap(object); 473 ctx1 = nvkm_ro32(object, 0x00); 474 class = ctx1 & 0xff; 475 op = (ctx1 >> 15) & 7; 476 477 tmp = nvkm_ro32(object, 0x0c); 478 tmp &= ~mask; 479 tmp |= value; 480 nvkm_wo32(object, 0x0c, tmp); 481 nvkm_done(object); 482 483 /* check for valid surf2d/surf_dst/surf_color */ 484 if (!(tmp & 0x02000000)) 485 valid = 0; 486 /* check for valid surf_src/surf_zeta */ 487 if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000)) 488 valid = 0; 489 490 switch (op) { 491 /* SRCCOPY_AND, SRCCOPY: no extra objects required */ 492 case 0: 493 case 3: 494 break; 495 /* ROP_AND: requires pattern and rop */ 496 case 1: 497 if (!(tmp & 0x18000000)) 498 valid = 0; 499 break; 500 /* BLEND_AND: requires beta1 */ 501 case 2: 502 if (!(tmp & 0x20000000)) 503 valid = 0; 504 break; 505 /* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */ 506 case 4: 507 case 5: 508 if (!(tmp & 0x40000000)) 509 valid = 0; 510 break; 511 } 512 513 nv04_gr_set_ctx1(obj, 0x01000000, valid << 24); 514 } 515 516 static int 517 nv04_gr_mthd_set_operation(struct nvkm_object *obj, u32 mthd, 518 void *args, u32 size) 519 { 520 struct nvkm_gpuobj *object = container_of(obj, typeof(*object), object); 521 u32 class = nvkm_ro32(object, 0) & 0xff; 522 u32 data = *(u32 *)args; 523 if (data > 5) 524 return 1; 525 /* Old versions of the objects only accept first three operations. */ 526 if (data > 2 && class < 0x40) 527 return 1; 528 nv04_gr_set_ctx1(obj, 0x00038000, data << 15); 529 /* changing operation changes set of objects needed for validation */ 530 nv04_gr_set_ctx_val(obj, 0, 0); 531 return 0; 532 } 533 534 static int 535 nv04_gr_mthd_surf3d_clip_h(struct nvkm_object *object, u32 mthd, 536 void *args, u32 size) 537 { 538 struct nv04_gr *gr = (void *)object->engine; 539 struct nvkm_device *device = gr->base.engine.subdev.device; 540 u32 data = *(u32 *)args; 541 u32 min = data & 0xffff, max; 542 u32 w = data >> 16; 543 if (min & 0x8000) 544 /* too large */ 545 return 1; 546 if (w & 0x8000) 547 /* yes, it accepts negative for some reason. */ 548 w |= 0xffff0000; 549 max = min + w; 550 max &= 0x3ffff; 551 nvkm_wr32(device, 0x40053c, min); 552 nvkm_wr32(device, 0x400544, max); 553 return 0; 554 } 555 556 static int 557 nv04_gr_mthd_surf3d_clip_v(struct nvkm_object *object, u32 mthd, 558 void *args, u32 size) 559 { 560 struct nv04_gr *gr = (void *)object->engine; 561 struct nvkm_device *device = gr->base.engine.subdev.device; 562 u32 data = *(u32 *)args; 563 u32 min = data & 0xffff, max; 564 u32 w = data >> 16; 565 if (min & 0x8000) 566 /* too large */ 567 return 1; 568 if (w & 0x8000) 569 /* yes, it accepts negative for some reason. */ 570 w |= 0xffff0000; 571 max = min + w; 572 max &= 0x3ffff; 573 nvkm_wr32(device, 0x400540, min); 574 nvkm_wr32(device, 0x400548, max); 575 return 0; 576 } 577 578 static u16 579 nv04_gr_mthd_bind_class(struct nvkm_object *object, u32 *args, u32 size) 580 { 581 struct nvkm_instmem *imem = nvkm_instmem(object); 582 u32 inst = *(u32 *)args << 4; 583 return imem->func->rd32(imem, inst); 584 } 585 586 static int 587 nv04_gr_mthd_bind_surf2d(struct nvkm_object *object, u32 mthd, 588 void *args, u32 size) 589 { 590 switch (nv04_gr_mthd_bind_class(object, args, size)) { 591 case 0x30: 592 nv04_gr_set_ctx1(object, 0x00004000, 0); 593 nv04_gr_set_ctx_val(object, 0x02000000, 0); 594 return 0; 595 case 0x42: 596 nv04_gr_set_ctx1(object, 0x00004000, 0); 597 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 598 return 0; 599 } 600 return 1; 601 } 602 603 static int 604 nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_object *object, u32 mthd, 605 void *args, u32 size) 606 { 607 switch (nv04_gr_mthd_bind_class(object, args, size)) { 608 case 0x30: 609 nv04_gr_set_ctx1(object, 0x00004000, 0); 610 nv04_gr_set_ctx_val(object, 0x02000000, 0); 611 return 0; 612 case 0x42: 613 nv04_gr_set_ctx1(object, 0x00004000, 0); 614 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 615 return 0; 616 case 0x52: 617 nv04_gr_set_ctx1(object, 0x00004000, 0x00004000); 618 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 619 return 0; 620 } 621 return 1; 622 } 623 624 static int 625 nv01_gr_mthd_bind_patt(struct nvkm_object *object, u32 mthd, 626 void *args, u32 size) 627 { 628 switch (nv04_gr_mthd_bind_class(object, args, size)) { 629 case 0x30: 630 nv04_gr_set_ctx_val(object, 0x08000000, 0); 631 return 0; 632 case 0x18: 633 nv04_gr_set_ctx_val(object, 0x08000000, 0x08000000); 634 return 0; 635 } 636 return 1; 637 } 638 639 static int 640 nv04_gr_mthd_bind_patt(struct nvkm_object *object, u32 mthd, 641 void *args, u32 size) 642 { 643 switch (nv04_gr_mthd_bind_class(object, args, size)) { 644 case 0x30: 645 nv04_gr_set_ctx_val(object, 0x08000000, 0); 646 return 0; 647 case 0x44: 648 nv04_gr_set_ctx_val(object, 0x08000000, 0x08000000); 649 return 0; 650 } 651 return 1; 652 } 653 654 static int 655 nv04_gr_mthd_bind_rop(struct nvkm_object *object, u32 mthd, 656 void *args, u32 size) 657 { 658 switch (nv04_gr_mthd_bind_class(object, args, size)) { 659 case 0x30: 660 nv04_gr_set_ctx_val(object, 0x10000000, 0); 661 return 0; 662 case 0x43: 663 nv04_gr_set_ctx_val(object, 0x10000000, 0x10000000); 664 return 0; 665 } 666 return 1; 667 } 668 669 static int 670 nv04_gr_mthd_bind_beta1(struct nvkm_object *object, u32 mthd, 671 void *args, u32 size) 672 { 673 switch (nv04_gr_mthd_bind_class(object, args, size)) { 674 case 0x30: 675 nv04_gr_set_ctx_val(object, 0x20000000, 0); 676 return 0; 677 case 0x12: 678 nv04_gr_set_ctx_val(object, 0x20000000, 0x20000000); 679 return 0; 680 } 681 return 1; 682 } 683 684 static int 685 nv04_gr_mthd_bind_beta4(struct nvkm_object *object, u32 mthd, 686 void *args, u32 size) 687 { 688 switch (nv04_gr_mthd_bind_class(object, args, size)) { 689 case 0x30: 690 nv04_gr_set_ctx_val(object, 0x40000000, 0); 691 return 0; 692 case 0x72: 693 nv04_gr_set_ctx_val(object, 0x40000000, 0x40000000); 694 return 0; 695 } 696 return 1; 697 } 698 699 static int 700 nv04_gr_mthd_bind_surf_dst(struct nvkm_object *object, u32 mthd, 701 void *args, u32 size) 702 { 703 switch (nv04_gr_mthd_bind_class(object, args, size)) { 704 case 0x30: 705 nv04_gr_set_ctx_val(object, 0x02000000, 0); 706 return 0; 707 case 0x58: 708 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 709 return 0; 710 } 711 return 1; 712 } 713 714 static int 715 nv04_gr_mthd_bind_surf_src(struct nvkm_object *object, u32 mthd, 716 void *args, u32 size) 717 { 718 switch (nv04_gr_mthd_bind_class(object, args, size)) { 719 case 0x30: 720 nv04_gr_set_ctx_val(object, 0x04000000, 0); 721 return 0; 722 case 0x59: 723 nv04_gr_set_ctx_val(object, 0x04000000, 0x04000000); 724 return 0; 725 } 726 return 1; 727 } 728 729 static int 730 nv04_gr_mthd_bind_surf_color(struct nvkm_object *object, u32 mthd, 731 void *args, u32 size) 732 { 733 switch (nv04_gr_mthd_bind_class(object, args, size)) { 734 case 0x30: 735 nv04_gr_set_ctx_val(object, 0x02000000, 0); 736 return 0; 737 case 0x5a: 738 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 739 return 0; 740 } 741 return 1; 742 } 743 744 static int 745 nv04_gr_mthd_bind_surf_zeta(struct nvkm_object *object, u32 mthd, 746 void *args, u32 size) 747 { 748 switch (nv04_gr_mthd_bind_class(object, args, size)) { 749 case 0x30: 750 nv04_gr_set_ctx_val(object, 0x04000000, 0); 751 return 0; 752 case 0x5b: 753 nv04_gr_set_ctx_val(object, 0x04000000, 0x04000000); 754 return 0; 755 } 756 return 1; 757 } 758 759 static int 760 nv01_gr_mthd_bind_clip(struct nvkm_object *object, u32 mthd, 761 void *args, u32 size) 762 { 763 switch (nv04_gr_mthd_bind_class(object, args, size)) { 764 case 0x30: 765 nv04_gr_set_ctx1(object, 0x2000, 0); 766 return 0; 767 case 0x19: 768 nv04_gr_set_ctx1(object, 0x2000, 0x2000); 769 return 0; 770 } 771 return 1; 772 } 773 774 static int 775 nv01_gr_mthd_bind_chroma(struct nvkm_object *object, u32 mthd, 776 void *args, u32 size) 777 { 778 switch (nv04_gr_mthd_bind_class(object, args, size)) { 779 case 0x30: 780 nv04_gr_set_ctx1(object, 0x1000, 0); 781 return 0; 782 /* Yes, for some reason even the old versions of objects 783 * accept 0x57 and not 0x17. Consistency be damned. 784 */ 785 case 0x57: 786 nv04_gr_set_ctx1(object, 0x1000, 0x1000); 787 return 0; 788 } 789 return 1; 790 } 791 792 static struct nvkm_omthds 793 nv03_gr_gdi_omthds[] = { 794 { 0x0184, 0x0184, nv01_gr_mthd_bind_patt }, 795 { 0x0188, 0x0188, nv04_gr_mthd_bind_rop }, 796 { 0x018c, 0x018c, nv04_gr_mthd_bind_beta1 }, 797 { 0x0190, 0x0190, nv04_gr_mthd_bind_surf_dst }, 798 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 799 {} 800 }; 801 802 static struct nvkm_omthds 803 nv04_gr_gdi_omthds[] = { 804 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 805 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 806 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 807 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 808 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 809 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 810 {} 811 }; 812 813 static struct nvkm_omthds 814 nv01_gr_blit_omthds[] = { 815 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 816 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 817 { 0x018c, 0x018c, nv01_gr_mthd_bind_patt }, 818 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 819 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 820 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf_dst }, 821 { 0x019c, 0x019c, nv04_gr_mthd_bind_surf_src }, 822 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 823 {} 824 }; 825 826 static struct nvkm_omthds 827 nv04_gr_blit_omthds[] = { 828 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 829 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 830 { 0x018c, 0x018c, nv04_gr_mthd_bind_patt }, 831 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 832 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 833 { 0x0198, 0x0198, nv04_gr_mthd_bind_beta4 }, 834 { 0x019c, 0x019c, nv04_gr_mthd_bind_surf2d }, 835 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 836 {} 837 }; 838 839 static struct nvkm_omthds 840 nv04_gr_iifc_omthds[] = { 841 { 0x0188, 0x0188, nv01_gr_mthd_bind_chroma }, 842 { 0x018c, 0x018c, nv01_gr_mthd_bind_clip }, 843 { 0x0190, 0x0190, nv04_gr_mthd_bind_patt }, 844 { 0x0194, 0x0194, nv04_gr_mthd_bind_rop }, 845 { 0x0198, 0x0198, nv04_gr_mthd_bind_beta1 }, 846 { 0x019c, 0x019c, nv04_gr_mthd_bind_beta4 }, 847 { 0x01a0, 0x01a0, nv04_gr_mthd_bind_surf2d_swzsurf }, 848 { 0x03e4, 0x03e4, nv04_gr_mthd_set_operation }, 849 {} 850 }; 851 852 static struct nvkm_omthds 853 nv01_gr_ifc_omthds[] = { 854 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 855 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 856 { 0x018c, 0x018c, nv01_gr_mthd_bind_patt }, 857 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 858 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 859 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf_dst }, 860 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 861 {} 862 }; 863 864 static struct nvkm_omthds 865 nv04_gr_ifc_omthds[] = { 866 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 867 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 868 { 0x018c, 0x018c, nv04_gr_mthd_bind_patt }, 869 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 870 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 871 { 0x0198, 0x0198, nv04_gr_mthd_bind_beta4 }, 872 { 0x019c, 0x019c, nv04_gr_mthd_bind_surf2d }, 873 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 874 {} 875 }; 876 877 static struct nvkm_omthds 878 nv03_gr_sifc_omthds[] = { 879 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 880 { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, 881 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 882 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 883 { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, 884 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 885 {} 886 }; 887 888 static struct nvkm_omthds 889 nv04_gr_sifc_omthds[] = { 890 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 891 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 892 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 893 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 894 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 895 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 896 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 897 {} 898 }; 899 900 static struct nvkm_omthds 901 nv03_gr_sifm_omthds[] = { 902 { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, 903 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 904 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 905 { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, 906 { 0x0304, 0x0304, nv04_gr_mthd_set_operation }, 907 {} 908 }; 909 910 static struct nvkm_omthds 911 nv04_gr_sifm_omthds[] = { 912 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 913 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 914 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 915 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 916 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 917 { 0x0304, 0x0304, nv04_gr_mthd_set_operation }, 918 {} 919 }; 920 921 static struct nvkm_omthds 922 nv04_gr_surf3d_omthds[] = { 923 { 0x02f8, 0x02f8, nv04_gr_mthd_surf3d_clip_h }, 924 { 0x02fc, 0x02fc, nv04_gr_mthd_surf3d_clip_v }, 925 {} 926 }; 927 928 static struct nvkm_omthds 929 nv03_gr_ttri_omthds[] = { 930 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 931 { 0x018c, 0x018c, nv04_gr_mthd_bind_surf_color }, 932 { 0x0190, 0x0190, nv04_gr_mthd_bind_surf_zeta }, 933 {} 934 }; 935 936 static struct nvkm_omthds 937 nv01_gr_prim_omthds[] = { 938 { 0x0184, 0x0184, nv01_gr_mthd_bind_clip }, 939 { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, 940 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 941 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 942 { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, 943 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 944 {} 945 }; 946 947 static struct nvkm_omthds 948 nv04_gr_prim_omthds[] = { 949 { 0x0184, 0x0184, nv01_gr_mthd_bind_clip }, 950 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 951 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 952 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 953 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 954 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 955 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 956 {} 957 }; 958 959 static int 960 nv04_gr_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 961 struct nvkm_oclass *oclass, void *data, u32 size, 962 struct nvkm_object **pobject) 963 { 964 struct nvkm_gpuobj *obj; 965 int ret; 966 967 ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, 968 16, 16, 0, &obj); 969 *pobject = nv_object(obj); 970 if (ret) 971 return ret; 972 973 nvkm_kmap(obj); 974 nvkm_wo32(obj, 0x00, nv_mclass(obj)); 975 #ifdef __BIG_ENDIAN 976 nvkm_mo32(obj, 0x00, 0x00080000, 0x00080000); 977 #endif 978 nvkm_wo32(obj, 0x04, 0x00000000); 979 nvkm_wo32(obj, 0x08, 0x00000000); 980 nvkm_wo32(obj, 0x0c, 0x00000000); 981 nvkm_done(obj); 982 return 0; 983 } 984 985 struct nvkm_ofuncs 986 nv04_gr_ofuncs = { 987 .ctor = nv04_gr_object_ctor, 988 .dtor = _nvkm_gpuobj_dtor, 989 .init = _nvkm_gpuobj_init, 990 .fini = _nvkm_gpuobj_fini, 991 .rd32 = _nvkm_gpuobj_rd32, 992 .wr32 = _nvkm_gpuobj_wr32, 993 }; 994 995 static struct nvkm_oclass 996 nv04_gr_sclass[] = { 997 { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ 998 { 0x0017, &nv04_gr_ofuncs }, /* chroma */ 999 { 0x0018, &nv04_gr_ofuncs }, /* pattern (nv01) */ 1000 { 0x0019, &nv04_gr_ofuncs }, /* clip */ 1001 { 0x001c, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* line */ 1002 { 0x001d, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* tri */ 1003 { 0x001e, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* rect */ 1004 { 0x001f, &nv04_gr_ofuncs, nv01_gr_blit_omthds }, 1005 { 0x0021, &nv04_gr_ofuncs, nv01_gr_ifc_omthds }, 1006 { 0x0030, &nv04_gr_ofuncs }, /* null */ 1007 { 0x0036, &nv04_gr_ofuncs, nv03_gr_sifc_omthds }, 1008 { 0x0037, &nv04_gr_ofuncs, nv03_gr_sifm_omthds }, 1009 { 0x0038, &nv04_gr_ofuncs }, /* dvd subpicture */ 1010 { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ 1011 { 0x0042, &nv04_gr_ofuncs }, /* surf2d */ 1012 { 0x0043, &nv04_gr_ofuncs }, /* rop */ 1013 { 0x0044, &nv04_gr_ofuncs }, /* pattern */ 1014 { 0x0048, &nv04_gr_ofuncs, nv03_gr_ttri_omthds }, 1015 { 0x004a, &nv04_gr_ofuncs, nv04_gr_gdi_omthds }, 1016 { 0x004b, &nv04_gr_ofuncs, nv03_gr_gdi_omthds }, 1017 { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ 1018 { 0x0053, &nv04_gr_ofuncs, nv04_gr_surf3d_omthds }, 1019 { 0x0054, &nv04_gr_ofuncs }, /* ttri */ 1020 { 0x0055, &nv04_gr_ofuncs }, /* mtri */ 1021 { 0x0057, &nv04_gr_ofuncs }, /* chroma */ 1022 { 0x0058, &nv04_gr_ofuncs }, /* surf_dst */ 1023 { 0x0059, &nv04_gr_ofuncs }, /* surf_src */ 1024 { 0x005a, &nv04_gr_ofuncs }, /* surf_color */ 1025 { 0x005b, &nv04_gr_ofuncs }, /* surf_zeta */ 1026 { 0x005c, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* line */ 1027 { 0x005d, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* tri */ 1028 { 0x005e, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* rect */ 1029 { 0x005f, &nv04_gr_ofuncs, nv04_gr_blit_omthds }, 1030 { 0x0060, &nv04_gr_ofuncs, nv04_gr_iifc_omthds }, 1031 { 0x0061, &nv04_gr_ofuncs, nv04_gr_ifc_omthds }, 1032 { 0x0064, &nv04_gr_ofuncs }, /* iifc (nv05) */ 1033 { 0x0065, &nv04_gr_ofuncs }, /* ifc (nv05) */ 1034 { 0x0066, &nv04_gr_ofuncs }, /* sifc (nv05) */ 1035 { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ 1036 { 0x0076, &nv04_gr_ofuncs, nv04_gr_sifc_omthds }, 1037 { 0x0077, &nv04_gr_ofuncs, nv04_gr_sifm_omthds }, 1038 {}, 1039 }; 1040 1041 /******************************************************************************* 1042 * PGRAPH context 1043 ******************************************************************************/ 1044 1045 static struct nv04_gr_chan * 1046 nv04_gr_channel(struct nv04_gr *gr) 1047 { 1048 struct nvkm_device *device = gr->base.engine.subdev.device; 1049 struct nv04_gr_chan *chan = NULL; 1050 if (nvkm_rd32(device, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) { 1051 int chid = nvkm_rd32(device, NV04_PGRAPH_CTX_USER) >> 24; 1052 if (chid < ARRAY_SIZE(gr->chan)) 1053 chan = gr->chan[chid]; 1054 } 1055 return chan; 1056 } 1057 1058 static int 1059 nv04_gr_load_context(struct nv04_gr_chan *chan, int chid) 1060 { 1061 struct nv04_gr *gr = nv04_gr(chan); 1062 struct nvkm_device *device = gr->base.engine.subdev.device; 1063 int i; 1064 1065 for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) 1066 nvkm_wr32(device, nv04_gr_ctx_regs[i], chan->nv04[i]); 1067 1068 nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10010100); 1069 nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24); 1070 nvkm_mask(device, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000); 1071 return 0; 1072 } 1073 1074 static int 1075 nv04_gr_unload_context(struct nv04_gr_chan *chan) 1076 { 1077 struct nv04_gr *gr = nv04_gr(chan); 1078 struct nvkm_device *device = gr->base.engine.subdev.device; 1079 int i; 1080 1081 for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) 1082 chan->nv04[i] = nvkm_rd32(device, nv04_gr_ctx_regs[i]); 1083 1084 nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10000000); 1085 nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); 1086 return 0; 1087 } 1088 1089 static void 1090 nv04_gr_context_switch(struct nv04_gr *gr) 1091 { 1092 struct nvkm_device *device = gr->base.engine.subdev.device; 1093 struct nv04_gr_chan *prev = NULL; 1094 struct nv04_gr_chan *next = NULL; 1095 unsigned long flags; 1096 int chid; 1097 1098 spin_lock_irqsave(&gr->lock, flags); 1099 nv04_gr_idle(gr); 1100 1101 /* If previous context is valid, we need to save it */ 1102 prev = nv04_gr_channel(gr); 1103 if (prev) 1104 nv04_gr_unload_context(prev); 1105 1106 /* load context for next channel */ 1107 chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f; 1108 next = gr->chan[chid]; 1109 if (next) 1110 nv04_gr_load_context(next, chid); 1111 1112 spin_unlock_irqrestore(&gr->lock, flags); 1113 } 1114 1115 static u32 *ctx_reg(struct nv04_gr_chan *chan, u32 reg) 1116 { 1117 int i; 1118 1119 for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) { 1120 if (nv04_gr_ctx_regs[i] == reg) 1121 return &chan->nv04[i]; 1122 } 1123 1124 return NULL; 1125 } 1126 1127 static int 1128 nv04_gr_context_ctor(struct nvkm_object *parent, 1129 struct nvkm_object *engine, 1130 struct nvkm_oclass *oclass, void *data, u32 size, 1131 struct nvkm_object **pobject) 1132 { 1133 struct nvkm_fifo_chan *fifo = (void *)parent; 1134 struct nv04_gr *gr = (void *)engine; 1135 struct nv04_gr_chan *chan; 1136 unsigned long flags; 1137 int ret; 1138 1139 ret = nvkm_object_create(parent, engine, oclass, 0, &chan); 1140 *pobject = nv_object(chan); 1141 if (ret) 1142 return ret; 1143 1144 spin_lock_irqsave(&gr->lock, flags); 1145 if (gr->chan[fifo->chid]) { 1146 *pobject = nv_object(gr->chan[fifo->chid]); 1147 atomic_inc(&(*pobject)->refcount); 1148 spin_unlock_irqrestore(&gr->lock, flags); 1149 nvkm_object_destroy(&chan->base); 1150 return 1; 1151 } 1152 1153 *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; 1154 1155 gr->chan[fifo->chid] = chan; 1156 chan->chid = fifo->chid; 1157 spin_unlock_irqrestore(&gr->lock, flags); 1158 return 0; 1159 } 1160 1161 static void 1162 nv04_gr_context_dtor(struct nvkm_object *object) 1163 { 1164 struct nv04_gr *gr = (void *)object->engine; 1165 struct nv04_gr_chan *chan = (void *)object; 1166 unsigned long flags; 1167 1168 spin_lock_irqsave(&gr->lock, flags); 1169 gr->chan[chan->chid] = NULL; 1170 spin_unlock_irqrestore(&gr->lock, flags); 1171 1172 nvkm_object_destroy(&chan->base); 1173 } 1174 1175 static int 1176 nv04_gr_context_fini(struct nvkm_object *object, bool suspend) 1177 { 1178 struct nv04_gr *gr = (void *)object->engine; 1179 struct nv04_gr_chan *chan = (void *)object; 1180 struct nvkm_device *device = gr->base.engine.subdev.device; 1181 unsigned long flags; 1182 1183 spin_lock_irqsave(&gr->lock, flags); 1184 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); 1185 if (nv04_gr_channel(gr) == chan) 1186 nv04_gr_unload_context(chan); 1187 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); 1188 spin_unlock_irqrestore(&gr->lock, flags); 1189 1190 return _nvkm_object_fini(&chan->base, suspend); 1191 } 1192 1193 static struct nvkm_oclass 1194 nv04_gr_cclass = { 1195 .handle = NV_ENGCTX(GR, 0x04), 1196 .ofuncs = &(struct nvkm_ofuncs) { 1197 .ctor = nv04_gr_context_ctor, 1198 .dtor = nv04_gr_context_dtor, 1199 .init = _nvkm_object_init, 1200 .fini = nv04_gr_context_fini, 1201 }, 1202 }; 1203 1204 /******************************************************************************* 1205 * PGRAPH engine/subdev functions 1206 ******************************************************************************/ 1207 1208 bool 1209 nv04_gr_idle(void *obj) 1210 { 1211 struct nvkm_gr *gr = nvkm_gr(obj); 1212 struct nvkm_subdev *subdev = &gr->engine.subdev; 1213 struct nvkm_device *device = subdev->device; 1214 u32 mask = 0xffffffff; 1215 1216 if (nv_device(obj)->card_type == NV_40) 1217 mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; 1218 1219 if (nvkm_msec(device, 2000, 1220 if (!(nvkm_rd32(device, NV04_PGRAPH_STATUS) & mask)) 1221 break; 1222 ) < 0) { 1223 nvkm_error(subdev, "idle timed out with status %08x\n", 1224 nvkm_rd32(device, NV04_PGRAPH_STATUS)); 1225 return false; 1226 } 1227 1228 return true; 1229 } 1230 1231 static const struct nvkm_bitfield 1232 nv04_gr_intr_name[] = { 1233 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, 1234 {} 1235 }; 1236 1237 static const struct nvkm_bitfield 1238 nv04_gr_nstatus[] = { 1239 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, 1240 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, 1241 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, 1242 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, 1243 {} 1244 }; 1245 1246 const struct nvkm_bitfield 1247 nv04_gr_nsource[] = { 1248 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, 1249 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, 1250 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, 1251 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, 1252 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, 1253 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, 1254 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, 1255 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, 1256 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, 1257 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, 1258 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, 1259 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, 1260 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, 1261 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, 1262 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, 1263 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, 1264 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, 1265 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, 1266 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, 1267 {} 1268 }; 1269 1270 static void 1271 nv04_gr_intr(struct nvkm_subdev *subdev) 1272 { 1273 struct nv04_gr *gr = (void *)subdev; 1274 struct nv04_gr_chan *chan = NULL; 1275 struct nvkm_namedb *namedb = NULL; 1276 struct nvkm_handle *handle = NULL; 1277 struct nvkm_device *device = gr->base.engine.subdev.device; 1278 u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); 1279 u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); 1280 u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); 1281 u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); 1282 u32 chid = (addr & 0x0f000000) >> 24; 1283 u32 subc = (addr & 0x0000e000) >> 13; 1284 u32 mthd = (addr & 0x00001ffc); 1285 u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); 1286 u32 class = nvkm_rd32(device, 0x400180 + subc * 4) & 0xff; 1287 u32 inst = (nvkm_rd32(device, 0x40016c) & 0xffff) << 4; 1288 u32 show = stat; 1289 char msg[128], src[128], sta[128]; 1290 unsigned long flags; 1291 1292 spin_lock_irqsave(&gr->lock, flags); 1293 chan = gr->chan[chid]; 1294 if (chan) 1295 namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); 1296 spin_unlock_irqrestore(&gr->lock, flags); 1297 1298 if (stat & NV_PGRAPH_INTR_NOTIFY) { 1299 if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { 1300 handle = nvkm_namedb_get_vinst(namedb, inst); 1301 if (handle && !nv_call(handle->object, mthd, data)) 1302 show &= ~NV_PGRAPH_INTR_NOTIFY; 1303 } 1304 } 1305 1306 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { 1307 nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); 1308 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; 1309 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; 1310 nv04_gr_context_switch(gr); 1311 } 1312 1313 nvkm_wr32(device, NV03_PGRAPH_INTR, stat); 1314 nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); 1315 1316 if (show) { 1317 nvkm_snprintbf(msg, sizeof(msg), nv04_gr_intr_name, show); 1318 nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); 1319 nvkm_snprintbf(sta, sizeof(sta), nv04_gr_nstatus, nstatus); 1320 nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " 1321 "nstatus %08x [%s] ch %d [%s] subc %d " 1322 "class %04x mthd %04x data %08x\n", 1323 show, msg, nsource, src, nstatus, sta, chid, 1324 nvkm_client_name(chan), subc, class, mthd, data); 1325 } 1326 1327 nvkm_namedb_put(handle); 1328 } 1329 1330 static int 1331 nv04_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 1332 struct nvkm_oclass *oclass, void *data, u32 size, 1333 struct nvkm_object **pobject) 1334 { 1335 struct nv04_gr *gr; 1336 int ret; 1337 1338 ret = nvkm_gr_create(parent, engine, oclass, true, &gr); 1339 *pobject = nv_object(gr); 1340 if (ret) 1341 return ret; 1342 1343 nv_subdev(gr)->unit = 0x00001000; 1344 nv_subdev(gr)->intr = nv04_gr_intr; 1345 nv_engine(gr)->cclass = &nv04_gr_cclass; 1346 nv_engine(gr)->sclass = nv04_gr_sclass; 1347 spin_lock_init(&gr->lock); 1348 return 0; 1349 } 1350 1351 static int 1352 nv04_gr_init(struct nvkm_object *object) 1353 { 1354 struct nvkm_engine *engine = nv_engine(object); 1355 struct nv04_gr *gr = (void *)engine; 1356 struct nvkm_device *device = gr->base.engine.subdev.device; 1357 int ret; 1358 1359 ret = nvkm_gr_init(&gr->base); 1360 if (ret) 1361 return ret; 1362 1363 /* Enable PGRAPH interrupts */ 1364 nvkm_wr32(device, NV03_PGRAPH_INTR, 0xFFFFFFFF); 1365 nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 1366 1367 nvkm_wr32(device, NV04_PGRAPH_VALID1, 0); 1368 nvkm_wr32(device, NV04_PGRAPH_VALID2, 0); 1369 /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x000001FF); 1370 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ 1371 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x1231c000); 1372 /*1231C000 blob, 001 haiku*/ 1373 /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ 1374 nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x72111100); 1375 /*0x72111100 blob , 01 haiku*/ 1376 /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ 1377 nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f071); 1378 /*haiku same*/ 1379 1380 /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ 1381 nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); 1382 /*haiku and blob 10d4*/ 1383 1384 nvkm_wr32(device, NV04_PGRAPH_STATE , 0xFFFFFFFF); 1385 nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL , 0x10000100); 1386 nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); 1387 1388 /* These don't belong here, they're part of a per-channel context */ 1389 nvkm_wr32(device, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); 1390 nvkm_wr32(device, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); 1391 return 0; 1392 } 1393 1394 struct nvkm_oclass 1395 nv04_gr_oclass = { 1396 .handle = NV_ENGINE(GR, 0x04), 1397 .ofuncs = &(struct nvkm_ofuncs) { 1398 .ctor = nv04_gr_ctor, 1399 .dtor = _nvkm_gr_dtor, 1400 .init = nv04_gr_init, 1401 .fini = _nvkm_gr_fini, 1402 }, 1403 }; 1404