linux/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
<<
>>
Prefs
   1/*
   2 * Copyright 2007 Stephane Marchesin
   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 "priv.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/instmem.h>
  32#include <subdev/timer.h>
  33
  34static u32
  35nv04_gr_ctx_regs[] = {
  36        0x0040053c,
  37        0x00400544,
  38        0x00400540,
  39        0x00400548,
  40        NV04_PGRAPH_CTX_SWITCH1,
  41        NV04_PGRAPH_CTX_SWITCH2,
  42        NV04_PGRAPH_CTX_SWITCH3,
  43        NV04_PGRAPH_CTX_SWITCH4,
  44        NV04_PGRAPH_CTX_CACHE1,
  45        NV04_PGRAPH_CTX_CACHE2,
  46        NV04_PGRAPH_CTX_CACHE3,
  47        NV04_PGRAPH_CTX_CACHE4,
  48        0x00400184,
  49        0x004001a4,
  50        0x004001c4,
  51        0x004001e4,
  52        0x00400188,
  53        0x004001a8,
  54        0x004001c8,
  55        0x004001e8,
  56        0x0040018c,
  57        0x004001ac,
  58        0x004001cc,
  59        0x004001ec,
  60        0x00400190,
  61        0x004001b0,
  62        0x004001d0,
  63        0x004001f0,
  64        0x00400194,
  65        0x004001b4,
  66        0x004001d4,
  67        0x004001f4,
  68        0x00400198,
  69        0x004001b8,
  70        0x004001d8,
  71        0x004001f8,
  72        0x0040019c,
  73        0x004001bc,
  74        0x004001dc,
  75        0x004001fc,
  76        0x00400174,
  77        NV04_PGRAPH_DMA_START_0,
  78        NV04_PGRAPH_DMA_START_1,
  79        NV04_PGRAPH_DMA_LENGTH,
  80        NV04_PGRAPH_DMA_MISC,
  81        NV04_PGRAPH_DMA_PITCH,
  82        NV04_PGRAPH_BOFFSET0,
  83        NV04_PGRAPH_BBASE0,
  84        NV04_PGRAPH_BLIMIT0,
  85        NV04_PGRAPH_BOFFSET1,
  86        NV04_PGRAPH_BBASE1,
  87        NV04_PGRAPH_BLIMIT1,
  88        NV04_PGRAPH_BOFFSET2,
  89        NV04_PGRAPH_BBASE2,
  90        NV04_PGRAPH_BLIMIT2,
  91        NV04_PGRAPH_BOFFSET3,
  92        NV04_PGRAPH_BBASE3,
  93        NV04_PGRAPH_BLIMIT3,
  94        NV04_PGRAPH_BOFFSET4,
  95        NV04_PGRAPH_BBASE4,
  96        NV04_PGRAPH_BLIMIT4,
  97        NV04_PGRAPH_BOFFSET5,
  98        NV04_PGRAPH_BBASE5,
  99        NV04_PGRAPH_BLIMIT5,
 100        NV04_PGRAPH_BPITCH0,
 101        NV04_PGRAPH_BPITCH1,
 102        NV04_PGRAPH_BPITCH2,
 103        NV04_PGRAPH_BPITCH3,
 104        NV04_PGRAPH_BPITCH4,
 105        NV04_PGRAPH_SURFACE,
 106        NV04_PGRAPH_STATE,
 107        NV04_PGRAPH_BSWIZZLE2,
 108        NV04_PGRAPH_BSWIZZLE5,
 109        NV04_PGRAPH_BPIXEL,
 110        NV04_PGRAPH_NOTIFY,
 111        NV04_PGRAPH_PATT_COLOR0,
 112        NV04_PGRAPH_PATT_COLOR1,
 113        NV04_PGRAPH_PATT_COLORRAM+0x00,
 114        NV04_PGRAPH_PATT_COLORRAM+0x04,
 115        NV04_PGRAPH_PATT_COLORRAM+0x08,
 116        NV04_PGRAPH_PATT_COLORRAM+0x0c,
 117        NV04_PGRAPH_PATT_COLORRAM+0x10,
 118        NV04_PGRAPH_PATT_COLORRAM+0x14,
 119        NV04_PGRAPH_PATT_COLORRAM+0x18,
 120        NV04_PGRAPH_PATT_COLORRAM+0x1c,
 121        NV04_PGRAPH_PATT_COLORRAM+0x20,
 122        NV04_PGRAPH_PATT_COLORRAM+0x24,
 123        NV04_PGRAPH_PATT_COLORRAM+0x28,
 124        NV04_PGRAPH_PATT_COLORRAM+0x2c,
 125        NV04_PGRAPH_PATT_COLORRAM+0x30,
 126        NV04_PGRAPH_PATT_COLORRAM+0x34,
 127        NV04_PGRAPH_PATT_COLORRAM+0x38,
 128        NV04_PGRAPH_PATT_COLORRAM+0x3c,
 129        NV04_PGRAPH_PATT_COLORRAM+0x40,
 130        NV04_PGRAPH_PATT_COLORRAM+0x44,
 131        NV04_PGRAPH_PATT_COLORRAM+0x48,
 132        NV04_PGRAPH_PATT_COLORRAM+0x4c,
 133        NV04_PGRAPH_PATT_COLORRAM+0x50,
 134        NV04_PGRAPH_PATT_COLORRAM+0x54,
 135        NV04_PGRAPH_PATT_COLORRAM+0x58,
 136        NV04_PGRAPH_PATT_COLORRAM+0x5c,
 137        NV04_PGRAPH_PATT_COLORRAM+0x60,
 138        NV04_PGRAPH_PATT_COLORRAM+0x64,
 139        NV04_PGRAPH_PATT_COLORRAM+0x68,
 140        NV04_PGRAPH_PATT_COLORRAM+0x6c,
 141        NV04_PGRAPH_PATT_COLORRAM+0x70,
 142        NV04_PGRAPH_PATT_COLORRAM+0x74,
 143        NV04_PGRAPH_PATT_COLORRAM+0x78,
 144        NV04_PGRAPH_PATT_COLORRAM+0x7c,
 145        NV04_PGRAPH_PATT_COLORRAM+0x80,
 146        NV04_PGRAPH_PATT_COLORRAM+0x84,
 147        NV04_PGRAPH_PATT_COLORRAM+0x88,
 148        NV04_PGRAPH_PATT_COLORRAM+0x8c,
 149        NV04_PGRAPH_PATT_COLORRAM+0x90,
 150        NV04_PGRAPH_PATT_COLORRAM+0x94,
 151        NV04_PGRAPH_PATT_COLORRAM+0x98,
 152        NV04_PGRAPH_PATT_COLORRAM+0x9c,
 153        NV04_PGRAPH_PATT_COLORRAM+0xa0,
 154        NV04_PGRAPH_PATT_COLORRAM+0xa4,
 155        NV04_PGRAPH_PATT_COLORRAM+0xa8,
 156        NV04_PGRAPH_PATT_COLORRAM+0xac,
 157        NV04_PGRAPH_PATT_COLORRAM+0xb0,
 158        NV04_PGRAPH_PATT_COLORRAM+0xb4,
 159        NV04_PGRAPH_PATT_COLORRAM+0xb8,
 160        NV04_PGRAPH_PATT_COLORRAM+0xbc,
 161        NV04_PGRAPH_PATT_COLORRAM+0xc0,
 162        NV04_PGRAPH_PATT_COLORRAM+0xc4,
 163        NV04_PGRAPH_PATT_COLORRAM+0xc8,
 164        NV04_PGRAPH_PATT_COLORRAM+0xcc,
 165        NV04_PGRAPH_PATT_COLORRAM+0xd0,
 166        NV04_PGRAPH_PATT_COLORRAM+0xd4,
 167        NV04_PGRAPH_PATT_COLORRAM+0xd8,
 168        NV04_PGRAPH_PATT_COLORRAM+0xdc,
 169        NV04_PGRAPH_PATT_COLORRAM+0xe0,
 170        NV04_PGRAPH_PATT_COLORRAM+0xe4,
 171        NV04_PGRAPH_PATT_COLORRAM+0xe8,
 172        NV04_PGRAPH_PATT_COLORRAM+0xec,
 173        NV04_PGRAPH_PATT_COLORRAM+0xf0,
 174        NV04_PGRAPH_PATT_COLORRAM+0xf4,
 175        NV04_PGRAPH_PATT_COLORRAM+0xf8,
 176        NV04_PGRAPH_PATT_COLORRAM+0xfc,
 177        NV04_PGRAPH_PATTERN,
 178        0x0040080c,
 179        NV04_PGRAPH_PATTERN_SHAPE,
 180        0x00400600,
 181        NV04_PGRAPH_ROP3,
 182        NV04_PGRAPH_CHROMA,
 183        NV04_PGRAPH_BETA_AND,
 184        NV04_PGRAPH_BETA_PREMULT,
 185        NV04_PGRAPH_CONTROL0,
 186        NV04_PGRAPH_CONTROL1,
 187        NV04_PGRAPH_CONTROL2,
 188        NV04_PGRAPH_BLEND,
 189        NV04_PGRAPH_STORED_FMT,
 190        NV04_PGRAPH_SOURCE_COLOR,
 191        0x00400560,
 192        0x00400568,
 193        0x00400564,
 194        0x0040056c,
 195        0x00400400,
 196        0x00400480,
 197        0x00400404,
 198        0x00400484,
 199        0x00400408,
 200        0x00400488,
 201        0x0040040c,
 202        0x0040048c,
 203        0x00400410,
 204        0x00400490,
 205        0x00400414,
 206        0x00400494,
 207        0x00400418,
 208        0x00400498,
 209        0x0040041c,
 210        0x0040049c,
 211        0x00400420,
 212        0x004004a0,
 213        0x00400424,
 214        0x004004a4,
 215        0x00400428,
 216        0x004004a8,
 217        0x0040042c,
 218        0x004004ac,
 219        0x00400430,
 220        0x004004b0,
 221        0x00400434,
 222        0x004004b4,
 223        0x00400438,
 224        0x004004b8,
 225        0x0040043c,
 226        0x004004bc,
 227        0x00400440,
 228        0x004004c0,
 229        0x00400444,
 230        0x004004c4,
 231        0x00400448,
 232        0x004004c8,
 233        0x0040044c,
 234        0x004004cc,
 235        0x00400450,
 236        0x004004d0,
 237        0x00400454,
 238        0x004004d4,
 239        0x00400458,
 240        0x004004d8,
 241        0x0040045c,
 242        0x004004dc,
 243        0x00400460,
 244        0x004004e0,
 245        0x00400464,
 246        0x004004e4,
 247        0x00400468,
 248        0x004004e8,
 249        0x0040046c,
 250        0x004004ec,
 251        0x00400470,
 252        0x004004f0,
 253        0x00400474,
 254        0x004004f4,
 255        0x00400478,
 256        0x004004f8,
 257        0x0040047c,
 258        0x004004fc,
 259        0x00400534,
 260        0x00400538,
 261        0x00400514,
 262        0x00400518,
 263        0x0040051c,
 264        0x00400520,
 265        0x00400524,
 266        0x00400528,
 267        0x0040052c,
 268        0x00400530,
 269        0x00400d00,
 270        0x00400d40,
 271        0x00400d80,
 272        0x00400d04,
 273        0x00400d44,
 274        0x00400d84,
 275        0x00400d08,
 276        0x00400d48,
 277        0x00400d88,
 278        0x00400d0c,
 279        0x00400d4c,
 280        0x00400d8c,
 281        0x00400d10,
 282        0x00400d50,
 283        0x00400d90,
 284        0x00400d14,
 285        0x00400d54,
 286        0x00400d94,
 287        0x00400d18,
 288        0x00400d58,
 289        0x00400d98,
 290        0x00400d1c,
 291        0x00400d5c,
 292        0x00400d9c,
 293        0x00400d20,
 294        0x00400d60,
 295        0x00400da0,
 296        0x00400d24,
 297        0x00400d64,
 298        0x00400da4,
 299        0x00400d28,
 300        0x00400d68,
 301        0x00400da8,
 302        0x00400d2c,
 303        0x00400d6c,
 304        0x00400dac,
 305        0x00400d30,
 306        0x00400d70,
 307        0x00400db0,
 308        0x00400d34,
 309        0x00400d74,
 310        0x00400db4,
 311        0x00400d38,
 312        0x00400d78,
 313        0x00400db8,
 314        0x00400d3c,
 315        0x00400d7c,
 316        0x00400dbc,
 317        0x00400590,
 318        0x00400594,
 319        0x00400598,
 320        0x0040059c,
 321        0x004005a8,
 322        0x004005ac,
 323        0x004005b0,
 324        0x004005b4,
 325        0x004005c0,
 326        0x004005c4,
 327        0x004005c8,
 328        0x004005cc,
 329        0x004005d0,
 330        0x004005d4,
 331        0x004005d8,
 332        0x004005dc,
 333        0x004005e0,
 334        NV04_PGRAPH_PASSTHRU_0,
 335        NV04_PGRAPH_PASSTHRU_1,
 336        NV04_PGRAPH_PASSTHRU_2,
 337        NV04_PGRAPH_DVD_COLORFMT,
 338        NV04_PGRAPH_SCALED_FORMAT,
 339        NV04_PGRAPH_MISC24_0,
 340        NV04_PGRAPH_MISC24_1,
 341        NV04_PGRAPH_MISC24_2,
 342        0x00400500,
 343        0x00400504,
 344        NV04_PGRAPH_VALID1,
 345        NV04_PGRAPH_VALID2,
 346        NV04_PGRAPH_DEBUG_3
 347};
 348
 349#define nv04_gr(p) container_of((p), struct nv04_gr, base)
 350
 351struct nv04_gr {
 352        struct nvkm_gr base;
 353        struct nv04_gr_chan *chan[16];
 354        spinlock_t lock;
 355};
 356
 357#define nv04_gr_chan(p) container_of((p), struct nv04_gr_chan, object)
 358
 359struct nv04_gr_chan {
 360        struct nvkm_object object;
 361        struct nv04_gr *gr;
 362        int chid;
 363        u32 nv04[ARRAY_SIZE(nv04_gr_ctx_regs)];
 364};
 365
 366/*******************************************************************************
 367 * Graphics object classes
 368 ******************************************************************************/
 369
 370/*
 371 * Software methods, why they are needed, and how they all work:
 372 *
 373 * NV04 and NV05 keep most of the state in PGRAPH context itself, but some
 374 * 2d engine settings are kept inside the grobjs themselves. The grobjs are
 375 * 3 words long on both. grobj format on NV04 is:
 376 *
 377 * word 0:
 378 *  - bits 0-7: class
 379 *  - bit 12: color key active
 380 *  - bit 13: clip rect active
 381 *  - bit 14: if set, destination surface is swizzled and taken from buffer 5
 382 *            [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
 383 *            from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
 384 *            NV03_CONTEXT_SURFACE_DST].
 385 *  - bits 15-17: 2d operation [aka patch config]
 386 *  - bit 24: patch valid [enables rendering using this object]
 387 *  - bit 25: surf3d valid [for tex_tri and multitex_tri only]
 388 * word 1:
 389 *  - bits 0-1: mono format
 390 *  - bits 8-13: color format
 391 *  - bits 16-31: DMA_NOTIFY instance
 392 * word 2:
 393 *  - bits 0-15: DMA_A instance
 394 *  - bits 16-31: DMA_B instance
 395 *
 396 * On NV05 it's:
 397 *
 398 * word 0:
 399 *  - bits 0-7: class
 400 *  - bit 12: color key active
 401 *  - bit 13: clip rect active
 402 *  - bit 14: if set, destination surface is swizzled and taken from buffer 5
 403 *            [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
 404 *            from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
 405 *            NV03_CONTEXT_SURFACE_DST].
 406 *  - bits 15-17: 2d operation [aka patch config]
 407 *  - bits 20-22: dither mode
 408 *  - bit 24: patch valid [enables rendering using this object]
 409 *  - bit 25: surface_dst/surface_color/surf2d/surf3d valid
 410 *  - bit 26: surface_src/surface_zeta valid
 411 *  - bit 27: pattern valid
 412 *  - bit 28: rop valid
 413 *  - bit 29: beta1 valid
 414 *  - bit 30: beta4 valid
 415 * word 1:
 416 *  - bits 0-1: mono format
 417 *  - bits 8-13: color format
 418 *  - bits 16-31: DMA_NOTIFY instance
 419 * word 2:
 420 *  - bits 0-15: DMA_A instance
 421 *  - bits 16-31: DMA_B instance
 422 *
 423 * NV05 will set/unset the relevant valid bits when you poke the relevant
 424 * object-binding methods with object of the proper type, or with the NULL
 425 * type. It'll only allow rendering using the grobj if all needed objects
 426 * are bound. The needed set of objects depends on selected operation: for
 427 * example rop object is needed by ROP_AND, but not by SRCCOPY_AND.
 428 *
 429 * NV04 doesn't have these methods implemented at all, and doesn't have the
 430 * relevant bits in grobj. Instead, it'll allow rendering whenever bit 24
 431 * is set. So we have to emulate them in software, internally keeping the
 432 * same bits as NV05 does. Since grobjs are aligned to 16 bytes on nv04,
 433 * but the last word isn't actually used for anything, we abuse it for this
 434 * purpose.
 435 *
 436 * Actually, NV05 can optionally check bit 24 too, but we disable this since
 437 * there's no use for it.
 438 *
 439 * For unknown reasons, NV04 implements surf3d binding in hardware as an
 440 * exception. Also for unknown reasons, NV04 doesn't implement the clipping
 441 * methods on the surf3d object, so we have to emulate them too.
 442 */
 443
 444static void
 445nv04_gr_set_ctx1(struct nvkm_device *device, u32 inst, u32 mask, u32 value)
 446{
 447        int subc = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
 448        u32 tmp;
 449
 450        tmp  = nvkm_rd32(device, 0x700000 + inst);
 451        tmp &= ~mask;
 452        tmp |= value;
 453        nvkm_wr32(device, 0x700000 + inst, tmp);
 454
 455        nvkm_wr32(device, NV04_PGRAPH_CTX_SWITCH1, tmp);
 456        nvkm_wr32(device, NV04_PGRAPH_CTX_CACHE1 + (subc << 2), tmp);
 457}
 458
 459static void
 460nv04_gr_set_ctx_val(struct nvkm_device *device, u32 inst, u32 mask, u32 value)
 461{
 462        int class, op, valid = 1;
 463        u32 tmp, ctx1;
 464
 465        ctx1 = nvkm_rd32(device, 0x700000 + inst);
 466        class = ctx1 & 0xff;
 467        op = (ctx1 >> 15) & 7;
 468
 469        tmp = nvkm_rd32(device, 0x70000c + inst);
 470        tmp &= ~mask;
 471        tmp |= value;
 472        nvkm_wr32(device, 0x70000c + inst, tmp);
 473
 474        /* check for valid surf2d/surf_dst/surf_color */
 475        if (!(tmp & 0x02000000))
 476                valid = 0;
 477        /* check for valid surf_src/surf_zeta */
 478        if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000))
 479                valid = 0;
 480
 481        switch (op) {
 482        /* SRCCOPY_AND, SRCCOPY: no extra objects required */
 483        case 0:
 484        case 3:
 485                break;
 486        /* ROP_AND: requires pattern and rop */
 487        case 1:
 488                if (!(tmp & 0x18000000))
 489                        valid = 0;
 490                break;
 491        /* BLEND_AND: requires beta1 */
 492        case 2:
 493                if (!(tmp & 0x20000000))
 494                        valid = 0;
 495                break;
 496        /* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */
 497        case 4:
 498        case 5:
 499                if (!(tmp & 0x40000000))
 500                        valid = 0;
 501                break;
 502        }
 503
 504        nv04_gr_set_ctx1(device, inst, 0x01000000, valid << 24);
 505}
 506
 507static bool
 508nv04_gr_mthd_set_operation(struct nvkm_device *device, u32 inst, u32 data)
 509{
 510        u8 class = nvkm_rd32(device, 0x700000) & 0x000000ff;
 511        if (data > 5)
 512                return false;
 513        /* Old versions of the objects only accept first three operations. */
 514        if (data > 2 && class < 0x40)
 515                return false;
 516        nv04_gr_set_ctx1(device, inst, 0x00038000, data << 15);
 517        /* changing operation changes set of objects needed for validation */
 518        nv04_gr_set_ctx_val(device, inst, 0, 0);
 519        return true;
 520}
 521
 522static bool
 523nv04_gr_mthd_surf3d_clip_h(struct nvkm_device *device, u32 inst, u32 data)
 524{
 525        u32 min = data & 0xffff, max;
 526        u32 w = data >> 16;
 527        if (min & 0x8000)
 528                /* too large */
 529                return false;
 530        if (w & 0x8000)
 531                /* yes, it accepts negative for some reason. */
 532                w |= 0xffff0000;
 533        max = min + w;
 534        max &= 0x3ffff;
 535        nvkm_wr32(device, 0x40053c, min);
 536        nvkm_wr32(device, 0x400544, max);
 537        return true;
 538}
 539
 540static bool
 541nv04_gr_mthd_surf3d_clip_v(struct nvkm_device *device, u32 inst, u32 data)
 542{
 543        u32 min = data & 0xffff, max;
 544        u32 w = data >> 16;
 545        if (min & 0x8000)
 546                /* too large */
 547                return false;
 548        if (w & 0x8000)
 549                /* yes, it accepts negative for some reason. */
 550                w |= 0xffff0000;
 551        max = min + w;
 552        max &= 0x3ffff;
 553        nvkm_wr32(device, 0x400540, min);
 554        nvkm_wr32(device, 0x400548, max);
 555        return true;
 556}
 557
 558static u8
 559nv04_gr_mthd_bind_class(struct nvkm_device *device, u32 inst)
 560{
 561        return nvkm_rd32(device, 0x700000 + (inst << 4));
 562}
 563
 564static bool
 565nv04_gr_mthd_bind_surf2d(struct nvkm_device *device, u32 inst, u32 data)
 566{
 567        switch (nv04_gr_mthd_bind_class(device, data)) {
 568        case 0x30:
 569                nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
 570                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
 571                return true;
 572        case 0x42:
 573                nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
 574                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
 575                return true;
 576        }
 577        return false;
 578}
 579
 580static bool
 581nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_device *device, u32 inst, u32 data)
 582{
 583        switch (nv04_gr_mthd_bind_class(device, data)) {
 584        case 0x30:
 585                nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
 586                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
 587                return true;
 588        case 0x42:
 589                nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
 590                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
 591                return true;
 592        case 0x52:
 593                nv04_gr_set_ctx1(device, inst, 0x00004000, 0x00004000);
 594                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
 595                return true;
 596        }
 597        return false;
 598}
 599
 600static bool
 601nv01_gr_mthd_bind_patt(struct nvkm_device *device, u32 inst, u32 data)
 602{
 603        switch (nv04_gr_mthd_bind_class(device, data)) {
 604        case 0x30:
 605                nv04_gr_set_ctx_val(device, inst, 0x08000000, 0);
 606                return true;
 607        case 0x18:
 608                nv04_gr_set_ctx_val(device, inst, 0x08000000, 0x08000000);
 609                return true;
 610        }
 611        return false;
 612}
 613
 614static bool
 615nv04_gr_mthd_bind_patt(struct nvkm_device *device, u32 inst, u32 data)
 616{
 617        switch (nv04_gr_mthd_bind_class(device, data)) {
 618        case 0x30:
 619                nv04_gr_set_ctx_val(device, inst, 0x08000000, 0);
 620                return true;
 621        case 0x44:
 622                nv04_gr_set_ctx_val(device, inst, 0x08000000, 0x08000000);
 623                return true;
 624        }
 625        return false;
 626}
 627
 628static bool
 629nv04_gr_mthd_bind_rop(struct nvkm_device *device, u32 inst, u32 data)
 630{
 631        switch (nv04_gr_mthd_bind_class(device, data)) {
 632        case 0x30:
 633                nv04_gr_set_ctx_val(device, inst, 0x10000000, 0);
 634                return true;
 635        case 0x43:
 636                nv04_gr_set_ctx_val(device, inst, 0x10000000, 0x10000000);
 637                return true;
 638        }
 639        return false;
 640}
 641
 642static bool
 643nv04_gr_mthd_bind_beta1(struct nvkm_device *device, u32 inst, u32 data)
 644{
 645        switch (nv04_gr_mthd_bind_class(device, data)) {
 646        case 0x30:
 647                nv04_gr_set_ctx_val(device, inst, 0x20000000, 0);
 648                return true;
 649        case 0x12:
 650                nv04_gr_set_ctx_val(device, inst, 0x20000000, 0x20000000);
 651                return true;
 652        }
 653        return false;
 654}
 655
 656static bool
 657nv04_gr_mthd_bind_beta4(struct nvkm_device *device, u32 inst, u32 data)
 658{
 659        switch (nv04_gr_mthd_bind_class(device, data)) {
 660        case 0x30:
 661                nv04_gr_set_ctx_val(device, inst, 0x40000000, 0);
 662                return true;
 663        case 0x72:
 664                nv04_gr_set_ctx_val(device, inst, 0x40000000, 0x40000000);
 665                return true;
 666        }
 667        return false;
 668}
 669
 670static bool
 671nv04_gr_mthd_bind_surf_dst(struct nvkm_device *device, u32 inst, u32 data)
 672{
 673        switch (nv04_gr_mthd_bind_class(device, data)) {
 674        case 0x30:
 675                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
 676                return true;
 677        case 0x58:
 678                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
 679                return true;
 680        }
 681        return false;
 682}
 683
 684static bool
 685nv04_gr_mthd_bind_surf_src(struct nvkm_device *device, u32 inst, u32 data)
 686{
 687        switch (nv04_gr_mthd_bind_class(device, data)) {
 688        case 0x30:
 689                nv04_gr_set_ctx_val(device, inst, 0x04000000, 0);
 690                return true;
 691        case 0x59:
 692                nv04_gr_set_ctx_val(device, inst, 0x04000000, 0x04000000);
 693                return true;
 694        }
 695        return false;
 696}
 697
 698static bool
 699nv04_gr_mthd_bind_surf_color(struct nvkm_device *device, u32 inst, u32 data)
 700{
 701        switch (nv04_gr_mthd_bind_class(device, data)) {
 702        case 0x30:
 703                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
 704                return true;
 705        case 0x5a:
 706                nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
 707                return true;
 708        }
 709        return false;
 710}
 711
 712static bool
 713nv04_gr_mthd_bind_surf_zeta(struct nvkm_device *device, u32 inst, u32 data)
 714{
 715        switch (nv04_gr_mthd_bind_class(device, data)) {
 716        case 0x30:
 717                nv04_gr_set_ctx_val(device, inst, 0x04000000, 0);
 718                return true;
 719        case 0x5b:
 720                nv04_gr_set_ctx_val(device, inst, 0x04000000, 0x04000000);
 721                return true;
 722        }
 723        return false;
 724}
 725
 726static bool
 727nv01_gr_mthd_bind_clip(struct nvkm_device *device, u32 inst, u32 data)
 728{
 729        switch (nv04_gr_mthd_bind_class(device, data)) {
 730        case 0x30:
 731                nv04_gr_set_ctx1(device, inst, 0x2000, 0);
 732                return true;
 733        case 0x19:
 734                nv04_gr_set_ctx1(device, inst, 0x2000, 0x2000);
 735                return true;
 736        }
 737        return false;
 738}
 739
 740static bool
 741nv01_gr_mthd_bind_chroma(struct nvkm_device *device, u32 inst, u32 data)
 742{
 743        switch (nv04_gr_mthd_bind_class(device, data)) {
 744        case 0x30:
 745                nv04_gr_set_ctx1(device, inst, 0x1000, 0);
 746                return true;
 747        /* Yes, for some reason even the old versions of objects
 748         * accept 0x57 and not 0x17. Consistency be damned.
 749         */
 750        case 0x57:
 751                nv04_gr_set_ctx1(device, inst, 0x1000, 0x1000);
 752                return true;
 753        }
 754        return false;
 755}
 756
 757static bool
 758nv03_gr_mthd_gdi(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 759{
 760        bool (*func)(struct nvkm_device *, u32, u32);
 761        switch (mthd) {
 762        case 0x0184: func = nv01_gr_mthd_bind_patt; break;
 763        case 0x0188: func = nv04_gr_mthd_bind_rop; break;
 764        case 0x018c: func = nv04_gr_mthd_bind_beta1; break;
 765        case 0x0190: func = nv04_gr_mthd_bind_surf_dst; break;
 766        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 767        default:
 768                return false;
 769        }
 770        return func(device, inst, data);
 771}
 772
 773static bool
 774nv04_gr_mthd_gdi(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 775{
 776        bool (*func)(struct nvkm_device *, u32, u32);
 777        switch (mthd) {
 778        case 0x0188: func = nv04_gr_mthd_bind_patt; break;
 779        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
 780        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
 781        case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
 782        case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
 783        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 784        default:
 785                return false;
 786        }
 787        return func(device, inst, data);
 788}
 789
 790static bool
 791nv01_gr_mthd_blit(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 792{
 793        bool (*func)(struct nvkm_device *, u32, u32);
 794        switch (mthd) {
 795        case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
 796        case 0x0188: func = nv01_gr_mthd_bind_clip; break;
 797        case 0x018c: func = nv01_gr_mthd_bind_patt; break;
 798        case 0x0190: func = nv04_gr_mthd_bind_rop; break;
 799        case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
 800        case 0x0198: func = nv04_gr_mthd_bind_surf_dst; break;
 801        case 0x019c: func = nv04_gr_mthd_bind_surf_src; break;
 802        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 803        default:
 804                return false;
 805        }
 806        return func(device, inst, data);
 807}
 808
 809static bool
 810nv04_gr_mthd_blit(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 811{
 812        bool (*func)(struct nvkm_device *, u32, u32);
 813        switch (mthd) {
 814        case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
 815        case 0x0188: func = nv01_gr_mthd_bind_clip; break;
 816        case 0x018c: func = nv04_gr_mthd_bind_patt; break;
 817        case 0x0190: func = nv04_gr_mthd_bind_rop; break;
 818        case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
 819        case 0x0198: func = nv04_gr_mthd_bind_beta4; break;
 820        case 0x019c: func = nv04_gr_mthd_bind_surf2d; break;
 821        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 822        default:
 823                return false;
 824        }
 825        return func(device, inst, data);
 826}
 827
 828static bool
 829nv04_gr_mthd_iifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 830{
 831        bool (*func)(struct nvkm_device *, u32, u32);
 832        switch (mthd) {
 833        case 0x0188: func = nv01_gr_mthd_bind_chroma; break;
 834        case 0x018c: func = nv01_gr_mthd_bind_clip; break;
 835        case 0x0190: func = nv04_gr_mthd_bind_patt; break;
 836        case 0x0194: func = nv04_gr_mthd_bind_rop; break;
 837        case 0x0198: func = nv04_gr_mthd_bind_beta1; break;
 838        case 0x019c: func = nv04_gr_mthd_bind_beta4; break;
 839        case 0x01a0: func = nv04_gr_mthd_bind_surf2d_swzsurf; break;
 840        case 0x03e4: func = nv04_gr_mthd_set_operation; break;
 841        default:
 842                return false;
 843        }
 844        return func(device, inst, data);
 845}
 846
 847static bool
 848nv01_gr_mthd_ifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 849{
 850        bool (*func)(struct nvkm_device *, u32, u32);
 851        switch (mthd) {
 852        case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
 853        case 0x0188: func = nv01_gr_mthd_bind_clip; break;
 854        case 0x018c: func = nv01_gr_mthd_bind_patt; break;
 855        case 0x0190: func = nv04_gr_mthd_bind_rop; break;
 856        case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
 857        case 0x0198: func = nv04_gr_mthd_bind_surf_dst; break;
 858        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 859        default:
 860                return false;
 861        }
 862        return func(device, inst, data);
 863}
 864
 865static bool
 866nv04_gr_mthd_ifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 867{
 868        bool (*func)(struct nvkm_device *, u32, u32);
 869        switch (mthd) {
 870        case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
 871        case 0x0188: func = nv01_gr_mthd_bind_clip; break;
 872        case 0x018c: func = nv04_gr_mthd_bind_patt; break;
 873        case 0x0190: func = nv04_gr_mthd_bind_rop; break;
 874        case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
 875        case 0x0198: func = nv04_gr_mthd_bind_beta4; break;
 876        case 0x019c: func = nv04_gr_mthd_bind_surf2d; break;
 877        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 878        default:
 879                return false;
 880        }
 881        return func(device, inst, data);
 882}
 883
 884static bool
 885nv03_gr_mthd_sifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 886{
 887        bool (*func)(struct nvkm_device *, u32, u32);
 888        switch (mthd) {
 889        case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
 890        case 0x0188: func = nv01_gr_mthd_bind_patt; break;
 891        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
 892        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
 893        case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break;
 894        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 895        default:
 896                return false;
 897        }
 898        return func(device, inst, data);
 899}
 900
 901static bool
 902nv04_gr_mthd_sifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 903{
 904        bool (*func)(struct nvkm_device *, u32, u32);
 905        switch (mthd) {
 906        case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
 907        case 0x0188: func = nv04_gr_mthd_bind_patt; break;
 908        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
 909        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
 910        case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
 911        case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
 912        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 913        default:
 914                return false;
 915        }
 916        return func(device, inst, data);
 917}
 918
 919static bool
 920nv03_gr_mthd_sifm(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 921{
 922        bool (*func)(struct nvkm_device *, u32, u32);
 923        switch (mthd) {
 924        case 0x0188: func = nv01_gr_mthd_bind_patt; break;
 925        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
 926        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
 927        case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break;
 928        case 0x0304: func = nv04_gr_mthd_set_operation; break;
 929        default:
 930                return false;
 931        }
 932        return func(device, inst, data);
 933}
 934
 935static bool
 936nv04_gr_mthd_sifm(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 937{
 938        bool (*func)(struct nvkm_device *, u32, u32);
 939        switch (mthd) {
 940        case 0x0188: func = nv04_gr_mthd_bind_patt; break;
 941        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
 942        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
 943        case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
 944        case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
 945        case 0x0304: func = nv04_gr_mthd_set_operation; break;
 946        default:
 947                return false;
 948        }
 949        return func(device, inst, data);
 950}
 951
 952static bool
 953nv04_gr_mthd_surf3d(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 954{
 955        bool (*func)(struct nvkm_device *, u32, u32);
 956        switch (mthd) {
 957        case 0x02f8: func = nv04_gr_mthd_surf3d_clip_h; break;
 958        case 0x02fc: func = nv04_gr_mthd_surf3d_clip_v; break;
 959        default:
 960                return false;
 961        }
 962        return func(device, inst, data);
 963}
 964
 965static bool
 966nv03_gr_mthd_ttri(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 967{
 968        bool (*func)(struct nvkm_device *, u32, u32);
 969        switch (mthd) {
 970        case 0x0188: func = nv01_gr_mthd_bind_clip; break;
 971        case 0x018c: func = nv04_gr_mthd_bind_surf_color; break;
 972        case 0x0190: func = nv04_gr_mthd_bind_surf_zeta; break;
 973        default:
 974                return false;
 975        }
 976        return func(device, inst, data);
 977}
 978
 979static bool
 980nv01_gr_mthd_prim(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 981{
 982        bool (*func)(struct nvkm_device *, u32, u32);
 983        switch (mthd) {
 984        case 0x0184: func = nv01_gr_mthd_bind_clip; break;
 985        case 0x0188: func = nv01_gr_mthd_bind_patt; break;
 986        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
 987        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
 988        case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break;
 989        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
 990        default:
 991                return false;
 992        }
 993        return func(device, inst, data);
 994}
 995
 996static bool
 997nv04_gr_mthd_prim(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
 998{
 999        bool (*func)(struct nvkm_device *, u32, u32);
1000        switch (mthd) {
1001        case 0x0184: func = nv01_gr_mthd_bind_clip; break;
1002        case 0x0188: func = nv04_gr_mthd_bind_patt; break;
1003        case 0x018c: func = nv04_gr_mthd_bind_rop; break;
1004        case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
1005        case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
1006        case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
1007        case 0x02fc: func = nv04_gr_mthd_set_operation; break;
1008        default:
1009                return false;
1010        }
1011        return func(device, inst, data);
1012}
1013
1014static bool
1015nv04_gr_mthd(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
1016{
1017        bool (*func)(struct nvkm_device *, u32, u32, u32);
1018        switch (nvkm_rd32(device, 0x700000 + inst) & 0x000000ff) {
1019        case 0x1c ... 0x1e:
1020                   func = nv01_gr_mthd_prim; break;
1021        case 0x1f: func = nv01_gr_mthd_blit; break;
1022        case 0x21: func = nv01_gr_mthd_ifc; break;
1023        case 0x36: func = nv03_gr_mthd_sifc; break;
1024        case 0x37: func = nv03_gr_mthd_sifm; break;
1025        case 0x48: func = nv03_gr_mthd_ttri; break;
1026        case 0x4a: func = nv04_gr_mthd_gdi; break;
1027        case 0x4b: func = nv03_gr_mthd_gdi; break;
1028        case 0x53: func = nv04_gr_mthd_surf3d; break;
1029        case 0x5c ... 0x5e:
1030                   func = nv04_gr_mthd_prim; break;
1031        case 0x5f: func = nv04_gr_mthd_blit; break;
1032        case 0x60: func = nv04_gr_mthd_iifc; break;
1033        case 0x61: func = nv04_gr_mthd_ifc; break;
1034        case 0x76: func = nv04_gr_mthd_sifc; break;
1035        case 0x77: func = nv04_gr_mthd_sifm; break;
1036        default:
1037                return false;
1038        }
1039        return func(device, inst, mthd, data);
1040}
1041
1042static int
1043nv04_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
1044                    int align, struct nvkm_gpuobj **pgpuobj)
1045{
1046        int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16, align,
1047                                  false, parent, pgpuobj);
1048        if (ret == 0) {
1049                nvkm_kmap(*pgpuobj);
1050                nvkm_wo32(*pgpuobj, 0x00, object->oclass);
1051#ifdef __BIG_ENDIAN
1052                nvkm_mo32(*pgpuobj, 0x00, 0x00080000, 0x00080000);
1053#endif
1054                nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
1055                nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
1056                nvkm_wo32(*pgpuobj, 0x0c, 0x00000000);
1057                nvkm_done(*pgpuobj);
1058        }
1059        return ret;
1060}
1061
1062const struct nvkm_object_func
1063nv04_gr_object = {
1064        .bind = nv04_gr_object_bind,
1065};
1066
1067/*******************************************************************************
1068 * PGRAPH context
1069 ******************************************************************************/
1070
1071static struct nv04_gr_chan *
1072nv04_gr_channel(struct nv04_gr *gr)
1073{
1074        struct nvkm_device *device = gr->base.engine.subdev.device;
1075        struct nv04_gr_chan *chan = NULL;
1076        if (nvkm_rd32(device, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) {
1077                int chid = nvkm_rd32(device, NV04_PGRAPH_CTX_USER) >> 24;
1078                if (chid < ARRAY_SIZE(gr->chan))
1079                        chan = gr->chan[chid];
1080        }
1081        return chan;
1082}
1083
1084static int
1085nv04_gr_load_context(struct nv04_gr_chan *chan, int chid)
1086{
1087        struct nvkm_device *device = chan->gr->base.engine.subdev.device;
1088        int i;
1089
1090        for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++)
1091                nvkm_wr32(device, nv04_gr_ctx_regs[i], chan->nv04[i]);
1092
1093        nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
1094        nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24);
1095        nvkm_mask(device, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000);
1096        return 0;
1097}
1098
1099static int
1100nv04_gr_unload_context(struct nv04_gr_chan *chan)
1101{
1102        struct nvkm_device *device = chan->gr->base.engine.subdev.device;
1103        int i;
1104
1105        for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++)
1106                chan->nv04[i] = nvkm_rd32(device, nv04_gr_ctx_regs[i]);
1107
1108        nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10000000);
1109        nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000);
1110        return 0;
1111}
1112
1113static void
1114nv04_gr_context_switch(struct nv04_gr *gr)
1115{
1116        struct nvkm_device *device = gr->base.engine.subdev.device;
1117        struct nv04_gr_chan *prev = NULL;
1118        struct nv04_gr_chan *next = NULL;
1119        int chid;
1120
1121        nv04_gr_idle(&gr->base);
1122
1123        /* If previous context is valid, we need to save it */
1124        prev = nv04_gr_channel(gr);
1125        if (prev)
1126                nv04_gr_unload_context(prev);
1127
1128        /* load context for next channel */
1129        chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f;
1130        next = gr->chan[chid];
1131        if (next)
1132                nv04_gr_load_context(next, chid);
1133}
1134
1135static u32 *ctx_reg(struct nv04_gr_chan *chan, u32 reg)
1136{
1137        int i;
1138
1139        for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) {
1140                if (nv04_gr_ctx_regs[i] == reg)
1141                        return &chan->nv04[i];
1142        }
1143
1144        return NULL;
1145}
1146
1147static void *
1148nv04_gr_chan_dtor(struct nvkm_object *object)
1149{
1150        struct nv04_gr_chan *chan = nv04_gr_chan(object);
1151        struct nv04_gr *gr = chan->gr;
1152        unsigned long flags;
1153
1154        spin_lock_irqsave(&gr->lock, flags);
1155        gr->chan[chan->chid] = NULL;
1156        spin_unlock_irqrestore(&gr->lock, flags);
1157        return chan;
1158}
1159
1160static int
1161nv04_gr_chan_fini(struct nvkm_object *object, bool suspend)
1162{
1163        struct nv04_gr_chan *chan = nv04_gr_chan(object);
1164        struct nv04_gr *gr = chan->gr;
1165        struct nvkm_device *device = gr->base.engine.subdev.device;
1166        unsigned long flags;
1167
1168        spin_lock_irqsave(&gr->lock, flags);
1169        nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
1170        if (nv04_gr_channel(gr) == chan)
1171                nv04_gr_unload_context(chan);
1172        nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
1173        spin_unlock_irqrestore(&gr->lock, flags);
1174        return 0;
1175}
1176
1177static const struct nvkm_object_func
1178nv04_gr_chan = {
1179        .dtor = nv04_gr_chan_dtor,
1180        .fini = nv04_gr_chan_fini,
1181};
1182
1183static int
1184nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
1185                 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
1186{
1187        struct nv04_gr *gr = nv04_gr(base);
1188        struct nv04_gr_chan *chan;
1189        unsigned long flags;
1190
1191        if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
1192                return -ENOMEM;
1193        nvkm_object_ctor(&nv04_gr_chan, oclass, &chan->object);
1194        chan->gr = gr;
1195        chan->chid = fifoch->chid;
1196        *pobject = &chan->object;
1197
1198        *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
1199
1200        spin_lock_irqsave(&gr->lock, flags);
1201        gr->chan[chan->chid] = chan;
1202        spin_unlock_irqrestore(&gr->lock, flags);
1203        return 0;
1204}
1205
1206/*******************************************************************************
1207 * PGRAPH engine/subdev functions
1208 ******************************************************************************/
1209
1210bool
1211nv04_gr_idle(struct nvkm_gr *gr)
1212{
1213        struct nvkm_subdev *subdev = &gr->engine.subdev;
1214        struct nvkm_device *device = subdev->device;
1215        u32 mask = 0xffffffff;
1216
1217        if (device->card_type == NV_40)
1218                mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL;
1219
1220        if (nvkm_msec(device, 2000,
1221                if (!(nvkm_rd32(device, NV04_PGRAPH_STATUS) & mask))
1222                        break;
1223        ) < 0) {
1224                nvkm_error(subdev, "idle timed out with status %08x\n",
1225                           nvkm_rd32(device, NV04_PGRAPH_STATUS));
1226                return false;
1227        }
1228
1229        return true;
1230}
1231
1232static const struct nvkm_bitfield
1233nv04_gr_intr_name[] = {
1234        { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1235        {}
1236};
1237
1238static const struct nvkm_bitfield
1239nv04_gr_nstatus[] = {
1240        { NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
1241        { NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
1242        { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
1243        { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
1244        {}
1245};
1246
1247const struct nvkm_bitfield
1248nv04_gr_nsource[] = {
1249        { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
1250        { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
1251        { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
1252        { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
1253        { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
1254        { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
1255        { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
1256        { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
1257        { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
1258        { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
1259        { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
1260        { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
1261        { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
1262        { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
1263        { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
1264        { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
1265        { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
1266        { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
1267        { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
1268        {}
1269};
1270
1271static void
1272nv04_gr_intr(struct nvkm_gr *base)
1273{
1274        struct nv04_gr *gr = nv04_gr(base);
1275        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1276        struct nvkm_device *device = subdev->device;
1277        u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR);
1278        u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE);
1279        u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS);
1280        u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR);
1281        u32 chid = (addr & 0x0f000000) >> 24;
1282        u32 subc = (addr & 0x0000e000) >> 13;
1283        u32 mthd = (addr & 0x00001ffc);
1284        u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA);
1285        u32 class = nvkm_rd32(device, 0x400180 + subc * 4) & 0xff;
1286        u32 inst = (nvkm_rd32(device, 0x40016c) & 0xffff) << 4;
1287        u32 show = stat;
1288        char msg[128], src[128], sta[128];
1289        struct nv04_gr_chan *chan;
1290        unsigned long flags;
1291
1292        spin_lock_irqsave(&gr->lock, flags);
1293        chan = gr->chan[chid];
1294
1295        if (stat & NV_PGRAPH_INTR_NOTIFY) {
1296                if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
1297                        if (!nv04_gr_mthd(device, inst, mthd, data))
1298                                show &= ~NV_PGRAPH_INTR_NOTIFY;
1299                }
1300        }
1301
1302        if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1303                nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1304                stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1305                show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1306                nv04_gr_context_switch(gr);
1307        }
1308
1309        nvkm_wr32(device, NV03_PGRAPH_INTR, stat);
1310        nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001);
1311
1312        if (show) {
1313                nvkm_snprintbf(msg, sizeof(msg), nv04_gr_intr_name, show);
1314                nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource);
1315                nvkm_snprintbf(sta, sizeof(sta), nv04_gr_nstatus, nstatus);
1316                nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] "
1317                                   "nstatus %08x [%s] ch %d [%s] subc %d "
1318                                   "class %04x mthd %04x data %08x\n",
1319                           show, msg, nsource, src, nstatus, sta, chid,
1320                           chan ? chan->object.client->name : "unknown",
1321                           subc, class, mthd, data);
1322        }
1323
1324        spin_unlock_irqrestore(&gr->lock, flags);
1325}
1326
1327static int
1328nv04_gr_init(struct nvkm_gr *base)
1329{
1330        struct nv04_gr *gr = nv04_gr(base);
1331        struct nvkm_device *device = gr->base.engine.subdev.device;
1332
1333        /* Enable PGRAPH interrupts */
1334        nvkm_wr32(device, NV03_PGRAPH_INTR, 0xFFFFFFFF);
1335        nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
1336
1337        nvkm_wr32(device, NV04_PGRAPH_VALID1, 0);
1338        nvkm_wr32(device, NV04_PGRAPH_VALID2, 0);
1339        /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x000001FF);
1340        nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
1341        nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x1231c000);
1342        /*1231C000 blob, 001 haiku*/
1343        /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
1344        nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x72111100);
1345        /*0x72111100 blob , 01 haiku*/
1346        /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
1347        nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f071);
1348        /*haiku same*/
1349
1350        /*nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
1351        nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31);
1352        /*haiku and blob 10d4*/
1353
1354        nvkm_wr32(device, NV04_PGRAPH_STATE        , 0xFFFFFFFF);
1355        nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL  , 0x10000100);
1356        nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000);
1357
1358        /* These don't belong here, they're part of a per-channel context */
1359        nvkm_wr32(device, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
1360        nvkm_wr32(device, NV04_PGRAPH_BETA_AND     , 0xFFFFFFFF);
1361        return 0;
1362}
1363
1364static const struct nvkm_gr_func
1365nv04_gr = {
1366        .init = nv04_gr_init,
1367        .intr = nv04_gr_intr,
1368        .chan_new = nv04_gr_chan_new,
1369        .sclass = {
1370                { -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */
1371                { -1, -1, 0x0017, &nv04_gr_object }, /* chroma */
1372                { -1, -1, 0x0018, &nv04_gr_object }, /* pattern (nv01) */
1373                { -1, -1, 0x0019, &nv04_gr_object }, /* clip */
1374                { -1, -1, 0x001c, &nv04_gr_object }, /* line */
1375                { -1, -1, 0x001d, &nv04_gr_object }, /* tri */
1376                { -1, -1, 0x001e, &nv04_gr_object }, /* rect */
1377                { -1, -1, 0x001f, &nv04_gr_object },
1378                { -1, -1, 0x0021, &nv04_gr_object },
1379                { -1, -1, 0x0030, &nv04_gr_object }, /* null */
1380                { -1, -1, 0x0036, &nv04_gr_object },
1381                { -1, -1, 0x0037, &nv04_gr_object },
1382                { -1, -1, 0x0038, &nv04_gr_object }, /* dvd subpicture */
1383                { -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */
1384                { -1, -1, 0x0042, &nv04_gr_object }, /* surf2d */
1385                { -1, -1, 0x0043, &nv04_gr_object }, /* rop */
1386                { -1, -1, 0x0044, &nv04_gr_object }, /* pattern */
1387                { -1, -1, 0x0048, &nv04_gr_object },
1388                { -1, -1, 0x004a, &nv04_gr_object },
1389                { -1, -1, 0x004b, &nv04_gr_object },
1390                { -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */
1391                { -1, -1, 0x0053, &nv04_gr_object },
1392                { -1, -1, 0x0054, &nv04_gr_object }, /* ttri */
1393                { -1, -1, 0x0055, &nv04_gr_object }, /* mtri */
1394                { -1, -1, 0x0057, &nv04_gr_object }, /* chroma */
1395                { -1, -1, 0x0058, &nv04_gr_object }, /* surf_dst */
1396                { -1, -1, 0x0059, &nv04_gr_object }, /* surf_src */
1397                { -1, -1, 0x005a, &nv04_gr_object }, /* surf_color */
1398                { -1, -1, 0x005b, &nv04_gr_object }, /* surf_zeta */
1399                { -1, -1, 0x005c, &nv04_gr_object }, /* line */
1400                { -1, -1, 0x005d, &nv04_gr_object }, /* tri */
1401                { -1, -1, 0x005e, &nv04_gr_object }, /* rect */
1402                { -1, -1, 0x005f, &nv04_gr_object },
1403                { -1, -1, 0x0060, &nv04_gr_object },
1404                { -1, -1, 0x0061, &nv04_gr_object },
1405                { -1, -1, 0x0064, &nv04_gr_object }, /* iifc (nv05) */
1406                { -1, -1, 0x0065, &nv04_gr_object }, /* ifc (nv05) */
1407                { -1, -1, 0x0066, &nv04_gr_object }, /* sifc (nv05) */
1408                { -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */
1409                { -1, -1, 0x0076, &nv04_gr_object },
1410                { -1, -1, 0x0077, &nv04_gr_object },
1411                {}
1412        }
1413};
1414
1415int
1416nv04_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
1417{
1418        struct nv04_gr *gr;
1419
1420        if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
1421                return -ENOMEM;
1422        spin_lock_init(&gr->lock);
1423        *pgr = &gr->base;
1424
1425        return nvkm_gr_ctor(&nv04_gr, device, index, true, &gr->base);
1426}
1427