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