linux/drivers/gpu/drm/nouveau/nv10_graph.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 "drmP.h"
  26#include "drm.h"
  27#include "nouveau_drm.h"
  28#include "nouveau_drv.h"
  29#include "nouveau_util.h"
  30
  31static int  nv10_graph_register(struct drm_device *);
  32static void nv10_graph_isr(struct drm_device *);
  33
  34#define NV10_FIFO_NUMBER 32
  35
  36struct pipe_state {
  37        uint32_t pipe_0x0000[0x040/4];
  38        uint32_t pipe_0x0040[0x010/4];
  39        uint32_t pipe_0x0200[0x0c0/4];
  40        uint32_t pipe_0x4400[0x080/4];
  41        uint32_t pipe_0x6400[0x3b0/4];
  42        uint32_t pipe_0x6800[0x2f0/4];
  43        uint32_t pipe_0x6c00[0x030/4];
  44        uint32_t pipe_0x7000[0x130/4];
  45        uint32_t pipe_0x7400[0x0c0/4];
  46        uint32_t pipe_0x7800[0x0c0/4];
  47};
  48
  49static int nv10_graph_ctx_regs[] = {
  50        NV10_PGRAPH_CTX_SWITCH(0),
  51        NV10_PGRAPH_CTX_SWITCH(1),
  52        NV10_PGRAPH_CTX_SWITCH(2),
  53        NV10_PGRAPH_CTX_SWITCH(3),
  54        NV10_PGRAPH_CTX_SWITCH(4),
  55        NV10_PGRAPH_CTX_CACHE(0, 0),
  56        NV10_PGRAPH_CTX_CACHE(0, 1),
  57        NV10_PGRAPH_CTX_CACHE(0, 2),
  58        NV10_PGRAPH_CTX_CACHE(0, 3),
  59        NV10_PGRAPH_CTX_CACHE(0, 4),
  60        NV10_PGRAPH_CTX_CACHE(1, 0),
  61        NV10_PGRAPH_CTX_CACHE(1, 1),
  62        NV10_PGRAPH_CTX_CACHE(1, 2),
  63        NV10_PGRAPH_CTX_CACHE(1, 3),
  64        NV10_PGRAPH_CTX_CACHE(1, 4),
  65        NV10_PGRAPH_CTX_CACHE(2, 0),
  66        NV10_PGRAPH_CTX_CACHE(2, 1),
  67        NV10_PGRAPH_CTX_CACHE(2, 2),
  68        NV10_PGRAPH_CTX_CACHE(2, 3),
  69        NV10_PGRAPH_CTX_CACHE(2, 4),
  70        NV10_PGRAPH_CTX_CACHE(3, 0),
  71        NV10_PGRAPH_CTX_CACHE(3, 1),
  72        NV10_PGRAPH_CTX_CACHE(3, 2),
  73        NV10_PGRAPH_CTX_CACHE(3, 3),
  74        NV10_PGRAPH_CTX_CACHE(3, 4),
  75        NV10_PGRAPH_CTX_CACHE(4, 0),
  76        NV10_PGRAPH_CTX_CACHE(4, 1),
  77        NV10_PGRAPH_CTX_CACHE(4, 2),
  78        NV10_PGRAPH_CTX_CACHE(4, 3),
  79        NV10_PGRAPH_CTX_CACHE(4, 4),
  80        NV10_PGRAPH_CTX_CACHE(5, 0),
  81        NV10_PGRAPH_CTX_CACHE(5, 1),
  82        NV10_PGRAPH_CTX_CACHE(5, 2),
  83        NV10_PGRAPH_CTX_CACHE(5, 3),
  84        NV10_PGRAPH_CTX_CACHE(5, 4),
  85        NV10_PGRAPH_CTX_CACHE(6, 0),
  86        NV10_PGRAPH_CTX_CACHE(6, 1),
  87        NV10_PGRAPH_CTX_CACHE(6, 2),
  88        NV10_PGRAPH_CTX_CACHE(6, 3),
  89        NV10_PGRAPH_CTX_CACHE(6, 4),
  90        NV10_PGRAPH_CTX_CACHE(7, 0),
  91        NV10_PGRAPH_CTX_CACHE(7, 1),
  92        NV10_PGRAPH_CTX_CACHE(7, 2),
  93        NV10_PGRAPH_CTX_CACHE(7, 3),
  94        NV10_PGRAPH_CTX_CACHE(7, 4),
  95        NV10_PGRAPH_CTX_USER,
  96        NV04_PGRAPH_DMA_START_0,
  97        NV04_PGRAPH_DMA_START_1,
  98        NV04_PGRAPH_DMA_LENGTH,
  99        NV04_PGRAPH_DMA_MISC,
 100        NV10_PGRAPH_DMA_PITCH,
 101        NV04_PGRAPH_BOFFSET0,
 102        NV04_PGRAPH_BBASE0,
 103        NV04_PGRAPH_BLIMIT0,
 104        NV04_PGRAPH_BOFFSET1,
 105        NV04_PGRAPH_BBASE1,
 106        NV04_PGRAPH_BLIMIT1,
 107        NV04_PGRAPH_BOFFSET2,
 108        NV04_PGRAPH_BBASE2,
 109        NV04_PGRAPH_BLIMIT2,
 110        NV04_PGRAPH_BOFFSET3,
 111        NV04_PGRAPH_BBASE3,
 112        NV04_PGRAPH_BLIMIT3,
 113        NV04_PGRAPH_BOFFSET4,
 114        NV04_PGRAPH_BBASE4,
 115        NV04_PGRAPH_BLIMIT4,
 116        NV04_PGRAPH_BOFFSET5,
 117        NV04_PGRAPH_BBASE5,
 118        NV04_PGRAPH_BLIMIT5,
 119        NV04_PGRAPH_BPITCH0,
 120        NV04_PGRAPH_BPITCH1,
 121        NV04_PGRAPH_BPITCH2,
 122        NV04_PGRAPH_BPITCH3,
 123        NV04_PGRAPH_BPITCH4,
 124        NV10_PGRAPH_SURFACE,
 125        NV10_PGRAPH_STATE,
 126        NV04_PGRAPH_BSWIZZLE2,
 127        NV04_PGRAPH_BSWIZZLE5,
 128        NV04_PGRAPH_BPIXEL,
 129        NV10_PGRAPH_NOTIFY,
 130        NV04_PGRAPH_PATT_COLOR0,
 131        NV04_PGRAPH_PATT_COLOR1,
 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,
 198        NV04_PGRAPH_PATTERN_SHAPE,
 199        NV03_PGRAPH_MONO_COLOR0,
 200        NV04_PGRAPH_ROP3,
 201        NV04_PGRAPH_CHROMA,
 202        NV04_PGRAPH_BETA_AND,
 203        NV04_PGRAPH_BETA_PREMULT,
 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,
 235        NV10_PGRAPH_XFMODE0,
 236        NV10_PGRAPH_XFMODE1,
 237        NV10_PGRAPH_GLOBALSTATE0,
 238        NV10_PGRAPH_GLOBALSTATE1,
 239        NV04_PGRAPH_STORED_FMT,
 240        NV04_PGRAPH_SOURCE_COLOR,
 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,
 305        NV03_PGRAPH_ABS_UCLIP_XMIN,
 306        NV03_PGRAPH_ABS_UCLIP_XMAX,
 307        NV03_PGRAPH_ABS_UCLIP_YMIN,
 308        NV03_PGRAPH_ABS_UCLIP_YMAX,
 309        0x00400550,
 310        0x00400558,
 311        0x00400554,
 312        0x0040055c,
 313        NV03_PGRAPH_ABS_UCLIPA_XMIN,
 314        NV03_PGRAPH_ABS_UCLIPA_XMAX,
 315        NV03_PGRAPH_ABS_UCLIPA_YMIN,
 316        NV03_PGRAPH_ABS_UCLIPA_YMAX,
 317        NV03_PGRAPH_ABS_ICLIP_XMAX,
 318        NV03_PGRAPH_ABS_ICLIP_YMAX,
 319        NV03_PGRAPH_XY_LOGIC_MISC0,
 320        NV03_PGRAPH_XY_LOGIC_MISC1,
 321        NV03_PGRAPH_XY_LOGIC_MISC2,
 322        NV03_PGRAPH_XY_LOGIC_MISC3,
 323        NV03_PGRAPH_CLIPX_0,
 324        NV03_PGRAPH_CLIPX_1,
 325        NV03_PGRAPH_CLIPY_0,
 326        NV03_PGRAPH_CLIPY_1,
 327        NV10_PGRAPH_COMBINER0_IN_ALPHA,
 328        NV10_PGRAPH_COMBINER1_IN_ALPHA,
 329        NV10_PGRAPH_COMBINER0_IN_RGB,
 330        NV10_PGRAPH_COMBINER1_IN_RGB,
 331        NV10_PGRAPH_COMBINER_COLOR0,
 332        NV10_PGRAPH_COMBINER_COLOR1,
 333        NV10_PGRAPH_COMBINER0_OUT_ALPHA,
 334        NV10_PGRAPH_COMBINER1_OUT_ALPHA,
 335        NV10_PGRAPH_COMBINER0_OUT_RGB,
 336        NV10_PGRAPH_COMBINER1_OUT_RGB,
 337        NV10_PGRAPH_COMBINER_FINAL0,
 338        NV10_PGRAPH_COMBINER_FINAL1,
 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,
 355        NV04_PGRAPH_PASSTHRU_0,
 356        NV04_PGRAPH_PASSTHRU_1,
 357        NV04_PGRAPH_PASSTHRU_2,
 358        NV10_PGRAPH_DIMX_TEXTURE,
 359        NV10_PGRAPH_WDIMX_TEXTURE,
 360        NV10_PGRAPH_DVD_COLORFMT,
 361        NV10_PGRAPH_SCALED_FORMAT,
 362        NV04_PGRAPH_MISC24_0,
 363        NV04_PGRAPH_MISC24_1,
 364        NV04_PGRAPH_MISC24_2,
 365        NV03_PGRAPH_X_MISC,
 366        NV03_PGRAPH_Y_MISC,
 367        NV04_PGRAPH_VALID1,
 368        NV04_PGRAPH_VALID2,
 369};
 370
 371static int nv17_graph_ctx_regs[] = {
 372        NV10_PGRAPH_DEBUG_4,
 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
 392struct graph_state {
 393        int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)];
 394        int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)];
 395        struct pipe_state pipe_state;
 396        uint32_t lma_window[4];
 397};
 398
 399#define PIPE_SAVE(dev, state, addr)                                     \
 400        do {                                                            \
 401                int __i;                                                \
 402                nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);           \
 403                for (__i = 0; __i < ARRAY_SIZE(state); __i++)           \
 404                        state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \
 405        } while (0)
 406
 407#define PIPE_RESTORE(dev, state, addr)                                  \
 408        do {                                                            \
 409                int __i;                                                \
 410                nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);           \
 411                for (__i = 0; __i < ARRAY_SIZE(state); __i++)           \
 412                        nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \
 413        } while (0)
 414
 415static void nv10_graph_save_pipe(struct nouveau_channel *chan)
 416{
 417        struct drm_device *dev = chan->dev;
 418        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
 419        struct pipe_state *pipe = &pgraph_ctx->pipe_state;
 420
 421        PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
 422        PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
 423        PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400);
 424        PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800);
 425        PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00);
 426        PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000);
 427        PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400);
 428        PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800);
 429        PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040);
 430        PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000);
 431}
 432
 433static void nv10_graph_load_pipe(struct nouveau_channel *chan)
 434{
 435        struct drm_device *dev = chan->dev;
 436        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
 437        struct pipe_state *pipe = &pgraph_ctx->pipe_state;
 438        uint32_t xfmode0, xfmode1;
 439        int i;
 440
 441        nouveau_wait_for_idle(dev);
 442        /* XXX check haiku comments */
 443        xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
 444        xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
 445        nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
 446        nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
 447        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
 448        for (i = 0; i < 4; i++)
 449                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
 450        for (i = 0; i < 4; i++)
 451                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
 452
 453        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
 454        for (i = 0; i < 3; i++)
 455                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
 456
 457        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
 458        for (i = 0; i < 3; i++)
 459                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
 460
 461        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
 462        nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
 463
 464
 465        PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
 466        nouveau_wait_for_idle(dev);
 467
 468        /* restore XFMODE */
 469        nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
 470        nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
 471        PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400);
 472        PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800);
 473        PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00);
 474        PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000);
 475        PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400);
 476        PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800);
 477        PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
 478        PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000);
 479        PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040);
 480        nouveau_wait_for_idle(dev);
 481}
 482
 483static void nv10_graph_create_pipe(struct nouveau_channel *chan)
 484{
 485        struct drm_device *dev = chan->dev;
 486        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
 487        struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
 488        uint32_t *fifo_pipe_state_addr;
 489        int i;
 490#define PIPE_INIT(addr) \
 491        do { \
 492                fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \
 493        } while (0)
 494#define PIPE_INIT_END(addr) \
 495        do { \
 496                uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \
 497                                ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \
 498                if (fifo_pipe_state_addr != __end_addr) \
 499                        NV_ERROR(dev, "incomplete pipe init for 0x%x :  %p/%p\n", \
 500                                addr, fifo_pipe_state_addr, __end_addr); \
 501        } while (0)
 502#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value
 503
 504        PIPE_INIT(0x0200);
 505        for (i = 0; i < 48; i++)
 506                NV_WRITE_PIPE_INIT(0x00000000);
 507        PIPE_INIT_END(0x0200);
 508
 509        PIPE_INIT(0x6400);
 510        for (i = 0; i < 211; i++)
 511                NV_WRITE_PIPE_INIT(0x00000000);
 512        NV_WRITE_PIPE_INIT(0x3f800000);
 513        NV_WRITE_PIPE_INIT(0x40000000);
 514        NV_WRITE_PIPE_INIT(0x40000000);
 515        NV_WRITE_PIPE_INIT(0x40000000);
 516        NV_WRITE_PIPE_INIT(0x40000000);
 517        NV_WRITE_PIPE_INIT(0x00000000);
 518        NV_WRITE_PIPE_INIT(0x00000000);
 519        NV_WRITE_PIPE_INIT(0x3f800000);
 520        NV_WRITE_PIPE_INIT(0x00000000);
 521        NV_WRITE_PIPE_INIT(0x3f000000);
 522        NV_WRITE_PIPE_INIT(0x3f000000);
 523        NV_WRITE_PIPE_INIT(0x00000000);
 524        NV_WRITE_PIPE_INIT(0x00000000);
 525        NV_WRITE_PIPE_INIT(0x00000000);
 526        NV_WRITE_PIPE_INIT(0x00000000);
 527        NV_WRITE_PIPE_INIT(0x3f800000);
 528        NV_WRITE_PIPE_INIT(0x00000000);
 529        NV_WRITE_PIPE_INIT(0x00000000);
 530        NV_WRITE_PIPE_INIT(0x00000000);
 531        NV_WRITE_PIPE_INIT(0x00000000);
 532        NV_WRITE_PIPE_INIT(0x00000000);
 533        NV_WRITE_PIPE_INIT(0x3f800000);
 534        NV_WRITE_PIPE_INIT(0x3f800000);
 535        NV_WRITE_PIPE_INIT(0x3f800000);
 536        NV_WRITE_PIPE_INIT(0x3f800000);
 537        PIPE_INIT_END(0x6400);
 538
 539        PIPE_INIT(0x6800);
 540        for (i = 0; i < 162; i++)
 541                NV_WRITE_PIPE_INIT(0x00000000);
 542        NV_WRITE_PIPE_INIT(0x3f800000);
 543        for (i = 0; i < 25; i++)
 544                NV_WRITE_PIPE_INIT(0x00000000);
 545        PIPE_INIT_END(0x6800);
 546
 547        PIPE_INIT(0x6c00);
 548        NV_WRITE_PIPE_INIT(0x00000000);
 549        NV_WRITE_PIPE_INIT(0x00000000);
 550        NV_WRITE_PIPE_INIT(0x00000000);
 551        NV_WRITE_PIPE_INIT(0x00000000);
 552        NV_WRITE_PIPE_INIT(0xbf800000);
 553        NV_WRITE_PIPE_INIT(0x00000000);
 554        NV_WRITE_PIPE_INIT(0x00000000);
 555        NV_WRITE_PIPE_INIT(0x00000000);
 556        NV_WRITE_PIPE_INIT(0x00000000);
 557        NV_WRITE_PIPE_INIT(0x00000000);
 558        NV_WRITE_PIPE_INIT(0x00000000);
 559        NV_WRITE_PIPE_INIT(0x00000000);
 560        PIPE_INIT_END(0x6c00);
 561
 562        PIPE_INIT(0x7000);
 563        NV_WRITE_PIPE_INIT(0x00000000);
 564        NV_WRITE_PIPE_INIT(0x00000000);
 565        NV_WRITE_PIPE_INIT(0x00000000);
 566        NV_WRITE_PIPE_INIT(0x00000000);
 567        NV_WRITE_PIPE_INIT(0x00000000);
 568        NV_WRITE_PIPE_INIT(0x00000000);
 569        NV_WRITE_PIPE_INIT(0x00000000);
 570        NV_WRITE_PIPE_INIT(0x00000000);
 571        NV_WRITE_PIPE_INIT(0x00000000);
 572        NV_WRITE_PIPE_INIT(0x00000000);
 573        NV_WRITE_PIPE_INIT(0x00000000);
 574        NV_WRITE_PIPE_INIT(0x00000000);
 575        NV_WRITE_PIPE_INIT(0x7149f2ca);
 576        NV_WRITE_PIPE_INIT(0x00000000);
 577        NV_WRITE_PIPE_INIT(0x00000000);
 578        NV_WRITE_PIPE_INIT(0x00000000);
 579        NV_WRITE_PIPE_INIT(0x7149f2ca);
 580        NV_WRITE_PIPE_INIT(0x00000000);
 581        NV_WRITE_PIPE_INIT(0x00000000);
 582        NV_WRITE_PIPE_INIT(0x00000000);
 583        NV_WRITE_PIPE_INIT(0x7149f2ca);
 584        NV_WRITE_PIPE_INIT(0x00000000);
 585        NV_WRITE_PIPE_INIT(0x00000000);
 586        NV_WRITE_PIPE_INIT(0x00000000);
 587        NV_WRITE_PIPE_INIT(0x7149f2ca);
 588        NV_WRITE_PIPE_INIT(0x00000000);
 589        NV_WRITE_PIPE_INIT(0x00000000);
 590        NV_WRITE_PIPE_INIT(0x00000000);
 591        NV_WRITE_PIPE_INIT(0x7149f2ca);
 592        NV_WRITE_PIPE_INIT(0x00000000);
 593        NV_WRITE_PIPE_INIT(0x00000000);
 594        NV_WRITE_PIPE_INIT(0x00000000);
 595        NV_WRITE_PIPE_INIT(0x7149f2ca);
 596        NV_WRITE_PIPE_INIT(0x00000000);
 597        NV_WRITE_PIPE_INIT(0x00000000);
 598        NV_WRITE_PIPE_INIT(0x00000000);
 599        NV_WRITE_PIPE_INIT(0x7149f2ca);
 600        NV_WRITE_PIPE_INIT(0x00000000);
 601        NV_WRITE_PIPE_INIT(0x00000000);
 602        NV_WRITE_PIPE_INIT(0x00000000);
 603        NV_WRITE_PIPE_INIT(0x7149f2ca);
 604        for (i = 0; i < 35; i++)
 605                NV_WRITE_PIPE_INIT(0x00000000);
 606        PIPE_INIT_END(0x7000);
 607
 608        PIPE_INIT(0x7400);
 609        for (i = 0; i < 48; i++)
 610                NV_WRITE_PIPE_INIT(0x00000000);
 611        PIPE_INIT_END(0x7400);
 612
 613        PIPE_INIT(0x7800);
 614        for (i = 0; i < 48; i++)
 615                NV_WRITE_PIPE_INIT(0x00000000);
 616        PIPE_INIT_END(0x7800);
 617
 618        PIPE_INIT(0x4400);
 619        for (i = 0; i < 32; i++)
 620                NV_WRITE_PIPE_INIT(0x00000000);
 621        PIPE_INIT_END(0x4400);
 622
 623        PIPE_INIT(0x0000);
 624        for (i = 0; i < 16; i++)
 625                NV_WRITE_PIPE_INIT(0x00000000);
 626        PIPE_INIT_END(0x0000);
 627
 628        PIPE_INIT(0x0040);
 629        for (i = 0; i < 4; i++)
 630                NV_WRITE_PIPE_INIT(0x00000000);
 631        PIPE_INIT_END(0x0040);
 632
 633#undef PIPE_INIT
 634#undef PIPE_INIT_END
 635#undef NV_WRITE_PIPE_INIT
 636}
 637
 638static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
 639{
 640        int i;
 641        for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) {
 642                if (nv10_graph_ctx_regs[i] == reg)
 643                        return i;
 644        }
 645        NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg);
 646        return -1;
 647}
 648
 649static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
 650{
 651        int i;
 652        for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) {
 653                if (nv17_graph_ctx_regs[i] == reg)
 654                        return i;
 655        }
 656        NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg);
 657        return -1;
 658}
 659
 660static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
 661                                       uint32_t inst)
 662{
 663        struct drm_device *dev = chan->dev;
 664        struct drm_nouveau_private *dev_priv = dev->dev_private;
 665        struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 666        uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4];
 667        uint32_t ctx_user, ctx_switch[5];
 668        int i, subchan = -1;
 669
 670        /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state
 671         * that cannot be restored via MMIO. Do it through the FIFO
 672         * instead.
 673         */
 674
 675        /* Look for a celsius object */
 676        for (i = 0; i < 8; i++) {
 677                int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff;
 678
 679                if (class == 0x56 || class == 0x96 || class == 0x99) {
 680                        subchan = i;
 681                        break;
 682                }
 683        }
 684
 685        if (subchan < 0 || !inst)
 686                return;
 687
 688        /* Save the current ctx object */
 689        ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
 690        for (i = 0; i < 5; i++)
 691                ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i));
 692
 693        /* Save the FIFO state */
 694        st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2);
 695        st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL);
 696        st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH);
 697        fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR);
 698
 699        for (i = 0; i < ARRAY_SIZE(fifo); i++)
 700                fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i);
 701
 702        /* Switch to the celsius subchannel */
 703        for (i = 0; i < 5; i++)
 704                nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i),
 705                        nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i)));
 706        nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13);
 707
 708        /* Inject NV10TCL_DMA_VTXBUF */
 709        nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0);
 710        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2,
 711                0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
 712        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
 713        nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
 714        pgraph->fifo_access(dev, true);
 715        pgraph->fifo_access(dev, false);
 716
 717        /* Restore the FIFO state */
 718        for (i = 0; i < ARRAY_SIZE(fifo); i++)
 719                nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]);
 720
 721        nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr);
 722        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2);
 723        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl);
 724        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh);
 725
 726        /* Restore the current ctx object */
 727        for (i = 0; i < 5; i++)
 728                nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]);
 729        nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user);
 730}
 731
 732int nv10_graph_load_context(struct nouveau_channel *chan)
 733{
 734        struct drm_device *dev = chan->dev;
 735        struct drm_nouveau_private *dev_priv = dev->dev_private;
 736        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
 737        uint32_t tmp;
 738        int i;
 739
 740        for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
 741                nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]);
 742        if (dev_priv->chipset >= 0x17) {
 743                for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
 744                        nv_wr32(dev, nv17_graph_ctx_regs[i],
 745                                                pgraph_ctx->nv17[i]);
 746        }
 747
 748        nv10_graph_load_pipe(chan);
 749        nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1)
 750                                          & 0xffff));
 751
 752        nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
 753        tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
 754        nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24);
 755        tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2);
 756        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff);
 757        return 0;
 758}
 759
 760int
 761nv10_graph_unload_context(struct drm_device *dev)
 762{
 763        struct drm_nouveau_private *dev_priv = dev->dev_private;
 764        struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 765        struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
 766        struct nouveau_channel *chan;
 767        struct graph_state *ctx;
 768        uint32_t tmp;
 769        int i;
 770
 771        chan = pgraph->channel(dev);
 772        if (!chan)
 773                return 0;
 774        ctx = chan->pgraph_ctx;
 775
 776        for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
 777                ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]);
 778
 779        if (dev_priv->chipset >= 0x17) {
 780                for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
 781                        ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]);
 782        }
 783
 784        nv10_graph_save_pipe(chan);
 785
 786        nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
 787        tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
 788        tmp |= (pfifo->channels - 1) << 24;
 789        nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
 790        return 0;
 791}
 792
 793static void
 794nv10_graph_context_switch(struct drm_device *dev)
 795{
 796        struct drm_nouveau_private *dev_priv = dev->dev_private;
 797        struct nouveau_channel *chan = NULL;
 798        int chid;
 799
 800        nouveau_wait_for_idle(dev);
 801
 802        /* If previous context is valid, we need to save it */
 803        nv10_graph_unload_context(dev);
 804
 805        /* Load context for next channel */
 806        chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
 807        chan = dev_priv->channels.ptr[chid];
 808        if (chan && chan->pgraph_ctx)
 809                nv10_graph_load_context(chan);
 810}
 811
 812#define NV_WRITE_CTX(reg, val) do { \
 813        int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
 814        if (offset > 0) \
 815                pgraph_ctx->nv10[offset] = val; \
 816        } while (0)
 817
 818#define NV17_WRITE_CTX(reg, val) do { \
 819        int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \
 820        if (offset > 0) \
 821                pgraph_ctx->nv17[offset] = val; \
 822        } while (0)
 823
 824struct nouveau_channel *
 825nv10_graph_channel(struct drm_device *dev)
 826{
 827        struct drm_nouveau_private *dev_priv = dev->dev_private;
 828        int chid = dev_priv->engine.fifo.channels;
 829
 830        if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000)
 831                chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24;
 832
 833        if (chid >= dev_priv->engine.fifo.channels)
 834                return NULL;
 835
 836        return dev_priv->channels.ptr[chid];
 837}
 838
 839int nv10_graph_create_context(struct nouveau_channel *chan)
 840{
 841        struct drm_device *dev = chan->dev;
 842        struct drm_nouveau_private *dev_priv = dev->dev_private;
 843        struct graph_state *pgraph_ctx;
 844
 845        NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id);
 846
 847        chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx),
 848                                                GFP_KERNEL);
 849        if (pgraph_ctx == NULL)
 850                return -ENOMEM;
 851
 852
 853        NV_WRITE_CTX(0x00400e88, 0x08000000);
 854        NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
 855        NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
 856        NV_WRITE_CTX(0x00400e10, 0x00001000);
 857        NV_WRITE_CTX(0x00400e14, 0x00001000);
 858        NV_WRITE_CTX(0x00400e30, 0x00080008);
 859        NV_WRITE_CTX(0x00400e34, 0x00080008);
 860        if (dev_priv->chipset >= 0x17) {
 861                /* is it really needed ??? */
 862                NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
 863                                        nv_rd32(dev, NV10_PGRAPH_DEBUG_4));
 864                NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0));
 865                NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
 866                NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
 867                NV17_WRITE_CTX(0x00400ec0, 0x00000080);
 868                NV17_WRITE_CTX(0x00400ed0, 0x00000080);
 869        }
 870        NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24);
 871
 872        nv10_graph_create_pipe(chan);
 873        return 0;
 874}
 875
 876void nv10_graph_destroy_context(struct nouveau_channel *chan)
 877{
 878        struct drm_device *dev = chan->dev;
 879        struct drm_nouveau_private *dev_priv = dev->dev_private;
 880        struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 881        struct graph_state *pgraph_ctx = chan->pgraph_ctx;
 882        unsigned long flags;
 883
 884        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 885        pgraph->fifo_access(dev, false);
 886
 887        /* Unload the context if it's the currently active one */
 888        if (pgraph->channel(dev) == chan)
 889                pgraph->unload_context(dev);
 890
 891        /* Free the context resources */
 892        kfree(pgraph_ctx);
 893        chan->pgraph_ctx = NULL;
 894
 895        pgraph->fifo_access(dev, true);
 896        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 897}
 898
 899void
 900nv10_graph_set_tile_region(struct drm_device *dev, int i)
 901{
 902        struct drm_nouveau_private *dev_priv = dev->dev_private;
 903        struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
 904
 905        nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit);
 906        nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch);
 907        nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr);
 908}
 909
 910int nv10_graph_init(struct drm_device *dev)
 911{
 912        struct drm_nouveau_private *dev_priv = dev->dev_private;
 913        uint32_t tmp;
 914        int ret, i;
 915
 916        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
 917                        ~NV_PMC_ENABLE_PGRAPH);
 918        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
 919                         NV_PMC_ENABLE_PGRAPH);
 920
 921        ret = nv10_graph_register(dev);
 922        if (ret)
 923                return ret;
 924
 925        nouveau_irq_register(dev, 12, nv10_graph_isr);
 926        nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
 927        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 928
 929        nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
 930        nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
 931        nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700);
 932        /* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
 933        nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
 934        nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
 935                                      (1<<29) |
 936                                      (1<<31));
 937        if (dev_priv->chipset >= 0x17) {
 938                nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000);
 939                nv_wr32(dev, 0x400a10, 0x3ff3fb6);
 940                nv_wr32(dev, 0x400838, 0x2f8684);
 941                nv_wr32(dev, 0x40083c, 0x115f3f);
 942                nv_wr32(dev, 0x004006b0, 0x40000020);
 943        } else
 944                nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
 945
 946        /* Turn all the tiling regions off. */
 947        for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
 948                nv10_graph_set_tile_region(dev, i);
 949
 950        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000);
 951        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000);
 952        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000);
 953        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000);
 954        nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000);
 955        nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF);
 956
 957        tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
 958        tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
 959        nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
 960        nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
 961        nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
 962
 963        return 0;
 964}
 965
 966void nv10_graph_takedown(struct drm_device *dev)
 967{
 968        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
 969        nouveau_irq_unregister(dev, 12);
 970}
 971
 972static int
 973nv17_graph_mthd_lma_window(struct nouveau_channel *chan,
 974                           u32 class, u32 mthd, u32 data)
 975{
 976        struct drm_device *dev = chan->dev;
 977        struct graph_state *ctx = chan->pgraph_ctx;
 978        struct pipe_state *pipe = &ctx->pipe_state;
 979        uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
 980        uint32_t xfmode0, xfmode1;
 981        int i;
 982
 983        ctx->lma_window[(mthd - 0x1638) / 4] = data;
 984
 985        if (mthd != 0x1644)
 986                return 0;
 987
 988        nouveau_wait_for_idle(dev);
 989
 990        PIPE_SAVE(dev, pipe_0x0040, 0x0040);
 991        PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
 992
 993        PIPE_RESTORE(dev, ctx->lma_window, 0x6790);
 994
 995        nouveau_wait_for_idle(dev);
 996
 997        xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
 998        xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
 999
1000        PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
1001        PIPE_SAVE(dev, pipe_0x64c0, 0x64c0);
1002        PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0);
1003        PIPE_SAVE(dev, pipe_0x6a80, 0x6a80);
1004
1005        nouveau_wait_for_idle(dev);
1006
1007        nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
1008        nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
1009        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
1010        for (i = 0; i < 4; i++)
1011                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
1012        for (i = 0; i < 4; i++)
1013                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
1014
1015        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
1016        for (i = 0; i < 3; i++)
1017                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
1018
1019        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
1020        for (i = 0; i < 3; i++)
1021                nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
1022
1023        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
1024        nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
1025
1026        PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
1027
1028        nouveau_wait_for_idle(dev);
1029
1030        PIPE_RESTORE(dev, pipe_0x0040, 0x0040);
1031
1032        nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
1033        nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
1034
1035        PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0);
1036        PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0);
1037        PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80);
1038        PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
1039
1040        nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
1041        nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
1042
1043        nouveau_wait_for_idle(dev);
1044
1045        return 0;
1046}
1047
1048static int
1049nv17_graph_mthd_lma_enable(struct nouveau_channel *chan,
1050                           u32 class, u32 mthd, u32 data)
1051{
1052        struct drm_device *dev = chan->dev;
1053
1054        nouveau_wait_for_idle(dev);
1055
1056        nv_wr32(dev, NV10_PGRAPH_DEBUG_4,
1057                nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8);
1058        nv_wr32(dev, 0x004006b0,
1059                nv_rd32(dev, 0x004006b0) | 0x8 << 24);
1060
1061        return 0;
1062}
1063
1064static int
1065nv10_graph_register(struct drm_device *dev)
1066{
1067        struct drm_nouveau_private *dev_priv = dev->dev_private;
1068
1069        if (dev_priv->engine.graph.registered)
1070                return 0;
1071
1072        NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
1073        NVOBJ_CLASS(dev, 0x0030, GR); /* null */
1074        NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
1075        NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
1076        NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */
1077        NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
1078        NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
1079        NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
1080        NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
1081        NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
1082        NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
1083        NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
1084        NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
1085        NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
1086        NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */
1087        NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */
1088        NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */
1089        NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */
1090
1091        /* celcius */
1092        if (dev_priv->chipset <= 0x10) {
1093                NVOBJ_CLASS(dev, 0x0056, GR);
1094        } else
1095        if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) {
1096                NVOBJ_CLASS(dev, 0x0096, GR);
1097        } else {
1098                NVOBJ_CLASS(dev, 0x0099, GR);
1099                NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window);
1100                NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window);
1101                NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window);
1102                NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window);
1103                NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable);
1104        }
1105
1106        /* nvsw */
1107        NVOBJ_CLASS(dev, 0x506e, SW);
1108        NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
1109
1110        dev_priv->engine.graph.registered = true;
1111        return 0;
1112}
1113
1114struct nouveau_bitfield nv10_graph_intr[] = {
1115        { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1116        { NV_PGRAPH_INTR_ERROR,  "ERROR"  },
1117        {}
1118};
1119
1120struct nouveau_bitfield nv10_graph_nstatus[] =
1121{
1122        { NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
1123        { NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
1124        { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
1125        { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
1126        {}
1127};
1128
1129static void
1130nv10_graph_isr(struct drm_device *dev)
1131{
1132        u32 stat;
1133
1134        while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1135                u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
1136                u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
1137                u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
1138                u32 chid = (addr & 0x01f00000) >> 20;
1139                u32 subc = (addr & 0x00070000) >> 16;
1140                u32 mthd = (addr & 0x00001ffc);
1141                u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
1142                u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
1143                u32 show = stat;
1144
1145                if (stat & NV_PGRAPH_INTR_ERROR) {
1146                        if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
1147                                if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
1148                                        show &= ~NV_PGRAPH_INTR_ERROR;
1149                        }
1150                }
1151
1152                if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1153                        nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1154                        stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1155                        show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1156                        nv10_graph_context_switch(dev);
1157                }
1158
1159                nv_wr32(dev, NV03_PGRAPH_INTR, stat);
1160                nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
1161
1162                if (show && nouveau_ratelimit()) {
1163                        NV_INFO(dev, "PGRAPH -");
1164                        nouveau_bitfield_print(nv10_graph_intr, show);
1165                        printk(" nsource:");
1166                        nouveau_bitfield_print(nv04_graph_nsource, nsource);
1167                        printk(" nstatus:");
1168                        nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
1169                        printk("\n");
1170                        NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
1171                                     "mthd 0x%04x data 0x%08x\n",
1172                                chid, subc, class, mthd, data);
1173                }
1174        }
1175}
1176
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.