1 /* 2 * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr> 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 <engine/fifo.h> 29 #include <subdev/fb.h> 30 31 struct pipe_state { 32 u32 pipe_0x0000[0x040/4]; 33 u32 pipe_0x0040[0x010/4]; 34 u32 pipe_0x0200[0x0c0/4]; 35 u32 pipe_0x4400[0x080/4]; 36 u32 pipe_0x6400[0x3b0/4]; 37 u32 pipe_0x6800[0x2f0/4]; 38 u32 pipe_0x6c00[0x030/4]; 39 u32 pipe_0x7000[0x130/4]; 40 u32 pipe_0x7400[0x0c0/4]; 41 u32 pipe_0x7800[0x0c0/4]; 42 }; 43 44 static int nv10_gr_ctx_regs[] = { 45 NV10_PGRAPH_CTX_SWITCH(0), 46 NV10_PGRAPH_CTX_SWITCH(1), 47 NV10_PGRAPH_CTX_SWITCH(2), 48 NV10_PGRAPH_CTX_SWITCH(3), 49 NV10_PGRAPH_CTX_SWITCH(4), 50 NV10_PGRAPH_CTX_CACHE(0, 0), 51 NV10_PGRAPH_CTX_CACHE(0, 1), 52 NV10_PGRAPH_CTX_CACHE(0, 2), 53 NV10_PGRAPH_CTX_CACHE(0, 3), 54 NV10_PGRAPH_CTX_CACHE(0, 4), 55 NV10_PGRAPH_CTX_CACHE(1, 0), 56 NV10_PGRAPH_CTX_CACHE(1, 1), 57 NV10_PGRAPH_CTX_CACHE(1, 2), 58 NV10_PGRAPH_CTX_CACHE(1, 3), 59 NV10_PGRAPH_CTX_CACHE(1, 4), 60 NV10_PGRAPH_CTX_CACHE(2, 0), 61 NV10_PGRAPH_CTX_CACHE(2, 1), 62 NV10_PGRAPH_CTX_CACHE(2, 2), 63 NV10_PGRAPH_CTX_CACHE(2, 3), 64 NV10_PGRAPH_CTX_CACHE(2, 4), 65 NV10_PGRAPH_CTX_CACHE(3, 0), 66 NV10_PGRAPH_CTX_CACHE(3, 1), 67 NV10_PGRAPH_CTX_CACHE(3, 2), 68 NV10_PGRAPH_CTX_CACHE(3, 3), 69 NV10_PGRAPH_CTX_CACHE(3, 4), 70 NV10_PGRAPH_CTX_CACHE(4, 0), 71 NV10_PGRAPH_CTX_CACHE(4, 1), 72 NV10_PGRAPH_CTX_CACHE(4, 2), 73 NV10_PGRAPH_CTX_CACHE(4, 3), 74 NV10_PGRAPH_CTX_CACHE(4, 4), 75 NV10_PGRAPH_CTX_CACHE(5, 0), 76 NV10_PGRAPH_CTX_CACHE(5, 1), 77 NV10_PGRAPH_CTX_CACHE(5, 2), 78 NV10_PGRAPH_CTX_CACHE(5, 3), 79 NV10_PGRAPH_CTX_CACHE(5, 4), 80 NV10_PGRAPH_CTX_CACHE(6, 0), 81 NV10_PGRAPH_CTX_CACHE(6, 1), 82 NV10_PGRAPH_CTX_CACHE(6, 2), 83 NV10_PGRAPH_CTX_CACHE(6, 3), 84 NV10_PGRAPH_CTX_CACHE(6, 4), 85 NV10_PGRAPH_CTX_CACHE(7, 0), 86 NV10_PGRAPH_CTX_CACHE(7, 1), 87 NV10_PGRAPH_CTX_CACHE(7, 2), 88 NV10_PGRAPH_CTX_CACHE(7, 3), 89 NV10_PGRAPH_CTX_CACHE(7, 4), 90 NV10_PGRAPH_CTX_USER, 91 NV04_PGRAPH_DMA_START_0, 92 NV04_PGRAPH_DMA_START_1, 93 NV04_PGRAPH_DMA_LENGTH, 94 NV04_PGRAPH_DMA_MISC, 95 NV10_PGRAPH_DMA_PITCH, 96 NV04_PGRAPH_BOFFSET0, 97 NV04_PGRAPH_BBASE0, 98 NV04_PGRAPH_BLIMIT0, 99 NV04_PGRAPH_BOFFSET1, 100 NV04_PGRAPH_BBASE1, 101 NV04_PGRAPH_BLIMIT1, 102 NV04_PGRAPH_BOFFSET2, 103 NV04_PGRAPH_BBASE2, 104 NV04_PGRAPH_BLIMIT2, 105 NV04_PGRAPH_BOFFSET3, 106 NV04_PGRAPH_BBASE3, 107 NV04_PGRAPH_BLIMIT3, 108 NV04_PGRAPH_BOFFSET4, 109 NV04_PGRAPH_BBASE4, 110 NV04_PGRAPH_BLIMIT4, 111 NV04_PGRAPH_BOFFSET5, 112 NV04_PGRAPH_BBASE5, 113 NV04_PGRAPH_BLIMIT5, 114 NV04_PGRAPH_BPITCH0, 115 NV04_PGRAPH_BPITCH1, 116 NV04_PGRAPH_BPITCH2, 117 NV04_PGRAPH_BPITCH3, 118 NV04_PGRAPH_BPITCH4, 119 NV10_PGRAPH_SURFACE, 120 NV10_PGRAPH_STATE, 121 NV04_PGRAPH_BSWIZZLE2, 122 NV04_PGRAPH_BSWIZZLE5, 123 NV04_PGRAPH_BPIXEL, 124 NV10_PGRAPH_NOTIFY, 125 NV04_PGRAPH_PATT_COLOR0, 126 NV04_PGRAPH_PATT_COLOR1, 127 NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */ 128 0x00400904, 129 0x00400908, 130 0x0040090c, 131 0x00400910, 132 0x00400914, 133 0x00400918, 134 0x0040091c, 135 0x00400920, 136 0x00400924, 137 0x00400928, 138 0x0040092c, 139 0x00400930, 140 0x00400934, 141 0x00400938, 142 0x0040093c, 143 0x00400940, 144 0x00400944, 145 0x00400948, 146 0x0040094c, 147 0x00400950, 148 0x00400954, 149 0x00400958, 150 0x0040095c, 151 0x00400960, 152 0x00400964, 153 0x00400968, 154 0x0040096c, 155 0x00400970, 156 0x00400974, 157 0x00400978, 158 0x0040097c, 159 0x00400980, 160 0x00400984, 161 0x00400988, 162 0x0040098c, 163 0x00400990, 164 0x00400994, 165 0x00400998, 166 0x0040099c, 167 0x004009a0, 168 0x004009a4, 169 0x004009a8, 170 0x004009ac, 171 0x004009b0, 172 0x004009b4, 173 0x004009b8, 174 0x004009bc, 175 0x004009c0, 176 0x004009c4, 177 0x004009c8, 178 0x004009cc, 179 0x004009d0, 180 0x004009d4, 181 0x004009d8, 182 0x004009dc, 183 0x004009e0, 184 0x004009e4, 185 0x004009e8, 186 0x004009ec, 187 0x004009f0, 188 0x004009f4, 189 0x004009f8, 190 0x004009fc, 191 NV04_PGRAPH_PATTERN, /* 2 values from 0x400808 to 0x40080c */ 192 0x0040080c, 193 NV04_PGRAPH_PATTERN_SHAPE, 194 NV03_PGRAPH_MONO_COLOR0, 195 NV04_PGRAPH_ROP3, 196 NV04_PGRAPH_CHROMA, 197 NV04_PGRAPH_BETA_AND, 198 NV04_PGRAPH_BETA_PREMULT, 199 0x00400e70, 200 0x00400e74, 201 0x00400e78, 202 0x00400e7c, 203 0x00400e80, 204 0x00400e84, 205 0x00400e88, 206 0x00400e8c, 207 0x00400ea0, 208 0x00400ea4, 209 0x00400ea8, 210 0x00400e90, 211 0x00400e94, 212 0x00400e98, 213 0x00400e9c, 214 NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */ 215 NV10_PGRAPH_WINDOWCLIP_VERTICAL, /* 8 values from 0x400f20-0x400f3c */ 216 0x00400f04, 217 0x00400f24, 218 0x00400f08, 219 0x00400f28, 220 0x00400f0c, 221 0x00400f2c, 222 0x00400f10, 223 0x00400f30, 224 0x00400f14, 225 0x00400f34, 226 0x00400f18, 227 0x00400f38, 228 0x00400f1c, 229 0x00400f3c, 230 NV10_PGRAPH_XFMODE0, 231 NV10_PGRAPH_XFMODE1, 232 NV10_PGRAPH_GLOBALSTATE0, 233 NV10_PGRAPH_GLOBALSTATE1, 234 NV04_PGRAPH_STORED_FMT, 235 NV04_PGRAPH_SOURCE_COLOR, 236 NV03_PGRAPH_ABS_X_RAM, /* 32 values from 0x400400 to 0x40047c */ 237 NV03_PGRAPH_ABS_Y_RAM, /* 32 values from 0x400480 to 0x4004fc */ 238 0x00400404, 239 0x00400484, 240 0x00400408, 241 0x00400488, 242 0x0040040c, 243 0x0040048c, 244 0x00400410, 245 0x00400490, 246 0x00400414, 247 0x00400494, 248 0x00400418, 249 0x00400498, 250 0x0040041c, 251 0x0040049c, 252 0x00400420, 253 0x004004a0, 254 0x00400424, 255 0x004004a4, 256 0x00400428, 257 0x004004a8, 258 0x0040042c, 259 0x004004ac, 260 0x00400430, 261 0x004004b0, 262 0x00400434, 263 0x004004b4, 264 0x00400438, 265 0x004004b8, 266 0x0040043c, 267 0x004004bc, 268 0x00400440, 269 0x004004c0, 270 0x00400444, 271 0x004004c4, 272 0x00400448, 273 0x004004c8, 274 0x0040044c, 275 0x004004cc, 276 0x00400450, 277 0x004004d0, 278 0x00400454, 279 0x004004d4, 280 0x00400458, 281 0x004004d8, 282 0x0040045c, 283 0x004004dc, 284 0x00400460, 285 0x004004e0, 286 0x00400464, 287 0x004004e4, 288 0x00400468, 289 0x004004e8, 290 0x0040046c, 291 0x004004ec, 292 0x00400470, 293 0x004004f0, 294 0x00400474, 295 0x004004f4, 296 0x00400478, 297 0x004004f8, 298 0x0040047c, 299 0x004004fc, 300 NV03_PGRAPH_ABS_UCLIP_XMIN, 301 NV03_PGRAPH_ABS_UCLIP_XMAX, 302 NV03_PGRAPH_ABS_UCLIP_YMIN, 303 NV03_PGRAPH_ABS_UCLIP_YMAX, 304 0x00400550, 305 0x00400558, 306 0x00400554, 307 0x0040055c, 308 NV03_PGRAPH_ABS_UCLIPA_XMIN, 309 NV03_PGRAPH_ABS_UCLIPA_XMAX, 310 NV03_PGRAPH_ABS_UCLIPA_YMIN, 311 NV03_PGRAPH_ABS_UCLIPA_YMAX, 312 NV03_PGRAPH_ABS_ICLIP_XMAX, 313 NV03_PGRAPH_ABS_ICLIP_YMAX, 314 NV03_PGRAPH_XY_LOGIC_MISC0, 315 NV03_PGRAPH_XY_LOGIC_MISC1, 316 NV03_PGRAPH_XY_LOGIC_MISC2, 317 NV03_PGRAPH_XY_LOGIC_MISC3, 318 NV03_PGRAPH_CLIPX_0, 319 NV03_PGRAPH_CLIPX_1, 320 NV03_PGRAPH_CLIPY_0, 321 NV03_PGRAPH_CLIPY_1, 322 NV10_PGRAPH_COMBINER0_IN_ALPHA, 323 NV10_PGRAPH_COMBINER1_IN_ALPHA, 324 NV10_PGRAPH_COMBINER0_IN_RGB, 325 NV10_PGRAPH_COMBINER1_IN_RGB, 326 NV10_PGRAPH_COMBINER_COLOR0, 327 NV10_PGRAPH_COMBINER_COLOR1, 328 NV10_PGRAPH_COMBINER0_OUT_ALPHA, 329 NV10_PGRAPH_COMBINER1_OUT_ALPHA, 330 NV10_PGRAPH_COMBINER0_OUT_RGB, 331 NV10_PGRAPH_COMBINER1_OUT_RGB, 332 NV10_PGRAPH_COMBINER_FINAL0, 333 NV10_PGRAPH_COMBINER_FINAL1, 334 0x00400e00, 335 0x00400e04, 336 0x00400e08, 337 0x00400e0c, 338 0x00400e10, 339 0x00400e14, 340 0x00400e18, 341 0x00400e1c, 342 0x00400e20, 343 0x00400e24, 344 0x00400e28, 345 0x00400e2c, 346 0x00400e30, 347 0x00400e34, 348 0x00400e38, 349 0x00400e3c, 350 NV04_PGRAPH_PASSTHRU_0, 351 NV04_PGRAPH_PASSTHRU_1, 352 NV04_PGRAPH_PASSTHRU_2, 353 NV10_PGRAPH_DIMX_TEXTURE, 354 NV10_PGRAPH_WDIMX_TEXTURE, 355 NV10_PGRAPH_DVD_COLORFMT, 356 NV10_PGRAPH_SCALED_FORMAT, 357 NV04_PGRAPH_MISC24_0, 358 NV04_PGRAPH_MISC24_1, 359 NV04_PGRAPH_MISC24_2, 360 NV03_PGRAPH_X_MISC, 361 NV03_PGRAPH_Y_MISC, 362 NV04_PGRAPH_VALID1, 363 NV04_PGRAPH_VALID2, 364 }; 365 366 static int nv17_gr_ctx_regs[] = { 367 NV10_PGRAPH_DEBUG_4, 368 0x004006b0, 369 0x00400eac, 370 0x00400eb0, 371 0x00400eb4, 372 0x00400eb8, 373 0x00400ebc, 374 0x00400ec0, 375 0x00400ec4, 376 0x00400ec8, 377 0x00400ecc, 378 0x00400ed0, 379 0x00400ed4, 380 0x00400ed8, 381 0x00400edc, 382 0x00400ee0, 383 0x00400a00, 384 0x00400a04, 385 }; 386 387 struct nv10_gr { 388 struct nvkm_gr base; 389 struct nv10_gr_chan *chan[32]; 390 spinlock_t lock; 391 }; 392 393 struct nv10_gr_chan { 394 struct nvkm_object base; 395 int chid; 396 int nv10[ARRAY_SIZE(nv10_gr_ctx_regs)]; 397 int nv17[ARRAY_SIZE(nv17_gr_ctx_regs)]; 398 struct pipe_state pipe_state; 399 u32 lma_window[4]; 400 }; 401 402 403 static inline struct nv10_gr * 404 nv10_gr(struct nv10_gr_chan *chan) 405 { 406 return (void *)nv_object(chan)->engine; 407 } 408 409 /******************************************************************************* 410 * Graphics object classes 411 ******************************************************************************/ 412 413 #define PIPE_SAVE(gr, state, addr) \ 414 do { \ 415 int __i; \ 416 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, addr); \ 417 for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ 418 state[__i] = nvkm_rd32(device, NV10_PGRAPH_PIPE_DATA); \ 419 } while (0) 420 421 #define PIPE_RESTORE(gr, state, addr) \ 422 do { \ 423 int __i; \ 424 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, addr); \ 425 for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ 426 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, state[__i]); \ 427 } while (0) 428 429 static struct nvkm_oclass 430 nv10_gr_sclass[] = { 431 { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ 432 { 0x0019, &nv04_gr_ofuncs }, /* clip */ 433 { 0x0030, &nv04_gr_ofuncs }, /* null */ 434 { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ 435 { 0x0043, &nv04_gr_ofuncs }, /* rop */ 436 { 0x0044, &nv04_gr_ofuncs }, /* pattern */ 437 { 0x004a, &nv04_gr_ofuncs }, /* gdi */ 438 { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ 439 { 0x005f, &nv04_gr_ofuncs }, /* blit */ 440 { 0x0062, &nv04_gr_ofuncs }, /* surf2d */ 441 { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ 442 { 0x0089, &nv04_gr_ofuncs }, /* sifm */ 443 { 0x008a, &nv04_gr_ofuncs }, /* ifc */ 444 { 0x009f, &nv04_gr_ofuncs }, /* blit */ 445 { 0x0093, &nv04_gr_ofuncs }, /* surf3d */ 446 { 0x0094, &nv04_gr_ofuncs }, /* ttri */ 447 { 0x0095, &nv04_gr_ofuncs }, /* mtri */ 448 { 0x0056, &nv04_gr_ofuncs }, /* celcius */ 449 {}, 450 }; 451 452 static struct nvkm_oclass 453 nv15_gr_sclass[] = { 454 { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ 455 { 0x0019, &nv04_gr_ofuncs }, /* clip */ 456 { 0x0030, &nv04_gr_ofuncs }, /* null */ 457 { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ 458 { 0x0043, &nv04_gr_ofuncs }, /* rop */ 459 { 0x0044, &nv04_gr_ofuncs }, /* pattern */ 460 { 0x004a, &nv04_gr_ofuncs }, /* gdi */ 461 { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ 462 { 0x005f, &nv04_gr_ofuncs }, /* blit */ 463 { 0x0062, &nv04_gr_ofuncs }, /* surf2d */ 464 { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ 465 { 0x0089, &nv04_gr_ofuncs }, /* sifm */ 466 { 0x008a, &nv04_gr_ofuncs }, /* ifc */ 467 { 0x009f, &nv04_gr_ofuncs }, /* blit */ 468 { 0x0093, &nv04_gr_ofuncs }, /* surf3d */ 469 { 0x0094, &nv04_gr_ofuncs }, /* ttri */ 470 { 0x0095, &nv04_gr_ofuncs }, /* mtri */ 471 { 0x0096, &nv04_gr_ofuncs }, /* celcius */ 472 {}, 473 }; 474 475 static void 476 nv17_gr_mthd_lma_window(struct nv10_gr_chan *chan, u32 mthd, u32 data) 477 { 478 struct nvkm_device *device = chan->base.engine->subdev.device; 479 struct nvkm_gr *gr = nvkm_gr(chan); 480 struct pipe_state *pipe = &chan->pipe_state; 481 u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; 482 u32 xfmode0, xfmode1; 483 int i; 484 485 chan->lma_window[(mthd - 0x1638) / 4] = data; 486 487 if (mthd != 0x1644) 488 return; 489 490 nv04_gr_idle(gr); 491 492 PIPE_SAVE(device, pipe_0x0040, 0x0040); 493 PIPE_SAVE(device, pipe->pipe_0x0200, 0x0200); 494 495 PIPE_RESTORE(device, chan->lma_window, 0x6790); 496 497 nv04_gr_idle(gr); 498 499 xfmode0 = nvkm_rd32(device, NV10_PGRAPH_XFMODE0); 500 xfmode1 = nvkm_rd32(device, NV10_PGRAPH_XFMODE1); 501 502 PIPE_SAVE(device, pipe->pipe_0x4400, 0x4400); 503 PIPE_SAVE(device, pipe_0x64c0, 0x64c0); 504 PIPE_SAVE(device, pipe_0x6ab0, 0x6ab0); 505 PIPE_SAVE(device, pipe_0x6a80, 0x6a80); 506 507 nv04_gr_idle(gr); 508 509 nvkm_wr32(device, NV10_PGRAPH_XFMODE0, 0x10000000); 510 nvkm_wr32(device, NV10_PGRAPH_XFMODE1, 0x00000000); 511 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); 512 for (i = 0; i < 4; i++) 513 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); 514 for (i = 0; i < 4; i++) 515 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); 516 517 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); 518 for (i = 0; i < 3; i++) 519 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); 520 521 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); 522 for (i = 0; i < 3; i++) 523 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); 524 525 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); 526 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000008); 527 528 PIPE_RESTORE(device, pipe->pipe_0x0200, 0x0200); 529 530 nv04_gr_idle(gr); 531 532 PIPE_RESTORE(device, pipe_0x0040, 0x0040); 533 534 nvkm_wr32(device, NV10_PGRAPH_XFMODE0, xfmode0); 535 nvkm_wr32(device, NV10_PGRAPH_XFMODE1, xfmode1); 536 537 PIPE_RESTORE(device, pipe_0x64c0, 0x64c0); 538 PIPE_RESTORE(device, pipe_0x6ab0, 0x6ab0); 539 PIPE_RESTORE(device, pipe_0x6a80, 0x6a80); 540 PIPE_RESTORE(device, pipe->pipe_0x4400, 0x4400); 541 542 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); 543 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); 544 545 nv04_gr_idle(gr); 546 } 547 548 static void 549 nv17_gr_mthd_lma_enable(struct nv10_gr_chan *chan, u32 mthd, u32 data) 550 { 551 struct nvkm_device *device = chan->base.engine->subdev.device; 552 struct nvkm_gr *gr = nvkm_gr(chan); 553 554 nv04_gr_idle(gr); 555 556 nvkm_mask(device, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100); 557 nvkm_mask(device, 0x4006b0, 0x08000000, 0x08000000); 558 } 559 560 static bool 561 nv17_gr_mthd_celcius(struct nv10_gr_chan *chan, u32 mthd, u32 data) 562 { 563 void (*func)(struct nv10_gr_chan *, u32, u32); 564 switch (mthd) { 565 case 0x1638 ... 0x1644: 566 func = nv17_gr_mthd_lma_window; break; 567 case 0x1658: func = nv17_gr_mthd_lma_enable; break; 568 default: 569 return false; 570 } 571 func(chan, mthd, data); 572 return true; 573 } 574 575 static bool 576 nv10_gr_mthd(struct nv10_gr_chan *chan, u8 class, u32 mthd, u32 data) 577 { 578 bool (*func)(struct nv10_gr_chan *, u32, u32); 579 switch (class) { 580 case 0x99: func = nv17_gr_mthd_celcius; break; 581 default: 582 return false; 583 } 584 return func(chan, mthd, data); 585 } 586 587 static struct nvkm_oclass 588 nv17_gr_sclass[] = { 589 { 0x0012, &nv04_gr_ofuncs }, /* beta1 */ 590 { 0x0019, &nv04_gr_ofuncs }, /* clip */ 591 { 0x0030, &nv04_gr_ofuncs }, /* null */ 592 { 0x0039, &nv04_gr_ofuncs }, /* m2mf */ 593 { 0x0043, &nv04_gr_ofuncs }, /* rop */ 594 { 0x0044, &nv04_gr_ofuncs }, /* pattern */ 595 { 0x004a, &nv04_gr_ofuncs }, /* gdi */ 596 { 0x0052, &nv04_gr_ofuncs }, /* swzsurf */ 597 { 0x005f, &nv04_gr_ofuncs }, /* blit */ 598 { 0x0062, &nv04_gr_ofuncs }, /* surf2d */ 599 { 0x0072, &nv04_gr_ofuncs }, /* beta4 */ 600 { 0x0089, &nv04_gr_ofuncs }, /* sifm */ 601 { 0x008a, &nv04_gr_ofuncs }, /* ifc */ 602 { 0x009f, &nv04_gr_ofuncs }, /* blit */ 603 { 0x0093, &nv04_gr_ofuncs }, /* surf3d */ 604 { 0x0094, &nv04_gr_ofuncs }, /* ttri */ 605 { 0x0095, &nv04_gr_ofuncs }, /* mtri */ 606 { 0x0099, &nv04_gr_ofuncs }, 607 {}, 608 }; 609 610 /******************************************************************************* 611 * PGRAPH context 612 ******************************************************************************/ 613 614 static struct nv10_gr_chan * 615 nv10_gr_channel(struct nv10_gr *gr) 616 { 617 struct nvkm_device *device = gr->base.engine.subdev.device; 618 struct nv10_gr_chan *chan = NULL; 619 if (nvkm_rd32(device, 0x400144) & 0x00010000) { 620 int chid = nvkm_rd32(device, 0x400148) >> 24; 621 if (chid < ARRAY_SIZE(gr->chan)) 622 chan = gr->chan[chid]; 623 } 624 return chan; 625 } 626 627 static void 628 nv10_gr_save_pipe(struct nv10_gr_chan *chan) 629 { 630 struct nv10_gr *gr = nv10_gr(chan); 631 struct pipe_state *pipe = &chan->pipe_state; 632 struct nvkm_device *device = gr->base.engine.subdev.device; 633 634 PIPE_SAVE(gr, pipe->pipe_0x4400, 0x4400); 635 PIPE_SAVE(gr, pipe->pipe_0x0200, 0x0200); 636 PIPE_SAVE(gr, pipe->pipe_0x6400, 0x6400); 637 PIPE_SAVE(gr, pipe->pipe_0x6800, 0x6800); 638 PIPE_SAVE(gr, pipe->pipe_0x6c00, 0x6c00); 639 PIPE_SAVE(gr, pipe->pipe_0x7000, 0x7000); 640 PIPE_SAVE(gr, pipe->pipe_0x7400, 0x7400); 641 PIPE_SAVE(gr, pipe->pipe_0x7800, 0x7800); 642 PIPE_SAVE(gr, pipe->pipe_0x0040, 0x0040); 643 PIPE_SAVE(gr, pipe->pipe_0x0000, 0x0000); 644 } 645 646 static void 647 nv10_gr_load_pipe(struct nv10_gr_chan *chan) 648 { 649 struct nv10_gr *gr = nv10_gr(chan); 650 struct pipe_state *pipe = &chan->pipe_state; 651 struct nvkm_device *device = gr->base.engine.subdev.device; 652 u32 xfmode0, xfmode1; 653 int i; 654 655 nv04_gr_idle(gr); 656 /* XXX check haiku comments */ 657 xfmode0 = nvkm_rd32(device, NV10_PGRAPH_XFMODE0); 658 xfmode1 = nvkm_rd32(device, NV10_PGRAPH_XFMODE1); 659 nvkm_wr32(device, NV10_PGRAPH_XFMODE0, 0x10000000); 660 nvkm_wr32(device, NV10_PGRAPH_XFMODE1, 0x00000000); 661 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); 662 for (i = 0; i < 4; i++) 663 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); 664 for (i = 0; i < 4; i++) 665 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); 666 667 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); 668 for (i = 0; i < 3; i++) 669 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000); 670 671 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); 672 for (i = 0; i < 3; i++) 673 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000); 674 675 nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); 676 nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000008); 677 678 679 PIPE_RESTORE(gr, pipe->pipe_0x0200, 0x0200); 680 nv04_gr_idle(gr); 681 682 /* restore XFMODE */ 683 nvkm_wr32(device, NV10_PGRAPH_XFMODE0, xfmode0); 684 nvkm_wr32(device, NV10_PGRAPH_XFMODE1, xfmode1); 685 PIPE_RESTORE(gr, pipe->pipe_0x6400, 0x6400); 686 PIPE_RESTORE(gr, pipe->pipe_0x6800, 0x6800); 687 PIPE_RESTORE(gr, pipe->pipe_0x6c00, 0x6c00); 688 PIPE_RESTORE(gr, pipe->pipe_0x7000, 0x7000); 689 PIPE_RESTORE(gr, pipe->pipe_0x7400, 0x7400); 690 PIPE_RESTORE(gr, pipe->pipe_0x7800, 0x7800); 691 PIPE_RESTORE(gr, pipe->pipe_0x4400, 0x4400); 692 PIPE_RESTORE(gr, pipe->pipe_0x0000, 0x0000); 693 PIPE_RESTORE(gr, pipe->pipe_0x0040, 0x0040); 694 nv04_gr_idle(gr); 695 } 696 697 static void 698 nv10_gr_create_pipe(struct nv10_gr_chan *chan) 699 { 700 struct nv10_gr *gr = nv10_gr(chan); 701 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 702 struct pipe_state *pipe_state = &chan->pipe_state; 703 u32 *pipe_state_addr; 704 int i; 705 #define PIPE_INIT(addr) \ 706 do { \ 707 pipe_state_addr = pipe_state->pipe_##addr; \ 708 } while (0) 709 #define PIPE_INIT_END(addr) \ 710 do { \ 711 u32 *__end_addr = pipe_state->pipe_##addr + \ 712 ARRAY_SIZE(pipe_state->pipe_##addr); \ 713 if (pipe_state_addr != __end_addr) \ 714 nvkm_error(subdev, "incomplete pipe init for 0x%x : %p/%p\n", \ 715 addr, pipe_state_addr, __end_addr); \ 716 } while (0) 717 #define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value 718 719 PIPE_INIT(0x0200); 720 for (i = 0; i < 48; i++) 721 NV_WRITE_PIPE_INIT(0x00000000); 722 PIPE_INIT_END(0x0200); 723 724 PIPE_INIT(0x6400); 725 for (i = 0; i < 211; i++) 726 NV_WRITE_PIPE_INIT(0x00000000); 727 NV_WRITE_PIPE_INIT(0x3f800000); 728 NV_WRITE_PIPE_INIT(0x40000000); 729 NV_WRITE_PIPE_INIT(0x40000000); 730 NV_WRITE_PIPE_INIT(0x40000000); 731 NV_WRITE_PIPE_INIT(0x40000000); 732 NV_WRITE_PIPE_INIT(0x00000000); 733 NV_WRITE_PIPE_INIT(0x00000000); 734 NV_WRITE_PIPE_INIT(0x3f800000); 735 NV_WRITE_PIPE_INIT(0x00000000); 736 NV_WRITE_PIPE_INIT(0x3f000000); 737 NV_WRITE_PIPE_INIT(0x3f000000); 738 NV_WRITE_PIPE_INIT(0x00000000); 739 NV_WRITE_PIPE_INIT(0x00000000); 740 NV_WRITE_PIPE_INIT(0x00000000); 741 NV_WRITE_PIPE_INIT(0x00000000); 742 NV_WRITE_PIPE_INIT(0x3f800000); 743 NV_WRITE_PIPE_INIT(0x00000000); 744 NV_WRITE_PIPE_INIT(0x00000000); 745 NV_WRITE_PIPE_INIT(0x00000000); 746 NV_WRITE_PIPE_INIT(0x00000000); 747 NV_WRITE_PIPE_INIT(0x00000000); 748 NV_WRITE_PIPE_INIT(0x3f800000); 749 NV_WRITE_PIPE_INIT(0x3f800000); 750 NV_WRITE_PIPE_INIT(0x3f800000); 751 NV_WRITE_PIPE_INIT(0x3f800000); 752 PIPE_INIT_END(0x6400); 753 754 PIPE_INIT(0x6800); 755 for (i = 0; i < 162; i++) 756 NV_WRITE_PIPE_INIT(0x00000000); 757 NV_WRITE_PIPE_INIT(0x3f800000); 758 for (i = 0; i < 25; i++) 759 NV_WRITE_PIPE_INIT(0x00000000); 760 PIPE_INIT_END(0x6800); 761 762 PIPE_INIT(0x6c00); 763 NV_WRITE_PIPE_INIT(0x00000000); 764 NV_WRITE_PIPE_INIT(0x00000000); 765 NV_WRITE_PIPE_INIT(0x00000000); 766 NV_WRITE_PIPE_INIT(0x00000000); 767 NV_WRITE_PIPE_INIT(0xbf800000); 768 NV_WRITE_PIPE_INIT(0x00000000); 769 NV_WRITE_PIPE_INIT(0x00000000); 770 NV_WRITE_PIPE_INIT(0x00000000); 771 NV_WRITE_PIPE_INIT(0x00000000); 772 NV_WRITE_PIPE_INIT(0x00000000); 773 NV_WRITE_PIPE_INIT(0x00000000); 774 NV_WRITE_PIPE_INIT(0x00000000); 775 PIPE_INIT_END(0x6c00); 776 777 PIPE_INIT(0x7000); 778 NV_WRITE_PIPE_INIT(0x00000000); 779 NV_WRITE_PIPE_INIT(0x00000000); 780 NV_WRITE_PIPE_INIT(0x00000000); 781 NV_WRITE_PIPE_INIT(0x00000000); 782 NV_WRITE_PIPE_INIT(0x00000000); 783 NV_WRITE_PIPE_INIT(0x00000000); 784 NV_WRITE_PIPE_INIT(0x00000000); 785 NV_WRITE_PIPE_INIT(0x00000000); 786 NV_WRITE_PIPE_INIT(0x00000000); 787 NV_WRITE_PIPE_INIT(0x00000000); 788 NV_WRITE_PIPE_INIT(0x00000000); 789 NV_WRITE_PIPE_INIT(0x00000000); 790 NV_WRITE_PIPE_INIT(0x7149f2ca); 791 NV_WRITE_PIPE_INIT(0x00000000); 792 NV_WRITE_PIPE_INIT(0x00000000); 793 NV_WRITE_PIPE_INIT(0x00000000); 794 NV_WRITE_PIPE_INIT(0x7149f2ca); 795 NV_WRITE_PIPE_INIT(0x00000000); 796 NV_WRITE_PIPE_INIT(0x00000000); 797 NV_WRITE_PIPE_INIT(0x00000000); 798 NV_WRITE_PIPE_INIT(0x7149f2ca); 799 NV_WRITE_PIPE_INIT(0x00000000); 800 NV_WRITE_PIPE_INIT(0x00000000); 801 NV_WRITE_PIPE_INIT(0x00000000); 802 NV_WRITE_PIPE_INIT(0x7149f2ca); 803 NV_WRITE_PIPE_INIT(0x00000000); 804 NV_WRITE_PIPE_INIT(0x00000000); 805 NV_WRITE_PIPE_INIT(0x00000000); 806 NV_WRITE_PIPE_INIT(0x7149f2ca); 807 NV_WRITE_PIPE_INIT(0x00000000); 808 NV_WRITE_PIPE_INIT(0x00000000); 809 NV_WRITE_PIPE_INIT(0x00000000); 810 NV_WRITE_PIPE_INIT(0x7149f2ca); 811 NV_WRITE_PIPE_INIT(0x00000000); 812 NV_WRITE_PIPE_INIT(0x00000000); 813 NV_WRITE_PIPE_INIT(0x00000000); 814 NV_WRITE_PIPE_INIT(0x7149f2ca); 815 NV_WRITE_PIPE_INIT(0x00000000); 816 NV_WRITE_PIPE_INIT(0x00000000); 817 NV_WRITE_PIPE_INIT(0x00000000); 818 NV_WRITE_PIPE_INIT(0x7149f2ca); 819 for (i = 0; i < 35; i++) 820 NV_WRITE_PIPE_INIT(0x00000000); 821 PIPE_INIT_END(0x7000); 822 823 PIPE_INIT(0x7400); 824 for (i = 0; i < 48; i++) 825 NV_WRITE_PIPE_INIT(0x00000000); 826 PIPE_INIT_END(0x7400); 827 828 PIPE_INIT(0x7800); 829 for (i = 0; i < 48; i++) 830 NV_WRITE_PIPE_INIT(0x00000000); 831 PIPE_INIT_END(0x7800); 832 833 PIPE_INIT(0x4400); 834 for (i = 0; i < 32; i++) 835 NV_WRITE_PIPE_INIT(0x00000000); 836 PIPE_INIT_END(0x4400); 837 838 PIPE_INIT(0x0000); 839 for (i = 0; i < 16; i++) 840 NV_WRITE_PIPE_INIT(0x00000000); 841 PIPE_INIT_END(0x0000); 842 843 PIPE_INIT(0x0040); 844 for (i = 0; i < 4; i++) 845 NV_WRITE_PIPE_INIT(0x00000000); 846 PIPE_INIT_END(0x0040); 847 848 #undef PIPE_INIT 849 #undef PIPE_INIT_END 850 #undef NV_WRITE_PIPE_INIT 851 } 852 853 static int 854 nv10_gr_ctx_regs_find_offset(struct nv10_gr *gr, int reg) 855 { 856 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 857 int i; 858 for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) { 859 if (nv10_gr_ctx_regs[i] == reg) 860 return i; 861 } 862 nvkm_error(subdev, "unknow offset nv10_ctx_regs %d\n", reg); 863 return -1; 864 } 865 866 static int 867 nv17_gr_ctx_regs_find_offset(struct nv10_gr *gr, int reg) 868 { 869 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 870 int i; 871 for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) { 872 if (nv17_gr_ctx_regs[i] == reg) 873 return i; 874 } 875 nvkm_error(subdev, "unknow offset nv17_ctx_regs %d\n", reg); 876 return -1; 877 } 878 879 static void 880 nv10_gr_load_dma_vtxbuf(struct nv10_gr_chan *chan, int chid, u32 inst) 881 { 882 struct nv10_gr *gr = nv10_gr(chan); 883 struct nvkm_device *device = gr->base.engine.subdev.device; 884 u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; 885 u32 ctx_user, ctx_switch[5]; 886 int i, subchan = -1; 887 888 /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state 889 * that cannot be restored via MMIO. Do it through the FIFO 890 * instead. 891 */ 892 893 /* Look for a celsius object */ 894 for (i = 0; i < 8; i++) { 895 int class = nvkm_rd32(device, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; 896 897 if (class == 0x56 || class == 0x96 || class == 0x99) { 898 subchan = i; 899 break; 900 } 901 } 902 903 if (subchan < 0 || !inst) 904 return; 905 906 /* Save the current ctx object */ 907 ctx_user = nvkm_rd32(device, NV10_PGRAPH_CTX_USER); 908 for (i = 0; i < 5; i++) 909 ctx_switch[i] = nvkm_rd32(device, NV10_PGRAPH_CTX_SWITCH(i)); 910 911 /* Save the FIFO state */ 912 st2 = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2); 913 st2_dl = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2_DL); 914 st2_dh = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2_DH); 915 fifo_ptr = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR); 916 917 for (i = 0; i < ARRAY_SIZE(fifo); i++) 918 fifo[i] = nvkm_rd32(device, 0x4007a0 + 4 * i); 919 920 /* Switch to the celsius subchannel */ 921 for (i = 0; i < 5; i++) 922 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(i), 923 nvkm_rd32(device, NV10_PGRAPH_CTX_CACHE(subchan, i))); 924 nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); 925 926 /* Inject NV10TCL_DMA_VTXBUF */ 927 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); 928 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, 929 0x2c000000 | chid << 20 | subchan << 16 | 0x18c); 930 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DL, inst); 931 nvkm_mask(device, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); 932 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); 933 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); 934 935 /* Restore the FIFO state */ 936 for (i = 0; i < ARRAY_SIZE(fifo); i++) 937 nvkm_wr32(device, 0x4007a0 + 4 * i, fifo[i]); 938 939 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); 940 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, st2); 941 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); 942 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); 943 944 /* Restore the current ctx object */ 945 for (i = 0; i < 5; i++) 946 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); 947 nvkm_wr32(device, NV10_PGRAPH_CTX_USER, ctx_user); 948 } 949 950 static int 951 nv10_gr_load_context(struct nv10_gr_chan *chan, int chid) 952 { 953 struct nv10_gr *gr = nv10_gr(chan); 954 struct nvkm_device *device = gr->base.engine.subdev.device; 955 u32 inst; 956 int i; 957 958 for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) 959 nvkm_wr32(device, nv10_gr_ctx_regs[i], chan->nv10[i]); 960 961 if (nv_device(gr)->card_type >= NV_11 && 962 nv_device(gr)->chipset >= 0x17) { 963 for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) 964 nvkm_wr32(device, nv17_gr_ctx_regs[i], chan->nv17[i]); 965 } 966 967 nv10_gr_load_pipe(chan); 968 969 inst = nvkm_rd32(device, NV10_PGRAPH_GLOBALSTATE1) & 0xffff; 970 nv10_gr_load_dma_vtxbuf(chan, chid, inst); 971 972 nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10010100); 973 nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24); 974 nvkm_mask(device, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000); 975 return 0; 976 } 977 978 static int 979 nv10_gr_unload_context(struct nv10_gr_chan *chan) 980 { 981 struct nv10_gr *gr = nv10_gr(chan); 982 struct nvkm_device *device = gr->base.engine.subdev.device; 983 int i; 984 985 for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) 986 chan->nv10[i] = nvkm_rd32(device, nv10_gr_ctx_regs[i]); 987 988 if (nv_device(gr)->card_type >= NV_11 && 989 nv_device(gr)->chipset >= 0x17) { 990 for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) 991 chan->nv17[i] = nvkm_rd32(device, nv17_gr_ctx_regs[i]); 992 } 993 994 nv10_gr_save_pipe(chan); 995 996 nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000000); 997 nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); 998 return 0; 999 } 1000 1001 static void 1002 nv10_gr_context_switch(struct nv10_gr *gr) 1003 { 1004 struct nvkm_device *device = gr->base.engine.subdev.device; 1005 struct nv10_gr_chan *prev = NULL; 1006 struct nv10_gr_chan *next = NULL; 1007 int chid; 1008 1009 nv04_gr_idle(gr); 1010 1011 /* If previous context is valid, we need to save it */ 1012 prev = nv10_gr_channel(gr); 1013 if (prev) 1014 nv10_gr_unload_context(prev); 1015 1016 /* load context for next channel */ 1017 chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; 1018 next = gr->chan[chid]; 1019 if (next) 1020 nv10_gr_load_context(next, chid); 1021 } 1022 1023 #define NV_WRITE_CTX(reg, val) do { \ 1024 int offset = nv10_gr_ctx_regs_find_offset(gr, reg); \ 1025 if (offset > 0) \ 1026 chan->nv10[offset] = val; \ 1027 } while (0) 1028 1029 #define NV17_WRITE_CTX(reg, val) do { \ 1030 int offset = nv17_gr_ctx_regs_find_offset(gr, reg); \ 1031 if (offset > 0) \ 1032 chan->nv17[offset] = val; \ 1033 } while (0) 1034 1035 static int 1036 nv10_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 1037 struct nvkm_oclass *oclass, void *data, u32 size, 1038 struct nvkm_object **pobject) 1039 { 1040 struct nvkm_fifo_chan *fifo = (void *)parent; 1041 struct nv10_gr *gr = (void *)engine; 1042 struct nv10_gr_chan *chan; 1043 struct nvkm_device *device = gr->base.engine.subdev.device; 1044 unsigned long flags; 1045 int ret; 1046 1047 ret = nvkm_object_create(parent, engine, oclass, 0, &chan); 1048 *pobject = nv_object(chan); 1049 if (ret) 1050 return ret; 1051 1052 spin_lock_irqsave(&gr->lock, flags); 1053 if (gr->chan[fifo->chid]) { 1054 *pobject = nv_object(gr->chan[fifo->chid]); 1055 atomic_inc(&(*pobject)->refcount); 1056 spin_unlock_irqrestore(&gr->lock, flags); 1057 nvkm_object_destroy(&chan->base); 1058 return 1; 1059 } 1060 1061 NV_WRITE_CTX(0x00400e88, 0x08000000); 1062 NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); 1063 NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff); 1064 NV_WRITE_CTX(0x00400e10, 0x00001000); 1065 NV_WRITE_CTX(0x00400e14, 0x00001000); 1066 NV_WRITE_CTX(0x00400e30, 0x00080008); 1067 NV_WRITE_CTX(0x00400e34, 0x00080008); 1068 if (nv_device(gr)->card_type >= NV_11 && 1069 nv_device(gr)->chipset >= 0x17) { 1070 /* is it really needed ??? */ 1071 NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, 1072 nvkm_rd32(device, NV10_PGRAPH_DEBUG_4)); 1073 NV17_WRITE_CTX(0x004006b0, nvkm_rd32(device, 0x004006b0)); 1074 NV17_WRITE_CTX(0x00400eac, 0x0fff0000); 1075 NV17_WRITE_CTX(0x00400eb0, 0x0fff0000); 1076 NV17_WRITE_CTX(0x00400ec0, 0x00000080); 1077 NV17_WRITE_CTX(0x00400ed0, 0x00000080); 1078 } 1079 NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->chid << 24); 1080 1081 nv10_gr_create_pipe(chan); 1082 1083 gr->chan[fifo->chid] = chan; 1084 chan->chid = fifo->chid; 1085 spin_unlock_irqrestore(&gr->lock, flags); 1086 return 0; 1087 } 1088 1089 static void 1090 nv10_gr_context_dtor(struct nvkm_object *object) 1091 { 1092 struct nv10_gr *gr = (void *)object->engine; 1093 struct nv10_gr_chan *chan = (void *)object; 1094 unsigned long flags; 1095 1096 spin_lock_irqsave(&gr->lock, flags); 1097 gr->chan[chan->chid] = NULL; 1098 spin_unlock_irqrestore(&gr->lock, flags); 1099 1100 nvkm_object_destroy(&chan->base); 1101 } 1102 1103 static int 1104 nv10_gr_context_fini(struct nvkm_object *object, bool suspend) 1105 { 1106 struct nv10_gr *gr = (void *)object->engine; 1107 struct nv10_gr_chan *chan = (void *)object; 1108 struct nvkm_device *device = gr->base.engine.subdev.device; 1109 unsigned long flags; 1110 1111 spin_lock_irqsave(&gr->lock, flags); 1112 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); 1113 if (nv10_gr_channel(gr) == chan) 1114 nv10_gr_unload_context(chan); 1115 nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); 1116 spin_unlock_irqrestore(&gr->lock, flags); 1117 1118 return _nvkm_object_fini(&chan->base, suspend); 1119 } 1120 1121 static struct nvkm_oclass 1122 nv10_gr_cclass = { 1123 .handle = NV_ENGCTX(GR, 0x10), 1124 .ofuncs = &(struct nvkm_ofuncs) { 1125 .ctor = nv10_gr_context_ctor, 1126 .dtor = nv10_gr_context_dtor, 1127 .init = _nvkm_object_init, 1128 .fini = nv10_gr_context_fini, 1129 }, 1130 }; 1131 1132 /******************************************************************************* 1133 * PGRAPH engine/subdev functions 1134 ******************************************************************************/ 1135 1136 static void 1137 nv10_gr_tile_prog(struct nvkm_engine *engine, int i) 1138 { 1139 struct nv10_gr *gr = (void *)engine; 1140 struct nvkm_device *device = gr->base.engine.subdev.device; 1141 struct nvkm_fifo *fifo = device->fifo; 1142 struct nvkm_fb_tile *tile = &device->fb->tile.region[i]; 1143 unsigned long flags; 1144 1145 fifo->pause(fifo, &flags); 1146 nv04_gr_idle(gr); 1147 1148 nvkm_wr32(device, NV10_PGRAPH_TLIMIT(i), tile->limit); 1149 nvkm_wr32(device, NV10_PGRAPH_TSIZE(i), tile->pitch); 1150 nvkm_wr32(device, NV10_PGRAPH_TILE(i), tile->addr); 1151 1152 fifo->start(fifo, &flags); 1153 } 1154 1155 const struct nvkm_bitfield nv10_gr_intr_name[] = { 1156 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, 1157 { NV_PGRAPH_INTR_ERROR, "ERROR" }, 1158 {} 1159 }; 1160 1161 const struct nvkm_bitfield nv10_gr_nstatus[] = { 1162 { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, 1163 { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, 1164 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, 1165 { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, 1166 {} 1167 }; 1168 1169 static void 1170 nv10_gr_intr(struct nvkm_subdev *subdev) 1171 { 1172 struct nv10_gr *gr = (void *)subdev; 1173 struct nv10_gr_chan *chan = NULL; 1174 struct nvkm_device *device = gr->base.engine.subdev.device; 1175 u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR); 1176 u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE); 1177 u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS); 1178 u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR); 1179 u32 chid = (addr & 0x01f00000) >> 20; 1180 u32 subc = (addr & 0x00070000) >> 16; 1181 u32 mthd = (addr & 0x00001ffc); 1182 u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA); 1183 u32 class = nvkm_rd32(device, 0x400160 + subc * 4) & 0xfff; 1184 u32 show = stat; 1185 char msg[128], src[128], sta[128]; 1186 unsigned long flags; 1187 1188 spin_lock_irqsave(&gr->lock, flags); 1189 chan = gr->chan[chid]; 1190 1191 if (stat & NV_PGRAPH_INTR_ERROR) { 1192 if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { 1193 if (!nv10_gr_mthd(chan, class, mthd, data)) 1194 show &= ~NV_PGRAPH_INTR_ERROR; 1195 } 1196 } 1197 1198 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { 1199 nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); 1200 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; 1201 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; 1202 nv10_gr_context_switch(gr); 1203 } 1204 1205 nvkm_wr32(device, NV03_PGRAPH_INTR, stat); 1206 nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001); 1207 1208 if (show) { 1209 nvkm_snprintbf(msg, sizeof(msg), nv10_gr_intr_name, show); 1210 nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource); 1211 nvkm_snprintbf(sta, sizeof(sta), nv10_gr_nstatus, nstatus); 1212 nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] " 1213 "nstatus %08x [%s] ch %d [%s] subc %d " 1214 "class %04x mthd %04x data %08x\n", 1215 show, msg, nsource, src, nstatus, sta, chid, 1216 nvkm_client_name(chan), subc, class, mthd, data); 1217 } 1218 1219 spin_unlock_irqrestore(&gr->lock, flags); 1220 } 1221 1222 static int 1223 nv10_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 1224 struct nvkm_oclass *oclass, void *data, u32 size, 1225 struct nvkm_object **pobject) 1226 { 1227 struct nv10_gr *gr; 1228 int ret; 1229 1230 ret = nvkm_gr_create(parent, engine, oclass, true, &gr); 1231 *pobject = nv_object(gr); 1232 if (ret) 1233 return ret; 1234 1235 nv_subdev(gr)->unit = 0x00001000; 1236 nv_subdev(gr)->intr = nv10_gr_intr; 1237 nv_engine(gr)->cclass = &nv10_gr_cclass; 1238 1239 if (nv_device(gr)->chipset <= 0x10) 1240 nv_engine(gr)->sclass = nv10_gr_sclass; 1241 else 1242 if (nv_device(gr)->chipset < 0x17 || 1243 nv_device(gr)->card_type < NV_11) 1244 nv_engine(gr)->sclass = nv15_gr_sclass; 1245 else 1246 nv_engine(gr)->sclass = nv17_gr_sclass; 1247 1248 nv_engine(gr)->tile_prog = nv10_gr_tile_prog; 1249 spin_lock_init(&gr->lock); 1250 return 0; 1251 } 1252 1253 static void 1254 nv10_gr_dtor(struct nvkm_object *object) 1255 { 1256 struct nv10_gr *gr = (void *)object; 1257 nvkm_gr_destroy(&gr->base); 1258 } 1259 1260 static int 1261 nv10_gr_init(struct nvkm_object *object) 1262 { 1263 struct nvkm_engine *engine = nv_engine(object); 1264 struct nv10_gr *gr = (void *)engine; 1265 struct nvkm_device *device = gr->base.engine.subdev.device; 1266 struct nvkm_fb *fb = device->fb; 1267 int ret, i; 1268 1269 ret = nvkm_gr_init(&gr->base); 1270 if (ret) 1271 return ret; 1272 1273 nvkm_wr32(device, NV03_PGRAPH_INTR , 0xFFFFFFFF); 1274 nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 1275 1276 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); 1277 nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000); 1278 nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x00118700); 1279 /* nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ 1280 nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); 1281 nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31)); 1282 1283 if (nv_device(gr)->card_type >= NV_11 && 1284 nv_device(gr)->chipset >= 0x17) { 1285 nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x1f000000); 1286 nvkm_wr32(device, 0x400a10, 0x03ff3fb6); 1287 nvkm_wr32(device, 0x400838, 0x002f8684); 1288 nvkm_wr32(device, 0x40083c, 0x00115f3f); 1289 nvkm_wr32(device, 0x4006b0, 0x40000020); 1290 } else { 1291 nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00000000); 1292 } 1293 1294 /* Turn all the tiling regions off. */ 1295 for (i = 0; i < fb->tile.regions; i++) 1296 engine->tile_prog(engine, i); 1297 1298 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); 1299 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); 1300 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); 1301 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); 1302 nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); 1303 nvkm_wr32(device, NV10_PGRAPH_STATE, 0xFFFFFFFF); 1304 1305 nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); 1306 nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000100); 1307 nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); 1308 return 0; 1309 } 1310 1311 static int 1312 nv10_gr_fini(struct nvkm_object *object, bool suspend) 1313 { 1314 struct nv10_gr *gr = (void *)object; 1315 return nvkm_gr_fini(&gr->base, suspend); 1316 } 1317 1318 struct nvkm_oclass 1319 nv10_gr_oclass = { 1320 .handle = NV_ENGINE(GR, 0x10), 1321 .ofuncs = &(struct nvkm_ofuncs) { 1322 .ctor = nv10_gr_ctor, 1323 .dtor = nv10_gr_dtor, 1324 .init = nv10_gr_init, 1325 .fini = nv10_gr_fini, 1326 }, 1327 }; 1328