diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/graph')
22 files changed, 5014 insertions, 4197 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h index b0795ececbda..e1947013d3bc 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h @@ -2,7 +2,7 @@ #define __NOUVEAU_GRCTX_H__ struct nouveau_grctx { - struct drm_device *dev; + struct nouveau_device *device; enum { NOUVEAU_GRCTX_PROG, @@ -10,18 +10,18 @@ struct nouveau_grctx { } mode; void *data; - uint32_t ctxprog_max; - uint32_t ctxprog_len; - uint32_t ctxprog_reg; - int ctxprog_label[32]; - uint32_t ctxvals_pos; - uint32_t ctxvals_base; + u32 ctxprog_max; + u32 ctxprog_len; + u32 ctxprog_reg; + int ctxprog_label[32]; + u32 ctxvals_pos; + u32 ctxvals_base; }; static inline void -cp_out(struct nouveau_grctx *ctx, uint32_t inst) +cp_out(struct nouveau_grctx *ctx, u32 inst) { - uint32_t *ctxprog = ctx->data; + u32 *ctxprog = ctx->data; if (ctx->mode != NOUVEAU_GRCTX_PROG) return; @@ -31,13 +31,13 @@ cp_out(struct nouveau_grctx *ctx, uint32_t inst) } static inline void -cp_lsr(struct nouveau_grctx *ctx, uint32_t val) +cp_lsr(struct nouveau_grctx *ctx, u32 val) { cp_out(ctx, CP_LOAD_SR | val); } static inline void -cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length) +cp_ctx(struct nouveau_grctx *ctx, u32 reg, u32 length) { ctx->ctxprog_reg = (reg - 0x00400000) >> 2; @@ -55,7 +55,7 @@ cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length) static inline void cp_name(struct nouveau_grctx *ctx, int name) { - uint32_t *ctxprog = ctx->data; + u32 *ctxprog = ctx->data; int i; if (ctx->mode != NOUVEAU_GRCTX_PROG) @@ -115,7 +115,7 @@ cp_pos(struct nouveau_grctx *ctx, int offset) } static inline void -gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) +gr_def(struct nouveau_grctx *ctx, u32 reg, u32 val) { if (ctx->mode != NOUVEAU_GRCTX_VALS) return; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c index b17506d7eb60..e45035efb8ca 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs */ +#include <core/gpuobj.h> + /* NVIDIA context programs handle a number of other conditions which are * not implemented in our versions. It's not clear why NVIDIA context * programs have this code, nor whether it's strictly necessary for @@ -109,8 +111,7 @@ #define CP_LOAD_MAGIC_NV44TCL 0x00800029 /* per-vs state (0x4497) */ #define CP_LOAD_MAGIC_NV40TCL 0x00800041 /* per-vs state (0x4097) */ -#include "drmP.h" -#include "nouveau_drv.h" +#include "nv40.h" #include "ctx.h" /* TODO: @@ -118,11 +119,10 @@ */ static int -nv40_graph_vs_count(struct drm_device *dev) +nv40_graph_vs_count(struct nouveau_device *device) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -160,7 +160,7 @@ enum cp_label { static void nv40_graph_construct_general(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; cp_ctx(ctx, 0x4000a4, 1); @@ -187,7 +187,7 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x400724, 1); gr_def(ctx, 0x400724, 0x02008821); cp_ctx(ctx, 0x400770, 3); - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x400814, 4); cp_ctx(ctx, 0x400828, 5); cp_ctx(ctx, 0x400840, 5); @@ -208,7 +208,7 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) gr_def(ctx, 0x4009dc, 0x80000000); } else { cp_ctx(ctx, 0x400840, 20); - if (nv44_graph_class(ctx->dev)) { + if (nv44_graph_class(ctx->device)) { for (i = 0; i < 8; i++) gr_def(ctx, 0x400860 + (i * 4), 0x00000001); } @@ -217,21 +217,21 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) gr_def(ctx, 0x400888, 0x00000040); cp_ctx(ctx, 0x400894, 11); gr_def(ctx, 0x400894, 0x00000040); - if (!nv44_graph_class(ctx->dev)) { + if (!nv44_graph_class(ctx->device)) { for (i = 0; i < 8; i++) gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000); } cp_ctx(ctx, 0x4008e0, 2); cp_ctx(ctx, 0x4008f8, 2); - if (dev_priv->chipset == 0x4c || - (dev_priv->chipset & 0xf0) == 0x60) + if (device->chipset == 0x4c || + (device->chipset & 0xf0) == 0x60) cp_ctx(ctx, 0x4009f8, 1); } cp_ctx(ctx, 0x400a00, 73); gr_def(ctx, 0x400b0c, 0x0b0b0b0c); cp_ctx(ctx, 0x401000, 4); cp_ctx(ctx, 0x405004, 1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -240,7 +240,7 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) break; default: cp_ctx(ctx, 0x403440, 1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x40: gr_def(ctx, 0x403440, 0x00000010); break; @@ -266,19 +266,19 @@ nv40_graph_construct_general(struct nouveau_grctx *ctx) static void nv40_graph_construct_state3d(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x401880, 51); gr_def(ctx, 0x401940, 0x00000100); } else - if (dev_priv->chipset == 0x46 || dev_priv->chipset == 0x47 || - dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { + if (device->chipset == 0x46 || device->chipset == 0x47 || + device->chipset == 0x49 || device->chipset == 0x4b) { cp_ctx(ctx, 0x401880, 32); for (i = 0; i < 16; i++) gr_def(ctx, 0x401880 + (i * 4), 0x00000111); - if (dev_priv->chipset == 0x46) + if (device->chipset == 0x46) cp_ctx(ctx, 0x401900, 16); cp_ctx(ctx, 0x401940, 3); } @@ -289,7 +289,7 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) gr_def(ctx, 0x401978, 0xffff0000); gr_def(ctx, 0x40197c, 0x00000001); gr_def(ctx, 0x401990, 0x46400000); - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x4019a0, 2); cp_ctx(ctx, 0x4019ac, 5); } else { @@ -297,7 +297,7 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x4019b4, 3); } gr_def(ctx, 0x4019bc, 0xffff0000); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x46: case 0x47: case 0x49: @@ -316,7 +316,7 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) for (i = 0; i < 16; i++) gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000); gr_def(ctx, 0x401a8c, 0x4b7fffff); - if (dev_priv->chipset == 0x40) { + if (device->chipset == 0x40) { cp_ctx(ctx, 0x401ab8, 3); } else { cp_ctx(ctx, 0x401ab8, 1); @@ -327,10 +327,10 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) gr_def(ctx, 0x401ad4, 0x70605040); gr_def(ctx, 0x401ad8, 0xb8a89888); gr_def(ctx, 0x401adc, 0xf8e8d8c8); - cp_ctx(ctx, 0x401b10, dev_priv->chipset == 0x40 ? 2 : 1); + cp_ctx(ctx, 0x401b10, device->chipset == 0x40 ? 2 : 1); gr_def(ctx, 0x401b10, 0x40100000); - cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5); - gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ? + cp_ctx(ctx, 0x401b18, device->chipset == 0x40 ? 6 : 5); + gr_def(ctx, 0x401b28, device->chipset == 0x40 ? 0x00000004 : 0x00000000); cp_ctx(ctx, 0x401b30, 25); gr_def(ctx, 0x401b34, 0x0000ffff); @@ -341,8 +341,8 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) gr_def(ctx, 0x401b84, 0xffffffff); gr_def(ctx, 0x401b88, 0x00ff7000); gr_def(ctx, 0x401b8c, 0x0000ffff); - if (dev_priv->chipset != 0x44 && dev_priv->chipset != 0x4a && - dev_priv->chipset != 0x4e) + if (device->chipset != 0x44 && device->chipset != 0x4a && + device->chipset != 0x4e) cp_ctx(ctx, 0x401b94, 1); cp_ctx(ctx, 0x401b98, 8); gr_def(ctx, 0x401b9c, 0x00ff0000); @@ -371,12 +371,12 @@ nv40_graph_construct_state3d(struct nouveau_grctx *ctx) static void nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; cp_ctx(ctx, 0x402000, 1); - cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2); - switch (dev_priv->chipset) { + cp_ctx(ctx, 0x402404, device->chipset == 0x40 ? 1 : 2); + switch (device->chipset) { case 0x40: gr_def(ctx, 0x402404, 0x00000001); break; @@ -393,9 +393,9 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) default: gr_def(ctx, 0x402404, 0x00000021); } - if (dev_priv->chipset != 0x40) + if (device->chipset != 0x40) gr_def(ctx, 0x402408, 0x030c30c3); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x44: case 0x46: case 0x4a: @@ -408,10 +408,10 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) default: break; } - cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9); + cp_ctx(ctx, 0x402480, device->chipset == 0x40 ? 8 : 9); gr_def(ctx, 0x402488, 0x3e020200); gr_def(ctx, 0x40248c, 0x00ffffff); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x40: gr_def(ctx, 0x402490, 0x60103f00); break; @@ -428,16 +428,16 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) gr_def(ctx, 0x402490, 0x0c103f00); break; } - gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ? + gr_def(ctx, 0x40249c, device->chipset <= 0x43 ? 0x00020000 : 0x00040000); cp_ctx(ctx, 0x402500, 31); gr_def(ctx, 0x402530, 0x00008100); - if (dev_priv->chipset == 0x40) + if (device->chipset == 0x40) cp_ctx(ctx, 0x40257c, 6); cp_ctx(ctx, 0x402594, 16); cp_ctx(ctx, 0x402800, 17); gr_def(ctx, 0x402800, 0x00000001); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -445,7 +445,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) gr_def(ctx, 0x402864, 0x00001001); cp_ctx(ctx, 0x402870, 3); gr_def(ctx, 0x402878, 0x00000003); - if (dev_priv->chipset != 0x47) { /* belong at end!! */ + if (device->chipset != 0x47) { /* belong at end!! */ cp_ctx(ctx, 0x402900, 1); cp_ctx(ctx, 0x402940, 1); cp_ctx(ctx, 0x402980, 1); @@ -470,9 +470,9 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) } cp_ctx(ctx, 0x402c00, 4); - gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ? + gr_def(ctx, 0x402c00, device->chipset == 0x40 ? 0x80800001 : 0x00888001); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x47: case 0x49: case 0x4b: @@ -485,30 +485,30 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) break; default: cp_ctx(ctx, 0x402c10, 4); - if (dev_priv->chipset == 0x40) + if (device->chipset == 0x40) cp_ctx(ctx, 0x402c20, 36); else - if (dev_priv->chipset <= 0x42) + if (device->chipset <= 0x42) cp_ctx(ctx, 0x402c20, 24); else - if (dev_priv->chipset <= 0x4a) + if (device->chipset <= 0x4a) cp_ctx(ctx, 0x402c20, 16); else cp_ctx(ctx, 0x402c20, 8); - cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13); + cp_ctx(ctx, 0x402cb0, device->chipset == 0x40 ? 12 : 13); gr_def(ctx, 0x402cd4, 0x00000005); - if (dev_priv->chipset != 0x40) + if (device->chipset != 0x40) gr_def(ctx, 0x402ce0, 0x0000ffff); break; } - cp_ctx(ctx, 0x403400, dev_priv->chipset == 0x40 ? 4 : 3); - cp_ctx(ctx, 0x403410, dev_priv->chipset == 0x40 ? 4 : 3); - cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->dev)); - for (i = 0; i < nv40_graph_vs_count(ctx->dev); i++) + cp_ctx(ctx, 0x403400, device->chipset == 0x40 ? 4 : 3); + cp_ctx(ctx, 0x403410, device->chipset == 0x40 ? 4 : 3); + cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->device)); + for (i = 0; i < nv40_graph_vs_count(ctx->device); i++) gr_def(ctx, 0x403420 + (i * 4), 0x00005555); - if (dev_priv->chipset != 0x40) { + if (device->chipset != 0x40) { cp_ctx(ctx, 0x403600, 1); gr_def(ctx, 0x403600, 0x00000001); } @@ -516,7 +516,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x403c18, 1); gr_def(ctx, 0x403c18, 0x00000001); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x46: case 0x47: case 0x49: @@ -527,7 +527,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) gr_def(ctx, 0x405c24, 0x000e3000); break; } - if (dev_priv->chipset != 0x4e) + if (device->chipset != 0x4e) cp_ctx(ctx, 0x405800, 11); cp_ctx(ctx, 0x407000, 1); } @@ -535,7 +535,7 @@ nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) static void nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx) { - int len = nv44_graph_class(ctx->dev) ? 0x0084 : 0x0684; + int len = nv44_graph_class(ctx->device) ? 0x0084 : 0x0684; cp_out (ctx, 0x300000); cp_lsr (ctx, len - 4); @@ -550,32 +550,31 @@ nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx) static void nv40_graph_construct_shader(struct nouveau_grctx *ctx) { - struct drm_device *dev = ctx->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = ctx->device; struct nouveau_gpuobj *obj = ctx->data; int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset; int offset, i; - vs_nr = nv40_graph_vs_count(ctx->dev); + vs_nr = nv40_graph_vs_count(ctx->device); vs_nr_b0 = 363; - vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64; - if (dev_priv->chipset == 0x40) { + vs_nr_b1 = device->chipset == 0x40 ? 128 : 64; + if (device->chipset == 0x40) { b0_offset = 0x2200/4; /* 33a0 */ b1_offset = 0x55a0/4; /* 1500 */ vs_len = 0x6aa0/4; } else - if (dev_priv->chipset == 0x41 || dev_priv->chipset == 0x42) { + if (device->chipset == 0x41 || device->chipset == 0x42) { b0_offset = 0x2200/4; /* 2200 */ b1_offset = 0x4400/4; /* 0b00 */ vs_len = 0x4f00/4; } else { b0_offset = 0x1d40/4; /* 2200 */ b1_offset = 0x3f40/4; /* 0b00 : 0a40 */ - vs_len = nv44_graph_class(dev) ? 0x4980/4 : 0x4a40/4; + vs_len = nv44_graph_class(device) ? 0x4980/4 : 0x4a40/4; } cp_lsr(ctx, vs_len * vs_nr + 0x300/4); - cp_out(ctx, nv44_graph_class(dev) ? 0x800029 : 0x800041); + cp_out(ctx, nv44_graph_class(device) ? 0x800029 : 0x800041); offset = ctx->ctxvals_pos; ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len)); @@ -661,21 +660,21 @@ nv40_grctx_generate(struct nouveau_grctx *ctx) } void -nv40_grctx_fill(struct drm_device *dev, struct nouveau_gpuobj *mem) +nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) { nv40_grctx_generate(&(struct nouveau_grctx) { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_VALS, .data = mem, }); } void -nv40_grctx_init(struct drm_device *dev, u32 *size) +nv40_grctx_init(struct nouveau_device *device, u32 *size) { u32 ctxprog[256], i; struct nouveau_grctx ctx = { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_PROG, .data = ctxprog, .ctxprog_max = ARRAY_SIZE(ctxprog) @@ -683,8 +682,8 @@ nv40_grctx_init(struct drm_device *dev, u32 *size) nv40_grctx_generate(&ctx); - nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + nv_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) - nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, ctxprog[i]); + nv_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c index e17c17bfd89e..552fdbd45ebe 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c @@ -20,6 +20,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <core/gpuobj.h> + #define CP_FLAG_CLEAR 0 #define CP_FLAG_SET 1 #define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0) @@ -105,8 +107,7 @@ #define CP_SEEK_1 0x00c000ff #define CP_SEEK_2 0x00c800ff -#include "drmP.h" -#include "nouveau_drv.h" +#include "nv50.h" #include "ctx.h" #define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) @@ -175,32 +176,6 @@ static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx); static int nv50_grctx_generate(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - - switch (dev_priv->chipset) { - case 0x50: - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - case 0xa0: - case 0xa3: - case 0xa5: - case 0xa8: - case 0xaa: - case 0xac: - case 0xaf: - break; - default: - NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for " - "your NV%x card.\n", dev_priv->chipset); - NV_ERROR(ctx->dev, "Disabling acceleration. Please contact " - "the devs.\n"); - return -ENOSYS; - } - cp_set (ctx, STATE, RUNNING); cp_set (ctx, XFER_SWITCH, ENABLE); /* decide whether we're loading/unloading the context */ @@ -278,30 +253,36 @@ nv50_grctx_generate(struct nouveau_grctx *ctx) } void -nv50_grctx_fill(struct drm_device *dev, struct nouveau_gpuobj *mem) +nv50_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) { nv50_grctx_generate(&(struct nouveau_grctx) { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_VALS, .data = mem, }); } int -nv50_grctx_init(struct drm_device *dev, u32 *data, u32 max, u32 *len, u32 *cnt) +nv50_grctx_init(struct nouveau_device *device, u32 *size) { + u32 *ctxprog = kmalloc(512 * 4, GFP_KERNEL), i; struct nouveau_grctx ctx = { - .dev = dev, + .device = device, .mode = NOUVEAU_GRCTX_PROG, - .data = data, - .ctxprog_max = max + .data = ctxprog, + .ctxprog_max = 512, }; - int ret; - ret = nv50_grctx_generate(&ctx); - *cnt = ctx.ctxvals_pos * 4; - *len = ctx.ctxprog_len; - return ret; + if (!ctxprog) + return -ENOMEM; + nv50_grctx_generate(&ctx); + + nv_wr32(device, 0x400324, 0); + for (i = 0; i < ctx.ctxprog_len; i++) + nv_wr32(device, 0x400328, ctxprog[i]); + *size = ctx.ctxvals_pos * 4; + kfree(ctxprog); + return 0; } /* @@ -315,36 +296,36 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx); static void nv50_graph_construct_mmio(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i, j; int offset, base; - uint32_t units = nv_rd32 (ctx->dev, 0x1540); + u32 units = nv_rd32 (ctx->device, 0x1540); /* 0800: DISPATCH */ cp_ctx(ctx, 0x400808, 7); gr_def(ctx, 0x400814, 0x00000030); cp_ctx(ctx, 0x400834, 0x32); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { gr_def(ctx, 0x400834, 0xff400040); gr_def(ctx, 0x400838, 0xfff00080); gr_def(ctx, 0x40083c, 0xfff70090); gr_def(ctx, 0x400840, 0xffe806a8); } gr_def(ctx, 0x400844, 0x00000002); - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) gr_def(ctx, 0x400894, 0x00001000); gr_def(ctx, 0x4008e8, 0x00000003); gr_def(ctx, 0x4008ec, 0x00001000); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x400908, 0xb); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) cp_ctx(ctx, 0x400908, 0xc); else cp_ctx(ctx, 0x400908, 0xe); - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) cp_ctx(ctx, 0x400b00, 0x1); - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { cp_ctx(ctx, 0x400b10, 0x1); gr_def(ctx, 0x400b10, 0x0001629d); cp_ctx(ctx, 0x400b20, 0x1); @@ -358,10 +339,10 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, 0x400c08, 0x0000fe0c); /* 1000 */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { cp_ctx(ctx, 0x401008, 0x4); gr_def(ctx, 0x401014, 0x00001000); - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { cp_ctx(ctx, 0x401008, 0x5); gr_def(ctx, 0x401018, 0x00001000); } else { @@ -372,7 +353,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 1400 */ cp_ctx(ctx, 0x401400, 0x8); cp_ctx(ctx, 0x401424, 0x3); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x40142c, 0x0001fd87); else gr_def(ctx, 0x40142c, 0x00000187); @@ -382,10 +363,10 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 1800: STREAMOUT */ cp_ctx(ctx, 0x401814, 0x1); gr_def(ctx, 0x401814, 0x000000ff); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { cp_ctx(ctx, 0x40181c, 0xe); gr_def(ctx, 0x401850, 0x00000004); - } else if (dev_priv->chipset < 0xa0) { + } else if (device->chipset < 0xa0) { cp_ctx(ctx, 0x40181c, 0xf); gr_def(ctx, 0x401854, 0x00000004); } else { @@ -395,7 +376,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 1C00 */ cp_ctx(ctx, 0x401c00, 0x1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: gr_def(ctx, 0x401c00, 0x0001005f); break; @@ -424,7 +405,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 2400 */ cp_ctx(ctx, 0x402400, 0x1); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x402408, 0x1); else cp_ctx(ctx, 0x402408, 0x2); @@ -432,21 +413,21 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 2800: CSCHED */ cp_ctx(ctx, 0x402800, 0x1); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x402800, 0x00000006); /* 2C00: ZCULL */ cp_ctx(ctx, 0x402c08, 0x6); - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) gr_def(ctx, 0x402c14, 0x01000000); gr_def(ctx, 0x402c18, 0x000000ff); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x402ca0, 0x1); else cp_ctx(ctx, 0x402ca0, 0x2); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) gr_def(ctx, 0x402ca0, 0x00000400); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) gr_def(ctx, 0x402ca0, 0x00000800); else gr_def(ctx, 0x402ca0, 0x00000400); @@ -457,14 +438,14 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, 0x403004, 0x00000001); /* 3400 */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { cp_ctx(ctx, 0x403404, 0x1); gr_def(ctx, 0x403404, 0x00000001); } /* 5000: CCACHE */ cp_ctx(ctx, 0x405000, 0x1); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: gr_def(ctx, 0x405000, 0x00300080); break; @@ -493,22 +474,22 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) cp_ctx(ctx, 0x40502c, 0x1); /* 6000? */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) cp_ctx(ctx, 0x4063e0, 0x1); /* 6800: M2MF */ - if (dev_priv->chipset < 0x90) { + if (device->chipset < 0x90) { cp_ctx(ctx, 0x406814, 0x2b); gr_def(ctx, 0x406818, 0x00000f80); gr_def(ctx, 0x406860, 0x007f0080); gr_def(ctx, 0x40689c, 0x007f0080); } else { cp_ctx(ctx, 0x406814, 0x4); - if (dev_priv->chipset == 0x98) + if (device->chipset == 0x98) gr_def(ctx, 0x406818, 0x00000f80); else gr_def(ctx, 0x406818, 0x00001f80); - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) gr_def(ctx, 0x40681c, 0x00000030); cp_ctx(ctx, 0x406830, 0x3); } @@ -517,43 +498,43 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) for (i = 0; i < 8; i++) { if (units & (1<<(i+16))) { cp_ctx(ctx, 0x407000 + (i<<8), 3); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x407000 + (i<<8), 0x1b74f820); - else if (dev_priv->chipset != 0xa5) + else if (device->chipset != 0xa5) gr_def(ctx, 0x407000 + (i<<8), 0x3b74f821); else gr_def(ctx, 0x407000 + (i<<8), 0x7b74f821); gr_def(ctx, 0x407004 + (i<<8), 0x89058001); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { cp_ctx(ctx, 0x407010 + (i<<8), 1); - } else if (dev_priv->chipset < 0xa0) { + } else if (device->chipset < 0xa0) { cp_ctx(ctx, 0x407010 + (i<<8), 2); gr_def(ctx, 0x407010 + (i<<8), 0x00001000); gr_def(ctx, 0x407014 + (i<<8), 0x0000001f); } else { cp_ctx(ctx, 0x407010 + (i<<8), 3); gr_def(ctx, 0x407010 + (i<<8), 0x00001000); - if (dev_priv->chipset != 0xa5) + if (device->chipset != 0xa5) gr_def(ctx, 0x407014 + (i<<8), 0x000000ff); else gr_def(ctx, 0x407014 + (i<<8), 0x000001ff); } cp_ctx(ctx, 0x407080 + (i<<8), 4); - if (dev_priv->chipset != 0xa5) + if (device->chipset != 0xa5) gr_def(ctx, 0x407080 + (i<<8), 0x027c10fa); else gr_def(ctx, 0x407080 + (i<<8), 0x827c10fa); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, 0x407084 + (i<<8), 0x000000c0); else gr_def(ctx, 0x407084 + (i<<8), 0x400000c0); gr_def(ctx, 0x407088 + (i<<8), 0xb7892080); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, 0x407094 + (i<<8), 1); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) cp_ctx(ctx, 0x407094 + (i<<8), 3); else { cp_ctx(ctx, 0x407094 + (i<<8), 4); @@ -563,30 +544,30 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) } cp_ctx(ctx, 0x407c00, 0x3); - if (dev_priv->chipset < 0x90) + if (device->chipset < 0x90) gr_def(ctx, 0x407c00, 0x00010040); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, 0x407c00, 0x00390040); else gr_def(ctx, 0x407c00, 0x003d0040); gr_def(ctx, 0x407c08, 0x00000022); - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { cp_ctx(ctx, 0x407c10, 0x3); cp_ctx(ctx, 0x407c20, 0x1); cp_ctx(ctx, 0x407c2c, 0x1); } - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { cp_ctx(ctx, 0x407d00, 0x9); } else { cp_ctx(ctx, 0x407d00, 0x15); } - if (dev_priv->chipset == 0x98) + if (device->chipset == 0x98) gr_def(ctx, 0x407d08, 0x00380040); else { - if (dev_priv->chipset < 0x90) + if (device->chipset < 0x90) gr_def(ctx, 0x407d08, 0x00010040); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, 0x407d08, 0x00390040); else gr_def(ctx, 0x407d08, 0x003d0040); @@ -596,11 +577,11 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) /* 8000+: per-TP state */ for (i = 0; i < 10; i++) { if (units & (1<<i)) { - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) base = 0x408000 + (i<<12); else base = 0x408000 + (i<<11); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0xc00; else offset = base + 0x80; @@ -609,9 +590,9 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) cp_ctx(ctx, offset + 0x08, 1); /* per-MP state */ - for (j = 0; j < (dev_priv->chipset < 0xa0 ? 2 : 4); j++) { + for (j = 0; j < (device->chipset < 0xa0 ? 2 : 4); j++) { if (!(units & (1 << (j+24)))) continue; - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0x200 + (j<<7); else offset = base + 0x100 + (j<<7); @@ -620,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x04, 0x00160000); gr_def(ctx, offset + 0x08, 0x01800000); gr_def(ctx, offset + 0x18, 0x0003ffff); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: gr_def(ctx, offset + 0x1c, 0x00080000); break; @@ -651,53 +632,53 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) break; } gr_def(ctx, offset + 0x40, 0x00010401); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x48, 0x00000040); else gr_def(ctx, offset + 0x48, 0x00000078); gr_def(ctx, offset + 0x50, 0x000000bf); gr_def(ctx, offset + 0x58, 0x00001210); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x5c, 0x00000080); else gr_def(ctx, offset + 0x5c, 0x08000080); - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) gr_def(ctx, offset + 0x68, 0x0000003e); } - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, base + 0x300, 0x4); else cp_ctx(ctx, base + 0x300, 0x5); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, base + 0x304, 0x00007070); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, base + 0x304, 0x00027070); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) gr_def(ctx, base + 0x304, 0x01127070); else gr_def(ctx, base + 0x304, 0x05127070); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, base + 0x318, 1); else cp_ctx(ctx, base + 0x320, 1); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, base + 0x318, 0x0003ffff); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, base + 0x318, 0x03ffffff); else gr_def(ctx, base + 0x320, 0x07ffffff); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) cp_ctx(ctx, base + 0x324, 5); else cp_ctx(ctx, base + 0x328, 4); - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { cp_ctx(ctx, base + 0x340, 9); offset = base + 0x340; - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { cp_ctx(ctx, base + 0x33c, 0xb); offset = base + 0x344; } else { @@ -706,12 +687,12 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) } gr_def(ctx, offset + 0x0, 0x00120407); gr_def(ctx, offset + 0x4, 0x05091507); - if (dev_priv->chipset == 0x84) + if (device->chipset == 0x84) gr_def(ctx, offset + 0x8, 0x05100202); else gr_def(ctx, offset + 0x8, 0x05010202); gr_def(ctx, offset + 0xc, 0x00030201); - if (dev_priv->chipset == 0xa3) + if (device->chipset == 0xa3) cp_ctx(ctx, base + 0x36c, 1); cp_ctx(ctx, base + 0x400, 2); @@ -720,7 +701,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, base + 0x40c, 0x0d0c0b0a); gr_def(ctx, base + 0x410, 0x00141210); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0x800; else offset = base + 0x500; @@ -728,55 +709,55 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x0, 0x000001f0); gr_def(ctx, offset + 0x4, 0x00000001); gr_def(ctx, offset + 0x8, 0x00000003); - if (dev_priv->chipset == 0x50 || IS_NVAAF(dev_priv->chipset)) + if (device->chipset == 0x50 || IS_NVAAF(device->chipset)) gr_def(ctx, offset + 0xc, 0x00008000); gr_def(ctx, offset + 0x14, 0x00039e00); cp_ctx(ctx, offset + 0x1c, 2); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x1c, 0x00000040); else gr_def(ctx, offset + 0x1c, 0x00000100); gr_def(ctx, offset + 0x20, 0x00003800); - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { cp_ctx(ctx, base + 0x54c, 2); - if (!IS_NVA3F(dev_priv->chipset)) + if (!IS_NVA3F(device->chipset)) gr_def(ctx, base + 0x54c, 0x003fe006); else gr_def(ctx, base + 0x54c, 0x003fe007); gr_def(ctx, base + 0x550, 0x003fe000); } - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0xa00; else offset = base + 0x680; cp_ctx(ctx, offset, 1); gr_def(ctx, offset, 0x00404040); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) offset = base + 0xe00; else offset = base + 0x700; cp_ctx(ctx, offset, 2); - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) gr_def(ctx, offset, 0x0077f005); - else if (dev_priv->chipset == 0xa5) + else if (device->chipset == 0xa5) gr_def(ctx, offset, 0x6cf7f007); - else if (dev_priv->chipset == 0xa8) + else if (device->chipset == 0xa8) gr_def(ctx, offset, 0x6cfff007); - else if (dev_priv->chipset == 0xac) + else if (device->chipset == 0xac) gr_def(ctx, offset, 0x0cfff007); else gr_def(ctx, offset, 0x0cf7f007); - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) gr_def(ctx, offset + 0x4, 0x00007fff); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) gr_def(ctx, offset + 0x4, 0x003f7fff); else gr_def(ctx, offset + 0x4, 0x02bf7fff); cp_ctx(ctx, offset + 0x2c, 1); - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { cp_ctx(ctx, offset + 0x50, 9); gr_def(ctx, offset + 0x54, 0x000003ff); gr_def(ctx, offset + 0x58, 0x00000003); @@ -785,7 +766,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x64, 0x0000001f); gr_def(ctx, offset + 0x68, 0x0000000f); gr_def(ctx, offset + 0x6c, 0x0000000f); - } else if (dev_priv->chipset < 0xa0) { + } else if (device->chipset < 0xa0) { cp_ctx(ctx, offset + 0x50, 1); cp_ctx(ctx, offset + 0x70, 1); } else { @@ -797,7 +778,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) } static void -dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { +dd_emit(struct nouveau_grctx *ctx, int num, u32 val) { int i; if (val && ctx->mode == NOUVEAU_GRCTX_VALS) for (i = 0; i < num; i++) @@ -808,7 +789,7 @@ dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { static void nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int base, num; base = ctx->ctxvals_pos; @@ -822,7 +803,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 00000001 SRC_LINEAR #1 */ dd_emit(ctx, 1, 0); /* 000000ff SRC_ADDRESS_HIGH */ dd_emit(ctx, 1, 0); /* 00000001 SRC_SRGB */ - if (dev_priv->chipset >= 0x94) + if (device->chipset >= 0x94) dd_emit(ctx, 1, 0); /* 00000003 eng2d UNK0258 */ dd_emit(ctx, 1, 1); /* 00000fff SRC_DEPTH */ dd_emit(ctx, 1, 0x100); /* 0000ffff SRC_HEIGHT */ @@ -851,7 +832,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 0000007f BLOCKDIM_Z */ dd_emit(ctx, 1, 4); /* 000000ff CP_REG_ALLOC_TEMP */ dd_emit(ctx, 1, 1); /* 00000001 BLOCKDIM_DIRTY */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) dd_emit(ctx, 1, 0); /* 00000003 UNK03E8 */ dd_emit(ctx, 1, 1); /* 0000007f BLOCK_ALLOC_HALFWARPS */ dd_emit(ctx, 1, 1); /* 00000007 LOCAL_WARPS_NO_CLAMP */ @@ -863,7 +844,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 000007ff BLOCK_ALLOC_THREADS */ /* compat 2d state */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { dd_emit(ctx, 4, 0); /* 0000ffff clip X, Y, W, H */ dd_emit(ctx, 1, 1); /* ffffffff chroma COLOR_FORMAT */ @@ -923,7 +904,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_IN */ /* more compat 2d state */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { dd_emit(ctx, 1, 1); /* ffffffff line COLOR_FORMAT */ dd_emit(ctx, 1, 0); /* ffffffff line OPERATION */ @@ -957,18 +938,18 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0); /* 000000ff UNK12B0_2 */ dd_emit(ctx, 1, 0); /* 0000000f FP_TEXTURES_LOG2 */ dd_emit(ctx, 1, 0); /* 0000000f FP_SAMPLERS_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { dd_emit(ctx, 1, 0); /* ffffffff */ dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ } else { dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ } dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ dd_emit(ctx, 1, 8); /* 000000ff SEMANTIC_COLOR.COLR_NR */ dd_emit(ctx, 1, 0x14); /* 000000ff SEMANTIC_COLOR.FFC0_ID */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { dd_emit(ctx, 1, 0); /* 000000ff SEMANTIC_LAYER */ dd_emit(ctx, 1, 0); /* 00000001 */ } else { @@ -994,7 +975,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ dd_emit(ctx, 1, 0xcf); /* 000000ff RT_FORMAT */ dd_emit(ctx, 7, 0); /* 000000ff RT_FORMAT */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 3, 0); /* 1, 1, 1 */ else dd_emit(ctx, 2, 0); /* 1, 1 */ @@ -1002,15 +983,15 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT*/ dd_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ dd_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { dd_emit(ctx, 1, 3); /* 00000003 */ dd_emit(ctx, 1, 0); /* 00000001 UNK1418. Alone. */ } - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 1, 3); /* 00000003 UNK15AC */ dd_emit(ctx, 1, 1); /* ffffffff RASTERIZE_ENABLE */ dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.EXPORTS_Z */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.MULTIPLE_RESULTS */ dd_emit(ctx, 1, 0x12); /* 000000ff FP_INTERPOLANT_CTRL.COUNT */ dd_emit(ctx, 1, 0x10); /* 000000ff FP_INTERPOLANT_CTRL.COUNT_NONFLAT */ @@ -1022,16 +1003,16 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ dd_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) dd_emit(ctx, 1, 0); /* ffffffff */ dd_emit(ctx, 1, 0); /* 00000001 GP_BUILTIN_RESULT_EN.LAYER_IDX */ dd_emit(ctx, 1, 0); /* ffffffff STRMOUT_ENABLE */ dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ dd_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE*/ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) dd_emit(ctx, 8, 0); /* 00000001 */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.COMP */ dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.SIZE */ dd_emit(ctx, 1, 2); /* 00000007 VTX_ATTR_DEFINE.TYPE */ @@ -1042,20 +1023,20 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ dd_emit(ctx, 1, 0); /* 0000000f VP_TEXTURES_LOG2 */ dd_emit(ctx, 1, 0); /* 0000000f VP_SAMPLERS_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) dd_emit(ctx, 1, 0); /* 00000001 */ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_BACK */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) dd_emit(ctx, 1, 0); /* 00000003 VTX_ATTR_DEFINE.SIZE - 1 */ dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) dd_emit(ctx, 1, 0); /* 00000003 */ dd_emit(ctx, 1, 0); /* 00000001 CULL_FACE_ENABLE */ dd_emit(ctx, 1, 1); /* 00000003 CULL_FACE */ dd_emit(ctx, 1, 0); /* 00000001 FRONT_FACE */ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_FRONT */ dd_emit(ctx, 1, 0x1000); /* 00007fff UNK141C */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { dd_emit(ctx, 1, 0xe00); /* 7fff */ dd_emit(ctx, 1, 0x1000); /* 7fff */ dd_emit(ctx, 1, 0x1e00); /* 7fff */ @@ -1070,10 +1051,10 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK0 nonempty */ dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK1 nonempty */ dd_emit(ctx, 1, 0x200); /* 0003ffff GP_VERTEX_OUTPUT_COUNT*GP_REG_ALLOC_RESULT */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) dd_emit(ctx, 1, 0x200); dd_emit(ctx, 1, 0); /* 00000001 */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { dd_emit(ctx, 1, 1); /* 00000001 */ dd_emit(ctx, 1, 0x70); /* 000000ff */ dd_emit(ctx, 1, 0x80); /* 000000ff */ @@ -1120,7 +1101,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) num = ctx->ctxvals_pos - base; ctx->ctxvals_pos = base; - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) cp_ctx(ctx, 0x404800, num); else cp_ctx(ctx, 0x405400, num); @@ -1169,7 +1150,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) */ static void -xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { +xf_emit(struct nouveau_grctx *ctx, int num, u32 val) { int i; if (val && ctx->mode == NOUVEAU_GRCTX_VALS) for (i = 0; i < num; i++) @@ -1201,16 +1182,16 @@ static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx); static void nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; int offset; int size = 0; - uint32_t units = nv_rd32 (ctx->dev, 0x1540); + u32 units = nv_rd32 (ctx->device, 0x1540); offset = (ctx->ctxvals_pos+0x3f)&~0x3f; ctx->ctxvals_base = offset; - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { /* Strand 0 */ ctx->ctxvals_pos = offset; nv50_graph_construct_gene_dispatch(ctx); @@ -1280,7 +1261,7 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) /* Strand 2 */ ctx->ctxvals_pos = offset + 2; - if (dev_priv->chipset == 0xa0) + if (device->chipset == 0xa0) nv50_graph_construct_gene_unk14xx(ctx); nv50_graph_construct_gene_unk24xx(ctx); if ((ctx->ctxvals_pos-offset)/8 > size) @@ -1327,7 +1308,7 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) /* Strand 7 */ ctx->ctxvals_pos = offset + 7; - if (dev_priv->chipset == 0xa0) { + if (device->chipset == 0xa0) { if (units & (1 << 4)) nv50_graph_construct_xfer_tp(ctx); if (units & (1 << 5)) @@ -1365,24 +1346,24 @@ static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) { /* start of strand 0 */ - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* SEEK */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 5, 0); - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) xf_emit(ctx, 6, 0); else xf_emit(ctx, 4, 0); /* SEEK */ /* the PGRAPH's internal FIFO */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 8*3, 0); else xf_emit(ctx, 0x100*3, 0); /* and another bonus slot?!? */ xf_emit(ctx, 3, 0); /* and YET ANOTHER bonus slot? */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 3, 0); /* SEEK */ /* CTX_SWITCH: caches of gr objects bound to subchannels. 8 values, last used index */ @@ -1394,7 +1375,7 @@ nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) /* SEEK */ xf_emit(ctx, 9, 0); /* SEEK */ - if (dev_priv->chipset < 0x90) + if (device->chipset < 0x90) xf_emit(ctx, 4, 0); /* SEEK */ xf_emit(ctx, 2, 0); @@ -1407,9 +1388,9 @@ nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) xf_emit(ctx, 6*2, 0); xf_emit(ctx, 2, 0); /* SEEK */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 0x1c, 0); - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) xf_emit(ctx, 0x1e, 0); else xf_emit(ctx, 0x22, 0); @@ -1421,9 +1402,9 @@ static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) { /* Strand 0, right after dispatch */ - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int smallm2mf = 0; - if (dev_priv->chipset < 0x92 || dev_priv->chipset == 0x98) + if (device->chipset < 0x92 || device->chipset == 0x98) smallm2mf = 1; /* SEEK */ xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ @@ -1472,10 +1453,10 @@ nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 2, 0); /* RO */ xf_emit(ctx, 0x800, 0); /* ffffffff */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: case 0x92: case 0xa0: @@ -1540,7 +1521,7 @@ nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; /* end of area 2 on pre-NVA0, area 1 on NVAx */ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ @@ -1550,14 +1531,14 @@ nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); else xf_emit(ctx, 1, 0x7ff); /* 000007ff */ xf_emit(ctx, 1, 0); /* 111/113 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ for (i = 0; i < 8; i++) { - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: case 0x86: case 0x98: @@ -1600,7 +1581,7 @@ nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* end of area 2 on pre-NVA0, area 1 on NVAx */ xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ xf_emit(ctx, 1, 0); /* 00000003 VIEWPORT_CLIP_MODE */ @@ -1614,9 +1595,9 @@ nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0x1fe21); /* 0001ffff tesla UNK0FAC */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0x0fac6881); - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 1); xf_emit(ctx, 3, 0); } @@ -1625,9 +1606,9 @@ nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 5, 0); /* ffffffff */ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 0); /* 00000001 */ @@ -1643,14 +1624,14 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ xf_emit(ctx, 1, 0); /* 000000ff VP_CLIP_DISTANCE_ENABLE */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 3ff */ xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1940 */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0x7f); /* 000000ff tesla UNK0FFC */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ xf_emit(ctx, 1, 1); /* 00000001 SHADE_MODEL */ @@ -1669,7 +1650,7 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ xf_emit(ctx, 1, 0); /* 0000000f */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ else xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ @@ -1704,11 +1685,11 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 0); /* ffffffff */ xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 000003ff */ @@ -1736,7 +1717,7 @@ nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */ /* SEEK */ xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ @@ -1774,7 +1755,7 @@ nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ xf_emit(ctx, 1, 0); /* 00000007 */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1108 */ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ @@ -1789,7 +1770,7 @@ nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ xf_emit(ctx, 1, 3); /* 00000003 FP_CTRL_UNK196C */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1968 */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 0fffffff tesla UNK1104 */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK151C */ } @@ -1817,7 +1798,7 @@ nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */ /* SEEK */ @@ -1829,7 +1810,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 4, 0); /* RO */ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ xf_emit(ctx, 1, 0); /* 1ff */ @@ -1860,7 +1841,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ /* SEEK */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ @@ -1869,7 +1850,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 1); /* 00000001 */ /* SEEK */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 2, 4); /* 000000ff */ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ @@ -1893,20 +1874,20 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) xf_emit(ctx, 0x10, 0); /* 00ffffff POINT_COORD_REPLACE_MAP */ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 000003ff */ } static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int acnt = 0x10, rep, i; /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) acnt = 0x20; /* SEEK */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */ xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */ } @@ -1923,9 +1904,9 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0000ffff turing USER_PARAM_COUNT */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0xb, 0); /* RO */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 0x9, 0); /* RO */ else xf_emit(ctx, 0x8, 0); /* RO */ @@ -1944,11 +1925,11 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 000001ff UNK1A28 */ xf_emit(ctx, 1, 8); /* 000001ff UNK0DF0 */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */ else xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */ - if (dev_priv->chipset == 0xa8) + if (device->chipset == 0xa8) xf_emit(ctx, 1, 0x1e00); /* 7fff */ /* SEEK */ xf_emit(ctx, 0xc, 0); /* RO or close */ @@ -1956,13 +1937,13 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ - if (dev_priv->chipset > 0x50 && dev_priv->chipset < 0xa0) + if (device->chipset > 0x50 && device->chipset < 0xa0) xf_emit(ctx, 2, 0); /* ffffffff */ else xf_emit(ctx, 1, 0); /* ffffffff */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0FD8 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 0x10, 0); /* 0? */ xf_emit(ctx, 2, 0); /* weird... */ xf_emit(ctx, 2, 0); /* RO */ @@ -1975,7 +1956,7 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* ffffffff VB_ELEMENT_BASE */ xf_emit(ctx, 1, 0); /* ffffffff UNK1438 */ xf_emit(ctx, acnt, 0); /* 1 tesla UNK1000 */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */ /* SEEK */ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ @@ -2013,23 +1994,23 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */ xf_emit(ctx, 3, 0); /* f/1f */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, acnt, 0); /* f */ xf_emit(ctx, 3, 0); /* f/1f */ } /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 2, 0); /* RO */ else xf_emit(ctx, 5, 0); /* RO */ /* SEEK */ xf_emit(ctx, 1, 0); /* ffff DMA_VTXBUF */ /* SEEK */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { xf_emit(ctx, 0x41, 0); /* RO */ /* SEEK */ xf_emit(ctx, 0x11, 0); /* RO */ - } else if (!IS_NVA3F(dev_priv->chipset)) + } else if (!IS_NVA3F(device->chipset)) xf_emit(ctx, 0x50, 0); /* RO */ else xf_emit(ctx, 0x58, 0); /* RO */ @@ -2041,7 +2022,7 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, acnt*4, 0); /* ffffffff VTX_ATTR */ xf_emit(ctx, 4, 0); /* f/1f, 0, 0, 0 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x1d, 0); /* RO */ else xf_emit(ctx, 0x16, 0); /* RO */ @@ -2049,21 +2030,21 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ /* SEEK */ - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) xf_emit(ctx, 8, 0); /* RO */ - else if (IS_NVA3F(dev_priv->chipset)) + else if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0xc, 0); /* RO */ else xf_emit(ctx, 7, 0); /* RO */ /* SEEK */ xf_emit(ctx, 0xa, 0); /* RO */ - if (dev_priv->chipset == 0xa0) + if (device->chipset == 0xa0) rep = 0xc; else rep = 4; for (i = 0; i < rep; i++) { /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x20, 0); /* ffffffff */ xf_emit(ctx, 0x200, 0); /* ffffffff */ xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */ @@ -2077,7 +2058,7 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ /* SEEK */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 7, 0); /* weird... */ else xf_emit(ctx, 5, 0); /* weird... */ @@ -2086,13 +2067,13 @@ nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* middle of strand 1 on pre-NVA0 [after vfetch], middle of strand 6 on NVAx */ /* SEEK */ xf_emit(ctx, 2, 0); /* 0001ffff CLIP_X, CLIP_Y */ xf_emit(ctx, 2, 0); /* 0000ffff CLIP_W, CLIP_H */ xf_emit(ctx, 1, 0); /* 00000001 CLIP_ENABLE */ - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { /* this is useless on everything but the original NV50, * guess they forgot to nuke it. Or just didn't bother. */ xf_emit(ctx, 2, 0); /* 0000ffff IFC_CLIP_X, Y */ @@ -2148,7 +2129,7 @@ nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* middle of strand 1 on pre-NVA0 [after eng2d], middle of strand 0 on NVAx */ /* SEEK */ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY... what is it doing here??? */ @@ -2173,7 +2154,7 @@ nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ /* SEEK */ xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: case 0x92: xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ @@ -2247,7 +2228,7 @@ nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ @@ -2277,9 +2258,9 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 1, 1); /* 00000001 UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ @@ -2293,11 +2274,11 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* ffffffff POINT_SIZE */ xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 00000007 tesla UNK0FB4 */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 0); /* 3ff */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */ } - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ @@ -2316,11 +2297,11 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) xf_emit(ctx, 0x1c, 0); /* RO */ - else if (IS_NVA3F(dev_priv->chipset)) + else if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x9, 0); xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ @@ -2328,13 +2309,13 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ xf_emit(ctx, 1, 0); /* 3ff */ } /* XXX: the following block could belong either to unk1cxx, or * to STRMOUT. Rather hard to tell. */ - if (dev_priv->chipset < 0xa0) + if (device->chipset < 0xa0) xf_emit(ctx, 0x25, 0); else xf_emit(ctx, 0x3b, 0); @@ -2343,18 +2324,18 @@ nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ } xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ else xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ @@ -2365,7 +2346,7 @@ nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) xf_emit(ctx, 4, 0); /* 000000ff STRMOUT_ADDRESS_HIGH */ xf_emit(ctx, 4, 0); /* ffffffff STRMOUT_ADDRESS_LOW */ xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ } @@ -2385,12 +2366,12 @@ nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0); /* 000003ff */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ } @@ -2398,7 +2379,7 @@ nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; /* SEEK */ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ @@ -2416,7 +2397,7 @@ nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 eng2d UNK260 */ xf_emit(ctx, 1, 0); /* ff/3ff */ xf_emit(ctx, 1, 0); /* 00000007 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ } @@ -2424,11 +2405,11 @@ nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int magic2; - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { magic2 = 0x00003e60; - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { magic2 = 0x001ffe67; } else { magic2 = 0x00087e67; @@ -2446,14 +2427,14 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ - if (dev_priv->chipset >= 0xa0 && !IS_NVAAF(dev_priv->chipset)) + if (device->chipset >= 0xa0 && !IS_NVAAF(device->chipset)) xf_emit(ctx, 1, 0x15); /* 000000ff */ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ @@ -2462,14 +2443,14 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) { + if (device->chipset == 0x86 || device->chipset == 0x92 || device->chipset == 0x98 || device->chipset >= 0xa0) { xf_emit(ctx, 3, 0); /* ff, ffffffff, ffffffff */ xf_emit(ctx, 1, 4); /* 7 */ xf_emit(ctx, 1, 0x400); /* fffffff */ xf_emit(ctx, 1, 0x300); /* ffff */ xf_emit(ctx, 1, 0x1001); /* 1fff */ - if (dev_priv->chipset != 0xa0) { - if (IS_NVA3F(dev_priv->chipset)) + if (device->chipset != 0xa0) { + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */ else xf_emit(ctx, 1, 0x15); /* ff */ @@ -2547,7 +2528,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 2, 0); xf_emit(ctx, 1, 0x1001); xf_emit(ctx, 0xb, 0); @@ -2564,7 +2545,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ xf_emit(ctx, 1, 0x11); /* 3f/7f */ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ - if (dev_priv->chipset != 0x50) { + if (device->chipset != 0x50) { xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ xf_emit(ctx, 1, 0); /* 000000ff */ } @@ -2581,7 +2562,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 tesla UNK12E4 */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ @@ -2600,7 +2581,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 000003ff */ - } else if (dev_priv->chipset >= 0xa0) { + } else if (device->chipset >= 0xa0) { xf_emit(ctx, 2, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0); /* 00000003 */ @@ -2614,7 +2595,7 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 4, 0); /* ffffffff CLEAR_COLOR */ xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR A R G B */ xf_emit(ctx, 1, 0); /* 00000fff eng2d UNK2B0 */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 2, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* 000003ff */ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ @@ -2628,9 +2609,9 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ @@ -2659,9 +2640,9 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int magic3; - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: magic3 = 0x1000; break; @@ -2681,16 +2662,16 @@ nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ xf_emit(ctx, 1, 0); /* 111/113[NVA0+] */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x1f, 0); /* ffffffff */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 0x0f, 0); /* ffffffff */ else xf_emit(ctx, 0x10, 0); /* fffffff VP_RESULT_MAP_1 up */ xf_emit(ctx, 2, 0); /* f/1f[NVA3], fffffff/ffffffff[NVA0+] */ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0x03020100); /* ffffffff */ else xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */ @@ -2733,11 +2714,11 @@ nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ xf_emit(ctx, 1, 0); /* 111/113 */ - if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96) + if (device->chipset == 0x94 || device->chipset == 0x96) xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ - else if (dev_priv->chipset < 0xa0) + else if (device->chipset < 0xa0) xf_emit(ctx, 0xa20, 0); /* 4 x (0x280 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ - else if (!IS_NVA3F(dev_priv->chipset)) + else if (!IS_NVA3F(device->chipset)) xf_emit(ctx, 0x210, 0); /* ffffffff */ else xf_emit(ctx, 0x410, 0); /* ffffffff */ @@ -2751,12 +2732,12 @@ nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int magic1, magic2; - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { magic1 = 0x3ff; magic2 = 0x00003e60; - } else if (!IS_NVA3F(dev_priv->chipset)) { + } else if (!IS_NVA3F(device->chipset)) { magic1 = 0x7ff; magic2 = 0x001ffe67; } else { @@ -2766,7 +2747,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ xf_emit(ctx, 1, 0); /* ffffffff ALPHA_TEST_REF */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000000f UNK16A0 */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ @@ -2800,11 +2781,11 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 SIFC_BITMAP_WRITE_BIT0_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000003 */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1298 */ - } else if (dev_priv->chipset >= 0xa0) { + } else if (device->chipset >= 0xa0) { xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000003 */ } else { @@ -2818,7 +2799,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ @@ -2846,7 +2827,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ xf_emit(ctx, 1, 0xcf); /* 000000ff DRAW_COLOR_FORMAT */ xf_emit(ctx, 1, 0xcf); /* 000000ff SRC_FORMAT */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ xf_emit(ctx, 1, 0); /* 7/f[NVA3] MULTISAMPLE_SAMPLES_LOG2 */ @@ -2870,9 +2851,9 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0); /* ff */ else xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ @@ -2907,7 +2888,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */ xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */ @@ -2945,7 +2926,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ xf_emit(ctx, 1, 0); /* 00000007 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ @@ -2974,7 +2955,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 0); /* 00000001 */ xf_emit(ctx, 1, 0); /* ffff0ff3 */ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ @@ -2988,14 +2969,14 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ xf_emit(ctx, 1, 0); /* 7 */ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ } xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ xf_emit(ctx, 1, 0); /* ffff0ff3 */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0x0fac6881); /* fffffff */ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ @@ -3012,12 +2993,12 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 0000000f tesla UNK15C8 */ } xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */ xf_emit(ctx, 1, 0xfac6881); /* fffffff */ xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */ @@ -3027,7 +3008,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 2, 0); /* 7, f */ xf_emit(ctx, 1, 1); /* 1 */ xf_emit(ctx, 1, 0); /* 7/f */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 0x9, 0); /* 1 */ else xf_emit(ctx, 0x8, 0); /* 1 */ @@ -3041,7 +3022,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x11); /* 7f */ xf_emit(ctx, 1, 1); /* 1 */ xf_emit(ctx, 5, 0); /* 1, 7, 3ff, 3, 7 */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ } @@ -3051,15 +3032,15 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */ - if (dev_priv->chipset != 0x50) + if (device->chipset != 0x50) xf_emit(ctx, 1, 0); /* 3 */ xf_emit(ctx, 1, 1); /* 1ffff BLIT_DU_DX_INT */ xf_emit(ctx, 1, 0); /* fffff BLIT_DU_DX_FRACT */ xf_emit(ctx, 1, 1); /* 1ffff BLIT_DV_DY_INT */ xf_emit(ctx, 1, 0); /* fffff BLIT_DV_DY_FRACT */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */ else xf_emit(ctx, 2, 0); /* 3ff, 1 */ @@ -3071,13 +3052,13 @@ nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x10100); /* ffffffff SRC_TIC_5 */ xf_emit(ctx, 1, 0x02800000); /* ffffffff SRC_TIC_6 */ xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_7 */ - if (dev_priv->chipset == 0x50) { + if (device->chipset == 0x50) { xf_emit(ctx, 1, 0); /* 00000001 turing UNK358 */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ xf_emit(ctx, 1, 0); /* 00000003 turing UNK37C tesla UNK1690 */ xf_emit(ctx, 1, 0); /* 00000003 BLIT_CONTROL */ xf_emit(ctx, 1, 0); /* 00000001 turing UNK32C tesla UNK0F94 */ - } else if (!IS_NVAAF(dev_priv->chipset)) { + } else if (!IS_NVAAF(device->chipset)) { xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ xf_emit(ctx, 1, 0); /* 00000003 */ xf_emit(ctx, 1, 0); /* 000003ff */ @@ -3097,7 +3078,7 @@ nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */ @@ -3109,7 +3090,7 @@ nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK0F98 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ @@ -3136,8 +3117,8 @@ nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; - if (dev_priv->chipset < 0xa0) { + struct nouveau_device *device = ctx->device; + if (device->chipset < 0xa0) { nv50_graph_construct_xfer_unk84xx(ctx); nv50_graph_construct_xfer_tprop(ctx); nv50_graph_construct_xfer_tex(ctx); @@ -3153,9 +3134,9 @@ nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i, mpcnt = 2; - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x98: case 0xaa: mpcnt = 1; @@ -3182,34 +3163,34 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0x80); /* ffffffff tesla UNK1404 */ xf_emit(ctx, 1, 0x80007004); /* ffffffff tesla UNK12B0 */ xf_emit(ctx, 1, 0x04000400); /* ffffffff */ - if (dev_priv->chipset >= 0xa0) + if (device->chipset >= 0xa0) xf_emit(ctx, 1, 0xc0); /* 00007fff tesla UNK152C */ xf_emit(ctx, 1, 0x1000); /* 0000ffff tesla UNK0D60 */ xf_emit(ctx, 1, 0); /* ff/3ff */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ - if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset == 0xa8 || IS_NVAAF(dev_priv->chipset)) { + if (device->chipset == 0x86 || device->chipset == 0x98 || device->chipset == 0xa8 || IS_NVAAF(device->chipset)) { xf_emit(ctx, 1, 0xe00); /* 7fff */ xf_emit(ctx, 1, 0x1e00); /* 7fff */ } xf_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP */ xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 2, 0x1000); /* 7fff tesla UNK141C */ xf_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP */ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ - if (IS_NVAAF(dev_priv->chipset)) + if (IS_NVAAF(device->chipset)) xf_emit(ctx, 0xb, 0); /* RO */ - else if (dev_priv->chipset >= 0xa0) + else if (device->chipset >= 0xa0) xf_emit(ctx, 0xc, 0); /* RO */ else xf_emit(ctx, 0xa, 0); /* RO */ } xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ xf_emit(ctx, 1, 0); /* ff/3ff */ - if (dev_priv->chipset >= 0xa0) { + if (device->chipset >= 0xa0) { xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */ } xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */ @@ -3223,7 +3204,7 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ xf_emit(ctx, 1, 0x1fe21); /* 1ffff/3ffff[NVA0+] tesla UNk0FAC */ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ xf_emit(ctx, 1, 0); /* ff/3ff */ xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */ @@ -3238,7 +3219,7 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000007 */ xf_emit(ctx, 1, 0xfac6881); /* 0fffffff RT_CONTROL */ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ - if (IS_NVA3F(dev_priv->chipset)) + if (IS_NVA3F(device->chipset)) xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ @@ -3253,7 +3234,7 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ - if (IS_NVA3F(dev_priv->chipset)) { + if (IS_NVA3F(device->chipset)) { xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ @@ -3268,11 +3249,11 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ xf_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ /* XXX: demagic this part some day */ - if (dev_priv->chipset == 0x50) + if (device->chipset == 0x50) xf_emit(ctx, 0x3a0, 0); - else if (dev_priv->chipset < 0x94) + else if (device->chipset < 0x94) xf_emit(ctx, 0x3a2, 0); - else if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa) + else if (device->chipset == 0x98 || device->chipset == 0xaa) xf_emit(ctx, 0x39f, 0); else xf_emit(ctx, 0x3a3, 0); @@ -3285,15 +3266,15 @@ nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx) { - struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + struct nouveau_device *device = ctx->device; int i; - uint32_t offset; - uint32_t units = nv_rd32 (ctx->dev, 0x1540); + u32 offset; + u32 units = nv_rd32 (ctx->device, 0x1540); int size = 0; offset = (ctx->ctxvals_pos+0x3f)&~0x3f; - if (dev_priv->chipset < 0xa0) { + if (device->chipset < 0xa0) { for (i = 0; i < 8; i++) { ctx->ctxvals_pos = offset + i; /* that little bugger belongs to csched. No idea diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index b19a406e55d9..c12e7668dbfe 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -22,13 +22,10 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include <core/mm.h> #include "nvc0.h" void -nv_icmd(struct drm_device *priv, u32 icmd, u32 data) +nv_icmd(struct nvc0_graph_priv *priv, u32 icmd, u32 data) { nv_wr32(priv, 0x400204, data); nv_wr32(priv, 0x400200, icmd); @@ -36,21 +33,22 @@ nv_icmd(struct drm_device *priv, u32 icmd, u32 data) } int -nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, - struct nvc0_grctx *info) +nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) { + struct nouveau_bar *bar = nouveau_bar(priv); + struct nouveau_object *parent = nv_object(priv); struct nouveau_gpuobj *chan; - u32 size = (0x80000 + oprv->size + 4095) & ~4095; + u32 size = (0x80000 + priv->size + 4095) & ~4095; int ret, i; /* allocate memory to for a "channel", which we'll use to generate * the default context values */ - ret = nouveau_gpuobj_new(priv, NULL, size, 0x1000, + ret = nouveau_gpuobj_new(parent, NULL, size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &info->chan); chan = info->chan; if (ret) { - NV_ERROR(priv, "failed to allocate channel memory, %d\n", ret); + nv_error(priv, "failed to allocate channel memory, %d\n", ret); return ret; } @@ -75,32 +73,31 @@ nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, nv_wo32(chan, 0x0210, 0x00080004); nv_wo32(chan, 0x0214, 0x00000000); - nvimem_flush(priv); + bar->flush(bar); nv_wr32(priv, 0x100cb8, (chan->addr + 0x1000) >> 8); nv_wr32(priv, 0x100cbc, 0x80000001); nv_wait(priv, 0x100c80, 0x00008000, 0x00008000); /* setup default state for mmio list construction */ - info->dev = priv; - info->data = oprv->mmio_data; - info->mmio = oprv->mmio_list; + info->data = priv->mmio_data; + info->mmio = priv->mmio_list; info->addr = 0x2000 + (i * 8); - info->priv = oprv; + info->priv = priv; info->buffer_nr = 0; - if (oprv->firmware) { + if (priv->firmware) { nv_wr32(priv, 0x409840, 0x00000030); nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); nv_wr32(priv, 0x409504, 0x00000003); if (!nv_wait(priv, 0x409800, 0x00000010, 0x00000010)) - NV_ERROR(priv, "load_ctx timeout\n"); + nv_error(priv, "load_ctx timeout\n"); nv_wo32(chan, 0x8001c, 1); nv_wo32(chan, 0x80020, 0); nv_wo32(chan, 0x80028, 0); nv_wo32(chan, 0x8002c, 0); - nvimem_flush(priv); + bar->flush(bar); return 0; } @@ -109,7 +106,7 @@ nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); nv_wr32(priv, 0x409504, 0x00000001); if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(priv, "HUB_SET_CHAN timeout\n"); + nv_error(priv, "HUB_SET_CHAN timeout\n"); nvc0_graph_ctxctl_debug(priv); nouveau_gpuobj_ref(NULL, &info->chan); return -EBUSY; @@ -135,6 +132,8 @@ nvc0_grctx_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access) void nvc0_grctx_mmio(struct nvc0_grctx *info, u32 addr, u32 data, u32 shift, u32 buf) { + struct nvc0_graph_priv *priv = info->priv; + info->mmio->addr = addr; info->mmio->data = data; info->mmio->shift = shift; @@ -143,7 +142,7 @@ nvc0_grctx_mmio(struct nvc0_grctx *info, u32 addr, u32 data, u32 shift, u32 buf) if (shift) data |= info->buffer[buf] >> shift; - nv_wr32(info->dev, addr, data); + nv_wr32(priv, addr, data); } int @@ -153,11 +152,11 @@ nvc0_grctx_fini(struct nvc0_grctx *info) int i; if (priv->firmware) { - nv_wr32(info->dev, 0x409840, 0x00000003); - nv_wr32(info->dev, 0x409500, 0x80000000 | info->chan->addr >> 12); - nv_wr32(info->dev, 0x409504, 0x00000009); - if (!nv_wait(info->dev, 0x409800, 0x00000001, 0x00000000)) { - NV_ERROR(info->dev, "unload_ctx timeout\n"); + nv_wr32(priv, 0x409840, 0x00000003); + nv_wr32(priv, 0x409500, 0x80000000 | info->chan->addr >> 12); + nv_wr32(priv, 0x409504, 0x00000009); + if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000000)) { + nv_error(priv, "unload_ctx timeout\n"); return -EBUSY; } @@ -165,12 +164,12 @@ nvc0_grctx_fini(struct nvc0_grctx *info) } /* HUB_FUC(CTX_SAVE) */ - nv_wr32(info->dev, 0x409840, 0x80000000); - nv_wr32(info->dev, 0x409500, 0x80000000 | info->chan->addr >> 12); - nv_wr32(info->dev, 0x409504, 0x00000002); - if (!nv_wait(info->dev, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(info->dev, "HUB_CTX_SAVE timeout\n"); - nvc0_graph_ctxctl_debug(info->dev); + nv_wr32(priv, 0x409840, 0x80000000); + nv_wr32(priv, 0x409500, 0x80000000 | info->chan->addr >> 12); + nv_wr32(priv, 0x409504, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { + nv_error(priv, "HUB_CTX_SAVE timeout\n"); + nvc0_graph_ctxctl_debug(priv); return -EBUSY; } @@ -186,7 +185,7 @@ save: } static void -nvc0_grctx_generate_9097(struct drm_device *priv) +nvc0_grctx_generate_9097(struct nvc0_graph_priv *priv) { u32 fermi = nvc0_graph_class(priv); u32 mthd; @@ -1343,7 +1342,7 @@ nvc0_grctx_generate_9097(struct drm_device *priv) } static void -nvc0_grctx_generate_9197(struct drm_device *priv) +nvc0_grctx_generate_9197(struct nvc0_graph_priv *priv) { u32 fermi = nvc0_graph_class(priv); u32 mthd; @@ -1356,7 +1355,7 @@ nvc0_grctx_generate_9197(struct drm_device *priv) } static void -nvc0_grctx_generate_9297(struct drm_device *priv) +nvc0_grctx_generate_9297(struct nvc0_graph_priv *priv) { u32 fermi = nvc0_graph_class(priv); u32 mthd; @@ -1374,7 +1373,7 @@ nvc0_grctx_generate_9297(struct drm_device *priv) } static void -nvc0_grctx_generate_902d(struct drm_device *priv) +nvc0_grctx_generate_902d(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0x902d, 0x0200, 0x000000cf); nv_mthd(priv, 0x902d, 0x0204, 0x00000001); @@ -1396,7 +1395,7 @@ nvc0_grctx_generate_902d(struct drm_device *priv) } static void -nvc0_grctx_generate_9039(struct drm_device *priv) +nvc0_grctx_generate_9039(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0x9039, 0x030c, 0x00000000); nv_mthd(priv, 0x9039, 0x0310, 0x00000000); @@ -1409,12 +1408,11 @@ nvc0_grctx_generate_9039(struct drm_device *priv) } static void -nvc0_grctx_generate_90c0(struct drm_device *priv) +nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; int i; - for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { + for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) { nv_mthd(priv, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); @@ -1430,7 +1428,7 @@ nvc0_grctx_generate_90c0(struct drm_device *priv) nv_mthd(priv, 0x90c0, 0x27ac, 0x00000000); nv_mthd(priv, 0x90c0, 0x27cc, 0x00000000); nv_mthd(priv, 0x90c0, 0x27ec, 0x00000000); - for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { + for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) { nv_mthd(priv, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); @@ -1458,7 +1456,7 @@ nvc0_grctx_generate_90c0(struct drm_device *priv) } static void -nvc0_grctx_generate_dispatch(struct drm_device *priv) +nvc0_grctx_generate_dispatch(struct nvc0_graph_priv *priv) { int i; @@ -1511,7 +1509,7 @@ nvc0_grctx_generate_dispatch(struct drm_device *priv) } static void -nvc0_grctx_generate_macro(struct drm_device *priv) +nvc0_grctx_generate_macro(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404404, 0x00000000); nv_wr32(priv, 0x404408, 0x00000000); @@ -1536,7 +1534,7 @@ nvc0_grctx_generate_macro(struct drm_device *priv) } static void -nvc0_grctx_generate_m2mf(struct drm_device *priv) +nvc0_grctx_generate_m2mf(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404604, 0x00000015); nv_wr32(priv, 0x404608, 0x00000000); @@ -1600,7 +1598,7 @@ nvc0_grctx_generate_m2mf(struct drm_device *priv) } static void -nvc0_grctx_generate_unk47xx(struct drm_device *priv) +nvc0_grctx_generate_unk47xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404700, 0x00000000); nv_wr32(priv, 0x404704, 0x00000000); @@ -1627,16 +1625,15 @@ nvc0_grctx_generate_unk47xx(struct drm_device *priv) } static void -nvc0_grctx_generate_shaders(struct drm_device *priv) +nvc0_grctx_generate_shaders(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { nv_wr32(priv, 0x405800, 0x0f8000bf); nv_wr32(priv, 0x405830, 0x02180218); nv_wr32(priv, 0x405834, 0x08000000); } else - if (dev_priv->chipset == 0xc1) { + if (nv_device(priv)->chipset == 0xc1) { nv_wr32(priv, 0x405800, 0x0f8000bf); nv_wr32(priv, 0x405830, 0x02180218); nv_wr32(priv, 0x405834, 0x00000000); @@ -1657,7 +1654,7 @@ nvc0_grctx_generate_shaders(struct drm_device *priv) } static void -nvc0_grctx_generate_unk60xx(struct drm_device *priv) +nvc0_grctx_generate_unk60xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x406020, 0x000103c1); nv_wr32(priv, 0x406028, 0x00000001); @@ -1667,25 +1664,24 @@ nvc0_grctx_generate_unk60xx(struct drm_device *priv) } static void -nvc0_grctx_generate_unk64xx(struct drm_device *priv) +nvc0_grctx_generate_unk64xx(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; nv_wr32(priv, 0x4064a8, 0x00000000); nv_wr32(priv, 0x4064ac, 0x00003fff); nv_wr32(priv, 0x4064b4, 0x00000000); nv_wr32(priv, 0x4064b8, 0x00000000); - if (dev_priv->chipset == 0xd9) + if (nv_device(priv)->chipset == 0xd9) nv_wr32(priv, 0x4064bc, 0x00000000); - if (dev_priv->chipset == 0xc1 || - dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xc1 || + nv_device(priv)->chipset == 0xd9) { nv_wr32(priv, 0x4064c0, 0x80140078); nv_wr32(priv, 0x4064c4, 0x0086ffff); } } static void -nvc0_grctx_generate_tpbus(struct drm_device *priv) +nvc0_grctx_generate_tpbus(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x407804, 0x00000023); nv_wr32(priv, 0x40780c, 0x0a418820); @@ -1698,7 +1694,7 @@ nvc0_grctx_generate_tpbus(struct drm_device *priv) } static void -nvc0_grctx_generate_ccache(struct drm_device *priv) +nvc0_grctx_generate_ccache(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x408000, 0x00000000); nv_wr32(priv, 0x408004, 0x00000000); @@ -1711,10 +1707,9 @@ nvc0_grctx_generate_ccache(struct drm_device *priv) } static void -nvc0_grctx_generate_rop(struct drm_device *priv) +nvc0_grctx_generate_rop(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - int chipset = dev_priv->chipset; + int chipset = nv_device(priv)->chipset; /* ROPC_BROADCAST */ nv_wr32(priv, 0x408800, 0x02802a3c); @@ -1741,10 +1736,9 @@ nvc0_grctx_generate_rop(struct drm_device *priv) } static void -nvc0_grctx_generate_gpc(struct drm_device *priv) +nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - int chipset = dev_priv->chipset; + int chipset = nv_device(priv)->chipset; int i; /* GPC_BROADCAST */ @@ -1834,10 +1828,9 @@ nvc0_grctx_generate_gpc(struct drm_device *priv) } static void -nvc0_grctx_generate_tp(struct drm_device *priv) +nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - int chipset = dev_priv->chipset; + int chipset = nv_device(priv)->chipset; /* GPC_BROADCAST.TP_BROADCAST */ nv_wr32(priv, 0x419818, 0x00000000); @@ -1876,7 +1869,7 @@ nvc0_grctx_generate_tp(struct drm_device *priv) nv_wr32(priv, 0x419c04, 0x00000006); nv_wr32(priv, 0x419c08, 0x00000002); nv_wr32(priv, 0x419c20, 0x00000000); - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { nv_wr32(priv, 0x419c24, 0x00084210); nv_wr32(priv, 0x419c28, 0x3cf3cf3c); nv_wr32(priv, 0x419cb0, 0x00020048); @@ -1929,16 +1922,14 @@ nvc0_grctx_generate_tp(struct drm_device *priv) } int -nvc0_grctx_generate(struct drm_device *priv) +nvc0_grctx_generate(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = priv->dev_private; - struct nvc0_graph_priv *oprv = nv_engine(priv, NVOBJ_ENGINE_GR); struct nvc0_grctx info; int ret, i, gpc, tpc, id; u32 fermi = nvc0_graph_class(priv); u32 r000260, tmp; - ret = nvc0_grctx_init(priv, oprv, &info); + ret = nvc0_grctx_init(priv, &info); if (ret) return ret; @@ -1975,11 +1966,11 @@ nvc0_grctx_generate(struct drm_device *priv) mmio_list(0x419008, 0x00000000, 0, 0); mmio_list(0x418808, 0x00000000, 8, 0); mmio_list(0x41880c, 0x80000018, 0, 0); - if (dev_priv->chipset != 0xc1) { + if (nv_device(priv)->chipset != 0xc1) { tmp = 0x02180000; mmio_list(0x405830, tmp, 0, 0); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { u32 reg = TPC_UNIT(gpc, tpc, 0x0520); mmio_list(reg, tmp, 0, 0); tmp += 0x0324; @@ -1989,13 +1980,13 @@ nvc0_grctx_generate(struct drm_device *priv) tmp = 0x02180000; mmio_list(0x405830, 0x00000218 | tmp, 0, 0); mmio_list(0x4064c4, 0x0086ffff, 0, 0); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { u32 reg = TPC_UNIT(gpc, tpc, 0x0520); mmio_list(reg, 0x10000000 | tmp, 0, 0); tmp += 0x0324; } - for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { u32 reg = TPC_UNIT(gpc, tpc, 0x0544); mmio_list(reg, tmp, 0, 0); tmp += 0x0324; @@ -2004,8 +1995,8 @@ nvc0_grctx_generate(struct drm_device *priv) } for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - if (tpc < oprv->tpc_nr[gpc]) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tpc < priv->tpc_nr[gpc]) { nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x4e8), id); nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); @@ -2013,14 +2004,14 @@ nvc0_grctx_generate(struct drm_device *priv) id++; } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); } } tmp = 0; - for (i = 0; i < oprv->gpc_nr; i++) - tmp |= oprv->tpc_nr[i] << (i * 4); + for (i = 0; i < priv->gpc_nr; i++) + tmp |= priv->tpc_nr[i] << (i * 4); nv_wr32(priv, 0x406028, tmp); nv_wr32(priv, 0x405870, tmp); @@ -2034,13 +2025,13 @@ nvc0_grctx_generate(struct drm_device *priv) if (1) { u8 tpcnr[GPC_MAX], data[TPC_MAX]; - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); memset(data, 0x1f, sizeof(data)); gpc = -1; - for (tpc = 0; tpc < oprv->tpc_total; tpc++) { + for (tpc = 0; tpc < priv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; data[tpc] = gpc; @@ -2056,12 +2047,12 @@ nvc0_grctx_generate(struct drm_device *priv) u8 shift, ntpcv; /* calculate first set of magics */ - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < oprv->tpc_total; tpc++) { + for (tpc = 0; tpc < priv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -2073,7 +2064,7 @@ nvc0_grctx_generate(struct drm_device *priv) /* and the second... */ shift = 0; - ntpcv = oprv->tpc_total; + ntpcv = priv->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -2086,22 +2077,22 @@ nvc0_grctx_generate(struct drm_device *priv) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* GPC_BROADCAST */ - nv_wr32(priv, 0x418bb8, (oprv->tpc_total << 8) | - oprv->magic_not_rop_nr); + nv_wr32(priv, 0x418bb8, (priv->tpc_total << 8) | + priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x418b08 + (i * 4), data[i]); /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(priv, 0x419bd0, (oprv->tpc_total << 8) | - oprv->magic_not_rop_nr | + nv_wr32(priv, 0x419bd0, (priv->tpc_total << 8) | + priv->magic_not_rop_nr | data2[0]); nv_wr32(priv, 0x419be4, data2[1]); for (i = 0; i < 6; i++) nv_wr32(priv, 0x419b00 + (i * 4), data[i]); /* UNK78xx */ - nv_wr32(priv, 0x4078bc, (oprv->tpc_total << 8) | - oprv->magic_not_rop_nr); + nv_wr32(priv, 0x4078bc, (priv->tpc_total << 8) | + priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x40780c + (i * 4), data[i]); } @@ -2110,18 +2101,18 @@ nvc0_grctx_generate(struct drm_device *priv) u32 tpc_mask = 0, tpc_set = 0; u8 tpcnr[GPC_MAX], a, b; - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) - tpc_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) + tpc_mask |= ((1 << priv->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (oprv->tpc_total - 1)) / 32; + a = (i * (priv->tpc_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); - tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; tpc_set |= 1 << ((gpc * 8) + tpc); } @@ -2232,7 +2223,7 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x00000215, 0x00000040); nv_icmd(priv, 0x00000216, 0x00000040); nv_icmd(priv, 0x00000217, 0x00000040); - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { for (i = 0x0400; i <= 0x0417; i++) nv_icmd(priv, i, 0x00000040); } @@ -2244,7 +2235,7 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x0000021d, 0x0000c080); nv_icmd(priv, 0x0000021e, 0x0000c080); nv_icmd(priv, 0x0000021f, 0x0000c080); - if (dev_priv->chipset == 0xd9) { + if (nv_device(priv)->chipset == 0xd9) { for (i = 0x0440; i <= 0x0457; i++) nv_icmd(priv, i, 0x0000c080); } @@ -2810,8 +2801,8 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x0000053f, 0xffff0000); nv_icmd(priv, 0x00000585, 0x0000003f); nv_icmd(priv, 0x00000576, 0x00000003); - if (dev_priv->chipset == 0xc1 || - dev_priv->chipset == 0xd9) + if (nv_device(priv)->chipset == 0xc1 || + nv_device(priv)->chipset == 0xd9) nv_icmd(priv, 0x0000057b, 0x00000059); nv_icmd(priv, 0x00000586, 0x00000040); nv_icmd(priv, 0x00000582, 0x00000080); @@ -2913,7 +2904,7 @@ nvc0_grctx_generate(struct drm_device *priv) nv_icmd(priv, 0x00000957, 0x00000003); nv_icmd(priv, 0x0000095e, 0x20164010); nv_icmd(priv, 0x0000095f, 0x00000020); - if (dev_priv->chipset == 0xd9) + if (nv_device(priv)->chipset == 0xd9) nv_icmd(priv, 0x0000097d, 0x00000020); nv_icmd(priv, 0x00000683, 0x00000006); nv_icmd(priv, 0x00000685, 0x003fffff); @@ -3056,5 +3047,6 @@ nvc0_grctx_generate(struct drm_device *priv) nvc0_grctx_generate_90c0(priv); nv_wr32(priv, 0x000260, r000260); + return nvc0_grctx_fini(&info); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c index e5503170d68c..6d8c63931ee6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -22,13 +22,10 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include <core/mm.h> #include "nvc0.h" static void -nve0_grctx_generate_icmd(struct drm_device *priv) +nve0_grctx_generate_icmd(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x400208, 0x80000000); nv_icmd(priv, 0x001000, 0x00000004); @@ -916,7 +913,7 @@ nve0_grctx_generate_icmd(struct drm_device *priv) } static void -nve0_grctx_generate_a097(struct drm_device *priv) +nve0_grctx_generate_a097(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0xa097, 0x0800, 0x00000000); nv_mthd(priv, 0xa097, 0x0840, 0x00000000); @@ -2146,7 +2143,7 @@ nve0_grctx_generate_a097(struct drm_device *priv) } static void -nve0_grctx_generate_902d(struct drm_device *priv) +nve0_grctx_generate_902d(struct nvc0_graph_priv *priv) { nv_mthd(priv, 0x902d, 0x0200, 0x000000cf); nv_mthd(priv, 0x902d, 0x0204, 0x00000001); @@ -2169,7 +2166,7 @@ nve0_grctx_generate_902d(struct drm_device *priv) } static void -nve0_graph_generate_unk40xx(struct drm_device *priv) +nve0_graph_generate_unk40xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404010, 0x0); nv_wr32(priv, 0x404014, 0x0); @@ -2213,7 +2210,7 @@ nve0_graph_generate_unk40xx(struct drm_device *priv) } static void -nve0_graph_generate_unk44xx(struct drm_device *priv) +nve0_graph_generate_unk44xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404404, 0x0); nv_wr32(priv, 0x404408, 0x0); @@ -2238,7 +2235,7 @@ nve0_graph_generate_unk44xx(struct drm_device *priv) } static void -nve0_graph_generate_unk46xx(struct drm_device *priv) +nve0_graph_generate_unk46xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404604, 0x14); nv_wr32(priv, 0x404608, 0x0); @@ -2278,7 +2275,7 @@ nve0_graph_generate_unk46xx(struct drm_device *priv) } static void -nve0_graph_generate_unk47xx(struct drm_device *priv) +nve0_graph_generate_unk47xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x404700, 0x0); nv_wr32(priv, 0x404704, 0x0); @@ -2299,7 +2296,7 @@ nve0_graph_generate_unk47xx(struct drm_device *priv) } static void -nve0_graph_generate_unk58xx(struct drm_device *priv) +nve0_graph_generate_unk58xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x405800, 0xf8000bf); nv_wr32(priv, 0x405830, 0x2180648); @@ -2318,7 +2315,7 @@ nve0_graph_generate_unk58xx(struct drm_device *priv) } static void -nve0_graph_generate_unk60xx(struct drm_device *priv) +nve0_graph_generate_unk60xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x406020, 0x4103c1); nv_wr32(priv, 0x406028, 0x1); @@ -2328,7 +2325,7 @@ nve0_graph_generate_unk60xx(struct drm_device *priv) } static void -nve0_graph_generate_unk64xx(struct drm_device *priv) +nve0_graph_generate_unk64xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x4064a8, 0x0); nv_wr32(priv, 0x4064ac, 0x3fff); @@ -2350,13 +2347,13 @@ nve0_graph_generate_unk64xx(struct drm_device *priv) } static void -nve0_graph_generate_unk70xx(struct drm_device *priv) +nve0_graph_generate_unk70xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x407040, 0x0); } static void -nve0_graph_generate_unk78xx(struct drm_device *priv) +nve0_graph_generate_unk78xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x407804, 0x23); nv_wr32(priv, 0x40780c, 0xa418820); @@ -2369,7 +2366,7 @@ nve0_graph_generate_unk78xx(struct drm_device *priv) } static void -nve0_graph_generate_unk80xx(struct drm_device *priv) +nve0_graph_generate_unk80xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x408000, 0x0); nv_wr32(priv, 0x408004, 0x0); @@ -2382,7 +2379,7 @@ nve0_graph_generate_unk80xx(struct drm_device *priv) } static void -nve0_graph_generate_unk88xx(struct drm_device *priv) +nve0_graph_generate_unk88xx(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x408800, 0x2802a3c); nv_wr32(priv, 0x408804, 0x40); @@ -2395,7 +2392,7 @@ nve0_graph_generate_unk88xx(struct drm_device *priv) } static void -nve0_graph_generate_gpc(struct drm_device *priv) +nve0_graph_generate_gpc(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x418380, 0x16); nv_wr32(priv, 0x418400, 0x38004e00); @@ -2521,7 +2518,7 @@ nve0_graph_generate_gpc(struct drm_device *priv) } static void -nve0_graph_generate_tpc(struct drm_device *priv) +nve0_graph_generate_tpc(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x419848, 0x0); nv_wr32(priv, 0x419864, 0x129); @@ -2586,7 +2583,7 @@ nve0_graph_generate_tpc(struct drm_device *priv) } static void -nve0_graph_generate_tpcunk(struct drm_device *priv) +nve0_graph_generate_tpcunk(struct nvc0_graph_priv *priv) { nv_wr32(priv, 0x41be24, 0x6); nv_wr32(priv, 0x41bec0, 0x12180000); @@ -2604,9 +2601,8 @@ nve0_graph_generate_tpcunk(struct drm_device *priv) } int -nve0_grctx_generate(struct drm_device *priv) +nve0_grctx_generate(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *oprv = nv_engine(priv, NVOBJ_ENGINE_GR); struct nvc0_grctx info; int ret, i, gpc, tpc, id; u32 data[6] = {}, data2[2] = {}, tmp; @@ -2615,7 +2611,7 @@ nve0_grctx_generate(struct drm_device *priv) u8 tpcnr[GPC_MAX], a, b; u8 shift, ntpcv; - ret = nvc0_grctx_init(priv, oprv, &info); + ret = nvc0_grctx_init(priv, &info); if (ret) return ret; @@ -2657,17 +2653,17 @@ nve0_grctx_generate(struct drm_device *priv) mmio_list(0x419848, 0x10000000, 12, 2); mmio_list(0x405830, 0x02180648, 0, 0); mmio_list(0x4064c4, 0x0192ffff, 0, 0); - for (gpc = 0, offset = 0; gpc < oprv->gpc_nr; gpc++) { - u16 magic0 = 0x0218 * oprv->tpc_nr[gpc]; - u16 magic1 = 0x0648 * oprv->tpc_nr[gpc]; + for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) { + u16 magic0 = 0x0218 * priv->tpc_nr[gpc]; + u16 magic1 = 0x0648 * priv->tpc_nr[gpc]; magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset; magic[gpc][1] = 0x00000000 | (magic1 << 16); - offset += 0x0324 * oprv->tpc_nr[gpc]; + offset += 0x0324 * priv->tpc_nr[gpc]; } - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0); mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0); - offset += 0x07ff * oprv->tpc_nr[gpc]; + offset += 0x07ff * priv->tpc_nr[gpc]; } mmio_list(0x17e91c, 0x06060609, 0, 0); mmio_list(0x17e920, 0x00090a05, 0, 0); @@ -2680,22 +2676,22 @@ nve0_grctx_generate(struct drm_device *priv) nv_wr32(priv, 0x419c00, 0xa); for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - if (tpc < oprv->tpc_nr[gpc]) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tpc < priv->tpc_nr[gpc]) { nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0698), id); nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x04e8), id); nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0088), id++); } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tpc_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); } } tmp = 0; - for (i = 0; i < oprv->gpc_nr; i++) - tmp |= oprv->tpc_nr[i] << (i * 4); + for (i = 0; i < priv->gpc_nr; i++) + tmp |= priv->tpc_nr[i] << (i * 4); nv_wr32(priv, 0x406028, tmp); nv_wr32(priv, 0x405870, tmp); @@ -2707,12 +2703,12 @@ nve0_grctx_generate(struct drm_device *priv) nv_wr32(priv, 0x40587c, 0x0); /* calculate first set of magics */ - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < oprv->tpc_total; tpc++) { + for (tpc = 0; tpc < priv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -2724,7 +2720,7 @@ nve0_grctx_generate(struct drm_device *priv) /* and the second... */ shift = 0; - ntpcv = oprv->tpc_total; + ntpcv = priv->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -2733,13 +2729,13 @@ nve0_grctx_generate(struct drm_device *priv) data2[0] = ntpcv << 16; data2[0] |= shift << 21; data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24); - data2[0] |= oprv->tpc_total << 8; - data2[0] |= oprv->magic_not_rop_nr; + data2[0] |= priv->tpc_total << 8; + data2[0] |= priv->magic_not_rop_nr; for (i = 1; i < 7; i++) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* and write it all the various parts of PGRAPH */ - nv_wr32(priv, 0x418bb8, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); + nv_wr32(priv, 0x418bb8, (priv->tpc_total << 8) | priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x418b08 + (i * 4), data[i]); @@ -2748,23 +2744,23 @@ nve0_grctx_generate(struct drm_device *priv) for (i = 0; i < 6; i++) nv_wr32(priv, 0x41bf00 + (i * 4), data[i]); - nv_wr32(priv, 0x4078bc, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); + nv_wr32(priv, 0x4078bc, (priv->tpc_total << 8) | priv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x40780c + (i * 4), data[i]); - memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); - for (gpc = 0; gpc < oprv->gpc_nr; gpc++) - tpc_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) + tpc_mask |= ((1 << priv->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (oprv->tpc_total - 1)) / 32; + a = (i * (priv->tpc_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % oprv->gpc_nr; + gpc = (gpc + 1) % priv->gpc_nr; } while (!tpcnr[gpc]); - tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; tpc_set |= 1 << ((gpc * 8) + tpc); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c index 7f3a275157bb..e5b01899dece 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c @@ -22,19 +22,22 @@ * DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" -#include "drm.h" -#include <nouveau_drm.h> -#include "nouveau_drv.h" -#include "nouveau_hw.h" -#include "nouveau_util.h" -#include <core/ramht.h> - -struct nv04_graph_engine { - struct nouveau_exec_engine base; -}; +#include <core/os.h> +#include <core/class.h> +#include <core/handle.h> +#include <core/namedb.h> + +#include <subdev/fb.h> +#include <subdev/instmem.h> +#include <subdev/timer.h> + +#include <engine/fifo.h> +#include <engine/graph.h> -static uint32_t nv04_graph_ctx_regs[] = { +#include "regs.h" + +static u32 +nv04_graph_ctx_regs[] = { 0x0040053c, 0x00400544, 0x00400540, @@ -348,205 +351,28 @@ static uint32_t nv04_graph_ctx_regs[] = { NV04_PGRAPH_DEBUG_3 }; -struct graph_state { - uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; +struct nv04_graph_priv { + struct nouveau_graph base; + struct nv04_graph_chan *chan[16]; + spinlock_t lock; }; -static struct nouveau_channel * -nv04_graph_channel(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chid = 15; - - if (nv_rd32(dev, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) - chid = nv_rd32(dev, NV04_PGRAPH_CTX_USER) >> 24; - - if (chid > 15) - return NULL; - - return dev_priv->channels.ptr[chid]; -} - -static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) { - if (nv04_graph_ctx_regs[i] == reg) - return &ctx->nv04[i]; - } - - return NULL; -} - -static int -nv04_graph_load_context(struct nouveau_channel *chan) -{ - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - uint32_t tmp; - int i; - - for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) - nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]); - - nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100); - - tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24); - - tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2); - nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff); - - return 0; -} - -static int -nv04_graph_unload_context(struct drm_device *dev) -{ - struct nouveau_channel *chan = NULL; - struct graph_state *ctx; - uint32_t tmp; - int i; - - chan = nv04_graph_channel(dev); - if (!chan) - return 0; - ctx = chan->engctx[NVOBJ_ENGINE_GR]; - - for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) - ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]); - - nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10000000); - tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 15 << 24; - nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); - return 0; -} - -static int -nv04_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct graph_state *pgraph_ctx; - NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id); - - pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL); - if (pgraph_ctx == NULL) - return -ENOMEM; - - *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; - - chan->engctx[engine] = pgraph_ctx; - return 0; -} - -static void -nv04_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx = chan->engctx[engine]; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv04_graph_channel(dev) == chan) - nv04_graph_unload_context(dev); - - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ - kfree(pgraph_ctx); - chan->engctx[engine] = NULL; -} - -int -nv04_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; - int ret; - - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); - if (ret) - return ret; - obj->engine = 1; - obj->class = class; - -#ifdef __BIG_ENDIAN - nv_wo32(obj, 0x00, 0x00080000 | class); -#else - nv_wo32(obj, 0x00, class); -#endif - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); +struct nv04_graph_chan { + struct nouveau_object base; + int chid; + u32 nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; +}; - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} -static int -nv04_graph_init(struct drm_device *dev, int engine) +static inline struct nv04_graph_priv * +nv04_graph_priv(struct nv04_graph_chan *chan) { - uint32_t tmp; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - - /* Enable PGRAPH interrupts */ - nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_VALID1, 0); - nv_wr32(dev, NV04_PGRAPH_VALID2, 0); - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x000001FF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000); - /*1231C000 blob, 001 haiku*/ - /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100); - /*0x72111100 blob , 01 haiku*/ - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f071); - /*haiku same*/ - - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); - /*haiku and blob 10d4*/ - - nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100); - tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 15 << 24; - nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); - - /* These don't belong here, they're part of a per-channel context */ - nv_wr32(dev, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); - - return 0; + return (void *)nv_object(chan)->engine; } -static int -nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - return -EBUSY; - } - nv04_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -} +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ /* * Software methods, why they are needed, and how they all work: @@ -623,37 +449,35 @@ nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) */ static void -nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value) +nv04_graph_set_ctx1(struct nouveau_object *object, u32 mask, u32 value) { - struct drm_device *dev = chan->dev; - u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; + struct nv04_graph_priv *priv = (void *)object->engine; + int subc = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; u32 tmp; - tmp = nv_ri32(dev, instance); + tmp = nv_ro32(object, 0x00); tmp &= ~mask; tmp |= value; + nv_wo32(object, 0x00, tmp); - nv_wi32(dev, instance, tmp); - nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp); - nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); + nv_wr32(priv, NV04_PGRAPH_CTX_SWITCH1, tmp); + nv_wr32(priv, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); } static void -nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) +nv04_graph_set_ctx_val(struct nouveau_object *object, u32 mask, u32 value) { - struct drm_device *dev = chan->dev; - u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - u32 tmp, ctx1; int class, op, valid = 1; + u32 tmp, ctx1; - ctx1 = nv_ri32(dev, instance); + ctx1 = nv_ro32(object, 0x00); class = ctx1 & 0xff; op = (ctx1 >> 15) & 7; - tmp = nv_ri32(dev, instance + 0xc); + + tmp = nv_ro32(object, 0x0c); tmp &= ~mask; tmp |= value; - nv_wi32(dev, instance + 0xc, tmp); + nv_wo32(object, 0x0c, tmp); /* check for valid surf2d/surf_dst/surf_color */ if (!(tmp & 0x02000000)) @@ -685,30 +509,34 @@ nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) break; } - nv04_graph_set_ctx1(chan, 0x01000000, valid << 24); + nv04_graph_set_ctx1(object, 0x01000000, valid << 24); } static int -nv04_graph_mthd_set_operation(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_set_operation(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { + u32 class = nv_ro32(object, 0) & 0xff; + u32 data = *(u32 *)args; if (data > 5) return 1; /* Old versions of the objects only accept first three operations. */ if (data > 2 && class < 0x40) return 1; - nv04_graph_set_ctx1(chan, 0x00038000, data << 15); + nv04_graph_set_ctx1(object, 0x00038000, data << 15); /* changing operation changes set of objects needed for validation */ - nv04_graph_set_ctx_val(chan, 0, 0); + nv04_graph_set_ctx_val(object, 0, 0); return 0; } static int -nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_surf3d_clip_h(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; + struct nv04_graph_priv *priv = (void *)object->engine; + u32 data = *(u32 *)args; + u32 min = data & 0xffff, max; + u32 w = data >> 16; if (min & 0x8000) /* too large */ return 1; @@ -717,17 +545,19 @@ nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, w |= 0xffff0000; max = min + w; max &= 0x3ffff; - nv_wr32(chan->dev, 0x40053c, min); - nv_wr32(chan->dev, 0x400544, max); + nv_wr32(priv, 0x40053c, min); + nv_wr32(priv, 0x400544, max); return 0; } static int -nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_surf3d_clip_v(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; + struct nv04_graph_priv *priv = (void *)object->engine; + u32 data = *(u32 *)args; + u32 min = data & 0xffff, max; + u32 w = data >> 16; if (min & 0x8000) /* too large */ return 1; @@ -736,223 +566,661 @@ nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, w |= 0xffff0000; max = min + w; max &= 0x3ffff; - nv_wr32(chan->dev, 0x400540, min); - nv_wr32(chan->dev, 0x400548, max); + nv_wr32(priv, 0x400540, min); + nv_wr32(priv, 0x400548, max); return 0; } +static u16 +nv04_graph_mthd_bind_class(struct nouveau_object *object, u32 *args, u32 size) +{ + struct nouveau_instmem *imem = nouveau_instmem(object); + u32 inst = *(u32 *)args << 4; + return nv_ro32(imem, inst); +} + static int -nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf2d(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x42: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x42: - nv04_graph_set_ctx1(chan, 0x00004000, 0); - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx1(object, 0x00004000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; case 0x52: - nv04_graph_set_ctx1(chan, 0x00004000, 0x00004000); - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx1(object, 0x00004000, 0x00004000); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv01_graph_mthd_bind_patt(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x08000000, 0); + nv04_graph_set_ctx_val(object, 0x08000000, 0); return 0; case 0x18: - nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000); + nv04_graph_set_ctx_val(object, 0x08000000, 0x08000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_patt(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x08000000, 0); + nv04_graph_set_ctx_val(object, 0x08000000, 0); return 0; case 0x44: - nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000); + nv04_graph_set_ctx_val(object, 0x08000000, 0x08000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_rop(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x10000000, 0); + nv04_graph_set_ctx_val(object, 0x10000000, 0); return 0; case 0x43: - nv04_graph_set_ctx_val(chan, 0x10000000, 0x10000000); + nv04_graph_set_ctx_val(object, 0x10000000, 0x10000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_beta1(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x20000000, 0); + nv04_graph_set_ctx_val(object, 0x20000000, 0); return 0; case 0x12: - nv04_graph_set_ctx_val(chan, 0x20000000, 0x20000000); + nv04_graph_set_ctx_val(object, 0x20000000, 0x20000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_beta4(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x40000000, 0); + nv04_graph_set_ctx_val(object, 0x40000000, 0); return 0; case 0x72: - nv04_graph_set_ctx_val(chan, 0x40000000, 0x40000000); + nv04_graph_set_ctx_val(object, 0x40000000, 0x40000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_dst(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x58: - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_src(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x04000000, 0); + nv04_graph_set_ctx_val(object, 0x04000000, 0); return 0; case 0x59: - nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000); + nv04_graph_set_ctx_val(object, 0x04000000, 0x04000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_color(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x02000000, 0); + nv04_graph_set_ctx_val(object, 0x02000000, 0); return 0; case 0x5a: - nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + nv04_graph_set_ctx_val(object, 0x02000000, 0x02000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv04_graph_mthd_bind_surf_zeta(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx_val(chan, 0x04000000, 0); + nv04_graph_set_ctx_val(object, 0x04000000, 0); return 0; case 0x5b: - nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000); + nv04_graph_set_ctx_val(object, 0x04000000, 0x04000000); return 0; } return 1; } static int -nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv01_graph_mthd_bind_clip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x2000, 0); + nv04_graph_set_ctx1(object, 0x2000, 0); return 0; case 0x19: - nv04_graph_set_ctx1(chan, 0x2000, 0x2000); + nv04_graph_set_ctx1(object, 0x2000, 0x2000); return 0; } return 1; } static int -nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +nv01_graph_mthd_bind_chroma(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { + switch (nv04_graph_mthd_bind_class(object, args, size)) { case 0x30: - nv04_graph_set_ctx1(chan, 0x1000, 0); + nv04_graph_set_ctx1(object, 0x1000, 0); return 0; /* Yes, for some reason even the old versions of objects * accept 0x57 and not 0x17. Consistency be damned. */ case 0x57: - nv04_graph_set_ctx1(chan, 0x1000, 0x1000); + nv04_graph_set_ctx1(object, 0x1000, 0x1000); return 0; } return 1; } -static struct nouveau_bitfield nv04_graph_intr[] = { +static struct nouveau_omthds +nv03_graph_gdi_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_patt }, + { 0x0188, nv04_graph_mthd_bind_rop }, + { 0x018c, nv04_graph_mthd_bind_beta1 }, + { 0x0190, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_gdi_omthds[] = { + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv01_graph_blit_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv01_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_surf_dst }, + { 0x019c, nv04_graph_mthd_bind_surf_src }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_blit_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv04_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_beta4 }, + { 0x019c, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_iifc_omthds[] = { + { 0x0188, nv01_graph_mthd_bind_chroma }, + { 0x018c, nv01_graph_mthd_bind_clip }, + { 0x0190, nv04_graph_mthd_bind_patt }, + { 0x0194, nv04_graph_mthd_bind_rop }, + { 0x0198, nv04_graph_mthd_bind_beta1 }, + { 0x019c, nv04_graph_mthd_bind_beta4 }, + { 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf }, + { 0x03e4, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv01_graph_ifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv01_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_ifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv04_graph_mthd_bind_patt }, + { 0x0190, nv04_graph_mthd_bind_rop }, + { 0x0194, nv04_graph_mthd_bind_beta1 }, + { 0x0198, nv04_graph_mthd_bind_beta4 }, + { 0x019c, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv03_graph_sifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv01_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_sifc_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_chroma }, + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv03_graph_sifm_omthds[] = { + { 0x0188, nv01_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_surf_dst }, + { 0x0304, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_sifm_omthds[] = { + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x0304, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_surf3d_omthds[] = { + { 0x02f8, nv04_graph_mthd_surf3d_clip_h }, + { 0x02fc, nv04_graph_mthd_surf3d_clip_v }, + {} +}; + +static struct nouveau_omthds +nv03_graph_ttri_omthds[] = { + { 0x0188, nv01_graph_mthd_bind_clip }, + { 0x018c, nv04_graph_mthd_bind_surf_color }, + { 0x0190, nv04_graph_mthd_bind_surf_zeta }, + {} +}; + +static struct nouveau_omthds +nv01_graph_prim_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_clip }, + { 0x0188, nv01_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_surf_dst }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static struct nouveau_omthds +nv04_graph_prim_omthds[] = { + { 0x0184, nv01_graph_mthd_bind_clip }, + { 0x0188, nv04_graph_mthd_bind_patt }, + { 0x018c, nv04_graph_mthd_bind_rop }, + { 0x0190, nv04_graph_mthd_bind_beta1 }, + { 0x0194, nv04_graph_mthd_bind_beta4 }, + { 0x0198, nv04_graph_mthd_bind_surf2d }, + { 0x02fc, nv04_graph_mthd_set_operation }, + {} +}; + +static int +nv04_graph_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_gpuobj *obj; + int ret; + + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); + if (ret) + return ret; + + nv_wo32(obj, 0x00, nv_mclass(obj)); +#ifdef __BIG_ENDIAN + nv_mo32(obj, 0x00, 0x00080000, 0x00080000); +#endif + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); + return 0; +} + +struct nouveau_ofuncs +nv04_graph_ofuncs = { + .ctor = nv04_graph_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; + +static struct nouveau_oclass +nv04_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0017, &nv04_graph_ofuncs }, /* chroma */ + { 0x0018, &nv04_graph_ofuncs }, /* pattern (nv01) */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x001c, &nv04_graph_ofuncs, nv01_graph_prim_omthds }, /* line */ + { 0x001d, &nv04_graph_ofuncs, nv01_graph_prim_omthds }, /* tri */ + { 0x001e, &nv04_graph_ofuncs, nv01_graph_prim_omthds }, /* rect */ + { 0x001f, &nv04_graph_ofuncs, nv01_graph_blit_omthds }, + { 0x0021, &nv04_graph_ofuncs, nv01_graph_ifc_omthds }, + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0036, &nv04_graph_ofuncs, nv03_graph_sifc_omthds }, + { 0x0037, &nv04_graph_ofuncs, nv03_graph_sifm_omthds }, + { 0x0038, &nv04_graph_ofuncs }, /* dvd subpicture */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0042, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x0048, &nv04_graph_ofuncs, nv03_graph_ttri_omthds }, + { 0x004a, &nv04_graph_ofuncs, nv04_graph_gdi_omthds }, + { 0x004b, &nv04_graph_ofuncs, nv03_graph_gdi_omthds }, + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x0053, &nv04_graph_ofuncs, nv04_graph_surf3d_omthds }, + { 0x0054, &nv04_graph_ofuncs }, /* ttri */ + { 0x0055, &nv04_graph_ofuncs }, /* mtri */ + { 0x0057, &nv04_graph_ofuncs }, /* chroma */ + { 0x0058, &nv04_graph_ofuncs }, /* surf_dst */ + { 0x0059, &nv04_graph_ofuncs }, /* surf_src */ + { 0x005a, &nv04_graph_ofuncs }, /* surf_color */ + { 0x005b, &nv04_graph_ofuncs }, /* surf_zeta */ + { 0x005c, &nv04_graph_ofuncs, nv04_graph_prim_omthds }, /* line */ + { 0x005d, &nv04_graph_ofuncs, nv04_graph_prim_omthds }, /* tri */ + { 0x005e, &nv04_graph_ofuncs, nv04_graph_prim_omthds }, /* rect */ + { 0x005f, &nv04_graph_ofuncs, nv04_graph_blit_omthds }, + { 0x0060, &nv04_graph_ofuncs, nv04_graph_iifc_omthds }, + { 0x0061, &nv04_graph_ofuncs, nv04_graph_ifc_omthds }, + { 0x0064, &nv04_graph_ofuncs }, /* iifc (nv05) */ + { 0x0065, &nv04_graph_ofuncs }, /* ifc (nv05) */ + { 0x0066, &nv04_graph_ofuncs }, /* sifc (nv05) */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0076, &nv04_graph_ofuncs, nv04_graph_sifc_omthds }, + { 0x0077, &nv04_graph_ofuncs, nv04_graph_sifm_omthds }, + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static struct nv04_graph_chan * +nv04_graph_channel(struct nv04_graph_priv *priv) +{ + struct nv04_graph_chan *chan = NULL; + if (nv_rd32(priv, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) { + int chid = nv_rd32(priv, NV04_PGRAPH_CTX_USER) >> 24; + if (chid < ARRAY_SIZE(priv->chan)) + chan = priv->chan[chid]; + } + return chan; +} + +static int +nv04_graph_load_context(struct nv04_graph_chan *chan, int chid) +{ + struct nv04_graph_priv *priv = nv04_graph_priv(chan); + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) + nv_wr32(priv, nv04_graph_ctx_regs[i], chan->nv04[i]); + + nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL, 0x10010100); + nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24); + nv_mask(priv, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000); + return 0; +} + +static int +nv04_graph_unload_context(struct nv04_graph_chan *chan) +{ + struct nv04_graph_priv *priv = nv04_graph_priv(chan); + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) + chan->nv04[i] = nv_rd32(priv, nv04_graph_ctx_regs[i]); + + nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL, 0x10000000); + nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); + return 0; +} + +static void +nv04_graph_context_switch(struct nv04_graph_priv *priv) +{ + struct nv04_graph_chan *prev = NULL; + struct nv04_graph_chan *next = NULL; + unsigned long flags; + int chid; + + spin_lock_irqsave(&priv->lock, flags); + nv04_graph_idle(priv); + + /* If previous context is valid, we need to save it */ + prev = nv04_graph_channel(priv); + if (prev) + nv04_graph_unload_context(prev); + + /* load context for next channel */ + chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f; + next = priv->chan[chid]; + if (next) + nv04_graph_load_context(next, chid); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +static u32 *ctx_reg(struct nv04_graph_chan *chan, u32 reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) { + if (nv04_graph_ctx_regs[i] == reg) + return &chan->nv04[i]; + } + + return NULL; +} + +static int +nv04_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_fifo_chan *fifo = (void *)parent; + struct nv04_graph_priv *priv = (void *)engine; + struct nv04_graph_chan *chan; + unsigned long flags; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->chan[fifo->chid]) { + *pobject = nv_object(priv->chan[fifo->chid]); + atomic_inc(&(*pobject)->refcount); + spin_unlock_irqrestore(&priv->lock, flags); + nouveau_object_destroy(&chan->base); + return 1; + } + + *ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; + + priv->chan[fifo->chid] = chan; + chan->chid = fifo->chid; + spin_unlock_irqrestore(&priv->lock, flags); + return 0; +} + +static void +nv04_graph_context_dtor(struct nouveau_object *object) +{ + struct nv04_graph_priv *priv = (void *)object->engine; + struct nv04_graph_chan *chan = (void *)object; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->chan[chan->chid] = NULL; + spin_unlock_irqrestore(&priv->lock, flags); + + nouveau_object_destroy(&chan->base); +} + +static int +nv04_graph_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv04_graph_priv *priv = (void *)object->engine; + struct nv04_graph_chan *chan = (void *)object; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + if (nv04_graph_channel(priv) == chan) + nv04_graph_unload_context(chan); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->lock, flags); + + return nouveau_object_fini(&chan->base, suspend); +} + +static struct nouveau_oclass +nv04_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_graph_context_ctor, + .dtor = nv04_graph_context_dtor, + .init = nouveau_object_init, + .fini = nv04_graph_context_fini, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +bool +nv04_graph_idle(void *obj) +{ + struct nouveau_graph *graph = nouveau_graph(obj); + u32 mask = 0xffffffff; + + if (nv_device(obj)->card_type == NV_40) + mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; + + if (!nv_wait(graph, NV04_PGRAPH_STATUS, mask, 0)) { + nv_error(graph, "idle timed out with status 0x%08x\n", + nv_rd32(graph, NV04_PGRAPH_STATUS)); + return false; + } + + return true; +} + +static struct nouveau_bitfield +nv04_graph_intr_name[] = { { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, {} }; -static struct nouveau_bitfield nv04_graph_nstatus[] = { +static struct nouveau_bitfield +nv04_graph_nstatus[] = { { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, @@ -960,7 +1228,8 @@ static struct nouveau_bitfield nv04_graph_nstatus[] = { {} }; -struct nouveau_bitfield nv04_graph_nsource[] = { +struct nouveau_bitfield +nv04_graph_nsource[] = { { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, @@ -984,343 +1253,135 @@ struct nouveau_bitfield nv04_graph_nsource[] = { }; static void -nv04_graph_context_switch(struct drm_device *dev) +nv04_graph_intr(struct nouveau_subdev *subdev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; - int chid; - - nouveau_wait_for_idle(dev); - - /* If previous context is valid, we need to save it */ - nv04_graph_unload_context(dev); + struct nv04_graph_priv *priv = (void *)subdev; + struct nv04_graph_chan *chan = NULL; + struct nouveau_namedb *namedb = NULL; + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x0f000000) >> 24; + u32 subc = (addr & 0x0000e000) >> 13; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400180 + subc * 4) & 0xff; + u32 inst = (nv_rd32(priv, 0x40016c) & 0xffff) << 4; + u32 show = stat; + unsigned long flags; - /* Load context for next channel */ - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & - NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; - chan = dev_priv->channels.ptr[chid]; + spin_lock_irqsave(&priv->lock, flags); + chan = priv->chan[chid]; if (chan) - nv04_graph_load_context(chan); -} - -static void -nv04_graph_isr(struct drm_device *dev) -{ - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 chid = (addr & 0x0f000000) >> 24; - u32 subc = (addr & 0x0000e000) >> 13; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_NOTIFY) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_NOTIFY; - } + namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); + spin_unlock_irqrestore(&priv->lock, flags); + + if (stat & NV_PGRAPH_INTR_NOTIFY) { + if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { + handle = nouveau_namedb_get_vinst(namedb, inst); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_NOTIFY; } + } - if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); - stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv04_graph_context_switch(dev); - } + if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv04_graph_context_switch(priv); + } - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv04_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv04_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, subc, class, mthd, data); - } + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_error(priv, ""); + nouveau_bitfield_print(nv04_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv04_graph_nstatus, nstatus); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } + + nouveau_namedb_put(handle); } -static void -nv04_graph_destroy(struct drm_device *dev, int engine) +static int +nv04_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv04_graph_engine *pgraph = nv_engine(dev, engine); + struct nv04_graph_priv *priv; + int ret; - nouveau_irq_unregister(dev, 12); + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - NVOBJ_ENGINE_DEL(dev, GR); - kfree(pgraph); + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv04_graph_intr; + nv_engine(priv)->cclass = &nv04_graph_cclass; + nv_engine(priv)->sclass = nv04_graph_sclass; + spin_lock_init(&priv->lock); + return 0; } -int -nv04_graph_create(struct drm_device *dev) +static int +nv04_graph_init(struct nouveau_object *object) { - struct nv04_graph_engine *pgraph; - - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv04_graph_destroy; - pgraph->base.init = nv04_graph_init; - pgraph->base.fini = nv04_graph_fini; - pgraph->base.context_new = nv04_graph_context_new; - pgraph->base.context_del = nv04_graph_context_del; - pgraph->base.object_new = nv04_graph_object_new; - - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv04_graph_isr); - - /* dvd subpicture */ - NVOBJ_CLASS(dev, 0x0038, GR); - - /* m2mf */ - NVOBJ_CLASS(dev, 0x0039, GR); - - /* nv03 gdirect */ - NVOBJ_CLASS(dev, 0x004b, GR); - NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 gdirect */ - NVOBJ_CLASS(dev, 0x004a, GR); - NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv01 imageblit */ - NVOBJ_CLASS(dev, 0x001f, GR); - NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src); - NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 imageblit */ - NVOBJ_CLASS(dev, 0x005f, GR); - NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 iifc */ - NVOBJ_CLASS(dev, 0x0060, GR); - NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf); - NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation); - - /* nv05 iifc */ - NVOBJ_CLASS(dev, 0x0064, GR); - - /* nv01 ifc */ - NVOBJ_CLASS(dev, 0x0021, GR); - NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 ifc */ - NVOBJ_CLASS(dev, 0x0061, GR); - NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv05 ifc */ - NVOBJ_CLASS(dev, 0x0065, GR); - - /* nv03 sifc */ - NVOBJ_CLASS(dev, 0x0036, GR); - NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 sifc */ - NVOBJ_CLASS(dev, 0x0076, GR); - NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma); - NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv05 sifc */ - NVOBJ_CLASS(dev, 0x0066, GR); - - /* nv03 sifm */ - NVOBJ_CLASS(dev, 0x0037, GR); - NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation); - - /* nv04 sifm */ - NVOBJ_CLASS(dev, 0x0077, GR); - NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf); - NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation); - - /* null */ - NVOBJ_CLASS(dev, 0x0030, GR); - - /* surf2d */ - NVOBJ_CLASS(dev, 0x0042, GR); - - /* rop */ - NVOBJ_CLASS(dev, 0x0043, GR); - - /* beta1 */ - NVOBJ_CLASS(dev, 0x0012, GR); - - /* beta4 */ - NVOBJ_CLASS(dev, 0x0072, GR); - - /* cliprect */ - NVOBJ_CLASS(dev, 0x0019, GR); - - /* nv01 pattern */ - NVOBJ_CLASS(dev, 0x0018, GR); - - /* nv04 pattern */ - NVOBJ_CLASS(dev, 0x0044, GR); - - /* swzsurf */ - NVOBJ_CLASS(dev, 0x0052, GR); - - /* surf3d */ - NVOBJ_CLASS(dev, 0x0053, GR); - NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h); - NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v); - - /* nv03 tex_tri */ - NVOBJ_CLASS(dev, 0x0048, GR); - NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color); - NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta); - - /* tex_tri */ - NVOBJ_CLASS(dev, 0x0054, GR); - - /* multitex_tri */ - NVOBJ_CLASS(dev, 0x0055, GR); - - /* nv01 chroma */ - NVOBJ_CLASS(dev, 0x0017, GR); - - /* nv04 chroma */ - NVOBJ_CLASS(dev, 0x0057, GR); - - /* surf_dst */ - NVOBJ_CLASS(dev, 0x0058, GR); - - /* surf_src */ - NVOBJ_CLASS(dev, 0x0059, GR); - - /* surf_color */ - NVOBJ_CLASS(dev, 0x005a, GR); - - /* surf_zeta */ - NVOBJ_CLASS(dev, 0x005b, GR); - - /* nv01 line */ - NVOBJ_CLASS(dev, 0x001c, GR); - NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 line */ - NVOBJ_CLASS(dev, 0x005c, GR); - NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv01 tri */ - NVOBJ_CLASS(dev, 0x001d, GR); - NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 tri */ - NVOBJ_CLASS(dev, 0x005d, GR); - NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv01 rect */ - NVOBJ_CLASS(dev, 0x001e, GR); - NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt); - NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst); - NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation); - - /* nv04 rect */ - NVOBJ_CLASS(dev, 0x005e, GR); - NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip); - NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt); - NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop); - NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1); - NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4); - NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d); - NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation); + struct nouveau_engine *engine = nv_engine(object); + struct nv04_graph_priv *priv = (void *)engine; + int ret; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + /* Enable PGRAPH interrupts */ + nv_wr32(priv, NV03_PGRAPH_INTR, 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(priv, NV04_PGRAPH_VALID1, 0); + nv_wr32(priv, NV04_PGRAPH_VALID2, 0); + /*nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x000001FF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x1231c000); + /*1231C000 blob, 001 haiku*/ + /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x72111100); + /*0x72111100 blob , 01 haiku*/ + /*nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x11d5f071); + /*haiku same*/ + + /*nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); + /*haiku and blob 10d4*/ + + nv_wr32(priv, NV04_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_CTX_CONTROL , 0x10000100); + nv_mask(priv, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000); + + /* These don't belong here, they're part of a per-channel context */ + nv_wr32(priv, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); return 0; } + +struct nouveau_oclass +nv04_graph_oclass = { + .handle = NV_ENGINE(GR, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_graph_ctor, + .dtor = _nouveau_graph_dtor, + .init = nv04_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index d006658e6468..ce38196634df 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -22,27 +22,28 @@ * DEALINGS IN THE SOFTWARE. */ -#include "drmP.h" -#include "drm.h" -#include <nouveau_drm.h> -#include "nouveau_drv.h" -#include "nouveau_util.h" - -struct nv10_graph_engine { - struct nouveau_exec_engine base; -}; +#include <core/os.h> +#include <core/class.h> +#include <core/handle.h> + +#include <subdev/fb.h> + +#include <engine/fifo.h> +#include <engine/graph.h> + +#include "regs.h" struct pipe_state { - uint32_t pipe_0x0000[0x040/4]; - uint32_t pipe_0x0040[0x010/4]; - uint32_t pipe_0x0200[0x0c0/4]; - uint32_t pipe_0x4400[0x080/4]; - uint32_t pipe_0x6400[0x3b0/4]; - uint32_t pipe_0x6800[0x2f0/4]; - uint32_t pipe_0x6c00[0x030/4]; - uint32_t pipe_0x7000[0x130/4]; - uint32_t pipe_0x7400[0x0c0/4]; - uint32_t pipe_0x7800[0x0c0/4]; + u32 pipe_0x0000[0x040/4]; + u32 pipe_0x0040[0x010/4]; + u32 pipe_0x0200[0x0c0/4]; + u32 pipe_0x4400[0x080/4]; + u32 pipe_0x6400[0x3b0/4]; + u32 pipe_0x6800[0x2f0/4]; + u32 pipe_0x6c00[0x030/4]; + u32 pipe_0x7000[0x130/4]; + u32 pipe_0x7400[0x0c0/4]; + u32 pipe_0x7800[0x0c0/4]; }; static int nv10_graph_ctx_regs[] = { @@ -388,117 +389,322 @@ static int nv17_graph_ctx_regs[] = { 0x00400a04, }; -struct graph_state { +struct nv10_graph_priv { + struct nouveau_graph base; + struct nv10_graph_chan *chan[32]; + spinlock_t lock; +}; + +struct nv10_graph_chan { + struct nouveau_object base; + int chid; int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)]; int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)]; struct pipe_state pipe_state; - uint32_t lma_window[4]; + u32 lma_window[4]; }; -#define PIPE_SAVE(dev, state, addr) \ + +static inline struct nv10_graph_priv * +nv10_graph_priv(struct nv10_graph_chan *chan) +{ + return (void *)nv_object(chan)->engine; +} + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +#define PIPE_SAVE(priv, state, addr) \ do { \ int __i; \ - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \ for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ - state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ + state[__i] = nv_rd32(priv, NV10_PGRAPH_PIPE_DATA); \ } while (0) -#define PIPE_RESTORE(dev, state, addr) \ +#define PIPE_RESTORE(priv, state, addr) \ do { \ int __i; \ - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr); \ for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \ + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, state[__i]); \ } while (0) -static void nv10_graph_save_pipe(struct nouveau_channel *chan) +static struct nouveau_oclass +nv10_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x004a, &nv04_graph_ofuncs }, /* gdi */ + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x005f, &nv04_graph_ofuncs }, /* blit */ + { 0x0062, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs }, /* blit */ + { 0x0093, &nv04_graph_ofuncs }, /* surf3d */ + { 0x0094, &nv04_graph_ofuncs }, /* ttri */ + { 0x0095, &nv04_graph_ofuncs }, /* mtri */ + { 0x0056, &nv04_graph_ofuncs }, /* celcius */ + {}, +}; + +static struct nouveau_oclass +nv15_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x004a, &nv04_graph_ofuncs }, /* gdi */ + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x005f, &nv04_graph_ofuncs }, /* blit */ + { 0x0062, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs }, /* blit */ + { 0x0093, &nv04_graph_ofuncs }, /* surf3d */ + { 0x0094, &nv04_graph_ofuncs }, /* ttri */ + { 0x0095, &nv04_graph_ofuncs }, /* mtri */ + { 0x0096, &nv04_graph_ofuncs }, /* celcius */ + {}, +}; + +static int +nv17_graph_mthd_lma_window(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv10_graph_chan *chan = (void *)object->parent; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe = &chan->pipe_state; + u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; + u32 xfmode0, xfmode1; + u32 data = *(u32 *)args; + int i; + + chan->lma_window[(mthd - 0x1638) / 4] = data; + + if (mthd != 0x1644) + return 0; + + nv04_graph_idle(priv); + + PIPE_SAVE(priv, pipe_0x0040, 0x0040); + PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200); + + PIPE_RESTORE(priv, chan->lma_window, 0x6790); + + nv04_graph_idle(priv); + + xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0); + xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1); + + PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(priv, pipe_0x64c0, 0x64c0); + PIPE_SAVE(priv, pipe_0x6ab0, 0x6ab0); + PIPE_SAVE(priv, pipe_0x6a80, 0x6a80); + + nv04_graph_idle(priv); + + nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + for (i = 0; i < 3; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008); + + PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200); + + nv04_graph_idle(priv); + + PIPE_RESTORE(priv, pipe_0x0040, 0x0040); + + nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1); + + PIPE_RESTORE(priv, pipe_0x64c0, 0x64c0); + PIPE_RESTORE(priv, pipe_0x6ab0, 0x6ab0); + PIPE_RESTORE(priv, pipe_0x6a80, 0x6a80); + PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400); + + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv04_graph_idle(priv); + + return 0; +} + +static int +nv17_graph_mthd_lma_enable(struct nouveau_object *object, u32 mthd, + void *args, u32 size) { - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct pipe_state *pipe = &pgraph_ctx->pipe_state; - struct drm_device *dev = chan->dev; - - PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); - PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); - PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400); - PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800); - PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00); - PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000); - PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400); - PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800); - PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040); - PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000); + struct nv10_graph_chan *chan = (void *)object->parent; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + + nv04_graph_idle(priv); + + nv_mask(priv, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100); + nv_mask(priv, 0x4006b0, 0x08000000, 0x08000000); + return 0; } -static void nv10_graph_load_pipe(struct nouveau_channel *chan) +static struct nouveau_omthds +nv17_celcius_omthds[] = { + { 0x1638, nv17_graph_mthd_lma_window }, + { 0x163c, nv17_graph_mthd_lma_window }, + { 0x1640, nv17_graph_mthd_lma_window }, + { 0x1644, nv17_graph_mthd_lma_window }, + { 0x1658, nv17_graph_mthd_lma_enable }, + {} +}; + +static struct nouveau_oclass +nv17_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs }, /* clip */ + { 0x0030, &nv04_graph_ofuncs }, /* null */ + { 0x0039, &nv04_graph_ofuncs }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs }, /* rop */ + { 0x0044, &nv04_graph_ofuncs }, /* pattern */ + { 0x004a, &nv04_graph_ofuncs }, /* gdi */ + { 0x0052, &nv04_graph_ofuncs }, /* swzsurf */ + { 0x005f, &nv04_graph_ofuncs }, /* blit */ + { 0x0062, &nv04_graph_ofuncs }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs }, /* blit */ + { 0x0093, &nv04_graph_ofuncs }, /* surf3d */ + { 0x0094, &nv04_graph_ofuncs }, /* ttri */ + { 0x0095, &nv04_graph_ofuncs }, /* mtri */ + { 0x0099, &nv04_graph_ofuncs, nv17_celcius_omthds }, + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static struct nv10_graph_chan * +nv10_graph_channel(struct nv10_graph_priv *priv) { - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct pipe_state *pipe = &pgraph_ctx->pipe_state; - struct drm_device *dev = chan->dev; - uint32_t xfmode0, xfmode1; + struct nv10_graph_chan *chan = NULL; + if (nv_rd32(priv, 0x400144) & 0x00010000) { + int chid = nv_rd32(priv, 0x400148) >> 24; + if (chid < ARRAY_SIZE(priv->chan)) + chan = priv->chan[chid]; + } + return chan; +} + +static void +nv10_graph_save_pipe(struct nv10_graph_chan *chan) +{ + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe = &chan->pipe_state; + + PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200); + PIPE_SAVE(priv, pipe->pipe_0x6400, 0x6400); + PIPE_SAVE(priv, pipe->pipe_0x6800, 0x6800); + PIPE_SAVE(priv, pipe->pipe_0x6c00, 0x6c00); + PIPE_SAVE(priv, pipe->pipe_0x7000, 0x7000); + PIPE_SAVE(priv, pipe->pipe_0x7400, 0x7400); + PIPE_SAVE(priv, pipe->pipe_0x7800, 0x7800); + PIPE_SAVE(priv, pipe->pipe_0x0040, 0x0040); + PIPE_SAVE(priv, pipe->pipe_0x0000, 0x0000); +} + +static void +nv10_graph_load_pipe(struct nv10_graph_chan *chan) +{ + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe = &chan->pipe_state; + u32 xfmode0, xfmode1; int i; - nouveau_wait_for_idle(dev); + nv04_graph_idle(priv); /* XXX check haiku comments */ - xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); - xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); - nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0); + xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1); + nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); + nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008); - PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); - nouveau_wait_for_idle(dev); + PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200); + nv04_graph_idle(priv); /* restore XFMODE */ - nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); - PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400); - PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800); - PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00); - PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000); - PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400); - PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800); - PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); - PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000); - PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040); - nouveau_wait_for_idle(dev); + nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0); + nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1); + PIPE_RESTORE(priv, pipe->pipe_0x6400, 0x6400); + PIPE_RESTORE(priv, pipe->pipe_0x6800, 0x6800); + PIPE_RESTORE(priv, pipe->pipe_0x6c00, 0x6c00); + PIPE_RESTORE(priv, pipe->pipe_0x7000, 0x7000); + PIPE_RESTORE(priv, pipe->pipe_0x7400, 0x7400); + PIPE_RESTORE(priv, pipe->pipe_0x7800, 0x7800); + PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400); + PIPE_RESTORE(priv, pipe->pipe_0x0000, 0x0000); + PIPE_RESTORE(priv, pipe->pipe_0x0040, 0x0040); + nv04_graph_idle(priv); } -static void nv10_graph_create_pipe(struct nouveau_channel *chan) +static void +nv10_graph_create_pipe(struct nv10_graph_chan *chan) { - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; - struct drm_device *dev = chan->dev; - uint32_t *fifo_pipe_state_addr; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + struct pipe_state *pipe_state = &chan->pipe_state; + u32 *pipe_state_addr; int i; #define PIPE_INIT(addr) \ do { \ - fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \ + pipe_state_addr = pipe_state->pipe_##addr; \ } while (0) #define PIPE_INIT_END(addr) \ do { \ - uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \ - ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \ - if (fifo_pipe_state_addr != __end_addr) \ - NV_ERROR(dev, "incomplete pipe init for 0x%x : %p/%p\n", \ - addr, fifo_pipe_state_addr, __end_addr); \ + u32 *__end_addr = pipe_state->pipe_##addr + \ + ARRAY_SIZE(pipe_state->pipe_##addr); \ + if (pipe_state_addr != __end_addr) \ + nv_error(priv, "incomplete pipe init for 0x%x : %p/%p\n", \ + addr, pipe_state_addr, __end_addr); \ } while (0) -#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value +#define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value PIPE_INIT(0x0200); for (i = 0; i < 48; i++) @@ -634,34 +840,36 @@ static void nv10_graph_create_pipe(struct nouveau_channel *chan) #undef NV_WRITE_PIPE_INIT } -static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) +static int +nv10_graph_ctx_regs_find_offset(struct nv10_graph_priv *priv, int reg) { int i; for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) { if (nv10_graph_ctx_regs[i] == reg) return i; } - NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg); + nv_error(priv, "unknow offset nv10_ctx_regs %d\n", reg); return -1; } -static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) +static int +nv17_graph_ctx_regs_find_offset(struct nv10_graph_priv *priv, int reg) { int i; for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) { if (nv17_graph_ctx_regs[i] == reg) return i; } - NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg); + nv_error(priv, "unknow offset nv17_ctx_regs %d\n", reg); return -1; } -static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, - uint32_t inst) +static void +nv10_graph_load_dma_vtxbuf(struct nv10_graph_chan *chan, int chid, u32 inst) { - struct drm_device *dev = chan->dev; - uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; - uint32_t ctx_user, ctx_switch[5]; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; + u32 ctx_user, ctx_switch[5]; int i, subchan = -1; /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state @@ -671,7 +879,7 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, /* Look for a celsius object */ for (i = 0; i < 8; i++) { - int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; + int class = nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; if (class == 0x56 || class == 0x96 || class == 0x99) { subchan = i; @@ -683,168 +891,158 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, return; /* Save the current ctx object */ - ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER); + ctx_user = nv_rd32(priv, NV10_PGRAPH_CTX_USER); for (i = 0; i < 5; i++) - ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i)); + ctx_switch[i] = nv_rd32(priv, NV10_PGRAPH_CTX_SWITCH(i)); /* Save the FIFO state */ - st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); - st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL); - st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH); - fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR); + st2 = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2); + st2_dl = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DL); + st2_dh = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DH); + fifo_ptr = nv_rd32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR); for (i = 0; i < ARRAY_SIZE(fifo); i++) - fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i); + fifo[i] = nv_rd32(priv, 0x4007a0 + 4 * i); /* Switch to the celsius subchannel */ for (i = 0; i < 5; i++) - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), - nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i))); - nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), + nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(subchan, i))); + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); /* Inject NV10TCL_DMA_VTXBUF */ - nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, - 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); - nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, + 0x2c000000 | chid << 20 | subchan << 16 | 0x18c); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, inst); + nv_mask(priv, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); /* Restore the FIFO state */ for (i = 0; i < ARRAY_SIZE(fifo); i++) - nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]); + nv_wr32(priv, 0x4007a0 + 4 * i, fifo[i]); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, st2); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); /* Restore the current ctx object */ for (i = 0; i < 5; i++) - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); - nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); + nv_wr32(priv, NV10_PGRAPH_CTX_USER, ctx_user); } static int -nv10_graph_load_context(struct nouveau_channel *chan) +nv10_graph_load_context(struct nv10_graph_chan *chan, int chid) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR]; - uint32_t tmp; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); + u32 inst; int i; for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) - nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]); - if (dev_priv->chipset >= 0x17) { + nv_wr32(priv, nv10_graph_ctx_regs[i], chan->nv10[i]); + + if (nv_device(priv)->chipset >= 0x17) { for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) - nv_wr32(dev, nv17_graph_ctx_regs[i], - pgraph_ctx->nv17[i]); + nv_wr32(priv, nv17_graph_ctx_regs[i], chan->nv17[i]); } nv10_graph_load_pipe(chan); - nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1) - & 0xffff)); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); - nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24); - tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff); + + inst = nv_rd32(priv, NV10_PGRAPH_GLOBALSTATE1) & 0xffff; + nv10_graph_load_dma_vtxbuf(chan, chid, inst); + + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24); + nv_mask(priv, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000); return 0; } static int -nv10_graph_unload_context(struct drm_device *dev) +nv10_graph_unload_context(struct nv10_graph_chan *chan) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - struct graph_state *ctx; - uint32_t tmp; + struct nv10_graph_priv *priv = nv10_graph_priv(chan); int i; - chan = nv10_graph_channel(dev); - if (!chan) - return 0; - ctx = chan->engctx[NVOBJ_ENGINE_GR]; - for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) - ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]); + chan->nv10[i] = nv_rd32(priv, nv10_graph_ctx_regs[i]); - if (dev_priv->chipset >= 0x17) { + if (nv_device(priv)->chipset >= 0x17) { for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) - ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]); + chan->nv17[i] = nv_rd32(priv, nv17_graph_ctx_regs[i]); } nv10_graph_save_pipe(chan); - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000); - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 31 << 24; - nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000000); + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); return 0; } static void -nv10_graph_context_switch(struct drm_device *dev) +nv10_graph_context_switch(struct nv10_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; + struct nv10_graph_chan *prev = NULL; + struct nv10_graph_chan *next = NULL; + unsigned long flags; int chid; - nouveau_wait_for_idle(dev); + spin_lock_irqsave(&priv->lock, flags); + nv04_graph_idle(priv); /* If previous context is valid, we need to save it */ - nv10_graph_unload_context(dev); + prev = nv10_graph_channel(priv); + if (prev) + nv10_graph_unload_context(prev); + + /* load context for next channel */ + chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; + next = priv->chan[chid]; + if (next) + nv10_graph_load_context(next, chid); - /* Load context for next channel */ - chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; - chan = dev_priv->channels.ptr[chid]; - if (chan && chan->engctx[NVOBJ_ENGINE_GR]) - nv10_graph_load_context(chan); + spin_unlock_irqrestore(&priv->lock, flags); } #define NV_WRITE_CTX(reg, val) do { \ - int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \ + int offset = nv10_graph_ctx_regs_find_offset(priv, reg); \ if (offset > 0) \ - pgraph_ctx->nv10[offset] = val; \ + chan->nv10[offset] = val; \ } while (0) #define NV17_WRITE_CTX(reg, val) do { \ - int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \ + int offset = nv17_graph_ctx_regs_find_offset(priv, reg); \ if (offset > 0) \ - pgraph_ctx->nv17[offset] = val; \ + chan->nv17[offset] = val; \ } while (0) -struct nouveau_channel * -nv10_graph_channel(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int chid = 31; - - if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000) - chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24; - - if (chid >= 31) - return NULL; - - return dev_priv->channels.ptr[chid]; -} - static int -nv10_graph_context_new(struct nouveau_channel *chan, int engine) +nv10_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx; - - NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id); - - pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL); - if (pgraph_ctx == NULL) - return -ENOMEM; - chan->engctx[engine] = pgraph_ctx; + struct nouveau_fifo_chan *fifo = (void *)parent; + struct nv10_graph_priv *priv = (void *)engine; + struct nv10_graph_chan *chan; + unsigned long flags; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->chan[fifo->chid]) { + *pobject = nv_object(priv->chan[fifo->chid]); + atomic_inc(&(*pobject)->refcount); + spin_unlock_irqrestore(&priv->lock, flags); + nouveau_object_destroy(&chan->base); + return 1; + } NV_WRITE_CTX(0x00400e88, 0x08000000); NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); @@ -853,212 +1051,91 @@ nv10_graph_context_new(struct nouveau_channel *chan, int engine) NV_WRITE_CTX(0x00400e14, 0x00001000); NV_WRITE_CTX(0x00400e30, 0x00080008); NV_WRITE_CTX(0x00400e34, 0x00080008); - if (dev_priv->chipset >= 0x17) { + if (nv_device(priv)->chipset >= 0x17) { /* is it really needed ??? */ NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, - nv_rd32(dev, NV10_PGRAPH_DEBUG_4)); - NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0)); + nv_rd32(priv, NV10_PGRAPH_DEBUG_4)); + NV17_WRITE_CTX(0x004006b0, nv_rd32(priv, 0x004006b0)); NV17_WRITE_CTX(0x00400eac, 0x0fff0000); NV17_WRITE_CTX(0x00400eb0, 0x0fff0000); NV17_WRITE_CTX(0x00400ec0, 0x00000080); NV17_WRITE_CTX(0x00400ed0, 0x00000080); } - NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24); + NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->chid << 24); nv10_graph_create_pipe(chan); + + priv->chan[fifo->chid] = chan; + chan->chid = fifo->chid; + spin_unlock_irqrestore(&priv->lock, flags); return 0; } static void -nv10_graph_context_del(struct nouveau_channel *chan, int engine) +nv10_graph_context_dtor(struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct graph_state *pgraph_ctx = chan->engctx[engine]; + struct nv10_graph_priv *priv = (void *)object->engine; + struct nv10_graph_chan *chan = (void *)object; unsigned long flags; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv10_graph_unload_context(dev); + spin_lock_irqsave(&priv->lock, flags); + priv->chan[chan->chid] = NULL; + spin_unlock_irqrestore(&priv->lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ - chan->engctx[engine] = NULL; - kfree(pgraph_ctx); -} - -static void -nv10_graph_set_tile_region(struct drm_device *dev, int i) -{ - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); + nouveau_object_destroy(&chan->base); } static int -nv10_graph_init(struct drm_device *dev, int engine) +nv10_graph_context_fini(struct nouveau_object *object, bool suspend) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 tmp; - int i; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700); - /* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ - nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | - (1<<29) | - (1<<31)); - if (dev_priv->chipset >= 0x17) { - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000); - nv_wr32(dev, 0x400a10, 0x3ff3fb6); - nv_wr32(dev, 0x400838, 0x2f8684); - nv_wr32(dev, 0x40083c, 0x115f3f); - nv_wr32(dev, 0x004006b0, 0x40000020); - } else - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); + struct nv10_graph_priv *priv = (void *)object->engine; + struct nv10_graph_chan *chan = (void *)object; + unsigned long flags; - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv10_graph_set_tile_region(dev, i); - - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF); - - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 31 << 24; - nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); + spin_lock_irqsave(&priv->lock, flags); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + if (nv10_graph_channel(priv) == chan) + nv10_graph_unload_context(chan); + nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->lock, flags); - return 0; + return nouveau_object_fini(&chan->base, suspend); } -static int -nv10_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - return -EBUSY; - } - nv10_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -} - -static int -nv17_graph_mthd_lma_window(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) -{ - struct graph_state *ctx = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - struct pipe_state *pipe = &ctx->pipe_state; - uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; - uint32_t xfmode0, xfmode1; - int i; - - ctx->lma_window[(mthd - 0x1638) / 4] = data; - - if (mthd != 0x1644) - return 0; - - nouveau_wait_for_idle(dev); - - PIPE_SAVE(dev, pipe_0x0040, 0x0040); - PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); - - PIPE_RESTORE(dev, ctx->lma_window, 0x6790); - - nouveau_wait_for_idle(dev); - - xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); - xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); - - PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); - PIPE_SAVE(dev, pipe_0x64c0, 0x64c0); - PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0); - PIPE_SAVE(dev, pipe_0x6a80, 0x6a80); - - nouveau_wait_for_idle(dev); - - nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); - for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - for (i = 0; i < 4; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); - for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); - for (i = 0; i < 3; i++) - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); - - PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); - - nouveau_wait_for_idle(dev); - - PIPE_RESTORE(dev, pipe_0x0040, 0x0040); - - nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); - nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); - - PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0); - PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0); - PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80); - PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); - - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); - - nouveau_wait_for_idle(dev); +static struct nouveau_oclass +nv10_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_graph_context_ctor, + .dtor = nv10_graph_context_dtor, + .init = nouveau_object_init, + .fini = nv10_graph_context_fini, + }, +}; - return 0; -} +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ -static int -nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) +static void +nv10_graph_tile_prog(struct nouveau_engine *engine, int i) { - struct drm_device *dev = chan->dev; + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nouveau_fifo *pfifo = nouveau_fifo(engine); + struct nv10_graph_priv *priv = (void *)engine; + unsigned long flags; - nouveau_wait_for_idle(dev); + pfifo->pause(pfifo, &flags); + nv04_graph_idle(priv); - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, - nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8); - nv_wr32(dev, 0x004006b0, - nv_rd32(dev, 0x004006b0) | 0x8 << 24); + nv_wr32(priv, NV10_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV10_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV10_PGRAPH_TILE(i), tile->addr); - return 0; + pfifo->start(pfifo, &flags); } -struct nouveau_bitfield nv10_graph_intr[] = { +struct nouveau_bitfield nv10_graph_intr_name[] = { { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, { NV_PGRAPH_INTR_ERROR, "ERROR" }, {} @@ -1073,115 +1150,165 @@ struct nouveau_bitfield nv10_graph_nstatus[] = { }; static void -nv10_graph_isr(struct drm_device *dev) +nv10_graph_intr(struct nouveau_subdev *subdev) { - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 chid = (addr & 0x01f00000) >> 20; - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - } - } + struct nv10_graph_priv *priv = (void *)subdev; + struct nv10_graph_chan *chan = NULL; + struct nouveau_namedb *namedb = NULL; + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x01f00000) >> 20; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff; + u32 show = stat; + unsigned long flags; - if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); - stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv10_graph_context_switch(dev); + spin_lock_irqsave(&priv->lock, flags); + chan = priv->chan[chid]; + if (chan) + namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS); + spin_unlock_irqrestore(&priv->lock, flags); + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) { + handle = nouveau_namedb_get_class(namedb, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; } + } - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv10_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, subc, class, mthd, data); - } + if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv10_graph_context_switch(priv); + } + + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_error(priv, ""); + nouveau_bitfield_print(nv10_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } + + nouveau_namedb_put(handle); } -static void -nv10_graph_destroy(struct drm_device *dev, int engine) +static int +nv10_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv10_graph_engine *pgraph = nv_engine(dev, engine); + struct nv10_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv10_graph_intr; + nv_engine(priv)->cclass = &nv10_graph_cclass; + + if (nv_device(priv)->chipset <= 0x10) + nv_engine(priv)->sclass = nv10_graph_sclass; + else + if (nv_device(priv)->chipset < 0x17 || + nv_device(priv)->chipset == 0x1a) + nv_engine(priv)->sclass = nv15_graph_sclass; + else + nv_engine(priv)->sclass = nv17_graph_sclass; + + nv_engine(priv)->tile_prog = nv10_graph_tile_prog; + spin_lock_init(&priv->lock); + return 0; +} - nouveau_irq_unregister(dev, 12); - kfree(pgraph); +static void +nv10_graph_dtor(struct nouveau_object *object) +{ + struct nv10_graph_priv *priv = (void *)object; + nouveau_graph_destroy(&priv->base); } -int -nv10_graph_create(struct drm_device *dev) +static int +nv10_graph_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv10_graph_engine *pgraph; - - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv10_graph_destroy; - pgraph->base.init = nv10_graph_init; - pgraph->base.fini = nv10_graph_fini; - pgraph->base.context_new = nv10_graph_context_new; - pgraph->base.context_del = nv10_graph_context_del; - pgraph->base.object_new = nv04_graph_object_new; - pgraph->base.set_tile_region = nv10_graph_set_tile_region; - - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv10_graph_isr); - - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ - NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */ - NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ - NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ - NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ - NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ - NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ - NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ - NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ - NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ - NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ - NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */ - NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */ - NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */ - NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */ - - /* celcius */ - if (dev_priv->chipset <= 0x10) { - NVOBJ_CLASS(dev, 0x0056, GR); - } else - if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) { - NVOBJ_CLASS(dev, 0x0096, GR); + struct nouveau_engine *engine = nv_engine(object); + struct nouveau_fb *pfb = nouveau_fb(object); + struct nv10_graph_priv *priv = (void *)engine; + int ret, i; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700); + /* nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */ + nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31)); + + if (nv_device(priv)->chipset >= 0x17) { + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000); + nv_wr32(priv, 0x400a10, 0x03ff3fb6); + nv_wr32(priv, 0x400838, 0x002f8684); + nv_wr32(priv, 0x40083c, 0x00115f3f); + nv_wr32(priv, 0x4006b0, 0x40000020); } else { - NVOBJ_CLASS(dev, 0x0099, GR); - NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window); - NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000); } + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); + + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); + nv_wr32(priv, NV10_PGRAPH_STATE, 0xFFFFFFFF); + + nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000); + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, 0x08000000); return 0; } + +static int +nv10_graph_fini(struct nouveau_object *object, bool suspend) +{ + struct nv10_graph_priv *priv = (void *)object; + return nouveau_graph_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv10_graph_oclass = { + .handle = NV_ENGINE(GR, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_graph_ctor, + .dtor = nv10_graph_dtor, + .init = nv10_graph_init, + .fini = nv10_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 0d874b8b18e5..61faef976aee 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -1,836 +1,378 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include <nouveau_drm.h> - -/* - * NV20 - * ----- - * There are 3 families : - * NV20 is 0x10de:0x020* - * NV25/28 is 0x10de:0x025* / 0x10de:0x028* - * NV2A is 0x10de:0x02A0 - * - * NV30 - * ----- - * There are 3 families : - * NV30/31 is 0x10de:0x030* / 0x10de:0x031* - * NV34 is 0x10de:0x032* - * NV35/36 is 0x10de:0x033* / 0x10de:0x034* - * - * Not seen in the wild, no dumps (probably NV35) : - * NV37 is 0x10de:0x00fc, 0x10de:0x00fd - * NV38 is 0x10de:0x0333, 0x10de:0x00fe - * - */ - -struct nv20_graph_engine { - struct nouveau_exec_engine base; - struct nouveau_gpuobj *ctxtab; - void (*grctx_init)(struct nouveau_gpuobj *); - u32 grctx_size; - u32 grctx_user; +#include <core/os.h> +#include <core/class.h> +#include <core/engctx.h> +#include <core/handle.h> +#include <core/enum.h> + +#include <subdev/timer.h> +#include <subdev/fb.h> + +#include <engine/graph.h> +#include <engine/fifo.h> + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv20_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x0096, &nv04_graph_ofuncs, NULL }, /* celcius */ + { 0x0097, &nv04_graph_ofuncs, NULL }, /* kelvin */ + { 0x009e, &nv04_graph_ofuncs, NULL }, /* swzsurf */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + {}, }; -#define NV20_GRCTX_SIZE (3580*4) -#define NV25_GRCTX_SIZE (3529*4) -#define NV2A_GRCTX_SIZE (3500*4) +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ -#define NV30_31_GRCTX_SIZE (24392) -#define NV34_GRCTX_SIZE (18140) -#define NV35_36_GRCTX_SIZE (22396) - -int -nv20_graph_unload_context(struct drm_device *dev) +static int +nv20_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nouveau_channel *chan; - struct nouveau_gpuobj *grctx; - u32 tmp; - - chan = nv10_graph_channel(dev); - if (!chan) - return 0; - grctx = chan->engctx[NVOBJ_ENGINE_GR]; - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->addr >> 4); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, - NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE); - - nouveau_wait_for_idle(dev); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000); - tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= 31 << 24; - nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp); - return 0; -} + struct nv20_graph_chan *chan; + int ret, i; -static void -nv20_graph_rdi(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, writecount = 32; - uint32_t rdi_index = 0x2c80000; - - if (dev_priv->chipset == 0x20) { - rdi_index = 0x3d0000; - writecount = 15; - } - - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index); - for (i = 0; i < writecount; i++) - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0); + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + 0x37f0, 16, NVOBJ_FLAG_ZERO_ALLOC, + &chan); + *pobject = nv_object(chan); + if (ret) + return ret; - nouveau_wait_for_idle(dev); -} + chan->chid = nouveau_fifo_chan(parent)->chid; -static void -nv20_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x033c, 0xffff0000); - nv_wo32(ctx, 0x03a0, 0x0fff0000); - nv_wo32(ctx, 0x03a4, 0x0fff0000); - nv_wo32(ctx, 0x047c, 0x00000101); - nv_wo32(ctx, 0x0490, 0x00000111); - nv_wo32(ctx, 0x04a8, 0x44400000); + nv_wo32(chan, 0x0000, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x033c, 0xffff0000); + nv_wo32(chan, 0x03a0, 0x0fff0000); + nv_wo32(chan, 0x03a4, 0x0fff0000); + nv_wo32(chan, 0x047c, 0x00000101); + nv_wo32(chan, 0x0490, 0x00000111); + nv_wo32(chan, 0x04a8, 0x44400000); for (i = 0x04d4; i <= 0x04e0; i += 4) - nv_wo32(ctx, i, 0x00030303); + nv_wo32(chan, i, 0x00030303); for (i = 0x04f4; i <= 0x0500; i += 4) - nv_wo32(ctx, i, 0x00080000); + nv_wo32(chan, i, 0x00080000); for (i = 0x050c; i <= 0x0518; i += 4) - nv_wo32(ctx, i, 0x01012000); + nv_wo32(chan, i, 0x01012000); for (i = 0x051c; i <= 0x0528; i += 4) - nv_wo32(ctx, i, 0x000105b8); + nv_wo32(chan, i, 0x000105b8); for (i = 0x052c; i <= 0x0538; i += 4) - nv_wo32(ctx, i, 0x00080008); + nv_wo32(chan, i, 0x00080008); for (i = 0x055c; i <= 0x0598; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x05a4, 0x4b7fffff); - nv_wo32(ctx, 0x05fc, 0x00000001); - nv_wo32(ctx, 0x0604, 0x00004000); - nv_wo32(ctx, 0x0610, 0x00000001); - nv_wo32(ctx, 0x0618, 0x00040000); - nv_wo32(ctx, 0x061c, 0x00010000); + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x05a4, 0x4b7fffff); + nv_wo32(chan, 0x05fc, 0x00000001); + nv_wo32(chan, 0x0604, 0x00004000); + nv_wo32(chan, 0x0610, 0x00000001); + nv_wo32(chan, 0x0618, 0x00040000); + nv_wo32(chan, 0x061c, 0x00010000); for (i = 0x1c1c; i <= 0x248c; i += 16) { - nv_wo32(ctx, (i + 0), 0x10700ff9); - nv_wo32(ctx, (i + 4), 0x0436086c); - nv_wo32(ctx, (i + 8), 0x000c001b); + nv_wo32(chan, (i + 0), 0x10700ff9); + nv_wo32(chan, (i + 4), 0x0436086c); + nv_wo32(chan, (i + 8), 0x000c001b); } - nv_wo32(ctx, 0x281c, 0x3f800000); - nv_wo32(ctx, 0x2830, 0x3f800000); - nv_wo32(ctx, 0x285c, 0x40000000); - nv_wo32(ctx, 0x2860, 0x3f800000); - nv_wo32(ctx, 0x2864, 0x3f000000); - nv_wo32(ctx, 0x286c, 0x40000000); - nv_wo32(ctx, 0x2870, 0x3f800000); - nv_wo32(ctx, 0x2878, 0xbf800000); - nv_wo32(ctx, 0x2880, 0xbf800000); - nv_wo32(ctx, 0x34a4, 0x000fe000); - nv_wo32(ctx, 0x3530, 0x000003f8); - nv_wo32(ctx, 0x3540, 0x002fe000); + nv_wo32(chan, 0x281c, 0x3f800000); + nv_wo32(chan, 0x2830, 0x3f800000); + nv_wo32(chan, 0x285c, 0x40000000); + nv_wo32(chan, 0x2860, 0x3f800000); + nv_wo32(chan, 0x2864, 0x3f000000); + nv_wo32(chan, 0x286c, 0x40000000); + nv_wo32(chan, 0x2870, 0x3f800000); + nv_wo32(chan, 0x2878, 0xbf800000); + nv_wo32(chan, 0x2880, 0xbf800000); + nv_wo32(chan, 0x34a4, 0x000fe000); + nv_wo32(chan, 0x3530, 0x000003f8); + nv_wo32(chan, 0x3540, 0x002fe000); for (i = 0x355c; i <= 0x3578; i += 4) - nv_wo32(ctx, i, 0x001c527c); + nv_wo32(chan, i, 0x001c527c); + return 0; } -static void -nv25_graph_context_init(struct nouveau_gpuobj *ctx) +int +nv20_graph_context_init(struct nouveau_object *object) { - int i; - - nv_wo32(ctx, 0x035c, 0xffff0000); - nv_wo32(ctx, 0x03c0, 0x0fff0000); - nv_wo32(ctx, 0x03c4, 0x0fff0000); - nv_wo32(ctx, 0x049c, 0x00000101); - nv_wo32(ctx, 0x04b0, 0x00000111); - nv_wo32(ctx, 0x04c8, 0x00000080); - nv_wo32(ctx, 0x04cc, 0xffff0000); - nv_wo32(ctx, 0x04d0, 0x00000001); - nv_wo32(ctx, 0x04e4, 0x44400000); - nv_wo32(ctx, 0x04fc, 0x4b800000); - for (i = 0x0510; i <= 0x051c; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x0530; i <= 0x053c; i += 4) - nv_wo32(ctx, i, 0x00080000); - for (i = 0x0548; i <= 0x0554; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0558; i <= 0x0564; i += 4) - nv_wo32(ctx, i, 0x000105b8); - for (i = 0x0568; i <= 0x0574; i += 4) - nv_wo32(ctx, i, 0x00080008); - for (i = 0x0598; i <= 0x05d4; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x05e0, 0x4b7fffff); - nv_wo32(ctx, 0x0620, 0x00000080); - nv_wo32(ctx, 0x0624, 0x30201000); - nv_wo32(ctx, 0x0628, 0x70605040); - nv_wo32(ctx, 0x062c, 0xb0a09080); - nv_wo32(ctx, 0x0630, 0xf0e0d0c0); - nv_wo32(ctx, 0x0664, 0x00000001); - nv_wo32(ctx, 0x066c, 0x00004000); - nv_wo32(ctx, 0x0678, 0x00000001); - nv_wo32(ctx, 0x0680, 0x00040000); - nv_wo32(ctx, 0x0684, 0x00010000); - for (i = 0x1b04; i <= 0x2374; i += 16) { - nv_wo32(ctx, (i + 0), 0x10700ff9); - nv_wo32(ctx, (i + 4), 0x0436086c); - nv_wo32(ctx, (i + 8), 0x000c001b); - } - nv_wo32(ctx, 0x2704, 0x3f800000); - nv_wo32(ctx, 0x2718, 0x3f800000); - nv_wo32(ctx, 0x2744, 0x40000000); - nv_wo32(ctx, 0x2748, 0x3f800000); - nv_wo32(ctx, 0x274c, 0x3f000000); - nv_wo32(ctx, 0x2754, 0x40000000); - nv_wo32(ctx, 0x2758, 0x3f800000); - nv_wo32(ctx, 0x2760, 0xbf800000); - nv_wo32(ctx, 0x2768, 0xbf800000); - nv_wo32(ctx, 0x308c, 0x000fe000); - nv_wo32(ctx, 0x3108, 0x000003f8); - nv_wo32(ctx, 0x3468, 0x002fe000); - for (i = 0x3484; i <= 0x34a0; i += 4) - nv_wo32(ctx, i, 0x001c527c); -} + struct nv20_graph_priv *priv = (void *)object->engine; + struct nv20_graph_chan *chan = (void *)object; + int ret; -static void -nv2a_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x033c, 0xffff0000); - nv_wo32(ctx, 0x03a0, 0x0fff0000); - nv_wo32(ctx, 0x03a4, 0x0fff0000); - nv_wo32(ctx, 0x047c, 0x00000101); - nv_wo32(ctx, 0x0490, 0x00000111); - nv_wo32(ctx, 0x04a8, 0x44400000); - for (i = 0x04d4; i <= 0x04e0; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x04f4; i <= 0x0500; i += 4) - nv_wo32(ctx, i, 0x00080000); - for (i = 0x050c; i <= 0x0518; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x051c; i <= 0x0528; i += 4) - nv_wo32(ctx, i, 0x000105b8); - for (i = 0x052c; i <= 0x0538; i += 4) - nv_wo32(ctx, i, 0x00080008); - for (i = 0x055c; i <= 0x0598; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x05a4, 0x4b7fffff); - nv_wo32(ctx, 0x05fc, 0x00000001); - nv_wo32(ctx, 0x0604, 0x00004000); - nv_wo32(ctx, 0x0610, 0x00000001); - nv_wo32(ctx, 0x0618, 0x00040000); - nv_wo32(ctx, 0x061c, 0x00010000); - for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ - nv_wo32(ctx, (i + 0), 0x10700ff9); - nv_wo32(ctx, (i + 4), 0x0436086c); - nv_wo32(ctx, (i + 8), 0x000c001b); - } - nv_wo32(ctx, 0x269c, 0x3f800000); - nv_wo32(ctx, 0x26b0, 0x3f800000); - nv_wo32(ctx, 0x26dc, 0x40000000); - nv_wo32(ctx, 0x26e0, 0x3f800000); - nv_wo32(ctx, 0x26e4, 0x3f000000); - nv_wo32(ctx, 0x26ec, 0x40000000); - nv_wo32(ctx, 0x26f0, 0x3f800000); - nv_wo32(ctx, 0x26f8, 0xbf800000); - nv_wo32(ctx, 0x2700, 0xbf800000); - nv_wo32(ctx, 0x3024, 0x000fe000); - nv_wo32(ctx, 0x30a0, 0x000003f8); - nv_wo32(ctx, 0x33fc, 0x002fe000); - for (i = 0x341c; i <= 0x3438; i += 4) - nv_wo32(ctx, i, 0x001c527c); -} + ret = nouveau_graph_context_init(&chan->base); + if (ret) + return ret; -static void -nv30_31_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x0410, 0x00000101); - nv_wo32(ctx, 0x0424, 0x00000111); - nv_wo32(ctx, 0x0428, 0x00000060); - nv_wo32(ctx, 0x0444, 0x00000080); - nv_wo32(ctx, 0x0448, 0xffff0000); - nv_wo32(ctx, 0x044c, 0x00000001); - nv_wo32(ctx, 0x0460, 0x44400000); - nv_wo32(ctx, 0x048c, 0xffff0000); - for (i = 0x04e0; i < 0x04e8; i += 4) - nv_wo32(ctx, i, 0x0fff0000); - nv_wo32(ctx, 0x04ec, 0x00011100); - for (i = 0x0508; i < 0x0548; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x0550, 0x4b7fffff); - nv_wo32(ctx, 0x058c, 0x00000080); - nv_wo32(ctx, 0x0590, 0x30201000); - nv_wo32(ctx, 0x0594, 0x70605040); - nv_wo32(ctx, 0x0598, 0xb8a89888); - nv_wo32(ctx, 0x059c, 0xf8e8d8c8); - nv_wo32(ctx, 0x05b0, 0xb0000000); - for (i = 0x0600; i < 0x0640; i += 4) - nv_wo32(ctx, i, 0x00010588); - for (i = 0x0640; i < 0x0680; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x06c0; i < 0x0700; i += 4) - nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x0700; i < 0x0740; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0740; i < 0x0780; i += 4) - nv_wo32(ctx, i, 0x00080008); - nv_wo32(ctx, 0x085c, 0x00040000); - nv_wo32(ctx, 0x0860, 0x00010000); - for (i = 0x0864; i < 0x0874; i += 4) - nv_wo32(ctx, i, 0x00040004); - for (i = 0x1f18; i <= 0x3088 ; i += 16) { - nv_wo32(ctx, i + 0, 0x10700ff9); - nv_wo32(ctx, i + 1, 0x0436086c); - nv_wo32(ctx, i + 2, 0x000c001b); - } - for (i = 0x30b8; i < 0x30c8; i += 4) - nv_wo32(ctx, i, 0x0000ffff); - nv_wo32(ctx, 0x344c, 0x3f800000); - nv_wo32(ctx, 0x3808, 0x3f800000); - nv_wo32(ctx, 0x381c, 0x3f800000); - nv_wo32(ctx, 0x3848, 0x40000000); - nv_wo32(ctx, 0x384c, 0x3f800000); - nv_wo32(ctx, 0x3850, 0x3f000000); - nv_wo32(ctx, 0x3858, 0x40000000); - nv_wo32(ctx, 0x385c, 0x3f800000); - nv_wo32(ctx, 0x3864, 0xbf800000); - nv_wo32(ctx, 0x386c, 0xbf800000); + nv_wo32(priv->ctxtab, chan->chid * 4, nv_gpuobj(chan)->addr >> 4); + return 0; } -static void -nv34_graph_context_init(struct nouveau_gpuobj *ctx) +int +nv20_graph_context_fini(struct nouveau_object *object, bool suspend) { - int i; - - nv_wo32(ctx, 0x040c, 0x01000101); - nv_wo32(ctx, 0x0420, 0x00000111); - nv_wo32(ctx, 0x0424, 0x00000060); - nv_wo32(ctx, 0x0440, 0x00000080); - nv_wo32(ctx, 0x0444, 0xffff0000); - nv_wo32(ctx, 0x0448, 0x00000001); - nv_wo32(ctx, 0x045c, 0x44400000); - nv_wo32(ctx, 0x0480, 0xffff0000); - for (i = 0x04d4; i < 0x04dc; i += 4) - nv_wo32(ctx, i, 0x0fff0000); - nv_wo32(ctx, 0x04e0, 0x00011100); - for (i = 0x04fc; i < 0x053c; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x0544, 0x4b7fffff); - nv_wo32(ctx, 0x057c, 0x00000080); - nv_wo32(ctx, 0x0580, 0x30201000); - nv_wo32(ctx, 0x0584, 0x70605040); - nv_wo32(ctx, 0x0588, 0xb8a89888); - nv_wo32(ctx, 0x058c, 0xf8e8d8c8); - nv_wo32(ctx, 0x05a0, 0xb0000000); - for (i = 0x05f0; i < 0x0630; i += 4) - nv_wo32(ctx, i, 0x00010588); - for (i = 0x0630; i < 0x0670; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x06b0; i < 0x06f0; i += 4) - nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x06f0; i < 0x0730; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0730; i < 0x0770; i += 4) - nv_wo32(ctx, i, 0x00080008); - nv_wo32(ctx, 0x0850, 0x00040000); - nv_wo32(ctx, 0x0854, 0x00010000); - for (i = 0x0858; i < 0x0868; i += 4) - nv_wo32(ctx, i, 0x00040004); - for (i = 0x15ac; i <= 0x271c ; i += 16) { - nv_wo32(ctx, i + 0, 0x10700ff9); - nv_wo32(ctx, i + 1, 0x0436086c); - nv_wo32(ctx, i + 2, 0x000c001b); + struct nv20_graph_priv *priv = (void *)object->engine; + struct nv20_graph_chan *chan = (void *)object; + int chid = -1; + + nv_mask(priv, 0x400720, 0x00000001, 0x00000000); + if (nv_rd32(priv, 0x400144) & 0x00010000) + chid = (nv_rd32(priv, 0x400148) & 0x1f000000) >> 24; + if (chan->chid == chid) { + nv_wr32(priv, 0x400784, nv_gpuobj(chan)->addr >> 4); + nv_wr32(priv, 0x400788, 0x00000002); + nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); + nv_wr32(priv, 0x400144, 0x10000000); + nv_mask(priv, 0x400148, 0xff000000, 0x1f000000); } - for (i = 0x274c; i < 0x275c; i += 4) - nv_wo32(ctx, i, 0x0000ffff); - nv_wo32(ctx, 0x2ae0, 0x3f800000); - nv_wo32(ctx, 0x2e9c, 0x3f800000); - nv_wo32(ctx, 0x2eb0, 0x3f800000); - nv_wo32(ctx, 0x2edc, 0x40000000); - nv_wo32(ctx, 0x2ee0, 0x3f800000); - nv_wo32(ctx, 0x2ee4, 0x3f000000); - nv_wo32(ctx, 0x2eec, 0x40000000); - nv_wo32(ctx, 0x2ef0, 0x3f800000); - nv_wo32(ctx, 0x2ef8, 0xbf800000); - nv_wo32(ctx, 0x2f00, 0xbf800000); -} + nv_mask(priv, 0x400720, 0x00000001, 0x00000001); -static void -nv35_36_graph_context_init(struct nouveau_gpuobj *ctx) -{ - int i; - - nv_wo32(ctx, 0x040c, 0x00000101); - nv_wo32(ctx, 0x0420, 0x00000111); - nv_wo32(ctx, 0x0424, 0x00000060); - nv_wo32(ctx, 0x0440, 0x00000080); - nv_wo32(ctx, 0x0444, 0xffff0000); - nv_wo32(ctx, 0x0448, 0x00000001); - nv_wo32(ctx, 0x045c, 0x44400000); - nv_wo32(ctx, 0x0488, 0xffff0000); - for (i = 0x04dc; i < 0x04e4; i += 4) - nv_wo32(ctx, i, 0x0fff0000); - nv_wo32(ctx, 0x04e8, 0x00011100); - for (i = 0x0504; i < 0x0544; i += 4) - nv_wo32(ctx, i, 0x07ff0000); - nv_wo32(ctx, 0x054c, 0x4b7fffff); - nv_wo32(ctx, 0x0588, 0x00000080); - nv_wo32(ctx, 0x058c, 0x30201000); - nv_wo32(ctx, 0x0590, 0x70605040); - nv_wo32(ctx, 0x0594, 0xb8a89888); - nv_wo32(ctx, 0x0598, 0xf8e8d8c8); - nv_wo32(ctx, 0x05ac, 0xb0000000); - for (i = 0x0604; i < 0x0644; i += 4) - nv_wo32(ctx, i, 0x00010588); - for (i = 0x0644; i < 0x0684; i += 4) - nv_wo32(ctx, i, 0x00030303); - for (i = 0x06c4; i < 0x0704; i += 4) - nv_wo32(ctx, i, 0x0008aae4); - for (i = 0x0704; i < 0x0744; i += 4) - nv_wo32(ctx, i, 0x01012000); - for (i = 0x0744; i < 0x0784; i += 4) - nv_wo32(ctx, i, 0x00080008); - nv_wo32(ctx, 0x0860, 0x00040000); - nv_wo32(ctx, 0x0864, 0x00010000); - for (i = 0x0868; i < 0x0878; i += 4) - nv_wo32(ctx, i, 0x00040004); - for (i = 0x1f1c; i <= 0x308c ; i += 16) { - nv_wo32(ctx, i + 0, 0x10700ff9); - nv_wo32(ctx, i + 4, 0x0436086c); - nv_wo32(ctx, i + 8, 0x000c001b); - } - for (i = 0x30bc; i < 0x30cc; i += 4) - nv_wo32(ctx, i, 0x0000ffff); - nv_wo32(ctx, 0x3450, 0x3f800000); - nv_wo32(ctx, 0x380c, 0x3f800000); - nv_wo32(ctx, 0x3820, 0x3f800000); - nv_wo32(ctx, 0x384c, 0x40000000); - nv_wo32(ctx, 0x3850, 0x3f800000); - nv_wo32(ctx, 0x3854, 0x3f000000); - nv_wo32(ctx, 0x385c, 0x40000000); - nv_wo32(ctx, 0x3860, 0x3f800000); - nv_wo32(ctx, 0x3868, 0xbf800000); - nv_wo32(ctx, 0x3870, 0xbf800000); + nv_wo32(priv->ctxtab, chan->chid * 4, 0x00000000); + return nouveau_graph_context_fini(&chan->base, suspend); } -int -nv20_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine); - struct nouveau_gpuobj *grctx = NULL; - struct drm_device *dev = chan->dev; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16, - NVOBJ_FLAG_ZERO_ALLOC, &grctx); - if (ret) - return ret; - - /* Initialise default context values */ - pgraph->grctx_init(grctx); - - /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ - /* CTX_USER */ - nv_wo32(grctx, pgraph->grctx_user, (chan->id << 24) | 0x1); +static struct nouveau_oclass +nv20_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; - nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->addr >> 4); - chan->engctx[engine] = grctx; - return 0; -} +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ void -nv20_graph_context_del(struct nouveau_channel *chan, int engine) +nv20_graph_tile_prog(struct nouveau_engine *engine, int i) { - struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine); - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nouveau_fifo *pfifo = nouveau_fifo(engine); + struct nv20_graph_priv *priv = (void *)engine; unsigned long flags; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + pfifo->pause(pfifo, &flags); + nv04_graph_idle(priv); - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv20_graph_unload_context(dev); + nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->limit); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->pitch); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->addr); - /* Free the context resources */ - nv_wo32(pgraph->ctxtab, chan->id * 4, 0); + if (nv_device(engine)->card_type == NV_20) { + nv_wr32(priv, NV20_PGRAPH_ZCOMP(i), tile->zcomp); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, tile->zcomp); + } - nouveau_gpuobj_ref(NULL, &grctx); - chan->engctx[engine] = NULL; + pfifo->start(pfifo, &flags); } -static void -nv20_graph_set_tile_region(struct drm_device *dev, int i) +void +nv20_graph_intr(struct nouveau_subdev *subdev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->limit); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr); - - if (dev_priv->card_type == NV_20) { - nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp); + struct nv20_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x01f00000) >> 20; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff; + u32 inst = nv_ro32(priv->ctxtab, (chid * 4)) << 4; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + nouveau_engctx_handle_put(handle); + } } -} - -int -nv20_graph_init(struct drm_device *dev, int engine) -{ - struct nv20_graph_engine *pgraph = nv_engine(dev, engine); - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t tmp, vramsz; - int i; - - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); - - nv20_graph_rdi(dev); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); - nv_wr32(dev, 0x40009C , 0x00000040); - - if (dev_priv->chipset >= 0x25) { - nv_wr32(dev, 0x400890, 0x00a8cfff); - nv_wr32(dev, 0x400610, 0x304B1FB6); - nv_wr32(dev, 0x400B80, 0x1cbd3883); - nv_wr32(dev, 0x400B84, 0x44000000); - nv_wr32(dev, 0x400098, 0x40000080); - nv_wr32(dev, 0x400B88, 0x000000ff); - } else { - nv_wr32(dev, 0x400880, 0x0008c7df); - nv_wr32(dev, 0x400094, 0x00000005); - nv_wr32(dev, 0x400B80, 0x45eae20e); - nv_wr32(dev, 0x400B84, 0x24000000); - nv_wr32(dev, 0x400098, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E10038); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_info(priv, ""); + nouveau_bitfield_print(nv10_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + nv_info(priv, "ch %d/%d class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } +} - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv20_graph_set_tile_region(dev, i); - - nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324)); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); - - tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) & 0x0007ff00; - nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); - tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) | 0x00020100; - nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); - - /* begin RAM config */ - vramsz = pci_resource_len(dev->pdev, 0) - 1; - nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x400820, 0); - nv_wr32(dev, 0x400824, 0); - nv_wr32(dev, 0x400864, vramsz - 1); - nv_wr32(dev, 0x400868, vramsz - 1); +static int +nv20_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; - /* interesting.. the below overwrites some of the tile setup above.. */ - nv_wr32(dev, 0x400B20, 0x00000000); - nv_wr32(dev, 0x400B04, 0xFFFFFFFF); + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); - nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv20_graph_cclass; + nv_engine(priv)->sclass = nv20_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; return 0; } -int -nv30_graph_init(struct drm_device *dev, int engine) +void +nv20_graph_dtor(struct nouveau_object *object) { - struct nv20_graph_engine *pgraph = nv_engine(dev, engine); - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i; - - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0); - nv_wr32(dev, 0x400890, 0x01b463ff); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf2de0475); - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000); - nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); - nv_wr32(dev, 0x400B80, 0x1003d888); - nv_wr32(dev, 0x400B84, 0x0c000000); - nv_wr32(dev, 0x400098, 0x00000000); - nv_wr32(dev, 0x40009C, 0x0005ad00); - nv_wr32(dev, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ - nv_wr32(dev, 0x4000a0, 0x00000000); - nv_wr32(dev, 0x4000a4, 0x00000008); - nv_wr32(dev, 0x4008a8, 0xb784a400); - nv_wr32(dev, 0x400ba0, 0x002f8685); - nv_wr32(dev, 0x400ba4, 0x00231f3f); - nv_wr32(dev, 0x4008a4, 0x40000020); - - if (dev_priv->chipset == 0x34) { - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00200201); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000008); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000032); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00004); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000002); - } + struct nv20_graph_priv *priv = (void *)object; + nouveau_gpuobj_ref(NULL, &priv->ctxtab); + nouveau_graph_destroy(&priv->base); +} - nv_wr32(dev, 0x4000c0, 0x00000016); +int +nv20_graph_init(struct nouveau_object *object) +{ + struct nouveau_engine *engine = nv_engine(object); + struct nv20_graph_priv *priv = (void *)engine; + struct nouveau_fb *pfb = nouveau_fb(object); + u32 tmp, vramsz; + int ret, i; - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv20_graph_set_tile_region(dev, i); + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); - nv_wr32(dev, 0x0040075c , 0x00000001); + nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); - /* begin RAM config */ - /* vramsz = pci_resource_len(dev->pdev, 0) - 1; */ - nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); - if (dev_priv->chipset != 0x34) { - nv_wr32(dev, 0x400750, 0x00EA0000); - nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x400750, 0x00EA0004); - nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG1)); + if (nv_device(priv)->chipset == 0x20) { + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x003d0000); + for (i = 0; i < 15; i++) + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, 0x00000000); + nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); + } else { + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x02c80000); + for (i = 0; i < 32; i++) + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, 0x00000000); + nv_wait(priv, 0x400700, 0xffffffff, 0x00000000); } - return 0; -} + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); -int -nv20_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { - nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - return -EBUSY; - } - nv20_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -} + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */ + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000); + nv_wr32(priv, 0x40009C , 0x00000040); -static void -nv20_graph_isr(struct drm_device *dev) -{ - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 chid = (addr & 0x01f00000) >> 20; - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - } - } + if (nv_device(priv)->chipset >= 0x25) { + nv_wr32(priv, 0x400890, 0x00a8cfff); + nv_wr32(priv, 0x400610, 0x304B1FB6); + nv_wr32(priv, 0x400B80, 0x1cbd3883); + nv_wr32(priv, 0x400B84, 0x44000000); + nv_wr32(priv, 0x400098, 0x40000080); + nv_wr32(priv, 0x400B88, 0x000000ff); - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv10_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, subc, class, mthd, data); - } + } else { + nv_wr32(priv, 0x400880, 0x0008c7df); + nv_wr32(priv, 0x400094, 0x00000005); + nv_wr32(priv, 0x400B80, 0x45eae20e); + nv_wr32(priv, 0x400B84, 0x24000000); + nv_wr32(priv, 0x400098, 0x00000040); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00038); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000030); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E10038); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000030); } -} - -static void -nv20_graph_destroy(struct drm_device *dev, int engine) -{ - struct nv20_graph_engine *pgraph = nv_engine(dev, engine); - nouveau_irq_unregister(dev, 12); - nouveau_gpuobj_ref(NULL, &pgraph->ctxtab); + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); - NVOBJ_ENGINE_DEL(dev, GR); - kfree(pgraph); -} + nv_wr32(priv, 0x4009a0, nv_rd32(priv, 0x100324)); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA, nv_rd32(priv, 0x100324)); -int -nv20_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv20_graph_engine *pgraph; - int ret; + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv20_graph_destroy; - pgraph->base.fini = nv20_graph_fini; - pgraph->base.context_new = nv20_graph_context_new; - pgraph->base.context_del = nv20_graph_context_del; - pgraph->base.object_new = nv04_graph_object_new; - pgraph->base.set_tile_region = nv20_graph_set_tile_region; - - pgraph->grctx_user = 0x0028; - if (dev_priv->card_type == NV_20) { - pgraph->base.init = nv20_graph_init; - switch (dev_priv->chipset) { - case 0x20: - pgraph->grctx_init = nv20_graph_context_init; - pgraph->grctx_size = NV20_GRCTX_SIZE; - pgraph->grctx_user = 0x0000; - break; - case 0x25: - case 0x28: - pgraph->grctx_init = nv25_graph_context_init; - pgraph->grctx_size = NV25_GRCTX_SIZE; - break; - case 0x2a: - pgraph->grctx_init = nv2a_graph_context_init; - pgraph->grctx_size = NV2A_GRCTX_SIZE; - pgraph->grctx_user = 0x0000; - break; - default: - NV_ERROR(dev, "PGRAPH: unknown chipset\n"); - kfree(pgraph); - return 0; - } - } else { - pgraph->base.init = nv30_graph_init; - switch (dev_priv->chipset) { - case 0x30: - case 0x31: - pgraph->grctx_init = nv30_31_graph_context_init; - pgraph->grctx_size = NV30_31_GRCTX_SIZE; - break; - case 0x34: - pgraph->grctx_init = nv34_graph_context_init; - pgraph->grctx_size = NV34_GRCTX_SIZE; - break; - case 0x35: - case 0x36: - pgraph->grctx_init = nv35_36_graph_context_init; - pgraph->grctx_size = NV35_36_GRCTX_SIZE; - break; - default: - NV_ERROR(dev, "PGRAPH: unknown chipset\n"); - kfree(pgraph); - return 0; - } - } + tmp = nv_rd32(priv, NV10_PGRAPH_SURFACE) & 0x0007ff00; + nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); + tmp = nv_rd32(priv, NV10_PGRAPH_SURFACE) | 0x00020100; + nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp); - /* Create Context Pointer Table */ - ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, - &pgraph->ctxtab); - if (ret) { - kfree(pgraph); - return ret; - } + /* begin RAM config */ + vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; + nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , nv_rd32(priv, 0x100200)); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x400820, 0); + nv_wr32(priv, 0x400824, 0); + nv_wr32(priv, 0x400864, vramsz - 1); + nv_wr32(priv, 0x400868, vramsz - 1); - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv20_graph_isr); - - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ - NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ - NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ - NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ - NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ - NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ - NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ - NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ - NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ - NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ - if (dev_priv->card_type == NV_20) { - NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */ - NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */ - - /* kelvin */ - if (dev_priv->chipset < 0x25) - NVOBJ_CLASS(dev, 0x0097, GR); - else - NVOBJ_CLASS(dev, 0x0597, GR); - } else { - NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */ - NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */ - NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */ - NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */ - - /* rankine */ - if (0x00000003 & (1 << (dev_priv->chipset & 0x0f))) - NVOBJ_CLASS(dev, 0x0397, GR); - else - if (0x00000010 & (1 << (dev_priv->chipset & 0x0f))) - NVOBJ_CLASS(dev, 0x0697, GR); - else - if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) - NVOBJ_CLASS(dev, 0x0497, GR); - } + /* interesting.. the below overwrites some of the tile setup above.. */ + nv_wr32(priv, 0x400B20, 0x00000000); + nv_wr32(priv, 0x400B04, 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_XMIN, 0); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_YMIN, 0); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); + nv_wr32(priv, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); return 0; } + +struct nouveau_oclass +nv20_graph_oclass = { + .handle = NV_ENGINE(GR, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv20_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.h new file mode 100644 index 000000000000..2bea7313e03f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.h @@ -0,0 +1,31 @@ +#ifndef __NV20_GRAPH_H__ +#define __NV20_GRAPH_H__ + +#include <core/enum.h> + +#include <engine/graph.h> +#include <engine/fifo.h> + +struct nv20_graph_priv { + struct nouveau_graph base; + struct nouveau_gpuobj *ctxtab; +}; + +struct nv20_graph_chan { + struct nouveau_graph_chan base; + int chid; +}; + +extern struct nouveau_oclass nv25_graph_sclass[]; +int nv20_graph_context_init(struct nouveau_object *); +int nv20_graph_context_fini(struct nouveau_object *, bool); + +void nv20_graph_tile_prog(struct nouveau_engine *, int); +void nv20_graph_intr(struct nouveau_subdev *); + +void nv20_graph_dtor(struct nouveau_object *); +int nv20_graph_init(struct nouveau_object *); + +int nv30_graph_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c new file mode 100644 index 000000000000..b2b650dd8b28 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c @@ -0,0 +1,167 @@ +#include <core/os.h> +#include <core/class.h> +#include <core/engctx.h> +#include <core/enum.h> + +#include <subdev/timer.h> +#include <subdev/fb.h> + +#include <engine/graph.h> + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +struct nouveau_oclass +nv25_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x0096, &nv04_graph_ofuncs, NULL }, /* celcius */ + { 0x009e, &nv04_graph_ofuncs, NULL }, /* swzsurf */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0597, &nv04_graph_ofuncs, NULL }, /* kelvin */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv25_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x3724, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x035c, 0xffff0000); + nv_wo32(chan, 0x03c0, 0x0fff0000); + nv_wo32(chan, 0x03c4, 0x0fff0000); + nv_wo32(chan, 0x049c, 0x00000101); + nv_wo32(chan, 0x04b0, 0x00000111); + nv_wo32(chan, 0x04c8, 0x00000080); + nv_wo32(chan, 0x04cc, 0xffff0000); + nv_wo32(chan, 0x04d0, 0x00000001); + nv_wo32(chan, 0x04e4, 0x44400000); + nv_wo32(chan, 0x04fc, 0x4b800000); + for (i = 0x0510; i <= 0x051c; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x0530; i <= 0x053c; i += 4) + nv_wo32(chan, i, 0x00080000); + for (i = 0x0548; i <= 0x0554; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0558; i <= 0x0564; i += 4) + nv_wo32(chan, i, 0x000105b8); + for (i = 0x0568; i <= 0x0574; i += 4) + nv_wo32(chan, i, 0x00080008); + for (i = 0x0598; i <= 0x05d4; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x05e0, 0x4b7fffff); + nv_wo32(chan, 0x0620, 0x00000080); + nv_wo32(chan, 0x0624, 0x30201000); + nv_wo32(chan, 0x0628, 0x70605040); + nv_wo32(chan, 0x062c, 0xb0a09080); + nv_wo32(chan, 0x0630, 0xf0e0d0c0); + nv_wo32(chan, 0x0664, 0x00000001); + nv_wo32(chan, 0x066c, 0x00004000); + nv_wo32(chan, 0x0678, 0x00000001); + nv_wo32(chan, 0x0680, 0x00040000); + nv_wo32(chan, 0x0684, 0x00010000); + for (i = 0x1b04; i <= 0x2374; i += 16) { + nv_wo32(chan, (i + 0), 0x10700ff9); + nv_wo32(chan, (i + 4), 0x0436086c); + nv_wo32(chan, (i + 8), 0x000c001b); + } + nv_wo32(chan, 0x2704, 0x3f800000); + nv_wo32(chan, 0x2718, 0x3f800000); + nv_wo32(chan, 0x2744, 0x40000000); + nv_wo32(chan, 0x2748, 0x3f800000); + nv_wo32(chan, 0x274c, 0x3f000000); + nv_wo32(chan, 0x2754, 0x40000000); + nv_wo32(chan, 0x2758, 0x3f800000); + nv_wo32(chan, 0x2760, 0xbf800000); + nv_wo32(chan, 0x2768, 0xbf800000); + nv_wo32(chan, 0x308c, 0x000fe000); + nv_wo32(chan, 0x3108, 0x000003f8); + nv_wo32(chan, 0x3468, 0x002fe000); + for (i = 0x3484; i <= 0x34a0; i += 4) + nv_wo32(chan, i, 0x001c527c); + return 0; +} + +static struct nouveau_oclass +nv25_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x25), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv25_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv25_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv25_graph_cclass; + nv_engine(priv)->sclass = nv25_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv25_graph_oclass = { + .handle = NV_ENGINE(GR, 0x25), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv25_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv20_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c new file mode 100644 index 000000000000..700462fa0ae0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c @@ -0,0 +1,134 @@ +#include <core/os.h> +#include <core/class.h> +#include <core/engctx.h> +#include <core/enum.h> + +#include <subdev/timer.h> +#include <subdev/fb.h> + +#include <engine/graph.h> + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv2a_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x36b0, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0000, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x033c, 0xffff0000); + nv_wo32(chan, 0x03a0, 0x0fff0000); + nv_wo32(chan, 0x03a4, 0x0fff0000); + nv_wo32(chan, 0x047c, 0x00000101); + nv_wo32(chan, 0x0490, 0x00000111); + nv_wo32(chan, 0x04a8, 0x44400000); + for (i = 0x04d4; i <= 0x04e0; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x04f4; i <= 0x0500; i += 4) + nv_wo32(chan, i, 0x00080000); + for (i = 0x050c; i <= 0x0518; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x051c; i <= 0x0528; i += 4) + nv_wo32(chan, i, 0x000105b8); + for (i = 0x052c; i <= 0x0538; i += 4) + nv_wo32(chan, i, 0x00080008); + for (i = 0x055c; i <= 0x0598; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x05a4, 0x4b7fffff); + nv_wo32(chan, 0x05fc, 0x00000001); + nv_wo32(chan, 0x0604, 0x00004000); + nv_wo32(chan, 0x0610, 0x00000001); + nv_wo32(chan, 0x0618, 0x00040000); + nv_wo32(chan, 0x061c, 0x00010000); + for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ + nv_wo32(chan, (i + 0), 0x10700ff9); + nv_wo32(chan, (i + 4), 0x0436086c); + nv_wo32(chan, (i + 8), 0x000c001b); + } + nv_wo32(chan, 0x269c, 0x3f800000); + nv_wo32(chan, 0x26b0, 0x3f800000); + nv_wo32(chan, 0x26dc, 0x40000000); + nv_wo32(chan, 0x26e0, 0x3f800000); + nv_wo32(chan, 0x26e4, 0x3f000000); + nv_wo32(chan, 0x26ec, 0x40000000); + nv_wo32(chan, 0x26f0, 0x3f800000); + nv_wo32(chan, 0x26f8, 0xbf800000); + nv_wo32(chan, 0x2700, 0xbf800000); + nv_wo32(chan, 0x3024, 0x000fe000); + nv_wo32(chan, 0x30a0, 0x000003f8); + nv_wo32(chan, 0x33fc, 0x002fe000); + for (i = 0x341c; i <= 0x3438; i += 4) + nv_wo32(chan, i, 0x001c527c); + return 0; +} + +static struct nouveau_oclass +nv2a_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x2a), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv2a_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv2a_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv2a_graph_cclass; + nv_engine(priv)->sclass = nv25_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv2a_graph_oclass = { + .handle = NV_ENGINE(GR, 0x2a), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv2a_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv20_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c new file mode 100644 index 000000000000..cedadaa92d3f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c @@ -0,0 +1,238 @@ +#include <core/os.h> +#include <core/class.h> +#include <core/engctx.h> +#include <core/enum.h> + +#include <subdev/timer.h> +#include <subdev/fb.h> + +#include <engine/graph.h> + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv30_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0362, &nv04_graph_ofuncs, NULL }, /* surf2d (nv30) */ + { 0x0389, &nv04_graph_ofuncs, NULL }, /* sifm (nv30) */ + { 0x038a, &nv04_graph_ofuncs, NULL }, /* ifc (nv30) */ + { 0x039e, &nv04_graph_ofuncs, NULL }, /* swzsurf (nv30) */ + { 0x0397, &nv04_graph_ofuncs, NULL }, /* rankine */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv30_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x5f48, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x0410, 0x00000101); + nv_wo32(chan, 0x0424, 0x00000111); + nv_wo32(chan, 0x0428, 0x00000060); + nv_wo32(chan, 0x0444, 0x00000080); + nv_wo32(chan, 0x0448, 0xffff0000); + nv_wo32(chan, 0x044c, 0x00000001); + nv_wo32(chan, 0x0460, 0x44400000); + nv_wo32(chan, 0x048c, 0xffff0000); + for (i = 0x04e0; i < 0x04e8; i += 4) + nv_wo32(chan, i, 0x0fff0000); + nv_wo32(chan, 0x04ec, 0x00011100); + for (i = 0x0508; i < 0x0548; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x0550, 0x4b7fffff); + nv_wo32(chan, 0x058c, 0x00000080); + nv_wo32(chan, 0x0590, 0x30201000); + nv_wo32(chan, 0x0594, 0x70605040); + nv_wo32(chan, 0x0598, 0xb8a89888); + nv_wo32(chan, 0x059c, 0xf8e8d8c8); + nv_wo32(chan, 0x05b0, 0xb0000000); + for (i = 0x0600; i < 0x0640; i += 4) + nv_wo32(chan, i, 0x00010588); + for (i = 0x0640; i < 0x0680; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x06c0; i < 0x0700; i += 4) + nv_wo32(chan, i, 0x0008aae4); + for (i = 0x0700; i < 0x0740; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0740; i < 0x0780; i += 4) + nv_wo32(chan, i, 0x00080008); + nv_wo32(chan, 0x085c, 0x00040000); + nv_wo32(chan, 0x0860, 0x00010000); + for (i = 0x0864; i < 0x0874; i += 4) + nv_wo32(chan, i, 0x00040004); + for (i = 0x1f18; i <= 0x3088 ; i += 16) { + nv_wo32(chan, i + 0, 0x10700ff9); + nv_wo32(chan, i + 1, 0x0436086c); + nv_wo32(chan, i + 2, 0x000c001b); + } + for (i = 0x30b8; i < 0x30c8; i += 4) + nv_wo32(chan, i, 0x0000ffff); + nv_wo32(chan, 0x344c, 0x3f800000); + nv_wo32(chan, 0x3808, 0x3f800000); + nv_wo32(chan, 0x381c, 0x3f800000); + nv_wo32(chan, 0x3848, 0x40000000); + nv_wo32(chan, 0x384c, 0x3f800000); + nv_wo32(chan, 0x3850, 0x3f000000); + nv_wo32(chan, 0x3858, 0x40000000); + nv_wo32(chan, 0x385c, 0x3f800000); + nv_wo32(chan, 0x3864, 0xbf800000); + nv_wo32(chan, 0x386c, 0xbf800000); + return 0; +} + +static struct nouveau_oclass +nv30_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv30_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv30_graph_cclass; + nv_engine(priv)->sclass = nv30_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +int +nv30_graph_init(struct nouveau_object *object) +{ + struct nouveau_engine *engine = nv_engine(object); + struct nv20_graph_priv *priv = (void *)engine; + struct nouveau_fb *pfb = nouveau_fb(object); + int ret, i; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); + + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nv_wr32(priv, 0x400890, 0x01b463ff); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf2de0475); + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); + nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); + nv_wr32(priv, 0x400B80, 0x1003d888); + nv_wr32(priv, 0x400B84, 0x0c000000); + nv_wr32(priv, 0x400098, 0x00000000); + nv_wr32(priv, 0x40009C, 0x0005ad00); + nv_wr32(priv, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ + nv_wr32(priv, 0x4000a0, 0x00000000); + nv_wr32(priv, 0x4000a4, 0x00000008); + nv_wr32(priv, 0x4008a8, 0xb784a400); + nv_wr32(priv, 0x400ba0, 0x002f8685); + nv_wr32(priv, 0x400ba4, 0x00231f3f); + nv_wr32(priv, 0x4008a4, 0x40000020); + + if (nv_device(priv)->chipset == 0x34) { + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00200201); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000008); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000032); + nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00004); + nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000002); + } + + nv_wr32(priv, 0x4000c0, 0x00000016); + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); + + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(priv, 0x0040075c , 0x00000001); + + /* begin RAM config */ + /* vramsz = pci_resource_len(priv->dev->pdev, 0) - 1; */ + nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); + if (nv_device(priv)->chipset != 0x34) { + nv_wr32(priv, 0x400750, 0x00EA0000); + nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x400750, 0x00EA0004); + nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100204)); + } + return 0; +} + +struct nouveau_oclass +nv30_graph_oclass = { + .handle = NV_ENGINE(GR, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv30_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c new file mode 100644 index 000000000000..273f6320027b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c @@ -0,0 +1,168 @@ +#include <core/os.h> +#include <core/class.h> +#include <core/engctx.h> +#include <core/enum.h> + +#include <subdev/timer.h> +#include <subdev/fb.h> + +#include <engine/graph.h> + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv34_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0362, &nv04_graph_ofuncs, NULL }, /* surf2d (nv30) */ + { 0x0389, &nv04_graph_ofuncs, NULL }, /* sifm (nv30) */ + { 0x038a, &nv04_graph_ofuncs, NULL }, /* ifc (nv30) */ + { 0x039e, &nv04_graph_ofuncs, NULL }, /* swzsurf (nv30) */ + { 0x0697, &nv04_graph_ofuncs, NULL }, /* rankine */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv34_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x46dc, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x040c, 0x01000101); + nv_wo32(chan, 0x0420, 0x00000111); + nv_wo32(chan, 0x0424, 0x00000060); + nv_wo32(chan, 0x0440, 0x00000080); + nv_wo32(chan, 0x0444, 0xffff0000); + nv_wo32(chan, 0x0448, 0x00000001); + nv_wo32(chan, 0x045c, 0x44400000); + nv_wo32(chan, 0x0480, 0xffff0000); + for (i = 0x04d4; i < 0x04dc; i += 4) + nv_wo32(chan, i, 0x0fff0000); + nv_wo32(chan, 0x04e0, 0x00011100); + for (i = 0x04fc; i < 0x053c; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x0544, 0x4b7fffff); + nv_wo32(chan, 0x057c, 0x00000080); + nv_wo32(chan, 0x0580, 0x30201000); + nv_wo32(chan, 0x0584, 0x70605040); + nv_wo32(chan, 0x0588, 0xb8a89888); + nv_wo32(chan, 0x058c, 0xf8e8d8c8); + nv_wo32(chan, 0x05a0, 0xb0000000); + for (i = 0x05f0; i < 0x0630; i += 4) + nv_wo32(chan, i, 0x00010588); + for (i = 0x0630; i < 0x0670; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x06b0; i < 0x06f0; i += 4) + nv_wo32(chan, i, 0x0008aae4); + for (i = 0x06f0; i < 0x0730; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0730; i < 0x0770; i += 4) + nv_wo32(chan, i, 0x00080008); + nv_wo32(chan, 0x0850, 0x00040000); + nv_wo32(chan, 0x0854, 0x00010000); + for (i = 0x0858; i < 0x0868; i += 4) + nv_wo32(chan, i, 0x00040004); + for (i = 0x15ac; i <= 0x271c ; i += 16) { + nv_wo32(chan, i + 0, 0x10700ff9); + nv_wo32(chan, i + 1, 0x0436086c); + nv_wo32(chan, i + 2, 0x000c001b); + } + for (i = 0x274c; i < 0x275c; i += 4) + nv_wo32(chan, i, 0x0000ffff); + nv_wo32(chan, 0x2ae0, 0x3f800000); + nv_wo32(chan, 0x2e9c, 0x3f800000); + nv_wo32(chan, 0x2eb0, 0x3f800000); + nv_wo32(chan, 0x2edc, 0x40000000); + nv_wo32(chan, 0x2ee0, 0x3f800000); + nv_wo32(chan, 0x2ee4, 0x3f000000); + nv_wo32(chan, 0x2eec, 0x40000000); + nv_wo32(chan, 0x2ef0, 0x3f800000); + nv_wo32(chan, 0x2ef8, 0xbf800000); + nv_wo32(chan, 0x2f00, 0xbf800000); + return 0; +} + +static struct nouveau_oclass +nv34_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x34), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv34_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv34_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv34_graph_cclass; + nv_engine(priv)->sclass = nv34_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv34_graph_oclass = { + .handle = NV_ENGINE(GR, 0x34), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv34_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv30_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c new file mode 100644 index 000000000000..f40ee2116ee1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c @@ -0,0 +1,166 @@ +#include <core/os.h> +#include <core/class.h> +#include <core/engctx.h> +#include <core/enum.h> + +#include <subdev/timer.h> +#include <subdev/fb.h> + +#include "nv20.h" +#include "regs.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv35_graph_sclass[] = { + { 0x0012, &nv04_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv04_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv04_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv04_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv04_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv04_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv04_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv04_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv04_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv04_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv04_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv04_graph_ofuncs, NULL }, /* imageblit */ + { 0x0362, &nv04_graph_ofuncs, NULL }, /* surf2d (nv30) */ + { 0x0389, &nv04_graph_ofuncs, NULL }, /* sifm (nv30) */ + { 0x038a, &nv04_graph_ofuncs, NULL }, /* ifc (nv30) */ + { 0x039e, &nv04_graph_ofuncs, NULL }, /* swzsurf (nv30) */ + { 0x0497, &nv04_graph_ofuncs, NULL }, /* rankine */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static int +nv35_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_chan *chan; + int ret, i; + + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, 0x577c, + 16, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->chid = nouveau_fifo_chan(parent)->chid; + + nv_wo32(chan, 0x0028, 0x00000001 | (chan->chid << 24)); + nv_wo32(chan, 0x040c, 0x00000101); + nv_wo32(chan, 0x0420, 0x00000111); + nv_wo32(chan, 0x0424, 0x00000060); + nv_wo32(chan, 0x0440, 0x00000080); + nv_wo32(chan, 0x0444, 0xffff0000); + nv_wo32(chan, 0x0448, 0x00000001); + nv_wo32(chan, 0x045c, 0x44400000); + nv_wo32(chan, 0x0488, 0xffff0000); + for (i = 0x04dc; i < 0x04e4; i += 4) + nv_wo32(chan, i, 0x0fff0000); + nv_wo32(chan, 0x04e8, 0x00011100); + for (i = 0x0504; i < 0x0544; i += 4) + nv_wo32(chan, i, 0x07ff0000); + nv_wo32(chan, 0x054c, 0x4b7fffff); + nv_wo32(chan, 0x0588, 0x00000080); + nv_wo32(chan, 0x058c, 0x30201000); + nv_wo32(chan, 0x0590, 0x70605040); + nv_wo32(chan, 0x0594, 0xb8a89888); + nv_wo32(chan, 0x0598, 0xf8e8d8c8); + nv_wo32(chan, 0x05ac, 0xb0000000); + for (i = 0x0604; i < 0x0644; i += 4) + nv_wo32(chan, i, 0x00010588); + for (i = 0x0644; i < 0x0684; i += 4) + nv_wo32(chan, i, 0x00030303); + for (i = 0x06c4; i < 0x0704; i += 4) + nv_wo32(chan, i, 0x0008aae4); + for (i = 0x0704; i < 0x0744; i += 4) + nv_wo32(chan, i, 0x01012000); + for (i = 0x0744; i < 0x0784; i += 4) + nv_wo32(chan, i, 0x00080008); + nv_wo32(chan, 0x0860, 0x00040000); + nv_wo32(chan, 0x0864, 0x00010000); + for (i = 0x0868; i < 0x0878; i += 4) + nv_wo32(chan, i, 0x00040004); + for (i = 0x1f1c; i <= 0x308c ; i += 16) { + nv_wo32(chan, i + 0, 0x10700ff9); + nv_wo32(chan, i + 4, 0x0436086c); + nv_wo32(chan, i + 8, 0x000c001b); + } + for (i = 0x30bc; i < 0x30cc; i += 4) + nv_wo32(chan, i, 0x0000ffff); + nv_wo32(chan, 0x3450, 0x3f800000); + nv_wo32(chan, 0x380c, 0x3f800000); + nv_wo32(chan, 0x3820, 0x3f800000); + nv_wo32(chan, 0x384c, 0x40000000); + nv_wo32(chan, 0x3850, 0x3f800000); + nv_wo32(chan, 0x3854, 0x3f000000); + nv_wo32(chan, 0x385c, 0x40000000); + nv_wo32(chan, 0x3860, 0x3f800000); + nv_wo32(chan, 0x3868, 0xbf800000); + nv_wo32(chan, 0x3870, 0xbf800000); + return 0; +} + +static struct nouveau_oclass +nv35_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x35), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv35_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = nv20_graph_context_init, + .fini = nv20_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv35_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv20_graph_intr; + nv_engine(priv)->cclass = &nv35_graph_cclass; + nv_engine(priv)->sclass = nv35_graph_sclass; + nv_engine(priv)->tile_prog = nv20_graph_tile_prog; + return 0; +} + +struct nouveau_oclass +nv35_graph_oclass = { + .handle = NV_ENGINE(GR, 0x35), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv35_graph_ctor, + .dtor = nv20_graph_dtor, + .init = nv30_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 466d21514b2c..2f9f2c69d1e3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -1,151 +1,238 @@ /* - * Copyright (C) 2007 Ben Skeggs. - * All Rights Reserved. + * Copyright 2012 Red Hat Inc. * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. * + * Authors: Ben Skeggs */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" +#include <core/os.h> +#include <core/class.h> +#include <core/handle.h> +#include <core/engctx.h> + +#include <subdev/fb.h> +#include <subdev/timer.h> + +#include <engine/graph.h> #include <engine/fifo.h> -#include <core/ramht.h> -struct nv40_graph_engine { - struct nouveau_exec_engine base; - u32 grctx_size; +#include "nv40.h" +#include "regs.h" + +struct nv40_graph_priv { + struct nouveau_graph base; + u32 size; }; +struct nv40_graph_chan { + struct nouveau_graph_chan base; +}; + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + static int -nv40_graph_context_new(struct nouveau_channel *chan, int engine) +nv40_graph_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine); - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *grctx = NULL; - unsigned long flags; + struct nouveau_gpuobj *obj; int ret; - ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16, - NVOBJ_FLAG_ZERO_ALLOC, &grctx); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 20, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - /* Initialise default context values */ - nv40_grctx_fill(dev, grctx); - nv_wo32(grctx, 0, grctx->addr); - - /* init grctx pointer in ramfc, and on PFIFO if channel is - * already active there - */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wo32(chan->ramfc, 0x38, grctx->addr >> 4); - nv_mask(dev, 0x002500, 0x00000001, 0x00000000); - if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) - nv_wr32(dev, 0x0032e0, grctx->addr >> 4); - nv_mask(dev, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - chan->engctx[engine] = grctx; + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); +#ifdef __BIG_ENDIAN + nv_mo32(obj, 0x08, 0x01000000, 0x01000000); +#endif + nv_wo32(obj, 0x0c, 0x00000000); + nv_wo32(obj, 0x10, 0x00000000); return 0; } -static void -nv40_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 inst = 0x01000000 | (grctx->addr >> 4); - unsigned long flags; +struct nouveau_ofuncs +nv40_graph_ofuncs = { + .ctor = nv40_graph_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x400720, 0x00000000, 0x00000001); - if (nv_rd32(dev, 0x40032c) == inst) - nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); - if (nv_rd32(dev, 0x400330) == inst) - nv_mask(dev, 0x400330, 0x01000000, 0x00000000); - nv_mask(dev, 0x400720, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ - nouveau_gpuobj_ref(NULL, &grctx); - chan->engctx[engine] = NULL; -} +static struct nouveau_oclass +nv40_graph_sclass[] = { + { 0x0012, &nv40_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv40_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv40_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv40_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv40_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv40_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv40_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv40_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv40_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv40_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv40_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv40_graph_ofuncs, NULL }, /* imageblit */ + { 0x3062, &nv40_graph_ofuncs, NULL }, /* surf2d (nv40) */ + { 0x3089, &nv40_graph_ofuncs, NULL }, /* sifm (nv40) */ + { 0x309e, &nv40_graph_ofuncs, NULL }, /* swzsurf (nv40) */ + { 0x4097, &nv40_graph_ofuncs, NULL }, /* curie */ + {}, +}; + +static struct nouveau_oclass +nv44_graph_sclass[] = { + { 0x0012, &nv40_graph_ofuncs, NULL }, /* beta1 */ + { 0x0019, &nv40_graph_ofuncs, NULL }, /* clip */ + { 0x0030, &nv40_graph_ofuncs, NULL }, /* null */ + { 0x0039, &nv40_graph_ofuncs, NULL }, /* m2mf */ + { 0x0043, &nv40_graph_ofuncs, NULL }, /* rop */ + { 0x0044, &nv40_graph_ofuncs, NULL }, /* patt */ + { 0x004a, &nv40_graph_ofuncs, NULL }, /* gdi */ + { 0x0062, &nv40_graph_ofuncs, NULL }, /* surf2d */ + { 0x0072, &nv40_graph_ofuncs, NULL }, /* beta4 */ + { 0x0089, &nv40_graph_ofuncs, NULL }, /* sifm */ + { 0x008a, &nv40_graph_ofuncs, NULL }, /* ifc */ + { 0x009f, &nv40_graph_ofuncs, NULL }, /* imageblit */ + { 0x3062, &nv40_graph_ofuncs, NULL }, /* surf2d (nv40) */ + { 0x3089, &nv40_graph_ofuncs, NULL }, /* sifm (nv40) */ + { 0x309e, &nv40_graph_ofuncs, NULL }, /* swzsurf (nv40) */ + { 0x4497, &nv40_graph_ofuncs, NULL }, /* curie */ + {}, +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ -int -nv40_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +static int +nv40_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nv40_graph_priv *priv = (void *)engine; + struct nv40_graph_chan *chan; int ret; - ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + priv->size, 16, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - obj->engine = 1; - obj->class = class; - nv_wo32(obj, 0x00, class); - nv_wo32(obj, 0x04, 0x00000000); -#ifndef __BIG_ENDIAN - nv_wo32(obj, 0x08, 0x00000000); -#else - nv_wo32(obj, 0x08, 0x01000000); -#endif - nv_wo32(obj, 0x0c, 0x00000000); - nv_wo32(obj, 0x10, 0x00000000); + nv40_grctx_fill(nv_device(priv), nv_gpuobj(chan)); + nv_wo32(chan, 0x00000, nv_gpuobj(chan)->addr >> 4); + return 0; +} + +static int +nv40_graph_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv04_graph_priv *priv = (void *)object->engine; + struct nv04_graph_chan *chan = (void *)object; + u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; + int ret = 0; + + nv_mask(priv, 0x400720, 0x00000001, 0x00000000); + + if (nv_rd32(priv, 0x40032c) == inst) { + if (suspend) { + nv_wr32(priv, 0x400720, 0x00000000); + nv_wr32(priv, 0x400784, inst); + nv_mask(priv, 0x400310, 0x00000020, 0x00000020); + nv_mask(priv, 0x400304, 0x00000001, 0x00000001); + if (!nv_wait(priv, 0x400300, 0x00000001, 0x00000000)) { + u32 insn = nv_rd32(priv, 0x400308); + nv_warn(priv, "ctxprog timeout 0x%08x\n", insn); + ret = -EBUSY; + } + } - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); + nv_mask(priv, 0x40032c, 0x01000000, 0x00000000); + } + + if (nv_rd32(priv, 0x400330) == inst) + nv_mask(priv, 0x400330, 0x01000000, 0x00000000); + + nv_mask(priv, 0x400720, 0x00000001, 0x00000001); return ret; } +static struct nouveau_oclass +nv40_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = nv40_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + static void -nv40_graph_set_tile_region(struct drm_device *dev, int i) +nv40_graph_tile_prog(struct nouveau_engine *engine, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nouveau_fifo *pfifo = nouveau_fifo(engine); + struct nv40_graph_priv *priv = (void *)engine; + unsigned long flags; + + pfifo->pause(pfifo, &flags); + nv04_graph_idle(priv); - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x40: case 0x41: /* guess */ case 0x42: case 0x43: case 0x45: /* guess */ case 0x4e: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); + nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); + nv_wr32(priv, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nv_wr32(priv, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(priv, NV40_PGRAPH_TILE1(i), tile->addr); break; case 0x44: case 0x4a: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); + nv_wr32(priv, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV20_PGRAPH_TILE(i), tile->addr); break; case 0x46: case 0x47: @@ -154,149 +241,213 @@ nv40_graph_set_tile_region(struct drm_device *dev, int i) case 0x4c: case 0x67: default: - nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); + nv_wr32(priv, NV47_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(priv, NV47_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(priv, NV47_PGRAPH_TILE(i), tile->addr); + nv_wr32(priv, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nv_wr32(priv, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(priv, NV40_PGRAPH_TILE1(i), tile->addr); break; } + + pfifo->start(pfifo, &flags); } -/* - * G70 0x47 - * G71 0x49 - * NV45 0x48 - * G72[M] 0x46 - * G73 0x4b - * C51_G7X 0x4c - * C51 0x4e - */ -int -nv40_graph_init(struct drm_device *dev, int engine) +static void +nv40_graph_intr(struct nouveau_subdev *subdev) +{ + struct nv40_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); + u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); + u32 inst = (nv_rd32(priv, 0x40032c) & 0x000fffff) << 4; + u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xffff; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + nouveau_engctx_handle_put(handle); + } + + if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { + nv_mask(priv, 0x402000, 0, 0); + } + } + + nv_wr32(priv, NV03_PGRAPH_INTR, stat); + nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); + + if (show) { + nv_info(priv, ""); + nouveau_bitfield_print(nv10_graph_intr_name, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + nv_error(priv, "ch 0x%08x subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + } +} + +static int +nv40_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv40_graph_engine *pgraph = nv_engine(dev, engine); - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t vramsz; - int i, j; + struct nv40_graph_priv *priv; + int ret; + + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); + nv_subdev(priv)->unit = 0x00001000; + nv_subdev(priv)->intr = nv40_graph_intr; + nv_engine(priv)->cclass = &nv40_graph_cclass; + if (nv44_graph_class(priv)) + nv_engine(priv)->sclass = nv44_graph_sclass; + else + nv_engine(priv)->sclass = nv40_graph_sclass; + nv_engine(priv)->tile_prog = nv40_graph_tile_prog; + return 0; +} + +static int +nv40_graph_init(struct nouveau_object *object) +{ + struct nouveau_engine *engine = nv_engine(object); + struct nouveau_fb *pfb = nouveau_fb(object); + struct nv40_graph_priv *priv = (void *)engine; + int ret, i, j; + u32 vramsz; + + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; /* generate and upload context program */ - nv40_grctx_init(dev, &pgraph->grctx_size); + nv40_grctx_init(nv_device(priv), &priv->size); /* No context present currently */ - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); + nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(priv, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000); - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0); - nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xe0de8055); - nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000); - nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); + nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); + nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xe0de8055); + nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); + nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); - j = nv_rd32(dev, 0x1540) & 0xff; + j = nv_rd32(priv, 0x1540) & 0xff; if (j) { for (i = 0; !(j & 1); j >>= 1, i++) ; - nv_wr32(dev, 0x405000, i); + nv_wr32(priv, 0x405000, i); } - if (dev_priv->chipset == 0x40) { - nv_wr32(dev, 0x4009b0, 0x83280fff); - nv_wr32(dev, 0x4009b4, 0x000000a0); + if (nv_device(priv)->chipset == 0x40) { + nv_wr32(priv, 0x4009b0, 0x83280fff); + nv_wr32(priv, 0x4009b4, 0x000000a0); } else { - nv_wr32(dev, 0x400820, 0x83280eff); - nv_wr32(dev, 0x400824, 0x000000a0); + nv_wr32(priv, 0x400820, 0x83280eff); + nv_wr32(priv, 0x400824, 0x000000a0); } - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x40: case 0x45: - nv_wr32(dev, 0x4009b8, 0x0078e366); - nv_wr32(dev, 0x4009bc, 0x0000014c); + nv_wr32(priv, 0x4009b8, 0x0078e366); + nv_wr32(priv, 0x4009bc, 0x0000014c); break; case 0x41: case 0x42: /* pciid also 0x00Cx */ /* case 0x0120: XXX (pciid) */ - nv_wr32(dev, 0x400828, 0x007596ff); - nv_wr32(dev, 0x40082c, 0x00000108); + nv_wr32(priv, 0x400828, 0x007596ff); + nv_wr32(priv, 0x40082c, 0x00000108); break; case 0x43: - nv_wr32(dev, 0x400828, 0x0072cb77); - nv_wr32(dev, 0x40082c, 0x00000108); + nv_wr32(priv, 0x400828, 0x0072cb77); + nv_wr32(priv, 0x40082c, 0x00000108); break; case 0x44: case 0x46: /* G72 */ case 0x4a: case 0x4c: /* G7x-based C51 */ case 0x4e: - nv_wr32(dev, 0x400860, 0); - nv_wr32(dev, 0x400864, 0); + nv_wr32(priv, 0x400860, 0); + nv_wr32(priv, 0x400864, 0); break; case 0x47: /* G70 */ case 0x49: /* G71 */ case 0x4b: /* G73 */ - nv_wr32(dev, 0x400828, 0x07830610); - nv_wr32(dev, 0x40082c, 0x0000016A); + nv_wr32(priv, 0x400828, 0x07830610); + nv_wr32(priv, 0x40082c, 0x0000016A); break; default: break; } - nv_wr32(dev, 0x400b38, 0x2ffff800); - nv_wr32(dev, 0x400b3c, 0x00006000); + nv_wr32(priv, 0x400b38, 0x2ffff800); + nv_wr32(priv, 0x400b3c, 0x00006000); /* Tiling related stuff. */ - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x44: case 0x4a: - nv_wr32(dev, 0x400bc4, 0x1003d888); - nv_wr32(dev, 0x400bbc, 0xb7a7b500); + nv_wr32(priv, 0x400bc4, 0x1003d888); + nv_wr32(priv, 0x400bbc, 0xb7a7b500); break; case 0x46: - nv_wr32(dev, 0x400bc4, 0x0000e024); - nv_wr32(dev, 0x400bbc, 0xb7a7b520); + nv_wr32(priv, 0x400bc4, 0x0000e024); + nv_wr32(priv, 0x400bbc, 0xb7a7b520); break; case 0x4c: case 0x4e: case 0x67: - nv_wr32(dev, 0x400bc4, 0x1003d888); - nv_wr32(dev, 0x400bbc, 0xb7a7b540); + nv_wr32(priv, 0x400bc4, 0x1003d888); + nv_wr32(priv, 0x400bbc, 0xb7a7b540); break; default: break; } /* Turn all the tiling regions off. */ - for (i = 0; i < nvfb_tile_nr(dev); i++) - nv40_graph_set_tile_region(dev, i); + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); /* begin RAM config */ - vramsz = pci_resource_len(dev->pdev, 0) - 1; - switch (dev_priv->chipset) { + vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; + switch (nv_device(priv)->chipset) { case 0x40: - nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x4069A4, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4069A8, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x400820, 0); - nv_wr32(dev, 0x400824, 0); - nv_wr32(dev, 0x400864, vramsz); - nv_wr32(dev, 0x400868, vramsz); + nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x4069A4, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4069A8, nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x400820, 0); + nv_wr32(priv, 0x400824, 0); + nv_wr32(priv, 0x400864, vramsz); + nv_wr32(priv, 0x400868, vramsz); break; default: - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x41: case 0x42: case 0x43: @@ -304,163 +455,33 @@ nv40_graph_init(struct drm_device *dev, int engine) case 0x4e: case 0x44: case 0x4a: - nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(priv, 0x4009F0, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4009F4, nv_rd32(priv, 0x100204)); break; default: - nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); + nv_wr32(priv, 0x400DF0, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x400DF4, nv_rd32(priv, 0x100204)); break; } - nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1)); - nv_wr32(dev, 0x400840, 0); - nv_wr32(dev, 0x400844, 0); - nv_wr32(dev, 0x4008A0, vramsz); - nv_wr32(dev, 0x4008A4, vramsz); + nv_wr32(priv, 0x4069F0, nv_rd32(priv, 0x100200)); + nv_wr32(priv, 0x4069F4, nv_rd32(priv, 0x100204)); + nv_wr32(priv, 0x400840, 0); + nv_wr32(priv, 0x400844, 0); + nv_wr32(priv, 0x4008A0, vramsz); + nv_wr32(priv, 0x4008A4, vramsz); break; } return 0; } -static int -nv40_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - u32 inst = nv_rd32(dev, 0x40032c); - if (inst & 0x01000000) { - nv_wr32(dev, 0x400720, 0x00000000); - nv_wr32(dev, 0x400784, inst); - nv_mask(dev, 0x400310, 0x00000020, 0x00000020); - nv_mask(dev, 0x400304, 0x00000001, 0x00000001); - if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { - u32 insn = nv_rd32(dev, 0x400308); - NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); - } - nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); - } - return 0; -} - -static int -nv40_graph_isr_chid(struct drm_device *dev, u32 inst) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *grctx; - unsigned long flags; - int i; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - if (!dev_priv->channels.ptr[i]) - continue; - grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; - - if (grctx && grctx->addr == inst) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; -} - -static void -nv40_graph_isr(struct drm_device *dev) -{ - u32 stat; - - while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { - u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4; - u32 chid = nv40_graph_isr_chid(dev, inst); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff; - u32 show = stat; - - if (stat & NV_PGRAPH_INTR_ERROR) { - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) - show &= ~NV_PGRAPH_INTR_ERROR; - } else - if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { - nv_mask(dev, 0x402000, 0, 0); - } - } - - nv_wr32(dev, NV03_PGRAPH_INTR, stat); - nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv10_graph_intr, show); - printk(" nsource:"); - nouveau_bitfield_print(nv04_graph_nsource, nsource); - printk(" nstatus:"); - nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - } - } -} - -static void -nv40_graph_destroy(struct drm_device *dev, int engine) -{ - struct nv40_graph_engine *pgraph = nv_engine(dev, engine); - - nouveau_irq_unregister(dev, 12); - - NVOBJ_ENGINE_DEL(dev, GR); - kfree(pgraph); -} - -int -nv40_graph_create(struct drm_device *dev) -{ - struct nv40_graph_engine *pgraph; - - pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - pgraph->base.destroy = nv40_graph_destroy; - pgraph->base.init = nv40_graph_init; - pgraph->base.fini = nv40_graph_fini; - pgraph->base.context_new = nv40_graph_context_new; - pgraph->base.context_del = nv40_graph_context_del; - pgraph->base.object_new = nv40_graph_object_new; - pgraph->base.set_tile_region = nv40_graph_set_tile_region; - - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - nouveau_irq_register(dev, 12, nv40_graph_isr); - - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ - NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ - NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ - NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ - NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ - NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ - NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ - NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ - NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ - NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ - NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ - NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ - NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ - - /* curie */ - if (nv44_graph_class(dev)) - NVOBJ_CLASS(dev, 0x4497, GR); - else - NVOBJ_CLASS(dev, 0x4097, GR); - - return 0; -} +struct nouveau_oclass +nv40_graph_oclass = { + .handle = NV_ENGINE(GR, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_graph_ctor, + .dtor = _nouveau_graph_dtor, + .init = nv40_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h new file mode 100644 index 000000000000..d2ac975afc2e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h @@ -0,0 +1,21 @@ +#ifndef __NV40_GRAPH_H__ +#define __NV40_GRAPH_H__ + +/* returns 1 if device is one of the nv4x using the 0x4497 object class, + * helpful to determine a number of other hardware features + */ +static inline int +nv44_graph_class(void *priv) +{ + struct nouveau_device *device = nv_device(priv); + + if ((device->chipset & 0xf0) == 0x60) + return 1; + + return !(0x0baf & (1 << (device->chipset & 0x0f))); +} + +void nv40_grctx_init(struct nouveau_device *, u32 *size); +void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 28932c4662e9..8955bdd3551c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -1,266 +1,234 @@ /* - * Copyright (C) 2007 Ben Skeggs. - * All Rights Reserved. + * Copyright 2012 Red Hat Inc. * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. * + * Authors: Ben Skeggs */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include <engine/fifo.h> -#include <core/ramht.h> -#include "nouveau_dma.h" -#include "nv50_evo.h" - -struct nv50_graph_engine { - struct nouveau_exec_engine base; - u32 ctxprog[512]; - u32 ctxprog_size; - u32 grctx_size; -}; - -static int -nv50_graph_init(struct drm_device *dev, int engine) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_graph_engine *pgraph = nv_engine(dev, engine); - u32 units = nv_rd32(dev, 0x001540); - int i; +#include <core/os.h> +#include <core/class.h> +#include <core/handle.h> +#include <core/engctx.h> +#include <core/enum.h> - NV_DEBUG(dev, "\n"); +#include <subdev/fb.h> +#include <subdev/vm.h> +#include <subdev/timer.h> - /* master reset */ - nv_mask(dev, 0x000200, 0x00201000, 0x00000000); - nv_mask(dev, 0x000200, 0x00201000, 0x00201000); - nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ - - /* reset/enable traps and interrupts */ - nv_wr32(dev, 0x400804, 0xc0000000); - nv_wr32(dev, 0x406800, 0xc0000000); - nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x401800, 0xc0000000); - nv_wr32(dev, 0x405018, 0xc0000000); - nv_wr32(dev, 0x402000, 0xc0000000); - for (i = 0; i < 16; i++) { - if (!(units & (1 << i))) - continue; +#include <engine/graph.h> - if (dev_priv->chipset < 0xa0) { - nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); - nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); - nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); - } else { - nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); - nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); - nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); - } - } +#include "nv50.h" - nv_wr32(dev, 0x400108, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, 0x400100, 0xffffffff); - nv_wr32(dev, 0x40013c, 0xffffffff); - nv_wr32(dev, 0x400500, 0x00010001); +struct nv50_graph_priv { + struct nouveau_graph base; + spinlock_t lock; + u32 size; +}; - /* upload context program, initialise ctxctl defaults */ - nv_wr32(dev, 0x400324, 0x00000000); - for (i = 0; i < pgraph->ctxprog_size; i++) - nv_wr32(dev, 0x400328, pgraph->ctxprog[i]); - nv_wr32(dev, 0x400824, 0x00000000); - nv_wr32(dev, 0x400828, 0x00000000); - nv_wr32(dev, 0x40082c, 0x00000000); - nv_wr32(dev, 0x400830, 0x00000000); - nv_wr32(dev, 0x400724, 0x00000000); - nv_wr32(dev, 0x40032c, 0x00000000); - nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ +struct nv50_graph_chan { + struct nouveau_graph_chan base; +}; - /* some unknown zcull magic */ - switch (dev_priv->chipset & 0xf0) { - case 0x50: - case 0x80: - case 0x90: - nv_wr32(dev, 0x402ca8, 0x00000800); - break; - case 0xa0: - default: - nv_wr32(dev, 0x402cc0, 0x00000000); - if (dev_priv->chipset == 0xa0 || - dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) { - nv_wr32(dev, 0x402ca8, 0x00000802); - } else { - nv_wr32(dev, 0x402cc0, 0x00000000); - nv_wr32(dev, 0x402ca8, 0x00000002); - } +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ - break; - } +static int +nv50_graph_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_gpuobj *obj; + int ret; - /* zero out zcull regions */ - for (i = 0; i < 8; i++) { - nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); - } + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); + if (ret) + return ret; + nv_wo32(obj, 0x00, nv_mclass(obj)); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); return 0; } -static int -nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_wr32(dev, 0x40013c, 0x00000000); - return 0; -} +struct nouveau_ofuncs +nv50_graph_ofuncs = { + .ctor = nv50_graph_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; -static int -nv50_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *grctx = NULL; - struct nv50_graph_engine *pgraph = nv_engine(dev, engine); - int hdr, ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); - - ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 0, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &grctx); - if (ret) - return ret; +static struct nouveau_oclass +nv50_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x5097, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + {} +}; - hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - nv_wo32(ramin, hdr + 0x00, 0x00190002); - nv_wo32(ramin, hdr + 0x04, grctx->addr + grctx->size - 1); - nv_wo32(ramin, hdr + 0x08, grctx->addr); - nv_wo32(ramin, hdr + 0x0c, 0); - nv_wo32(ramin, hdr + 0x10, 0); - nv_wo32(ramin, hdr + 0x14, 0x00010000); +static struct nouveau_oclass +nv84_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x8297, &nv50_graph_ofuncs }, + {} +}; - nv50_grctx_fill(dev, grctx); - nv_wo32(grctx, 0x00000, chan->ramin->addr >> 12); +static struct nouveau_oclass +nva0_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x8397, &nv50_graph_ofuncs }, + {} +}; - nvimem_flush(dev); +static struct nouveau_oclass +nva3_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x8597, &nv50_graph_ofuncs }, + { 0x85c0, &nv50_graph_ofuncs }, + {} +}; - nvvm_engref(chan->vm, engine, 1); - chan->engctx[NVOBJ_ENGINE_GR] = grctx; - return 0; -} +static struct nouveau_oclass +nvaf_graph_sclass[] = { + { 0x0030, &nv50_graph_ofuncs }, + { 0x502d, &nv50_graph_ofuncs }, + { 0x5039, &nv50_graph_ofuncs }, + { 0x50c0, &nv50_graph_ofuncs }, + { 0x85c0, &nv50_graph_ofuncs }, + { 0x8697, &nv50_graph_ofuncs }, + {} +}; -static void -nv50_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - - for (i = hdr; i < hdr + 24; i += 4) - nv_wo32(chan->ramin, i, 0); - nvimem_flush(dev); - - nvvm_engref(chan->vm, engine, -1); - nouveau_gpuobj_ref(NULL, &grctx); - chan->engctx[engine] = NULL; -} +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ static int -nv50_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv50_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *obj = NULL; + struct nv50_graph_priv *priv = (void *)engine; + struct nv50_graph_chan *chan; int ret; - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + priv->size, 0, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - obj->engine = 1; - obj->class = class; - - nv_wo32(obj, 0x00, class); - nv_wo32(obj, 0x04, 0x00000000); - nv_wo32(obj, 0x08, 0x00000000); - nv_wo32(obj, 0x0c, 0x00000000); - nvimem_flush(dev); - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; + nv50_grctx_fill(nv_device(priv), nv_gpuobj(chan)); + return 0; } -static void -nv50_graph_tlb_flush(struct drm_device *dev, int engine) +static struct nouveau_oclass +nv50_graph_cclass = { + .handle = NV_ENGCTX(GR, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_graph_context_ctor, + .dtor = _nouveau_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = _nouveau_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv50_graph_tlb_flush(struct nouveau_engine *engine) { - nv50_vm_flush_engine(dev, 0); + nv50_vm_flush_engine(&engine->base, 0x00); + return 0; } -static void -nv84_graph_tlb_flush(struct drm_device *dev, int engine) +static int +nv84_graph_tlb_flush(struct nouveau_engine *engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer *ptimer = nouveau_timer(engine); + struct nv50_graph_priv *priv = (void *)engine; bool idle, timeout = false; unsigned long flags; u64 start; u32 tmp; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x400500, 0x00000001, 0x00000000); + spin_lock_irqsave(&priv->lock, flags); + nv_mask(priv, 0x400500, 0x00000001, 0x00000000); - start = nv_timer_read(dev); + start = ptimer->read(ptimer); do { idle = true; - for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) { + for (tmp = nv_rd32(priv, 0x400380); tmp && idle; tmp >>= 3) { if ((tmp & 7) == 1) idle = false; } - for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) { + for (tmp = nv_rd32(priv, 0x400384); tmp && idle; tmp >>= 3) { if ((tmp & 7) == 1) idle = false; } - for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) { + for (tmp = nv_rd32(priv, 0x400388); tmp && idle; tmp >>= 3) { if ((tmp & 7) == 1) idle = false; } - } while (!idle && !(timeout = nv_timer_read(dev) - start > 2000000000)); + } while (!idle && + !(timeout = ptimer->read(ptimer) - start > 2000000000)); if (timeout) { - NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: " + nv_error(priv, "PGRAPH TLB flush idle timeout fail: " "0x%08x 0x%08x 0x%08x 0x%08x\n", - nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380), - nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388)); + nv_rd32(priv, 0x400700), nv_rd32(priv, 0x400380), + nv_rd32(priv, 0x400384), nv_rd32(priv, 0x400388)); } - nv50_vm_flush_engine(dev, 0); + nv50_vm_flush_engine(&engine->base, 0x00); - nv_mask(dev, 0x400500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + nv_mask(priv, 0x400500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->lock, flags); + return timeout ? -EBUSY : 0; } static struct nouveau_enum nv50_mp_exec_error_names[] = { @@ -341,7 +309,7 @@ struct nouveau_enum nv50_data_error_names[] = { {} }; -static struct nouveau_bitfield nv50_graph_intr[] = { +static struct nouveau_bitfield nv50_graph_intr_name[] = { { 0x00000001, "NOTIFY" }, { 0x00000002, "COMPUTE_QUERY" }, { 0x00000010, "ILLEGAL_MTHD" }, @@ -356,95 +324,93 @@ static struct nouveau_bitfield nv50_graph_intr[] = { }; static void -nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) +nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t units = nv_rd32(dev, 0x1540); - uint32_t addr, mp10, status, pc, oplow, ophigh; + u32 units = nv_rd32(priv, 0x1540); + u32 addr, mp10, status, pc, oplow, ophigh; int i; int mps = 0; for (i = 0; i < 4; i++) { if (!(units & 1 << (i+24))) continue; - if (dev_priv->chipset < 0xa0) + if (nv_device(priv)->chipset < 0xa0) addr = 0x408200 + (tpid << 12) + (i << 7); else addr = 0x408100 + (tpid << 11) + (i << 7); - mp10 = nv_rd32(dev, addr + 0x10); - status = nv_rd32(dev, addr + 0x14); + mp10 = nv_rd32(priv, addr + 0x10); + status = nv_rd32(priv, addr + 0x14); if (!status) continue; if (display) { - nv_rd32(dev, addr + 0x20); - pc = nv_rd32(dev, addr + 0x24); - oplow = nv_rd32(dev, addr + 0x70); - ophigh = nv_rd32(dev, addr + 0x74); - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " + nv_rd32(priv, addr + 0x20); + pc = nv_rd32(priv, addr + 0x24); + oplow = nv_rd32(priv, addr + 0x70); + ophigh = nv_rd32(priv, addr + 0x74); + nv_error(priv, "TRAP_MP_EXEC - " "TP %d MP %d: ", tpid, i); nouveau_enum_print(nv50_mp_exec_error_names, status); printk(" at %06x warp %d, opcode %08x %08x\n", pc&0xffffff, pc >> 24, oplow, ophigh); } - nv_wr32(dev, addr + 0x10, mp10); - nv_wr32(dev, addr + 0x14, 0); + nv_wr32(priv, addr + 0x10, mp10); + nv_wr32(priv, addr + 0x14, 0); mps++; } if (!mps && display) - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: " + nv_error(priv, "TRAP_MP_EXEC - TP %d: " "No MPs claiming errors?\n", tpid); } static void -nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, - uint32_t ustatus_new, int display, const char *name) +nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old, + u32 ustatus_new, int display, const char *name) { - struct drm_nouveau_private *dev_priv = dev->dev_private; int tps = 0; - uint32_t units = nv_rd32(dev, 0x1540); + u32 units = nv_rd32(priv, 0x1540); int i, r; - uint32_t ustatus_addr, ustatus; + u32 ustatus_addr, ustatus; for (i = 0; i < 16; i++) { if (!(units & (1 << i))) continue; - if (dev_priv->chipset < 0xa0) + if (nv_device(priv)->chipset < 0xa0) ustatus_addr = ustatus_old + (i << 12); else ustatus_addr = ustatus_new + (i << 11); - ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff; + ustatus = nv_rd32(priv, ustatus_addr) & 0x7fffffff; if (!ustatus) continue; tps++; switch (type) { case 6: /* texture error... unknown for now */ if (display) { - NV_ERROR(dev, "magic set %d:\n", i); + nv_error(priv, "magic set %d:\n", i); for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) - NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, - nv_rd32(dev, r)); + nv_error(priv, "\t0x%08x: 0x%08x\n", r, + nv_rd32(priv, r)); } break; case 7: /* MP error */ if (ustatus & 0x04030000) { - nv50_pgraph_mp_trap(dev, i, display); + nv50_priv_mp_trap(priv, i, display); ustatus &= ~0x04030000; } break; case 8: /* TPDMA error */ { - uint32_t e0c = nv_rd32(dev, ustatus_addr + 4); - uint32_t e10 = nv_rd32(dev, ustatus_addr + 8); - uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc); - uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10); - uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); - uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); - uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); + u32 e0c = nv_rd32(priv, ustatus_addr + 4); + u32 e10 = nv_rd32(priv, ustatus_addr + 8); + u32 e14 = nv_rd32(priv, ustatus_addr + 0xc); + u32 e18 = nv_rd32(priv, ustatus_addr + 0x10); + u32 e1c = nv_rd32(priv, ustatus_addr + 0x14); + u32 e20 = nv_rd32(priv, ustatus_addr + 0x18); + u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c); /* 2d engine destination */ if (ustatus & 0x00000010) { if (display) { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", i, e14, e10); - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", i, e0c, e18, e1c, e20, e24); } ustatus &= ~0x00000010; @@ -452,9 +418,9 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, /* Render target */ if (ustatus & 0x00000040) { if (display) { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", i, e14, e10); - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", i, e0c, e18, e1c, e20, e24); } ustatus &= ~0x00000040; @@ -464,19 +430,19 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, if (display) { if (e18 & 0x80000000) { /* g[] read fault? */ - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", i, e14, e10 | ((e18 >> 24) & 0x1f)); e18 &= ~0x1f000000; } else if (e18 & 0xc) { /* g[] write fault? */ - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", i, e14, e10 | ((e18 >> 7) & 0x1f)); e18 &= ~0x00000f80; } else { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", i, e14, e10); } - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", i, e0c, e18, e1c, e20, e24); } ustatus &= ~0x00000080; @@ -486,23 +452,23 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, } if (ustatus) { if (display) - NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); + nv_info(priv, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); } - nv_wr32(dev, ustatus_addr, 0xc0000000); + nv_wr32(priv, ustatus_addr, 0xc0000000); } if (!tps && display) - NV_INFO(dev, "%s - No TPs claiming errors?\n", name); + nv_info(priv, "%s - No TPs claiming errors?\n", name); } static int -nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid) +nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, u64 inst) { - u32 status = nv_rd32(dev, 0x400108); + u32 status = nv_rd32(priv, 0x400108); u32 ustatus; if (!status && display) { - NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n"); + nv_error(priv, "TRAP: no units reporting traps?\n"); return 1; } @@ -510,72 +476,72 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid * COND, QUERY. If you get a trap from it, the command is still stuck * in DISPATCH and you need to do something about it. */ if (status & 0x001) { - ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x400804) & 0x7fffffff; if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); + nv_error(priv, "TRAP_DISPATCH - no ustatus?\n"); } - nv_wr32(dev, 0x400500, 0x00000000); + nv_wr32(priv, 0x400500, 0x00000000); /* Known to be triggered by screwed up NOTIFY and COND... */ if (ustatus & 0x00000001) { - u32 addr = nv_rd32(dev, 0x400808); + u32 addr = nv_rd32(priv, 0x400808); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 datal = nv_rd32(dev, 0x40080c); - u32 datah = nv_rd32(dev, 0x400810); - u32 class = nv_rd32(dev, 0x400814); - u32 r848 = nv_rd32(dev, 0x400848); + u32 datal = nv_rd32(priv, 0x40080c); + u32 datah = nv_rd32(priv, 0x400810); + u32 class = nv_rd32(priv, 0x400814); + u32 r848 = nv_rd32(priv, 0x400848); - NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n"); + nv_error(priv, "TRAP DISPATCH_FAULT\n"); if (display && (addr & 0x80000000)) { - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + nv_error(priv, "ch 0x%010llx " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x%08x " "400808 0x%08x 400848 0x%08x\n", - chid, inst, subc, class, mthd, datah, + inst, subc, class, mthd, datah, datal, addr, r848); } else if (display) { - NV_INFO(dev, "PGRAPH - no stuck command?\n"); + nv_error(priv, "no stuck command?\n"); } - nv_wr32(dev, 0x400808, 0); - nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); - nv_wr32(dev, 0x400848, 0); + nv_wr32(priv, 0x400808, 0); + nv_wr32(priv, 0x4008e8, nv_rd32(priv, 0x4008e8) & 3); + nv_wr32(priv, 0x400848, 0); ustatus &= ~0x00000001; } if (ustatus & 0x00000002) { - u32 addr = nv_rd32(dev, 0x40084c); + u32 addr = nv_rd32(priv, 0x40084c); u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, 0x40085c); - u32 class = nv_rd32(dev, 0x400814); + u32 data = nv_rd32(priv, 0x40085c); + u32 class = nv_rd32(priv, 0x400814); - NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n"); + nv_error(priv, "TRAP DISPATCH_QUERY\n"); if (display && (addr & 0x80000000)) { - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + nv_error(priv, "ch 0x%010llx " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x 40084c 0x%08x\n", - chid, inst, subc, class, mthd, + inst, subc, class, mthd, data, addr); } else if (display) { - NV_INFO(dev, "PGRAPH - no stuck command?\n"); + nv_error(priv, "no stuck command?\n"); } - nv_wr32(dev, 0x40084c, 0); + nv_wr32(priv, 0x40084c, 0); ustatus &= ~0x00000002; } if (ustatus && display) { - NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown " + nv_error(priv, "TRAP_DISPATCH (unknown " "0x%08x)\n", ustatus); } - nv_wr32(dev, 0x400804, 0xc0000000); - nv_wr32(dev, 0x400108, 0x001); + nv_wr32(priv, 0x400804, 0xc0000000); + nv_wr32(priv, 0x400108, 0x001); status &= ~0x001; if (!status) return 0; @@ -583,81 +549,81 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid /* M2MF: Memory to memory copy engine. */ if (status & 0x002) { - u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; + u32 ustatus = nv_rd32(priv, 0x406800) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_M2MF"); + nv_error(priv, "TRAP_M2MF"); nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_M2MF %08x %08x %08x %08x\n", - nv_rd32(dev, 0x406804), nv_rd32(dev, 0x406808), - nv_rd32(dev, 0x40680c), nv_rd32(dev, 0x406810)); + nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n", + nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808), + nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810)); } /* No sane way found yet -- just reset the bugger. */ - nv_wr32(dev, 0x400040, 2); - nv_wr32(dev, 0x400040, 0); - nv_wr32(dev, 0x406800, 0xc0000000); - nv_wr32(dev, 0x400108, 0x002); + nv_wr32(priv, 0x400040, 2); + nv_wr32(priv, 0x400040, 0); + nv_wr32(priv, 0x406800, 0xc0000000); + nv_wr32(priv, 0x400108, 0x002); status &= ~0x002; } /* VFETCH: Fetches data from vertex buffers. */ if (status & 0x004) { - u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; + u32 ustatus = nv_rd32(priv, 0x400c04) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_VFETCH"); + nv_error(priv, "TRAP_VFETCH"); nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_VFETCH %08x %08x %08x %08x\n", - nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08), - nv_rd32(dev, 0x400c0c), nv_rd32(dev, 0x400c10)); + nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n", + nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08), + nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10)); } - nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x400108, 0x004); + nv_wr32(priv, 0x400c04, 0xc0000000); + nv_wr32(priv, 0x400108, 0x004); status &= ~0x004; } /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ if (status & 0x008) { - ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x401800) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_STRMOUT"); + nv_error(priv, "TRAP_STRMOUT"); nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_STRMOUT %08x %08x %08x %08x\n", - nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808), - nv_rd32(dev, 0x40180c), nv_rd32(dev, 0x401810)); + nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n", + nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808), + nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810)); } /* No sane way found yet -- just reset the bugger. */ - nv_wr32(dev, 0x400040, 0x80); - nv_wr32(dev, 0x400040, 0); - nv_wr32(dev, 0x401800, 0xc0000000); - nv_wr32(dev, 0x400108, 0x008); + nv_wr32(priv, 0x400040, 0x80); + nv_wr32(priv, 0x400040, 0); + nv_wr32(priv, 0x401800, 0xc0000000); + nv_wr32(priv, 0x400108, 0x008); status &= ~0x008; } /* CCACHE: Handles code and c[] caches and fills them. */ if (status & 0x010) { - ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x405018) & 0x7fffffff; if (display) { - NV_INFO(dev, "PGRAPH - TRAP_CCACHE"); + nv_error(priv, "TRAP_CCACHE"); nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" + nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x" " %08x %08x %08x\n", - nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004), - nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c), - nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014), - nv_rd32(dev, 0x40501c)); + nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004), + nv_rd32(priv, 0x405008), nv_rd32(priv, 0x40500c), + nv_rd32(priv, 0x405010), nv_rd32(priv, 0x405014), + nv_rd32(priv, 0x40501c)); } - nv_wr32(dev, 0x405018, 0xc0000000); - nv_wr32(dev, 0x400108, 0x010); + nv_wr32(priv, 0x405018, 0xc0000000); + nv_wr32(priv, 0x400108, 0x010); status &= ~0x010; } @@ -665,201 +631,248 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid * remaining, so try to handle it anyway. Perhaps related to that * unknown DMA slot on tesla? */ if (status & 0x20) { - ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; + ustatus = nv_rd32(priv, 0x402000) & 0x7fffffff; if (display) - NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus); - nv_wr32(dev, 0x402000, 0xc0000000); + nv_error(priv, "TRAP_UNKC04 0x%08x\n", ustatus); + nv_wr32(priv, 0x402000, 0xc0000000); /* no status modifiction on purpose */ } /* TEXTURE: CUDA texturing units */ if (status & 0x040) { - nv50_pgraph_tp_trap(dev, 6, 0x408900, 0x408600, display, - "PGRAPH - TRAP_TEXTURE"); - nv_wr32(dev, 0x400108, 0x040); + nv50_priv_tp_trap(priv, 6, 0x408900, 0x408600, display, + "TRAP_TEXTURE"); + nv_wr32(priv, 0x400108, 0x040); status &= ~0x040; } /* MP: CUDA execution engines. */ if (status & 0x080) { - nv50_pgraph_tp_trap(dev, 7, 0x408314, 0x40831c, display, - "PGRAPH - TRAP_MP"); - nv_wr32(dev, 0x400108, 0x080); + nv50_priv_tp_trap(priv, 7, 0x408314, 0x40831c, display, + "TRAP_MP"); + nv_wr32(priv, 0x400108, 0x080); status &= ~0x080; } /* TPDMA: Handles TP-initiated uncached memory accesses: * l[], g[], stack, 2d surfaces, render targets. */ if (status & 0x100) { - nv50_pgraph_tp_trap(dev, 8, 0x408e08, 0x408708, display, - "PGRAPH - TRAP_TPDMA"); - nv_wr32(dev, 0x400108, 0x100); + nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display, + "TRAP_TPDMA"); + nv_wr32(priv, 0x400108, 0x100); status &= ~0x100; } if (status) { if (display) - NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status); - nv_wr32(dev, 0x400108, status); + nv_error(priv, "TRAP: unknown 0x%08x\n", status); + nv_wr32(priv, 0x400108, status); } return 1; } -int -nv50_graph_isr_chid(struct drm_device *dev, u64 inst) +static void +nv50_graph_intr(struct nouveau_subdev *subdev) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - unsigned long flags; - int i; + struct nv50_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 stat = nv_rd32(priv, 0x400100); + u64 inst = (u64)(nv_rd32(priv, 0x40032c) & 0x0fffffff) << 12; + u32 addr = nv_rd32(priv, 0x400704); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(priv, 0x400708); + u32 class = nv_rd32(priv, 0x400814); + u32 show = stat; + + if (stat & 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (handle && !nv_call(handle->object, mthd, data)) + show &= ~0x00000010; + nouveau_engctx_handle_put(handle); + } - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; + if (show & 0x00100000) { + u32 ecode = nv_rd32(priv, 0x400110); + nv_error(priv, "DATA_ERROR "); + nouveau_enum_print(nv50_data_error_names, ecode); + printk("\n"); + } - if (inst == chan->ramin->addr) - break; + if (stat & 0x00200000) { + if (!nv50_graph_trap_handler(priv, show, inst)) + show &= ~0x00200000; + } + + nv_wr32(priv, 0x400100, stat); + nv_wr32(priv, 0x400500, 0x00010001); + + if (show) { + nv_info(priv, ""); + nouveau_bitfield_print(nv50_graph_intr_name, show); + printk("\n"); + nv_error(priv, "ch 0x%010llx subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv50_fb_trap(nouveau_fb(priv), 1); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; + + if (nv_rd32(priv, 0x400824) & (1 << 31)) + nv_wr32(priv, 0x400824, nv_rd32(priv, 0x400824) & ~(1 << 31)); } -static void -nv50_graph_isr(struct drm_device *dev) +static int +nv50_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - u32 stat; - - while ((stat = nv_rd32(dev, 0x400100))) { - u64 inst = (u64)(nv_rd32(dev, 0x40032c) & 0x0fffffff) << 12; - u32 chid = nv50_graph_isr_chid(dev, inst); - u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - u32 subc = (addr & 0x00070000) >> 16; - u32 mthd = (addr & 0x00001ffc); - u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - u32 class = nv_rd32(dev, 0x400814); - u32 show = stat; - - if (stat & 0x00000010) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, class, - mthd, data)) - show &= ~0x00000010; - } + struct nv50_graph_priv *priv; + int ret; - show = (show && nouveau_ratelimit()) ? show : 0; + ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - if (show & 0x00100000) { - u32 ecode = nv_rd32(dev, 0x400110); - NV_INFO(dev, "PGRAPH - DATA_ERROR "); - nouveau_enum_print(nv50_data_error_names, ecode); - printk("\n"); - } + nv_subdev(priv)->unit = 0x00201000; + nv_subdev(priv)->intr = nv50_graph_intr; + nv_engine(priv)->cclass = &nv50_graph_cclass; - if (stat & 0x00200000) { - if (!nv50_pgraph_trap_handler(dev, show, inst, chid)) - show &= ~0x00200000; - } + switch (nv_device(priv)->chipset) { + case 0x50: + nv_engine(priv)->sclass = nv50_graph_sclass; + break; + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0x98: + nv_engine(priv)->sclass = nv84_graph_sclass; + break; + case 0xa0: + case 0xaa: + case 0xac: + nv_engine(priv)->sclass = nva0_graph_sclass; + break; + case 0xa3: + case 0xa5: + case 0xa8: + nv_engine(priv)->sclass = nva3_graph_sclass; + break; + case 0xaf: + nv_engine(priv)->sclass = nvaf_graph_sclass; + break; - nv_wr32(dev, 0x400100, stat); - nv_wr32(dev, 0x400500, 0x00010001); + }; - if (show) { - NV_INFO(dev, "PGRAPH -"); - nouveau_bitfield_print(nv50_graph_intr, show); - printk("\n"); - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv50_fb_vm_trap(dev, 1); - } - } + if (nv_device(priv)->chipset == 0x50 || + nv_device(priv)->chipset == 0xac) + nv_engine(priv)->tlb_flush = nv50_graph_tlb_flush; + else + nv_engine(priv)->tlb_flush = nv84_graph_tlb_flush; - if (nv_rd32(dev, 0x400824) & (1 << 31)) - nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); + spin_lock_init(&priv->lock); + return 0; } -static void -nv50_graph_destroy(struct drm_device *dev, int engine) +static int +nv50_graph_init(struct nouveau_object *object) { - struct nv50_graph_engine *pgraph = nv_engine(dev, engine); + struct nv50_graph_priv *priv = (void *)object; + int ret, units, i; - NVOBJ_ENGINE_DEL(dev, GR); + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; - nouveau_irq_unregister(dev, 12); - kfree(pgraph); -} + /* NV_PGRAPH_DEBUG_3_HW_CTX_SWITCH_ENABLED */ + nv_wr32(priv, 0x40008c, 0x00000004); -int -nv50_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_graph_engine *pgraph; - int ret; + /* reset/enable traps and interrupts */ + nv_wr32(priv, 0x400804, 0xc0000000); + nv_wr32(priv, 0x406800, 0xc0000000); + nv_wr32(priv, 0x400c04, 0xc0000000); + nv_wr32(priv, 0x401800, 0xc0000000); + nv_wr32(priv, 0x405018, 0xc0000000); + nv_wr32(priv, 0x402000, 0xc0000000); + + units = nv_rd32(priv, 0x001540); + for (i = 0; i < 16; i++) { + if (!(units & (1 << i))) + continue; - pgraph = kzalloc(sizeof(*pgraph),GFP_KERNEL); - if (!pgraph) - return -ENOMEM; - - ret = nv50_grctx_init(dev, pgraph->ctxprog, ARRAY_SIZE(pgraph->ctxprog), - &pgraph->ctxprog_size, - &pgraph->grctx_size); - if (ret) { - NV_ERROR(dev, "PGRAPH: ctxprog build failed\n"); - kfree(pgraph); - return 0; + if (nv_device(priv)->chipset < 0xa0) { + nv_wr32(priv, 0x408900 + (i << 12), 0xc0000000); + nv_wr32(priv, 0x408e08 + (i << 12), 0xc0000000); + nv_wr32(priv, 0x408314 + (i << 12), 0xc0000000); + } else { + nv_wr32(priv, 0x408600 + (i << 11), 0xc0000000); + nv_wr32(priv, 0x408708 + (i << 11), 0xc0000000); + nv_wr32(priv, 0x40831c + (i << 11), 0xc0000000); + } } - pgraph->base.destroy = nv50_graph_destroy; - pgraph->base.init = nv50_graph_init; - pgraph->base.fini = nv50_graph_fini; - pgraph->base.context_new = nv50_graph_context_new; - pgraph->base.context_del = nv50_graph_context_del; - pgraph->base.object_new = nv50_graph_object_new; - if (dev_priv->chipset == 0x50 || dev_priv->chipset == 0xac) - pgraph->base.tlb_flush = nv50_graph_tlb_flush; - else - pgraph->base.tlb_flush = nv84_graph_tlb_flush; + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); + nv_wr32(priv, 0x400500, 0x00010001); - nouveau_irq_register(dev, 12, nv50_graph_isr); + /* upload context program, initialise ctxctl defaults */ + ret = nv50_grctx_init(nv_device(priv), &priv->size); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); - NVOBJ_CLASS(dev, 0x0030, GR); /* null */ - NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ - NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */ + nv_wr32(priv, 0x400824, 0x00000000); + nv_wr32(priv, 0x400828, 0x00000000); + nv_wr32(priv, 0x40082c, 0x00000000); + nv_wr32(priv, 0x400830, 0x00000000); + nv_wr32(priv, 0x400724, 0x00000000); + nv_wr32(priv, 0x40032c, 0x00000000); + nv_wr32(priv, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ - /* tesla */ - if (dev_priv->chipset == 0x50) - NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */ - else - if (dev_priv->chipset < 0xa0) - NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */ - else { - switch (dev_priv->chipset) { - case 0xa0: - case 0xaa: - case 0xac: - NVOBJ_CLASS(dev, 0x8397, GR); - break; - case 0xa3: - case 0xa5: - case 0xa8: - NVOBJ_CLASS(dev, 0x8597, GR); - break; - case 0xaf: - NVOBJ_CLASS(dev, 0x8697, GR); - break; + /* some unknown zcull magic */ + switch (nv_device(priv)->chipset & 0xf0) { + case 0x50: + case 0x80: + case 0x90: + nv_wr32(priv, 0x402ca8, 0x00000800); + break; + case 0xa0: + default: + nv_wr32(priv, 0x402cc0, 0x00000000); + if (nv_device(priv)->chipset == 0xa0 || + nv_device(priv)->chipset == 0xaa || + nv_device(priv)->chipset == 0xac) { + nv_wr32(priv, 0x402ca8, 0x00000802); + } else { + nv_wr32(priv, 0x402cc0, 0x00000000); + nv_wr32(priv, 0x402ca8, 0x00000002); } - } - /* compute */ - NVOBJ_CLASS(dev, 0x50c0, GR); - if (dev_priv->chipset > 0xa0 && - dev_priv->chipset != 0xaa && - dev_priv->chipset != 0xac) - NVOBJ_CLASS(dev, 0x85c0, GR); + break; + } + /* zero out zcull regions */ + for (i = 0; i < 8; i++) { + nv_wr32(priv, 0x402c20 + (i * 8), 0x00000000); + nv_wr32(priv, 0x402c24 + (i * 8), 0x00000000); + nv_wr32(priv, 0x402c28 + (i * 8), 0x00000000); + nv_wr32(priv, 0x402c2c + (i * 8), 0x00000000); + } return 0; } + +struct nouveau_oclass +nv50_graph_oclass = { + .handle = NV_ENGINE(GR, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_graph_ctor, + .dtor = _nouveau_graph_dtor, + .init = nv50_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.h new file mode 100644 index 000000000000..0505fb419bde --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.h @@ -0,0 +1,7 @@ +#ifndef __NV50_GRAPH_H__ +#define __NV50_GRAPH_H__ + +int nv50_grctx_init(struct nouveau_device *, u32 *size); +void nv50_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index f994d2f7e8d5..db8aefc3cf3e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -1,5 +1,5 @@ /* - * Copyright 2010 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,94 +22,92 @@ * Authors: Ben Skeggs */ -#include <linux/firmware.h> -#include <linux/module.h> - -#include "drmP.h" - -#include "nouveau_drv.h" -#include <core/mm.h> -#include <engine/fifo.h> - #include "nvc0.h" #include "fuc/hubnvc0.fuc.h" #include "fuc/gpcnvc0.fuc.h" -static void -nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) -{ - NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base, - nv_rd32(dev, base + 0x400)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804), - nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814), - nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); -} - -void -nvc0_graph_ctxctl_debug(struct drm_device *dev) -{ - u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; - u32 gpc; - - nvc0_graph_ctxctl_debug_unit(dev, 0x409000); - for (gpc = 0; gpc < gpcnr; gpc++) - nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); -} +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nvc0_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0x9039, &nouveau_object_ofuncs }, + { 0x9097, &nouveau_object_ofuncs }, + { 0x90c0, &nouveau_object_ofuncs }, + {} +}; + +static struct nouveau_oclass +nvc1_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0x9039, &nouveau_object_ofuncs }, + { 0x9097, &nouveau_object_ofuncs }, + { 0x90c0, &nouveau_object_ofuncs }, + { 0x9197, &nouveau_object_ofuncs }, + {} +}; + +static struct nouveau_oclass +nvc8_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0x9039, &nouveau_object_ofuncs }, + { 0x9097, &nouveau_object_ofuncs }, + { 0x90c0, &nouveau_object_ofuncs }, + { 0x9197, &nouveau_object_ofuncs }, + { 0x9297, &nouveau_object_ofuncs }, + {} +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ int -nvc0_graph_context_new(struct nouveau_channel *chan, int engine) +nvc0_graph_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *args, u32 size, + struct nouveau_object **pobject) { - struct drm_device *dev = chan->dev; - struct nvc0_graph_priv *priv = nv_engine(dev, engine); + struct nouveau_vm *vm = nouveau_client(parent)->vm; + struct nvc0_graph_priv *priv = (void *)engine; struct nvc0_graph_data *data = priv->mmio_data; struct nvc0_graph_mmio *mmio = priv->mmio_list; - struct nvc0_graph_chan *grch; - struct nouveau_gpuobj *grctx; + struct nvc0_graph_chan *chan; int ret, i; - grch = kzalloc(sizeof(*grch), GFP_KERNEL); - if (!grch) - return -ENOMEM; - chan->engctx[NVOBJ_ENGINE_GR] = grch; - - ret = nouveau_gpuobj_new(dev, NULL, priv->size, 256, 0, &grch->grctx); - if (ret) - goto error; - - ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, &grch->grctx_vma); + /* allocate memory for context, and fill with default values */ + ret = nouveau_graph_context_create(parent, engine, oclass, NULL, + priv->size, 0x100, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - grctx = grch->grctx; - /* allocate memory for a "mmio list" buffer that's used by the HUB * fuc to modify some per-context register settings on first load * of the context. */ - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x100, 0, &grch->mmio); + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x100, 0, &chan->mmio); if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, + ret = nouveau_gpuobj_map_vm(nv_gpuobj(chan->mmio), vm, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->mmio_vma); + &chan->mmio_vma); if (ret) return ret; /* allocate buffers referenced by mmio list */ for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) { - ret = nouveau_gpuobj_new(dev, NULL, data->size, data->align, - 0, &grch->data[i].mem); + ret = nouveau_gpuobj_new(parent, NULL, data->size, data->align, + 0, &chan->data[i].mem); if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->data[i].mem, chan->vm, - data->access, - &grch->data[i].vma); + ret = nouveau_gpuobj_map_vm(chan->data[i].mem, vm, data->access, + &chan->data[i].vma); if (ret) return ret; @@ -122,117 +120,378 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) u32 data = mmio->data; if (mmio->shift) { - u64 info = grch->data[mmio->buffer].vma.offset; + u64 info = chan->data[mmio->buffer].vma.offset; data |= info >> mmio->shift; } - nv_wo32(grch->mmio, grch->mmio_nr++ * 4, addr); - nv_wo32(grch->mmio, grch->mmio_nr++ * 4, data); + nv_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); + nv_wo32(chan->mmio, chan->mmio_nr++ * 4, data); mmio++; } for (i = 0; i < priv->size; i += 4) - nv_wo32(grch->grctx, i, priv->data[i / 4]); - - nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4); - nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset)); - nvimem_flush(dev); + nv_wo32(chan, i, priv->data[i / 4]); if (!priv->firmware) { - nv_wo32(grctx, 0x00, grch->mmio_nr / 2); - nv_wo32(grctx, 0x04, grch->mmio_vma.offset >> 8); + nv_wo32(chan, 0x00, chan->mmio_nr / 2); + nv_wo32(chan, 0x04, chan->mmio_vma.offset >> 8); } else { - nv_wo32(grctx, 0xf4, 0); - nv_wo32(grctx, 0xf8, 0); - nv_wo32(grctx, 0x10, grch->mmio_nr / 2); - nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio_vma.offset)); - nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio_vma.offset)); - nv_wo32(grctx, 0x1c, 1); - nv_wo32(grctx, 0x20, 0); - nv_wo32(grctx, 0x28, 0); - nv_wo32(grctx, 0x2c, 0); + nv_wo32(chan, 0xf4, 0); + nv_wo32(chan, 0xf8, 0); + nv_wo32(chan, 0x10, chan->mmio_nr / 2); + nv_wo32(chan, 0x14, lower_32_bits(chan->mmio_vma.offset)); + nv_wo32(chan, 0x18, upper_32_bits(chan->mmio_vma.offset)); + nv_wo32(chan, 0x1c, 1); + nv_wo32(chan, 0x20, 0); + nv_wo32(chan, 0x28, 0); + nv_wo32(chan, 0x2c, 0); } - nvimem_flush(dev); - return 0; -error: - priv->base.context_del(chan, engine); - return ret; + return 0; } void -nvc0_graph_context_del(struct nouveau_channel *chan, int engine) +nvc0_graph_context_dtor(struct nouveau_object *object) { - struct nvc0_graph_chan *grch = chan->engctx[engine]; + struct nvc0_graph_chan *chan = (void *)object; int i; - for (i = 0; i < ARRAY_SIZE(grch->data); i++) { - nouveau_gpuobj_unmap(&grch->data[i].vma); - nouveau_gpuobj_ref(NULL, &grch->data[i].mem); + for (i = 0; i < ARRAY_SIZE(chan->data); i++) { + nouveau_gpuobj_unmap(&chan->data[i].vma); + nouveau_gpuobj_ref(NULL, &chan->data[i].mem); } - nouveau_gpuobj_unmap(&grch->mmio_vma); - nouveau_gpuobj_ref(NULL, &grch->mmio); + nouveau_gpuobj_unmap(&chan->mmio_vma); + nouveau_gpuobj_ref(NULL, &chan->mmio); - nouveau_gpuobj_unmap(&grch->grctx_vma); - nouveau_gpuobj_ref(NULL, &grch->grctx); - chan->engctx[engine] = NULL; + nouveau_graph_context_destroy(&chan->base); } -static int -nvc0_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +static struct nouveau_oclass +nvc0_graph_cclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_graph_context_ctor, + .dtor = nvc0_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = _nouveau_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static void +nvc0_graph_ctxctl_debug_unit(struct nvc0_graph_priv *priv, u32 base) { - return 0; + nv_error(priv, "%06x - done 0x%08x\n", base, + nv_rd32(priv, base + 0x400)); + nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, + nv_rd32(priv, base + 0x800), nv_rd32(priv, base + 0x804), + nv_rd32(priv, base + 0x808), nv_rd32(priv, base + 0x80c)); + nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, + nv_rd32(priv, base + 0x810), nv_rd32(priv, base + 0x814), + nv_rd32(priv, base + 0x818), nv_rd32(priv, base + 0x81c)); +} + +void +nvc0_graph_ctxctl_debug(struct nvc0_graph_priv *priv) +{ + u32 gpcnr = nv_rd32(priv, 0x409604) & 0xffff; + u32 gpc; + + nvc0_graph_ctxctl_debug_unit(priv, 0x409000); + for (gpc = 0; gpc < gpcnr; gpc++) + nvc0_graph_ctxctl_debug_unit(priv, 0x502000 + (gpc * 0x8000)); +} + +static void +nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) +{ + u32 ustat = nv_rd32(priv, 0x409c18); + + if (ustat & 0x00000001) + nv_error(priv, "CTXCTRL ucode error\n"); + if (ustat & 0x00080000) + nv_error(priv, "CTXCTRL watchdog timeout\n"); + if (ustat & ~0x00080001) + nv_error(priv, "CTXCTRL 0x%08x\n", ustat); + + nvc0_graph_ctxctl_debug(priv); + nv_wr32(priv, 0x409c20, ustat); +} + +static void +nvc0_graph_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; + u32 stat = nv_rd32(priv, 0x400100); + u32 addr = nv_rd32(priv, 0x400704); + u32 mthd = (addr & 0x00003ffc); + u32 subc = (addr & 0x00070000) >> 16; + u32 data = nv_rd32(priv, 0x400708); + u32 code = nv_rd32(priv, 0x400110); + u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + + if (stat & 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (!handle || nv_call(handle->object, mthd, data)) { + nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x\n", + inst, subc, class, mthd, data); + } + nouveau_engctx_handle_put(handle); + nv_wr32(priv, 0x400100, 0x00000010); + stat &= ~0x00000010; + } + + if (stat & 0x00000020) { + nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00000020); + stat &= ~0x00000020; + } + + if (stat & 0x00100000) { + nv_error(priv, "DATA_ERROR ["); + nouveau_enum_print(nv50_data_error_names, code); + printk("] ch 0x%010llx subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00100000); + stat &= ~0x00100000; + } + + if (stat & 0x00200000) { + u32 trap = nv_rd32(priv, 0x400108); + nv_error(priv, "TRAP ch 0x%010llx status 0x%08x\n", inst, trap); + nv_wr32(priv, 0x400108, trap); + nv_wr32(priv, 0x400100, 0x00200000); + stat &= ~0x00200000; + } + + if (stat & 0x00080000) { + nvc0_graph_ctxctl_isr(priv); + nv_wr32(priv, 0x400100, 0x00080000); + stat &= ~0x00080000; + } + + if (stat) { + nv_error(priv, "unknown stat 0x%08x\n", stat); + nv_wr32(priv, 0x400100, stat); + } + + nv_wr32(priv, 0x400500, 0x00010001); +} + +int +nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname, + struct nvc0_graph_fuc *fuc) +{ + struct nouveau_device *device = nv_device(priv); + const struct firmware *fw; + char f[32]; + int ret; + + snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); + ret = request_firmware(&fw, f, &device->pdev->dev); + if (ret) { + snprintf(f, sizeof(f), "nouveau/%s", fwname); + ret = request_firmware(&fw, f, &device->pdev->dev); + if (ret) { + nv_error(priv, "failed to load %s\n", fwname); + return ret; + } + } + + fuc->size = fw->size; + fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); + release_firmware(fw); + return (fuc->data != NULL) ? 0 : -ENOMEM; } static int -nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) +nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nouveau_device *device = nv_device(parent); + struct nvc0_graph_priv *priv; + bool enable = true; + int ret, i; + + switch (device->chipset) { + case 0xd9: /* known broken without binary driver firmware */ + enable = false; + break; + default: + break; + } + + ret = nouveau_graph_create(parent, engine, oclass, enable, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x18001000; + nv_subdev(priv)->intr = nvc0_graph_intr; + nv_engine(priv)->cclass = &nvc0_graph_cclass; + + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { + nv_info(priv, "using external firmware\n"); + if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || + nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || + nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || + nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) + return -EINVAL; + priv->firmware = true; + } + + switch (nvc0_graph_class(priv)) { + case 0x9097: + nv_engine(priv)->sclass = nvc0_graph_sclass; + break; + case 0x9197: + nv_engine(priv)->sclass = nvc1_graph_sclass; + break; + case 0x9297: + nv_engine(priv)->sclass = nvc8_graph_sclass; + break; + } + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); + if (ret) + return ret; + + for (i = 0; i < 0x1000; i += 4) { + nv_wo32(priv->unk4188b4, i, 0x00000010); + nv_wo32(priv->unk4188b8, i, 0x00000010); + } + + priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; + priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; + for (i = 0; i < priv->gpc_nr; i++) { + priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); + priv->tpc_total += priv->tpc_nr[i]; + } + + /*XXX: these need figuring out... though it might not even matter */ + switch (nv_device(priv)->chipset) { + case 0xc0: + if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ + priv->magic_not_rop_nr = 0x07; + } else + if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ + priv->magic_not_rop_nr = 0x05; + } else + if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ + priv->magic_not_rop_nr = 0x06; + } + break; + case 0xc3: /* 450, 4/0/0/0, 2 */ + priv->magic_not_rop_nr = 0x03; + break; + case 0xc4: /* 460, 3/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x01; + break; + case 0xc1: /* 2/0/0/0, 1 */ + priv->magic_not_rop_nr = 0x01; + break; + case 0xc8: /* 4/4/3/4, 5 */ + priv->magic_not_rop_nr = 0x06; + break; + case 0xce: /* 4/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x03; + break; + case 0xcf: /* 4/0/0/0, 3 */ + priv->magic_not_rop_nr = 0x03; + break; + case 0xd9: /* 1/0/0/0, 1 */ + priv->magic_not_rop_nr = 0x01; + break; + } + return 0; } static void -nvc0_graph_init_obj418880(struct drm_device *dev) +nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc) +{ + if (fuc->data) { + kfree(fuc->data); + fuc->data = NULL; + } +} + +void +nvc0_graph_dtor(struct nouveau_object *object) +{ + struct nvc0_graph_priv *priv = (void *)object; + + if (priv->data) + kfree(priv->data); + + nvc0_graph_dtor_fw(&priv->fuc409c); + nvc0_graph_dtor_fw(&priv->fuc409d); + nvc0_graph_dtor_fw(&priv->fuc41ac); + nvc0_graph_dtor_fw(&priv->fuc41ad); + + nouveau_gpuobj_ref(NULL, &priv->unk4188b8); + nouveau_gpuobj_ref(NULL, &priv->unk4188b4); + + nouveau_graph_destroy(&priv->base); +} + +static void +nvc0_graph_init_obj418880(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; - nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); for (i = 0; i < 4; i++) - nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void -nvc0_graph_init_regs(struct drm_device *dev) +nvc0_graph_init_regs(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x400080, 0x003083c2); - nv_wr32(dev, 0x400088, 0x00006fe7); - nv_wr32(dev, 0x40008c, 0x00000000); - nv_wr32(dev, 0x400090, 0x00000030); - nv_wr32(dev, 0x40013c, 0x013901f7); - nv_wr32(dev, 0x400140, 0x00000100); - nv_wr32(dev, 0x400144, 0x00000000); - nv_wr32(dev, 0x400148, 0x00000110); - nv_wr32(dev, 0x400138, 0x00000000); - nv_wr32(dev, 0x400130, 0x00000000); - nv_wr32(dev, 0x400134, 0x00000000); - nv_wr32(dev, 0x400124, 0x00000002); + nv_wr32(priv, 0x400080, 0x003083c2); + nv_wr32(priv, 0x400088, 0x00006fe7); + nv_wr32(priv, 0x40008c, 0x00000000); + nv_wr32(priv, 0x400090, 0x00000030); + nv_wr32(priv, 0x40013c, 0x013901f7); + nv_wr32(priv, 0x400140, 0x00000100); + nv_wr32(priv, 0x400144, 0x00000000); + nv_wr32(priv, 0x400148, 0x00000110); + nv_wr32(priv, 0x400138, 0x00000000); + nv_wr32(priv, 0x400130, 0x00000000); + nv_wr32(priv, 0x400134, 0x00000000); + nv_wr32(priv, 0x400124, 0x00000002); } static void -nvc0_graph_init_gpc_0(struct drm_device *dev) +nvc0_graph_init_gpc_0(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); u32 data[TPC_MAX / 8]; - u8 tpnr[GPC_MAX]; + u8 tpcnr[GPC_MAX]; int i, gpc, tpc; - nv_wr32(dev, TPC_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ + nv_wr32(priv, TPC_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ /* * TP ROP UNKVAL(magic_not_rop_nr) @@ -244,205 +503,208 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) */ memset(data, 0x00, sizeof(data)); - memcpy(tpnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); for (i = 0, gpc = -1; i < priv->tpc_total; i++) { do { gpc = (gpc + 1) % priv->gpc_nr; - } while (!tpnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpnr[gpc]--; + } while (!tpcnr[gpc]); + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(dev, GPC_BCAST(0x0980), data[0]); - nv_wr32(dev, GPC_BCAST(0x0984), data[1]); - nv_wr32(dev, GPC_BCAST(0x0988), data[2]); - nv_wr32(dev, GPC_BCAST(0x098c), data[3]); + nv_wr32(priv, GPC_BCAST(0x0980), data[0]); + nv_wr32(priv, GPC_BCAST(0x0984), data[1]); + nv_wr32(priv, GPC_BCAST(0x0988), data[2]); + nv_wr32(priv, GPC_BCAST(0x098c), data[3]); for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | + nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); - nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); + nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); + nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); - nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); + nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); } static void -nvc0_graph_init_units(struct drm_device *dev) +nvc0_graph_init_units(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x409c24, 0x000f0000); - nv_wr32(dev, 0x404000, 0xc0000000); /* DISPATCH */ - nv_wr32(dev, 0x404600, 0xc0000000); /* M2MF */ - nv_wr32(dev, 0x408030, 0xc0000000); - nv_wr32(dev, 0x40601c, 0xc0000000); - nv_wr32(dev, 0x404490, 0xc0000000); /* MACRO */ - nv_wr32(dev, 0x406018, 0xc0000000); - nv_wr32(dev, 0x405840, 0xc0000000); - nv_wr32(dev, 0x405844, 0x00ffffff); - nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008); - nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000); + nv_wr32(priv, 0x409c24, 0x000f0000); + nv_wr32(priv, 0x404000, 0xc0000000); /* DISPATCH */ + nv_wr32(priv, 0x404600, 0xc0000000); /* M2MF */ + nv_wr32(priv, 0x408030, 0xc0000000); + nv_wr32(priv, 0x40601c, 0xc0000000); + nv_wr32(priv, 0x404490, 0xc0000000); /* MACRO */ + nv_wr32(priv, 0x406018, 0xc0000000); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x405844, 0x00ffffff); + nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); + nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); } static void -nvc0_graph_init_gpc_1(struct drm_device *dev) +nvc0_graph_init_gpc_1(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); - int gpc, tp; + int gpc, tpc; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000); - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x508), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x50c), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x224), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x48c), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x084), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x644), 0x001ffffe); - nv_wr32(dev, TPC_UNIT(gpc, tp, 0x64c), 0x0000000f); + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); } - nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } } static void -nvc0_graph_init_rop(struct drm_device *dev) +nvc0_graph_init_rop(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); } } -static void -nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base, - struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) +void +nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base, + struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) { int i; - nv_wr32(dev, fuc_base + 0x01c0, 0x01000000); + nv_wr32(priv, fuc_base + 0x01c0, 0x01000000); for (i = 0; i < data->size / 4; i++) - nv_wr32(dev, fuc_base + 0x01c4, data->data[i]); + nv_wr32(priv, fuc_base + 0x01c4, data->data[i]); - nv_wr32(dev, fuc_base + 0x0180, 0x01000000); + nv_wr32(priv, fuc_base + 0x0180, 0x01000000); for (i = 0; i < code->size / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(dev, fuc_base + 0x0188, i >> 6); - nv_wr32(dev, fuc_base + 0x0184, code->data[i]); + nv_wr32(priv, fuc_base + 0x0188, i >> 6); + nv_wr32(priv, fuc_base + 0x0184, code->data[i]); } } static int -nvc0_graph_init_ctxctl(struct drm_device *dev) +nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; int i; if (priv->firmware) { /* load fuc microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d); - nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, + nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); - nv_wr32(dev, 0x000260, r000260); + nv_wr32(priv, 0x000260, r000260); /* start both of them running */ - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x41a10c, 0x00000000); - nv_wr32(dev, 0x40910c, 0x00000000); - nv_wr32(dev, 0x41a100, 0x00000002); - nv_wr32(dev, 0x409100, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) - NV_INFO(dev, "0x409800 wait failed\n"); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x7fffffff); - nv_wr32(dev, 0x409504, 0x00000021); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000010); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x41a10c, 0x00000000); + nv_wr32(priv, 0x40910c, 0x00000000); + nv_wr32(priv, 0x41a100, 0x00000002); + nv_wr32(priv, 0x409100, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) + nv_info(priv, "0x409800 wait failed\n"); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x7fffffff); + nv_wr32(priv, 0x409504, 0x00000021); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000010); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x10 timeout\n"); return -EBUSY; } - priv->size = nv_rd32(dev, 0x409800); + priv->size = nv_rd32(priv, 0x409800); - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000016); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000016); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x16 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000025); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000025); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x25 timeout\n"); return -EBUSY; } - goto done; + if (priv->data == NULL) { + int ret = nvc0_grctx_generate(priv); + if (ret) { + nv_error(priv, "failed to construct context\n"); + return ret; + } + } + + return 0; } /* load HUB microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nv_wr32(dev, 0x4091c0, 0x01000000); + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nv_wr32(priv, 0x4091c0, 0x01000000); for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) - nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); + nv_wr32(priv, 0x4091c4, nvc0_grhub_data[i]); - nv_wr32(dev, 0x409180, 0x01000000); + nv_wr32(priv, 0x409180, 0x01000000); for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(dev, 0x409188, i >> 6); - nv_wr32(dev, 0x409184, nvc0_grhub_code[i]); + nv_wr32(priv, 0x409188, i >> 6); + nv_wr32(priv, 0x409184, nvc0_grhub_code[i]); } /* load GPC microcode */ - nv_wr32(dev, 0x41a1c0, 0x01000000); + nv_wr32(priv, 0x41a1c0, 0x01000000); for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) - nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); + nv_wr32(priv, 0x41a1c4, nvc0_grgpc_data[i]); - nv_wr32(dev, 0x41a180, 0x01000000); + nv_wr32(priv, 0x41a180, 0x01000000); for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) { if ((i & 0x3f) == 0) - nv_wr32(dev, 0x41a188, i >> 6); - nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]); + nv_wr32(priv, 0x41a188, i >> 6); + nv_wr32(priv, 0x41a184, nvc0_grgpc_code[i]); } - nv_wr32(dev, 0x000260, r000260); + nv_wr32(priv, 0x000260, r000260); /* start HUB ucode running, it'll init the GPCs */ - nv_wr32(dev, 0x409800, dev_priv->chipset); - nv_wr32(dev, 0x40910c, 0x00000000); - nv_wr32(dev, 0x409100, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); - nvc0_graph_ctxctl_debug(dev); + nv_wr32(priv, 0x409800, nv_device(priv)->chipset); + nv_wr32(priv, 0x40910c, 0x00000000); + nv_wr32(priv, 0x409100, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { + nv_error(priv, "HUB_INIT timed out\n"); + nvc0_graph_ctxctl_debug(priv); return -EBUSY; } - priv->size = nv_rd32(dev, 0x409804); -done: + priv->size = nv_rd32(priv, 0x409804); if (priv->data == NULL) { - int ret = nvc0_grctx_generate(dev); + int ret = nvc0_grctx_generate(priv); if (ret) { - NV_ERROR(dev, "PGRAPH: failed to construct context\n"); + nv_error(priv, "failed to construct context\n"); return ret; } @@ -453,37 +715,39 @@ done: } static int -nvc0_graph_init(struct drm_device *dev, int engine) +nvc0_graph_init(struct nouveau_object *object) { + struct nvc0_graph_priv *priv = (void *)object; int ret; reset: - nv_mask(dev, 0x000200, 0x18001000, 0x00000000); - nv_mask(dev, 0x000200, 0x18001000, 0x18001000); - - nvc0_graph_init_obj418880(dev); - nvc0_graph_init_regs(dev); - /*nvc0_graph_init_unitplemented_magics(dev);*/ - nvc0_graph_init_gpc_0(dev); - /*nvc0_graph_init_unitplemented_c242(dev);*/ - - nv_wr32(dev, 0x400500, 0x00010001); - nv_wr32(dev, 0x400100, 0xffffffff); - nv_wr32(dev, 0x40013c, 0xffffffff); - - nvc0_graph_init_units(dev); - nvc0_graph_init_gpc_1(dev); - nvc0_graph_init_rop(dev); - - nv_wr32(dev, 0x400108, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, 0x400118, 0xffffffff); - nv_wr32(dev, 0x400130, 0xffffffff); - nv_wr32(dev, 0x40011c, 0xffffffff); - nv_wr32(dev, 0x400134, 0xffffffff); - nv_wr32(dev, 0x400054, 0x34ce3464); - - ret = nvc0_graph_init_ctxctl(dev); + ret = nouveau_graph_init(&priv->base); + if (ret) + return ret; + + nvc0_graph_init_obj418880(priv); + nvc0_graph_init_regs(priv); + /*nvc0_graph_init_unitplemented_magics(priv);*/ + nvc0_graph_init_gpc_0(priv); + /*nvc0_graph_init_unitplemented_c242(priv);*/ + + nv_wr32(priv, 0x400500, 0x00010001); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); + + nvc0_graph_init_units(priv); + nvc0_graph_init_gpc_1(priv); + nvc0_graph_init_rop(priv); + + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400118, 0xffffffff); + nv_wr32(priv, 0x400130, 0xffffffff); + nv_wr32(priv, 0x40011c, 0xffffffff); + nv_wr32(priv, 0x400134, 0xffffffff); + nv_wr32(priv, 0x400054, 0x34ce3464); + + ret = nvc0_graph_init_ctxctl(priv); if (ret) { if (ret == 1) goto reset; @@ -493,279 +757,13 @@ reset: return 0; } -int -nvc0_graph_isr_chid(struct drm_device *dev, u64 inst) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - unsigned long flags; - int i; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; - - if (inst == chan->ramin->addr) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; -} - -static void -nvc0_graph_ctxctl_isr(struct drm_device *dev) -{ - u32 ustat = nv_rd32(dev, 0x409c18); - - if (ustat & 0x00000001) - NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n"); - if (ustat & 0x00080000) - NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n"); - if (ustat & ~0x00080001) - NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat); - - nvc0_graph_ctxctl_debug(dev); - nv_wr32(dev, 0x409c20, ustat); -} - -static void -nvc0_graph_isr(struct drm_device *dev) -{ - u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; - u32 chid = nvc0_graph_isr_chid(dev, inst); - u32 stat = nv_rd32(dev, 0x400100); - u32 addr = nv_rd32(dev, 0x400704); - u32 mthd = (addr & 0x00003ffc); - u32 subc = (addr & 0x00070000) >> 16; - u32 data = nv_rd32(dev, 0x400708); - u32 code = nv_rd32(dev, 0x400110); - u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); - - if (stat & 0x00000010) { - if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { - NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " - "subc %d class 0x%04x mthd 0x%04x " - "data 0x%08x\n", - chid, inst, subc, class, mthd, data); - } - nv_wr32(dev, 0x400100, 0x00000010); - stat &= ~0x00000010; - } - - if (stat & 0x00000020) { - NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00000020); - stat &= ~0x00000020; - } - - if (stat & 0x00100000) { - NV_INFO(dev, "PGRAPH: DATA_ERROR ["); - nouveau_enum_print(nv50_data_error_names, code); - printk("] ch %d [0x%010llx] subc %d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00100000); - stat &= ~0x00100000; - } - - if (stat & 0x00200000) { - u32 trap = nv_rd32(dev, 0x400108); - NV_INFO(dev, "PGRAPH: TRAP ch %d status 0x%08x\n", chid, trap); - nv_wr32(dev, 0x400108, trap); - nv_wr32(dev, 0x400100, 0x00200000); - stat &= ~0x00200000; - } - - if (stat & 0x00080000) { - nvc0_graph_ctxctl_isr(dev); - nv_wr32(dev, 0x400100, 0x00080000); - stat &= ~0x00080000; - } - - if (stat) { - NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat); - nv_wr32(dev, 0x400100, stat); - } - - nv_wr32(dev, 0x400500, 0x00010001); -} - -static int -nvc0_graph_create_fw(struct drm_device *dev, const char *fwname, - struct nvc0_graph_fuc *fuc) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - const struct firmware *fw; - char f[32]; - int ret; - - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname); - ret = request_firmware(&fw, f, &dev->pdev->dev); - if (ret) { - snprintf(f, sizeof(f), "nouveau/%s", fwname); - ret = request_firmware(&fw, f, &dev->pdev->dev); - if (ret) { - NV_ERROR(dev, "failed to load %s\n", fwname); - return ret; - } - } - - fuc->size = fw->size; - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); - release_firmware(fw); - return (fuc->data != NULL) ? 0 : -ENOMEM; -} - -static void -nvc0_graph_destroy_fw(struct nvc0_graph_fuc *fuc) -{ - if (fuc->data) { - kfree(fuc->data); - fuc->data = NULL; - } -} - -static void -nvc0_graph_destroy(struct drm_device *dev, int engine) -{ - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - - nvc0_graph_destroy_fw(&priv->fuc409c); - nvc0_graph_destroy_fw(&priv->fuc409d); - nvc0_graph_destroy_fw(&priv->fuc41ac); - nvc0_graph_destroy_fw(&priv->fuc41ad); - - nouveau_irq_unregister(dev, 12); - - nouveau_gpuobj_ref(NULL, &priv->unk4188b8); - nouveau_gpuobj_ref(NULL, &priv->unk4188b4); - - if (priv->data) - kfree(priv->data); - - NVOBJ_ENGINE_DEL(dev, GR); - kfree(priv); -} - -int -nvc0_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv; - int ret, gpc, i; - u32 fermi; - - fermi = nvc0_graph_class(dev); - if (!fermi) { - NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); - return 0; - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.destroy = nvc0_graph_destroy; - priv->base.init = nvc0_graph_init; - priv->base.fini = nvc0_graph_fini; - priv->base.context_new = nvc0_graph_context_new; - priv->base.context_del = nvc0_graph_context_del; - priv->base.object_new = nvc0_graph_object_new; - - NVOBJ_ENGINE_ADD(dev, GR, &priv->base); - nouveau_irq_register(dev, 12, nvc0_graph_isr); - - if (nouveau_ctxfw) { - NV_INFO(dev, "PGRAPH: using external firmware\n"); - if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || - nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || - nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || - nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { - ret = 0; - goto error; - } - priv->firmware = true; - } - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); - if (ret) - goto error; - - for (i = 0; i < 0x1000; i += 4) { - nv_wo32(priv->unk4188b4, i, 0x00000010); - nv_wo32(priv->unk4188b8, i, 0x00000010); - } - - priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; - priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - priv->tpc_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); - priv->tpc_total += priv->tpc_nr[gpc]; - } - - /*XXX: these need figuring out... */ - switch (dev_priv->chipset) { - case 0xc0: - if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ - priv->magic_not_rop_nr = 0x07; - } else - if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ - priv->magic_not_rop_nr = 0x05; - } else - if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ - priv->magic_not_rop_nr = 0x06; - } - break; - case 0xc3: /* 450, 4/0/0/0, 2 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xc4: /* 460, 3/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x01; - break; - case 0xc1: /* 2/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; - case 0xc8: /* 4/4/3/4, 5 */ - priv->magic_not_rop_nr = 0x06; - break; - case 0xce: /* 4/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xcf: /* 4/0/0/0, 3 */ - priv->magic_not_rop_nr = 0x03; - break; - case 0xd9: /* 1/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; - } - - if (!priv->magic_not_rop_nr) { - NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", - priv->tpc_nr[0], priv->tpc_nr[1], priv->tpc_nr[2], - priv->tpc_nr[3], priv->rop_nr); - priv->magic_not_rop_nr = 0x00; - } - - NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ - NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ - NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ - if (fermi >= 0x9197) - NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */ - if (fermi >= 0x9297) - NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */ - NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ - return 0; - -error: - nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); - return ret; -} +struct nouveau_oclass +nvc0_graph_oclass = { + .handle = NV_ENGINE(GR, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_graph_ctor, + .dtor = nvc0_graph_dtor, + .init = nvc0_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 30ea3ab135c6..26f8268cc8c2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -25,6 +25,18 @@ #ifndef __NVC0_GRAPH_H__ #define __NVC0_GRAPH_H__ +#include <core/client.h> +#include <core/handle.h> +#include <core/gpuobj.h> +#include <core/option.h> + +#include <subdev/fb.h> +#include <subdev/vm.h> +#include <subdev/bar.h> +#include <subdev/timer.h> + +#include <engine/graph.h> + #define GPC_MAX 4 #define TPC_MAX 32 @@ -53,7 +65,7 @@ struct nvc0_graph_fuc { }; struct nvc0_graph_priv { - struct nouveau_exec_engine base; + struct nouveau_graph base; struct nvc0_graph_fuc fuc409c; struct nvc0_graph_fuc fuc409d; @@ -78,11 +90,10 @@ struct nvc0_graph_priv { }; struct nvc0_graph_chan { - struct nouveau_gpuobj *grctx; - struct nouveau_vma grctx_vma; + struct nouveau_graph_chan base; struct nouveau_gpuobj *mmio; - struct nouveau_vma mmio_vma; + struct nouveau_vma mmio_vma; int mmio_nr; struct { struct nouveau_gpuobj *mem; @@ -91,11 +102,11 @@ struct nvc0_graph_chan { }; static inline u32 -nvc0_graph_class(struct drm_device *priv) +nvc0_graph_class(void *obj) { - struct drm_nouveau_private *dev_priv = priv->dev_private; + struct nouveau_device *device = nv_device(obj); - switch (dev_priv->chipset) { + switch (device->chipset) { case 0xc0: case 0xc3: case 0xc4: @@ -115,17 +126,16 @@ nvc0_graph_class(struct drm_device *priv) } } -void nv_icmd(struct drm_device *priv, u32 icmd, u32 data); +void nv_icmd(struct nvc0_graph_priv *priv, u32 icmd, u32 data); static inline void -nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) +nv_mthd(struct nvc0_graph_priv *priv, u32 class, u32 mthd, u32 data) { nv_wr32(priv, 0x40448c, data); nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); } struct nvc0_grctx { - struct drm_device *dev; struct nvc0_graph_priv *priv; struct nvc0_graph_data *data; struct nvc0_graph_mmio *mmio; @@ -135,18 +145,18 @@ struct nvc0_grctx { u64 addr; }; -int nvc0_grctx_generate(struct drm_device *); -int nvc0_grctx_init(struct drm_device *, struct nvc0_graph_priv *, - struct nvc0_grctx *); +int nvc0_grctx_generate(struct nvc0_graph_priv *); +int nvc0_grctx_init(struct nvc0_graph_priv *, struct nvc0_grctx *); void nvc0_grctx_data(struct nvc0_grctx *, u32, u32, u32); void nvc0_grctx_mmio(struct nvc0_grctx *, u32, u32, u32, u32); int nvc0_grctx_fini(struct nvc0_grctx *); -int nve0_grctx_generate(struct drm_device *); +int nve0_grctx_generate(struct nvc0_graph_priv *); #define mmio_data(s,a,p) nvc0_grctx_data(&info, (s), (a), (p)) #define mmio_list(r,d,s,b) nvc0_grctx_mmio(&info, (r), (d), (s), (b)) +void nvc0_graph_ctxctl_debug(struct nvc0_graph_priv *); int nvc0_graph_ctor_fw(struct nvc0_graph_priv *, const char *, struct nvc0_graph_fuc *); void nvc0_graph_dtor(struct nouveau_object *); @@ -157,9 +167,4 @@ int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *, struct nouveau_object **); void nvc0_graph_context_dtor(struct nouveau_object *); -void nvc0_graph_ctxctl_debug(struct drm_device *); - -int nvc0_graph_context_new(struct nouveau_channel *, int); -void nvc0_graph_context_del(struct nouveau_channel *, int); - #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index a3a4ee7c0b2e..c79748a6fa2b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -1,5 +1,5 @@ /* - * Copyright 2010 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,116 +22,290 @@ * Authors: Ben Skeggs */ -#include <linux/firmware.h> -#include <linux/module.h> - -#include "drmP.h" - -#include "nouveau_drv.h" -#include <core/mm.h> -#include <engine/fifo.h> - #include "nvc0.h" +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nve0_graph_sclass[] = { + { 0x902d, &nouveau_object_ofuncs }, + { 0xa040, &nouveau_object_ofuncs }, + { 0xa097, &nouveau_object_ofuncs }, + { 0xa0c0, &nouveau_object_ofuncs }, + { 0xa0b5, &nouveau_object_ofuncs }, + {} +}; + +/******************************************************************************* + * PGRAPH context + ******************************************************************************/ + +static struct nouveau_oclass +nve0_graph_cclass = { + .handle = NV_ENGCTX(GR, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_graph_context_ctor, + .dtor = nvc0_graph_context_dtor, + .init = _nouveau_graph_context_init, + .fini = _nouveau_graph_context_fini, + .rd32 = _nouveau_graph_context_rd32, + .wr32 = _nouveau_graph_context_wr32, + }, +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + static void -nve0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) +nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) { - NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base, - nv_rd32(dev, base + 0x400)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804), - nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c)); - NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, - nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814), - nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); + u32 ustat = nv_rd32(priv, 0x409c18); + + if (ustat & 0x00000001) + nv_error(priv, "CTXCTRL ucode error\n"); + if (ustat & 0x00080000) + nv_error(priv, "CTXCTRL watchdog timeout\n"); + if (ustat & ~0x00080001) + nv_error(priv, "CTXCTRL 0x%08x\n", ustat); + + nvc0_graph_ctxctl_debug(priv); + nv_wr32(priv, 0x409c20, ustat); } static void -nve0_graph_ctxctl_debug(struct drm_device *dev) +nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) { - u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; - u32 gpc; + u32 trap = nv_rd32(priv, 0x400108); + int rop; + + if (trap & 0x00000001) { + u32 stat = nv_rd32(priv, 0x404000); + nv_error(priv, "DISPATCH ch 0x%010llx 0x%08x\n", inst, stat); + nv_wr32(priv, 0x404000, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000001); + trap &= ~0x00000001; + } - nve0_graph_ctxctl_debug_unit(dev, 0x409000); - for (gpc = 0; gpc < gpcnr; gpc++) - nve0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); + if (trap & 0x00000010) { + u32 stat = nv_rd32(priv, 0x405840); + nv_error(priv, "SHADER ch 0x%010llx 0x%08x\n", inst, stat); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000010); + trap &= ~0x00000010; + } + + if (trap & 0x02000000) { + for (rop = 0; rop < priv->rop_nr; rop++) { + u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); + u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); + nv_error(priv, "ROP%d ch 0x%010llx 0x%08x 0x%08x\n", + rop, inst, statz, statc); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + } + nv_wr32(priv, 0x400108, 0x02000000); + trap &= ~0x02000000; + } + + if (trap) { + nv_error(priv, "TRAP ch 0x%010llx 0x%08x\n", inst, trap); + nv_wr32(priv, 0x400108, trap); + } } -static int -nve0_graph_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +static void +nve0_graph_intr(struct nouveau_subdev *subdev) { - return 0; + struct nvc0_graph_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; + u32 stat = nv_rd32(priv, 0x400100); + u32 addr = nv_rd32(priv, 0x400704); + u32 mthd = (addr & 0x00003ffc); + u32 subc = (addr & 0x00070000) >> 16; + u32 data = nv_rd32(priv, 0x400708); + u32 code = nv_rd32(priv, 0x400110); + u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + + if (stat & 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, class); + if (!handle || nv_call(handle->object, mthd, data)) { + nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x\n", + inst, subc, class, mthd, data); + } + nouveau_engctx_handle_put(handle); + nv_wr32(priv, 0x400100, 0x00000010); + stat &= ~0x00000010; + } + + if (stat & 0x00000020) { + nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00000020); + stat &= ~0x00000020; + } + + if (stat & 0x00100000) { + nv_error(priv, "DATA_ERROR ["); + nouveau_enum_print(nv50_data_error_names, code); + printk("] ch 0x%010llx subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + inst, subc, class, mthd, data); + nv_wr32(priv, 0x400100, 0x00100000); + stat &= ~0x00100000; + } + + if (stat & 0x00200000) { + nve0_graph_trap_isr(priv, inst); + nv_wr32(priv, 0x400100, 0x00200000); + stat &= ~0x00200000; + } + + if (stat & 0x00080000) { + nve0_graph_ctxctl_isr(priv); + nv_wr32(priv, 0x400100, 0x00080000); + stat &= ~0x00080000; + } + + if (stat) { + nv_error(priv, "unknown stat 0x%08x\n", stat); + nv_wr32(priv, 0x400100, stat); + } + + nv_wr32(priv, 0x400500, 0x00010001); } static int -nve0_graph_fini(struct drm_device *dev, int engine, bool suspend) +nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nvc0_graph_priv *priv; + int ret, i; + + ret = nouveau_graph_create(parent, engine, oclass, false, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x18001000; + nv_subdev(priv)->intr = nve0_graph_intr; + nv_engine(priv)->cclass = &nve0_graph_cclass; + nv_engine(priv)->sclass = nve0_graph_sclass; + + nv_info(priv, "using external firmware\n"); + if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || + nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || + nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || + nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) + return -EINVAL; + priv->firmware = true; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); + if (ret) + return ret; + + for (i = 0; i < 0x1000; i += 4) { + nv_wo32(priv->unk4188b4, i, 0x00000010); + nv_wo32(priv->unk4188b8, i, 0x00000010); + } + + priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; + priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; + for (i = 0; i < priv->gpc_nr; i++) { + priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); + priv->tpc_total += priv->tpc_nr[i]; + } + + switch (nv_device(priv)->chipset) { + case 0xe4: + if (priv->tpc_total == 8) + priv->magic_not_rop_nr = 3; + else + if (priv->tpc_total == 7) + priv->magic_not_rop_nr = 1; + break; + case 0xe7: + priv->magic_not_rop_nr = 1; + break; + default: + break; + } + return 0; } static void -nve0_graph_init_obj418880(struct drm_device *dev) +nve0_graph_init_obj418880(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; - nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); for (i = 0; i < 4; i++) - nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); - nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000); + nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void -nve0_graph_init_regs(struct drm_device *dev) +nve0_graph_init_regs(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x400080, 0x003083c2); - nv_wr32(dev, 0x400088, 0x0001ffe7); - nv_wr32(dev, 0x40008c, 0x00000000); - nv_wr32(dev, 0x400090, 0x00000030); - nv_wr32(dev, 0x40013c, 0x003901f7); - nv_wr32(dev, 0x400140, 0x00000100); - nv_wr32(dev, 0x400144, 0x00000000); - nv_wr32(dev, 0x400148, 0x00000110); - nv_wr32(dev, 0x400138, 0x00000000); - nv_wr32(dev, 0x400130, 0x00000000); - nv_wr32(dev, 0x400134, 0x00000000); - nv_wr32(dev, 0x400124, 0x00000002); + nv_wr32(priv, 0x400080, 0x003083c2); + nv_wr32(priv, 0x400088, 0x0001ffe7); + nv_wr32(priv, 0x40008c, 0x00000000); + nv_wr32(priv, 0x400090, 0x00000030); + nv_wr32(priv, 0x40013c, 0x003901f7); + nv_wr32(priv, 0x400140, 0x00000100); + nv_wr32(priv, 0x400144, 0x00000000); + nv_wr32(priv, 0x400148, 0x00000110); + nv_wr32(priv, 0x400138, 0x00000000); + nv_wr32(priv, 0x400130, 0x00000000); + nv_wr32(priv, 0x400134, 0x00000000); + nv_wr32(priv, 0x400124, 0x00000002); } static void -nve0_graph_init_units(struct drm_device *dev) +nve0_graph_init_units(struct nvc0_graph_priv *priv) { - nv_wr32(dev, 0x409ffc, 0x00000000); - nv_wr32(dev, 0x409c14, 0x00003e3e); - nv_wr32(dev, 0x409c24, 0x000f0000); - - nv_wr32(dev, 0x404000, 0xc0000000); - nv_wr32(dev, 0x404600, 0xc0000000); - nv_wr32(dev, 0x408030, 0xc0000000); - nv_wr32(dev, 0x404490, 0xc0000000); - nv_wr32(dev, 0x406018, 0xc0000000); - nv_wr32(dev, 0x407020, 0xc0000000); - nv_wr32(dev, 0x405840, 0xc0000000); - nv_wr32(dev, 0x405844, 0x00ffffff); - - nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008); - nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000); + nv_wr32(priv, 0x409ffc, 0x00000000); + nv_wr32(priv, 0x409c14, 0x00003e3e); + nv_wr32(priv, 0x409c24, 0x000f0000); + + nv_wr32(priv, 0x404000, 0xc0000000); + nv_wr32(priv, 0x404600, 0xc0000000); + nv_wr32(priv, 0x408030, 0xc0000000); + nv_wr32(priv, 0x404490, 0xc0000000); + nv_wr32(priv, 0x406018, 0xc0000000); + nv_wr32(priv, 0x407020, 0xc0000000); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x405844, 0x00ffffff); + + nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); + nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); } static void -nve0_graph_init_gpc_0(struct drm_device *dev) +nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); u32 data[TPC_MAX / 8]; u8 tpcnr[GPC_MAX]; int i, gpc, tpc; - nv_wr32(dev, GPC_UNIT(0, 0x3018), 0x00000001); + nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); memset(data, 0x00, sizeof(data)); memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); @@ -144,164 +318,143 @@ nve0_graph_init_gpc_0(struct drm_device *dev) data[i / 8] |= tpc << ((i % 8) * 4); } - nv_wr32(dev, GPC_BCAST(0x0980), data[0]); - nv_wr32(dev, GPC_BCAST(0x0984), data[1]); - nv_wr32(dev, GPC_BCAST(0x0988), data[2]); - nv_wr32(dev, GPC_BCAST(0x098c), data[3]); + nv_wr32(priv, GPC_BCAST(0x0980), data[0]); + nv_wr32(priv, GPC_BCAST(0x0984), data[1]); + nv_wr32(priv, GPC_BCAST(0x0988), data[2]); + nv_wr32(priv, GPC_BCAST(0x098c), data[3]); for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | + nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); - nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); + nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); + nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); } - nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); - nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); + nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); } static void -nve0_graph_init_gpc_1(struct drm_device *dev) +nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc, tpc; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - nv_wr32(dev, GPC_UNIT(gpc, 0x3038), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000); - nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); } - nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); - nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); } } static void -nve0_graph_init_rop(struct drm_device *dev) +nve0_graph_init_rop(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { - nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff); - nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff); - } -} - -static void -nve0_graph_init_fuc(struct drm_device *dev, u32 fuc_base, - struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) -{ - int i; - - nv_wr32(dev, fuc_base + 0x01c0, 0x01000000); - for (i = 0; i < data->size / 4; i++) - nv_wr32(dev, fuc_base + 0x01c4, data->data[i]); - - nv_wr32(dev, fuc_base + 0x0180, 0x01000000); - for (i = 0; i < code->size / 4; i++) { - if ((i & 0x3f) == 0) - nv_wr32(dev, fuc_base + 0x0188, i >> 6); - nv_wr32(dev, fuc_base + 0x0184, code->data[i]); + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); + nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); } } static int -nve0_graph_init_ctxctl(struct drm_device *dev) +nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv) { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; /* load fuc microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nve0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d); - nve0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); - nv_wr32(dev, 0x000260, r000260); + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d); + nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); + nv_wr32(priv, 0x000260, r000260); /* start both of them running */ - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x41a10c, 0x00000000); - nv_wr32(dev, 0x40910c, 0x00000000); - nv_wr32(dev, 0x41a100, 0x00000002); - nv_wr32(dev, 0x409100, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) - NV_INFO(dev, "0x409800 wait failed\n"); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x7fffffff); - nv_wr32(dev, 0x409504, 0x00000021); - - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000010); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x41a10c, 0x00000000); + nv_wr32(priv, 0x40910c, 0x00000000); + nv_wr32(priv, 0x41a100, 0x00000002); + nv_wr32(priv, 0x409100, 0x00000002); + if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) + nv_error(priv, "0x409800 wait failed\n"); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x7fffffff); + nv_wr32(priv, 0x409504, 0x00000021); + + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000010); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x10 timeout\n"); return -EBUSY; } - priv->size = nv_rd32(dev, 0x409800); + priv->size = nv_rd32(priv, 0x409800); - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000016); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000016); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x16 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x409500, 0x00000000); - nv_wr32(dev, 0x409504, 0x00000025); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); + nv_wr32(priv, 0x409840, 0xffffffff); + nv_wr32(priv, 0x409500, 0x00000000); + nv_wr32(priv, 0x409504, 0x00000025); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x25 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409800, 0x00000000); - nv_wr32(dev, 0x409500, 0x00000001); - nv_wr32(dev, 0x409504, 0x00000030); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x30 timeout\n"); + nv_wr32(priv, 0x409800, 0x00000000); + nv_wr32(priv, 0x409500, 0x00000001); + nv_wr32(priv, 0x409504, 0x00000030); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x30 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409810, 0xb00095c8); - nv_wr32(dev, 0x409800, 0x00000000); - nv_wr32(dev, 0x409500, 0x00000001); - nv_wr32(dev, 0x409504, 0x00000031); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x31 timeout\n"); + nv_wr32(priv, 0x409810, 0xb00095c8); + nv_wr32(priv, 0x409800, 0x00000000); + nv_wr32(priv, 0x409500, 0x00000001); + nv_wr32(priv, 0x409504, 0x00000031); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x31 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409810, 0x00080420); - nv_wr32(dev, 0x409800, 0x00000000); - nv_wr32(dev, 0x409500, 0x00000001); - nv_wr32(dev, 0x409504, 0x00000032); - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { - NV_ERROR(dev, "fuc09 req 0x32 timeout\n"); + nv_wr32(priv, 0x409810, 0x00080420); + nv_wr32(priv, 0x409800, 0x00000000); + nv_wr32(priv, 0x409500, 0x00000001); + nv_wr32(priv, 0x409504, 0x00000032); + if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { + nv_error(priv, "fuc09 req 0x32 timeout\n"); return -EBUSY; } - nv_wr32(dev, 0x409614, 0x00000070); - nv_wr32(dev, 0x409614, 0x00000770); - nv_wr32(dev, 0x40802c, 0x00000001); + nv_wr32(priv, 0x409614, 0x00000070); + nv_wr32(priv, 0x409614, 0x00000770); + nv_wr32(priv, 0x40802c, 0x00000001); if (priv->data == NULL) { - int ret = nve0_grctx_generate(dev); + int ret = nve0_grctx_generate(priv); if (ret) { - NV_ERROR(dev, "PGRAPH: failed to construct context\n"); + nv_error(priv, "failed to construct context\n"); return ret; } @@ -312,325 +465,53 @@ nve0_graph_init_ctxctl(struct drm_device *dev) } static int -nve0_graph_init(struct drm_device *dev, int engine) +nve0_graph_init(struct nouveau_object *object) { + struct nvc0_graph_priv *priv = (void *)object; int ret; reset: - nv_mask(dev, 0x000200, 0x18001000, 0x00000000); - nv_mask(dev, 0x000200, 0x18001000, 0x18001000); - - nve0_graph_init_obj418880(dev); - nve0_graph_init_regs(dev); - nve0_graph_init_gpc_0(dev); - - nv_wr32(dev, 0x400500, 0x00010001); - nv_wr32(dev, 0x400100, 0xffffffff); - nv_wr32(dev, 0x40013c, 0xffffffff); - - nve0_graph_init_units(dev); - nve0_graph_init_gpc_1(dev); - nve0_graph_init_rop(dev); - - nv_wr32(dev, 0x400108, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, 0x400118, 0xffffffff); - nv_wr32(dev, 0x400130, 0xffffffff); - nv_wr32(dev, 0x40011c, 0xffffffff); - nv_wr32(dev, 0x400134, 0xffffffff); - nv_wr32(dev, 0x400054, 0x34ce3464); - - ret = nve0_graph_init_ctxctl(dev); - if (ret) { - if (ret == 1) - goto reset; - return ret; - } - - return 0; -} - -int -nve0_graph_isr_chid(struct drm_device *dev, u64 inst) -{ - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - unsigned long flags; - int i; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->ramin) - continue; - - if (inst == chan->ramin->addr) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; -} - -static void -nve0_graph_ctxctl_isr(struct drm_device *dev) -{ - u32 ustat = nv_rd32(dev, 0x409c18); - - if (ustat & 0x00000001) - NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n"); - if (ustat & 0x00080000) - NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n"); - if (ustat & ~0x00080001) - NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat); - - nve0_graph_ctxctl_debug(dev); - nv_wr32(dev, 0x409c20, ustat); -} - -static void -nve0_graph_trap_isr(struct drm_device *dev, int chid) -{ - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); - u32 trap = nv_rd32(dev, 0x400108); - int rop; - - if (trap & 0x00000001) { - u32 stat = nv_rd32(dev, 0x404000); - NV_INFO(dev, "PGRAPH: DISPATCH ch %d 0x%08x\n", chid, stat); - nv_wr32(dev, 0x404000, 0xc0000000); - nv_wr32(dev, 0x400108, 0x00000001); - trap &= ~0x00000001; - } - - if (trap & 0x00000010) { - u32 stat = nv_rd32(dev, 0x405840); - NV_INFO(dev, "PGRAPH: SHADER ch %d 0x%08x\n", chid, stat); - nv_wr32(dev, 0x405840, 0xc0000000); - nv_wr32(dev, 0x400108, 0x00000010); - trap &= ~0x00000010; - } - - if (trap & 0x02000000) { - for (rop = 0; rop < priv->rop_nr; rop++) { - u32 statz = nv_rd32(dev, ROP_UNIT(rop, 0x070)); - u32 statc = nv_rd32(dev, ROP_UNIT(rop, 0x144)); - NV_INFO(dev, "PGRAPH: ROP%d ch %d 0x%08x 0x%08x\n", - rop, chid, statz, statc); - nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); - nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); - } - nv_wr32(dev, 0x400108, 0x02000000); - trap &= ~0x02000000; - } - - if (trap) { - NV_INFO(dev, "PGRAPH: TRAP ch %d 0x%08x\n", chid, trap); - nv_wr32(dev, 0x400108, trap); - } -} - -static void -nve0_graph_isr(struct drm_device *dev) -{ - u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; - u32 chid = nve0_graph_isr_chid(dev, inst); - u32 stat = nv_rd32(dev, 0x400100); - u32 addr = nv_rd32(dev, 0x400704); - u32 mthd = (addr & 0x00003ffc); - u32 subc = (addr & 0x00070000) >> 16; - u32 data = nv_rd32(dev, 0x400708); - u32 code = nv_rd32(dev, 0x400110); - u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); - - if (stat & 0x00000010) { - if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { - NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " - "subc %d class 0x%04x mthd 0x%04x " - "data 0x%08x\n", - chid, inst, subc, class, mthd, data); - } - nv_wr32(dev, 0x400100, 0x00000010); - stat &= ~0x00000010; - } - - if (stat & 0x00000020) { - NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00000020); - stat &= ~0x00000020; - } - - if (stat & 0x00100000) { - NV_INFO(dev, "PGRAPH: DATA_ERROR ["); - nouveau_enum_print(nv50_data_error_names, code); - printk("] ch %d [0x%010llx] subc %d class 0x%04x " - "mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); - nv_wr32(dev, 0x400100, 0x00100000); - stat &= ~0x00100000; - } - - if (stat & 0x00200000) { - nve0_graph_trap_isr(dev, chid); - nv_wr32(dev, 0x400100, 0x00200000); - stat &= ~0x00200000; - } - - if (stat & 0x00080000) { - nve0_graph_ctxctl_isr(dev); - nv_wr32(dev, 0x400100, 0x00080000); - stat &= ~0x00080000; - } - - if (stat) { - NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat); - nv_wr32(dev, 0x400100, stat); - } - - nv_wr32(dev, 0x400500, 0x00010001); -} - -static int -nve0_graph_create_fw(struct drm_device *dev, const char *fwname, - struct nvc0_graph_fuc *fuc) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - const struct firmware *fw; - char f[32]; - int ret; - - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname); - ret = request_firmware(&fw, f, &dev->pdev->dev); + ret = nouveau_graph_init(&priv->base); if (ret) return ret; - fuc->size = fw->size; - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); - release_firmware(fw); - return (fuc->data != NULL) ? 0 : -ENOMEM; -} - -static void -nve0_graph_destroy_fw(struct nvc0_graph_fuc *fuc) -{ - if (fuc->data) { - kfree(fuc->data); - fuc->data = NULL; - } -} - -static void -nve0_graph_destroy(struct drm_device *dev, int engine) -{ - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - - nve0_graph_destroy_fw(&priv->fuc409c); - nve0_graph_destroy_fw(&priv->fuc409d); - nve0_graph_destroy_fw(&priv->fuc41ac); - nve0_graph_destroy_fw(&priv->fuc41ad); - - nouveau_irq_unregister(dev, 12); - - nouveau_gpuobj_ref(NULL, &priv->unk4188b8); - nouveau_gpuobj_ref(NULL, &priv->unk4188b4); - - if (priv->data) - kfree(priv->data); - - NVOBJ_ENGINE_DEL(dev, GR); - kfree(priv); -} - -int -nve0_graph_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv; - int ret, gpc, i; - u32 kepler; - - kepler = nvc0_graph_class(dev); - if (!kepler) { - NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); - return 0; - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.destroy = nve0_graph_destroy; - priv->base.init = nve0_graph_init; - priv->base.fini = nve0_graph_fini; - priv->base.context_new = nvc0_graph_context_new; - priv->base.context_del = nvc0_graph_context_del; - priv->base.object_new = nve0_graph_object_new; - - NVOBJ_ENGINE_ADD(dev, GR, &priv->base); - nouveau_irq_register(dev, 12, nve0_graph_isr); - - NV_INFO(dev, "PGRAPH: using external firmware\n"); - if (nve0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || - nve0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || - nve0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || - nve0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { - ret = 0; - goto error; - } - priv->firmware = true; - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); - if (ret) - goto error; + nve0_graph_init_obj418880(priv); + nve0_graph_init_regs(priv); + nve0_graph_init_gpc_0(priv); - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); - if (ret) - goto error; + nv_wr32(priv, 0x400500, 0x00010001); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); - for (i = 0; i < 0x1000; i += 4) { - nv_wo32(priv->unk4188b4, i, 0x00000010); - nv_wo32(priv->unk4188b8, i, 0x00000010); - } + nve0_graph_init_units(priv); + nve0_graph_init_gpc_1(priv); + nve0_graph_init_rop(priv); - priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; - priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - priv->tpc_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); - priv->tpc_total += priv->tpc_nr[gpc]; - } - - switch (dev_priv->chipset) { - case 0xe4: - if (priv->tpc_total == 8) - priv->magic_not_rop_nr = 3; - else - if (priv->tpc_total == 7) - priv->magic_not_rop_nr = 1; - break; - case 0xe7: - priv->magic_not_rop_nr = 1; - break; - default: - break; - } + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400118, 0xffffffff); + nv_wr32(priv, 0x400130, 0xffffffff); + nv_wr32(priv, 0x40011c, 0xffffffff); + nv_wr32(priv, 0x400134, 0xffffffff); + nv_wr32(priv, 0x400054, 0x34ce3464); - if (!priv->magic_not_rop_nr) { - NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", - priv->tpc_nr[0], priv->tpc_nr[1], priv->tpc_nr[2], - priv->tpc_nr[3], priv->rop_nr); - priv->magic_not_rop_nr = 0x00; + ret = nve0_graph_init_ctxctl(priv); + if (ret) { + if (ret == 1) + goto reset; + return ret; } - NVOBJ_CLASS(dev, 0xa097, GR); /* subc 0: 3D */ - NVOBJ_CLASS(dev, 0xa0c0, GR); /* subc 1: COMPUTE */ - NVOBJ_CLASS(dev, 0xa040, GR); /* subc 2: P2MF */ - NVOBJ_CLASS(dev, 0x902d, GR); /* subc 3: 2D */ - NVOBJ_CLASS(dev, 0xa0b5, GR); /* subc 4: COPY */ return 0; - -error: - nve0_graph_destroy(dev, NVOBJ_ENGINE_GR); - return ret; } + +struct nouveau_oclass +nve0_graph_oclass = { + .handle = NV_ENGINE(GR, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_graph_ctor, + .dtor = nvc0_graph_dtor, + .init = nve0_graph_init, + .fini = _nouveau_graph_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/regs.h b/drivers/gpu/drm/nouveau/core/engine/graph/regs.h new file mode 100644 index 000000000000..9c715a25cecb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/regs.h @@ -0,0 +1,269 @@ +#ifndef __NOUVEAU_GRAPH_REGS_H__ +#define __NOUVEAU_GRAPH_REGS_H__ + +#define NV04_PGRAPH_DEBUG_0 0x00400080 +#define NV04_PGRAPH_DEBUG_1 0x00400084 +#define NV04_PGRAPH_DEBUG_2 0x00400088 +#define NV04_PGRAPH_DEBUG_3 0x0040008c +#define NV10_PGRAPH_DEBUG_4 0x00400090 +#define NV03_PGRAPH_INTR 0x00400100 +#define NV03_PGRAPH_NSTATUS 0x00400104 +# define NV04_PGRAPH_NSTATUS_STATE_IN_USE (1<<11) +# define NV04_PGRAPH_NSTATUS_INVALID_STATE (1<<12) +# define NV04_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<13) +# define NV04_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<14) +# define NV10_PGRAPH_NSTATUS_STATE_IN_USE (1<<23) +# define NV10_PGRAPH_NSTATUS_INVALID_STATE (1<<24) +# define NV10_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<25) +# define NV10_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<26) +#define NV03_PGRAPH_NSOURCE 0x00400108 +# define NV03_PGRAPH_NSOURCE_NOTIFICATION (1<<0) +# define NV03_PGRAPH_NSOURCE_DATA_ERROR (1<<1) +# define NV03_PGRAPH_NSOURCE_PROTECTION_ERROR (1<<2) +# define NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION (1<<3) +# define NV03_PGRAPH_NSOURCE_LIMIT_COLOR (1<<4) +# define NV03_PGRAPH_NSOURCE_LIMIT_ZETA (1<<5) +# define NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD (1<<6) +# define NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION (1<<7) +# define NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION (1<<8) +# define NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION (1<<9) +# define NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION (1<<10) +# define NV03_PGRAPH_NSOURCE_STATE_INVALID (1<<11) +# define NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY (1<<12) +# define NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE (1<<13) +# define NV03_PGRAPH_NSOURCE_METHOD_CNT (1<<14) +# define NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION (1<<15) +# define NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION (1<<16) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_A (1<<17) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_B (1<<18) +#define NV03_PGRAPH_INTR_EN 0x00400140 +#define NV40_PGRAPH_INTR_EN 0x0040013C +# define NV_PGRAPH_INTR_NOTIFY (1<<0) +# define NV_PGRAPH_INTR_MISSING_HW (1<<4) +# define NV_PGRAPH_INTR_CONTEXT_SWITCH (1<<12) +# define NV_PGRAPH_INTR_BUFFER_NOTIFY (1<<16) +# define NV_PGRAPH_INTR_ERROR (1<<20) +#define NV10_PGRAPH_CTX_CONTROL 0x00400144 +#define NV10_PGRAPH_CTX_USER 0x00400148 +#define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) +#define NV04_PGRAPH_CTX_SWITCH1 0x00400160 +#define NV10_PGRAPH_CTX_CACHE(i, j) (0x00400160 \ + + 0x4*(i) + 0x20*(j)) +#define NV04_PGRAPH_CTX_SWITCH2 0x00400164 +#define NV04_PGRAPH_CTX_SWITCH3 0x00400168 +#define NV04_PGRAPH_CTX_SWITCH4 0x0040016C +#define NV04_PGRAPH_CTX_CONTROL 0x00400170 +#define NV04_PGRAPH_CTX_USER 0x00400174 +#define NV04_PGRAPH_CTX_CACHE1 0x00400180 +#define NV03_PGRAPH_CTX_CONTROL 0x00400190 +#define NV03_PGRAPH_CTX_USER 0x00400194 +#define NV04_PGRAPH_CTX_CACHE2 0x004001A0 +#define NV04_PGRAPH_CTX_CACHE3 0x004001C0 +#define NV04_PGRAPH_CTX_CACHE4 0x004001E0 +#define NV40_PGRAPH_CTXCTL_0304 0x00400304 +#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_MASK 0xff000000 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT 24 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK 0x00ffffff +#define NV40_PGRAPH_CTXCTL_0310 0x00400310 +#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE 0x00000020 +#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD 0x00000040 +#define NV40_PGRAPH_CTXCTL_030C 0x0040030c +#define NV40_PGRAPH_CTXCTL_UCODE_INDEX 0x00400324 +#define NV40_PGRAPH_CTXCTL_UCODE_DATA 0x00400328 +#define NV40_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV40_PGRAPH_CTXCTL_CUR_LOADED 0x01000000 +#define NV40_PGRAPH_CTXCTL_CUR_INSTANCE 0x000FFFFF +#define NV40_PGRAPH_CTXCTL_NEXT 0x00400330 +#define NV40_PGRAPH_CTXCTL_NEXT_INSTANCE 0x000fffff +#define NV50_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV50_PGRAPH_CTXCTL_CUR_LOADED 0x80000000 +#define NV50_PGRAPH_CTXCTL_CUR_INSTANCE 0x00ffffff +#define NV50_PGRAPH_CTXCTL_NEXT 0x00400330 +#define NV50_PGRAPH_CTXCTL_NEXT_INSTANCE 0x00ffffff +#define NV03_PGRAPH_ABS_X_RAM 0x00400400 +#define NV03_PGRAPH_ABS_Y_RAM 0x00400480 +#define NV03_PGRAPH_X_MISC 0x00400500 +#define NV03_PGRAPH_Y_MISC 0x00400504 +#define NV04_PGRAPH_VALID1 0x00400508 +#define NV04_PGRAPH_SOURCE_COLOR 0x0040050C +#define NV04_PGRAPH_MISC24_0 0x00400510 +#define NV03_PGRAPH_XY_LOGIC_MISC0 0x00400514 +#define NV03_PGRAPH_XY_LOGIC_MISC1 0x00400518 +#define NV03_PGRAPH_XY_LOGIC_MISC2 0x0040051C +#define NV03_PGRAPH_XY_LOGIC_MISC3 0x00400520 +#define NV03_PGRAPH_CLIPX_0 0x00400524 +#define NV03_PGRAPH_CLIPX_1 0x00400528 +#define NV03_PGRAPH_CLIPY_0 0x0040052C +#define NV03_PGRAPH_CLIPY_1 0x00400530 +#define NV03_PGRAPH_ABS_ICLIP_XMAX 0x00400534 +#define NV03_PGRAPH_ABS_ICLIP_YMAX 0x00400538 +#define NV03_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV03_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV03_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV03_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV03_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 +#define NV03_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 +#define NV03_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 +#define NV03_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C +#define NV04_PGRAPH_MISC24_1 0x00400570 +#define NV04_PGRAPH_MISC24_2 0x00400574 +#define NV04_PGRAPH_VALID2 0x00400578 +#define NV04_PGRAPH_PASSTHRU_0 0x0040057C +#define NV04_PGRAPH_PASSTHRU_1 0x00400580 +#define NV04_PGRAPH_PASSTHRU_2 0x00400584 +#define NV10_PGRAPH_DIMX_TEXTURE 0x00400588 +#define NV10_PGRAPH_WDIMX_TEXTURE 0x0040058C +#define NV04_PGRAPH_COMBINE_0_ALPHA 0x00400590 +#define NV04_PGRAPH_COMBINE_0_COLOR 0x00400594 +#define NV04_PGRAPH_COMBINE_1_ALPHA 0x00400598 +#define NV04_PGRAPH_COMBINE_1_COLOR 0x0040059C +#define NV04_PGRAPH_FORMAT_0 0x004005A8 +#define NV04_PGRAPH_FORMAT_1 0x004005AC +#define NV04_PGRAPH_FILTER_0 0x004005B0 +#define NV04_PGRAPH_FILTER_1 0x004005B4 +#define NV03_PGRAPH_MONO_COLOR0 0x00400600 +#define NV04_PGRAPH_ROP3 0x00400604 +#define NV04_PGRAPH_BETA_AND 0x00400608 +#define NV04_PGRAPH_BETA_PREMULT 0x0040060C +#define NV04_PGRAPH_LIMIT_VIOL_PIX 0x00400610 +#define NV04_PGRAPH_FORMATS 0x00400618 +#define NV10_PGRAPH_DEBUG_2 0x00400620 +#define NV04_PGRAPH_BOFFSET0 0x00400640 +#define NV04_PGRAPH_BOFFSET1 0x00400644 +#define NV04_PGRAPH_BOFFSET2 0x00400648 +#define NV04_PGRAPH_BOFFSET3 0x0040064C +#define NV04_PGRAPH_BOFFSET4 0x00400650 +#define NV04_PGRAPH_BOFFSET5 0x00400654 +#define NV04_PGRAPH_BBASE0 0x00400658 +#define NV04_PGRAPH_BBASE1 0x0040065C +#define NV04_PGRAPH_BBASE2 0x00400660 +#define NV04_PGRAPH_BBASE3 0x00400664 +#define NV04_PGRAPH_BBASE4 0x00400668 +#define NV04_PGRAPH_BBASE5 0x0040066C +#define NV04_PGRAPH_BPITCH0 0x00400670 +#define NV04_PGRAPH_BPITCH1 0x00400674 +#define NV04_PGRAPH_BPITCH2 0x00400678 +#define NV04_PGRAPH_BPITCH3 0x0040067C +#define NV04_PGRAPH_BPITCH4 0x00400680 +#define NV04_PGRAPH_BLIMIT0 0x00400684 +#define NV04_PGRAPH_BLIMIT1 0x00400688 +#define NV04_PGRAPH_BLIMIT2 0x0040068C +#define NV04_PGRAPH_BLIMIT3 0x00400690 +#define NV04_PGRAPH_BLIMIT4 0x00400694 +#define NV04_PGRAPH_BLIMIT5 0x00400698 +#define NV04_PGRAPH_BSWIZZLE2 0x0040069C +#define NV04_PGRAPH_BSWIZZLE5 0x004006A0 +#define NV03_PGRAPH_STATUS 0x004006B0 +#define NV04_PGRAPH_STATUS 0x00400700 +# define NV40_PGRAPH_STATUS_SYNC_STALL 0x00004000 +#define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 +#define NV04_PGRAPH_TRAPPED_DATA 0x00400708 +#define NV04_PGRAPH_SURFACE 0x0040070C +#define NV10_PGRAPH_TRAPPED_DATA_HIGH 0x0040070C +#define NV04_PGRAPH_STATE 0x00400710 +#define NV10_PGRAPH_SURFACE 0x00400710 +#define NV04_PGRAPH_NOTIFY 0x00400714 +#define NV10_PGRAPH_STATE 0x00400714 +#define NV10_PGRAPH_NOTIFY 0x00400718 + +#define NV04_PGRAPH_FIFO 0x00400720 + +#define NV04_PGRAPH_BPIXEL 0x00400724 +#define NV10_PGRAPH_RDI_INDEX 0x00400750 +#define NV04_PGRAPH_FFINTFC_ST2 0x00400754 +#define NV10_PGRAPH_RDI_DATA 0x00400754 +#define NV04_PGRAPH_DMA_PITCH 0x00400760 +#define NV10_PGRAPH_FFINTFC_FIFO_PTR 0x00400760 +#define NV04_PGRAPH_DVD_COLORFMT 0x00400764 +#define NV10_PGRAPH_FFINTFC_ST2 0x00400764 +#define NV04_PGRAPH_SCALED_FORMAT 0x00400768 +#define NV10_PGRAPH_FFINTFC_ST2_DL 0x00400768 +#define NV10_PGRAPH_FFINTFC_ST2_DH 0x0040076c +#define NV10_PGRAPH_DMA_PITCH 0x00400770 +#define NV10_PGRAPH_DVD_COLORFMT 0x00400774 +#define NV10_PGRAPH_SCALED_FORMAT 0x00400778 +#define NV20_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV20_PGRAPH_CHANNEL_CTX_POINTER 0x00400784 +#define NV20_PGRAPH_CHANNEL_CTX_XFER 0x00400788 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD 0x00000001 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE 0x00000002 +#define NV04_PGRAPH_PATT_COLOR0 0x00400800 +#define NV04_PGRAPH_PATT_COLOR1 0x00400804 +#define NV04_PGRAPH_PATTERN 0x00400808 +#define NV04_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV04_PGRAPH_CHROMA 0x00400814 +#define NV04_PGRAPH_CONTROL0 0x00400818 +#define NV04_PGRAPH_CONTROL1 0x0040081C +#define NV04_PGRAPH_CONTROL2 0x00400820 +#define NV04_PGRAPH_BLEND 0x00400824 +#define NV04_PGRAPH_STORED_FMT 0x00400830 +#define NV04_PGRAPH_PATT_COLORRAM 0x00400900 +#define NV20_PGRAPH_TILE(i) (0x00400900 + (i*16)) +#define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) +#define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) +#define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) +#define NV20_PGRAPH_ZCOMP(i) (0x00400980 + 4*(i)) +#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) +#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) +#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) +#define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) +#define NV04_PGRAPH_U_RAM 0x00400D00 +#define NV47_PGRAPH_TILE(i) (0x00400D00 + (i*16)) +#define NV47_PGRAPH_TLIMIT(i) (0x00400D04 + (i*16)) +#define NV47_PGRAPH_TSIZE(i) (0x00400D08 + (i*16)) +#define NV47_PGRAPH_TSTATUS(i) (0x00400D0C + (i*16)) +#define NV04_PGRAPH_V_RAM 0x00400D40 +#define NV04_PGRAPH_W_RAM 0x00400D80 +#define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 +#define NV10_PGRAPH_COMBINER1_IN_ALPHA 0x00400E44 +#define NV10_PGRAPH_COMBINER0_IN_RGB 0x00400E48 +#define NV10_PGRAPH_COMBINER1_IN_RGB 0x00400E4C +#define NV10_PGRAPH_COMBINER_COLOR0 0x00400E50 +#define NV10_PGRAPH_COMBINER_COLOR1 0x00400E54 +#define NV10_PGRAPH_COMBINER0_OUT_ALPHA 0x00400E58 +#define NV10_PGRAPH_COMBINER1_OUT_ALPHA 0x00400E5C +#define NV10_PGRAPH_COMBINER0_OUT_RGB 0x00400E60 +#define NV10_PGRAPH_COMBINER1_OUT_RGB 0x00400E64 +#define NV10_PGRAPH_COMBINER_FINAL0 0x00400E68 +#define NV10_PGRAPH_COMBINER_FINAL1 0x00400E6C +#define NV10_PGRAPH_WINDOWCLIP_HORIZONTAL 0x00400F00 +#define NV10_PGRAPH_WINDOWCLIP_VERTICAL 0x00400F20 +#define NV10_PGRAPH_XFMODE0 0x00400F40 +#define NV10_PGRAPH_XFMODE1 0x00400F44 +#define NV10_PGRAPH_GLOBALSTATE0 0x00400F48 +#define NV10_PGRAPH_GLOBALSTATE1 0x00400F4C +#define NV10_PGRAPH_PIPE_ADDRESS 0x00400F50 +#define NV10_PGRAPH_PIPE_DATA 0x00400F54 +#define NV04_PGRAPH_DMA_START_0 0x00401000 +#define NV04_PGRAPH_DMA_START_1 0x00401004 +#define NV04_PGRAPH_DMA_LENGTH 0x00401008 +#define NV04_PGRAPH_DMA_MISC 0x0040100C +#define NV04_PGRAPH_DMA_DATA_0 0x00401020 +#define NV04_PGRAPH_DMA_DATA_1 0x00401024 +#define NV04_PGRAPH_DMA_RM 0x00401030 +#define NV04_PGRAPH_DMA_A_XLATE_INST 0x00401040 +#define NV04_PGRAPH_DMA_A_CONTROL 0x00401044 +#define NV04_PGRAPH_DMA_A_LIMIT 0x00401048 +#define NV04_PGRAPH_DMA_A_TLB_PTE 0x0040104C +#define NV04_PGRAPH_DMA_A_TLB_TAG 0x00401050 +#define NV04_PGRAPH_DMA_A_ADJ_OFFSET 0x00401054 +#define NV04_PGRAPH_DMA_A_OFFSET 0x00401058 +#define NV04_PGRAPH_DMA_A_SIZE 0x0040105C +#define NV04_PGRAPH_DMA_A_Y_SIZE 0x00401060 +#define NV04_PGRAPH_DMA_B_XLATE_INST 0x00401080 +#define NV04_PGRAPH_DMA_B_CONTROL 0x00401084 +#define NV04_PGRAPH_DMA_B_LIMIT 0x00401088 +#define NV04_PGRAPH_DMA_B_TLB_PTE 0x0040108C +#define NV04_PGRAPH_DMA_B_TLB_TAG 0x00401090 +#define NV04_PGRAPH_DMA_B_ADJ_OFFSET 0x00401094 +#define NV04_PGRAPH_DMA_B_OFFSET 0x00401098 +#define NV04_PGRAPH_DMA_B_SIZE 0x0040109C +#define NV04_PGRAPH_DMA_B_Y_SIZE 0x004010A0 +#define NV40_PGRAPH_TILE1(i) (0x00406900 + (i*16)) +#define NV40_PGRAPH_TLIMIT1(i) (0x00406904 + (i*16)) +#define NV40_PGRAPH_TSIZE1(i) (0x00406908 + (i*16)) +#define NV40_PGRAPH_TSTATUS1(i) (0x0040690C + (i*16)) + +#endif |