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