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