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