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