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