Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nv10.c
Go to the documentation of this file.
1 /*
2  * Copyright 2007 Matthieu CASTET <[email protected]>
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  * paragraph) 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 
25 #include <core/os.h>
26 #include <core/class.h>
27 #include <core/handle.h>
28 
29 #include <subdev/fb.h>
30 
31 #include <engine/fifo.h>
32 #include <engine/graph.h>
33 
34 #include "regs.h"
35 
36 struct pipe_state {
37  u32 pipe_0x0000[0x040/4];
38  u32 pipe_0x0040[0x010/4];
39  u32 pipe_0x0200[0x0c0/4];
40  u32 pipe_0x4400[0x080/4];
41  u32 pipe_0x6400[0x3b0/4];
42  u32 pipe_0x6800[0x2f0/4];
43  u32 pipe_0x6c00[0x030/4];
44  u32 pipe_0x7000[0x130/4];
45  u32 pipe_0x7400[0x0c0/4];
46  u32 pipe_0x7800[0x0c0/4];
47 };
48 
49 static int nv10_graph_ctx_regs[] = {
132  NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */
133  0x00400904,
134  0x00400908,
135  0x0040090c,
136  0x00400910,
137  0x00400914,
138  0x00400918,
139  0x0040091c,
140  0x00400920,
141  0x00400924,
142  0x00400928,
143  0x0040092c,
144  0x00400930,
145  0x00400934,
146  0x00400938,
147  0x0040093c,
148  0x00400940,
149  0x00400944,
150  0x00400948,
151  0x0040094c,
152  0x00400950,
153  0x00400954,
154  0x00400958,
155  0x0040095c,
156  0x00400960,
157  0x00400964,
158  0x00400968,
159  0x0040096c,
160  0x00400970,
161  0x00400974,
162  0x00400978,
163  0x0040097c,
164  0x00400980,
165  0x00400984,
166  0x00400988,
167  0x0040098c,
168  0x00400990,
169  0x00400994,
170  0x00400998,
171  0x0040099c,
172  0x004009a0,
173  0x004009a4,
174  0x004009a8,
175  0x004009ac,
176  0x004009b0,
177  0x004009b4,
178  0x004009b8,
179  0x004009bc,
180  0x004009c0,
181  0x004009c4,
182  0x004009c8,
183  0x004009cc,
184  0x004009d0,
185  0x004009d4,
186  0x004009d8,
187  0x004009dc,
188  0x004009e0,
189  0x004009e4,
190  0x004009e8,
191  0x004009ec,
192  0x004009f0,
193  0x004009f4,
194  0x004009f8,
195  0x004009fc,
196  NV04_PGRAPH_PATTERN, /* 2 values from 0x400808 to 0x40080c */
197  0x0040080c,
204  0x00400e70,
205  0x00400e74,
206  0x00400e78,
207  0x00400e7c,
208  0x00400e80,
209  0x00400e84,
210  0x00400e88,
211  0x00400e8c,
212  0x00400ea0,
213  0x00400ea4,
214  0x00400ea8,
215  0x00400e90,
216  0x00400e94,
217  0x00400e98,
218  0x00400e9c,
219  NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */
220  NV10_PGRAPH_WINDOWCLIP_VERTICAL, /* 8 values from 0x400f20-0x400f3c */
221  0x00400f04,
222  0x00400f24,
223  0x00400f08,
224  0x00400f28,
225  0x00400f0c,
226  0x00400f2c,
227  0x00400f10,
228  0x00400f30,
229  0x00400f14,
230  0x00400f34,
231  0x00400f18,
232  0x00400f38,
233  0x00400f1c,
234  0x00400f3c,
241  NV03_PGRAPH_ABS_X_RAM, /* 32 values from 0x400400 to 0x40047c */
242  NV03_PGRAPH_ABS_Y_RAM, /* 32 values from 0x400480 to 0x4004fc */
243  0x00400404,
244  0x00400484,
245  0x00400408,
246  0x00400488,
247  0x0040040c,
248  0x0040048c,
249  0x00400410,
250  0x00400490,
251  0x00400414,
252  0x00400494,
253  0x00400418,
254  0x00400498,
255  0x0040041c,
256  0x0040049c,
257  0x00400420,
258  0x004004a0,
259  0x00400424,
260  0x004004a4,
261  0x00400428,
262  0x004004a8,
263  0x0040042c,
264  0x004004ac,
265  0x00400430,
266  0x004004b0,
267  0x00400434,
268  0x004004b4,
269  0x00400438,
270  0x004004b8,
271  0x0040043c,
272  0x004004bc,
273  0x00400440,
274  0x004004c0,
275  0x00400444,
276  0x004004c4,
277  0x00400448,
278  0x004004c8,
279  0x0040044c,
280  0x004004cc,
281  0x00400450,
282  0x004004d0,
283  0x00400454,
284  0x004004d4,
285  0x00400458,
286  0x004004d8,
287  0x0040045c,
288  0x004004dc,
289  0x00400460,
290  0x004004e0,
291  0x00400464,
292  0x004004e4,
293  0x00400468,
294  0x004004e8,
295  0x0040046c,
296  0x004004ec,
297  0x00400470,
298  0x004004f0,
299  0x00400474,
300  0x004004f4,
301  0x00400478,
302  0x004004f8,
303  0x0040047c,
304  0x004004fc,
309  0x00400550,
310  0x00400558,
311  0x00400554,
312  0x0040055c,
339  0x00400e00,
340  0x00400e04,
341  0x00400e08,
342  0x00400e0c,
343  0x00400e10,
344  0x00400e14,
345  0x00400e18,
346  0x00400e1c,
347  0x00400e20,
348  0x00400e24,
349  0x00400e28,
350  0x00400e2c,
351  0x00400e30,
352  0x00400e34,
353  0x00400e38,
354  0x00400e3c,
369 };
370 
371 static int nv17_graph_ctx_regs[] = {
373  0x004006b0,
374  0x00400eac,
375  0x00400eb0,
376  0x00400eb4,
377  0x00400eb8,
378  0x00400ebc,
379  0x00400ec0,
380  0x00400ec4,
381  0x00400ec8,
382  0x00400ecc,
383  0x00400ed0,
384  0x00400ed4,
385  0x00400ed8,
386  0x00400edc,
387  0x00400ee0,
388  0x00400a00,
389  0x00400a04,
390 };
391 
394  struct nv10_graph_chan *chan[32];
396 };
397 
400  int chid;
401  int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)];
402  int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)];
405 };
406 
407 
408 static inline struct nv10_graph_priv *
410 {
411  return (void *)nv_object(chan)->engine;
412 }
413 
414 /*******************************************************************************
415  * Graphics object classes
416  ******************************************************************************/
417 
418 #define PIPE_SAVE(priv, state, addr) \
419  do { \
420  int __i; \
421  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \
422  for (__i = 0; __i < ARRAY_SIZE(state); __i++) \
423  state[__i] = nv_rd32(priv, NV10_PGRAPH_PIPE_DATA); \
424  } while (0)
425 
426 #define PIPE_RESTORE(priv, state, addr) \
427  do { \
428  int __i; \
429  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \
430  for (__i = 0; __i < ARRAY_SIZE(state); __i++) \
431  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, state[__i]); \
432  } while (0)
433 
434 static struct nouveau_oclass
435 nv10_graph_sclass[] = {
436  { 0x0012, &nv04_graph_ofuncs }, /* beta1 */
437  { 0x0019, &nv04_graph_ofuncs }, /* clip */
438  { 0x0030, &nv04_graph_ofuncs }, /* null */
439  { 0x0039, &nv04_graph_ofuncs }, /* m2mf */
440  { 0x0043, &nv04_graph_ofuncs }, /* rop */
441  { 0x0044, &nv04_graph_ofuncs }, /* pattern */
442  { 0x004a, &nv04_graph_ofuncs }, /* gdi */
443  { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */
444  { 0x005f, &nv04_graph_ofuncs }, /* blit */
445  { 0x0062, &nv04_graph_ofuncs }, /* surf2d */
446  { 0x0072, &nv04_graph_ofuncs }, /* beta4 */
447  { 0x0089, &nv04_graph_ofuncs }, /* sifm */
448  { 0x008a, &nv04_graph_ofuncs }, /* ifc */
449  { 0x009f, &nv04_graph_ofuncs }, /* blit */
450  { 0x0093, &nv04_graph_ofuncs }, /* surf3d */
451  { 0x0094, &nv04_graph_ofuncs }, /* ttri */
452  { 0x0095, &nv04_graph_ofuncs }, /* mtri */
453  { 0x0056, &nv04_graph_ofuncs }, /* celcius */
454  {},
455 };
456 
457 static struct nouveau_oclass
458 nv15_graph_sclass[] = {
459  { 0x0012, &nv04_graph_ofuncs }, /* beta1 */
460  { 0x0019, &nv04_graph_ofuncs }, /* clip */
461  { 0x0030, &nv04_graph_ofuncs }, /* null */
462  { 0x0039, &nv04_graph_ofuncs }, /* m2mf */
463  { 0x0043, &nv04_graph_ofuncs }, /* rop */
464  { 0x0044, &nv04_graph_ofuncs }, /* pattern */
465  { 0x004a, &nv04_graph_ofuncs }, /* gdi */
466  { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */
467  { 0x005f, &nv04_graph_ofuncs }, /* blit */
468  { 0x0062, &nv04_graph_ofuncs }, /* surf2d */
469  { 0x0072, &nv04_graph_ofuncs }, /* beta4 */
470  { 0x0089, &nv04_graph_ofuncs }, /* sifm */
471  { 0x008a, &nv04_graph_ofuncs }, /* ifc */
472  { 0x009f, &nv04_graph_ofuncs }, /* blit */
473  { 0x0093, &nv04_graph_ofuncs }, /* surf3d */
474  { 0x0094, &nv04_graph_ofuncs }, /* ttri */
475  { 0x0095, &nv04_graph_ofuncs }, /* mtri */
476  { 0x0096, &nv04_graph_ofuncs }, /* celcius */
477  {},
478 };
479 
480 static int
481 nv17_graph_mthd_lma_window(struct nouveau_object *object, u32 mthd,
482  void *args, u32 size)
483 {
484  struct nv10_graph_chan *chan = (void *)object->parent;
485  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
486  struct pipe_state *pipe = &chan->pipe_state;
487  u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
488  u32 xfmode0, xfmode1;
489  u32 data = *(u32 *)args;
490  int i;
491 
492  chan->lma_window[(mthd - 0x1638) / 4] = data;
493 
494  if (mthd != 0x1644)
495  return 0;
496 
498 
499  PIPE_SAVE(priv, pipe_0x0040, 0x0040);
500  PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200);
501 
502  PIPE_RESTORE(priv, chan->lma_window, 0x6790);
503 
505 
506  xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0);
507  xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1);
508 
509  PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400);
510  PIPE_SAVE(priv, pipe_0x64c0, 0x64c0);
511  PIPE_SAVE(priv, pipe_0x6ab0, 0x6ab0);
512  PIPE_SAVE(priv, pipe_0x6a80, 0x6a80);
513 
515 
516  nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000);
517  nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000);
518  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
519  for (i = 0; i < 4; i++)
520  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
521  for (i = 0; i < 4; i++)
522  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
523 
524  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
525  for (i = 0; i < 3; i++)
526  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
527 
528  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
529  for (i = 0; i < 3; i++)
530  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
531 
532  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
533  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008);
534 
535  PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200);
536 
538 
539  PIPE_RESTORE(priv, pipe_0x0040, 0x0040);
540 
541  nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0);
542  nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1);
543 
544  PIPE_RESTORE(priv, pipe_0x64c0, 0x64c0);
545  PIPE_RESTORE(priv, pipe_0x6ab0, 0x6ab0);
546  PIPE_RESTORE(priv, pipe_0x6a80, 0x6a80);
547  PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400);
548 
549  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
550  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
551 
553 
554  return 0;
555 }
556 
557 static int
558 nv17_graph_mthd_lma_enable(struct nouveau_object *object, u32 mthd,
559  void *args, u32 size)
560 {
561  struct nv10_graph_chan *chan = (void *)object->parent;
562  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
563 
565 
566  nv_mask(priv, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100);
567  nv_mask(priv, 0x4006b0, 0x08000000, 0x08000000);
568  return 0;
569 }
570 
571 static struct nouveau_omthds
572 nv17_celcius_omthds[] = {
573  { 0x1638, nv17_graph_mthd_lma_window },
574  { 0x163c, nv17_graph_mthd_lma_window },
575  { 0x1640, nv17_graph_mthd_lma_window },
576  { 0x1644, nv17_graph_mthd_lma_window },
577  { 0x1658, nv17_graph_mthd_lma_enable },
578  {}
579 };
580 
581 static struct nouveau_oclass
582 nv17_graph_sclass[] = {
583  { 0x0012, &nv04_graph_ofuncs }, /* beta1 */
584  { 0x0019, &nv04_graph_ofuncs }, /* clip */
585  { 0x0030, &nv04_graph_ofuncs }, /* null */
586  { 0x0039, &nv04_graph_ofuncs }, /* m2mf */
587  { 0x0043, &nv04_graph_ofuncs }, /* rop */
588  { 0x0044, &nv04_graph_ofuncs }, /* pattern */
589  { 0x004a, &nv04_graph_ofuncs }, /* gdi */
590  { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */
591  { 0x005f, &nv04_graph_ofuncs }, /* blit */
592  { 0x0062, &nv04_graph_ofuncs }, /* surf2d */
593  { 0x0072, &nv04_graph_ofuncs }, /* beta4 */
594  { 0x0089, &nv04_graph_ofuncs }, /* sifm */
595  { 0x008a, &nv04_graph_ofuncs }, /* ifc */
596  { 0x009f, &nv04_graph_ofuncs }, /* blit */
597  { 0x0093, &nv04_graph_ofuncs }, /* surf3d */
598  { 0x0094, &nv04_graph_ofuncs }, /* ttri */
599  { 0x0095, &nv04_graph_ofuncs }, /* mtri */
600  { 0x0099, &nv04_graph_ofuncs, nv17_celcius_omthds },
601  {},
602 };
603 
604 /*******************************************************************************
605  * PGRAPH context
606  ******************************************************************************/
607 
608 static struct nv10_graph_chan *
609 nv10_graph_channel(struct nv10_graph_priv *priv)
610 {
611  struct nv10_graph_chan *chan = NULL;
612  if (nv_rd32(priv, 0x400144) & 0x00010000) {
613  int chid = nv_rd32(priv, 0x400148) >> 24;
614  if (chid < ARRAY_SIZE(priv->chan))
615  chan = priv->chan[chid];
616  }
617  return chan;
618 }
619 
620 static void
621 nv10_graph_save_pipe(struct nv10_graph_chan *chan)
622 {
623  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
624  struct pipe_state *pipe = &chan->pipe_state;
625 
626  PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400);
627  PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200);
628  PIPE_SAVE(priv, pipe->pipe_0x6400, 0x6400);
629  PIPE_SAVE(priv, pipe->pipe_0x6800, 0x6800);
630  PIPE_SAVE(priv, pipe->pipe_0x6c00, 0x6c00);
631  PIPE_SAVE(priv, pipe->pipe_0x7000, 0x7000);
632  PIPE_SAVE(priv, pipe->pipe_0x7400, 0x7400);
633  PIPE_SAVE(priv, pipe->pipe_0x7800, 0x7800);
634  PIPE_SAVE(priv, pipe->pipe_0x0040, 0x0040);
635  PIPE_SAVE(priv, pipe->pipe_0x0000, 0x0000);
636 }
637 
638 static void
639 nv10_graph_load_pipe(struct nv10_graph_chan *chan)
640 {
641  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
642  struct pipe_state *pipe = &chan->pipe_state;
643  u32 xfmode0, xfmode1;
644  int i;
645 
646  nv04_graph_idle(priv);
647  /* XXX check haiku comments */
648  xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0);
649  xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1);
650  nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000);
651  nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000);
652  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
653  for (i = 0; i < 4; i++)
654  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
655  for (i = 0; i < 4; i++)
656  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
657 
658  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
659  for (i = 0; i < 3; i++)
660  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
661 
662  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
663  for (i = 0; i < 3; i++)
664  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
665 
666  nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
667  nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008);
668 
669 
670  PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200);
671  nv04_graph_idle(priv);
672 
673  /* restore XFMODE */
674  nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0);
675  nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1);
676  PIPE_RESTORE(priv, pipe->pipe_0x6400, 0x6400);
677  PIPE_RESTORE(priv, pipe->pipe_0x6800, 0x6800);
678  PIPE_RESTORE(priv, pipe->pipe_0x6c00, 0x6c00);
679  PIPE_RESTORE(priv, pipe->pipe_0x7000, 0x7000);
680  PIPE_RESTORE(priv, pipe->pipe_0x7400, 0x7400);
681  PIPE_RESTORE(priv, pipe->pipe_0x7800, 0x7800);
682  PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400);
683  PIPE_RESTORE(priv, pipe->pipe_0x0000, 0x0000);
684  PIPE_RESTORE(priv, pipe->pipe_0x0040, 0x0040);
685  nv04_graph_idle(priv);
686 }
687 
688 static void
689 nv10_graph_create_pipe(struct nv10_graph_chan *chan)
690 {
691  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
692  struct pipe_state *pipe_state = &chan->pipe_state;
693  u32 *pipe_state_addr;
694  int i;
695 #define PIPE_INIT(addr) \
696  do { \
697  pipe_state_addr = pipe_state->pipe_##addr; \
698  } while (0)
699 #define PIPE_INIT_END(addr) \
700  do { \
701  u32 *__end_addr = pipe_state->pipe_##addr + \
702  ARRAY_SIZE(pipe_state->pipe_##addr); \
703  if (pipe_state_addr != __end_addr) \
704  nv_error(priv, "incomplete pipe init for 0x%x : %p/%p\n", \
705  addr, pipe_state_addr, __end_addr); \
706  } while (0)
707 #define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value
708 
709  PIPE_INIT(0x0200);
710  for (i = 0; i < 48; i++)
711  NV_WRITE_PIPE_INIT(0x00000000);
712  PIPE_INIT_END(0x0200);
713 
714  PIPE_INIT(0x6400);
715  for (i = 0; i < 211; i++)
716  NV_WRITE_PIPE_INIT(0x00000000);
717  NV_WRITE_PIPE_INIT(0x3f800000);
718  NV_WRITE_PIPE_INIT(0x40000000);
719  NV_WRITE_PIPE_INIT(0x40000000);
720  NV_WRITE_PIPE_INIT(0x40000000);
721  NV_WRITE_PIPE_INIT(0x40000000);
722  NV_WRITE_PIPE_INIT(0x00000000);
723  NV_WRITE_PIPE_INIT(0x00000000);
724  NV_WRITE_PIPE_INIT(0x3f800000);
725  NV_WRITE_PIPE_INIT(0x00000000);
726  NV_WRITE_PIPE_INIT(0x3f000000);
727  NV_WRITE_PIPE_INIT(0x3f000000);
728  NV_WRITE_PIPE_INIT(0x00000000);
729  NV_WRITE_PIPE_INIT(0x00000000);
730  NV_WRITE_PIPE_INIT(0x00000000);
731  NV_WRITE_PIPE_INIT(0x00000000);
732  NV_WRITE_PIPE_INIT(0x3f800000);
733  NV_WRITE_PIPE_INIT(0x00000000);
734  NV_WRITE_PIPE_INIT(0x00000000);
735  NV_WRITE_PIPE_INIT(0x00000000);
736  NV_WRITE_PIPE_INIT(0x00000000);
737  NV_WRITE_PIPE_INIT(0x00000000);
738  NV_WRITE_PIPE_INIT(0x3f800000);
739  NV_WRITE_PIPE_INIT(0x3f800000);
740  NV_WRITE_PIPE_INIT(0x3f800000);
741  NV_WRITE_PIPE_INIT(0x3f800000);
742  PIPE_INIT_END(0x6400);
743 
744  PIPE_INIT(0x6800);
745  for (i = 0; i < 162; i++)
746  NV_WRITE_PIPE_INIT(0x00000000);
747  NV_WRITE_PIPE_INIT(0x3f800000);
748  for (i = 0; i < 25; i++)
749  NV_WRITE_PIPE_INIT(0x00000000);
750  PIPE_INIT_END(0x6800);
751 
752  PIPE_INIT(0x6c00);
753  NV_WRITE_PIPE_INIT(0x00000000);
754  NV_WRITE_PIPE_INIT(0x00000000);
755  NV_WRITE_PIPE_INIT(0x00000000);
756  NV_WRITE_PIPE_INIT(0x00000000);
757  NV_WRITE_PIPE_INIT(0xbf800000);
758  NV_WRITE_PIPE_INIT(0x00000000);
759  NV_WRITE_PIPE_INIT(0x00000000);
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  PIPE_INIT_END(0x6c00);
766 
767  PIPE_INIT(0x7000);
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  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(0x7149f2ca);
781  NV_WRITE_PIPE_INIT(0x00000000);
782  NV_WRITE_PIPE_INIT(0x00000000);
783  NV_WRITE_PIPE_INIT(0x00000000);
784  NV_WRITE_PIPE_INIT(0x7149f2ca);
785  NV_WRITE_PIPE_INIT(0x00000000);
786  NV_WRITE_PIPE_INIT(0x00000000);
787  NV_WRITE_PIPE_INIT(0x00000000);
788  NV_WRITE_PIPE_INIT(0x7149f2ca);
789  NV_WRITE_PIPE_INIT(0x00000000);
790  NV_WRITE_PIPE_INIT(0x00000000);
791  NV_WRITE_PIPE_INIT(0x00000000);
792  NV_WRITE_PIPE_INIT(0x7149f2ca);
793  NV_WRITE_PIPE_INIT(0x00000000);
794  NV_WRITE_PIPE_INIT(0x00000000);
795  NV_WRITE_PIPE_INIT(0x00000000);
796  NV_WRITE_PIPE_INIT(0x7149f2ca);
797  NV_WRITE_PIPE_INIT(0x00000000);
798  NV_WRITE_PIPE_INIT(0x00000000);
799  NV_WRITE_PIPE_INIT(0x00000000);
800  NV_WRITE_PIPE_INIT(0x7149f2ca);
801  NV_WRITE_PIPE_INIT(0x00000000);
802  NV_WRITE_PIPE_INIT(0x00000000);
803  NV_WRITE_PIPE_INIT(0x00000000);
804  NV_WRITE_PIPE_INIT(0x7149f2ca);
805  NV_WRITE_PIPE_INIT(0x00000000);
806  NV_WRITE_PIPE_INIT(0x00000000);
807  NV_WRITE_PIPE_INIT(0x00000000);
808  NV_WRITE_PIPE_INIT(0x7149f2ca);
809  for (i = 0; i < 35; i++)
810  NV_WRITE_PIPE_INIT(0x00000000);
811  PIPE_INIT_END(0x7000);
812 
813  PIPE_INIT(0x7400);
814  for (i = 0; i < 48; i++)
815  NV_WRITE_PIPE_INIT(0x00000000);
816  PIPE_INIT_END(0x7400);
817 
818  PIPE_INIT(0x7800);
819  for (i = 0; i < 48; i++)
820  NV_WRITE_PIPE_INIT(0x00000000);
821  PIPE_INIT_END(0x7800);
822 
823  PIPE_INIT(0x4400);
824  for (i = 0; i < 32; i++)
825  NV_WRITE_PIPE_INIT(0x00000000);
826  PIPE_INIT_END(0x4400);
827 
828  PIPE_INIT(0x0000);
829  for (i = 0; i < 16; i++)
830  NV_WRITE_PIPE_INIT(0x00000000);
831  PIPE_INIT_END(0x0000);
832 
833  PIPE_INIT(0x0040);
834  for (i = 0; i < 4; i++)
835  NV_WRITE_PIPE_INIT(0x00000000);
836  PIPE_INIT_END(0x0040);
837 
838 #undef PIPE_INIT
839 #undef PIPE_INIT_END
840 #undef NV_WRITE_PIPE_INIT
841 }
842 
843 static int
844 nv10_graph_ctx_regs_find_offset(struct nv10_graph_priv *priv, int reg)
845 {
846  int i;
847  for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) {
848  if (nv10_graph_ctx_regs[i] == reg)
849  return i;
850  }
851  nv_error(priv, "unknow offset nv10_ctx_regs %d\n", reg);
852  return -1;
853 }
854 
855 static int
856 nv17_graph_ctx_regs_find_offset(struct nv10_graph_priv *priv, int reg)
857 {
858  int i;
859  for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) {
860  if (nv17_graph_ctx_regs[i] == reg)
861  return i;
862  }
863  nv_error(priv, "unknow offset nv17_ctx_regs %d\n", reg);
864  return -1;
865 }
866 
867 static void
868 nv10_graph_load_dma_vtxbuf(struct nv10_graph_chan *chan, int chid, u32 inst)
869 {
870  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
871  u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4];
872  u32 ctx_user, ctx_switch[5];
873  int i, subchan = -1;
874 
875  /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state
876  * that cannot be restored via MMIO. Do it through the FIFO
877  * instead.
878  */
879 
880  /* Look for a celsius object */
881  for (i = 0; i < 8; i++) {
882  int class = nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff;
883 
884  if (class == 0x56 || class == 0x96 || class == 0x99) {
885  subchan = i;
886  break;
887  }
888  }
889 
890  if (subchan < 0 || !inst)
891  return;
892 
893  /* Save the current ctx object */
894  ctx_user = nv_rd32(priv, NV10_PGRAPH_CTX_USER);
895  for (i = 0; i < 5; i++)
896  ctx_switch[i] = nv_rd32(priv, NV10_PGRAPH_CTX_SWITCH(i));
897 
898  /* Save the FIFO state */
899  st2 = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2);
900  st2_dl = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DL);
901  st2_dh = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DH);
902  fifo_ptr = nv_rd32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR);
903 
904  for (i = 0; i < ARRAY_SIZE(fifo); i++)
905  fifo[i] = nv_rd32(priv, 0x4007a0 + 4 * i);
906 
907  /* Switch to the celsius subchannel */
908  for (i = 0; i < 5; i++)
909  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i),
910  nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(subchan, i)));
911  nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13);
912 
913  /* Inject NV10TCL_DMA_VTXBUF */
914  nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0);
915  nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2,
916  0x2c000000 | chid << 20 | subchan << 16 | 0x18c);
917  nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
918  nv_mask(priv, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
919  nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
920  nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
921 
922  /* Restore the FIFO state */
923  for (i = 0; i < ARRAY_SIZE(fifo); i++)
924  nv_wr32(priv, 0x4007a0 + 4 * i, fifo[i]);
925 
926  nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr);
927  nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, st2);
928  nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl);
929  nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh);
930 
931  /* Restore the current ctx object */
932  for (i = 0; i < 5; i++)
933  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]);
934  nv_wr32(priv, NV10_PGRAPH_CTX_USER, ctx_user);
935 }
936 
937 static int
938 nv10_graph_load_context(struct nv10_graph_chan *chan, int chid)
939 {
940  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
941  u32 inst;
942  int i;
943 
944  for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
945  nv_wr32(priv, nv10_graph_ctx_regs[i], chan->nv10[i]);
946 
947  if (nv_device(priv)->chipset >= 0x17) {
948  for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
949  nv_wr32(priv, nv17_graph_ctx_regs[i], chan->nv17[i]);
950  }
951 
952  nv10_graph_load_pipe(chan);
953 
954  inst = nv_rd32(priv, NV10_PGRAPH_GLOBALSTATE1) & 0xffff;
955  nv10_graph_load_dma_vtxbuf(chan, chid, inst);
956 
957  nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
958  nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24);
959  nv_mask(priv, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000);
960  return 0;
961 }
962 
963 static int
964 nv10_graph_unload_context(struct nv10_graph_chan *chan)
965 {
966  struct nv10_graph_priv *priv = nv10_graph_priv(chan);
967  int i;
968 
969  for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
970  chan->nv10[i] = nv_rd32(priv, nv10_graph_ctx_regs[i]);
971 
972  if (nv_device(priv)->chipset >= 0x17) {
973  for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
974  chan->nv17[i] = nv_rd32(priv, nv17_graph_ctx_regs[i]);
975  }
976 
977  nv10_graph_save_pipe(chan);
978 
979  nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
980  nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000);
981  return 0;
982 }
983 
984 static void
985 nv10_graph_context_switch(struct nv10_graph_priv *priv)
986 {
987  struct nv10_graph_chan *prev = NULL;
988  struct nv10_graph_chan *next = NULL;
989  unsigned long flags;
990  int chid;
991 
992  spin_lock_irqsave(&priv->lock, flags);
993  nv04_graph_idle(priv);
994 
995  /* If previous context is valid, we need to save it */
996  prev = nv10_graph_channel(priv);
997  if (prev)
998  nv10_graph_unload_context(prev);
999 
1000  /* load context for next channel */
1001  chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
1002  next = priv->chan[chid];
1003  if (next)
1004  nv10_graph_load_context(next, chid);
1005 
1006  spin_unlock_irqrestore(&priv->lock, flags);
1007 }
1008 
1009 #define NV_WRITE_CTX(reg, val) do { \
1010  int offset = nv10_graph_ctx_regs_find_offset(priv, reg); \
1011  if (offset > 0) \
1012  chan->nv10[offset] = val; \
1013  } while (0)
1014 
1015 #define NV17_WRITE_CTX(reg, val) do { \
1016  int offset = nv17_graph_ctx_regs_find_offset(priv, reg); \
1017  if (offset > 0) \
1018  chan->nv17[offset] = val; \
1019  } while (0)
1020 
1021 static int
1022 nv10_graph_context_ctor(struct nouveau_object *parent,
1023  struct nouveau_object *engine,
1024  struct nouveau_oclass *oclass, void *data, u32 size,
1025  struct nouveau_object **pobject)
1026 {
1027  struct nouveau_fifo_chan *fifo = (void *)parent;
1028  struct nv10_graph_priv *priv = (void *)engine;
1029  struct nv10_graph_chan *chan;
1030  unsigned long flags;
1031  int ret;
1032 
1033  ret = nouveau_object_create(parent, engine, oclass, 0, &chan);
1034  *pobject = nv_object(chan);
1035  if (ret)
1036  return ret;
1037 
1038  spin_lock_irqsave(&priv->lock, flags);
1039  if (priv->chan[fifo->chid]) {
1040  *pobject = nv_object(priv->chan[fifo->chid]);
1041  atomic_inc(&(*pobject)->refcount);
1042  spin_unlock_irqrestore(&priv->lock, flags);
1043  nouveau_object_destroy(&chan->base);
1044  return 1;
1045  }
1046 
1047  NV_WRITE_CTX(0x00400e88, 0x08000000);
1048  NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
1050  NV_WRITE_CTX(0x00400e10, 0x00001000);
1051  NV_WRITE_CTX(0x00400e14, 0x00001000);
1052  NV_WRITE_CTX(0x00400e30, 0x00080008);
1053  NV_WRITE_CTX(0x00400e34, 0x00080008);
1054  if (nv_device(priv)->chipset >= 0x17) {
1055  /* is it really needed ??? */
1057  nv_rd32(priv, NV10_PGRAPH_DEBUG_4));
1058  NV17_WRITE_CTX(0x004006b0, nv_rd32(priv, 0x004006b0));
1059  NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
1060  NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
1061  NV17_WRITE_CTX(0x00400ec0, 0x00000080);
1062  NV17_WRITE_CTX(0x00400ed0, 0x00000080);
1063  }
1064  NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->chid << 24);
1065 
1066  nv10_graph_create_pipe(chan);
1067 
1068  priv->chan[fifo->chid] = chan;
1069  chan->chid = fifo->chid;
1070  spin_unlock_irqrestore(&priv->lock, flags);
1071  return 0;
1072 }
1073 
1074 static void
1075 nv10_graph_context_dtor(struct nouveau_object *object)
1076 {
1077  struct nv10_graph_priv *priv = (void *)object->engine;
1078  struct nv10_graph_chan *chan = (void *)object;
1079  unsigned long flags;
1080 
1081  spin_lock_irqsave(&priv->lock, flags);
1082  priv->chan[chan->chid] = NULL;
1083  spin_unlock_irqrestore(&priv->lock, flags);
1084 
1085  nouveau_object_destroy(&chan->base);
1086 }
1087 
1088 static int
1089 nv10_graph_context_fini(struct nouveau_object *object, bool suspend)
1090 {
1091  struct nv10_graph_priv *priv = (void *)object->engine;
1092  struct nv10_graph_chan *chan = (void *)object;
1093  unsigned long flags;
1094 
1095  spin_lock_irqsave(&priv->lock, flags);
1096  nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
1097  if (nv10_graph_channel(priv) == chan)
1098  nv10_graph_unload_context(chan);
1099  nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
1100  spin_unlock_irqrestore(&priv->lock, flags);
1101 
1102  return nouveau_object_fini(&chan->base, suspend);
1103 }
1104 
1105 static struct nouveau_oclass
1106 nv10_graph_cclass = {
1107  .handle = NV_ENGCTX(GR, 0x10),
1108  .ofuncs = &(struct nouveau_ofuncs) {
1109  .ctor = nv10_graph_context_ctor,
1110  .dtor = nv10_graph_context_dtor,
1111  .init = nouveau_object_init,
1112  .fini = nv10_graph_context_fini,
1113  },
1114 };
1115 
1116 /*******************************************************************************
1117  * PGRAPH engine/subdev functions
1118  ******************************************************************************/
1119 
1120 static void
1121 nv10_graph_tile_prog(struct nouveau_engine *engine, int i)
1122 {
1123  struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i];
1124  struct nouveau_fifo *pfifo = nouveau_fifo(engine);
1125  struct nv10_graph_priv *priv = (void *)engine;
1126  unsigned long flags;
1127 
1128  pfifo->pause(pfifo, &flags);
1129  nv04_graph_idle(priv);
1130 
1131  nv_wr32(priv, NV10_PGRAPH_TLIMIT(i), tile->limit);
1132  nv_wr32(priv, NV10_PGRAPH_TSIZE(i), tile->pitch);
1133  nv_wr32(priv, NV10_PGRAPH_TILE(i), tile->addr);
1134 
1135  pfifo->start(pfifo, &flags);
1136 }
1137 
1139  { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1140  { NV_PGRAPH_INTR_ERROR, "ERROR" },
1141  {}
1142 };
1143 
1145  { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
1146  { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
1147  { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
1148  { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
1149  {}
1150 };
1151 
1152 static void
1153 nv10_graph_intr(struct nouveau_subdev *subdev)
1154 {
1155  struct nv10_graph_priv *priv = (void *)subdev;
1156  struct nv10_graph_chan *chan = NULL;
1157  struct nouveau_namedb *namedb = NULL;
1158  struct nouveau_handle *handle = NULL;
1159  u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR);
1160  u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE);
1161  u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS);
1162  u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR);
1163  u32 chid = (addr & 0x01f00000) >> 20;
1164  u32 subc = (addr & 0x00070000) >> 16;
1165  u32 mthd = (addr & 0x00001ffc);
1166  u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA);
1167  u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff;
1168  u32 show = stat;
1169  unsigned long flags;
1170 
1171  spin_lock_irqsave(&priv->lock, flags);
1172  chan = priv->chan[chid];
1173  if (chan)
1174  namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS);
1175  spin_unlock_irqrestore(&priv->lock, flags);
1176 
1177  if (stat & NV_PGRAPH_INTR_ERROR) {
1178  if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
1179  handle = nouveau_namedb_get_class(namedb, class);
1180  if (handle && !nv_call(handle->object, mthd, data))
1181  show &= ~NV_PGRAPH_INTR_ERROR;
1182  }
1183  }
1184 
1185  if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1186  nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1187  stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1188  show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1189  nv10_graph_context_switch(priv);
1190  }
1191 
1192  nv_wr32(priv, NV03_PGRAPH_INTR, stat);
1193  nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001);
1194 
1195  if (show) {
1196  nv_error(priv, "");
1197  nouveau_bitfield_print(nv10_graph_intr_name, show);
1198  printk(" nsource:");
1200  printk(" nstatus:");
1201  nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
1202  printk("\n");
1203  nv_error(priv, "ch %d/%d class 0x%04x "
1204  "mthd 0x%04x data 0x%08x\n",
1205  chid, subc, class, mthd, data);
1206  }
1207 
1208  nouveau_namedb_put(handle);
1209 }
1210 
1211 static int
1212 nv10_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1213  struct nouveau_oclass *oclass, void *data, u32 size,
1214  struct nouveau_object **pobject)
1215 {
1216  struct nv10_graph_priv *priv;
1217  int ret;
1218 
1219  ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
1220  *pobject = nv_object(priv);
1221  if (ret)
1222  return ret;
1223 
1224  nv_subdev(priv)->unit = 0x00001000;
1225  nv_subdev(priv)->intr = nv10_graph_intr;
1226  nv_engine(priv)->cclass = &nv10_graph_cclass;
1227 
1228  if (nv_device(priv)->chipset <= 0x10)
1229  nv_engine(priv)->sclass = nv10_graph_sclass;
1230  else
1231  if (nv_device(priv)->chipset < 0x17 ||
1232  nv_device(priv)->chipset == 0x1a)
1233  nv_engine(priv)->sclass = nv15_graph_sclass;
1234  else
1235  nv_engine(priv)->sclass = nv17_graph_sclass;
1236 
1237  nv_engine(priv)->tile_prog = nv10_graph_tile_prog;
1238  spin_lock_init(&priv->lock);
1239  return 0;
1240 }
1241 
1242 static void
1243 nv10_graph_dtor(struct nouveau_object *object)
1244 {
1245  struct nv10_graph_priv *priv = (void *)object;
1246  nouveau_graph_destroy(&priv->base);
1247 }
1248 
1249 static int
1250 nv10_graph_init(struct nouveau_object *object)
1251 {
1252  struct nouveau_engine *engine = nv_engine(object);
1253  struct nouveau_fb *pfb = nouveau_fb(object);
1254  struct nv10_graph_priv *priv = (void *)engine;
1255  int ret, i;
1256 
1257  ret = nouveau_graph_init(&priv->base);
1258  if (ret)
1259  return ret;
1260 
1261  nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF);
1262  nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
1263 
1264  nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
1265  nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000);
1266  nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700);
1267  /* nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
1268  nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
1269  nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31));
1270 
1271  if (nv_device(priv)->chipset >= 0x17) {
1272  nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000);
1273  nv_wr32(priv, 0x400a10, 0x03ff3fb6);
1274  nv_wr32(priv, 0x400838, 0x002f8684);
1275  nv_wr32(priv, 0x40083c, 0x00115f3f);
1276  nv_wr32(priv, 0x4006b0, 0x40000020);
1277  } else {
1278  nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000);
1279  }
1280 
1281  /* Turn all the tiling regions off. */
1282  for (i = 0; i < pfb->tile.regions; i++)
1283  engine->tile_prog(engine, i);
1284 
1285  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000);
1286  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000);
1287  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000);
1288  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000);
1289  nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000);
1290  nv_wr32(priv, NV10_PGRAPH_STATE, 0xFFFFFFFF);
1291 
1292  nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000);
1293  nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
1294  nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
1295  return 0;
1296 }
1297 
1298 static int
1299 nv10_graph_fini(struct nouveau_object *object, bool suspend)
1300 {
1301  struct nv10_graph_priv *priv = (void *)object;
1302  return nouveau_graph_fini(&priv->base, suspend);
1303 }
1304 
1305 struct nouveau_oclass
1307  .handle = NV_ENGINE(GR, 0x10),
1308  .ofuncs = &(struct nouveau_ofuncs) {
1309  .ctor = nv10_graph_ctor,
1310  .dtor = nv10_graph_dtor,
1311  .init = nv10_graph_init,
1312  .fini = nv10_graph_fini,
1313  },
1314 };