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 *object, u32 mask, u32 value) 447 { 448 struct nv04_gr *gr = (void *)object->engine; 449 struct nvkm_device *device = gr->base.engine.subdev.device; 450 int subc = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; 451 u32 tmp; 452 453 tmp = nv_ro32(object, 0x00); 454 tmp &= ~mask; 455 tmp |= value; 456 nv_wo32(object, 0x00, tmp); 457 458 nvkm_wr32(device, NV04_PGRAPH_CTX_SWITCH1, tmp); 459 nvkm_wr32(device, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); 460 } 461 462 static void 463 nv04_gr_set_ctx_val(struct nvkm_object *object, u32 mask, u32 value) 464 { 465 int class, op, valid = 1; 466 u32 tmp, ctx1; 467 468 ctx1 = nv_ro32(object, 0x00); 469 class = ctx1 & 0xff; 470 op = (ctx1 >> 15) & 7; 471 472 tmp = nv_ro32(object, 0x0c); 473 tmp &= ~mask; 474 tmp |= value; 475 nv_wo32(object, 0x0c, tmp); 476 477 /* check for valid surf2d/surf_dst/surf_color */ 478 if (!(tmp & 0x02000000)) 479 valid = 0; 480 /* check for valid surf_src/surf_zeta */ 481 if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000)) 482 valid = 0; 483 484 switch (op) { 485 /* SRCCOPY_AND, SRCCOPY: no extra objects required */ 486 case 0: 487 case 3: 488 break; 489 /* ROP_AND: requires pattern and rop */ 490 case 1: 491 if (!(tmp & 0x18000000)) 492 valid = 0; 493 break; 494 /* BLEND_AND: requires beta1 */ 495 case 2: 496 if (!(tmp & 0x20000000)) 497 valid = 0; 498 break; 499 /* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */ 500 case 4: 501 case 5: 502 if (!(tmp & 0x40000000)) 503 valid = 0; 504 break; 505 } 506 507 nv04_gr_set_ctx1(object, 0x01000000, valid << 24); 508 } 509 510 static int 511 nv04_gr_mthd_set_operation(struct nvkm_object *object, u32 mthd, 512 void *args, u32 size) 513 { 514 u32 class = nv_ro32(object, 0) & 0xff; 515 u32 data = *(u32 *)args; 516 if (data > 5) 517 return 1; 518 /* Old versions of the objects only accept first three operations. */ 519 if (data > 2 && class < 0x40) 520 return 1; 521 nv04_gr_set_ctx1(object, 0x00038000, data << 15); 522 /* changing operation changes set of objects needed for validation */ 523 nv04_gr_set_ctx_val(object, 0, 0); 524 return 0; 525 } 526 527 static int 528 nv04_gr_mthd_surf3d_clip_h(struct nvkm_object *object, u32 mthd, 529 void *args, u32 size) 530 { 531 struct nv04_gr *gr = (void *)object->engine; 532 struct nvkm_device *device = gr->base.engine.subdev.device; 533 u32 data = *(u32 *)args; 534 u32 min = data & 0xffff, max; 535 u32 w = data >> 16; 536 if (min & 0x8000) 537 /* too large */ 538 return 1; 539 if (w & 0x8000) 540 /* yes, it accepts negative for some reason. */ 541 w |= 0xffff0000; 542 max = min + w; 543 max &= 0x3ffff; 544 nvkm_wr32(device, 0x40053c, min); 545 nvkm_wr32(device, 0x400544, max); 546 return 0; 547 } 548 549 static int 550 nv04_gr_mthd_surf3d_clip_v(struct nvkm_object *object, u32 mthd, 551 void *args, u32 size) 552 { 553 struct nv04_gr *gr = (void *)object->engine; 554 struct nvkm_device *device = gr->base.engine.subdev.device; 555 u32 data = *(u32 *)args; 556 u32 min = data & 0xffff, max; 557 u32 w = data >> 16; 558 if (min & 0x8000) 559 /* too large */ 560 return 1; 561 if (w & 0x8000) 562 /* yes, it accepts negative for some reason. */ 563 w |= 0xffff0000; 564 max = min + w; 565 max &= 0x3ffff; 566 nvkm_wr32(device, 0x400540, min); 567 nvkm_wr32(device, 0x400548, max); 568 return 0; 569 } 570 571 static u16 572 nv04_gr_mthd_bind_class(struct nvkm_object *object, u32 *args, u32 size) 573 { 574 struct nvkm_instmem *imem = nvkm_instmem(object); 575 u32 inst = *(u32 *)args << 4; 576 return nv_ro32(imem, inst); 577 } 578 579 static int 580 nv04_gr_mthd_bind_surf2d(struct nvkm_object *object, u32 mthd, 581 void *args, u32 size) 582 { 583 switch (nv04_gr_mthd_bind_class(object, args, size)) { 584 case 0x30: 585 nv04_gr_set_ctx1(object, 0x00004000, 0); 586 nv04_gr_set_ctx_val(object, 0x02000000, 0); 587 return 0; 588 case 0x42: 589 nv04_gr_set_ctx1(object, 0x00004000, 0); 590 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 591 return 0; 592 } 593 return 1; 594 } 595 596 static int 597 nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_object *object, u32 mthd, 598 void *args, u32 size) 599 { 600 switch (nv04_gr_mthd_bind_class(object, args, size)) { 601 case 0x30: 602 nv04_gr_set_ctx1(object, 0x00004000, 0); 603 nv04_gr_set_ctx_val(object, 0x02000000, 0); 604 return 0; 605 case 0x42: 606 nv04_gr_set_ctx1(object, 0x00004000, 0); 607 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 608 return 0; 609 case 0x52: 610 nv04_gr_set_ctx1(object, 0x00004000, 0x00004000); 611 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 612 return 0; 613 } 614 return 1; 615 } 616 617 static int 618 nv01_gr_mthd_bind_patt(struct nvkm_object *object, u32 mthd, 619 void *args, u32 size) 620 { 621 switch (nv04_gr_mthd_bind_class(object, args, size)) { 622 case 0x30: 623 nv04_gr_set_ctx_val(object, 0x08000000, 0); 624 return 0; 625 case 0x18: 626 nv04_gr_set_ctx_val(object, 0x08000000, 0x08000000); 627 return 0; 628 } 629 return 1; 630 } 631 632 static int 633 nv04_gr_mthd_bind_patt(struct nvkm_object *object, u32 mthd, 634 void *args, u32 size) 635 { 636 switch (nv04_gr_mthd_bind_class(object, args, size)) { 637 case 0x30: 638 nv04_gr_set_ctx_val(object, 0x08000000, 0); 639 return 0; 640 case 0x44: 641 nv04_gr_set_ctx_val(object, 0x08000000, 0x08000000); 642 return 0; 643 } 644 return 1; 645 } 646 647 static int 648 nv04_gr_mthd_bind_rop(struct nvkm_object *object, u32 mthd, 649 void *args, u32 size) 650 { 651 switch (nv04_gr_mthd_bind_class(object, args, size)) { 652 case 0x30: 653 nv04_gr_set_ctx_val(object, 0x10000000, 0); 654 return 0; 655 case 0x43: 656 nv04_gr_set_ctx_val(object, 0x10000000, 0x10000000); 657 return 0; 658 } 659 return 1; 660 } 661 662 static int 663 nv04_gr_mthd_bind_beta1(struct nvkm_object *object, u32 mthd, 664 void *args, u32 size) 665 { 666 switch (nv04_gr_mthd_bind_class(object, args, size)) { 667 case 0x30: 668 nv04_gr_set_ctx_val(object, 0x20000000, 0); 669 return 0; 670 case 0x12: 671 nv04_gr_set_ctx_val(object, 0x20000000, 0x20000000); 672 return 0; 673 } 674 return 1; 675 } 676 677 static int 678 nv04_gr_mthd_bind_beta4(struct nvkm_object *object, u32 mthd, 679 void *args, u32 size) 680 { 681 switch (nv04_gr_mthd_bind_class(object, args, size)) { 682 case 0x30: 683 nv04_gr_set_ctx_val(object, 0x40000000, 0); 684 return 0; 685 case 0x72: 686 nv04_gr_set_ctx_val(object, 0x40000000, 0x40000000); 687 return 0; 688 } 689 return 1; 690 } 691 692 static int 693 nv04_gr_mthd_bind_surf_dst(struct nvkm_object *object, u32 mthd, 694 void *args, u32 size) 695 { 696 switch (nv04_gr_mthd_bind_class(object, args, size)) { 697 case 0x30: 698 nv04_gr_set_ctx_val(object, 0x02000000, 0); 699 return 0; 700 case 0x58: 701 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 702 return 0; 703 } 704 return 1; 705 } 706 707 static int 708 nv04_gr_mthd_bind_surf_src(struct nvkm_object *object, u32 mthd, 709 void *args, u32 size) 710 { 711 switch (nv04_gr_mthd_bind_class(object, args, size)) { 712 case 0x30: 713 nv04_gr_set_ctx_val(object, 0x04000000, 0); 714 return 0; 715 case 0x59: 716 nv04_gr_set_ctx_val(object, 0x04000000, 0x04000000); 717 return 0; 718 } 719 return 1; 720 } 721 722 static int 723 nv04_gr_mthd_bind_surf_color(struct nvkm_object *object, u32 mthd, 724 void *args, u32 size) 725 { 726 switch (nv04_gr_mthd_bind_class(object, args, size)) { 727 case 0x30: 728 nv04_gr_set_ctx_val(object, 0x02000000, 0); 729 return 0; 730 case 0x5a: 731 nv04_gr_set_ctx_val(object, 0x02000000, 0x02000000); 732 return 0; 733 } 734 return 1; 735 } 736 737 static int 738 nv04_gr_mthd_bind_surf_zeta(struct nvkm_object *object, u32 mthd, 739 void *args, u32 size) 740 { 741 switch (nv04_gr_mthd_bind_class(object, args, size)) { 742 case 0x30: 743 nv04_gr_set_ctx_val(object, 0x04000000, 0); 744 return 0; 745 case 0x5b: 746 nv04_gr_set_ctx_val(object, 0x04000000, 0x04000000); 747 return 0; 748 } 749 return 1; 750 } 751 752 static int 753 nv01_gr_mthd_bind_clip(struct nvkm_object *object, u32 mthd, 754 void *args, u32 size) 755 { 756 switch (nv04_gr_mthd_bind_class(object, args, size)) { 757 case 0x30: 758 nv04_gr_set_ctx1(object, 0x2000, 0); 759 return 0; 760 case 0x19: 761 nv04_gr_set_ctx1(object, 0x2000, 0x2000); 762 return 0; 763 } 764 return 1; 765 } 766 767 static int 768 nv01_gr_mthd_bind_chroma(struct nvkm_object *object, u32 mthd, 769 void *args, u32 size) 770 { 771 switch (nv04_gr_mthd_bind_class(object, args, size)) { 772 case 0x30: 773 nv04_gr_set_ctx1(object, 0x1000, 0); 774 return 0; 775 /* Yes, for some reason even the old versions of objects 776 * accept 0x57 and not 0x17. Consistency be damned. 777 */ 778 case 0x57: 779 nv04_gr_set_ctx1(object, 0x1000, 0x1000); 780 return 0; 781 } 782 return 1; 783 } 784 785 static struct nvkm_omthds 786 nv03_gr_gdi_omthds[] = { 787 { 0x0184, 0x0184, nv01_gr_mthd_bind_patt }, 788 { 0x0188, 0x0188, nv04_gr_mthd_bind_rop }, 789 { 0x018c, 0x018c, nv04_gr_mthd_bind_beta1 }, 790 { 0x0190, 0x0190, nv04_gr_mthd_bind_surf_dst }, 791 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 792 {} 793 }; 794 795 static struct nvkm_omthds 796 nv04_gr_gdi_omthds[] = { 797 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 798 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 799 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 800 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 801 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 802 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 803 {} 804 }; 805 806 static struct nvkm_omthds 807 nv01_gr_blit_omthds[] = { 808 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 809 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 810 { 0x018c, 0x018c, nv01_gr_mthd_bind_patt }, 811 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 812 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 813 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf_dst }, 814 { 0x019c, 0x019c, nv04_gr_mthd_bind_surf_src }, 815 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 816 {} 817 }; 818 819 static struct nvkm_omthds 820 nv04_gr_blit_omthds[] = { 821 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 822 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 823 { 0x018c, 0x018c, nv04_gr_mthd_bind_patt }, 824 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 825 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 826 { 0x0198, 0x0198, nv04_gr_mthd_bind_beta4 }, 827 { 0x019c, 0x019c, nv04_gr_mthd_bind_surf2d }, 828 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 829 {} 830 }; 831 832 static struct nvkm_omthds 833 nv04_gr_iifc_omthds[] = { 834 { 0x0188, 0x0188, nv01_gr_mthd_bind_chroma }, 835 { 0x018c, 0x018c, nv01_gr_mthd_bind_clip }, 836 { 0x0190, 0x0190, nv04_gr_mthd_bind_patt }, 837 { 0x0194, 0x0194, nv04_gr_mthd_bind_rop }, 838 { 0x0198, 0x0198, nv04_gr_mthd_bind_beta1 }, 839 { 0x019c, 0x019c, nv04_gr_mthd_bind_beta4 }, 840 { 0x01a0, 0x01a0, nv04_gr_mthd_bind_surf2d_swzsurf }, 841 { 0x03e4, 0x03e4, nv04_gr_mthd_set_operation }, 842 {} 843 }; 844 845 static struct nvkm_omthds 846 nv01_gr_ifc_omthds[] = { 847 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 848 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 849 { 0x018c, 0x018c, nv01_gr_mthd_bind_patt }, 850 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 851 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 852 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf_dst }, 853 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 854 {} 855 }; 856 857 static struct nvkm_omthds 858 nv04_gr_ifc_omthds[] = { 859 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 860 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 861 { 0x018c, 0x018c, nv04_gr_mthd_bind_patt }, 862 { 0x0190, 0x0190, nv04_gr_mthd_bind_rop }, 863 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta1 }, 864 { 0x0198, 0x0198, nv04_gr_mthd_bind_beta4 }, 865 { 0x019c, 0x019c, nv04_gr_mthd_bind_surf2d }, 866 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 867 {} 868 }; 869 870 static struct nvkm_omthds 871 nv03_gr_sifc_omthds[] = { 872 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 873 { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, 874 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 875 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 876 { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, 877 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 878 {} 879 }; 880 881 static struct nvkm_omthds 882 nv04_gr_sifc_omthds[] = { 883 { 0x0184, 0x0184, nv01_gr_mthd_bind_chroma }, 884 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 885 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 886 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 887 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 888 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 889 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 890 {} 891 }; 892 893 static struct nvkm_omthds 894 nv03_gr_sifm_omthds[] = { 895 { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, 896 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 897 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 898 { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, 899 { 0x0304, 0x0304, nv04_gr_mthd_set_operation }, 900 {} 901 }; 902 903 static struct nvkm_omthds 904 nv04_gr_sifm_omthds[] = { 905 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 906 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 907 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 908 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 909 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 910 { 0x0304, 0x0304, nv04_gr_mthd_set_operation }, 911 {} 912 }; 913 914 static struct nvkm_omthds 915 nv04_gr_surf3d_omthds[] = { 916 { 0x02f8, 0x02f8, nv04_gr_mthd_surf3d_clip_h }, 917 { 0x02fc, 0x02fc, nv04_gr_mthd_surf3d_clip_v }, 918 {} 919 }; 920 921 static struct nvkm_omthds 922 nv03_gr_ttri_omthds[] = { 923 { 0x0188, 0x0188, nv01_gr_mthd_bind_clip }, 924 { 0x018c, 0x018c, nv04_gr_mthd_bind_surf_color }, 925 { 0x0190, 0x0190, nv04_gr_mthd_bind_surf_zeta }, 926 {} 927 }; 928 929 static struct nvkm_omthds 930 nv01_gr_prim_omthds[] = { 931 { 0x0184, 0x0184, nv01_gr_mthd_bind_clip }, 932 { 0x0188, 0x0188, nv01_gr_mthd_bind_patt }, 933 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 934 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 935 { 0x0194, 0x0194, nv04_gr_mthd_bind_surf_dst }, 936 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 937 {} 938 }; 939 940 static struct nvkm_omthds 941 nv04_gr_prim_omthds[] = { 942 { 0x0184, 0x0184, nv01_gr_mthd_bind_clip }, 943 { 0x0188, 0x0188, nv04_gr_mthd_bind_patt }, 944 { 0x018c, 0x018c, nv04_gr_mthd_bind_rop }, 945 { 0x0190, 0x0190, nv04_gr_mthd_bind_beta1 }, 946 { 0x0194, 0x0194, nv04_gr_mthd_bind_beta4 }, 947 { 0x0198, 0x0198, nv04_gr_mthd_bind_surf2d }, 948 { 0x02fc, 0x02fc, nv04_gr_mthd_set_operation }, 949 {} 950 }; 951 952 static int 953 nv04_gr_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 954 struct nvkm_oclass *oclass, void *data, u32 size, 955 struct nvkm_object **pobject) 956 { 957 struct nvkm_gpuobj *obj; 958 int ret; 959 960 ret = nvkm_gpuobj_create(parent, engine, oclass, 0, parent, 961 16, 16, 0, &obj); 962 *pobject = nv_object(obj); 963 if (ret) 964 return ret; 965 966 nv_wo32(obj, 0x00, nv_mclass(obj)); 967 #ifdef __BIG_ENDIAN 968 nv_mo32(obj, 0x00, 0x00080000, 0x00080000); 969 #endif 970 nv_wo32(obj, 0x04, 0x00000000); 971 nv_wo32(obj, 0x08, 0x00000000); 972 nv_wo32(obj, 0x0c, 0x00000000); 973 return 0; 974 } 975 976 struct nvkm_ofuncs 977 nv04_gr_ofuncs = { 978 .ctor = nv04_gr_object_ctor, 979 .dtor = _nvkm_gpuobj_dtor, 980 .init = _nvkm_gpuobj_init, 981 .fini = _nvkm_gpuobj_fini, 982 .rd32 = _nvkm_gpuobj_rd32, 983 .wr32 = _nvkm_gpuobj_wr32, 984 }; 985 986 static struct nvkm_oclass 987 nv04_gr_sclass[] = { 988 { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ 989 { 0x0017, &nv04_gr_ofuncs }, /* chroma */ 990 { 0x0018, &nv04_gr_ofuncs }, /* pattern (nv01) */ 991 { 0x0019, &nv04_gr_ofuncs }, /* clip */ 992 { 0x001c, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* line */ 993 { 0x001d, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* tri */ 994 { 0x001e, &nv04_gr_ofuncs, nv01_gr_prim_omthds }, /* rect */ 995 { 0x001f, &nv04_gr_ofuncs, nv01_gr_blit_omthds }, 996 { 0x0021, &nv04_gr_ofuncs, nv01_gr_ifc_omthds }, 997 { 0x0030, &nv04_gr_ofuncs }, /* null */ 998 { 0x0036, &nv04_gr_ofuncs, nv03_gr_sifc_omthds }, 999 { 0x0037, &nv04_gr_ofuncs, nv03_gr_sifm_omthds }, 1000 { 0x0038, &nv04_gr_ofuncs }, /* dvd subpicture */ 1001 { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ 1002 { 0x0042, &nv04_gr_ofuncs }, /* surf2d */ 1003 { 0x0043, &nv04_gr_ofuncs }, /* rop */ 1004 { 0x0044, &nv04_gr_ofuncs }, /* pattern */ 1005 { 0x0048, &nv04_gr_ofuncs, nv03_gr_ttri_omthds }, 1006 { 0x004a, &nv04_gr_ofuncs, nv04_gr_gdi_omthds }, 1007 { 0x004b, &nv04_gr_ofuncs, nv03_gr_gdi_omthds }, 1008 { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ 1009 { 0x0053, &nv04_gr_ofuncs, nv04_gr_surf3d_omthds }, 1010 { 0x0054, &nv04_gr_ofuncs }, /* ttri */ 1011 { 0x0055, &nv04_gr_ofuncs }, /* mtri */ 1012 { 0x0057, &nv04_gr_ofuncs }, /* chroma */ 1013 { 0x0058, &nv04_gr_ofuncs }, /* surf_dst */ 1014 { 0x0059, &nv04_gr_ofuncs }, /* surf_src */ 1015 { 0x005a, &nv04_gr_ofuncs }, /* surf_color */ 1016 { 0x005b, &nv04_gr_ofuncs }, /* surf_zeta */ 1017 { 0x005c, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* line */ 1018 { 0x005d, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* tri */ 1019 { 0x005e, &nv04_gr_ofuncs, nv04_gr_prim_omthds }, /* rect */ 1020 { 0x005f, &nv04_gr_ofuncs, nv04_gr_blit_omthds }, 1021 { 0x0060, &nv04_gr_ofuncs, nv04_gr_iifc_omthds }, 1022 { 0x0061, &nv04_gr_ofuncs, nv04_gr_ifc_omthds }, 1023 { 0x0064, &nv04_gr_ofuncs }, /* iifc (nv05) */ 1024 { 0x0065, &nv04_gr_ofuncs }, /* ifc (nv05) */ 1025 { 0x0066, &nv04_gr_ofuncs }, /* sifc (nv05) */ 1026 { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ 1027 { 0x0076, &nv04_gr_ofuncs, nv04_gr_sifc_omthds }, 1028 { 0x0077, &nv04_gr_ofuncs, nv04_gr_sifm_omthds }, 1029 {}, 1030 }; 1031 1032 /******************************************************************************* 1033 * PGRAPH context 1034 ******************************************************************************/ 1035 1036 static struct nv04_gr_chan * 1037 nv04_gr_channel(struct nv04_gr *gr) 1038 { 1039 struct nvkm_device *device = gr->base.engine.subdev.device; 1040 struct nv04_gr_chan *chan = NULL; 1041 if (nvkm_rd32(device, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) { 1042 int chid = nvkm_rd32(device, NV04_PGRAPH_CTX_USER) >> 24; 1043 if (chid < ARRAY_SIZE(gr->chan)) 1044 chan = gr->chan[chid]; 1045 } 1046 return chan; 1047 } 1048 1049 static int 1050 nv04_gr_load_context(struct nv04_gr_chan *chan, int chid) 1051 { 1052 struct nv04_gr *gr = nv04_gr(chan); 1053 struct nvkm_device *device = gr->base.engine.subdev.device; 1054 int i; 1055 1056 for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) 1057 nvkm_wr32(device, nv04_gr_ctx_regs[i], chan->nv04[i]); 1058 1059 nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10010100); 1060 nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24); 1061 nvkm_mask(device, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000); 1062 return 0; 1063 } 1064 1065 static int 1066 nv04_gr_unload_context(struct nv04_gr_chan *chan) 1067 { 1068 struct nv04_gr *gr = nv04_gr(chan); 1069 struct nvkm_device *device = gr->base.engine.subdev.device; 1070 int i; 1071 1072 for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) 1073 chan->nv04[i] = nvkm_rd32(device, nv04_gr_ctx_regs[i]); 1074 1075 nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10000000); 1076 nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); 1077 return 0; 1078 } 1079 1080 static void 1081 nv04_gr_context_switch(struct nv04_gr *gr) 1082 { 1083 struct nvkm_device *device = gr->base.engine.subdev.device; 1084 struct nv04_gr_chan *prev = NULL; 1085 struct nv04_gr_chan *next = NULL; 1086 unsigned long flags; 1087 int chid; 1088 1089 spin_lock_irqsave(&gr->lock, flags); 1090 nv04_gr_idle(gr); 1091 1092 /* If previous context is valid, we need to save it */ 1093 prev = nv04_gr_channel(gr); 1094 if (prev) 1095 nv04_gr_unload_context(prev); 1096 1097 /* load context for next channel */ 1098 chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f; 1099 next = gr->chan[chid]; 1100 if (next) 1101 nv04_gr_load_context(next, chid); 1102 1103 spin_unlock_irqrestore(&gr->lock, flags); 1104 } 1105 1106 static u32 *ctx_reg(struct nv04_gr_chan *chan, u32 reg) 1107 { 1108 int i; 1109 1110 for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) { 1111 if (nv04_gr_ctx_regs[i] == reg) 1112 return &chan->nv04[i]; 1113 } 1114 1115 return NULL; 1116 } 1117 1118 static int 1119 nv04_gr_context_ctor(struct nvkm_object *parent, 1120 struct nvkm_object *engine, 1121 struct nvkm_oclass *oclass, void *data, u32 size, 1122 struct nvkm_object **pobject) 1123 { 1124 struct nvkm_fifo_chan *fifo = (void *)parent; 1125 struct nv04_gr *gr = (void *)engine; 1126 struct nv04_gr_chan *chan; 1127 unsigned long flags; 1128 int ret; 1129 1130 ret = nvkm_object_create(parent, engine, oclass, 0, &chan); 1131 *pobject = nv_object(chan); 1132 if (ret) 1133 return ret; 1134 1135 spin_lock_irqsave(&gr->lock, flags); 1136 if (gr->chan[fifo->chid]) { 1137 *pobject = nv_object(gr->chan[fifo->chid]); 1138 atomic_inc(&(*pobject)->refcount); 1139 spin_unlock_irqrestore(&gr->lock, flags); 1140 nvkm_object_destroy(&chan->base); 1141 return 1; 1142 } 1143 1144 *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; 1145 1146 gr->chan[fifo->chid] = chan; 1147 chan->chid = fifo->chid; 1148 spin_unlock_irqrestore(&gr->lock, flags); 1149 return 0; 1150 } 1151 1152 static void 1153 nv04_gr_context_dtor(struct nvkm_object *object) 1154 { 1155 struct nv04_gr *gr = (void *)object->engine; 1156 struct nv04_gr_chan *chan = (void *)object; 1157 unsigned long flags; 1158 1159 spin_lock_irqsave(&gr->lock, flags); 1160 gr->chan[chan->chid] = NULL; 1161 spin_unlock_irqrestore(&gr->lock, flags); 1162 1163 nvkm_object_destroy(&chan->base); 1164 } 1165 1166 static int 1167 nv04_gr_context_fini(struct nvkm_object *object, bool suspend) 1168 { 1169 struct nv04_gr *gr = (void *)object->engine; 1170 struct nv04_gr_chan *chan = (void *)object; 1171 struct nvkm_device *device = gr->base.engine.subdev.device; 1172 unsigned long flags; 1173 1174 spin_lock_irqsave(&gr->lock, flags); 1175 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); 1176 if (nv04_gr_channel(gr) == chan) 1177 nv04_gr_unload_context(chan); 1178 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); 1179 spin_unlock_irqrestore(&gr->lock, flags); 1180 1181 return nvkm_object_fini(&chan->base, suspend); 1182 } 1183 1184 static struct nvkm_oclass 1185 nv04_gr_cclass = { 1186 .handle = NV_ENGCTX(GR, 0x04), 1187 .ofuncs = &(struct nvkm_ofuncs) { 1188 .ctor = nv04_gr_context_ctor, 1189 .dtor = nv04_gr_context_dtor, 1190 .init = nvkm_object_init, 1191 .fini = nv04_gr_context_fini, 1192 }, 1193 }; 1194 1195 /******************************************************************************* 1196 * PGRAPH engine/subdev functions 1197 ******************************************************************************/ 1198 1199 bool 1200 nv04_gr_idle(void *obj) 1201 { 1202 struct nvkm_gr *gr = nvkm_gr(obj); 1203 struct nvkm_device *device = gr->engine.subdev.device; 1204 u32 mask = 0xffffffff; 1205 1206 if (nv_device(obj)->card_type == NV_40) 1207 mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; 1208 1209 if (nvkm_msec(device, 2000, 1210 if (!(nvkm_rd32(device, NV04_PGRAPH_STATUS) & mask)) 1211 break; 1212 ) < 0) { 1213 nv_error(gr, "idle timed out with status 0x%08x\n", 1214 nvkm_rd32(device, NV04_PGRAPH_STATUS)); 1215 return false; 1216 } 1217 1218 return true; 1219 } 1220 1221 static const struct nvkm_bitfield 1222 nv04_gr_intr_name[] = { 1223 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, 1224 {} 1225 }; 1226 1227 static const struct nvkm_bitfield 1228 nv04_gr_nstatus[] = { 1229 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, 1230 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, 1231 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, 1232 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, 1233 {} 1234 }; 1235 1236 const struct nvkm_bitfield 1237 nv04_gr_nsource[] = { 1238 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, 1239 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, 1240 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, 1241 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, 1242 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, 1243 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, 1244 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, 1245 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, 1246 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, 1247 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, 1248 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, 1249 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, 1250 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, 1251 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, 1252 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, 1253 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, 1254 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, 1255 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, 1256 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, 1257 {} 1258 }; 1259 1260 static void 1261 nv04_gr_intr(struct nvkm_subdev *subdev) 1262 { 1263 struct nv04_gr *gr = (void *)subdev; 1264 struct nv04_gr_chan *chan = NULL; 1265 struct nvkm_namedb *namedb = NULL; 1266 struct nvkm_handle *handle = NULL; 1267 struct nvkm_device *device = gr->base.engine.subdev.device; 1268 u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); 1269 u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); 1270 u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); 1271 u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); 1272 u32 chid = (addr & 0x0f000000) >> 24; 1273 u32 subc = (addr & 0x0000e000) >> 13; 1274 u32 mthd = (addr & 0x00001ffc); 1275 u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); 1276 u32 class = nvkm_rd32(device, 0x400180 + subc * 4) & 0xff; 1277 u32 inst = (nvkm_rd32(device, 0x40016c) & 0xffff) << 4; 1278 u32 show = stat; 1279 unsigned long flags; 1280 1281 spin_lock_irqsave(&gr->lock, flags); 1282 chan = gr->chan[chid]; 1283 if (chan) 1284 namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); 1285 spin_unlock_irqrestore(&gr->lock, flags); 1286 1287 if (stat & NV_PGRAPH_INTR_NOTIFY) { 1288 if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { 1289 handle = nvkm_namedb_get_vinst(namedb, inst); 1290 if (handle && !nv_call(handle->object, mthd, data)) 1291 show &= ~NV_PGRAPH_INTR_NOTIFY; 1292 } 1293 } 1294 1295 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { 1296 nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); 1297 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; 1298 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; 1299 nv04_gr_context_switch(gr); 1300 } 1301 1302 nvkm_wr32(device, NV03_PGRAPH_INTR, stat); 1303 nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); 1304 1305 if (show) { 1306 nv_error(gr, "%s", ""); 1307 nvkm_bitfield_print(nv04_gr_intr_name, show); 1308 pr_cont(" nsource:"); 1309 nvkm_bitfield_print(nv04_gr_nsource, nsource); 1310 pr_cont(" nstatus:"); 1311 nvkm_bitfield_print(nv04_gr_nstatus, nstatus); 1312 pr_cont("\n"); 1313 nv_error(gr, 1314 "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 1315 chid, nvkm_client_name(chan), subc, class, mthd, 1316 data); 1317 } 1318 1319 nvkm_namedb_put(handle); 1320 } 1321 1322 static int 1323 nv04_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 1324 struct nvkm_oclass *oclass, void *data, u32 size, 1325 struct nvkm_object **pobject) 1326 { 1327 struct nv04_gr *gr; 1328 int ret; 1329 1330 ret = nvkm_gr_create(parent, engine, oclass, true, &gr); 1331 *pobject = nv_object(gr); 1332 if (ret) 1333 return ret; 1334 1335 nv_subdev(gr)->unit = 0x00001000; 1336 nv_subdev(gr)->intr = nv04_gr_intr; 1337 nv_engine(gr)->cclass = &nv04_gr_cclass; 1338 nv_engine(gr)->sclass = nv04_gr_sclass; 1339 spin_lock_init(&gr->lock); 1340 return 0; 1341 } 1342 1343 static int 1344 nv04_gr_init(struct nvkm_object *object) 1345 { 1346 struct nvkm_engine *engine = nv_engine(object); 1347 struct nv04_gr *gr = (void *)engine; 1348 struct nvkm_device *device = gr->base.engine.subdev.device; 1349 int ret; 1350 1351 ret = nvkm_gr_init(&gr->base); 1352 if (ret) 1353 return ret; 1354 1355 /* Enable PGRAPH interrupts */ 1356 nvkm_wr32(device, NV03_PGRAPH_INTR, 0xFFFFFFFF); 1357 nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 1358 1359 nvkm_wr32(device, NV04_PGRAPH_VALID1, 0); 1360 nvkm_wr32(device, NV04_PGRAPH_VALID2, 0); 1361 /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x000001FF); 1362 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ 1363 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x1231c000); 1364 /*1231C000 blob, 001 haiku*/ 1365 /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ 1366 nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x72111100); 1367 /*0x72111100 blob , 01 haiku*/ 1368 /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ 1369 nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f071); 1370 /*haiku same*/ 1371 1372 /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ 1373 nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); 1374 /*haiku and blob 10d4*/ 1375 1376 nvkm_wr32(device, NV04_PGRAPH_STATE , 0xFFFFFFFF); 1377 nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL , 0x10000100); 1378 nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); 1379 1380 /* These don't belong here, they're part of a per-channel context */ 1381 nvkm_wr32(device, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); 1382 nvkm_wr32(device, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); 1383 return 0; 1384 } 1385 1386 struct nvkm_oclass 1387 nv04_gr_oclass = { 1388 .handle = NV_ENGINE(GR, 0x04), 1389 .ofuncs = &(struct nvkm_ofuncs) { 1390 .ctor = nv04_gr_ctor, 1391 .dtor = _nvkm_gr_dtor, 1392 .init = nv04_gr_init, 1393 .fini = _nvkm_gr_fini, 1394 }, 1395 }; 1396