From 02a841d434513c7b3620250271c372fabce56de5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 4 Jul 2012 23:44:54 +1000 Subject: drm/nouveau: restructure source tree, split core from drm implementation Future work will be headed in the way of separating the policy supplied by the nouveau drm module from the mechanisms provided by the driver core. There will be a couple of major classes (subdev, engine) of driver modules that have clearly defined tasks, and the further directory structure change is to reflect this. No code changes here whatsoever, aside from fixing up a couple of include file pathnames. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/mm.c | 175 + drivers/gpu/drm/nouveau/core/core/ramht.c | 309 ++ drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c | 83 + .../gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc | 872 +++++ .../drm/nouveau/core/engine/copy/fuc/nva3.fuc.h | 620 ++++ .../drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h | 606 ++++ drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 203 ++ drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 243 ++ .../gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc | 698 ++++ .../drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h | 584 ++++ drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 205 ++ drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 216 ++ drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 506 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 138 + drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 177 ++ drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 210 ++ drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 294 ++ drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 250 ++ drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 477 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 453 +++ drivers/gpu/drm/nouveau/core/engine/graph/ctx.h | 129 + .../gpu/drm/nouveau/core/engine/graph/ctxnv40.c | 690 ++++ .../gpu/drm/nouveau/core/engine/graph/ctxnv50.c | 3360 ++++++++++++++++++++ .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 2878 +++++++++++++++++ .../gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 2777 ++++++++++++++++ .../drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc | 539 ++++ .../nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h | 538 ++++ .../drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc | 856 +++++ .../nouveau/core/engine/graph/fuc/hubnvc0.fuc.h | 838 +++++ .../gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc | 400 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv04.c | 1326 ++++++++ drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 1189 +++++++ drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 836 +++++ drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 467 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 868 +++++ drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 897 ++++++ drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 97 + drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 831 +++++ drivers/gpu/drm/nouveau/core/engine/graph/nve0.h | 89 + drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 346 ++ drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c | 241 ++ drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | 78 + drivers/gpu/drm/nouveau/core/engine/vp/nv84.c | 83 + drivers/gpu/drm/nouveau/core/include/core/mm.h | 55 + drivers/gpu/drm/nouveau/core/include/core/ramht.h | 55 + drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 32 + drivers/gpu/drm/nouveau/core/include/subdev/gpio.h | 71 + drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | 59 + drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 119 + drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c | 55 + drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c | 104 + drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c | 148 + drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c | 116 + drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 163 + drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 296 ++ drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c | 237 ++ drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 135 + drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c | 160 + drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | 400 +++ drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c | 123 + drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | 155 + drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | 394 +++ drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 193 ++ drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 427 +++ drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c | 222 ++ drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c | 24 + drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c | 28 + drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c | 40 + drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 84 + drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 493 +++ drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 177 ++ drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 136 + 72 files changed, 32373 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/core/mm.c create mode 100644 drivers/gpu/drm/nouveau/core/core/ramht.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/copy/nva3.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/ctx.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv20.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nve0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nve0.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/vp/nv84.c create mode 100644 drivers/gpu/drm/nouveau/core/include/core/mm.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/ramht.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/fifo.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/gpio.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/i2c.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/vm.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/gpio/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c new file mode 100644 index 0000000..024dd2c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -0,0 +1,175 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +static inline void +region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a) +{ + list_del(&a->nl_entry); + list_del(&a->fl_entry); + kfree(a); +} + +static struct nouveau_mm_node * +region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) +{ + struct nouveau_mm_node *b; + + if (a->length == size) + return a; + + b = kmalloc(sizeof(*b), GFP_KERNEL); + if (unlikely(b == NULL)) + return NULL; + + b->offset = a->offset; + b->length = size; + b->type = a->type; + a->offset += size; + a->length -= size; + list_add_tail(&b->nl_entry, &a->nl_entry); + if (b->type == 0) + list_add_tail(&b->fl_entry, &a->fl_entry); + return b; +} + +#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ + list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) + +void +nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this) +{ + struct nouveau_mm_node *prev = node(this, prev); + struct nouveau_mm_node *next = node(this, next); + + list_add(&this->fl_entry, &mm->free); + this->type = 0; + + if (prev && prev->type == 0) { + prev->length += this->length; + region_put(mm, this); + this = prev; + } + + if (next && next->type == 0) { + next->offset = this->offset; + next->length += this->length; + region_put(mm, this); + } +} + +int +nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **pnode) +{ + struct nouveau_mm_node *prev, *this, *next; + u32 min = size_nc ? size_nc : size; + u32 align_mask = align - 1; + u32 splitoff; + u32 s, e; + + list_for_each_entry(this, &mm->free, fl_entry) { + e = this->offset + this->length; + s = this->offset; + + prev = node(this, prev); + if (prev && prev->type != type) + s = roundup(s, mm->block_size); + + next = node(this, next); + if (next && next->type != type) + e = rounddown(e, mm->block_size); + + s = (s + align_mask) & ~align_mask; + e &= ~align_mask; + if (s > e || e - s < min) + continue; + + splitoff = s - this->offset; + if (splitoff && !region_split(mm, this, splitoff)) + return -ENOMEM; + + this = region_split(mm, this, min(size, e - s)); + if (!this) + return -ENOMEM; + + this->type = type; + list_del(&this->fl_entry); + *pnode = this; + return 0; + } + + return -ENOSPC; +} + +int +nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) +{ + struct nouveau_mm_node *node; + + if (block) { + mutex_init(&mm->mutex); + INIT_LIST_HEAD(&mm->nodes); + INIT_LIST_HEAD(&mm->free); + mm->block_size = block; + mm->heap_nodes = 0; + } + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + node->offset = roundup(offset, mm->block_size); + node->length = rounddown(offset + length, mm->block_size) - node->offset; + + list_add_tail(&node->nl_entry, &mm->nodes); + list_add_tail(&node->fl_entry, &mm->free); + mm->heap_nodes++; + return 0; +} + +int +nouveau_mm_fini(struct nouveau_mm *mm) +{ + struct nouveau_mm_node *node, *heap = + list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); + int nodes = 0; + + list_for_each_entry(node, &mm->nodes, nl_entry) { + if (nodes++ == mm->heap_nodes) { + printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); + list_for_each_entry(node, &mm->nodes, nl_entry) { + printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", + node->type, node->offset, node->length); + } + WARN_ON(1); + return -EBUSY; + } + } + + kfree(heap); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c new file mode 100644 index 0000000..59c1619 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/ramht.c @@ -0,0 +1,309 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +static u32 +nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_ramht *ramht = chan->ramht; + u32 hash = 0; + int i; + + NV_DEBUG(dev, "ch%d handle=0x%08x\n", chan->id, handle); + + for (i = 32; i > 0; i -= ramht->bits) { + hash ^= (handle & ((1 << ramht->bits) - 1)); + handle >>= ramht->bits; + } + + if (dev_priv->card_type < NV_50) + hash ^= chan->id << (ramht->bits - 4); + hash <<= 3; + + NV_DEBUG(dev, "hash=0x%08x\n", hash); + return hash; +} + +static int +nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, + u32 offset) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 ctx = nv_ro32(ramht, offset + 4); + + if (dev_priv->card_type < NV_40) + return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); + return (ctx != 0); +} + +static int +nouveau_ramht_entry_same_channel(struct nouveau_channel *chan, + struct nouveau_gpuobj *ramht, u32 offset) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + u32 ctx = nv_ro32(ramht, offset + 4); + + if (dev_priv->card_type >= NV_50) + return true; + else if (dev_priv->card_type >= NV_40) + return chan->id == + ((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); + else + return chan->id == + ((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); +} + +int +nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, + struct nouveau_gpuobj *gpuobj) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + struct nouveau_ramht_entry *entry; + struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; + unsigned long flags; + u32 ctx, co, ho; + + if (nouveau_ramht_find(chan, handle)) + return -EEXIST; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + entry->channel = chan; + entry->gpuobj = NULL; + entry->handle = handle; + nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); + + if (dev_priv->card_type < NV_40) { + ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->pinst >> 4) | + (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); + } else + if (dev_priv->card_type < NV_50) { + ctx = (gpuobj->pinst >> 4) | + (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } else { + if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { + ctx = (gpuobj->cinst << 10) | + (chan->id << 28) | + chan->id; /* HASH_TAG */ + } else { + ctx = (gpuobj->cinst >> 4) | + ((gpuobj->engine << + NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); + } + } + + spin_lock_irqsave(&chan->ramht->lock, flags); + list_add(&entry->head, &chan->ramht->entries); + + co = ho = nouveau_ramht_hash_handle(chan, handle); + do { + if (!nouveau_ramht_entry_valid(dev, ramht, co)) { + NV_DEBUG(dev, + "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", + chan->id, co, handle, ctx); + nv_wo32(ramht, co + 0, handle); + nv_wo32(ramht, co + 4, ctx); + + spin_unlock_irqrestore(&chan->ramht->lock, flags); + instmem->flush(dev); + return 0; + } + NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", + chan->id, co, nv_ro32(ramht, co)); + + co += 8; + if (co >= ramht->size) + co = 0; + } while (co != ho); + + NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); + list_del(&entry->head); + spin_unlock_irqrestore(&chan->ramht->lock, flags); + kfree(entry); + return -ENOMEM; +} + +static struct nouveau_ramht_entry * +nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle) +{ + struct nouveau_ramht *ramht = chan ? chan->ramht : NULL; + struct nouveau_ramht_entry *entry; + unsigned long flags; + + if (!ramht) + return NULL; + + spin_lock_irqsave(&ramht->lock, flags); + list_for_each_entry(entry, &ramht->entries, head) { + if (entry->channel == chan && + (!handle || entry->handle == handle)) { + list_del(&entry->head); + spin_unlock_irqrestore(&ramht->lock, flags); + + return entry; + } + } + spin_unlock_irqrestore(&ramht->lock, flags); + + return NULL; +} + +static void +nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; + struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; + unsigned long flags; + u32 co, ho; + + spin_lock_irqsave(&chan->ramht->lock, flags); + co = ho = nouveau_ramht_hash_handle(chan, handle); + do { + if (nouveau_ramht_entry_valid(dev, ramht, co) && + nouveau_ramht_entry_same_channel(chan, ramht, co) && + (handle == nv_ro32(ramht, co))) { + NV_DEBUG(dev, + "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", + chan->id, co, handle, nv_ro32(ramht, co + 4)); + nv_wo32(ramht, co + 0, 0x00000000); + nv_wo32(ramht, co + 4, 0x00000000); + instmem->flush(dev); + goto out; + } + + co += 8; + if (co >= ramht->size) + co = 0; + } while (co != ho); + + NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", + chan->id, handle); +out: + spin_unlock_irqrestore(&chan->ramht->lock, flags); +} + +int +nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) +{ + struct nouveau_ramht_entry *entry; + + entry = nouveau_ramht_remove_entry(chan, handle); + if (!entry) + return -ENOENT; + + nouveau_ramht_remove_hash(chan, entry->handle); + nouveau_gpuobj_ref(NULL, &entry->gpuobj); + kfree(entry); + return 0; +} + +struct nouveau_gpuobj * +nouveau_ramht_find(struct nouveau_channel *chan, u32 handle) +{ + struct nouveau_ramht *ramht = chan->ramht; + struct nouveau_ramht_entry *entry; + struct nouveau_gpuobj *gpuobj = NULL; + unsigned long flags; + + if (unlikely(!chan->ramht)) + return NULL; + + spin_lock_irqsave(&ramht->lock, flags); + list_for_each_entry(entry, &chan->ramht->entries, head) { + if (entry->channel == chan && entry->handle == handle) { + gpuobj = entry->gpuobj; + break; + } + } + spin_unlock_irqrestore(&ramht->lock, flags); + + return gpuobj; +} + +int +nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, + struct nouveau_ramht **pramht) +{ + struct nouveau_ramht *ramht; + + ramht = kzalloc(sizeof(*ramht), GFP_KERNEL); + if (!ramht) + return -ENOMEM; + + ramht->dev = dev; + kref_init(&ramht->refcount); + ramht->bits = drm_order(gpuobj->size / 8); + INIT_LIST_HEAD(&ramht->entries); + spin_lock_init(&ramht->lock); + nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj); + + *pramht = ramht; + return 0; +} + +static void +nouveau_ramht_del(struct kref *ref) +{ + struct nouveau_ramht *ramht = + container_of(ref, struct nouveau_ramht, refcount); + + nouveau_gpuobj_ref(NULL, &ramht->gpuobj); + kfree(ramht); +} + +void +nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, + struct nouveau_channel *chan) +{ + struct nouveau_ramht_entry *entry; + struct nouveau_ramht *ramht; + + if (ref) + kref_get(&ref->refcount); + + ramht = *ptr; + if (ramht) { + while ((entry = nouveau_ramht_remove_entry(chan, 0))) { + nouveau_ramht_remove_hash(chan, entry->handle); + nouveau_gpuobj_ref(NULL, &entry->gpuobj); + kfree(entry); + } + + kref_put(&ramht->refcount, nouveau_ramht_del); + } + *ptr = ref; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c new file mode 100644 index 0000000..db3b573 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c @@ -0,0 +1,83 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include + +/*XXX: This stub is currently used on NV98+ also, as soon as this becomes + * more than just an enable/disable stub this needs to be split out to + * nv98_bsp.c... + */ + +struct nv84_bsp_engine { + struct nouveau_exec_engine base; +}; + +static int +nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend) +{ + if (!(nv_rd32(dev, 0x000200) & 0x00008000)) + return 0; + + nv_mask(dev, 0x000200, 0x00008000, 0x00000000); + return 0; +} + +static int +nv84_bsp_init(struct drm_device *dev, int engine) +{ + nv_mask(dev, 0x000200, 0x00008000, 0x00000000); + nv_mask(dev, 0x000200, 0x00008000, 0x00008000); + return 0; +} + +static void +nv84_bsp_destroy(struct drm_device *dev, int engine) +{ + struct nv84_bsp_engine *pbsp = nv_engine(dev, engine); + + NVOBJ_ENGINE_DEL(dev, BSP); + + kfree(pbsp); +} + +int +nv84_bsp_create(struct drm_device *dev) +{ + struct nv84_bsp_engine *pbsp; + + pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL); + if (!pbsp) + return -ENOMEM; + + pbsp->base.destroy = nv84_bsp_destroy; + pbsp->base.init = nv84_bsp_init; + pbsp->base.fini = nv84_bsp_fini; + + NVOBJ_ENGINE_ADD(dev, BSP, &pbsp->base); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc new file mode 100644 index 0000000..219850d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc @@ -0,0 +1,872 @@ +/* fuc microcode for copy engine on nva3- chipsets + * + * Copyright 2011 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: + * + * 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 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 + */ + +/* To build for nva3:nvc0 + * m4 -DNVA3 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nva3_copy.fuc.h + * + * To build for nvc0- + * m4 -DNVC0 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_copy.fuc.h + */ + +ifdef(`NVA3', +.section #nva3_pcopy_data +, +.section #nvc0_pcopy_data +) + +ctx_object: .b32 0 +ifdef(`NVA3', +ctx_dma: +ctx_dma_query: .b32 0 +ctx_dma_src: .b32 0 +ctx_dma_dst: .b32 0 +,) +.equ #ctx_dma_count 3 +ctx_query_address_high: .b32 0 +ctx_query_address_low: .b32 0 +ctx_query_counter: .b32 0 +ctx_src_address_high: .b32 0 +ctx_src_address_low: .b32 0 +ctx_src_pitch: .b32 0 +ctx_src_tile_mode: .b32 0 +ctx_src_xsize: .b32 0 +ctx_src_ysize: .b32 0 +ctx_src_zsize: .b32 0 +ctx_src_zoff: .b32 0 +ctx_src_xoff: .b32 0 +ctx_src_yoff: .b32 0 +ctx_src_cpp: .b32 0 +ctx_dst_address_high: .b32 0 +ctx_dst_address_low: .b32 0 +ctx_dst_pitch: .b32 0 +ctx_dst_tile_mode: .b32 0 +ctx_dst_xsize: .b32 0 +ctx_dst_ysize: .b32 0 +ctx_dst_zsize: .b32 0 +ctx_dst_zoff: .b32 0 +ctx_dst_xoff: .b32 0 +ctx_dst_yoff: .b32 0 +ctx_dst_cpp: .b32 0 +ctx_format: .b32 0 +ctx_swz_const0: .b32 0 +ctx_swz_const1: .b32 0 +ctx_xcnt: .b32 0 +ctx_ycnt: .b32 0 +.align 256 + +dispatch_table: +// mthd 0x0000, NAME +.b16 0x000 1 +.b32 #ctx_object ~0xffffffff +// mthd 0x0100, NOP +.b16 0x040 1 +.b32 0x00010000 + #cmd_nop ~0xffffffff +// mthd 0x0140, PM_TRIGGER +.b16 0x050 1 +.b32 0x00010000 + #cmd_pm_trigger ~0xffffffff +ifdef(`NVA3', ` +// mthd 0x0180-0x018c, DMA_ +.b16 0x060 #ctx_dma_count +dispatch_dma: +.b32 0x00010000 + #cmd_dma ~0xffffffff +.b32 0x00010000 + #cmd_dma ~0xffffffff +.b32 0x00010000 + #cmd_dma ~0xffffffff +',) +// mthd 0x0200-0x0218, SRC_TILE +.b16 0x80 7 +.b32 #ctx_src_tile_mode ~0x00000fff +.b32 #ctx_src_xsize ~0x0007ffff +.b32 #ctx_src_ysize ~0x00001fff +.b32 #ctx_src_zsize ~0x000007ff +.b32 #ctx_src_zoff ~0x00000fff +.b32 #ctx_src_xoff ~0x0007ffff +.b32 #ctx_src_yoff ~0x00001fff +// mthd 0x0220-0x0238, DST_TILE +.b16 0x88 7 +.b32 #ctx_dst_tile_mode ~0x00000fff +.b32 #ctx_dst_xsize ~0x0007ffff +.b32 #ctx_dst_ysize ~0x00001fff +.b32 #ctx_dst_zsize ~0x000007ff +.b32 #ctx_dst_zoff ~0x00000fff +.b32 #ctx_dst_xoff ~0x0007ffff +.b32 #ctx_dst_yoff ~0x00001fff +// mthd 0x0300-0x0304, EXEC, WRCACHE_FLUSH +.b16 0xc0 2 +.b32 0x00010000 + #cmd_exec ~0xffffffff +.b32 0x00010000 + #cmd_wrcache_flush ~0xffffffff +// mthd 0x030c-0x0340, various stuff +.b16 0xc3 14 +.b32 #ctx_src_address_high ~0x000000ff +.b32 #ctx_src_address_low ~0xffffffff +.b32 #ctx_dst_address_high ~0x000000ff +.b32 #ctx_dst_address_low ~0xffffffff +.b32 #ctx_src_pitch ~0x0007ffff +.b32 #ctx_dst_pitch ~0x0007ffff +.b32 #ctx_xcnt ~0x0000ffff +.b32 #ctx_ycnt ~0x00001fff +.b32 #ctx_format ~0x0333ffff +.b32 #ctx_swz_const0 ~0xffffffff +.b32 #ctx_swz_const1 ~0xffffffff +.b32 #ctx_query_address_high ~0x000000ff +.b32 #ctx_query_address_low ~0xffffffff +.b32 #ctx_query_counter ~0xffffffff +.b16 0x800 0 + +ifdef(`NVA3', +.section #nva3_pcopy_code +, +.section #nvc0_pcopy_code +) + +main: + clear b32 $r0 + mov $sp $r0 + + // setup i0 handler and route fifo and ctxswitch to it + mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + movw $r2 0xfff3 + sethi $r2 0 + iowr I[$r1 + 0x300] $r2 + + // enable interrupts + or $r2 0xc + iowr I[$r1] $r2 + bset $flags ie0 + + // enable fifo access and context switching + mov $r1 0x1200 + mov $r2 3 + iowr I[$r1] $r2 + + // sleep forever, waking for interrupts + bset $flags $p0 + spin: + sleep $p0 + bra #spin + +// i0 handler +ih: + iord $r1 I[$r0 + 0x200] + + and $r2 $r1 0x00000008 + bra e #ih_no_chsw + call #chsw + ih_no_chsw: + and $r2 $r1 0x00000004 + bra e #ih_no_cmd + call #dispatch + + ih_no_cmd: + and $r1 $r1 0x0000000c + iowr I[$r0 + 0x100] $r1 + iret + +// $p1 direction (0 = unload, 1 = load) +// $r3 channel +swctx: + mov $r4 0x7700 + mov $xtargets $r4 +ifdef(`NVA3', ` + // target 7 hardcoded to ctx dma object + mov $xdbase $r0 +', ` // NVC0 + // read SCRATCH3 to decide if we are PCOPY0 or PCOPY1 + mov $r4 0x2100 + iord $r4 I[$r4 + 0] + and $r4 1 + shl b32 $r4 4 + add b32 $r4 0x30 + + // channel is in vram + mov $r15 0x61c + shl b32 $r15 6 + mov $r5 0x114 + iowrs I[$r15] $r5 + + // read 16-byte PCOPYn info, containing context pointer, from channel + shl b32 $r5 $r3 4 + add b32 $r5 2 + mov $xdbase $r5 + mov $r5 $sp + // get a chunk of stack space, aligned to 256 byte boundary + sub b32 $r5 0x100 + mov $r6 0xff + not b32 $r6 + and $r5 $r6 + sethi $r5 0x00020000 + xdld $r4 $r5 + xdwait + sethi $r5 0 + + // set context pointer, from within channel VM + mov $r14 0 + iowrs I[$r15] $r14 + ld b32 $r4 D[$r5 + 0] + shr b32 $r4 8 + ld b32 $r6 D[$r5 + 4] + shl b32 $r6 24 + or $r4 $r6 + mov $xdbase $r4 +') + // 256-byte context, at start of data segment + mov b32 $r4 $r0 + sethi $r4 0x60000 + + // swap! + bra $p1 #swctx_load + xdst $r0 $r4 + bra #swctx_done + swctx_load: + xdld $r0 $r4 + swctx_done: + xdwait + ret + +chsw: + // read current channel + mov $r2 0x1400 + iord $r3 I[$r2] + + // if it's active, unload it and return + xbit $r15 $r3 0x1e + bra e #chsw_no_unload + bclr $flags $p1 + call #swctx + bclr $r3 0x1e + iowr I[$r2] $r3 + mov $r4 1 + iowr I[$r2 + 0x200] $r4 + ret + + // read next channel + chsw_no_unload: + iord $r3 I[$r2 + 0x100] + + // is there a channel waiting to be loaded? + xbit $r13 $r3 0x1e + bra e #chsw_finish_load + bset $flags $p1 + call #swctx +ifdef(`NVA3', + // load dma objects back into TARGET regs + mov $r5 #ctx_dma + mov $r6 #ctx_dma_count + chsw_load_ctx_dma: + ld b32 $r7 D[$r5 + $r6 * 4] + add b32 $r8 $r6 0x180 + shl b32 $r8 8 + iowr I[$r8] $r7 + sub b32 $r6 1 + bra nc #chsw_load_ctx_dma +,) + + chsw_finish_load: + mov $r3 2 + iowr I[$r2 + 0x200] $r3 + ret + +dispatch: + // read incoming fifo command + mov $r3 0x1900 + iord $r2 I[$r3 + 0x100] + iord $r3 I[$r3 + 0x000] + and $r4 $r2 0x7ff + // $r2 will be used to store exception data + shl b32 $r2 0x10 + + // lookup method in the dispatch table, ILLEGAL_MTHD if not found + mov $r5 #dispatch_table + clear b32 $r6 + clear b32 $r7 + dispatch_loop: + ld b16 $r6 D[$r5 + 0] + ld b16 $r7 D[$r5 + 2] + add b32 $r5 4 + cmpu b32 $r4 $r6 + bra c #dispatch_illegal_mthd + add b32 $r7 $r6 + cmpu b32 $r4 $r7 + bra c #dispatch_valid_mthd + sub b32 $r7 $r6 + shl b32 $r7 3 + add b32 $r5 $r7 + bra #dispatch_loop + + // ensure no bits set in reserved fields, INVALID_BITFIELD + dispatch_valid_mthd: + sub b32 $r4 $r6 + shl b32 $r4 3 + add b32 $r4 $r5 + ld b32 $r5 D[$r4 + 4] + and $r5 $r3 + cmpu b32 $r5 0 + bra ne #dispatch_invalid_bitfield + + // depending on dispatch flags: execute method, or save data as state + ld b16 $r5 D[$r4 + 0] + ld b16 $r6 D[$r4 + 2] + cmpu b32 $r6 0 + bra ne #dispatch_cmd + st b32 D[$r5] $r3 + bra #dispatch_done + dispatch_cmd: + bclr $flags $p1 + call $r5 + bra $p1 #dispatch_error + bra #dispatch_done + + dispatch_invalid_bitfield: + or $r2 2 + dispatch_illegal_mthd: + or $r2 1 + + // store exception data in SCRATCH0/SCRATCH1, signal hostirq + dispatch_error: + mov $r4 0x1000 + iowr I[$r4 + 0x000] $r2 + iowr I[$r4 + 0x100] $r3 + mov $r2 0x40 + iowr I[$r0] $r2 + hostirq_wait: + iord $r2 I[$r0 + 0x200] + and $r2 0x40 + cmpu b32 $r2 0 + bra ne #hostirq_wait + + dispatch_done: + mov $r2 0x1d00 + mov $r3 1 + iowr I[$r2] $r3 + ret + +// No-operation +// +// Inputs: +// $r1: irqh state +// $r2: hostirq state +// $r3: data +// $r4: dispatch table entry +// Outputs: +// $r1: irqh state +// $p1: set on error +// $r2: hostirq state +// $r3: data +cmd_nop: + ret + +// PM_TRIGGER +// +// Inputs: +// $r1: irqh state +// $r2: hostirq state +// $r3: data +// $r4: dispatch table entry +// Outputs: +// $r1: irqh state +// $p1: set on error +// $r2: hostirq state +// $r3: data +cmd_pm_trigger: + mov $r2 0x2200 + clear b32 $r3 + sethi $r3 0x20000 + iowr I[$r2] $r3 + ret + +ifdef(`NVA3', +// SET_DMA_* method handler +// +// Inputs: +// $r1: irqh state +// $r2: hostirq state +// $r3: data +// $r4: dispatch table entry +// Outputs: +// $r1: irqh state +// $p1: set on error +// $r2: hostirq state +// $r3: data +cmd_dma: + sub b32 $r4 #dispatch_dma + shr b32 $r4 1 + bset $r3 0x1e + st b32 D[$r4 + #ctx_dma] $r3 + add b32 $r4 0x600 + shl b32 $r4 6 + iowr I[$r4] $r3 + ret +,) + +// Calculates the hw swizzle mask and adjusts the surface's xcnt to match +// +cmd_exec_set_format: + // zero out a chunk of the stack to store the swizzle into + add $sp -0x10 + st b32 D[$sp + 0x00] $r0 + st b32 D[$sp + 0x04] $r0 + st b32 D[$sp + 0x08] $r0 + st b32 D[$sp + 0x0c] $r0 + + // extract cpp, src_ncomp and dst_ncomp from FORMAT + ld b32 $r4 D[$r0 + #ctx_format] + extr $r5 $r4 16:17 + add b32 $r5 1 + extr $r6 $r4 20:21 + add b32 $r6 1 + extr $r7 $r4 24:25 + add b32 $r7 1 + + // convert FORMAT swizzle mask to hw swizzle mask + bclr $flags $p2 + clear b32 $r8 + clear b32 $r9 + ncomp_loop: + and $r10 $r4 0xf + shr b32 $r4 4 + clear b32 $r11 + bpc_loop: + cmpu b8 $r10 4 + bra nc #cmp_c0 + mulu $r12 $r10 $r5 + add b32 $r12 $r11 + bset $flags $p2 + bra #bpc_next + cmp_c0: + bra ne #cmp_c1 + mov $r12 0x10 + add b32 $r12 $r11 + bra #bpc_next + cmp_c1: + cmpu b8 $r10 6 + bra nc #cmp_zero + mov $r12 0x14 + add b32 $r12 $r11 + bra #bpc_next + cmp_zero: + mov $r12 0x80 + bpc_next: + st b8 D[$sp + $r8] $r12 + add b32 $r8 1 + add b32 $r11 1 + cmpu b32 $r11 $r5 + bra c #bpc_loop + add b32 $r9 1 + cmpu b32 $r9 $r7 + bra c #ncomp_loop + + // SRC_XCNT = (xcnt * src_cpp), or 0 if no src ref in swz (hw will hang) + mulu $r6 $r5 + st b32 D[$r0 + #ctx_src_cpp] $r6 + ld b32 $r8 D[$r0 + #ctx_xcnt] + mulu $r6 $r8 + bra $p2 #dst_xcnt + clear b32 $r6 + + dst_xcnt: + mulu $r7 $r5 + st b32 D[$r0 + #ctx_dst_cpp] $r7 + mulu $r7 $r8 + + mov $r5 0x810 + shl b32 $r5 6 + iowr I[$r5 + 0x000] $r6 + iowr I[$r5 + 0x100] $r7 + add b32 $r5 0x800 + ld b32 $r6 D[$r0 + #ctx_dst_cpp] + sub b32 $r6 1 + shl b32 $r6 8 + ld b32 $r7 D[$r0 + #ctx_src_cpp] + sub b32 $r7 1 + or $r6 $r7 + iowr I[$r5 + 0x000] $r6 + add b32 $r5 0x100 + ld b32 $r6 D[$sp + 0x00] + iowr I[$r5 + 0x000] $r6 + ld b32 $r6 D[$sp + 0x04] + iowr I[$r5 + 0x100] $r6 + ld b32 $r6 D[$sp + 0x08] + iowr I[$r5 + 0x200] $r6 + ld b32 $r6 D[$sp + 0x0c] + iowr I[$r5 + 0x300] $r6 + add b32 $r5 0x400 + ld b32 $r6 D[$r0 + #ctx_swz_const0] + iowr I[$r5 + 0x000] $r6 + ld b32 $r6 D[$r0 + #ctx_swz_const1] + iowr I[$r5 + 0x100] $r6 + add $sp 0x10 + ret + +// Setup to handle a tiled surface +// +// Calculates a number of parameters the hardware requires in order +// to correctly handle tiling. +// +// Offset calculation is performed as follows (Tp/Th/Td from TILE_MODE): +// nTx = round_up(w * cpp, 1 << Tp) >> Tp +// nTy = round_up(h, 1 << Th) >> Th +// Txo = (x * cpp) & ((1 << Tp) - 1) +// Tx = (x * cpp) >> Tp +// Tyo = y & ((1 << Th) - 1) +// Ty = y >> Th +// Tzo = z & ((1 << Td) - 1) +// Tz = z >> Td +// +// off = (Tzo << Tp << Th) + (Tyo << Tp) + Txo +// off += ((Tz * nTy * nTx)) + (Ty * nTx) + Tx) << Td << Th << Tp; +// +// Inputs: +// $r4: hw command (0x104800) +// $r5: ctx offset adjustment for src/dst selection +// $p2: set if dst surface +// +cmd_exec_set_surface_tiled: + // translate TILE_MODE into Tp, Th, Td shift values + ld b32 $r7 D[$r5 + #ctx_src_tile_mode] + extr $r9 $r7 8:11 + extr $r8 $r7 4:7 +ifdef(`NVA3', + add b32 $r8 2 +, + add b32 $r8 3 +) + extr $r7 $r7 0:3 + cmp b32 $r7 0xe + bra ne #xtile64 + mov $r7 4 + bra #xtileok + xtile64: + xbit $r7 $flags $p2 + add b32 $r7 17 + bset $r4 $r7 + mov $r7 6 + xtileok: + + // Op = (x * cpp) & ((1 << Tp) - 1) + // Tx = (x * cpp) >> Tp + ld b32 $r10 D[$r5 + #ctx_src_xoff] + ld b32 $r11 D[$r5 + #ctx_src_cpp] + mulu $r10 $r11 + mov $r11 1 + shl b32 $r11 $r7 + sub b32 $r11 1 + and $r12 $r10 $r11 + shr b32 $r10 $r7 + + // Tyo = y & ((1 << Th) - 1) + // Ty = y >> Th + ld b32 $r13 D[$r5 + #ctx_src_yoff] + mov $r14 1 + shl b32 $r14 $r8 + sub b32 $r14 1 + and $r11 $r13 $r14 + shr b32 $r13 $r8 + + // YTILE = ((1 << Th) << 12) | ((1 << Th) - Tyo) + add b32 $r14 1 + shl b32 $r15 $r14 12 + sub b32 $r14 $r11 + or $r15 $r14 + xbit $r6 $flags $p2 + add b32 $r6 0x208 + shl b32 $r6 8 + iowr I[$r6 + 0x000] $r15 + + // Op += Tyo << Tp + shl b32 $r11 $r7 + add b32 $r12 $r11 + + // nTx = ((w * cpp) + ((1 << Tp) - 1) >> Tp) + ld b32 $r15 D[$r5 + #ctx_src_xsize] + ld b32 $r11 D[$r5 + #ctx_src_cpp] + mulu $r15 $r11 + mov $r11 1 + shl b32 $r11 $r7 + sub b32 $r11 1 + add b32 $r15 $r11 + shr b32 $r15 $r7 + push $r15 + + // nTy = (h + ((1 << Th) - 1)) >> Th + ld b32 $r15 D[$r5 + #ctx_src_ysize] + mov $r11 1 + shl b32 $r11 $r8 + sub b32 $r11 1 + add b32 $r15 $r11 + shr b32 $r15 $r8 + push $r15 + + // Tys = Tp + Th + // CFG_YZ_TILE_SIZE = ((1 << Th) >> 2) << Td + add b32 $r7 $r8 + sub b32 $r8 2 + mov $r11 1 + shl b32 $r11 $r8 + shl b32 $r11 $r9 + + // Tzo = z & ((1 << Td) - 1) + // Tz = z >> Td + // Op += Tzo << Tys + // Ts = Tys + Td + ld b32 $r8 D[$r5 + #ctx_src_zoff] + mov $r14 1 + shl b32 $r14 $r9 + sub b32 $r14 1 + and $r15 $r8 $r14 + shl b32 $r15 $r7 + add b32 $r12 $r15 + add b32 $r7 $r9 + shr b32 $r8 $r9 + + // Ot = ((Tz * nTy * nTx) + (Ty * nTx) + Tx) << Ts + pop $r15 + pop $r9 + mulu $r13 $r9 + add b32 $r10 $r13 + mulu $r8 $r9 + mulu $r8 $r15 + add b32 $r10 $r8 + shl b32 $r10 $r7 + + // PITCH = (nTx - 1) << Ts + sub b32 $r9 1 + shl b32 $r9 $r7 + iowr I[$r6 + 0x200] $r9 + + // SRC_ADDRESS_LOW = (Ot + Op) & 0xffffffff + // CFG_ADDRESS_HIGH |= ((Ot + Op) >> 32) << 16 + ld b32 $r7 D[$r5 + #ctx_src_address_low] + ld b32 $r8 D[$r5 + #ctx_src_address_high] + add b32 $r10 $r12 + add b32 $r7 $r10 + adc b32 $r8 0 + shl b32 $r8 16 + or $r8 $r11 + sub b32 $r6 0x600 + iowr I[$r6 + 0x000] $r7 + add b32 $r6 0x400 + iowr I[$r6 + 0x000] $r8 + ret + +// Setup to handle a linear surface +// +// Nothing to see here.. Sets ADDRESS and PITCH, pretty non-exciting +// +cmd_exec_set_surface_linear: + xbit $r6 $flags $p2 + add b32 $r6 0x202 + shl b32 $r6 8 + ld b32 $r7 D[$r5 + #ctx_src_address_low] + iowr I[$r6 + 0x000] $r7 + add b32 $r6 0x400 + ld b32 $r7 D[$r5 + #ctx_src_address_high] + shl b32 $r7 16 + iowr I[$r6 + 0x000] $r7 + add b32 $r6 0x400 + ld b32 $r7 D[$r5 + #ctx_src_pitch] + iowr I[$r6 + 0x000] $r7 + ret + +// wait for regs to be available for use +cmd_exec_wait: + push $r0 + push $r1 + mov $r0 0x800 + shl b32 $r0 6 + loop: + iord $r1 I[$r0] + and $r1 1 + bra ne #loop + pop $r1 + pop $r0 + ret + +cmd_exec_query: + // if QUERY_SHORT not set, write out { -, 0, TIME_LO, TIME_HI } + xbit $r4 $r3 13 + bra ne #query_counter + call #cmd_exec_wait + mov $r4 0x80c + shl b32 $r4 6 + ld b32 $r5 D[$r0 + #ctx_query_address_low] + add b32 $r5 4 + iowr I[$r4 + 0x000] $r5 + iowr I[$r4 + 0x100] $r0 + mov $r5 0xc + iowr I[$r4 + 0x200] $r5 + add b32 $r4 0x400 + ld b32 $r5 D[$r0 + #ctx_query_address_high] + shl b32 $r5 16 + iowr I[$r4 + 0x000] $r5 + add b32 $r4 0x500 + mov $r5 0x00000b00 + sethi $r5 0x00010000 + iowr I[$r4 + 0x000] $r5 + mov $r5 0x00004040 + shl b32 $r5 1 + sethi $r5 0x80800000 + iowr I[$r4 + 0x100] $r5 + mov $r5 0x00001110 + sethi $r5 0x13120000 + iowr I[$r4 + 0x200] $r5 + mov $r5 0x00001514 + sethi $r5 0x17160000 + iowr I[$r4 + 0x300] $r5 + mov $r5 0x00002601 + sethi $r5 0x00010000 + mov $r4 0x800 + shl b32 $r4 6 + iowr I[$r4 + 0x000] $r5 + + // write COUNTER + query_counter: + call #cmd_exec_wait + mov $r4 0x80c + shl b32 $r4 6 + ld b32 $r5 D[$r0 + #ctx_query_address_low] + iowr I[$r4 + 0x000] $r5 + iowr I[$r4 + 0x100] $r0 + mov $r5 0x4 + iowr I[$r4 + 0x200] $r5 + add b32 $r4 0x400 + ld b32 $r5 D[$r0 + #ctx_query_address_high] + shl b32 $r5 16 + iowr I[$r4 + 0x000] $r5 + add b32 $r4 0x500 + mov $r5 0x00000300 + iowr I[$r4 + 0x000] $r5 + mov $r5 0x00001110 + sethi $r5 0x13120000 + iowr I[$r4 + 0x100] $r5 + ld b32 $r5 D[$r0 + #ctx_query_counter] + add b32 $r4 0x500 + iowr I[$r4 + 0x000] $r5 + mov $r5 0x00002601 + sethi $r5 0x00010000 + mov $r4 0x800 + shl b32 $r4 6 + iowr I[$r4 + 0x000] $r5 + ret + +// Execute a copy operation +// +// Inputs: +// $r1: irqh state +// $r2: hostirq state +// $r3: data +// 000002000 QUERY_SHORT +// 000001000 QUERY +// 000000100 DST_LINEAR +// 000000010 SRC_LINEAR +// 000000001 FORMAT +// $r4: dispatch table entry +// Outputs: +// $r1: irqh state +// $p1: set on error +// $r2: hostirq state +// $r3: data +cmd_exec: + call #cmd_exec_wait + + // if format requested, call function to calculate it, otherwise + // fill in cpp/xcnt for both surfaces as if (cpp == 1) + xbit $r15 $r3 0 + bra e #cmd_exec_no_format + call #cmd_exec_set_format + mov $r4 0x200 + bra #cmd_exec_init_src_surface + cmd_exec_no_format: + mov $r6 0x810 + shl b32 $r6 6 + mov $r7 1 + st b32 D[$r0 + #ctx_src_cpp] $r7 + st b32 D[$r0 + #ctx_dst_cpp] $r7 + ld b32 $r7 D[$r0 + #ctx_xcnt] + iowr I[$r6 + 0x000] $r7 + iowr I[$r6 + 0x100] $r7 + clear b32 $r4 + + cmd_exec_init_src_surface: + bclr $flags $p2 + clear b32 $r5 + xbit $r15 $r3 4 + bra e #src_tiled + call #cmd_exec_set_surface_linear + bra #cmd_exec_init_dst_surface + src_tiled: + call #cmd_exec_set_surface_tiled + bset $r4 7 + + cmd_exec_init_dst_surface: + bset $flags $p2 + mov $r5 #ctx_dst_address_high - #ctx_src_address_high + xbit $r15 $r3 8 + bra e #dst_tiled + call #cmd_exec_set_surface_linear + bra #cmd_exec_kick + dst_tiled: + call #cmd_exec_set_surface_tiled + bset $r4 8 + + cmd_exec_kick: + mov $r5 0x800 + shl b32 $r5 6 + ld b32 $r6 D[$r0 + #ctx_ycnt] + iowr I[$r5 + 0x100] $r6 + mov $r6 0x0041 + // SRC_TARGET = 1, DST_TARGET = 2 + sethi $r6 0x44000000 + or $r4 $r6 + iowr I[$r5] $r4 + + // if requested, queue up a QUERY write after the copy has completed + xbit $r15 $r3 12 + bra e #cmd_exec_done + call #cmd_exec_query + + cmd_exec_done: + ret + +// Flush write cache +// +// Inputs: +// $r1: irqh state +// $r2: hostirq state +// $r3: data +// $r4: dispatch table entry +// Outputs: +// $r1: irqh state +// $p1: set on error +// $r2: hostirq state +// $r3: data +cmd_wrcache_flush: + mov $r2 0x2200 + clear b32 $r3 + sethi $r3 0x10000 + iowr I[$r2] $r3 + ret + +.align 0x100 diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h new file mode 100644 index 0000000..37d6de3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h @@ -0,0 +1,620 @@ +u32 nva3_pcopy_data[] = { +/* 0x0000: ctx_object */ + 0x00000000, +/* 0x0004: ctx_dma */ +/* 0x0004: ctx_dma_query */ + 0x00000000, +/* 0x0008: ctx_dma_src */ + 0x00000000, +/* 0x000c: ctx_dma_dst */ + 0x00000000, +/* 0x0010: ctx_query_address_high */ + 0x00000000, +/* 0x0014: ctx_query_address_low */ + 0x00000000, +/* 0x0018: ctx_query_counter */ + 0x00000000, +/* 0x001c: ctx_src_address_high */ + 0x00000000, +/* 0x0020: ctx_src_address_low */ + 0x00000000, +/* 0x0024: ctx_src_pitch */ + 0x00000000, +/* 0x0028: ctx_src_tile_mode */ + 0x00000000, +/* 0x002c: ctx_src_xsize */ + 0x00000000, +/* 0x0030: ctx_src_ysize */ + 0x00000000, +/* 0x0034: ctx_src_zsize */ + 0x00000000, +/* 0x0038: ctx_src_zoff */ + 0x00000000, +/* 0x003c: ctx_src_xoff */ + 0x00000000, +/* 0x0040: ctx_src_yoff */ + 0x00000000, +/* 0x0044: ctx_src_cpp */ + 0x00000000, +/* 0x0048: ctx_dst_address_high */ + 0x00000000, +/* 0x004c: ctx_dst_address_low */ + 0x00000000, +/* 0x0050: ctx_dst_pitch */ + 0x00000000, +/* 0x0054: ctx_dst_tile_mode */ + 0x00000000, +/* 0x0058: ctx_dst_xsize */ + 0x00000000, +/* 0x005c: ctx_dst_ysize */ + 0x00000000, +/* 0x0060: ctx_dst_zsize */ + 0x00000000, +/* 0x0064: ctx_dst_zoff */ + 0x00000000, +/* 0x0068: ctx_dst_xoff */ + 0x00000000, +/* 0x006c: ctx_dst_yoff */ + 0x00000000, +/* 0x0070: ctx_dst_cpp */ + 0x00000000, +/* 0x0074: ctx_format */ + 0x00000000, +/* 0x0078: ctx_swz_const0 */ + 0x00000000, +/* 0x007c: ctx_swz_const1 */ + 0x00000000, +/* 0x0080: ctx_xcnt */ + 0x00000000, +/* 0x0084: ctx_ycnt */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0100: dispatch_table */ + 0x00010000, + 0x00000000, + 0x00000000, + 0x00010040, + 0x00010160, + 0x00000000, + 0x00010050, + 0x00010162, + 0x00000000, + 0x00030060, +/* 0x0128: dispatch_dma */ + 0x00010170, + 0x00000000, + 0x00010170, + 0x00000000, + 0x00010170, + 0x00000000, + 0x00070080, + 0x00000028, + 0xfffff000, + 0x0000002c, + 0xfff80000, + 0x00000030, + 0xffffe000, + 0x00000034, + 0xfffff800, + 0x00000038, + 0xfffff000, + 0x0000003c, + 0xfff80000, + 0x00000040, + 0xffffe000, + 0x00070088, + 0x00000054, + 0xfffff000, + 0x00000058, + 0xfff80000, + 0x0000005c, + 0xffffe000, + 0x00000060, + 0xfffff800, + 0x00000064, + 0xfffff000, + 0x00000068, + 0xfff80000, + 0x0000006c, + 0xffffe000, + 0x000200c0, + 0x00010492, + 0x00000000, + 0x0001051b, + 0x00000000, + 0x000e00c3, + 0x0000001c, + 0xffffff00, + 0x00000020, + 0x00000000, + 0x00000048, + 0xffffff00, + 0x0000004c, + 0x00000000, + 0x00000024, + 0xfff80000, + 0x00000050, + 0xfff80000, + 0x00000080, + 0xffff0000, + 0x00000084, + 0xffffe000, + 0x00000074, + 0xfccc0000, + 0x00000078, + 0x00000000, + 0x0000007c, + 0x00000000, + 0x00000010, + 0xffffff00, + 0x00000014, + 0x00000000, + 0x00000018, + 0x00000000, + 0x00000800, +}; + +u32 nva3_pcopy_code[] = { +/* 0x0000: main */ + 0x04fe04bd, + 0x3517f000, + 0xf10010fe, + 0xf1040017, + 0xf0fff327, + 0x12d00023, + 0x0c25f0c0, + 0xf40012d0, + 0x17f11031, + 0x27f01200, + 0x0012d003, +/* 0x002f: spin */ + 0xf40031f4, + 0x0ef40028, +/* 0x0035: ih */ + 0x8001cffd, + 0xf40812c4, + 0x21f4060b, +/* 0x0041: ih_no_chsw */ + 0x0412c472, + 0xf4060bf4, +/* 0x004a: ih_no_cmd */ + 0x11c4c321, + 0x4001d00c, +/* 0x0052: swctx */ + 0x47f101f8, + 0x4bfe7700, + 0x0007fe00, + 0xf00204b9, + 0x01f40643, + 0x0604fa09, +/* 0x006b: swctx_load */ + 0xfa060ef4, +/* 0x006e: swctx_done */ + 0x03f80504, +/* 0x0072: chsw */ + 0x27f100f8, + 0x23cf1400, + 0x1e3fc800, + 0xf4170bf4, + 0x21f40132, + 0x1e3af052, + 0xf00023d0, + 0x24d00147, +/* 0x0093: chsw_no_unload */ + 0xcf00f880, + 0x3dc84023, + 0x220bf41e, + 0xf40131f4, + 0x57f05221, + 0x0367f004, +/* 0x00a8: chsw_load_ctx_dma */ + 0xa07856bc, + 0xb6018068, + 0x87d00884, + 0x0162b600, +/* 0x00bb: chsw_finish_load */ + 0xf0f018f4, + 0x23d00237, +/* 0x00c3: dispatch */ + 0xf100f880, + 0xcf190037, + 0x33cf4032, + 0xff24e400, + 0x1024b607, + 0x010057f1, + 0x74bd64bd, +/* 0x00dc: dispatch_loop */ + 0x58005658, + 0x50b60157, + 0x0446b804, + 0xbb4d08f4, + 0x47b80076, + 0x0f08f404, + 0xb60276bb, + 0x57bb0374, + 0xdf0ef400, +/* 0x0100: dispatch_valid_mthd */ + 0xb60246bb, + 0x45bb0344, + 0x01459800, + 0xb00453fd, + 0x1bf40054, + 0x00455820, + 0xb0014658, + 0x1bf40064, + 0x00538009, +/* 0x0127: dispatch_cmd */ + 0xf4300ef4, + 0x55f90132, + 0xf40c01f4, +/* 0x0132: dispatch_invalid_bitfield */ + 0x25f0250e, +/* 0x0135: dispatch_illegal_mthd */ + 0x0125f002, +/* 0x0138: dispatch_error */ + 0x100047f1, + 0xd00042d0, + 0x27f04043, + 0x0002d040, +/* 0x0148: hostirq_wait */ + 0xf08002cf, + 0x24b04024, + 0xf71bf400, +/* 0x0154: dispatch_done */ + 0x1d0027f1, + 0xd00137f0, + 0x00f80023, +/* 0x0160: cmd_nop */ +/* 0x0162: cmd_pm_trigger */ + 0x27f100f8, + 0x34bd2200, + 0xd00233f0, + 0x00f80023, +/* 0x0170: cmd_dma */ + 0x012842b7, + 0xf00145b6, + 0x43801e39, + 0x0040b701, + 0x0644b606, + 0xf80043d0, +/* 0x0189: cmd_exec_set_format */ + 0xf030f400, + 0xb00001b0, + 0x01b00101, + 0x0301b002, + 0xc71d0498, + 0x50b63045, + 0x3446c701, + 0xc70160b6, + 0x70b63847, + 0x0232f401, + 0x94bd84bd, +/* 0x01b4: ncomp_loop */ + 0xb60f4ac4, + 0xb4bd0445, +/* 0x01bc: bpc_loop */ + 0xf404a430, + 0xa5ff0f18, + 0x00cbbbc0, + 0xf40231f4, +/* 0x01ce: cmp_c0 */ + 0x1bf4220e, + 0x10c7f00c, + 0xf400cbbb, +/* 0x01da: cmp_c1 */ + 0xa430160e, + 0x0c18f406, + 0xbb14c7f0, + 0x0ef400cb, +/* 0x01e9: cmp_zero */ + 0x80c7f107, +/* 0x01ed: bpc_next */ + 0x01c83800, + 0xb60180b6, + 0xb5b801b0, + 0xc308f404, + 0xb80190b6, + 0x08f40497, + 0x0065fdb2, + 0x98110680, + 0x68fd2008, + 0x0502f400, +/* 0x0216: dst_xcnt */ + 0x75fd64bd, + 0x1c078000, + 0xf10078fd, + 0xb6081057, + 0x56d00654, + 0x4057d000, + 0x080050b7, + 0xb61c0698, + 0x64b60162, + 0x11079808, + 0xfd0172b6, + 0x56d00567, + 0x0050b700, + 0x0060b401, + 0xb40056d0, + 0x56d00160, + 0x0260b440, + 0xb48056d0, + 0x56d00360, + 0x0050b7c0, + 0x1e069804, + 0x980056d0, + 0x56d01f06, + 0x1030f440, +/* 0x0276: cmd_exec_set_surface_tiled */ + 0x579800f8, + 0x6879c70a, + 0xb66478c7, + 0x77c70280, + 0x0e76b060, + 0xf0091bf4, + 0x0ef40477, +/* 0x0291: xtile64 */ + 0x027cf00f, + 0xfd1170b6, + 0x77f00947, +/* 0x029d: xtileok */ + 0x0f5a9806, + 0xfd115b98, + 0xb7f000ab, + 0x04b7bb01, + 0xff01b2b6, + 0xa7bbc4ab, + 0x105d9805, + 0xbb01e7f0, + 0xe2b604e8, + 0xb4deff01, + 0xb605d8bb, + 0xef9401e0, + 0x02ebbb0c, + 0xf005fefd, + 0x60b7026c, + 0x64b60208, + 0x006fd008, + 0xbb04b7bb, + 0x5f9800cb, + 0x115b980b, + 0xf000fbfd, + 0xb7bb01b7, + 0x01b2b604, + 0xbb00fbbb, + 0xf0f905f7, + 0xf00c5f98, + 0xb8bb01b7, + 0x01b2b604, + 0xbb00fbbb, + 0xf0f905f8, + 0xb60078bb, + 0xb7f00282, + 0x04b8bb01, + 0x9804b9bb, + 0xe7f00e58, + 0x04e9bb01, + 0xff01e2b6, + 0xf7bbf48e, + 0x00cfbb04, + 0xbb0079bb, + 0xf0fc0589, + 0xd9fd90fc, + 0x00adbb00, + 0xfd0089fd, + 0xa8bb008f, + 0x04a7bb00, + 0xbb0192b6, + 0x69d00497, + 0x08579880, + 0xbb075898, + 0x7abb00ac, + 0x0081b600, + 0xfd1084b6, + 0x62b7058b, + 0x67d00600, + 0x0060b700, + 0x0068d004, +/* 0x0382: cmd_exec_set_surface_linear */ + 0x6cf000f8, + 0x0260b702, + 0x0864b602, + 0xd0085798, + 0x60b70067, + 0x57980400, + 0x1074b607, + 0xb70067d0, + 0x98040060, + 0x67d00957, +/* 0x03ab: cmd_exec_wait */ + 0xf900f800, + 0xf110f900, + 0xb6080007, +/* 0x03b6: loop */ + 0x01cf0604, + 0x0114f000, + 0xfcfa1bf4, + 0xf800fc10, +/* 0x03c5: cmd_exec_query */ + 0x0d34c800, + 0xf5701bf4, + 0xf103ab21, + 0xb6080c47, + 0x05980644, + 0x0450b605, + 0xd00045d0, + 0x57f04040, + 0x8045d00c, + 0x040040b7, + 0xb6040598, + 0x45d01054, + 0x0040b700, + 0x0057f105, + 0x0153f00b, + 0xf10045d0, + 0xb6404057, + 0x53f10154, + 0x45d08080, + 0x1057f140, + 0x1253f111, + 0x8045d013, + 0x151457f1, + 0x171653f1, + 0xf1c045d0, + 0xf0260157, + 0x47f10153, + 0x44b60800, + 0x0045d006, +/* 0x0438: query_counter */ + 0x03ab21f5, + 0x080c47f1, + 0x980644b6, + 0x45d00505, + 0x4040d000, + 0xd00457f0, + 0x40b78045, + 0x05980400, + 0x1054b604, + 0xb70045d0, + 0xf1050040, + 0xd0030057, + 0x57f10045, + 0x53f11110, + 0x45d01312, + 0x06059840, + 0x050040b7, + 0xf10045d0, + 0xf0260157, + 0x47f10153, + 0x44b60800, + 0x0045d006, +/* 0x0492: cmd_exec */ + 0x21f500f8, + 0x3fc803ab, + 0x0e0bf400, + 0x018921f5, + 0x020047f1, +/* 0x04a7: cmd_exec_no_format */ + 0xf11e0ef4, + 0xb6081067, + 0x77f00664, + 0x11078001, + 0x981c0780, + 0x67d02007, + 0x4067d000, +/* 0x04c2: cmd_exec_init_src_surface */ + 0x32f444bd, + 0xc854bd02, + 0x0bf4043f, + 0x8221f50a, + 0x0a0ef403, +/* 0x04d4: src_tiled */ + 0x027621f5, +/* 0x04db: cmd_exec_init_dst_surface */ + 0xf40749f0, + 0x57f00231, + 0x083fc82c, + 0xf50a0bf4, + 0xf4038221, +/* 0x04ee: dst_tiled */ + 0x21f50a0e, + 0x49f00276, +/* 0x04f5: cmd_exec_kick */ + 0x0057f108, + 0x0654b608, + 0xd0210698, + 0x67f04056, + 0x0063f141, + 0x0546fd44, + 0xc80054d0, + 0x0bf40c3f, + 0xc521f507, +/* 0x0519: cmd_exec_done */ +/* 0x051b: cmd_wrcache_flush */ + 0xf100f803, + 0xbd220027, + 0x0133f034, + 0xf80023d0, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h new file mode 100644 index 0000000..cd879f3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h @@ -0,0 +1,606 @@ +u32 nvc0_pcopy_data[] = { +/* 0x0000: ctx_object */ + 0x00000000, +/* 0x0004: ctx_query_address_high */ + 0x00000000, +/* 0x0008: ctx_query_address_low */ + 0x00000000, +/* 0x000c: ctx_query_counter */ + 0x00000000, +/* 0x0010: ctx_src_address_high */ + 0x00000000, +/* 0x0014: ctx_src_address_low */ + 0x00000000, +/* 0x0018: ctx_src_pitch */ + 0x00000000, +/* 0x001c: ctx_src_tile_mode */ + 0x00000000, +/* 0x0020: ctx_src_xsize */ + 0x00000000, +/* 0x0024: ctx_src_ysize */ + 0x00000000, +/* 0x0028: ctx_src_zsize */ + 0x00000000, +/* 0x002c: ctx_src_zoff */ + 0x00000000, +/* 0x0030: ctx_src_xoff */ + 0x00000000, +/* 0x0034: ctx_src_yoff */ + 0x00000000, +/* 0x0038: ctx_src_cpp */ + 0x00000000, +/* 0x003c: ctx_dst_address_high */ + 0x00000000, +/* 0x0040: ctx_dst_address_low */ + 0x00000000, +/* 0x0044: ctx_dst_pitch */ + 0x00000000, +/* 0x0048: ctx_dst_tile_mode */ + 0x00000000, +/* 0x004c: ctx_dst_xsize */ + 0x00000000, +/* 0x0050: ctx_dst_ysize */ + 0x00000000, +/* 0x0054: ctx_dst_zsize */ + 0x00000000, +/* 0x0058: ctx_dst_zoff */ + 0x00000000, +/* 0x005c: ctx_dst_xoff */ + 0x00000000, +/* 0x0060: ctx_dst_yoff */ + 0x00000000, +/* 0x0064: ctx_dst_cpp */ + 0x00000000, +/* 0x0068: ctx_format */ + 0x00000000, +/* 0x006c: ctx_swz_const0 */ + 0x00000000, +/* 0x0070: ctx_swz_const1 */ + 0x00000000, +/* 0x0074: ctx_xcnt */ + 0x00000000, +/* 0x0078: ctx_ycnt */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0100: dispatch_table */ + 0x00010000, + 0x00000000, + 0x00000000, + 0x00010040, + 0x0001019f, + 0x00000000, + 0x00010050, + 0x000101a1, + 0x00000000, + 0x00070080, + 0x0000001c, + 0xfffff000, + 0x00000020, + 0xfff80000, + 0x00000024, + 0xffffe000, + 0x00000028, + 0xfffff800, + 0x0000002c, + 0xfffff000, + 0x00000030, + 0xfff80000, + 0x00000034, + 0xffffe000, + 0x00070088, + 0x00000048, + 0xfffff000, + 0x0000004c, + 0xfff80000, + 0x00000050, + 0xffffe000, + 0x00000054, + 0xfffff800, + 0x00000058, + 0xfffff000, + 0x0000005c, + 0xfff80000, + 0x00000060, + 0xffffe000, + 0x000200c0, + 0x000104b8, + 0x00000000, + 0x00010541, + 0x00000000, + 0x000e00c3, + 0x00000010, + 0xffffff00, + 0x00000014, + 0x00000000, + 0x0000003c, + 0xffffff00, + 0x00000040, + 0x00000000, + 0x00000018, + 0xfff80000, + 0x00000044, + 0xfff80000, + 0x00000074, + 0xffff0000, + 0x00000078, + 0xffffe000, + 0x00000068, + 0xfccc0000, + 0x0000006c, + 0x00000000, + 0x00000070, + 0x00000000, + 0x00000004, + 0xffffff00, + 0x00000008, + 0x00000000, + 0x0000000c, + 0x00000000, + 0x00000800, +}; + +u32 nvc0_pcopy_code[] = { +/* 0x0000: main */ + 0x04fe04bd, + 0x3517f000, + 0xf10010fe, + 0xf1040017, + 0xf0fff327, + 0x12d00023, + 0x0c25f0c0, + 0xf40012d0, + 0x17f11031, + 0x27f01200, + 0x0012d003, +/* 0x002f: spin */ + 0xf40031f4, + 0x0ef40028, +/* 0x0035: ih */ + 0x8001cffd, + 0xf40812c4, + 0x21f4060b, +/* 0x0041: ih_no_chsw */ + 0x0412c4ca, + 0xf5070bf4, +/* 0x004b: ih_no_cmd */ + 0xc4010221, + 0x01d00c11, +/* 0x0053: swctx */ + 0xf101f840, + 0xfe770047, + 0x47f1004b, + 0x44cf2100, + 0x0144f000, + 0xb60444b6, + 0xf7f13040, + 0xf4b6061c, + 0x1457f106, + 0x00f5d101, + 0xb6043594, + 0x57fe0250, + 0x0145fe00, + 0x010052b7, + 0x00ff67f1, + 0x56fd60bd, + 0x0253f004, + 0xf80545fa, + 0x0053f003, + 0xd100e7f0, + 0x549800fe, + 0x0845b600, + 0xb6015698, + 0x46fd1864, + 0x0047fe05, + 0xf00204b9, + 0x01f40643, + 0x0604fa09, +/* 0x00c3: swctx_load */ + 0xfa060ef4, +/* 0x00c6: swctx_done */ + 0x03f80504, +/* 0x00ca: chsw */ + 0x27f100f8, + 0x23cf1400, + 0x1e3fc800, + 0xf4170bf4, + 0x21f40132, + 0x1e3af053, + 0xf00023d0, + 0x24d00147, +/* 0x00eb: chsw_no_unload */ + 0xcf00f880, + 0x3dc84023, + 0x090bf41e, + 0xf40131f4, +/* 0x00fa: chsw_finish_load */ + 0x37f05321, + 0x8023d002, +/* 0x0102: dispatch */ + 0x37f100f8, + 0x32cf1900, + 0x0033cf40, + 0x07ff24e4, + 0xf11024b6, + 0xbd010057, +/* 0x011b: dispatch_loop */ + 0x5874bd64, + 0x57580056, + 0x0450b601, + 0xf40446b8, + 0x76bb4d08, + 0x0447b800, + 0xbb0f08f4, + 0x74b60276, + 0x0057bb03, +/* 0x013f: dispatch_valid_mthd */ + 0xbbdf0ef4, + 0x44b60246, + 0x0045bb03, + 0xfd014598, + 0x54b00453, + 0x201bf400, + 0x58004558, + 0x64b00146, + 0x091bf400, + 0xf4005380, +/* 0x0166: dispatch_cmd */ + 0x32f4300e, + 0xf455f901, + 0x0ef40c01, +/* 0x0171: dispatch_invalid_bitfield */ + 0x0225f025, +/* 0x0174: dispatch_illegal_mthd */ +/* 0x0177: dispatch_error */ + 0xf10125f0, + 0xd0100047, + 0x43d00042, + 0x4027f040, +/* 0x0187: hostirq_wait */ + 0xcf0002d0, + 0x24f08002, + 0x0024b040, +/* 0x0193: dispatch_done */ + 0xf1f71bf4, + 0xf01d0027, + 0x23d00137, +/* 0x019f: cmd_nop */ + 0xf800f800, +/* 0x01a1: cmd_pm_trigger */ + 0x0027f100, + 0xf034bd22, + 0x23d00233, +/* 0x01af: cmd_exec_set_format */ + 0xf400f800, + 0x01b0f030, + 0x0101b000, + 0xb00201b0, + 0x04980301, + 0x3045c71a, + 0xc70150b6, + 0x60b63446, + 0x3847c701, + 0xf40170b6, + 0x84bd0232, +/* 0x01da: ncomp_loop */ + 0x4ac494bd, + 0x0445b60f, +/* 0x01e2: bpc_loop */ + 0xa430b4bd, + 0x0f18f404, + 0xbbc0a5ff, + 0x31f400cb, + 0x220ef402, +/* 0x01f4: cmp_c0 */ + 0xf00c1bf4, + 0xcbbb10c7, + 0x160ef400, +/* 0x0200: cmp_c1 */ + 0xf406a430, + 0xc7f00c18, + 0x00cbbb14, +/* 0x020f: cmp_zero */ + 0xf1070ef4, +/* 0x0213: bpc_next */ + 0x380080c7, + 0x80b601c8, + 0x01b0b601, + 0xf404b5b8, + 0x90b6c308, + 0x0497b801, + 0xfdb208f4, + 0x06800065, + 0x1d08980e, + 0xf40068fd, + 0x64bd0502, +/* 0x023c: dst_xcnt */ + 0x800075fd, + 0x78fd1907, + 0x1057f100, + 0x0654b608, + 0xd00056d0, + 0x50b74057, + 0x06980800, + 0x0162b619, + 0x980864b6, + 0x72b60e07, + 0x0567fd01, + 0xb70056d0, + 0xb4010050, + 0x56d00060, + 0x0160b400, + 0xb44056d0, + 0x56d00260, + 0x0360b480, + 0xb7c056d0, + 0x98040050, + 0x56d01b06, + 0x1c069800, + 0xf44056d0, + 0x00f81030, +/* 0x029c: cmd_exec_set_surface_tiled */ + 0xc7075798, + 0x78c76879, + 0x0380b664, + 0xb06077c7, + 0x1bf40e76, + 0x0477f009, +/* 0x02b7: xtile64 */ + 0xf00f0ef4, + 0x70b6027c, + 0x0947fd11, +/* 0x02c3: xtileok */ + 0x980677f0, + 0x5b980c5a, + 0x00abfd0e, + 0xbb01b7f0, + 0xb2b604b7, + 0xc4abff01, + 0x9805a7bb, + 0xe7f00d5d, + 0x04e8bb01, + 0xff01e2b6, + 0xd8bbb4de, + 0x01e0b605, + 0xbb0cef94, + 0xfefd02eb, + 0x026cf005, + 0x020860b7, + 0xd00864b6, + 0xb7bb006f, + 0x00cbbb04, + 0x98085f98, + 0xfbfd0e5b, + 0x01b7f000, + 0xb604b7bb, + 0xfbbb01b2, + 0x05f7bb00, + 0x5f98f0f9, + 0x01b7f009, + 0xb604b8bb, + 0xfbbb01b2, + 0x05f8bb00, + 0x78bbf0f9, + 0x0282b600, + 0xbb01b7f0, + 0xb9bb04b8, + 0x0b589804, + 0xbb01e7f0, + 0xe2b604e9, + 0xf48eff01, + 0xbb04f7bb, + 0x79bb00cf, + 0x0589bb00, + 0x90fcf0fc, + 0xbb00d9fd, + 0x89fd00ad, + 0x008ffd00, + 0xbb00a8bb, + 0x92b604a7, + 0x0497bb01, + 0x988069d0, + 0x58980557, + 0x00acbb04, + 0xb6007abb, + 0x84b60081, + 0x058bfd10, + 0x060062b7, + 0xb70067d0, + 0xd0040060, + 0x00f80068, +/* 0x03a8: cmd_exec_set_surface_linear */ + 0xb7026cf0, + 0xb6020260, + 0x57980864, + 0x0067d005, + 0x040060b7, + 0xb6045798, + 0x67d01074, + 0x0060b700, + 0x06579804, + 0xf80067d0, +/* 0x03d1: cmd_exec_wait */ + 0xf900f900, + 0x0007f110, + 0x0604b608, +/* 0x03dc: loop */ + 0xf00001cf, + 0x1bf40114, + 0xfc10fcfa, +/* 0x03eb: cmd_exec_query */ + 0xc800f800, + 0x1bf40d34, + 0xd121f570, + 0x0c47f103, + 0x0644b608, + 0xb6020598, + 0x45d00450, + 0x4040d000, + 0xd00c57f0, + 0x40b78045, + 0x05980400, + 0x1054b601, + 0xb70045d0, + 0xf1050040, + 0xf00b0057, + 0x45d00153, + 0x4057f100, + 0x0154b640, + 0x808053f1, + 0xf14045d0, + 0xf1111057, + 0xd0131253, + 0x57f18045, + 0x53f11514, + 0x45d01716, + 0x0157f1c0, + 0x0153f026, + 0x080047f1, + 0xd00644b6, +/* 0x045e: query_counter */ + 0x21f50045, + 0x47f103d1, + 0x44b6080c, + 0x02059806, + 0xd00045d0, + 0x57f04040, + 0x8045d004, + 0x040040b7, + 0xb6010598, + 0x45d01054, + 0x0040b700, + 0x0057f105, + 0x0045d003, + 0x111057f1, + 0x131253f1, + 0x984045d0, + 0x40b70305, + 0x45d00500, + 0x0157f100, + 0x0153f026, + 0x080047f1, + 0xd00644b6, + 0x00f80045, +/* 0x04b8: cmd_exec */ + 0x03d121f5, + 0xf4003fc8, + 0x21f50e0b, + 0x47f101af, + 0x0ef40200, +/* 0x04cd: cmd_exec_no_format */ + 0x1067f11e, + 0x0664b608, + 0x800177f0, + 0x07800e07, + 0x1d079819, + 0xd00067d0, + 0x44bd4067, +/* 0x04e8: cmd_exec_init_src_surface */ + 0xbd0232f4, + 0x043fc854, + 0xf50a0bf4, + 0xf403a821, +/* 0x04fa: src_tiled */ + 0x21f50a0e, + 0x49f0029c, +/* 0x0501: cmd_exec_init_dst_surface */ + 0x0231f407, + 0xc82c57f0, + 0x0bf4083f, + 0xa821f50a, + 0x0a0ef403, +/* 0x0514: dst_tiled */ + 0x029c21f5, +/* 0x051b: cmd_exec_kick */ + 0xf10849f0, + 0xb6080057, + 0x06980654, + 0x4056d01e, + 0xf14167f0, + 0xfd440063, + 0x54d00546, + 0x0c3fc800, + 0xf5070bf4, +/* 0x053f: cmd_exec_done */ + 0xf803eb21, +/* 0x0541: cmd_wrcache_flush */ + 0x0027f100, + 0xf034bd22, + 0x23d00133, + 0x0000f800, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c new file mode 100644 index 0000000..fec5246 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -0,0 +1,203 @@ +/* + * Copyright 2011 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: + * + * 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 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 +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include +#include "fuc/nva3.fuc.h" + +struct nva3_copy_engine { + struct nouveau_exec_engine base; +}; + +static int +nva3_copy_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 *ctx = NULL; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &ctx); + if (ret) + return ret; + + nv_wo32(ramin, 0xc0, 0x00190000); + nv_wo32(ramin, 0xc4, ctx->vinst + ctx->size - 1); + nv_wo32(ramin, 0xc8, ctx->vinst); + nv_wo32(ramin, 0xcc, 0x00000000); + nv_wo32(ramin, 0xd0, 0x00000000); + nv_wo32(ramin, 0xd4, 0x00000000); + dev_priv->engine.instmem.flush(dev); + + atomic_inc(&chan->vm->engref[engine]); + chan->engctx[engine] = ctx; + return 0; +} + +static int +nva3_copy_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + struct nouveau_gpuobj *ctx = chan->engctx[engine]; + + /* fuc engine doesn't need an object, our ramht code does.. */ + ctx->engine = 3; + ctx->class = class; + return nouveau_ramht_insert(chan, handle, ctx); +} + +static void +nva3_copy_context_del(struct nouveau_channel *chan, int engine) +{ + struct nouveau_gpuobj *ctx = chan->engctx[engine]; + int i; + + for (i = 0xc0; i <= 0xd4; i += 4) + nv_wo32(chan->ramin, i, 0x00000000); + + atomic_dec(&chan->vm->engref[engine]); + nouveau_gpuobj_ref(NULL, &ctx); + chan->engctx[engine] = ctx; +} + +static void +nva3_copy_tlb_flush(struct drm_device *dev, int engine) +{ + nv50_vm_flush_engine(dev, 0x0d); +} + +static int +nva3_copy_init(struct drm_device *dev, int engine) +{ + int i; + + nv_mask(dev, 0x000200, 0x00002000, 0x00000000); + nv_mask(dev, 0x000200, 0x00002000, 0x00002000); + nv_wr32(dev, 0x104014, 0xffffffff); /* disable all interrupts */ + + /* upload ucode */ + nv_wr32(dev, 0x1041c0, 0x01000000); + for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++) + nv_wr32(dev, 0x1041c4, nva3_pcopy_data[i]); + + nv_wr32(dev, 0x104180, 0x01000000); + for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(dev, 0x104188, i >> 6); + nv_wr32(dev, 0x104184, nva3_pcopy_code[i]); + } + + /* start it running */ + nv_wr32(dev, 0x10410c, 0x00000000); + nv_wr32(dev, 0x104104, 0x00000000); /* ENTRY */ + nv_wr32(dev, 0x104100, 0x00000002); /* TRIGGER */ + return 0; +} + +static int +nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) +{ + nv_mask(dev, 0x104048, 0x00000003, 0x00000000); + nv_wr32(dev, 0x104014, 0xffffffff); + return 0; +} + +static struct nouveau_enum nva3_copy_isr_error_name[] = { + { 0x0001, "ILLEGAL_MTHD" }, + { 0x0002, "INVALID_ENUM" }, + { 0x0003, "INVALID_BITFIELD" }, + {} +}; + +static void +nva3_copy_isr(struct drm_device *dev) +{ + u32 dispatch = nv_rd32(dev, 0x10401c); + u32 stat = nv_rd32(dev, 0x104008) & dispatch & ~(dispatch >> 16); + u32 inst = nv_rd32(dev, 0x104050) & 0x3fffffff; + u32 ssta = nv_rd32(dev, 0x104040) & 0x0000ffff; + u32 addr = nv_rd32(dev, 0x104040) >> 16; + u32 mthd = (addr & 0x07ff) << 2; + u32 subc = (addr & 0x3800) >> 11; + u32 data = nv_rd32(dev, 0x104044); + int chid = nv50_graph_isr_chid(dev, inst); + + if (stat & 0x00000040) { + NV_INFO(dev, "PCOPY: DISPATCH_ERROR ["); + nouveau_enum_print(nva3_copy_isr_error_name, ssta); + printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n", + chid, inst, subc, mthd, data); + nv_wr32(dev, 0x104004, 0x00000040); + stat &= ~0x00000040; + } + + if (stat) { + NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat); + nv_wr32(dev, 0x104004, stat); + } + nv50_fb_vm_trap(dev, 1); +} + +static void +nva3_copy_destroy(struct drm_device *dev, int engine) +{ + struct nva3_copy_engine *pcopy = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 22); + + NVOBJ_ENGINE_DEL(dev, COPY0); + kfree(pcopy); +} + +int +nva3_copy_create(struct drm_device *dev) +{ + struct nva3_copy_engine *pcopy; + + pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL); + if (!pcopy) + return -ENOMEM; + + pcopy->base.destroy = nva3_copy_destroy; + pcopy->base.init = nva3_copy_init; + pcopy->base.fini = nva3_copy_fini; + pcopy->base.context_new = nva3_copy_context_new; + pcopy->base.context_del = nva3_copy_context_del; + pcopy->base.object_new = nva3_copy_object_new; + pcopy->base.tlb_flush = nva3_copy_tlb_flush; + + nouveau_irq_register(dev, 22, nva3_copy_isr); + + NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base); + NVOBJ_CLASS(dev, 0x85b5, COPY0); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c new file mode 100644 index 0000000..90a069b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -0,0 +1,243 @@ +/* + * Copyright 2011 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: + * + * 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 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 +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include +#include "fuc/nvc0.fuc.h" + +struct nvc0_copy_engine { + struct nouveau_exec_engine base; + u32 irq; + u32 pmc; + u32 fuc; + u32 ctx; +}; + +static int +nvc0_copy_context_new(struct nouveau_channel *chan, int engine) +{ + struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, 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 *ctx = NULL; + int ret; + + ret = nouveau_gpuobj_new(dev, chan, 256, 256, + NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER | + NVOBJ_FLAG_ZERO_ALLOC, &ctx); + if (ret) + return ret; + + nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst)); + nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst)); + dev_priv->engine.instmem.flush(dev); + + chan->engctx[engine] = ctx; + return 0; +} + +static int +nvc0_copy_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + return 0; +} + +static void +nvc0_copy_context_del(struct nouveau_channel *chan, int engine) +{ + struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); + struct nouveau_gpuobj *ctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + u32 inst; + + inst = (chan->ramin->vinst >> 12); + inst |= 0x40000000; + + /* disable fifo access */ + nv_wr32(dev, pcopy->fuc + 0x048, 0x00000000); + /* mark channel as unloaded if it's currently active */ + if (nv_rd32(dev, pcopy->fuc + 0x050) == inst) + nv_mask(dev, pcopy->fuc + 0x050, 0x40000000, 0x00000000); + /* mark next channel as invalid if it's about to be loaded */ + if (nv_rd32(dev, pcopy->fuc + 0x054) == inst) + nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000); + /* restore fifo access */ + nv_wr32(dev, pcopy->fuc + 0x048, 0x00000003); + + nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000); + nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000); + nouveau_gpuobj_ref(NULL, &ctx); + + chan->engctx[engine] = ctx; +} + +static int +nvc0_copy_init(struct drm_device *dev, int engine) +{ + struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + int i; + + nv_mask(dev, 0x000200, pcopy->pmc, 0x00000000); + nv_mask(dev, 0x000200, pcopy->pmc, pcopy->pmc); + nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff); + + nv_wr32(dev, pcopy->fuc + 0x1c0, 0x01000000); + for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++) + nv_wr32(dev, pcopy->fuc + 0x1c4, nvc0_pcopy_data[i]); + + nv_wr32(dev, pcopy->fuc + 0x180, 0x01000000); + for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(dev, pcopy->fuc + 0x188, i >> 6); + nv_wr32(dev, pcopy->fuc + 0x184, nvc0_pcopy_code[i]); + } + + nv_wr32(dev, pcopy->fuc + 0x084, engine - NVOBJ_ENGINE_COPY0); + nv_wr32(dev, pcopy->fuc + 0x10c, 0x00000000); + nv_wr32(dev, pcopy->fuc + 0x104, 0x00000000); /* ENTRY */ + nv_wr32(dev, pcopy->fuc + 0x100, 0x00000002); /* TRIGGER */ + return 0; +} + +static int +nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) +{ + struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + + nv_mask(dev, pcopy->fuc + 0x048, 0x00000003, 0x00000000); + + /* trigger fuc context unload */ + nv_wait(dev, pcopy->fuc + 0x008, 0x0000000c, 0x00000000); + nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000); + nv_wr32(dev, pcopy->fuc + 0x000, 0x00000008); + nv_wait(dev, pcopy->fuc + 0x008, 0x00000008, 0x00000000); + + nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff); + return 0; +} + +static struct nouveau_enum nvc0_copy_isr_error_name[] = { + { 0x0001, "ILLEGAL_MTHD" }, + { 0x0002, "INVALID_ENUM" }, + { 0x0003, "INVALID_BITFIELD" }, + {} +}; + +static void +nvc0_copy_isr(struct drm_device *dev, int engine) +{ + struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + u32 disp = nv_rd32(dev, pcopy->fuc + 0x01c); + u32 stat = nv_rd32(dev, pcopy->fuc + 0x008) & disp & ~(disp >> 16); + u64 inst = (u64)(nv_rd32(dev, pcopy->fuc + 0x050) & 0x0fffffff) << 12; + u32 chid = nvc0_graph_isr_chid(dev, inst); + u32 ssta = nv_rd32(dev, pcopy->fuc + 0x040) & 0x0000ffff; + u32 addr = nv_rd32(dev, pcopy->fuc + 0x040) >> 16; + u32 mthd = (addr & 0x07ff) << 2; + u32 subc = (addr & 0x3800) >> 11; + u32 data = nv_rd32(dev, pcopy->fuc + 0x044); + + if (stat & 0x00000040) { + NV_INFO(dev, "PCOPY: DISPATCH_ERROR ["); + nouveau_enum_print(nvc0_copy_isr_error_name, ssta); + printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", + chid, inst, subc, mthd, data); + nv_wr32(dev, pcopy->fuc + 0x004, 0x00000040); + stat &= ~0x00000040; + } + + if (stat) { + NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat); + nv_wr32(dev, pcopy->fuc + 0x004, stat); + } +} + +static void +nvc0_copy_isr_0(struct drm_device *dev) +{ + nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY0); +} + +static void +nvc0_copy_isr_1(struct drm_device *dev) +{ + nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY1); +} + +static void +nvc0_copy_destroy(struct drm_device *dev, int engine) +{ + struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, pcopy->irq); + + if (engine == NVOBJ_ENGINE_COPY0) + NVOBJ_ENGINE_DEL(dev, COPY0); + else + NVOBJ_ENGINE_DEL(dev, COPY1); + kfree(pcopy); +} + +int +nvc0_copy_create(struct drm_device *dev, int engine) +{ + struct nvc0_copy_engine *pcopy; + + pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL); + if (!pcopy) + return -ENOMEM; + + pcopy->base.destroy = nvc0_copy_destroy; + pcopy->base.init = nvc0_copy_init; + pcopy->base.fini = nvc0_copy_fini; + pcopy->base.context_new = nvc0_copy_context_new; + pcopy->base.context_del = nvc0_copy_context_del; + pcopy->base.object_new = nvc0_copy_object_new; + + if (engine == 0) { + pcopy->irq = 5; + pcopy->pmc = 0x00000040; + pcopy->fuc = 0x104000; + pcopy->ctx = 0x0230; + nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_0); + NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base); + NVOBJ_CLASS(dev, 0x90b5, COPY0); + } else { + pcopy->irq = 6; + pcopy->pmc = 0x00000080; + pcopy->fuc = 0x105000; + pcopy->ctx = 0x0240; + nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_1); + NVOBJ_ENGINE_ADD(dev, COPY1, &pcopy->base); + NVOBJ_CLASS(dev, 0x90b8, COPY1); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc new file mode 100644 index 0000000..7393813 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc @@ -0,0 +1,698 @@ +/* + * fuc microcode for nv98 pcrypt engine + * Copyright (C) 2010 Marcin KoÅ›cielnicki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +.section #nv98_pcrypt_data + +ctx_dma: +ctx_dma_query: .b32 0 +ctx_dma_src: .b32 0 +ctx_dma_dst: .b32 0 +.equ #dma_count 3 +ctx_query_address_high: .b32 0 +ctx_query_address_low: .b32 0 +ctx_query_counter: .b32 0 +ctx_cond_address_high: .b32 0 +ctx_cond_address_low: .b32 0 +ctx_cond_off: .b32 0 +ctx_src_address_high: .b32 0 +ctx_src_address_low: .b32 0 +ctx_dst_address_high: .b32 0 +ctx_dst_address_low: .b32 0 +ctx_mode: .b32 0 +.align 16 +ctx_key: .skip 16 +ctx_iv: .skip 16 + +.align 0x80 +swap: +.skip 32 + +.align 8 +common_cmd_dtable: +.b32 #ctx_query_address_high + 0x20000 ~0xff +.b32 #ctx_query_address_low + 0x20000 ~0xfffffff0 +.b32 #ctx_query_counter + 0x20000 ~0xffffffff +.b32 #cmd_query_get + 0x00000 ~1 +.b32 #ctx_cond_address_high + 0x20000 ~0xff +.b32 #ctx_cond_address_low + 0x20000 ~0xfffffff0 +.b32 #cmd_cond_mode + 0x00000 ~7 +.b32 #cmd_wrcache_flush + 0x00000 ~0 +.equ #common_cmd_max 0x88 + + +.align 8 +engine_cmd_dtable: +.b32 #ctx_key + 0x0 + 0x20000 ~0xffffffff +.b32 #ctx_key + 0x4 + 0x20000 ~0xffffffff +.b32 #ctx_key + 0x8 + 0x20000 ~0xffffffff +.b32 #ctx_key + 0xc + 0x20000 ~0xffffffff +.b32 #ctx_iv + 0x0 + 0x20000 ~0xffffffff +.b32 #ctx_iv + 0x4 + 0x20000 ~0xffffffff +.b32 #ctx_iv + 0x8 + 0x20000 ~0xffffffff +.b32 #ctx_iv + 0xc + 0x20000 ~0xffffffff +.b32 #ctx_src_address_high + 0x20000 ~0xff +.b32 #ctx_src_address_low + 0x20000 ~0xfffffff0 +.b32 #ctx_dst_address_high + 0x20000 ~0xff +.b32 #ctx_dst_address_low + 0x20000 ~0xfffffff0 +.b32 #crypt_cmd_mode + 0x00000 ~0xf +.b32 #crypt_cmd_length + 0x10000 ~0x0ffffff0 +.equ #engine_cmd_max 0xce + +.align 4 +crypt_dtable: +.b16 #crypt_copy_prep #crypt_do_inout +.b16 #crypt_store_prep #crypt_do_out +.b16 #crypt_ecb_e_prep #crypt_do_inout +.b16 #crypt_ecb_d_prep #crypt_do_inout +.b16 #crypt_cbc_e_prep #crypt_do_inout +.b16 #crypt_cbc_d_prep #crypt_do_inout +.b16 #crypt_pcbc_e_prep #crypt_do_inout +.b16 #crypt_pcbc_d_prep #crypt_do_inout +.b16 #crypt_cfb_e_prep #crypt_do_inout +.b16 #crypt_cfb_d_prep #crypt_do_inout +.b16 #crypt_ofb_prep #crypt_do_inout +.b16 #crypt_ctr_prep #crypt_do_inout +.b16 #crypt_cbc_mac_prep #crypt_do_in +.b16 #crypt_cmac_finish_complete_prep #crypt_do_in +.b16 #crypt_cmac_finish_partial_prep #crypt_do_in + +.align 0x100 + +.section #nv98_pcrypt_code + + // $r0 is always set to 0 in our code - this allows some space savings. + clear b32 $r0 + + // set up the interrupt handler + mov $r1 #ih + mov $iv0 $r1 + + // init stack pointer + mov $sp $r0 + + // set interrupt dispatch - route timer, fifo, ctxswitch to i0, others to host + movw $r1 0xfff0 + sethi $r1 0 + mov $r2 0x400 + iowr I[$r2 + 0x300] $r1 + + // enable the interrupts + or $r1 0xc + iowr I[$r2] $r1 + + // enable fifo access and context switching + mov $r1 3 + mov $r2 0x1200 + iowr I[$r2] $r1 + + // enable i0 delivery + bset $flags ie0 + + // sleep forver, waking only for interrupts. + bset $flags $p0 + spin: + sleep $p0 + bra #spin + +// i0 handler +ih: + // see which interrupts we got + iord $r1 I[$r0 + 0x200] + + and $r2 $r1 0x8 + cmpu b32 $r2 0 + bra e #noctx + + // context switch... prepare the regs for xfer + mov $r2 0x7700 + mov $xtargets $r2 + mov $xdbase $r0 + // 128-byte context. + mov $r2 0 + sethi $r2 0x50000 + + // read current channel + mov $r3 0x1400 + iord $r4 I[$r3] + // if bit 30 set, it's active, so we have to unload it first. + shl b32 $r5 $r4 1 + cmps b32 $r5 0 + bra nc #ctxload + + // unload the current channel - save the context + xdst $r0 $r2 + xdwait + // and clear bit 30, then write back + bclr $r4 0x1e + iowr I[$r3] $r4 + // tell PFIFO we unloaded + mov $r4 1 + iowr I[$r3 + 0x200] $r4 + + bra #noctx + + ctxload: + // no channel loaded - perhaps we're requested to load one + iord $r4 I[$r3 + 0x100] + shl b32 $r15 $r4 1 + cmps b32 $r15 0 + // if bit 30 of next channel not set, probably PFIFO is just + // killing a context. do a faux load, without the active bit. + bra nc #dummyload + + // ok, do a real context load. + xdld $r0 $r2 + xdwait + mov $r5 #ctx_dma + mov $r6 #dma_count - 1 + ctxload_dma_loop: + ld b32 $r7 D[$r5 + $r6 * 4] + add b32 $r8 $r6 0x180 + shl b32 $r8 8 + iowr I[$r8] $r7 + sub b32 $r6 1 + bra nc #ctxload_dma_loop + + dummyload: + // tell PFIFO we're done + mov $r5 2 + iowr I[$r3 + 0x200] $r5 + + noctx: + and $r2 $r1 0x4 + cmpu b32 $r2 0 + bra e #nocmd + + // incoming fifo command. + mov $r3 0x1900 + iord $r2 I[$r3 + 0x100] + iord $r3 I[$r3] + // extract the method + and $r4 $r2 0x7ff + // shift the addr to proper position if we need to interrupt later + shl b32 $r2 0x10 + + // mthd 0 and 0x100 [NAME, NOP]: ignore + and $r5 $r4 0x7bf + cmpu b32 $r5 0 + bra e #cmddone + + mov $r5 #engine_cmd_dtable - 0xc0 * 8 + mov $r6 #engine_cmd_max + cmpu b32 $r4 0xc0 + bra nc #dtable_cmd + mov $r5 #common_cmd_dtable - 0x80 * 8 + mov $r6 #common_cmd_max + cmpu b32 $r4 0x80 + bra nc #dtable_cmd + cmpu b32 $r4 0x60 + bra nc #dma_cmd + cmpu b32 $r4 0x50 + bra ne #illegal_mthd + + // mthd 0x140: PM_TRIGGER + mov $r2 0x2200 + clear b32 $r3 + sethi $r3 0x20000 + iowr I[$r2] $r3 + bra #cmddone + + dma_cmd: + // mthd 0x180...: DMA_* + cmpu b32 $r4 0x60+#dma_count + bra nc #illegal_mthd + shl b32 $r5 $r4 2 + add b32 $r5 (#ctx_dma - 0x60 * 4) & 0xffff + bset $r3 0x1e + st b32 D[$r5] $r3 + add b32 $r4 0x180 - 0x60 + shl b32 $r4 8 + iowr I[$r4] $r3 + bra #cmddone + + dtable_cmd: + cmpu b32 $r4 $r6 + bra nc #illegal_mthd + shl b32 $r4 3 + add b32 $r4 $r5 + ld b32 $r5 D[$r4 + 4] + and $r5 $r3 + cmpu b32 $r5 0 + bra ne #invalid_bitfield + ld b16 $r5 D[$r4] + ld b16 $r6 D[$r4 + 2] + cmpu b32 $r6 2 + bra e #cmd_setctx + ld b32 $r7 D[$r0 + #ctx_cond_off] + and $r6 $r7 + cmpu b32 $r6 1 + bra e #cmddone + call $r5 + bra $p1 #dispatch_error + bra #cmddone + + cmd_setctx: + st b32 D[$r5] $r3 + bra #cmddone + + + invalid_bitfield: + or $r2 1 + dispatch_error: + illegal_mthd: + mov $r4 0x1000 + iowr I[$r4] $r2 + iowr I[$r4 + 0x100] $r3 + mov $r4 0x40 + iowr I[$r0] $r4 + + im_loop: + iord $r4 I[$r0 + 0x200] + and $r4 0x40 + cmpu b32 $r4 0 + bra ne #im_loop + + cmddone: + // remove the command from FIFO + mov $r3 0x1d00 + mov $r4 1 + iowr I[$r3] $r4 + + nocmd: + // ack the processed interrupts + and $r1 $r1 0xc + iowr I[$r0 + 0x100] $r1 +iret + +cmd_query_get: + // if bit 0 of param set, trigger interrupt afterwards. + setp $p1 $r3 + or $r2 3 + + // read PTIMER, beware of races... + mov $r4 0xb00 + ptimer_retry: + iord $r6 I[$r4 + 0x100] + iord $r5 I[$r4] + iord $r7 I[$r4 + 0x100] + cmpu b32 $r6 $r7 + bra ne #ptimer_retry + + // prepare the query structure + ld b32 $r4 D[$r0 + #ctx_query_counter] + st b32 D[$r0 + #swap + 0x0] $r4 + st b32 D[$r0 + #swap + 0x4] $r0 + st b32 D[$r0 + #swap + 0x8] $r5 + st b32 D[$r0 + #swap + 0xc] $r6 + + // will use target 0, DMA_QUERY. + mov $xtargets $r0 + + ld b32 $r4 D[$r0 + #ctx_query_address_high] + shl b32 $r4 0x18 + mov $xdbase $r4 + + ld b32 $r4 D[$r0 + #ctx_query_address_low] + mov $r5 #swap + sethi $r5 0x20000 + xdst $r4 $r5 + xdwait + + ret + +cmd_cond_mode: + // if >= 5, INVALID_ENUM + bset $flags $p1 + or $r2 2 + cmpu b32 $r3 5 + bra nc #return + + // otherwise, no error. + bclr $flags $p1 + + // if < 2, no QUERY object is involved + cmpu b32 $r3 2 + bra nc #cmd_cond_mode_queryful + + xor $r3 1 + st b32 D[$r0 + #ctx_cond_off] $r3 + return: + ret + + cmd_cond_mode_queryful: + // ok, will need to pull a QUERY object, prepare offsets + ld b32 $r4 D[$r0 + #ctx_cond_address_high] + ld b32 $r5 D[$r0 + #ctx_cond_address_low] + and $r6 $r5 0xff + shr b32 $r5 8 + shl b32 $r4 0x18 + or $r4 $r5 + mov $xdbase $r4 + mov $xtargets $r0 + + // pull the first one + mov $r5 #swap + sethi $r5 0x20000 + xdld $r6 $r5 + + // if == 2, only a single QUERY is involved... + cmpu b32 $r3 2 + bra ne #cmd_cond_mode_double + + xdwait + ld b32 $r4 D[$r0 + #swap + 4] + cmpu b32 $r4 0 + xbit $r4 $flags z + st b32 D[$r0 + #ctx_cond_off] $r4 + ret + + // ok, we'll need to pull second one too + cmd_cond_mode_double: + add b32 $r6 0x10 + add b32 $r5 0x10 + xdld $r6 $r5 + xdwait + + // compare COUNTERs + ld b32 $r5 D[$r0 + #swap + 0x00] + ld b32 $r6 D[$r0 + #swap + 0x10] + cmpu b32 $r5 $r6 + xbit $r4 $flags z + + // compare RESen + ld b32 $r5 D[$r0 + #swap + 0x04] + ld b32 $r6 D[$r0 + #swap + 0x14] + cmpu b32 $r5 $r6 + xbit $r5 $flags z + and $r4 $r5 + + // and negate or not, depending on mode + cmpu b32 $r3 3 + xbit $r5 $flags z + xor $r4 $r5 + st b32 D[$r0 + #ctx_cond_off] $r4 + ret + +cmd_wrcache_flush: + bclr $flags $p1 + mov $r2 0x2200 + clear b32 $r3 + sethi $r3 0x10000 + iowr I[$r2] $r3 + ret + +crypt_cmd_mode: + // if >= 0xf, INVALID_ENUM + bset $flags $p1 + or $r2 2 + cmpu b32 $r3 0xf + bra nc #crypt_cmd_mode_return + + bclr $flags $p1 + st b32 D[$r0 + #ctx_mode] $r3 + + crypt_cmd_mode_return: + ret + +crypt_cmd_length: + // nop if length == 0 + cmpu b32 $r3 0 + bra e #crypt_cmd_mode_return + + // init key, IV + cxset 3 + mov $r4 #ctx_key + sethi $r4 0x70000 + xdst $r0 $r4 + mov $r4 #ctx_iv + sethi $r4 0x60000 + xdst $r0 $r4 + xdwait + ckeyreg $c7 + + // prepare the targets + mov $r4 0x2100 + mov $xtargets $r4 + + // prepare src address + ld b32 $r4 D[$r0 + #ctx_src_address_high] + ld b32 $r5 D[$r0 + #ctx_src_address_low] + shr b32 $r8 $r5 8 + shl b32 $r4 0x18 + or $r4 $r8 + and $r5 $r5 0xff + + // prepare dst address + ld b32 $r6 D[$r0 + #ctx_dst_address_high] + ld b32 $r7 D[$r0 + #ctx_dst_address_low] + shr b32 $r8 $r7 8 + shl b32 $r6 0x18 + or $r6 $r8 + and $r7 $r7 0xff + + // find the proper prep & do functions + ld b32 $r8 D[$r0 + #ctx_mode] + shl b32 $r8 2 + + // run prep + ld b16 $r9 D[$r8 + #crypt_dtable] + call $r9 + + // do it + ld b16 $r9 D[$r8 + #crypt_dtable + 2] + call $r9 + cxset 1 + xdwait + cxset 0x61 + xdwait + xdwait + + // update src address + shr b32 $r8 $r4 0x18 + shl b32 $r9 $r4 8 + add b32 $r9 $r5 + adc b32 $r8 0 + st b32 D[$r0 + #ctx_src_address_high] $r8 + st b32 D[$r0 + #ctx_src_address_low] $r9 + + // update dst address + shr b32 $r8 $r6 0x18 + shl b32 $r9 $r6 8 + add b32 $r9 $r7 + adc b32 $r8 0 + st b32 D[$r0 + #ctx_dst_address_high] $r8 + st b32 D[$r0 + #ctx_dst_address_low] $r9 + + // pull updated IV + cxset 2 + mov $r4 #ctx_iv + sethi $r4 0x60000 + xdld $r0 $r4 + xdwait + + ret + + +crypt_copy_prep: + cs0begin 2 + cxsin $c0 + cxsout $c0 + ret + +crypt_store_prep: + cs0begin 1 + cxsout $c6 + ret + +crypt_ecb_e_prep: + cs0begin 3 + cxsin $c0 + cenc $c0 $c0 + cxsout $c0 + ret + +crypt_ecb_d_prep: + ckexp $c7 $c7 + cs0begin 3 + cxsin $c0 + cdec $c0 $c0 + cxsout $c0 + ret + +crypt_cbc_e_prep: + cs0begin 4 + cxsin $c0 + cxor $c6 $c0 + cenc $c6 $c6 + cxsout $c6 + ret + +crypt_cbc_d_prep: + ckexp $c7 $c7 + cs0begin 5 + cmov $c2 $c6 + cxsin $c6 + cdec $c0 $c6 + cxor $c0 $c2 + cxsout $c0 + ret + +crypt_pcbc_e_prep: + cs0begin 5 + cxsin $c0 + cxor $c6 $c0 + cenc $c6 $c6 + cxsout $c6 + cxor $c6 $c0 + ret + +crypt_pcbc_d_prep: + ckexp $c7 $c7 + cs0begin 5 + cxsin $c0 + cdec $c1 $c0 + cxor $c6 $c1 + cxsout $c6 + cxor $c6 $c0 + ret + +crypt_cfb_e_prep: + cs0begin 4 + cenc $c6 $c6 + cxsin $c0 + cxor $c6 $c0 + cxsout $c6 + ret + +crypt_cfb_d_prep: + cs0begin 4 + cenc $c0 $c6 + cxsin $c6 + cxor $c0 $c6 + cxsout $c0 + ret + +crypt_ofb_prep: + cs0begin 4 + cenc $c6 $c6 + cxsin $c0 + cxor $c0 $c6 + cxsout $c0 + ret + +crypt_ctr_prep: + cs0begin 5 + cenc $c1 $c6 + cadd $c6 1 + cxsin $c0 + cxor $c0 $c1 + cxsout $c0 + ret + +crypt_cbc_mac_prep: + cs0begin 3 + cxsin $c0 + cxor $c6 $c0 + cenc $c6 $c6 + ret + +crypt_cmac_finish_complete_prep: + cs0begin 7 + cxsin $c0 + cxor $c6 $c0 + cxor $c0 $c0 + cenc $c0 $c0 + cprecmac $c0 $c0 + cxor $c6 $c0 + cenc $c6 $c6 + ret + +crypt_cmac_finish_partial_prep: + cs0begin 8 + cxsin $c0 + cxor $c6 $c0 + cxor $c0 $c0 + cenc $c0 $c0 + cprecmac $c0 $c0 + cprecmac $c0 $c0 + cxor $c6 $c0 + cenc $c6 $c6 + ret + +// TODO +crypt_do_in: + add b32 $r3 $r5 + mov $xdbase $r4 + mov $r9 #swap + sethi $r9 0x20000 + crypt_do_in_loop: + xdld $r5 $r9 + xdwait + cxset 0x22 + xdst $r0 $r9 + cs0exec 1 + xdwait + add b32 $r5 0x10 + cmpu b32 $r5 $r3 + bra ne #crypt_do_in_loop + cxset 1 + xdwait + ret + +crypt_do_out: + add b32 $r3 $r7 + mov $xdbase $r6 + mov $r9 #swap + sethi $r9 0x20000 + crypt_do_out_loop: + cs0exec 1 + cxset 0x61 + xdld $r7 $r9 + xdst $r7 $r9 + cxset 1 + xdwait + add b32 $r7 0x10 + cmpu b32 $r7 $r3 + bra ne #crypt_do_out_loop + ret + +crypt_do_inout: + add b32 $r3 $r5 + mov $r9 #swap + sethi $r9 0x20000 + crypt_do_inout_loop: + mov $xdbase $r4 + xdld $r5 $r9 + xdwait + cxset 0x21 + xdst $r0 $r9 + cs0exec 1 + cxset 0x61 + mov $xdbase $r6 + xdld $r7 $r9 + xdst $r7 $r9 + cxset 1 + xdwait + add b32 $r5 0x10 + add b32 $r7 0x10 + cmpu b32 $r5 $r3 + bra ne #crypt_do_inout_loop + ret + +.align 0x100 diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h new file mode 100644 index 0000000..38676c7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h @@ -0,0 +1,584 @@ +uint32_t nv98_pcrypt_data[] = { +/* 0x0000: ctx_dma */ +/* 0x0000: ctx_dma_query */ + 0x00000000, +/* 0x0004: ctx_dma_src */ + 0x00000000, +/* 0x0008: ctx_dma_dst */ + 0x00000000, +/* 0x000c: ctx_query_address_high */ + 0x00000000, +/* 0x0010: ctx_query_address_low */ + 0x00000000, +/* 0x0014: ctx_query_counter */ + 0x00000000, +/* 0x0018: ctx_cond_address_high */ + 0x00000000, +/* 0x001c: ctx_cond_address_low */ + 0x00000000, +/* 0x0020: ctx_cond_off */ + 0x00000000, +/* 0x0024: ctx_src_address_high */ + 0x00000000, +/* 0x0028: ctx_src_address_low */ + 0x00000000, +/* 0x002c: ctx_dst_address_high */ + 0x00000000, +/* 0x0030: ctx_dst_address_low */ + 0x00000000, +/* 0x0034: ctx_mode */ + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0040: ctx_key */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0050: ctx_iv */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0080: swap */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x00a0: common_cmd_dtable */ + 0x0002000c, + 0xffffff00, + 0x00020010, + 0x0000000f, + 0x00020014, + 0x00000000, + 0x00000192, + 0xfffffffe, + 0x00020018, + 0xffffff00, + 0x0002001c, + 0x0000000f, + 0x000001d7, + 0xfffffff8, + 0x00000260, + 0xffffffff, +/* 0x00e0: engine_cmd_dtable */ + 0x00020040, + 0x00000000, + 0x00020044, + 0x00000000, + 0x00020048, + 0x00000000, + 0x0002004c, + 0x00000000, + 0x00020050, + 0x00000000, + 0x00020054, + 0x00000000, + 0x00020058, + 0x00000000, + 0x0002005c, + 0x00000000, + 0x00020024, + 0xffffff00, + 0x00020028, + 0x0000000f, + 0x0002002c, + 0xffffff00, + 0x00020030, + 0x0000000f, + 0x00000271, + 0xfffffff0, + 0x00010285, + 0xf000000f, +/* 0x0150: crypt_dtable */ + 0x04db0321, + 0x04b1032f, + 0x04db0339, + 0x04db034b, + 0x04db0361, + 0x04db0377, + 0x04db0395, + 0x04db03af, + 0x04db03cd, + 0x04db03e3, + 0x04db03f9, + 0x04db040f, + 0x04830429, + 0x0483043b, + 0x0483045d, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +uint32_t nv98_pcrypt_code[] = { + 0x17f004bd, + 0x0010fe35, + 0xf10004fe, + 0xf0fff017, + 0x27f10013, + 0x21d00400, + 0x0c15f0c0, + 0xf00021d0, + 0x27f10317, + 0x21d01200, + 0x1031f400, +/* 0x002f: spin */ + 0xf40031f4, + 0x0ef40028, +/* 0x0035: ih */ + 0x8001cffd, + 0xb00812c4, + 0x0bf40024, + 0x0027f167, + 0x002bfe77, + 0xf00007fe, + 0x23f00027, + 0x0037f105, + 0x0034cf14, + 0xb0014594, + 0x18f40055, + 0x0602fa17, + 0x4af003f8, + 0x0034d01e, + 0xd00147f0, + 0x0ef48034, +/* 0x0075: ctxload */ + 0x4034cf33, + 0xb0014f94, + 0x18f400f5, + 0x0502fa21, + 0x57f003f8, + 0x0267f000, +/* 0x008c: ctxload_dma_loop */ + 0xa07856bc, + 0xb6018068, + 0x87d00884, + 0x0162b600, +/* 0x009f: dummyload */ + 0xf0f018f4, + 0x35d00257, +/* 0x00a5: noctx */ + 0x0412c480, + 0xf50024b0, + 0xf100df0b, + 0xcf190037, + 0x33cf4032, + 0xff24e400, + 0x1024b607, + 0x07bf45e4, + 0xf50054b0, + 0xf100b90b, + 0xf1fae057, + 0xb000ce67, + 0x18f4c044, + 0xa057f14d, + 0x8867f1fc, + 0x8044b000, + 0xb03f18f4, + 0x18f46044, + 0x5044b019, + 0xf1741bf4, + 0xbd220027, + 0x0233f034, + 0xf50023d0, +/* 0x0103: dma_cmd */ + 0xb000810e, + 0x18f46344, + 0x0245945e, + 0xfe8050b7, + 0x801e39f0, + 0x40b70053, + 0x44b60120, + 0x0043d008, +/* 0x0123: dtable_cmd */ + 0xb8600ef4, + 0x18f40446, + 0x0344b63e, + 0x980045bb, + 0x53fd0145, + 0x0054b004, + 0x58291bf4, + 0x46580045, + 0x0264b001, + 0x98170bf4, + 0x67fd0807, + 0x0164b004, + 0xf9300bf4, + 0x0f01f455, +/* 0x015b: cmd_setctx */ + 0x80280ef4, + 0x0ef40053, +/* 0x0161: invalid_bitfield */ + 0x0125f022, +/* 0x0164: dispatch_error */ +/* 0x0164: illegal_mthd */ + 0x100047f1, + 0xd00042d0, + 0x47f04043, + 0x0004d040, +/* 0x0174: im_loop */ + 0xf08004cf, + 0x44b04044, + 0xf71bf400, +/* 0x0180: cmddone */ + 0x1d0037f1, + 0xd00147f0, +/* 0x018a: nocmd */ + 0x11c40034, + 0x4001d00c, +/* 0x0192: cmd_query_get */ + 0x38f201f8, + 0x0325f001, + 0x0b0047f1, +/* 0x019c: ptimer_retry */ + 0xcf4046cf, + 0x47cf0045, + 0x0467b840, + 0x98f41bf4, + 0x04800504, + 0x21008020, + 0x80220580, + 0x0bfe2306, + 0x03049800, + 0xfe1844b6, + 0x04980047, + 0x8057f104, + 0x0253f000, + 0xf80645fa, +/* 0x01d7: cmd_cond_mode */ + 0xf400f803, + 0x25f00131, + 0x0534b002, + 0xf41218f4, + 0x34b00132, + 0x0b18f402, + 0x800136f0, +/* 0x01f2: return */ + 0x00f80803, +/* 0x01f4: cmd_cond_mode_queryful */ + 0x98060498, + 0x56c40705, + 0x0855b6ff, + 0xfd1844b6, + 0x47fe0545, + 0x000bfe00, + 0x008057f1, + 0xfa0253f0, + 0x34b00565, + 0x131bf402, + 0x049803f8, + 0x0044b021, + 0x800b4cf0, + 0x00f80804, +/* 0x022c: cmd_cond_mode_double */ + 0xb61060b6, + 0x65fa1050, + 0x9803f805, + 0x06982005, + 0x0456b824, + 0x980b4cf0, + 0x06982105, + 0x0456b825, + 0xfd0b5cf0, + 0x34b00445, + 0x0b5cf003, + 0x800645fd, + 0x00f80804, +/* 0x0260: cmd_wrcache_flush */ + 0xf10132f4, + 0xbd220027, + 0x0133f034, + 0xf80023d0, +/* 0x0271: crypt_cmd_mode */ + 0x0131f400, + 0xb00225f0, + 0x18f40f34, + 0x0132f409, +/* 0x0283: crypt_cmd_mode_return */ + 0xf80d0380, +/* 0x0285: crypt_cmd_length */ + 0x0034b000, + 0xf4fb0bf4, + 0x47f0033c, + 0x0743f040, + 0xf00604fa, + 0x43f05047, + 0x0604fa06, + 0x3cf503f8, + 0x47f1c407, + 0x4bfe2100, + 0x09049800, + 0x950a0598, + 0x44b60858, + 0x0548fd18, + 0x98ff55c4, + 0x07980b06, + 0x0878950c, + 0xfd1864b6, + 0x77c40568, + 0x0d0898ff, + 0x580284b6, + 0x95f9a889, + 0xf9a98958, + 0x013cf495, + 0x3cf403f8, + 0xf803f861, + 0x18489503, + 0xbb084994, + 0x81b60095, + 0x09088000, + 0x950a0980, + 0x69941868, + 0x0097bb08, + 0x800081b6, + 0x09800b08, + 0x023cf40c, + 0xf05047f0, + 0x04fa0643, + 0xf803f805, +/* 0x0321: crypt_copy_prep */ + 0x203cf500, + 0x003cf594, + 0x003cf588, +/* 0x032f: crypt_store_prep */ + 0xf500f88c, + 0xf594103c, + 0xf88c063c, +/* 0x0339: crypt_ecb_e_prep */ + 0x303cf500, + 0x003cf594, + 0x003cf588, + 0x003cf5d0, +/* 0x034b: crypt_ecb_d_prep */ + 0xf500f88c, + 0xf5c8773c, + 0xf594303c, + 0xf588003c, + 0xf5d4003c, + 0xf88c003c, +/* 0x0361: crypt_cbc_e_prep */ + 0x403cf500, + 0x003cf594, + 0x063cf588, + 0x663cf5ac, + 0x063cf5d0, +/* 0x0377: crypt_cbc_d_prep */ + 0xf500f88c, + 0xf5c8773c, + 0xf594503c, + 0xf584623c, + 0xf588063c, + 0xf5d4603c, + 0xf5ac203c, + 0xf88c003c, +/* 0x0395: crypt_pcbc_e_prep */ + 0x503cf500, + 0x003cf594, + 0x063cf588, + 0x663cf5ac, + 0x063cf5d0, + 0x063cf58c, +/* 0x03af: crypt_pcbc_d_prep */ + 0xf500f8ac, + 0xf5c8773c, + 0xf594503c, + 0xf588003c, + 0xf5d4013c, + 0xf5ac163c, + 0xf58c063c, + 0xf8ac063c, +/* 0x03cd: crypt_cfb_e_prep */ + 0x403cf500, + 0x663cf594, + 0x003cf5d0, + 0x063cf588, + 0x063cf5ac, +/* 0x03e3: crypt_cfb_d_prep */ + 0xf500f88c, + 0xf594403c, + 0xf5d0603c, + 0xf588063c, + 0xf5ac603c, + 0xf88c003c, +/* 0x03f9: crypt_ofb_prep */ + 0x403cf500, + 0x663cf594, + 0x003cf5d0, + 0x603cf588, + 0x003cf5ac, +/* 0x040f: crypt_ctr_prep */ + 0xf500f88c, + 0xf594503c, + 0xf5d0613c, + 0xf5b0163c, + 0xf588003c, + 0xf5ac103c, + 0xf88c003c, +/* 0x0429: crypt_cbc_mac_prep */ + 0x303cf500, + 0x003cf594, + 0x063cf588, + 0x663cf5ac, +/* 0x043b: crypt_cmac_finish_complete_prep */ + 0xf500f8d0, + 0xf594703c, + 0xf588003c, + 0xf5ac063c, + 0xf5ac003c, + 0xf5d0003c, + 0xf5bc003c, + 0xf5ac063c, + 0xf8d0663c, +/* 0x045d: crypt_cmac_finish_partial_prep */ + 0x803cf500, + 0x003cf594, + 0x063cf588, + 0x003cf5ac, + 0x003cf5ac, + 0x003cf5d0, + 0x003cf5bc, + 0x063cf5bc, + 0x663cf5ac, +/* 0x0483: crypt_do_in */ + 0xbb00f8d0, + 0x47fe0035, + 0x8097f100, + 0x0293f000, +/* 0x0490: crypt_do_in_loop */ + 0xf80559fa, + 0x223cf403, + 0xf50609fa, + 0xf898103c, + 0x1050b603, + 0xf40453b8, + 0x3cf4e91b, + 0xf803f801, +/* 0x04b1: crypt_do_out */ + 0x0037bb00, + 0xf10067fe, + 0xf0008097, +/* 0x04be: crypt_do_out_loop */ + 0x3cf50293, + 0x3cf49810, + 0x0579fa61, + 0xf40679fa, + 0x03f8013c, + 0xb81070b6, + 0x1bf40473, +/* 0x04db: crypt_do_inout */ + 0xbb00f8e8, + 0x97f10035, + 0x93f00080, +/* 0x04e5: crypt_do_inout_loop */ + 0x0047fe02, + 0xf80559fa, + 0x213cf403, + 0xf50609fa, + 0xf498103c, + 0x67fe613c, + 0x0579fa00, + 0xf40679fa, + 0x03f8013c, + 0xb61050b6, + 0x53b81070, + 0xd41bf404, + 0x000000f8, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c new file mode 100644 index 0000000..3881389 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -0,0 +1,205 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include + +struct nv84_crypt_engine { + struct nouveau_exec_engine base; +}; + +static int +nv84_crypt_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 *ctx; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &ctx); + if (ret) + return ret; + + nv_wo32(ramin, 0xa0, 0x00190000); + nv_wo32(ramin, 0xa4, ctx->vinst + ctx->size - 1); + nv_wo32(ramin, 0xa8, ctx->vinst); + nv_wo32(ramin, 0xac, 0); + nv_wo32(ramin, 0xb0, 0); + nv_wo32(ramin, 0xb4, 0); + dev_priv->engine.instmem.flush(dev); + + atomic_inc(&chan->vm->engref[engine]); + chan->engctx[engine] = ctx; + return 0; +} + +static void +nv84_crypt_context_del(struct nouveau_channel *chan, int engine) +{ + struct nouveau_gpuobj *ctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + u32 inst; + + inst = (chan->ramin->vinst >> 12); + inst |= 0x80000000; + + /* mark context as invalid if still on the hardware, not + * doing this causes issues the next time PCRYPT is used, + * unsurprisingly :) + */ + nv_wr32(dev, 0x10200c, 0x00000000); + if (nv_rd32(dev, 0x102188) == inst) + nv_mask(dev, 0x102188, 0x80000000, 0x00000000); + if (nv_rd32(dev, 0x10218c) == inst) + nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); + nv_wr32(dev, 0x10200c, 0x00000010); + + nouveau_gpuobj_ref(NULL, &ctx); + + atomic_dec(&chan->vm->engref[engine]); + chan->engctx[engine] = NULL; +} + +static int +nv84_crypt_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + 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 = 5; + obj->class = class; + + nv_wo32(obj, 0x00, class); + dev_priv->engine.instmem.flush(dev); + + ret = nouveau_ramht_insert(chan, handle, obj); + nouveau_gpuobj_ref(NULL, &obj); + return ret; +} + +static void +nv84_crypt_tlb_flush(struct drm_device *dev, int engine) +{ + nv50_vm_flush_engine(dev, 0x0a); +} + +static struct nouveau_bitfield nv84_crypt_intr[] = { + { 0x00000001, "INVALID_STATE" }, + { 0x00000002, "ILLEGAL_MTHD" }, + { 0x00000004, "ILLEGAL_CLASS" }, + { 0x00000080, "QUERY" }, + { 0x00000100, "FAULT" }, + {} +}; + +static void +nv84_crypt_isr(struct drm_device *dev) +{ + u32 stat = nv_rd32(dev, 0x102130); + u32 mthd = nv_rd32(dev, 0x102190); + u32 data = nv_rd32(dev, 0x102194); + u64 inst = (u64)(nv_rd32(dev, 0x102188) & 0x7fffffff) << 12; + int show = nouveau_ratelimit(); + int chid = nv50_graph_isr_chid(dev, inst); + + if (show) { + NV_INFO(dev, "PCRYPT:"); + nouveau_bitfield_print(nv84_crypt_intr, stat); + printk(KERN_CONT " ch %d (0x%010llx) mthd 0x%04x data 0x%08x\n", + chid, inst, mthd, data); + } + + nv_wr32(dev, 0x102130, stat); + nv_wr32(dev, 0x10200c, 0x10); + + nv50_fb_vm_trap(dev, show); +} + +static int +nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) +{ + nv_wr32(dev, 0x102140, 0x00000000); + return 0; +} + +static int +nv84_crypt_init(struct drm_device *dev, int engine) +{ + nv_mask(dev, 0x000200, 0x00004000, 0x00000000); + nv_mask(dev, 0x000200, 0x00004000, 0x00004000); + + nv_wr32(dev, 0x102130, 0xffffffff); + nv_wr32(dev, 0x102140, 0xffffffbf); + + nv_wr32(dev, 0x10200c, 0x00000010); + return 0; +} + +static void +nv84_crypt_destroy(struct drm_device *dev, int engine) +{ + struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine); + + NVOBJ_ENGINE_DEL(dev, CRYPT); + + nouveau_irq_unregister(dev, 14); + kfree(pcrypt); +} + +int +nv84_crypt_create(struct drm_device *dev) +{ + struct nv84_crypt_engine *pcrypt; + + pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL); + if (!pcrypt) + return -ENOMEM; + + pcrypt->base.destroy = nv84_crypt_destroy; + pcrypt->base.init = nv84_crypt_init; + pcrypt->base.fini = nv84_crypt_fini; + pcrypt->base.context_new = nv84_crypt_context_new; + pcrypt->base.context_del = nv84_crypt_context_del; + pcrypt->base.object_new = nv84_crypt_object_new; + pcrypt->base.tlb_flush = nv84_crypt_tlb_flush; + + nouveau_irq_register(dev, 14, nv84_crypt_isr); + + NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base); + NVOBJ_CLASS (dev, 0x74c1, CRYPT); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c new file mode 100644 index 0000000..563f60d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -0,0 +1,216 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include + +#include "fuc/nv98.fuc.h" + +struct nv98_crypt_priv { + struct nouveau_exec_engine base; +}; + +struct nv98_crypt_chan { + struct nouveau_gpuobj *mem; +}; + +static int +nv98_crypt_context_new(struct nouveau_channel *chan, int engine) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv98_crypt_priv *priv = nv_engine(dev, engine); + struct nv98_crypt_chan *cctx; + int ret; + + cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL); + if (!cctx) + return -ENOMEM; + + atomic_inc(&chan->vm->engref[engine]); + + ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &cctx->mem); + if (ret) + goto error; + + nv_wo32(chan->ramin, 0xa0, 0x00190000); + nv_wo32(chan->ramin, 0xa4, cctx->mem->vinst + cctx->mem->size - 1); + nv_wo32(chan->ramin, 0xa8, cctx->mem->vinst); + nv_wo32(chan->ramin, 0xac, 0x00000000); + nv_wo32(chan->ramin, 0xb0, 0x00000000); + nv_wo32(chan->ramin, 0xb4, 0x00000000); + dev_priv->engine.instmem.flush(dev); + +error: + if (ret) + priv->base.context_del(chan, engine); + return ret; +} + +static void +nv98_crypt_context_del(struct nouveau_channel *chan, int engine) +{ + struct nv98_crypt_chan *cctx = chan->engctx[engine]; + int i; + + for (i = 0xa0; i < 0xb4; i += 4) + nv_wo32(chan->ramin, i, 0x00000000); + + nouveau_gpuobj_ref(NULL, &cctx->mem); + + atomic_dec(&chan->vm->engref[engine]); + chan->engctx[engine] = NULL; + kfree(cctx); +} + +static int +nv98_crypt_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + struct nv98_crypt_chan *cctx = chan->engctx[engine]; + + /* fuc engine doesn't need an object, our ramht code does.. */ + cctx->mem->engine = 5; + cctx->mem->class = class; + return nouveau_ramht_insert(chan, handle, cctx->mem); +} + +static void +nv98_crypt_tlb_flush(struct drm_device *dev, int engine) +{ + nv50_vm_flush_engine(dev, 0x0a); +} + +static int +nv98_crypt_fini(struct drm_device *dev, int engine, bool suspend) +{ + nv_mask(dev, 0x000200, 0x00004000, 0x00000000); + return 0; +} + +static int +nv98_crypt_init(struct drm_device *dev, int engine) +{ + int i; + + /* reset! */ + nv_mask(dev, 0x000200, 0x00004000, 0x00000000); + nv_mask(dev, 0x000200, 0x00004000, 0x00004000); + + /* wait for exit interrupt to signal */ + nv_wait(dev, 0x087008, 0x00000010, 0x00000010); + nv_wr32(dev, 0x087004, 0x00000010); + + /* upload microcode code and data segments */ + nv_wr32(dev, 0x087ff8, 0x00100000); + for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_code); i++) + nv_wr32(dev, 0x087ff4, nv98_pcrypt_code[i]); + + nv_wr32(dev, 0x087ff8, 0x00000000); + for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_data); i++) + nv_wr32(dev, 0x087ff4, nv98_pcrypt_data[i]); + + /* start it running */ + nv_wr32(dev, 0x08710c, 0x00000000); + nv_wr32(dev, 0x087104, 0x00000000); /* ENTRY */ + nv_wr32(dev, 0x087100, 0x00000002); /* TRIGGER */ + return 0; +} + +static struct nouveau_enum nv98_crypt_isr_error_name[] = { + { 0x0000, "ILLEGAL_MTHD" }, + { 0x0001, "INVALID_BITFIELD" }, + { 0x0002, "INVALID_ENUM" }, + { 0x0003, "QUERY" }, + {} +}; + +static void +nv98_crypt_isr(struct drm_device *dev) +{ + u32 disp = nv_rd32(dev, 0x08701c); + u32 stat = nv_rd32(dev, 0x087008) & disp & ~(disp >> 16); + u32 inst = nv_rd32(dev, 0x087050) & 0x3fffffff; + u32 ssta = nv_rd32(dev, 0x087040) & 0x0000ffff; + u32 addr = nv_rd32(dev, 0x087040) >> 16; + u32 mthd = (addr & 0x07ff) << 2; + u32 subc = (addr & 0x3800) >> 11; + u32 data = nv_rd32(dev, 0x087044); + int chid = nv50_graph_isr_chid(dev, inst); + + if (stat & 0x00000040) { + NV_INFO(dev, "PCRYPT: DISPATCH_ERROR ["); + nouveau_enum_print(nv98_crypt_isr_error_name, ssta); + printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n", + chid, inst, subc, mthd, data); + nv_wr32(dev, 0x087004, 0x00000040); + stat &= ~0x00000040; + } + + if (stat) { + NV_INFO(dev, "PCRYPT: unhandled intr 0x%08x\n", stat); + nv_wr32(dev, 0x087004, stat); + } + + nv50_fb_vm_trap(dev, 1); +} + +static void +nv98_crypt_destroy(struct drm_device *dev, int engine) +{ + struct nv98_crypt_priv *priv = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 14); + NVOBJ_ENGINE_DEL(dev, CRYPT); + kfree(priv); +} + +int +nv98_crypt_create(struct drm_device *dev) +{ + struct nv98_crypt_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.destroy = nv98_crypt_destroy; + priv->base.init = nv98_crypt_init; + priv->base.fini = nv98_crypt_fini; + priv->base.context_new = nv98_crypt_context_new; + priv->base.context_del = nv98_crypt_context_del; + priv->base.object_new = nv98_crypt_object_new; + priv->base.tlb_flush = nv98_crypt_tlb_flush; + + nouveau_irq_register(dev, 14, nv98_crypt_isr); + + NVOBJ_ENGINE_ADD(dev, CRYPT, &priv->base); + NVOBJ_CLASS(dev, 0x88b4, CRYPT); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c new file mode 100644 index 0000000..bc38087 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2012 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include "nouveau_util.h" +#include +#include "nouveau_software.h" + +static struct ramfc_desc { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; +} nv04_ramfc[] = { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 16, 16, 0x08, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_PULL1 }, + {} +}; + +struct nv04_fifo_priv { + struct nouveau_fifo_priv base; + struct ramfc_desc *ramfc_desc; +}; + +struct nv04_fifo_chan { + struct nouveau_fifo_chan base; + struct nouveau_gpuobj *ramfc; +}; + +bool +nv04_fifo_cache_pull(struct drm_device *dev, bool enable) +{ + int pull = nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 1, enable); + + if (!enable) { + /* In some cases the PFIFO puller may be left in an + * inconsistent state if you try to stop it when it's + * busy translating handles. Sometimes you get a + * PFIFO_CACHE_ERROR, sometimes it just fails silently + * sending incorrect instance offsets to PGRAPH after + * it's started up again. To avoid the latter we + * invalidate the most recently calculated instance. + */ + if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0, + NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0)) + NV_ERROR(dev, "Timeout idling the PFIFO puller.\n"); + + if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) & + NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + } + + return pull & 1; +} + +static int +nv04_fifo_context_new(struct nouveau_channel *chan, int engine) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_fifo_priv *priv = nv_engine(dev, engine); + struct nv04_fifo_chan *fctx; + unsigned long flags; + int ret; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + /* map channel control registers */ + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV03_USER(chan->id), PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + /* initialise default fifo context */ + ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + chan->id * 32, ~0, 32, + NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); + if (ret) + goto error; + + nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x08, chan->pushbuf->pinst >> 4); + nv_wo32(fctx->ramfc, 0x0c, 0x00000000); + nv_wo32(fctx->ramfc, 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nv_wo32(fctx->ramfc, 0x14, 0x00000000); + nv_wo32(fctx->ramfc, 0x18, 0x00000000); + nv_wo32(fctx->ramfc, 0x1c, 0x00000000); + + /* enable dma mode on the channel */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +void +nv04_fifo_context_del(struct nouveau_channel *chan, int engine) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_fifo_priv *priv = nv_engine(chan->dev, engine); + struct nv04_fifo_chan *fctx = chan->engctx[engine]; + struct ramfc_desc *c = priv->ramfc_desc; + unsigned long flags; + int chid; + + /* prevent fifo context switches */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_wr32(dev, NV03_PFIFO_CACHES, 0); + + /* if this channel is active, replace it with a null context */ + chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels; + if (chid == chan->id) { + nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); + nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + + do { + u32 mask = ((1ULL << c->bits) - 1) << c->regs; + nv_mask(dev, c->regp, mask, 0x00000000); + } while ((++c)->bits); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + } + + /* restore normal operation, after disabling dma mode */ + nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); + nv_wr32(dev, NV03_PFIFO_CACHES, 1); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* clean up */ + nouveau_gpuobj_ref(NULL, &fctx->ramfc); + nouveau_gpuobj_ref(NULL, &chan->ramfc); /*XXX: nv40 */ + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } +} + +int +nv04_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_fifo_priv *priv = nv_engine(dev, engine); + int i; + + nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); + nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + + nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff); + nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); + + nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht->bits - 9) << 16) | + (dev_priv->ramht->gpuobj->pinst >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); + nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + + nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(dev, NV03_PFIFO_CACHES, 1); + + for (i = 0; i < priv->base.channels; i++) { + if (dev_priv->channels.ptr[i]) + nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); + } + + return 0; +} + +int +nv04_fifo_fini(struct drm_device *dev, int engine, bool suspend) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_fifo_priv *priv = nv_engine(dev, engine); + struct nouveau_channel *chan; + int chid; + + /* prevent context switches and halt fifo operation */ + nv_wr32(dev, NV03_PFIFO_CACHES, 0); + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 0); + + /* store current fifo context in ramfc */ + chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels; + chan = dev_priv->channels.ptr[chid]; + if (suspend && chid != priv->base.channels && chan) { + struct nv04_fifo_chan *fctx = chan->engctx[engine]; + struct nouveau_gpuobj *ctx = fctx->ramfc; + struct ramfc_desc *c = priv->ramfc_desc; + do { + u32 rm = ((1ULL << c->bits) - 1) << c->regs; + u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; + u32 rv = (nv_rd32(dev, c->regp) & rm) >> c->regs; + u32 cv = (nv_ro32(ctx, c->ctxp) & ~cm); + nv_wo32(ctx, c->ctxp, cv | (rv << c->ctxs)); + } while ((++c)->bits); + } + + nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0x00000000); + return 0; +} + +static bool +nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) +{ + struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + struct nouveau_gpuobj *obj; + unsigned long flags; + const int subc = (addr >> 13) & 0x7; + const int mthd = addr & 0x1ffc; + bool handled = false; + u32 engine; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + if (likely(chid >= 0 && chid < pfifo->channels)) + chan = dev_priv->channels.ptr[chid]; + if (unlikely(!chan)) + goto out; + + switch (mthd) { + case 0x0000: /* bind object to subchannel */ + obj = nouveau_ramht_find(chan, data); + if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW)) + break; + + engine = 0x0000000f << (subc * 4); + + nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); + handled = true; + break; + default: + engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE); + if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) + break; + + if (!nouveau_gpuobj_mthd_call(chan, nouveau_software_class(dev), + mthd, data)) + handled = true; + break; + } + +out: + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return handled; +} + +static const char *nv_dma_state_err(u32 state) +{ + static const char * const desc[] = { + "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", + "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" + }; + return desc[(state >> 29) & 0x7]; +} + +void +nv04_fifo_isr(struct drm_device *dev) +{ + struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t status, reassign; + int cnt = 0; + + reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; + while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { + uint32_t chid, get; + + nv_wr32(dev, NV03_PFIFO_CACHES, 0); + + chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & pfifo->channels; + get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); + + if (status & NV_PFIFO_INTR_CACHE_ERROR) { + uint32_t mthd, data; + int ptr; + + /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before + * wrapping on my G80 chips, but CACHE1 isn't big + * enough for this much data.. Tests show that it + * wraps around to the start at GET=0x800.. No clue + * as to why.. + */ + ptr = (get & 0x7ff) >> 2; + + if (dev_priv->card_type < NV_40) { + mthd = nv_rd32(dev, + NV04_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(dev, + NV04_PFIFO_CACHE1_DATA(ptr)); + } else { + mthd = nv_rd32(dev, + NV40_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(dev, + NV40_PFIFO_CACHE1_DATA(ptr)); + } + + if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) { + NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " + "Mthd 0x%04x Data 0x%08x\n", + chid, (mthd >> 13) & 7, mthd & 0x1ffc, + data); + } + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, + nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + + status &= ~NV_PFIFO_INTR_CACHE_ERROR; + } + + if (status & NV_PFIFO_INTR_DMA_PUSHER) { + u32 dma_get = nv_rd32(dev, 0x003244); + u32 dma_put = nv_rd32(dev, 0x003240); + u32 push = nv_rd32(dev, 0x003220); + u32 state = nv_rd32(dev, 0x003228); + + if (dev_priv->card_type == NV_50) { + u32 ho_get = nv_rd32(dev, 0x003328); + u32 ho_put = nv_rd32(dev, 0x003320); + u32 ib_get = nv_rd32(dev, 0x003334); + u32 ib_put = nv_rd32(dev, 0x003330); + + if (nouveau_ratelimit()) + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " + "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " + "State 0x%08x (err: %s) Push 0x%08x\n", + chid, ho_get, dma_get, ho_put, + dma_put, ib_get, ib_put, state, + nv_dma_state_err(state), + push); + + /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ + nv_wr32(dev, 0x003364, 0x00000000); + if (dma_get != dma_put || ho_get != ho_put) { + nv_wr32(dev, 0x003244, dma_put); + nv_wr32(dev, 0x003328, ho_put); + } else + if (ib_get != ib_put) { + nv_wr32(dev, 0x003334, ib_put); + } + } else { + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " + "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", + chid, dma_get, dma_put, state, + nv_dma_state_err(state), push); + + if (dma_get != dma_put) + nv_wr32(dev, 0x003244, dma_put); + } + + nv_wr32(dev, 0x003228, 0x00000000); + nv_wr32(dev, 0x003220, 0x00000001); + nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); + status &= ~NV_PFIFO_INTR_DMA_PUSHER; + } + + if (status & NV_PFIFO_INTR_SEMAPHORE) { + uint32_t sem; + + status &= ~NV_PFIFO_INTR_SEMAPHORE; + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_SEMAPHORE); + + sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); + nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + } + + if (dev_priv->card_type == NV_50) { + if (status & 0x00000010) { + nv50_fb_vm_trap(dev, nouveau_ratelimit()); + status &= ~0x00000010; + nv_wr32(dev, 0x002100, 0x00000010); + } + } + + if (status) { + if (nouveau_ratelimit()) + NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", + status, chid); + nv_wr32(dev, NV03_PFIFO_INTR_0, status); + status = 0; + } + + nv_wr32(dev, NV03_PFIFO_CACHES, reassign); + } + + if (status) { + NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); + nv_wr32(dev, 0x2140, 0); + nv_wr32(dev, 0x140, 0); + } + + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); +} + +void +nv04_fifo_destroy(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_fifo_priv *priv = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 8); + + dev_priv->eng[engine] = NULL; + kfree(priv); +} + +int +nv04_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_fifo_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nv04_fifo_destroy; + priv->base.base.init = nv04_fifo_init; + priv->base.base.fini = nv04_fifo_fini; + priv->base.base.context_new = nv04_fifo_context_new; + priv->base.base.context_del = nv04_fifo_context_del; + priv->base.channels = 15; + priv->ramfc_desc = nv04_ramfc; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + nouveau_irq_register(dev, 8, nv04_fifo_isr); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c new file mode 100644 index 0000000..9058c31 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include "nouveau_util.h" +#include + +static struct ramfc_desc { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; +} nv10_ramfc[] = { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, + { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, + {} +}; + +struct nv10_fifo_priv { + struct nouveau_fifo_priv base; + struct ramfc_desc *ramfc_desc; +}; + +struct nv10_fifo_chan { + struct nouveau_fifo_chan base; + struct nouveau_gpuobj *ramfc; +}; + +static int +nv10_fifo_context_new(struct nouveau_channel *chan, int engine) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv10_fifo_priv *priv = nv_engine(dev, engine); + struct nv10_fifo_chan *fctx; + unsigned long flags; + int ret; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + /* map channel control registers */ + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV03_USER(chan->id), PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + /* initialise default fifo context */ + ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + chan->id * 32, ~0, 32, + NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); + if (ret) + goto error; + + nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x08, 0x00000000); + nv_wo32(fctx->ramfc, 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(fctx->ramfc, 0x10, 0x00000000); + nv_wo32(fctx->ramfc, 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nv_wo32(fctx->ramfc, 0x18, 0x00000000); + nv_wo32(fctx->ramfc, 0x1c, 0x00000000); + + /* enable dma mode on the channel */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +int +nv10_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv10_fifo_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nv04_fifo_destroy; + priv->base.base.init = nv04_fifo_init; + priv->base.base.fini = nv04_fifo_fini; + priv->base.base.context_new = nv10_fifo_context_new; + priv->base.base.context_del = nv04_fifo_context_del; + priv->base.channels = 31; + priv->ramfc_desc = nv10_ramfc; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + nouveau_irq_register(dev, 8, nv04_fifo_isr); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c new file mode 100644 index 0000000..c514364 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2012 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include "nouveau_util.h" +#include + +static struct ramfc_desc { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; +} nv17_ramfc[] = { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, + { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 }, + { 32, 0, 0x20, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE }, + { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP }, + { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT }, + { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_SEMAPHORE }, + { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE }, + {} +}; + +struct nv17_fifo_priv { + struct nouveau_fifo_priv base; + struct ramfc_desc *ramfc_desc; +}; + +struct nv17_fifo_chan { + struct nouveau_fifo_chan base; + struct nouveau_gpuobj *ramfc; +}; + +static int +nv17_fifo_context_new(struct nouveau_channel *chan, int engine) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv17_fifo_priv *priv = nv_engine(dev, engine); + struct nv17_fifo_chan *fctx; + unsigned long flags; + int ret; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + /* map channel control registers */ + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV03_USER(chan->id), PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + /* initialise default fifo context */ + ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + chan->id * 64, ~0, 64, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); + if (ret) + goto error; + + nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(fctx->ramfc, 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + + /* enable dma mode on the channel */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +static int +nv17_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv17_fifo_priv *priv = nv_engine(dev, engine); + int i; + + nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); + nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + + nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff); + nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); + + nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht->bits - 9) << 16) | + (dev_priv->ramht->gpuobj->pinst >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); + nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 | + dev_priv->ramfc->pinst >> 8); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + + nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(dev, NV03_PFIFO_CACHES, 1); + + for (i = 0; i < priv->base.channels; i++) { + if (dev_priv->channels.ptr[i]) + nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); + } + + return 0; +} + +int +nv17_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv17_fifo_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nv04_fifo_destroy; + priv->base.base.init = nv17_fifo_init; + priv->base.base.fini = nv04_fifo_fini; + priv->base.base.context_new = nv17_fifo_context_new; + priv->base.base.context_del = nv04_fifo_context_del; + priv->base.channels = 31; + priv->ramfc_desc = nv17_ramfc; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + nouveau_irq_register(dev, 8, nv04_fifo_isr); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c new file mode 100644 index 0000000..3079f08 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2012 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include "nouveau_util.h" +#include + +static struct ramfc_desc { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; +} nv40_ramfc[] = { + { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, + { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, + { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, + { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, + { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT }, + { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_STATE }, + { 28, 0, 0x18, 0, NV04_PFIFO_CACHE1_DMA_FETCH }, + { 2, 28, 0x18, 28, 0x002058 }, + { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_ENGINE }, + { 32, 0, 0x20, 0, NV04_PFIFO_CACHE1_PULL1 }, + { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE }, + { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP }, + { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT }, + { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_SEMAPHORE }, + { 32, 0, 0x34, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE }, + { 32, 0, 0x38, 0, NV40_PFIFO_GRCTX_INSTANCE }, + { 17, 0, 0x3c, 0, NV04_PFIFO_DMA_TIMESLICE }, + { 32, 0, 0x40, 0, 0x0032e4 }, + { 32, 0, 0x44, 0, 0x0032e8 }, + { 32, 0, 0x4c, 0, 0x002088 }, + { 32, 0, 0x50, 0, 0x003300 }, + { 32, 0, 0x54, 0, 0x00330c }, + {} +}; + +struct nv40_fifo_priv { + struct nouveau_fifo_priv base; + struct ramfc_desc *ramfc_desc; +}; + +struct nv40_fifo_chan { + struct nouveau_fifo_chan base; + struct nouveau_gpuobj *ramfc; +}; + +static int +nv40_fifo_context_new(struct nouveau_channel *chan, int engine) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv40_fifo_priv *priv = nv_engine(dev, engine); + struct nv40_fifo_chan *fctx; + unsigned long flags; + int ret; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + /* map channel control registers */ + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV03_USER(chan->id), PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + /* initialise default fifo context */ + ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + chan->id * 128, ~0, 128, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); + if (ret) + goto error; + + nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); + nv_wo32(fctx->ramfc, 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(fctx->ramfc, 0x18, 0x30000000 | + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nv_wo32(fctx->ramfc, 0x3c, 0x0001ffff); + + /* enable dma mode on the channel */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /*XXX: remove this later, need fifo engine context commit hook */ + nouveau_gpuobj_ref(fctx->ramfc, &chan->ramfc); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +static int +nv40_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv40_fifo_priv *priv = nv_engine(dev, engine); + int i; + + nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); + nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + + nv_wr32(dev, 0x002040, 0x000000ff); + nv_wr32(dev, 0x002044, 0x2101ffff); + nv_wr32(dev, 0x002058, 0x00000001); + + nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht->bits - 9) << 16) | + (dev_priv->ramht->gpuobj->pinst >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); + + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + nv_wr32(dev, 0x002230, 0x00000001); + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x45: + case 0x48: + nv_wr32(dev, 0x002220, 0x00030002); + break; + default: + nv_wr32(dev, 0x002230, 0x00000000); + nv_wr32(dev, 0x002220, ((dev_priv->vram_size - 512 * 1024 + + dev_priv->ramfc->pinst) >> 16) | + 0x00030000); + break; + } + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + + nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(dev, NV03_PFIFO_CACHES, 1); + + for (i = 0; i < priv->base.channels; i++) { + if (dev_priv->channels.ptr[i]) + nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); + } + + return 0; +} + +int +nv40_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv40_fifo_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nv04_fifo_destroy; + priv->base.base.init = nv40_fifo_init; + priv->base.base.fini = nv04_fifo_fini; + priv->base.base.context_new = nv40_fifo_context_new; + priv->base.base.context_del = nv04_fifo_context_del; + priv->base.channels = 31; + priv->ramfc_desc = nv40_ramfc; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + nouveau_irq_register(dev, 8, nv04_fifo_isr); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c new file mode 100644 index 0000000..2309871 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2012 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include +#include + +struct nv50_fifo_priv { + struct nouveau_fifo_priv base; + struct nouveau_gpuobj *playlist[2]; + int cur_playlist; +}; + +struct nv50_fifo_chan { + struct nouveau_fifo_chan base; +}; + +void +nv50_fifo_playlist_update(struct drm_device *dev) +{ + struct nv50_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *cur; + int i, p; + + cur = priv->playlist[priv->cur_playlist]; + priv->cur_playlist = !priv->cur_playlist; + + for (i = 0, p = 0; i < priv->base.channels; i++) { + if (nv_rd32(dev, 0x002600 + (i * 4)) & 0x80000000) + nv_wo32(cur, p++ * 4, i); + } + + dev_priv->engine.instmem.flush(dev); + + nv_wr32(dev, 0x0032f4, cur->vinst >> 12); + nv_wr32(dev, 0x0032ec, p); + nv_wr32(dev, 0x002500, 0x00000101); +} + +static int +nv50_fifo_context_new(struct nouveau_channel *chan, int engine) +{ + struct nv50_fifo_priv *priv = nv_engine(chan->dev, engine); + struct nv50_fifo_chan *fctx; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; + u64 instance = chan->ramin->vinst >> 12; + unsigned long flags; + int ret = 0, i; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + atomic_inc(&chan->vm->engref[engine]); + + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV50_USER(chan->id), PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + for (i = 0; i < 0x100; i += 4) + nv_wo32(chan->ramin, i, 0x00000000); + nv_wo32(chan->ramin, 0x3c, 0x403f6078); + nv_wo32(chan->ramin, 0x40, 0x00000000); + nv_wo32(chan->ramin, 0x44, 0x01003fff); + nv_wo32(chan->ramin, 0x48, chan->pushbuf->cinst >> 4); + nv_wo32(chan->ramin, 0x50, lower_32_bits(ib_offset)); + nv_wo32(chan->ramin, 0x54, upper_32_bits(ib_offset) | + drm_order(chan->dma.ib_max + 1) << 16); + nv_wo32(chan->ramin, 0x60, 0x7fffffff); + nv_wo32(chan->ramin, 0x78, 0x00000000); + nv_wo32(chan->ramin, 0x7c, 0x30000001); + nv_wo32(chan->ramin, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->cinst >> 4)); + + dev_priv->engine.instmem.flush(dev); + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); + nv50_fifo_playlist_update(dev); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +static bool +nv50_fifo_kickoff(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + bool done = true; + u32 me; + + /* HW bug workaround: + * + * PFIFO will hang forever if the connected engines don't report + * that they've processed the context switch request. + * + * In order for the kickoff to work, we need to ensure all the + * connected engines are in a state where they can answer. + * + * Newer chipsets don't seem to suffer from this issue, and well, + * there's also a "ignore these engines" bitmask reg we can use + * if we hit the issue there.. + */ + + /* PME: make sure engine is enabled */ + me = nv_mask(dev, 0x00b860, 0x00000001, 0x00000001); + + /* do the kickoff... */ + nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { + NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); + done = false; + } + + /* restore any engine states we changed, and exit */ + nv_wr32(dev, 0x00b860, me); + return done; +} + +static void +nv50_fifo_context_del(struct nouveau_channel *chan, int engine) +{ + struct nv50_fifo_chan *fctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; + + /* remove channel from playlist, will context switch if active */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); + nv50_fifo_playlist_update(dev); + + /* tell any engines on this channel to unload their contexts */ + nv50_fifo_kickoff(chan); + + nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* clean up */ + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } + + atomic_dec(&chan->vm->engref[engine]); + chan->engctx[engine] = NULL; + kfree(fctx); +} + +static int +nv50_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 instance; + int i; + + nv_mask(dev, 0x000200, 0x00000100, 0x00000000); + nv_mask(dev, 0x000200, 0x00000100, 0x00000100); + nv_wr32(dev, 0x00250c, 0x6f3cfc34); + nv_wr32(dev, 0x002044, 0x01003fff); + + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xffffffff); + + for (i = 0; i < 128; i++) { + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; + if (chan && chan->engctx[engine]) + instance = 0x80000000 | chan->ramin->vinst >> 12; + else + instance = 0x00000000; + nv_wr32(dev, 0x002600 + (i * 4), instance); + } + + nv50_fifo_playlist_update(dev); + + nv_wr32(dev, 0x003200, 1); + nv_wr32(dev, 0x003250, 1); + nv_wr32(dev, 0x002500, 1); + return 0; +} + +static int +nv50_fifo_fini(struct drm_device *dev, int engine, bool suspend) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fifo_priv *priv = nv_engine(dev, engine); + int i; + + /* set playlist length to zero, fifo will unload context */ + nv_wr32(dev, 0x0032ec, 0); + + /* tell all connected engines to unload their contexts */ + for (i = 0; i < priv->base.channels; i++) { + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; + if (chan && !nv50_fifo_kickoff(chan)) + return -EBUSY; + } + + nv_wr32(dev, 0x002140, 0); + return 0; +} + +void +nv50_fifo_tlb_flush(struct drm_device *dev, int engine) +{ + nv50_vm_flush_engine(dev, 5); +} + +void +nv50_fifo_destroy(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fifo_priv *priv = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 8); + + nouveau_gpuobj_ref(NULL, &priv->playlist[0]); + nouveau_gpuobj_ref(NULL, &priv->playlist[1]); + + dev_priv->eng[engine] = NULL; + kfree(priv); +} + +int +nv50_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fifo_priv *priv; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nv50_fifo_destroy; + priv->base.base.init = nv50_fifo_init; + priv->base.base.fini = nv50_fifo_fini; + priv->base.base.context_new = nv50_fifo_context_new; + priv->base.base.context_del = nv50_fifo_context_del; + priv->base.base.tlb_flush = nv50_fifo_tlb_flush; + priv->base.channels = 127; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[0]); + if (ret) + goto error; + + ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[1]); + if (ret) + goto error; + + nouveau_irq_register(dev, 8, nv04_fifo_isr); +error: + if (ret) + priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c new file mode 100644 index 0000000..f505d1e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2012 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include +#include + +struct nv84_fifo_priv { + struct nouveau_fifo_priv base; + struct nouveau_gpuobj *playlist[2]; + int cur_playlist; +}; + +struct nv84_fifo_chan { + struct nouveau_fifo_chan base; + struct nouveau_gpuobj *ramfc; + struct nouveau_gpuobj *cache; +}; + +static int +nv84_fifo_context_new(struct nouveau_channel *chan, int engine) +{ + struct nv84_fifo_priv *priv = nv_engine(chan->dev, engine); + struct nv84_fifo_chan *fctx; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; + u64 instance; + unsigned long flags; + int ret; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + atomic_inc(&chan->vm->engref[engine]); + + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV50_USER(chan->id), PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + ret = nouveau_gpuobj_new(dev, chan, 256, 256, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); + if (ret) + goto error; + + instance = fctx->ramfc->vinst >> 8; + + ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, 0, &fctx->cache); + if (ret) + goto error; + + nv_wo32(fctx->ramfc, 0x3c, 0x403f6078); + nv_wo32(fctx->ramfc, 0x40, 0x00000000); + nv_wo32(fctx->ramfc, 0x44, 0x01003fff); + nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->cinst >> 4); + nv_wo32(fctx->ramfc, 0x50, lower_32_bits(ib_offset)); + nv_wo32(fctx->ramfc, 0x54, upper_32_bits(ib_offset) | + drm_order(chan->dma.ib_max + 1) << 16); + nv_wo32(fctx->ramfc, 0x60, 0x7fffffff); + nv_wo32(fctx->ramfc, 0x78, 0x00000000); + nv_wo32(fctx->ramfc, 0x7c, 0x30000001); + nv_wo32(fctx->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->cinst >> 4)); + nv_wo32(fctx->ramfc, 0x88, fctx->cache->vinst >> 10); + nv_wo32(fctx->ramfc, 0x98, chan->ramin->vinst >> 12); + + nv_wo32(chan->ramin, 0x00, chan->id); + nv_wo32(chan->ramin, 0x04, fctx->ramfc->vinst >> 8); + + dev_priv->engine.instmem.flush(dev); + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); + nv50_fifo_playlist_update(dev); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +static void +nv84_fifo_context_del(struct nouveau_channel *chan, int engine) +{ + struct nv84_fifo_chan *fctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; + u32 save; + + /* remove channel from playlist, will context switch if active */ + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); + nv50_fifo_playlist_update(dev); + + save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); + + /* tell any engines on this channel to unload their contexts */ + nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) + NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); + + nv_wr32(dev, 0x002520, save); + + nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* clean up */ + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } + + nouveau_gpuobj_ref(NULL, &fctx->ramfc); + nouveau_gpuobj_ref(NULL, &fctx->cache); + + atomic_dec(&chan->vm->engref[engine]); + chan->engctx[engine] = NULL; + kfree(fctx); +} + +static int +nv84_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv84_fifo_chan *fctx; + u32 instance; + int i; + + nv_mask(dev, 0x000200, 0x00000100, 0x00000000); + nv_mask(dev, 0x000200, 0x00000100, 0x00000100); + nv_wr32(dev, 0x00250c, 0x6f3cfc34); + nv_wr32(dev, 0x002044, 0x01003fff); + + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xffffffff); + + for (i = 0; i < 128; i++) { + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; + if (chan && (fctx = chan->engctx[engine])) + instance = 0x80000000 | fctx->ramfc->vinst >> 8; + else + instance = 0x00000000; + nv_wr32(dev, 0x002600 + (i * 4), instance); + } + + nv50_fifo_playlist_update(dev); + + nv_wr32(dev, 0x003200, 1); + nv_wr32(dev, 0x003250, 1); + nv_wr32(dev, 0x002500, 1); + return 0; +} + +static int +nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv84_fifo_priv *priv = nv_engine(dev, engine); + int i; + u32 save; + + /* set playlist length to zero, fifo will unload context */ + nv_wr32(dev, 0x0032ec, 0); + + save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); + + /* tell all connected engines to unload their contexts */ + for (i = 0; i < priv->base.channels; i++) { + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; + if (chan) + nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { + NV_INFO(dev, "PFIFO: channel %d unload timeout\n", i); + return -EBUSY; + } + } + + nv_wr32(dev, 0x002520, save); + nv_wr32(dev, 0x002140, 0); + return 0; +} + +int +nv84_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv84_fifo_priv *priv; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nv50_fifo_destroy; + priv->base.base.init = nv84_fifo_init; + priv->base.base.fini = nv84_fifo_fini; + priv->base.base.context_new = nv84_fifo_context_new; + priv->base.base.context_del = nv84_fifo_context_del; + priv->base.base.tlb_flush = nv50_fifo_tlb_flush; + priv->base.channels = 127; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[0]); + if (ret) + goto error; + + ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[1]); + if (ret) + goto error; + + nouveau_irq_register(dev, 8, nv04_fifo_isr); +error: + if (ret) + priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c new file mode 100644 index 0000000..398f32d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -0,0 +1,477 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include +#include + +static void nvc0_fifo_isr(struct drm_device *); + +struct nvc0_fifo_priv { + struct nouveau_fifo_priv base; + struct nouveau_gpuobj *playlist[2]; + int cur_playlist; + struct nouveau_vma user_vma; + int spoon_nr; +}; + +struct nvc0_fifo_chan { + struct nouveau_fifo_chan base; + struct nouveau_gpuobj *user; +}; + +static void +nvc0_fifo_playlist_update(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nouveau_gpuobj *cur; + int i, p; + + cur = priv->playlist[priv->cur_playlist]; + priv->cur_playlist = !priv->cur_playlist; + + for (i = 0, p = 0; i < 128; i++) { + if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1)) + continue; + nv_wo32(cur, p + 0, i); + nv_wo32(cur, p + 4, 0x00000004); + p += 8; + } + pinstmem->flush(dev); + + nv_wr32(dev, 0x002270, cur->vinst >> 12); + nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); + if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) + NV_ERROR(dev, "PFIFO - playlist update failed\n"); +} + +static int +nvc0_fifo_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nvc0_fifo_priv *priv = nv_engine(dev, engine); + struct nvc0_fifo_chan *fctx; + u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; + int ret, i; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + + priv->user_vma.offset + (chan->id * 0x1000), + PAGE_SIZE); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + /* allocate vram for control regs, map into polling area */ + ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &fctx->user); + if (ret) + goto error; + + nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000, + *(struct nouveau_mem **)fctx->user->node); + + for (i = 0; i < 0x100; i += 4) + nv_wo32(chan->ramin, i, 0x00000000); + nv_wo32(chan->ramin, 0x08, lower_32_bits(fctx->user->vinst)); + nv_wo32(chan->ramin, 0x0c, upper_32_bits(fctx->user->vinst)); + nv_wo32(chan->ramin, 0x10, 0x0000face); + nv_wo32(chan->ramin, 0x30, 0xfffff902); + nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); + nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | + upper_32_bits(ib_virt)); + nv_wo32(chan->ramin, 0x54, 0x00000002); + nv_wo32(chan->ramin, 0x84, 0x20400000); + nv_wo32(chan->ramin, 0x94, 0x30000001); + nv_wo32(chan->ramin, 0x9c, 0x00000100); + nv_wo32(chan->ramin, 0xa4, 0x1f1f1f1f); + nv_wo32(chan->ramin, 0xa8, 0x1f1f1f1f); + nv_wo32(chan->ramin, 0xac, 0x0000001f); + nv_wo32(chan->ramin, 0xb8, 0xf8000000); + nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ + nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ + pinstmem->flush(dev); + + nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | + (chan->ramin->vinst >> 12)); + nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); + nvc0_fifo_playlist_update(dev); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +static void +nvc0_fifo_context_del(struct nouveau_channel *chan, int engine) +{ + struct nvc0_fifo_chan *fctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + + nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000); + nv_wr32(dev, 0x002634, chan->id); + if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) + NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); + nvc0_fifo_playlist_update(dev); + nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000); + + nouveau_gpuobj_ref(NULL, &fctx->user); + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } + + chan->engctx[engine] = NULL; + kfree(fctx); +} + +static int +nvc0_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_fifo_priv *priv = nv_engine(dev, engine); + struct nouveau_channel *chan; + int i; + + /* reset PFIFO, enable all available PSUBFIFO areas */ + nv_mask(dev, 0x000200, 0x00000100, 0x00000000); + nv_mask(dev, 0x000200, 0x00000100, 0x00000100); + nv_wr32(dev, 0x000204, 0xffffffff); + nv_wr32(dev, 0x002204, 0xffffffff); + + priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204)); + NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); + + /* assign engines to subfifos */ + if (priv->spoon_nr >= 3) { + nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */ + nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */ + nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */ + nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */ + nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */ + nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */ + } + + /* PSUBFIFO[n] */ + for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ + } + + nv_mask(dev, 0x002200, 0x00000001, 0x00000001); + nv_wr32(dev, 0x002254, 0x10000000 | priv->user_vma.offset >> 12); + + nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xbfffffff); + + /* restore PFIFO context table */ + for (i = 0; i < 128; i++) { + chan = dev_priv->channels.ptr[i]; + if (!chan || !chan->engctx[engine]) + continue; + + nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 | + (chan->ramin->vinst >> 12)); + nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001); + } + nvc0_fifo_playlist_update(dev); + + return 0; +} + +static int +nvc0_fifo_fini(struct drm_device *dev, int engine, bool suspend) +{ + int i; + + for (i = 0; i < 128; i++) { + if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1)) + continue; + + nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000); + nv_wr32(dev, 0x002634, i); + if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { + NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", + i, nv_rd32(dev, 0x002634)); + return -EBUSY; + } + } + + nv_wr32(dev, 0x002140, 0x00000000); + return 0; +} + + +struct nouveau_enum nvc0_fifo_fault_unit[] = { + { 0x00, "PGRAPH" }, + { 0x03, "PEEPHOLE" }, + { 0x04, "BAR1" }, + { 0x05, "BAR3" }, + { 0x07, "PFIFO" }, + { 0x10, "PBSP" }, + { 0x11, "PPPP" }, + { 0x13, "PCOUNTER" }, + { 0x14, "PVP" }, + { 0x15, "PCOPY0" }, + { 0x16, "PCOPY1" }, + { 0x17, "PDAEMON" }, + {} +}; + +struct nouveau_enum nvc0_fifo_fault_reason[] = { + { 0x00, "PT_NOT_PRESENT" }, + { 0x01, "PT_TOO_SHORT" }, + { 0x02, "PAGE_NOT_PRESENT" }, + { 0x03, "VM_LIMIT_EXCEEDED" }, + { 0x04, "NO_CHANNEL" }, + { 0x05, "PAGE_SYSTEM_ONLY" }, + { 0x06, "PAGE_READ_ONLY" }, + { 0x0a, "COMPRESSED_SYSRAM" }, + { 0x0c, "INVALID_STORAGE_TYPE" }, + {} +}; + +struct nouveau_enum nvc0_fifo_fault_hubclient[] = { + { 0x01, "PCOPY0" }, + { 0x02, "PCOPY1" }, + { 0x04, "DISPATCH" }, + { 0x05, "CTXCTL" }, + { 0x06, "PFIFO" }, + { 0x07, "BAR_READ" }, + { 0x08, "BAR_WRITE" }, + { 0x0b, "PVP" }, + { 0x0c, "PPPP" }, + { 0x0d, "PBSP" }, + { 0x11, "PCOUNTER" }, + { 0x12, "PDAEMON" }, + { 0x14, "CCACHE" }, + { 0x15, "CCACHE_POST" }, + {} +}; + +struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { + { 0x01, "TEX" }, + { 0x0c, "ESETUP" }, + { 0x0e, "CTXCTL" }, + { 0x0f, "PROP" }, + {} +}; + +struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { +/* { 0x00008000, "" } seen with null ib push */ + { 0x00200000, "ILLEGAL_MTHD" }, + { 0x00800000, "EMPTY_SUBC" }, + {} +}; + +static void +nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) +{ + u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); + u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); + u32 client = (stat & 0x00001f00) >> 8; + + NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", + (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); + printk("] from "); + nouveau_enum_print(nvc0_fifo_fault_unit, unit); + if (stat & 0x00000040) { + printk("/"); + nouveau_enum_print(nvc0_fifo_fault_hubclient, client); + } else { + printk("/GPC%d/", (stat & 0x1f000000) >> 24); + nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); + } + printk(" on channel 0x%010llx\n", (u64)inst << 12); +} + +static int +nvc0_fifo_page_flip(struct drm_device *dev, u32 chid) +{ + struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + if (likely(chid >= 0 && chid < priv->base.channels)) { + chan = dev_priv->channels.ptr[chid]; + if (likely(chan)) + ret = nouveau_finish_page_flip(chan, NULL); + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return ret; +} + +static void +nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) +{ + u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); + u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); + u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); + u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 subc = (addr & 0x00070000); + u32 mthd = (addr & 0x00003ffc); + u32 show = stat; + + if (stat & 0x00200000) { + if (mthd == 0x0054) { + if (!nvc0_fifo_page_flip(dev, chid)) + show &= ~0x00200000; + } + } + + if (show) { + NV_INFO(dev, "PFIFO%d:", unit); + nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); + NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", + unit, chid, subc, mthd, data); + } + + nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); +} + +static void +nvc0_fifo_isr(struct drm_device *dev) +{ + u32 mask = nv_rd32(dev, 0x002140); + u32 stat = nv_rd32(dev, 0x002100) & mask; + + if (stat & 0x00000100) { + NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); + nv_wr32(dev, 0x002100, 0x00000100); + stat &= ~0x00000100; + } + + if (stat & 0x10000000) { + u32 units = nv_rd32(dev, 0x00259c); + u32 u = units; + + while (u) { + int i = ffs(u) - 1; + nvc0_fifo_isr_vm_fault(dev, i); + u &= ~(1 << i); + } + + nv_wr32(dev, 0x00259c, units); + stat &= ~0x10000000; + } + + if (stat & 0x20000000) { + u32 units = nv_rd32(dev, 0x0025a0); + u32 u = units; + + while (u) { + int i = ffs(u) - 1; + nvc0_fifo_isr_subfifo_intr(dev, i); + u &= ~(1 << i); + } + + nv_wr32(dev, 0x0025a0, units); + stat &= ~0x20000000; + } + + if (stat & 0x40000000) { + NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); + nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); + stat &= ~0x40000000; + } + + if (stat) { + NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); + nv_wr32(dev, 0x002100, stat); + nv_wr32(dev, 0x002140, 0); + } +} + +static void +nvc0_fifo_destroy(struct drm_device *dev, int engine) +{ + struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_vm_put(&priv->user_vma); + nouveau_gpuobj_ref(NULL, &priv->playlist[1]); + nouveau_gpuobj_ref(NULL, &priv->playlist[0]); + + dev_priv->eng[engine] = NULL; + kfree(priv); +} + +int +nvc0_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_fifo_priv *priv; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nvc0_fifo_destroy; + priv->base.base.init = nvc0_fifo_init; + priv->base.base.fini = nvc0_fifo_fini; + priv->base.base.context_new = nvc0_fifo_context_new; + priv->base.base.context_del = nvc0_fifo_context_del; + priv->base.channels = 128; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[0]); + if (ret) + goto error; + + ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[1]); + if (ret) + goto error; + + ret = nouveau_vm_get(dev_priv->bar1_vm, priv->base.channels * 0x1000, + 12, NV_MEM_ACCESS_RW, &priv->user_vma); + if (ret) + goto error; + + nouveau_irq_register(dev, 8, nvc0_fifo_isr); +error: + if (ret) + priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c new file mode 100644 index 0000000..829959f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -0,0 +1,453 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include +#include + +#define NVE0_FIFO_ENGINE_NUM 32 + +static void nve0_fifo_isr(struct drm_device *); + +struct nve0_fifo_engine { + struct nouveau_gpuobj *playlist[2]; + int cur_playlist; +}; + +struct nve0_fifo_priv { + struct nouveau_fifo_priv base; + struct nve0_fifo_engine engine[NVE0_FIFO_ENGINE_NUM]; + struct { + struct nouveau_gpuobj *mem; + struct nouveau_vma bar; + } user; + int spoon_nr; +}; + +struct nve0_fifo_chan { + struct nouveau_fifo_chan base; + u32 engine; +}; + +static void +nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nve0_fifo_engine *peng = &priv->engine[engine]; + struct nouveau_gpuobj *cur; + u32 match = (engine << 16) | 0x00000001; + int ret, i, p; + + cur = peng->playlist[peng->cur_playlist]; + if (unlikely(cur == NULL)) { + ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 0x1000, 0, &cur); + if (ret) { + NV_ERROR(dev, "PFIFO: playlist alloc failed\n"); + return; + } + + peng->playlist[peng->cur_playlist] = cur; + } + + peng->cur_playlist = !peng->cur_playlist; + + for (i = 0, p = 0; i < priv->base.channels; i++) { + u32 ctrl = nv_rd32(dev, 0x800004 + (i * 8)) & 0x001f0001; + if (ctrl != match) + continue; + nv_wo32(cur, p + 0, i); + nv_wo32(cur, p + 4, 0x00000000); + p += 8; + } + pinstmem->flush(dev); + + nv_wr32(dev, 0x002270, cur->vinst >> 12); + nv_wr32(dev, 0x002274, (engine << 20) | (p >> 3)); + if (!nv_wait(dev, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) + NV_ERROR(dev, "PFIFO: playlist %d update timeout\n", engine); +} + +static int +nve0_fifo_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nve0_fifo_priv *priv = nv_engine(dev, engine); + struct nve0_fifo_chan *fctx; + u64 usermem = priv->user.mem->vinst + chan->id * 512; + u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; + int ret = 0, i; + + fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + fctx->engine = 0; /* PGRAPH */ + + /* allocate vram for control regs, map into polling area */ + chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + + priv->user.bar.offset + (chan->id * 512), 512); + if (!chan->user) { + ret = -ENOMEM; + goto error; + } + + for (i = 0; i < 0x100; i += 4) + nv_wo32(chan->ramin, i, 0x00000000); + nv_wo32(chan->ramin, 0x08, lower_32_bits(usermem)); + nv_wo32(chan->ramin, 0x0c, upper_32_bits(usermem)); + nv_wo32(chan->ramin, 0x10, 0x0000face); + nv_wo32(chan->ramin, 0x30, 0xfffff902); + nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); + nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | + upper_32_bits(ib_virt)); + nv_wo32(chan->ramin, 0x84, 0x20400000); + nv_wo32(chan->ramin, 0x94, 0x30000001); + nv_wo32(chan->ramin, 0x9c, 0x00000100); + nv_wo32(chan->ramin, 0xac, 0x0000001f); + nv_wo32(chan->ramin, 0xe4, 0x00000000); + nv_wo32(chan->ramin, 0xe8, chan->id); + nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ + nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ + pinstmem->flush(dev); + + nv_wr32(dev, 0x800000 + (chan->id * 8), 0x80000000 | + (chan->ramin->vinst >> 12)); + nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); + nve0_fifo_playlist_update(dev, fctx->engine); + nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); + +error: + if (ret) + priv->base.base.context_del(chan, engine); + return ret; +} + +static void +nve0_fifo_context_del(struct nouveau_channel *chan, int engine) +{ + struct nve0_fifo_chan *fctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + + nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000800, 0x00000800); + nv_wr32(dev, 0x002634, chan->id); + if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) + NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); + nve0_fifo_playlist_update(dev, fctx->engine); + nv_wr32(dev, 0x800000 + (chan->id * 8), 0x00000000); + + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } + + chan->engctx[NVOBJ_ENGINE_FIFO] = NULL; + kfree(fctx); +} + +static int +nve0_fifo_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nve0_fifo_priv *priv = nv_engine(dev, engine); + struct nve0_fifo_chan *fctx; + int i; + + /* reset PFIFO, enable all available PSUBFIFO areas */ + nv_mask(dev, 0x000200, 0x00000100, 0x00000000); + nv_mask(dev, 0x000200, 0x00000100, 0x00000100); + nv_wr32(dev, 0x000204, 0xffffffff); + + priv->spoon_nr = hweight32(nv_rd32(dev, 0x000204)); + NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); + + /* PSUBFIFO[n] */ + for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ + } + + nv_wr32(dev, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); + + nv_wr32(dev, 0x002a00, 0xffffffff); + nv_wr32(dev, 0x002100, 0xffffffff); + nv_wr32(dev, 0x002140, 0xbfffffff); + + /* restore PFIFO context table */ + for (i = 0; i < priv->base.channels; i++) { + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; + if (!chan || !(fctx = chan->engctx[engine])) + continue; + + nv_wr32(dev, 0x800000 + (i * 8), 0x80000000 | + (chan->ramin->vinst >> 12)); + nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); + nve0_fifo_playlist_update(dev, fctx->engine); + nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); + } + + return 0; +} + +static int +nve0_fifo_fini(struct drm_device *dev, int engine, bool suspend) +{ + struct nve0_fifo_priv *priv = nv_engine(dev, engine); + int i; + + for (i = 0; i < priv->base.channels; i++) { + if (!(nv_rd32(dev, 0x800004 + (i * 8)) & 1)) + continue; + + nv_mask(dev, 0x800004 + (i * 8), 0x00000800, 0x00000800); + nv_wr32(dev, 0x002634, i); + if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { + NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", + i, nv_rd32(dev, 0x002634)); + return -EBUSY; + } + } + + nv_wr32(dev, 0x002140, 0x00000000); + return 0; +} + +struct nouveau_enum nve0_fifo_fault_unit[] = { + {} +}; + +struct nouveau_enum nve0_fifo_fault_reason[] = { + { 0x00, "PT_NOT_PRESENT" }, + { 0x01, "PT_TOO_SHORT" }, + { 0x02, "PAGE_NOT_PRESENT" }, + { 0x03, "VM_LIMIT_EXCEEDED" }, + { 0x04, "NO_CHANNEL" }, + { 0x05, "PAGE_SYSTEM_ONLY" }, + { 0x06, "PAGE_READ_ONLY" }, + { 0x0a, "COMPRESSED_SYSRAM" }, + { 0x0c, "INVALID_STORAGE_TYPE" }, + {} +}; + +struct nouveau_enum nve0_fifo_fault_hubclient[] = { + {} +}; + +struct nouveau_enum nve0_fifo_fault_gpcclient[] = { + {} +}; + +struct nouveau_bitfield nve0_fifo_subfifo_intr[] = { + { 0x00200000, "ILLEGAL_MTHD" }, + { 0x00800000, "EMPTY_SUBC" }, + {} +}; + +static void +nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) +{ + u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); + u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); + u32 client = (stat & 0x00001f00) >> 8; + + NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", + (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); + printk("] from "); + nouveau_enum_print(nve0_fifo_fault_unit, unit); + if (stat & 0x00000040) { + printk("/"); + nouveau_enum_print(nve0_fifo_fault_hubclient, client); + } else { + printk("/GPC%d/", (stat & 0x1f000000) >> 24); + nouveau_enum_print(nve0_fifo_fault_gpcclient, client); + } + printk(" on channel 0x%010llx\n", (u64)inst << 12); +} + +static int +nve0_fifo_page_flip(struct drm_device *dev, u32 chid) +{ + struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + if (likely(chid >= 0 && chid < priv->base.channels)) { + chan = dev_priv->channels.ptr[chid]; + if (likely(chan)) + ret = nouveau_finish_page_flip(chan, NULL); + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return ret; +} + +static void +nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) +{ + u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); + u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); + u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); + u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 subc = (addr & 0x00070000); + u32 mthd = (addr & 0x00003ffc); + u32 show = stat; + + if (stat & 0x00200000) { + if (mthd == 0x0054) { + if (!nve0_fifo_page_flip(dev, chid)) + show &= ~0x00200000; + } + } + + if (show) { + NV_INFO(dev, "PFIFO%d:", unit); + nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); + NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", + unit, chid, subc, mthd, data); + } + + nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); +} + +static void +nve0_fifo_isr(struct drm_device *dev) +{ + u32 mask = nv_rd32(dev, 0x002140); + u32 stat = nv_rd32(dev, 0x002100) & mask; + + if (stat & 0x00000100) { + NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); + nv_wr32(dev, 0x002100, 0x00000100); + stat &= ~0x00000100; + } + + if (stat & 0x10000000) { + u32 units = nv_rd32(dev, 0x00259c); + u32 u = units; + + while (u) { + int i = ffs(u) - 1; + nve0_fifo_isr_vm_fault(dev, i); + u &= ~(1 << i); + } + + nv_wr32(dev, 0x00259c, units); + stat &= ~0x10000000; + } + + if (stat & 0x20000000) { + u32 units = nv_rd32(dev, 0x0025a0); + u32 u = units; + + while (u) { + int i = ffs(u) - 1; + nve0_fifo_isr_subfifo_intr(dev, i); + u &= ~(1 << i); + } + + nv_wr32(dev, 0x0025a0, units); + stat &= ~0x20000000; + } + + if (stat & 0x40000000) { + NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); + nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); + stat &= ~0x40000000; + } + + if (stat) { + NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); + nv_wr32(dev, 0x002100, stat); + nv_wr32(dev, 0x002140, 0); + } +} + +static void +nve0_fifo_destroy(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nve0_fifo_priv *priv = nv_engine(dev, engine); + int i; + + nouveau_vm_put(&priv->user.bar); + nouveau_gpuobj_ref(NULL, &priv->user.mem); + + for (i = 0; i < NVE0_FIFO_ENGINE_NUM; i++) { + nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]); + nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]); + } + + dev_priv->eng[engine] = NULL; + kfree(priv); +} + +int +nve0_fifo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nve0_fifo_priv *priv; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.base.destroy = nve0_fifo_destroy; + priv->base.base.init = nve0_fifo_init; + priv->base.base.fini = nve0_fifo_fini; + priv->base.base.context_new = nve0_fifo_context_new; + priv->base.base.context_del = nve0_fifo_context_del; + priv->base.channels = 4096; + dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + + ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 512, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); + if (ret) + goto error; + + ret = nouveau_vm_get(dev_priv->bar1_vm, priv->user.mem->size, + 12, NV_MEM_ACCESS_RW, &priv->user.bar); + if (ret) + goto error; + + nouveau_vm_map(&priv->user.bar, *(struct nouveau_mem **)priv->user.mem->node); + + nouveau_irq_register(dev, 8, nve0_fifo_isr); +error: + if (ret) + priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h new file mode 100644 index 0000000..b0795ec --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h @@ -0,0 +1,129 @@ +#ifndef __NOUVEAU_GRCTX_H__ +#define __NOUVEAU_GRCTX_H__ + +struct nouveau_grctx { + struct drm_device *dev; + + enum { + NOUVEAU_GRCTX_PROG, + NOUVEAU_GRCTX_VALS + } 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; +}; + +static inline void +cp_out(struct nouveau_grctx *ctx, uint32_t inst) +{ + uint32_t *ctxprog = ctx->data; + + if (ctx->mode != NOUVEAU_GRCTX_PROG) + return; + + BUG_ON(ctx->ctxprog_len == ctx->ctxprog_max); + ctxprog[ctx->ctxprog_len++] = inst; +} + +static inline void +cp_lsr(struct nouveau_grctx *ctx, uint32_t val) +{ + cp_out(ctx, CP_LOAD_SR | val); +} + +static inline void +cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length) +{ + ctx->ctxprog_reg = (reg - 0x00400000) >> 2; + + ctx->ctxvals_base = ctx->ctxvals_pos; + ctx->ctxvals_pos = ctx->ctxvals_base + length; + + if (length > (CP_CTX_COUNT >> CP_CTX_COUNT_SHIFT)) { + cp_lsr(ctx, length); + length = 0; + } + + cp_out(ctx, CP_CTX | (length << CP_CTX_COUNT_SHIFT) | ctx->ctxprog_reg); +} + +static inline void +cp_name(struct nouveau_grctx *ctx, int name) +{ + uint32_t *ctxprog = ctx->data; + int i; + + if (ctx->mode != NOUVEAU_GRCTX_PROG) + return; + + ctx->ctxprog_label[name] = ctx->ctxprog_len; + for (i = 0; i < ctx->ctxprog_len; i++) { + if ((ctxprog[i] & 0xfff00000) != 0xff400000) + continue; + if ((ctxprog[i] & CP_BRA_IP) != ((name) << CP_BRA_IP_SHIFT)) + continue; + ctxprog[i] = (ctxprog[i] & 0x00ff00ff) | + (ctx->ctxprog_len << CP_BRA_IP_SHIFT); + } +} + +static inline void +_cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name) +{ + int ip = 0; + + if (mod != 2) { + ip = ctx->ctxprog_label[name] << CP_BRA_IP_SHIFT; + if (ip == 0) + ip = 0xff000000 | (name << CP_BRA_IP_SHIFT); + } + + cp_out(ctx, CP_BRA | (mod << 18) | ip | flag | + (state ? 0 : CP_BRA_IF_CLEAR)); +} +#define cp_bra(c, f, s, n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) +#define cp_cal(c, f, s, n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) +#define cp_ret(c, f, s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) + +static inline void +_cp_wait(struct nouveau_grctx *ctx, int flag, int state) +{ + cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0)); +} +#define cp_wait(c, f, s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) + +static inline void +_cp_set(struct nouveau_grctx *ctx, int flag, int state) +{ + cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0)); +} +#define cp_set(c, f, s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) + +static inline void +cp_pos(struct nouveau_grctx *ctx, int offset) +{ + ctx->ctxvals_pos = offset; + ctx->ctxvals_base = ctx->ctxvals_pos; + + cp_lsr(ctx, ctx->ctxvals_pos); + cp_out(ctx, CP_SET_CONTEXT_POINTER); +} + +static inline void +gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) +{ + if (ctx->mode != NOUVEAU_GRCTX_VALS) + return; + + reg = (reg - 0x00400000) / 4; + reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; + + nv_wo32(ctx->data, reg * 4, val); +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c new file mode 100644 index 0000000..b17506d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c @@ -0,0 +1,690 @@ +/* + * Copyright 2009 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: + * + * 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 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 + */ + +/* 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 + * correct operation. We'll implement additional handling if/when we + * discover it's necessary. + * + * - On context save, NVIDIA set 0x400314 bit 0 to 1 if the "3D state" + * flag is set, this gets saved into the context. + * - On context save, the context program for all cards load nsource + * into a flag register and check for ILLEGAL_MTHD. If it's set, + * opcode 0x60000d is called before resuming normal operation. + * - Some context programs check more conditions than the above. NV44 + * checks: ((nsource & 0x0857) || (0x400718 & 0x0100) || (intr & 0x0001)) + * and calls 0x60000d before resuming normal operation. + * - At the very beginning of NVIDIA's context programs, flag 9 is checked + * and if true 0x800001 is called with count=0, pos=0, the flag is cleared + * and then the ctxprog is aborted. It looks like a complicated NOP, + * its purpose is unknown. + * - In the section of code that loads the per-vs state, NVIDIA check + * flag 10. If it's set, they only transfer the small 0x300 byte block + * of state + the state for a single vs as opposed to the state for + * all vs units. It doesn't seem likely that it'll occur in normal + * operation, especially seeing as it appears NVIDIA may have screwed + * up the ctxprogs for some cards and have an invalid instruction + * rather than a cp_lsr(ctx, dwords_for_1_vs_unit) instruction. + * - There's a number of places where context offset 0 (where we place + * the PRAMIN offset of the context) is loaded into either 0x408000, + * 0x408004 or 0x408008. Not sure what's up there either. + * - The ctxprogs for some cards save 0x400a00 again during the cleanup + * path for auto-loadctx. + */ + +#define CP_FLAG_CLEAR 0 +#define CP_FLAG_SET 1 +#define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0) +#define CP_FLAG_SWAP_DIRECTION_LOAD 0 +#define CP_FLAG_SWAP_DIRECTION_SAVE 1 +#define CP_FLAG_USER_SAVE ((0 * 32) + 5) +#define CP_FLAG_USER_SAVE_NOT_PENDING 0 +#define CP_FLAG_USER_SAVE_PENDING 1 +#define CP_FLAG_USER_LOAD ((0 * 32) + 6) +#define CP_FLAG_USER_LOAD_NOT_PENDING 0 +#define CP_FLAG_USER_LOAD_PENDING 1 +#define CP_FLAG_STATUS ((3 * 32) + 0) +#define CP_FLAG_STATUS_IDLE 0 +#define CP_FLAG_STATUS_BUSY 1 +#define CP_FLAG_AUTO_SAVE ((3 * 32) + 4) +#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0 +#define CP_FLAG_AUTO_SAVE_PENDING 1 +#define CP_FLAG_AUTO_LOAD ((3 * 32) + 5) +#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0 +#define CP_FLAG_AUTO_LOAD_PENDING 1 +#define CP_FLAG_UNK54 ((3 * 32) + 6) +#define CP_FLAG_UNK54_CLEAR 0 +#define CP_FLAG_UNK54_SET 1 +#define CP_FLAG_ALWAYS ((3 * 32) + 8) +#define CP_FLAG_ALWAYS_FALSE 0 +#define CP_FLAG_ALWAYS_TRUE 1 +#define CP_FLAG_UNK57 ((3 * 32) + 9) +#define CP_FLAG_UNK57_CLEAR 0 +#define CP_FLAG_UNK57_SET 1 + +#define CP_CTX 0x00100000 +#define CP_CTX_COUNT 0x000fc000 +#define CP_CTX_COUNT_SHIFT 14 +#define CP_CTX_REG 0x00003fff +#define CP_LOAD_SR 0x00200000 +#define CP_LOAD_SR_VALUE 0x000fffff +#define CP_BRA 0x00400000 +#define CP_BRA_IP 0x0000ff00 +#define CP_BRA_IP_SHIFT 8 +#define CP_BRA_IF_CLEAR 0x00000080 +#define CP_BRA_FLAG 0x0000007f +#define CP_WAIT 0x00500000 +#define CP_WAIT_SET 0x00000080 +#define CP_WAIT_FLAG 0x0000007f +#define CP_SET 0x00700000 +#define CP_SET_1 0x00000080 +#define CP_SET_FLAG 0x0000007f +#define CP_NEXT_TO_SWAP 0x00600007 +#define CP_NEXT_TO_CURRENT 0x00600009 +#define CP_SET_CONTEXT_POINTER 0x0060000a +#define CP_END 0x0060000e +#define CP_LOAD_MAGIC_UNK01 0x00800001 /* unknown */ +#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 "ctx.h" + +/* TODO: + * - get vs count from 0x1540 + */ + +static int +nv40_graph_vs_count(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + return 8; + case 0x40: + return 6; + case 0x41: + case 0x42: + return 5; + case 0x43: + case 0x44: + case 0x46: + case 0x4a: + return 3; + case 0x4c: + case 0x4e: + case 0x67: + default: + return 1; + } +} + + +enum cp_label { + cp_check_load = 1, + cp_setup_auto_load, + cp_setup_load, + cp_setup_save, + cp_swap_state, + cp_swap_state3d_3_is_save, + cp_prepare_exit, + cp_exit, +}; + +static void +nv40_graph_construct_general(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + + cp_ctx(ctx, 0x4000a4, 1); + gr_def(ctx, 0x4000a4, 0x00000008); + cp_ctx(ctx, 0x400144, 58); + gr_def(ctx, 0x400144, 0x00000001); + cp_ctx(ctx, 0x400314, 1); + gr_def(ctx, 0x400314, 0x00000000); + cp_ctx(ctx, 0x400400, 10); + cp_ctx(ctx, 0x400480, 10); + cp_ctx(ctx, 0x400500, 19); + gr_def(ctx, 0x400514, 0x00040000); + gr_def(ctx, 0x400524, 0x55555555); + gr_def(ctx, 0x400528, 0x55555555); + gr_def(ctx, 0x40052c, 0x55555555); + gr_def(ctx, 0x400530, 0x55555555); + cp_ctx(ctx, 0x400560, 6); + gr_def(ctx, 0x400568, 0x0000ffff); + gr_def(ctx, 0x40056c, 0x0000ffff); + cp_ctx(ctx, 0x40057c, 5); + cp_ctx(ctx, 0x400710, 3); + gr_def(ctx, 0x400710, 0x20010001); + gr_def(ctx, 0x400714, 0x0f73ef00); + cp_ctx(ctx, 0x400724, 1); + gr_def(ctx, 0x400724, 0x02008821); + cp_ctx(ctx, 0x400770, 3); + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x400814, 4); + cp_ctx(ctx, 0x400828, 5); + cp_ctx(ctx, 0x400840, 5); + gr_def(ctx, 0x400850, 0x00000040); + cp_ctx(ctx, 0x400858, 4); + gr_def(ctx, 0x400858, 0x00000040); + gr_def(ctx, 0x40085c, 0x00000040); + gr_def(ctx, 0x400864, 0x80000000); + cp_ctx(ctx, 0x40086c, 9); + gr_def(ctx, 0x40086c, 0x80000000); + gr_def(ctx, 0x400870, 0x80000000); + gr_def(ctx, 0x400874, 0x80000000); + gr_def(ctx, 0x400878, 0x80000000); + gr_def(ctx, 0x400888, 0x00000040); + gr_def(ctx, 0x40088c, 0x80000000); + cp_ctx(ctx, 0x4009c0, 8); + gr_def(ctx, 0x4009cc, 0x80000000); + gr_def(ctx, 0x4009dc, 0x80000000); + } else { + cp_ctx(ctx, 0x400840, 20); + if (nv44_graph_class(ctx->dev)) { + for (i = 0; i < 8; i++) + gr_def(ctx, 0x400860 + (i * 4), 0x00000001); + } + gr_def(ctx, 0x400880, 0x00000040); + gr_def(ctx, 0x400884, 0x00000040); + gr_def(ctx, 0x400888, 0x00000040); + cp_ctx(ctx, 0x400894, 11); + gr_def(ctx, 0x400894, 0x00000040); + if (!nv44_graph_class(ctx->dev)) { + 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) + 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) { + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x403448, 1); + gr_def(ctx, 0x403448, 0x00001010); + break; + default: + cp_ctx(ctx, 0x403440, 1); + switch (dev_priv->chipset) { + case 0x40: + gr_def(ctx, 0x403440, 0x00000010); + break; + case 0x44: + case 0x46: + case 0x4a: + gr_def(ctx, 0x403440, 0x00003010); + break; + case 0x41: + case 0x42: + case 0x43: + case 0x4c: + case 0x4e: + case 0x67: + default: + gr_def(ctx, 0x403440, 0x00001010); + break; + } + break; + } +} + +static void +nv40_graph_construct_state3d(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + + if (dev_priv->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) { + cp_ctx(ctx, 0x401880, 32); + for (i = 0; i < 16; i++) + gr_def(ctx, 0x401880 + (i * 4), 0x00000111); + if (dev_priv->chipset == 0x46) + cp_ctx(ctx, 0x401900, 16); + cp_ctx(ctx, 0x401940, 3); + } + cp_ctx(ctx, 0x40194c, 18); + gr_def(ctx, 0x401954, 0x00000111); + gr_def(ctx, 0x401958, 0x00080060); + gr_def(ctx, 0x401974, 0x00000080); + gr_def(ctx, 0x401978, 0xffff0000); + gr_def(ctx, 0x40197c, 0x00000001); + gr_def(ctx, 0x401990, 0x46400000); + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x4019a0, 2); + cp_ctx(ctx, 0x4019ac, 5); + } else { + cp_ctx(ctx, 0x4019a0, 1); + cp_ctx(ctx, 0x4019b4, 3); + } + gr_def(ctx, 0x4019bc, 0xffff0000); + switch (dev_priv->chipset) { + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x4019c0, 18); + for (i = 0; i < 16; i++) + gr_def(ctx, 0x4019c0 + (i * 4), 0x88888888); + break; + } + cp_ctx(ctx, 0x401a08, 8); + gr_def(ctx, 0x401a10, 0x0fff0000); + gr_def(ctx, 0x401a14, 0x0fff0000); + gr_def(ctx, 0x401a1c, 0x00011100); + cp_ctx(ctx, 0x401a2c, 4); + cp_ctx(ctx, 0x401a44, 26); + for (i = 0; i < 16; i++) + gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000); + gr_def(ctx, 0x401a8c, 0x4b7fffff); + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x401ab8, 3); + } else { + cp_ctx(ctx, 0x401ab8, 1); + cp_ctx(ctx, 0x401ac0, 1); + } + cp_ctx(ctx, 0x401ad0, 8); + gr_def(ctx, 0x401ad0, 0x30201000); + 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); + gr_def(ctx, 0x401b10, 0x40100000); + cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5); + gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ? + 0x00000004 : 0x00000000); + cp_ctx(ctx, 0x401b30, 25); + gr_def(ctx, 0x401b34, 0x0000ffff); + gr_def(ctx, 0x401b68, 0x435185d6); + gr_def(ctx, 0x401b6c, 0x2155b699); + gr_def(ctx, 0x401b70, 0xfedcba98); + gr_def(ctx, 0x401b74, 0x00000098); + 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) + cp_ctx(ctx, 0x401b94, 1); + cp_ctx(ctx, 0x401b98, 8); + gr_def(ctx, 0x401b9c, 0x00ff0000); + cp_ctx(ctx, 0x401bc0, 9); + gr_def(ctx, 0x401be0, 0x00ffff00); + cp_ctx(ctx, 0x401c00, 192); + for (i = 0; i < 16; i++) { /* fragment texture units */ + gr_def(ctx, 0x401c40 + (i * 4), 0x00018488); + gr_def(ctx, 0x401c80 + (i * 4), 0x00028202); + gr_def(ctx, 0x401d00 + (i * 4), 0x0000aae4); + gr_def(ctx, 0x401d40 + (i * 4), 0x01012000); + gr_def(ctx, 0x401d80 + (i * 4), 0x00080008); + gr_def(ctx, 0x401e00 + (i * 4), 0x00100008); + } + for (i = 0; i < 4; i++) { /* vertex texture units */ + gr_def(ctx, 0x401e90 + (i * 4), 0x0001bc80); + gr_def(ctx, 0x401ea0 + (i * 4), 0x00000202); + gr_def(ctx, 0x401ec0 + (i * 4), 0x00000008); + gr_def(ctx, 0x401ee0 + (i * 4), 0x00080008); + } + cp_ctx(ctx, 0x400f5c, 3); + gr_def(ctx, 0x400f5c, 0x00000002); + cp_ctx(ctx, 0x400f84, 1); +} + +static void +nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + + cp_ctx(ctx, 0x402000, 1); + cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2); + switch (dev_priv->chipset) { + case 0x40: + gr_def(ctx, 0x402404, 0x00000001); + break; + case 0x4c: + case 0x4e: + case 0x67: + gr_def(ctx, 0x402404, 0x00000020); + break; + case 0x46: + case 0x49: + case 0x4b: + gr_def(ctx, 0x402404, 0x00000421); + break; + default: + gr_def(ctx, 0x402404, 0x00000021); + } + if (dev_priv->chipset != 0x40) + gr_def(ctx, 0x402408, 0x030c30c3); + switch (dev_priv->chipset) { + case 0x44: + case 0x46: + case 0x4a: + case 0x4c: + case 0x4e: + case 0x67: + cp_ctx(ctx, 0x402440, 1); + gr_def(ctx, 0x402440, 0x00011001); + break; + default: + break; + } + cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9); + gr_def(ctx, 0x402488, 0x3e020200); + gr_def(ctx, 0x40248c, 0x00ffffff); + switch (dev_priv->chipset) { + case 0x40: + gr_def(ctx, 0x402490, 0x60103f00); + break; + case 0x47: + gr_def(ctx, 0x402490, 0x40103f00); + break; + case 0x41: + case 0x42: + case 0x49: + case 0x4b: + gr_def(ctx, 0x402490, 0x20103f00); + break; + default: + gr_def(ctx, 0x402490, 0x0c103f00); + break; + } + gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ? + 0x00020000 : 0x00040000); + cp_ctx(ctx, 0x402500, 31); + gr_def(ctx, 0x402530, 0x00008100); + if (dev_priv->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) { + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x402864, 1); + gr_def(ctx, 0x402864, 0x00001001); + cp_ctx(ctx, 0x402870, 3); + gr_def(ctx, 0x402878, 0x00000003); + if (dev_priv->chipset != 0x47) { /* belong at end!! */ + cp_ctx(ctx, 0x402900, 1); + cp_ctx(ctx, 0x402940, 1); + cp_ctx(ctx, 0x402980, 1); + cp_ctx(ctx, 0x4029c0, 1); + cp_ctx(ctx, 0x402a00, 1); + cp_ctx(ctx, 0x402a40, 1); + cp_ctx(ctx, 0x402a80, 1); + cp_ctx(ctx, 0x402ac0, 1); + } + break; + case 0x40: + cp_ctx(ctx, 0x402844, 1); + gr_def(ctx, 0x402844, 0x00000001); + cp_ctx(ctx, 0x402850, 1); + break; + default: + cp_ctx(ctx, 0x402844, 1); + gr_def(ctx, 0x402844, 0x00001001); + cp_ctx(ctx, 0x402850, 2); + gr_def(ctx, 0x402854, 0x00000003); + break; + } + + cp_ctx(ctx, 0x402c00, 4); + gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ? + 0x80800001 : 0x00888001); + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x402c20, 40); + for (i = 0; i < 32; i++) + gr_def(ctx, 0x402c40 + (i * 4), 0xffffffff); + cp_ctx(ctx, 0x4030b8, 13); + gr_def(ctx, 0x4030dc, 0x00000005); + gr_def(ctx, 0x4030e8, 0x0000ffff); + break; + default: + cp_ctx(ctx, 0x402c10, 4); + if (dev_priv->chipset == 0x40) + cp_ctx(ctx, 0x402c20, 36); + else + if (dev_priv->chipset <= 0x42) + cp_ctx(ctx, 0x402c20, 24); + else + if (dev_priv->chipset <= 0x4a) + cp_ctx(ctx, 0x402c20, 16); + else + cp_ctx(ctx, 0x402c20, 8); + cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13); + gr_def(ctx, 0x402cd4, 0x00000005); + if (dev_priv->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++) + gr_def(ctx, 0x403420 + (i * 4), 0x00005555); + + if (dev_priv->chipset != 0x40) { + cp_ctx(ctx, 0x403600, 1); + gr_def(ctx, 0x403600, 0x00000001); + } + cp_ctx(ctx, 0x403800, 1); + + cp_ctx(ctx, 0x403c18, 1); + gr_def(ctx, 0x403c18, 0x00000001); + switch (dev_priv->chipset) { + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x405018, 1); + gr_def(ctx, 0x405018, 0x08e00001); + cp_ctx(ctx, 0x405c24, 1); + gr_def(ctx, 0x405c24, 0x000e3000); + break; + } + if (dev_priv->chipset != 0x4e) + cp_ctx(ctx, 0x405800, 11); + cp_ctx(ctx, 0x407000, 1); +} + +static void +nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx) +{ + int len = nv44_graph_class(ctx->dev) ? 0x0084 : 0x0684; + + cp_out (ctx, 0x300000); + cp_lsr (ctx, len - 4); + cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_swap_state3d_3_is_save); + cp_lsr (ctx, len); + cp_name(ctx, cp_swap_state3d_3_is_save); + cp_out (ctx, 0x800001); + + ctx->ctxvals_pos += len; +} + +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_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_b0 = 363; + vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64; + if (dev_priv->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) { + 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; + } + + cp_lsr(ctx, vs_len * vs_nr + 0x300/4); + cp_out(ctx, nv44_graph_class(dev) ? 0x800029 : 0x800041); + + offset = ctx->ctxvals_pos; + ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len)); + + if (ctx->mode != NOUVEAU_GRCTX_VALS) + return; + + offset += 0x0280/4; + for (i = 0; i < 16; i++, offset += 2) + nv_wo32(obj, offset * 4, 0x3f800000); + + for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { + for (i = 0; i < vs_nr_b0 * 6; i += 6) + nv_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001); + for (i = 0; i < vs_nr_b1 * 4; i += 4) + nv_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000); + } +} + +static void +nv40_grctx_generate(struct nouveau_grctx *ctx) +{ + /* decide whether we're loading/unloading the context */ + cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); + cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); + + cp_name(ctx, cp_check_load); + cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load); + cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load); + cp_bra (ctx, ALWAYS, TRUE, cp_exit); + + /* setup for context load */ + cp_name(ctx, cp_setup_auto_load); + cp_wait(ctx, STATUS, IDLE); + cp_out (ctx, CP_NEXT_TO_SWAP); + cp_name(ctx, cp_setup_load); + cp_wait(ctx, STATUS, IDLE); + cp_set (ctx, SWAP_DIRECTION, LOAD); + cp_out (ctx, 0x00910880); /* ?? */ + cp_out (ctx, 0x00901ffe); /* ?? */ + cp_out (ctx, 0x01940000); /* ?? */ + cp_lsr (ctx, 0x20); + cp_out (ctx, 0x0060000b); /* ?? */ + cp_wait(ctx, UNK57, CLEAR); + cp_out (ctx, 0x0060000c); /* ?? */ + cp_bra (ctx, ALWAYS, TRUE, cp_swap_state); + + /* setup for context save */ + cp_name(ctx, cp_setup_save); + cp_set (ctx, SWAP_DIRECTION, SAVE); + + /* general PGRAPH state */ + cp_name(ctx, cp_swap_state); + cp_pos (ctx, 0x00020/4); + nv40_graph_construct_general(ctx); + cp_wait(ctx, STATUS, IDLE); + + /* 3D state, block 1 */ + cp_bra (ctx, UNK54, CLEAR, cp_prepare_exit); + nv40_graph_construct_state3d(ctx); + cp_wait(ctx, STATUS, IDLE); + + /* 3D state, block 2 */ + nv40_graph_construct_state3d_2(ctx); + + /* Some other block of "random" state */ + nv40_graph_construct_state3d_3(ctx); + + /* Per-vertex shader state */ + cp_pos (ctx, ctx->ctxvals_pos); + nv40_graph_construct_shader(ctx); + + /* pre-exit state updates */ + cp_name(ctx, cp_prepare_exit); + cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load); + cp_bra (ctx, USER_SAVE, PENDING, cp_exit); + cp_out (ctx, CP_NEXT_TO_CURRENT); + + cp_name(ctx, cp_exit); + cp_set (ctx, USER_SAVE, NOT_PENDING); + cp_set (ctx, USER_LOAD, NOT_PENDING); + cp_out (ctx, CP_END); +} + +void +nv40_grctx_fill(struct drm_device *dev, struct nouveau_gpuobj *mem) +{ + nv40_grctx_generate(&(struct nouveau_grctx) { + .dev = dev, + .mode = NOUVEAU_GRCTX_VALS, + .data = mem, + }); +} + +void +nv40_grctx_init(struct drm_device *dev, u32 *size) +{ + u32 ctxprog[256], i; + struct nouveau_grctx ctx = { + .dev = dev, + .mode = NOUVEAU_GRCTX_PROG, + .data = ctxprog, + .ctxprog_max = ARRAY_SIZE(ctxprog) + }; + + nv40_grctx_generate(&ctx); + + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + for (i = 0; i < ctx.ctxprog_len; i++) + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, 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 new file mode 100644 index 0000000..e17c17b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c @@ -0,0 +1,3360 @@ +/* + * Copyright 2009 Marcin KoÅ›cielnicki + * + * 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 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 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. + */ + +#define CP_FLAG_CLEAR 0 +#define CP_FLAG_SET 1 +#define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0) +#define CP_FLAG_SWAP_DIRECTION_LOAD 0 +#define CP_FLAG_SWAP_DIRECTION_SAVE 1 +#define CP_FLAG_UNK01 ((0 * 32) + 1) +#define CP_FLAG_UNK01_CLEAR 0 +#define CP_FLAG_UNK01_SET 1 +#define CP_FLAG_UNK03 ((0 * 32) + 3) +#define CP_FLAG_UNK03_CLEAR 0 +#define CP_FLAG_UNK03_SET 1 +#define CP_FLAG_USER_SAVE ((0 * 32) + 5) +#define CP_FLAG_USER_SAVE_NOT_PENDING 0 +#define CP_FLAG_USER_SAVE_PENDING 1 +#define CP_FLAG_USER_LOAD ((0 * 32) + 6) +#define CP_FLAG_USER_LOAD_NOT_PENDING 0 +#define CP_FLAG_USER_LOAD_PENDING 1 +#define CP_FLAG_UNK0B ((0 * 32) + 0xb) +#define CP_FLAG_UNK0B_CLEAR 0 +#define CP_FLAG_UNK0B_SET 1 +#define CP_FLAG_XFER_SWITCH ((0 * 32) + 0xe) +#define CP_FLAG_XFER_SWITCH_DISABLE 0 +#define CP_FLAG_XFER_SWITCH_ENABLE 1 +#define CP_FLAG_STATE ((0 * 32) + 0x1c) +#define CP_FLAG_STATE_STOPPED 0 +#define CP_FLAG_STATE_RUNNING 1 +#define CP_FLAG_UNK1D ((0 * 32) + 0x1d) +#define CP_FLAG_UNK1D_CLEAR 0 +#define CP_FLAG_UNK1D_SET 1 +#define CP_FLAG_UNK20 ((1 * 32) + 0) +#define CP_FLAG_UNK20_CLEAR 0 +#define CP_FLAG_UNK20_SET 1 +#define CP_FLAG_STATUS ((2 * 32) + 0) +#define CP_FLAG_STATUS_BUSY 0 +#define CP_FLAG_STATUS_IDLE 1 +#define CP_FLAG_AUTO_SAVE ((2 * 32) + 4) +#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0 +#define CP_FLAG_AUTO_SAVE_PENDING 1 +#define CP_FLAG_AUTO_LOAD ((2 * 32) + 5) +#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0 +#define CP_FLAG_AUTO_LOAD_PENDING 1 +#define CP_FLAG_NEWCTX ((2 * 32) + 10) +#define CP_FLAG_NEWCTX_BUSY 0 +#define CP_FLAG_NEWCTX_DONE 1 +#define CP_FLAG_XFER ((2 * 32) + 11) +#define CP_FLAG_XFER_IDLE 0 +#define CP_FLAG_XFER_BUSY 1 +#define CP_FLAG_ALWAYS ((2 * 32) + 13) +#define CP_FLAG_ALWAYS_FALSE 0 +#define CP_FLAG_ALWAYS_TRUE 1 +#define CP_FLAG_INTR ((2 * 32) + 15) +#define CP_FLAG_INTR_NOT_PENDING 0 +#define CP_FLAG_INTR_PENDING 1 + +#define CP_CTX 0x00100000 +#define CP_CTX_COUNT 0x000f0000 +#define CP_CTX_COUNT_SHIFT 16 +#define CP_CTX_REG 0x00003fff +#define CP_LOAD_SR 0x00200000 +#define CP_LOAD_SR_VALUE 0x000fffff +#define CP_BRA 0x00400000 +#define CP_BRA_IP 0x0001ff00 +#define CP_BRA_IP_SHIFT 8 +#define CP_BRA_IF_CLEAR 0x00000080 +#define CP_BRA_FLAG 0x0000007f +#define CP_WAIT 0x00500000 +#define CP_WAIT_SET 0x00000080 +#define CP_WAIT_FLAG 0x0000007f +#define CP_SET 0x00700000 +#define CP_SET_1 0x00000080 +#define CP_SET_FLAG 0x0000007f +#define CP_NEWCTX 0x00600004 +#define CP_NEXT_TO_SWAP 0x00600005 +#define CP_SET_CONTEXT_POINTER 0x00600006 +#define CP_SET_XFER_POINTER 0x00600007 +#define CP_ENABLE 0x00600009 +#define CP_END 0x0060000c +#define CP_NEXT_TO_CURRENT 0x0060000d +#define CP_DISABLE1 0x0090ffff +#define CP_DISABLE2 0x0091ffff +#define CP_XFER_1 0x008000ff +#define CP_XFER_2 0x008800ff +#define CP_SEEK_1 0x00c000ff +#define CP_SEEK_2 0x00c800ff + +#include "drmP.h" +#include "nouveau_drv.h" +#include "ctx.h" + +#define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) +#define IS_NVAAF(x) ((x) >= 0xaa && (x) <= 0xac) + +/* + * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's + * the GPU itself that does context-switching, but it needs a special + * microcode to do it. And it's the driver's task to supply this microcode, + * further known as ctxprog, as well as the initial context values, known + * as ctxvals. + * + * Without ctxprog, you cannot switch contexts. Not even in software, since + * the majority of context [xfer strands] isn't accessible directly. You're + * stuck with a single channel, and you also suffer all the problems resulting + * from missing ctxvals, since you cannot load them. + * + * Without ctxvals, you're stuck with PGRAPH's default context. It's enough to + * run 2d operations, but trying to utilise 3d or CUDA will just lock you up, + * since you don't have... some sort of needed setup. + * + * Nouveau will just disable acceleration if not given ctxprog + ctxvals, since + * it's too much hassle to handle no-ctxprog as a special case. + */ + +/* + * How ctxprogs work. + * + * The ctxprog is written in its own kind of microcode, with very small and + * crappy set of available commands. You upload it to a small [512 insns] + * area of memory on PGRAPH, and it'll be run when PFIFO wants PGRAPH to + * switch channel. or when the driver explicitely requests it. Stuff visible + * to ctxprog consists of: PGRAPH MMIO registers, PGRAPH context strands, + * the per-channel context save area in VRAM [known as ctxvals or grctx], + * 4 flags registers, a scratch register, two grctx pointers, plus many + * random poorly-understood details. + * + * When ctxprog runs, it's supposed to check what operations are asked of it, + * save old context if requested, optionally reset PGRAPH and switch to the + * new channel, and load the new context. Context consists of three major + * parts: subset of MMIO registers and two "xfer areas". + */ + +/* TODO: + * - document unimplemented bits compared to nvidia + * - NVAx: make a TP subroutine, use it. + * - use 0x4008fc instead of 0x1540? + */ + +enum cp_label { + cp_check_load = 1, + cp_setup_auto_load, + cp_setup_load, + cp_setup_save, + cp_swap_state, + cp_prepare_exit, + cp_exit, +}; + +static void nv50_graph_construct_mmio(struct nouveau_grctx *ctx); +static void nv50_graph_construct_xfer1(struct nouveau_grctx *ctx); +static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx); + +/* Main function: construct the ctxprog skeleton, call the other functions. */ + +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 */ + cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); + cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); + + cp_name(ctx, cp_check_load); + cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load); + cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load); + cp_bra (ctx, ALWAYS, TRUE, cp_prepare_exit); + + /* setup for context load */ + cp_name(ctx, cp_setup_auto_load); + cp_out (ctx, CP_DISABLE1); + cp_out (ctx, CP_DISABLE2); + cp_out (ctx, CP_ENABLE); + cp_out (ctx, CP_NEXT_TO_SWAP); + cp_set (ctx, UNK01, SET); + cp_name(ctx, cp_setup_load); + cp_out (ctx, CP_NEWCTX); + cp_wait(ctx, NEWCTX, BUSY); + cp_set (ctx, UNK1D, CLEAR); + cp_set (ctx, SWAP_DIRECTION, LOAD); + cp_bra (ctx, UNK0B, SET, cp_prepare_exit); + cp_bra (ctx, ALWAYS, TRUE, cp_swap_state); + + /* setup for context save */ + cp_name(ctx, cp_setup_save); + cp_set (ctx, UNK1D, SET); + cp_wait(ctx, STATUS, BUSY); + cp_wait(ctx, INTR, PENDING); + cp_bra (ctx, STATUS, BUSY, cp_setup_save); + cp_set (ctx, UNK01, SET); + cp_set (ctx, SWAP_DIRECTION, SAVE); + + /* general PGRAPH state */ + cp_name(ctx, cp_swap_state); + cp_set (ctx, UNK03, SET); + cp_pos (ctx, 0x00004/4); + cp_ctx (ctx, 0x400828, 1); /* needed. otherwise, flickering happens. */ + cp_pos (ctx, 0x00100/4); + nv50_graph_construct_mmio(ctx); + nv50_graph_construct_xfer1(ctx); + nv50_graph_construct_xfer2(ctx); + + cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load); + + cp_set (ctx, UNK20, SET); + cp_set (ctx, SWAP_DIRECTION, SAVE); /* no idea why this is needed, but fixes at least one lockup. */ + cp_lsr (ctx, ctx->ctxvals_base); + cp_out (ctx, CP_SET_XFER_POINTER); + cp_lsr (ctx, 4); + cp_out (ctx, CP_SEEK_1); + cp_out (ctx, CP_XFER_1); + cp_wait(ctx, XFER, BUSY); + + /* pre-exit state updates */ + cp_name(ctx, cp_prepare_exit); + cp_set (ctx, UNK01, CLEAR); + cp_set (ctx, UNK03, CLEAR); + cp_set (ctx, UNK1D, CLEAR); + + cp_bra (ctx, USER_SAVE, PENDING, cp_exit); + cp_out (ctx, CP_NEXT_TO_CURRENT); + + cp_name(ctx, cp_exit); + cp_set (ctx, USER_SAVE, NOT_PENDING); + cp_set (ctx, USER_LOAD, NOT_PENDING); + cp_set (ctx, XFER_SWITCH, DISABLE); + cp_set (ctx, STATE, STOPPED); + cp_out (ctx, CP_END); + ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */ + + return 0; +} + +void +nv50_grctx_fill(struct drm_device *dev, struct nouveau_gpuobj *mem) +{ + nv50_grctx_generate(&(struct nouveau_grctx) { + .dev = dev, + .mode = NOUVEAU_GRCTX_VALS, + .data = mem, + }); +} + +int +nv50_grctx_init(struct drm_device *dev, u32 *data, u32 max, u32 *len, u32 *cnt) +{ + struct nouveau_grctx ctx = { + .dev = dev, + .mode = NOUVEAU_GRCTX_PROG, + .data = data, + .ctxprog_max = max + }; + int ret; + + ret = nv50_grctx_generate(&ctx); + *cnt = ctx.ctxvals_pos * 4; + *len = ctx.ctxprog_len; + return ret; +} + +/* + * Constructs MMIO part of ctxprog and ctxvals. Just a matter of knowing which + * registers to save/restore and the default values for them. + */ + +static void +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; + int i, j; + int offset, base; + uint32_t units = nv_rd32 (ctx->dev, 0x1540); + + /* 0800: DISPATCH */ + cp_ctx(ctx, 0x400808, 7); + gr_def(ctx, 0x400814, 0x00000030); + cp_ctx(ctx, 0x400834, 0x32); + if (dev_priv->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)) + gr_def(ctx, 0x400894, 0x00001000); + gr_def(ctx, 0x4008e8, 0x00000003); + gr_def(ctx, 0x4008ec, 0x00001000); + if (dev_priv->chipset == 0x50) + cp_ctx(ctx, 0x400908, 0xb); + else if (dev_priv->chipset < 0xa0) + cp_ctx(ctx, 0x400908, 0xc); + else + cp_ctx(ctx, 0x400908, 0xe); + + if (dev_priv->chipset >= 0xa0) + cp_ctx(ctx, 0x400b00, 0x1); + if (IS_NVA3F(dev_priv->chipset)) { + cp_ctx(ctx, 0x400b10, 0x1); + gr_def(ctx, 0x400b10, 0x0001629d); + cp_ctx(ctx, 0x400b20, 0x1); + gr_def(ctx, 0x400b20, 0x0001629d); + } + + nv50_graph_construct_mmio_ddata(ctx); + + /* 0C00: VFETCH */ + cp_ctx(ctx, 0x400c08, 0x2); + gr_def(ctx, 0x400c08, 0x0000fe0c); + + /* 1000 */ + if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, 0x401008, 0x4); + gr_def(ctx, 0x401014, 0x00001000); + } else if (!IS_NVA3F(dev_priv->chipset)) { + cp_ctx(ctx, 0x401008, 0x5); + gr_def(ctx, 0x401018, 0x00001000); + } else { + cp_ctx(ctx, 0x401008, 0x5); + gr_def(ctx, 0x401018, 0x00004000); + } + + /* 1400 */ + cp_ctx(ctx, 0x401400, 0x8); + cp_ctx(ctx, 0x401424, 0x3); + if (dev_priv->chipset == 0x50) + gr_def(ctx, 0x40142c, 0x0001fd87); + else + gr_def(ctx, 0x40142c, 0x00000187); + cp_ctx(ctx, 0x401540, 0x5); + gr_def(ctx, 0x401550, 0x00001018); + + /* 1800: STREAMOUT */ + cp_ctx(ctx, 0x401814, 0x1); + gr_def(ctx, 0x401814, 0x000000ff); + if (dev_priv->chipset == 0x50) { + cp_ctx(ctx, 0x40181c, 0xe); + gr_def(ctx, 0x401850, 0x00000004); + } else if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, 0x40181c, 0xf); + gr_def(ctx, 0x401854, 0x00000004); + } else { + cp_ctx(ctx, 0x40181c, 0x13); + gr_def(ctx, 0x401864, 0x00000004); + } + + /* 1C00 */ + cp_ctx(ctx, 0x401c00, 0x1); + switch (dev_priv->chipset) { + case 0x50: + gr_def(ctx, 0x401c00, 0x0001005f); + break; + case 0x84: + case 0x86: + case 0x94: + gr_def(ctx, 0x401c00, 0x044d00df); + break; + case 0x92: + case 0x96: + case 0x98: + case 0xa0: + case 0xaa: + case 0xac: + gr_def(ctx, 0x401c00, 0x042500df); + break; + case 0xa3: + case 0xa5: + case 0xa8: + case 0xaf: + gr_def(ctx, 0x401c00, 0x142500df); + break; + } + + /* 2000 */ + + /* 2400 */ + cp_ctx(ctx, 0x402400, 0x1); + if (dev_priv->chipset == 0x50) + cp_ctx(ctx, 0x402408, 0x1); + else + cp_ctx(ctx, 0x402408, 0x2); + gr_def(ctx, 0x402408, 0x00000600); + + /* 2800: CSCHED */ + cp_ctx(ctx, 0x402800, 0x1); + if (dev_priv->chipset == 0x50) + gr_def(ctx, 0x402800, 0x00000006); + + /* 2C00: ZCULL */ + cp_ctx(ctx, 0x402c08, 0x6); + if (dev_priv->chipset != 0x50) + gr_def(ctx, 0x402c14, 0x01000000); + gr_def(ctx, 0x402c18, 0x000000ff); + if (dev_priv->chipset == 0x50) + cp_ctx(ctx, 0x402ca0, 0x1); + else + cp_ctx(ctx, 0x402ca0, 0x2); + if (dev_priv->chipset < 0xa0) + gr_def(ctx, 0x402ca0, 0x00000400); + else if (!IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, 0x402ca0, 0x00000800); + else + gr_def(ctx, 0x402ca0, 0x00000400); + cp_ctx(ctx, 0x402cac, 0x4); + + /* 3000: ENG2D */ + cp_ctx(ctx, 0x403004, 0x1); + gr_def(ctx, 0x403004, 0x00000001); + + /* 3400 */ + if (dev_priv->chipset >= 0xa0) { + cp_ctx(ctx, 0x403404, 0x1); + gr_def(ctx, 0x403404, 0x00000001); + } + + /* 5000: CCACHE */ + cp_ctx(ctx, 0x405000, 0x1); + switch (dev_priv->chipset) { + case 0x50: + gr_def(ctx, 0x405000, 0x00300080); + break; + case 0x84: + case 0xa0: + case 0xa3: + case 0xa5: + case 0xa8: + case 0xaa: + case 0xac: + case 0xaf: + gr_def(ctx, 0x405000, 0x000e0080); + break; + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0x98: + gr_def(ctx, 0x405000, 0x00000080); + break; + } + cp_ctx(ctx, 0x405014, 0x1); + gr_def(ctx, 0x405014, 0x00000004); + cp_ctx(ctx, 0x40501c, 0x1); + cp_ctx(ctx, 0x405024, 0x1); + cp_ctx(ctx, 0x40502c, 0x1); + + /* 6000? */ + if (dev_priv->chipset == 0x50) + cp_ctx(ctx, 0x4063e0, 0x1); + + /* 6800: M2MF */ + if (dev_priv->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) + gr_def(ctx, 0x406818, 0x00000f80); + else + gr_def(ctx, 0x406818, 0x00001f80); + if (IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, 0x40681c, 0x00000030); + cp_ctx(ctx, 0x406830, 0x3); + } + + /* 7000: per-ROP group state */ + for (i = 0; i < 8; i++) { + if (units & (1<<(i+16))) { + cp_ctx(ctx, 0x407000 + (i<<8), 3); + if (dev_priv->chipset == 0x50) + gr_def(ctx, 0x407000 + (i<<8), 0x1b74f820); + else if (dev_priv->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) { + cp_ctx(ctx, 0x407010 + (i<<8), 1); + } else if (dev_priv->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) + 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) + gr_def(ctx, 0x407080 + (i<<8), 0x027c10fa); + else + gr_def(ctx, 0x407080 + (i<<8), 0x827c10fa); + if (dev_priv->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) + cp_ctx(ctx, 0x407094 + (i<<8), 1); + else if (!IS_NVA3F(dev_priv->chipset)) + cp_ctx(ctx, 0x407094 + (i<<8), 3); + else { + cp_ctx(ctx, 0x407094 + (i<<8), 4); + gr_def(ctx, 0x4070a0 + (i<<8), 1); + } + } + } + + cp_ctx(ctx, 0x407c00, 0x3); + if (dev_priv->chipset < 0x90) + gr_def(ctx, 0x407c00, 0x00010040); + else if (dev_priv->chipset < 0xa0) + gr_def(ctx, 0x407c00, 0x00390040); + else + gr_def(ctx, 0x407c00, 0x003d0040); + gr_def(ctx, 0x407c08, 0x00000022); + if (dev_priv->chipset >= 0xa0) { + cp_ctx(ctx, 0x407c10, 0x3); + cp_ctx(ctx, 0x407c20, 0x1); + cp_ctx(ctx, 0x407c2c, 0x1); + } + + if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, 0x407d00, 0x9); + } else { + cp_ctx(ctx, 0x407d00, 0x15); + } + if (dev_priv->chipset == 0x98) + gr_def(ctx, 0x407d08, 0x00380040); + else { + if (dev_priv->chipset < 0x90) + gr_def(ctx, 0x407d08, 0x00010040); + else if (dev_priv->chipset < 0xa0) + gr_def(ctx, 0x407d08, 0x00390040); + else + gr_def(ctx, 0x407d08, 0x003d0040); + gr_def(ctx, 0x407d0c, 0x00000022); + } + + /* 8000+: per-TP state */ + for (i = 0; i < 10; i++) { + if (units & (1<chipset < 0xa0) + base = 0x408000 + (i<<12); + else + base = 0x408000 + (i<<11); + if (dev_priv->chipset < 0xa0) + offset = base + 0xc00; + else + offset = base + 0x80; + cp_ctx(ctx, offset + 0x00, 1); + gr_def(ctx, offset + 0x00, 0x0000ff0a); + cp_ctx(ctx, offset + 0x08, 1); + + /* per-MP state */ + for (j = 0; j < (dev_priv->chipset < 0xa0 ? 2 : 4); j++) { + if (!(units & (1 << (j+24)))) continue; + if (dev_priv->chipset < 0xa0) + offset = base + 0x200 + (j<<7); + else + offset = base + 0x100 + (j<<7); + cp_ctx(ctx, offset, 0x20); + gr_def(ctx, offset + 0x00, 0x01800000); + gr_def(ctx, offset + 0x04, 0x00160000); + gr_def(ctx, offset + 0x08, 0x01800000); + gr_def(ctx, offset + 0x18, 0x0003ffff); + switch (dev_priv->chipset) { + case 0x50: + gr_def(ctx, offset + 0x1c, 0x00080000); + break; + case 0x84: + gr_def(ctx, offset + 0x1c, 0x00880000); + break; + case 0x86: + gr_def(ctx, offset + 0x1c, 0x018c0000); + break; + case 0x92: + case 0x96: + case 0x98: + gr_def(ctx, offset + 0x1c, 0x118c0000); + break; + case 0x94: + gr_def(ctx, offset + 0x1c, 0x10880000); + break; + case 0xa0: + case 0xa5: + gr_def(ctx, offset + 0x1c, 0x310c0000); + break; + case 0xa3: + case 0xa8: + case 0xaa: + case 0xac: + case 0xaf: + gr_def(ctx, offset + 0x1c, 0x300c0000); + break; + } + gr_def(ctx, offset + 0x40, 0x00010401); + if (dev_priv->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) + gr_def(ctx, offset + 0x5c, 0x00000080); + else + gr_def(ctx, offset + 0x5c, 0x08000080); + if (dev_priv->chipset >= 0xa0) + gr_def(ctx, offset + 0x68, 0x0000003e); + } + + if (dev_priv->chipset < 0xa0) + cp_ctx(ctx, base + 0x300, 0x4); + else + cp_ctx(ctx, base + 0x300, 0x5); + if (dev_priv->chipset == 0x50) + gr_def(ctx, base + 0x304, 0x00007070); + else if (dev_priv->chipset < 0xa0) + gr_def(ctx, base + 0x304, 0x00027070); + else if (!IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, base + 0x304, 0x01127070); + else + gr_def(ctx, base + 0x304, 0x05127070); + + if (dev_priv->chipset < 0xa0) + cp_ctx(ctx, base + 0x318, 1); + else + cp_ctx(ctx, base + 0x320, 1); + if (dev_priv->chipset == 0x50) + gr_def(ctx, base + 0x318, 0x0003ffff); + else if (dev_priv->chipset < 0xa0) + gr_def(ctx, base + 0x318, 0x03ffffff); + else + gr_def(ctx, base + 0x320, 0x07ffffff); + + if (dev_priv->chipset < 0xa0) + cp_ctx(ctx, base + 0x324, 5); + else + cp_ctx(ctx, base + 0x328, 4); + + if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, base + 0x340, 9); + offset = base + 0x340; + } else if (!IS_NVA3F(dev_priv->chipset)) { + cp_ctx(ctx, base + 0x33c, 0xb); + offset = base + 0x344; + } else { + cp_ctx(ctx, base + 0x33c, 0xd); + offset = base + 0x344; + } + gr_def(ctx, offset + 0x0, 0x00120407); + gr_def(ctx, offset + 0x4, 0x05091507); + if (dev_priv->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) + cp_ctx(ctx, base + 0x36c, 1); + + cp_ctx(ctx, base + 0x400, 2); + gr_def(ctx, base + 0x404, 0x00000040); + cp_ctx(ctx, base + 0x40c, 2); + gr_def(ctx, base + 0x40c, 0x0d0c0b0a); + gr_def(ctx, base + 0x410, 0x00141210); + + if (dev_priv->chipset < 0xa0) + offset = base + 0x800; + else + offset = base + 0x500; + cp_ctx(ctx, offset, 6); + 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)) + gr_def(ctx, offset + 0xc, 0x00008000); + gr_def(ctx, offset + 0x14, 0x00039e00); + cp_ctx(ctx, offset + 0x1c, 2); + if (dev_priv->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) { + cp_ctx(ctx, base + 0x54c, 2); + if (!IS_NVA3F(dev_priv->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) + offset = base + 0xa00; + else + offset = base + 0x680; + cp_ctx(ctx, offset, 1); + gr_def(ctx, offset, 0x00404040); + + if (dev_priv->chipset < 0xa0) + offset = base + 0xe00; + else + offset = base + 0x700; + cp_ctx(ctx, offset, 2); + if (dev_priv->chipset < 0xa0) + gr_def(ctx, offset, 0x0077f005); + else if (dev_priv->chipset == 0xa5) + gr_def(ctx, offset, 0x6cf7f007); + else if (dev_priv->chipset == 0xa8) + gr_def(ctx, offset, 0x6cfff007); + else if (dev_priv->chipset == 0xac) + gr_def(ctx, offset, 0x0cfff007); + else + gr_def(ctx, offset, 0x0cf7f007); + if (dev_priv->chipset == 0x50) + gr_def(ctx, offset + 0x4, 0x00007fff); + else if (dev_priv->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) { + cp_ctx(ctx, offset + 0x50, 9); + gr_def(ctx, offset + 0x54, 0x000003ff); + gr_def(ctx, offset + 0x58, 0x00000003); + gr_def(ctx, offset + 0x5c, 0x00000003); + gr_def(ctx, offset + 0x60, 0x000001ff); + gr_def(ctx, offset + 0x64, 0x0000001f); + gr_def(ctx, offset + 0x68, 0x0000000f); + gr_def(ctx, offset + 0x6c, 0x0000000f); + } else if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, offset + 0x50, 1); + cp_ctx(ctx, offset + 0x70, 1); + } else { + cp_ctx(ctx, offset + 0x50, 1); + cp_ctx(ctx, offset + 0x60, 5); + } + } + } +} + +static void +dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { + int i; + if (val && ctx->mode == NOUVEAU_GRCTX_VALS) + for (i = 0; i < num; i++) + nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + i), val); + ctx->ctxvals_pos += num; +} + +static void +nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int base, num; + base = ctx->ctxvals_pos; + + /* tesla state */ + dd_emit(ctx, 1, 0); /* 00000001 UNK0F90 */ + dd_emit(ctx, 1, 0); /* 00000001 UNK135C */ + + /* SRC_TIC state */ + dd_emit(ctx, 1, 0); /* 00000007 SRC_TILE_MODE_Z */ + dd_emit(ctx, 1, 2); /* 00000007 SRC_TILE_MODE_Y */ + 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) + dd_emit(ctx, 1, 0); /* 00000003 eng2d UNK0258 */ + dd_emit(ctx, 1, 1); /* 00000fff SRC_DEPTH */ + dd_emit(ctx, 1, 0x100); /* 0000ffff SRC_HEIGHT */ + + /* turing state */ + dd_emit(ctx, 1, 0); /* 0000000f TEXTURES_LOG2 */ + dd_emit(ctx, 1, 0); /* 0000000f SAMPLERS_LOG2 */ + dd_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ + dd_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ + dd_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ + dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ + dd_emit(ctx, 1, 1); /* 0000ffff BLOCK_ALLOC_THREADS */ + dd_emit(ctx, 1, 1); /* 00000001 LANES32 */ + dd_emit(ctx, 1, 0); /* 000000ff UNK370 */ + dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_UNK */ + dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_COUNT */ + dd_emit(ctx, 1, 1); /* 000000ff UNK384 bits 8-15 */ + dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ + dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ + dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ + dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_X */ + dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_XMY */ + dd_emit(ctx, 1, 0); /* 00000001 BLOCKDIM_XMY_OVERFLOW */ + dd_emit(ctx, 1, 1); /* 0003ffff BLOCKDIM_XMYMZ */ + dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_Y */ + 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)) + 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 */ + dd_emit(ctx, 1, 7); /* 00000007 LOCAL_WARPS_LOG_ALLOC */ + dd_emit(ctx, 1, 1); /* 00000007 STACK_WARPS_NO_CLAMP */ + dd_emit(ctx, 1, 7); /* 00000007 STACK_WARPS_LOG_ALLOC */ + dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_PACKED */ + dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_STRIDED */ + dd_emit(ctx, 1, 1); /* 000007ff BLOCK_ALLOC_THREADS */ + + /* compat 2d state */ + if (dev_priv->chipset == 0x50) { + dd_emit(ctx, 4, 0); /* 0000ffff clip X, Y, W, H */ + + dd_emit(ctx, 1, 1); /* ffffffff chroma COLOR_FORMAT */ + + dd_emit(ctx, 1, 1); /* ffffffff pattern COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff pattern SHAPE */ + dd_emit(ctx, 1, 1); /* ffffffff pattern PATTERN_SELECT */ + + dd_emit(ctx, 1, 0xa); /* ffffffff surf2d SRC_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff surf2d DMA_SRC */ + dd_emit(ctx, 1, 0); /* 000000ff surf2d SRC_ADDRESS_HIGH */ + dd_emit(ctx, 1, 0); /* ffffffff surf2d SRC_ADDRESS_LOW */ + dd_emit(ctx, 1, 0x40); /* 0000ffff surf2d SRC_PITCH */ + dd_emit(ctx, 1, 0); /* 0000000f surf2d SRC_TILE_MODE_Z */ + dd_emit(ctx, 1, 2); /* 0000000f surf2d SRC_TILE_MODE_Y */ + dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_HEIGHT */ + dd_emit(ctx, 1, 1); /* 00000001 surf2d SRC_LINEAR */ + dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_WIDTH */ + + dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_X */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_Y */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_X */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_Y */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_X */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_Y */ + dd_emit(ctx, 1, 1); /* ffffffff gdirect COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff gdirect OPERATION */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_X */ + dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_Y */ + + dd_emit(ctx, 1, 0); /* 0000ffff blit SRC_Y */ + dd_emit(ctx, 1, 0); /* ffffffff blit OPERATION */ + + dd_emit(ctx, 1, 0); /* ffffffff ifc OPERATION */ + + dd_emit(ctx, 1, 0); /* ffffffff iifc INDEX_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff iifc LUT_OFFSET */ + dd_emit(ctx, 1, 4); /* ffffffff iifc COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff iifc OPERATION */ + } + + /* m2mf state */ + dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_COUNT */ + dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_LENGTH_IN */ + dd_emit(ctx, 2, 0); /* ffffffff m2mf OFFSET_IN, OFFSET_OUT */ + dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_OUT */ + dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_OUT */ + dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_OUT_Z */ + dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_OUT */ + dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_OUT_X, Y */ + dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_OUT */ + dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_IN */ + dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_IN */ + dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_IN_Z */ + dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_IN */ + dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_IN_X, Y */ + dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_IN */ + + /* more compat 2d state */ + if (dev_priv->chipset == 0x50) { + dd_emit(ctx, 1, 1); /* ffffffff line COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff line OPERATION */ + + dd_emit(ctx, 1, 1); /* ffffffff triangle COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff triangle OPERATION */ + + dd_emit(ctx, 1, 0); /* 0000000f sifm TILE_MODE_Z */ + dd_emit(ctx, 1, 2); /* 0000000f sifm TILE_MODE_Y */ + dd_emit(ctx, 1, 0); /* 000000ff sifm FORMAT_FILTER */ + dd_emit(ctx, 1, 1); /* 000000ff sifm FORMAT_ORIGIN */ + dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_PITCH */ + dd_emit(ctx, 1, 1); /* 00000001 sifm SRC_LINEAR */ + dd_emit(ctx, 1, 0); /* 000000ff sifm SRC_OFFSET_HIGH */ + dd_emit(ctx, 1, 0); /* ffffffff sifm SRC_OFFSET */ + dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_HEIGHT */ + dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_WIDTH */ + dd_emit(ctx, 1, 3); /* ffffffff sifm COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff sifm OPERATION */ + + dd_emit(ctx, 1, 0); /* ffffffff sifc OPERATION */ + } + + /* tesla state */ + dd_emit(ctx, 1, 0); /* 0000000f GP_TEXTURES_LOG2 */ + dd_emit(ctx, 1, 0); /* 0000000f GP_SAMPLERS_LOG2 */ + dd_emit(ctx, 1, 0); /* 000000ff */ + dd_emit(ctx, 1, 0); /* ffffffff */ + dd_emit(ctx, 1, 4); /* 000000ff UNK12B0_0 */ + dd_emit(ctx, 1, 0x70); /* 000000ff UNK12B0_1 */ + dd_emit(ctx, 1, 0x80); /* 000000ff UNK12B0_3 */ + 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)) { + 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) + 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) { + dd_emit(ctx, 1, 0); /* 000000ff SEMANTIC_LAYER */ + dd_emit(ctx, 1, 0); /* 00000001 */ + } else { + dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_PTSZ.ENABLE */ + dd_emit(ctx, 1, 0x29); /* 000000ff SEMANTIC_PTSZ.PTSZ_ID */ + dd_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM */ + dd_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ + dd_emit(ctx, 1, 8); /* 0000000f SMENATIC_CLIP.CLIP_HIGH */ + dd_emit(ctx, 1, 4); /* 000000ff SEMANTIC_CLIP.CLIP_LO */ + dd_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ + dd_emit(ctx, 1, 0); /* 00000001 UNK1900 */ + } + dd_emit(ctx, 1, 0); /* 00000007 RT_CONTROL_MAP0 */ + dd_emit(ctx, 1, 1); /* 00000007 RT_CONTROL_MAP1 */ + dd_emit(ctx, 1, 2); /* 00000007 RT_CONTROL_MAP2 */ + dd_emit(ctx, 1, 3); /* 00000007 RT_CONTROL_MAP3 */ + dd_emit(ctx, 1, 4); /* 00000007 RT_CONTROL_MAP4 */ + dd_emit(ctx, 1, 5); /* 00000007 RT_CONTROL_MAP5 */ + dd_emit(ctx, 1, 6); /* 00000007 RT_CONTROL_MAP6 */ + dd_emit(ctx, 1, 7); /* 00000007 RT_CONTROL_MAP7 */ + dd_emit(ctx, 1, 1); /* 0000000f RT_CONTROL_COUNT */ + dd_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_UNK */ + 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) + dd_emit(ctx, 3, 0); /* 1, 1, 1 */ + else + dd_emit(ctx, 2, 0); /* 1, 1 */ + dd_emit(ctx, 1, 0); /* ffffffff GP_ENABLE */ + 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)) { + dd_emit(ctx, 1, 3); /* 00000003 */ + dd_emit(ctx, 1, 0); /* 00000001 UNK1418. Alone. */ + } + if (dev_priv->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) + 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 */ + dd_emit(ctx, 1, 0xc); /* 000000ff FP_INTERPOLANT_CTRL.OFFSET */ + dd_emit(ctx, 1, 1); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.W */ + dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.X */ + dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Y */ + dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Z */ + 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) + 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) + dd_emit(ctx, 8, 0); /* 00000001 */ + if (dev_priv->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 */ + dd_emit(ctx, 1, 0); /* 000000ff VTX_ATTR_DEFINE.ATTR */ + } + dd_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ + dd_emit(ctx, 1, 0x14); /* 0000001f ZETA_FORMAT */ + 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)) + dd_emit(ctx, 1, 0); /* 00000001 */ + dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_BACK */ + if (dev_priv->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) + 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) { + dd_emit(ctx, 1, 0xe00); /* 7fff */ + dd_emit(ctx, 1, 0x1000); /* 7fff */ + dd_emit(ctx, 1, 0x1e00); /* 7fff */ + } + dd_emit(ctx, 1, 0); /* 00000001 BEGIN_END_ACTIVE */ + dd_emit(ctx, 1, 1); /* 00000001 POLYGON_MODE_??? */ + dd_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP / 4 rounded up */ + dd_emit(ctx, 1, 1); /* 000000ff FP_REG_ALLOC_TEMP... without /4? */ + dd_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP / 4 rounded up */ + dd_emit(ctx, 1, 1); /* 00000001 */ + dd_emit(ctx, 1, 0); /* 00000001 */ + 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)) + dd_emit(ctx, 1, 0x200); + dd_emit(ctx, 1, 0); /* 00000001 */ + if (dev_priv->chipset < 0xa0) { + dd_emit(ctx, 1, 1); /* 00000001 */ + dd_emit(ctx, 1, 0x70); /* 000000ff */ + dd_emit(ctx, 1, 0x80); /* 000000ff */ + dd_emit(ctx, 1, 0); /* 000000ff */ + dd_emit(ctx, 1, 0); /* 00000001 */ + dd_emit(ctx, 1, 1); /* 00000001 */ + dd_emit(ctx, 1, 0x70); /* 000000ff */ + dd_emit(ctx, 1, 0x80); /* 000000ff */ + dd_emit(ctx, 1, 0); /* 000000ff */ + } else { + dd_emit(ctx, 1, 1); /* 00000001 */ + dd_emit(ctx, 1, 0xf0); /* 000000ff */ + dd_emit(ctx, 1, 0xff); /* 000000ff */ + dd_emit(ctx, 1, 0); /* 000000ff */ + dd_emit(ctx, 1, 0); /* 00000001 */ + dd_emit(ctx, 1, 1); /* 00000001 */ + dd_emit(ctx, 1, 0xf0); /* 000000ff */ + dd_emit(ctx, 1, 0xff); /* 000000ff */ + dd_emit(ctx, 1, 0); /* 000000ff */ + dd_emit(ctx, 1, 9); /* 0000003f UNK114C.COMP,SIZE */ + } + + /* eng2d state */ + dd_emit(ctx, 1, 0); /* 00000001 eng2d COLOR_KEY_ENABLE */ + dd_emit(ctx, 1, 0); /* 00000007 eng2d COLOR_KEY_FORMAT */ + dd_emit(ctx, 1, 1); /* ffffffff eng2d DST_DEPTH */ + dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DST_FORMAT */ + dd_emit(ctx, 1, 0); /* ffffffff eng2d DST_LAYER */ + dd_emit(ctx, 1, 1); /* 00000001 eng2d DST_LINEAR */ + dd_emit(ctx, 1, 0); /* 00000007 eng2d PATTERN_COLOR_FORMAT */ + dd_emit(ctx, 1, 0); /* 00000007 eng2d OPERATION */ + dd_emit(ctx, 1, 0); /* 00000003 eng2d PATTERN_SELECT */ + dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SIFC_FORMAT */ + dd_emit(ctx, 1, 0); /* 00000001 eng2d SIFC_BITMAP_ENABLE */ + dd_emit(ctx, 1, 2); /* 00000003 eng2d SIFC_BITMAP_UNK808 */ + dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DU_DX_FRACT */ + dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DU_DX_INT */ + dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DV_DY_FRACT */ + dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DV_DY_INT */ + dd_emit(ctx, 1, 0); /* 00000001 eng2d BLIT_CONTROL_FILTER */ + dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DRAW_COLOR_FORMAT */ + dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SRC_FORMAT */ + dd_emit(ctx, 1, 1); /* 00000001 eng2d SRC_LINEAR #2 */ + + num = ctx->ctxvals_pos - base; + ctx->ctxvals_pos = base; + if (IS_NVA3F(dev_priv->chipset)) + cp_ctx(ctx, 0x404800, num); + else + cp_ctx(ctx, 0x405400, num); +} + +/* + * xfer areas. These are a pain. + * + * There are 2 xfer areas: the first one is big and contains all sorts of + * stuff, the second is small and contains some per-TP context. + * + * Each area is split into 8 "strands". The areas, when saved to grctx, + * are made of 8-word blocks. Each block contains a single word from + * each strand. The strands are independent of each other, their + * addresses are unrelated to each other, and data in them is closely + * packed together. The strand layout varies a bit between cards: here + * and there, a single word is thrown out in the middle and the whole + * strand is offset by a bit from corresponding one on another chipset. + * For this reason, addresses of stuff in strands are almost useless. + * Knowing sequence of stuff and size of gaps between them is much more + * useful, and that's how we build the strands in our generator. + * + * NVA0 takes this mess to a whole new level by cutting the old strands + * into a few dozen pieces [known as genes], rearranging them randomly, + * and putting them back together to make new strands. Hopefully these + * genes correspond more or less directly to the same PGRAPH subunits + * as in 400040 register. + * + * The most common value in default context is 0, and when the genes + * are separated by 0's, gene bounduaries are quite speculative... + * some of them can be clearly deduced, others can be guessed, and yet + * others won't be resolved without figuring out the real meaning of + * given ctxval. For the same reason, ending point of each strand + * is unknown. Except for strand 0, which is the longest strand and + * its end corresponds to end of the whole xfer. + * + * An unsolved mystery is the seek instruction: it takes an argument + * in bits 8-18, and that argument is clearly the place in strands to + * seek to... but the offsets don't seem to correspond to offsets as + * seen in grctx. Perhaps there's another, real, not randomly-changing + * addressing in strands, and the xfer insn just happens to skip over + * the unused bits? NV10-NV30 PIPE comes to mind... + * + * As far as I know, there's no way to access the xfer areas directly + * without the help of ctxprog. + */ + +static void +xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { + int i; + if (val && ctx->mode == NOUVEAU_GRCTX_VALS) + for (i = 0; i < num; i++) + nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val); + ctx->ctxvals_pos += num << 3; +} + +/* Gene declarations... */ + +static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx); +static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx); +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; + int i; + int offset; + int size = 0; + uint32_t units = nv_rd32 (ctx->dev, 0x1540); + + offset = (ctx->ctxvals_pos+0x3f)&~0x3f; + ctx->ctxvals_base = offset; + + if (dev_priv->chipset < 0xa0) { + /* Strand 0 */ + ctx->ctxvals_pos = offset; + nv50_graph_construct_gene_dispatch(ctx); + nv50_graph_construct_gene_m2mf(ctx); + nv50_graph_construct_gene_unk24xx(ctx); + nv50_graph_construct_gene_clipid(ctx); + nv50_graph_construct_gene_zcull(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 1 */ + ctx->ctxvals_pos = offset + 0x1; + nv50_graph_construct_gene_vfetch(ctx); + nv50_graph_construct_gene_eng2d(ctx); + nv50_graph_construct_gene_csched(ctx); + nv50_graph_construct_gene_ropm1(ctx); + nv50_graph_construct_gene_ropm2(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 2 */ + ctx->ctxvals_pos = offset + 0x2; + nv50_graph_construct_gene_ccache(ctx); + nv50_graph_construct_gene_unk1cxx(ctx); + nv50_graph_construct_gene_strmout(ctx); + nv50_graph_construct_gene_unk14xx(ctx); + nv50_graph_construct_gene_unk10xx(ctx); + nv50_graph_construct_gene_unk34xx(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 3: per-ROP group state */ + ctx->ctxvals_pos = offset + 3; + for (i = 0; i < 6; i++) + if (units & (1 << (i + 16))) + nv50_graph_construct_gene_ropc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strands 4-7: per-TP state */ + for (i = 0; i < 4; i++) { + ctx->ctxvals_pos = offset + 4 + i; + if (units & (1 << (2 * i))) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << (2 * i + 1))) + nv50_graph_construct_xfer_tp(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + } + } else { + /* Strand 0 */ + ctx->ctxvals_pos = offset; + nv50_graph_construct_gene_dispatch(ctx); + nv50_graph_construct_gene_m2mf(ctx); + nv50_graph_construct_gene_unk34xx(ctx); + nv50_graph_construct_gene_csched(ctx); + nv50_graph_construct_gene_unk1cxx(ctx); + nv50_graph_construct_gene_strmout(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 1 */ + ctx->ctxvals_pos = offset + 1; + nv50_graph_construct_gene_unk10xx(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 2 */ + ctx->ctxvals_pos = offset + 2; + if (dev_priv->chipset == 0xa0) + nv50_graph_construct_gene_unk14xx(ctx); + nv50_graph_construct_gene_unk24xx(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 3 */ + ctx->ctxvals_pos = offset + 3; + nv50_graph_construct_gene_vfetch(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 4 */ + ctx->ctxvals_pos = offset + 4; + nv50_graph_construct_gene_ccache(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 5 */ + ctx->ctxvals_pos = offset + 5; + nv50_graph_construct_gene_ropm2(ctx); + nv50_graph_construct_gene_ropm1(ctx); + /* per-ROP context */ + for (i = 0; i < 8; i++) + if (units & (1<<(i+16))) + nv50_graph_construct_gene_ropc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 6 */ + ctx->ctxvals_pos = offset + 6; + nv50_graph_construct_gene_zcull(ctx); + nv50_graph_construct_gene_clipid(ctx); + nv50_graph_construct_gene_eng2d(ctx); + if (units & (1 << 0)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 1)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 2)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 3)) + nv50_graph_construct_xfer_tp(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 7 */ + ctx->ctxvals_pos = offset + 7; + if (dev_priv->chipset == 0xa0) { + if (units & (1 << 4)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 5)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 6)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 7)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 8)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 9)) + nv50_graph_construct_xfer_tp(ctx); + } else { + nv50_graph_construct_gene_unk14xx(ctx); + } + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + } + + ctx->ctxvals_pos = offset + size * 8; + ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f; + cp_lsr (ctx, offset); + cp_out (ctx, CP_SET_XFER_POINTER); + cp_lsr (ctx, size); + cp_out (ctx, CP_SEEK_1); + cp_out (ctx, CP_XFER_1); + cp_wait(ctx, XFER, BUSY); +} + +/* + * non-trivial demagiced parts of ctx init go here + */ + +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; + /* SEEK */ + if (dev_priv->chipset == 0x50) + xf_emit(ctx, 5, 0); + else if (!IS_NVA3F(dev_priv->chipset)) + xf_emit(ctx, 6, 0); + else + xf_emit(ctx, 4, 0); + /* SEEK */ + /* the PGRAPH's internal FIFO */ + if (dev_priv->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)) + xf_emit(ctx, 3, 0); + /* SEEK */ + /* CTX_SWITCH: caches of gr objects bound to subchannels. 8 values, last used index */ + xf_emit(ctx, 9, 0); + /* SEEK */ + xf_emit(ctx, 9, 0); + /* SEEK */ + xf_emit(ctx, 9, 0); + /* SEEK */ + xf_emit(ctx, 9, 0); + /* SEEK */ + if (dev_priv->chipset < 0x90) + xf_emit(ctx, 4, 0); + /* SEEK */ + xf_emit(ctx, 2, 0); + /* SEEK */ + xf_emit(ctx, 6*2, 0); + xf_emit(ctx, 2, 0); + /* SEEK */ + xf_emit(ctx, 2, 0); + /* SEEK */ + xf_emit(ctx, 6*2, 0); + xf_emit(ctx, 2, 0); + /* SEEK */ + if (dev_priv->chipset == 0x50) + xf_emit(ctx, 0x1c, 0); + else if (dev_priv->chipset < 0xa0) + xf_emit(ctx, 0x1e, 0); + else + xf_emit(ctx, 0x22, 0); + /* SEEK */ + xf_emit(ctx, 0x15, 0); +} + +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; + int smallm2mf = 0; + if (dev_priv->chipset < 0x92 || dev_priv->chipset == 0x98) + smallm2mf = 1; + /* SEEK */ + xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ + xf_emit (ctx, 1, 0); /* DMA_BUFFER_IN instance >> 4 */ + xf_emit (ctx, 1, 0); /* DMA_BUFFER_OUT instance >> 4 */ + xf_emit (ctx, 1, 0); /* OFFSET_IN */ + xf_emit (ctx, 1, 0); /* OFFSET_OUT */ + xf_emit (ctx, 1, 0); /* PITCH_IN */ + xf_emit (ctx, 1, 0); /* PITCH_OUT */ + xf_emit (ctx, 1, 0); /* LINE_LENGTH */ + xf_emit (ctx, 1, 0); /* LINE_COUNT */ + xf_emit (ctx, 1, 0x21); /* FORMAT: bits 0-4 INPUT_INC, bits 5-9 OUTPUT_INC */ + xf_emit (ctx, 1, 1); /* LINEAR_IN */ + xf_emit (ctx, 1, 0x2); /* TILING_MODE_IN: bits 0-2 y tiling, bits 3-5 z tiling */ + xf_emit (ctx, 1, 0x100); /* TILING_PITCH_IN */ + xf_emit (ctx, 1, 0x100); /* TILING_HEIGHT_IN */ + xf_emit (ctx, 1, 1); /* TILING_DEPTH_IN */ + xf_emit (ctx, 1, 0); /* TILING_POSITION_IN_Z */ + xf_emit (ctx, 1, 0); /* TILING_POSITION_IN */ + xf_emit (ctx, 1, 1); /* LINEAR_OUT */ + xf_emit (ctx, 1, 0x2); /* TILING_MODE_OUT: bits 0-2 y tiling, bits 3-5 z tiling */ + xf_emit (ctx, 1, 0x100); /* TILING_PITCH_OUT */ + xf_emit (ctx, 1, 0x100); /* TILING_HEIGHT_OUT */ + xf_emit (ctx, 1, 1); /* TILING_DEPTH_OUT */ + xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT_Z */ + xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT */ + xf_emit (ctx, 1, 0); /* OFFSET_IN_HIGH */ + xf_emit (ctx, 1, 0); /* OFFSET_OUT_HIGH */ + /* SEEK */ + if (smallm2mf) + xf_emit(ctx, 0x40, 0); /* 20 * ffffffff, 3ffff */ + else + xf_emit(ctx, 0x100, 0); /* 80 * ffffffff, 3ffff */ + xf_emit(ctx, 4, 0); /* 1f/7f, 0, 1f/7f, 0 [1f for smallm2mf, 7f otherwise] */ + /* SEEK */ + if (smallm2mf) + xf_emit(ctx, 0x400, 0); /* ffffffff */ + else + xf_emit(ctx, 0x800, 0); /* ffffffff */ + xf_emit(ctx, 4, 0); /* ff/1ff, 0, 0, 0 [ff for smallm2mf, 1ff otherwise] */ + /* SEEK */ + xf_emit(ctx, 0x40, 0); /* 20 * bits ffffffff, 3ffff */ + xf_emit(ctx, 0x6, 0); /* 1f, 0, 1f, 0, 1f, 0 */ +} + +static void +nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + xf_emit(ctx, 2, 0); /* RO */ + xf_emit(ctx, 0x800, 0); /* ffffffff */ + switch (dev_priv->chipset) { + case 0x50: + case 0x92: + case 0xa0: + xf_emit(ctx, 0x2b, 0); + break; + case 0x84: + xf_emit(ctx, 0x29, 0); + break; + case 0x94: + case 0x96: + case 0xa3: + xf_emit(ctx, 0x27, 0); + break; + case 0x86: + case 0x98: + case 0xa5: + case 0xa8: + case 0xaa: + case 0xac: + case 0xaf: + xf_emit(ctx, 0x25, 0); + break; + } + /* CB bindings, 0x80 of them. first word is address >> 8, second is + * size >> 4 | valid << 24 */ + xf_emit(ctx, 0x100, 0); /* ffffffff CB_DEF */ + xf_emit(ctx, 1, 0); /* 0000007f CB_ADDR_BUFFER */ + xf_emit(ctx, 1, 0); /* 0 */ + xf_emit(ctx, 0x30, 0); /* ff SET_PROGRAM_CB */ + xf_emit(ctx, 1, 0); /* 3f last SET_PROGRAM_CB */ + xf_emit(ctx, 4, 0); /* RO */ + xf_emit(ctx, 0x100, 0); /* ffffffff */ + xf_emit(ctx, 8, 0); /* 1f, 0, 0, ... */ + xf_emit(ctx, 8, 0); /* ffffffff */ + xf_emit(ctx, 4, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 3 */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_CODE_CB */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_TIC */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_TSC */ + xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ + xf_emit(ctx, 1, 0); /* 000000ff TIC_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff TIC_ADDRESS_LOW */ + xf_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ + xf_emit(ctx, 1, 0); /* 000000ff TSC_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff TSC_ADDRESS_LOW */ + xf_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ + xf_emit(ctx, 1, 0); /* 000000ff VP_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff VP_ADDRESS_LOW */ + xf_emit(ctx, 1, 0); /* 00ffffff VP_START_ID */ + xf_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0); /* 000000ff GP_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff GP_ADDRESS_LOW */ + xf_emit(ctx, 1, 0); /* 00ffffff GP_START_ID */ + xf_emit(ctx, 1, 0); /* 000000ff FP_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ + xf_emit(ctx, 1, 0); /* 00ffffff FP_START_ID */ +} + +static void +nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + /* end of area 2 on pre-NVA0, area 1 on NVAx */ + 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 */ + xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ + 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) + 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) { + case 0x50: + case 0x86: + case 0x98: + case 0xaa: + case 0xac: + xf_emit(ctx, 0xa0, 0); /* ffffffff */ + break; + case 0x84: + case 0x92: + case 0x94: + case 0x96: + xf_emit(ctx, 0x120, 0); + break; + case 0xa5: + case 0xa8: + xf_emit(ctx, 0x100, 0); /* ffffffff */ + break; + case 0xa0: + case 0xa3: + case 0xaf: + xf_emit(ctx, 0x400, 0); /* ffffffff */ + break; + } + xf_emit(ctx, 4, 0); /* 3f, 0, 0, 0 */ + xf_emit(ctx, 4, 0); /* ffffffff */ + } + 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 */ + xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ + xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_TEMP */ + xf_emit(ctx, 1, 1); /* 00000001 RASTERIZE_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ + xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ + xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ +} + +static void +nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* 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 */ + xf_emit(ctx, 0x10, 0x04000000); /* 07ffffff VIEWPORT_CLIP_HORIZ*8, VIEWPORT_CLIP_VERT*8 */ + xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ + xf_emit(ctx, 0x20, 0); /* ffffffff POLYGON_STIPPLE */ + xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ + xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ + 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) + xf_emit(ctx, 1, 0x0fac6881); + if (IS_NVA3F(dev_priv->chipset)) { + xf_emit(ctx, 1, 1); + xf_emit(ctx, 3, 0); + } +} + +static void +nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ + if (dev_priv->chipset != 0x50) { + xf_emit(ctx, 5, 0); /* ffffffff */ + xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ + xf_emit(ctx, 1, 0); /* 00000001 */ + xf_emit(ctx, 1, 0); /* 000003ff */ + xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ + xf_emit(ctx, 1, 0); /* 00000001 */ + xf_emit(ctx, 2, 4); /* 7f, ff */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + } + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + 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) + 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) + xf_emit(ctx, 1, 0x7f); /* 000000ff tesla UNK0FFC */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 1); /* 00000001 SHADE_MODEL */ + xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0F8C */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + 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) + xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ + else + xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ + xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ + xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ + xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_SCALE: X0, Y0, Z0, X1, Y1, ... */ + xf_emit(ctx, 3, 0); /* f, 0, 0 */ + xf_emit(ctx, 3, 0); /* ffffffff last VIEWPORT_SCALE? */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ + xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 1, 0); /* 00000001 */ + xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_TRANSLATE */ + xf_emit(ctx, 3, 0); /* f, 0, 0 */ + xf_emit(ctx, 3, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 2, 0x88); /* 000001ff tesla UNK19D8 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ + xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ + xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ + xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ + xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ + xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ + xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 0); /* 0000000f */ + xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ + 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)) + 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) { + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 00000001 */ + xf_emit(ctx, 1, 0); /* 000003ff */ + } + xf_emit(ctx, 0x20, 0); /* 10xbits ffffffff, 3fffff. SCISSOR_* */ + xf_emit(ctx, 1, 0); /* f */ + xf_emit(ctx, 1, 0); /* 0? */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 003fffff */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ + xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ + xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ + xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ + xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ + xf_emit(ctx, 1, 0); /* 0000000f */ +} + +static void +nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */ + /* SEEK */ + xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ + xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ + xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ + xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ + xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ + xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ + xf_emit(ctx, 1, 0); /* 00000001 */ + 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 */ + xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ + xf_emit(ctx, 1, 0); /* 0000ffff */ + xf_emit(ctx, 1, 0); /* 00000001 UNK0FB0 */ + xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ + xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ + xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ + 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_FUNC_REF */ + 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 */ + 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) + xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1108 */ + xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ + xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ + /* SEEK */ + xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ + xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ + xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ + xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ + xf_emit(ctx, 1, 0x10); /* 7f/ff/3ff VIEW_VOLUME_CLIP_CTRL */ + 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) + xf_emit(ctx, 1, 0); /* 0fffffff tesla UNK1104 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK151C */ +} + +static void +nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx) +{ + /* middle of strand 0 on pre-NVA0 [after 24xx], middle of area 6 on NVAx */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* 00000007 UNK0FB4 */ + /* SEEK */ + xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_HORIZ */ + xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_VERT */ + xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ + xf_emit(ctx, 2, 0x04000000); /* 07ffffff UNK1508 */ + xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ + xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_WIDTH */ + xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ID */ + xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff CLIPID_ADDRESS_LOW */ + xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_HEIGHT */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_CLIPID */ +} + +static void +nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */ + /* SEEK */ + xf_emit(ctx, 0x33, 0); + /* SEEK */ + xf_emit(ctx, 2, 0); + /* SEEK */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + 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)) { + xf_emit(ctx, 4, 0); /* RO */ + xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ + xf_emit(ctx, 1, 0); /* 1ff */ + xf_emit(ctx, 8, 0); /* 0? */ + xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ + + xf_emit(ctx, 4, 0); /* RO */ + xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ + xf_emit(ctx, 1, 0); /* 1ff */ + xf_emit(ctx, 8, 0); /* 0? */ + xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ + } else { + xf_emit(ctx, 0xc, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ + xf_emit(ctx, 1, 0); /* 1ff */ + xf_emit(ctx, 8, 0); /* 0? */ + + /* SEEK */ + xf_emit(ctx, 0xc, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ + xf_emit(ctx, 1, 0); /* 1ff */ + xf_emit(ctx, 8, 0); /* 0? */ + } + /* SEEK */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + 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) + xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ + xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ + xf_emit(ctx, 1, 1); /* 00000001 */ + /* SEEK */ + if (dev_priv->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 */ + xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + xf_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM_ID */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0); /* 0000000f */ + xf_emit(ctx, 1, 1); /* 00000001 */ + for (i = 0; i < 10; i++) { + /* SEEK */ + xf_emit(ctx, 0x40, 0); /* ffffffff */ + xf_emit(ctx, 0x10, 0); /* 3, 0, 0.... */ + xf_emit(ctx, 0x10, 0); /* ffffffff */ + } + /* SEEK */ + xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_CTRL */ + xf_emit(ctx, 1, 1); /* 00000001 */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ + 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) + 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; + int acnt = 0x10, rep, i; + /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */ + if (IS_NVA3F(dev_priv->chipset)) + acnt = 0x20; + /* SEEK */ + if (dev_priv->chipset >= 0xa0) { + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */ + xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */ + } + xf_emit(ctx, 1, 0); /* ffffffff VERTEX_BUFFER_FIRST */ + xf_emit(ctx, 1, 0); /* 00000001 PRIMITIVE_RESTART_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 UNK0DE8 */ + xf_emit(ctx, 1, 0); /* ffffffff PRIMITIVE_RESTART_INDEX */ + xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ + xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ + xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATR_MASK_UNK0DD0 */ + xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ + xf_emit(ctx, 1, 0x20); /* 0000ffff tesla UNK129C */ + xf_emit(ctx, 1, 0); /* 000000ff turing UNK370??? */ + 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)) + xf_emit(ctx, 0xb, 0); /* RO */ + else if (dev_priv->chipset >= 0xa0) + xf_emit(ctx, 0x9, 0); /* RO */ + else + xf_emit(ctx, 0x8, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* 00000001 EDGE_FLAG */ + xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ + /* SEEK */ + xf_emit(ctx, 0xc, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* 7f/ff */ + xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ + xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ + 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) + xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */ + else + xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */ + if (dev_priv->chipset == 0xa8) + xf_emit(ctx, 1, 0x1e00); /* 7fff */ + /* SEEK */ + xf_emit(ctx, 0xc, 0); /* RO or close */ + /* SEEK */ + 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) + 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)) { + xf_emit(ctx, 0x10, 0); /* 0? */ + xf_emit(ctx, 2, 0); /* weird... */ + xf_emit(ctx, 2, 0); /* RO */ + } else { + xf_emit(ctx, 8, 0); /* 0? */ + xf_emit(ctx, 1, 0); /* weird... */ + xf_emit(ctx, 2, 0); /* RO */ + } + /* SEEK */ + 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) + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ + xf_emit(ctx, 1, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ + xf_emit(ctx, 1, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* RO */ + xf_emit(ctx, 2, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK111C? */ + xf_emit(ctx, 1, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* 000000ff UNK15F4_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff UNK15F4_ADDRESS_LOW */ + xf_emit(ctx, 1, 0); /* 000000ff UNK0F84_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff UNK0F84_ADDRESS_LOW */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* 00003fff VERTEX_ARRAY_ATTRIB_OFFSET */ + xf_emit(ctx, 3, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* 00000fff VERTEX_ARRAY_STRIDE */ + xf_emit(ctx, 3, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_LOW */ + xf_emit(ctx, 3, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_ARRAY_HIGH */ + xf_emit(ctx, 3, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_LIMIT_LOW */ + xf_emit(ctx, 3, 0); /* f/1f */ + /* SEEK */ + xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */ + xf_emit(ctx, 3, 0); /* f/1f */ + /* SEEK */ + if (IS_NVA3F(dev_priv->chipset)) { + xf_emit(ctx, acnt, 0); /* f */ + xf_emit(ctx, 3, 0); /* f/1f */ + } + /* SEEK */ + if (IS_NVA3F(dev_priv->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) { + xf_emit(ctx, 0x41, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 0x11, 0); /* RO */ + } else if (!IS_NVA3F(dev_priv->chipset)) + xf_emit(ctx, 0x50, 0); /* RO */ + else + xf_emit(ctx, 0x58, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ + xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ + xf_emit(ctx, 1, 1); /* 1 UNK0DEC */ + /* SEEK */ + 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)) + xf_emit(ctx, 0x1d, 0); /* RO */ + else + xf_emit(ctx, 0x16, 0); /* RO */ + /* SEEK */ + 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) + xf_emit(ctx, 8, 0); /* RO */ + else if (IS_NVA3F(dev_priv->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) + rep = 0xc; + else + rep = 4; + for (i = 0; i < rep; i++) { + /* SEEK */ + if (IS_NVA3F(dev_priv->chipset)) + xf_emit(ctx, 0x20, 0); /* ffffffff */ + xf_emit(ctx, 0x200, 0); /* ffffffff */ + xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */ + xf_emit(ctx, 4, 0); /* ffffffff */ + } + /* SEEK */ + xf_emit(ctx, 1, 0); /* 113/111 */ + xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ + xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ + xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATTR_MASK_UNK0DD0 */ + 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)) + xf_emit(ctx, 7, 0); /* weird... */ + else + xf_emit(ctx, 5, 0); /* weird... */ +} + +static void +nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* 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) { + /* 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 */ + xf_emit(ctx, 2, 1); /* 0000ffff IFC_CLIP_W, H */ + xf_emit(ctx, 1, 0); /* 00000001 IFC_CLIP_ENABLE */ + } + xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ + xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ + xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ + xf_emit(ctx, 1, 0x11); /* 3f[NV50]/7f[NV84+] DST_FORMAT */ + xf_emit(ctx, 1, 0); /* 0001ffff DRAW_POINT_X */ + xf_emit(ctx, 1, 8); /* 0000000f DRAW_UNK58C */ + xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_X_FRACT */ + xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_X_INT */ + xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_Y_FRACT */ + xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_Y_INT */ + xf_emit(ctx, 1, 0); /* 000fffff SIFC_DX_DU_FRACT */ + xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DX_DU_INT */ + xf_emit(ctx, 1, 0); /* 000fffff SIFC_DY_DV_FRACT */ + xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DY_DV_INT */ + xf_emit(ctx, 1, 1); /* 0000ffff SIFC_WIDTH */ + xf_emit(ctx, 1, 1); /* 0000ffff SIFC_HEIGHT */ + xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ + xf_emit(ctx, 1, 2); /* 00000003 SIFC_BITMAP_UNK808 */ + xf_emit(ctx, 1, 0); /* 00000003 SIFC_BITMAP_LINE_PACK_MODE */ + xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_LSB_FIRST */ + xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_ENABLE */ + xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_X */ + xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_Y */ + xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ + xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ + xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ + xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ + xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_W */ + xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_H */ + xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_X_FRACT */ + xf_emit(ctx, 1, 0); /* 0001ffff BLIT_SRC_X_INT */ + xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_Y_FRACT */ + xf_emit(ctx, 1, 0); /* 00000001 UNK888 */ + xf_emit(ctx, 1, 4); /* 0000003f UNK884 */ + xf_emit(ctx, 1, 0); /* 00000007 UNK880 */ + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK0FB8 */ + xf_emit(ctx, 1, 0x15); /* 000000ff tesla UNK128C */ + xf_emit(ctx, 2, 0); /* 00000007, ffff0ff3 */ + xf_emit(ctx, 1, 0); /* 00000001 UNK260 */ + xf_emit(ctx, 1, 0x4444480); /* 1fffffff UNK870 */ + /* SEEK */ + xf_emit(ctx, 0x10, 0); + /* SEEK */ + xf_emit(ctx, 0x27, 0); +} + +static void +nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* 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??? */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ + xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + xf_emit(ctx, 1, 0); /* 000003ff */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* ffffffff turing UNK364 */ + xf_emit(ctx, 1, 0); /* 0000000f turing UNK36C */ + xf_emit(ctx, 1, 0); /* 0000ffff USER_PARAM_COUNT */ + xf_emit(ctx, 1, 0x100); /* 00ffffff turing UNK384 */ + xf_emit(ctx, 1, 0); /* 0000000f turing UNK2A0 */ + xf_emit(ctx, 1, 0); /* 0000ffff GRIDID */ + xf_emit(ctx, 1, 0x10001); /* ffffffff GRIDDIM_XY */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ + xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ + xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ + xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ + xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ + xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ + /* SEEK */ + xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */ + switch (dev_priv->chipset) { + case 0x50: + case 0x92: + xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ + xf_emit(ctx, 0x80, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 0x10*2, 0); /* ffffffff, 1f */ + break; + case 0x84: + xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ + xf_emit(ctx, 0x60, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ + break; + case 0x94: + case 0x96: + xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ + xf_emit(ctx, 0x40, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 8*2, 0); /* ffffffff, 1f */ + break; + case 0x86: + case 0x98: + xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ + xf_emit(ctx, 0x10, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ + break; + case 0xa0: + xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ + xf_emit(ctx, 0xf0, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 0x1e*2, 0); /* ffffffff, 1f */ + break; + case 0xa3: + xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ + xf_emit(ctx, 0x60, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ + break; + case 0xa5: + case 0xaf: + xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ + xf_emit(ctx, 0x30, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 6*2, 0); /* ffffffff, 1f */ + break; + case 0xaa: + xf_emit(ctx, 0x12, 0); + break; + case 0xa8: + case 0xac: + xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ + xf_emit(ctx, 0x10, 0); /* fff */ + xf_emit(ctx, 2, 0); /* ff, fff */ + xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ + break; + } + xf_emit(ctx, 1, 0); /* 0000000f */ + xf_emit(ctx, 1, 0); /* 00000000 */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 0000001f */ + xf_emit(ctx, 4, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 4, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 000000ff */ +} + +static void +nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + 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 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ + xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ + xf_emit(ctx, 3, 0); /* 00000001 POLYGON_OFFSET_*_ENABLE */ + xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ + xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ + xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ + xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ + xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_UNITS */ + xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_FACTOR */ + xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ + xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ + xf_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_LINEAR */ + 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)) + xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */ + else if (dev_priv->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 */ + xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ + xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ + xf_emit(ctx, 1, 5); /* 0000000f UNK1408 */ + xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ + 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) { + xf_emit(ctx, 1, 0); /* 3ff */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */ + } + if (IS_NVA3F(dev_priv->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 */ + xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 0x20, 0); /* 07ffffff VIEWPORT_HORIZ, then VIEWPORT_VERT. (W&0x3fff)<<13 | (X&0x1fff). */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK187C */ + xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ + xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + xf_emit(ctx, 1, 5); /* 0000000f tesla UNK1220 */ + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1A20 */ + 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) + xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ + if (dev_priv->chipset < 0xa0) + xf_emit(ctx, 0x1c, 0); /* RO */ + else if (IS_NVA3F(dev_priv->chipset)) + xf_emit(ctx, 0x9, 0); + xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ + 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) { + 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) + xf_emit(ctx, 0x25, 0); + else + xf_emit(ctx, 0x3b, 0); +} + +static void +nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + 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) { + 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) + xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ + else + xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + /* SEEK */ + xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ + xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ + 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) { + xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ + xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ + } + xf_emit(ctx, 1, 0); /* 0000ffff DMA_STRMOUT */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ + xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ + xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW QUERY_COUNTER */ + xf_emit(ctx, 2, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + /* SEEK */ + xf_emit(ctx, 0x20, 0); /* ffffffff STRMOUT_MAP */ + xf_emit(ctx, 1, 0); /* 0000000f */ + xf_emit(ctx, 1, 0); /* 00000000? */ + xf_emit(ctx, 2, 0); /* ffffffff */ +} + +static void +nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + 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)) + xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ +} + +static void +nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* SEEK */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 2, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ + xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ + xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ + xf_emit(ctx, 1, 0); /* 7 */ + /* SEEK */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ + xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ + xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ + xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ + xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ + 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)) + xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ +} + +static void +nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int magic2; + if (dev_priv->chipset == 0x50) { + magic2 = 0x00003e60; + } else if (!IS_NVA3F(dev_priv->chipset)) { + magic2 = 0x001ffe67; + } else { + magic2 = 0x00087e67; + } + xf_emit(ctx, 1, 0); /* f/7 MUTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ + xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ + xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + 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)) + 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)) + xf_emit(ctx, 1, 0x15); /* 000000ff */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ + xf_emit(ctx, 1, 0x10); /* 3ff/ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ + 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) { + 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)) + xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */ + else + xf_emit(ctx, 1, 0x15); /* ff */ + } + } + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + 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 */ + 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); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ + xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ + xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ + xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + 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 */ + xf_emit(ctx, 1, 0); /* 0000000f */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ + 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_FUNC_REF */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ + xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ + xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ + xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ + xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + 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 */ + xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ + 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_FUNC_REF */ + 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 */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ + xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 2, 0); /* ffff0ff3, ffff */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ + xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + 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) { + xf_emit(ctx, 2, 0); + xf_emit(ctx, 1, 0x1001); + xf_emit(ctx, 0xb, 0); + } else { + xf_emit(ctx, 1, 0); /* 00000007 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + } + xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ + 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) { + xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ + xf_emit(ctx, 1, 0); /* 000000ff */ + } + xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ + xf_emit(ctx, 2, 1); /* 00000007 BLEND_EQUATION_RGB, ALPHA */ + xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ + xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ + xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ + xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ + xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 1, 0); /* 00000001 */ + 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)) { + 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 */ + xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ + xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ + xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ + xf_emit(ctx, 2, 0); /* 00000001 */ + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ + xf_emit(ctx, 1, 0); /* 0000000f */ + xf_emit(ctx, 1, 0); /* 00000003 */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 2, 0); /* 00000001 */ + 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) { + xf_emit(ctx, 2, 0); /* 00000001 */ + xf_emit(ctx, 1, 0); /* 00000007 */ + xf_emit(ctx, 1, 0); /* 00000003 */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 2, 0); /* 00000001 */ + } else { + xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1430 */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ + } + 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) + xf_emit(ctx, 2, 0); /* 00000001 */ + xf_emit(ctx, 1, 0); /* 000003ff */ + xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ + xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ + 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_ALPHA */ + xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ + 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) + xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */ + if (IS_NVA3F(dev_priv->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 */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ + xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ + xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK15C4 */ + xf_emit(ctx, 1, 0); /* 00000001 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ + } + xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ + xf_emit(ctx, 1, 0); /* 00000007 PATTERN_COLOR_FORMAT */ + xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_COLOR */ + xf_emit(ctx, 1, 0); /* 00000001 PATTERN_MONO_FORMAT */ + xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_BITMAP */ + xf_emit(ctx, 1, 0); /* 00000003 PATTERN_SELECT */ + xf_emit(ctx, 1, 0); /* 000000ff ROP */ + xf_emit(ctx, 1, 0); /* ffffffff BETA1 */ + xf_emit(ctx, 1, 0); /* ffffffff BETA4 */ + xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ + xf_emit(ctx, 0x50, 0); /* 10x ffffff, ffffff, ffffff, ffffff, 3 PATTERN */ +} + +static void +nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int magic3; + switch (dev_priv->chipset) { + case 0x50: + magic3 = 0x1000; + break; + case 0x86: + case 0x98: + case 0xa8: + case 0xaa: + case 0xac: + case 0xaf: + magic3 = 0x1e00; + break; + default: + magic3 = 0; + } + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 4); /* 7f/ff[NVA0+] VP_REG_ALLOC_RESULT */ + 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)) + xf_emit(ctx, 0x1f, 0); /* ffffffff */ + else if (dev_priv->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) + xf_emit(ctx, 1, 0x03020100); /* ffffffff */ + else + xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 2, 0); /* 111/113, 7f/ff */ + xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ + if (magic3) + xf_emit(ctx, 1, magic3); /* 00007fff tesla UNK141C */ + xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 0); /* 111/113 */ + xf_emit(ctx, 0x1f, 0); /* ffffffff GP_RESULT_MAP_1 up */ + xf_emit(ctx, 1, 0); /* 0000001f */ + xf_emit(ctx, 1, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ + xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0x03020100); /* ffffffff GP_RESULT_MAP_0 */ + xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ + if (magic3) + xf_emit(ctx, 1, magic3); /* 7fff tesla UNK141C */ + xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 0); /* 111/113 */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ + xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + xf_emit(ctx, 1, 0); /* 00000003 tesla UNK13A0 */ + xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ + 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) + xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ + else if (dev_priv->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)) + xf_emit(ctx, 0x210, 0); /* ffffffff */ + else + xf_emit(ctx, 0x410, 0); /* ffffffff */ + xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ + xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ + xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ +} + +static void +nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int magic1, magic2; + if (dev_priv->chipset == 0x50) { + magic1 = 0x3ff; + magic2 = 0x00003e60; + } else if (!IS_NVA3F(dev_priv->chipset)) { + magic1 = 0x7ff; + magic2 = 0x001ffe67; + } else { + magic1 = 0x7ff; + magic2 = 0x00087e67; + } + 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)) + 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 */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ + xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ + xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR */ + xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ + xf_emit(ctx, 1, 0); /* 00000001 UNK0FDC */ + xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ + xf_emit(ctx, 1, 0); /* ff[NV50]/3ff[NV84+] */ + xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ + xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_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 */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ + xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ + xf_emit(ctx, 1, 0); /* 7 */ + xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ + xf_emit(ctx, 1, 0); /* ffffffff COLOR_KEY */ + xf_emit(ctx, 1, 0); /* 00000001 COLOR_KEY_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000007 COLOR_KEY_FORMAT */ + xf_emit(ctx, 2, 0); /* ffffffff SIFC_BITMAP_COLOR */ + 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)) { + 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) { + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */ + xf_emit(ctx, 1, 0); /* 00000003 */ + } else { + xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ + } + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ + xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ + xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ + 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)) { + 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 */ + xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ + xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_RGB */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_RGB */ + xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_ALPHA */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_ALPHA */ + xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ + } + xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ + xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ + xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ + xf_emit(ctx, 1, 0); /* 7 */ + xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ + xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ + 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)) + 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 */ + xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ + xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ + xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ + 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 */ + xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 8, 1); /* 00000001 UNK19E0 */ + xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + 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)) + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ + if (dev_priv->chipset == 0x50) + xf_emit(ctx, 1, 0); /* ff */ + else + xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ + xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ + xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000007 */ + xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ + xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ + xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ + xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ + xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ + xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ + xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 1, magic1); /* 3ff/7ff tesla UNK0D68 */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + 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)) + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ + xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_LOCAL */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_STACK */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_DST */ + xf_emit(ctx, 1, 0); /* 7 */ + xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 8, 0); /* 000000ff RT_ADDRESS_HIGH */ + xf_emit(ctx, 8, 0); /* ffffffff RT_LAYER_STRIDE */ + xf_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ + xf_emit(ctx, 8, 8); /* 0000007f RT_TILE_MODE */ + xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 8, 0x400); /* 0fffffff RT_HORIZ */ + xf_emit(ctx, 8, 0x300); /* 0000ffff RT_VERT */ + xf_emit(ctx, 1, 1); /* 00001fff RT_ARRAY_MODE */ + xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 1, 0x20); /* 00000fff DST_TILE_MODE */ + xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ + xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ + xf_emit(ctx, 1, 0); /* 000007ff DST_LAYER */ + xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ + xf_emit(ctx, 1, 0); /* ffffffff DST_ADDRESS_LOW */ + xf_emit(ctx, 1, 0); /* 000000ff DST_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0x40); /* 0007ffff DST_PITCH */ + xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ + xf_emit(ctx, 1, 0); /* 0000ffff */ + xf_emit(ctx, 1, 3); /* 00000003 tesla UNK15AC */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + 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)) + 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 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_ZETA */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ + xf_emit(ctx, 2, 0); /* ffff, ff/3ff */ + xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ + xf_emit(ctx, 1, 0); /* 00000007 */ + xf_emit(ctx, 1, 0); /* ffffffff ZETA_LAYER_STRIDE */ + xf_emit(ctx, 1, 0); /* 000000ff ZETA_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff ZETA_ADDRESS_LOW */ + xf_emit(ctx, 1, 4); /* 00000007 ZETA_TILE_MODE */ + xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ + xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ + xf_emit(ctx, 1, 0x400); /* 0fffffff ZETA_HORIZ */ + xf_emit(ctx, 1, 0x300); /* 0000ffff ZETA_VERT */ + 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)) + xf_emit(ctx, 1, 0); /* 00000001 */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ + xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ + xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ + 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)) { + 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) + xf_emit(ctx, 1, 0x0fac6881); /* fffffff */ + xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ + xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ + xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ + xf_emit(ctx, 1, 0); /* 00000007 */ + 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)) { + 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) { + xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */ + xf_emit(ctx, 1, 0xfac6881); /* fffffff */ + xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */ + xf_emit(ctx, 1, 4); /* 7 */ + xf_emit(ctx, 1, 0); /* 1 */ + xf_emit(ctx, 2, 1); /* 1 */ + 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)) + xf_emit(ctx, 0x9, 0); /* 1 */ + else + xf_emit(ctx, 0x8, 0); /* 1 */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 8, 1); /* 1 */ + xf_emit(ctx, 1, 0x11); /* 7f */ + xf_emit(ctx, 7, 0); /* 7f */ + xf_emit(ctx, 1, 0xfac6881); /* fffffff */ + xf_emit(ctx, 1, 0xf); /* f */ + xf_emit(ctx, 7, 0); /* f */ + 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)) { + xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ + } + } +} + +static void +nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */ + if (dev_priv->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) + xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */ + else + xf_emit(ctx, 2, 0); /* 3ff, 1 */ + xf_emit(ctx, 1, 0x2a712488); /* ffffffff SRC_TIC_0 */ + xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_1 */ + xf_emit(ctx, 1, 0x4085c000); /* ffffffff SRC_TIC_2 */ + xf_emit(ctx, 1, 0x40); /* ffffffff SRC_TIC_3 */ + xf_emit(ctx, 1, 0x100); /* ffffffff SRC_TIC_4 */ + 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) { + 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)) { + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ + xf_emit(ctx, 1, 0); /* 00000003 */ + xf_emit(ctx, 1, 0); /* 000003ff */ + xf_emit(ctx, 1, 0); /* 00000003 */ + xf_emit(ctx, 1, 0); /* 000003ff */ + xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1664 / turing UNK03E8 */ + xf_emit(ctx, 1, 0); /* 00000003 */ + xf_emit(ctx, 1, 0); /* 000003ff */ + } else { + xf_emit(ctx, 0x6, 0); + } + xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_TEXTURE */ + xf_emit(ctx, 1, 0); /* 0000ffff DMA_SRC */ +} + +static void +nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ + xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ + xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ + xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ + xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ + 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)) + 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 */ + xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ + xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ + xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ + xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ + xf_emit(ctx, 1, 0); /* ffff0ff3 */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ + xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ + xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ + xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ + xf_emit(ctx, 1, 0x30201000); /* ffffffff tesla UNK1670 */ + xf_emit(ctx, 1, 0x70605040); /* ffffffff tesla UNK1670 */ + xf_emit(ctx, 1, 0xb8a89888); /* ffffffff tesla UNK1670 */ + xf_emit(ctx, 1, 0xf8e8d8c8); /* ffffffff tesla UNK1670 */ + xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ + xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ +} + +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) { + nv50_graph_construct_xfer_unk84xx(ctx); + nv50_graph_construct_xfer_tprop(ctx); + nv50_graph_construct_xfer_tex(ctx); + nv50_graph_construct_xfer_unk8cxx(ctx); + } else { + nv50_graph_construct_xfer_tex(ctx); + nv50_graph_construct_xfer_tprop(ctx); + nv50_graph_construct_xfer_unk8cxx(ctx); + nv50_graph_construct_xfer_unk84xx(ctx); + } +} + +static void +nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i, mpcnt = 2; + switch (dev_priv->chipset) { + case 0x98: + case 0xaa: + mpcnt = 1; + break; + case 0x50: + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0xa8: + case 0xac: + mpcnt = 2; + break; + case 0xa0: + case 0xa3: + case 0xa5: + case 0xaf: + mpcnt = 3; + break; + } + for (i = 0; i < mpcnt; i++) { + xf_emit(ctx, 1, 0); /* ff */ + 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) + 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)) { + 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) + 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)) + xf_emit(ctx, 0xb, 0); /* RO */ + else if (dev_priv->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) { + xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */ + } + xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */ + xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ + xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ + xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ + xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ + xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ + xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ + xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ + 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)) + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ + xf_emit(ctx, 1, 0); /* ff/3ff */ + xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */ + xf_emit(ctx, 1, 0); /* ff FP_ADDRESS_HIGH */ + xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ + xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ + xf_emit(ctx, 1, 0); /* 000000ff FRAG_COLOR_CLAMP_EN */ + xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ + xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ + xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ + 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)) + 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 */ + xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ + xf_emit(ctx, 1, 4); /* ffffffff tesla UNK1400 */ + xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ + xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ + xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ + 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_ALPHA */ + 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)) { + 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 */ + xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ + xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ + xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ + xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ + xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ + xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ + xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ + } + 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) + xf_emit(ctx, 0x3a0, 0); + else if (dev_priv->chipset < 0x94) + xf_emit(ctx, 0x3a2, 0); + else if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa) + xf_emit(ctx, 0x39f, 0); + else + xf_emit(ctx, 0x3a3, 0); + xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ + xf_emit(ctx, 1, 0); /* 7 OPERATION */ + xf_emit(ctx, 1, 1); /* 1 DST_LINEAR */ + xf_emit(ctx, 0x2d, 0); +} + +static void +nv50_graph_construct_xfer2(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + uint32_t offset; + uint32_t units = nv_rd32 (ctx->dev, 0x1540); + int size = 0; + + offset = (ctx->ctxvals_pos+0x3f)&~0x3f; + + if (dev_priv->chipset < 0xa0) { + for (i = 0; i < 8; i++) { + ctx->ctxvals_pos = offset + i; + /* that little bugger belongs to csched. No idea + * what it's doing here. */ + if (i == 0) + xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ + if (units & (1 << i)) + nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + } + } else { + /* Strand 0: TPs 0, 1 */ + ctx->ctxvals_pos = offset; + /* that little bugger belongs to csched. No idea + * what it's doing here. */ + xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ + if (units & (1 << 0)) + nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 1)) + nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 1: TPs 2, 3 */ + ctx->ctxvals_pos = offset + 1; + if (units & (1 << 2)) + nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 3)) + nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 2: TPs 4, 5, 6 */ + ctx->ctxvals_pos = offset + 2; + if (units & (1 << 4)) + nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 5)) + nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 6)) + nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 3: TPs 7, 8, 9 */ + ctx->ctxvals_pos = offset + 3; + if (units & (1 << 7)) + nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 8)) + nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 9)) + nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + } + ctx->ctxvals_pos = offset + size * 8; + ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f; + cp_lsr (ctx, offset); + cp_out (ctx, CP_SET_XFER_POINTER); + cp_lsr (ctx, size); + cp_out (ctx, CP_SEEK_2); + cp_out (ctx, CP_XFER_2); + cp_wait(ctx, XFER, BUSY); +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c new file mode 100644 index 0000000..5083fda --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -0,0 +1,2878 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include +#include "nvc0.h" + +static void +nv_icmd(struct drm_device *dev, u32 icmd, u32 data) +{ + nv_wr32(dev, 0x400204, data); + nv_wr32(dev, 0x400200, icmd); + while (nv_rd32(dev, 0x400700) & 2) {} +} + +static void +nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data) +{ + nv_wr32(dev, 0x40448c, data); + nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class); +} + +static void +nvc0_grctx_generate_9097(struct drm_device *dev) +{ + u32 fermi = nvc0_graph_class(dev); + u32 mthd; + + nv_mthd(dev, 0x9097, 0x0800, 0x00000000); + nv_mthd(dev, 0x9097, 0x0840, 0x00000000); + nv_mthd(dev, 0x9097, 0x0880, 0x00000000); + nv_mthd(dev, 0x9097, 0x08c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0900, 0x00000000); + nv_mthd(dev, 0x9097, 0x0940, 0x00000000); + nv_mthd(dev, 0x9097, 0x0980, 0x00000000); + nv_mthd(dev, 0x9097, 0x09c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0804, 0x00000000); + nv_mthd(dev, 0x9097, 0x0844, 0x00000000); + nv_mthd(dev, 0x9097, 0x0884, 0x00000000); + nv_mthd(dev, 0x9097, 0x08c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0904, 0x00000000); + nv_mthd(dev, 0x9097, 0x0944, 0x00000000); + nv_mthd(dev, 0x9097, 0x0984, 0x00000000); + nv_mthd(dev, 0x9097, 0x09c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0808, 0x00000400); + nv_mthd(dev, 0x9097, 0x0848, 0x00000400); + nv_mthd(dev, 0x9097, 0x0888, 0x00000400); + nv_mthd(dev, 0x9097, 0x08c8, 0x00000400); + nv_mthd(dev, 0x9097, 0x0908, 0x00000400); + nv_mthd(dev, 0x9097, 0x0948, 0x00000400); + nv_mthd(dev, 0x9097, 0x0988, 0x00000400); + nv_mthd(dev, 0x9097, 0x09c8, 0x00000400); + nv_mthd(dev, 0x9097, 0x080c, 0x00000300); + nv_mthd(dev, 0x9097, 0x084c, 0x00000300); + nv_mthd(dev, 0x9097, 0x088c, 0x00000300); + nv_mthd(dev, 0x9097, 0x08cc, 0x00000300); + nv_mthd(dev, 0x9097, 0x090c, 0x00000300); + nv_mthd(dev, 0x9097, 0x094c, 0x00000300); + nv_mthd(dev, 0x9097, 0x098c, 0x00000300); + nv_mthd(dev, 0x9097, 0x09cc, 0x00000300); + nv_mthd(dev, 0x9097, 0x0810, 0x000000cf); + nv_mthd(dev, 0x9097, 0x0850, 0x00000000); + nv_mthd(dev, 0x9097, 0x0890, 0x00000000); + nv_mthd(dev, 0x9097, 0x08d0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0910, 0x00000000); + nv_mthd(dev, 0x9097, 0x0950, 0x00000000); + nv_mthd(dev, 0x9097, 0x0990, 0x00000000); + nv_mthd(dev, 0x9097, 0x09d0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0814, 0x00000040); + nv_mthd(dev, 0x9097, 0x0854, 0x00000040); + nv_mthd(dev, 0x9097, 0x0894, 0x00000040); + nv_mthd(dev, 0x9097, 0x08d4, 0x00000040); + nv_mthd(dev, 0x9097, 0x0914, 0x00000040); + nv_mthd(dev, 0x9097, 0x0954, 0x00000040); + nv_mthd(dev, 0x9097, 0x0994, 0x00000040); + nv_mthd(dev, 0x9097, 0x09d4, 0x00000040); + nv_mthd(dev, 0x9097, 0x0818, 0x00000001); + nv_mthd(dev, 0x9097, 0x0858, 0x00000001); + nv_mthd(dev, 0x9097, 0x0898, 0x00000001); + nv_mthd(dev, 0x9097, 0x08d8, 0x00000001); + nv_mthd(dev, 0x9097, 0x0918, 0x00000001); + nv_mthd(dev, 0x9097, 0x0958, 0x00000001); + nv_mthd(dev, 0x9097, 0x0998, 0x00000001); + nv_mthd(dev, 0x9097, 0x09d8, 0x00000001); + nv_mthd(dev, 0x9097, 0x081c, 0x00000000); + nv_mthd(dev, 0x9097, 0x085c, 0x00000000); + nv_mthd(dev, 0x9097, 0x089c, 0x00000000); + nv_mthd(dev, 0x9097, 0x08dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x091c, 0x00000000); + nv_mthd(dev, 0x9097, 0x095c, 0x00000000); + nv_mthd(dev, 0x9097, 0x099c, 0x00000000); + nv_mthd(dev, 0x9097, 0x09dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0820, 0x00000000); + nv_mthd(dev, 0x9097, 0x0860, 0x00000000); + nv_mthd(dev, 0x9097, 0x08a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x08e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0920, 0x00000000); + nv_mthd(dev, 0x9097, 0x0960, 0x00000000); + nv_mthd(dev, 0x9097, 0x09a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x09e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x2700, 0x00000000); + nv_mthd(dev, 0x9097, 0x2720, 0x00000000); + nv_mthd(dev, 0x9097, 0x2740, 0x00000000); + nv_mthd(dev, 0x9097, 0x2760, 0x00000000); + nv_mthd(dev, 0x9097, 0x2780, 0x00000000); + nv_mthd(dev, 0x9097, 0x27a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x27c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x27e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x2704, 0x00000000); + nv_mthd(dev, 0x9097, 0x2724, 0x00000000); + nv_mthd(dev, 0x9097, 0x2744, 0x00000000); + nv_mthd(dev, 0x9097, 0x2764, 0x00000000); + nv_mthd(dev, 0x9097, 0x2784, 0x00000000); + nv_mthd(dev, 0x9097, 0x27a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x27c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x27e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x2708, 0x00000000); + nv_mthd(dev, 0x9097, 0x2728, 0x00000000); + nv_mthd(dev, 0x9097, 0x2748, 0x00000000); + nv_mthd(dev, 0x9097, 0x2768, 0x00000000); + nv_mthd(dev, 0x9097, 0x2788, 0x00000000); + nv_mthd(dev, 0x9097, 0x27a8, 0x00000000); + nv_mthd(dev, 0x9097, 0x27c8, 0x00000000); + nv_mthd(dev, 0x9097, 0x27e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x270c, 0x00000000); + nv_mthd(dev, 0x9097, 0x272c, 0x00000000); + nv_mthd(dev, 0x9097, 0x274c, 0x00000000); + nv_mthd(dev, 0x9097, 0x276c, 0x00000000); + nv_mthd(dev, 0x9097, 0x278c, 0x00000000); + nv_mthd(dev, 0x9097, 0x27ac, 0x00000000); + nv_mthd(dev, 0x9097, 0x27cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x27ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x2710, 0x00014000); + nv_mthd(dev, 0x9097, 0x2730, 0x00014000); + nv_mthd(dev, 0x9097, 0x2750, 0x00014000); + nv_mthd(dev, 0x9097, 0x2770, 0x00014000); + nv_mthd(dev, 0x9097, 0x2790, 0x00014000); + nv_mthd(dev, 0x9097, 0x27b0, 0x00014000); + nv_mthd(dev, 0x9097, 0x27d0, 0x00014000); + nv_mthd(dev, 0x9097, 0x27f0, 0x00014000); + nv_mthd(dev, 0x9097, 0x2714, 0x00000040); + nv_mthd(dev, 0x9097, 0x2734, 0x00000040); + nv_mthd(dev, 0x9097, 0x2754, 0x00000040); + nv_mthd(dev, 0x9097, 0x2774, 0x00000040); + nv_mthd(dev, 0x9097, 0x2794, 0x00000040); + nv_mthd(dev, 0x9097, 0x27b4, 0x00000040); + nv_mthd(dev, 0x9097, 0x27d4, 0x00000040); + nv_mthd(dev, 0x9097, 0x27f4, 0x00000040); + nv_mthd(dev, 0x9097, 0x1c00, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c10, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c20, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c30, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c40, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c50, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c60, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c70, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c80, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c90, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ca0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cb0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cc0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cd0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ce0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cf0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c04, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c14, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c24, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c34, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c44, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c54, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c64, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c74, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c84, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c94, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ca4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cb4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cc4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cd4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ce4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cf4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c08, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c18, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c28, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c38, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c48, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c58, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c68, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c78, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c88, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c98, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ca8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cb8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cc8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cd8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ce8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cf8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c0c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c1c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c2c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c3c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c4c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c5c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c6c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c7c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1c9c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cac, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cbc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ccc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cdc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cec, 0x00000000); + nv_mthd(dev, 0x9097, 0x1cfc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d00, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d10, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d20, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d30, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d40, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d50, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d60, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d70, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d80, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d90, 0x00000000); + nv_mthd(dev, 0x9097, 0x1da0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1db0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dc0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dd0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1de0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1df0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d04, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d14, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d24, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d34, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d44, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d54, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d64, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d74, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d84, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d94, 0x00000000); + nv_mthd(dev, 0x9097, 0x1da4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1db4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dc4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dd4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1de4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1df4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d08, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d18, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d28, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d38, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d48, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d58, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d68, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d78, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d88, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d98, 0x00000000); + nv_mthd(dev, 0x9097, 0x1da8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1db8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dc8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dd8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1de8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1df8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d0c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d1c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d2c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d3c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d4c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d5c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d6c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d7c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1d9c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dac, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dbc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dcc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ddc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dec, 0x00000000); + nv_mthd(dev, 0x9097, 0x1dfc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f00, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f08, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f10, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f18, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f20, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f28, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f30, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f38, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f40, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f48, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f50, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f58, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f60, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f68, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f70, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f78, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f04, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f0c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f14, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f1c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f24, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f2c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f34, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f3c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f44, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f4c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f54, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f5c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f64, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f6c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f74, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f7c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f80, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f88, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f90, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f98, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fa0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fa8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fb0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fb8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fc0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fc8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fd0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fd8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fe0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fe8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ff0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ff8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f84, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f94, 0x00000000); + nv_mthd(dev, 0x9097, 0x1f9c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fa4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fac, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fb4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fbc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fc4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fcc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fd4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fdc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fe4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1fec, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ff4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1ffc, 0x00000000); + nv_mthd(dev, 0x9097, 0x2200, 0x00000022); + nv_mthd(dev, 0x9097, 0x2210, 0x00000022); + nv_mthd(dev, 0x9097, 0x2220, 0x00000022); + nv_mthd(dev, 0x9097, 0x2230, 0x00000022); + nv_mthd(dev, 0x9097, 0x2240, 0x00000022); + nv_mthd(dev, 0x9097, 0x2000, 0x00000000); + nv_mthd(dev, 0x9097, 0x2040, 0x00000011); + nv_mthd(dev, 0x9097, 0x2080, 0x00000020); + nv_mthd(dev, 0x9097, 0x20c0, 0x00000030); + nv_mthd(dev, 0x9097, 0x2100, 0x00000040); + nv_mthd(dev, 0x9097, 0x2140, 0x00000051); + nv_mthd(dev, 0x9097, 0x200c, 0x00000001); + nv_mthd(dev, 0x9097, 0x204c, 0x00000001); + nv_mthd(dev, 0x9097, 0x208c, 0x00000001); + nv_mthd(dev, 0x9097, 0x20cc, 0x00000001); + nv_mthd(dev, 0x9097, 0x210c, 0x00000001); + nv_mthd(dev, 0x9097, 0x214c, 0x00000001); + nv_mthd(dev, 0x9097, 0x2010, 0x00000000); + nv_mthd(dev, 0x9097, 0x2050, 0x00000000); + nv_mthd(dev, 0x9097, 0x2090, 0x00000001); + nv_mthd(dev, 0x9097, 0x20d0, 0x00000002); + nv_mthd(dev, 0x9097, 0x2110, 0x00000003); + nv_mthd(dev, 0x9097, 0x2150, 0x00000004); + nv_mthd(dev, 0x9097, 0x0380, 0x00000000); + nv_mthd(dev, 0x9097, 0x03a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x03c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x03e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0384, 0x00000000); + nv_mthd(dev, 0x9097, 0x03a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x03c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x03e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0388, 0x00000000); + nv_mthd(dev, 0x9097, 0x03a8, 0x00000000); + nv_mthd(dev, 0x9097, 0x03c8, 0x00000000); + nv_mthd(dev, 0x9097, 0x03e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x038c, 0x00000000); + nv_mthd(dev, 0x9097, 0x03ac, 0x00000000); + nv_mthd(dev, 0x9097, 0x03cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x03ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x0700, 0x00000000); + nv_mthd(dev, 0x9097, 0x0710, 0x00000000); + nv_mthd(dev, 0x9097, 0x0720, 0x00000000); + nv_mthd(dev, 0x9097, 0x0730, 0x00000000); + nv_mthd(dev, 0x9097, 0x0704, 0x00000000); + nv_mthd(dev, 0x9097, 0x0714, 0x00000000); + nv_mthd(dev, 0x9097, 0x0724, 0x00000000); + nv_mthd(dev, 0x9097, 0x0734, 0x00000000); + nv_mthd(dev, 0x9097, 0x0708, 0x00000000); + nv_mthd(dev, 0x9097, 0x0718, 0x00000000); + nv_mthd(dev, 0x9097, 0x0728, 0x00000000); + nv_mthd(dev, 0x9097, 0x0738, 0x00000000); + nv_mthd(dev, 0x9097, 0x2800, 0x00000000); + nv_mthd(dev, 0x9097, 0x2804, 0x00000000); + nv_mthd(dev, 0x9097, 0x2808, 0x00000000); + nv_mthd(dev, 0x9097, 0x280c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2810, 0x00000000); + nv_mthd(dev, 0x9097, 0x2814, 0x00000000); + nv_mthd(dev, 0x9097, 0x2818, 0x00000000); + nv_mthd(dev, 0x9097, 0x281c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2820, 0x00000000); + nv_mthd(dev, 0x9097, 0x2824, 0x00000000); + nv_mthd(dev, 0x9097, 0x2828, 0x00000000); + nv_mthd(dev, 0x9097, 0x282c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2830, 0x00000000); + nv_mthd(dev, 0x9097, 0x2834, 0x00000000); + nv_mthd(dev, 0x9097, 0x2838, 0x00000000); + nv_mthd(dev, 0x9097, 0x283c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2840, 0x00000000); + nv_mthd(dev, 0x9097, 0x2844, 0x00000000); + nv_mthd(dev, 0x9097, 0x2848, 0x00000000); + nv_mthd(dev, 0x9097, 0x284c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2850, 0x00000000); + nv_mthd(dev, 0x9097, 0x2854, 0x00000000); + nv_mthd(dev, 0x9097, 0x2858, 0x00000000); + nv_mthd(dev, 0x9097, 0x285c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2860, 0x00000000); + nv_mthd(dev, 0x9097, 0x2864, 0x00000000); + nv_mthd(dev, 0x9097, 0x2868, 0x00000000); + nv_mthd(dev, 0x9097, 0x286c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2870, 0x00000000); + nv_mthd(dev, 0x9097, 0x2874, 0x00000000); + nv_mthd(dev, 0x9097, 0x2878, 0x00000000); + nv_mthd(dev, 0x9097, 0x287c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2880, 0x00000000); + nv_mthd(dev, 0x9097, 0x2884, 0x00000000); + nv_mthd(dev, 0x9097, 0x2888, 0x00000000); + nv_mthd(dev, 0x9097, 0x288c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2890, 0x00000000); + nv_mthd(dev, 0x9097, 0x2894, 0x00000000); + nv_mthd(dev, 0x9097, 0x2898, 0x00000000); + nv_mthd(dev, 0x9097, 0x289c, 0x00000000); + nv_mthd(dev, 0x9097, 0x28a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x28a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x28a8, 0x00000000); + nv_mthd(dev, 0x9097, 0x28ac, 0x00000000); + nv_mthd(dev, 0x9097, 0x28b0, 0x00000000); + nv_mthd(dev, 0x9097, 0x28b4, 0x00000000); + nv_mthd(dev, 0x9097, 0x28b8, 0x00000000); + nv_mthd(dev, 0x9097, 0x28bc, 0x00000000); + nv_mthd(dev, 0x9097, 0x28c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x28c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x28c8, 0x00000000); + nv_mthd(dev, 0x9097, 0x28cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x28d0, 0x00000000); + nv_mthd(dev, 0x9097, 0x28d4, 0x00000000); + nv_mthd(dev, 0x9097, 0x28d8, 0x00000000); + nv_mthd(dev, 0x9097, 0x28dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x28e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x28e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x28e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x28ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x28f0, 0x00000000); + nv_mthd(dev, 0x9097, 0x28f4, 0x00000000); + nv_mthd(dev, 0x9097, 0x28f8, 0x00000000); + nv_mthd(dev, 0x9097, 0x28fc, 0x00000000); + nv_mthd(dev, 0x9097, 0x2900, 0x00000000); + nv_mthd(dev, 0x9097, 0x2904, 0x00000000); + nv_mthd(dev, 0x9097, 0x2908, 0x00000000); + nv_mthd(dev, 0x9097, 0x290c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2910, 0x00000000); + nv_mthd(dev, 0x9097, 0x2914, 0x00000000); + nv_mthd(dev, 0x9097, 0x2918, 0x00000000); + nv_mthd(dev, 0x9097, 0x291c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2920, 0x00000000); + nv_mthd(dev, 0x9097, 0x2924, 0x00000000); + nv_mthd(dev, 0x9097, 0x2928, 0x00000000); + nv_mthd(dev, 0x9097, 0x292c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2930, 0x00000000); + nv_mthd(dev, 0x9097, 0x2934, 0x00000000); + nv_mthd(dev, 0x9097, 0x2938, 0x00000000); + nv_mthd(dev, 0x9097, 0x293c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2940, 0x00000000); + nv_mthd(dev, 0x9097, 0x2944, 0x00000000); + nv_mthd(dev, 0x9097, 0x2948, 0x00000000); + nv_mthd(dev, 0x9097, 0x294c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2950, 0x00000000); + nv_mthd(dev, 0x9097, 0x2954, 0x00000000); + nv_mthd(dev, 0x9097, 0x2958, 0x00000000); + nv_mthd(dev, 0x9097, 0x295c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2960, 0x00000000); + nv_mthd(dev, 0x9097, 0x2964, 0x00000000); + nv_mthd(dev, 0x9097, 0x2968, 0x00000000); + nv_mthd(dev, 0x9097, 0x296c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2970, 0x00000000); + nv_mthd(dev, 0x9097, 0x2974, 0x00000000); + nv_mthd(dev, 0x9097, 0x2978, 0x00000000); + nv_mthd(dev, 0x9097, 0x297c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2980, 0x00000000); + nv_mthd(dev, 0x9097, 0x2984, 0x00000000); + nv_mthd(dev, 0x9097, 0x2988, 0x00000000); + nv_mthd(dev, 0x9097, 0x298c, 0x00000000); + nv_mthd(dev, 0x9097, 0x2990, 0x00000000); + nv_mthd(dev, 0x9097, 0x2994, 0x00000000); + nv_mthd(dev, 0x9097, 0x2998, 0x00000000); + nv_mthd(dev, 0x9097, 0x299c, 0x00000000); + nv_mthd(dev, 0x9097, 0x29a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x29a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x29a8, 0x00000000); + nv_mthd(dev, 0x9097, 0x29ac, 0x00000000); + nv_mthd(dev, 0x9097, 0x29b0, 0x00000000); + nv_mthd(dev, 0x9097, 0x29b4, 0x00000000); + nv_mthd(dev, 0x9097, 0x29b8, 0x00000000); + nv_mthd(dev, 0x9097, 0x29bc, 0x00000000); + nv_mthd(dev, 0x9097, 0x29c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x29c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x29c8, 0x00000000); + nv_mthd(dev, 0x9097, 0x29cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x29d0, 0x00000000); + nv_mthd(dev, 0x9097, 0x29d4, 0x00000000); + nv_mthd(dev, 0x9097, 0x29d8, 0x00000000); + nv_mthd(dev, 0x9097, 0x29dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x29e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x29e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x29e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x29ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x29f0, 0x00000000); + nv_mthd(dev, 0x9097, 0x29f4, 0x00000000); + nv_mthd(dev, 0x9097, 0x29f8, 0x00000000); + nv_mthd(dev, 0x9097, 0x29fc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a00, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a20, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a40, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a60, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a80, 0x00000000); + nv_mthd(dev, 0x9097, 0x0aa0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ac0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ae0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b00, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b20, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b40, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b60, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b80, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ba0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bc0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0be0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a04, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a24, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a44, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a64, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a84, 0x00000000); + nv_mthd(dev, 0x9097, 0x0aa4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ac4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ae4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b04, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b24, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b44, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b64, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b84, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ba4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bc4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0be4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a08, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a28, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a48, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a68, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a88, 0x00000000); + nv_mthd(dev, 0x9097, 0x0aa8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ac8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ae8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b08, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b28, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b48, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b68, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b88, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ba8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bc8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0be8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a0c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a2c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a4c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a6c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0aac, 0x00000000); + nv_mthd(dev, 0x9097, 0x0acc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0aec, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b0c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b2c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b4c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b6c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bac, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bcc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bec, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a10, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a30, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a50, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a70, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a90, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ab0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ad0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0af0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b10, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b30, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b50, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b70, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b90, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bb0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bd0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bf0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a14, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a34, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a54, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a74, 0x00000000); + nv_mthd(dev, 0x9097, 0x0a94, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ab4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ad4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0af4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b14, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b34, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b54, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b74, 0x00000000); + nv_mthd(dev, 0x9097, 0x0b94, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bb4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bd4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0bf4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c00, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c10, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c20, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c30, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c40, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c50, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c60, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c70, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c80, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c90, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ca0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cb0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cc0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cd0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ce0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cf0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c04, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c14, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c24, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c34, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c44, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c54, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c64, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c74, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c84, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c94, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ca4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cb4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cc4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cd4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ce4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cf4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c08, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c18, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c28, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c38, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c48, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c58, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c68, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c78, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c88, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c98, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ca8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cb8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cc8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cd8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ce8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0cf8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0c0c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c1c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c2c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c3c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c4c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c5c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c6c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c7c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c8c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0c9c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0cac, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0cbc, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0ccc, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0cdc, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0cec, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0cfc, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0d00, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d08, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d10, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d18, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d20, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d28, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d30, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d38, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d04, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d0c, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d14, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d1c, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d24, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d2c, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d34, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d3c, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e00, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e10, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e20, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e30, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e40, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e50, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e60, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e70, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e80, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e90, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ea0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0eb0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ec0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ed0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ee0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ef0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0e04, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e14, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e24, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e34, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e44, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e54, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e64, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e74, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e84, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e94, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ea4, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0eb4, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ec4, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ed4, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ee4, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ef4, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e08, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e18, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e28, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e38, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e48, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e58, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e68, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e78, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e88, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0e98, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ea8, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0eb8, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ec8, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ed8, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ee8, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0ef8, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d40, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d48, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d50, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d58, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d44, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d4c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d54, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d5c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1e00, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e20, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e40, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e60, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e80, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ea0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ec0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ee0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e04, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e24, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e44, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e64, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e84, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ea4, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ec4, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ee4, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e08, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e28, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e48, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e68, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e88, 0x00000002); + nv_mthd(dev, 0x9097, 0x1ea8, 0x00000002); + nv_mthd(dev, 0x9097, 0x1ec8, 0x00000002); + nv_mthd(dev, 0x9097, 0x1ee8, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e0c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e2c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e4c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e6c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e8c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1eac, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ecc, 0x00000001); + nv_mthd(dev, 0x9097, 0x1eec, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e10, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e30, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e50, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e70, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e90, 0x00000001); + nv_mthd(dev, 0x9097, 0x1eb0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ed0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ef0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e14, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e34, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e54, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e74, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e94, 0x00000002); + nv_mthd(dev, 0x9097, 0x1eb4, 0x00000002); + nv_mthd(dev, 0x9097, 0x1ed4, 0x00000002); + nv_mthd(dev, 0x9097, 0x1ef4, 0x00000002); + nv_mthd(dev, 0x9097, 0x1e18, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e38, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e58, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e78, 0x00000001); + nv_mthd(dev, 0x9097, 0x1e98, 0x00000001); + nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001); + if (fermi == 0x9097) { + for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) + nv_mthd(dev, 0x9097, mthd, 0x00000000); + } + nv_mthd(dev, 0x9097, 0x030c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1944, 0x00000000); + nv_mthd(dev, 0x9097, 0x1514, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d68, 0x0000ffff); + nv_mthd(dev, 0x9097, 0x121c, 0x0fac6881); + nv_mthd(dev, 0x9097, 0x0fac, 0x00000001); + nv_mthd(dev, 0x9097, 0x1538, 0x00000001); + nv_mthd(dev, 0x9097, 0x0fe0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0fe4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0fe8, 0x00000014); + nv_mthd(dev, 0x9097, 0x0fec, 0x00000040); + nv_mthd(dev, 0x9097, 0x0ff0, 0x00000000); + nv_mthd(dev, 0x9097, 0x179c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1228, 0x00000400); + nv_mthd(dev, 0x9097, 0x122c, 0x00000300); + nv_mthd(dev, 0x9097, 0x1230, 0x00010001); + nv_mthd(dev, 0x9097, 0x07f8, 0x00000000); + nv_mthd(dev, 0x9097, 0x15b4, 0x00000001); + nv_mthd(dev, 0x9097, 0x15cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1534, 0x00000000); + nv_mthd(dev, 0x9097, 0x0fb0, 0x00000000); + nv_mthd(dev, 0x9097, 0x15d0, 0x00000000); + nv_mthd(dev, 0x9097, 0x153c, 0x00000000); + nv_mthd(dev, 0x9097, 0x16b4, 0x00000003); + nv_mthd(dev, 0x9097, 0x0fbc, 0x0000ffff); + nv_mthd(dev, 0x9097, 0x0fc0, 0x0000ffff); + nv_mthd(dev, 0x9097, 0x0fc4, 0x0000ffff); + nv_mthd(dev, 0x9097, 0x0fc8, 0x0000ffff); + nv_mthd(dev, 0x9097, 0x0df8, 0x00000000); + nv_mthd(dev, 0x9097, 0x0dfc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1948, 0x00000000); + nv_mthd(dev, 0x9097, 0x1970, 0x00000001); + nv_mthd(dev, 0x9097, 0x161c, 0x000009f0); + nv_mthd(dev, 0x9097, 0x0dcc, 0x00000010); + nv_mthd(dev, 0x9097, 0x163c, 0x00000000); + nv_mthd(dev, 0x9097, 0x15e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1160, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1164, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1168, 0x25e00040); + nv_mthd(dev, 0x9097, 0x116c, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1170, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1174, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1178, 0x25e00040); + nv_mthd(dev, 0x9097, 0x117c, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1180, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1184, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1188, 0x25e00040); + nv_mthd(dev, 0x9097, 0x118c, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1190, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1194, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1198, 0x25e00040); + nv_mthd(dev, 0x9097, 0x119c, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11a0, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11a4, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11a8, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11ac, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11b0, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11b4, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11b8, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11bc, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11c0, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11c4, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11c8, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11cc, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11d0, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11d4, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11d8, 0x25e00040); + nv_mthd(dev, 0x9097, 0x11dc, 0x25e00040); + nv_mthd(dev, 0x9097, 0x1880, 0x00000000); + nv_mthd(dev, 0x9097, 0x1884, 0x00000000); + nv_mthd(dev, 0x9097, 0x1888, 0x00000000); + nv_mthd(dev, 0x9097, 0x188c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1890, 0x00000000); + nv_mthd(dev, 0x9097, 0x1894, 0x00000000); + nv_mthd(dev, 0x9097, 0x1898, 0x00000000); + nv_mthd(dev, 0x9097, 0x189c, 0x00000000); + nv_mthd(dev, 0x9097, 0x18a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x18a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x18a8, 0x00000000); + nv_mthd(dev, 0x9097, 0x18ac, 0x00000000); + nv_mthd(dev, 0x9097, 0x18b0, 0x00000000); + nv_mthd(dev, 0x9097, 0x18b4, 0x00000000); + nv_mthd(dev, 0x9097, 0x18b8, 0x00000000); + nv_mthd(dev, 0x9097, 0x18bc, 0x00000000); + nv_mthd(dev, 0x9097, 0x18c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x18c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x18c8, 0x00000000); + nv_mthd(dev, 0x9097, 0x18cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x18d0, 0x00000000); + nv_mthd(dev, 0x9097, 0x18d4, 0x00000000); + nv_mthd(dev, 0x9097, 0x18d8, 0x00000000); + nv_mthd(dev, 0x9097, 0x18dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x18e0, 0x00000000); + nv_mthd(dev, 0x9097, 0x18e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x18e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x18ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x18f0, 0x00000000); + nv_mthd(dev, 0x9097, 0x18f4, 0x00000000); + nv_mthd(dev, 0x9097, 0x18f8, 0x00000000); + nv_mthd(dev, 0x9097, 0x18fc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f84, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f88, 0x00000000); + nv_mthd(dev, 0x9097, 0x17c8, 0x00000000); + nv_mthd(dev, 0x9097, 0x17cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x17d0, 0x000000ff); + nv_mthd(dev, 0x9097, 0x17d4, 0xffffffff); + nv_mthd(dev, 0x9097, 0x17d8, 0x00000002); + nv_mthd(dev, 0x9097, 0x17dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x15f4, 0x00000000); + nv_mthd(dev, 0x9097, 0x15f8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1434, 0x00000000); + nv_mthd(dev, 0x9097, 0x1438, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d74, 0x00000000); + nv_mthd(dev, 0x9097, 0x0dec, 0x00000001); + nv_mthd(dev, 0x9097, 0x13a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1318, 0x00000001); + nv_mthd(dev, 0x9097, 0x1644, 0x00000000); + nv_mthd(dev, 0x9097, 0x0748, 0x00000000); + nv_mthd(dev, 0x9097, 0x0de8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1648, 0x00000000); + nv_mthd(dev, 0x9097, 0x12a4, 0x00000000); + nv_mthd(dev, 0x9097, 0x1120, 0x00000000); + nv_mthd(dev, 0x9097, 0x1124, 0x00000000); + nv_mthd(dev, 0x9097, 0x1128, 0x00000000); + nv_mthd(dev, 0x9097, 0x112c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1118, 0x00000000); + nv_mthd(dev, 0x9097, 0x164c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1658, 0x00000000); + nv_mthd(dev, 0x9097, 0x1910, 0x00000290); + nv_mthd(dev, 0x9097, 0x1518, 0x00000000); + nv_mthd(dev, 0x9097, 0x165c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1520, 0x00000000); + nv_mthd(dev, 0x9097, 0x1604, 0x00000000); + nv_mthd(dev, 0x9097, 0x1570, 0x00000000); + nv_mthd(dev, 0x9097, 0x13b0, 0x3f800000); + nv_mthd(dev, 0x9097, 0x13b4, 0x3f800000); + nv_mthd(dev, 0x9097, 0x020c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1670, 0x30201000); + nv_mthd(dev, 0x9097, 0x1674, 0x70605040); + nv_mthd(dev, 0x9097, 0x1678, 0xb8a89888); + nv_mthd(dev, 0x9097, 0x167c, 0xf8e8d8c8); + nv_mthd(dev, 0x9097, 0x166c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1680, 0x00ffff00); + nv_mthd(dev, 0x9097, 0x12d0, 0x00000003); + nv_mthd(dev, 0x9097, 0x12d4, 0x00000002); + nv_mthd(dev, 0x9097, 0x1684, 0x00000000); + nv_mthd(dev, 0x9097, 0x1688, 0x00000000); + nv_mthd(dev, 0x9097, 0x0dac, 0x00001b02); + nv_mthd(dev, 0x9097, 0x0db0, 0x00001b02); + nv_mthd(dev, 0x9097, 0x0db4, 0x00000000); + nv_mthd(dev, 0x9097, 0x168c, 0x00000000); + nv_mthd(dev, 0x9097, 0x15bc, 0x00000000); + nv_mthd(dev, 0x9097, 0x156c, 0x00000000); + nv_mthd(dev, 0x9097, 0x187c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1110, 0x00000001); + nv_mthd(dev, 0x9097, 0x0dc0, 0x00000000); + nv_mthd(dev, 0x9097, 0x0dc4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0dc8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1234, 0x00000000); + nv_mthd(dev, 0x9097, 0x1690, 0x00000000); + nv_mthd(dev, 0x9097, 0x12ac, 0x00000001); + nv_mthd(dev, 0x9097, 0x02c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0790, 0x00000000); + nv_mthd(dev, 0x9097, 0x0794, 0x00000000); + nv_mthd(dev, 0x9097, 0x0798, 0x00000000); + nv_mthd(dev, 0x9097, 0x079c, 0x00000000); + nv_mthd(dev, 0x9097, 0x07a0, 0x00000000); + nv_mthd(dev, 0x9097, 0x077c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1000, 0x00000010); + nv_mthd(dev, 0x9097, 0x10fc, 0x00000000); + nv_mthd(dev, 0x9097, 0x1290, 0x00000000); + nv_mthd(dev, 0x9097, 0x0218, 0x00000010); + nv_mthd(dev, 0x9097, 0x12d8, 0x00000000); + nv_mthd(dev, 0x9097, 0x12dc, 0x00000010); + nv_mthd(dev, 0x9097, 0x0d94, 0x00000001); + nv_mthd(dev, 0x9097, 0x155c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1560, 0x00000000); + nv_mthd(dev, 0x9097, 0x1564, 0x00001fff); + nv_mthd(dev, 0x9097, 0x1574, 0x00000000); + nv_mthd(dev, 0x9097, 0x1578, 0x00000000); + nv_mthd(dev, 0x9097, 0x157c, 0x003fffff); + nv_mthd(dev, 0x9097, 0x1354, 0x00000000); + nv_mthd(dev, 0x9097, 0x1664, 0x00000000); + nv_mthd(dev, 0x9097, 0x1610, 0x00000012); + nv_mthd(dev, 0x9097, 0x1608, 0x00000000); + nv_mthd(dev, 0x9097, 0x160c, 0x00000000); + nv_mthd(dev, 0x9097, 0x162c, 0x00000003); + nv_mthd(dev, 0x9097, 0x0210, 0x00000000); + nv_mthd(dev, 0x9097, 0x0320, 0x00000000); + nv_mthd(dev, 0x9097, 0x0324, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0328, 0x3f800000); + nv_mthd(dev, 0x9097, 0x032c, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0330, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0334, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0338, 0x3f800000); + nv_mthd(dev, 0x9097, 0x0750, 0x00000000); + nv_mthd(dev, 0x9097, 0x0760, 0x39291909); + nv_mthd(dev, 0x9097, 0x0764, 0x79695949); + nv_mthd(dev, 0x9097, 0x0768, 0xb9a99989); + nv_mthd(dev, 0x9097, 0x076c, 0xf9e9d9c9); + nv_mthd(dev, 0x9097, 0x0770, 0x30201000); + nv_mthd(dev, 0x9097, 0x0774, 0x70605040); + nv_mthd(dev, 0x9097, 0x0778, 0x00009080); + nv_mthd(dev, 0x9097, 0x0780, 0x39291909); + nv_mthd(dev, 0x9097, 0x0784, 0x79695949); + nv_mthd(dev, 0x9097, 0x0788, 0xb9a99989); + nv_mthd(dev, 0x9097, 0x078c, 0xf9e9d9c9); + nv_mthd(dev, 0x9097, 0x07d0, 0x30201000); + nv_mthd(dev, 0x9097, 0x07d4, 0x70605040); + nv_mthd(dev, 0x9097, 0x07d8, 0x00009080); + nv_mthd(dev, 0x9097, 0x037c, 0x00000001); + nv_mthd(dev, 0x9097, 0x0740, 0x00000000); + nv_mthd(dev, 0x9097, 0x0744, 0x00000000); + nv_mthd(dev, 0x9097, 0x2600, 0x00000000); + nv_mthd(dev, 0x9097, 0x1918, 0x00000000); + nv_mthd(dev, 0x9097, 0x191c, 0x00000900); + nv_mthd(dev, 0x9097, 0x1920, 0x00000405); + nv_mthd(dev, 0x9097, 0x1308, 0x00000001); + nv_mthd(dev, 0x9097, 0x1924, 0x00000000); + nv_mthd(dev, 0x9097, 0x13ac, 0x00000000); + nv_mthd(dev, 0x9097, 0x192c, 0x00000001); + nv_mthd(dev, 0x9097, 0x193c, 0x00002c1c); + nv_mthd(dev, 0x9097, 0x0d7c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x02c0, 0x00000001); + nv_mthd(dev, 0x9097, 0x1510, 0x00000000); + nv_mthd(dev, 0x9097, 0x1940, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ff4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0ff8, 0x00000000); + nv_mthd(dev, 0x9097, 0x194c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1950, 0x00000000); + nv_mthd(dev, 0x9097, 0x1968, 0x00000000); + nv_mthd(dev, 0x9097, 0x1590, 0x0000003f); + nv_mthd(dev, 0x9097, 0x07e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x07ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x07f0, 0x00000000); + nv_mthd(dev, 0x9097, 0x07f4, 0x00000000); + nv_mthd(dev, 0x9097, 0x196c, 0x00000011); + nv_mthd(dev, 0x9097, 0x197c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0fcc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0fd0, 0x00000000); + nv_mthd(dev, 0x9097, 0x02d8, 0x00000040); + nv_mthd(dev, 0x9097, 0x1980, 0x00000080); + nv_mthd(dev, 0x9097, 0x1504, 0x00000080); + nv_mthd(dev, 0x9097, 0x1984, 0x00000000); + nv_mthd(dev, 0x9097, 0x0300, 0x00000001); + nv_mthd(dev, 0x9097, 0x13a8, 0x00000000); + nv_mthd(dev, 0x9097, 0x12ec, 0x00000000); + nv_mthd(dev, 0x9097, 0x1310, 0x00000000); + nv_mthd(dev, 0x9097, 0x1314, 0x00000001); + nv_mthd(dev, 0x9097, 0x1380, 0x00000000); + nv_mthd(dev, 0x9097, 0x1384, 0x00000001); + nv_mthd(dev, 0x9097, 0x1388, 0x00000001); + nv_mthd(dev, 0x9097, 0x138c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1390, 0x00000001); + nv_mthd(dev, 0x9097, 0x1394, 0x00000000); + nv_mthd(dev, 0x9097, 0x139c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1398, 0x00000000); + nv_mthd(dev, 0x9097, 0x1594, 0x00000000); + nv_mthd(dev, 0x9097, 0x1598, 0x00000001); + nv_mthd(dev, 0x9097, 0x159c, 0x00000001); + nv_mthd(dev, 0x9097, 0x15a0, 0x00000001); + nv_mthd(dev, 0x9097, 0x15a4, 0x00000001); + nv_mthd(dev, 0x9097, 0x0f54, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f58, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f5c, 0x00000000); + nv_mthd(dev, 0x9097, 0x19bc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f9c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0fa0, 0x00000000); + nv_mthd(dev, 0x9097, 0x12cc, 0x00000000); + nv_mthd(dev, 0x9097, 0x12e8, 0x00000000); + nv_mthd(dev, 0x9097, 0x130c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1360, 0x00000000); + nv_mthd(dev, 0x9097, 0x1364, 0x00000000); + nv_mthd(dev, 0x9097, 0x1368, 0x00000000); + nv_mthd(dev, 0x9097, 0x136c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1370, 0x00000000); + nv_mthd(dev, 0x9097, 0x1374, 0x00000000); + nv_mthd(dev, 0x9097, 0x1378, 0x00000000); + nv_mthd(dev, 0x9097, 0x137c, 0x00000000); + nv_mthd(dev, 0x9097, 0x133c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1340, 0x00000001); + nv_mthd(dev, 0x9097, 0x1344, 0x00000002); + nv_mthd(dev, 0x9097, 0x1348, 0x00000001); + nv_mthd(dev, 0x9097, 0x134c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1350, 0x00000002); + nv_mthd(dev, 0x9097, 0x1358, 0x00000001); + nv_mthd(dev, 0x9097, 0x12e4, 0x00000000); + nv_mthd(dev, 0x9097, 0x131c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1320, 0x00000000); + nv_mthd(dev, 0x9097, 0x1324, 0x00000000); + nv_mthd(dev, 0x9097, 0x1328, 0x00000000); + nv_mthd(dev, 0x9097, 0x19c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1140, 0x00000000); + nv_mthd(dev, 0x9097, 0x19c4, 0x00000000); + nv_mthd(dev, 0x9097, 0x19c8, 0x00001500); + nv_mthd(dev, 0x9097, 0x135c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f90, 0x00000000); + nv_mthd(dev, 0x9097, 0x19e0, 0x00000001); + nv_mthd(dev, 0x9097, 0x19e4, 0x00000001); + nv_mthd(dev, 0x9097, 0x19e8, 0x00000001); + nv_mthd(dev, 0x9097, 0x19ec, 0x00000001); + nv_mthd(dev, 0x9097, 0x19f0, 0x00000001); + nv_mthd(dev, 0x9097, 0x19f4, 0x00000001); + nv_mthd(dev, 0x9097, 0x19f8, 0x00000001); + nv_mthd(dev, 0x9097, 0x19fc, 0x00000001); + nv_mthd(dev, 0x9097, 0x19cc, 0x00000001); + nv_mthd(dev, 0x9097, 0x15b8, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a00, 0x00001111); + nv_mthd(dev, 0x9097, 0x1a04, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a08, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a0c, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a10, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a14, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a18, 0x00000000); + nv_mthd(dev, 0x9097, 0x1a1c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d6c, 0xffff0000); + nv_mthd(dev, 0x9097, 0x0d70, 0xffff0000); + nv_mthd(dev, 0x9097, 0x10f8, 0x00001010); + nv_mthd(dev, 0x9097, 0x0d80, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d84, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d88, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d8c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0d90, 0x00000000); + nv_mthd(dev, 0x9097, 0x0da0, 0x00000000); + nv_mthd(dev, 0x9097, 0x1508, 0x80000000); + nv_mthd(dev, 0x9097, 0x150c, 0x40000000); + nv_mthd(dev, 0x9097, 0x1668, 0x00000000); + nv_mthd(dev, 0x9097, 0x0318, 0x00000008); + nv_mthd(dev, 0x9097, 0x031c, 0x00000008); + nv_mthd(dev, 0x9097, 0x0d9c, 0x00000001); + nv_mthd(dev, 0x9097, 0x07dc, 0x00000000); + nv_mthd(dev, 0x9097, 0x074c, 0x00000055); + nv_mthd(dev, 0x9097, 0x1420, 0x00000003); + nv_mthd(dev, 0x9097, 0x17bc, 0x00000000); + nv_mthd(dev, 0x9097, 0x17c0, 0x00000000); + nv_mthd(dev, 0x9097, 0x17c4, 0x00000001); + nv_mthd(dev, 0x9097, 0x1008, 0x00000008); + nv_mthd(dev, 0x9097, 0x100c, 0x00000040); + nv_mthd(dev, 0x9097, 0x1010, 0x0000012c); + nv_mthd(dev, 0x9097, 0x0d60, 0x00000040); + nv_mthd(dev, 0x9097, 0x075c, 0x00000003); + nv_mthd(dev, 0x9097, 0x1018, 0x00000020); + nv_mthd(dev, 0x9097, 0x101c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1020, 0x00000020); + nv_mthd(dev, 0x9097, 0x1024, 0x00000001); + nv_mthd(dev, 0x9097, 0x1444, 0x00000000); + nv_mthd(dev, 0x9097, 0x1448, 0x00000000); + nv_mthd(dev, 0x9097, 0x144c, 0x00000000); + nv_mthd(dev, 0x9097, 0x0360, 0x20164010); + nv_mthd(dev, 0x9097, 0x0364, 0x00000020); + nv_mthd(dev, 0x9097, 0x0368, 0x00000000); + nv_mthd(dev, 0x9097, 0x0de4, 0x00000000); + nv_mthd(dev, 0x9097, 0x0204, 0x00000006); + nv_mthd(dev, 0x9097, 0x0208, 0x00000000); + nv_mthd(dev, 0x9097, 0x02cc, 0x003fffff); + nv_mthd(dev, 0x9097, 0x02d0, 0x00000c48); + nv_mthd(dev, 0x9097, 0x1220, 0x00000005); + nv_mthd(dev, 0x9097, 0x0fdc, 0x00000000); + nv_mthd(dev, 0x9097, 0x0f98, 0x00300008); + nv_mthd(dev, 0x9097, 0x1284, 0x04000080); + nv_mthd(dev, 0x9097, 0x1450, 0x00300008); + nv_mthd(dev, 0x9097, 0x1454, 0x04000080); + nv_mthd(dev, 0x9097, 0x0214, 0x00000000); + /* in trace, right after 0x90c0, not here */ + nv_mthd(dev, 0x9097, 0x3410, 0x80002006); +} + +static void +nvc0_grctx_generate_9197(struct drm_device *dev) +{ + u32 fermi = nvc0_graph_class(dev); + u32 mthd; + + if (fermi == 0x9197) { + for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) + nv_mthd(dev, 0x9197, mthd, 0x00000000); + } + nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001); +} + +static void +nvc0_grctx_generate_9297(struct drm_device *dev) +{ + u32 fermi = nvc0_graph_class(dev); + u32 mthd; + + if (fermi == 0x9297) { + for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) + nv_mthd(dev, 0x9297, mthd, 0x00000000); + } + nv_mthd(dev, 0x9297, 0x036c, 0x00000000); + nv_mthd(dev, 0x9297, 0x0370, 0x00000000); + nv_mthd(dev, 0x9297, 0x07a4, 0x00000000); + nv_mthd(dev, 0x9297, 0x07a8, 0x00000000); + nv_mthd(dev, 0x9297, 0x0374, 0x00000000); + nv_mthd(dev, 0x9297, 0x0378, 0x00000020); +} + +static void +nvc0_grctx_generate_902d(struct drm_device *dev) +{ + nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); + nv_mthd(dev, 0x902d, 0x0204, 0x00000001); + nv_mthd(dev, 0x902d, 0x0208, 0x00000020); + nv_mthd(dev, 0x902d, 0x020c, 0x00000001); + nv_mthd(dev, 0x902d, 0x0210, 0x00000000); + nv_mthd(dev, 0x902d, 0x0214, 0x00000080); + nv_mthd(dev, 0x902d, 0x0218, 0x00000100); + nv_mthd(dev, 0x902d, 0x021c, 0x00000100); + nv_mthd(dev, 0x902d, 0x0220, 0x00000000); + nv_mthd(dev, 0x902d, 0x0224, 0x00000000); + nv_mthd(dev, 0x902d, 0x0230, 0x000000cf); + nv_mthd(dev, 0x902d, 0x0234, 0x00000001); + nv_mthd(dev, 0x902d, 0x0238, 0x00000020); + nv_mthd(dev, 0x902d, 0x023c, 0x00000001); + nv_mthd(dev, 0x902d, 0x0244, 0x00000080); + nv_mthd(dev, 0x902d, 0x0248, 0x00000100); + nv_mthd(dev, 0x902d, 0x024c, 0x00000100); +} + +static void +nvc0_grctx_generate_9039(struct drm_device *dev) +{ + nv_mthd(dev, 0x9039, 0x030c, 0x00000000); + nv_mthd(dev, 0x9039, 0x0310, 0x00000000); + nv_mthd(dev, 0x9039, 0x0314, 0x00000000); + nv_mthd(dev, 0x9039, 0x0320, 0x00000000); + nv_mthd(dev, 0x9039, 0x0238, 0x00000000); + nv_mthd(dev, 0x9039, 0x023c, 0x00000000); + nv_mthd(dev, 0x9039, 0x0318, 0x00000000); + nv_mthd(dev, 0x9039, 0x031c, 0x00000000); +} + +static void +nvc0_grctx_generate_90c0(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { + nv_mthd(dev, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); + nv_mthd(dev, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); + nv_mthd(dev, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); + nv_mthd(dev, 0x90c0, 0x2724 + (i * 0x40), 0x00000000); + nv_mthd(dev, 0x90c0, 0x2708 + (i * 0x40), 0x00000000); + nv_mthd(dev, 0x90c0, 0x2728 + (i * 0x40), 0x00000000); + } + nv_mthd(dev, 0x90c0, 0x270c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x272c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x274c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x276c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x278c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000); + nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000); + nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000); + for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { + nv_mthd(dev, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); + nv_mthd(dev, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); + nv_mthd(dev, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); + nv_mthd(dev, 0x90c0, 0x2734 + (i * 0x40), 0x00000040); + } + nv_mthd(dev, 0x90c0, 0x030c, 0x00000001); + nv_mthd(dev, 0x90c0, 0x1944, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0758, 0x00000100); + nv_mthd(dev, 0x90c0, 0x02c4, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0790, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0794, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0798, 0x00000000); + nv_mthd(dev, 0x90c0, 0x079c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x07a0, 0x00000000); + nv_mthd(dev, 0x90c0, 0x077c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0204, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0208, 0x00000000); + nv_mthd(dev, 0x90c0, 0x020c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0214, 0x00000000); + nv_mthd(dev, 0x90c0, 0x024c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x0d94, 0x00000001); + nv_mthd(dev, 0x90c0, 0x1608, 0x00000000); + nv_mthd(dev, 0x90c0, 0x160c, 0x00000000); + nv_mthd(dev, 0x90c0, 0x1664, 0x00000000); +} + +static void +nvc0_grctx_generate_dispatch(struct drm_device *dev) +{ + int i; + + nv_wr32(dev, 0x404004, 0x00000000); + nv_wr32(dev, 0x404008, 0x00000000); + nv_wr32(dev, 0x40400c, 0x00000000); + nv_wr32(dev, 0x404010, 0x00000000); + nv_wr32(dev, 0x404014, 0x00000000); + nv_wr32(dev, 0x404018, 0x00000000); + nv_wr32(dev, 0x40401c, 0x00000000); + nv_wr32(dev, 0x404020, 0x00000000); + nv_wr32(dev, 0x404024, 0x00000000); + nv_wr32(dev, 0x404028, 0x00000000); + nv_wr32(dev, 0x40402c, 0x00000000); + nv_wr32(dev, 0x404044, 0x00000000); + nv_wr32(dev, 0x404094, 0x00000000); + nv_wr32(dev, 0x404098, 0x00000000); + nv_wr32(dev, 0x40409c, 0x00000000); + nv_wr32(dev, 0x4040a0, 0x00000000); + nv_wr32(dev, 0x4040a4, 0x00000000); + nv_wr32(dev, 0x4040a8, 0x00000000); + nv_wr32(dev, 0x4040ac, 0x00000000); + nv_wr32(dev, 0x4040b0, 0x00000000); + nv_wr32(dev, 0x4040b4, 0x00000000); + nv_wr32(dev, 0x4040b8, 0x00000000); + nv_wr32(dev, 0x4040bc, 0x00000000); + nv_wr32(dev, 0x4040c0, 0x00000000); + nv_wr32(dev, 0x4040c4, 0x00000000); + nv_wr32(dev, 0x4040c8, 0xf0000087); + nv_wr32(dev, 0x4040d4, 0x00000000); + nv_wr32(dev, 0x4040d8, 0x00000000); + nv_wr32(dev, 0x4040dc, 0x00000000); + nv_wr32(dev, 0x4040e0, 0x00000000); + nv_wr32(dev, 0x4040e4, 0x00000000); + nv_wr32(dev, 0x4040e8, 0x00001000); + nv_wr32(dev, 0x4040f8, 0x00000000); + nv_wr32(dev, 0x404130, 0x00000000); + nv_wr32(dev, 0x404134, 0x00000000); + nv_wr32(dev, 0x404138, 0x20000040); + nv_wr32(dev, 0x404150, 0x0000002e); + nv_wr32(dev, 0x404154, 0x00000400); + nv_wr32(dev, 0x404158, 0x00000200); + nv_wr32(dev, 0x404164, 0x00000055); + nv_wr32(dev, 0x404168, 0x00000000); + nv_wr32(dev, 0x404174, 0x00000000); + nv_wr32(dev, 0x404178, 0x00000000); + nv_wr32(dev, 0x40417c, 0x00000000); + for (i = 0; i < 8; i++) + nv_wr32(dev, 0x404200 + (i * 4), 0x00000000); /* subc */ +} + +static void +nvc0_grctx_generate_macro(struct drm_device *dev) +{ + nv_wr32(dev, 0x404404, 0x00000000); + nv_wr32(dev, 0x404408, 0x00000000); + nv_wr32(dev, 0x40440c, 0x00000000); + nv_wr32(dev, 0x404410, 0x00000000); + nv_wr32(dev, 0x404414, 0x00000000); + nv_wr32(dev, 0x404418, 0x00000000); + nv_wr32(dev, 0x40441c, 0x00000000); + nv_wr32(dev, 0x404420, 0x00000000); + nv_wr32(dev, 0x404424, 0x00000000); + nv_wr32(dev, 0x404428, 0x00000000); + nv_wr32(dev, 0x40442c, 0x00000000); + nv_wr32(dev, 0x404430, 0x00000000); + nv_wr32(dev, 0x404434, 0x00000000); + nv_wr32(dev, 0x404438, 0x00000000); + nv_wr32(dev, 0x404460, 0x00000000); + nv_wr32(dev, 0x404464, 0x00000000); + nv_wr32(dev, 0x404468, 0x00ffffff); + nv_wr32(dev, 0x40446c, 0x00000000); + nv_wr32(dev, 0x404480, 0x00000001); + nv_wr32(dev, 0x404498, 0x00000001); +} + +static void +nvc0_grctx_generate_m2mf(struct drm_device *dev) +{ + nv_wr32(dev, 0x404604, 0x00000015); + nv_wr32(dev, 0x404608, 0x00000000); + nv_wr32(dev, 0x40460c, 0x00002e00); + nv_wr32(dev, 0x404610, 0x00000100); + nv_wr32(dev, 0x404618, 0x00000000); + nv_wr32(dev, 0x40461c, 0x00000000); + nv_wr32(dev, 0x404620, 0x00000000); + nv_wr32(dev, 0x404624, 0x00000000); + nv_wr32(dev, 0x404628, 0x00000000); + nv_wr32(dev, 0x40462c, 0x00000000); + nv_wr32(dev, 0x404630, 0x00000000); + nv_wr32(dev, 0x404634, 0x00000000); + nv_wr32(dev, 0x404638, 0x00000004); + nv_wr32(dev, 0x40463c, 0x00000000); + nv_wr32(dev, 0x404640, 0x00000000); + nv_wr32(dev, 0x404644, 0x00000000); + nv_wr32(dev, 0x404648, 0x00000000); + nv_wr32(dev, 0x40464c, 0x00000000); + nv_wr32(dev, 0x404650, 0x00000000); + nv_wr32(dev, 0x404654, 0x00000000); + nv_wr32(dev, 0x404658, 0x00000000); + nv_wr32(dev, 0x40465c, 0x007f0100); + nv_wr32(dev, 0x404660, 0x00000000); + nv_wr32(dev, 0x404664, 0x00000000); + nv_wr32(dev, 0x404668, 0x00000000); + nv_wr32(dev, 0x40466c, 0x00000000); + nv_wr32(dev, 0x404670, 0x00000000); + nv_wr32(dev, 0x404674, 0x00000000); + nv_wr32(dev, 0x404678, 0x00000000); + nv_wr32(dev, 0x40467c, 0x00000002); + nv_wr32(dev, 0x404680, 0x00000000); + nv_wr32(dev, 0x404684, 0x00000000); + nv_wr32(dev, 0x404688, 0x00000000); + nv_wr32(dev, 0x40468c, 0x00000000); + nv_wr32(dev, 0x404690, 0x00000000); + nv_wr32(dev, 0x404694, 0x00000000); + nv_wr32(dev, 0x404698, 0x00000000); + nv_wr32(dev, 0x40469c, 0x00000000); + nv_wr32(dev, 0x4046a0, 0x007f0080); + nv_wr32(dev, 0x4046a4, 0x00000000); + nv_wr32(dev, 0x4046a8, 0x00000000); + nv_wr32(dev, 0x4046ac, 0x00000000); + nv_wr32(dev, 0x4046b0, 0x00000000); + nv_wr32(dev, 0x4046b4, 0x00000000); + nv_wr32(dev, 0x4046b8, 0x00000000); + nv_wr32(dev, 0x4046bc, 0x00000000); + nv_wr32(dev, 0x4046c0, 0x00000000); + nv_wr32(dev, 0x4046c4, 0x00000000); + nv_wr32(dev, 0x4046c8, 0x00000000); + nv_wr32(dev, 0x4046cc, 0x00000000); + nv_wr32(dev, 0x4046d0, 0x00000000); + nv_wr32(dev, 0x4046d4, 0x00000000); + nv_wr32(dev, 0x4046d8, 0x00000000); + nv_wr32(dev, 0x4046dc, 0x00000000); + nv_wr32(dev, 0x4046e0, 0x00000000); + nv_wr32(dev, 0x4046e4, 0x00000000); + nv_wr32(dev, 0x4046e8, 0x00000000); + nv_wr32(dev, 0x4046f0, 0x00000000); + nv_wr32(dev, 0x4046f4, 0x00000000); +} + +static void +nvc0_grctx_generate_unk47xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x404700, 0x00000000); + nv_wr32(dev, 0x404704, 0x00000000); + nv_wr32(dev, 0x404708, 0x00000000); + nv_wr32(dev, 0x40470c, 0x00000000); + nv_wr32(dev, 0x404710, 0x00000000); + nv_wr32(dev, 0x404714, 0x00000000); + nv_wr32(dev, 0x404718, 0x00000000); + nv_wr32(dev, 0x40471c, 0x00000000); + nv_wr32(dev, 0x404720, 0x00000000); + nv_wr32(dev, 0x404724, 0x00000000); + nv_wr32(dev, 0x404728, 0x00000000); + nv_wr32(dev, 0x40472c, 0x00000000); + nv_wr32(dev, 0x404730, 0x00000000); + nv_wr32(dev, 0x404734, 0x00000100); + nv_wr32(dev, 0x404738, 0x00000000); + nv_wr32(dev, 0x40473c, 0x00000000); + nv_wr32(dev, 0x404740, 0x00000000); + nv_wr32(dev, 0x404744, 0x00000000); + nv_wr32(dev, 0x404748, 0x00000000); + nv_wr32(dev, 0x40474c, 0x00000000); + nv_wr32(dev, 0x404750, 0x00000000); + nv_wr32(dev, 0x404754, 0x00000000); +} + +static void +nvc0_grctx_generate_shaders(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset == 0xd9) { + nv_wr32(dev, 0x405800, 0x0f8000bf); + nv_wr32(dev, 0x405830, 0x02180218); + nv_wr32(dev, 0x405834, 0x08000000); + } else + if (dev_priv->chipset == 0xc1) { + nv_wr32(dev, 0x405800, 0x0f8000bf); + nv_wr32(dev, 0x405830, 0x02180218); + nv_wr32(dev, 0x405834, 0x00000000); + } else { + nv_wr32(dev, 0x405800, 0x078000bf); + nv_wr32(dev, 0x405830, 0x02180000); + nv_wr32(dev, 0x405834, 0x00000000); + } + nv_wr32(dev, 0x405838, 0x00000000); + nv_wr32(dev, 0x405854, 0x00000000); + nv_wr32(dev, 0x405870, 0x00000001); + nv_wr32(dev, 0x405874, 0x00000001); + nv_wr32(dev, 0x405878, 0x00000001); + nv_wr32(dev, 0x40587c, 0x00000001); + nv_wr32(dev, 0x405a00, 0x00000000); + nv_wr32(dev, 0x405a04, 0x00000000); + nv_wr32(dev, 0x405a18, 0x00000000); +} + +static void +nvc0_grctx_generate_unk60xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x406020, 0x000103c1); + nv_wr32(dev, 0x406028, 0x00000001); + nv_wr32(dev, 0x40602c, 0x00000001); + nv_wr32(dev, 0x406030, 0x00000001); + nv_wr32(dev, 0x406034, 0x00000001); +} + +static void +nvc0_grctx_generate_unk64xx(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nv_wr32(dev, 0x4064a8, 0x00000000); + nv_wr32(dev, 0x4064ac, 0x00003fff); + nv_wr32(dev, 0x4064b4, 0x00000000); + nv_wr32(dev, 0x4064b8, 0x00000000); + if (dev_priv->chipset == 0xd9) + nv_wr32(dev, 0x4064bc, 0x00000000); + if (dev_priv->chipset == 0xc1 || + dev_priv->chipset == 0xd9) { + nv_wr32(dev, 0x4064c0, 0x80140078); + nv_wr32(dev, 0x4064c4, 0x0086ffff); + } +} + +static void +nvc0_grctx_generate_tpbus(struct drm_device *dev) +{ + nv_wr32(dev, 0x407804, 0x00000023); + nv_wr32(dev, 0x40780c, 0x0a418820); + nv_wr32(dev, 0x407810, 0x062080e6); + nv_wr32(dev, 0x407814, 0x020398a4); + nv_wr32(dev, 0x407818, 0x0e629062); + nv_wr32(dev, 0x40781c, 0x0a418820); + nv_wr32(dev, 0x407820, 0x000000e6); + nv_wr32(dev, 0x4078bc, 0x00000103); +} + +static void +nvc0_grctx_generate_ccache(struct drm_device *dev) +{ + nv_wr32(dev, 0x408000, 0x00000000); + nv_wr32(dev, 0x408004, 0x00000000); + nv_wr32(dev, 0x408008, 0x00000018); + nv_wr32(dev, 0x40800c, 0x00000000); + nv_wr32(dev, 0x408010, 0x00000000); + nv_wr32(dev, 0x408014, 0x00000069); + nv_wr32(dev, 0x408018, 0xe100e100); + nv_wr32(dev, 0x408064, 0x00000000); +} + +static void +nvc0_grctx_generate_rop(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chipset = dev_priv->chipset; + + /* ROPC_BROADCAST */ + nv_wr32(dev, 0x408800, 0x02802a3c); + nv_wr32(dev, 0x408804, 0x00000040); + if (chipset == 0xd9) { + nv_wr32(dev, 0x408808, 0x1043e005); + nv_wr32(dev, 0x408900, 0x3080b801); + nv_wr32(dev, 0x408904, 0x1043e005); + nv_wr32(dev, 0x408908, 0x00c8102f); + } else + if (chipset == 0xc1) { + nv_wr32(dev, 0x408808, 0x1003e005); + nv_wr32(dev, 0x408900, 0x3080b801); + nv_wr32(dev, 0x408904, 0x62000001); + nv_wr32(dev, 0x408908, 0x00c80929); + } else { + nv_wr32(dev, 0x408808, 0x0003e00d); + nv_wr32(dev, 0x408900, 0x3080b801); + nv_wr32(dev, 0x408904, 0x02000001); + nv_wr32(dev, 0x408908, 0x00c80929); + } + nv_wr32(dev, 0x40890c, 0x00000000); + nv_wr32(dev, 0x408980, 0x0000011d); +} + +static void +nvc0_grctx_generate_gpc(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chipset = dev_priv->chipset; + int i; + + /* GPC_BROADCAST */ + nv_wr32(dev, 0x418380, 0x00000016); + nv_wr32(dev, 0x418400, 0x38004e00); + nv_wr32(dev, 0x418404, 0x71e0ffff); + nv_wr32(dev, 0x418408, 0x00000000); + nv_wr32(dev, 0x41840c, 0x00001008); + nv_wr32(dev, 0x418410, 0x0fff0fff); + nv_wr32(dev, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff); + nv_wr32(dev, 0x418450, 0x00000000); + nv_wr32(dev, 0x418454, 0x00000000); + nv_wr32(dev, 0x418458, 0x00000000); + nv_wr32(dev, 0x41845c, 0x00000000); + nv_wr32(dev, 0x418460, 0x00000000); + nv_wr32(dev, 0x418464, 0x00000000); + nv_wr32(dev, 0x418468, 0x00000001); + nv_wr32(dev, 0x41846c, 0x00000000); + nv_wr32(dev, 0x418470, 0x00000000); + nv_wr32(dev, 0x418600, 0x0000001f); + nv_wr32(dev, 0x418684, 0x0000000f); + nv_wr32(dev, 0x418700, 0x00000002); + nv_wr32(dev, 0x418704, 0x00000080); + nv_wr32(dev, 0x418708, 0x00000000); + nv_wr32(dev, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000); + nv_wr32(dev, 0x418710, 0x00000000); + nv_wr32(dev, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a); + nv_wr32(dev, 0x418808, 0x00000000); + nv_wr32(dev, 0x41880c, 0x00000000); + nv_wr32(dev, 0x418810, 0x00000000); + nv_wr32(dev, 0x418828, 0x00008442); + if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x418830, 0x10000001); + else + nv_wr32(dev, 0x418830, 0x00000001); + nv_wr32(dev, 0x4188d8, 0x00000008); + nv_wr32(dev, 0x4188e0, 0x01000000); + nv_wr32(dev, 0x4188e8, 0x00000000); + nv_wr32(dev, 0x4188ec, 0x00000000); + nv_wr32(dev, 0x4188f0, 0x00000000); + nv_wr32(dev, 0x4188f4, 0x00000000); + nv_wr32(dev, 0x4188f8, 0x00000000); + if (chipset == 0xd9) + nv_wr32(dev, 0x4188fc, 0x20100008); + else if (chipset == 0xc1) + nv_wr32(dev, 0x4188fc, 0x00100018); + else + nv_wr32(dev, 0x4188fc, 0x00100000); + nv_wr32(dev, 0x41891c, 0x00ff00ff); + nv_wr32(dev, 0x418924, 0x00000000); + nv_wr32(dev, 0x418928, 0x00ffff00); + nv_wr32(dev, 0x41892c, 0x0000ff00); + for (i = 0; i < 8; i++) { + nv_wr32(dev, 0x418a00 + (i * 0x20), 0x00000000); + nv_wr32(dev, 0x418a04 + (i * 0x20), 0x00000000); + nv_wr32(dev, 0x418a08 + (i * 0x20), 0x00000000); + nv_wr32(dev, 0x418a0c + (i * 0x20), 0x00010000); + nv_wr32(dev, 0x418a10 + (i * 0x20), 0x00000000); + nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000); + nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000); + } + nv_wr32(dev, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); + nv_wr32(dev, 0x418b08, 0x0a418820); + nv_wr32(dev, 0x418b0c, 0x062080e6); + nv_wr32(dev, 0x418b10, 0x020398a4); + nv_wr32(dev, 0x418b14, 0x0e629062); + nv_wr32(dev, 0x418b18, 0x0a418820); + nv_wr32(dev, 0x418b1c, 0x000000e6); + nv_wr32(dev, 0x418bb8, 0x00000103); + nv_wr32(dev, 0x418c08, 0x00000001); + nv_wr32(dev, 0x418c10, 0x00000000); + nv_wr32(dev, 0x418c14, 0x00000000); + nv_wr32(dev, 0x418c18, 0x00000000); + nv_wr32(dev, 0x418c1c, 0x00000000); + nv_wr32(dev, 0x418c20, 0x00000000); + nv_wr32(dev, 0x418c24, 0x00000000); + nv_wr32(dev, 0x418c28, 0x00000000); + nv_wr32(dev, 0x418c2c, 0x00000000); + if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x418c6c, 0x00000001); + nv_wr32(dev, 0x418c80, 0x20200004); + nv_wr32(dev, 0x418c8c, 0x00000001); + nv_wr32(dev, 0x419000, 0x00000780); + nv_wr32(dev, 0x419004, 0x00000000); + nv_wr32(dev, 0x419008, 0x00000000); + nv_wr32(dev, 0x419014, 0x00000004); +} + +static void +nvc0_grctx_generate_tp(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chipset = dev_priv->chipset; + + /* GPC_BROADCAST.TP_BROADCAST */ + nv_wr32(dev, 0x419818, 0x00000000); + nv_wr32(dev, 0x41983c, 0x00038bc7); + nv_wr32(dev, 0x419848, 0x00000000); + if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x419864, 0x00000129); + else + nv_wr32(dev, 0x419864, 0x0000012a); + nv_wr32(dev, 0x419888, 0x00000000); + nv_wr32(dev, 0x419a00, 0x000001f0); + nv_wr32(dev, 0x419a04, 0x00000001); + nv_wr32(dev, 0x419a08, 0x00000023); + nv_wr32(dev, 0x419a0c, 0x00020000); + nv_wr32(dev, 0x419a10, 0x00000000); + nv_wr32(dev, 0x419a14, 0x00000200); + nv_wr32(dev, 0x419a1c, 0x00000000); + nv_wr32(dev, 0x419a20, 0x00000800); + if (chipset == 0xd9) + nv_wr32(dev, 0x00419ac4, 0x0017f440); + else if (chipset != 0xc0 && chipset != 0xc8) + nv_wr32(dev, 0x00419ac4, 0x0007f440); + nv_wr32(dev, 0x419b00, 0x0a418820); + nv_wr32(dev, 0x419b04, 0x062080e6); + nv_wr32(dev, 0x419b08, 0x020398a4); + nv_wr32(dev, 0x419b0c, 0x0e629062); + nv_wr32(dev, 0x419b10, 0x0a418820); + nv_wr32(dev, 0x419b14, 0x000000e6); + nv_wr32(dev, 0x419bd0, 0x00900103); + if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x419be0, 0x00400001); + else + nv_wr32(dev, 0x419be0, 0x00000001); + nv_wr32(dev, 0x419be4, 0x00000000); + nv_wr32(dev, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a); + nv_wr32(dev, 0x419c04, 0x00000006); + nv_wr32(dev, 0x419c08, 0x00000002); + nv_wr32(dev, 0x419c20, 0x00000000); + if (dev_priv->chipset == 0xd9) { + nv_wr32(dev, 0x419c24, 0x00084210); + nv_wr32(dev, 0x419c28, 0x3cf3cf3c); + nv_wr32(dev, 0x419cb0, 0x00020048); + } else + if (chipset == 0xce || chipset == 0xcf) { + nv_wr32(dev, 0x419cb0, 0x00020048); + } else { + nv_wr32(dev, 0x419cb0, 0x00060048); + } + nv_wr32(dev, 0x419ce8, 0x00000000); + nv_wr32(dev, 0x419cf4, 0x00000183); + if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x419d20, 0x12180000); + else + nv_wr32(dev, 0x419d20, 0x02180000); + nv_wr32(dev, 0x419d24, 0x00001fff); + if (chipset == 0xc1 || chipset == 0xd9) + nv_wr32(dev, 0x419d44, 0x02180218); + nv_wr32(dev, 0x419e04, 0x00000000); + nv_wr32(dev, 0x419e08, 0x00000000); + nv_wr32(dev, 0x419e0c, 0x00000000); + nv_wr32(dev, 0x419e10, 0x00000002); + nv_wr32(dev, 0x419e44, 0x001beff2); + nv_wr32(dev, 0x419e48, 0x00000000); + nv_wr32(dev, 0x419e4c, 0x0000000f); + nv_wr32(dev, 0x419e50, 0x00000000); + nv_wr32(dev, 0x419e54, 0x00000000); + nv_wr32(dev, 0x419e58, 0x00000000); + nv_wr32(dev, 0x419e5c, 0x00000000); + nv_wr32(dev, 0x419e60, 0x00000000); + nv_wr32(dev, 0x419e64, 0x00000000); + nv_wr32(dev, 0x419e68, 0x00000000); + nv_wr32(dev, 0x419e6c, 0x00000000); + nv_wr32(dev, 0x419e70, 0x00000000); + nv_wr32(dev, 0x419e74, 0x00000000); + nv_wr32(dev, 0x419e78, 0x00000000); + nv_wr32(dev, 0x419e7c, 0x00000000); + nv_wr32(dev, 0x419e80, 0x00000000); + nv_wr32(dev, 0x419e84, 0x00000000); + nv_wr32(dev, 0x419e88, 0x00000000); + nv_wr32(dev, 0x419e8c, 0x00000000); + nv_wr32(dev, 0x419e90, 0x00000000); + nv_wr32(dev, 0x419e98, 0x00000000); + if (chipset != 0xc0 && chipset != 0xc8) + nv_wr32(dev, 0x419ee0, 0x00011110); + nv_wr32(dev, 0x419f50, 0x00000000); + nv_wr32(dev, 0x419f54, 0x00000000); + if (chipset != 0xc0 && chipset != 0xc8) + nv_wr32(dev, 0x419f58, 0x00000000); +} + +int +nvc0_grctx_generate(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + int i, gpc, tp, id; + u32 fermi = nvc0_graph_class(dev); + u32 r000260, tmp; + + r000260 = nv_rd32(dev, 0x000260); + nv_wr32(dev, 0x000260, r000260 & ~1); + nv_wr32(dev, 0x400208, 0x00000000); + + nvc0_grctx_generate_dispatch(dev); + nvc0_grctx_generate_macro(dev); + nvc0_grctx_generate_m2mf(dev); + nvc0_grctx_generate_unk47xx(dev); + nvc0_grctx_generate_shaders(dev); + nvc0_grctx_generate_unk60xx(dev); + nvc0_grctx_generate_unk64xx(dev); + nvc0_grctx_generate_tpbus(dev); + nvc0_grctx_generate_ccache(dev); + nvc0_grctx_generate_rop(dev); + nvc0_grctx_generate_gpc(dev); + nvc0_grctx_generate_tp(dev); + + nv_wr32(dev, 0x404154, 0x00000000); + + /* fuc "mmio list" writes */ + for (i = 0; i < grch->mmio_nr * 8; i += 8) { + u32 reg = nv_ro32(grch->mmio, i + 0); + nv_wr32(dev, reg, nv_ro32(grch->mmio, i + 4)); + } + + for (tp = 0, id = 0; tp < 4; tp++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tp < priv->tp_nr[gpc]) { + nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id); + nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x088), id); + id++; + } + + nv_wr32(dev, GPC_UNIT(gpc, 0x0c08), priv->tp_nr[gpc]); + nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tp_nr[gpc]); + } + } + + tmp = 0; + for (i = 0; i < priv->gpc_nr; i++) + tmp |= priv->tp_nr[i] << (i * 4); + nv_wr32(dev, 0x406028, tmp); + nv_wr32(dev, 0x405870, tmp); + + nv_wr32(dev, 0x40602c, 0x00000000); + nv_wr32(dev, 0x405874, 0x00000000); + nv_wr32(dev, 0x406030, 0x00000000); + nv_wr32(dev, 0x405878, 0x00000000); + nv_wr32(dev, 0x406034, 0x00000000); + nv_wr32(dev, 0x40587c, 0x00000000); + + if (1) { + u8 tpnr[GPC_MAX], data[TP_MAX]; + + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + memset(data, 0x1f, sizeof(data)); + + gpc = -1; + for (tp = 0; tp < priv->tp_total; tp++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpnr[gpc]); + tpnr[gpc]--; + data[tp] = gpc; + } + + for (i = 0; i < 4; i++) + nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); + } + + if (1) { + u32 data[6] = {}, data2[2] = {}; + u8 tpnr[GPC_MAX]; + u8 shift, ntpcv; + + /* calculate first set of magics */ + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + + gpc = -1; + for (tp = 0; tp < priv->tp_total; tp++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpnr[gpc]); + tpnr[gpc]--; + + data[tp / 6] |= gpc << ((tp % 6) * 5); + } + + for (; tp < 32; tp++) + data[tp / 6] |= 7 << ((tp % 6) * 5); + + /* and the second... */ + shift = 0; + ntpcv = priv->tp_total; + while (!(ntpcv & (1 << 4))) { + ntpcv <<= 1; + shift++; + } + + data2[0] = (ntpcv << 16); + data2[0] |= (shift << 21); + data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24); + for (i = 1; i < 7; i++) + data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); + + /* GPC_BROADCAST */ + nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) | + priv->magic_not_rop_nr); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x418b08 + (i * 4), data[i]); + + /* GPC_BROADCAST.TP_BROADCAST */ + nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) | + priv->magic_not_rop_nr | + data2[0]); + nv_wr32(dev, 0x419be4, data2[1]); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x419b00 + (i * 4), data[i]); + + /* UNK78xx */ + nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) | + priv->magic_not_rop_nr); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x40780c + (i * 4), data[i]); + } + + if (1) { + u32 tp_mask = 0, tp_set = 0; + u8 tpnr[GPC_MAX], a, b; + + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) + tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8); + + for (i = 0, gpc = -1, b = -1; i < 32; i++) { + a = (i * (priv->tp_total - 1)) / 32; + if (a != b) { + b = a; + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpnr[gpc]); + tp = priv->tp_nr[gpc] - tpnr[gpc]--; + + tp_set |= 1 << ((gpc * 8) + tp); + } + + nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); + nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); + } + } + + nv_wr32(dev, 0x400208, 0x80000000); + + nv_icmd(dev, 0x00001000, 0x00000004); + nv_icmd(dev, 0x000000a9, 0x0000ffff); + nv_icmd(dev, 0x00000038, 0x0fac6881); + nv_icmd(dev, 0x0000003d, 0x00000001); + nv_icmd(dev, 0x000000e8, 0x00000400); + nv_icmd(dev, 0x000000e9, 0x00000400); + nv_icmd(dev, 0x000000ea, 0x00000400); + nv_icmd(dev, 0x000000eb, 0x00000400); + nv_icmd(dev, 0x000000ec, 0x00000400); + nv_icmd(dev, 0x000000ed, 0x00000400); + nv_icmd(dev, 0x000000ee, 0x00000400); + nv_icmd(dev, 0x000000ef, 0x00000400); + nv_icmd(dev, 0x00000078, 0x00000300); + nv_icmd(dev, 0x00000079, 0x00000300); + nv_icmd(dev, 0x0000007a, 0x00000300); + nv_icmd(dev, 0x0000007b, 0x00000300); + nv_icmd(dev, 0x0000007c, 0x00000300); + nv_icmd(dev, 0x0000007d, 0x00000300); + nv_icmd(dev, 0x0000007e, 0x00000300); + nv_icmd(dev, 0x0000007f, 0x00000300); + nv_icmd(dev, 0x00000050, 0x00000011); + nv_icmd(dev, 0x00000058, 0x00000008); + nv_icmd(dev, 0x00000059, 0x00000008); + nv_icmd(dev, 0x0000005a, 0x00000008); + nv_icmd(dev, 0x0000005b, 0x00000008); + nv_icmd(dev, 0x0000005c, 0x00000008); + nv_icmd(dev, 0x0000005d, 0x00000008); + nv_icmd(dev, 0x0000005e, 0x00000008); + nv_icmd(dev, 0x0000005f, 0x00000008); + nv_icmd(dev, 0x00000208, 0x00000001); + nv_icmd(dev, 0x00000209, 0x00000001); + nv_icmd(dev, 0x0000020a, 0x00000001); + nv_icmd(dev, 0x0000020b, 0x00000001); + nv_icmd(dev, 0x0000020c, 0x00000001); + nv_icmd(dev, 0x0000020d, 0x00000001); + nv_icmd(dev, 0x0000020e, 0x00000001); + nv_icmd(dev, 0x0000020f, 0x00000001); + nv_icmd(dev, 0x00000081, 0x00000001); + nv_icmd(dev, 0x00000085, 0x00000004); + nv_icmd(dev, 0x00000088, 0x00000400); + nv_icmd(dev, 0x00000090, 0x00000300); + nv_icmd(dev, 0x00000098, 0x00001001); + nv_icmd(dev, 0x000000e3, 0x00000001); + nv_icmd(dev, 0x000000da, 0x00000001); + nv_icmd(dev, 0x000000f8, 0x00000003); + nv_icmd(dev, 0x000000fa, 0x00000001); + nv_icmd(dev, 0x0000009f, 0x0000ffff); + nv_icmd(dev, 0x000000a0, 0x0000ffff); + nv_icmd(dev, 0x000000a1, 0x0000ffff); + nv_icmd(dev, 0x000000a2, 0x0000ffff); + nv_icmd(dev, 0x000000b1, 0x00000001); + nv_icmd(dev, 0x000000b2, 0x00000000); + nv_icmd(dev, 0x000000b3, 0x00000000); + nv_icmd(dev, 0x000000b4, 0x00000000); + nv_icmd(dev, 0x000000b5, 0x00000000); + nv_icmd(dev, 0x000000b6, 0x00000000); + nv_icmd(dev, 0x000000b7, 0x00000000); + nv_icmd(dev, 0x000000b8, 0x00000000); + nv_icmd(dev, 0x000000b9, 0x00000000); + nv_icmd(dev, 0x000000ba, 0x00000000); + nv_icmd(dev, 0x000000bb, 0x00000000); + nv_icmd(dev, 0x000000bc, 0x00000000); + nv_icmd(dev, 0x000000bd, 0x00000000); + nv_icmd(dev, 0x000000be, 0x00000000); + nv_icmd(dev, 0x000000bf, 0x00000000); + nv_icmd(dev, 0x000000c0, 0x00000000); + nv_icmd(dev, 0x000000c1, 0x00000000); + nv_icmd(dev, 0x000000c2, 0x00000000); + nv_icmd(dev, 0x000000c3, 0x00000000); + nv_icmd(dev, 0x000000c4, 0x00000000); + nv_icmd(dev, 0x000000c5, 0x00000000); + nv_icmd(dev, 0x000000c6, 0x00000000); + nv_icmd(dev, 0x000000c7, 0x00000000); + nv_icmd(dev, 0x000000c8, 0x00000000); + nv_icmd(dev, 0x000000c9, 0x00000000); + nv_icmd(dev, 0x000000ca, 0x00000000); + nv_icmd(dev, 0x000000cb, 0x00000000); + nv_icmd(dev, 0x000000cc, 0x00000000); + nv_icmd(dev, 0x000000cd, 0x00000000); + nv_icmd(dev, 0x000000ce, 0x00000000); + nv_icmd(dev, 0x000000cf, 0x00000000); + nv_icmd(dev, 0x000000d0, 0x00000000); + nv_icmd(dev, 0x000000d1, 0x00000000); + nv_icmd(dev, 0x000000d2, 0x00000000); + nv_icmd(dev, 0x000000d3, 0x00000000); + nv_icmd(dev, 0x000000d4, 0x00000000); + nv_icmd(dev, 0x000000d5, 0x00000000); + nv_icmd(dev, 0x000000d6, 0x00000000); + nv_icmd(dev, 0x000000d7, 0x00000000); + nv_icmd(dev, 0x000000d8, 0x00000000); + nv_icmd(dev, 0x000000d9, 0x00000000); + nv_icmd(dev, 0x00000210, 0x00000040); + nv_icmd(dev, 0x00000211, 0x00000040); + nv_icmd(dev, 0x00000212, 0x00000040); + nv_icmd(dev, 0x00000213, 0x00000040); + nv_icmd(dev, 0x00000214, 0x00000040); + nv_icmd(dev, 0x00000215, 0x00000040); + nv_icmd(dev, 0x00000216, 0x00000040); + nv_icmd(dev, 0x00000217, 0x00000040); + if (dev_priv->chipset == 0xd9) { + for (i = 0x0400; i <= 0x0417; i++) + nv_icmd(dev, i, 0x00000040); + } + nv_icmd(dev, 0x00000218, 0x0000c080); + nv_icmd(dev, 0x00000219, 0x0000c080); + nv_icmd(dev, 0x0000021a, 0x0000c080); + nv_icmd(dev, 0x0000021b, 0x0000c080); + nv_icmd(dev, 0x0000021c, 0x0000c080); + nv_icmd(dev, 0x0000021d, 0x0000c080); + nv_icmd(dev, 0x0000021e, 0x0000c080); + nv_icmd(dev, 0x0000021f, 0x0000c080); + if (dev_priv->chipset == 0xd9) { + for (i = 0x0440; i <= 0x0457; i++) + nv_icmd(dev, i, 0x0000c080); + } + nv_icmd(dev, 0x000000ad, 0x0000013e); + nv_icmd(dev, 0x000000e1, 0x00000010); + nv_icmd(dev, 0x00000290, 0x00000000); + nv_icmd(dev, 0x00000291, 0x00000000); + nv_icmd(dev, 0x00000292, 0x00000000); + nv_icmd(dev, 0x00000293, 0x00000000); + nv_icmd(dev, 0x00000294, 0x00000000); + nv_icmd(dev, 0x00000295, 0x00000000); + nv_icmd(dev, 0x00000296, 0x00000000); + nv_icmd(dev, 0x00000297, 0x00000000); + nv_icmd(dev, 0x00000298, 0x00000000); + nv_icmd(dev, 0x00000299, 0x00000000); + nv_icmd(dev, 0x0000029a, 0x00000000); + nv_icmd(dev, 0x0000029b, 0x00000000); + nv_icmd(dev, 0x0000029c, 0x00000000); + nv_icmd(dev, 0x0000029d, 0x00000000); + nv_icmd(dev, 0x0000029e, 0x00000000); + nv_icmd(dev, 0x0000029f, 0x00000000); + nv_icmd(dev, 0x000003b0, 0x00000000); + nv_icmd(dev, 0x000003b1, 0x00000000); + nv_icmd(dev, 0x000003b2, 0x00000000); + nv_icmd(dev, 0x000003b3, 0x00000000); + nv_icmd(dev, 0x000003b4, 0x00000000); + nv_icmd(dev, 0x000003b5, 0x00000000); + nv_icmd(dev, 0x000003b6, 0x00000000); + nv_icmd(dev, 0x000003b7, 0x00000000); + nv_icmd(dev, 0x000003b8, 0x00000000); + nv_icmd(dev, 0x000003b9, 0x00000000); + nv_icmd(dev, 0x000003ba, 0x00000000); + nv_icmd(dev, 0x000003bb, 0x00000000); + nv_icmd(dev, 0x000003bc, 0x00000000); + nv_icmd(dev, 0x000003bd, 0x00000000); + nv_icmd(dev, 0x000003be, 0x00000000); + nv_icmd(dev, 0x000003bf, 0x00000000); + nv_icmd(dev, 0x000002a0, 0x00000000); + nv_icmd(dev, 0x000002a1, 0x00000000); + nv_icmd(dev, 0x000002a2, 0x00000000); + nv_icmd(dev, 0x000002a3, 0x00000000); + nv_icmd(dev, 0x000002a4, 0x00000000); + nv_icmd(dev, 0x000002a5, 0x00000000); + nv_icmd(dev, 0x000002a6, 0x00000000); + nv_icmd(dev, 0x000002a7, 0x00000000); + nv_icmd(dev, 0x000002a8, 0x00000000); + nv_icmd(dev, 0x000002a9, 0x00000000); + nv_icmd(dev, 0x000002aa, 0x00000000); + nv_icmd(dev, 0x000002ab, 0x00000000); + nv_icmd(dev, 0x000002ac, 0x00000000); + nv_icmd(dev, 0x000002ad, 0x00000000); + nv_icmd(dev, 0x000002ae, 0x00000000); + nv_icmd(dev, 0x000002af, 0x00000000); + nv_icmd(dev, 0x00000420, 0x00000000); + nv_icmd(dev, 0x00000421, 0x00000000); + nv_icmd(dev, 0x00000422, 0x00000000); + nv_icmd(dev, 0x00000423, 0x00000000); + nv_icmd(dev, 0x00000424, 0x00000000); + nv_icmd(dev, 0x00000425, 0x00000000); + nv_icmd(dev, 0x00000426, 0x00000000); + nv_icmd(dev, 0x00000427, 0x00000000); + nv_icmd(dev, 0x00000428, 0x00000000); + nv_icmd(dev, 0x00000429, 0x00000000); + nv_icmd(dev, 0x0000042a, 0x00000000); + nv_icmd(dev, 0x0000042b, 0x00000000); + nv_icmd(dev, 0x0000042c, 0x00000000); + nv_icmd(dev, 0x0000042d, 0x00000000); + nv_icmd(dev, 0x0000042e, 0x00000000); + nv_icmd(dev, 0x0000042f, 0x00000000); + nv_icmd(dev, 0x000002b0, 0x00000000); + nv_icmd(dev, 0x000002b1, 0x00000000); + nv_icmd(dev, 0x000002b2, 0x00000000); + nv_icmd(dev, 0x000002b3, 0x00000000); + nv_icmd(dev, 0x000002b4, 0x00000000); + nv_icmd(dev, 0x000002b5, 0x00000000); + nv_icmd(dev, 0x000002b6, 0x00000000); + nv_icmd(dev, 0x000002b7, 0x00000000); + nv_icmd(dev, 0x000002b8, 0x00000000); + nv_icmd(dev, 0x000002b9, 0x00000000); + nv_icmd(dev, 0x000002ba, 0x00000000); + nv_icmd(dev, 0x000002bb, 0x00000000); + nv_icmd(dev, 0x000002bc, 0x00000000); + nv_icmd(dev, 0x000002bd, 0x00000000); + nv_icmd(dev, 0x000002be, 0x00000000); + nv_icmd(dev, 0x000002bf, 0x00000000); + nv_icmd(dev, 0x00000430, 0x00000000); + nv_icmd(dev, 0x00000431, 0x00000000); + nv_icmd(dev, 0x00000432, 0x00000000); + nv_icmd(dev, 0x00000433, 0x00000000); + nv_icmd(dev, 0x00000434, 0x00000000); + nv_icmd(dev, 0x00000435, 0x00000000); + nv_icmd(dev, 0x00000436, 0x00000000); + nv_icmd(dev, 0x00000437, 0x00000000); + nv_icmd(dev, 0x00000438, 0x00000000); + nv_icmd(dev, 0x00000439, 0x00000000); + nv_icmd(dev, 0x0000043a, 0x00000000); + nv_icmd(dev, 0x0000043b, 0x00000000); + nv_icmd(dev, 0x0000043c, 0x00000000); + nv_icmd(dev, 0x0000043d, 0x00000000); + nv_icmd(dev, 0x0000043e, 0x00000000); + nv_icmd(dev, 0x0000043f, 0x00000000); + nv_icmd(dev, 0x000002c0, 0x00000000); + nv_icmd(dev, 0x000002c1, 0x00000000); + nv_icmd(dev, 0x000002c2, 0x00000000); + nv_icmd(dev, 0x000002c3, 0x00000000); + nv_icmd(dev, 0x000002c4, 0x00000000); + nv_icmd(dev, 0x000002c5, 0x00000000); + nv_icmd(dev, 0x000002c6, 0x00000000); + nv_icmd(dev, 0x000002c7, 0x00000000); + nv_icmd(dev, 0x000002c8, 0x00000000); + nv_icmd(dev, 0x000002c9, 0x00000000); + nv_icmd(dev, 0x000002ca, 0x00000000); + nv_icmd(dev, 0x000002cb, 0x00000000); + nv_icmd(dev, 0x000002cc, 0x00000000); + nv_icmd(dev, 0x000002cd, 0x00000000); + nv_icmd(dev, 0x000002ce, 0x00000000); + nv_icmd(dev, 0x000002cf, 0x00000000); + nv_icmd(dev, 0x000004d0, 0x00000000); + nv_icmd(dev, 0x000004d1, 0x00000000); + nv_icmd(dev, 0x000004d2, 0x00000000); + nv_icmd(dev, 0x000004d3, 0x00000000); + nv_icmd(dev, 0x000004d4, 0x00000000); + nv_icmd(dev, 0x000004d5, 0x00000000); + nv_icmd(dev, 0x000004d6, 0x00000000); + nv_icmd(dev, 0x000004d7, 0x00000000); + nv_icmd(dev, 0x000004d8, 0x00000000); + nv_icmd(dev, 0x000004d9, 0x00000000); + nv_icmd(dev, 0x000004da, 0x00000000); + nv_icmd(dev, 0x000004db, 0x00000000); + nv_icmd(dev, 0x000004dc, 0x00000000); + nv_icmd(dev, 0x000004dd, 0x00000000); + nv_icmd(dev, 0x000004de, 0x00000000); + nv_icmd(dev, 0x000004df, 0x00000000); + nv_icmd(dev, 0x00000720, 0x00000000); + nv_icmd(dev, 0x00000721, 0x00000000); + nv_icmd(dev, 0x00000722, 0x00000000); + nv_icmd(dev, 0x00000723, 0x00000000); + nv_icmd(dev, 0x00000724, 0x00000000); + nv_icmd(dev, 0x00000725, 0x00000000); + nv_icmd(dev, 0x00000726, 0x00000000); + nv_icmd(dev, 0x00000727, 0x00000000); + nv_icmd(dev, 0x00000728, 0x00000000); + nv_icmd(dev, 0x00000729, 0x00000000); + nv_icmd(dev, 0x0000072a, 0x00000000); + nv_icmd(dev, 0x0000072b, 0x00000000); + nv_icmd(dev, 0x0000072c, 0x00000000); + nv_icmd(dev, 0x0000072d, 0x00000000); + nv_icmd(dev, 0x0000072e, 0x00000000); + nv_icmd(dev, 0x0000072f, 0x00000000); + nv_icmd(dev, 0x000008c0, 0x00000000); + nv_icmd(dev, 0x000008c1, 0x00000000); + nv_icmd(dev, 0x000008c2, 0x00000000); + nv_icmd(dev, 0x000008c3, 0x00000000); + nv_icmd(dev, 0x000008c4, 0x00000000); + nv_icmd(dev, 0x000008c5, 0x00000000); + nv_icmd(dev, 0x000008c6, 0x00000000); + nv_icmd(dev, 0x000008c7, 0x00000000); + nv_icmd(dev, 0x000008c8, 0x00000000); + nv_icmd(dev, 0x000008c9, 0x00000000); + nv_icmd(dev, 0x000008ca, 0x00000000); + nv_icmd(dev, 0x000008cb, 0x00000000); + nv_icmd(dev, 0x000008cc, 0x00000000); + nv_icmd(dev, 0x000008cd, 0x00000000); + nv_icmd(dev, 0x000008ce, 0x00000000); + nv_icmd(dev, 0x000008cf, 0x00000000); + nv_icmd(dev, 0x00000890, 0x00000000); + nv_icmd(dev, 0x00000891, 0x00000000); + nv_icmd(dev, 0x00000892, 0x00000000); + nv_icmd(dev, 0x00000893, 0x00000000); + nv_icmd(dev, 0x00000894, 0x00000000); + nv_icmd(dev, 0x00000895, 0x00000000); + nv_icmd(dev, 0x00000896, 0x00000000); + nv_icmd(dev, 0x00000897, 0x00000000); + nv_icmd(dev, 0x00000898, 0x00000000); + nv_icmd(dev, 0x00000899, 0x00000000); + nv_icmd(dev, 0x0000089a, 0x00000000); + nv_icmd(dev, 0x0000089b, 0x00000000); + nv_icmd(dev, 0x0000089c, 0x00000000); + nv_icmd(dev, 0x0000089d, 0x00000000); + nv_icmd(dev, 0x0000089e, 0x00000000); + nv_icmd(dev, 0x0000089f, 0x00000000); + nv_icmd(dev, 0x000008e0, 0x00000000); + nv_icmd(dev, 0x000008e1, 0x00000000); + nv_icmd(dev, 0x000008e2, 0x00000000); + nv_icmd(dev, 0x000008e3, 0x00000000); + nv_icmd(dev, 0x000008e4, 0x00000000); + nv_icmd(dev, 0x000008e5, 0x00000000); + nv_icmd(dev, 0x000008e6, 0x00000000); + nv_icmd(dev, 0x000008e7, 0x00000000); + nv_icmd(dev, 0x000008e8, 0x00000000); + nv_icmd(dev, 0x000008e9, 0x00000000); + nv_icmd(dev, 0x000008ea, 0x00000000); + nv_icmd(dev, 0x000008eb, 0x00000000); + nv_icmd(dev, 0x000008ec, 0x00000000); + nv_icmd(dev, 0x000008ed, 0x00000000); + nv_icmd(dev, 0x000008ee, 0x00000000); + nv_icmd(dev, 0x000008ef, 0x00000000); + nv_icmd(dev, 0x000008a0, 0x00000000); + nv_icmd(dev, 0x000008a1, 0x00000000); + nv_icmd(dev, 0x000008a2, 0x00000000); + nv_icmd(dev, 0x000008a3, 0x00000000); + nv_icmd(dev, 0x000008a4, 0x00000000); + nv_icmd(dev, 0x000008a5, 0x00000000); + nv_icmd(dev, 0x000008a6, 0x00000000); + nv_icmd(dev, 0x000008a7, 0x00000000); + nv_icmd(dev, 0x000008a8, 0x00000000); + nv_icmd(dev, 0x000008a9, 0x00000000); + nv_icmd(dev, 0x000008aa, 0x00000000); + nv_icmd(dev, 0x000008ab, 0x00000000); + nv_icmd(dev, 0x000008ac, 0x00000000); + nv_icmd(dev, 0x000008ad, 0x00000000); + nv_icmd(dev, 0x000008ae, 0x00000000); + nv_icmd(dev, 0x000008af, 0x00000000); + nv_icmd(dev, 0x000008f0, 0x00000000); + nv_icmd(dev, 0x000008f1, 0x00000000); + nv_icmd(dev, 0x000008f2, 0x00000000); + nv_icmd(dev, 0x000008f3, 0x00000000); + nv_icmd(dev, 0x000008f4, 0x00000000); + nv_icmd(dev, 0x000008f5, 0x00000000); + nv_icmd(dev, 0x000008f6, 0x00000000); + nv_icmd(dev, 0x000008f7, 0x00000000); + nv_icmd(dev, 0x000008f8, 0x00000000); + nv_icmd(dev, 0x000008f9, 0x00000000); + nv_icmd(dev, 0x000008fa, 0x00000000); + nv_icmd(dev, 0x000008fb, 0x00000000); + nv_icmd(dev, 0x000008fc, 0x00000000); + nv_icmd(dev, 0x000008fd, 0x00000000); + nv_icmd(dev, 0x000008fe, 0x00000000); + nv_icmd(dev, 0x000008ff, 0x00000000); + nv_icmd(dev, 0x0000094c, 0x000000ff); + nv_icmd(dev, 0x0000094d, 0xffffffff); + nv_icmd(dev, 0x0000094e, 0x00000002); + nv_icmd(dev, 0x000002ec, 0x00000001); + nv_icmd(dev, 0x00000303, 0x00000001); + nv_icmd(dev, 0x000002e6, 0x00000001); + nv_icmd(dev, 0x00000466, 0x00000052); + nv_icmd(dev, 0x00000301, 0x3f800000); + nv_icmd(dev, 0x00000304, 0x30201000); + nv_icmd(dev, 0x00000305, 0x70605040); + nv_icmd(dev, 0x00000306, 0xb8a89888); + nv_icmd(dev, 0x00000307, 0xf8e8d8c8); + nv_icmd(dev, 0x0000030a, 0x00ffff00); + nv_icmd(dev, 0x0000030b, 0x0000001a); + nv_icmd(dev, 0x0000030c, 0x00000001); + nv_icmd(dev, 0x00000318, 0x00000001); + nv_icmd(dev, 0x00000340, 0x00000000); + nv_icmd(dev, 0x00000375, 0x00000001); + nv_icmd(dev, 0x00000351, 0x00000100); + nv_icmd(dev, 0x0000037d, 0x00000006); + nv_icmd(dev, 0x000003a0, 0x00000002); + nv_icmd(dev, 0x000003aa, 0x00000001); + nv_icmd(dev, 0x000003a9, 0x00000001); + nv_icmd(dev, 0x00000380, 0x00000001); + nv_icmd(dev, 0x00000360, 0x00000040); + nv_icmd(dev, 0x00000366, 0x00000000); + nv_icmd(dev, 0x00000367, 0x00000000); + nv_icmd(dev, 0x00000368, 0x00001fff); + nv_icmd(dev, 0x00000370, 0x00000000); + nv_icmd(dev, 0x00000371, 0x00000000); + nv_icmd(dev, 0x00000372, 0x003fffff); + nv_icmd(dev, 0x0000037a, 0x00000012); + nv_icmd(dev, 0x000005e0, 0x00000022); + nv_icmd(dev, 0x000005e1, 0x00000022); + nv_icmd(dev, 0x000005e2, 0x00000022); + nv_icmd(dev, 0x000005e3, 0x00000022); + nv_icmd(dev, 0x000005e4, 0x00000022); + nv_icmd(dev, 0x00000619, 0x00000003); + nv_icmd(dev, 0x00000811, 0x00000003); + nv_icmd(dev, 0x00000812, 0x00000004); + nv_icmd(dev, 0x00000813, 0x00000006); + nv_icmd(dev, 0x00000814, 0x00000008); + nv_icmd(dev, 0x00000815, 0x0000000b); + nv_icmd(dev, 0x00000800, 0x00000001); + nv_icmd(dev, 0x00000801, 0x00000001); + nv_icmd(dev, 0x00000802, 0x00000001); + nv_icmd(dev, 0x00000803, 0x00000001); + nv_icmd(dev, 0x00000804, 0x00000001); + nv_icmd(dev, 0x00000805, 0x00000001); + nv_icmd(dev, 0x00000632, 0x00000001); + nv_icmd(dev, 0x00000633, 0x00000002); + nv_icmd(dev, 0x00000634, 0x00000003); + nv_icmd(dev, 0x00000635, 0x00000004); + nv_icmd(dev, 0x00000654, 0x3f800000); + nv_icmd(dev, 0x00000657, 0x3f800000); + nv_icmd(dev, 0x00000655, 0x3f800000); + nv_icmd(dev, 0x00000656, 0x3f800000); + nv_icmd(dev, 0x000006cd, 0x3f800000); + nv_icmd(dev, 0x000007f5, 0x3f800000); + nv_icmd(dev, 0x000007dc, 0x39291909); + nv_icmd(dev, 0x000007dd, 0x79695949); + nv_icmd(dev, 0x000007de, 0xb9a99989); + nv_icmd(dev, 0x000007df, 0xf9e9d9c9); + nv_icmd(dev, 0x000007e8, 0x00003210); + nv_icmd(dev, 0x000007e9, 0x00007654); + nv_icmd(dev, 0x000007ea, 0x00000098); + nv_icmd(dev, 0x000007ec, 0x39291909); + nv_icmd(dev, 0x000007ed, 0x79695949); + nv_icmd(dev, 0x000007ee, 0xb9a99989); + nv_icmd(dev, 0x000007ef, 0xf9e9d9c9); + nv_icmd(dev, 0x000007f0, 0x00003210); + nv_icmd(dev, 0x000007f1, 0x00007654); + nv_icmd(dev, 0x000007f2, 0x00000098); + nv_icmd(dev, 0x000005a5, 0x00000001); + nv_icmd(dev, 0x00000980, 0x00000000); + nv_icmd(dev, 0x00000981, 0x00000000); + nv_icmd(dev, 0x00000982, 0x00000000); + nv_icmd(dev, 0x00000983, 0x00000000); + nv_icmd(dev, 0x00000984, 0x00000000); + nv_icmd(dev, 0x00000985, 0x00000000); + nv_icmd(dev, 0x00000986, 0x00000000); + nv_icmd(dev, 0x00000987, 0x00000000); + nv_icmd(dev, 0x00000988, 0x00000000); + nv_icmd(dev, 0x00000989, 0x00000000); + nv_icmd(dev, 0x0000098a, 0x00000000); + nv_icmd(dev, 0x0000098b, 0x00000000); + nv_icmd(dev, 0x0000098c, 0x00000000); + nv_icmd(dev, 0x0000098d, 0x00000000); + nv_icmd(dev, 0x0000098e, 0x00000000); + nv_icmd(dev, 0x0000098f, 0x00000000); + nv_icmd(dev, 0x00000990, 0x00000000); + nv_icmd(dev, 0x00000991, 0x00000000); + nv_icmd(dev, 0x00000992, 0x00000000); + nv_icmd(dev, 0x00000993, 0x00000000); + nv_icmd(dev, 0x00000994, 0x00000000); + nv_icmd(dev, 0x00000995, 0x00000000); + nv_icmd(dev, 0x00000996, 0x00000000); + nv_icmd(dev, 0x00000997, 0x00000000); + nv_icmd(dev, 0x00000998, 0x00000000); + nv_icmd(dev, 0x00000999, 0x00000000); + nv_icmd(dev, 0x0000099a, 0x00000000); + nv_icmd(dev, 0x0000099b, 0x00000000); + nv_icmd(dev, 0x0000099c, 0x00000000); + nv_icmd(dev, 0x0000099d, 0x00000000); + nv_icmd(dev, 0x0000099e, 0x00000000); + nv_icmd(dev, 0x0000099f, 0x00000000); + nv_icmd(dev, 0x000009a0, 0x00000000); + nv_icmd(dev, 0x000009a1, 0x00000000); + nv_icmd(dev, 0x000009a2, 0x00000000); + nv_icmd(dev, 0x000009a3, 0x00000000); + nv_icmd(dev, 0x000009a4, 0x00000000); + nv_icmd(dev, 0x000009a5, 0x00000000); + nv_icmd(dev, 0x000009a6, 0x00000000); + nv_icmd(dev, 0x000009a7, 0x00000000); + nv_icmd(dev, 0x000009a8, 0x00000000); + nv_icmd(dev, 0x000009a9, 0x00000000); + nv_icmd(dev, 0x000009aa, 0x00000000); + nv_icmd(dev, 0x000009ab, 0x00000000); + nv_icmd(dev, 0x000009ac, 0x00000000); + nv_icmd(dev, 0x000009ad, 0x00000000); + nv_icmd(dev, 0x000009ae, 0x00000000); + nv_icmd(dev, 0x000009af, 0x00000000); + nv_icmd(dev, 0x000009b0, 0x00000000); + nv_icmd(dev, 0x000009b1, 0x00000000); + nv_icmd(dev, 0x000009b2, 0x00000000); + nv_icmd(dev, 0x000009b3, 0x00000000); + nv_icmd(dev, 0x000009b4, 0x00000000); + nv_icmd(dev, 0x000009b5, 0x00000000); + nv_icmd(dev, 0x000009b6, 0x00000000); + nv_icmd(dev, 0x000009b7, 0x00000000); + nv_icmd(dev, 0x000009b8, 0x00000000); + nv_icmd(dev, 0x000009b9, 0x00000000); + nv_icmd(dev, 0x000009ba, 0x00000000); + nv_icmd(dev, 0x000009bb, 0x00000000); + nv_icmd(dev, 0x000009bc, 0x00000000); + nv_icmd(dev, 0x000009bd, 0x00000000); + nv_icmd(dev, 0x000009be, 0x00000000); + nv_icmd(dev, 0x000009bf, 0x00000000); + nv_icmd(dev, 0x000009c0, 0x00000000); + nv_icmd(dev, 0x000009c1, 0x00000000); + nv_icmd(dev, 0x000009c2, 0x00000000); + nv_icmd(dev, 0x000009c3, 0x00000000); + nv_icmd(dev, 0x000009c4, 0x00000000); + nv_icmd(dev, 0x000009c5, 0x00000000); + nv_icmd(dev, 0x000009c6, 0x00000000); + nv_icmd(dev, 0x000009c7, 0x00000000); + nv_icmd(dev, 0x000009c8, 0x00000000); + nv_icmd(dev, 0x000009c9, 0x00000000); + nv_icmd(dev, 0x000009ca, 0x00000000); + nv_icmd(dev, 0x000009cb, 0x00000000); + nv_icmd(dev, 0x000009cc, 0x00000000); + nv_icmd(dev, 0x000009cd, 0x00000000); + nv_icmd(dev, 0x000009ce, 0x00000000); + nv_icmd(dev, 0x000009cf, 0x00000000); + nv_icmd(dev, 0x000009d0, 0x00000000); + nv_icmd(dev, 0x000009d1, 0x00000000); + nv_icmd(dev, 0x000009d2, 0x00000000); + nv_icmd(dev, 0x000009d3, 0x00000000); + nv_icmd(dev, 0x000009d4, 0x00000000); + nv_icmd(dev, 0x000009d5, 0x00000000); + nv_icmd(dev, 0x000009d6, 0x00000000); + nv_icmd(dev, 0x000009d7, 0x00000000); + nv_icmd(dev, 0x000009d8, 0x00000000); + nv_icmd(dev, 0x000009d9, 0x00000000); + nv_icmd(dev, 0x000009da, 0x00000000); + nv_icmd(dev, 0x000009db, 0x00000000); + nv_icmd(dev, 0x000009dc, 0x00000000); + nv_icmd(dev, 0x000009dd, 0x00000000); + nv_icmd(dev, 0x000009de, 0x00000000); + nv_icmd(dev, 0x000009df, 0x00000000); + nv_icmd(dev, 0x000009e0, 0x00000000); + nv_icmd(dev, 0x000009e1, 0x00000000); + nv_icmd(dev, 0x000009e2, 0x00000000); + nv_icmd(dev, 0x000009e3, 0x00000000); + nv_icmd(dev, 0x000009e4, 0x00000000); + nv_icmd(dev, 0x000009e5, 0x00000000); + nv_icmd(dev, 0x000009e6, 0x00000000); + nv_icmd(dev, 0x000009e7, 0x00000000); + nv_icmd(dev, 0x000009e8, 0x00000000); + nv_icmd(dev, 0x000009e9, 0x00000000); + nv_icmd(dev, 0x000009ea, 0x00000000); + nv_icmd(dev, 0x000009eb, 0x00000000); + nv_icmd(dev, 0x000009ec, 0x00000000); + nv_icmd(dev, 0x000009ed, 0x00000000); + nv_icmd(dev, 0x000009ee, 0x00000000); + nv_icmd(dev, 0x000009ef, 0x00000000); + nv_icmd(dev, 0x000009f0, 0x00000000); + nv_icmd(dev, 0x000009f1, 0x00000000); + nv_icmd(dev, 0x000009f2, 0x00000000); + nv_icmd(dev, 0x000009f3, 0x00000000); + nv_icmd(dev, 0x000009f4, 0x00000000); + nv_icmd(dev, 0x000009f5, 0x00000000); + nv_icmd(dev, 0x000009f6, 0x00000000); + nv_icmd(dev, 0x000009f7, 0x00000000); + nv_icmd(dev, 0x000009f8, 0x00000000); + nv_icmd(dev, 0x000009f9, 0x00000000); + nv_icmd(dev, 0x000009fa, 0x00000000); + nv_icmd(dev, 0x000009fb, 0x00000000); + nv_icmd(dev, 0x000009fc, 0x00000000); + nv_icmd(dev, 0x000009fd, 0x00000000); + nv_icmd(dev, 0x000009fe, 0x00000000); + nv_icmd(dev, 0x000009ff, 0x00000000); + nv_icmd(dev, 0x00000468, 0x00000004); + nv_icmd(dev, 0x0000046c, 0x00000001); + nv_icmd(dev, 0x00000470, 0x00000000); + nv_icmd(dev, 0x00000471, 0x00000000); + nv_icmd(dev, 0x00000472, 0x00000000); + nv_icmd(dev, 0x00000473, 0x00000000); + nv_icmd(dev, 0x00000474, 0x00000000); + nv_icmd(dev, 0x00000475, 0x00000000); + nv_icmd(dev, 0x00000476, 0x00000000); + nv_icmd(dev, 0x00000477, 0x00000000); + nv_icmd(dev, 0x00000478, 0x00000000); + nv_icmd(dev, 0x00000479, 0x00000000); + nv_icmd(dev, 0x0000047a, 0x00000000); + nv_icmd(dev, 0x0000047b, 0x00000000); + nv_icmd(dev, 0x0000047c, 0x00000000); + nv_icmd(dev, 0x0000047d, 0x00000000); + nv_icmd(dev, 0x0000047e, 0x00000000); + nv_icmd(dev, 0x0000047f, 0x00000000); + nv_icmd(dev, 0x00000480, 0x00000000); + nv_icmd(dev, 0x00000481, 0x00000000); + nv_icmd(dev, 0x00000482, 0x00000000); + nv_icmd(dev, 0x00000483, 0x00000000); + nv_icmd(dev, 0x00000484, 0x00000000); + nv_icmd(dev, 0x00000485, 0x00000000); + nv_icmd(dev, 0x00000486, 0x00000000); + nv_icmd(dev, 0x00000487, 0x00000000); + nv_icmd(dev, 0x00000488, 0x00000000); + nv_icmd(dev, 0x00000489, 0x00000000); + nv_icmd(dev, 0x0000048a, 0x00000000); + nv_icmd(dev, 0x0000048b, 0x00000000); + nv_icmd(dev, 0x0000048c, 0x00000000); + nv_icmd(dev, 0x0000048d, 0x00000000); + nv_icmd(dev, 0x0000048e, 0x00000000); + nv_icmd(dev, 0x0000048f, 0x00000000); + nv_icmd(dev, 0x00000490, 0x00000000); + nv_icmd(dev, 0x00000491, 0x00000000); + nv_icmd(dev, 0x00000492, 0x00000000); + nv_icmd(dev, 0x00000493, 0x00000000); + nv_icmd(dev, 0x00000494, 0x00000000); + nv_icmd(dev, 0x00000495, 0x00000000); + nv_icmd(dev, 0x00000496, 0x00000000); + nv_icmd(dev, 0x00000497, 0x00000000); + nv_icmd(dev, 0x00000498, 0x00000000); + nv_icmd(dev, 0x00000499, 0x00000000); + nv_icmd(dev, 0x0000049a, 0x00000000); + nv_icmd(dev, 0x0000049b, 0x00000000); + nv_icmd(dev, 0x0000049c, 0x00000000); + nv_icmd(dev, 0x0000049d, 0x00000000); + nv_icmd(dev, 0x0000049e, 0x00000000); + nv_icmd(dev, 0x0000049f, 0x00000000); + nv_icmd(dev, 0x000004a0, 0x00000000); + nv_icmd(dev, 0x000004a1, 0x00000000); + nv_icmd(dev, 0x000004a2, 0x00000000); + nv_icmd(dev, 0x000004a3, 0x00000000); + nv_icmd(dev, 0x000004a4, 0x00000000); + nv_icmd(dev, 0x000004a5, 0x00000000); + nv_icmd(dev, 0x000004a6, 0x00000000); + nv_icmd(dev, 0x000004a7, 0x00000000); + nv_icmd(dev, 0x000004a8, 0x00000000); + nv_icmd(dev, 0x000004a9, 0x00000000); + nv_icmd(dev, 0x000004aa, 0x00000000); + nv_icmd(dev, 0x000004ab, 0x00000000); + nv_icmd(dev, 0x000004ac, 0x00000000); + nv_icmd(dev, 0x000004ad, 0x00000000); + nv_icmd(dev, 0x000004ae, 0x00000000); + nv_icmd(dev, 0x000004af, 0x00000000); + nv_icmd(dev, 0x000004b0, 0x00000000); + nv_icmd(dev, 0x000004b1, 0x00000000); + nv_icmd(dev, 0x000004b2, 0x00000000); + nv_icmd(dev, 0x000004b3, 0x00000000); + nv_icmd(dev, 0x000004b4, 0x00000000); + nv_icmd(dev, 0x000004b5, 0x00000000); + nv_icmd(dev, 0x000004b6, 0x00000000); + nv_icmd(dev, 0x000004b7, 0x00000000); + nv_icmd(dev, 0x000004b8, 0x00000000); + nv_icmd(dev, 0x000004b9, 0x00000000); + nv_icmd(dev, 0x000004ba, 0x00000000); + nv_icmd(dev, 0x000004bb, 0x00000000); + nv_icmd(dev, 0x000004bc, 0x00000000); + nv_icmd(dev, 0x000004bd, 0x00000000); + nv_icmd(dev, 0x000004be, 0x00000000); + nv_icmd(dev, 0x000004bf, 0x00000000); + nv_icmd(dev, 0x000004c0, 0x00000000); + nv_icmd(dev, 0x000004c1, 0x00000000); + nv_icmd(dev, 0x000004c2, 0x00000000); + nv_icmd(dev, 0x000004c3, 0x00000000); + nv_icmd(dev, 0x000004c4, 0x00000000); + nv_icmd(dev, 0x000004c5, 0x00000000); + nv_icmd(dev, 0x000004c6, 0x00000000); + nv_icmd(dev, 0x000004c7, 0x00000000); + nv_icmd(dev, 0x000004c8, 0x00000000); + nv_icmd(dev, 0x000004c9, 0x00000000); + nv_icmd(dev, 0x000004ca, 0x00000000); + nv_icmd(dev, 0x000004cb, 0x00000000); + nv_icmd(dev, 0x000004cc, 0x00000000); + nv_icmd(dev, 0x000004cd, 0x00000000); + nv_icmd(dev, 0x000004ce, 0x00000000); + nv_icmd(dev, 0x000004cf, 0x00000000); + nv_icmd(dev, 0x00000510, 0x3f800000); + nv_icmd(dev, 0x00000511, 0x3f800000); + nv_icmd(dev, 0x00000512, 0x3f800000); + nv_icmd(dev, 0x00000513, 0x3f800000); + nv_icmd(dev, 0x00000514, 0x3f800000); + nv_icmd(dev, 0x00000515, 0x3f800000); + nv_icmd(dev, 0x00000516, 0x3f800000); + nv_icmd(dev, 0x00000517, 0x3f800000); + nv_icmd(dev, 0x00000518, 0x3f800000); + nv_icmd(dev, 0x00000519, 0x3f800000); + nv_icmd(dev, 0x0000051a, 0x3f800000); + nv_icmd(dev, 0x0000051b, 0x3f800000); + nv_icmd(dev, 0x0000051c, 0x3f800000); + nv_icmd(dev, 0x0000051d, 0x3f800000); + nv_icmd(dev, 0x0000051e, 0x3f800000); + nv_icmd(dev, 0x0000051f, 0x3f800000); + nv_icmd(dev, 0x00000520, 0x000002b6); + nv_icmd(dev, 0x00000529, 0x00000001); + nv_icmd(dev, 0x00000530, 0xffff0000); + nv_icmd(dev, 0x00000531, 0xffff0000); + nv_icmd(dev, 0x00000532, 0xffff0000); + nv_icmd(dev, 0x00000533, 0xffff0000); + nv_icmd(dev, 0x00000534, 0xffff0000); + nv_icmd(dev, 0x00000535, 0xffff0000); + nv_icmd(dev, 0x00000536, 0xffff0000); + nv_icmd(dev, 0x00000537, 0xffff0000); + nv_icmd(dev, 0x00000538, 0xffff0000); + nv_icmd(dev, 0x00000539, 0xffff0000); + nv_icmd(dev, 0x0000053a, 0xffff0000); + nv_icmd(dev, 0x0000053b, 0xffff0000); + nv_icmd(dev, 0x0000053c, 0xffff0000); + nv_icmd(dev, 0x0000053d, 0xffff0000); + nv_icmd(dev, 0x0000053e, 0xffff0000); + nv_icmd(dev, 0x0000053f, 0xffff0000); + nv_icmd(dev, 0x00000585, 0x0000003f); + nv_icmd(dev, 0x00000576, 0x00000003); + if (dev_priv->chipset == 0xc1 || + dev_priv->chipset == 0xd9) + nv_icmd(dev, 0x0000057b, 0x00000059); + nv_icmd(dev, 0x00000586, 0x00000040); + nv_icmd(dev, 0x00000582, 0x00000080); + nv_icmd(dev, 0x00000583, 0x00000080); + nv_icmd(dev, 0x000005c2, 0x00000001); + nv_icmd(dev, 0x00000638, 0x00000001); + nv_icmd(dev, 0x00000639, 0x00000001); + nv_icmd(dev, 0x0000063a, 0x00000002); + nv_icmd(dev, 0x0000063b, 0x00000001); + nv_icmd(dev, 0x0000063c, 0x00000001); + nv_icmd(dev, 0x0000063d, 0x00000002); + nv_icmd(dev, 0x0000063e, 0x00000001); + nv_icmd(dev, 0x000008b8, 0x00000001); + nv_icmd(dev, 0x000008b9, 0x00000001); + nv_icmd(dev, 0x000008ba, 0x00000001); + nv_icmd(dev, 0x000008bb, 0x00000001); + nv_icmd(dev, 0x000008bc, 0x00000001); + nv_icmd(dev, 0x000008bd, 0x00000001); + nv_icmd(dev, 0x000008be, 0x00000001); + nv_icmd(dev, 0x000008bf, 0x00000001); + nv_icmd(dev, 0x00000900, 0x00000001); + nv_icmd(dev, 0x00000901, 0x00000001); + nv_icmd(dev, 0x00000902, 0x00000001); + nv_icmd(dev, 0x00000903, 0x00000001); + nv_icmd(dev, 0x00000904, 0x00000001); + nv_icmd(dev, 0x00000905, 0x00000001); + nv_icmd(dev, 0x00000906, 0x00000001); + nv_icmd(dev, 0x00000907, 0x00000001); + nv_icmd(dev, 0x00000908, 0x00000002); + nv_icmd(dev, 0x00000909, 0x00000002); + nv_icmd(dev, 0x0000090a, 0x00000002); + nv_icmd(dev, 0x0000090b, 0x00000002); + nv_icmd(dev, 0x0000090c, 0x00000002); + nv_icmd(dev, 0x0000090d, 0x00000002); + nv_icmd(dev, 0x0000090e, 0x00000002); + nv_icmd(dev, 0x0000090f, 0x00000002); + nv_icmd(dev, 0x00000910, 0x00000001); + nv_icmd(dev, 0x00000911, 0x00000001); + nv_icmd(dev, 0x00000912, 0x00000001); + nv_icmd(dev, 0x00000913, 0x00000001); + nv_icmd(dev, 0x00000914, 0x00000001); + nv_icmd(dev, 0x00000915, 0x00000001); + nv_icmd(dev, 0x00000916, 0x00000001); + nv_icmd(dev, 0x00000917, 0x00000001); + nv_icmd(dev, 0x00000918, 0x00000001); + nv_icmd(dev, 0x00000919, 0x00000001); + nv_icmd(dev, 0x0000091a, 0x00000001); + nv_icmd(dev, 0x0000091b, 0x00000001); + nv_icmd(dev, 0x0000091c, 0x00000001); + nv_icmd(dev, 0x0000091d, 0x00000001); + nv_icmd(dev, 0x0000091e, 0x00000001); + nv_icmd(dev, 0x0000091f, 0x00000001); + nv_icmd(dev, 0x00000920, 0x00000002); + nv_icmd(dev, 0x00000921, 0x00000002); + nv_icmd(dev, 0x00000922, 0x00000002); + nv_icmd(dev, 0x00000923, 0x00000002); + nv_icmd(dev, 0x00000924, 0x00000002); + nv_icmd(dev, 0x00000925, 0x00000002); + nv_icmd(dev, 0x00000926, 0x00000002); + nv_icmd(dev, 0x00000927, 0x00000002); + nv_icmd(dev, 0x00000928, 0x00000001); + nv_icmd(dev, 0x00000929, 0x00000001); + nv_icmd(dev, 0x0000092a, 0x00000001); + nv_icmd(dev, 0x0000092b, 0x00000001); + nv_icmd(dev, 0x0000092c, 0x00000001); + nv_icmd(dev, 0x0000092d, 0x00000001); + nv_icmd(dev, 0x0000092e, 0x00000001); + nv_icmd(dev, 0x0000092f, 0x00000001); + nv_icmd(dev, 0x00000648, 0x00000001); + nv_icmd(dev, 0x00000649, 0x00000001); + nv_icmd(dev, 0x0000064a, 0x00000001); + nv_icmd(dev, 0x0000064b, 0x00000001); + nv_icmd(dev, 0x0000064c, 0x00000001); + nv_icmd(dev, 0x0000064d, 0x00000001); + nv_icmd(dev, 0x0000064e, 0x00000001); + nv_icmd(dev, 0x0000064f, 0x00000001); + nv_icmd(dev, 0x00000650, 0x00000001); + nv_icmd(dev, 0x00000658, 0x0000000f); + nv_icmd(dev, 0x000007ff, 0x0000000a); + nv_icmd(dev, 0x0000066a, 0x40000000); + nv_icmd(dev, 0x0000066b, 0x10000000); + nv_icmd(dev, 0x0000066c, 0xffff0000); + nv_icmd(dev, 0x0000066d, 0xffff0000); + nv_icmd(dev, 0x000007af, 0x00000008); + nv_icmd(dev, 0x000007b0, 0x00000008); + nv_icmd(dev, 0x000007f6, 0x00000001); + nv_icmd(dev, 0x000006b2, 0x00000055); + nv_icmd(dev, 0x000007ad, 0x00000003); + nv_icmd(dev, 0x00000937, 0x00000001); + nv_icmd(dev, 0x00000971, 0x00000008); + nv_icmd(dev, 0x00000972, 0x00000040); + nv_icmd(dev, 0x00000973, 0x0000012c); + nv_icmd(dev, 0x0000097c, 0x00000040); + nv_icmd(dev, 0x00000979, 0x00000003); + nv_icmd(dev, 0x00000975, 0x00000020); + nv_icmd(dev, 0x00000976, 0x00000001); + nv_icmd(dev, 0x00000977, 0x00000020); + nv_icmd(dev, 0x00000978, 0x00000001); + nv_icmd(dev, 0x00000957, 0x00000003); + nv_icmd(dev, 0x0000095e, 0x20164010); + nv_icmd(dev, 0x0000095f, 0x00000020); + if (dev_priv->chipset == 0xd9) + nv_icmd(dev, 0x0000097d, 0x00000020); + nv_icmd(dev, 0x00000683, 0x00000006); + nv_icmd(dev, 0x00000685, 0x003fffff); + nv_icmd(dev, 0x00000687, 0x00000c48); + nv_icmd(dev, 0x000006a0, 0x00000005); + nv_icmd(dev, 0x00000840, 0x00300008); + nv_icmd(dev, 0x00000841, 0x04000080); + nv_icmd(dev, 0x00000842, 0x00300008); + nv_icmd(dev, 0x00000843, 0x04000080); + nv_icmd(dev, 0x00000818, 0x00000000); + nv_icmd(dev, 0x00000819, 0x00000000); + nv_icmd(dev, 0x0000081a, 0x00000000); + nv_icmd(dev, 0x0000081b, 0x00000000); + nv_icmd(dev, 0x0000081c, 0x00000000); + nv_icmd(dev, 0x0000081d, 0x00000000); + nv_icmd(dev, 0x0000081e, 0x00000000); + nv_icmd(dev, 0x0000081f, 0x00000000); + nv_icmd(dev, 0x00000848, 0x00000000); + nv_icmd(dev, 0x00000849, 0x00000000); + nv_icmd(dev, 0x0000084a, 0x00000000); + nv_icmd(dev, 0x0000084b, 0x00000000); + nv_icmd(dev, 0x0000084c, 0x00000000); + nv_icmd(dev, 0x0000084d, 0x00000000); + nv_icmd(dev, 0x0000084e, 0x00000000); + nv_icmd(dev, 0x0000084f, 0x00000000); + nv_icmd(dev, 0x00000850, 0x00000000); + nv_icmd(dev, 0x00000851, 0x00000000); + nv_icmd(dev, 0x00000852, 0x00000000); + nv_icmd(dev, 0x00000853, 0x00000000); + nv_icmd(dev, 0x00000854, 0x00000000); + nv_icmd(dev, 0x00000855, 0x00000000); + nv_icmd(dev, 0x00000856, 0x00000000); + nv_icmd(dev, 0x00000857, 0x00000000); + nv_icmd(dev, 0x00000738, 0x00000000); + nv_icmd(dev, 0x000006aa, 0x00000001); + nv_icmd(dev, 0x000006ab, 0x00000002); + nv_icmd(dev, 0x000006ac, 0x00000080); + nv_icmd(dev, 0x000006ad, 0x00000100); + nv_icmd(dev, 0x000006ae, 0x00000100); + nv_icmd(dev, 0x000006b1, 0x00000011); + nv_icmd(dev, 0x000006bb, 0x000000cf); + nv_icmd(dev, 0x000006ce, 0x2a712488); + nv_icmd(dev, 0x00000739, 0x4085c000); + nv_icmd(dev, 0x0000073a, 0x00000080); + nv_icmd(dev, 0x00000786, 0x80000100); + nv_icmd(dev, 0x0000073c, 0x00010100); + nv_icmd(dev, 0x0000073d, 0x02800000); + nv_icmd(dev, 0x00000787, 0x000000cf); + nv_icmd(dev, 0x0000078c, 0x00000008); + nv_icmd(dev, 0x00000792, 0x00000001); + nv_icmd(dev, 0x00000794, 0x00000001); + nv_icmd(dev, 0x00000795, 0x00000001); + nv_icmd(dev, 0x00000796, 0x00000001); + nv_icmd(dev, 0x00000797, 0x000000cf); + nv_icmd(dev, 0x00000836, 0x00000001); + nv_icmd(dev, 0x0000079a, 0x00000002); + nv_icmd(dev, 0x00000833, 0x04444480); + nv_icmd(dev, 0x000007a1, 0x00000001); + nv_icmd(dev, 0x000007a3, 0x00000001); + nv_icmd(dev, 0x000007a4, 0x00000001); + nv_icmd(dev, 0x000007a5, 0x00000001); + nv_icmd(dev, 0x00000831, 0x00000004); + nv_icmd(dev, 0x0000080c, 0x00000002); + nv_icmd(dev, 0x0000080d, 0x00000100); + nv_icmd(dev, 0x0000080e, 0x00000100); + nv_icmd(dev, 0x0000080f, 0x00000001); + nv_icmd(dev, 0x00000823, 0x00000002); + nv_icmd(dev, 0x00000824, 0x00000100); + nv_icmd(dev, 0x00000825, 0x00000100); + nv_icmd(dev, 0x00000826, 0x00000001); + nv_icmd(dev, 0x0000095d, 0x00000001); + nv_icmd(dev, 0x0000082b, 0x00000004); + nv_icmd(dev, 0x00000942, 0x00010001); + nv_icmd(dev, 0x00000943, 0x00000001); + nv_icmd(dev, 0x00000944, 0x00000022); + nv_icmd(dev, 0x000007c5, 0x00010001); + nv_icmd(dev, 0x00000834, 0x00000001); + nv_icmd(dev, 0x000007c7, 0x00000001); + nv_icmd(dev, 0x0000c1b0, 0x0000000f); + nv_icmd(dev, 0x0000c1b1, 0x0000000f); + nv_icmd(dev, 0x0000c1b2, 0x0000000f); + nv_icmd(dev, 0x0000c1b3, 0x0000000f); + nv_icmd(dev, 0x0000c1b4, 0x0000000f); + nv_icmd(dev, 0x0000c1b5, 0x0000000f); + nv_icmd(dev, 0x0000c1b6, 0x0000000f); + nv_icmd(dev, 0x0000c1b7, 0x0000000f); + nv_icmd(dev, 0x0000c1b8, 0x0fac6881); + nv_icmd(dev, 0x0000c1b9, 0x00fac688); + nv_icmd(dev, 0x0001e100, 0x00000001); + nv_icmd(dev, 0x00001000, 0x00000002); + nv_icmd(dev, 0x000006aa, 0x00000001); + nv_icmd(dev, 0x000006ad, 0x00000100); + nv_icmd(dev, 0x000006ae, 0x00000100); + nv_icmd(dev, 0x000006b1, 0x00000011); + nv_icmd(dev, 0x0000078c, 0x00000008); + nv_icmd(dev, 0x00000792, 0x00000001); + nv_icmd(dev, 0x00000794, 0x00000001); + nv_icmd(dev, 0x00000795, 0x00000001); + nv_icmd(dev, 0x00000796, 0x00000001); + nv_icmd(dev, 0x00000797, 0x000000cf); + nv_icmd(dev, 0x0000079a, 0x00000002); + nv_icmd(dev, 0x00000833, 0x04444480); + nv_icmd(dev, 0x000007a1, 0x00000001); + nv_icmd(dev, 0x000007a3, 0x00000001); + nv_icmd(dev, 0x000007a4, 0x00000001); + nv_icmd(dev, 0x000007a5, 0x00000001); + nv_icmd(dev, 0x00000831, 0x00000004); + nv_icmd(dev, 0x0001e100, 0x00000001); + nv_icmd(dev, 0x00001000, 0x00000014); + nv_icmd(dev, 0x00000351, 0x00000100); + nv_icmd(dev, 0x00000957, 0x00000003); + nv_icmd(dev, 0x0000095d, 0x00000001); + nv_icmd(dev, 0x0000082b, 0x00000004); + nv_icmd(dev, 0x00000942, 0x00010001); + nv_icmd(dev, 0x00000943, 0x00000001); + nv_icmd(dev, 0x000007c5, 0x00010001); + nv_icmd(dev, 0x00000834, 0x00000001); + nv_icmd(dev, 0x000007c7, 0x00000001); + nv_icmd(dev, 0x0001e100, 0x00000001); + nv_icmd(dev, 0x00001000, 0x00000001); + nv_icmd(dev, 0x0000080c, 0x00000002); + nv_icmd(dev, 0x0000080d, 0x00000100); + nv_icmd(dev, 0x0000080e, 0x00000100); + nv_icmd(dev, 0x0000080f, 0x00000001); + nv_icmd(dev, 0x00000823, 0x00000002); + nv_icmd(dev, 0x00000824, 0x00000100); + nv_icmd(dev, 0x00000825, 0x00000100); + nv_icmd(dev, 0x00000826, 0x00000001); + nv_icmd(dev, 0x0001e100, 0x00000001); + nv_wr32(dev, 0x400208, 0x00000000); + nv_wr32(dev, 0x404154, 0x00000400); + + nvc0_grctx_generate_9097(dev); + if (fermi >= 0x9197) + nvc0_grctx_generate_9197(dev); + if (fermi >= 0x9297) + nvc0_grctx_generate_9297(dev); + nvc0_grctx_generate_902d(dev); + nvc0_grctx_generate_9039(dev); + nvc0_grctx_generate_90c0(dev); + + nv_wr32(dev, 0x000260, r000260); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c new file mode 100644 index 0000000..bd40bd9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -0,0 +1,2777 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include +#include "nve0.h" + +static void +nv_icmd(struct drm_device *dev, u32 icmd, u32 data) +{ + nv_wr32(dev, 0x400204, data); + nv_wr32(dev, 0x400200, icmd); + while (nv_rd32(dev, 0x400700) & 0x00000002) {} +} + +static void +nve0_grctx_generate_icmd(struct drm_device *dev) +{ + nv_wr32(dev, 0x400208, 0x80000000); + nv_icmd(dev, 0x001000, 0x00000004); + nv_icmd(dev, 0x000039, 0x00000000); + nv_icmd(dev, 0x00003a, 0x00000000); + nv_icmd(dev, 0x00003b, 0x00000000); + nv_icmd(dev, 0x0000a9, 0x0000ffff); + nv_icmd(dev, 0x000038, 0x0fac6881); + nv_icmd(dev, 0x00003d, 0x00000001); + nv_icmd(dev, 0x0000e8, 0x00000400); + nv_icmd(dev, 0x0000e9, 0x00000400); + nv_icmd(dev, 0x0000ea, 0x00000400); + nv_icmd(dev, 0x0000eb, 0x00000400); + nv_icmd(dev, 0x0000ec, 0x00000400); + nv_icmd(dev, 0x0000ed, 0x00000400); + nv_icmd(dev, 0x0000ee, 0x00000400); + nv_icmd(dev, 0x0000ef, 0x00000400); + nv_icmd(dev, 0x000078, 0x00000300); + nv_icmd(dev, 0x000079, 0x00000300); + nv_icmd(dev, 0x00007a, 0x00000300); + nv_icmd(dev, 0x00007b, 0x00000300); + nv_icmd(dev, 0x00007c, 0x00000300); + nv_icmd(dev, 0x00007d, 0x00000300); + nv_icmd(dev, 0x00007e, 0x00000300); + nv_icmd(dev, 0x00007f, 0x00000300); + nv_icmd(dev, 0x000050, 0x00000011); + nv_icmd(dev, 0x000058, 0x00000008); + nv_icmd(dev, 0x000059, 0x00000008); + nv_icmd(dev, 0x00005a, 0x00000008); + nv_icmd(dev, 0x00005b, 0x00000008); + nv_icmd(dev, 0x00005c, 0x00000008); + nv_icmd(dev, 0x00005d, 0x00000008); + nv_icmd(dev, 0x00005e, 0x00000008); + nv_icmd(dev, 0x00005f, 0x00000008); + nv_icmd(dev, 0x000208, 0x00000001); + nv_icmd(dev, 0x000209, 0x00000001); + nv_icmd(dev, 0x00020a, 0x00000001); + nv_icmd(dev, 0x00020b, 0x00000001); + nv_icmd(dev, 0x00020c, 0x00000001); + nv_icmd(dev, 0x00020d, 0x00000001); + nv_icmd(dev, 0x00020e, 0x00000001); + nv_icmd(dev, 0x00020f, 0x00000001); + nv_icmd(dev, 0x000081, 0x00000001); + nv_icmd(dev, 0x000085, 0x00000004); + nv_icmd(dev, 0x000088, 0x00000400); + nv_icmd(dev, 0x000090, 0x00000300); + nv_icmd(dev, 0x000098, 0x00001001); + nv_icmd(dev, 0x0000e3, 0x00000001); + nv_icmd(dev, 0x0000da, 0x00000001); + nv_icmd(dev, 0x0000f8, 0x00000003); + nv_icmd(dev, 0x0000fa, 0x00000001); + nv_icmd(dev, 0x00009f, 0x0000ffff); + nv_icmd(dev, 0x0000a0, 0x0000ffff); + nv_icmd(dev, 0x0000a1, 0x0000ffff); + nv_icmd(dev, 0x0000a2, 0x0000ffff); + nv_icmd(dev, 0x0000b1, 0x00000001); + nv_icmd(dev, 0x0000ad, 0x0000013e); + nv_icmd(dev, 0x0000e1, 0x00000010); + nv_icmd(dev, 0x000290, 0x00000000); + nv_icmd(dev, 0x000291, 0x00000000); + nv_icmd(dev, 0x000292, 0x00000000); + nv_icmd(dev, 0x000293, 0x00000000); + nv_icmd(dev, 0x000294, 0x00000000); + nv_icmd(dev, 0x000295, 0x00000000); + nv_icmd(dev, 0x000296, 0x00000000); + nv_icmd(dev, 0x000297, 0x00000000); + nv_icmd(dev, 0x000298, 0x00000000); + nv_icmd(dev, 0x000299, 0x00000000); + nv_icmd(dev, 0x00029a, 0x00000000); + nv_icmd(dev, 0x00029b, 0x00000000); + nv_icmd(dev, 0x00029c, 0x00000000); + nv_icmd(dev, 0x00029d, 0x00000000); + nv_icmd(dev, 0x00029e, 0x00000000); + nv_icmd(dev, 0x00029f, 0x00000000); + nv_icmd(dev, 0x0003b0, 0x00000000); + nv_icmd(dev, 0x0003b1, 0x00000000); + nv_icmd(dev, 0x0003b2, 0x00000000); + nv_icmd(dev, 0x0003b3, 0x00000000); + nv_icmd(dev, 0x0003b4, 0x00000000); + nv_icmd(dev, 0x0003b5, 0x00000000); + nv_icmd(dev, 0x0003b6, 0x00000000); + nv_icmd(dev, 0x0003b7, 0x00000000); + nv_icmd(dev, 0x0003b8, 0x00000000); + nv_icmd(dev, 0x0003b9, 0x00000000); + nv_icmd(dev, 0x0003ba, 0x00000000); + nv_icmd(dev, 0x0003bb, 0x00000000); + nv_icmd(dev, 0x0003bc, 0x00000000); + nv_icmd(dev, 0x0003bd, 0x00000000); + nv_icmd(dev, 0x0003be, 0x00000000); + nv_icmd(dev, 0x0003bf, 0x00000000); + nv_icmd(dev, 0x0002a0, 0x00000000); + nv_icmd(dev, 0x0002a1, 0x00000000); + nv_icmd(dev, 0x0002a2, 0x00000000); + nv_icmd(dev, 0x0002a3, 0x00000000); + nv_icmd(dev, 0x0002a4, 0x00000000); + nv_icmd(dev, 0x0002a5, 0x00000000); + nv_icmd(dev, 0x0002a6, 0x00000000); + nv_icmd(dev, 0x0002a7, 0x00000000); + nv_icmd(dev, 0x0002a8, 0x00000000); + nv_icmd(dev, 0x0002a9, 0x00000000); + nv_icmd(dev, 0x0002aa, 0x00000000); + nv_icmd(dev, 0x0002ab, 0x00000000); + nv_icmd(dev, 0x0002ac, 0x00000000); + nv_icmd(dev, 0x0002ad, 0x00000000); + nv_icmd(dev, 0x0002ae, 0x00000000); + nv_icmd(dev, 0x0002af, 0x00000000); + nv_icmd(dev, 0x000420, 0x00000000); + nv_icmd(dev, 0x000421, 0x00000000); + nv_icmd(dev, 0x000422, 0x00000000); + nv_icmd(dev, 0x000423, 0x00000000); + nv_icmd(dev, 0x000424, 0x00000000); + nv_icmd(dev, 0x000425, 0x00000000); + nv_icmd(dev, 0x000426, 0x00000000); + nv_icmd(dev, 0x000427, 0x00000000); + nv_icmd(dev, 0x000428, 0x00000000); + nv_icmd(dev, 0x000429, 0x00000000); + nv_icmd(dev, 0x00042a, 0x00000000); + nv_icmd(dev, 0x00042b, 0x00000000); + nv_icmd(dev, 0x00042c, 0x00000000); + nv_icmd(dev, 0x00042d, 0x00000000); + nv_icmd(dev, 0x00042e, 0x00000000); + nv_icmd(dev, 0x00042f, 0x00000000); + nv_icmd(dev, 0x0002b0, 0x00000000); + nv_icmd(dev, 0x0002b1, 0x00000000); + nv_icmd(dev, 0x0002b2, 0x00000000); + nv_icmd(dev, 0x0002b3, 0x00000000); + nv_icmd(dev, 0x0002b4, 0x00000000); + nv_icmd(dev, 0x0002b5, 0x00000000); + nv_icmd(dev, 0x0002b6, 0x00000000); + nv_icmd(dev, 0x0002b7, 0x00000000); + nv_icmd(dev, 0x0002b8, 0x00000000); + nv_icmd(dev, 0x0002b9, 0x00000000); + nv_icmd(dev, 0x0002ba, 0x00000000); + nv_icmd(dev, 0x0002bb, 0x00000000); + nv_icmd(dev, 0x0002bc, 0x00000000); + nv_icmd(dev, 0x0002bd, 0x00000000); + nv_icmd(dev, 0x0002be, 0x00000000); + nv_icmd(dev, 0x0002bf, 0x00000000); + nv_icmd(dev, 0x000430, 0x00000000); + nv_icmd(dev, 0x000431, 0x00000000); + nv_icmd(dev, 0x000432, 0x00000000); + nv_icmd(dev, 0x000433, 0x00000000); + nv_icmd(dev, 0x000434, 0x00000000); + nv_icmd(dev, 0x000435, 0x00000000); + nv_icmd(dev, 0x000436, 0x00000000); + nv_icmd(dev, 0x000437, 0x00000000); + nv_icmd(dev, 0x000438, 0x00000000); + nv_icmd(dev, 0x000439, 0x00000000); + nv_icmd(dev, 0x00043a, 0x00000000); + nv_icmd(dev, 0x00043b, 0x00000000); + nv_icmd(dev, 0x00043c, 0x00000000); + nv_icmd(dev, 0x00043d, 0x00000000); + nv_icmd(dev, 0x00043e, 0x00000000); + nv_icmd(dev, 0x00043f, 0x00000000); + nv_icmd(dev, 0x0002c0, 0x00000000); + nv_icmd(dev, 0x0002c1, 0x00000000); + nv_icmd(dev, 0x0002c2, 0x00000000); + nv_icmd(dev, 0x0002c3, 0x00000000); + nv_icmd(dev, 0x0002c4, 0x00000000); + nv_icmd(dev, 0x0002c5, 0x00000000); + nv_icmd(dev, 0x0002c6, 0x00000000); + nv_icmd(dev, 0x0002c7, 0x00000000); + nv_icmd(dev, 0x0002c8, 0x00000000); + nv_icmd(dev, 0x0002c9, 0x00000000); + nv_icmd(dev, 0x0002ca, 0x00000000); + nv_icmd(dev, 0x0002cb, 0x00000000); + nv_icmd(dev, 0x0002cc, 0x00000000); + nv_icmd(dev, 0x0002cd, 0x00000000); + nv_icmd(dev, 0x0002ce, 0x00000000); + nv_icmd(dev, 0x0002cf, 0x00000000); + nv_icmd(dev, 0x0004d0, 0x00000000); + nv_icmd(dev, 0x0004d1, 0x00000000); + nv_icmd(dev, 0x0004d2, 0x00000000); + nv_icmd(dev, 0x0004d3, 0x00000000); + nv_icmd(dev, 0x0004d4, 0x00000000); + nv_icmd(dev, 0x0004d5, 0x00000000); + nv_icmd(dev, 0x0004d6, 0x00000000); + nv_icmd(dev, 0x0004d7, 0x00000000); + nv_icmd(dev, 0x0004d8, 0x00000000); + nv_icmd(dev, 0x0004d9, 0x00000000); + nv_icmd(dev, 0x0004da, 0x00000000); + nv_icmd(dev, 0x0004db, 0x00000000); + nv_icmd(dev, 0x0004dc, 0x00000000); + nv_icmd(dev, 0x0004dd, 0x00000000); + nv_icmd(dev, 0x0004de, 0x00000000); + nv_icmd(dev, 0x0004df, 0x00000000); + nv_icmd(dev, 0x000720, 0x00000000); + nv_icmd(dev, 0x000721, 0x00000000); + nv_icmd(dev, 0x000722, 0x00000000); + nv_icmd(dev, 0x000723, 0x00000000); + nv_icmd(dev, 0x000724, 0x00000000); + nv_icmd(dev, 0x000725, 0x00000000); + nv_icmd(dev, 0x000726, 0x00000000); + nv_icmd(dev, 0x000727, 0x00000000); + nv_icmd(dev, 0x000728, 0x00000000); + nv_icmd(dev, 0x000729, 0x00000000); + nv_icmd(dev, 0x00072a, 0x00000000); + nv_icmd(dev, 0x00072b, 0x00000000); + nv_icmd(dev, 0x00072c, 0x00000000); + nv_icmd(dev, 0x00072d, 0x00000000); + nv_icmd(dev, 0x00072e, 0x00000000); + nv_icmd(dev, 0x00072f, 0x00000000); + nv_icmd(dev, 0x0008c0, 0x00000000); + nv_icmd(dev, 0x0008c1, 0x00000000); + nv_icmd(dev, 0x0008c2, 0x00000000); + nv_icmd(dev, 0x0008c3, 0x00000000); + nv_icmd(dev, 0x0008c4, 0x00000000); + nv_icmd(dev, 0x0008c5, 0x00000000); + nv_icmd(dev, 0x0008c6, 0x00000000); + nv_icmd(dev, 0x0008c7, 0x00000000); + nv_icmd(dev, 0x0008c8, 0x00000000); + nv_icmd(dev, 0x0008c9, 0x00000000); + nv_icmd(dev, 0x0008ca, 0x00000000); + nv_icmd(dev, 0x0008cb, 0x00000000); + nv_icmd(dev, 0x0008cc, 0x00000000); + nv_icmd(dev, 0x0008cd, 0x00000000); + nv_icmd(dev, 0x0008ce, 0x00000000); + nv_icmd(dev, 0x0008cf, 0x00000000); + nv_icmd(dev, 0x000890, 0x00000000); + nv_icmd(dev, 0x000891, 0x00000000); + nv_icmd(dev, 0x000892, 0x00000000); + nv_icmd(dev, 0x000893, 0x00000000); + nv_icmd(dev, 0x000894, 0x00000000); + nv_icmd(dev, 0x000895, 0x00000000); + nv_icmd(dev, 0x000896, 0x00000000); + nv_icmd(dev, 0x000897, 0x00000000); + nv_icmd(dev, 0x000898, 0x00000000); + nv_icmd(dev, 0x000899, 0x00000000); + nv_icmd(dev, 0x00089a, 0x00000000); + nv_icmd(dev, 0x00089b, 0x00000000); + nv_icmd(dev, 0x00089c, 0x00000000); + nv_icmd(dev, 0x00089d, 0x00000000); + nv_icmd(dev, 0x00089e, 0x00000000); + nv_icmd(dev, 0x00089f, 0x00000000); + nv_icmd(dev, 0x0008e0, 0x00000000); + nv_icmd(dev, 0x0008e1, 0x00000000); + nv_icmd(dev, 0x0008e2, 0x00000000); + nv_icmd(dev, 0x0008e3, 0x00000000); + nv_icmd(dev, 0x0008e4, 0x00000000); + nv_icmd(dev, 0x0008e5, 0x00000000); + nv_icmd(dev, 0x0008e6, 0x00000000); + nv_icmd(dev, 0x0008e7, 0x00000000); + nv_icmd(dev, 0x0008e8, 0x00000000); + nv_icmd(dev, 0x0008e9, 0x00000000); + nv_icmd(dev, 0x0008ea, 0x00000000); + nv_icmd(dev, 0x0008eb, 0x00000000); + nv_icmd(dev, 0x0008ec, 0x00000000); + nv_icmd(dev, 0x0008ed, 0x00000000); + nv_icmd(dev, 0x0008ee, 0x00000000); + nv_icmd(dev, 0x0008ef, 0x00000000); + nv_icmd(dev, 0x0008a0, 0x00000000); + nv_icmd(dev, 0x0008a1, 0x00000000); + nv_icmd(dev, 0x0008a2, 0x00000000); + nv_icmd(dev, 0x0008a3, 0x00000000); + nv_icmd(dev, 0x0008a4, 0x00000000); + nv_icmd(dev, 0x0008a5, 0x00000000); + nv_icmd(dev, 0x0008a6, 0x00000000); + nv_icmd(dev, 0x0008a7, 0x00000000); + nv_icmd(dev, 0x0008a8, 0x00000000); + nv_icmd(dev, 0x0008a9, 0x00000000); + nv_icmd(dev, 0x0008aa, 0x00000000); + nv_icmd(dev, 0x0008ab, 0x00000000); + nv_icmd(dev, 0x0008ac, 0x00000000); + nv_icmd(dev, 0x0008ad, 0x00000000); + nv_icmd(dev, 0x0008ae, 0x00000000); + nv_icmd(dev, 0x0008af, 0x00000000); + nv_icmd(dev, 0x0008f0, 0x00000000); + nv_icmd(dev, 0x0008f1, 0x00000000); + nv_icmd(dev, 0x0008f2, 0x00000000); + nv_icmd(dev, 0x0008f3, 0x00000000); + nv_icmd(dev, 0x0008f4, 0x00000000); + nv_icmd(dev, 0x0008f5, 0x00000000); + nv_icmd(dev, 0x0008f6, 0x00000000); + nv_icmd(dev, 0x0008f7, 0x00000000); + nv_icmd(dev, 0x0008f8, 0x00000000); + nv_icmd(dev, 0x0008f9, 0x00000000); + nv_icmd(dev, 0x0008fa, 0x00000000); + nv_icmd(dev, 0x0008fb, 0x00000000); + nv_icmd(dev, 0x0008fc, 0x00000000); + nv_icmd(dev, 0x0008fd, 0x00000000); + nv_icmd(dev, 0x0008fe, 0x00000000); + nv_icmd(dev, 0x0008ff, 0x00000000); + nv_icmd(dev, 0x00094c, 0x000000ff); + nv_icmd(dev, 0x00094d, 0xffffffff); + nv_icmd(dev, 0x00094e, 0x00000002); + nv_icmd(dev, 0x0002ec, 0x00000001); + nv_icmd(dev, 0x000303, 0x00000001); + nv_icmd(dev, 0x0002e6, 0x00000001); + nv_icmd(dev, 0x000466, 0x00000052); + nv_icmd(dev, 0x000301, 0x3f800000); + nv_icmd(dev, 0x000304, 0x30201000); + nv_icmd(dev, 0x000305, 0x70605040); + nv_icmd(dev, 0x000306, 0xb8a89888); + nv_icmd(dev, 0x000307, 0xf8e8d8c8); + nv_icmd(dev, 0x00030a, 0x00ffff00); + nv_icmd(dev, 0x00030b, 0x0000001a); + nv_icmd(dev, 0x00030c, 0x00000001); + nv_icmd(dev, 0x000318, 0x00000001); + nv_icmd(dev, 0x000340, 0x00000000); + nv_icmd(dev, 0x000375, 0x00000001); + nv_icmd(dev, 0x00037d, 0x00000006); + nv_icmd(dev, 0x0003a0, 0x00000002); + nv_icmd(dev, 0x0003aa, 0x00000001); + nv_icmd(dev, 0x0003a9, 0x00000001); + nv_icmd(dev, 0x000380, 0x00000001); + nv_icmd(dev, 0x000383, 0x00000011); + nv_icmd(dev, 0x000360, 0x00000040); + nv_icmd(dev, 0x000366, 0x00000000); + nv_icmd(dev, 0x000367, 0x00000000); + nv_icmd(dev, 0x000368, 0x00000fff); + nv_icmd(dev, 0x000370, 0x00000000); + nv_icmd(dev, 0x000371, 0x00000000); + nv_icmd(dev, 0x000372, 0x000fffff); + nv_icmd(dev, 0x00037a, 0x00000012); + nv_icmd(dev, 0x000619, 0x00000003); + nv_icmd(dev, 0x000811, 0x00000003); + nv_icmd(dev, 0x000812, 0x00000004); + nv_icmd(dev, 0x000813, 0x00000006); + nv_icmd(dev, 0x000814, 0x00000008); + nv_icmd(dev, 0x000815, 0x0000000b); + nv_icmd(dev, 0x000800, 0x00000001); + nv_icmd(dev, 0x000801, 0x00000001); + nv_icmd(dev, 0x000802, 0x00000001); + nv_icmd(dev, 0x000803, 0x00000001); + nv_icmd(dev, 0x000804, 0x00000001); + nv_icmd(dev, 0x000805, 0x00000001); + nv_icmd(dev, 0x000632, 0x00000001); + nv_icmd(dev, 0x000633, 0x00000002); + nv_icmd(dev, 0x000634, 0x00000003); + nv_icmd(dev, 0x000635, 0x00000004); + nv_icmd(dev, 0x000654, 0x3f800000); + nv_icmd(dev, 0x000657, 0x3f800000); + nv_icmd(dev, 0x000655, 0x3f800000); + nv_icmd(dev, 0x000656, 0x3f800000); + nv_icmd(dev, 0x0006cd, 0x3f800000); + nv_icmd(dev, 0x0007f5, 0x3f800000); + nv_icmd(dev, 0x0007dc, 0x39291909); + nv_icmd(dev, 0x0007dd, 0x79695949); + nv_icmd(dev, 0x0007de, 0xb9a99989); + nv_icmd(dev, 0x0007df, 0xf9e9d9c9); + nv_icmd(dev, 0x0007e8, 0x00003210); + nv_icmd(dev, 0x0007e9, 0x00007654); + nv_icmd(dev, 0x0007ea, 0x00000098); + nv_icmd(dev, 0x0007ec, 0x39291909); + nv_icmd(dev, 0x0007ed, 0x79695949); + nv_icmd(dev, 0x0007ee, 0xb9a99989); + nv_icmd(dev, 0x0007ef, 0xf9e9d9c9); + nv_icmd(dev, 0x0007f0, 0x00003210); + nv_icmd(dev, 0x0007f1, 0x00007654); + nv_icmd(dev, 0x0007f2, 0x00000098); + nv_icmd(dev, 0x0005a5, 0x00000001); + nv_icmd(dev, 0x000980, 0x00000000); + nv_icmd(dev, 0x000981, 0x00000000); + nv_icmd(dev, 0x000982, 0x00000000); + nv_icmd(dev, 0x000983, 0x00000000); + nv_icmd(dev, 0x000984, 0x00000000); + nv_icmd(dev, 0x000985, 0x00000000); + nv_icmd(dev, 0x000986, 0x00000000); + nv_icmd(dev, 0x000987, 0x00000000); + nv_icmd(dev, 0x000988, 0x00000000); + nv_icmd(dev, 0x000989, 0x00000000); + nv_icmd(dev, 0x00098a, 0x00000000); + nv_icmd(dev, 0x00098b, 0x00000000); + nv_icmd(dev, 0x00098c, 0x00000000); + nv_icmd(dev, 0x00098d, 0x00000000); + nv_icmd(dev, 0x00098e, 0x00000000); + nv_icmd(dev, 0x00098f, 0x00000000); + nv_icmd(dev, 0x000990, 0x00000000); + nv_icmd(dev, 0x000991, 0x00000000); + nv_icmd(dev, 0x000992, 0x00000000); + nv_icmd(dev, 0x000993, 0x00000000); + nv_icmd(dev, 0x000994, 0x00000000); + nv_icmd(dev, 0x000995, 0x00000000); + nv_icmd(dev, 0x000996, 0x00000000); + nv_icmd(dev, 0x000997, 0x00000000); + nv_icmd(dev, 0x000998, 0x00000000); + nv_icmd(dev, 0x000999, 0x00000000); + nv_icmd(dev, 0x00099a, 0x00000000); + nv_icmd(dev, 0x00099b, 0x00000000); + nv_icmd(dev, 0x00099c, 0x00000000); + nv_icmd(dev, 0x00099d, 0x00000000); + nv_icmd(dev, 0x00099e, 0x00000000); + nv_icmd(dev, 0x00099f, 0x00000000); + nv_icmd(dev, 0x0009a0, 0x00000000); + nv_icmd(dev, 0x0009a1, 0x00000000); + nv_icmd(dev, 0x0009a2, 0x00000000); + nv_icmd(dev, 0x0009a3, 0x00000000); + nv_icmd(dev, 0x0009a4, 0x00000000); + nv_icmd(dev, 0x0009a5, 0x00000000); + nv_icmd(dev, 0x0009a6, 0x00000000); + nv_icmd(dev, 0x0009a7, 0x00000000); + nv_icmd(dev, 0x0009a8, 0x00000000); + nv_icmd(dev, 0x0009a9, 0x00000000); + nv_icmd(dev, 0x0009aa, 0x00000000); + nv_icmd(dev, 0x0009ab, 0x00000000); + nv_icmd(dev, 0x0009ac, 0x00000000); + nv_icmd(dev, 0x0009ad, 0x00000000); + nv_icmd(dev, 0x0009ae, 0x00000000); + nv_icmd(dev, 0x0009af, 0x00000000); + nv_icmd(dev, 0x0009b0, 0x00000000); + nv_icmd(dev, 0x0009b1, 0x00000000); + nv_icmd(dev, 0x0009b2, 0x00000000); + nv_icmd(dev, 0x0009b3, 0x00000000); + nv_icmd(dev, 0x0009b4, 0x00000000); + nv_icmd(dev, 0x0009b5, 0x00000000); + nv_icmd(dev, 0x0009b6, 0x00000000); + nv_icmd(dev, 0x0009b7, 0x00000000); + nv_icmd(dev, 0x0009b8, 0x00000000); + nv_icmd(dev, 0x0009b9, 0x00000000); + nv_icmd(dev, 0x0009ba, 0x00000000); + nv_icmd(dev, 0x0009bb, 0x00000000); + nv_icmd(dev, 0x0009bc, 0x00000000); + nv_icmd(dev, 0x0009bd, 0x00000000); + nv_icmd(dev, 0x0009be, 0x00000000); + nv_icmd(dev, 0x0009bf, 0x00000000); + nv_icmd(dev, 0x0009c0, 0x00000000); + nv_icmd(dev, 0x0009c1, 0x00000000); + nv_icmd(dev, 0x0009c2, 0x00000000); + nv_icmd(dev, 0x0009c3, 0x00000000); + nv_icmd(dev, 0x0009c4, 0x00000000); + nv_icmd(dev, 0x0009c5, 0x00000000); + nv_icmd(dev, 0x0009c6, 0x00000000); + nv_icmd(dev, 0x0009c7, 0x00000000); + nv_icmd(dev, 0x0009c8, 0x00000000); + nv_icmd(dev, 0x0009c9, 0x00000000); + nv_icmd(dev, 0x0009ca, 0x00000000); + nv_icmd(dev, 0x0009cb, 0x00000000); + nv_icmd(dev, 0x0009cc, 0x00000000); + nv_icmd(dev, 0x0009cd, 0x00000000); + nv_icmd(dev, 0x0009ce, 0x00000000); + nv_icmd(dev, 0x0009cf, 0x00000000); + nv_icmd(dev, 0x0009d0, 0x00000000); + nv_icmd(dev, 0x0009d1, 0x00000000); + nv_icmd(dev, 0x0009d2, 0x00000000); + nv_icmd(dev, 0x0009d3, 0x00000000); + nv_icmd(dev, 0x0009d4, 0x00000000); + nv_icmd(dev, 0x0009d5, 0x00000000); + nv_icmd(dev, 0x0009d6, 0x00000000); + nv_icmd(dev, 0x0009d7, 0x00000000); + nv_icmd(dev, 0x0009d8, 0x00000000); + nv_icmd(dev, 0x0009d9, 0x00000000); + nv_icmd(dev, 0x0009da, 0x00000000); + nv_icmd(dev, 0x0009db, 0x00000000); + nv_icmd(dev, 0x0009dc, 0x00000000); + nv_icmd(dev, 0x0009dd, 0x00000000); + nv_icmd(dev, 0x0009de, 0x00000000); + nv_icmd(dev, 0x0009df, 0x00000000); + nv_icmd(dev, 0x0009e0, 0x00000000); + nv_icmd(dev, 0x0009e1, 0x00000000); + nv_icmd(dev, 0x0009e2, 0x00000000); + nv_icmd(dev, 0x0009e3, 0x00000000); + nv_icmd(dev, 0x0009e4, 0x00000000); + nv_icmd(dev, 0x0009e5, 0x00000000); + nv_icmd(dev, 0x0009e6, 0x00000000); + nv_icmd(dev, 0x0009e7, 0x00000000); + nv_icmd(dev, 0x0009e8, 0x00000000); + nv_icmd(dev, 0x0009e9, 0x00000000); + nv_icmd(dev, 0x0009ea, 0x00000000); + nv_icmd(dev, 0x0009eb, 0x00000000); + nv_icmd(dev, 0x0009ec, 0x00000000); + nv_icmd(dev, 0x0009ed, 0x00000000); + nv_icmd(dev, 0x0009ee, 0x00000000); + nv_icmd(dev, 0x0009ef, 0x00000000); + nv_icmd(dev, 0x0009f0, 0x00000000); + nv_icmd(dev, 0x0009f1, 0x00000000); + nv_icmd(dev, 0x0009f2, 0x00000000); + nv_icmd(dev, 0x0009f3, 0x00000000); + nv_icmd(dev, 0x0009f4, 0x00000000); + nv_icmd(dev, 0x0009f5, 0x00000000); + nv_icmd(dev, 0x0009f6, 0x00000000); + nv_icmd(dev, 0x0009f7, 0x00000000); + nv_icmd(dev, 0x0009f8, 0x00000000); + nv_icmd(dev, 0x0009f9, 0x00000000); + nv_icmd(dev, 0x0009fa, 0x00000000); + nv_icmd(dev, 0x0009fb, 0x00000000); + nv_icmd(dev, 0x0009fc, 0x00000000); + nv_icmd(dev, 0x0009fd, 0x00000000); + nv_icmd(dev, 0x0009fe, 0x00000000); + nv_icmd(dev, 0x0009ff, 0x00000000); + nv_icmd(dev, 0x000468, 0x00000004); + nv_icmd(dev, 0x00046c, 0x00000001); + nv_icmd(dev, 0x000470, 0x00000000); + nv_icmd(dev, 0x000471, 0x00000000); + nv_icmd(dev, 0x000472, 0x00000000); + nv_icmd(dev, 0x000473, 0x00000000); + nv_icmd(dev, 0x000474, 0x00000000); + nv_icmd(dev, 0x000475, 0x00000000); + nv_icmd(dev, 0x000476, 0x00000000); + nv_icmd(dev, 0x000477, 0x00000000); + nv_icmd(dev, 0x000478, 0x00000000); + nv_icmd(dev, 0x000479, 0x00000000); + nv_icmd(dev, 0x00047a, 0x00000000); + nv_icmd(dev, 0x00047b, 0x00000000); + nv_icmd(dev, 0x00047c, 0x00000000); + nv_icmd(dev, 0x00047d, 0x00000000); + nv_icmd(dev, 0x00047e, 0x00000000); + nv_icmd(dev, 0x00047f, 0x00000000); + nv_icmd(dev, 0x000480, 0x00000000); + nv_icmd(dev, 0x000481, 0x00000000); + nv_icmd(dev, 0x000482, 0x00000000); + nv_icmd(dev, 0x000483, 0x00000000); + nv_icmd(dev, 0x000484, 0x00000000); + nv_icmd(dev, 0x000485, 0x00000000); + nv_icmd(dev, 0x000486, 0x00000000); + nv_icmd(dev, 0x000487, 0x00000000); + nv_icmd(dev, 0x000488, 0x00000000); + nv_icmd(dev, 0x000489, 0x00000000); + nv_icmd(dev, 0x00048a, 0x00000000); + nv_icmd(dev, 0x00048b, 0x00000000); + nv_icmd(dev, 0x00048c, 0x00000000); + nv_icmd(dev, 0x00048d, 0x00000000); + nv_icmd(dev, 0x00048e, 0x00000000); + nv_icmd(dev, 0x00048f, 0x00000000); + nv_icmd(dev, 0x000490, 0x00000000); + nv_icmd(dev, 0x000491, 0x00000000); + nv_icmd(dev, 0x000492, 0x00000000); + nv_icmd(dev, 0x000493, 0x00000000); + nv_icmd(dev, 0x000494, 0x00000000); + nv_icmd(dev, 0x000495, 0x00000000); + nv_icmd(dev, 0x000496, 0x00000000); + nv_icmd(dev, 0x000497, 0x00000000); + nv_icmd(dev, 0x000498, 0x00000000); + nv_icmd(dev, 0x000499, 0x00000000); + nv_icmd(dev, 0x00049a, 0x00000000); + nv_icmd(dev, 0x00049b, 0x00000000); + nv_icmd(dev, 0x00049c, 0x00000000); + nv_icmd(dev, 0x00049d, 0x00000000); + nv_icmd(dev, 0x00049e, 0x00000000); + nv_icmd(dev, 0x00049f, 0x00000000); + nv_icmd(dev, 0x0004a0, 0x00000000); + nv_icmd(dev, 0x0004a1, 0x00000000); + nv_icmd(dev, 0x0004a2, 0x00000000); + nv_icmd(dev, 0x0004a3, 0x00000000); + nv_icmd(dev, 0x0004a4, 0x00000000); + nv_icmd(dev, 0x0004a5, 0x00000000); + nv_icmd(dev, 0x0004a6, 0x00000000); + nv_icmd(dev, 0x0004a7, 0x00000000); + nv_icmd(dev, 0x0004a8, 0x00000000); + nv_icmd(dev, 0x0004a9, 0x00000000); + nv_icmd(dev, 0x0004aa, 0x00000000); + nv_icmd(dev, 0x0004ab, 0x00000000); + nv_icmd(dev, 0x0004ac, 0x00000000); + nv_icmd(dev, 0x0004ad, 0x00000000); + nv_icmd(dev, 0x0004ae, 0x00000000); + nv_icmd(dev, 0x0004af, 0x00000000); + nv_icmd(dev, 0x0004b0, 0x00000000); + nv_icmd(dev, 0x0004b1, 0x00000000); + nv_icmd(dev, 0x0004b2, 0x00000000); + nv_icmd(dev, 0x0004b3, 0x00000000); + nv_icmd(dev, 0x0004b4, 0x00000000); + nv_icmd(dev, 0x0004b5, 0x00000000); + nv_icmd(dev, 0x0004b6, 0x00000000); + nv_icmd(dev, 0x0004b7, 0x00000000); + nv_icmd(dev, 0x0004b8, 0x00000000); + nv_icmd(dev, 0x0004b9, 0x00000000); + nv_icmd(dev, 0x0004ba, 0x00000000); + nv_icmd(dev, 0x0004bb, 0x00000000); + nv_icmd(dev, 0x0004bc, 0x00000000); + nv_icmd(dev, 0x0004bd, 0x00000000); + nv_icmd(dev, 0x0004be, 0x00000000); + nv_icmd(dev, 0x0004bf, 0x00000000); + nv_icmd(dev, 0x0004c0, 0x00000000); + nv_icmd(dev, 0x0004c1, 0x00000000); + nv_icmd(dev, 0x0004c2, 0x00000000); + nv_icmd(dev, 0x0004c3, 0x00000000); + nv_icmd(dev, 0x0004c4, 0x00000000); + nv_icmd(dev, 0x0004c5, 0x00000000); + nv_icmd(dev, 0x0004c6, 0x00000000); + nv_icmd(dev, 0x0004c7, 0x00000000); + nv_icmd(dev, 0x0004c8, 0x00000000); + nv_icmd(dev, 0x0004c9, 0x00000000); + nv_icmd(dev, 0x0004ca, 0x00000000); + nv_icmd(dev, 0x0004cb, 0x00000000); + nv_icmd(dev, 0x0004cc, 0x00000000); + nv_icmd(dev, 0x0004cd, 0x00000000); + nv_icmd(dev, 0x0004ce, 0x00000000); + nv_icmd(dev, 0x0004cf, 0x00000000); + nv_icmd(dev, 0x000510, 0x3f800000); + nv_icmd(dev, 0x000511, 0x3f800000); + nv_icmd(dev, 0x000512, 0x3f800000); + nv_icmd(dev, 0x000513, 0x3f800000); + nv_icmd(dev, 0x000514, 0x3f800000); + nv_icmd(dev, 0x000515, 0x3f800000); + nv_icmd(dev, 0x000516, 0x3f800000); + nv_icmd(dev, 0x000517, 0x3f800000); + nv_icmd(dev, 0x000518, 0x3f800000); + nv_icmd(dev, 0x000519, 0x3f800000); + nv_icmd(dev, 0x00051a, 0x3f800000); + nv_icmd(dev, 0x00051b, 0x3f800000); + nv_icmd(dev, 0x00051c, 0x3f800000); + nv_icmd(dev, 0x00051d, 0x3f800000); + nv_icmd(dev, 0x00051e, 0x3f800000); + nv_icmd(dev, 0x00051f, 0x3f800000); + nv_icmd(dev, 0x000520, 0x000002b6); + nv_icmd(dev, 0x000529, 0x00000001); + nv_icmd(dev, 0x000530, 0xffff0000); + nv_icmd(dev, 0x000531, 0xffff0000); + nv_icmd(dev, 0x000532, 0xffff0000); + nv_icmd(dev, 0x000533, 0xffff0000); + nv_icmd(dev, 0x000534, 0xffff0000); + nv_icmd(dev, 0x000535, 0xffff0000); + nv_icmd(dev, 0x000536, 0xffff0000); + nv_icmd(dev, 0x000537, 0xffff0000); + nv_icmd(dev, 0x000538, 0xffff0000); + nv_icmd(dev, 0x000539, 0xffff0000); + nv_icmd(dev, 0x00053a, 0xffff0000); + nv_icmd(dev, 0x00053b, 0xffff0000); + nv_icmd(dev, 0x00053c, 0xffff0000); + nv_icmd(dev, 0x00053d, 0xffff0000); + nv_icmd(dev, 0x00053e, 0xffff0000); + nv_icmd(dev, 0x00053f, 0xffff0000); + nv_icmd(dev, 0x000585, 0x0000003f); + nv_icmd(dev, 0x000576, 0x00000003); + nv_icmd(dev, 0x00057b, 0x00000059); + nv_icmd(dev, 0x000586, 0x00000040); + nv_icmd(dev, 0x000582, 0x00000080); + nv_icmd(dev, 0x000583, 0x00000080); + nv_icmd(dev, 0x0005c2, 0x00000001); + nv_icmd(dev, 0x000638, 0x00000001); + nv_icmd(dev, 0x000639, 0x00000001); + nv_icmd(dev, 0x00063a, 0x00000002); + nv_icmd(dev, 0x00063b, 0x00000001); + nv_icmd(dev, 0x00063c, 0x00000001); + nv_icmd(dev, 0x00063d, 0x00000002); + nv_icmd(dev, 0x00063e, 0x00000001); + nv_icmd(dev, 0x0008b8, 0x00000001); + nv_icmd(dev, 0x0008b9, 0x00000001); + nv_icmd(dev, 0x0008ba, 0x00000001); + nv_icmd(dev, 0x0008bb, 0x00000001); + nv_icmd(dev, 0x0008bc, 0x00000001); + nv_icmd(dev, 0x0008bd, 0x00000001); + nv_icmd(dev, 0x0008be, 0x00000001); + nv_icmd(dev, 0x0008bf, 0x00000001); + nv_icmd(dev, 0x000900, 0x00000001); + nv_icmd(dev, 0x000901, 0x00000001); + nv_icmd(dev, 0x000902, 0x00000001); + nv_icmd(dev, 0x000903, 0x00000001); + nv_icmd(dev, 0x000904, 0x00000001); + nv_icmd(dev, 0x000905, 0x00000001); + nv_icmd(dev, 0x000906, 0x00000001); + nv_icmd(dev, 0x000907, 0x00000001); + nv_icmd(dev, 0x000908, 0x00000002); + nv_icmd(dev, 0x000909, 0x00000002); + nv_icmd(dev, 0x00090a, 0x00000002); + nv_icmd(dev, 0x00090b, 0x00000002); + nv_icmd(dev, 0x00090c, 0x00000002); + nv_icmd(dev, 0x00090d, 0x00000002); + nv_icmd(dev, 0x00090e, 0x00000002); + nv_icmd(dev, 0x00090f, 0x00000002); + nv_icmd(dev, 0x000910, 0x00000001); + nv_icmd(dev, 0x000911, 0x00000001); + nv_icmd(dev, 0x000912, 0x00000001); + nv_icmd(dev, 0x000913, 0x00000001); + nv_icmd(dev, 0x000914, 0x00000001); + nv_icmd(dev, 0x000915, 0x00000001); + nv_icmd(dev, 0x000916, 0x00000001); + nv_icmd(dev, 0x000917, 0x00000001); + nv_icmd(dev, 0x000918, 0x00000001); + nv_icmd(dev, 0x000919, 0x00000001); + nv_icmd(dev, 0x00091a, 0x00000001); + nv_icmd(dev, 0x00091b, 0x00000001); + nv_icmd(dev, 0x00091c, 0x00000001); + nv_icmd(dev, 0x00091d, 0x00000001); + nv_icmd(dev, 0x00091e, 0x00000001); + nv_icmd(dev, 0x00091f, 0x00000001); + nv_icmd(dev, 0x000920, 0x00000002); + nv_icmd(dev, 0x000921, 0x00000002); + nv_icmd(dev, 0x000922, 0x00000002); + nv_icmd(dev, 0x000923, 0x00000002); + nv_icmd(dev, 0x000924, 0x00000002); + nv_icmd(dev, 0x000925, 0x00000002); + nv_icmd(dev, 0x000926, 0x00000002); + nv_icmd(dev, 0x000927, 0x00000002); + nv_icmd(dev, 0x000928, 0x00000001); + nv_icmd(dev, 0x000929, 0x00000001); + nv_icmd(dev, 0x00092a, 0x00000001); + nv_icmd(dev, 0x00092b, 0x00000001); + nv_icmd(dev, 0x00092c, 0x00000001); + nv_icmd(dev, 0x00092d, 0x00000001); + nv_icmd(dev, 0x00092e, 0x00000001); + nv_icmd(dev, 0x00092f, 0x00000001); + nv_icmd(dev, 0x000648, 0x00000001); + nv_icmd(dev, 0x000649, 0x00000001); + nv_icmd(dev, 0x00064a, 0x00000001); + nv_icmd(dev, 0x00064b, 0x00000001); + nv_icmd(dev, 0x00064c, 0x00000001); + nv_icmd(dev, 0x00064d, 0x00000001); + nv_icmd(dev, 0x00064e, 0x00000001); + nv_icmd(dev, 0x00064f, 0x00000001); + nv_icmd(dev, 0x000650, 0x00000001); + nv_icmd(dev, 0x000658, 0x0000000f); + nv_icmd(dev, 0x0007ff, 0x0000000a); + nv_icmd(dev, 0x00066a, 0x40000000); + nv_icmd(dev, 0x00066b, 0x10000000); + nv_icmd(dev, 0x00066c, 0xffff0000); + nv_icmd(dev, 0x00066d, 0xffff0000); + nv_icmd(dev, 0x0007af, 0x00000008); + nv_icmd(dev, 0x0007b0, 0x00000008); + nv_icmd(dev, 0x0007f6, 0x00000001); + nv_icmd(dev, 0x0006b2, 0x00000055); + nv_icmd(dev, 0x0007ad, 0x00000003); + nv_icmd(dev, 0x000937, 0x00000001); + nv_icmd(dev, 0x000971, 0x00000008); + nv_icmd(dev, 0x000972, 0x00000040); + nv_icmd(dev, 0x000973, 0x0000012c); + nv_icmd(dev, 0x00097c, 0x00000040); + nv_icmd(dev, 0x000979, 0x00000003); + nv_icmd(dev, 0x000975, 0x00000020); + nv_icmd(dev, 0x000976, 0x00000001); + nv_icmd(dev, 0x000977, 0x00000020); + nv_icmd(dev, 0x000978, 0x00000001); + nv_icmd(dev, 0x000957, 0x00000003); + nv_icmd(dev, 0x00095e, 0x20164010); + nv_icmd(dev, 0x00095f, 0x00000020); + nv_icmd(dev, 0x00097d, 0x00000020); + nv_icmd(dev, 0x000683, 0x00000006); + nv_icmd(dev, 0x000685, 0x003fffff); + nv_icmd(dev, 0x000687, 0x003fffff); + nv_icmd(dev, 0x0006a0, 0x00000005); + nv_icmd(dev, 0x000840, 0x00400008); + nv_icmd(dev, 0x000841, 0x08000080); + nv_icmd(dev, 0x000842, 0x00400008); + nv_icmd(dev, 0x000843, 0x08000080); + nv_icmd(dev, 0x000818, 0x00000000); + nv_icmd(dev, 0x000819, 0x00000000); + nv_icmd(dev, 0x00081a, 0x00000000); + nv_icmd(dev, 0x00081b, 0x00000000); + nv_icmd(dev, 0x00081c, 0x00000000); + nv_icmd(dev, 0x00081d, 0x00000000); + nv_icmd(dev, 0x00081e, 0x00000000); + nv_icmd(dev, 0x00081f, 0x00000000); + nv_icmd(dev, 0x000848, 0x00000000); + nv_icmd(dev, 0x000849, 0x00000000); + nv_icmd(dev, 0x00084a, 0x00000000); + nv_icmd(dev, 0x00084b, 0x00000000); + nv_icmd(dev, 0x00084c, 0x00000000); + nv_icmd(dev, 0x00084d, 0x00000000); + nv_icmd(dev, 0x00084e, 0x00000000); + nv_icmd(dev, 0x00084f, 0x00000000); + nv_icmd(dev, 0x000850, 0x00000000); + nv_icmd(dev, 0x000851, 0x00000000); + nv_icmd(dev, 0x000852, 0x00000000); + nv_icmd(dev, 0x000853, 0x00000000); + nv_icmd(dev, 0x000854, 0x00000000); + nv_icmd(dev, 0x000855, 0x00000000); + nv_icmd(dev, 0x000856, 0x00000000); + nv_icmd(dev, 0x000857, 0x00000000); + nv_icmd(dev, 0x000738, 0x00000000); + nv_icmd(dev, 0x0006aa, 0x00000001); + nv_icmd(dev, 0x0006ab, 0x00000002); + nv_icmd(dev, 0x0006ac, 0x00000080); + nv_icmd(dev, 0x0006ad, 0x00000100); + nv_icmd(dev, 0x0006ae, 0x00000100); + nv_icmd(dev, 0x0006b1, 0x00000011); + nv_icmd(dev, 0x0006bb, 0x000000cf); + nv_icmd(dev, 0x0006ce, 0x2a712488); + nv_icmd(dev, 0x000739, 0x4085c000); + nv_icmd(dev, 0x00073a, 0x00000080); + nv_icmd(dev, 0x000786, 0x80000100); + nv_icmd(dev, 0x00073c, 0x00010100); + nv_icmd(dev, 0x00073d, 0x02800000); + nv_icmd(dev, 0x000787, 0x000000cf); + nv_icmd(dev, 0x00078c, 0x00000008); + nv_icmd(dev, 0x000792, 0x00000001); + nv_icmd(dev, 0x000794, 0x00000001); + nv_icmd(dev, 0x000795, 0x00000001); + nv_icmd(dev, 0x000796, 0x00000001); + nv_icmd(dev, 0x000797, 0x000000cf); + nv_icmd(dev, 0x000836, 0x00000001); + nv_icmd(dev, 0x00079a, 0x00000002); + nv_icmd(dev, 0x000833, 0x04444480); + nv_icmd(dev, 0x0007a1, 0x00000001); + nv_icmd(dev, 0x0007a3, 0x00000001); + nv_icmd(dev, 0x0007a4, 0x00000001); + nv_icmd(dev, 0x0007a5, 0x00000001); + nv_icmd(dev, 0x000831, 0x00000004); + nv_icmd(dev, 0x000b07, 0x00000002); + nv_icmd(dev, 0x000b08, 0x00000100); + nv_icmd(dev, 0x000b09, 0x00000100); + nv_icmd(dev, 0x000b0a, 0x00000001); + nv_icmd(dev, 0x000a04, 0x000000ff); + nv_icmd(dev, 0x000a0b, 0x00000040); + nv_icmd(dev, 0x00097f, 0x00000100); + nv_icmd(dev, 0x000a02, 0x00000001); + nv_icmd(dev, 0x000809, 0x00000007); + nv_icmd(dev, 0x00c221, 0x00000040); + nv_icmd(dev, 0x00c1b0, 0x0000000f); + nv_icmd(dev, 0x00c1b1, 0x0000000f); + nv_icmd(dev, 0x00c1b2, 0x0000000f); + nv_icmd(dev, 0x00c1b3, 0x0000000f); + nv_icmd(dev, 0x00c1b4, 0x0000000f); + nv_icmd(dev, 0x00c1b5, 0x0000000f); + nv_icmd(dev, 0x00c1b6, 0x0000000f); + nv_icmd(dev, 0x00c1b7, 0x0000000f); + nv_icmd(dev, 0x00c1b8, 0x0fac6881); + nv_icmd(dev, 0x00c1b9, 0x00fac688); + nv_icmd(dev, 0x00c401, 0x00000001); + nv_icmd(dev, 0x00c402, 0x00010001); + nv_icmd(dev, 0x00c403, 0x00000001); + nv_icmd(dev, 0x00c404, 0x00000001); + nv_icmd(dev, 0x00c40e, 0x00000020); + nv_icmd(dev, 0x00c500, 0x00000003); + nv_icmd(dev, 0x01e100, 0x00000001); + nv_icmd(dev, 0x001000, 0x00000002); + nv_icmd(dev, 0x0006aa, 0x00000001); + nv_icmd(dev, 0x0006ad, 0x00000100); + nv_icmd(dev, 0x0006ae, 0x00000100); + nv_icmd(dev, 0x0006b1, 0x00000011); + nv_icmd(dev, 0x00078c, 0x00000008); + nv_icmd(dev, 0x000792, 0x00000001); + nv_icmd(dev, 0x000794, 0x00000001); + nv_icmd(dev, 0x000795, 0x00000001); + nv_icmd(dev, 0x000796, 0x00000001); + nv_icmd(dev, 0x000797, 0x000000cf); + nv_icmd(dev, 0x00079a, 0x00000002); + nv_icmd(dev, 0x000833, 0x04444480); + nv_icmd(dev, 0x0007a1, 0x00000001); + nv_icmd(dev, 0x0007a3, 0x00000001); + nv_icmd(dev, 0x0007a4, 0x00000001); + nv_icmd(dev, 0x0007a5, 0x00000001); + nv_icmd(dev, 0x000831, 0x00000004); + nv_icmd(dev, 0x01e100, 0x00000001); + nv_icmd(dev, 0x001000, 0x00000008); + nv_icmd(dev, 0x000039, 0x00000000); + nv_icmd(dev, 0x00003a, 0x00000000); + nv_icmd(dev, 0x00003b, 0x00000000); + nv_icmd(dev, 0x000380, 0x00000001); + nv_icmd(dev, 0x000366, 0x00000000); + nv_icmd(dev, 0x000367, 0x00000000); + nv_icmd(dev, 0x000368, 0x00000fff); + nv_icmd(dev, 0x000370, 0x00000000); + nv_icmd(dev, 0x000371, 0x00000000); + nv_icmd(dev, 0x000372, 0x000fffff); + nv_icmd(dev, 0x000813, 0x00000006); + nv_icmd(dev, 0x000814, 0x00000008); + nv_icmd(dev, 0x000957, 0x00000003); + nv_icmd(dev, 0x000818, 0x00000000); + nv_icmd(dev, 0x000819, 0x00000000); + nv_icmd(dev, 0x00081a, 0x00000000); + nv_icmd(dev, 0x00081b, 0x00000000); + nv_icmd(dev, 0x00081c, 0x00000000); + nv_icmd(dev, 0x00081d, 0x00000000); + nv_icmd(dev, 0x00081e, 0x00000000); + nv_icmd(dev, 0x00081f, 0x00000000); + nv_icmd(dev, 0x000848, 0x00000000); + nv_icmd(dev, 0x000849, 0x00000000); + nv_icmd(dev, 0x00084a, 0x00000000); + nv_icmd(dev, 0x00084b, 0x00000000); + nv_icmd(dev, 0x00084c, 0x00000000); + nv_icmd(dev, 0x00084d, 0x00000000); + nv_icmd(dev, 0x00084e, 0x00000000); + nv_icmd(dev, 0x00084f, 0x00000000); + nv_icmd(dev, 0x000850, 0x00000000); + nv_icmd(dev, 0x000851, 0x00000000); + nv_icmd(dev, 0x000852, 0x00000000); + nv_icmd(dev, 0x000853, 0x00000000); + nv_icmd(dev, 0x000854, 0x00000000); + nv_icmd(dev, 0x000855, 0x00000000); + nv_icmd(dev, 0x000856, 0x00000000); + nv_icmd(dev, 0x000857, 0x00000000); + nv_icmd(dev, 0x000738, 0x00000000); + nv_icmd(dev, 0x000b07, 0x00000002); + nv_icmd(dev, 0x000b08, 0x00000100); + nv_icmd(dev, 0x000b09, 0x00000100); + nv_icmd(dev, 0x000b0a, 0x00000001); + nv_icmd(dev, 0x000a04, 0x000000ff); + nv_icmd(dev, 0x00097f, 0x00000100); + nv_icmd(dev, 0x000a02, 0x00000001); + nv_icmd(dev, 0x000809, 0x00000007); + nv_icmd(dev, 0x00c221, 0x00000040); + nv_icmd(dev, 0x00c401, 0x00000001); + nv_icmd(dev, 0x00c402, 0x00010001); + nv_icmd(dev, 0x00c403, 0x00000001); + nv_icmd(dev, 0x00c404, 0x00000001); + nv_icmd(dev, 0x00c40e, 0x00000020); + nv_icmd(dev, 0x00c500, 0x00000003); + nv_icmd(dev, 0x01e100, 0x00000001); + nv_icmd(dev, 0x001000, 0x00000001); + nv_icmd(dev, 0x000b07, 0x00000002); + nv_icmd(dev, 0x000b08, 0x00000100); + nv_icmd(dev, 0x000b09, 0x00000100); + nv_icmd(dev, 0x000b0a, 0x00000001); + nv_icmd(dev, 0x01e100, 0x00000001); + nv_wr32(dev, 0x400208, 0x00000000); +} + +static void +nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data) +{ + nv_wr32(dev, 0x40448c, data); + nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class); +} + +static void +nve0_grctx_generate_a097(struct drm_device *dev) +{ + nv_mthd(dev, 0xa097, 0x0800, 0x00000000); + nv_mthd(dev, 0xa097, 0x0840, 0x00000000); + nv_mthd(dev, 0xa097, 0x0880, 0x00000000); + nv_mthd(dev, 0xa097, 0x08c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0900, 0x00000000); + nv_mthd(dev, 0xa097, 0x0940, 0x00000000); + nv_mthd(dev, 0xa097, 0x0980, 0x00000000); + nv_mthd(dev, 0xa097, 0x09c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0804, 0x00000000); + nv_mthd(dev, 0xa097, 0x0844, 0x00000000); + nv_mthd(dev, 0xa097, 0x0884, 0x00000000); + nv_mthd(dev, 0xa097, 0x08c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0904, 0x00000000); + nv_mthd(dev, 0xa097, 0x0944, 0x00000000); + nv_mthd(dev, 0xa097, 0x0984, 0x00000000); + nv_mthd(dev, 0xa097, 0x09c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0808, 0x00000400); + nv_mthd(dev, 0xa097, 0x0848, 0x00000400); + nv_mthd(dev, 0xa097, 0x0888, 0x00000400); + nv_mthd(dev, 0xa097, 0x08c8, 0x00000400); + nv_mthd(dev, 0xa097, 0x0908, 0x00000400); + nv_mthd(dev, 0xa097, 0x0948, 0x00000400); + nv_mthd(dev, 0xa097, 0x0988, 0x00000400); + nv_mthd(dev, 0xa097, 0x09c8, 0x00000400); + nv_mthd(dev, 0xa097, 0x080c, 0x00000300); + nv_mthd(dev, 0xa097, 0x084c, 0x00000300); + nv_mthd(dev, 0xa097, 0x088c, 0x00000300); + nv_mthd(dev, 0xa097, 0x08cc, 0x00000300); + nv_mthd(dev, 0xa097, 0x090c, 0x00000300); + nv_mthd(dev, 0xa097, 0x094c, 0x00000300); + nv_mthd(dev, 0xa097, 0x098c, 0x00000300); + nv_mthd(dev, 0xa097, 0x09cc, 0x00000300); + nv_mthd(dev, 0xa097, 0x0810, 0x000000cf); + nv_mthd(dev, 0xa097, 0x0850, 0x00000000); + nv_mthd(dev, 0xa097, 0x0890, 0x00000000); + nv_mthd(dev, 0xa097, 0x08d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0910, 0x00000000); + nv_mthd(dev, 0xa097, 0x0950, 0x00000000); + nv_mthd(dev, 0xa097, 0x0990, 0x00000000); + nv_mthd(dev, 0xa097, 0x09d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0814, 0x00000040); + nv_mthd(dev, 0xa097, 0x0854, 0x00000040); + nv_mthd(dev, 0xa097, 0x0894, 0x00000040); + nv_mthd(dev, 0xa097, 0x08d4, 0x00000040); + nv_mthd(dev, 0xa097, 0x0914, 0x00000040); + nv_mthd(dev, 0xa097, 0x0954, 0x00000040); + nv_mthd(dev, 0xa097, 0x0994, 0x00000040); + nv_mthd(dev, 0xa097, 0x09d4, 0x00000040); + nv_mthd(dev, 0xa097, 0x0818, 0x00000001); + nv_mthd(dev, 0xa097, 0x0858, 0x00000001); + nv_mthd(dev, 0xa097, 0x0898, 0x00000001); + nv_mthd(dev, 0xa097, 0x08d8, 0x00000001); + nv_mthd(dev, 0xa097, 0x0918, 0x00000001); + nv_mthd(dev, 0xa097, 0x0958, 0x00000001); + nv_mthd(dev, 0xa097, 0x0998, 0x00000001); + nv_mthd(dev, 0xa097, 0x09d8, 0x00000001); + nv_mthd(dev, 0xa097, 0x081c, 0x00000000); + nv_mthd(dev, 0xa097, 0x085c, 0x00000000); + nv_mthd(dev, 0xa097, 0x089c, 0x00000000); + nv_mthd(dev, 0xa097, 0x08dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x091c, 0x00000000); + nv_mthd(dev, 0xa097, 0x095c, 0x00000000); + nv_mthd(dev, 0xa097, 0x099c, 0x00000000); + nv_mthd(dev, 0xa097, 0x09dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0820, 0x00000000); + nv_mthd(dev, 0xa097, 0x0860, 0x00000000); + nv_mthd(dev, 0xa097, 0x08a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x08e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0920, 0x00000000); + nv_mthd(dev, 0xa097, 0x0960, 0x00000000); + nv_mthd(dev, 0xa097, 0x09a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x09e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c00, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c10, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c20, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c30, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c40, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c50, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c60, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c70, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c80, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c90, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ca0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cb0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cc0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cd0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ce0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cf0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c04, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c14, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c24, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c34, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c44, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c54, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c64, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c74, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c84, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c94, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ca4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cb4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cc4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cd4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ce4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cf4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c08, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c18, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c28, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c38, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c48, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c58, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c68, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c78, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c88, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c98, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ca8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cb8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cc8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cd8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ce8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cf8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c0c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c1c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c2c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c3c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c4c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c5c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c6c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c7c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1c9c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cac, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cbc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ccc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cdc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cec, 0x00000000); + nv_mthd(dev, 0xa097, 0x1cfc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d00, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d10, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d20, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d30, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d40, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d50, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d60, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d70, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d80, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d90, 0x00000000); + nv_mthd(dev, 0xa097, 0x1da0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1db0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dc0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dd0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1de0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1df0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d04, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d14, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d24, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d34, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d44, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d54, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d64, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d74, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d84, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d94, 0x00000000); + nv_mthd(dev, 0xa097, 0x1da4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1db4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dc4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dd4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1de4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1df4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d08, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d18, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d28, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d38, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d48, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d58, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d68, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d78, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d88, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d98, 0x00000000); + nv_mthd(dev, 0xa097, 0x1da8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1db8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dc8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dd8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1de8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1df8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d0c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d1c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d2c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d3c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d4c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d5c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d6c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d7c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1d9c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dac, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dbc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dcc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ddc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dec, 0x00000000); + nv_mthd(dev, 0xa097, 0x1dfc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f00, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f08, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f10, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f18, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f20, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f28, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f30, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f38, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f40, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f48, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f50, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f58, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f60, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f68, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f70, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f78, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f04, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f0c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f14, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f1c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f24, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f2c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f34, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f3c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f44, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f4c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f54, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f5c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f64, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f6c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f74, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f7c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f80, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f88, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f90, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f98, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fa0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fa8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fb0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fb8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fc0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fc8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fd0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fd8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fe0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fe8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ff0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ff8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f84, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f94, 0x00000000); + nv_mthd(dev, 0xa097, 0x1f9c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fa4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fac, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fb4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fbc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fc4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fcc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fd4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fdc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fe4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1fec, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ff4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1ffc, 0x00000000); + nv_mthd(dev, 0xa097, 0x2000, 0x00000000); + nv_mthd(dev, 0xa097, 0x2040, 0x00000011); + nv_mthd(dev, 0xa097, 0x2080, 0x00000020); + nv_mthd(dev, 0xa097, 0x20c0, 0x00000030); + nv_mthd(dev, 0xa097, 0x2100, 0x00000040); + nv_mthd(dev, 0xa097, 0x2140, 0x00000051); + nv_mthd(dev, 0xa097, 0x200c, 0x00000001); + nv_mthd(dev, 0xa097, 0x204c, 0x00000001); + nv_mthd(dev, 0xa097, 0x208c, 0x00000001); + nv_mthd(dev, 0xa097, 0x20cc, 0x00000001); + nv_mthd(dev, 0xa097, 0x210c, 0x00000001); + nv_mthd(dev, 0xa097, 0x214c, 0x00000001); + nv_mthd(dev, 0xa097, 0x2010, 0x00000000); + nv_mthd(dev, 0xa097, 0x2050, 0x00000000); + nv_mthd(dev, 0xa097, 0x2090, 0x00000001); + nv_mthd(dev, 0xa097, 0x20d0, 0x00000002); + nv_mthd(dev, 0xa097, 0x2110, 0x00000003); + nv_mthd(dev, 0xa097, 0x2150, 0x00000004); + nv_mthd(dev, 0xa097, 0x0380, 0x00000000); + nv_mthd(dev, 0xa097, 0x03a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x03c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x03e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0384, 0x00000000); + nv_mthd(dev, 0xa097, 0x03a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x03c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x03e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0388, 0x00000000); + nv_mthd(dev, 0xa097, 0x03a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x03c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x03e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x038c, 0x00000000); + nv_mthd(dev, 0xa097, 0x03ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x03cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x03ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x0700, 0x00000000); + nv_mthd(dev, 0xa097, 0x0710, 0x00000000); + nv_mthd(dev, 0xa097, 0x0720, 0x00000000); + nv_mthd(dev, 0xa097, 0x0730, 0x00000000); + nv_mthd(dev, 0xa097, 0x0704, 0x00000000); + nv_mthd(dev, 0xa097, 0x0714, 0x00000000); + nv_mthd(dev, 0xa097, 0x0724, 0x00000000); + nv_mthd(dev, 0xa097, 0x0734, 0x00000000); + nv_mthd(dev, 0xa097, 0x0708, 0x00000000); + nv_mthd(dev, 0xa097, 0x0718, 0x00000000); + nv_mthd(dev, 0xa097, 0x0728, 0x00000000); + nv_mthd(dev, 0xa097, 0x0738, 0x00000000); + nv_mthd(dev, 0xa097, 0x2800, 0x00000000); + nv_mthd(dev, 0xa097, 0x2804, 0x00000000); + nv_mthd(dev, 0xa097, 0x2808, 0x00000000); + nv_mthd(dev, 0xa097, 0x280c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2810, 0x00000000); + nv_mthd(dev, 0xa097, 0x2814, 0x00000000); + nv_mthd(dev, 0xa097, 0x2818, 0x00000000); + nv_mthd(dev, 0xa097, 0x281c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2820, 0x00000000); + nv_mthd(dev, 0xa097, 0x2824, 0x00000000); + nv_mthd(dev, 0xa097, 0x2828, 0x00000000); + nv_mthd(dev, 0xa097, 0x282c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2830, 0x00000000); + nv_mthd(dev, 0xa097, 0x2834, 0x00000000); + nv_mthd(dev, 0xa097, 0x2838, 0x00000000); + nv_mthd(dev, 0xa097, 0x283c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2840, 0x00000000); + nv_mthd(dev, 0xa097, 0x2844, 0x00000000); + nv_mthd(dev, 0xa097, 0x2848, 0x00000000); + nv_mthd(dev, 0xa097, 0x284c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2850, 0x00000000); + nv_mthd(dev, 0xa097, 0x2854, 0x00000000); + nv_mthd(dev, 0xa097, 0x2858, 0x00000000); + nv_mthd(dev, 0xa097, 0x285c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2860, 0x00000000); + nv_mthd(dev, 0xa097, 0x2864, 0x00000000); + nv_mthd(dev, 0xa097, 0x2868, 0x00000000); + nv_mthd(dev, 0xa097, 0x286c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2870, 0x00000000); + nv_mthd(dev, 0xa097, 0x2874, 0x00000000); + nv_mthd(dev, 0xa097, 0x2878, 0x00000000); + nv_mthd(dev, 0xa097, 0x287c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2880, 0x00000000); + nv_mthd(dev, 0xa097, 0x2884, 0x00000000); + nv_mthd(dev, 0xa097, 0x2888, 0x00000000); + nv_mthd(dev, 0xa097, 0x288c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2890, 0x00000000); + nv_mthd(dev, 0xa097, 0x2894, 0x00000000); + nv_mthd(dev, 0xa097, 0x2898, 0x00000000); + nv_mthd(dev, 0xa097, 0x289c, 0x00000000); + nv_mthd(dev, 0xa097, 0x28a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x28a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x28a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x28ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x28b0, 0x00000000); + nv_mthd(dev, 0xa097, 0x28b4, 0x00000000); + nv_mthd(dev, 0xa097, 0x28b8, 0x00000000); + nv_mthd(dev, 0xa097, 0x28bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x28c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x28c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x28c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x28cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x28d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x28d4, 0x00000000); + nv_mthd(dev, 0xa097, 0x28d8, 0x00000000); + nv_mthd(dev, 0xa097, 0x28dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x28e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x28e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x28e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x28ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x28f0, 0x00000000); + nv_mthd(dev, 0xa097, 0x28f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x28f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x28fc, 0x00000000); + nv_mthd(dev, 0xa097, 0x2900, 0x00000000); + nv_mthd(dev, 0xa097, 0x2904, 0x00000000); + nv_mthd(dev, 0xa097, 0x2908, 0x00000000); + nv_mthd(dev, 0xa097, 0x290c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2910, 0x00000000); + nv_mthd(dev, 0xa097, 0x2914, 0x00000000); + nv_mthd(dev, 0xa097, 0x2918, 0x00000000); + nv_mthd(dev, 0xa097, 0x291c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2920, 0x00000000); + nv_mthd(dev, 0xa097, 0x2924, 0x00000000); + nv_mthd(dev, 0xa097, 0x2928, 0x00000000); + nv_mthd(dev, 0xa097, 0x292c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2930, 0x00000000); + nv_mthd(dev, 0xa097, 0x2934, 0x00000000); + nv_mthd(dev, 0xa097, 0x2938, 0x00000000); + nv_mthd(dev, 0xa097, 0x293c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2940, 0x00000000); + nv_mthd(dev, 0xa097, 0x2944, 0x00000000); + nv_mthd(dev, 0xa097, 0x2948, 0x00000000); + nv_mthd(dev, 0xa097, 0x294c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2950, 0x00000000); + nv_mthd(dev, 0xa097, 0x2954, 0x00000000); + nv_mthd(dev, 0xa097, 0x2958, 0x00000000); + nv_mthd(dev, 0xa097, 0x295c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2960, 0x00000000); + nv_mthd(dev, 0xa097, 0x2964, 0x00000000); + nv_mthd(dev, 0xa097, 0x2968, 0x00000000); + nv_mthd(dev, 0xa097, 0x296c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2970, 0x00000000); + nv_mthd(dev, 0xa097, 0x2974, 0x00000000); + nv_mthd(dev, 0xa097, 0x2978, 0x00000000); + nv_mthd(dev, 0xa097, 0x297c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2980, 0x00000000); + nv_mthd(dev, 0xa097, 0x2984, 0x00000000); + nv_mthd(dev, 0xa097, 0x2988, 0x00000000); + nv_mthd(dev, 0xa097, 0x298c, 0x00000000); + nv_mthd(dev, 0xa097, 0x2990, 0x00000000); + nv_mthd(dev, 0xa097, 0x2994, 0x00000000); + nv_mthd(dev, 0xa097, 0x2998, 0x00000000); + nv_mthd(dev, 0xa097, 0x299c, 0x00000000); + nv_mthd(dev, 0xa097, 0x29a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x29a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x29a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x29ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x29b0, 0x00000000); + nv_mthd(dev, 0xa097, 0x29b4, 0x00000000); + nv_mthd(dev, 0xa097, 0x29b8, 0x00000000); + nv_mthd(dev, 0xa097, 0x29bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x29c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x29c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x29c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x29cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x29d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x29d4, 0x00000000); + nv_mthd(dev, 0xa097, 0x29d8, 0x00000000); + nv_mthd(dev, 0xa097, 0x29dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x29e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x29e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x29e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x29ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x29f0, 0x00000000); + nv_mthd(dev, 0xa097, 0x29f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x29f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x29fc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a00, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a20, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a40, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a60, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a80, 0x00000000); + nv_mthd(dev, 0xa097, 0x0aa0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ac0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ae0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b00, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b20, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b40, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b60, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b80, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ba0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bc0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0be0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a04, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a24, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a44, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a64, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a84, 0x00000000); + nv_mthd(dev, 0xa097, 0x0aa4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ac4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ae4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b04, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b24, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b44, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b64, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b84, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ba4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bc4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0be4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a08, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a28, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a48, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a68, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a88, 0x00000000); + nv_mthd(dev, 0xa097, 0x0aa8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ac8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ae8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b08, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b28, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b48, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b68, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b88, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ba8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bc8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0be8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a0c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a2c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a4c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a6c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0aac, 0x00000000); + nv_mthd(dev, 0xa097, 0x0acc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0aec, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b0c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b2c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b4c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b6c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bac, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bcc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bec, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a10, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a30, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a50, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a70, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a90, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ab0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ad0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0af0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b10, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b30, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b50, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b70, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b90, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bb0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bd0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bf0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a14, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a34, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a54, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a74, 0x00000000); + nv_mthd(dev, 0xa097, 0x0a94, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ab4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ad4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0af4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b14, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b34, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b54, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b74, 0x00000000); + nv_mthd(dev, 0xa097, 0x0b94, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bb4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bd4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0bf4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c00, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c10, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c20, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c30, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c40, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c50, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c60, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c70, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c80, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c90, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ca0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cb0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cc0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cd0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ce0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cf0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c04, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c14, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c24, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c34, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c44, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c54, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c64, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c74, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c84, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c94, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ca4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cb4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cc4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cd4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ce4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cf4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c08, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c18, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c28, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c38, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c48, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c58, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c68, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c78, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c88, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c98, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ca8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cb8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cc8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cd8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ce8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0cf8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0c0c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c1c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c2c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c3c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c4c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c5c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c6c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c7c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c8c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0c9c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0cac, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0cbc, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0ccc, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0cdc, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0cec, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0cfc, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0d00, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d08, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d10, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d18, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d20, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d28, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d30, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d38, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d04, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d0c, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d14, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d1c, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d24, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d2c, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d34, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d3c, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e00, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e10, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e20, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e30, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e40, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e50, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e60, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e70, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e80, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e90, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ea0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0eb0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ec0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ed0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ee0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ef0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0e04, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e14, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e24, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e34, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e44, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e54, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e64, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e74, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e84, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e94, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ea4, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0eb4, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ec4, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ed4, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ee4, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ef4, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e08, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e18, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e28, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e38, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e48, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e58, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e68, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e78, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e88, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0e98, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ea8, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0eb8, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ec8, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ed8, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ee8, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0ef8, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d40, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d48, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d50, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d58, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d44, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d4c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d54, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d5c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1e00, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e20, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e40, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e60, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e80, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ea0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ec0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ee0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e04, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e24, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e44, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e64, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e84, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ea4, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ec4, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ee4, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e08, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e28, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e48, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e68, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e88, 0x00000002); + nv_mthd(dev, 0xa097, 0x1ea8, 0x00000002); + nv_mthd(dev, 0xa097, 0x1ec8, 0x00000002); + nv_mthd(dev, 0xa097, 0x1ee8, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e0c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e2c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e4c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e6c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e8c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1eac, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ecc, 0x00000001); + nv_mthd(dev, 0xa097, 0x1eec, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e10, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e30, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e50, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e70, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e90, 0x00000001); + nv_mthd(dev, 0xa097, 0x1eb0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ed0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ef0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e14, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e34, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e54, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e74, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e94, 0x00000002); + nv_mthd(dev, 0xa097, 0x1eb4, 0x00000002); + nv_mthd(dev, 0xa097, 0x1ed4, 0x00000002); + nv_mthd(dev, 0xa097, 0x1ef4, 0x00000002); + nv_mthd(dev, 0xa097, 0x1e18, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e38, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e58, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e78, 0x00000001); + nv_mthd(dev, 0xa097, 0x1e98, 0x00000001); + nv_mthd(dev, 0xa097, 0x1eb8, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ed8, 0x00000001); + nv_mthd(dev, 0xa097, 0x1ef8, 0x00000001); + nv_mthd(dev, 0xa097, 0x3400, 0x00000000); + nv_mthd(dev, 0xa097, 0x3404, 0x00000000); + nv_mthd(dev, 0xa097, 0x3408, 0x00000000); + nv_mthd(dev, 0xa097, 0x340c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3410, 0x00000000); + nv_mthd(dev, 0xa097, 0x3414, 0x00000000); + nv_mthd(dev, 0xa097, 0x3418, 0x00000000); + nv_mthd(dev, 0xa097, 0x341c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3420, 0x00000000); + nv_mthd(dev, 0xa097, 0x3424, 0x00000000); + nv_mthd(dev, 0xa097, 0x3428, 0x00000000); + nv_mthd(dev, 0xa097, 0x342c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3430, 0x00000000); + nv_mthd(dev, 0xa097, 0x3434, 0x00000000); + nv_mthd(dev, 0xa097, 0x3438, 0x00000000); + nv_mthd(dev, 0xa097, 0x343c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3440, 0x00000000); + nv_mthd(dev, 0xa097, 0x3444, 0x00000000); + nv_mthd(dev, 0xa097, 0x3448, 0x00000000); + nv_mthd(dev, 0xa097, 0x344c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3450, 0x00000000); + nv_mthd(dev, 0xa097, 0x3454, 0x00000000); + nv_mthd(dev, 0xa097, 0x3458, 0x00000000); + nv_mthd(dev, 0xa097, 0x345c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3460, 0x00000000); + nv_mthd(dev, 0xa097, 0x3464, 0x00000000); + nv_mthd(dev, 0xa097, 0x3468, 0x00000000); + nv_mthd(dev, 0xa097, 0x346c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3470, 0x00000000); + nv_mthd(dev, 0xa097, 0x3474, 0x00000000); + nv_mthd(dev, 0xa097, 0x3478, 0x00000000); + nv_mthd(dev, 0xa097, 0x347c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3480, 0x00000000); + nv_mthd(dev, 0xa097, 0x3484, 0x00000000); + nv_mthd(dev, 0xa097, 0x3488, 0x00000000); + nv_mthd(dev, 0xa097, 0x348c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3490, 0x00000000); + nv_mthd(dev, 0xa097, 0x3494, 0x00000000); + nv_mthd(dev, 0xa097, 0x3498, 0x00000000); + nv_mthd(dev, 0xa097, 0x349c, 0x00000000); + nv_mthd(dev, 0xa097, 0x34a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x34a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x34a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x34ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x34b0, 0x00000000); + nv_mthd(dev, 0xa097, 0x34b4, 0x00000000); + nv_mthd(dev, 0xa097, 0x34b8, 0x00000000); + nv_mthd(dev, 0xa097, 0x34bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x34c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x34c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x34c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x34cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x34d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x34d4, 0x00000000); + nv_mthd(dev, 0xa097, 0x34d8, 0x00000000); + nv_mthd(dev, 0xa097, 0x34dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x34e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x34e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x34e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x34ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x34f0, 0x00000000); + nv_mthd(dev, 0xa097, 0x34f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x34f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x34fc, 0x00000000); + nv_mthd(dev, 0xa097, 0x3500, 0x00000000); + nv_mthd(dev, 0xa097, 0x3504, 0x00000000); + nv_mthd(dev, 0xa097, 0x3508, 0x00000000); + nv_mthd(dev, 0xa097, 0x350c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3510, 0x00000000); + nv_mthd(dev, 0xa097, 0x3514, 0x00000000); + nv_mthd(dev, 0xa097, 0x3518, 0x00000000); + nv_mthd(dev, 0xa097, 0x351c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3520, 0x00000000); + nv_mthd(dev, 0xa097, 0x3524, 0x00000000); + nv_mthd(dev, 0xa097, 0x3528, 0x00000000); + nv_mthd(dev, 0xa097, 0x352c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3530, 0x00000000); + nv_mthd(dev, 0xa097, 0x3534, 0x00000000); + nv_mthd(dev, 0xa097, 0x3538, 0x00000000); + nv_mthd(dev, 0xa097, 0x353c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3540, 0x00000000); + nv_mthd(dev, 0xa097, 0x3544, 0x00000000); + nv_mthd(dev, 0xa097, 0x3548, 0x00000000); + nv_mthd(dev, 0xa097, 0x354c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3550, 0x00000000); + nv_mthd(dev, 0xa097, 0x3554, 0x00000000); + nv_mthd(dev, 0xa097, 0x3558, 0x00000000); + nv_mthd(dev, 0xa097, 0x355c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3560, 0x00000000); + nv_mthd(dev, 0xa097, 0x3564, 0x00000000); + nv_mthd(dev, 0xa097, 0x3568, 0x00000000); + nv_mthd(dev, 0xa097, 0x356c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3570, 0x00000000); + nv_mthd(dev, 0xa097, 0x3574, 0x00000000); + nv_mthd(dev, 0xa097, 0x3578, 0x00000000); + nv_mthd(dev, 0xa097, 0x357c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3580, 0x00000000); + nv_mthd(dev, 0xa097, 0x3584, 0x00000000); + nv_mthd(dev, 0xa097, 0x3588, 0x00000000); + nv_mthd(dev, 0xa097, 0x358c, 0x00000000); + nv_mthd(dev, 0xa097, 0x3590, 0x00000000); + nv_mthd(dev, 0xa097, 0x3594, 0x00000000); + nv_mthd(dev, 0xa097, 0x3598, 0x00000000); + nv_mthd(dev, 0xa097, 0x359c, 0x00000000); + nv_mthd(dev, 0xa097, 0x35a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x35a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x35a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x35ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x35b0, 0x00000000); + nv_mthd(dev, 0xa097, 0x35b4, 0x00000000); + nv_mthd(dev, 0xa097, 0x35b8, 0x00000000); + nv_mthd(dev, 0xa097, 0x35bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x35c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x35c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x35c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x35cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x35d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x35d4, 0x00000000); + nv_mthd(dev, 0xa097, 0x35d8, 0x00000000); + nv_mthd(dev, 0xa097, 0x35dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x35e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x35e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x35e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x35ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x35f0, 0x00000000); + nv_mthd(dev, 0xa097, 0x35f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x35f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x35fc, 0x00000000); + nv_mthd(dev, 0xa097, 0x030c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1944, 0x00000000); + nv_mthd(dev, 0xa097, 0x1514, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d68, 0x0000ffff); + nv_mthd(dev, 0xa097, 0x121c, 0x0fac6881); + nv_mthd(dev, 0xa097, 0x0fac, 0x00000001); + nv_mthd(dev, 0xa097, 0x1538, 0x00000001); + nv_mthd(dev, 0xa097, 0x0fe0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0fe4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0fe8, 0x00000014); + nv_mthd(dev, 0xa097, 0x0fec, 0x00000040); + nv_mthd(dev, 0xa097, 0x0ff0, 0x00000000); + nv_mthd(dev, 0xa097, 0x179c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1228, 0x00000400); + nv_mthd(dev, 0xa097, 0x122c, 0x00000300); + nv_mthd(dev, 0xa097, 0x1230, 0x00010001); + nv_mthd(dev, 0xa097, 0x07f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x15b4, 0x00000001); + nv_mthd(dev, 0xa097, 0x15cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1534, 0x00000000); + nv_mthd(dev, 0xa097, 0x0fb0, 0x00000000); + nv_mthd(dev, 0xa097, 0x15d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x153c, 0x00000000); + nv_mthd(dev, 0xa097, 0x16b4, 0x00000003); + nv_mthd(dev, 0xa097, 0x0fbc, 0x0000ffff); + nv_mthd(dev, 0xa097, 0x0fc0, 0x0000ffff); + nv_mthd(dev, 0xa097, 0x0fc4, 0x0000ffff); + nv_mthd(dev, 0xa097, 0x0fc8, 0x0000ffff); + nv_mthd(dev, 0xa097, 0x0df8, 0x00000000); + nv_mthd(dev, 0xa097, 0x0dfc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1948, 0x00000000); + nv_mthd(dev, 0xa097, 0x1970, 0x00000001); + nv_mthd(dev, 0xa097, 0x161c, 0x000009f0); + nv_mthd(dev, 0xa097, 0x0dcc, 0x00000010); + nv_mthd(dev, 0xa097, 0x163c, 0x00000000); + nv_mthd(dev, 0xa097, 0x15e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1160, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1164, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1168, 0x25e00040); + nv_mthd(dev, 0xa097, 0x116c, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1170, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1174, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1178, 0x25e00040); + nv_mthd(dev, 0xa097, 0x117c, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1180, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1184, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1188, 0x25e00040); + nv_mthd(dev, 0xa097, 0x118c, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1190, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1194, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1198, 0x25e00040); + nv_mthd(dev, 0xa097, 0x119c, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11a0, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11a4, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11a8, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11ac, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11b0, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11b4, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11b8, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11bc, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11c0, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11c4, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11c8, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11cc, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11d0, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11d4, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11d8, 0x25e00040); + nv_mthd(dev, 0xa097, 0x11dc, 0x25e00040); + nv_mthd(dev, 0xa097, 0x1880, 0x00000000); + nv_mthd(dev, 0xa097, 0x1884, 0x00000000); + nv_mthd(dev, 0xa097, 0x1888, 0x00000000); + nv_mthd(dev, 0xa097, 0x188c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1890, 0x00000000); + nv_mthd(dev, 0xa097, 0x1894, 0x00000000); + nv_mthd(dev, 0xa097, 0x1898, 0x00000000); + nv_mthd(dev, 0xa097, 0x189c, 0x00000000); + nv_mthd(dev, 0xa097, 0x18a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x18a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x18a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x18ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x18b0, 0x00000000); + nv_mthd(dev, 0xa097, 0x18b4, 0x00000000); + nv_mthd(dev, 0xa097, 0x18b8, 0x00000000); + nv_mthd(dev, 0xa097, 0x18bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x18c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x18c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x18c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x18cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x18d0, 0x00000000); + nv_mthd(dev, 0xa097, 0x18d4, 0x00000000); + nv_mthd(dev, 0xa097, 0x18d8, 0x00000000); + nv_mthd(dev, 0xa097, 0x18dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x18e0, 0x00000000); + nv_mthd(dev, 0xa097, 0x18e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x18e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x18ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x18f0, 0x00000000); + nv_mthd(dev, 0xa097, 0x18f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x18f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x18fc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f84, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f88, 0x00000000); + nv_mthd(dev, 0xa097, 0x17c8, 0x00000000); + nv_mthd(dev, 0xa097, 0x17cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x17d0, 0x000000ff); + nv_mthd(dev, 0xa097, 0x17d4, 0xffffffff); + nv_mthd(dev, 0xa097, 0x17d8, 0x00000002); + nv_mthd(dev, 0xa097, 0x17dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x15f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x15f8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1434, 0x00000000); + nv_mthd(dev, 0xa097, 0x1438, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d74, 0x00000000); + nv_mthd(dev, 0xa097, 0x0dec, 0x00000001); + nv_mthd(dev, 0xa097, 0x13a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1318, 0x00000001); + nv_mthd(dev, 0xa097, 0x1644, 0x00000000); + nv_mthd(dev, 0xa097, 0x0748, 0x00000000); + nv_mthd(dev, 0xa097, 0x0de8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1648, 0x00000000); + nv_mthd(dev, 0xa097, 0x12a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x1120, 0x00000000); + nv_mthd(dev, 0xa097, 0x1124, 0x00000000); + nv_mthd(dev, 0xa097, 0x1128, 0x00000000); + nv_mthd(dev, 0xa097, 0x112c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1118, 0x00000000); + nv_mthd(dev, 0xa097, 0x164c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1658, 0x00000000); + nv_mthd(dev, 0xa097, 0x1910, 0x00000290); + nv_mthd(dev, 0xa097, 0x1518, 0x00000000); + nv_mthd(dev, 0xa097, 0x165c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1520, 0x00000000); + nv_mthd(dev, 0xa097, 0x1604, 0x00000000); + nv_mthd(dev, 0xa097, 0x1570, 0x00000000); + nv_mthd(dev, 0xa097, 0x13b0, 0x3f800000); + nv_mthd(dev, 0xa097, 0x13b4, 0x3f800000); + nv_mthd(dev, 0xa097, 0x020c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1670, 0x30201000); + nv_mthd(dev, 0xa097, 0x1674, 0x70605040); + nv_mthd(dev, 0xa097, 0x1678, 0xb8a89888); + nv_mthd(dev, 0xa097, 0x167c, 0xf8e8d8c8); + nv_mthd(dev, 0xa097, 0x166c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1680, 0x00ffff00); + nv_mthd(dev, 0xa097, 0x12d0, 0x00000003); + nv_mthd(dev, 0xa097, 0x12d4, 0x00000002); + nv_mthd(dev, 0xa097, 0x1684, 0x00000000); + nv_mthd(dev, 0xa097, 0x1688, 0x00000000); + nv_mthd(dev, 0xa097, 0x0dac, 0x00001b02); + nv_mthd(dev, 0xa097, 0x0db0, 0x00001b02); + nv_mthd(dev, 0xa097, 0x0db4, 0x00000000); + nv_mthd(dev, 0xa097, 0x168c, 0x00000000); + nv_mthd(dev, 0xa097, 0x15bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x156c, 0x00000000); + nv_mthd(dev, 0xa097, 0x187c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1110, 0x00000001); + nv_mthd(dev, 0xa097, 0x0dc0, 0x00000000); + nv_mthd(dev, 0xa097, 0x0dc4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0dc8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1234, 0x00000000); + nv_mthd(dev, 0xa097, 0x1690, 0x00000000); + nv_mthd(dev, 0xa097, 0x12ac, 0x00000001); + nv_mthd(dev, 0xa097, 0x0790, 0x00000000); + nv_mthd(dev, 0xa097, 0x0794, 0x00000000); + nv_mthd(dev, 0xa097, 0x0798, 0x00000000); + nv_mthd(dev, 0xa097, 0x079c, 0x00000000); + nv_mthd(dev, 0xa097, 0x07a0, 0x00000000); + nv_mthd(dev, 0xa097, 0x077c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1000, 0x00000010); + nv_mthd(dev, 0xa097, 0x10fc, 0x00000000); + nv_mthd(dev, 0xa097, 0x1290, 0x00000000); + nv_mthd(dev, 0xa097, 0x0218, 0x00000010); + nv_mthd(dev, 0xa097, 0x12d8, 0x00000000); + nv_mthd(dev, 0xa097, 0x12dc, 0x00000010); + nv_mthd(dev, 0xa097, 0x0d94, 0x00000001); + nv_mthd(dev, 0xa097, 0x155c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1560, 0x00000000); + nv_mthd(dev, 0xa097, 0x1564, 0x00000fff); + nv_mthd(dev, 0xa097, 0x1574, 0x00000000); + nv_mthd(dev, 0xa097, 0x1578, 0x00000000); + nv_mthd(dev, 0xa097, 0x157c, 0x000fffff); + nv_mthd(dev, 0xa097, 0x1354, 0x00000000); + nv_mthd(dev, 0xa097, 0x1610, 0x00000012); + nv_mthd(dev, 0xa097, 0x1608, 0x00000000); + nv_mthd(dev, 0xa097, 0x160c, 0x00000000); + nv_mthd(dev, 0xa097, 0x260c, 0x00000000); + nv_mthd(dev, 0xa097, 0x07ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x162c, 0x00000003); + nv_mthd(dev, 0xa097, 0x0210, 0x00000000); + nv_mthd(dev, 0xa097, 0x0320, 0x00000000); + nv_mthd(dev, 0xa097, 0x0324, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0328, 0x3f800000); + nv_mthd(dev, 0xa097, 0x032c, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0330, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0334, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0338, 0x3f800000); + nv_mthd(dev, 0xa097, 0x0750, 0x00000000); + nv_mthd(dev, 0xa097, 0x0760, 0x39291909); + nv_mthd(dev, 0xa097, 0x0764, 0x79695949); + nv_mthd(dev, 0xa097, 0x0768, 0xb9a99989); + nv_mthd(dev, 0xa097, 0x076c, 0xf9e9d9c9); + nv_mthd(dev, 0xa097, 0x0770, 0x30201000); + nv_mthd(dev, 0xa097, 0x0774, 0x70605040); + nv_mthd(dev, 0xa097, 0x0778, 0x00009080); + nv_mthd(dev, 0xa097, 0x0780, 0x39291909); + nv_mthd(dev, 0xa097, 0x0784, 0x79695949); + nv_mthd(dev, 0xa097, 0x0788, 0xb9a99989); + nv_mthd(dev, 0xa097, 0x078c, 0xf9e9d9c9); + nv_mthd(dev, 0xa097, 0x07d0, 0x30201000); + nv_mthd(dev, 0xa097, 0x07d4, 0x70605040); + nv_mthd(dev, 0xa097, 0x07d8, 0x00009080); + nv_mthd(dev, 0xa097, 0x037c, 0x00000001); + nv_mthd(dev, 0xa097, 0x0740, 0x00000000); + nv_mthd(dev, 0xa097, 0x0744, 0x00000000); + nv_mthd(dev, 0xa097, 0x2600, 0x00000000); + nv_mthd(dev, 0xa097, 0x1918, 0x00000000); + nv_mthd(dev, 0xa097, 0x191c, 0x00000900); + nv_mthd(dev, 0xa097, 0x1920, 0x00000405); + nv_mthd(dev, 0xa097, 0x1308, 0x00000001); + nv_mthd(dev, 0xa097, 0x1924, 0x00000000); + nv_mthd(dev, 0xa097, 0x13ac, 0x00000000); + nv_mthd(dev, 0xa097, 0x192c, 0x00000001); + nv_mthd(dev, 0xa097, 0x193c, 0x00002c1c); + nv_mthd(dev, 0xa097, 0x0d7c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x02c0, 0x00000001); + nv_mthd(dev, 0xa097, 0x1510, 0x00000000); + nv_mthd(dev, 0xa097, 0x1940, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ff4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0ff8, 0x00000000); + nv_mthd(dev, 0xa097, 0x194c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1950, 0x00000000); + nv_mthd(dev, 0xa097, 0x1968, 0x00000000); + nv_mthd(dev, 0xa097, 0x1590, 0x0000003f); + nv_mthd(dev, 0xa097, 0x07e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x07ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x07f0, 0x00000000); + nv_mthd(dev, 0xa097, 0x07f4, 0x00000000); + nv_mthd(dev, 0xa097, 0x196c, 0x00000011); + nv_mthd(dev, 0xa097, 0x02e4, 0x0000b001); + nv_mthd(dev, 0xa097, 0x036c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0370, 0x00000000); + nv_mthd(dev, 0xa097, 0x197c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0fcc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0fd0, 0x00000000); + nv_mthd(dev, 0xa097, 0x02d8, 0x00000040); + nv_mthd(dev, 0xa097, 0x1980, 0x00000080); + nv_mthd(dev, 0xa097, 0x1504, 0x00000080); + nv_mthd(dev, 0xa097, 0x1984, 0x00000000); + nv_mthd(dev, 0xa097, 0x0300, 0x00000001); + nv_mthd(dev, 0xa097, 0x13a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x12ec, 0x00000000); + nv_mthd(dev, 0xa097, 0x1310, 0x00000000); + nv_mthd(dev, 0xa097, 0x1314, 0x00000001); + nv_mthd(dev, 0xa097, 0x1380, 0x00000000); + nv_mthd(dev, 0xa097, 0x1384, 0x00000001); + nv_mthd(dev, 0xa097, 0x1388, 0x00000001); + nv_mthd(dev, 0xa097, 0x138c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1390, 0x00000001); + nv_mthd(dev, 0xa097, 0x1394, 0x00000000); + nv_mthd(dev, 0xa097, 0x139c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1398, 0x00000000); + nv_mthd(dev, 0xa097, 0x1594, 0x00000000); + nv_mthd(dev, 0xa097, 0x1598, 0x00000001); + nv_mthd(dev, 0xa097, 0x159c, 0x00000001); + nv_mthd(dev, 0xa097, 0x15a0, 0x00000001); + nv_mthd(dev, 0xa097, 0x15a4, 0x00000001); + nv_mthd(dev, 0xa097, 0x0f54, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f58, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f5c, 0x00000000); + nv_mthd(dev, 0xa097, 0x19bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f9c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0fa0, 0x00000000); + nv_mthd(dev, 0xa097, 0x12cc, 0x00000000); + nv_mthd(dev, 0xa097, 0x12e8, 0x00000000); + nv_mthd(dev, 0xa097, 0x130c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1360, 0x00000000); + nv_mthd(dev, 0xa097, 0x1364, 0x00000000); + nv_mthd(dev, 0xa097, 0x1368, 0x00000000); + nv_mthd(dev, 0xa097, 0x136c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1370, 0x00000000); + nv_mthd(dev, 0xa097, 0x1374, 0x00000000); + nv_mthd(dev, 0xa097, 0x1378, 0x00000000); + nv_mthd(dev, 0xa097, 0x137c, 0x00000000); + nv_mthd(dev, 0xa097, 0x133c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1340, 0x00000001); + nv_mthd(dev, 0xa097, 0x1344, 0x00000002); + nv_mthd(dev, 0xa097, 0x1348, 0x00000001); + nv_mthd(dev, 0xa097, 0x134c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1350, 0x00000002); + nv_mthd(dev, 0xa097, 0x1358, 0x00000001); + nv_mthd(dev, 0xa097, 0x12e4, 0x00000000); + nv_mthd(dev, 0xa097, 0x131c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1320, 0x00000000); + nv_mthd(dev, 0xa097, 0x1324, 0x00000000); + nv_mthd(dev, 0xa097, 0x1328, 0x00000000); + nv_mthd(dev, 0xa097, 0x19c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x1140, 0x00000000); + nv_mthd(dev, 0xa097, 0x19c4, 0x00000000); + nv_mthd(dev, 0xa097, 0x19c8, 0x00001500); + nv_mthd(dev, 0xa097, 0x135c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f90, 0x00000000); + nv_mthd(dev, 0xa097, 0x19e0, 0x00000001); + nv_mthd(dev, 0xa097, 0x19e4, 0x00000001); + nv_mthd(dev, 0xa097, 0x19e8, 0x00000001); + nv_mthd(dev, 0xa097, 0x19ec, 0x00000001); + nv_mthd(dev, 0xa097, 0x19f0, 0x00000001); + nv_mthd(dev, 0xa097, 0x19f4, 0x00000001); + nv_mthd(dev, 0xa097, 0x19f8, 0x00000001); + nv_mthd(dev, 0xa097, 0x19fc, 0x00000001); + nv_mthd(dev, 0xa097, 0x19cc, 0x00000001); + nv_mthd(dev, 0xa097, 0x15b8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a00, 0x00001111); + nv_mthd(dev, 0xa097, 0x1a04, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a08, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a0c, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a10, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a14, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a18, 0x00000000); + nv_mthd(dev, 0xa097, 0x1a1c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d6c, 0xffff0000); + nv_mthd(dev, 0xa097, 0x0d70, 0xffff0000); + nv_mthd(dev, 0xa097, 0x10f8, 0x00001010); + nv_mthd(dev, 0xa097, 0x0d80, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d84, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d88, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d8c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0d90, 0x00000000); + nv_mthd(dev, 0xa097, 0x0da0, 0x00000000); + nv_mthd(dev, 0xa097, 0x07a4, 0x00000000); + nv_mthd(dev, 0xa097, 0x07a8, 0x00000000); + nv_mthd(dev, 0xa097, 0x1508, 0x80000000); + nv_mthd(dev, 0xa097, 0x150c, 0x40000000); + nv_mthd(dev, 0xa097, 0x1668, 0x00000000); + nv_mthd(dev, 0xa097, 0x0318, 0x00000008); + nv_mthd(dev, 0xa097, 0x031c, 0x00000008); + nv_mthd(dev, 0xa097, 0x0d9c, 0x00000001); + nv_mthd(dev, 0xa097, 0x0374, 0x00000000); + nv_mthd(dev, 0xa097, 0x0378, 0x00000020); + nv_mthd(dev, 0xa097, 0x07dc, 0x00000000); + nv_mthd(dev, 0xa097, 0x074c, 0x00000055); + nv_mthd(dev, 0xa097, 0x1420, 0x00000003); + nv_mthd(dev, 0xa097, 0x17bc, 0x00000000); + nv_mthd(dev, 0xa097, 0x17c0, 0x00000000); + nv_mthd(dev, 0xa097, 0x17c4, 0x00000001); + nv_mthd(dev, 0xa097, 0x1008, 0x00000008); + nv_mthd(dev, 0xa097, 0x100c, 0x00000040); + nv_mthd(dev, 0xa097, 0x1010, 0x0000012c); + nv_mthd(dev, 0xa097, 0x0d60, 0x00000040); + nv_mthd(dev, 0xa097, 0x075c, 0x00000003); + nv_mthd(dev, 0xa097, 0x1018, 0x00000020); + nv_mthd(dev, 0xa097, 0x101c, 0x00000001); + nv_mthd(dev, 0xa097, 0x1020, 0x00000020); + nv_mthd(dev, 0xa097, 0x1024, 0x00000001); + nv_mthd(dev, 0xa097, 0x1444, 0x00000000); + nv_mthd(dev, 0xa097, 0x1448, 0x00000000); + nv_mthd(dev, 0xa097, 0x144c, 0x00000000); + nv_mthd(dev, 0xa097, 0x0360, 0x20164010); + nv_mthd(dev, 0xa097, 0x0364, 0x00000020); + nv_mthd(dev, 0xa097, 0x0368, 0x00000000); + nv_mthd(dev, 0xa097, 0x0de4, 0x00000000); + nv_mthd(dev, 0xa097, 0x0204, 0x00000006); + nv_mthd(dev, 0xa097, 0x0208, 0x00000000); + nv_mthd(dev, 0xa097, 0x02cc, 0x003fffff); + nv_mthd(dev, 0xa097, 0x02d0, 0x003fffff); + nv_mthd(dev, 0xa097, 0x1220, 0x00000005); + nv_mthd(dev, 0xa097, 0x0fdc, 0x00000000); + nv_mthd(dev, 0xa097, 0x0f98, 0x00400008); + nv_mthd(dev, 0xa097, 0x1284, 0x08000080); + nv_mthd(dev, 0xa097, 0x1450, 0x00400008); + nv_mthd(dev, 0xa097, 0x1454, 0x08000080); + nv_mthd(dev, 0xa097, 0x0214, 0x00000000); +} + +static void +nve0_grctx_generate_902d(struct drm_device *dev) +{ + nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); + nv_mthd(dev, 0x902d, 0x0204, 0x00000001); + nv_mthd(dev, 0x902d, 0x0208, 0x00000020); + nv_mthd(dev, 0x902d, 0x020c, 0x00000001); + nv_mthd(dev, 0x902d, 0x0210, 0x00000000); + nv_mthd(dev, 0x902d, 0x0214, 0x00000080); + nv_mthd(dev, 0x902d, 0x0218, 0x00000100); + nv_mthd(dev, 0x902d, 0x021c, 0x00000100); + nv_mthd(dev, 0x902d, 0x0220, 0x00000000); + nv_mthd(dev, 0x902d, 0x0224, 0x00000000); + nv_mthd(dev, 0x902d, 0x0230, 0x000000cf); + nv_mthd(dev, 0x902d, 0x0234, 0x00000001); + nv_mthd(dev, 0x902d, 0x0238, 0x00000020); + nv_mthd(dev, 0x902d, 0x023c, 0x00000001); + nv_mthd(dev, 0x902d, 0x0244, 0x00000080); + nv_mthd(dev, 0x902d, 0x0248, 0x00000100); + nv_mthd(dev, 0x902d, 0x024c, 0x00000100); + nv_mthd(dev, 0x902d, 0x3410, 0x00000000); +} + +static void +nve0_graph_generate_unk40xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x404010, 0x0); + nv_wr32(dev, 0x404014, 0x0); + nv_wr32(dev, 0x404018, 0x0); + nv_wr32(dev, 0x40401c, 0x0); + nv_wr32(dev, 0x404020, 0x0); + nv_wr32(dev, 0x404024, 0xe000); + nv_wr32(dev, 0x404028, 0x0); + nv_wr32(dev, 0x4040a8, 0x0); + nv_wr32(dev, 0x4040ac, 0x0); + nv_wr32(dev, 0x4040b0, 0x0); + nv_wr32(dev, 0x4040b4, 0x0); + nv_wr32(dev, 0x4040b8, 0x0); + nv_wr32(dev, 0x4040bc, 0x0); + nv_wr32(dev, 0x4040c0, 0x0); + nv_wr32(dev, 0x4040c4, 0x0); + nv_wr32(dev, 0x4040c8, 0xf800008f); + nv_wr32(dev, 0x4040d0, 0x0); + nv_wr32(dev, 0x4040d4, 0x0); + nv_wr32(dev, 0x4040d8, 0x0); + nv_wr32(dev, 0x4040dc, 0x0); + nv_wr32(dev, 0x4040e0, 0x0); + nv_wr32(dev, 0x4040e4, 0x0); + nv_wr32(dev, 0x4040e8, 0x1000); + nv_wr32(dev, 0x4040f8, 0x0); + nv_wr32(dev, 0x404130, 0x0); + nv_wr32(dev, 0x404134, 0x0); + nv_wr32(dev, 0x404138, 0x20000040); + nv_wr32(dev, 0x404150, 0x2e); + nv_wr32(dev, 0x404154, 0x400); + nv_wr32(dev, 0x404158, 0x200); + nv_wr32(dev, 0x404164, 0x55); + nv_wr32(dev, 0x4041a0, 0x0); + nv_wr32(dev, 0x4041a4, 0x0); + nv_wr32(dev, 0x4041a8, 0x0); + nv_wr32(dev, 0x4041ac, 0x0); + nv_wr32(dev, 0x404200, 0x0); + nv_wr32(dev, 0x404204, 0x0); + nv_wr32(dev, 0x404208, 0x0); + nv_wr32(dev, 0x40420c, 0x0); +} + +static void +nve0_graph_generate_unk44xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x404404, 0x0); + nv_wr32(dev, 0x404408, 0x0); + nv_wr32(dev, 0x40440c, 0x0); + nv_wr32(dev, 0x404410, 0x0); + nv_wr32(dev, 0x404414, 0x0); + nv_wr32(dev, 0x404418, 0x0); + nv_wr32(dev, 0x40441c, 0x0); + nv_wr32(dev, 0x404420, 0x0); + nv_wr32(dev, 0x404424, 0x0); + nv_wr32(dev, 0x404428, 0x0); + nv_wr32(dev, 0x40442c, 0x0); + nv_wr32(dev, 0x404430, 0x0); + nv_wr32(dev, 0x404434, 0x0); + nv_wr32(dev, 0x404438, 0x0); + nv_wr32(dev, 0x404460, 0x0); + nv_wr32(dev, 0x404464, 0x0); + nv_wr32(dev, 0x404468, 0xffffff); + nv_wr32(dev, 0x40446c, 0x0); + nv_wr32(dev, 0x404480, 0x1); + nv_wr32(dev, 0x404498, 0x1); +} + +static void +nve0_graph_generate_unk46xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x404604, 0x14); + nv_wr32(dev, 0x404608, 0x0); + nv_wr32(dev, 0x40460c, 0x3fff); + nv_wr32(dev, 0x404610, 0x100); + nv_wr32(dev, 0x404618, 0x0); + nv_wr32(dev, 0x40461c, 0x0); + nv_wr32(dev, 0x404620, 0x0); + nv_wr32(dev, 0x404624, 0x0); + nv_wr32(dev, 0x40462c, 0x0); + nv_wr32(dev, 0x404630, 0x0); + nv_wr32(dev, 0x404640, 0x0); + nv_wr32(dev, 0x404654, 0x0); + nv_wr32(dev, 0x404660, 0x0); + nv_wr32(dev, 0x404678, 0x0); + nv_wr32(dev, 0x40467c, 0x2); + nv_wr32(dev, 0x404680, 0x0); + nv_wr32(dev, 0x404684, 0x0); + nv_wr32(dev, 0x404688, 0x0); + nv_wr32(dev, 0x40468c, 0x0); + nv_wr32(dev, 0x404690, 0x0); + nv_wr32(dev, 0x404694, 0x0); + nv_wr32(dev, 0x404698, 0x0); + nv_wr32(dev, 0x40469c, 0x0); + nv_wr32(dev, 0x4046a0, 0x7f0080); + nv_wr32(dev, 0x4046a4, 0x0); + nv_wr32(dev, 0x4046a8, 0x0); + nv_wr32(dev, 0x4046ac, 0x0); + nv_wr32(dev, 0x4046b0, 0x0); + nv_wr32(dev, 0x4046b4, 0x0); + nv_wr32(dev, 0x4046b8, 0x0); + nv_wr32(dev, 0x4046bc, 0x0); + nv_wr32(dev, 0x4046c0, 0x0); + nv_wr32(dev, 0x4046c8, 0x0); + nv_wr32(dev, 0x4046cc, 0x0); + nv_wr32(dev, 0x4046d0, 0x0); +} + +static void +nve0_graph_generate_unk47xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x404700, 0x0); + nv_wr32(dev, 0x404704, 0x0); + nv_wr32(dev, 0x404708, 0x0); + nv_wr32(dev, 0x404718, 0x0); + nv_wr32(dev, 0x40471c, 0x0); + nv_wr32(dev, 0x404720, 0x0); + nv_wr32(dev, 0x404724, 0x0); + nv_wr32(dev, 0x404728, 0x0); + nv_wr32(dev, 0x40472c, 0x0); + nv_wr32(dev, 0x404730, 0x0); + nv_wr32(dev, 0x404734, 0x100); + nv_wr32(dev, 0x404738, 0x0); + nv_wr32(dev, 0x40473c, 0x0); + nv_wr32(dev, 0x404744, 0x0); + nv_wr32(dev, 0x404748, 0x0); + nv_wr32(dev, 0x404754, 0x0); +} + +static void +nve0_graph_generate_unk58xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x405800, 0xf8000bf); + nv_wr32(dev, 0x405830, 0x2180648); + nv_wr32(dev, 0x405834, 0x8000000); + nv_wr32(dev, 0x405838, 0x0); + nv_wr32(dev, 0x405854, 0x0); + nv_wr32(dev, 0x405870, 0x1); + nv_wr32(dev, 0x405874, 0x1); + nv_wr32(dev, 0x405878, 0x1); + nv_wr32(dev, 0x40587c, 0x1); + nv_wr32(dev, 0x405a00, 0x0); + nv_wr32(dev, 0x405a04, 0x0); + nv_wr32(dev, 0x405a18, 0x0); + nv_wr32(dev, 0x405b00, 0x0); + nv_wr32(dev, 0x405b10, 0x1000); +} + +static void +nve0_graph_generate_unk60xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x406020, 0x4103c1); + nv_wr32(dev, 0x406028, 0x1); + nv_wr32(dev, 0x40602c, 0x1); + nv_wr32(dev, 0x406030, 0x1); + nv_wr32(dev, 0x406034, 0x1); +} + +static void +nve0_graph_generate_unk64xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x4064a8, 0x0); + nv_wr32(dev, 0x4064ac, 0x3fff); + nv_wr32(dev, 0x4064b4, 0x0); + nv_wr32(dev, 0x4064b8, 0x0); + nv_wr32(dev, 0x4064c0, 0x801a00f0); + nv_wr32(dev, 0x4064c4, 0x192ffff); + nv_wr32(dev, 0x4064c8, 0x1800600); + nv_wr32(dev, 0x4064cc, 0x0); + nv_wr32(dev, 0x4064d0, 0x0); + nv_wr32(dev, 0x4064d4, 0x0); + nv_wr32(dev, 0x4064d8, 0x0); + nv_wr32(dev, 0x4064dc, 0x0); + nv_wr32(dev, 0x4064e0, 0x0); + nv_wr32(dev, 0x4064e4, 0x0); + nv_wr32(dev, 0x4064e8, 0x0); + nv_wr32(dev, 0x4064ec, 0x0); + nv_wr32(dev, 0x4064fc, 0x22a); +} + +static void +nve0_graph_generate_unk70xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x407040, 0x0); +} + +static void +nve0_graph_generate_unk78xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x407804, 0x23); + nv_wr32(dev, 0x40780c, 0xa418820); + nv_wr32(dev, 0x407810, 0x62080e6); + nv_wr32(dev, 0x407814, 0x20398a4); + nv_wr32(dev, 0x407818, 0xe629062); + nv_wr32(dev, 0x40781c, 0xa418820); + nv_wr32(dev, 0x407820, 0xe6); + nv_wr32(dev, 0x4078bc, 0x103); +} + +static void +nve0_graph_generate_unk80xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x408000, 0x0); + nv_wr32(dev, 0x408004, 0x0); + nv_wr32(dev, 0x408008, 0x30); + nv_wr32(dev, 0x40800c, 0x0); + nv_wr32(dev, 0x408010, 0x0); + nv_wr32(dev, 0x408014, 0x69); + nv_wr32(dev, 0x408018, 0xe100e100); + nv_wr32(dev, 0x408064, 0x0); +} + +static void +nve0_graph_generate_unk88xx(struct drm_device *dev) +{ + nv_wr32(dev, 0x408800, 0x2802a3c); + nv_wr32(dev, 0x408804, 0x40); + nv_wr32(dev, 0x408808, 0x1043e005); + nv_wr32(dev, 0x408840, 0xb); + nv_wr32(dev, 0x408900, 0x3080b801); + nv_wr32(dev, 0x408904, 0x62000001); + nv_wr32(dev, 0x408908, 0xc8102f); + nv_wr32(dev, 0x408980, 0x11d); +} + +static void +nve0_graph_generate_gpc(struct drm_device *dev) +{ + nv_wr32(dev, 0x418380, 0x16); + nv_wr32(dev, 0x418400, 0x38004e00); + nv_wr32(dev, 0x418404, 0x71e0ffff); + nv_wr32(dev, 0x41840c, 0x1008); + nv_wr32(dev, 0x418410, 0xfff0fff); + nv_wr32(dev, 0x418414, 0x2200fff); + nv_wr32(dev, 0x418450, 0x0); + nv_wr32(dev, 0x418454, 0x0); + nv_wr32(dev, 0x418458, 0x0); + nv_wr32(dev, 0x41845c, 0x0); + nv_wr32(dev, 0x418460, 0x0); + nv_wr32(dev, 0x418464, 0x0); + nv_wr32(dev, 0x418468, 0x1); + nv_wr32(dev, 0x41846c, 0x0); + nv_wr32(dev, 0x418470, 0x0); + nv_wr32(dev, 0x418600, 0x1f); + nv_wr32(dev, 0x418684, 0xf); + nv_wr32(dev, 0x418700, 0x2); + nv_wr32(dev, 0x418704, 0x80); + nv_wr32(dev, 0x418708, 0x0); + nv_wr32(dev, 0x41870c, 0x0); + nv_wr32(dev, 0x418710, 0x0); + nv_wr32(dev, 0x418800, 0x7006860a); + nv_wr32(dev, 0x418808, 0x0); + nv_wr32(dev, 0x41880c, 0x0); + nv_wr32(dev, 0x418810, 0x0); + nv_wr32(dev, 0x418828, 0x44); + nv_wr32(dev, 0x418830, 0x10000001); + nv_wr32(dev, 0x4188d8, 0x8); + nv_wr32(dev, 0x4188e0, 0x1000000); + nv_wr32(dev, 0x4188e8, 0x0); + nv_wr32(dev, 0x4188ec, 0x0); + nv_wr32(dev, 0x4188f0, 0x0); + nv_wr32(dev, 0x4188f4, 0x0); + nv_wr32(dev, 0x4188f8, 0x0); + nv_wr32(dev, 0x4188fc, 0x20100018); + nv_wr32(dev, 0x41891c, 0xff00ff); + nv_wr32(dev, 0x418924, 0x0); + nv_wr32(dev, 0x418928, 0xffff00); + nv_wr32(dev, 0x41892c, 0xff00); + nv_wr32(dev, 0x418a00, 0x0); + nv_wr32(dev, 0x418a04, 0x0); + nv_wr32(dev, 0x418a08, 0x0); + nv_wr32(dev, 0x418a0c, 0x10000); + nv_wr32(dev, 0x418a10, 0x0); + nv_wr32(dev, 0x418a14, 0x0); + nv_wr32(dev, 0x418a18, 0x0); + nv_wr32(dev, 0x418a20, 0x0); + nv_wr32(dev, 0x418a24, 0x0); + nv_wr32(dev, 0x418a28, 0x0); + nv_wr32(dev, 0x418a2c, 0x10000); + nv_wr32(dev, 0x418a30, 0x0); + nv_wr32(dev, 0x418a34, 0x0); + nv_wr32(dev, 0x418a38, 0x0); + nv_wr32(dev, 0x418a40, 0x0); + nv_wr32(dev, 0x418a44, 0x0); + nv_wr32(dev, 0x418a48, 0x0); + nv_wr32(dev, 0x418a4c, 0x10000); + nv_wr32(dev, 0x418a50, 0x0); + nv_wr32(dev, 0x418a54, 0x0); + nv_wr32(dev, 0x418a58, 0x0); + nv_wr32(dev, 0x418a60, 0x0); + nv_wr32(dev, 0x418a64, 0x0); + nv_wr32(dev, 0x418a68, 0x0); + nv_wr32(dev, 0x418a6c, 0x10000); + nv_wr32(dev, 0x418a70, 0x0); + nv_wr32(dev, 0x418a74, 0x0); + nv_wr32(dev, 0x418a78, 0x0); + nv_wr32(dev, 0x418a80, 0x0); + nv_wr32(dev, 0x418a84, 0x0); + nv_wr32(dev, 0x418a88, 0x0); + nv_wr32(dev, 0x418a8c, 0x10000); + nv_wr32(dev, 0x418a90, 0x0); + nv_wr32(dev, 0x418a94, 0x0); + nv_wr32(dev, 0x418a98, 0x0); + nv_wr32(dev, 0x418aa0, 0x0); + nv_wr32(dev, 0x418aa4, 0x0); + nv_wr32(dev, 0x418aa8, 0x0); + nv_wr32(dev, 0x418aac, 0x10000); + nv_wr32(dev, 0x418ab0, 0x0); + nv_wr32(dev, 0x418ab4, 0x0); + nv_wr32(dev, 0x418ab8, 0x0); + nv_wr32(dev, 0x418ac0, 0x0); + nv_wr32(dev, 0x418ac4, 0x0); + nv_wr32(dev, 0x418ac8, 0x0); + nv_wr32(dev, 0x418acc, 0x10000); + nv_wr32(dev, 0x418ad0, 0x0); + nv_wr32(dev, 0x418ad4, 0x0); + nv_wr32(dev, 0x418ad8, 0x0); + nv_wr32(dev, 0x418ae0, 0x0); + nv_wr32(dev, 0x418ae4, 0x0); + nv_wr32(dev, 0x418ae8, 0x0); + nv_wr32(dev, 0x418aec, 0x10000); + nv_wr32(dev, 0x418af0, 0x0); + nv_wr32(dev, 0x418af4, 0x0); + nv_wr32(dev, 0x418af8, 0x0); + nv_wr32(dev, 0x418b00, 0x6); + nv_wr32(dev, 0x418b08, 0xa418820); + nv_wr32(dev, 0x418b0c, 0x62080e6); + nv_wr32(dev, 0x418b10, 0x20398a4); + nv_wr32(dev, 0x418b14, 0xe629062); + nv_wr32(dev, 0x418b18, 0xa418820); + nv_wr32(dev, 0x418b1c, 0xe6); + nv_wr32(dev, 0x418bb8, 0x103); + nv_wr32(dev, 0x418c08, 0x1); + nv_wr32(dev, 0x418c10, 0x0); + nv_wr32(dev, 0x418c14, 0x0); + nv_wr32(dev, 0x418c18, 0x0); + nv_wr32(dev, 0x418c1c, 0x0); + nv_wr32(dev, 0x418c20, 0x0); + nv_wr32(dev, 0x418c24, 0x0); + nv_wr32(dev, 0x418c28, 0x0); + nv_wr32(dev, 0x418c2c, 0x0); + nv_wr32(dev, 0x418c40, 0xffffffff); + nv_wr32(dev, 0x418c6c, 0x1); + nv_wr32(dev, 0x418c80, 0x20200004); + nv_wr32(dev, 0x418c8c, 0x1); + nv_wr32(dev, 0x419000, 0x780); + nv_wr32(dev, 0x419004, 0x0); + nv_wr32(dev, 0x419008, 0x0); + nv_wr32(dev, 0x419014, 0x4); +} + +static void +nve0_graph_generate_tpc(struct drm_device *dev) +{ + nv_wr32(dev, 0x419848, 0x0); + nv_wr32(dev, 0x419864, 0x129); + nv_wr32(dev, 0x419888, 0x0); + nv_wr32(dev, 0x419a00, 0xf0); + nv_wr32(dev, 0x419a04, 0x1); + nv_wr32(dev, 0x419a08, 0x21); + nv_wr32(dev, 0x419a0c, 0x20000); + nv_wr32(dev, 0x419a10, 0x0); + nv_wr32(dev, 0x419a14, 0x200); + nv_wr32(dev, 0x419a1c, 0xc000); + nv_wr32(dev, 0x419a20, 0x800); + nv_wr32(dev, 0x419a30, 0x1); + nv_wr32(dev, 0x419ac4, 0x37f440); + nv_wr32(dev, 0x419c00, 0xa); + nv_wr32(dev, 0x419c04, 0x80000006); + nv_wr32(dev, 0x419c08, 0x2); + nv_wr32(dev, 0x419c20, 0x0); + nv_wr32(dev, 0x419c24, 0x84210); + nv_wr32(dev, 0x419c28, 0x3efbefbe); + nv_wr32(dev, 0x419ce8, 0x0); + nv_wr32(dev, 0x419cf4, 0x3203); + nv_wr32(dev, 0x419e04, 0x0); + nv_wr32(dev, 0x419e08, 0x0); + nv_wr32(dev, 0x419e0c, 0x0); + nv_wr32(dev, 0x419e10, 0x402); + nv_wr32(dev, 0x419e44, 0x13eff2); + nv_wr32(dev, 0x419e48, 0x0); + nv_wr32(dev, 0x419e4c, 0x7f); + nv_wr32(dev, 0x419e50, 0x0); + nv_wr32(dev, 0x419e54, 0x0); + nv_wr32(dev, 0x419e58, 0x0); + nv_wr32(dev, 0x419e5c, 0x0); + nv_wr32(dev, 0x419e60, 0x0); + nv_wr32(dev, 0x419e64, 0x0); + nv_wr32(dev, 0x419e68, 0x0); + nv_wr32(dev, 0x419e6c, 0x0); + nv_wr32(dev, 0x419e70, 0x0); + nv_wr32(dev, 0x419e74, 0x0); + nv_wr32(dev, 0x419e78, 0x0); + nv_wr32(dev, 0x419e7c, 0x0); + nv_wr32(dev, 0x419e80, 0x0); + nv_wr32(dev, 0x419e84, 0x0); + nv_wr32(dev, 0x419e88, 0x0); + nv_wr32(dev, 0x419e8c, 0x0); + nv_wr32(dev, 0x419e90, 0x0); + nv_wr32(dev, 0x419e94, 0x0); + nv_wr32(dev, 0x419e98, 0x0); + nv_wr32(dev, 0x419eac, 0x1fcf); + nv_wr32(dev, 0x419eb0, 0xd3f); + nv_wr32(dev, 0x419ec8, 0x1304f); + nv_wr32(dev, 0x419f30, 0x0); + nv_wr32(dev, 0x419f34, 0x0); + nv_wr32(dev, 0x419f38, 0x0); + nv_wr32(dev, 0x419f3c, 0x0); + nv_wr32(dev, 0x419f40, 0x0); + nv_wr32(dev, 0x419f44, 0x0); + nv_wr32(dev, 0x419f48, 0x0); + nv_wr32(dev, 0x419f4c, 0x0); + nv_wr32(dev, 0x419f58, 0x0); + nv_wr32(dev, 0x419f78, 0xb); +} + +static void +nve0_graph_generate_tpcunk(struct drm_device *dev) +{ + nv_wr32(dev, 0x41be24, 0x6); + nv_wr32(dev, 0x41bec0, 0x12180000); + nv_wr32(dev, 0x41bec4, 0x37f7f); + nv_wr32(dev, 0x41bee4, 0x6480430); + nv_wr32(dev, 0x41bf00, 0xa418820); + nv_wr32(dev, 0x41bf04, 0x62080e6); + nv_wr32(dev, 0x41bf08, 0x20398a4); + nv_wr32(dev, 0x41bf0c, 0xe629062); + nv_wr32(dev, 0x41bf10, 0xa418820); + nv_wr32(dev, 0x41bf14, 0xe6); + nv_wr32(dev, 0x41bfd0, 0x900103); + nv_wr32(dev, 0x41bfe0, 0x400001); + nv_wr32(dev, 0x41bfe4, 0x0); +} + +int +nve0_grctx_generate(struct nouveau_channel *chan) +{ + struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + u32 data[6] = {}, data2[2] = {}, tmp; + u32 tpc_set = 0, tpc_mask = 0; + u8 tpcnr[GPC_MAX], a, b; + u8 shift, ntpcv; + int i, gpc, tpc, id; + + nv_mask(dev, 0x000260, 0x00000001, 0x00000000); + nv_wr32(dev, 0x400204, 0x00000000); + nv_wr32(dev, 0x400208, 0x00000000); + + nve0_graph_generate_unk40xx(dev); + nve0_graph_generate_unk44xx(dev); + nve0_graph_generate_unk46xx(dev); + nve0_graph_generate_unk47xx(dev); + nve0_graph_generate_unk58xx(dev); + nve0_graph_generate_unk60xx(dev); + nve0_graph_generate_unk64xx(dev); + nve0_graph_generate_unk70xx(dev); + nve0_graph_generate_unk78xx(dev); + nve0_graph_generate_unk80xx(dev); + nve0_graph_generate_unk88xx(dev); + nve0_graph_generate_gpc(dev); + nve0_graph_generate_tpc(dev); + nve0_graph_generate_tpcunk(dev); + + nv_wr32(dev, 0x404154, 0x0); + + for (i = 0; i < grch->mmio_nr * 8; i += 8) { + u32 reg = nv_ro32(grch->mmio, i + 0); + u32 val = nv_ro32(grch->mmio, i + 4); + nv_wr32(dev, reg, val); + } + + nv_wr32(dev, 0x418c6c, 0x1); + nv_wr32(dev, 0x41980c, 0x10); + nv_wr32(dev, 0x41be08, 0x4); + nv_wr32(dev, 0x4064c0, 0x801a00f0); + nv_wr32(dev, 0x405800, 0xf8000bf); + nv_wr32(dev, 0x419c00, 0xa); + + for (tpc = 0, id = 0; tpc < 4; tpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tpc < priv->tpc_nr[gpc]) { + nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x0698), id); + nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x04e8), id); + nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); + nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x0088), id++); + } + + nv_wr32(dev, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); + nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); + } + } + + tmp = 0; + for (i = 0; i < priv->gpc_nr; i++) + tmp |= priv->tpc_nr[i] << (i * 4); + nv_wr32(dev, 0x406028, tmp); + nv_wr32(dev, 0x405870, tmp); + + nv_wr32(dev, 0x40602c, 0x0); + nv_wr32(dev, 0x405874, 0x0); + nv_wr32(dev, 0x406030, 0x0); + nv_wr32(dev, 0x405878, 0x0); + nv_wr32(dev, 0x406034, 0x0); + nv_wr32(dev, 0x40587c, 0x0); + + /* calculate first set of magics */ + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + + gpc = -1; + for (tpc = 0; tpc < priv->tpc_total; tpc++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpcnr[gpc]); + tpcnr[gpc]--; + + data[tpc / 6] |= gpc << ((tpc % 6) * 5); + } + + for (; tpc < 32; tpc++) + data[tpc / 6] |= 7 << ((tpc % 6) * 5); + + /* and the second... */ + shift = 0; + ntpcv = priv->tpc_total; + while (!(ntpcv & (1 << 4))) { + ntpcv <<= 1; + shift++; + } + + data2[0] = ntpcv << 16; + data2[0] |= shift << 21; + data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24); + 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(dev, 0x418bb8, (priv->tpc_total << 8) | priv->magic_not_rop_nr); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x418b08 + (i * 4), data[i]); + + nv_wr32(dev, 0x41bfd0, data2[0]); + nv_wr32(dev, 0x41bfe4, data2[1]); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x41bf00 + (i * 4), data[i]); + + nv_wr32(dev, 0x4078bc, (priv->tpc_total << 8) | priv->magic_not_rop_nr); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x40780c + (i * 4), data[i]); + + + 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 * (priv->tpc_total - 1)) / 32; + if (a != b) { + b = a; + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpcnr[gpc]); + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + + tpc_set |= 1 << ((gpc * 8) + tpc); + } + + nv_wr32(dev, 0x406800 + (i * 0x20), tpc_set); + nv_wr32(dev, 0x406c00 + (i * 0x20), tpc_set ^ tpc_mask); + } + + for (i = 0; i < 8; i++) + nv_wr32(dev, 0x4064d0 + (i * 0x04), 0x00000000); + + nv_wr32(dev, 0x405b00, 0x201); + nv_wr32(dev, 0x408850, 0x2); + nv_wr32(dev, 0x408958, 0x2); + nv_wr32(dev, 0x419f78, 0xa); + + nve0_grctx_generate_icmd(dev); + nve0_grctx_generate_a097(dev); + nve0_grctx_generate_902d(dev); + + nv_mask(dev, 0x000260, 0x00000001, 0x00000001); + nv_wr32(dev, 0x418800, 0x7026860a); //XXX + nv_wr32(dev, 0x41be10, 0x00bb8bc7); //XXX + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc new file mode 100644 index 0000000..15272be --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc @@ -0,0 +1,539 @@ +/* fuc microcode for nvc0 PGRAPH/GPC + * + * Copyright 2011 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: + * + * 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 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 + */ + +/* To build: + * m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h + */ + +/* TODO + * - bracket certain functions with scratch writes, useful for debugging + * - watchdog timer around ctx operations + */ + +.section #nvc0_grgpc_data +include(`nvc0_graph.fuc') +gpc_id: .b32 0 +gpc_mmio_list_head: .b32 0 +gpc_mmio_list_tail: .b32 0 + +tpc_count: .b32 0 +tpc_mask: .b32 0 +tpc_mmio_list_head: .b32 0 +tpc_mmio_list_tail: .b32 0 + +cmd_queue: queue_init + +// chipset descriptions +chipsets: +.b8 0xc0 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc0_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvc0_tpc_mmio_tail +.b8 0xc1 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc1_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvc1_tpc_mmio_tail +.b8 0xc3 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc0_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvc3_tpc_mmio_tail +.b8 0xc4 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc0_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvc3_tpc_mmio_tail +.b8 0xc8 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc0_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvc0_tpc_mmio_tail +.b8 0xce 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc0_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvc3_tpc_mmio_tail +.b8 0xcf 0 0 0 +.b16 #nvc0_gpc_mmio_head +.b16 #nvc0_gpc_mmio_tail +.b16 #nvc0_tpc_mmio_head +.b16 #nvcf_tpc_mmio_tail +.b8 0xd9 0 0 0 +.b16 #nvd9_gpc_mmio_head +.b16 #nvd9_gpc_mmio_tail +.b16 #nvd9_tpc_mmio_head +.b16 #nvd9_tpc_mmio_tail +.b8 0 0 0 0 + +// GPC mmio lists +nvc0_gpc_mmio_head: +mmctx_data(0x000380, 1) +mmctx_data(0x000400, 6) +mmctx_data(0x000450, 9) +mmctx_data(0x000600, 1) +mmctx_data(0x000684, 1) +mmctx_data(0x000700, 5) +mmctx_data(0x000800, 1) +mmctx_data(0x000808, 3) +mmctx_data(0x000828, 1) +mmctx_data(0x000830, 1) +mmctx_data(0x0008d8, 1) +mmctx_data(0x0008e0, 1) +mmctx_data(0x0008e8, 6) +mmctx_data(0x00091c, 1) +mmctx_data(0x000924, 3) +mmctx_data(0x000b00, 1) +mmctx_data(0x000b08, 6) +mmctx_data(0x000bb8, 1) +mmctx_data(0x000c08, 1) +mmctx_data(0x000c10, 8) +mmctx_data(0x000c80, 1) +mmctx_data(0x000c8c, 1) +mmctx_data(0x001000, 3) +mmctx_data(0x001014, 1) +nvc0_gpc_mmio_tail: +mmctx_data(0x000c6c, 1); +nvc1_gpc_mmio_tail: + +nvd9_gpc_mmio_head: +mmctx_data(0x000380, 1) +mmctx_data(0x000400, 2) +mmctx_data(0x00040c, 3) +mmctx_data(0x000450, 9) +mmctx_data(0x000600, 1) +mmctx_data(0x000684, 1) +mmctx_data(0x000700, 5) +mmctx_data(0x000800, 1) +mmctx_data(0x000808, 3) +mmctx_data(0x000828, 1) +mmctx_data(0x000830, 1) +mmctx_data(0x0008d8, 1) +mmctx_data(0x0008e0, 1) +mmctx_data(0x0008e8, 6) +mmctx_data(0x00091c, 1) +mmctx_data(0x000924, 3) +mmctx_data(0x000b00, 1) +mmctx_data(0x000b08, 6) +mmctx_data(0x000bb8, 1) +mmctx_data(0x000c08, 1) +mmctx_data(0x000c10, 8) +mmctx_data(0x000c6c, 1) +mmctx_data(0x000c80, 1) +mmctx_data(0x000c8c, 1) +mmctx_data(0x001000, 3) +mmctx_data(0x001014, 1) +nvd9_gpc_mmio_tail: + +// TPC mmio lists +nvc0_tpc_mmio_head: +mmctx_data(0x000018, 1) +mmctx_data(0x00003c, 1) +mmctx_data(0x000048, 1) +mmctx_data(0x000064, 1) +mmctx_data(0x000088, 1) +mmctx_data(0x000200, 6) +mmctx_data(0x00021c, 2) +mmctx_data(0x000300, 6) +mmctx_data(0x0003d0, 1) +mmctx_data(0x0003e0, 2) +mmctx_data(0x000400, 3) +mmctx_data(0x000420, 1) +mmctx_data(0x0004b0, 1) +mmctx_data(0x0004e8, 1) +mmctx_data(0x0004f4, 1) +mmctx_data(0x000520, 2) +mmctx_data(0x000604, 4) +mmctx_data(0x000644, 20) +mmctx_data(0x000698, 1) +mmctx_data(0x000750, 2) +nvc0_tpc_mmio_tail: +mmctx_data(0x000758, 1) +mmctx_data(0x0002c4, 1) +mmctx_data(0x0006e0, 1) +nvcf_tpc_mmio_tail: +mmctx_data(0x0004bc, 1) +nvc3_tpc_mmio_tail: +mmctx_data(0x000544, 1) +nvc1_tpc_mmio_tail: + +nvd9_tpc_mmio_head: +mmctx_data(0x000018, 1) +mmctx_data(0x00003c, 1) +mmctx_data(0x000048, 1) +mmctx_data(0x000064, 1) +mmctx_data(0x000088, 1) +mmctx_data(0x000200, 6) +mmctx_data(0x00021c, 2) +mmctx_data(0x0002c4, 1) +mmctx_data(0x000300, 6) +mmctx_data(0x0003d0, 1) +mmctx_data(0x0003e0, 2) +mmctx_data(0x000400, 3) +mmctx_data(0x000420, 3) +mmctx_data(0x0004b0, 1) +mmctx_data(0x0004e8, 1) +mmctx_data(0x0004f4, 1) +mmctx_data(0x000520, 2) +mmctx_data(0x000544, 1) +mmctx_data(0x000604, 4) +mmctx_data(0x000644, 20) +mmctx_data(0x000698, 1) +mmctx_data(0x0006e0, 1) +mmctx_data(0x000750, 3) +nvd9_tpc_mmio_tail: + +.section #nvc0_grgpc_code +bra #init +define(`include_code') +include(`nvc0_graph.fuc') + +// reports an exception to the host +// +// In: $r15 error code (see nvc0_graph.fuc) +// +error: + push $r14 + mov $r14 -0x67ec // 0x9814 + sethi $r14 0x400000 + call #nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code + add b32 $r14 0x41c + mov $r15 1 + call #nv_wr32 // HUB_CTXCTL_INTR_UP_SET + pop $r14 + ret + +// GPC fuc initialisation, executed by triggering ucode start, will +// fall through to main loop after completion. +// +// Input: +// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) +// CC_SCRATCH[1]: context base +// +// Output: +// CC_SCRATCH[0]: +// 31:31: set to signal completion +// CC_SCRATCH[1]: +// 31:0: GPC context size +// +init: + clear b32 $r0 + mov $sp $r0 + + // enable fifo access + mov $r1 0x1200 + mov $r2 2 + iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE + + // setup i0 handler, and route all interrupts to it + mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH + + // enable fifo interrupt + mov $r2 4 + iowr I[$r1 + 0x000] $r2 // INTR_EN_SET + + // enable interrupts + bset $flags ie0 + + // figure out which GPC we are, and how many TPCs we have + mov $r1 0x608 + shl b32 $r1 6 + iord $r2 I[$r1 + 0x000] // UNITS + mov $r3 1 + and $r2 0x1f + shl b32 $r3 $r2 + sub b32 $r3 1 + st b32 D[$r0 + #tpc_count] $r2 + st b32 D[$r0 + #tpc_mask] $r3 + add b32 $r1 0x400 + iord $r2 I[$r1 + 0x000] // MYINDEX + st b32 D[$r0 + #gpc_id] $r2 + + // find context data for this chipset + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] + mov $r1 #chipsets - 12 + init_find_chipset: + add b32 $r1 12 + ld b32 $r3 D[$r1 + 0x00] + cmpu b32 $r3 $r2 + bra e #init_context + cmpu b32 $r3 0 + bra ne #init_find_chipset + // unknown chipset + ret + + // initialise context base, and size tracking + init_context: + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base + clear b32 $r3 // track GPC context size here + + // set mmctx base addresses now so we don't have to do it later, + // they don't currently ever change + mov $r4 0x700 + shl b32 $r4 6 + shr b32 $r5 $r2 8 + iowr I[$r4 + 0x000] $r5 // MMCTX_SAVE_SWBASE + iowr I[$r4 + 0x100] $r5 // MMCTX_LOAD_SWBASE + + // calculate GPC mmio context size, store the chipset-specific + // mmio list pointers somewhere we can get at them later without + // re-parsing the chipset list + clear b32 $r14 + clear b32 $r15 + ld b16 $r14 D[$r1 + 4] + ld b16 $r15 D[$r1 + 6] + st b16 D[$r0 + #gpc_mmio_list_head] $r14 + st b16 D[$r0 + #gpc_mmio_list_tail] $r15 + call #mmctx_size + add b32 $r2 $r15 + add b32 $r3 $r15 + + // calculate per-TPC mmio context size, store the list pointers + ld b16 $r14 D[$r1 + 8] + ld b16 $r15 D[$r1 + 10] + st b16 D[$r0 + #tpc_mmio_list_head] $r14 + st b16 D[$r0 + #tpc_mmio_list_tail] $r15 + call #mmctx_size + ld b32 $r14 D[$r0 + #tpc_count] + mulu $r14 $r15 + add b32 $r2 $r14 + add b32 $r3 $r14 + + // round up base/size to 256 byte boundary (for strand SWBASE) + add b32 $r4 0x1300 + shr b32 $r3 2 + iowr I[$r4 + 0x000] $r3 // MMCTX_LOAD_COUNT, wtf for?!? + shr b32 $r2 8 + shr b32 $r3 6 + add b32 $r2 1 + add b32 $r3 1 + shl b32 $r2 8 + shl b32 $r3 8 + + // calculate size of strand context data + mov b32 $r15 $r2 + call #strand_ctx_init + add b32 $r3 $r15 + + // save context size, and tell HUB we're done + mov $r1 0x800 + shl b32 $r1 6 + iowr I[$r1 + 0x100] $r3 // CC_SCRATCH[1] = context size + add b32 $r1 0x800 + clear b32 $r2 + bset $r2 31 + iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 + +// Main program loop, very simple, sleeps until woken up by the interrupt +// handler, pulls a command from the queue and executes its handler +// +main: + bset $flags $p0 + sleep $p0 + mov $r13 #cmd_queue + call #queue_get + bra $p1 #main + + // 0x0000-0x0003 are all context transfers + cmpu b32 $r14 0x04 + bra nc #main_not_ctx_xfer + // fetch $flags and mask off $p1/$p2 + mov $r1 $flags + mov $r2 0x0006 + not b32 $r2 + and $r1 $r2 + // set $p1/$p2 according to transfer type + shl b32 $r14 1 + or $r1 $r14 + mov $flags $r1 + // transfer context data + call #ctx_xfer + bra #main + + main_not_ctx_xfer: + shl b32 $r15 $r14 16 + or $r15 E_BAD_COMMAND + call #error + bra #main + +// interrupt handler +ih: + push $r8 + mov $r8 $flags + push $r8 + push $r9 + push $r10 + push $r11 + push $r13 + push $r14 + push $r15 + + // incoming fifo command? + iord $r10 I[$r0 + 0x200] // INTR + and $r11 $r10 0x00000004 + bra e #ih_no_fifo + // queue incoming fifo command for later processing + mov $r11 0x1900 + mov $r13 #cmd_queue + iord $r14 I[$r11 + 0x100] // FIFO_CMD + iord $r15 I[$r11 + 0x000] // FIFO_DATA + call #queue_put + add b32 $r11 0x400 + mov $r14 1 + iowr I[$r11 + 0x000] $r14 // FIFO_ACK + + // ack, and wake up main() + ih_no_fifo: + iowr I[$r0 + 0x100] $r10 // INTR_ACK + + pop $r15 + pop $r14 + pop $r13 + pop $r11 + pop $r10 + pop $r9 + pop $r8 + mov $flags $r8 + pop $r8 + bclr $flags $p0 + iret + +// Set this GPC's bit in HUB_BAR, used to signal completion of various +// activities to the HUB fuc +// +hub_barrier_done: + mov $r15 1 + ld b32 $r14 D[$r0 + #gpc_id] + shl b32 $r15 $r14 + mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET + sethi $r14 0x400000 + call #nv_wr32 + ret + +// Disables various things, waits a bit, and re-enables them.. +// +// Not sure how exactly this helps, perhaps "ENABLE" is not such a +// good description for the bits we turn off? Anyways, without this, +// funny things happen. +// +ctx_redswitch: + mov $r14 0x614 + shl b32 $r14 6 + mov $r15 0x020 + iowr I[$r14] $r15 // GPC_RED_SWITCH = POWER + mov $r15 8 + ctx_redswitch_delay: + sub b32 $r15 1 + bra ne #ctx_redswitch_delay + mov $r15 0xa20 + iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER + ret + +// Transfer GPC context data between GPU and storage area +// +// In: $r15 context base address +// $p1 clear on save, set on load +// $p2 set if opposite direction done/will be done, so: +// on save it means: "a load will follow this save" +// on load it means: "a save preceeded this load" +// +ctx_xfer: + // set context base address + mov $r1 0xa04 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r15// MEM_BASE + bra not $p1 #ctx_xfer_not_load + call #ctx_redswitch + ctx_xfer_not_load: + + // strands + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xc + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c + call #strand_wait + mov $r2 0x47fc + sethi $r2 0x20000 + iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 + xbit $r2 $flags $p1 + add b32 $r2 3 + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) + + // mmio context + xbit $r10 $flags $p1 // direction + or $r10 2 // first + mov $r11 0x0000 + sethi $r11 0x500000 + ld b32 $r12 D[$r0 + #gpc_id] + shl b32 $r12 15 + add b32 $r11 $r12 // base = NV_PGRAPH_GPCn + ld b32 $r12 D[$r0 + #gpc_mmio_list_head] + ld b32 $r13 D[$r0 + #gpc_mmio_list_tail] + mov $r14 0 // not multi + call #mmctx_xfer + + // per-TPC mmio context + xbit $r10 $flags $p1 // direction + or $r10 4 // last + mov $r11 0x4000 + sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0 + ld b32 $r12 D[$r0 + #gpc_id] + shl b32 $r12 15 + add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0 + ld b32 $r12 D[$r0 + #tpc_mmio_list_head] + ld b32 $r13 D[$r0 + #tpc_mmio_list_tail] + ld b32 $r15 D[$r0 + #tpc_mask] + mov $r14 0x800 // stride = 0x800 + call #mmctx_xfer + + // wait for strands to finish + call #strand_wait + + // if load, or a save without a load following, do some + // unknown stuff that's done after finishing a block of + // strand commands + bra $p1 #ctx_xfer_post + bra not $p2 #ctx_xfer_done + ctx_xfer_post: + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xd + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d + call #strand_wait + + // mark completion in HUB's barrier + ctx_xfer_done: + call #hub_barrier_done + ret + +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h new file mode 100644 index 0000000..a988b8a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h @@ -0,0 +1,538 @@ +uint32_t nvc0_grgpc_data[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x000000c0, + 0x012800c8, + 0x01e40194, + 0x000000c1, + 0x012c00c8, + 0x01f80194, + 0x000000c3, + 0x012800c8, + 0x01f40194, + 0x000000c4, + 0x012800c8, + 0x01f40194, + 0x000000c8, + 0x012800c8, + 0x01e40194, + 0x000000ce, + 0x012800c8, + 0x01f40194, + 0x000000cf, + 0x012800c8, + 0x01f00194, + 0x000000d9, + 0x0194012c, + 0x025401f8, + 0x00000000, + 0x00000380, + 0x14000400, + 0x20000450, + 0x00000600, + 0x00000684, + 0x10000700, + 0x00000800, + 0x08000808, + 0x00000828, + 0x00000830, + 0x000008d8, + 0x000008e0, + 0x140008e8, + 0x0000091c, + 0x08000924, + 0x00000b00, + 0x14000b08, + 0x00000bb8, + 0x00000c08, + 0x1c000c10, + 0x00000c80, + 0x00000c8c, + 0x08001000, + 0x00001014, + 0x00000c6c, + 0x00000380, + 0x04000400, + 0x0800040c, + 0x20000450, + 0x00000600, + 0x00000684, + 0x10000700, + 0x00000800, + 0x08000808, + 0x00000828, + 0x00000830, + 0x000008d8, + 0x000008e0, + 0x140008e8, + 0x0000091c, + 0x08000924, + 0x00000b00, + 0x14000b08, + 0x00000bb8, + 0x00000c08, + 0x1c000c10, + 0x00000c6c, + 0x00000c80, + 0x00000c8c, + 0x08001000, + 0x00001014, + 0x00000018, + 0x0000003c, + 0x00000048, + 0x00000064, + 0x00000088, + 0x14000200, + 0x0400021c, + 0x14000300, + 0x000003d0, + 0x040003e0, + 0x08000400, + 0x00000420, + 0x000004b0, + 0x000004e8, + 0x000004f4, + 0x04000520, + 0x0c000604, + 0x4c000644, + 0x00000698, + 0x04000750, + 0x00000758, + 0x000002c4, + 0x000006e0, + 0x000004bc, + 0x00000544, + 0x00000018, + 0x0000003c, + 0x00000048, + 0x00000064, + 0x00000088, + 0x14000200, + 0x0400021c, + 0x000002c4, + 0x14000300, + 0x000003d0, + 0x040003e0, + 0x08000400, + 0x08000420, + 0x000004b0, + 0x000004e8, + 0x000004f4, + 0x04000520, + 0x00000544, + 0x0c000604, + 0x4c000644, + 0x00000698, + 0x000006e0, + 0x08000750, +}; + +uint32_t nvc0_grgpc_code[] = { + 0x03060ef5, + 0x9800d898, + 0x86f001d9, + 0x0489b808, + 0xf00c1bf4, + 0x21f502f7, + 0x00f802ec, + 0xb60798c4, + 0x8dbb0384, + 0x0880b600, + 0x80008e80, + 0x90b6018f, + 0x0f94f001, + 0xf801d980, + 0x0131f400, + 0x9800d898, + 0x89b801d9, + 0x210bf404, + 0xb60789c4, + 0x9dbb0394, + 0x0890b600, + 0x98009e98, + 0x80b6019f, + 0x0f84f001, + 0xf400d880, + 0x00f80132, + 0x0728b7f1, + 0xb906b4b6, + 0xc9f002ec, + 0x00bcd01f, + 0xc800bccf, + 0x1bf41fcc, + 0x06a7f0fa, + 0x010321f5, + 0xf840bfcf, + 0x28b7f100, + 0x06b4b607, + 0xb980bfd0, + 0xc9f002ec, + 0x1ec9f01f, + 0xcf00bcd0, + 0xccc800bc, + 0xfa1bf41f, + 0x87f100f8, + 0x84b60430, + 0x1ff9f006, + 0xf8008fd0, + 0x3087f100, + 0x0684b604, + 0xf80080d0, + 0x3c87f100, + 0x0684b608, + 0x99f094bd, + 0x0089d000, + 0x081887f1, + 0xd00684b6, + 0x87f1008a, + 0x84b60400, + 0x0088cf06, + 0xf4888aff, + 0x87f1f31b, + 0x84b6085c, + 0xf094bd06, + 0x89d00099, + 0xf100f800, + 0xb6083c87, + 0x94bd0684, + 0xd00099f0, + 0x87f10089, + 0x84b60818, + 0x008ad006, + 0x040087f1, + 0xcf0684b6, + 0x8aff0088, + 0xf30bf488, + 0x085c87f1, + 0xbd0684b6, + 0x0099f094, + 0xf80089d0, + 0x9894bd00, + 0x85b600e8, + 0x0180b61a, + 0xbb0284b6, + 0xe0b60098, + 0x04efb804, + 0xb9eb1bf4, + 0x00f8029f, + 0x083c87f1, + 0xbd0684b6, + 0x0199f094, + 0xf10089d0, + 0xb6071087, + 0x94bd0684, + 0xf405bbfd, + 0x8bd0090b, + 0x0099f000, + 0xf405eefd, + 0x8ed00c0b, + 0xc08fd080, + 0xb70199f0, + 0xc8010080, + 0xb4b600ab, + 0x0cb9f010, + 0xb601aec8, + 0xbefd11e4, + 0x008bd005, + 0xf0008ecf, + 0x0bf41fe4, + 0x00ce98fa, + 0xd005e9fd, + 0xc0b6c08e, + 0x04cdb804, + 0xc8e81bf4, + 0x1bf402ab, + 0x008bcf18, + 0xb01fb4f0, + 0x1bf410b4, + 0x02a7f0f7, + 0xf4c921f4, + 0xabc81b0e, + 0x10b4b600, + 0xf00cb9f0, + 0x8bd012b9, + 0x008bcf00, + 0xf412bbc8, + 0x87f1fa1b, + 0x84b6085c, + 0xf094bd06, + 0x89d00199, + 0xf900f800, + 0x02a7f0a0, + 0xfcc921f4, + 0xf100f8a0, + 0xf04afc87, + 0x97f00283, + 0x0089d00c, + 0x020721f5, + 0x87f100f8, + 0x83f04afc, + 0x0d97f002, + 0xf50089d0, + 0xf8020721, + 0xfca7f100, + 0x02a3f04f, + 0x0500aba2, + 0xd00fc7f0, + 0xc7f000ac, + 0x00bcd00b, + 0x020721f5, + 0xf000aed0, + 0xbcd00ac7, + 0x0721f500, + 0xf100f802, + 0xb6083c87, + 0x94bd0684, + 0xd00399f0, + 0x21f50089, + 0xe7f00213, + 0x3921f503, + 0xfca7f102, + 0x02a3f046, + 0x0400aba0, + 0xf040a0d0, + 0xbcd001c7, + 0x0721f500, + 0x010c9202, + 0xf000acd0, + 0xbcd002c7, + 0x0721f500, + 0x2621f502, + 0x8087f102, + 0x0684b608, + 0xb70089cf, + 0x95220080, + 0x8ed008fe, + 0x408ed000, + 0xb6808acf, + 0xa0b606a5, + 0x00eabb01, + 0xb60480b6, + 0x1bf40192, + 0x08e4b6e8, + 0xf1f2efbc, + 0xb6085c87, + 0x94bd0684, + 0xd00399f0, + 0x00f80089, + 0xe7f1e0f9, + 0xe3f09814, + 0x8d21f440, + 0x041ce0b7, + 0xf401f7f0, + 0xe0fc8d21, + 0x04bd00f8, + 0xf10004fe, + 0xf0120017, + 0x12d00227, + 0x3e17f100, + 0x0010fe04, + 0x040017f1, + 0xf0c010d0, + 0x12d00427, + 0x1031f400, + 0x060817f1, + 0xcf0614b6, + 0x37f00012, + 0x1f24f001, + 0xb60432bb, + 0x02800132, + 0x04038003, + 0x040010b7, + 0x800012cf, + 0x27f10002, + 0x24b60800, + 0x0022cf06, + 0xb65817f0, + 0x13980c10, + 0x0432b800, + 0xb00b0bf4, + 0x1bf40034, + 0xf100f8f1, + 0xb6080027, + 0x22cf0624, + 0xf134bd40, + 0xb6070047, + 0x25950644, + 0x0045d008, + 0xbd4045d0, + 0x58f4bde4, + 0x1f58021e, + 0x020e4003, + 0xf5040f40, + 0xbb013d21, + 0x3fbb002f, + 0x041e5800, + 0x40051f58, + 0x0f400a0e, + 0x3d21f50c, + 0x030e9801, + 0xbb00effd, + 0x3ebb002e, + 0x0040b700, + 0x0235b613, + 0xb60043d0, + 0x35b60825, + 0x0120b606, + 0xb60130b6, + 0x34b60824, + 0x022fb908, + 0x026321f5, + 0xf1003fbb, + 0xb6080017, + 0x13d00614, + 0x0010b740, + 0xf024bd08, + 0x12d01f29, + 0x0031f400, + 0xf00028f4, + 0x21f41cd7, + 0xf401f439, + 0xf404e4b0, + 0x81fe1e18, + 0x0627f001, + 0x12fd20bd, + 0x01e4b604, + 0xfe051efd, + 0x21f50018, + 0x0ef404c3, + 0x10ef94d3, + 0xf501f5f0, + 0xf402ec21, + 0x80f9c60e, + 0xf90188fe, + 0xf990f980, + 0xf9b0f9a0, + 0xf9e0f9d0, + 0x800acff0, + 0xf404abc4, + 0xb7f11d0b, + 0xd7f01900, + 0x40becf1c, + 0xf400bfcf, + 0xb0b70421, + 0xe7f00400, + 0x00bed001, + 0xfc400ad0, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x32f480fc, + 0xf001f800, + 0x0e9801f7, + 0x04febb00, + 0x9418e7f1, + 0xf440e3f0, + 0x00f88d21, + 0x0614e7f1, + 0xf006e4b6, + 0xefd020f7, + 0x08f7f000, + 0xf401f2b6, + 0xf7f1fd1b, + 0xefd00a20, + 0xf100f800, + 0xb60a0417, + 0x1fd00614, + 0x0711f400, + 0x04a421f5, + 0x4afc17f1, + 0xf00213f0, + 0x12d00c27, + 0x0721f500, + 0xfc27f102, + 0x0223f047, + 0xf00020d0, + 0x20b6012c, + 0x0012d003, + 0xf001acf0, + 0xb7f002a5, + 0x50b3f000, + 0xb6000c98, + 0xbcbb0fc4, + 0x010c9800, + 0xf0020d98, + 0x21f500e7, + 0xacf0015c, + 0x04a5f001, + 0x4000b7f1, + 0x9850b3f0, + 0xc4b6000c, + 0x00bcbb0f, + 0x98050c98, + 0x0f98060d, + 0x00e7f104, + 0x5c21f508, + 0x0721f501, + 0x0601f402, + 0xf11412f4, + 0xf04afc17, + 0x27f00213, + 0x0012d00d, + 0x020721f5, + 0x048f21f5, + 0x000000f8, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc new file mode 100644 index 0000000..98acddb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc @@ -0,0 +1,856 @@ +/* fuc microcode for nvc0 PGRAPH/HUB + * + * Copyright 2011 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: + * + * 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 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 + */ + +/* To build: + * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h + */ + +.section #nvc0_grhub_data +include(`nvc0_graph.fuc') +gpc_count: .b32 0 +rop_count: .b32 0 +cmd_queue: queue_init +hub_mmio_list_head: .b32 0 +hub_mmio_list_tail: .b32 0 + +ctx_current: .b32 0 + +chipsets: +.b8 0xc0 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc0_hub_mmio_tail +.b8 0xc1 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc1_hub_mmio_tail +.b8 0xc3 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc0_hub_mmio_tail +.b8 0xc4 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc0_hub_mmio_tail +.b8 0xc8 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc0_hub_mmio_tail +.b8 0xce 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc0_hub_mmio_tail +.b8 0xcf 0 0 0 +.b16 #nvc0_hub_mmio_head +.b16 #nvc0_hub_mmio_tail +.b8 0xd9 0 0 0 +.b16 #nvd9_hub_mmio_head +.b16 #nvd9_hub_mmio_tail +.b8 0 0 0 0 + +nvc0_hub_mmio_head: +mmctx_data(0x17e91c, 2) +mmctx_data(0x400204, 2) +mmctx_data(0x404004, 11) +mmctx_data(0x404044, 1) +mmctx_data(0x404094, 14) +mmctx_data(0x4040d0, 7) +mmctx_data(0x4040f8, 1) +mmctx_data(0x404130, 3) +mmctx_data(0x404150, 3) +mmctx_data(0x404164, 2) +mmctx_data(0x404174, 3) +mmctx_data(0x404200, 8) +mmctx_data(0x404404, 14) +mmctx_data(0x404460, 4) +mmctx_data(0x404480, 1) +mmctx_data(0x404498, 1) +mmctx_data(0x404604, 4) +mmctx_data(0x404618, 32) +mmctx_data(0x404698, 21) +mmctx_data(0x4046f0, 2) +mmctx_data(0x404700, 22) +mmctx_data(0x405800, 1) +mmctx_data(0x405830, 3) +mmctx_data(0x405854, 1) +mmctx_data(0x405870, 4) +mmctx_data(0x405a00, 2) +mmctx_data(0x405a18, 1) +mmctx_data(0x406020, 1) +mmctx_data(0x406028, 4) +mmctx_data(0x4064a8, 2) +mmctx_data(0x4064b4, 2) +mmctx_data(0x407804, 1) +mmctx_data(0x40780c, 6) +mmctx_data(0x4078bc, 1) +mmctx_data(0x408000, 7) +mmctx_data(0x408064, 1) +mmctx_data(0x408800, 3) +mmctx_data(0x408900, 4) +mmctx_data(0x408980, 1) +nvc0_hub_mmio_tail: +mmctx_data(0x4064c0, 2) +nvc1_hub_mmio_tail: + +nvd9_hub_mmio_head: +mmctx_data(0x17e91c, 2) +mmctx_data(0x400204, 2) +mmctx_data(0x404004, 10) +mmctx_data(0x404044, 1) +mmctx_data(0x404094, 14) +mmctx_data(0x4040d0, 7) +mmctx_data(0x4040f8, 1) +mmctx_data(0x404130, 3) +mmctx_data(0x404150, 3) +mmctx_data(0x404164, 2) +mmctx_data(0x404178, 2) +mmctx_data(0x404200, 8) +mmctx_data(0x404404, 14) +mmctx_data(0x404460, 4) +mmctx_data(0x404480, 1) +mmctx_data(0x404498, 1) +mmctx_data(0x404604, 4) +mmctx_data(0x404618, 32) +mmctx_data(0x404698, 21) +mmctx_data(0x4046f0, 2) +mmctx_data(0x404700, 22) +mmctx_data(0x405800, 1) +mmctx_data(0x405830, 3) +mmctx_data(0x405854, 1) +mmctx_data(0x405870, 4) +mmctx_data(0x405a00, 2) +mmctx_data(0x405a18, 1) +mmctx_data(0x406020, 1) +mmctx_data(0x406028, 4) +mmctx_data(0x4064a8, 2) +mmctx_data(0x4064b4, 5) +mmctx_data(0x407804, 1) +mmctx_data(0x40780c, 6) +mmctx_data(0x4078bc, 1) +mmctx_data(0x408000, 7) +mmctx_data(0x408064, 1) +mmctx_data(0x408800, 3) +mmctx_data(0x408900, 4) +mmctx_data(0x408980, 1) +nvd9_hub_mmio_tail: + +.align 256 +chan_data: +chan_mmio_count: .b32 0 +chan_mmio_address: .b32 0 + +.align 256 +xfer_data: .b32 0 + +.section #nvc0_grhub_code +bra #init +define(`include_code') +include(`nvc0_graph.fuc') + +// reports an exception to the host +// +// In: $r15 error code (see nvc0_graph.fuc) +// +error: + push $r14 + mov $r14 0x814 + shl b32 $r14 6 + iowr I[$r14 + 0x000] $r15 // CC_SCRATCH[5] = error code + mov $r14 0xc1c + shl b32 $r14 6 + mov $r15 1 + iowr I[$r14 + 0x000] $r15 // INTR_UP_SET + pop $r14 + ret + +// HUB fuc initialisation, executed by triggering ucode start, will +// fall through to main loop after completion. +// +// Input: +// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) +// +// Output: +// CC_SCRATCH[0]: +// 31:31: set to signal completion +// CC_SCRATCH[1]: +// 31:0: total PGRAPH context size +// +init: + clear b32 $r0 + mov $sp $r0 + mov $xdbase $r0 + + // enable fifo access + mov $r1 0x1200 + mov $r2 2 + iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE + + // setup i0 handler, and route all interrupts to it + mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH + + // route HUB_CHANNEL_SWITCH to fuc interrupt 8 + mov $r3 0x404 + shl b32 $r3 6 + mov $r2 0x2003 // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8 + iowr I[$r3 + 0x000] $r2 + + // not sure what these are, route them because NVIDIA does, and + // the IRQ handler will signal the host if we ever get one.. we + // may find out if/why we need to handle these if so.. + // + mov $r2 0x2004 + iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9 + mov $r2 0x200b + iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10 + mov $r2 0x200c + iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15 + + // enable all INTR_UP interrupts + mov $r2 0xc24 + shl b32 $r2 6 + not b32 $r3 $r0 + iowr I[$r2] $r3 + + // enable fifo, ctxsw, 9, 10, 15 interrupts + mov $r2 -0x78fc // 0x8704 + sethi $r2 0 + iowr I[$r1 + 0x000] $r2 // INTR_EN_SET + + // fifo level triggered, rest edge + sub b32 $r1 0x100 + mov $r2 4 + iowr I[$r1] $r2 + + // enable interrupts + bset $flags ie0 + + // fetch enabled GPC/ROP counts + mov $r14 -0x69fc // 0x409604 + sethi $r14 0x400000 + call #nv_rd32 + extr $r1 $r15 16:20 + st b32 D[$r0 + #rop_count] $r1 + and $r15 0x1f + st b32 D[$r0 + #gpc_count] $r15 + + // set BAR_REQMASK to GPC mask + mov $r1 1 + shl b32 $r1 $r15 + sub b32 $r1 1 + mov $r2 0x40c + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r1 + iowr I[$r2 + 0x100] $r1 + + // find context data for this chipset + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] + mov $r15 #chipsets - 8 + init_find_chipset: + add b32 $r15 8 + ld b32 $r3 D[$r15 + 0x00] + cmpu b32 $r3 $r2 + bra e #init_context + cmpu b32 $r3 0 + bra ne #init_find_chipset + // unknown chipset + ret + + // context size calculation, reserve first 256 bytes for use by fuc + init_context: + mov $r1 256 + + // calculate size of mmio context data + ld b16 $r14 D[$r15 + 4] + ld b16 $r15 D[$r15 + 6] + sethi $r14 0 + st b32 D[$r0 + #hub_mmio_list_head] $r14 + st b32 D[$r0 + #hub_mmio_list_tail] $r15 + call #mmctx_size + + // set mmctx base addresses now so we don't have to do it later, + // they don't (currently) ever change + mov $r3 0x700 + shl b32 $r3 6 + shr b32 $r4 $r1 8 + iowr I[$r3 + 0x000] $r4 // MMCTX_SAVE_SWBASE + iowr I[$r3 + 0x100] $r4 // MMCTX_LOAD_SWBASE + add b32 $r3 0x1300 + add b32 $r1 $r15 + shr b32 $r15 2 + iowr I[$r3 + 0x000] $r15 // MMCTX_LOAD_COUNT, wtf for?!? + + // strands, base offset needs to be aligned to 256 bytes + shr b32 $r1 8 + add b32 $r1 1 + shl b32 $r1 8 + mov b32 $r15 $r1 + call #strand_ctx_init + add b32 $r1 $r15 + + // initialise each GPC in sequence by passing in the offset of its + // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which + // has previously been uploaded by the host) running. + // + // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31 + // when it has completed, and return the size of its context data + // in GPCn_CC_SCRATCH[1] + // + ld b32 $r3 D[$r0 + #gpc_count] + mov $r4 0x2000 + sethi $r4 0x500000 + init_gpc: + // setup, and start GPC ucode running + add b32 $r14 $r4 0x804 + mov b32 $r15 $r1 + call #nv_wr32 // CC_SCRATCH[1] = ctx offset + add b32 $r14 $r4 0x800 + mov b32 $r15 $r2 + call #nv_wr32 // CC_SCRATCH[0] = chipset + add b32 $r14 $r4 0x10c + clear b32 $r15 + call #nv_wr32 + add b32 $r14 $r4 0x104 + call #nv_wr32 // ENTRY + add b32 $r14 $r4 0x100 + mov $r15 2 // CTRL_START_TRIGGER + call #nv_wr32 // CTRL + + // wait for it to complete, and adjust context size + add b32 $r14 $r4 0x800 + init_gpc_wait: + call #nv_rd32 + xbit $r15 $r15 31 + bra e #init_gpc_wait + add b32 $r14 $r4 0x804 + call #nv_rd32 + add b32 $r1 $r15 + + // next! + add b32 $r4 0x8000 + sub b32 $r3 1 + bra ne #init_gpc + + // save context size, and tell host we're ready + mov $r2 0x800 + shl b32 $r2 6 + iowr I[$r2 + 0x100] $r1 // CC_SCRATCH[1] = context size + add b32 $r2 0x800 + clear b32 $r1 + bset $r1 31 + iowr I[$r2 + 0x000] $r1 // CC_SCRATCH[0] |= 0x80000000 + +// Main program loop, very simple, sleeps until woken up by the interrupt +// handler, pulls a command from the queue and executes its handler +// +main: + // sleep until we have something to do + bset $flags $p0 + sleep $p0 + mov $r13 #cmd_queue + call #queue_get + bra $p1 #main + + // context switch, requested by GPU? + cmpu b32 $r14 0x4001 + bra ne #main_not_ctx_switch + trace_set(T_AUTO) + mov $r1 0xb00 + shl b32 $r1 6 + iord $r2 I[$r1 + 0x100] // CHAN_NEXT + iord $r1 I[$r1 + 0x000] // CHAN_CUR + + xbit $r3 $r1 31 + bra e #chsw_no_prev + xbit $r3 $r2 31 + bra e #chsw_prev_no_next + push $r2 + mov b32 $r2 $r1 + trace_set(T_SAVE) + bclr $flags $p1 + bset $flags $p2 + call #ctx_xfer + trace_clr(T_SAVE); + pop $r2 + trace_set(T_LOAD); + bset $flags $p1 + call #ctx_xfer + trace_clr(T_LOAD); + bra #chsw_done + chsw_prev_no_next: + push $r2 + mov b32 $r2 $r1 + bclr $flags $p1 + bclr $flags $p2 + call #ctx_xfer + pop $r2 + mov $r1 0xb00 + shl b32 $r1 6 + iowr I[$r1] $r2 + bra #chsw_done + chsw_no_prev: + xbit $r3 $r2 31 + bra e #chsw_done + bset $flags $p1 + bclr $flags $p2 + call #ctx_xfer + + // ack the context switch request + chsw_done: + mov $r1 0xb0c + shl b32 $r1 6 + mov $r2 1 + iowr I[$r1 + 0x000] $r2 // 0x409b0c + trace_clr(T_AUTO) + bra #main + + // request to set current channel? (*not* a context switch) + main_not_ctx_switch: + cmpu b32 $r14 0x0001 + bra ne #main_not_ctx_chan + mov b32 $r2 $r15 + call #ctx_chan + bra #main_done + + // request to store current channel context? + main_not_ctx_chan: + cmpu b32 $r14 0x0002 + bra ne #main_not_ctx_save + trace_set(T_SAVE) + bclr $flags $p1 + bclr $flags $p2 + call #ctx_xfer + trace_clr(T_SAVE) + bra #main_done + + main_not_ctx_save: + shl b32 $r15 $r14 16 + or $r15 E_BAD_COMMAND + call #error + bra #main + + main_done: + mov $r1 0x820 + shl b32 $r1 6 + clear b32 $r2 + bset $r2 31 + iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 + bra #main + +// interrupt handler +ih: + push $r8 + mov $r8 $flags + push $r8 + push $r9 + push $r10 + push $r11 + push $r13 + push $r14 + push $r15 + + // incoming fifo command? + iord $r10 I[$r0 + 0x200] // INTR + and $r11 $r10 0x00000004 + bra e #ih_no_fifo + // queue incoming fifo command for later processing + mov $r11 0x1900 + mov $r13 #cmd_queue + iord $r14 I[$r11 + 0x100] // FIFO_CMD + iord $r15 I[$r11 + 0x000] // FIFO_DATA + call #queue_put + add b32 $r11 0x400 + mov $r14 1 + iowr I[$r11 + 0x000] $r14 // FIFO_ACK + + // context switch request? + ih_no_fifo: + and $r11 $r10 0x00000100 + bra e #ih_no_ctxsw + // enqueue a context switch for later processing + mov $r13 #cmd_queue + mov $r14 0x4001 + call #queue_put + + // anything we didn't handle, bring it to the host's attention + ih_no_ctxsw: + mov $r11 0x104 + not b32 $r11 + and $r11 $r10 $r11 + bra e #ih_no_other + mov $r10 0xc1c + shl b32 $r10 6 + iowr I[$r10] $r11 // INTR_UP_SET + + // ack, and wake up main() + ih_no_other: + iowr I[$r0 + 0x100] $r10 // INTR_ACK + + pop $r15 + pop $r14 + pop $r13 + pop $r11 + pop $r10 + pop $r9 + pop $r8 + mov $flags $r8 + pop $r8 + bclr $flags $p0 + iret + +// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done +ctx_4160s: + mov $r14 0x4160 + sethi $r14 0x400000 + mov $r15 1 + call #nv_wr32 + ctx_4160s_wait: + call #nv_rd32 + xbit $r15 $r15 4 + bra e #ctx_4160s_wait + ret + +// Without clearing again at end of xfer, some things cause PGRAPH +// to hang with STATUS=0x00000007 until it's cleared.. fbcon can +// still function with it set however... +ctx_4160c: + mov $r14 0x4160 + sethi $r14 0x400000 + clear b32 $r15 + call #nv_wr32 + ret + +// Again, not real sure +// +// In: $r15 value to set 0x404170 to +// +ctx_4170s: + mov $r14 0x4170 + sethi $r14 0x400000 + or $r15 0x10 + call #nv_wr32 + ret + +// Waits for a ctx_4170s() call to complete +// +ctx_4170w: + mov $r14 0x4170 + sethi $r14 0x400000 + call #nv_rd32 + and $r15 0x10 + bra ne #ctx_4170w + ret + +// Disables various things, waits a bit, and re-enables them.. +// +// Not sure how exactly this helps, perhaps "ENABLE" is not such a +// good description for the bits we turn off? Anyways, without this, +// funny things happen. +// +ctx_redswitch: + mov $r14 0x614 + shl b32 $r14 6 + mov $r15 0x270 + iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL + mov $r15 8 + ctx_redswitch_delay: + sub b32 $r15 1 + bra ne #ctx_redswitch_delay + mov $r15 0x770 + iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL + ret + +// Not a clue what this is for, except that unless the value is 0x10, the +// strand context is saved (and presumably restored) incorrectly.. +// +// In: $r15 value to set to (0x00/0x10 are used) +// +ctx_86c: + mov $r14 0x86c + shl b32 $r14 6 + iowr I[$r14] $r15 // HUB(0x86c) = val + mov $r14 -0x75ec + sethi $r14 0x400000 + call #nv_wr32 // ROP(0xa14) = val + mov $r14 -0x5794 + sethi $r14 0x410000 + call #nv_wr32 // GPC(0x86c) = val + ret + +// ctx_load - load's a channel's ctxctl data, and selects its vm +// +// In: $r2 channel address +// +ctx_load: + trace_set(T_CHAN) + + // switch to channel, somewhat magic in parts.. + mov $r10 12 // DONE_UNK12 + call #wait_donez + mov $r1 0xa24 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r0 // 0x409a24 + mov $r3 0xb00 + shl b32 $r3 6 + iowr I[$r3 + 0x100] $r2 // CHAN_NEXT + mov $r1 0xa0c + shl b32 $r1 6 + mov $r4 7 + iowr I[$r1 + 0x000] $r2 // MEM_CHAN + iowr I[$r1 + 0x100] $r4 // MEM_CMD + ctx_chan_wait_0: + iord $r4 I[$r1 + 0x100] + and $r4 0x1f + bra ne #ctx_chan_wait_0 + iowr I[$r3 + 0x000] $r2 // CHAN_CUR + + // load channel header, fetch PGRAPH context pointer + mov $xtargets $r0 + bclr $r2 31 + shl b32 $r2 4 + add b32 $r2 2 + + trace_set(T_LCHAN) + mov $r1 0xa04 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r2 // MEM_BASE + mov $r1 0xa20 + shl b32 $r1 6 + mov $r2 0x0002 + sethi $r2 0x80000000 + iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram + mov $r1 0x10 // chan + 0x0210 + mov $r2 #xfer_data + sethi $r2 0x00020000 // 16 bytes + xdld $r1 $r2 + xdwait + trace_clr(T_LCHAN) + + // update current context + ld b32 $r1 D[$r0 + #xfer_data + 4] + shl b32 $r1 24 + ld b32 $r2 D[$r0 + #xfer_data + 0] + shr b32 $r2 8 + or $r1 $r2 + st b32 D[$r0 + #ctx_current] $r1 + + // set transfer base to start of context, and fetch context header + trace_set(T_LCTXH) + mov $r2 0xa04 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r1 // MEM_BASE + mov $r2 1 + mov $r1 0xa20 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm + mov $r1 #chan_data + sethi $r1 0x00060000 // 256 bytes + xdld $r0 $r1 + xdwait + trace_clr(T_LCTXH) + + trace_clr(T_CHAN) + ret + +// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as +// the active channel for ctxctl, but not actually transfer +// any context data. intended for use only during initial +// context construction. +// +// In: $r2 channel address +// +ctx_chan: + call #ctx_4160s + call #ctx_load + mov $r10 12 // DONE_UNK12 + call #wait_donez + mov $r1 0xa10 + shl b32 $r1 6 + mov $r2 5 + iowr I[$r1 + 0x000] $r2 // MEM_CMD = 5 (???) + ctx_chan_wait: + iord $r2 I[$r1 + 0x000] + or $r2 $r2 + bra ne #ctx_chan_wait + call #ctx_4160c + ret + +// Execute per-context state overrides list +// +// Only executed on the first load of a channel. Might want to look into +// removing this and having the host directly modify the channel's context +// to change this state... The nouveau DRM already builds this list as +// it's definitely needed for NVIDIA's, so we may as well use it for now +// +// Input: $r1 mmio list length +// +ctx_mmio_exec: + // set transfer base to be the mmio list + ld b32 $r3 D[$r0 + #chan_mmio_address] + mov $r2 0xa04 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r3 // MEM_BASE + + clear b32 $r3 + ctx_mmio_loop: + // fetch next 256 bytes of mmio list if necessary + and $r4 $r3 0xff + bra ne #ctx_mmio_pull + mov $r5 #xfer_data + sethi $r5 0x00060000 // 256 bytes + xdld $r3 $r5 + xdwait + + // execute a single list entry + ctx_mmio_pull: + ld b32 $r14 D[$r4 + #xfer_data + 0x00] + ld b32 $r15 D[$r4 + #xfer_data + 0x04] + call #nv_wr32 + + // next! + add b32 $r3 8 + sub b32 $r1 1 + bra ne #ctx_mmio_loop + + // set transfer base back to the current context + ctx_mmio_done: + ld b32 $r3 D[$r0 + #ctx_current] + iowr I[$r2 + 0x000] $r3 // MEM_BASE + + // disable the mmio list now, we don't need/want to execute it again + st b32 D[$r0 + #chan_mmio_count] $r0 + mov $r1 #chan_data + sethi $r1 0x00060000 // 256 bytes + xdst $r0 $r1 + xdwait + ret + +// Transfer HUB context data between GPU and storage area +// +// In: $r2 channel address +// $p1 clear on save, set on load +// $p2 set if opposite direction done/will be done, so: +// on save it means: "a load will follow this save" +// on load it means: "a save preceeded this load" +// +ctx_xfer: + bra not $p1 #ctx_xfer_pre + bra $p2 #ctx_xfer_pre_load + ctx_xfer_pre: + mov $r15 0x10 + call #ctx_86c + call #ctx_4160s + bra not $p1 #ctx_xfer_exec + + ctx_xfer_pre_load: + mov $r15 2 + call #ctx_4170s + call #ctx_4170w + call #ctx_redswitch + clear b32 $r15 + call #ctx_4170s + call #ctx_load + + // fetch context pointer, and initiate xfer on all GPCs + ctx_xfer_exec: + ld b32 $r1 D[$r0 + #ctx_current] + mov $r2 0x414 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset + mov $r14 -0x5b00 + sethi $r14 0x410000 + mov b32 $r15 $r1 + call #nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer + add b32 $r14 4 + xbit $r15 $flags $p1 + xbit $r2 $flags $p2 + shl b32 $r2 1 + or $r15 $r2 + call #nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) + + // strands + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xc + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c + call #strand_wait + mov $r2 0x47fc + sethi $r2 0x20000 + iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 + xbit $r2 $flags $p1 + add b32 $r2 3 + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) + + // mmio context + xbit $r10 $flags $p1 // direction + or $r10 6 // first, last + mov $r11 0 // base = 0 + ld b32 $r12 D[$r0 + #hub_mmio_list_head] + ld b32 $r13 D[$r0 + #hub_mmio_list_tail] + mov $r14 0 // not multi + call #mmctx_xfer + + // wait for GPCs to all complete + mov $r10 8 // DONE_BAR + call #wait_doneo + + // wait for strand xfer to complete + call #strand_wait + + // post-op + bra $p1 #ctx_xfer_post + mov $r10 12 // DONE_UNK12 + call #wait_donez + mov $r1 0xa10 + shl b32 $r1 6 + mov $r2 5 + iowr I[$r1] $r2 // MEM_CMD + ctx_xfer_post_save_wait: + iord $r2 I[$r1] + or $r2 $r2 + bra ne #ctx_xfer_post_save_wait + + bra $p2 #ctx_xfer_done + ctx_xfer_post: + mov $r15 2 + call #ctx_4170s + clear b32 $r15 + call #ctx_86c + call #strand_post + call #ctx_4170w + clear b32 $r15 + call #ctx_4170s + + bra not $p1 #ctx_xfer_no_post_mmio + ld b32 $r1 D[$r0 + #chan_mmio_count] + or $r1 $r1 + bra e #ctx_xfer_no_post_mmio + call #ctx_mmio_exec + + ctx_xfer_no_post_mmio: + call #ctx_4160c + + ctx_xfer_done: + ret + +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h new file mode 100644 index 0000000..c5ed307 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h @@ -0,0 +1,838 @@ +uint32_t nvc0_grhub_data[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x000000c0, + 0x013c00a0, + 0x000000c1, + 0x014000a0, + 0x000000c3, + 0x013c00a0, + 0x000000c4, + 0x013c00a0, + 0x000000c8, + 0x013c00a0, + 0x000000ce, + 0x013c00a0, + 0x000000cf, + 0x013c00a0, + 0x000000d9, + 0x01dc0140, + 0x00000000, + 0x0417e91c, + 0x04400204, + 0x28404004, + 0x00404044, + 0x34404094, + 0x184040d0, + 0x004040f8, + 0x08404130, + 0x08404150, + 0x04404164, + 0x08404174, + 0x1c404200, + 0x34404404, + 0x0c404460, + 0x00404480, + 0x00404498, + 0x0c404604, + 0x7c404618, + 0x50404698, + 0x044046f0, + 0x54404700, + 0x00405800, + 0x08405830, + 0x00405854, + 0x0c405870, + 0x04405a00, + 0x00405a18, + 0x00406020, + 0x0c406028, + 0x044064a8, + 0x044064b4, + 0x00407804, + 0x1440780c, + 0x004078bc, + 0x18408000, + 0x00408064, + 0x08408800, + 0x0c408900, + 0x00408980, + 0x044064c0, + 0x0417e91c, + 0x04400204, + 0x24404004, + 0x00404044, + 0x34404094, + 0x184040d0, + 0x004040f8, + 0x08404130, + 0x08404150, + 0x04404164, + 0x04404178, + 0x1c404200, + 0x34404404, + 0x0c404460, + 0x00404480, + 0x00404498, + 0x0c404604, + 0x7c404618, + 0x50404698, + 0x044046f0, + 0x54404700, + 0x00405800, + 0x08405830, + 0x00405854, + 0x0c405870, + 0x04405a00, + 0x00405a18, + 0x00406020, + 0x0c406028, + 0x044064a8, + 0x104064b4, + 0x00407804, + 0x1440780c, + 0x004078bc, + 0x18408000, + 0x00408064, + 0x08408800, + 0x0c408900, + 0x00408980, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +uint32_t nvc0_grhub_code[] = { + 0x03090ef5, + 0x9800d898, + 0x86f001d9, + 0x0489b808, + 0xf00c1bf4, + 0x21f502f7, + 0x00f802ec, + 0xb60798c4, + 0x8dbb0384, + 0x0880b600, + 0x80008e80, + 0x90b6018f, + 0x0f94f001, + 0xf801d980, + 0x0131f400, + 0x9800d898, + 0x89b801d9, + 0x210bf404, + 0xb60789c4, + 0x9dbb0394, + 0x0890b600, + 0x98009e98, + 0x80b6019f, + 0x0f84f001, + 0xf400d880, + 0x00f80132, + 0x0728b7f1, + 0xb906b4b6, + 0xc9f002ec, + 0x00bcd01f, + 0xc800bccf, + 0x1bf41fcc, + 0x06a7f0fa, + 0x010321f5, + 0xf840bfcf, + 0x28b7f100, + 0x06b4b607, + 0xb980bfd0, + 0xc9f002ec, + 0x1ec9f01f, + 0xcf00bcd0, + 0xccc800bc, + 0xfa1bf41f, + 0x87f100f8, + 0x84b60430, + 0x1ff9f006, + 0xf8008fd0, + 0x3087f100, + 0x0684b604, + 0xf80080d0, + 0x3c87f100, + 0x0684b608, + 0x99f094bd, + 0x0089d000, + 0x081887f1, + 0xd00684b6, + 0x87f1008a, + 0x84b60400, + 0x0088cf06, + 0xf4888aff, + 0x87f1f31b, + 0x84b6085c, + 0xf094bd06, + 0x89d00099, + 0xf100f800, + 0xb6083c87, + 0x94bd0684, + 0xd00099f0, + 0x87f10089, + 0x84b60818, + 0x008ad006, + 0x040087f1, + 0xcf0684b6, + 0x8aff0088, + 0xf30bf488, + 0x085c87f1, + 0xbd0684b6, + 0x0099f094, + 0xf80089d0, + 0x9894bd00, + 0x85b600e8, + 0x0180b61a, + 0xbb0284b6, + 0xe0b60098, + 0x04efb804, + 0xb9eb1bf4, + 0x00f8029f, + 0x083c87f1, + 0xbd0684b6, + 0x0199f094, + 0xf10089d0, + 0xb6071087, + 0x94bd0684, + 0xf405bbfd, + 0x8bd0090b, + 0x0099f000, + 0xf405eefd, + 0x8ed00c0b, + 0xc08fd080, + 0xb70199f0, + 0xc8010080, + 0xb4b600ab, + 0x0cb9f010, + 0xb601aec8, + 0xbefd11e4, + 0x008bd005, + 0xf0008ecf, + 0x0bf41fe4, + 0x00ce98fa, + 0xd005e9fd, + 0xc0b6c08e, + 0x04cdb804, + 0xc8e81bf4, + 0x1bf402ab, + 0x008bcf18, + 0xb01fb4f0, + 0x1bf410b4, + 0x02a7f0f7, + 0xf4c921f4, + 0xabc81b0e, + 0x10b4b600, + 0xf00cb9f0, + 0x8bd012b9, + 0x008bcf00, + 0xf412bbc8, + 0x87f1fa1b, + 0x84b6085c, + 0xf094bd06, + 0x89d00199, + 0xf900f800, + 0x02a7f0a0, + 0xfcc921f4, + 0xf100f8a0, + 0xf04afc87, + 0x97f00283, + 0x0089d00c, + 0x020721f5, + 0x87f100f8, + 0x83f04afc, + 0x0d97f002, + 0xf50089d0, + 0xf8020721, + 0xfca7f100, + 0x02a3f04f, + 0x0500aba2, + 0xd00fc7f0, + 0xc7f000ac, + 0x00bcd00b, + 0x020721f5, + 0xf000aed0, + 0xbcd00ac7, + 0x0721f500, + 0xf100f802, + 0xb6083c87, + 0x94bd0684, + 0xd00399f0, + 0x21f50089, + 0xe7f00213, + 0x3921f503, + 0xfca7f102, + 0x02a3f046, + 0x0400aba0, + 0xf040a0d0, + 0xbcd001c7, + 0x0721f500, + 0x010c9202, + 0xf000acd0, + 0xbcd002c7, + 0x0721f500, + 0x2621f502, + 0x8087f102, + 0x0684b608, + 0xb70089cf, + 0x95220080, + 0x8ed008fe, + 0x408ed000, + 0xb6808acf, + 0xa0b606a5, + 0x00eabb01, + 0xb60480b6, + 0x1bf40192, + 0x08e4b6e8, + 0xf1f2efbc, + 0xb6085c87, + 0x94bd0684, + 0xd00399f0, + 0x00f80089, + 0xe7f1e0f9, + 0xe4b60814, + 0x00efd006, + 0x0c1ce7f1, + 0xf006e4b6, + 0xefd001f7, + 0xf8e0fc00, + 0xfe04bd00, + 0x07fe0004, + 0x0017f100, + 0x0227f012, + 0xf10012d0, + 0xfe05b917, + 0x17f10010, + 0x10d00400, + 0x0437f1c0, + 0x0634b604, + 0x200327f1, + 0xf10032d0, + 0xd0200427, + 0x27f10132, + 0x32d0200b, + 0x0c27f102, + 0x0732d020, + 0x0c2427f1, + 0xb90624b6, + 0x23d00003, + 0x0427f100, + 0x0023f087, + 0xb70012d0, + 0xf0010012, + 0x12d00427, + 0x1031f400, + 0x9604e7f1, + 0xf440e3f0, + 0xf1c76821, + 0x01018090, + 0x801ff4f0, + 0x17f0000f, + 0x041fbb01, + 0xf10112b6, + 0xb6040c27, + 0x21d00624, + 0x4021d000, + 0x080027f1, + 0xcf0624b6, + 0xf7f00022, + 0x08f0b654, + 0xb800f398, + 0x0bf40432, + 0x0034b00b, + 0xf8f11bf4, + 0x0017f100, + 0x02fe5801, + 0xf003ff58, + 0x0e8000e3, + 0x150f8014, + 0x013d21f5, + 0x070037f1, + 0x950634b6, + 0x34d00814, + 0x4034d000, + 0x130030b7, + 0xb6001fbb, + 0x3fd002f5, + 0x0815b600, + 0xb60110b6, + 0x1fb90814, + 0x6321f502, + 0x001fbb02, + 0xf1000398, + 0xf0200047, + 0x4ea05043, + 0x1fb90804, + 0x8d21f402, + 0x08004ea0, + 0xf4022fb9, + 0x4ea08d21, + 0xf4bd010c, + 0xa08d21f4, + 0xf401044e, + 0x4ea08d21, + 0xf7f00100, + 0x8d21f402, + 0x08004ea0, + 0xc86821f4, + 0x0bf41fff, + 0x044ea0fa, + 0x6821f408, + 0xb7001fbb, + 0xb6800040, + 0x1bf40132, + 0x0027f1b4, + 0x0624b608, + 0xb74021d0, + 0xbd080020, + 0x1f19f014, + 0xf40021d0, + 0x28f40031, + 0x08d7f000, + 0xf43921f4, + 0xe4b1f401, + 0x1bf54001, + 0x87f100d1, + 0x84b6083c, + 0xf094bd06, + 0x89d00499, + 0x0017f100, + 0x0614b60b, + 0xcf4012cf, + 0x13c80011, + 0x7e0bf41f, + 0xf41f23c8, + 0x20f95a0b, + 0xf10212b9, + 0xb6083c87, + 0x94bd0684, + 0xd00799f0, + 0x32f40089, + 0x0231f401, + 0x082921f5, + 0x085c87f1, + 0xbd0684b6, + 0x0799f094, + 0xfc0089d0, + 0x3c87f120, + 0x0684b608, + 0x99f094bd, + 0x0089d006, + 0xf50131f4, + 0xf1082921, + 0xb6085c87, + 0x94bd0684, + 0xd00699f0, + 0x0ef40089, + 0xb920f931, + 0x32f40212, + 0x0232f401, + 0x082921f5, + 0x17f120fc, + 0x14b60b00, + 0x0012d006, + 0xc8130ef4, + 0x0bf41f23, + 0x0131f40d, + 0xf50232f4, + 0xf1082921, + 0xb60b0c17, + 0x27f00614, + 0x0012d001, + 0x085c87f1, + 0xbd0684b6, + 0x0499f094, + 0xf50089d0, + 0xb0ff200e, + 0x1bf401e4, + 0x02f2b90d, + 0x07b521f5, + 0xb0420ef4, + 0x1bf402e4, + 0x3c87f12e, + 0x0684b608, + 0x99f094bd, + 0x0089d007, + 0xf40132f4, + 0x21f50232, + 0x87f10829, + 0x84b6085c, + 0xf094bd06, + 0x89d00799, + 0x110ef400, + 0xf010ef94, + 0x21f501f5, + 0x0ef502ec, + 0x17f1fed1, + 0x14b60820, + 0xf024bd06, + 0x12d01f29, + 0xbe0ef500, + 0xfe80f9fe, + 0x80f90188, + 0xa0f990f9, + 0xd0f9b0f9, + 0xf0f9e0f9, + 0xc4800acf, + 0x0bf404ab, + 0x00b7f11d, + 0x08d7f019, + 0xcf40becf, + 0x21f400bf, + 0x00b0b704, + 0x01e7f004, + 0xe400bed0, + 0xf40100ab, + 0xd7f00d0b, + 0x01e7f108, + 0x0421f440, + 0x0104b7f1, + 0xabffb0bd, + 0x0d0bf4b4, + 0x0c1ca7f1, + 0xd006a4b6, + 0x0ad000ab, + 0xfcf0fc40, + 0xfcd0fce0, + 0xfca0fcb0, + 0xfe80fc90, + 0x80fc0088, + 0xf80032f4, + 0x60e7f101, + 0x40e3f041, + 0xf401f7f0, + 0x21f48d21, + 0x04ffc868, + 0xf8fa0bf4, + 0x60e7f100, + 0x40e3f041, + 0x21f4f4bd, + 0xf100f88d, + 0xf04170e7, + 0xf5f040e3, + 0x8d21f410, + 0xe7f100f8, + 0xe3f04170, + 0x6821f440, + 0xf410f4f0, + 0x00f8f31b, + 0x0614e7f1, + 0xf106e4b6, + 0xd00270f7, + 0xf7f000ef, + 0x01f2b608, + 0xf1fd1bf4, + 0xd00770f7, + 0x00f800ef, + 0x086ce7f1, + 0xd006e4b6, + 0xe7f100ef, + 0xe3f08a14, + 0x8d21f440, + 0xa86ce7f1, + 0xf441e3f0, + 0x00f88d21, + 0x083c87f1, + 0xbd0684b6, + 0x0599f094, + 0xf00089d0, + 0x21f40ca7, + 0x2417f1c9, + 0x0614b60a, + 0xf10010d0, + 0xb60b0037, + 0x32d00634, + 0x0c17f140, + 0x0614b60a, + 0xd00747f0, + 0x14d00012, + 0x4014cf40, + 0xf41f44f0, + 0x32d0fa1b, + 0x000bfe00, + 0xb61f2af0, + 0x20b60424, + 0x3c87f102, + 0x0684b608, + 0x99f094bd, + 0x0089d008, + 0x0a0417f1, + 0xd00614b6, + 0x17f10012, + 0x14b60a20, + 0x0227f006, + 0x800023f1, + 0xf00012d0, + 0x27f11017, + 0x23f00300, + 0x0512fa02, + 0x87f103f8, + 0x84b6085c, + 0xf094bd06, + 0x89d00899, + 0xc1019800, + 0x981814b6, + 0x25b6c002, + 0x0512fd08, + 0xf1160180, + 0xb6083c87, + 0x94bd0684, + 0xd00999f0, + 0x27f10089, + 0x24b60a04, + 0x0021d006, + 0xf10127f0, + 0xb60a2017, + 0x12d00614, + 0x0017f100, + 0x0613f002, + 0xf80501fa, + 0x5c87f103, + 0x0684b608, + 0x99f094bd, + 0x0089d009, + 0x085c87f1, + 0xbd0684b6, + 0x0599f094, + 0xf80089d0, + 0x3121f500, + 0xb821f506, + 0x0ca7f006, + 0xf1c921f4, + 0xb60a1017, + 0x27f00614, + 0x0012d005, + 0xfd0012cf, + 0x1bf40522, + 0x4921f5fa, + 0x9800f806, + 0x27f18103, + 0x24b60a04, + 0x0023d006, + 0x34c434bd, + 0x0f1bf4ff, + 0x030057f1, + 0xfa0653f0, + 0x03f80535, + 0x98c04e98, + 0x21f4c14f, + 0x0830b68d, + 0xf40112b6, + 0x0398df1b, + 0x0023d016, + 0xf1800080, + 0xf0020017, + 0x01fa0613, + 0xf803f806, + 0x0611f400, + 0xf01102f4, + 0x21f510f7, + 0x21f50698, + 0x11f40631, + 0x02f7f01c, + 0x065721f5, + 0x066621f5, + 0x067821f5, + 0x21f5f4bd, + 0x21f50657, + 0x019806b8, + 0x1427f116, + 0x0624b604, + 0xf10020d0, + 0xf0a500e7, + 0x1fb941e3, + 0x8d21f402, + 0xf004e0b6, + 0x2cf001fc, + 0x0124b602, + 0xf405f2fd, + 0x17f18d21, + 0x13f04afc, + 0x0c27f002, + 0xf50012d0, + 0xf1020721, + 0xf047fc27, + 0x20d00223, + 0x012cf000, + 0xd00320b6, + 0xacf00012, + 0x06a5f001, + 0x9800b7f0, + 0x0d98140c, + 0x00e7f015, + 0x015c21f5, + 0xf508a7f0, + 0xf5010321, + 0xf4020721, + 0xa7f02201, + 0xc921f40c, + 0x0a1017f1, + 0xf00614b6, + 0x12d00527, + 0x0012cf00, + 0xf40522fd, + 0x02f4fa1b, + 0x02f7f032, + 0x065721f5, + 0x21f5f4bd, + 0x21f50698, + 0x21f50226, + 0xf4bd0666, + 0x065721f5, + 0x981011f4, + 0x11fd8001, + 0x070bf405, + 0x07df21f5, + 0x064921f5, + 0x000000f8, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc new file mode 100644 index 0000000..e6b2288 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc @@ -0,0 +1,400 @@ +/* fuc microcode util functions for nvc0 PGRAPH + * + * Copyright 2011 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: + * + * 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 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 + */ + +define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)') +define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))') + +ifdef(`include_code', ` +// Error codes +define(`E_BAD_COMMAND', 0x01) +define(`E_CMD_OVERFLOW', 0x02) + +// Util macros to help with debugging ucode hangs etc +define(`T_WAIT', 0) +define(`T_MMCTX', 1) +define(`T_STRWAIT', 2) +define(`T_STRINIT', 3) +define(`T_AUTO', 4) +define(`T_CHAN', 5) +define(`T_LOAD', 6) +define(`T_SAVE', 7) +define(`T_LCHAN', 8) +define(`T_LCTXH', 9) + +define(`trace_set', ` + mov $r8 0x83c + shl b32 $r8 6 + clear b32 $r9 + bset $r9 $1 + iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] +') + +define(`trace_clr', ` + mov $r8 0x85c + shl b32 $r8 6 + clear b32 $r9 + bset $r9 $1 + iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] +') + +// queue_put - add request to queue +// +// In : $r13 queue pointer +// $r14 command +// $r15 data +// +queue_put: + // make sure we have space.. + ld b32 $r8 D[$r13 + 0x0] // GET + ld b32 $r9 D[$r13 + 0x4] // PUT + xor $r8 8 + cmpu b32 $r8 $r9 + bra ne #queue_put_next + mov $r15 E_CMD_OVERFLOW + call #error + ret + + // store cmd/data on queue + queue_put_next: + and $r8 $r9 7 + shl b32 $r8 3 + add b32 $r8 $r13 + add b32 $r8 8 + st b32 D[$r8 + 0x0] $r14 + st b32 D[$r8 + 0x4] $r15 + + // update PUT + add b32 $r9 1 + and $r9 0xf + st b32 D[$r13 + 0x4] $r9 + ret + +// queue_get - fetch request from queue +// +// In : $r13 queue pointer +// +// Out: $p1 clear on success (data available) +// $r14 command +// $r15 data +// +queue_get: + bset $flags $p1 + ld b32 $r8 D[$r13 + 0x0] // GET + ld b32 $r9 D[$r13 + 0x4] // PUT + cmpu b32 $r8 $r9 + bra e #queue_get_done + // fetch first cmd/data pair + and $r9 $r8 7 + shl b32 $r9 3 + add b32 $r9 $r13 + add b32 $r9 8 + ld b32 $r14 D[$r9 + 0x0] + ld b32 $r15 D[$r9 + 0x4] + + // update GET + add b32 $r8 1 + and $r8 0xf + st b32 D[$r13 + 0x0] $r8 + bclr $flags $p1 +queue_get_done: + ret + +// nv_rd32 - read 32-bit value from nv register +// +// In : $r14 register +// Out: $r15 value +// +nv_rd32: + mov $r11 0x728 + shl b32 $r11 6 + mov b32 $r12 $r14 + bset $r12 31 // MMIO_CTRL_PENDING + iowr I[$r11 + 0x000] $r12 // MMIO_CTRL + nv_rd32_wait: + iord $r12 I[$r11 + 0x000] + xbit $r12 $r12 31 + bra ne #nv_rd32_wait + mov $r10 6 // DONE_MMIO_RD + call #wait_doneo + iord $r15 I[$r11 + 0x100] // MMIO_RDVAL + ret + +// nv_wr32 - write 32-bit value to nv register +// +// In : $r14 register +// $r15 value +// +nv_wr32: + mov $r11 0x728 + shl b32 $r11 6 + iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL + mov b32 $r12 $r14 + bset $r12 31 // MMIO_CTRL_PENDING + bset $r12 30 // MMIO_CTRL_WRITE + iowr I[$r11 + 0x000] $r12 // MMIO_CTRL + nv_wr32_wait: + iord $r12 I[$r11 + 0x000] + xbit $r12 $r12 31 + bra ne #nv_wr32_wait + ret + +// (re)set watchdog timer +// +// In : $r15 timeout +// +watchdog_reset: + mov $r8 0x430 + shl b32 $r8 6 + bset $r15 31 + iowr I[$r8 + 0x000] $r15 + ret + +// clear watchdog timer +watchdog_clear: + mov $r8 0x430 + shl b32 $r8 6 + iowr I[$r8 + 0x000] $r0 + ret + +// wait_done{z,o} - wait on FUC_DONE bit to become clear/set +// +// In : $r10 bit to wait on +// +define(`wait_done', ` +$1: + trace_set(T_WAIT); + mov $r8 0x818 + shl b32 $r8 6 + iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit + wait_done_$1: + mov $r8 0x400 + shl b32 $r8 6 + iord $r8 I[$r8 + 0x000] // DONE + xbit $r8 $r8 $r10 + bra $2 #wait_done_$1 + trace_clr(T_WAIT) + ret +') +wait_done(wait_donez, ne) +wait_done(wait_doneo, e) + +// mmctx_size - determine size of a mmio list transfer +// +// In : $r14 mmio list head +// $r15 mmio list tail +// Out: $r15 transfer size (in bytes) +// +mmctx_size: + clear b32 $r9 + nv_mmctx_size_loop: + ld b32 $r8 D[$r14] + shr b32 $r8 26 + add b32 $r8 1 + shl b32 $r8 2 + add b32 $r9 $r8 + add b32 $r14 4 + cmpu b32 $r14 $r15 + bra ne #nv_mmctx_size_loop + mov b32 $r15 $r9 + ret + +// mmctx_xfer - execute a list of mmio transfers +// +// In : $r10 flags +// bit 0: direction (0 = save, 1 = load) +// bit 1: set if first transfer +// bit 2: set if last transfer +// $r11 base +// $r12 mmio list head +// $r13 mmio list tail +// $r14 multi_stride +// $r15 multi_mask +// +mmctx_xfer: + trace_set(T_MMCTX) + mov $r8 0x710 + shl b32 $r8 6 + clear b32 $r9 + or $r11 $r11 + bra e #mmctx_base_disabled + iowr I[$r8 + 0x000] $r11 // MMCTX_BASE + bset $r9 0 // BASE_EN + mmctx_base_disabled: + or $r14 $r14 + bra e #mmctx_multi_disabled + iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE + iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK + bset $r9 1 // MULTI_EN + mmctx_multi_disabled: + add b32 $r8 0x100 + + xbit $r11 $r10 0 + shl b32 $r11 16 // DIR + bset $r11 12 // QLIMIT = 0x10 + xbit $r14 $r10 1 + shl b32 $r14 17 + or $r11 $r14 // START_TRIGGER + iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL + + // loop over the mmio list, and send requests to the hw + mmctx_exec_loop: + // wait for space in mmctx queue + mmctx_wait_free: + iord $r14 I[$r8 + 0x000] // MMCTX_CTRL + and $r14 0x1f + bra e #mmctx_wait_free + + // queue up an entry + ld b32 $r14 D[$r12] + or $r14 $r9 + iowr I[$r8 + 0x300] $r14 + add b32 $r12 4 + cmpu b32 $r12 $r13 + bra ne #mmctx_exec_loop + + xbit $r11 $r10 2 + bra ne #mmctx_stop + // wait for queue to empty + mmctx_fini_wait: + iord $r11 I[$r8 + 0x000] // MMCTX_CTRL + and $r11 0x1f + cmpu b32 $r11 0x10 + bra ne #mmctx_fini_wait + mov $r10 2 // DONE_MMCTX + call #wait_donez + bra #mmctx_done + mmctx_stop: + xbit $r11 $r10 0 + shl b32 $r11 16 // DIR + bset $r11 12 // QLIMIT = 0x10 + bset $r11 18 // STOP_TRIGGER + iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL + mmctx_stop_wait: + // wait for STOP_TRIGGER to clear + iord $r11 I[$r8 + 0x000] // MMCTX_CTRL + xbit $r11 $r11 18 + bra ne #mmctx_stop_wait + mmctx_done: + trace_clr(T_MMCTX) + ret + +// Wait for DONE_STRAND +// +strand_wait: + push $r10 + mov $r10 2 + call #wait_donez + pop $r10 + ret + +// unknown - call before issuing strand commands +// +strand_pre: + mov $r8 0x4afc + sethi $r8 0x20000 + mov $r9 0xc + iowr I[$r8] $r9 + call #strand_wait + ret + +// unknown - call after issuing strand commands +// +strand_post: + mov $r8 0x4afc + sethi $r8 0x20000 + mov $r9 0xd + iowr I[$r8] $r9 + call #strand_wait + ret + +// Selects strand set?! +// +// In: $r14 id +// +strand_set: + mov $r10 0x4ffc + sethi $r10 0x20000 + sub b32 $r11 $r10 0x500 + mov $r12 0xf + iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf + mov $r12 0xb + iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb + call #strand_wait + iowr I[$r10 + 0x000] $r14 // 0x93c = + mov $r12 0xa + iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa + call #strand_wait + ret + +// Initialise strand context data +// +// In : $r15 context base +// Out: $r15 context size (in bytes) +// +// Strandset(?) 3 hardcoded currently +// +strand_ctx_init: + trace_set(T_STRINIT) + call #strand_pre + mov $r14 3 + call #strand_set + mov $r10 0x46fc + sethi $r10 0x20000 + add b32 $r11 $r10 0x400 + iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 + mov $r12 1 + iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE + call #strand_wait + sub b32 $r12 $r0 1 + iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff + mov $r12 2 + iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT + call #strand_wait + call #strand_post + + // read the size of each strand, poke the context offset of + // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry + // about it later then. + mov $r8 0x880 + shl b32 $r8 6 + iord $r9 I[$r8 + 0x000] // STRANDS + add b32 $r8 0x2200 + shr b32 $r14 $r15 8 + ctx_init_strand_loop: + iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE + iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE + iord $r10 I[$r8 + 0x200] // STRAND_SIZE + shr b32 $r10 6 + add b32 $r10 1 + add b32 $r14 $r10 + add b32 $r8 4 + sub b32 $r9 1 + bra ne #ctx_init_strand_loop + + shl b32 $r14 8 + sub b32 $r15 $r14 $r15 + trace_clr(T_STRINIT) + ret +') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c new file mode 100644 index 0000000..353d4d3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c @@ -0,0 +1,1326 @@ +/* + * Copyright 2007 Stephane Marchesin + * All Rights Reserved. + * + * 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 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 + * PRECISION INSIGHT 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. + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" +#include "nouveau_util.h" +#include + +struct nv04_graph_engine { + struct nouveau_exec_engine base; +}; + +static uint32_t nv04_graph_ctx_regs[] = { + 0x0040053c, + 0x00400544, + 0x00400540, + 0x00400548, + NV04_PGRAPH_CTX_SWITCH1, + NV04_PGRAPH_CTX_SWITCH2, + NV04_PGRAPH_CTX_SWITCH3, + NV04_PGRAPH_CTX_SWITCH4, + NV04_PGRAPH_CTX_CACHE1, + NV04_PGRAPH_CTX_CACHE2, + NV04_PGRAPH_CTX_CACHE3, + NV04_PGRAPH_CTX_CACHE4, + 0x00400184, + 0x004001a4, + 0x004001c4, + 0x004001e4, + 0x00400188, + 0x004001a8, + 0x004001c8, + 0x004001e8, + 0x0040018c, + 0x004001ac, + 0x004001cc, + 0x004001ec, + 0x00400190, + 0x004001b0, + 0x004001d0, + 0x004001f0, + 0x00400194, + 0x004001b4, + 0x004001d4, + 0x004001f4, + 0x00400198, + 0x004001b8, + 0x004001d8, + 0x004001f8, + 0x0040019c, + 0x004001bc, + 0x004001dc, + 0x004001fc, + 0x00400174, + NV04_PGRAPH_DMA_START_0, + NV04_PGRAPH_DMA_START_1, + NV04_PGRAPH_DMA_LENGTH, + NV04_PGRAPH_DMA_MISC, + NV04_PGRAPH_DMA_PITCH, + NV04_PGRAPH_BOFFSET0, + NV04_PGRAPH_BBASE0, + NV04_PGRAPH_BLIMIT0, + NV04_PGRAPH_BOFFSET1, + NV04_PGRAPH_BBASE1, + NV04_PGRAPH_BLIMIT1, + NV04_PGRAPH_BOFFSET2, + NV04_PGRAPH_BBASE2, + NV04_PGRAPH_BLIMIT2, + NV04_PGRAPH_BOFFSET3, + NV04_PGRAPH_BBASE3, + NV04_PGRAPH_BLIMIT3, + NV04_PGRAPH_BOFFSET4, + NV04_PGRAPH_BBASE4, + NV04_PGRAPH_BLIMIT4, + NV04_PGRAPH_BOFFSET5, + NV04_PGRAPH_BBASE5, + NV04_PGRAPH_BLIMIT5, + NV04_PGRAPH_BPITCH0, + NV04_PGRAPH_BPITCH1, + NV04_PGRAPH_BPITCH2, + NV04_PGRAPH_BPITCH3, + NV04_PGRAPH_BPITCH4, + NV04_PGRAPH_SURFACE, + NV04_PGRAPH_STATE, + NV04_PGRAPH_BSWIZZLE2, + NV04_PGRAPH_BSWIZZLE5, + NV04_PGRAPH_BPIXEL, + NV04_PGRAPH_NOTIFY, + NV04_PGRAPH_PATT_COLOR0, + NV04_PGRAPH_PATT_COLOR1, + NV04_PGRAPH_PATT_COLORRAM+0x00, + NV04_PGRAPH_PATT_COLORRAM+0x04, + NV04_PGRAPH_PATT_COLORRAM+0x08, + NV04_PGRAPH_PATT_COLORRAM+0x0c, + NV04_PGRAPH_PATT_COLORRAM+0x10, + NV04_PGRAPH_PATT_COLORRAM+0x14, + NV04_PGRAPH_PATT_COLORRAM+0x18, + NV04_PGRAPH_PATT_COLORRAM+0x1c, + NV04_PGRAPH_PATT_COLORRAM+0x20, + NV04_PGRAPH_PATT_COLORRAM+0x24, + NV04_PGRAPH_PATT_COLORRAM+0x28, + NV04_PGRAPH_PATT_COLORRAM+0x2c, + NV04_PGRAPH_PATT_COLORRAM+0x30, + NV04_PGRAPH_PATT_COLORRAM+0x34, + NV04_PGRAPH_PATT_COLORRAM+0x38, + NV04_PGRAPH_PATT_COLORRAM+0x3c, + NV04_PGRAPH_PATT_COLORRAM+0x40, + NV04_PGRAPH_PATT_COLORRAM+0x44, + NV04_PGRAPH_PATT_COLORRAM+0x48, + NV04_PGRAPH_PATT_COLORRAM+0x4c, + NV04_PGRAPH_PATT_COLORRAM+0x50, + NV04_PGRAPH_PATT_COLORRAM+0x54, + NV04_PGRAPH_PATT_COLORRAM+0x58, + NV04_PGRAPH_PATT_COLORRAM+0x5c, + NV04_PGRAPH_PATT_COLORRAM+0x60, + NV04_PGRAPH_PATT_COLORRAM+0x64, + NV04_PGRAPH_PATT_COLORRAM+0x68, + NV04_PGRAPH_PATT_COLORRAM+0x6c, + NV04_PGRAPH_PATT_COLORRAM+0x70, + NV04_PGRAPH_PATT_COLORRAM+0x74, + NV04_PGRAPH_PATT_COLORRAM+0x78, + NV04_PGRAPH_PATT_COLORRAM+0x7c, + NV04_PGRAPH_PATT_COLORRAM+0x80, + NV04_PGRAPH_PATT_COLORRAM+0x84, + NV04_PGRAPH_PATT_COLORRAM+0x88, + NV04_PGRAPH_PATT_COLORRAM+0x8c, + NV04_PGRAPH_PATT_COLORRAM+0x90, + NV04_PGRAPH_PATT_COLORRAM+0x94, + NV04_PGRAPH_PATT_COLORRAM+0x98, + NV04_PGRAPH_PATT_COLORRAM+0x9c, + NV04_PGRAPH_PATT_COLORRAM+0xa0, + NV04_PGRAPH_PATT_COLORRAM+0xa4, + NV04_PGRAPH_PATT_COLORRAM+0xa8, + NV04_PGRAPH_PATT_COLORRAM+0xac, + NV04_PGRAPH_PATT_COLORRAM+0xb0, + NV04_PGRAPH_PATT_COLORRAM+0xb4, + NV04_PGRAPH_PATT_COLORRAM+0xb8, + NV04_PGRAPH_PATT_COLORRAM+0xbc, + NV04_PGRAPH_PATT_COLORRAM+0xc0, + NV04_PGRAPH_PATT_COLORRAM+0xc4, + NV04_PGRAPH_PATT_COLORRAM+0xc8, + NV04_PGRAPH_PATT_COLORRAM+0xcc, + NV04_PGRAPH_PATT_COLORRAM+0xd0, + NV04_PGRAPH_PATT_COLORRAM+0xd4, + NV04_PGRAPH_PATT_COLORRAM+0xd8, + NV04_PGRAPH_PATT_COLORRAM+0xdc, + NV04_PGRAPH_PATT_COLORRAM+0xe0, + NV04_PGRAPH_PATT_COLORRAM+0xe4, + NV04_PGRAPH_PATT_COLORRAM+0xe8, + NV04_PGRAPH_PATT_COLORRAM+0xec, + NV04_PGRAPH_PATT_COLORRAM+0xf0, + NV04_PGRAPH_PATT_COLORRAM+0xf4, + NV04_PGRAPH_PATT_COLORRAM+0xf8, + NV04_PGRAPH_PATT_COLORRAM+0xfc, + NV04_PGRAPH_PATTERN, + 0x0040080c, + NV04_PGRAPH_PATTERN_SHAPE, + 0x00400600, + NV04_PGRAPH_ROP3, + NV04_PGRAPH_CHROMA, + NV04_PGRAPH_BETA_AND, + NV04_PGRAPH_BETA_PREMULT, + NV04_PGRAPH_CONTROL0, + NV04_PGRAPH_CONTROL1, + NV04_PGRAPH_CONTROL2, + NV04_PGRAPH_BLEND, + NV04_PGRAPH_STORED_FMT, + NV04_PGRAPH_SOURCE_COLOR, + 0x00400560, + 0x00400568, + 0x00400564, + 0x0040056c, + 0x00400400, + 0x00400480, + 0x00400404, + 0x00400484, + 0x00400408, + 0x00400488, + 0x0040040c, + 0x0040048c, + 0x00400410, + 0x00400490, + 0x00400414, + 0x00400494, + 0x00400418, + 0x00400498, + 0x0040041c, + 0x0040049c, + 0x00400420, + 0x004004a0, + 0x00400424, + 0x004004a4, + 0x00400428, + 0x004004a8, + 0x0040042c, + 0x004004ac, + 0x00400430, + 0x004004b0, + 0x00400434, + 0x004004b4, + 0x00400438, + 0x004004b8, + 0x0040043c, + 0x004004bc, + 0x00400440, + 0x004004c0, + 0x00400444, + 0x004004c4, + 0x00400448, + 0x004004c8, + 0x0040044c, + 0x004004cc, + 0x00400450, + 0x004004d0, + 0x00400454, + 0x004004d4, + 0x00400458, + 0x004004d8, + 0x0040045c, + 0x004004dc, + 0x00400460, + 0x004004e0, + 0x00400464, + 0x004004e4, + 0x00400468, + 0x004004e8, + 0x0040046c, + 0x004004ec, + 0x00400470, + 0x004004f0, + 0x00400474, + 0x004004f4, + 0x00400478, + 0x004004f8, + 0x0040047c, + 0x004004fc, + 0x00400534, + 0x00400538, + 0x00400514, + 0x00400518, + 0x0040051c, + 0x00400520, + 0x00400524, + 0x00400528, + 0x0040052c, + 0x00400530, + 0x00400d00, + 0x00400d40, + 0x00400d80, + 0x00400d04, + 0x00400d44, + 0x00400d84, + 0x00400d08, + 0x00400d48, + 0x00400d88, + 0x00400d0c, + 0x00400d4c, + 0x00400d8c, + 0x00400d10, + 0x00400d50, + 0x00400d90, + 0x00400d14, + 0x00400d54, + 0x00400d94, + 0x00400d18, + 0x00400d58, + 0x00400d98, + 0x00400d1c, + 0x00400d5c, + 0x00400d9c, + 0x00400d20, + 0x00400d60, + 0x00400da0, + 0x00400d24, + 0x00400d64, + 0x00400da4, + 0x00400d28, + 0x00400d68, + 0x00400da8, + 0x00400d2c, + 0x00400d6c, + 0x00400dac, + 0x00400d30, + 0x00400d70, + 0x00400db0, + 0x00400d34, + 0x00400d74, + 0x00400db4, + 0x00400d38, + 0x00400d78, + 0x00400db8, + 0x00400d3c, + 0x00400d7c, + 0x00400dbc, + 0x00400590, + 0x00400594, + 0x00400598, + 0x0040059c, + 0x004005a8, + 0x004005ac, + 0x004005b0, + 0x004005b4, + 0x004005c0, + 0x004005c4, + 0x004005c8, + 0x004005cc, + 0x004005d0, + 0x004005d4, + 0x004005d8, + 0x004005dc, + 0x004005e0, + NV04_PGRAPH_PASSTHRU_0, + NV04_PGRAPH_PASSTHRU_1, + NV04_PGRAPH_PASSTHRU_2, + NV04_PGRAPH_DVD_COLORFMT, + NV04_PGRAPH_SCALED_FORMAT, + NV04_PGRAPH_MISC24_0, + NV04_PGRAPH_MISC24_1, + NV04_PGRAPH_MISC24_2, + 0x00400500, + 0x00400504, + NV04_PGRAPH_VALID1, + NV04_PGRAPH_VALID2, + NV04_PGRAPH_DEBUG_3 +}; + +struct graph_state { + uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; +}; + +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); + + 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) +{ + 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; +} + +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; +} + +/* + * Software methods, why they are needed, and how they all work: + * + * NV04 and NV05 keep most of the state in PGRAPH context itself, but some + * 2d engine settings are kept inside the grobjs themselves. The grobjs are + * 3 words long on both. grobj format on NV04 is: + * + * word 0: + * - bits 0-7: class + * - bit 12: color key active + * - bit 13: clip rect active + * - bit 14: if set, destination surface is swizzled and taken from buffer 5 + * [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken + * from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or + * NV03_CONTEXT_SURFACE_DST]. + * - bits 15-17: 2d operation [aka patch config] + * - bit 24: patch valid [enables rendering using this object] + * - bit 25: surf3d valid [for tex_tri and multitex_tri only] + * word 1: + * - bits 0-1: mono format + * - bits 8-13: color format + * - bits 16-31: DMA_NOTIFY instance + * word 2: + * - bits 0-15: DMA_A instance + * - bits 16-31: DMA_B instance + * + * On NV05 it's: + * + * word 0: + * - bits 0-7: class + * - bit 12: color key active + * - bit 13: clip rect active + * - bit 14: if set, destination surface is swizzled and taken from buffer 5 + * [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken + * from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or + * NV03_CONTEXT_SURFACE_DST]. + * - bits 15-17: 2d operation [aka patch config] + * - bits 20-22: dither mode + * - bit 24: patch valid [enables rendering using this object] + * - bit 25: surface_dst/surface_color/surf2d/surf3d valid + * - bit 26: surface_src/surface_zeta valid + * - bit 27: pattern valid + * - bit 28: rop valid + * - bit 29: beta1 valid + * - bit 30: beta4 valid + * word 1: + * - bits 0-1: mono format + * - bits 8-13: color format + * - bits 16-31: DMA_NOTIFY instance + * word 2: + * - bits 0-15: DMA_A instance + * - bits 16-31: DMA_B instance + * + * NV05 will set/unset the relevant valid bits when you poke the relevant + * object-binding methods with object of the proper type, or with the NULL + * type. It'll only allow rendering using the grobj if all needed objects + * are bound. The needed set of objects depends on selected operation: for + * example rop object is needed by ROP_AND, but not by SRCCOPY_AND. + * + * NV04 doesn't have these methods implemented at all, and doesn't have the + * relevant bits in grobj. Instead, it'll allow rendering whenever bit 24 + * is set. So we have to emulate them in software, internally keeping the + * same bits as NV05 does. Since grobjs are aligned to 16 bytes on nv04, + * but the last word isn't actually used for anything, we abuse it for this + * purpose. + * + * Actually, NV05 can optionally check bit 24 too, but we disable this since + * there's no use for it. + * + * For unknown reasons, NV04 implements surf3d binding in hardware as an + * exception. Also for unknown reasons, NV04 doesn't implement the clipping + * methods on the surf3d object, so we have to emulate them too. + */ + +static void +nv04_graph_set_ctx1(struct nouveau_channel *chan, 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; + u32 tmp; + + tmp = nv_ri32(dev, instance); + tmp &= ~mask; + tmp |= value; + + nv_wi32(dev, instance, tmp); + nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp); + nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); +} + +static void +nv04_graph_set_ctx_val(struct nouveau_channel *chan, 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; + + ctx1 = nv_ri32(dev, instance); + class = ctx1 & 0xff; + op = (ctx1 >> 15) & 7; + tmp = nv_ri32(dev, instance + 0xc); + tmp &= ~mask; + tmp |= value; + nv_wi32(dev, instance + 0xc, tmp); + + /* check for valid surf2d/surf_dst/surf_color */ + if (!(tmp & 0x02000000)) + valid = 0; + /* check for valid surf_src/surf_zeta */ + if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000)) + valid = 0; + + switch (op) { + /* SRCCOPY_AND, SRCCOPY: no extra objects required */ + case 0: + case 3: + break; + /* ROP_AND: requires pattern and rop */ + case 1: + if (!(tmp & 0x18000000)) + valid = 0; + break; + /* BLEND_AND: requires beta1 */ + case 2: + if (!(tmp & 0x20000000)) + valid = 0; + break; + /* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */ + case 4: + case 5: + if (!(tmp & 0x40000000)) + valid = 0; + break; + } + + nv04_graph_set_ctx1(chan, 0x01000000, valid << 24); +} + +static int +nv04_graph_mthd_set_operation(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + 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); + /* changing operation changes set of objects needed for validation */ + nv04_graph_set_ctx_val(chan, 0, 0); + return 0; +} + +static int +nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + uint32_t min = data & 0xffff, max; + uint32_t w = data >> 16; + if (min & 0x8000) + /* too large */ + return 1; + if (w & 0x8000) + /* yes, it accepts negative for some reason. */ + w |= 0xffff0000; + max = min + w; + max &= 0x3ffff; + nv_wr32(chan->dev, 0x40053c, min); + nv_wr32(chan->dev, 0x400544, max); + return 0; +} + +static int +nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + uint32_t min = data & 0xffff, max; + uint32_t w = data >> 16; + if (min & 0x8000) + /* too large */ + return 1; + if (w & 0x8000) + /* yes, it accepts negative for some reason. */ + w |= 0xffff0000; + max = min + w; + max &= 0x3ffff; + nv_wr32(chan->dev, 0x400540, min); + nv_wr32(chan->dev, 0x400548, max); + return 0; +} + +static int +nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx1(chan, 0x00004000, 0); + nv04_graph_set_ctx_val(chan, 0x02000000, 0); + return 0; + case 0x42: + nv04_graph_set_ctx1(chan, 0x00004000, 0); + nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx1(chan, 0x00004000, 0); + nv04_graph_set_ctx_val(chan, 0x02000000, 0); + return 0; + case 0x42: + nv04_graph_set_ctx1(chan, 0x00004000, 0); + nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + return 0; + case 0x52: + nv04_graph_set_ctx1(chan, 0x00004000, 0x00004000); + nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x08000000, 0); + return 0; + case 0x18: + nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x08000000, 0); + return 0; + case 0x44: + nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x10000000, 0); + return 0; + case 0x43: + nv04_graph_set_ctx_val(chan, 0x10000000, 0x10000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x20000000, 0); + return 0; + case 0x12: + nv04_graph_set_ctx_val(chan, 0x20000000, 0x20000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x40000000, 0); + return 0; + case 0x72: + nv04_graph_set_ctx_val(chan, 0x40000000, 0x40000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x02000000, 0); + return 0; + case 0x58: + nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x04000000, 0); + return 0; + case 0x59: + nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x02000000, 0); + return 0; + case 0x5a: + nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx_val(chan, 0x04000000, 0); + return 0; + case 0x5b: + nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx1(chan, 0x2000, 0); + return 0; + case 0x19: + nv04_graph_set_ctx1(chan, 0x2000, 0x2000); + return 0; + } + return 1; +} + +static int +nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: + nv04_graph_set_ctx1(chan, 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); + return 0; + } + return 1; +} + +static struct nouveau_bitfield nv04_graph_intr[] = { + { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, + {} +}; + +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" }, + { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, + {} +}; + +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" }, + { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, + { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, + { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, + { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, + { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, + { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, + { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, + { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, + {} +}; + +static void +nv04_graph_context_switch(struct drm_device *dev) +{ + 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); + + /* 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]; + 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; + } + } + + 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); + } + + 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); + } + } +} + +static void +nv04_graph_destroy(struct drm_device *dev, int engine) +{ + struct nv04_graph_engine *pgraph = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 12); + + NVOBJ_ENGINE_DEL(dev, GR); + kfree(pgraph); +} + +int +nv04_graph_create(struct drm_device *dev) +{ + 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); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c new file mode 100644 index 0000000..fb1d88a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -0,0 +1,1189 @@ +/* + * Copyright 2007 Matthieu CASTET + * All Rights Reserved. + * + * 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 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 + * PRECISION INSIGHT 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. + */ + +#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; +}; + +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]; +}; + +static int nv10_graph_ctx_regs[] = { + NV10_PGRAPH_CTX_SWITCH(0), + NV10_PGRAPH_CTX_SWITCH(1), + NV10_PGRAPH_CTX_SWITCH(2), + NV10_PGRAPH_CTX_SWITCH(3), + NV10_PGRAPH_CTX_SWITCH(4), + NV10_PGRAPH_CTX_CACHE(0, 0), + NV10_PGRAPH_CTX_CACHE(0, 1), + NV10_PGRAPH_CTX_CACHE(0, 2), + NV10_PGRAPH_CTX_CACHE(0, 3), + NV10_PGRAPH_CTX_CACHE(0, 4), + NV10_PGRAPH_CTX_CACHE(1, 0), + NV10_PGRAPH_CTX_CACHE(1, 1), + NV10_PGRAPH_CTX_CACHE(1, 2), + NV10_PGRAPH_CTX_CACHE(1, 3), + NV10_PGRAPH_CTX_CACHE(1, 4), + NV10_PGRAPH_CTX_CACHE(2, 0), + NV10_PGRAPH_CTX_CACHE(2, 1), + NV10_PGRAPH_CTX_CACHE(2, 2), + NV10_PGRAPH_CTX_CACHE(2, 3), + NV10_PGRAPH_CTX_CACHE(2, 4), + NV10_PGRAPH_CTX_CACHE(3, 0), + NV10_PGRAPH_CTX_CACHE(3, 1), + NV10_PGRAPH_CTX_CACHE(3, 2), + NV10_PGRAPH_CTX_CACHE(3, 3), + NV10_PGRAPH_CTX_CACHE(3, 4), + NV10_PGRAPH_CTX_CACHE(4, 0), + NV10_PGRAPH_CTX_CACHE(4, 1), + NV10_PGRAPH_CTX_CACHE(4, 2), + NV10_PGRAPH_CTX_CACHE(4, 3), + NV10_PGRAPH_CTX_CACHE(4, 4), + NV10_PGRAPH_CTX_CACHE(5, 0), + NV10_PGRAPH_CTX_CACHE(5, 1), + NV10_PGRAPH_CTX_CACHE(5, 2), + NV10_PGRAPH_CTX_CACHE(5, 3), + NV10_PGRAPH_CTX_CACHE(5, 4), + NV10_PGRAPH_CTX_CACHE(6, 0), + NV10_PGRAPH_CTX_CACHE(6, 1), + NV10_PGRAPH_CTX_CACHE(6, 2), + NV10_PGRAPH_CTX_CACHE(6, 3), + NV10_PGRAPH_CTX_CACHE(6, 4), + NV10_PGRAPH_CTX_CACHE(7, 0), + NV10_PGRAPH_CTX_CACHE(7, 1), + NV10_PGRAPH_CTX_CACHE(7, 2), + NV10_PGRAPH_CTX_CACHE(7, 3), + NV10_PGRAPH_CTX_CACHE(7, 4), + NV10_PGRAPH_CTX_USER, + NV04_PGRAPH_DMA_START_0, + NV04_PGRAPH_DMA_START_1, + NV04_PGRAPH_DMA_LENGTH, + NV04_PGRAPH_DMA_MISC, + NV10_PGRAPH_DMA_PITCH, + NV04_PGRAPH_BOFFSET0, + NV04_PGRAPH_BBASE0, + NV04_PGRAPH_BLIMIT0, + NV04_PGRAPH_BOFFSET1, + NV04_PGRAPH_BBASE1, + NV04_PGRAPH_BLIMIT1, + NV04_PGRAPH_BOFFSET2, + NV04_PGRAPH_BBASE2, + NV04_PGRAPH_BLIMIT2, + NV04_PGRAPH_BOFFSET3, + NV04_PGRAPH_BBASE3, + NV04_PGRAPH_BLIMIT3, + NV04_PGRAPH_BOFFSET4, + NV04_PGRAPH_BBASE4, + NV04_PGRAPH_BLIMIT4, + NV04_PGRAPH_BOFFSET5, + NV04_PGRAPH_BBASE5, + NV04_PGRAPH_BLIMIT5, + NV04_PGRAPH_BPITCH0, + NV04_PGRAPH_BPITCH1, + NV04_PGRAPH_BPITCH2, + NV04_PGRAPH_BPITCH3, + NV04_PGRAPH_BPITCH4, + NV10_PGRAPH_SURFACE, + NV10_PGRAPH_STATE, + NV04_PGRAPH_BSWIZZLE2, + NV04_PGRAPH_BSWIZZLE5, + NV04_PGRAPH_BPIXEL, + NV10_PGRAPH_NOTIFY, + NV04_PGRAPH_PATT_COLOR0, + NV04_PGRAPH_PATT_COLOR1, + NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */ + 0x00400904, + 0x00400908, + 0x0040090c, + 0x00400910, + 0x00400914, + 0x00400918, + 0x0040091c, + 0x00400920, + 0x00400924, + 0x00400928, + 0x0040092c, + 0x00400930, + 0x00400934, + 0x00400938, + 0x0040093c, + 0x00400940, + 0x00400944, + 0x00400948, + 0x0040094c, + 0x00400950, + 0x00400954, + 0x00400958, + 0x0040095c, + 0x00400960, + 0x00400964, + 0x00400968, + 0x0040096c, + 0x00400970, + 0x00400974, + 0x00400978, + 0x0040097c, + 0x00400980, + 0x00400984, + 0x00400988, + 0x0040098c, + 0x00400990, + 0x00400994, + 0x00400998, + 0x0040099c, + 0x004009a0, + 0x004009a4, + 0x004009a8, + 0x004009ac, + 0x004009b0, + 0x004009b4, + 0x004009b8, + 0x004009bc, + 0x004009c0, + 0x004009c4, + 0x004009c8, + 0x004009cc, + 0x004009d0, + 0x004009d4, + 0x004009d8, + 0x004009dc, + 0x004009e0, + 0x004009e4, + 0x004009e8, + 0x004009ec, + 0x004009f0, + 0x004009f4, + 0x004009f8, + 0x004009fc, + NV04_PGRAPH_PATTERN, /* 2 values from 0x400808 to 0x40080c */ + 0x0040080c, + NV04_PGRAPH_PATTERN_SHAPE, + NV03_PGRAPH_MONO_COLOR0, + NV04_PGRAPH_ROP3, + NV04_PGRAPH_CHROMA, + NV04_PGRAPH_BETA_AND, + NV04_PGRAPH_BETA_PREMULT, + 0x00400e70, + 0x00400e74, + 0x00400e78, + 0x00400e7c, + 0x00400e80, + 0x00400e84, + 0x00400e88, + 0x00400e8c, + 0x00400ea0, + 0x00400ea4, + 0x00400ea8, + 0x00400e90, + 0x00400e94, + 0x00400e98, + 0x00400e9c, + NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */ + NV10_PGRAPH_WINDOWCLIP_VERTICAL, /* 8 values from 0x400f20-0x400f3c */ + 0x00400f04, + 0x00400f24, + 0x00400f08, + 0x00400f28, + 0x00400f0c, + 0x00400f2c, + 0x00400f10, + 0x00400f30, + 0x00400f14, + 0x00400f34, + 0x00400f18, + 0x00400f38, + 0x00400f1c, + 0x00400f3c, + NV10_PGRAPH_XFMODE0, + NV10_PGRAPH_XFMODE1, + NV10_PGRAPH_GLOBALSTATE0, + NV10_PGRAPH_GLOBALSTATE1, + NV04_PGRAPH_STORED_FMT, + NV04_PGRAPH_SOURCE_COLOR, + NV03_PGRAPH_ABS_X_RAM, /* 32 values from 0x400400 to 0x40047c */ + NV03_PGRAPH_ABS_Y_RAM, /* 32 values from 0x400480 to 0x4004fc */ + 0x00400404, + 0x00400484, + 0x00400408, + 0x00400488, + 0x0040040c, + 0x0040048c, + 0x00400410, + 0x00400490, + 0x00400414, + 0x00400494, + 0x00400418, + 0x00400498, + 0x0040041c, + 0x0040049c, + 0x00400420, + 0x004004a0, + 0x00400424, + 0x004004a4, + 0x00400428, + 0x004004a8, + 0x0040042c, + 0x004004ac, + 0x00400430, + 0x004004b0, + 0x00400434, + 0x004004b4, + 0x00400438, + 0x004004b8, + 0x0040043c, + 0x004004bc, + 0x00400440, + 0x004004c0, + 0x00400444, + 0x004004c4, + 0x00400448, + 0x004004c8, + 0x0040044c, + 0x004004cc, + 0x00400450, + 0x004004d0, + 0x00400454, + 0x004004d4, + 0x00400458, + 0x004004d8, + 0x0040045c, + 0x004004dc, + 0x00400460, + 0x004004e0, + 0x00400464, + 0x004004e4, + 0x00400468, + 0x004004e8, + 0x0040046c, + 0x004004ec, + 0x00400470, + 0x004004f0, + 0x00400474, + 0x004004f4, + 0x00400478, + 0x004004f8, + 0x0040047c, + 0x004004fc, + NV03_PGRAPH_ABS_UCLIP_XMIN, + NV03_PGRAPH_ABS_UCLIP_XMAX, + NV03_PGRAPH_ABS_UCLIP_YMIN, + NV03_PGRAPH_ABS_UCLIP_YMAX, + 0x00400550, + 0x00400558, + 0x00400554, + 0x0040055c, + NV03_PGRAPH_ABS_UCLIPA_XMIN, + NV03_PGRAPH_ABS_UCLIPA_XMAX, + NV03_PGRAPH_ABS_UCLIPA_YMIN, + NV03_PGRAPH_ABS_UCLIPA_YMAX, + NV03_PGRAPH_ABS_ICLIP_XMAX, + NV03_PGRAPH_ABS_ICLIP_YMAX, + NV03_PGRAPH_XY_LOGIC_MISC0, + NV03_PGRAPH_XY_LOGIC_MISC1, + NV03_PGRAPH_XY_LOGIC_MISC2, + NV03_PGRAPH_XY_LOGIC_MISC3, + NV03_PGRAPH_CLIPX_0, + NV03_PGRAPH_CLIPX_1, + NV03_PGRAPH_CLIPY_0, + NV03_PGRAPH_CLIPY_1, + NV10_PGRAPH_COMBINER0_IN_ALPHA, + NV10_PGRAPH_COMBINER1_IN_ALPHA, + NV10_PGRAPH_COMBINER0_IN_RGB, + NV10_PGRAPH_COMBINER1_IN_RGB, + NV10_PGRAPH_COMBINER_COLOR0, + NV10_PGRAPH_COMBINER_COLOR1, + NV10_PGRAPH_COMBINER0_OUT_ALPHA, + NV10_PGRAPH_COMBINER1_OUT_ALPHA, + NV10_PGRAPH_COMBINER0_OUT_RGB, + NV10_PGRAPH_COMBINER1_OUT_RGB, + NV10_PGRAPH_COMBINER_FINAL0, + NV10_PGRAPH_COMBINER_FINAL1, + 0x00400e00, + 0x00400e04, + 0x00400e08, + 0x00400e0c, + 0x00400e10, + 0x00400e14, + 0x00400e18, + 0x00400e1c, + 0x00400e20, + 0x00400e24, + 0x00400e28, + 0x00400e2c, + 0x00400e30, + 0x00400e34, + 0x00400e38, + 0x00400e3c, + NV04_PGRAPH_PASSTHRU_0, + NV04_PGRAPH_PASSTHRU_1, + NV04_PGRAPH_PASSTHRU_2, + NV10_PGRAPH_DIMX_TEXTURE, + NV10_PGRAPH_WDIMX_TEXTURE, + NV10_PGRAPH_DVD_COLORFMT, + NV10_PGRAPH_SCALED_FORMAT, + NV04_PGRAPH_MISC24_0, + NV04_PGRAPH_MISC24_1, + NV04_PGRAPH_MISC24_2, + NV03_PGRAPH_X_MISC, + NV03_PGRAPH_Y_MISC, + NV04_PGRAPH_VALID1, + NV04_PGRAPH_VALID2, +}; + +static int nv17_graph_ctx_regs[] = { + NV10_PGRAPH_DEBUG_4, + 0x004006b0, + 0x00400eac, + 0x00400eb0, + 0x00400eb4, + 0x00400eb8, + 0x00400ebc, + 0x00400ec0, + 0x00400ec4, + 0x00400ec8, + 0x00400ecc, + 0x00400ed0, + 0x00400ed4, + 0x00400ed8, + 0x00400edc, + 0x00400ee0, + 0x00400a00, + 0x00400a04, +}; + +struct graph_state { + 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]; +}; + +#define PIPE_SAVE(dev, state, addr) \ + do { \ + int __i; \ + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ + state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ + } while (0) + +#define PIPE_RESTORE(dev, state, addr) \ + do { \ + int __i; \ + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \ + } while (0) + +static void nv10_graph_save_pipe(struct nouveau_channel *chan) +{ + 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); +} + +static void nv10_graph_load_pipe(struct nouveau_channel *chan) +{ + 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; + int i; + + nouveau_wait_for_idle(dev); + /* 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); + 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); + + /* 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); +} + +static void nv10_graph_create_pipe(struct nouveau_channel *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; + int i; +#define PIPE_INIT(addr) \ + do { \ + fifo_pipe_state_addr = fifo_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); \ + } while (0) +#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value + + PIPE_INIT(0x0200); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0200); + + PIPE_INIT(0x6400); + for (i = 0; i < 211; i++) + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x40000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f000000); + NV_WRITE_PIPE_INIT(0x3f000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + NV_WRITE_PIPE_INIT(0x3f800000); + PIPE_INIT_END(0x6400); + + PIPE_INIT(0x6800); + for (i = 0; i < 162; i++) + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x3f800000); + for (i = 0; i < 25; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x6800); + + PIPE_INIT(0x6c00); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0xbf800000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x6c00); + + PIPE_INIT(0x7000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x00000000); + NV_WRITE_PIPE_INIT(0x7149f2ca); + for (i = 0; i < 35; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7000); + + PIPE_INIT(0x7400); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7400); + + PIPE_INIT(0x7800); + for (i = 0; i < 48; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x7800); + + PIPE_INIT(0x4400); + for (i = 0; i < 32; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x4400); + + PIPE_INIT(0x0000); + for (i = 0; i < 16; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0000); + + PIPE_INIT(0x0040); + for (i = 0; i < 4; i++) + NV_WRITE_PIPE_INIT(0x00000000); + PIPE_INIT_END(0x0040); + +#undef PIPE_INIT +#undef PIPE_INIT_END +#undef NV_WRITE_PIPE_INIT +} + +static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, 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); + return -1; +} + +static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, 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); + return -1; +} + +static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, + uint32_t 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]; + int i, subchan = -1; + + /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state + * that cannot be restored via MMIO. Do it through the FIFO + * instead. + */ + + /* Look for a celsius object */ + for (i = 0; i < 8; i++) { + int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; + + if (class == 0x56 || class == 0x96 || class == 0x99) { + subchan = i; + break; + } + } + + if (subchan < 0 || !inst) + return; + + /* Save the current ctx object */ + ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER); + for (i = 0; i < 5; i++) + ctx_switch[i] = nv_rd32(dev, 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); + + for (i = 0; i < ARRAY_SIZE(fifo); i++) + fifo[i] = nv_rd32(dev, 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); + + /* 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); + + /* Restore the FIFO state */ + for (i = 0; i < ARRAY_SIZE(fifo); i++) + nv_wr32(dev, 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); + + /* 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); +} + +static int +nv10_graph_load_context(struct nouveau_channel *chan) +{ + 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; + 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) { + for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) + nv_wr32(dev, nv17_graph_ctx_regs[i], + pgraph_ctx->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); + return 0; +} + +static int +nv10_graph_unload_context(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + struct graph_state *ctx; + uint32_t tmp; + 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]); + + if (dev_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]); + } + + 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); + return 0; +} + +static void +nv10_graph_context_switch(struct drm_device *dev) +{ + 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 */ + nv10_graph_unload_context(dev); + + /* 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); +} + +#define NV_WRITE_CTX(reg, val) do { \ + int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \ + if (offset > 0) \ + pgraph_ctx->nv10[offset] = val; \ + } while (0) + +#define NV17_WRITE_CTX(reg, val) do { \ + int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \ + if (offset > 0) \ + pgraph_ctx->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) +{ + 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; + + NV_WRITE_CTX(0x00400e88, 0x08000000); + NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); + NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff); + NV_WRITE_CTX(0x00400e10, 0x00001000); + NV_WRITE_CTX(0x00400e14, 0x00001000); + NV_WRITE_CTX(0x00400e30, 0x00080008); + NV_WRITE_CTX(0x00400e34, 0x00080008); + if (dev_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)); + 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); + + nv10_graph_create_pipe(chan); + return 0; +} + +static void +nv10_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 (nv10_graph_channel(dev) == chan) + nv10_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 */ + chan->engctx[engine] = NULL; + kfree(pgraph_ctx); +} + +static void +nv10_graph_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[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); +} + +static int +nv10_graph_init(struct drm_device *dev, int engine) +{ + 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); + + /* 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); + + return 0; +} + +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); + + return 0; +} + +static int +nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + struct drm_device *dev = chan->dev; + + nouveau_wait_for_idle(dev); + + 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); + + return 0; +} + +struct nouveau_bitfield nv10_graph_intr[] = { + { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, + { NV_PGRAPH_INTR_ERROR, "ERROR" }, + {} +}; + +struct nouveau_bitfield nv10_graph_nstatus[] = { + { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, + {} +}; + +static void +nv10_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 (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); + } + + 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); + } + } +} + +static void +nv10_graph_destroy(struct drm_device *dev, int engine) +{ + struct nv10_graph_engine *pgraph = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 12); + kfree(pgraph); +} + +int +nv10_graph_create(struct drm_device *dev) +{ + 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); + } 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); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c new file mode 100644 index 0000000..e34ea30 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -0,0 +1,836 @@ +#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; +}; + +#define NV20_GRCTX_SIZE (3580*4) +#define NV25_GRCTX_SIZE (3529*4) +#define NV2A_GRCTX_SIZE (3500*4) + +#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) +{ + 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->pinst >> 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; +} + +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); + + nouveau_wait_for_idle(dev); +} + +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); + 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 = 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(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); + for (i = 0x355c; i <= 0x3578; i += 4) + nv_wo32(ctx, i, 0x001c527c); +} + +static void +nv25_graph_context_init(struct nouveau_gpuobj *ctx) +{ + 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); +} + +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); +} + +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); +} + +static void +nv34_graph_context_init(struct nouveau_gpuobj *ctx) +{ + 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); + } + 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); +} + +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); +} + +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); + + nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->pinst >> 4); + chan->engctx[engine] = grctx; + return 0; +} + +void +nv20_graph_context_del(struct nouveau_channel *chan, int engine) +{ + 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; + 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) + nv20_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 */ + nv_wo32(pgraph->ctxtab, chan->id * 4, 0); + + nouveau_gpuobj_ref(NULL, &grctx); + chan->engctx[engine] = NULL; +} + +static void +nv20_graph_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[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); + } +} + +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->pinst >> 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); + } + + /* 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); + + /* interesting.. the below overwrites some of the tile setup above.. */ + nv_wr32(dev, 0x400B20, 0x00000000); + nv_wr32(dev, 0x400B04, 0xFFFFFFFF); + + 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); + + return 0; +} + +int +nv30_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; + 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->pinst >> 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); + } + + nv_wr32(dev, 0x4000c0, 0x00000016); + + /* 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, NV10_PGRAPH_CTX_CONTROL, 0x10000100); + nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + nv_wr32(dev, 0x0040075c , 0x00000001); + + /* 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)); + } + + return 0; +} + +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; +} + +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; + } + } + + 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); + } + } +} + +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); + + NVOBJ_ENGINE_DEL(dev, GR); + kfree(pgraph); +} + +int +nv20_graph_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv20_graph_engine *pgraph; + int ret; + + 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; + } + } + + /* 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; + } + + 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); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c new file mode 100644 index 0000000..4ad9759 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include + +struct nv40_graph_engine { + struct nouveau_exec_engine base; + u32 grctx_size; +}; + +static int +nv40_graph_context_new(struct nouveau_channel *chan, int engine) +{ + 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; + 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 */ + nv40_grctx_fill(dev, grctx); + nv_wo32(grctx, 0, grctx->vinst); + + /* 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->vinst >> 4); + nv_mask(dev, 0x002500, 0x00000001, 0x00000000); + if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) + nv_wr32(dev, 0x0032e0, grctx->vinst >> 4); + nv_mask(dev, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + chan->engctx[engine] = grctx; + 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->pinst >> 4); + unsigned long flags; + + 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; +} + +int +nv40_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, 20, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + 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); + + ret = nouveau_ramht_insert(chan, handle, obj); + nouveau_gpuobj_ref(NULL, &obj); + return ret; +} + +static void +nv40_graph_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + switch (dev_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); + 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); + break; + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + 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); + break; + } +} + +/* + * 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) +{ + struct nv40_graph_engine *pgraph = nv_engine(dev, engine); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + uint32_t vramsz; + int i, j; + + 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); + + /* generate and upload context program */ + nv40_grctx_init(dev, &pgraph->grctx_size); + + /* No context present currently */ + nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, 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(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); + nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); + + j = nv_rd32(dev, 0x1540) & 0xff; + if (j) { + for (i = 0; !(j & 1); j >>= 1, i++) + ; + nv_wr32(dev, 0x405000, i); + } + + if (dev_priv->chipset == 0x40) { + nv_wr32(dev, 0x4009b0, 0x83280fff); + nv_wr32(dev, 0x4009b4, 0x000000a0); + } else { + nv_wr32(dev, 0x400820, 0x83280eff); + nv_wr32(dev, 0x400824, 0x000000a0); + } + + switch (dev_priv->chipset) { + case 0x40: + case 0x45: + nv_wr32(dev, 0x4009b8, 0x0078e366); + nv_wr32(dev, 0x4009bc, 0x0000014c); + break; + case 0x41: + case 0x42: /* pciid also 0x00Cx */ + /* case 0x0120: XXX (pciid) */ + nv_wr32(dev, 0x400828, 0x007596ff); + nv_wr32(dev, 0x40082c, 0x00000108); + break; + case 0x43: + nv_wr32(dev, 0x400828, 0x0072cb77); + nv_wr32(dev, 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); + break; + case 0x47: /* G70 */ + case 0x49: /* G71 */ + case 0x4b: /* G73 */ + nv_wr32(dev, 0x400828, 0x07830610); + nv_wr32(dev, 0x40082c, 0x0000016A); + break; + default: + break; + } + + nv_wr32(dev, 0x400b38, 0x2ffff800); + nv_wr32(dev, 0x400b3c, 0x00006000); + + /* Tiling related stuff. */ + switch (dev_priv->chipset) { + case 0x44: + case 0x4a: + nv_wr32(dev, 0x400bc4, 0x1003d888); + nv_wr32(dev, 0x400bbc, 0xb7a7b500); + break; + case 0x46: + nv_wr32(dev, 0x400bc4, 0x0000e024); + nv_wr32(dev, 0x400bbc, 0xb7a7b520); + break; + case 0x4c: + case 0x4e: + case 0x67: + nv_wr32(dev, 0x400bc4, 0x1003d888); + nv_wr32(dev, 0x400bbc, 0xb7a7b540); + break; + default: + break; + } + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + nv40_graph_set_tile_region(dev, i); + + /* begin RAM config */ + vramsz = pci_resource_len(dev->pdev, 0) - 1; + switch (dev_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); + break; + default: + switch (dev_priv->chipset) { + case 0x41: + case 0x42: + case 0x43: + case 0x45: + 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)); + break; + default: + nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); + 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); + 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->pinst == 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; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c new file mode 100644 index 0000000..c22e3a0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -0,0 +1,868 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include +#include +#include "nouveau_dma.h" +#include +#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; + + NV_DEBUG(dev, "\n"); + + /* 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; + + 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); + } + } + + 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); + + /* 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 */ + + /* 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); + } + + break; + } + + /* 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); + } + + return 0; +} + +static int +nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) +{ + nv_wr32(dev, 0x40013c, 0x00000000); + return 0; +} + +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; + + hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; + nv_wo32(ramin, hdr + 0x00, 0x00190002); + nv_wo32(ramin, hdr + 0x04, grctx->vinst + grctx->size - 1); + nv_wo32(ramin, hdr + 0x08, grctx->vinst); + nv_wo32(ramin, hdr + 0x0c, 0); + nv_wo32(ramin, hdr + 0x10, 0); + nv_wo32(ramin, hdr + 0x14, 0x00010000); + + nv50_grctx_fill(dev, grctx); + nv_wo32(grctx, 0x00000, chan->ramin->vinst >> 12); + + dev_priv->engine.instmem.flush(dev); + + atomic_inc(&chan->vm->engref[NVOBJ_ENGINE_GR]); + chan->engctx[NVOBJ_ENGINE_GR] = grctx; + return 0; +} + +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); + dev_priv->engine.instmem.flush(dev); + + atomic_dec(&chan->vm->engref[engine]); + nouveau_gpuobj_ref(NULL, &grctx); + chan->engctx[engine] = NULL; +} + +static int +nv50_graph_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + 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; + + nv_wo32(obj, 0x00, class); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); + dev_priv->engine.instmem.flush(dev); + + ret = nouveau_ramht_insert(chan, handle, obj); + nouveau_gpuobj_ref(NULL, &obj); + return ret; +} + +static void +nv50_graph_tlb_flush(struct drm_device *dev, int engine) +{ + nv50_vm_flush_engine(dev, 0); +} + +static void +nv84_graph_tlb_flush(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + 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); + + start = ptimer->read(dev); + do { + idle = true; + + for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) { + if ((tmp & 7) == 1) + idle = false; + } + + for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) { + if ((tmp & 7) == 1) + idle = false; + } + + for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) { + if ((tmp & 7) == 1) + idle = false; + } + } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000)); + + if (timeout) { + NV_ERROR(dev, "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)); + } + + nv50_vm_flush_engine(dev, 0); + + nv_mask(dev, 0x400500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +} + +static struct nouveau_enum nv50_mp_exec_error_names[] = { + { 3, "STACK_UNDERFLOW", NULL }, + { 4, "QUADON_ACTIVE", NULL }, + { 8, "TIMEOUT", NULL }, + { 0x10, "INVALID_OPCODE", NULL }, + { 0x40, "BREAKPOINT", NULL }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_m2mf[] = { + { 0x00000001, "NOTIFY" }, + { 0x00000002, "IN" }, + { 0x00000004, "OUT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_vfetch[] = { + { 0x00000001, "FAULT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_strmout[] = { + { 0x00000001, "FAULT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_ccache[] = { + { 0x00000001, "FAULT" }, + {} +}; + +/* There must be a *lot* of these. Will take some time to gather them up. */ +struct nouveau_enum nv50_data_error_names[] = { + { 0x00000003, "INVALID_OPERATION", NULL }, + { 0x00000004, "INVALID_VALUE", NULL }, + { 0x00000005, "INVALID_ENUM", NULL }, + { 0x00000008, "INVALID_OBJECT", NULL }, + { 0x00000009, "READ_ONLY_OBJECT", NULL }, + { 0x0000000a, "SUPERVISOR_OBJECT", NULL }, + { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL }, + { 0x0000000c, "INVALID_BITFIELD", NULL }, + { 0x0000000d, "BEGIN_END_ACTIVE", NULL }, + { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL }, + { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL }, + { 0x00000010, "RT_DOUBLE_BIND", NULL }, + { 0x00000011, "RT_TYPES_MISMATCH", NULL }, + { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL }, + { 0x00000015, "FP_TOO_FEW_REGS", NULL }, + { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL }, + { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL }, + { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL }, + { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL }, + { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL }, + { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL }, + { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL }, + { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL }, + { 0x0000001f, "RT_BPP128_WITH_MS8", NULL }, + { 0x00000021, "Z_OUT_OF_BOUNDS", NULL }, + { 0x00000023, "XY_OUT_OF_BOUNDS", NULL }, + { 0x00000024, "VP_ZERO_INPUTS", NULL }, + { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL }, + { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL }, + { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL }, + { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL }, + { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL }, + { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL }, + { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL }, + { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL }, + { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL }, + { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL }, + { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL }, + { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL }, + { 0x00000046, "LAYER_ID_NEEDS_GP", NULL }, + { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL }, + { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL }, + {} +}; + +static struct nouveau_bitfield nv50_graph_intr[] = { + { 0x00000001, "NOTIFY" }, + { 0x00000002, "COMPUTE_QUERY" }, + { 0x00000010, "ILLEGAL_MTHD" }, + { 0x00000020, "ILLEGAL_CLASS" }, + { 0x00000040, "DOUBLE_NOTIFY" }, + { 0x00001000, "CONTEXT_SWITCH" }, + { 0x00010000, "BUFFER_NOTIFY" }, + { 0x00100000, "DATA_ERROR" }, + { 0x00200000, "TRAP" }, + { 0x01000000, "SINGLE_STEP" }, + {} +}; + +static void +nv50_pgraph_mp_trap(struct drm_device *dev, 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; + int i; + int mps = 0; + for (i = 0; i < 4; i++) { + if (!(units & 1 << (i+24))) + continue; + if (dev_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); + 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 - " + "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); + mps++; + } + if (!mps && display) + NV_INFO(dev, "PGRAPH_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) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int tps = 0; + uint32_t units = nv_rd32(dev, 0x1540); + int i, r; + uint32_t ustatus_addr, ustatus; + for (i = 0; i < 16; i++) { + if (!(units & (1 << i))) + continue; + if (dev_priv->chipset < 0xa0) + ustatus_addr = ustatus_old + (i << 12); + else + ustatus_addr = ustatus_new + (i << 11); + ustatus = nv_rd32(dev, 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); + for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) + NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, + nv_rd32(dev, r)); + } + break; + case 7: /* MP error */ + if (ustatus & 0x04030000) { + nv50_pgraph_mp_trap(dev, 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); + /* 2d engine destination */ + if (ustatus & 0x00000010) { + if (display) { + NV_INFO(dev, "PGRAPH_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", + i, e0c, e18, e1c, e20, e24); + } + ustatus &= ~0x00000010; + } + /* Render target */ + if (ustatus & 0x00000040) { + if (display) { + NV_INFO(dev, "PGRAPH_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", + i, e0c, e18, e1c, e20, e24); + } + ustatus &= ~0x00000040; + } + /* CUDA memory: l[], g[] or stack. */ + if (ustatus & 0x00000080) { + if (display) { + if (e18 & 0x80000000) { + /* g[] read fault? */ + NV_INFO(dev, "PGRAPH_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", + 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", + i, e14, e10); + } + NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + i, e0c, e18, e1c, e20, e24); + } + ustatus &= ~0x00000080; + } + } + break; + } + if (ustatus) { + if (display) + NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); + } + nv_wr32(dev, ustatus_addr, 0xc0000000); + } + + if (!tps && display) + NV_INFO(dev, "%s - No TPs claiming errors?\n", name); +} + +static int +nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid) +{ + u32 status = nv_rd32(dev, 0x400108); + u32 ustatus; + + if (!status && display) { + NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n"); + return 1; + } + + /* DISPATCH: Relays commands to other units and handles NOTIFY, + * 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; + if (!ustatus && display) { + NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); + } + + nv_wr32(dev, 0x400500, 0x00000000); + + /* Known to be triggered by screwed up NOTIFY and COND... */ + if (ustatus & 0x00000001) { + u32 addr = nv_rd32(dev, 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); + + NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n"); + if (display && (addr & 0x80000000)) { + NV_INFO(dev, "PGRAPH - ch %d (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, + datal, addr, r848); + } else + if (display) { + NV_INFO(dev, "PGRAPH - no stuck command?\n"); + } + + nv_wr32(dev, 0x400808, 0); + nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); + nv_wr32(dev, 0x400848, 0); + ustatus &= ~0x00000001; + } + + if (ustatus & 0x00000002) { + u32 addr = nv_rd32(dev, 0x40084c); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, 0x40085c); + u32 class = nv_rd32(dev, 0x400814); + + NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n"); + if (display && (addr & 0x80000000)) { + NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x 40084c 0x%08x\n", + chid, inst, subc, class, mthd, + data, addr); + } else + if (display) { + NV_INFO(dev, "PGRAPH - no stuck command?\n"); + } + + nv_wr32(dev, 0x40084c, 0); + ustatus &= ~0x00000002; + } + + if (ustatus && display) { + NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown " + "0x%08x)\n", ustatus); + } + + nv_wr32(dev, 0x400804, 0xc0000000); + nv_wr32(dev, 0x400108, 0x001); + status &= ~0x001; + if (!status) + return 0; + } + + /* M2MF: Memory to memory copy engine. */ + if (status & 0x002) { + u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - 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)); + + } + + /* 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); + status &= ~0x002; + } + + /* VFETCH: Fetches data from vertex buffers. */ + if (status & 0x004) { + u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - 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_wr32(dev, 0x400c04, 0xc0000000); + nv_wr32(dev, 0x400108, 0x004); + status &= ~0x004; + } + + /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ + if (status & 0x008) { + ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - 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)); + + } + + /* 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); + status &= ~0x008; + } + + /* CCACHE: Handles code and c[] caches and fills them. */ + if (status & 0x010) { + ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - TRAP_CCACHE"); + nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - 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_wr32(dev, 0x405018, 0xc0000000); + nv_wr32(dev, 0x400108, 0x010); + status &= ~0x010; + } + + /* Unknown, not seen yet... 0x402000 is the only trap status reg + * 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; + if (display) + NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus); + nv_wr32(dev, 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); + 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); + 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); + status &= ~0x100; + } + + if (status) { + if (display) + NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status); + nv_wr32(dev, 0x400108, status); + } + + return 1; +} + +int +nv50_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->vinst) + break; + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return i; +} + +static void +nv50_graph_isr(struct drm_device *dev) +{ + 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; + } + + show = (show && nouveau_ratelimit()) ? show : 0; + + 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"); + } + + if (stat & 0x00200000) { + if (!nv50_pgraph_trap_handler(dev, show, inst, chid)) + show &= ~0x00200000; + } + + 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_rd32(dev, 0x400824) & (1 << 31)) + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); +} + +static void +nv50_graph_destroy(struct drm_device *dev, int engine) +{ + struct nv50_graph_engine *pgraph = nv_engine(dev, engine); + + NVOBJ_ENGINE_DEL(dev, GR); + + nouveau_irq_unregister(dev, 12); + kfree(pgraph); +} + +int +nv50_graph_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_graph_engine *pgraph; + int ret; + + 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; + } + + 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; + + nouveau_irq_register(dev, 12, nv50_graph_isr); + + 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 */ + + /* 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; + } + } + + /* compute */ + NVOBJ_CLASS(dev, 0x50c0, GR); + if (dev_priv->chipset > 0xa0 && + dev_priv->chipset != 0xaa && + dev_priv->chipset != 0xac) + NVOBJ_CLASS(dev, 0x85c0, GR); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c new file mode 100644 index 0000000..8f515dc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -0,0 +1,897 @@ +/* + * Copyright 2010 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: + * + * 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 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 +#include + +#include "drmP.h" + +#include "nouveau_drv.h" +#include +#include + +#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)); +} + +static 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)); +} + +static int +nvc0_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + nv_wr32(dev, 0x409840, 0x00000030); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409504, 0x00000003); + if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) + NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); + + return 0; +} + +static int +nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) +{ + nv_wr32(dev, 0x409840, 0x00000003); + nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); + nv_wr32(dev, 0x409504, 0x00000009); + if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); + return -EBUSY; + } + + return 0; +} + +static int +nvc0_graph_construct_context(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + int ret, i; + u32 *ctx; + + ctx = kmalloc(priv->grctx_size, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + if (!nouveau_ctxfw) { + nv_wr32(dev, 0x409840, 0x80000000); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409504, 0x00000001); + if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { + NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); + nvc0_graph_ctxctl_debug(dev); + ret = -EBUSY; + goto err; + } + } else { + nvc0_graph_load_context(chan); + + nv_wo32(grch->grctx, 0x1c, 1); + nv_wo32(grch->grctx, 0x20, 0); + nv_wo32(grch->grctx, 0x28, 0); + nv_wo32(grch->grctx, 0x2c, 0); + dev_priv->engine.instmem.flush(dev); + } + + ret = nvc0_grctx_generate(chan); + if (ret) + goto err; + + if (!nouveau_ctxfw) { + nv_wr32(dev, 0x409840, 0x80000000); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409504, 0x00000002); + if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { + NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); + nvc0_graph_ctxctl_debug(dev); + ret = -EBUSY; + goto err; + } + } else { + ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); + if (ret) + goto err; + } + + for (i = 0; i < priv->grctx_size; i += 4) + ctx[i / 4] = nv_ro32(grch->grctx, i); + + priv->grctx_vals = ctx; + return 0; + +err: + kfree(ctx); + return ret; +} + +static int +nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) +{ + struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i = 0, gpc, tp, ret; + + ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, + &grch->unk408004); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM, + &grch->unk40800c); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096, + NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER, + &grch->unk418810); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM, + &grch->mmio); + if (ret) + return ret; + + + nv_wo32(grch->mmio, i++ * 4, 0x00408004); + nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x00408008); + nv_wo32(grch->mmio, i++ * 4, 0x80000018); + + nv_wo32(grch->mmio, i++ * 4, 0x0040800c); + nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x00408010); + nv_wo32(grch->mmio, i++ * 4, 0x80000000); + + nv_wo32(grch->mmio, i++ * 4, 0x00418810); + nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12); + nv_wo32(grch->mmio, i++ * 4, 0x00419848); + nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12); + + nv_wo32(grch->mmio, i++ * 4, 0x00419004); + nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x00419008); + nv_wo32(grch->mmio, i++ * 4, 0x00000000); + + nv_wo32(grch->mmio, i++ * 4, 0x00418808); + nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x0041880c); + nv_wo32(grch->mmio, i++ * 4, 0x80000018); + + if (dev_priv->chipset != 0xc1) { + u32 magic = 0x02180000; + nv_wo32(grch->mmio, i++ * 4, 0x00405830); + nv_wo32(grch->mmio, i++ * 4, magic); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { + u32 reg = TP_UNIT(gpc, tp, 0x520); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, magic); + magic += 0x0324; + } + } + } else { + u32 magic = 0x02180000; + nv_wo32(grch->mmio, i++ * 4, 0x00405830); + nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218); + nv_wo32(grch->mmio, i++ * 4, 0x004064c4); + nv_wo32(grch->mmio, i++ * 4, 0x0086ffff); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { + u32 reg = TP_UNIT(gpc, tp, 0x520); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic); + magic += 0x0324; + } + for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { + u32 reg = TP_UNIT(gpc, tp, 0x544); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, magic); + magic += 0x0324; + } + } + } + + grch->mmio_nr = i / 2; + return 0; +} + +static int +nvc0_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nvc0_graph_priv *priv = nv_engine(dev, engine); + struct nvc0_graph_chan *grch; + struct nouveau_gpuobj *grctx; + int ret, i; + + grch = kzalloc(sizeof(*grch), GFP_KERNEL); + if (!grch) + return -ENOMEM; + chan->engctx[NVOBJ_ENGINE_GR] = grch; + + ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256, + NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, + &grch->grctx); + if (ret) + goto error; + grctx = grch->grctx; + + ret = nvc0_graph_create_context_mmio_list(chan); + if (ret) + goto error; + + nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4); + nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst)); + pinstmem->flush(dev); + + if (!priv->grctx_vals) { + ret = nvc0_graph_construct_context(chan); + if (ret) + goto error; + } + + for (i = 0; i < priv->grctx_size; i += 4) + nv_wo32(grctx, i, priv->grctx_vals[i / 4]); + + if (!nouveau_ctxfw) { + nv_wo32(grctx, 0x00, grch->mmio_nr); + nv_wo32(grctx, 0x04, grch->mmio->linst >> 8); + } else { + nv_wo32(grctx, 0xf4, 0); + nv_wo32(grctx, 0xf8, 0); + nv_wo32(grctx, 0x10, grch->mmio_nr); + nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst)); + nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst)); + nv_wo32(grctx, 0x1c, 1); + nv_wo32(grctx, 0x20, 0); + nv_wo32(grctx, 0x28, 0); + nv_wo32(grctx, 0x2c, 0); + } + pinstmem->flush(dev); + return 0; + +error: + priv->base.context_del(chan, engine); + return ret; +} + +static void +nvc0_graph_context_del(struct nouveau_channel *chan, int engine) +{ + struct nvc0_graph_chan *grch = chan->engctx[engine]; + + nouveau_gpuobj_ref(NULL, &grch->mmio); + nouveau_gpuobj_ref(NULL, &grch->unk418810); + nouveau_gpuobj_ref(NULL, &grch->unk40800c); + nouveau_gpuobj_ref(NULL, &grch->unk408004); + nouveau_gpuobj_ref(NULL, &grch->grctx); + chan->engctx[engine] = NULL; +} + +static int +nvc0_graph_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + return 0; +} + +static int +nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) +{ + return 0; +} + +static void +nvc0_graph_init_obj418880(struct drm_device *dev) +{ + 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); + for (i = 0; i < 4; i++) + nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); + nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8); + nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); +} + +static void +nvc0_graph_init_regs(struct drm_device *dev) +{ + 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); +} + +static void +nvc0_graph_init_gpc_0(struct drm_device *dev) +{ + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total); + u32 data[TP_MAX / 8]; + u8 tpnr[GPC_MAX]; + int i, gpc, tpc; + + nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ + + /* + * TP ROP UNKVAL(magic_not_rop_nr) + * 450: 4/0/0/0 2 3 + * 460: 3/4/0/0 4 1 + * 465: 3/4/4/0 4 7 + * 470: 3/3/4/4 5 5 + * 480: 3/4/4/4 6 6 + */ + + memset(data, 0x00, sizeof(data)); + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + for (i = 0, gpc = -1; i < priv->tp_total; i++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpnr[gpc]); + tpc = priv->tp_nr[gpc] - tpnr[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]); + + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | + priv->tp_nr[gpc]); + nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total); + nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); + } + + nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); +} + +static void +nvc0_graph_init_units(struct drm_device *dev) +{ + 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); +} + +static void +nvc0_graph_init_gpc_1(struct drm_device *dev) +{ + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + int gpc, tp; + + 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->tp_nr[gpc]; tp++) { + nv_wr32(dev, TP_UNIT(gpc, tp, 0x508), 0xffffffff); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x50c), 0xffffffff); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f); + } + nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + } +} + +static void +nvc0_graph_init_rop(struct drm_device *dev) +{ + 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 +nvc0_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]); + } +} + +static int +nvc0_graph_init_ctxctl(struct drm_device *dev) +{ + 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 (!nouveau_ctxfw) { + /* load HUB microcode */ + r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); + nv_wr32(dev, 0x4091c0, 0x01000000); + for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) + nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); + + nv_wr32(dev, 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]); + } + + /* load GPC microcode */ + nv_wr32(dev, 0x41a1c0, 0x01000000); + for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) + nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); + + nv_wr32(dev, 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(dev, 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); + return -EBUSY; + } + + priv->grctx_size = nv_rd32(dev, 0x409804); + return 0; + } + + /* load fuc microcode */ + r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); + nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d); + nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); + nv_wr32(dev, 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"); + return -EBUSY; + } + priv->grctx_size = nv_rd32(dev, 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"); + 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"); + return -EBUSY; + } + + return 0; +} + +static int +nvc0_graph_init(struct drm_device *dev, int engine) +{ + int ret; + + 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); + if (ret) + return ret; + + 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->vinst) + 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); + + if (nouveau_ctxfw) { + 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->grctx_vals) + kfree(priv->grctx_vals); + + 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; + } + } + + 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->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); + priv->tp_total += priv->tp_nr[gpc]; + } + + /*XXX: these need figuring out... */ + switch (dev_priv->chipset) { + case 0xc0: + if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ + priv->magic_not_rop_nr = 0x07; + } else + if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ + priv->magic_not_rop_nr = 0x05; + } else + if (priv->tp_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->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], + priv->tp_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; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h new file mode 100644 index 0000000..91d44ea6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -0,0 +1,97 @@ +/* + * Copyright 2010 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: + * + * 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 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 + */ + +#ifndef __NVC0_GRAPH_H__ +#define __NVC0_GRAPH_H__ + +#define GPC_MAX 4 +#define TP_MAX 32 + +#define ROP_BCAST(r) (0x408800 + (r)) +#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) +#define GPC_BCAST(r) (0x418000 + (r)) +#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) +#define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) + +struct nvc0_graph_fuc { + u32 *data; + u32 size; +}; + +struct nvc0_graph_priv { + struct nouveau_exec_engine base; + + struct nvc0_graph_fuc fuc409c; + struct nvc0_graph_fuc fuc409d; + struct nvc0_graph_fuc fuc41ac; + struct nvc0_graph_fuc fuc41ad; + + u8 gpc_nr; + u8 rop_nr; + u8 tp_nr[GPC_MAX]; + u8 tp_total; + + u32 grctx_size; + u32 *grctx_vals; + struct nouveau_gpuobj *unk4188b4; + struct nouveau_gpuobj *unk4188b8; + + u8 magic_not_rop_nr; +}; + +struct nvc0_graph_chan { + struct nouveau_gpuobj *grctx; + struct nouveau_gpuobj *unk408004; /* 0x418810 too */ + struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ + struct nouveau_gpuobj *unk418810; /* 0x419848 too */ + struct nouveau_gpuobj *mmio; + int mmio_nr; +}; + +int nvc0_grctx_generate(struct nouveau_channel *); + +/* nvc0_graph.c uses this also to determine supported chipsets */ +static inline u32 +nvc0_graph_class(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (dev_priv->chipset) { + case 0xc0: + case 0xc3: + case 0xc4: + case 0xce: /* guess, mmio trace shows only 0x9097 state */ + case 0xcf: /* guess, mmio trace shows only 0x9097 state */ + return 0x9097; + case 0xc1: + return 0x9197; + case 0xc8: + case 0xd9: + return 0x9297; + default: + return 0; + } +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c new file mode 100644 index 0000000..a8364b1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -0,0 +1,831 @@ +/* + * Copyright 2010 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: + * + * 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 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 +#include + +#include "drmP.h" + +#include "nouveau_drv.h" +#include +#include + +#include "nve0.h" + +static void +nve0_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)); +} + +static void +nve0_graph_ctxctl_debug(struct drm_device *dev) +{ + u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; + u32 gpc; + + nve0_graph_ctxctl_debug_unit(dev, 0x409000); + for (gpc = 0; gpc < gpcnr; gpc++) + nve0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); +} + +static int +nve0_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + nv_wr32(dev, 0x409840, 0x00000030); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409504, 0x00000003); + if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) + NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); + + return 0; +} + +static int +nve0_graph_unload_context_to(struct drm_device *dev, u64 chan) +{ + nv_wr32(dev, 0x409840, 0x00000003); + nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); + nv_wr32(dev, 0x409504, 0x00000009); + if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); + return -EBUSY; + } + + return 0; +} + +static int +nve0_graph_construct_context(struct nouveau_channel *chan) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + int ret, i; + u32 *ctx; + + ctx = kmalloc(priv->grctx_size, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + nve0_graph_load_context(chan); + + nv_wo32(grch->grctx, 0x1c, 1); + nv_wo32(grch->grctx, 0x20, 0); + nv_wo32(grch->grctx, 0x28, 0); + nv_wo32(grch->grctx, 0x2c, 0); + dev_priv->engine.instmem.flush(dev); + + ret = nve0_grctx_generate(chan); + if (ret) + goto err; + + ret = nve0_graph_unload_context_to(dev, chan->ramin->vinst); + if (ret) + goto err; + + for (i = 0; i < priv->grctx_size; i += 4) + ctx[i / 4] = nv_ro32(grch->grctx, i); + + priv->grctx_vals = ctx; + return 0; + +err: + kfree(ctx); + return ret; +} + +static int +nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) +{ + struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + u32 magic[GPC_MAX][2]; + u16 offset = 0x0000; + int gpc; + int ret; + + ret = nouveau_gpuobj_new(dev, chan, 0x3000, 256, NVOBJ_FLAG_VM, + &grch->unk408004); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM, + &grch->unk40800c); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096, + NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER, + &grch->unk418810); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM, + &grch->mmio); + if (ret) + return ret; + +#define mmio(r,v) do { \ + nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 0, (r)); \ + nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 4, (v)); \ + grch->mmio_nr++; \ +} while (0) + mmio(0x40800c, grch->unk40800c->linst >> 8); + mmio(0x408010, 0x80000000); + mmio(0x419004, grch->unk40800c->linst >> 8); + mmio(0x419008, 0x00000000); + mmio(0x4064cc, 0x80000000); + mmio(0x408004, grch->unk408004->linst >> 8); + mmio(0x408008, 0x80000030); + mmio(0x418808, grch->unk408004->linst >> 8); + mmio(0x41880c, 0x80000030); + mmio(0x4064c8, 0x01800600); + mmio(0x418810, 0x80000000 | grch->unk418810->linst >> 12); + mmio(0x419848, 0x10000000 | grch->unk418810->linst >> 12); + mmio(0x405830, 0x02180648); + mmio(0x4064c4, 0x0192ffff); + + for (gpc = 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 * priv->tpc_nr[gpc]; + } + + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + mmio(GPC_UNIT(gpc, 0x30c0), magic[gpc][0]); + mmio(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset); + offset += 0x07ff * priv->tpc_nr[gpc]; + } + + mmio(0x17e91c, 0x06060609); + mmio(0x17e920, 0x00090a05); +#undef mmio + return 0; +} + +static int +nve0_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nve0_graph_priv *priv = nv_engine(dev, engine); + struct nve0_graph_chan *grch; + struct nouveau_gpuobj *grctx; + int ret, i; + + grch = kzalloc(sizeof(*grch), GFP_KERNEL); + if (!grch) + return -ENOMEM; + chan->engctx[NVOBJ_ENGINE_GR] = grch; + + ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256, + NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, + &grch->grctx); + if (ret) + goto error; + grctx = grch->grctx; + + ret = nve0_graph_create_context_mmio_list(chan); + if (ret) + goto error; + + nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4); + nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst)); + pinstmem->flush(dev); + + if (!priv->grctx_vals) { + ret = nve0_graph_construct_context(chan); + if (ret) + goto error; + } + + for (i = 0; i < priv->grctx_size; i += 4) + nv_wo32(grctx, i, priv->grctx_vals[i / 4]); + nv_wo32(grctx, 0xf4, 0); + nv_wo32(grctx, 0xf8, 0); + nv_wo32(grctx, 0x10, grch->mmio_nr); + nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst)); + nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst)); + nv_wo32(grctx, 0x1c, 1); + nv_wo32(grctx, 0x20, 0); + nv_wo32(grctx, 0x28, 0); + nv_wo32(grctx, 0x2c, 0); + + pinstmem->flush(dev); + return 0; + +error: + priv->base.context_del(chan, engine); + return ret; +} + +static void +nve0_graph_context_del(struct nouveau_channel *chan, int engine) +{ + struct nve0_graph_chan *grch = chan->engctx[engine]; + + nouveau_gpuobj_ref(NULL, &grch->mmio); + nouveau_gpuobj_ref(NULL, &grch->unk418810); + nouveau_gpuobj_ref(NULL, &grch->unk40800c); + nouveau_gpuobj_ref(NULL, &grch->unk408004); + nouveau_gpuobj_ref(NULL, &grch->grctx); + chan->engctx[engine] = NULL; +} + +static int +nve0_graph_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + return 0; +} + +static int +nve0_graph_fini(struct drm_device *dev, int engine, bool suspend) +{ + return 0; +} + +static void +nve0_graph_init_obj418880(struct drm_device *dev) +{ + struct nve0_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); + for (i = 0; i < 4; i++) + nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); + nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8); + nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); +} + +static void +nve0_graph_init_regs(struct drm_device *dev) +{ + 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); +} + +static void +nve0_graph_init_units(struct drm_device *dev) +{ + 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); + +} + +static void +nve0_graph_init_gpc_0(struct drm_device *dev) +{ + struct nve0_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); + + memset(data, 0x00, sizeof(data)); + 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 (!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]); + + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + nv_wr32(dev, 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(dev, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); +} + +static void +nve0_graph_init_gpc_1(struct drm_device *dev) +{ + struct nve0_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); + 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(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + } +} + +static void +nve0_graph_init_rop(struct drm_device *dev) +{ + struct nve0_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 nve0_graph_fuc *code, struct nve0_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]); + } +} + +static int +nve0_graph_init_ctxctl(struct drm_device *dev) +{ + struct nve0_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); + + /* 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"); + return -EBUSY; + } + priv->grctx_size = nv_rd32(dev, 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"); + 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"); + 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"); + 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"); + 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"); + return -EBUSY; + } + + nv_wr32(dev, 0x409614, 0x00000070); + nv_wr32(dev, 0x409614, 0x00000770); + nv_wr32(dev, 0x40802c, 0x00000001); + return 0; +} + +static int +nve0_graph_init(struct drm_device *dev, int engine) +{ + int ret; + + 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) + 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->vinst) + 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 nve0_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 nve0_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) + 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 nve0_graph_fuc *fuc) +{ + if (fuc->data) { + kfree(fuc->data); + fuc->data = NULL; + } +} + +static void +nve0_graph_destroy(struct drm_device *dev, int engine) +{ + struct nve0_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->grctx_vals) + kfree(priv->grctx_vals); + + 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 nve0_graph_priv *priv; + int ret, gpc, i; + u32 kepler; + + kepler = nve0_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 = nve0_graph_context_new; + priv->base.context_del = nve0_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; + } + + 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]; + } + + 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; + } + + 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, 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; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h new file mode 100644 index 0000000..2ba7044 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h @@ -0,0 +1,89 @@ +/* + * 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: + * + * 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 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 + */ + +#ifndef __NVE0_GRAPH_H__ +#define __NVE0_GRAPH_H__ + +#define GPC_MAX 4 +#define TPC_MAX 32 + +#define ROP_BCAST(r) (0x408800 + (r)) +#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) +#define GPC_BCAST(r) (0x418000 + (r)) +#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) +#define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) + +struct nve0_graph_fuc { + u32 *data; + u32 size; +}; + +struct nve0_graph_priv { + struct nouveau_exec_engine base; + + struct nve0_graph_fuc fuc409c; + struct nve0_graph_fuc fuc409d; + struct nve0_graph_fuc fuc41ac; + struct nve0_graph_fuc fuc41ad; + + u8 gpc_nr; + u8 rop_nr; + u8 tpc_nr[GPC_MAX]; + u8 tpc_total; + + u32 grctx_size; + u32 *grctx_vals; + struct nouveau_gpuobj *unk4188b4; + struct nouveau_gpuobj *unk4188b8; + + u8 magic_not_rop_nr; +}; + +struct nve0_graph_chan { + struct nouveau_gpuobj *grctx; + struct nouveau_gpuobj *unk408004; /* 0x418810 too */ + struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ + struct nouveau_gpuobj *unk418810; /* 0x419848 too */ + struct nouveau_gpuobj *mmio; + int mmio_nr; +}; + +int nve0_grctx_generate(struct nouveau_channel *); + +/* nve0_graph.c uses this also to determine supported chipsets */ +static inline u32 +nve0_graph_class(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (dev_priv->chipset) { + case 0xe4: + case 0xe7: + return 0xa097; + default: + return 0; + } +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c new file mode 100644 index 0000000..4a14a67 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -0,0 +1,346 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include +#include + +struct nv31_mpeg_engine { + struct nouveau_exec_engine base; + atomic_t refcount; +}; + + +static int +nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) +{ + struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); + + if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) + return -EBUSY; + + chan->engctx[engine] = (void *)0xdeadcafe; + return 0; +} + +static void +nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) +{ + struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); + atomic_dec(&pmpeg->refcount); + chan->engctx[engine] = NULL; +} + +static int +nv40_mpeg_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 *ctx = NULL; + unsigned long flags; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &ctx); + if (ret) + return ret; + + nv_wo32(ctx, 0x78, 0x02001ec1); + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, 0x002500, 0x00000001, 0x00000000); + if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) + nv_wr32(dev, 0x00330c, ctx->pinst >> 4); + nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); + nv_mask(dev, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + chan->engctx[engine] = ctx; + return 0; +} + +static void +nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_gpuobj *ctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + unsigned long flags; + u32 inst = 0x80000000 | (ctx->pinst >> 4); + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); + if (nv_rd32(dev, 0x00b318) == inst) + nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + nouveau_gpuobj_ref(NULL, &ctx); + chan->engctx[engine] = NULL; +} + +static int +nv31_mpeg_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, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &obj); + if (ret) + return ret; + obj->engine = 2; + obj->class = class; + + nv_wo32(obj, 0x00, class); + + ret = nouveau_ramht_insert(chan, handle, obj); + nouveau_gpuobj_ref(NULL, &obj); + return ret; +} + +static int +nv31_mpeg_init(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); + int i; + + /* VPE init */ + nv_mask(dev, 0x000200, 0x00000002, 0x00000000); + nv_mask(dev, 0x000200, 0x00000002, 0x00000002); + nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ + nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ + + for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) + pmpeg->base.set_tile_region(dev, i); + + /* PMPEG init */ + nv_wr32(dev, 0x00b32c, 0x00000000); + nv_wr32(dev, 0x00b314, 0x00000100); + nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); + nv_wr32(dev, 0x00b300, 0x02001ec1); + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); + + nv_wr32(dev, 0x00b100, 0xffffffff); + nv_wr32(dev, 0x00b140, 0xffffffff); + + if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); + return -EBUSY; + } + + return 0; +} + +static int +nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) +{ + /*XXX: context save? */ + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); + nv_wr32(dev, 0x00b140, 0x00000000); + return 0; +} + +static int +nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) +{ + struct drm_device *dev = chan->dev; + u32 inst = data << 4; + u32 dma0 = nv_ri32(dev, inst + 0); + u32 dma1 = nv_ri32(dev, inst + 4); + u32 dma2 = nv_ri32(dev, inst + 8); + u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); + u32 size = dma1 + 1; + + /* only allow linear DMA objects */ + if (!(dma0 & 0x00002000)) + return -EINVAL; + + if (mthd == 0x0190) { + /* DMA_CMD */ + nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); + nv_wr32(dev, 0x00b334, base); + nv_wr32(dev, 0x00b324, size); + } else + if (mthd == 0x01a0) { + /* DMA_DATA */ + nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); + nv_wr32(dev, 0x00b360, base); + nv_wr32(dev, 0x00b364, size); + } else { + /* DMA_IMAGE, VRAM only */ + if (dma0 & 0x000c0000) + return -EINVAL; + + nv_wr32(dev, 0x00b370, base); + nv_wr32(dev, 0x00b374, size); + } + + return 0; +} + +static int +nv31_mpeg_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 *ctx; + unsigned long flags; + int i; + + /* hardcode drm channel id on nv3x, so swmthd lookup works */ + if (dev_priv->card_type < NV_40) + return 0; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + for (i = 0; i < pfifo->channels; i++) { + if (!dev_priv->channels.ptr[i]) + continue; + + ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; + if (ctx && ctx->pinst == inst) + break; + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return i; +} + +static void +nv31_vpe_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); + nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); + nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); +} + +static void +nv31_mpeg_isr(struct drm_device *dev) +{ + u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; + u32 chid = nv31_mpeg_isr_chid(dev, inst); + u32 stat = nv_rd32(dev, 0x00b100); + u32 type = nv_rd32(dev, 0x00b230); + u32 mthd = nv_rd32(dev, 0x00b234); + u32 data = nv_rd32(dev, 0x00b238); + u32 show = stat; + + if (stat & 0x01000000) { + /* happens on initial binding of the object */ + if (type == 0x00000020 && mthd == 0x0000) { + nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); + show &= ~0x01000000; + } + + if (type == 0x00000010) { + if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) + show &= ~0x01000000; + } + } + + nv_wr32(dev, 0x00b100, stat); + nv_wr32(dev, 0x00b230, 0x00000001); + + if (show && nouveau_ratelimit()) { + NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", + chid, inst, stat, type, mthd, data); + } +} + +static void +nv31_vpe_isr(struct drm_device *dev) +{ + if (nv_rd32(dev, 0x00b100)) + nv31_mpeg_isr(dev); + + if (nv_rd32(dev, 0x00b800)) { + u32 stat = nv_rd32(dev, 0x00b800); + NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); + nv_wr32(dev, 0xb800, stat); + } +} + +static void +nv31_mpeg_destroy(struct drm_device *dev, int engine) +{ + struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 0); + + NVOBJ_ENGINE_DEL(dev, MPEG); + kfree(pmpeg); +} + +int +nv31_mpeg_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv31_mpeg_engine *pmpeg; + + pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); + if (!pmpeg) + return -ENOMEM; + atomic_set(&pmpeg->refcount, 0); + + pmpeg->base.destroy = nv31_mpeg_destroy; + pmpeg->base.init = nv31_mpeg_init; + pmpeg->base.fini = nv31_mpeg_fini; + if (dev_priv->card_type < NV_40) { + pmpeg->base.context_new = nv31_mpeg_context_new; + pmpeg->base.context_del = nv31_mpeg_context_del; + } else { + pmpeg->base.context_new = nv40_mpeg_context_new; + pmpeg->base.context_del = nv40_mpeg_context_del; + } + pmpeg->base.object_new = nv31_mpeg_object_new; + + /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between + * all VPE engines, for this driver's purposes the PMPEG engine + * will be treated as the "master" and handle the global VPE + * bits too + */ + pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; + nouveau_irq_register(dev, 0, nv31_vpe_isr); + + NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); + NVOBJ_CLASS(dev, 0x3174, MPEG); + NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); + NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); + NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); + +#if 0 + NVOBJ_ENGINE_ADD(dev, ME, &pme->base); + NVOBJ_CLASS(dev, 0x4075, ME); +#endif + return 0; + +} diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c new file mode 100644 index 0000000..47d37a2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c @@ -0,0 +1,241 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include + +struct nv50_mpeg_engine { + struct nouveau_exec_engine base; +}; + +static inline u32 +CTX_PTR(struct drm_device *dev, u32 offset) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset == 0x50) + offset += 0x0260; + else + offset += 0x0060; + + return offset; +} + +static int +nv50_mpeg_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 *ctx = NULL; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + ret = nouveau_gpuobj_new(dev, chan, 128 * 4, 0, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &ctx); + if (ret) + return ret; + + nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002); + nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->vinst + ctx->size - 1); + nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->vinst); + nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0); + nv_wo32(ramin, CTX_PTR(dev, 0x10), 0); + nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000); + + nv_wo32(ctx, 0x70, 0x00801ec1); + nv_wo32(ctx, 0x7c, 0x0000037c); + dev_priv->engine.instmem.flush(dev); + + chan->engctx[engine] = ctx; + return 0; +} + +static void +nv50_mpeg_context_del(struct nouveau_channel *chan, int engine) +{ + struct nouveau_gpuobj *ctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + int i; + + for (i = 0x00; i <= 0x14; i += 4) + nv_wo32(chan->ramin, CTX_PTR(dev, i), 0x00000000); + + nouveau_gpuobj_ref(NULL, &ctx); + chan->engctx[engine] = NULL; +} + +static int +nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, + u32 handle, u16 class) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + 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 = 2; + obj->class = class; + + nv_wo32(obj, 0x00, class); + nv_wo32(obj, 0x04, 0x00000000); + nv_wo32(obj, 0x08, 0x00000000); + nv_wo32(obj, 0x0c, 0x00000000); + dev_priv->engine.instmem.flush(dev); + + ret = nouveau_ramht_insert(chan, handle, obj); + nouveau_gpuobj_ref(NULL, &obj); + return ret; +} + +static void +nv50_mpeg_tlb_flush(struct drm_device *dev, int engine) +{ + nv50_vm_flush_engine(dev, 0x08); +} + +static int +nv50_mpeg_init(struct drm_device *dev, int engine) +{ + nv_wr32(dev, 0x00b32c, 0x00000000); + nv_wr32(dev, 0x00b314, 0x00000100); + nv_wr32(dev, 0x00b0e0, 0x0000001a); + + nv_wr32(dev, 0x00b220, 0x00000044); + nv_wr32(dev, 0x00b300, 0x00801ec1); + nv_wr32(dev, 0x00b390, 0x00000000); + nv_wr32(dev, 0x00b394, 0x00000000); + nv_wr32(dev, 0x00b398, 0x00000000); + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); + + nv_wr32(dev, 0x00b100, 0xffffffff); + nv_wr32(dev, 0x00b140, 0xffffffff); + + if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { + NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); + return -EBUSY; + } + + return 0; +} + +static int +nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) +{ + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); + nv_wr32(dev, 0x00b140, 0x00000000); + return 0; +} + +static void +nv50_mpeg_isr(struct drm_device *dev) +{ + u32 stat = nv_rd32(dev, 0x00b100); + u32 type = nv_rd32(dev, 0x00b230); + u32 mthd = nv_rd32(dev, 0x00b234); + u32 data = nv_rd32(dev, 0x00b238); + u32 show = stat; + + if (stat & 0x01000000) { + /* happens on initial binding of the object */ + if (type == 0x00000020 && mthd == 0x0000) { + nv_wr32(dev, 0x00b308, 0x00000100); + show &= ~0x01000000; + } + } + + if (show && nouveau_ratelimit()) { + NV_INFO(dev, "PMPEG - 0x%08x 0x%08x 0x%08x 0x%08x\n", + stat, type, mthd, data); + } + + nv_wr32(dev, 0x00b100, stat); + nv_wr32(dev, 0x00b230, 0x00000001); + nv50_fb_vm_trap(dev, 1); +} + +static void +nv50_vpe_isr(struct drm_device *dev) +{ + if (nv_rd32(dev, 0x00b100)) + nv50_mpeg_isr(dev); + + if (nv_rd32(dev, 0x00b800)) { + u32 stat = nv_rd32(dev, 0x00b800); + NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); + nv_wr32(dev, 0xb800, stat); + } +} + +static void +nv50_mpeg_destroy(struct drm_device *dev, int engine) +{ + struct nv50_mpeg_engine *pmpeg = nv_engine(dev, engine); + + nouveau_irq_unregister(dev, 0); + + NVOBJ_ENGINE_DEL(dev, MPEG); + kfree(pmpeg); +} + +int +nv50_mpeg_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_mpeg_engine *pmpeg; + + pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); + if (!pmpeg) + return -ENOMEM; + + pmpeg->base.destroy = nv50_mpeg_destroy; + pmpeg->base.init = nv50_mpeg_init; + pmpeg->base.fini = nv50_mpeg_fini; + pmpeg->base.context_new = nv50_mpeg_context_new; + pmpeg->base.context_del = nv50_mpeg_context_del; + pmpeg->base.object_new = nv50_mpeg_object_new; + pmpeg->base.tlb_flush = nv50_mpeg_tlb_flush; + + if (dev_priv->chipset == 0x50) { + nouveau_irq_register(dev, 0, nv50_vpe_isr); + NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); + NVOBJ_CLASS(dev, 0x3174, MPEG); +#if 0 + NVOBJ_ENGINE_ADD(dev, ME, &pme->base); + NVOBJ_CLASS(dev, 0x4075, ME); +#endif + } else { + nouveau_irq_register(dev, 0, nv50_mpeg_isr); + NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); + NVOBJ_CLASS(dev, 0x8274, MPEG); + } + + return 0; + +} diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c new file mode 100644 index 0000000..20d33dc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c @@ -0,0 +1,78 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include + +struct nv98_ppp_engine { + struct nouveau_exec_engine base; +}; + +static int +nv98_ppp_fini(struct drm_device *dev, int engine, bool suspend) +{ + if (!(nv_rd32(dev, 0x000200) & 0x00000002)) + return 0; + + nv_mask(dev, 0x000200, 0x00000002, 0x00000000); + return 0; +} + +static int +nv98_ppp_init(struct drm_device *dev, int engine) +{ + nv_mask(dev, 0x000200, 0x00000002, 0x00000000); + nv_mask(dev, 0x000200, 0x00000002, 0x00000002); + return 0; +} + +static void +nv98_ppp_destroy(struct drm_device *dev, int engine) +{ + struct nv98_ppp_engine *pppp = nv_engine(dev, engine); + + NVOBJ_ENGINE_DEL(dev, PPP); + + kfree(pppp); +} + +int +nv98_ppp_create(struct drm_device *dev) +{ + struct nv98_ppp_engine *pppp; + + pppp = kzalloc(sizeof(*pppp), GFP_KERNEL); + if (!pppp) + return -ENOMEM; + + pppp->base.destroy = nv98_ppp_destroy; + pppp->base.init = nv98_ppp_init; + pppp->base.fini = nv98_ppp_fini; + + NVOBJ_ENGINE_ADD(dev, PPP, &pppp->base); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c new file mode 100644 index 0000000..eb7e196 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c @@ -0,0 +1,83 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include "nouveau_util.h" +#include +#include + +/*XXX: This stub is currently used on NV98+ also, as soon as this becomes + * more than just an enable/disable stub this needs to be split out to + * nv98_vp.c... + */ + +struct nv84_vp_engine { + struct nouveau_exec_engine base; +}; + +static int +nv84_vp_fini(struct drm_device *dev, int engine, bool suspend) +{ + if (!(nv_rd32(dev, 0x000200) & 0x00020000)) + return 0; + + nv_mask(dev, 0x000200, 0x00020000, 0x00000000); + return 0; +} + +static int +nv84_vp_init(struct drm_device *dev, int engine) +{ + nv_mask(dev, 0x000200, 0x00020000, 0x00000000); + nv_mask(dev, 0x000200, 0x00020000, 0x00020000); + return 0; +} + +static void +nv84_vp_destroy(struct drm_device *dev, int engine) +{ + struct nv84_vp_engine *pvp = nv_engine(dev, engine); + + NVOBJ_ENGINE_DEL(dev, VP); + + kfree(pvp); +} + +int +nv84_vp_create(struct drm_device *dev) +{ + struct nv84_vp_engine *pvp; + + pvp = kzalloc(sizeof(*pvp), GFP_KERNEL); + if (!pvp) + return -ENOMEM; + + pvp->base.destroy = nv84_vp_destroy; + pvp->base.init = nv84_vp_init; + pvp->base.fini = nv84_vp_fini; + + NVOBJ_ENGINE_ADD(dev, VP, &pvp->base); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h new file mode 100644 index 0000000..d2b4290 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -0,0 +1,55 @@ +/* + * Copyright 2010 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: + * + * 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 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 + */ + +#ifndef __NOUVEAU_REGION_H__ +#define __NOUVEAU_REGION_H__ + +struct nouveau_mm_node { + struct list_head nl_entry; + struct list_head fl_entry; + struct list_head rl_entry; + + u8 type; + u32 offset; + u32 length; +}; + +struct nouveau_mm { + struct list_head nodes; + struct list_head free; + + struct mutex mutex; + + u32 block_size; + int heap_nodes; +}; + +int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); +int nouveau_mm_fini(struct nouveau_mm *); +int nouveau_mm_pre(struct nouveau_mm *); +int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **); +void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/ramht.h b/drivers/gpu/drm/nouveau/core/include/core/ramht.h new file mode 100644 index 0000000..c82de98 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/ramht.h @@ -0,0 +1,55 @@ +/* + * Copyright 2010 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: + * + * 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 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 + */ + +#ifndef __NOUVEAU_RAMHT_H__ +#define __NOUVEAU_RAMHT_H__ + +struct nouveau_ramht_entry { + struct list_head head; + struct nouveau_channel *channel; + struct nouveau_gpuobj *gpuobj; + u32 handle; +}; + +struct nouveau_ramht { + struct drm_device *dev; + struct kref refcount; + spinlock_t lock; + struct nouveau_gpuobj *gpuobj; + struct list_head entries; + int bits; +}; + +extern int nouveau_ramht_new(struct drm_device *, struct nouveau_gpuobj *, + struct nouveau_ramht **); +extern void nouveau_ramht_ref(struct nouveau_ramht *, struct nouveau_ramht **, + struct nouveau_channel *unref_channel); + +extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, + struct nouveau_gpuobj *); +extern int nouveau_ramht_remove(struct nouveau_channel *, u32 handle); +extern struct nouveau_gpuobj * +nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h new file mode 100644 index 0000000..ce99cab --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -0,0 +1,32 @@ +#ifndef __NOUVEAU_FIFO_H__ +#define __NOUVEAU_FIFO_H__ + +struct nouveau_fifo_priv { + struct nouveau_exec_engine base; + u32 channels; +}; + +struct nouveau_fifo_chan { +}; + +bool nv04_fifo_cache_pull(struct drm_device *, bool); +void nv04_fifo_context_del(struct nouveau_channel *, int); +int nv04_fifo_fini(struct drm_device *, int, bool); +int nv04_fifo_init(struct drm_device *, int); +void nv04_fifo_isr(struct drm_device *); +void nv04_fifo_destroy(struct drm_device *, int); + +void nv50_fifo_playlist_update(struct drm_device *); +void nv50_fifo_destroy(struct drm_device *, int); +void nv50_fifo_tlb_flush(struct drm_device *, int); + +int nv04_fifo_create(struct drm_device *); +int nv10_fifo_create(struct drm_device *); +int nv17_fifo_create(struct drm_device *); +int nv40_fifo_create(struct drm_device *); +int nv50_fifo_create(struct drm_device *); +int nv84_fifo_create(struct drm_device *); +int nvc0_fifo_create(struct drm_device *); +int nve0_fifo_create(struct drm_device *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h new file mode 100644 index 0000000..64c5cb0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h @@ -0,0 +1,71 @@ +/* + * Copyright 2011 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: + * + * 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 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. + */ + +#ifndef __NOUVEAU_GPIO_H__ +#define __NOUVEAU_GPIO_H__ + +struct gpio_func { + u8 func; + u8 line; + u8 log[2]; +}; + +/* nouveau_gpio.c */ +int nouveau_gpio_create(struct drm_device *); +void nouveau_gpio_destroy(struct drm_device *); +int nouveau_gpio_init(struct drm_device *); +void nouveau_gpio_fini(struct drm_device *); +void nouveau_gpio_reset(struct drm_device *); +int nouveau_gpio_drive(struct drm_device *, int idx, int line, + int dir, int out); +int nouveau_gpio_sense(struct drm_device *, int idx, int line); +int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line, + struct gpio_func *); +int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state); +int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line); +int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); +void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask); +int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); +void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); + +static inline bool +nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) +{ + struct gpio_func func; + return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0; +} + +static inline int +nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) +{ + return nouveau_gpio_set(dev, 0, tag, 0xff, state); +} + +static inline int +nouveau_gpio_func_get(struct drm_device *dev, u8 tag) +{ + return nouveau_gpio_get(dev, 0, tag, 0xff); +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h new file mode 100644 index 0000000..1d08389 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -0,0 +1,59 @@ +/* + * Copyright 2009 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: + * + * 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 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. + */ + +#ifndef __NOUVEAU_I2C_H__ +#define __NOUVEAU_I2C_H__ + +#include +#include +#include "drm_dp_helper.h" + +#define NV_I2C_PORT(n) (0x00 + (n)) +#define NV_I2C_PORT_NUM 0x10 +#define NV_I2C_DEFAULT(n) (0x80 + (n)) + +struct nouveau_i2c_chan { + struct i2c_adapter adapter; + struct drm_device *dev; + struct i2c_algo_bit_data bit; + struct list_head head; + u8 index; + u8 type; + u32 dcb; + u32 drive; + u32 sense; + u32 state; +}; + +int nouveau_i2c_init(struct drm_device *); +void nouveau_i2c_fini(struct drm_device *); +struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index); +bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); +int nouveau_i2c_identify(struct drm_device *dev, const char *what, + struct i2c_board_info *info, + bool (*match)(struct nouveau_i2c_chan *, + struct i2c_board_info *), + int index); + +extern const struct i2c_algorithm nouveau_dp_i2c_algo; + +#endif /* __NOUVEAU_I2C_H__ */ diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h new file mode 100644 index 0000000..7c1fc21 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -0,0 +1,119 @@ +/* + * Copyright 2010 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: + * + * 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 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 + */ + +#ifndef __NOUVEAU_VM_H__ +#define __NOUVEAU_VM_H__ + +#include "drmP.h" + +#include "nouveau_drv.h" +#include + +struct nouveau_vm_pgt { + struct nouveau_gpuobj *obj[2]; + u32 refcount[2]; +}; + +struct nouveau_vm_pgd { + struct list_head head; + struct nouveau_gpuobj *obj; +}; + +struct nouveau_vma { + struct list_head head; + int refcount; + struct nouveau_vm *vm; + struct nouveau_mm_node *node; + u64 offset; + u32 access; +}; + +struct nouveau_vm { + struct drm_device *dev; + struct nouveau_mm mm; + int refcount; + + struct list_head pgd_list; + atomic_t engref[16]; + + struct nouveau_vm_pgt *pgt; + u32 fpde; + u32 lpde; + + u32 pgt_bits; + u8 spg_shift; + u8 lpg_shift; + + void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, + u64 phys, u64 delta); + void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + + void (*map_sg_table)(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); + void (*flush)(struct nouveau_vm *); +}; + +/* nouveau_vm.c */ +int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset, + struct nouveau_vm **); +int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, + struct nouveau_gpuobj *pgd); +int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, + u32 access, struct nouveau_vma *); +void nouveau_vm_put(struct nouveau_vma *); +void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); +void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); +void nouveau_vm_unmap(struct nouveau_vma *); +void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); +void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, + struct nouveau_mem *); +void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, + struct nouveau_mem *mem); +/* nv50_vm.c */ +void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); +void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); +void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); +void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); +void nv50_vm_flush(struct nouveau_vm *); +void nv50_vm_flush_engine(struct drm_device *, int engine); + +/* nvc0_vm.c */ +void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); +void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); +void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); +void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); +void nvc0_vm_flush(struct nouveau_vm *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c new file mode 100644 index 0000000..d5eedd6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -0,0 +1,55 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); + + if (boot0 & 0x00000100) { + dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2; + dev_priv->vram_size *= 1024 * 1024; + } else { + switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { + case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: + dev_priv->vram_size = 32 * 1024 * 1024; + break; + case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: + dev_priv->vram_size = 16 * 1024 * 1024; + break; + case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: + dev_priv->vram_size = 8 * 1024 * 1024; + break; + case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: + dev_priv->vram_size = 4 * 1024 * 1024; + break; + } + } + + if ((boot0 & 0x00000038) <= 0x10) + dev_priv->vram_type = NV_MEM_TYPE_SGRAM; + else + dev_priv->vram_type = NV_MEM_TYPE_SDRAM; + + return 0; +} + +int +nv04_fb_init(struct drm_device *dev) +{ + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows + * nvidia reading PFB_CFG_0, then writing back its original value. + * (which was 0x701114 in this case) + */ + + nv_wr32(dev, NV04_PFB_CFG0, 0x1114); + return 0; +} + +void +nv04_fb_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c new file mode 100644 index 0000000..420b1608 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -0,0 +1,104 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +void +nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = 0x80000000 | addr; + tile->limit = max(1u, addr + size) - 1; + tile->pitch = pitch; +} + +void +nv10_fb_free_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; +} + +void +nv10_fb_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); +} + +int +nv1a_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pci_dev *bridge; + uint32_t mem, mib; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + NV_ERROR(dev, "no bridge device\n"); + return 0; + } + + if (dev_priv->chipset == 0x1a) { + pci_read_config_dword(bridge, 0x7c, &mem); + mib = ((mem >> 6) & 31) + 1; + } else { + pci_read_config_dword(bridge, 0x84, &mem); + mib = ((mem >> 4) & 127) + 1; + } + + dev_priv->vram_size = mib * 1024 * 1024; + return 0; +} + +int +nv10_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA); + u32 cfg0 = nv_rd32(dev, 0x100200); + + dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; + + if (cfg0 & 0x00000001) + dev_priv->vram_type = NV_MEM_TYPE_DDR1; + else + dev_priv->vram_type = NV_MEM_TYPE_SDRAM; + + return 0; +} + +int +nv10_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i; + + /* Turn all the tiling regions off. */ + pfb->num_tiles = NV10_PFB_TILE__SIZE; + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_tile_region(dev, i); + + return 0; +} + +void +nv10_fb_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i; + + for (i = 0; i < pfb->num_tiles; i++) + pfb->free_tile_region(dev, i); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c new file mode 100644 index 0000000..19bd640 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -0,0 +1,148 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +static struct drm_mm_node * +nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct drm_mm_node *mem; + int ret; + + ret = drm_mm_pre_get(&pfb->tag_heap); + if (ret) + return NULL; + + spin_lock(&dev_priv->tile.lock); + mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); + if (mem) + mem = drm_mm_get_block_atomic(mem, size, 0); + spin_unlock(&dev_priv->tile.lock); + + return mem; +} + +static void +nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_mm_node *mem = *pmem; + if (mem) { + spin_lock(&dev_priv->tile.lock); + drm_mm_put_block(mem); + spin_unlock(&dev_priv->tile.lock); + *pmem = NULL; + } +} + +void +nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); + + tile->addr = 0x00000001 | addr; + tile->limit = max(1u, addr + size) - 1; + tile->pitch = pitch; + + /* Allocate some of the on-die tag memory, used to store Z + * compression meta-data (most likely just a bitmap determining + * if a given tile is compressed or not). + */ + if (flags & NOUVEAU_GEM_TILE_ZETA) { + tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); + if (tile->tag_mem) { + /* Enable Z compression */ + tile->zcomp = tile->tag_mem->start; + if (dev_priv->chipset >= 0x25) { + if (bpp == 16) + tile->zcomp |= NV25_PFB_ZCOMP_MODE_16; + else + tile->zcomp |= NV25_PFB_ZCOMP_MODE_32; + } else { + tile->zcomp |= NV20_PFB_ZCOMP_EN; + if (bpp != 16) + tile->zcomp |= NV20_PFB_ZCOMP_MODE_32; + } + } + + tile->addr |= 2; + } +} + +void +nv20_fb_free_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; + nv20_fb_free_tag(dev, &tile->tag_mem); +} + +void +nv20_fb_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); + nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); +} + +int +nv20_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 mem_size = nv_rd32(dev, 0x10020c); + u32 pbus1218 = nv_rd32(dev, 0x001218); + + dev_priv->vram_size = mem_size & 0xff000000; + switch (pbus1218 & 0x00000300) { + case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break; + } + + return 0; +} + +int +nv20_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i; + + if (dev_priv->chipset >= 0x25) + drm_mm_init(&pfb->tag_heap, 0, 64 * 1024); + else + drm_mm_init(&pfb->tag_heap, 0, 32 * 1024); + + /* Turn all the tiling regions off. */ + pfb->num_tiles = NV10_PFB_TILE__SIZE; + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_tile_region(dev, i); + + return 0; +} + +void +nv20_fb_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i; + + for (i = 0; i < pfb->num_tiles; i++) + pfb->free_tile_region(dev, i); + + drm_mm_takedown(&pfb->tag_heap); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c new file mode 100644 index 0000000..e0135f0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +void +nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = addr | 1; + tile->limit = max(1u, addr + size) - 1; + tile->pitch = pitch; +} + +void +nv30_fb_free_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = tile->limit = tile->pitch = 0; +} + +static int +calc_bias(struct drm_device *dev, int k, int i, int j) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int b = (dev_priv->chipset > 0x30 ? + nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : + 0) & 0xf; + + return 2 * (b & 0x8 ? b - 0x10 : b); +} + +static int +calc_ref(struct drm_device *dev, int l, int k, int i) +{ + int j, x = 0; + + for (j = 0; j < 4; j++) { + int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); + + x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); + } + + return x; +} + +int +nv30_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i, j; + + pfb->num_tiles = NV10_PFB_TILE__SIZE; + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_tile_region(dev, i); + + /* Init the memory timing regs at 0x10037c/0x1003ac */ + if (dev_priv->chipset == 0x30 || + dev_priv->chipset == 0x31 || + dev_priv->chipset == 0x35) { + /* Related to ROP count */ + int n = (dev_priv->chipset == 0x31 ? 2 : 4); + int l = nv_rd32(dev, 0x1003d0); + + for (i = 0; i < n; i++) { + for (j = 0; j < 3; j++) + nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, + calc_ref(dev, l, 0, j)); + + for (j = 0; j < 2; j++) + nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, + calc_ref(dev, l, 1, j)); + } + } + + return 0; +} + +void +nv30_fb_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c new file mode 100644 index 0000000..7fbcb33 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -0,0 +1,163 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +void +nv40_fb_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + switch (dev_priv->chipset) { + case 0x40: + nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); + break; + + default: + nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV40_PFB_TILE(i), tile->addr); + break; + } +} + +static void +nv40_fb_init_gart(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; + + if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { + nv_wr32(dev, 0x100800, 0x00000001); + return; + } + + nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); + nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); + nv_wr32(dev, 0x100820, 0x00000000); +} + +static void +nv44_fb_init_gart(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; + u32 vinst; + + if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { + nv_wr32(dev, 0x100850, 0x80000000); + nv_wr32(dev, 0x100800, 0x00000001); + return; + } + + /* calculate vram address of this PRAMIN block, object + * must be allocated on 512KiB alignment, and not exceed + * a total size of 512KiB for this to work correctly + */ + vinst = nv_rd32(dev, 0x10020c); + vinst -= ((gart->pinst >> 19) + 1) << 19; + + nv_wr32(dev, 0x100850, 0x80000000); + nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); + + nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); + nv_wr32(dev, 0x100850, 0x00008000); + nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); + nv_wr32(dev, 0x100820, 0x00000000); + nv_wr32(dev, 0x10082c, 0x00000001); + nv_wr32(dev, 0x100800, vinst | 0x00000010); +} + +int +nv40_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* 0x001218 is actually present on a few other NV4X I looked at, + * and even contains sane values matching 0x100474. From looking + * at various vbios images however, this isn't the case everywhere. + * So, I chose to use the same regs I've seen NVIDIA reading around + * the memory detection, hopefully that'll get us the right numbers + */ + if (dev_priv->chipset == 0x40) { + u32 pbus1218 = nv_rd32(dev, 0x001218); + switch (pbus1218 & 0x00000300) { + case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + } + } else + if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { + u32 pfb914 = nv_rd32(dev, 0x100914); + switch (pfb914 & 0x00000003) { + case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; + case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000003: break; + } + } else + if (dev_priv->chipset != 0x4e) { + u32 pfb474 = nv_rd32(dev, 0x100474); + if (pfb474 & 0x00000004) + dev_priv->vram_type = NV_MEM_TYPE_GDDR3; + if (pfb474 & 0x00000002) + dev_priv->vram_type = NV_MEM_TYPE_DDR2; + if (pfb474 & 0x00000001) + dev_priv->vram_type = NV_MEM_TYPE_DDR1; + } else { + dev_priv->vram_type = NV_MEM_TYPE_STOLEN; + } + + dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000; + return 0; +} + +int +nv40_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + uint32_t tmp; + int i; + + if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { + if (nv44_graph_class(dev)) + nv44_fb_init_gart(dev); + else + nv40_fb_init_gart(dev); + } + + switch (dev_priv->chipset) { + case 0x40: + case 0x45: + tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); + nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); + pfb->num_tiles = NV10_PFB_TILE__SIZE; + break; + case 0x46: /* G72 */ + case 0x47: /* G70 */ + case 0x49: /* G71 */ + case 0x4b: /* G73 */ + case 0x4c: /* C51 (G7X version) */ + pfb->num_tiles = NV40_PFB_TILE__SIZE_1; + break; + default: + pfb->num_tiles = NV40_PFB_TILE__SIZE_0; + break; + } + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_tile_region(dev, i); + + return 0; +} + +void +nv40_fb_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c new file mode 100644 index 0000000..3488358 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -0,0 +1,296 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include + +struct nv50_fb_priv { + struct page *r100c08_page; + dma_addr_t r100c08; +}; + +static void +nv50_fb_destroy(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nv50_fb_priv *priv = pfb->priv; + + if (drm_mm_initialized(&pfb->tag_heap)) + drm_mm_takedown(&pfb->tag_heap); + + if (priv->r100c08_page) { + pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c08_page); + } + + kfree(priv); + pfb->priv = NULL; +} + +static int +nv50_fb_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nv50_fb_priv *priv; + u32 tagmem; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + pfb->priv = priv; + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c08_page) { + nv50_fb_destroy(dev); + return -ENOMEM; + } + + priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { + nv50_fb_destroy(dev); + return -EFAULT; + } + + tagmem = nv_rd32(dev, 0x100320); + NV_DEBUG(dev, "%d tags available\n", tagmem); + ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); + if (ret) { + nv50_fb_destroy(dev); + return ret; + } + + return 0; +} + +int +nv50_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fb_priv *priv; + int ret; + + if (!dev_priv->engine.fb.priv) { + ret = nv50_fb_create(dev); + if (ret) + return ret; + } + priv = dev_priv->engine.fb.priv; + + /* Not a clue what this is exactly. Without pointing it at a + * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) + * cause IOMMU "read from address 0" errors (rh#561267) + */ + nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); + + /* This is needed to get meaningful information from 100c90 + * on traps. No idea what these values mean exactly. */ + switch (dev_priv->chipset) { + case 0x50: + nv_wr32(dev, 0x100c90, 0x000707ff); + break; + case 0xa3: + case 0xa5: + case 0xa8: + nv_wr32(dev, 0x100c90, 0x000d0fff); + break; + case 0xaf: + nv_wr32(dev, 0x100c90, 0x089d1fff); + break; + default: + nv_wr32(dev, 0x100c90, 0x001d07ff); + break; + } + + return 0; +} + +void +nv50_fb_takedown(struct drm_device *dev) +{ + nv50_fb_destroy(dev); +} + +static struct nouveau_enum vm_dispatch_subclients[] = { + { 0x00000000, "GRCTX", NULL }, + { 0x00000001, "NOTIFY", NULL }, + { 0x00000002, "QUERY", NULL }, + { 0x00000003, "COND", NULL }, + { 0x00000004, "M2M_IN", NULL }, + { 0x00000005, "M2M_OUT", NULL }, + { 0x00000006, "M2M_NOTIFY", NULL }, + {} +}; + +static struct nouveau_enum vm_ccache_subclients[] = { + { 0x00000000, "CB", NULL }, + { 0x00000001, "TIC", NULL }, + { 0x00000002, "TSC", NULL }, + {} +}; + +static struct nouveau_enum vm_prop_subclients[] = { + { 0x00000000, "RT0", NULL }, + { 0x00000001, "RT1", NULL }, + { 0x00000002, "RT2", NULL }, + { 0x00000003, "RT3", NULL }, + { 0x00000004, "RT4", NULL }, + { 0x00000005, "RT5", NULL }, + { 0x00000006, "RT6", NULL }, + { 0x00000007, "RT7", NULL }, + { 0x00000008, "ZETA", NULL }, + { 0x00000009, "LOCAL", NULL }, + { 0x0000000a, "GLOBAL", NULL }, + { 0x0000000b, "STACK", NULL }, + { 0x0000000c, "DST2D", NULL }, + {} +}; + +static struct nouveau_enum vm_pfifo_subclients[] = { + { 0x00000000, "PUSHBUF", NULL }, + { 0x00000001, "SEMAPHORE", NULL }, + {} +}; + +static struct nouveau_enum vm_bar_subclients[] = { + { 0x00000000, "FB", NULL }, + { 0x00000001, "IN", NULL }, + {} +}; + +static struct nouveau_enum vm_client[] = { + { 0x00000000, "STRMOUT", NULL }, + { 0x00000003, "DISPATCH", vm_dispatch_subclients }, + { 0x00000004, "PFIFO_WRITE", NULL }, + { 0x00000005, "CCACHE", vm_ccache_subclients }, + { 0x00000006, "PPPP", NULL }, + { 0x00000007, "CLIPID", NULL }, + { 0x00000008, "PFIFO_READ", NULL }, + { 0x00000009, "VFETCH", NULL }, + { 0x0000000a, "TEXTURE", NULL }, + { 0x0000000b, "PROP", vm_prop_subclients }, + { 0x0000000c, "PVP", NULL }, + { 0x0000000d, "PBSP", NULL }, + { 0x0000000e, "PCRYPT", NULL }, + { 0x0000000f, "PCOUNTER", NULL }, + { 0x00000011, "PDAEMON", NULL }, + {} +}; + +static struct nouveau_enum vm_engine[] = { + { 0x00000000, "PGRAPH", NULL }, + { 0x00000001, "PVP", NULL }, + { 0x00000004, "PEEPHOLE", NULL }, + { 0x00000005, "PFIFO", vm_pfifo_subclients }, + { 0x00000006, "BAR", vm_bar_subclients }, + { 0x00000008, "PPPP", NULL }, + { 0x00000009, "PBSP", NULL }, + { 0x0000000a, "PCRYPT", NULL }, + { 0x0000000b, "PCOUNTER", NULL }, + { 0x0000000c, "SEMAPHORE_BG", NULL }, + { 0x0000000d, "PCOPY", NULL }, + { 0x0000000e, "PDAEMON", NULL }, + {} +}; + +static struct nouveau_enum vm_fault[] = { + { 0x00000000, "PT_NOT_PRESENT", NULL }, + { 0x00000001, "PT_TOO_SHORT", NULL }, + { 0x00000002, "PAGE_NOT_PRESENT", NULL }, + { 0x00000003, "PAGE_SYSTEM_ONLY", NULL }, + { 0x00000004, "PAGE_READ_ONLY", NULL }, + { 0x00000006, "NULL_DMAOBJ", NULL }, + { 0x00000007, "WRONG_MEMTYPE", NULL }, + { 0x0000000b, "VRAM_LIMIT", NULL }, + { 0x0000000f, "DMAOBJ_LIMIT", NULL }, + {} +}; + +void +nv50_fb_vm_trap(struct drm_device *dev, int display) +{ + struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct drm_nouveau_private *dev_priv = dev->dev_private; + const struct nouveau_enum *en, *cl; + unsigned long flags; + u32 trap[6], idx, chinst; + u8 st0, st1, st2, st3; + int i, ch; + + idx = nv_rd32(dev, 0x100c90); + if (!(idx & 0x80000000)) + return; + idx &= 0x00ffffff; + + for (i = 0; i < 6; i++) { + nv_wr32(dev, 0x100c90, idx | i << 24); + trap[i] = nv_rd32(dev, 0x100c94); + } + nv_wr32(dev, 0x100c90, idx | 0x80000000); + + if (!display) + return; + + /* lookup channel id */ + chinst = (trap[2] << 16) | trap[1]; + spin_lock_irqsave(&dev_priv->channels.lock, flags); + for (ch = 0; ch < pfifo->channels; ch++) { + struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; + + if (!chan || !chan->ramin) + continue; + + if (chinst == chan->ramin->vinst >> 12) + break; + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + + /* decode status bits into something more useful */ + if (dev_priv->chipset < 0xa3 || + dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { + st0 = (trap[0] & 0x0000000f) >> 0; + st1 = (trap[0] & 0x000000f0) >> 4; + st2 = (trap[0] & 0x00000f00) >> 8; + st3 = (trap[0] & 0x0000f000) >> 12; + } else { + st0 = (trap[0] & 0x000000ff) >> 0; + st1 = (trap[0] & 0x0000ff00) >> 8; + st2 = (trap[0] & 0x00ff0000) >> 16; + st3 = (trap[0] & 0xff000000) >> 24; + } + + NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", + (trap[5] & 0x00000100) ? "read" : "write", + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); + + en = nouveau_enum_find(vm_engine, st0); + if (en) + printk("%s/", en->name); + else + printk("%02x/", st0); + + cl = nouveau_enum_find(vm_client, st2); + if (cl) + printk("%s/", cl->name); + else + printk("%02x/", st2); + + if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); + else if (en && en->data) cl = nouveau_enum_find(en->data, st3); + else cl = NULL; + if (cl) + printk("%s", cl->name); + else + printk("%02x", st3); + + printk(" reason: "); + en = nouveau_enum_find(vm_fault, st1); + if (en) + printk("%s\n", en->name); + else + printk("0x%08x\n", st1); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c new file mode 100644 index 0000000..029274b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c @@ -0,0 +1,237 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +static int types[0x80] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 +}; + +bool +nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) +{ + int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; + + if (likely(type < ARRAY_SIZE(types) && types[type])) + return true; + return false; +} + +void +nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; + + mem = *pmem; + *pmem = NULL; + if (unlikely(mem == NULL)) + return; + + mutex_lock(&mm->mutex); + while (!list_empty(&mem->regions)) { + this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_put(mm, this); + } + + if (mem->tag) { + drm_mm_put_block(mem->tag); + mem->tag = NULL; + } + mutex_unlock(&mm->mutex); + + kfree(mem); +} + +int +nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, + u32 memtype, struct nouveau_mem **pmem) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; + int type = (memtype & 0x07f); + int ret; + + if (!types[type]) + return -EINVAL; + size >>= 12; + align >>= 12; + size_nc >>= 12; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; + + mutex_lock(&mm->mutex); + if (comp) { + if (align == 16) { + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int n = (size >> 4) * comp; + + mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); + if (mem->tag) + mem->tag = drm_mm_get_block(mem->tag, n, 0); + } + + if (unlikely(!mem->tag)) + comp = 0; + } + + INIT_LIST_HEAD(&mem->regions); + mem->dev = dev_priv->dev; + mem->memtype = (comp << 7) | type; + mem->size = size; + + do { + ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); + nv50_vram_del(dev, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; +} + +static u32 +nv50_vram_rblock(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i, parts, colbits, rowbitsa, rowbitsb, banks; + u64 rowsize, predicted; + u32 r0, r4, rt, ru, rblock_size; + + r0 = nv_rd32(dev, 0x100200); + r4 = nv_rd32(dev, 0x100204); + rt = nv_rd32(dev, 0x100250); + ru = nv_rd32(dev, 0x001540); + NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); + + for (i = 0, parts = 0; i < 8; i++) { + if (ru & (0x00010000 << i)) + parts++; + } + + colbits = (r4 & 0x0000f000) >> 12; + rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; + rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; + banks = 1 << (((r4 & 0x03000000) >> 24) + 2); + + rowsize = parts * banks * (1 << colbits) * 8; + predicted = rowsize << rowbitsa; + if (r0 & 0x00000004) + predicted += rowsize << rowbitsb; + + if (predicted != dev_priv->vram_size) { + NV_WARN(dev, "memory controller reports %dMiB VRAM\n", + (u32)(dev_priv->vram_size >> 20)); + NV_WARN(dev, "we calculated %dMiB VRAM\n", + (u32)(predicted >> 20)); + } + + rblock_size = rowsize; + if (rt & 1) + rblock_size *= 3; + + NV_DEBUG(dev, "rblock %d bytes\n", rblock_size); + return rblock_size; +} + +int +nv50_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ + u32 pfb714 = nv_rd32(dev, 0x100714); + u32 rblock, length; + + switch (pfb714 & 0x00000007) { + case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; + case 1: + if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3) + dev_priv->vram_type = NV_MEM_TYPE_DDR3; + else + dev_priv->vram_type = NV_MEM_TYPE_DDR2; + break; + case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break; + case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break; + default: + break; + } + + dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4); + dev_priv->vram_size = nv_rd32(dev, 0x10020c); + dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; + dev_priv->vram_size &= 0xffffffff00ULL; + + /* IGPs, no funky reordering happens here, they don't have VRAM */ + if (dev_priv->chipset == 0xaa || + dev_priv->chipset == 0xac || + dev_priv->chipset == 0xaf) { + dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; + rblock = 4096 >> 12; + } else { + rblock = nv50_vram_rblock(dev) >> 12; + } + + length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; + + return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock); +} + +void +nv50_vram_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + + nouveau_mm_fini(&vram->mm); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c new file mode 100644 index 0000000..f376c39 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -0,0 +1,135 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drm.h" + +struct nvc0_fb_priv { + struct page *r100c10_page; + dma_addr_t r100c10; +}; + +static inline void +nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) +{ + u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); + u32 stat = nv_rd32(dev, subp_base + 0x020); + + if (stat) { + NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); + nv_wr32(dev, subp_base + 0x020, stat); + } +} + +static void +nvc0_mfb_isr(struct drm_device *dev) +{ + u32 units = nv_rd32(dev, 0x00017c); + while (units) { + u32 subp, unit = ffs(units) - 1; + for (subp = 0; subp < 2; subp++) + nvc0_mfb_subp_isr(dev, unit, subp); + units &= ~(1 << unit); + } + + /* we do something horribly wrong and upset PMFB a lot, so mask off + * interrupts from it after the first one until it's fixed + */ + nv_mask(dev, 0x000640, 0x02000000, 0x00000000); +} + +static void +nvc0_fb_destroy(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nvc0_fb_priv *priv = pfb->priv; + + nouveau_irq_unregister(dev, 25); + + if (priv->r100c10_page) { + pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c10_page); + } + + kfree(priv); + pfb->priv = NULL; +} + +static int +nvc0_fb_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nvc0_fb_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + pfb->priv = priv; + + priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c10_page) { + nvc0_fb_destroy(dev); + return -ENOMEM; + } + + priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { + nvc0_fb_destroy(dev); + return -EFAULT; + } + + nouveau_irq_register(dev, 25, nvc0_mfb_isr); + return 0; +} + +int +nvc0_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_fb_priv *priv; + int ret; + + if (!dev_priv->engine.fb.priv) { + ret = nvc0_fb_create(dev); + if (ret) + return ret; + } + priv = dev_priv->engine.fb.priv; + + nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); + nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */ + return 0; +} + +void +nvc0_fb_takedown(struct drm_device *dev) +{ + nvc0_fb_destroy(dev); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c new file mode 100644 index 0000000..8bb86e5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c @@ -0,0 +1,160 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +/* 0 = unsupported + * 1 = non-compressed + * 3 = compressed + */ +static const u8 types[256] = { + 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, + 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 +}; + +bool +nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) +{ + u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; + return likely((types[memtype] == 1)); +} + +int +nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 type, struct nouveau_mem **pmem) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int ret; + + size >>= 12; + align >>= 12; + ncmin >>= 12; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; + + INIT_LIST_HEAD(&mem->regions); + mem->dev = dev_priv->dev; + mem->memtype = (type & 0xff); + mem->size = size; + + mutex_lock(&mm->mutex); + do { + ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); + nv50_vram_del(dev, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; +} + +int +nvc0_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ + u32 parts = nv_rd32(dev, 0x022438); + u32 pmask = nv_rd32(dev, 0x022554); + u32 bsize = nv_rd32(dev, 0x10f20c); + u32 offset, length; + bool uniform = true; + int ret, part; + + NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); + NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask); + + dev_priv->vram_type = nouveau_mem_vbios_type(dev); + dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004); + + /* read amount of vram attached to each memory controller */ + for (part = 0; part < parts; part++) { + if (!(pmask & (1 << part))) { + u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000)); + if (psize != bsize) { + if (psize < bsize) + bsize = psize; + uniform = false; + } + + NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); + dev_priv->vram_size += (u64)psize << 20; + } + } + + /* if all controllers have the same amount attached, there's no holes */ + if (uniform) { + offset = rsvd_head; + length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; + return nouveau_mm_init(&vram->mm, offset, length, 1); + } + + /* otherwise, address lowest common amount from 0GiB */ + ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); + if (ret) + return ret; + + /* and the rest starting from (8GiB + common_size) */ + offset = (0x0200000000ULL >> 12) + (bsize << 8); + length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; + + ret = nouveau_mm_init(&vram->mm, offset, length, 0); + if (ret) { + nouveau_mm_fini(&vram->mm); + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c new file mode 100644 index 0000000..2c48309 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -0,0 +1,400 @@ +/* + * Copyright 2011 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: + * + * 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 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 "nouveau_drv.h" +#include +#include + +static u8 * +dcb_gpio_table(struct drm_device *dev) +{ + u8 *dcb = dcb_table(dev); + if (dcb) { + if (dcb[0] >= 0x30 && dcb[1] >= 0x0c) + return ROMPTR(dev, dcb[0x0a]); + if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) + return ROMPTR(dev, dcb[-15]); + } + return NULL; +} + +static u8 * +dcb_gpio_entry(struct drm_device *dev, int idx, int ent, u8 *version) +{ + u8 *table = dcb_gpio_table(dev); + if (table) { + *version = table[0]; + if (*version < 0x30 && ent < table[2]) + return table + 3 + (ent * table[1]); + else if (ent < table[2]) + return table + table[1] + (ent * table[3]); + } + return NULL; +} + +int +nouveau_gpio_drive(struct drm_device *dev, int idx, int line, int dir, int out) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + return pgpio->drive ? pgpio->drive(dev, line, dir, out) : -ENODEV; +} + +int +nouveau_gpio_sense(struct drm_device *dev, int idx, int line) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + return pgpio->sense ? pgpio->sense(dev, line) : -ENODEV; +} + +int +nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, + struct gpio_func *gpio) +{ + u8 *table, *entry, version; + int i = -1; + + if (line == 0xff && func == 0xff) + return -EINVAL; + + while ((entry = dcb_gpio_entry(dev, idx, ++i, &version))) { + if (version < 0x40) { + u16 data = ROM16(entry[0]); + *gpio = (struct gpio_func) { + .line = (data & 0x001f) >> 0, + .func = (data & 0x07e0) >> 5, + .log[0] = (data & 0x1800) >> 11, + .log[1] = (data & 0x6000) >> 13, + }; + } else + if (version < 0x41) { + *gpio = (struct gpio_func) { + .line = entry[0] & 0x1f, + .func = entry[1], + .log[0] = (entry[3] & 0x18) >> 3, + .log[1] = (entry[3] & 0x60) >> 5, + }; + } else { + *gpio = (struct gpio_func) { + .line = entry[0] & 0x3f, + .func = entry[1], + .log[0] = (entry[4] & 0x30) >> 4, + .log[1] = (entry[4] & 0xc0) >> 6, + }; + } + + if ((line == 0xff || line == gpio->line) && + (func == 0xff || func == gpio->func)) + return 0; + } + + /* DCB 2.2, fixed TVDAC GPIO data */ + if ((table = dcb_table(dev)) && table[0] >= 0x22) { + if (func == DCB_GPIO_TVDAC0) { + *gpio = (struct gpio_func) { + .func = DCB_GPIO_TVDAC0, + .line = table[-4] >> 4, + .log[0] = !!(table[-5] & 2), + .log[1] = !(table[-5] & 2), + }; + return 0; + } + } + + /* Apple iMac G4 NV18 */ + if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { + if (func == DCB_GPIO_TVDAC0) { + *gpio = (struct gpio_func) { + .func = DCB_GPIO_TVDAC0, + .line = 4, + .log[0] = 0, + .log[1] = 1, + }; + return 0; + } + } + + return -EINVAL; +} + +int +nouveau_gpio_set(struct drm_device *dev, int idx, u8 tag, u8 line, int state) +{ + struct gpio_func gpio; + int ret; + + ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + if (ret == 0) { + int dir = !!(gpio.log[state] & 0x02); + int out = !!(gpio.log[state] & 0x01); + ret = nouveau_gpio_drive(dev, idx, gpio.line, dir, out); + } + + return ret; +} + +int +nouveau_gpio_get(struct drm_device *dev, int idx, u8 tag, u8 line) +{ + struct gpio_func gpio; + int ret; + + ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + if (ret == 0) { + ret = nouveau_gpio_sense(dev, idx, gpio.line); + if (ret >= 0) + ret = (ret == (gpio.log[1] & 1)); + } + + return ret; +} + +int +nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct gpio_func gpio; + int ret; + + ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + if (ret == 0) { + if (idx == 0 && pgpio->irq_enable) + pgpio->irq_enable(dev, gpio.line, on); + else + ret = -ENODEV; + } + + return ret; +} + +struct gpio_isr { + struct drm_device *dev; + struct list_head head; + struct work_struct work; + int idx; + struct gpio_func func; + void (*handler)(void *, int); + void *data; + bool inhibit; +}; + +static void +nouveau_gpio_isr_bh(struct work_struct *work) +{ + struct gpio_isr *isr = container_of(work, struct gpio_isr, work); + struct drm_device *dev = isr->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + unsigned long flags; + int state; + + state = nouveau_gpio_get(dev, isr->idx, isr->func.func, isr->func.line); + if (state >= 0) + isr->handler(isr->data, state); + + spin_lock_irqsave(&pgpio->lock, flags); + isr->inhibit = false; + spin_unlock_irqrestore(&pgpio->lock, flags); +} + +void +nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct gpio_isr *isr; + + if (idx != 0) + return; + + spin_lock(&pgpio->lock); + list_for_each_entry(isr, &pgpio->isr, head) { + if (line_mask & (1 << isr->func.line)) { + if (isr->inhibit) + continue; + isr->inhibit = true; + schedule_work(&isr->work); + } + } + spin_unlock(&pgpio->lock); +} + +int +nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, + void (*handler)(void *, int), void *data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct gpio_isr *isr; + unsigned long flags; + int ret; + + isr = kzalloc(sizeof(*isr), GFP_KERNEL); + if (!isr) + return -ENOMEM; + + ret = nouveau_gpio_find(dev, idx, tag, line, &isr->func); + if (ret) { + kfree(isr); + return ret; + } + + INIT_WORK(&isr->work, nouveau_gpio_isr_bh); + isr->dev = dev; + isr->handler = handler; + isr->data = data; + isr->idx = idx; + + spin_lock_irqsave(&pgpio->lock, flags); + list_add(&isr->head, &pgpio->isr); + spin_unlock_irqrestore(&pgpio->lock, flags); + return 0; +} + +void +nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, + void (*handler)(void *, int), void *data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct gpio_isr *isr, *tmp; + struct gpio_func func; + unsigned long flags; + LIST_HEAD(tofree); + int ret; + + ret = nouveau_gpio_find(dev, idx, tag, line, &func); + if (ret == 0) { + spin_lock_irqsave(&pgpio->lock, flags); + list_for_each_entry_safe(isr, tmp, &pgpio->isr, head) { + if (memcmp(&isr->func, &func, sizeof(func)) || + isr->idx != idx || + isr->handler != handler || isr->data != data) + continue; + list_move(&isr->head, &tofree); + } + spin_unlock_irqrestore(&pgpio->lock, flags); + + list_for_each_entry_safe(isr, tmp, &tofree, head) { + flush_work_sync(&isr->work); + kfree(isr); + } + } +} + +int +nouveau_gpio_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + INIT_LIST_HEAD(&pgpio->isr); + spin_lock_init(&pgpio->lock); + + return nouveau_gpio_init(dev); +} + +void +nouveau_gpio_destroy(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + nouveau_gpio_fini(dev); + BUG_ON(!list_empty(&pgpio->isr)); +} + +int +nouveau_gpio_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + int ret = 0; + + if (pgpio->init) + ret = pgpio->init(dev); + + return ret; +} + +void +nouveau_gpio_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + if (pgpio->fini) + pgpio->fini(dev); +} + +void +nouveau_gpio_reset(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u8 *entry, version; + int ent = -1; + + while ((entry = dcb_gpio_entry(dev, 0, ++ent, &version))) { + u8 func = 0xff, line, defs, unk0, unk1; + if (version >= 0x41) { + defs = !!(entry[0] & 0x80); + line = entry[0] & 0x3f; + func = entry[1]; + unk0 = entry[2]; + unk1 = entry[3] & 0x1f; + } else + if (version >= 0x40) { + line = entry[0] & 0x1f; + func = entry[1]; + defs = !!(entry[3] & 0x01); + unk0 = !!(entry[3] & 0x02); + unk1 = !!(entry[3] & 0x04); + } else { + break; + } + + if (func == 0xff) + continue; + + nouveau_gpio_func_set(dev, func, defs); + + if (dev_priv->card_type >= NV_D0) { + nv_mask(dev, 0x00d610 + (line * 4), 0xff, unk0); + if (unk1--) + nv_mask(dev, 0x00d740 + (unk1 * 4), 0xff, line); + } else + if (dev_priv->card_type >= NV_50) { + static const u32 regs[] = { 0xe100, 0xe28c }; + u32 val = (unk1 << 16) | unk0; + u32 reg = regs[line >> 4]; line &= 0x0f; + + nv_mask(dev, reg, 0x00010001 << line, val << line); + } + } +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c new file mode 100644 index 0000000..42e600f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" +#include + +int +nv10_gpio_sense(struct drm_device *dev, int line) +{ + if (line < 2) { + line = line * 16; + line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line; + return !!(line & 0x0100); + } else + if (line < 10) { + line = (line - 2) * 4; + line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line; + return !!(line & 0x04); + } else + if (line < 14) { + line = (line - 10) * 4; + line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line; + return !!(line & 0x04); + } + + return -EINVAL; +} + +int +nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out) +{ + u32 reg, mask, data; + + if (line < 2) { + line = line * 16; + reg = NV_PCRTC_GPIO; + mask = 0x00000011; + data = (dir << 4) | out; + } else + if (line < 10) { + line = (line - 2) * 4; + reg = NV_PCRTC_GPIO_EXT; + mask = 0x00000003; + data = (dir << 1) | out; + } else + if (line < 14) { + line = (line - 10) * 4; + reg = NV_PCRTC_850; + mask = 0x00000003; + data = (dir << 1) | out; + } else { + return -EINVAL; + } + + mask = NVReadCRTC(dev, 0, reg) & ~(mask << line); + NVWriteCRTC(dev, 0, reg, mask | (data << line)); + return 0; +} + +void +nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on) +{ + u32 mask = 0x00010001 << line; + + nv_wr32(dev, 0x001104, mask); + nv_mask(dev, 0x001144, mask, on ? mask : 0); +} + +static void +nv10_gpio_isr(struct drm_device *dev) +{ + u32 intr = nv_rd32(dev, 0x1104); + u32 hi = (intr & 0x0000ffff) >> 0; + u32 lo = (intr & 0xffff0000) >> 16; + + nouveau_gpio_isr(dev, 0, hi | lo); + + nv_wr32(dev, 0x001104, intr); +} + +int +nv10_gpio_init(struct drm_device *dev) +{ + nv_wr32(dev, 0x001140, 0x00000000); + nv_wr32(dev, 0x001100, 0xffffffff); + nv_wr32(dev, 0x001144, 0x00000000); + nv_wr32(dev, 0x001104, 0xffffffff); + nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */ + return 0; +} + +void +nv10_gpio_fini(struct drm_device *dev) +{ + nv_wr32(dev, 0x001140, 0x00000000); + nv_wr32(dev, 0x001144, 0x00000000); + nouveau_irq_unregister(dev, 28); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c new file mode 100644 index 0000000..48509b0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c @@ -0,0 +1,155 @@ +/* + * Copyright 2010 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: + * + * 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 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 +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" +#include + +#include "nv50_display.h" + +static int +nv50_gpio_location(int line, u32 *reg, u32 *shift) +{ + const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + + if (line >= 32) + return -EINVAL; + + *reg = nv50_gpio_reg[line >> 3]; + *shift = (line & 7) << 2; + return 0; +} + +int +nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out) +{ + u32 reg, shift; + + if (nv50_gpio_location(line, ®, &shift)) + return -EINVAL; + + nv_mask(dev, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); + return 0; +} + +int +nv50_gpio_sense(struct drm_device *dev, int line) +{ + u32 reg, shift; + + if (nv50_gpio_location(line, ®, &shift)) + return -EINVAL; + + return !!(nv_rd32(dev, reg) & (4 << shift)); +} + +void +nv50_gpio_irq_enable(struct drm_device *dev, int line, bool on) +{ + u32 reg = line < 16 ? 0xe050 : 0xe070; + u32 mask = 0x00010001 << (line & 0xf); + + nv_wr32(dev, reg + 4, mask); + nv_mask(dev, reg + 0, mask, on ? mask : 0); +} + +int +nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out) +{ + u32 data = ((dir ^ 1) << 13) | (out << 12); + nv_mask(dev, 0x00d610 + (line * 4), 0x00003000, data); + nv_mask(dev, 0x00d604, 0x00000001, 0x00000001); /* update? */ + return 0; +} + +int +nvd0_gpio_sense(struct drm_device *dev, int line) +{ + return !!(nv_rd32(dev, 0x00d610 + (line * 4)) & 0x00004000); +} + +static void +nv50_gpio_isr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 intr0, intr1 = 0; + u32 hi, lo; + + intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); + if (dev_priv->chipset >= 0x90) + intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + + hi = (intr0 & 0x0000ffff) | (intr1 << 16); + lo = (intr0 >> 16) | (intr1 & 0xffff0000); + nouveau_gpio_isr(dev, 0, hi | lo); + + nv_wr32(dev, 0xe054, intr0); + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe074, intr1); +} + +static struct dmi_system_id gpio_reset_ids[] = { + { + .ident = "Apple Macbook 10,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), + } + }, + { } +}; + +int +nv50_gpio_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* initialise gpios and routing to vbios defaults */ + if (dmi_check_system(gpio_reset_ids)) + nouveau_gpio_reset(dev); + + /* disable, and ack any pending gpio interrupts */ + nv_wr32(dev, 0xe050, 0x00000000); + nv_wr32(dev, 0xe054, 0xffffffff); + if (dev_priv->chipset >= 0x90) { + nv_wr32(dev, 0xe070, 0x00000000); + nv_wr32(dev, 0xe074, 0xffffffff); + } + + nouveau_irq_register(dev, 21, nv50_gpio_isr); + return 0; +} + +void +nv50_gpio_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nv_wr32(dev, 0xe050, 0x00000000); + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe070, 0x00000000); + nouveau_irq_unregister(dev, 21); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c new file mode 100644 index 0000000..71e9361 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -0,0 +1,394 @@ +/* + * Copyright 2009 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: + * + * 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 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 + +#include "drmP.h" +#include "nouveau_drv.h" +#include +#include "nouveau_hw.h" + +static void +i2c_drive_scl(void *data, int state) +{ + struct nouveau_i2c_chan *port = data; + if (port->type == 0) { + u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + if (state) val |= 0x20; + else val &= 0xdf; + NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + } else + if (port->type == 4) { + nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01); + } else + if (port->type == 5) { + if (state) port->state |= 0x01; + else port->state &= 0xfe; + nv_wr32(port->dev, port->drive, 4 | port->state); + } +} + +static void +i2c_drive_sda(void *data, int state) +{ + struct nouveau_i2c_chan *port = data; + if (port->type == 0) { + u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + if (state) val |= 0x10; + else val &= 0xef; + NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + } else + if (port->type == 4) { + nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01); + } else + if (port->type == 5) { + if (state) port->state |= 0x02; + else port->state &= 0xfd; + nv_wr32(port->dev, port->drive, 4 | port->state); + } +} + +static int +i2c_sense_scl(void *data) +{ + struct nouveau_i2c_chan *port = data; + struct drm_nouveau_private *dev_priv = port->dev->dev_private; + if (port->type == 0) { + return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04); + } else + if (port->type == 4) { + return !!(nv_rd32(port->dev, port->sense) & 0x00040000); + } else + if (port->type == 5) { + if (dev_priv->card_type < NV_D0) + return !!(nv_rd32(port->dev, port->sense) & 0x01); + else + return !!(nv_rd32(port->dev, port->sense) & 0x10); + } + return 0; +} + +static int +i2c_sense_sda(void *data) +{ + struct nouveau_i2c_chan *port = data; + struct drm_nouveau_private *dev_priv = port->dev->dev_private; + if (port->type == 0) { + return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08); + } else + if (port->type == 4) { + return !!(nv_rd32(port->dev, port->sense) & 0x00080000); + } else + if (port->type == 5) { + if (dev_priv->card_type < NV_D0) + return !!(nv_rd32(port->dev, port->sense) & 0x02); + else + return !!(nv_rd32(port->dev, port->sense) & 0x20); + } + return 0; +} + +static const uint32_t nv50_i2c_port[] = { + 0x00e138, 0x00e150, 0x00e168, 0x00e180, + 0x00e254, 0x00e274, 0x00e764, 0x00e780, + 0x00e79c, 0x00e7b8 +}; + +static u8 * +i2c_table(struct drm_device *dev, u8 *version) +{ + u8 *dcb = dcb_table(dev), *i2c = NULL; + if (dcb) { + if (dcb[0] >= 0x15) + i2c = ROMPTR(dev, dcb[2]); + if (dcb[0] >= 0x30) + i2c = ROMPTR(dev, dcb[4]); + } + + /* early revisions had no version number, use dcb version */ + if (i2c) { + *version = dcb[0]; + if (*version >= 0x30) + *version = i2c[0]; + } + + return i2c; +} + +int +nouveau_i2c_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; + struct nouveau_i2c_chan *port; + u8 version = 0x00, entries, recordlen; + u8 *i2c, *entry, legacy[2][4] = {}; + int ret, i; + + INIT_LIST_HEAD(&dev_priv->i2c_ports); + + i2c = i2c_table(dev, &version); + if (!i2c) { + u8 *bmp = &bios->data[bios->offset]; + if (bios->type != NVBIOS_BMP) + return -ENODEV; + + legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX; + legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX; + legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX; + legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX; + + /* BMP (from v4.0) has i2c info in the structure, it's in a + * fixed location on earlier VBIOS + */ + if (bmp[5] < 4) + i2c = &bios->data[0x48]; + else + i2c = &bmp[0x36]; + + if (i2c[4]) legacy[0][0] = i2c[4]; + if (i2c[5]) legacy[0][1] = i2c[5]; + if (i2c[6]) legacy[1][0] = i2c[6]; + if (i2c[7]) legacy[1][1] = i2c[7]; + } + + if (version >= 0x30) { + entry = i2c[1] + i2c; + entries = i2c[2]; + recordlen = i2c[3]; + } else + if (version) { + entry = i2c; + entries = 16; + recordlen = 4; + } else { + entry = legacy[0]; + entries = 2; + recordlen = 4; + } + + for (i = 0; i < entries; i++, entry += recordlen) { + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (port == NULL) { + nouveau_i2c_fini(dev); + return -ENOMEM; + } + + port->type = entry[3]; + if (version < 0x30) { + port->type &= 0x07; + if (port->type == 0x07) + port->type = 0xff; + } + + if (port->type == 0xff) { + kfree(port); + continue; + } + + switch (port->type) { + case 0: /* NV04:NV50 */ + port->drive = entry[0]; + port->sense = entry[1]; + break; + case 4: /* NV4E */ + port->drive = 0x600800 + entry[1]; + port->sense = port->drive; + break; + case 5: /* NV50- */ + port->drive = entry[0] & 0x0f; + if (dev_priv->card_type < NV_D0) { + if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) + break; + port->drive = nv50_i2c_port[port->drive]; + port->sense = port->drive; + } else { + port->drive = 0x00d014 + (port->drive * 0x20); + port->sense = port->drive; + } + break; + case 6: /* NV50- DP AUX */ + port->drive = entry[0] & 0x0f; + port->sense = port->drive; + port->adapter.algo = &nouveau_dp_i2c_algo; + break; + default: + break; + } + + if (!port->adapter.algo && !port->drive) { + NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", + i, port->type, port->drive, port->sense); + kfree(port); + continue; + } + + snprintf(port->adapter.name, sizeof(port->adapter.name), + "nouveau-%s-%d", pci_name(dev->pdev), i); + port->adapter.owner = THIS_MODULE; + port->adapter.dev.parent = &dev->pdev->dev; + port->dev = dev; + port->index = i; + port->dcb = ROM32(entry[0]); + i2c_set_adapdata(&port->adapter, i2c); + + if (port->adapter.algo != &nouveau_dp_i2c_algo) { + port->adapter.algo_data = &port->bit; + port->bit.udelay = 10; + port->bit.timeout = usecs_to_jiffies(2200); + port->bit.data = port; + port->bit.setsda = i2c_drive_sda; + port->bit.setscl = i2c_drive_scl; + port->bit.getsda = i2c_sense_sda; + port->bit.getscl = i2c_sense_scl; + + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 1); + i2c_drive_scl(port, 1); + + ret = i2c_bit_add_bus(&port->adapter); + } else { + port->adapter.algo = &nouveau_dp_i2c_algo; + ret = i2c_add_adapter(&port->adapter); + } + + if (ret) { + NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); + kfree(port); + continue; + } + + list_add_tail(&port->head, &dev_priv->i2c_ports); + } + + return 0; +} + +void +nouveau_i2c_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_i2c_chan *port, *tmp; + + list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) { + i2c_del_adapter(&port->adapter); + kfree(port); + } +} + +struct nouveau_i2c_chan * +nouveau_i2c_find(struct drm_device *dev, u8 index) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_i2c_chan *port; + + if (index == NV_I2C_DEFAULT(0) || + index == NV_I2C_DEFAULT(1)) { + u8 version, *i2c = i2c_table(dev, &version); + if (i2c && version >= 0x30) { + if (index == NV_I2C_DEFAULT(0)) + index = (i2c[4] & 0x0f); + else + index = (i2c[4] & 0xf0) >> 4; + } else { + index = 2; + } + } + + list_for_each_entry(port, &dev_priv->i2c_ports, head) { + if (port->index == index) + break; + } + + if (&port->head == &dev_priv->i2c_ports) + return NULL; + + if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { + u32 reg = 0x00e500, val; + if (port->type == 6) { + reg += port->drive * 0x50; + val = 0x2002; + } else { + reg += ((port->dcb & 0x1e00) >> 9) * 0x50; + val = 0xe001; + } + + /* nfi, but neither auxch or i2c work if it's 1 */ + nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); + /* nfi, but switches auxch vs normal i2c */ + nv_mask(dev, reg + 0x00, 0x0000f003, val); + } + + return port; +} + +bool +nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) +{ + uint8_t buf[] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = buf, + }, + { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + return i2c_transfer(&i2c->adapter, msgs, 2) == 2; +} + +int +nouveau_i2c_identify(struct drm_device *dev, const char *what, + struct i2c_board_info *info, + bool (*match)(struct nouveau_i2c_chan *, + struct i2c_board_info *), + int index) +{ + struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); + int i; + + if (!i2c) { + NV_DEBUG(dev, "No bus when probing %s on %d\n", what, index); + return -ENODEV; + } + + NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, i2c->index); + for (i = 0; info[i].addr; i++) { + if (nouveau_probe_i2c_addr(i2c, info[i].addr) && + (!match || match(i2c, &info[i]))) { + NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); + return i; + } + } + + NV_DEBUG(dev, "No devices found.\n"); + return -ENODEV; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c new file mode 100644 index 0000000..f01063c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -0,0 +1,193 @@ +#include "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" +#include +#include + +/* returns the size of fifo context */ +static int +nouveau_fifo_ctx_size(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset >= 0x40) + return 128 * 32; + else + if (dev_priv->chipset >= 0x17) + return 64 * 32; + else + if (dev_priv->chipset >= 0x10) + return 32 * 32; + + return 32 * 16; +} + +int nv04_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramht = NULL; + u32 offset, length; + int ret; + + /* RAMIN always available */ + dev_priv->ramin_available = true; + + /* Reserve space at end of VRAM for PRAMIN */ + if (dev_priv->card_type >= NV_40) { + u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); + u32 rsvd; + + /* estimate grctx size, the magics come from nv40_grctx.c */ + if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; + else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; + else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; + else rsvd = 0x4a40 * vs; + rsvd += 16 * 1024; + rsvd *= 32; /* per-channel */ + + rsvd += 512 * 1024; /* pci(e)gart table */ + rsvd += 512 * 1024; /* object storage */ + + dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); + } else { + dev_priv->ramin_rsvd_vram = 512 * 1024; + } + + /* Setup shared RAMHT */ + ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, + NVOBJ_FLAG_ZERO_ALLOC, &ramht); + if (ret) + return ret; + + ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); + nouveau_gpuobj_ref(NULL, &ramht); + if (ret) + return ret; + + /* And RAMRO */ + ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, + NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); + if (ret) + return ret; + + /* And RAMFC */ + length = nouveau_fifo_ctx_size(dev); + switch (dev_priv->card_type) { + case NV_40: + offset = 0x20000; + break; + default: + offset = 0x11400; + break; + } + + ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, + NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); + if (ret) + return ret; + + /* Only allow space after RAMFC to be used for object allocation */ + offset += length; + + /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 + * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 + * ("new style" control) the upper 16-bits of 0x2220 points at this + * other mysterious table that's clobbering important things. + * + * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting + * smashed to pieces on us, so reserve 0x30000-0x40000 too.. + */ + if (dev_priv->card_type >= NV_40) { + if (offset < 0x40000) + offset = 0x40000; + } + + ret = drm_mm_init(&dev_priv->ramin_heap, offset, + dev_priv->ramin_rsvd_vram - offset); + if (ret) { + NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); + return ret; + } + + return 0; +} + +void +nv04_instmem_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); + nouveau_gpuobj_ref(NULL, &dev_priv->ramro); + nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); + + if (drm_mm_initialized(&dev_priv->ramin_heap)) + drm_mm_takedown(&dev_priv->ramin_heap); +} + +int +nv04_instmem_suspend(struct drm_device *dev) +{ + return 0; +} + +void +nv04_instmem_resume(struct drm_device *dev) +{ +} + +int +nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, + u32 size, u32 align) +{ + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_mm_node *ramin = NULL; + + do { + if (drm_mm_pre_get(&dev_priv->ramin_heap)) + return -ENOMEM; + + spin_lock(&dev_priv->ramin_lock); + ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); + if (ramin == NULL) { + spin_unlock(&dev_priv->ramin_lock); + return -ENOMEM; + } + + ramin = drm_mm_get_block_atomic(ramin, size, align); + spin_unlock(&dev_priv->ramin_lock); + } while (ramin == NULL); + + gpuobj->node = ramin; + gpuobj->vinst = ramin->start; + return 0; +} + +void +nv04_instmem_put(struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + + spin_lock(&dev_priv->ramin_lock); + drm_mm_put_block(gpuobj->node); + gpuobj->node = NULL; + spin_unlock(&dev_priv->ramin_lock); +} + +int +nv04_instmem_map(struct nouveau_gpuobj *gpuobj) +{ + gpuobj->pinst = gpuobj->vinst; + return 0; +} + +void +nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj) +{ +} + +void +nv04_instmem_flush(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c new file mode 100644 index 0000000..d9b3463 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" +#include + +#define BAR1_VM_BASE 0x0020000000ULL +#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1) +#define BAR3_VM_BASE 0x0000000000ULL +#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3) + +struct nv50_instmem_priv { + uint32_t save1700[5]; /* 0x1700->0x1710 */ + + struct nouveau_gpuobj *bar1_dmaobj; + struct nouveau_gpuobj *bar3_dmaobj; +}; + +static void +nv50_channel_del(struct nouveau_channel **pchan) +{ + struct nouveau_channel *chan; + + chan = *pchan; + *pchan = NULL; + if (!chan) + return; + + nouveau_gpuobj_ref(NULL, &chan->ramfc); + nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); + nouveau_gpuobj_ref(NULL, &chan->vm_pd); + if (drm_mm_initialized(&chan->ramin_heap)) + drm_mm_takedown(&chan->ramin_heap); + nouveau_gpuobj_ref(NULL, &chan->ramin); + kfree(chan); +} + +static int +nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, + struct nouveau_channel **pchan) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; + u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; + struct nouveau_channel *chan; + int ret, i; + + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + chan->dev = dev; + + ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); + if (ret) { + nv50_channel_del(&chan); + return ret; + } + + ret = drm_mm_init(&chan->ramin_heap, 0x6000, chan->ramin->size - 0x6000); + if (ret) { + nv50_channel_del(&chan); + return ret; + } + + ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : + chan->ramin->pinst + pgd, + chan->ramin->vinst + pgd, + 0x4000, NVOBJ_FLAG_ZERO_ALLOC, + &chan->vm_pd); + if (ret) { + nv50_channel_del(&chan); + return ret; + } + + for (i = 0; i < 0x4000; i += 8) { + nv_wo32(chan->vm_pd, i + 0, 0x00000000); + nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); + } + + ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); + if (ret) { + nv50_channel_del(&chan); + return ret; + } + + ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : + chan->ramin->pinst + fc, + chan->ramin->vinst + fc, 0x100, + NVOBJ_FLAG_ZERO_ALLOC, &chan->ramfc); + if (ret) { + nv50_channel_del(&chan); + return ret; + } + + *pchan = chan; + return 0; +} + +int +nv50_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv; + struct nouveau_channel *chan; + struct nouveau_vm *vm; + int ret, i; + u32 tmp; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_priv->engine.instmem.priv = priv; + + /* Save state, will restore at takedown. */ + for (i = 0x1700; i <= 0x1710; i += 4) + priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); + + /* Global PRAMIN heap */ + ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); + if (ret) { + NV_ERROR(dev, "Failed to init RAMIN heap\n"); + goto error; + } + + /* BAR3 */ + ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE, + &dev_priv->bar3_vm); + if (ret) + goto error; + + ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8, + 0x1000, NVOBJ_FLAG_DONT_MAP | + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->bar3_vm->pgt[0].obj[0]); + if (ret) + goto error; + dev_priv->bar3_vm->pgt[0].refcount[0] = 1; + + nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); + + ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan); + if (ret) + goto error; + dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan; + + ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE, + NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, + NV_MEM_TYPE_VM, NV_MEM_COMP_VM, + &priv->bar3_dmaobj); + if (ret) + goto error; + + nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); + nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); + nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4)); + + dev_priv->engine.instmem.flush(dev); + dev_priv->ramin_available = true; + + tmp = nv_ro32(chan->ramin, 0); + nv_wo32(chan->ramin, 0, ~tmp); + if (nv_ro32(chan->ramin, 0) != ~tmp) { + NV_ERROR(dev, "PRAMIN readback failed\n"); + ret = -EIO; + goto error; + } + nv_wo32(chan->ramin, 0, tmp); + + /* BAR1 */ + ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm); + if (ret) + goto error; + + ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd); + if (ret) + goto error; + nouveau_vm_ref(NULL, &vm, NULL); + + ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE, + NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, + NV_MEM_TYPE_VM, NV_MEM_COMP_VM, + &priv->bar1_dmaobj); + if (ret) + goto error; + + nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4)); + for (i = 0; i < 8; i++) + nv_wr32(dev, 0x1900 + (i*4), 0); + + /* Create shared channel VM, space is reserved at the beginning + * to catch "NULL pointer" references + */ + ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, + &dev_priv->chan_vm); + if (ret) + return ret; + + return 0; + +error: + nv50_instmem_takedown(dev); + return ret; +} + +void +nv50_instmem_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + struct nouveau_channel *chan = dev_priv->channels.ptr[0]; + int i; + + NV_DEBUG(dev, "\n"); + + if (!priv) + return; + + dev_priv->ramin_available = false; + + nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); + + for (i = 0x1700; i <= 0x1710; i += 4) + nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); + + nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj); + nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj); + + nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd); + dev_priv->channels.ptr[127] = 0; + nv50_channel_del(&dev_priv->channels.ptr[0]); + + nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); + + if (drm_mm_initialized(&dev_priv->ramin_heap)) + drm_mm_takedown(&dev_priv->ramin_heap); + + dev_priv->engine.instmem.priv = NULL; + kfree(priv); +} + +int +nv50_instmem_suspend(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + dev_priv->ramin_available = false; + return 0; +} + +void +nv50_instmem_resume(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; + struct nouveau_channel *chan = dev_priv->channels.ptr[0]; + int i; + + /* Poke the relevant regs, and pray it works :) */ + nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12)); + nv_wr32(dev, NV50_PUNK_UNK1710, 0); + nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | + NV50_PUNK_BAR_CFG_BASE_VALID); + nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) | + NV50_PUNK_BAR1_CTXDMA_VALID); + nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) | + NV50_PUNK_BAR3_CTXDMA_VALID); + + for (i = 0; i < 8; i++) + nv_wr32(dev, 0x1900 + (i*4), 0); + + dev_priv->ramin_available = true; +} + +struct nv50_gpuobj_node { + struct nouveau_mem *vram; + struct nouveau_vma chan_vma; + u32 align; +}; + +int +nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, + u32 size, u32 align) +{ + struct drm_device *dev = gpuobj->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct nv50_gpuobj_node *node = NULL; + int ret; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + node->align = align; + + size = (size + 4095) & ~4095; + align = max(align, (u32)4096); + + ret = vram->get(dev, size, align, 0, 0, &node->vram); + if (ret) { + kfree(node); + return ret; + } + + gpuobj->vinst = node->vram->offset; + + if (gpuobj->flags & NVOBJ_FLAG_VM) { + u32 flags = NV_MEM_ACCESS_RW; + if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER)) + flags |= NV_MEM_ACCESS_SYS; + + ret = nouveau_vm_get(chan->vm, size, 12, flags, + &node->chan_vma); + if (ret) { + vram->put(dev, &node->vram); + kfree(node); + return ret; + } + + nouveau_vm_map(&node->chan_vma, node->vram); + gpuobj->linst = node->chan_vma.offset; + } + + gpuobj->size = size; + gpuobj->node = node; + return 0; +} + +void +nv50_instmem_put(struct nouveau_gpuobj *gpuobj) +{ + struct drm_device *dev = gpuobj->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct nv50_gpuobj_node *node; + + node = gpuobj->node; + gpuobj->node = NULL; + + if (node->chan_vma.node) { + nouveau_vm_unmap(&node->chan_vma); + nouveau_vm_put(&node->chan_vma); + } + vram->put(dev, &node->vram); + kfree(node); +} + +int +nv50_instmem_map(struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct nv50_gpuobj_node *node = gpuobj->node; + int ret; + + ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12, + NV_MEM_ACCESS_RW, &node->vram->bar_vma); + if (ret) + return ret; + + nouveau_vm_map(&node->vram->bar_vma, node->vram); + gpuobj->pinst = node->vram->bar_vma.offset; + return 0; +} + +void +nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) +{ + struct nv50_gpuobj_node *node = gpuobj->node; + + if (node->vram->bar_vma.node) { + nouveau_vm_unmap(&node->vram->bar_vma); + nouveau_vm_put(&node->vram->bar_vma); + } +} + +void +nv50_instmem_flush(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x00330c, 0x00000001); + if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); + spin_unlock_irqrestore(&dev_priv->vm_lock, flags); +} + +void +nv84_instmem_flush(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x070000, 0x00000001); + if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); + spin_unlock_irqrestore(&dev_priv->vm_lock, flags); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c new file mode 100644 index 0000000..0ce9869 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c @@ -0,0 +1,222 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +struct nvc0_instmem_priv { + struct nouveau_gpuobj *bar1_pgd; + struct nouveau_channel *bar1; + struct nouveau_gpuobj *bar3_pgd; + struct nouveau_channel *bar3; +}; + +int +nvc0_instmem_suspend(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + dev_priv->ramin_available = false; + return 0; +} + +void +nvc0_instmem_resume(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; + + nv_mask(dev, 0x100c80, 0x00000001, 0x00000000); + nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12); + nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12); + dev_priv->ramin_available = true; +} + +static void +nvc0_channel_del(struct nouveau_channel **pchan) +{ + struct nouveau_channel *chan; + + chan = *pchan; + *pchan = NULL; + if (!chan) + return; + + nouveau_vm_ref(NULL, &chan->vm, NULL); + if (drm_mm_initialized(&chan->ramin_heap)) + drm_mm_takedown(&chan->ramin_heap); + nouveau_gpuobj_ref(NULL, &chan->ramin); + kfree(chan); +} + +static int +nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, + struct nouveau_channel **pchan, + struct nouveau_gpuobj *pgd, u64 vm_size) +{ + struct nouveau_channel *chan; + int ret; + + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + chan->dev = dev; + + ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); + if (ret) { + nvc0_channel_del(&chan); + return ret; + } + + ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000); + if (ret) { + nvc0_channel_del(&chan); + return ret; + } + + ret = nouveau_vm_ref(vm, &chan->vm, NULL); + if (ret) { + nvc0_channel_del(&chan); + return ret; + } + + nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst)); + nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst)); + nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1)); + nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1)); + + *pchan = chan; + return 0; +} + +int +nvc0_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct pci_dev *pdev = dev->pdev; + struct nvc0_instmem_priv *priv; + struct nouveau_vm *vm = NULL; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + pinstmem->priv = priv; + + /* BAR3 VM */ + ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0, + &dev_priv->bar3_vm); + if (ret) + goto error; + + ret = nouveau_gpuobj_new(dev, NULL, + (pci_resource_len(pdev, 3) >> 12) * 8, 0, + NVOBJ_FLAG_DONT_MAP | + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->bar3_vm->pgt[0].obj[0]); + if (ret) + goto error; + dev_priv->bar3_vm->pgt[0].refcount[0] = 1; + + nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); + + ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, + NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd); + if (ret) + goto error; + + ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd); + if (ret) + goto error; + nouveau_vm_ref(NULL, &vm, NULL); + + ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3, + priv->bar3_pgd, pci_resource_len(dev->pdev, 3)); + if (ret) + goto error; + + /* BAR1 VM */ + ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm); + if (ret) + goto error; + + ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, + NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd); + if (ret) + goto error; + + ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd); + if (ret) + goto error; + nouveau_vm_ref(NULL, &vm, NULL); + + ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1, + priv->bar1_pgd, pci_resource_len(dev->pdev, 1)); + if (ret) + goto error; + + /* channel vm */ + ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, + &dev_priv->chan_vm); + if (ret) + goto error; + + nvc0_instmem_resume(dev); + return 0; +error: + nvc0_instmem_takedown(dev); + return ret; +} + +void +nvc0_instmem_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; + struct nouveau_vm *vm = NULL; + + nvc0_instmem_suspend(dev); + + nv_wr32(dev, 0x1704, 0x00000000); + nv_wr32(dev, 0x1714, 0x00000000); + + nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); + + nvc0_channel_del(&priv->bar1); + nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd); + nouveau_gpuobj_ref(NULL, &priv->bar1_pgd); + + nvc0_channel_del(&priv->bar3); + nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL); + nouveau_vm_ref(NULL, &vm, priv->bar3_pgd); + nouveau_gpuobj_ref(NULL, &priv->bar3_pgd); + nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); + + dev_priv->engine.instmem.priv = NULL; + kfree(priv); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c new file mode 100644 index 0000000..2af43a1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c @@ -0,0 +1,24 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_mc_init(struct drm_device *dev) +{ + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + + nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + + /* Disable PROM access. */ + nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); + + return 0; +} + +void +nv04_mc_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c new file mode 100644 index 0000000..03c0d4c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c @@ -0,0 +1,28 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_mc_init(struct drm_device *dev) +{ + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + + if (nv44_graph_class(dev)) { + u32 tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA); + nv_wr32(dev, NV40_PMC_1700, tmp); + nv_wr32(dev, NV40_PMC_1704, 0); + nv_wr32(dev, NV40_PMC_1708, 0); + nv_wr32(dev, NV40_PMC_170C, tmp); + } + + return 0; +} + +void +nv40_mc_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c new file mode 100644 index 0000000..e0a9c3f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +int +nv50_mc_init(struct drm_device *dev) +{ + nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + return 0; +} + +void nv50_mc_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c new file mode 100644 index 0000000..55c9452 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -0,0 +1,84 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" +#include "nouveau_hw.h" + +int +nv04_timer_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 m, n, d; + + nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); + nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); + + /* aim for 31.25MHz, which gives us nanosecond timestamps */ + d = 1000000 / 32; + + /* determine base clock for timer source */ + if (dev_priv->chipset < 0x40) { + n = nouveau_hw_get_clock(dev, PLL_CORE); + } else + if (dev_priv->chipset == 0x40) { + /*XXX: figure this out */ + n = 0; + } else { + n = dev_priv->crystal; + m = 1; + while (n < (d * 2)) { + n += (n / m); + m++; + } + + nv_wr32(dev, 0x009220, m - 1); + } + + if (!n) { + NV_WARN(dev, "PTIMER: unknown input clock freq\n"); + if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || + !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { + nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1); + nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1); + } + return 0; + } + + /* reduce ratio to acceptable values */ + while (((n % 5) == 0) && ((d % 5) == 0)) { + n /= 5; + d /= 5; + } + + while (((n % 2) == 0) && ((d % 2) == 0)) { + n /= 2; + d /= 2; + } + + while (n > 0xffff || d > 0xffff) { + n >>= 1; + d >>= 1; + } + + nv_wr32(dev, NV04_PTIMER_NUMERATOR, n); + nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d); + return 0; +} + +u64 +nv04_timer_read(struct drm_device *dev) +{ + u32 hi, lo; + + do { + hi = nv_rd32(dev, NV04_PTIMER_TIME_1); + lo = nv_rd32(dev, NV04_PTIMER_TIME_0); + } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1)); + + return ((u64)hi << 32 | lo); +} + +void +nv04_timer_takedown(struct drm_device *dev) +{ +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c new file mode 100644 index 0000000..3d11a4a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -0,0 +1,493 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include +#include + +void +nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) +{ + struct nouveau_vm *vm = vma->vm; + struct nouveau_mm_node *r; + int big = vma->node->type != vm->spg_shift; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + + delta = 0; + list_for_each_entry(r, &node->regions, rl_entry) { + u64 phys = (u64)r->offset << 12; + u32 num = r->length >> bits; + + while (num) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; + + end = (pte + num); + if (unlikely(end >= max)) + end = max; + len = end - pte; + + vm->map(vma, pgt, node, pte, len, phys, delta); + + num -= len; + pte += len; + if (unlikely(end >= max)) { + phys += len << (bits + 12); + pde++; + pte = 0; + } + + delta += (u64)len << vma->node->type; + } + } + + vm->flush(vm); +} + +void +nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) +{ + nouveau_vm_map_at(vma, 0, node); +} + +void +nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, + struct nouveau_mem *mem) +{ + struct nouveau_vm *vm = vma->vm; + int big = vma->node->type != vm->spg_shift; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 num = length >> vma->node->type; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + unsigned m, sglen; + u32 end, len; + int i; + struct scatterlist *sg; + + for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; + sglen = sg_dma_len(sg) >> PAGE_SHIFT; + + end = pte + sglen; + if (unlikely(end >= max)) + end = max; + len = end - pte; + + for (m = 0; m < len; m++) { + dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); + + vm->map_sg(vma, pgt, mem, pte, 1, &addr); + num--; + pte++; + + if (num == 0) + goto finish; + } + if (unlikely(end >= max)) { + pde++; + pte = 0; + } + if (m < sglen) { + for (; m < sglen; m++) { + dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); + + vm->map_sg(vma, pgt, mem, pte, 1, &addr); + num--; + pte++; + if (num == 0) + goto finish; + } + } + + } +finish: + vm->flush(vm); +} + +void +nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, + struct nouveau_mem *mem) +{ + struct nouveau_vm *vm = vma->vm; + dma_addr_t *list = mem->pages; + int big = vma->node->type != vm->spg_shift; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 num = length >> vma->node->type; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + + while (num) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; + + end = (pte + num); + if (unlikely(end >= max)) + end = max; + len = end - pte; + + vm->map_sg(vma, pgt, mem, pte, len, list); + + num -= len; + pte += len; + list += len; + if (unlikely(end >= max)) { + pde++; + pte = 0; + } + } + + vm->flush(vm); +} + +void +nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) +{ + struct nouveau_vm *vm = vma->vm; + int big = vma->node->type != vm->spg_shift; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 num = length >> vma->node->type; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + + while (num) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; + + end = (pte + num); + if (unlikely(end >= max)) + end = max; + len = end - pte; + + vm->unmap(pgt, pte, len); + + num -= len; + pte += len; + if (unlikely(end >= max)) { + pde++; + pte = 0; + } + } + + vm->flush(vm); +} + +void +nouveau_vm_unmap(struct nouveau_vma *vma) +{ + nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); +} + +static void +nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) +{ + struct nouveau_vm_pgd *vpgd; + struct nouveau_vm_pgt *vpgt; + struct nouveau_gpuobj *pgt; + u32 pde; + + for (pde = fpde; pde <= lpde; pde++) { + vpgt = &vm->pgt[pde - vm->fpde]; + if (--vpgt->refcount[big]) + continue; + + pgt = vpgt->obj[big]; + vpgt->obj[big] = NULL; + + list_for_each_entry(vpgd, &vm->pgd_list, head) { + vm->map_pgt(vpgd->obj, pde, vpgt->obj); + } + + mutex_unlock(&vm->mm.mutex); + nouveau_gpuobj_ref(NULL, &pgt); + mutex_lock(&vm->mm.mutex); + } +} + +static int +nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) +{ + struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; + struct nouveau_vm_pgd *vpgd; + struct nouveau_gpuobj *pgt; + int big = (type != vm->spg_shift); + u32 pgt_size; + int ret; + + pgt_size = (1 << (vm->pgt_bits + 12)) >> type; + pgt_size *= 8; + + mutex_unlock(&vm->mm.mutex); + ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &pgt); + mutex_lock(&vm->mm.mutex); + if (unlikely(ret)) + return ret; + + /* someone beat us to filling the PDE while we didn't have the lock */ + if (unlikely(vpgt->refcount[big]++)) { + mutex_unlock(&vm->mm.mutex); + nouveau_gpuobj_ref(NULL, &pgt); + mutex_lock(&vm->mm.mutex); + return 0; + } + + vpgt->obj[big] = pgt; + list_for_each_entry(vpgd, &vm->pgd_list, head) { + vm->map_pgt(vpgd->obj, pde, vpgt->obj); + } + + return 0; +} + +int +nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, + u32 access, struct nouveau_vma *vma) +{ + u32 align = (1 << page_shift) >> 12; + u32 msize = size >> 12; + u32 fpde, lpde, pde; + int ret; + + mutex_lock(&vm->mm.mutex); + ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node); + if (unlikely(ret != 0)) { + mutex_unlock(&vm->mm.mutex); + return ret; + } + + fpde = (vma->node->offset >> vm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + for (pde = fpde; pde <= lpde; pde++) { + struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; + int big = (vma->node->type != vm->spg_shift); + + if (likely(vpgt->refcount[big])) { + vpgt->refcount[big]++; + continue; + } + + ret = nouveau_vm_map_pgt(vm, pde, vma->node->type); + if (ret) { + if (pde != fpde) + nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); + nouveau_mm_put(&vm->mm, vma->node); + mutex_unlock(&vm->mm.mutex); + vma->node = NULL; + return ret; + } + } + mutex_unlock(&vm->mm.mutex); + + vma->vm = vm; + vma->offset = (u64)vma->node->offset << 12; + vma->access = access; + return 0; +} + +void +nouveau_vm_put(struct nouveau_vma *vma) +{ + struct nouveau_vm *vm = vma->vm; + u32 fpde, lpde; + + if (unlikely(vma->node == NULL)) + return; + fpde = (vma->node->offset >> vm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + + mutex_lock(&vm->mm.mutex); + nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); + nouveau_mm_put(&vm->mm, vma->node); + vma->node = NULL; + mutex_unlock(&vm->mm.mutex); +} + +int +nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, + struct nouveau_vm **pvm) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vm *vm; + u64 mm_length = (offset + length) - mm_offset; + u32 block, pgt_bits; + int ret; + + vm = kzalloc(sizeof(*vm), GFP_KERNEL); + if (!vm) + return -ENOMEM; + + if (dev_priv->card_type == NV_50) { + vm->map_pgt = nv50_vm_map_pgt; + vm->map = nv50_vm_map; + vm->map_sg = nv50_vm_map_sg; + vm->unmap = nv50_vm_unmap; + vm->flush = nv50_vm_flush; + vm->spg_shift = 12; + vm->lpg_shift = 16; + + pgt_bits = 29; + block = (1 << pgt_bits); + if (length < block) + block = length; + + } else + if (dev_priv->card_type >= NV_C0) { + vm->map_pgt = nvc0_vm_map_pgt; + vm->map = nvc0_vm_map; + vm->map_sg = nvc0_vm_map_sg; + vm->unmap = nvc0_vm_unmap; + vm->flush = nvc0_vm_flush; + vm->spg_shift = 12; + vm->lpg_shift = 17; + pgt_bits = 27; + block = 4096; + } else { + kfree(vm); + return -ENOSYS; + } + + vm->fpde = offset >> pgt_bits; + vm->lpde = (offset + length - 1) >> pgt_bits; + vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); + if (!vm->pgt) { + kfree(vm); + return -ENOMEM; + } + + INIT_LIST_HEAD(&vm->pgd_list); + vm->dev = dev; + vm->refcount = 1; + vm->pgt_bits = pgt_bits - 12; + + ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12, + block >> 12); + if (ret) { + kfree(vm); + return ret; + } + + *pvm = vm; + return 0; +} + +static int +nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) +{ + struct nouveau_vm_pgd *vpgd; + int i; + + if (!pgd) + return 0; + + vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL); + if (!vpgd) + return -ENOMEM; + + nouveau_gpuobj_ref(pgd, &vpgd->obj); + + mutex_lock(&vm->mm.mutex); + for (i = vm->fpde; i <= vm->lpde; i++) + vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); + list_add(&vpgd->head, &vm->pgd_list); + mutex_unlock(&vm->mm.mutex); + return 0; +} + +static void +nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) +{ + struct nouveau_vm_pgd *vpgd, *tmp; + struct nouveau_gpuobj *pgd = NULL; + + if (!mpgd) + return; + + mutex_lock(&vm->mm.mutex); + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + if (vpgd->obj == mpgd) { + pgd = vpgd->obj; + list_del(&vpgd->head); + kfree(vpgd); + break; + } + } + mutex_unlock(&vm->mm.mutex); + + nouveau_gpuobj_ref(NULL, &pgd); +} + +static void +nouveau_vm_del(struct nouveau_vm *vm) +{ + struct nouveau_vm_pgd *vpgd, *tmp; + + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + nouveau_vm_unlink(vm, vpgd->obj); + } + + nouveau_mm_fini(&vm->mm); + kfree(vm->pgt); + kfree(vm); +} + +int +nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, + struct nouveau_gpuobj *pgd) +{ + struct nouveau_vm *vm; + int ret; + + vm = ref; + if (vm) { + ret = nouveau_vm_link(vm, pgd); + if (ret) + return ret; + + vm->refcount++; + } + + vm = *ptr; + *ptr = ref; + + if (vm) { + nouveau_vm_unlink(vm, pgd); + + if (--vm->refcount == 0) + nouveau_vm_del(vm); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c new file mode 100644 index 0000000..eeac72f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -0,0 +1,177 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +void +nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]) +{ + u64 phys = 0xdeadcafe00000000ULL; + u32 coverage = 0; + + if (pgt[0]) { + phys = 0x00000003 | pgt[0]->vinst; /* present, 4KiB pages */ + coverage = (pgt[0]->size >> 3) << 12; + } else + if (pgt[1]) { + phys = 0x00000001 | pgt[1]->vinst; /* present */ + coverage = (pgt[1]->size >> 3) << 16; + } + + if (phys & 1) { + if (coverage <= 32 * 1024 * 1024) + phys |= 0x60; + else if (coverage <= 64 * 1024 * 1024) + phys |= 0x40; + else if (coverage <= 128 * 1024 * 1024) + phys |= 0x20; + } + + nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); + nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); +} + +static inline u64 +vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) +{ + phys |= 1; /* present */ + phys |= (u64)memtype << 40; + phys |= target << 4; + if (vma->access & NV_MEM_ACCESS_SYS) + phys |= (1 << 6); + if (!(vma->access & NV_MEM_ACCESS_WO)) + phys |= (1 << 3); + return phys; +} + +void +nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) +{ + struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; + u32 comp = (mem->memtype & 0x180) >> 7; + u32 block, target; + int i; + + /* IGPs don't have real VRAM, re-target to stolen system memory */ + target = 0; + if (dev_priv->vram_sys_base) { + phys += dev_priv->vram_sys_base; + target = 3; + } + + phys = vm_addr(vma, phys, mem->memtype, target); + pte <<= 3; + cnt <<= 3; + + while (cnt) { + u32 offset_h = upper_32_bits(phys); + u32 offset_l = lower_32_bits(phys); + + for (i = 7; i >= 0; i--) { + block = 1 << (i + 3); + if (cnt >= block && !(pte & (block - 1))) + break; + } + offset_l |= (i << 7); + + phys += block << (vma->node->type - 3); + cnt -= block; + if (comp) { + u32 tag = mem->tag->start + ((delta >> 16) * comp); + offset_h |= (tag << 17); + delta += block << (vma->node->type - 3); + } + + while (block) { + nv_wo32(pgt, pte + 0, offset_l); + nv_wo32(pgt, pte + 4, offset_h); + pte += 8; + block -= 8; + } + } +} + +void +nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2; + pte <<= 3; + while (cnt--) { + u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; + } +} + +void +nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte <<= 3; + while (cnt--) { + nv_wo32(pgt, pte + 0, 0x00000000); + nv_wo32(pgt, pte + 4, 0x00000000); + pte += 8; + } +} + +void +nv50_vm_flush(struct nouveau_vm *vm) +{ + struct drm_nouveau_private *dev_priv = vm->dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + int i; + + pinstmem->flush(vm->dev); + + /* BAR */ + if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) { + nv50_vm_flush_engine(vm->dev, 6); + return; + } + + for (i = 0; i < NVOBJ_ENGINE_NR; i++) { + if (atomic_read(&vm->engref[i])) + dev_priv->eng[i]->tlb_flush(vm->dev, i); + } +} + +void +nv50_vm_flush_engine(struct drm_device *dev, int engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x100c80, (engine << 16) | 1); + if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) + NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); + spin_unlock_irqrestore(&dev_priv->vm_lock, flags); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c new file mode 100644 index 0000000..734877a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -0,0 +1,136 @@ +/* + * Copyright 2010 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: + * + * 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 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 "nouveau_drv.h" +#include + +void +nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, + struct nouveau_gpuobj *pgt[2]) +{ + u32 pde[2] = { 0, 0 }; + + if (pgt[0]) + pde[1] = 0x00000001 | (pgt[0]->vinst >> 8); + if (pgt[1]) + pde[0] = 0x00000001 | (pgt[1]->vinst >> 8); + + nv_wo32(pgd, (index * 8) + 0, pde[0]); + nv_wo32(pgd, (index * 8) + 4, pde[1]); +} + +static inline u64 +nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) +{ + phys >>= 8; + + phys |= 0x00000001; /* present */ + if (vma->access & NV_MEM_ACCESS_SYS) + phys |= 0x00000002; + + phys |= ((u64)target << 32); + phys |= ((u64)memtype << 36); + + return phys; +} + +void +nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) +{ + u32 next = 1 << (vma->node->type - 8); + + phys = nvc0_vm_addr(vma, phys, mem->memtype, 0); + pte <<= 3; + while (cnt--) { + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + phys += next; + pte += 8; + } +} + +void +nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5; + + pte <<= 3; + while (cnt--) { + u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, target); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; + } +} + +void +nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte <<= 3; + while (cnt--) { + nv_wo32(pgt, pte + 0, 0x00000000); + nv_wo32(pgt, pte + 4, 0x00000000); + pte += 8; + } +} + +void +nvc0_vm_flush(struct nouveau_vm *vm) +{ + struct drm_nouveau_private *dev_priv = vm->dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct drm_device *dev = vm->dev; + struct nouveau_vm_pgd *vpgd; + unsigned long flags; + u32 engine; + + engine = 1; + if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) + engine |= 4; + + pinstmem->flush(vm->dev); + + spin_lock_irqsave(&dev_priv->vm_lock, flags); + list_for_each_entry(vpgd, &vm->pgd_list, head) { + /* looks like maybe a "free flush slots" counter, the + * faster you write to 0x100cbc to more it decreases + */ + if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { + NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", + nv_rd32(dev, 0x100c80), engine); + } + nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); + nv_wr32(dev, 0x100cbc, 0x80000000 | engine); + /* wait for flush to be queued? */ + if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { + NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", + nv_rd32(dev, 0x100c80), engine); + } + } + spin_unlock_irqrestore(&dev_priv->vm_lock, flags); +} -- cgit v1.1 From 9274f4a9ba7e70d1770e237fca16d52f27f0c728 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 6 Jul 2012 07:36:43 +1000 Subject: drm/nouveau/core: pull in most of the new core infrastructure This commit provides most of the infrastructure to support a major overhaul of Nouveau's internals coming in the following commits. This work aims to take all the things we've learned over the last several years, and turn that into a cleaner architecture that's more maintainable going forward. RAMHT and MM bits of the new core have been left out for the moment, and will be pulled in as I go through the process of porting the code to become either subdev or engine modules. There are several main goals I wanted to achieve through this work: -- Reduce complexity The goal here was to make each component of the driver as independent as possible, which will ease maintainability and readability, and provide a good base for resetting locked up GPU units in the future. -- Better tracking of GPU units that are required at any given time This is for future PM work, we'll be able to tell exactly what parts of the GPU we need powered at any given point (etc). -- Expose all available NVIDIA GPUs to the client In order to support things such as multi-GPU channels, we want to be able to expose all the NVIDIA GPUs to the client over a single file descriptor so it can send a single push buffer to multiple GPUs. -- Untangle the core hardware support code from the DRM implementation This happened initially as an unexpected side-effect of developing the initial core infrastructure in userspace, but it turned into a goal of the whole project. Initial benefits will be the availablility of a number of userspace tools and tests using the same code as the driver itself, but will also be important as I look into some virtualisation ideas. v2: Ben Skeggs - fix duplicate assignments noticed by clang - implement some forgotten yelling in error path - ensure 64-bit engine mask is used everywhere v3: Marcin Slusarz - sparse fixes - inline nv_printk into nv_assert to prevent recursive inlining issues v4: Ben Skeggs - fixed minor memory leak on gpuobj destruction Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/client.c | 103 +++++ drivers/gpu/drm/nouveau/core/core/engctx.c | 230 ++++++++++ drivers/gpu/drm/nouveau/core/core/engine.c | 54 +++ drivers/gpu/drm/nouveau/core/core/enum.c | 67 +++ drivers/gpu/drm/nouveau/core/core/gpuobj.c | 318 ++++++++++++++ drivers/gpu/drm/nouveau/core/core/handle.c | 189 +++++++++ drivers/gpu/drm/nouveau/core/core/mm.c | 3 +- drivers/gpu/drm/nouveau/core/core/namedb.c | 203 +++++++++ drivers/gpu/drm/nouveau/core/core/object.c | 468 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/core/option.c | 131 ++++++ drivers/gpu/drm/nouveau/core/core/parent.c | 139 ++++++ drivers/gpu/drm/nouveau/core/core/printk.c | 74 ++++ drivers/gpu/drm/nouveau/core/core/subdev.c | 115 +++++ drivers/gpu/drm/nouveau/core/include/core/class.h | 77 ++++ drivers/gpu/drm/nouveau/core/include/core/client.h | 42 ++ drivers/gpu/drm/nouveau/core/include/core/debug.h | 13 + drivers/gpu/drm/nouveau/core/include/core/device.h | 122 ++++++ drivers/gpu/drm/nouveau/core/include/core/engctx.h | 61 +++ drivers/gpu/drm/nouveau/core/include/core/engine.h | 54 +++ drivers/gpu/drm/nouveau/core/include/core/enum.h | 23 + drivers/gpu/drm/nouveau/core/include/core/gpuobj.h | 82 ++++ drivers/gpu/drm/nouveau/core/include/core/handle.h | 26 ++ drivers/gpu/drm/nouveau/core/include/core/math.h | 16 + drivers/gpu/drm/nouveau/core/include/core/mm.h | 4 +- drivers/gpu/drm/nouveau/core/include/core/namedb.h | 56 +++ drivers/gpu/drm/nouveau/core/include/core/object.h | 188 +++++++++ drivers/gpu/drm/nouveau/core/include/core/option.h | 11 + drivers/gpu/drm/nouveau/core/include/core/parent.h | 64 +++ drivers/gpu/drm/nouveau/core/include/core/printk.h | 39 ++ drivers/gpu/drm/nouveau/core/include/core/subdev.h | 118 ++++++ .../gpu/drm/nouveau/core/include/subdev/device.h | 25 ++ drivers/gpu/drm/nouveau/core/os.h | 46 ++ drivers/gpu/drm/nouveau/core/subdev/device/base.c | 461 ++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 41 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 53 +++ drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 45 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 47 +++ drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 69 +++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 65 +++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 53 +++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 41 ++ 41 files changed, 4032 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/core/client.c create mode 100644 drivers/gpu/drm/nouveau/core/core/engctx.c create mode 100644 drivers/gpu/drm/nouveau/core/core/engine.c create mode 100644 drivers/gpu/drm/nouveau/core/core/enum.c create mode 100644 drivers/gpu/drm/nouveau/core/core/gpuobj.c create mode 100644 drivers/gpu/drm/nouveau/core/core/handle.c create mode 100644 drivers/gpu/drm/nouveau/core/core/namedb.c create mode 100644 drivers/gpu/drm/nouveau/core/core/object.c create mode 100644 drivers/gpu/drm/nouveau/core/core/option.c create mode 100644 drivers/gpu/drm/nouveau/core/core/parent.c create mode 100644 drivers/gpu/drm/nouveau/core/core/printk.c create mode 100644 drivers/gpu/drm/nouveau/core/core/subdev.c create mode 100644 drivers/gpu/drm/nouveau/core/include/core/class.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/client.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/debug.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/device.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/engctx.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/engine.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/enum.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/gpuobj.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/handle.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/math.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/namedb.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/object.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/option.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/parent.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/printk.h create mode 100644 drivers/gpu/drm/nouveau/core/include/core/subdev.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/device.h create mode 100644 drivers/gpu/drm/nouveau/core/os.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nv20.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nv30.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/device/nve0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c new file mode 100644 index 0000000..e190f18 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/client.c @@ -0,0 +1,103 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include + +#include + +static void +nouveau_client_dtor(struct nouveau_object *object) +{ + struct nouveau_client *client = (void *)object; + nouveau_object_ref(NULL, &client->device); + nouveau_handle_destroy(client->root); + nouveau_namedb_destroy(&client->base); +} + +static struct nouveau_oclass +nouveau_client_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .dtor = nouveau_client_dtor, + }, +}; + +int +nouveau_client_create_(u32 name, u64 devname, const char *cfg, const char *dbg, + int length, void **pobject) +{ + struct nouveau_object *device; + struct nouveau_client *client; + int ret; + + device = (void *)nouveau_device_find(devname); + if (!device) + return -ENODEV; + + ret = nouveau_namedb_create_(NULL, NULL, &nouveau_client_oclass, + NV_CLIENT_CLASS, nouveau_device_sclass, + 0, length, pobject); + client = *pobject; + if (ret) + return ret; + + ret = nouveau_handle_create(nv_object(client), ~0, ~0, + nv_object(client), &client->root); + if (ret) { + nouveau_namedb_destroy(&client->base); + return ret; + } + + /* prevent init/fini being called, os in in charge of this */ + atomic_set(&nv_object(client)->usecount, 2); + + nouveau_object_ref(device, &client->device); + client->handle = name; + client->debug = nouveau_dbgopt(dbg, "CLIENT"); + return 0; +} + +int +nouveau_client_init(struct nouveau_client *client) +{ + int ret; + nv_debug(client, "init running\n"); + ret = nouveau_handle_init(client->root); + nv_debug(client, "init completed with %d\n", ret); + return ret; +} + +int +nouveau_client_fini(struct nouveau_client *client, bool suspend) +{ + const char *name[2] = { "fini", "suspend" }; + int ret; + + nv_debug(client, "%s running\n", name[suspend]); + ret = nouveau_handle_fini(client->root, suspend); + nv_debug(client, "%s completed with %d\n", name[suspend], ret); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/core/engctx.c b/drivers/gpu/drm/nouveau/core/core/engctx.c new file mode 100644 index 0000000..50dc16d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/engctx.c @@ -0,0 +1,230 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include +#include + +#include + +int +nouveau_engctx_create_(struct nouveau_object *parent, + struct nouveau_object *engobj, + struct nouveau_oclass *oclass, + struct nouveau_object *pargpu, + u32 size, u32 align, u32 flags, + int length, void **pobject) +{ + struct nouveau_client *client = nouveau_client(parent); + struct nouveau_engine *engine = nv_engine(engobj); + struct nouveau_subdev *subdev = nv_subdev(engine); + struct nouveau_engctx *engctx; + struct nouveau_object *ctxpar; + int ret; + + /* use existing context for the engine if one is available */ + mutex_lock(&subdev->mutex); + list_for_each_entry(engctx, &engine->contexts, head) { + ctxpar = nv_pclass(nv_object(engctx), NV_PARENT_CLASS); + if (ctxpar == parent) { + atomic_inc(&nv_object(engctx)->refcount); + *pobject = engctx; + mutex_unlock(&subdev->mutex); + return 1; + } + } + mutex_unlock(&subdev->mutex); + + if (size) { + ret = nouveau_gpuobj_create_(parent, engobj, oclass, + NV_ENGCTX_CLASS, + pargpu, size, align, flags, + length, pobject); + } else { + ret = nouveau_object_create_(parent, engobj, oclass, + NV_ENGCTX_CLASS, length, pobject); + } + + engctx = *pobject; + if (engctx && client->vm) + atomic_inc(&client->vm->engref[nv_engidx(engobj)]); + if (ret) + return ret; + + list_add(&engctx->head, &engine->contexts); + return 0; +} + +void +nouveau_engctx_destroy(struct nouveau_engctx *engctx) +{ + struct nouveau_object *engine = nv_object(engctx)->engine; + struct nouveau_client *client = nouveau_client(engctx); + + nouveau_gpuobj_unmap(&engctx->vma); + list_del(&engctx->head); + if (client->vm) + atomic_dec(&client->vm->engref[nv_engidx(engine)]); + + if (engctx->base.size) + nouveau_gpuobj_destroy(&engctx->base); + else + nouveau_object_destroy(&engctx->base.base); +} + +int +nouveau_engctx_init(struct nouveau_engctx *engctx) +{ + struct nouveau_object *object = nv_object(engctx); + struct nouveau_subdev *subdev = nv_subdev(object->engine); + struct nouveau_object *parent; + struct nouveau_subdev *pardev; + int ret; + + ret = nouveau_gpuobj_init(&engctx->base); + if (ret) + return ret; + + parent = nv_pclass(object->parent, NV_PARENT_CLASS); + pardev = nv_subdev(parent->engine); + if (nv_parent(parent)->context_attach) { + mutex_lock(&pardev->mutex); + ret = nv_parent(parent)->context_attach(parent, object); + mutex_unlock(&pardev->mutex); + } + + if (ret) { + nv_error(parent, "failed to attach %s context, %d\n", + subdev->name, ret); + return ret; + } + + nv_debug(parent, "attached %s context\n", subdev->name); + return 0; +} + +int +nouveau_engctx_fini(struct nouveau_engctx *engctx, bool suspend) +{ + struct nouveau_object *object = nv_object(engctx); + struct nouveau_subdev *subdev = nv_subdev(object->engine); + struct nouveau_object *parent; + struct nouveau_subdev *pardev; + int ret = 0; + + parent = nv_pclass(object->parent, NV_PARENT_CLASS); + pardev = nv_subdev(parent->engine); + if (nv_parent(parent)->context_detach) { + mutex_lock(&pardev->mutex); + ret = nv_parent(parent)->context_detach(parent, suspend, object); + mutex_unlock(&pardev->mutex); + } + + if (ret) { + nv_error(parent, "failed to detach %s context, %d\n", + subdev->name, ret); + return ret; + } + + nv_debug(parent, "detached %s context\n", subdev->name); + return nouveau_gpuobj_fini(&engctx->base, suspend); +} + +void +_nouveau_engctx_dtor(struct nouveau_object *object) +{ + nouveau_engctx_destroy(nv_engctx(object)); +} + +int +_nouveau_engctx_init(struct nouveau_object *object) +{ + return nouveau_engctx_init(nv_engctx(object)); +} + + +int +_nouveau_engctx_fini(struct nouveau_object *object, bool suspend) +{ + return nouveau_engctx_fini(nv_engctx(object), suspend); +} + +struct nouveau_object * +nouveau_engctx_lookup(struct nouveau_engine *engine, u64 addr) +{ + struct nouveau_engctx *engctx; + + list_for_each_entry(engctx, &engine->contexts, head) { + if (engctx->base.size && + nv_gpuobj(engctx)->addr == addr) + return nv_object(engctx); + } + + return NULL; +} + +struct nouveau_handle * +nouveau_engctx_lookup_class(struct nouveau_engine *engine, u64 addr, u16 oclass) +{ + struct nouveau_object *engctx = nouveau_engctx_lookup(engine, addr); + struct nouveau_namedb *namedb; + + if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) + return nouveau_namedb_get_class(namedb, oclass); + + return NULL; +} + +struct nouveau_handle * +nouveau_engctx_lookup_vinst(struct nouveau_engine *engine, u64 addr, u64 vinst) +{ + struct nouveau_object *engctx = nouveau_engctx_lookup(engine, addr); + struct nouveau_namedb *namedb; + + if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) + return nouveau_namedb_get_vinst(namedb, vinst); + + return NULL; +} + +struct nouveau_handle * +nouveau_engctx_lookup_cinst(struct nouveau_engine *engine, u64 addr, u32 cinst) +{ + struct nouveau_object *engctx = nouveau_engctx_lookup(engine, addr); + struct nouveau_namedb *namedb; + + if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) + return nouveau_namedb_get_cinst(namedb, cinst); + + return NULL; +} + +void +nouveau_engctx_handle_put(struct nouveau_handle *handle) +{ + if (handle) + nouveau_namedb_put(handle); +} diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c new file mode 100644 index 0000000..ee2905b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/engine.c @@ -0,0 +1,54 @@ +/* + * 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: + * + * 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 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 +#include +#include + +int +nouveau_engine_create_(struct nouveau_object *parent, + struct nouveau_object *engobj, + struct nouveau_oclass *oclass, bool enable, + const char *iname, const char *fname, + int length, void **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_engine *engine; + int ret; + + ret = nouveau_subdev_create_(parent, engobj, oclass, NV_ENGINE_CLASS, + iname, fname, length, pobject); + engine = *pobject; + if (ret) + return ret; + + if (!nouveau_boolopt(device->cfgopt, iname, enable)) { + if (!enable) + nv_warn(engine, "disabled, %s=1 to enable\n", iname); + return -ENODEV; + } + + INIT_LIST_HEAD(&engine->contexts); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/core/enum.c b/drivers/gpu/drm/nouveau/core/core/enum.c new file mode 100644 index 0000000..7cc7133 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/enum.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Nouveau Project + * + * All Rights Reserved. + * + * 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 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. + * + */ + +#include +#include + +const struct nouveau_enum * +nouveau_enum_find(const struct nouveau_enum *en, u32 value) +{ + while (en->name) { + if (en->value == value) + return en; + en++; + } + + return NULL; +} + +void +nouveau_enum_print(const struct nouveau_enum *en, u32 value) +{ + en = nouveau_enum_find(en, value); + if (en) + printk("%s", en->name); + else + printk("(unknown enum 0x%08x)", value); +} + +void +nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) +{ + while (bf->name) { + if (value & bf->mask) { + printk(" %s", bf->name); + value &= ~bf->mask; + } + + bf++; + } + + if (value) + printk(" (unknown bits 0x%08x)", value); +} diff --git a/drivers/gpu/drm/nouveau/core/core/gpuobj.c b/drivers/gpu/drm/nouveau/core/core/gpuobj.c new file mode 100644 index 0000000..715fd31 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/gpuobj.c @@ -0,0 +1,318 @@ +/* + * 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: + * + * 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 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 +#include + +#include +#include +#include + +void +nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj) +{ + int i; + + if (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE) { + for (i = 0; i < gpuobj->size; i += 4) + nv_wo32(gpuobj, i, 0x00000000); + } + + if (gpuobj->heap.block_size) + nouveau_mm_fini(&gpuobj->heap); + + nouveau_object_destroy(&gpuobj->base); +} + +int +nouveau_gpuobj_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, u32 pclass, + struct nouveau_object *pargpu, + u32 size, u32 align, u32 flags, + int length, void **pobject) +{ + struct nouveau_instmem *imem = nouveau_instmem(parent); + struct nouveau_bar *bar = nouveau_bar(parent); + struct nouveau_gpuobj *gpuobj; + struct nouveau_mm *heap = NULL; + int ret, i; + u64 addr; + + *pobject = NULL; + + if (pargpu) { + while ((pargpu = nv_pclass(pargpu, NV_GPUOBJ_CLASS))) { + if (nv_gpuobj(pargpu)->heap.block_size) + break; + pargpu = pargpu->parent; + } + + if (unlikely(pargpu == NULL)) { + nv_error(parent, "no gpuobj heap\n"); + return -EINVAL; + } + + addr = nv_gpuobj(pargpu)->addr; + heap = &nv_gpuobj(pargpu)->heap; + atomic_inc(&parent->refcount); + } else { + ret = imem->alloc(imem, parent, size, align, &parent); + pargpu = parent; + if (ret) + return ret; + + addr = nv_memobj(pargpu)->addr; + size = nv_memobj(pargpu)->size; + + if (bar && bar->alloc) { + struct nouveau_instobj *iobj = (void *)parent; + struct nouveau_mem **mem = (void *)(iobj + 1); + struct nouveau_mem *node = *mem; + if (!bar->alloc(bar, parent, node, &pargpu)) { + nouveau_object_ref(NULL, &parent); + parent = pargpu; + } + } + } + + ret = nouveau_object_create_(parent, engine, oclass, pclass | + NV_GPUOBJ_CLASS, length, pobject); + nouveau_object_ref(NULL, &parent); + gpuobj = *pobject; + if (ret) + return ret; + + gpuobj->parent = pargpu; + gpuobj->flags = flags; + gpuobj->addr = addr; + gpuobj->size = size; + + if (heap) { + ret = nouveau_mm_head(heap, 1, size, size, + max(align, (u32)1), &gpuobj->node); + if (ret) + return ret; + + gpuobj->addr += gpuobj->node->offset; + } + + if (gpuobj->flags & NVOBJ_FLAG_HEAP) { + ret = nouveau_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); + if (ret) + return ret; + } + + if (flags & NVOBJ_FLAG_ZERO_ALLOC) { + for (i = 0; i < gpuobj->size; i += 4) + nv_wo32(gpuobj, i, 0x00000000); + } + + return ret; +} + +struct nouveau_gpuobj_class { + struct nouveau_object *pargpu; + u64 size; + u32 align; + u32 flags; +}; + +int +_nouveau_gpuobj_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_gpuobj_class *args = data; + struct nouveau_gpuobj *object; + int ret; + + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, args->pargpu, + args->size, args->align, args->flags, + &object); + *pobject = nv_object(object); + if (ret) + return ret; + + return 0; +} + +void +_nouveau_gpuobj_dtor(struct nouveau_object *object) +{ + nouveau_gpuobj_destroy(nv_gpuobj(object)); +} + +int +_nouveau_gpuobj_init(struct nouveau_object *object) +{ + return nouveau_gpuobj_init(nv_gpuobj(object)); +} + +int +_nouveau_gpuobj_fini(struct nouveau_object *object, bool suspend) +{ + return nouveau_gpuobj_fini(nv_gpuobj(object), suspend); +} + +u32 +_nouveau_gpuobj_rd32(struct nouveau_object *object, u32 addr) +{ + struct nouveau_gpuobj *gpuobj = nv_gpuobj(object); + struct nouveau_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent); + if (gpuobj->node) + addr += gpuobj->node->offset; + return pfuncs->rd32(gpuobj->parent, addr); +} + +void +_nouveau_gpuobj_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nouveau_gpuobj *gpuobj = nv_gpuobj(object); + struct nouveau_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent); + if (gpuobj->node) + addr += gpuobj->node->offset; + pfuncs->wr32(gpuobj->parent, addr, data); +} + +static struct nouveau_oclass +_nouveau_gpuobj_oclass = { + .handle = 0x00000000, + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = _nouveau_gpuobj_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, + }, +}; + +int +nouveau_gpuobj_new(struct nouveau_object *parent, struct nouveau_object *pargpu, + u32 size, u32 align, u32 flags, + struct nouveau_gpuobj **pgpuobj) +{ + struct nouveau_object *engine = parent; + struct nouveau_gpuobj_class args = { + .pargpu = pargpu, + .size = size, + .align = align, + .flags = flags, + }; + + if (!nv_iclass(engine, NV_SUBDEV_CLASS)) + engine = engine->engine; + BUG_ON(engine == NULL); + + return nouveau_object_ctor(parent, engine, &_nouveau_gpuobj_oclass, + &args, sizeof(args), + (struct nouveau_object **)pgpuobj); +} + +int +nouveau_gpuobj_map(struct nouveau_gpuobj *gpuobj, u32 access, + struct nouveau_vma *vma) +{ + struct nouveau_bar *bar = nouveau_bar(gpuobj); + int ret = -EINVAL; + + if (bar && bar->umap) { + struct nouveau_instobj *iobj = (void *) + nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); + struct nouveau_mem **mem = (void *)(iobj + 1); + ret = bar->umap(bar, *mem, access, vma); + } + + return ret; +} + +int +nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, struct nouveau_vm *vm, + u32 access, struct nouveau_vma *vma) +{ + struct nouveau_instobj *iobj = (void *) + nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); + struct nouveau_mem **mem = (void *)(iobj + 1); + int ret; + + ret = nouveau_vm_get(vm, gpuobj->size, 12, access, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, *mem); + return 0; +} + +void +nouveau_gpuobj_unmap(struct nouveau_vma *vma) +{ + if (vma->node) { + nouveau_vm_unmap(vma); + nouveau_vm_put(vma); + } +} + +/* the below is basically only here to support sharing the paged dma object + * for PCI(E)GART on <=nv4x chipsets, and should *not* be expected to work + * anywhere else. + */ + +static void +nouveau_gpudup_dtor(struct nouveau_object *object) +{ + struct nouveau_gpuobj *gpuobj = (void *)object; + nouveau_object_ref(NULL, &gpuobj->parent); + nouveau_object_destroy(&gpuobj->base); +} + +static struct nouveau_oclass +nouveau_gpudup_oclass = { + .handle = NV_GPUOBJ_CLASS, + .ofuncs = &(struct nouveau_ofuncs) { + .dtor = nouveau_gpudup_dtor, + .init = nouveau_object_init, + .fini = nouveau_object_fini, + }, +}; + +int +nouveau_gpuobj_dup(struct nouveau_object *parent, struct nouveau_gpuobj *base, + struct nouveau_gpuobj **pgpuobj) +{ + struct nouveau_gpuobj *gpuobj; + int ret; + + ret = nouveau_object_create(parent, parent->engine, + &nouveau_gpudup_oclass, 0, &gpuobj); + *pgpuobj = gpuobj; + if (ret) + return ret; + + nouveau_object_ref(nv_object(base), &gpuobj->parent); + gpuobj->addr = base->addr; + gpuobj->size = base->size; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c new file mode 100644 index 0000000..f2ab2e8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/handle.c @@ -0,0 +1,189 @@ +/* + * 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: + * + * 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 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 +#include +#include + +#define hprintk(h,l,f,a...) do { \ + struct nouveau_client *c = nouveau_client((h)->object); \ + struct nouveau_handle *p = (h)->parent; u32 n = p ? p->name : ~0; \ + nv_printk((c), l, "0x%08x:0x%08x "f, n, (h)->name, ##a); \ +} while(0) + +int +nouveau_handle_init(struct nouveau_handle *handle) +{ + struct nouveau_handle *item; + int ret; + + hprintk(handle, TRACE, "init running\n"); + ret = nouveau_object_inc(handle->object); + if (ret) + return ret; + + hprintk(handle, TRACE, "init children\n"); + list_for_each_entry(item, &handle->tree, head) { + ret = nouveau_handle_init(item); + if (ret) + goto fail; + } + + hprintk(handle, TRACE, "init completed\n"); + return 0; +fail: + hprintk(handle, ERROR, "init failed with %d\n", ret); + list_for_each_entry_continue_reverse(item, &handle->tree, head) { + nouveau_handle_fini(item, false); + } + + nouveau_object_dec(handle->object, false); + return ret; +} + +int +nouveau_handle_fini(struct nouveau_handle *handle, bool suspend) +{ + static char *name[2] = { "fini", "suspend" }; + struct nouveau_handle *item; + int ret; + + hprintk(handle, TRACE, "%s children\n", name[suspend]); + list_for_each_entry(item, &handle->tree, head) { + ret = nouveau_handle_fini(item, suspend); + if (ret && suspend) + goto fail; + } + + hprintk(handle, TRACE, "%s running\n", name[suspend]); + if (handle->object) { + ret = nouveau_object_dec(handle->object, suspend); + if (ret && suspend) + goto fail; + } + + hprintk(handle, TRACE, "%s completed\n", name[suspend]); + return 0; +fail: + hprintk(handle, ERROR, "%s failed with %d\n", name[suspend], ret); + list_for_each_entry_continue_reverse(item, &handle->tree, head) { + int rret = nouveau_handle_init(item); + if (rret) + hprintk(handle, FATAL, "failed to restart, %d\n", rret); + } + + return ret; +} + +int +nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, + struct nouveau_object *object, + struct nouveau_handle **phandle) +{ + struct nouveau_object *namedb; + struct nouveau_handle *handle; + int ret; + + namedb = parent; + while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) + namedb = namedb->parent; + + handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + INIT_LIST_HEAD(&handle->head); + INIT_LIST_HEAD(&handle->tree); + handle->name = _handle; + handle->priv = ~0; + + ret = nouveau_namedb_insert(nv_namedb(namedb), _handle, object, handle); + if (ret) { + kfree(handle); + return ret; + } + + if (nv_parent(parent)->object_attach) { + ret = nv_parent(parent)->object_attach(parent, object, _handle); + if (ret < 0) { + nouveau_handle_destroy(handle); + return ret; + } + + handle->priv = ret; + } + + if (object != namedb) { + while (!nv_iclass(namedb, NV_CLIENT_CLASS)) + namedb = namedb->parent; + + handle->parent = nouveau_namedb_get(nv_namedb(namedb), _parent); + if (handle->parent) { + list_add(&handle->head, &handle->parent->tree); + nouveau_namedb_put(handle->parent); + } + } + + hprintk(handle, TRACE, "created\n"); + return 0; +} + +void +nouveau_handle_destroy(struct nouveau_handle *handle) +{ + struct nouveau_handle *item, *temp; + + hprintk(handle, TRACE, "destroy running\n"); + list_for_each_entry_safe(item, temp, &handle->tree, head) { + nouveau_handle_destroy(item); + } + list_del(&handle->head); + + if (handle->priv != ~0) { + struct nouveau_object *parent = handle->parent->object; + nv_parent(parent)->object_detach(parent, handle->priv); + } + + hprintk(handle, TRACE, "destroy completed\n"); + nouveau_namedb_remove(handle); + kfree(handle); +} + +struct nouveau_object * +nouveau_handle_ref(struct nouveau_object *parent, u32 name) +{ + struct nouveau_object *object = NULL; + struct nouveau_handle *handle; + + while (!nv_iclass(parent, NV_NAMEDB_CLASS)) + parent = parent->parent; + + handle = nouveau_namedb_get(nv_namedb(parent), name); + if (handle) { + nouveau_object_ref(handle->object, &object); + nouveau_namedb_put(handle); + } + + return object; +} diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index 024dd2c..bf8d4a5 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -22,8 +22,7 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include #include static inline void diff --git a/drivers/gpu/drm/nouveau/core/core/namedb.c b/drivers/gpu/drm/nouveau/core/core/namedb.c new file mode 100644 index 0000000..1ce95a8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/namedb.c @@ -0,0 +1,203 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include + +static struct nouveau_handle * +nouveau_namedb_lookup(struct nouveau_namedb *namedb, u32 name) +{ + struct nouveau_handle *handle; + + list_for_each_entry(handle, &namedb->list, node) { + if (handle->name == name) + return handle; + } + + return NULL; +} + +static struct nouveau_handle * +nouveau_namedb_lookup_class(struct nouveau_namedb *namedb, u16 oclass) +{ + struct nouveau_handle *handle; + + list_for_each_entry(handle, &namedb->list, node) { + if (nv_mclass(handle->object) == oclass) + return handle; + } + + return NULL; +} + +static struct nouveau_handle * +nouveau_namedb_lookup_vinst(struct nouveau_namedb *namedb, u64 vinst) +{ + struct nouveau_handle *handle; + + list_for_each_entry(handle, &namedb->list, node) { + if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { + if (nv_gpuobj(handle->object)->addr == vinst) + return handle; + } + } + + return NULL; +} + +static struct nouveau_handle * +nouveau_namedb_lookup_cinst(struct nouveau_namedb *namedb, u32 cinst) +{ + struct nouveau_handle *handle; + + list_for_each_entry(handle, &namedb->list, node) { + if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { + if (nv_gpuobj(handle->object)->node && + nv_gpuobj(handle->object)->node->offset == cinst) + return handle; + } + } + + return NULL; +} + +int +nouveau_namedb_insert(struct nouveau_namedb *namedb, u32 name, + struct nouveau_object *object, + struct nouveau_handle *handle) +{ + int ret = -EEXIST; + write_lock_irq(&namedb->lock); + if (!nouveau_namedb_lookup(namedb, name)) { + nouveau_object_ref(object, &handle->object); + handle->namedb = namedb; + list_add(&handle->node, &namedb->list); + ret = 0; + } + write_unlock_irq(&namedb->lock); + return ret; +} + +void +nouveau_namedb_remove(struct nouveau_handle *handle) +{ + struct nouveau_namedb *namedb = handle->namedb; + struct nouveau_object *object = handle->object; + write_lock_irq(&namedb->lock); + list_del(&handle->node); + write_unlock_irq(&namedb->lock); + nouveau_object_ref(NULL, &object); +} + +struct nouveau_handle * +nouveau_namedb_get(struct nouveau_namedb *namedb, u32 name) +{ + struct nouveau_handle *handle; + read_lock(&namedb->lock); + handle = nouveau_namedb_lookup(namedb, name); + if (handle == NULL) + read_unlock(&namedb->lock); + return handle; +} + +struct nouveau_handle * +nouveau_namedb_get_class(struct nouveau_namedb *namedb, u16 oclass) +{ + struct nouveau_handle *handle; + read_lock(&namedb->lock); + handle = nouveau_namedb_lookup_class(namedb, oclass); + if (handle == NULL) + read_unlock(&namedb->lock); + return handle; +} + +struct nouveau_handle * +nouveau_namedb_get_vinst(struct nouveau_namedb *namedb, u64 vinst) +{ + struct nouveau_handle *handle; + read_lock(&namedb->lock); + handle = nouveau_namedb_lookup_vinst(namedb, vinst); + if (handle == NULL) + read_unlock(&namedb->lock); + return handle; +} + +struct nouveau_handle * +nouveau_namedb_get_cinst(struct nouveau_namedb *namedb, u32 cinst) +{ + struct nouveau_handle *handle; + read_lock(&namedb->lock); + handle = nouveau_namedb_lookup_cinst(namedb, cinst); + if (handle == NULL) + read_unlock(&namedb->lock); + return handle; +} + +void +nouveau_namedb_put(struct nouveau_handle *handle) +{ + if (handle) + read_unlock(&handle->namedb->lock); +} + +int +nouveau_namedb_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, u32 pclass, + struct nouveau_oclass *sclass, u32 engcls, + int length, void **pobject) +{ + struct nouveau_namedb *namedb; + int ret; + + ret = nouveau_parent_create_(parent, engine, oclass, pclass | + NV_NAMEDB_CLASS, sclass, engcls, + length, pobject); + namedb = *pobject; + if (ret) + return ret; + + rwlock_init(&namedb->lock); + INIT_LIST_HEAD(&namedb->list); + return 0; +} + +int +_nouveau_namedb_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_namedb *object; + int ret; + + ret = nouveau_namedb_create(parent, engine, oclass, 0, NULL, 0, &object); + *pobject = nv_object(object); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c new file mode 100644 index 0000000..f37598e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/object.c @@ -0,0 +1,468 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include +#include + +#ifdef NOUVEAU_OBJECT_MAGIC +static struct list_head _objlist = LIST_HEAD_INIT(_objlist); +static DEFINE_SPINLOCK(_objlist_lock); +#endif + +int +nouveau_object_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, u32 pclass, + int size, void **pobject) +{ + struct nouveau_object *object; + + object = *pobject = kzalloc(size, GFP_KERNEL); + if (!object) + return -ENOMEM; + + nouveau_object_ref(parent, &object->parent); + nouveau_object_ref(engine, &object->engine); + object->oclass = oclass; + object->oclass->handle |= pclass; + atomic_set(&object->refcount, 1); + atomic_set(&object->usecount, 0); + +#ifdef NOUVEAU_OBJECT_MAGIC + object->_magic = NOUVEAU_OBJECT_MAGIC; + spin_lock(&_objlist_lock); + list_add(&object->list, &_objlist); + spin_unlock(&_objlist_lock); +#endif + return 0; +} + +int +_nouveau_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_object *object; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &object); + *pobject = nv_object(object); + if (ret) + return ret; + + return 0; +} + +void +nouveau_object_destroy(struct nouveau_object *object) +{ +#ifdef NOUVEAU_OBJECT_MAGIC + spin_lock(&_objlist_lock); + list_del(&object->list); + spin_unlock(&_objlist_lock); +#endif + nouveau_object_ref(NULL, &object->engine); + nouveau_object_ref(NULL, &object->parent); + kfree(object); +} + +void +_nouveau_object_dtor(struct nouveau_object *object) +{ + nouveau_object_destroy(object); +} + +int +nouveau_object_init(struct nouveau_object *object) +{ + return 0; +} + +int +_nouveau_object_init(struct nouveau_object *object) +{ + return nouveau_object_init(object); +} + +int +nouveau_object_fini(struct nouveau_object *object, bool suspend) +{ + return 0; +} + +int +_nouveau_object_fini(struct nouveau_object *object, bool suspend) +{ + return nouveau_object_fini(object, suspend); +} + +struct nouveau_ofuncs +nouveau_object_ofuncs = { + .ctor = _nouveau_object_ctor, + .dtor = _nouveau_object_dtor, + .init = _nouveau_object_init, + .fini = _nouveau_object_fini, +}; + +int +nouveau_object_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_ofuncs *ofuncs = oclass->ofuncs; + int ret; + + *pobject = NULL; + + ret = ofuncs->ctor(parent, engine, oclass, data, size, pobject); + if (ret < 0) { + if (ret != -ENODEV) { + nv_error(parent, "failed to create 0x%08x, %d\n", + oclass->handle, ret); + } + + if (*pobject) { + ofuncs->dtor(*pobject); + *pobject = NULL; + } + + return ret; + } + + nv_debug(*pobject, "created\n"); + return 0; +} + +static void +nouveau_object_dtor(struct nouveau_object *object) +{ + nv_debug(object, "destroying\n"); + nv_ofuncs(object)->dtor(object); +} + +void +nouveau_object_ref(struct nouveau_object *obj, struct nouveau_object **ref) +{ + if (obj) { + atomic_inc(&obj->refcount); + nv_trace(obj, "inc() == %d\n", atomic_read(&obj->refcount)); + } + + if (*ref) { + int dead = atomic_dec_and_test(&(*ref)->refcount); + nv_trace(*ref, "dec() == %d\n", atomic_read(&(*ref)->refcount)); + if (dead) + nouveau_object_dtor(*ref); + } + + *ref = obj; +} + +int +nouveau_object_new(struct nouveau_object *client, u32 _parent, u32 _handle, + u16 _oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_object *parent = NULL; + struct nouveau_object *engctx = NULL; + struct nouveau_object *object = NULL; + struct nouveau_object *engine; + struct nouveau_oclass *oclass; + struct nouveau_handle *handle; + int ret; + + /* lookup parent object and ensure it *is* a parent */ + parent = nouveau_handle_ref(client, _parent); + if (!parent) { + nv_error(client, "parent 0x%08x not found\n", _parent); + return -ENOENT; + } + + if (!nv_iclass(parent, NV_PARENT_CLASS)) { + nv_error(parent, "cannot have children\n"); + ret = -EINVAL; + goto fail_class; + } + + /* check that parent supports the requested subclass */ + ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass); + if (ret) { + nv_debug(parent, "illegal class 0x%04x\n", _oclass); + goto fail_class; + } + + /* make sure engine init has been completed *before* any objects + * it controls are created - the constructors may depend on + * state calculated at init (ie. default context construction) + */ + if (engine) { + ret = nouveau_object_inc(engine); + if (ret) + goto fail_class; + } + + /* if engine requires it, create a context object to insert + * between the parent and its children (eg. PGRAPH context) + */ + if (engine && nv_engine(engine)->cclass) { + ret = nouveau_object_ctor(parent, engine, + nv_engine(engine)->cclass, + data, size, &engctx); + if (ret) + goto fail_engctx; + } else { + nouveau_object_ref(parent, &engctx); + } + + /* finally, create new object and bind it to its handle */ + ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object); + *pobject = object; + if (ret) + goto fail_ctor; + + ret = nouveau_object_inc(object); + if (ret) + goto fail_init; + + ret = nouveau_handle_create(parent, _parent, _handle, object, &handle); + if (ret) + goto fail_handle; + + ret = nouveau_handle_init(handle); + if (ret) + nouveau_handle_destroy(handle); + +fail_handle: + nouveau_object_dec(object, false); +fail_init: + nouveau_object_ref(NULL, &object); +fail_ctor: + nouveau_object_ref(NULL, &engctx); +fail_engctx: + if (engine) + nouveau_object_dec(engine, false); +fail_class: + nouveau_object_ref(NULL, &parent); + return ret; +} + +int +nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) +{ + struct nouveau_object *parent = NULL; + struct nouveau_object *namedb = NULL; + struct nouveau_handle *handle = NULL; + int ret = -EINVAL; + + parent = nouveau_handle_ref(client, _parent); + if (!parent) + return -ENOENT; + + namedb = nv_pclass(parent, NV_NAMEDB_CLASS); + if (namedb) { + handle = nouveau_namedb_get(nv_namedb(namedb), _handle); + if (handle) { + nouveau_namedb_put(handle); + nouveau_handle_fini(handle, false); + nouveau_handle_destroy(handle); + } + } + + nouveau_object_ref(NULL, &parent); + return ret; +} + +int +nouveau_object_inc(struct nouveau_object *object) +{ + int ref = atomic_add_return(1, &object->usecount); + int ret; + + nv_trace(object, "use(+1) == %d\n", atomic_read(&object->usecount)); + if (ref != 1) + return 0; + + nv_trace(object, "initialising...\n"); + if (object->parent) { + ret = nouveau_object_inc(object->parent); + if (ret) { + nv_error(object, "parent failed, %d\n", ret); + goto fail_parent; + } + } + + if (object->engine) { + mutex_lock(&nv_subdev(object->engine)->mutex); + ret = nouveau_object_inc(object->engine); + mutex_unlock(&nv_subdev(object->engine)->mutex); + if (ret) { + nv_error(object, "engine failed, %d\n", ret); + goto fail_engine; + } + } + + ret = nv_ofuncs(object)->init(object); + if (ret) { + nv_error(object, "init failed, %d\n", ret); + goto fail_self; + } + + nv_debug(object, "initialised\n"); + return 0; + +fail_self: + if (object->engine) { + mutex_lock(&nv_subdev(object->engine)->mutex); + nouveau_object_dec(object->engine, false); + mutex_unlock(&nv_subdev(object->engine)->mutex); + } +fail_engine: + if (object->parent) + nouveau_object_dec(object->parent, false); +fail_parent: + atomic_dec(&object->usecount); + return ret; +} + +static int +nouveau_object_decf(struct nouveau_object *object) +{ + int ret; + + nv_trace(object, "stopping...\n"); + + ret = nv_ofuncs(object)->fini(object, false); + if (ret) + nv_warn(object, "failed fini, %d\n", ret); + + if (object->engine) { + mutex_lock(&nv_subdev(object->engine)->mutex); + nouveau_object_dec(object->engine, false); + mutex_unlock(&nv_subdev(object->engine)->mutex); + } + + if (object->parent) + nouveau_object_dec(object->parent, false); + + nv_debug(object, "stopped\n"); + return 0; +} + +static int +nouveau_object_decs(struct nouveau_object *object) +{ + int ret, rret; + + nv_trace(object, "suspending...\n"); + + ret = nv_ofuncs(object)->fini(object, true); + if (ret) { + nv_error(object, "failed suspend, %d\n", ret); + return ret; + } + + if (object->engine) { + mutex_lock(&nv_subdev(object->engine)->mutex); + ret = nouveau_object_dec(object->engine, true); + mutex_unlock(&nv_subdev(object->engine)->mutex); + if (ret) { + nv_warn(object, "engine failed suspend, %d\n", ret); + goto fail_engine; + } + } + + if (object->parent) { + ret = nouveau_object_dec(object->parent, true); + if (ret) { + nv_warn(object, "parent failed suspend, %d\n", ret); + goto fail_parent; + } + } + + nv_debug(object, "suspended\n"); + return 0; + +fail_parent: + if (object->engine) { + mutex_lock(&nv_subdev(object->engine)->mutex); + rret = nouveau_object_inc(object->engine); + mutex_unlock(&nv_subdev(object->engine)->mutex); + if (rret) + nv_fatal(object, "engine failed to reinit, %d\n", rret); + } + +fail_engine: + rret = nv_ofuncs(object)->init(object); + if (rret) + nv_fatal(object, "failed to reinit, %d\n", rret); + + return ret; +} + +int +nouveau_object_dec(struct nouveau_object *object, bool suspend) +{ + int ref = atomic_add_return(-1, &object->usecount); + int ret; + + nv_trace(object, "use(-1) == %d\n", atomic_read(&object->usecount)); + + if (ref == 0) { + if (suspend) + ret = nouveau_object_decs(object); + else + ret = nouveau_object_decf(object); + + if (ret) { + atomic_inc(&object->usecount); + return ret; + } + } + + return 0; +} + +void +nouveau_object_debug(void) +{ +#ifdef NOUVEAU_OBJECT_MAGIC + struct nouveau_object *object; + if (!list_empty(&_objlist)) { + nv_fatal(NULL, "*******************************************\n"); + nv_fatal(NULL, "* AIIIII! object(s) still exist!!!\n"); + nv_fatal(NULL, "*******************************************\n"); + list_for_each_entry(object, &_objlist, list) { + nv_fatal(object, "%p/%p/%d/%d\n", + object->parent, object->engine, + atomic_read(&object->refcount), + atomic_read(&object->usecount)); + } + } +#endif +} diff --git a/drivers/gpu/drm/nouveau/core/core/option.c b/drivers/gpu/drm/nouveau/core/core/option.c new file mode 100644 index 0000000..1b53ebb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/option.c @@ -0,0 +1,131 @@ +/* + * 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: + * + * 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 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 +#include + +/* compares unterminated string 'str' with zero-terminated string 'cmp' */ +static inline int +strncasecmpz(const char *str, const char *cmp, size_t len) +{ + if (strlen(cmp) != len) + return len; + return strncasecmp(str, cmp, len); +} + +const char * +nouveau_stropt(const char *optstr, const char *opt, int *arglen) +{ + while (optstr && *optstr != '\0') { + int len = strcspn(optstr, ",="); + switch (optstr[len]) { + case '=': + if (!strncasecmpz(optstr, opt, len)) { + optstr += len + 1; + *arglen = strcspn(optstr, ",="); + return *arglen ? optstr : NULL; + } + optstr++; + break; + case ',': + optstr++; + break; + default: + break; + } + optstr += len; + } + + return NULL; +} + +bool +nouveau_boolopt(const char *optstr, const char *opt, bool value) +{ + int arglen; + + optstr = nouveau_stropt(optstr, opt, &arglen); + if (optstr) { + if (!strncasecmpz(optstr, "0", arglen) || + !strncasecmpz(optstr, "no", arglen) || + !strncasecmpz(optstr, "off", arglen) || + !strncasecmpz(optstr, "false", arglen)) + value = false; + else + if (!strncasecmpz(optstr, "1", arglen) || + !strncasecmpz(optstr, "yes", arglen) || + !strncasecmpz(optstr, "on", arglen) || + !strncasecmpz(optstr, "true", arglen)) + value = true; + } + + return value; +} + +int +nouveau_dbgopt(const char *optstr, const char *sub) +{ + int mode = 1, level = CONFIG_NOUVEAU_DEBUG_DEFAULT; + + while (optstr) { + int len = strcspn(optstr, ",="); + switch (optstr[len]) { + case '=': + if (strncasecmpz(optstr, sub, len)) + mode = 0; + optstr++; + break; + default: + if (mode) { + if (!strncasecmpz(optstr, "fatal", len)) + level = NV_DBG_FATAL; + else if (!strncasecmpz(optstr, "error", len)) + level = NV_DBG_ERROR; + else if (!strncasecmpz(optstr, "warn", len)) + level = NV_DBG_WARN; + else if (!strncasecmpz(optstr, "info", len)) + level = NV_DBG_INFO; + else if (!strncasecmpz(optstr, "debug", len)) + level = NV_DBG_DEBUG; + else if (!strncasecmpz(optstr, "trace", len)) + level = NV_DBG_TRACE; + else if (!strncasecmpz(optstr, "paranoia", len)) + level = NV_DBG_PARANOIA; + else if (!strncasecmpz(optstr, "spam", len)) + level = NV_DBG_SPAM; + } + + if (optstr[len] != '\0') { + optstr++; + mode = 1; + break; + } + + return level; + } + optstr += len; + } + + return level; +} diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c new file mode 100644 index 0000000..a1ea034 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/parent.c @@ -0,0 +1,139 @@ +/* + * 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: + * + * 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 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 +#include + +int +nouveau_parent_sclass(struct nouveau_object *parent, u16 handle, + struct nouveau_object **pengine, + struct nouveau_oclass **poclass) +{ + struct nouveau_sclass *sclass; + struct nouveau_engine *engine; + struct nouveau_oclass *oclass; + u64 mask; + + sclass = nv_parent(parent)->sclass; + while (sclass) { + if ((sclass->oclass->handle & 0xffff) == handle) { + *pengine = parent->engine; + *poclass = sclass->oclass; + return 0; + } + + sclass = sclass->sclass; + } + + mask = nv_parent(parent)->engine; + while (mask) { + int i = ffsll(mask) - 1; + + if ((engine = nouveau_engine(parent, i))) { + oclass = engine->sclass; + while (oclass->ofuncs) { + if ((oclass->handle & 0xffff) == handle) { + *pengine = nv_object(engine); + *poclass = oclass; + return 0; + } + oclass++; + } + } + + mask &= ~(1ULL << i); + } + + return -EINVAL; +} + +int +nouveau_parent_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, u32 pclass, + struct nouveau_oclass *sclass, u64 engcls, + int size, void **pobject) +{ + struct nouveau_parent *object; + struct nouveau_sclass *nclass; + int ret; + + ret = nouveau_object_create_(parent, engine, oclass, pclass | + NV_PARENT_CLASS, size, pobject); + object = *pobject; + if (ret) + return ret; + + while (sclass && sclass->ofuncs) { + nclass = kzalloc(sizeof(*nclass), GFP_KERNEL); + if (!nclass) + return -ENOMEM; + + nclass->sclass = object->sclass; + object->sclass = nclass; + nclass->engine = engine ? nv_engine(engine) : NULL; + nclass->oclass = sclass; + sclass++; + } + + object->engine = engcls; + return 0; +} + +int +_nouveau_parent_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_parent *object; + int ret; + + ret = nouveau_parent_create(parent, engine, oclass, 0, NULL, 0, &object); + *pobject = nv_object(object); + if (ret) + return ret; + + return 0; +} + +void +nouveau_parent_destroy(struct nouveau_parent *parent) +{ + struct nouveau_sclass *sclass; + + while ((sclass = parent->sclass)) { + parent->sclass = sclass->sclass; + kfree(sclass); + } + + nouveau_object_destroy(&parent->base); +} + + +void +_nouveau_parent_dtor(struct nouveau_object *object) +{ + nouveau_parent_destroy(nv_parent(object)); +} diff --git a/drivers/gpu/drm/nouveau/core/core/printk.c b/drivers/gpu/drm/nouveau/core/core/printk.c new file mode 100644 index 0000000..134dd6d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/printk.c @@ -0,0 +1,74 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include + +void +nv_printk_(struct nouveau_object *object, const char *pfx, int level, + const char *fmt, ...) +{ + static const char name[] = { '!', 'E', 'W', ' ', 'D', 'T', 'P', 'S' }; + char mfmt[256]; + va_list args; + + if (object && !nv_iclass(object, NV_CLIENT_CLASS)) { + struct nouveau_object *device = object; + struct nouveau_object *subdev = object; + char obuf[64], *ofmt = ""; + + if (object->engine) { + snprintf(obuf, sizeof(obuf), "[0x%08x][%p]", + nv_hclass(object), object); + ofmt = obuf; + subdev = object->engine; + device = object->engine; + } + + if (subdev->parent) + device = subdev->parent; + + if (level > nv_subdev(subdev)->debug) + return; + + snprintf(mfmt, sizeof(mfmt), "%snouveau %c[%8s][%s]%s %s", pfx, + name[level], nv_subdev(subdev)->name, + nv_device(device)->name, ofmt, fmt); + } else + if (object && nv_iclass(object, NV_CLIENT_CLASS)) { + if (level > nv_client(object)->debug) + return; + + snprintf(mfmt, sizeof(mfmt), "%snouveau %c[%8d] %s", pfx, + name[level], nv_client(object)->handle, fmt); + } else { + snprintf(mfmt, sizeof(mfmt), "%snouveau: %s", pfx, fmt); + } + + va_start(args, fmt); + vprintk(mfmt, args); + va_end(args); +} diff --git a/drivers/gpu/drm/nouveau/core/core/subdev.c b/drivers/gpu/drm/nouveau/core/core/subdev.c new file mode 100644 index 0000000..f74c30a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/core/subdev.c @@ -0,0 +1,115 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include + +void +nouveau_subdev_reset(struct nouveau_object *subdev) +{ + nv_trace(subdev, "resetting...\n"); + nv_ofuncs(subdev)->fini(subdev, false); + nv_debug(subdev, "reset\n"); +} + +int +nouveau_subdev_init(struct nouveau_subdev *subdev) +{ + int ret = nouveau_object_init(&subdev->base); + if (ret) + return ret; + + nouveau_subdev_reset(&subdev->base); + return 0; +} + +int +_nouveau_subdev_init(struct nouveau_object *object) +{ + return nouveau_subdev_init(nv_subdev(object)); +} + +int +nouveau_subdev_fini(struct nouveau_subdev *subdev, bool suspend) +{ + if (subdev->unit) { + nv_mask(subdev, 0x000200, subdev->unit, 0x00000000); + nv_mask(subdev, 0x000200, subdev->unit, subdev->unit); + } + + return nouveau_object_fini(&subdev->base, suspend); +} + +int +_nouveau_subdev_fini(struct nouveau_object *object, bool suspend) +{ + return nouveau_subdev_fini(nv_subdev(object), suspend); +} + +void +nouveau_subdev_destroy(struct nouveau_subdev *subdev) +{ + int subidx = nv_hclass(subdev) & 0xff; + nv_device(subdev)->subdev[subidx] = NULL; + nouveau_object_destroy(&subdev->base); +} + +void +_nouveau_subdev_dtor(struct nouveau_object *object) +{ + nouveau_subdev_destroy(nv_subdev(object)); +} + +int +nouveau_subdev_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, u32 pclass, + const char *subname, const char *sysname, + int size, void **pobject) +{ + struct nouveau_subdev *subdev; + int ret; + + ret = nouveau_object_create_(parent, engine, oclass, pclass | + NV_SUBDEV_CLASS, size, pobject); + subdev = *pobject; + if (ret) + return ret; + + mutex_init(&subdev->mutex); + subdev->name = subname; + + if (parent) { + struct nouveau_device *device = nv_device(parent); + int subidx = nv_hclass(subdev) & 0xff; + + subdev->debug = nouveau_dbgopt(device->dbgopt, subname); + subdev->mmio = nv_subdev(device)->mmio; + device->subdev[subidx] = *pobject; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h new file mode 100644 index 0000000..17326dd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -0,0 +1,77 @@ +#ifndef __NOUVEAU_CLASS_H__ +#define __NOUVEAU_CLASS_H__ + +/* 0080: NV_DEVICE + */ + +#define NV_DEVICE_DISABLE_IDENTIFY 0x0000000000000001ULL +#define NV_DEVICE_DISABLE_MMIO 0x0000000000000002ULL +#define NV_DEVICE_DISABLE_VBIOS 0x0000000000000004ULL +#define NV_DEVICE_DISABLE_CORE 0x0000000000000008ULL +#define NV_DEVICE_DISABLE_DISP 0x0000000000010000ULL +#define NV_DEVICE_DISABLE_FIFO 0x0000000000020000ULL +#define NV_DEVICE_DISABLE_GRAPH 0x0000000100000000ULL +#define NV_DEVICE_DISABLE_MPEG 0x0000000200000000ULL +#define NV_DEVICE_DISABLE_ME 0x0000000400000000ULL +#define NV_DEVICE_DISABLE_VP 0x0000000800000000ULL +#define NV_DEVICE_DISABLE_CRYPT 0x0000001000000000ULL +#define NV_DEVICE_DISABLE_BSP 0x0000002000000000ULL +#define NV_DEVICE_DISABLE_PPP 0x0000004000000000ULL +#define NV_DEVICE_DISABLE_COPY0 0x0000008000000000ULL +#define NV_DEVICE_DISABLE_COPY1 0x0000010000000000ULL +#define NV_DEVICE_DISABLE_UNK1C1 0x0000020000000000ULL + +struct nv_device_class { + u64 device; /* device identifier, ~0 for client default */ + u64 disable; /* disable particular subsystems */ + u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */ +}; + +/* 0002: NV_DMA_FROM_MEMORY + * 0003: NV_DMA_TO_MEMORY + * 003d: NV_DMA_IN_MEMORY + */ + +#define NV_DMA_TARGET_MASK 0x000000ff +#define NV_DMA_TARGET_VM 0x00000000 +#define NV_DMA_TARGET_VRAM 0x00000001 +#define NV_DMA_TARGET_PCI 0x00000002 +#define NV_DMA_TARGET_PCI_US 0x00000003 +#define NV_DMA_TARGET_AGP 0x00000004 +#define NV_DMA_ACCESS_MASK 0x00000f00 +#define NV_DMA_ACCESS_VM 0x00000000 +#define NV_DMA_ACCESS_RD 0x00000100 +#define NV_DMA_ACCESS_WR 0x00000200 +#define NV_DMA_ACCESS_RDWR 0x00000300 + +struct nv_dma_class { + u32 flags; + u32 pad0; + u64 start; + u64 limit; +}; + +/* 006b: NV03_CHANNEL_DMA + * 006e: NV10_CHANNEL_DMA + * 406e: NV40_CHANNEL_DMA + */ + +struct nv_channel_dma_class { + u32 pushbuf; + u32 pad0; + u64 offset; +}; + +/* 506f: NV50_CHANNEL_IND + * 826f: NV84_CHANNEL_IND + * 906f: NVC0_CHANNEL_IND + * a06f: NVE0_CHANNEL_IND + */ + +struct nv_channel_ind_class { + u32 pushbuf; + u32 ilength; + u64 ioffset; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h new file mode 100644 index 0000000..f5f45f2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h @@ -0,0 +1,42 @@ +#ifndef __NOUVEAU_CLIENT_H__ +#define __NOUVEAU_CLIENT_H__ + +#include + +struct nouveau_client { + struct nouveau_namedb base; + struct nouveau_handle *root; + struct nouveau_object *device; + u32 handle; + u32 debug; + struct nouveau_vm *vm; +}; + +static inline struct nouveau_client * +nv_client(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_CLIENT_CLASS))) + nv_assert("BAD CAST -> NvClient, %08x", nv_hclass(obj)); +#endif + return obj; +} + +static inline struct nouveau_client * +nouveau_client(void *obj) +{ + struct nouveau_object *client = nv_object(obj); + while (client && !(nv_iclass(client, NV_CLIENT_CLASS))) + client = client->parent; + return (void *)client; +} + +#define nouveau_client_create(n,c,oc,od,d) \ + nouveau_client_create_((n), (c), (oc), (od), sizeof(**d), (void **)d) + +int nouveau_client_create_(u32 name, u64 device, const char *cfg, + const char *dbg, int, void **); +int nouveau_client_init(struct nouveau_client *); +int nouveau_client_fini(struct nouveau_client *, bool suspend); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/debug.h b/drivers/gpu/drm/nouveau/core/include/core/debug.h new file mode 100644 index 0000000..9ea18df --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/debug.h @@ -0,0 +1,13 @@ +#ifndef __NOUVEAU_DEBUG_H__ +#define __NOUVEAU_DEBUG_H__ + +#define NV_DBG_FATAL 0 +#define NV_DBG_ERROR 1 +#define NV_DBG_WARN 2 +#define NV_DBG_INFO 3 +#define NV_DBG_DEBUG 4 +#define NV_DBG_TRACE 5 +#define NV_DBG_PARANOIA 6 +#define NV_DBG_SPAM 7 + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h new file mode 100644 index 0000000..4db7b01 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -0,0 +1,122 @@ +#ifndef __NOUVEAU_DEVICE_H__ +#define __NOUVEAU_DEVICE_H__ + +#include +#include +#include + +enum nv_subdev_type { + NVDEV_SUBDEV_DEVICE, + NVDEV_SUBDEV_VBIOS, + NVDEV_SUBDEV_GPIO, + NVDEV_SUBDEV_I2C, + NVDEV_SUBDEV_CLOCK, + NVDEV_SUBDEV_MXM, + NVDEV_SUBDEV_DEVINIT, + NVDEV_SUBDEV_MC, + NVDEV_SUBDEV_TIMER, + NVDEV_SUBDEV_FB, + NVDEV_SUBDEV_LTCG, + NVDEV_SUBDEV_INSTMEM, + NVDEV_SUBDEV_VM, + NVDEV_SUBDEV_BAR, + NVDEV_SUBDEV_VOLT, + NVDEV_SUBDEV_FAN0, + NVDEV_SUBDEV_THERM, + NVDEV_ENGINE_DMAOBJ, + NVDEV_ENGINE_FIFO, + NVDEV_ENGINE_SW, + NVDEV_ENGINE_GR, + NVDEV_ENGINE_MPEG, + NVDEV_ENGINE_ME, + NVDEV_ENGINE_VP, + NVDEV_ENGINE_CRYPT, + NVDEV_ENGINE_BSP, + NVDEV_ENGINE_PPP, + NVDEV_ENGINE_COPY0, + NVDEV_ENGINE_COPY1, + NVDEV_ENGINE_UNK1C1, + NVDEV_ENGINE_FENCE, + NVDEV_ENGINE_DISP, + NVDEV_SUBDEV_NR, +}; + +struct nouveau_device { + struct nouveau_subdev base; + struct list_head head; + + struct pci_dev *pdev; + u64 handle; + + const char *cfgopt; + const char *dbgopt; + const char *name; + const char *cname; + + enum { + NV_04 = 0x04, + NV_10 = 0x10, + NV_20 = 0x20, + NV_30 = 0x30, + NV_40 = 0x40, + NV_50 = 0x50, + NV_C0 = 0xc0, + NV_D0 = 0xd0, + NV_E0 = 0xe0, + } card_type; + u32 chipset; + u32 crystal; + + struct nouveau_oclass *oclass[NVDEV_SUBDEV_NR]; + struct nouveau_object *subdev[NVDEV_SUBDEV_NR]; +}; + +static inline struct nouveau_device * +nv_device(void *obj) +{ + struct nouveau_object *object = nv_object(obj); + struct nouveau_object *device = object; + + if (device->engine) + device = device->engine; + if (device->parent) + device = device->parent; + +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(device, NV_SUBDEV_CLASS) || + (nv_hclass(device) & 0xff) != NVDEV_SUBDEV_DEVICE)) { + nv_assert("BAD CAST -> NvDevice, 0x%08x 0x%08x", + nv_hclass(object), nv_hclass(device)); + } +#endif + + return (void *)device; +} + +static inline struct nouveau_subdev * +nouveau_subdev(void *obj, int sub) +{ + if (nv_device(obj)->subdev[sub]) + return nv_subdev(nv_device(obj)->subdev[sub]); + return NULL; +} + +static inline struct nouveau_engine * +nouveau_engine(void *obj, int sub) +{ + struct nouveau_subdev *subdev = nouveau_subdev(obj, sub); + if (subdev && nv_iclass(subdev, NV_ENGINE_CLASS)) + return nv_engine(subdev); + return NULL; +} + +static inline bool +nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub) +{ + struct nouveau_device *device = nv_device(object); + return device->pdev->device == dev && + device->pdev->subsystem_vendor == ven && + device->pdev->subsystem_device == sub; +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/engctx.h b/drivers/gpu/drm/nouveau/core/include/core/engctx.h new file mode 100644 index 0000000..cbc9eb3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/engctx.h @@ -0,0 +1,61 @@ +#ifndef __NOUVEAU_ENGCTX_H__ +#define __NOUVEAU_ENGCTX_H__ + +#include +#include + +#include + +#define NV_ENGCTX_(eng,var) (NV_ENGCTX_CLASS | ((var) << 8) | (eng)) +#define NV_ENGCTX(name,var) NV_ENGCTX_(NVDEV_ENGINE_##name, (var)) + +struct nouveau_engctx { + struct nouveau_gpuobj base; + struct nouveau_vma vma; + struct list_head head; +}; + +static inline void * +nv_engctx(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_ENGCTX_CLASS))) + nv_assert("BAD CAST -> NvEngCtx, %08x", nv_hclass(obj)); +#endif + return obj; +} + +#define nouveau_engctx_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create_((p), (e), (c), (g), (s), (a), (f), \ + sizeof(**d), (void **)d) + +int nouveau_engctx_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, struct nouveau_object *, + u32 size, u32 align, u32 flags, + int length, void **data); +void nouveau_engctx_destroy(struct nouveau_engctx *); +int nouveau_engctx_init(struct nouveau_engctx *); +int nouveau_engctx_fini(struct nouveau_engctx *, bool suspend); + +void _nouveau_engctx_dtor(struct nouveau_object *); +int _nouveau_engctx_init(struct nouveau_object *); +int _nouveau_engctx_fini(struct nouveau_object *, bool suspend); +#define _nouveau_engctx_rd32 _nouveau_gpuobj_rd32 +#define _nouveau_engctx_wr32 _nouveau_gpuobj_wr32 + +struct nouveau_object * +nouveau_engctx_lookup(struct nouveau_engine *, u64 addr); + +struct nouveau_handle * +nouveau_engctx_lookup_class(struct nouveau_engine *, u64, u16); + +struct nouveau_handle * +nouveau_engctx_lookup_vinst(struct nouveau_engine *, u64, u64); + +struct nouveau_handle * +nouveau_engctx_lookup_cinst(struct nouveau_engine *, u64, u32); + +void +nouveau_engctx_handle_put(struct nouveau_handle *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/engine.h b/drivers/gpu/drm/nouveau/core/include/core/engine.h new file mode 100644 index 0000000..1a7b0a7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/engine.h @@ -0,0 +1,54 @@ +#ifndef __NOUVEAU_ENGINE_H__ +#define __NOUVEAU_ENGINE_H__ + +#include +#include + +#define NV_ENGINE_(eng,var) (NV_ENGINE_CLASS | ((var) << 8) | (eng)) +#define NV_ENGINE(name,var) NV_ENGINE_(NVDEV_ENGINE_##name, (var)) + +struct nouveau_engine { + struct nouveau_subdev base; + struct nouveau_oclass *cclass; + struct nouveau_oclass *sclass; + struct list_head contexts; + void (*tile_prog)(struct nouveau_engine *, int region); + int (*tlb_flush)(struct nouveau_engine *); +}; + +static inline struct nouveau_engine * +nv_engine(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_ENGINE_CLASS))) + nv_assert("BAD CAST -> NvEngine, %08x", nv_hclass(obj)); +#endif + return obj; +} + +static inline int +nv_engidx(struct nouveau_object *object) +{ + return nv_subidx(object); +} + +#define nouveau_engine_create(p,e,c,d,i,f,r) \ + nouveau_engine_create_((p), (e), (c), (d), (i), (f), \ + sizeof(**r),(void **)r) + +#define nouveau_engine_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_engine_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_engine_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_engine_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, bool, const char *, + const char *, int, void **); + +#define _nouveau_engine_dtor _nouveau_subdev_dtor +#define _nouveau_engine_init _nouveau_subdev_init +#define _nouveau_engine_fini _nouveau_subdev_fini + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/enum.h b/drivers/gpu/drm/nouveau/core/include/core/enum.h new file mode 100644 index 0000000..62ec041 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/enum.h @@ -0,0 +1,23 @@ +#ifndef __NOUVEAU_ENUM_H__ +#define __NOUVEAU_ENUM_H__ + +struct nouveau_enum { + u32 value; + const char *name; + void *data; +}; + +const struct nouveau_enum * +nouveau_enum_find(const struct nouveau_enum *, u32 value); + +void +nouveau_enum_print(const struct nouveau_enum *en, u32 value); + +struct nouveau_bitfield { + u32 mask; + const char *name; +}; + +void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h b/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h new file mode 100644 index 0000000..7394a5e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h @@ -0,0 +1,82 @@ +#ifndef __NOUVEAU_GPUOBJ_H__ +#define __NOUVEAU_GPUOBJ_H__ + +#include +#ifndef XXX_THIS_IS_A_HACK +#include +#include +#include +#endif + +struct nouveau_vma; +struct nouveau_vm; + +#define NVOBJ_FLAG_ZERO_ALLOC 0x00000001 +#define NVOBJ_FLAG_ZERO_FREE 0x00000002 +#define NVOBJ_FLAG_HEAP 0x00000004 + +struct nouveau_gpuobj { + struct nouveau_object base; + struct nouveau_object *parent; + struct nouveau_mm_node *node; + struct nouveau_mm heap; + + u32 flags; + u64 addr; + u32 size; + + /*XXX*/ + struct drm_device *dev; + u32 engine; + u32 class; +}; + +#ifndef XXX_THIS_IS_A_HACK +static inline struct nouveau_gpuobj * +nv_gpuobj(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_GPUOBJ_CLASS))) + nv_assert("BAD CAST -> NvGpuObj, %08x", nv_hclass(obj)); +#endif + return obj; +} + +#define nouveau_gpuobj_create(p,e,c,v,g,s,a,f,d) \ + nouveau_gpuobj_create_((p), (e), (c), (v), (g), (s), (a), (f), \ + sizeof(**d), (void **)d) +#define nouveau_gpuobj_init(p) nouveau_object_init(&(p)->base) +#define nouveau_gpuobj_fini(p,s) nouveau_object_fini(&(p)->base, (s)) +int nouveau_gpuobj_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, u32 pclass, + struct nouveau_object *, u32 size, u32 align, + u32 flags, int length, void **); +void nouveau_gpuobj_destroy(struct nouveau_gpuobj *); + +int nouveau_gpuobj_new(struct nouveau_object *, struct nouveau_object *, + u32 size, u32 align, u32 flags, + struct nouveau_gpuobj **); +int nouveau_gpuobj_dup(struct nouveau_object *, struct nouveau_gpuobj *, + struct nouveau_gpuobj **); + +int nouveau_gpuobj_map(struct nouveau_gpuobj *, u32 acc, struct nouveau_vma *); +int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *, struct nouveau_vm *, + u32 access, struct nouveau_vma *); +void nouveau_gpuobj_unmap(struct nouveau_vma *); +#endif + +static inline void +nouveau_gpuobj_ref(struct nouveau_gpuobj *obj, struct nouveau_gpuobj **ref) +{ + nouveau_object_ref(&obj->base, (struct nouveau_object **)ref); +} + +#ifndef XXX_THIS_IS_A_HACK +void _nouveau_gpuobj_dtor(struct nouveau_object *); +int _nouveau_gpuobj_init(struct nouveau_object *); +int _nouveau_gpuobj_fini(struct nouveau_object *, bool); +u32 _nouveau_gpuobj_rd32(struct nouveau_object *, u32); +void _nouveau_gpuobj_wr32(struct nouveau_object *, u32, u32); +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/handle.h b/drivers/gpu/drm/nouveau/core/include/core/handle.h new file mode 100644 index 0000000..fbfbe55 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/handle.h @@ -0,0 +1,26 @@ +#ifndef __NOUVEAU_HANDLE_H__ +#define __NOUVEAU_HANDLE_H__ + +struct nouveau_handle { + struct nouveau_namedb *namedb; + struct list_head node; + + struct list_head head; + struct list_head tree; + u32 name; + u32 priv; + + struct nouveau_handle *parent; + struct nouveau_object *object; +}; + +int nouveau_handle_create(struct nouveau_object *, u32 parent, u32 handle, + struct nouveau_object *, struct nouveau_handle **); +void nouveau_handle_destroy(struct nouveau_handle *); +int nouveau_handle_init(struct nouveau_handle *); +int nouveau_handle_fini(struct nouveau_handle *, bool suspend); + +struct nouveau_object * +nouveau_handle_ref(struct nouveau_object *, u32 name); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/math.h b/drivers/gpu/drm/nouveau/core/include/core/math.h new file mode 100644 index 0000000..f808131 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/math.h @@ -0,0 +1,16 @@ +#ifndef __NOUVEAU_MATH_H__ +#define __NOUVEAU_MATH_H__ + +static inline int +log2i(u64 base) +{ + u64 temp = base >> 1; + int log2; + + for (log2 = 0; temp; log2++, temp >>= 1) { + } + + return (base & (base - 1)) ? log2 + 1: log2; +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index d2b4290..b4fd73b 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -22,8 +22,8 @@ * Authors: Ben Skeggs */ -#ifndef __NOUVEAU_REGION_H__ -#define __NOUVEAU_REGION_H__ +#ifndef __NOUVEAU_MM_H__ +#define __NOUVEAU_MM_H__ struct nouveau_mm_node { struct list_head nl_entry; diff --git a/drivers/gpu/drm/nouveau/core/include/core/namedb.h b/drivers/gpu/drm/nouveau/core/include/core/namedb.h new file mode 100644 index 0000000..8897e08 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/namedb.h @@ -0,0 +1,56 @@ +#ifndef __NOUVEAU_NAMEDB_H__ +#define __NOUVEAU_NAMEDB_H__ + +#include + +struct nouveau_handle; + +struct nouveau_namedb { + struct nouveau_parent base; + rwlock_t lock; + struct list_head list; +}; + +static inline struct nouveau_namedb * +nv_namedb(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_NAMEDB_CLASS))) + nv_assert("BAD CAST -> NvNameDB, %08x", nv_hclass(obj)); +#endif + return obj; +} + +#define nouveau_namedb_create(p,e,c,v,s,m,d) \ + nouveau_namedb_create_((p), (e), (c), (v), (s), (m), \ + sizeof(**d), (void **)d) +#define nouveau_namedb_init(p) \ + nouveau_parent_init(&(p)->base) +#define nouveau_namedb_fini(p,s) \ + nouveau_parent_fini(&(p)->base, (s)) +#define nouveau_namedb_destroy(p) \ + nouveau_parent_destroy(&(p)->base) + +int nouveau_namedb_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, u32 pclass, + struct nouveau_oclass *, u32 engcls, + int size, void **); + +int _nouveau_namedb_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +#define _nouveau_namedb_dtor _nouveau_parent_dtor +#define _nouveau_namedb_init _nouveau_parent_init +#define _nouveau_namedb_fini _nouveau_parent_fini + +int nouveau_namedb_insert(struct nouveau_namedb *, u32 name, + struct nouveau_object *, struct nouveau_handle *); +void nouveau_namedb_remove(struct nouveau_handle *); + +struct nouveau_handle *nouveau_namedb_get(struct nouveau_namedb *, u32); +struct nouveau_handle *nouveau_namedb_get_class(struct nouveau_namedb *, u16); +struct nouveau_handle *nouveau_namedb_get_vinst(struct nouveau_namedb *, u64); +struct nouveau_handle *nouveau_namedb_get_cinst(struct nouveau_namedb *, u32); +void nouveau_namedb_put(struct nouveau_handle *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h new file mode 100644 index 0000000..818feab --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/object.h @@ -0,0 +1,188 @@ +#ifndef __NOUVEAU_OBJECT_H__ +#define __NOUVEAU_OBJECT_H__ + +#include +#include + +#define NV_PARENT_CLASS 0x80000000 +#define NV_NAMEDB_CLASS 0x40000000 +#define NV_CLIENT_CLASS 0x20000000 +#define NV_SUBDEV_CLASS 0x10000000 +#define NV_ENGINE_CLASS 0x08000000 +#define NV_MEMOBJ_CLASS 0x04000000 +#define NV_GPUOBJ_CLASS 0x02000000 +#define NV_ENGCTX_CLASS 0x01000000 +#define NV_OBJECT_CLASS 0x0000ffff + +struct nouveau_object { + struct nouveau_oclass *oclass; + struct nouveau_object *parent; + struct nouveau_object *engine; + atomic_t refcount; + atomic_t usecount; +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA +#define NOUVEAU_OBJECT_MAGIC 0x75ef0bad + struct list_head list; + u32 _magic; +#endif +}; + +static inline struct nouveau_object * +nv_object(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (likely(obj)) { + struct nouveau_object *object = obj; + if (unlikely(object->_magic != NOUVEAU_OBJECT_MAGIC)) + nv_assert("BAD CAST -> NvObject, invalid magic"); + } +#endif + return obj; +} + +#define nouveau_object_create(p,e,c,s,d) \ + nouveau_object_create_((p), (e), (c), (s), sizeof(**d), (void **)d) +int nouveau_object_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, u32, int size, void **); +void nouveau_object_destroy(struct nouveau_object *); +int nouveau_object_init(struct nouveau_object *); +int nouveau_object_fini(struct nouveau_object *, bool suspend); + +extern struct nouveau_ofuncs nouveau_object_ofuncs; + +struct nouveau_oclass { + u32 handle; + struct nouveau_ofuncs *ofuncs; + struct nouveau_omthds *omthds; +}; + +#define nv_oclass(o) nv_object(o)->oclass +#define nv_hclass(o) nv_oclass(o)->handle +#define nv_iclass(o,i) (nv_hclass(o) & (i)) +#define nv_mclass(o) nv_iclass(o, NV_OBJECT_CLASS) + +static inline struct nouveau_object * +nv_pclass(struct nouveau_object *parent, u32 oclass) +{ + while (parent && !nv_iclass(parent, oclass)) + parent = parent->parent; + return parent; +} + +struct nouveau_omthds { + u32 method; + int (*call)(struct nouveau_object *, u32, void *, u32); +}; + +struct nouveau_ofuncs { + int (*ctor)(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *data, u32 size, + struct nouveau_object **); + void (*dtor)(struct nouveau_object *); + int (*init)(struct nouveau_object *); + int (*fini)(struct nouveau_object *, bool suspend); + u8 (*rd08)(struct nouveau_object *, u32 offset); + u16 (*rd16)(struct nouveau_object *, u32 offset); + u32 (*rd32)(struct nouveau_object *, u32 offset); + void (*wr08)(struct nouveau_object *, u32 offset, u8 data); + void (*wr16)(struct nouveau_object *, u32 offset, u16 data); + void (*wr32)(struct nouveau_object *, u32 offset, u32 data); +}; + +static inline struct nouveau_ofuncs * +nv_ofuncs(void *obj) +{ + return nv_oclass(obj)->ofuncs; +} + +int nouveau_object_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +void nouveau_object_ref(struct nouveau_object *, struct nouveau_object **); +int nouveau_object_inc(struct nouveau_object *); +int nouveau_object_dec(struct nouveau_object *, bool suspend); + +int nouveau_object_new(struct nouveau_object *, u32 parent, u32 handle, + u16 oclass, void *data, u32 size, + struct nouveau_object **); +int nouveau_object_del(struct nouveau_object *, u32 parent, u32 handle); +void nouveau_object_debug(void); + +static inline int +nv_call(void *obj, u32 mthd, u32 data) +{ + struct nouveau_omthds *method = nv_oclass(obj)->omthds; + + while (method && method->call) { + if (method->method == mthd) + return method->call(obj, mthd, &data, sizeof(data)); + method++; + } + + return -EINVAL; +} + +static inline u8 +nv_ro08(void *obj, u32 addr) +{ + u8 data = nv_ofuncs(obj)->rd08(obj, addr); + nv_spam(obj, "nv_ro08 0x%08x 0x%02x\n", addr, data); + return data; +} + +static inline u16 +nv_ro16(void *obj, u32 addr) +{ + u16 data = nv_ofuncs(obj)->rd16(obj, addr); + nv_spam(obj, "nv_ro16 0x%08x 0x%04x\n", addr, data); + return data; +} + +static inline u32 +nv_ro32(void *obj, u32 addr) +{ + u32 data = nv_ofuncs(obj)->rd32(obj, addr); + nv_spam(obj, "nv_ro32 0x%08x 0x%08x\n", addr, data); + return data; +} + +static inline void +nv_wo08(void *obj, u32 addr, u8 data) +{ + nv_spam(obj, "nv_wo08 0x%08x 0x%02x\n", addr, data); + nv_ofuncs(obj)->wr08(obj, addr, data); +} + +static inline void +nv_wo16(void *obj, u32 addr, u16 data) +{ + nv_spam(obj, "nv_wo16 0x%08x 0x%04x\n", addr, data); + nv_ofuncs(obj)->wr16(obj, addr, data); +} + +static inline void +nv_wo32(void *obj, u32 addr, u32 data) +{ + nv_spam(obj, "nv_wo32 0x%08x 0x%08x\n", addr, data); + nv_ofuncs(obj)->wr32(obj, addr, data); +} + +static inline u32 +nv_mo32(void *obj, u32 addr, u32 mask, u32 data) +{ + u32 temp = nv_ro32(obj, addr); + nv_wo32(obj, addr, (temp & ~mask) | data); + return temp; +} + +static inline bool +nv_strncmp(void *obj, u32 addr, u32 len, const char *str) +{ + while (len--) { + if (nv_ro08(obj, addr++) != *(str++)) + return false; + } + return true; +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/option.h b/drivers/gpu/drm/nouveau/core/include/core/option.h new file mode 100644 index 0000000..2707495 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/option.h @@ -0,0 +1,11 @@ +#ifndef __NOUVEAU_OPTION_H__ +#define __NOUVEAU_OPTION_H__ + +#include + +const char *nouveau_stropt(const char *optstr, const char *opt, int *len); +bool nouveau_boolopt(const char *optstr, const char *opt, bool value); + +int nouveau_dbgopt(const char *optstr, const char *sub); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/parent.h b/drivers/gpu/drm/nouveau/core/include/core/parent.h new file mode 100644 index 0000000..d3aa251 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/parent.h @@ -0,0 +1,64 @@ +#ifndef __NOUVEAU_PARENT_H__ +#define __NOUVEAU_PARENT_H__ + +#include +#include + +struct nouveau_sclass { + struct nouveau_sclass *sclass; + struct nouveau_engine *engine; + struct nouveau_oclass *oclass; +}; + +struct nouveau_parent { + struct nouveau_object base; + + struct nouveau_sclass *sclass; + u32 engine; + + int (*context_attach)(struct nouveau_object *, + struct nouveau_object *); + int (*context_detach)(struct nouveau_object *, bool suspend, + struct nouveau_object *); + + int (*object_attach)(struct nouveau_object *parent, + struct nouveau_object *object, u32 name); + void (*object_detach)(struct nouveau_object *parent, int cookie); +}; + +static inline struct nouveau_parent * +nv_parent(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!(nv_iclass(obj, NV_PARENT_CLASS)))) + nv_assert("BAD CAST -> NvParent, %08x", nv_hclass(obj)); +#endif + return obj; +} + +#define nouveau_parent_create(p,e,c,v,s,m,d) \ + nouveau_parent_create_((p), (e), (c), (v), (s), (m), \ + sizeof(**d), (void **)d) +#define nouveau_parent_init(p) \ + nouveau_object_init(&(p)->base) +#define nouveau_parent_fini(p,s) \ + nouveau_object_fini(&(p)->base, (s)) + +int nouveau_parent_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, u32 pclass, + struct nouveau_oclass *, u64 engcls, + int size, void **); +void nouveau_parent_destroy(struct nouveau_parent *); + +int _nouveau_parent_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +void _nouveau_parent_dtor(struct nouveau_object *); +#define _nouveau_parent_init _nouveau_object_init +#define _nouveau_parent_fini _nouveau_object_fini + +int nouveau_parent_sclass(struct nouveau_object *, u16 handle, + struct nouveau_object **pengine, + struct nouveau_oclass **poclass); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/printk.h b/drivers/gpu/drm/nouveau/core/include/core/printk.h new file mode 100644 index 0000000..1d62966 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/printk.h @@ -0,0 +1,39 @@ +#ifndef __NOUVEAU_PRINTK_H__ +#define __NOUVEAU_PRINTK_H__ + +#include +#include + +struct nouveau_object; + +#define NV_PRINTK_FATAL KERN_CRIT +#define NV_PRINTK_ERROR KERN_ERR +#define NV_PRINTK_WARN KERN_WARNING +#define NV_PRINTK_INFO KERN_INFO +#define NV_PRINTK_DEBUG KERN_DEBUG +#define NV_PRINTK_PARANOIA KERN_DEBUG +#define NV_PRINTK_TRACE KERN_DEBUG +#define NV_PRINTK_SPAM KERN_DEBUG + +void nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); + +#define nv_printk(o,l,f,a...) do { \ + if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG) \ + nv_printk_(nv_object(o), NV_PRINTK_##l, NV_DBG_##l, f, ##a); \ +} while(0) + +#define nv_fatal(o,f,a...) nv_printk((o), FATAL, f, ##a) +#define nv_error(o,f,a...) nv_printk((o), ERROR, f, ##a) +#define nv_warn(o,f,a...) nv_printk((o), WARN, f, ##a) +#define nv_info(o,f,a...) nv_printk((o), INFO, f, ##a) +#define nv_debug(o,f,a...) nv_printk((o), DEBUG, f, ##a) +#define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a) +#define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a) + +#define nv_assert(f,a...) do { \ + if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG) \ + nv_printk_(NULL, NV_PRINTK_FATAL, NV_DBG_FATAL, f "\n", ##a); \ + BUG_ON(1); \ +} while(0) + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/subdev.h b/drivers/gpu/drm/nouveau/core/include/core/subdev.h new file mode 100644 index 0000000..e9632e9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/core/subdev.h @@ -0,0 +1,118 @@ +#ifndef __NOUVEAU_SUBDEV_H__ +#define __NOUVEAU_SUBDEV_H__ + +#include + +#define NV_SUBDEV_(sub,var) (NV_SUBDEV_CLASS | ((var) << 8) | (sub)) +#define NV_SUBDEV(name,var) NV_SUBDEV_(NVDEV_SUBDEV_##name, (var)) + +struct nouveau_subdev { + struct nouveau_object base; + struct mutex mutex; + const char *name; + void __iomem *mmio; + u32 debug; + u32 unit; + + void (*intr)(struct nouveau_subdev *); +}; + +static inline struct nouveau_subdev * +nv_subdev(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_SUBDEV_CLASS))) + nv_assert("BAD CAST -> NvSubDev, %08x", nv_hclass(obj)); +#endif + return obj; +} + +static inline int +nv_subidx(struct nouveau_object *object) +{ + return nv_hclass(nv_subdev(object)) & 0xff; +} + +#define nouveau_subdev_create(p,e,o,v,s,f,d) \ + nouveau_subdev_create_((p), (e), (o), (v), (s), (f), \ + sizeof(**d),(void **)d) + +int nouveau_subdev_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, u32 pclass, + const char *sname, const char *fname, + int size, void **); +void nouveau_subdev_destroy(struct nouveau_subdev *); +int nouveau_subdev_init(struct nouveau_subdev *); +int nouveau_subdev_fini(struct nouveau_subdev *, bool suspend); +void nouveau_subdev_reset(struct nouveau_object *); + +void _nouveau_subdev_dtor(struct nouveau_object *); +int _nouveau_subdev_init(struct nouveau_object *); +int _nouveau_subdev_fini(struct nouveau_object *, bool suspend); + +#define s_printk(s,l,f,a...) do { \ + if ((s)->debug >= OS_DBG_##l) { \ + nv_printk((s)->base.parent, (s)->name, l, f, ##a); \ + } \ +} while(0) + +static inline u8 +nv_rd08(void *obj, u32 addr) +{ + struct nouveau_subdev *subdev = nv_subdev(obj); + u8 data = ioread8(subdev->mmio + addr); + nv_spam(subdev, "nv_rd08 0x%06x 0x%02x\n", addr, data); + return data; +} + +static inline u16 +nv_rd16(void *obj, u32 addr) +{ + struct nouveau_subdev *subdev = nv_subdev(obj); + u16 data = ioread16_native(subdev->mmio + addr); + nv_spam(subdev, "nv_rd16 0x%06x 0x%04x\n", addr, data); + return data; +} + +static inline u32 +nv_rd32(void *obj, u32 addr) +{ + struct nouveau_subdev *subdev = nv_subdev(obj); + u32 data = ioread32_native(subdev->mmio + addr); + nv_spam(subdev, "nv_rd32 0x%06x 0x%08x\n", addr, data); + return data; +} + +static inline void +nv_wr08(void *obj, u32 addr, u8 data) +{ + struct nouveau_subdev *subdev = nv_subdev(obj); + nv_spam(subdev, "nv_wr08 0x%06x 0x%02x\n", addr, data); + iowrite8(data, subdev->mmio + addr); +} + +static inline void +nv_wr16(void *obj, u32 addr, u16 data) +{ + struct nouveau_subdev *subdev = nv_subdev(obj); + nv_spam(subdev, "nv_wr16 0x%06x 0x%04x\n", addr, data); + iowrite16_native(data, subdev->mmio + addr); +} + +static inline void +nv_wr32(void *obj, u32 addr, u32 data) +{ + struct nouveau_subdev *subdev = nv_subdev(obj); + nv_spam(subdev, "nv_wr32 0x%06x 0x%08x\n", addr, data); + iowrite32_native(data, subdev->mmio + addr); +} + +static inline u32 +nv_mask(void *obj, u32 addr, u32 mask, u32 data) +{ + u32 temp = nv_rd32(obj, addr); + nv_wr32(obj, addr, (temp & ~mask) | data); + return temp; +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/device.h b/drivers/gpu/drm/nouveau/core/include/subdev/device.h new file mode 100644 index 0000000..5eec03a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/device.h @@ -0,0 +1,25 @@ +#ifndef __NOUVEAU_SUBDEV_DEVICE_H__ +#define __NOUVEAU_SUBDEV_DEVICE_H__ + +#include + +#define nouveau_device_create(p,n,s,c,d,u) \ + nouveau_device_create_((p), (n), (s), (c), (d), sizeof(**u), (void **)u) + +int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname, + const char *cfg, const char *dbg, int, void **); +void nouveau_device_destroy(struct nouveau_device **); + +int nv04_identify(struct nouveau_device *); +int nv10_identify(struct nouveau_device *); +int nv20_identify(struct nouveau_device *); +int nv30_identify(struct nouveau_device *); +int nv40_identify(struct nouveau_device *); +int nv50_identify(struct nouveau_device *); +int nvc0_identify(struct nouveau_device *); +int nve0_identify(struct nouveau_device *); + +extern struct nouveau_oclass nouveau_device_sclass[]; +struct nouveau_device *nouveau_device_find(u64 name); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h new file mode 100644 index 0000000..3bfb478 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -0,0 +1,46 @@ +#ifndef __NOUVEAU_OS_H__ +#define __NOUVEAU_OS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static inline int +ffsll(u64 mask) +{ + int i; + for (i = 0; i < 64; i++) { + if (mask & (1ULL << i)) + return i + 1; + } + return 0; +} + +#ifndef ioread32_native +#ifdef __BIG_ENDIAN +#define ioread16_native ioread16be +#define iowrite16_native iowrite16be +#define ioread32_native ioread32be +#define iowrite32_native iowrite32be +#else /* def __BIG_ENDIAN */ +#define ioread16_native ioread16 +#define iowrite16_native iowrite16 +#define ioread32_native ioread32 +#define iowrite32_native iowrite32 +#endif /* def __BIG_ENDIAN else */ +#endif /* !ioread32_native */ + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c new file mode 100644 index 0000000..40456b9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -0,0 +1,461 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include +#include + +#include + +#include + +static DEFINE_MUTEX(nv_devices_mutex); +static LIST_HEAD(nv_devices); + +struct nouveau_device * +nouveau_device_find(u64 name) +{ + struct nouveau_device *device, *match = NULL; + mutex_lock(&nv_devices_mutex); + list_for_each_entry(device, &nv_devices, head) { + if (device->handle == name) { + match = device; + break; + } + } + mutex_unlock(&nv_devices_mutex); + return match; +} + +/****************************************************************************** + * nouveau_devobj (0x0080): class implementation + *****************************************************************************/ +struct nouveau_devobj { + struct nouveau_parent base; + struct nouveau_object *subdev[NVDEV_SUBDEV_NR]; + bool created; +}; + +static const u64 disable_map[] = { + [NVDEV_SUBDEV_VBIOS] = NV_DEVICE_DISABLE_VBIOS, + [NVDEV_SUBDEV_GPIO] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_I2C] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_VM] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_FAN0] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, + [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE, + [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE, + [NVDEV_ENGINE_GR] = NV_DEVICE_DISABLE_GRAPH, + [NVDEV_ENGINE_MPEG] = NV_DEVICE_DISABLE_MPEG, + [NVDEV_ENGINE_ME] = NV_DEVICE_DISABLE_ME, + [NVDEV_ENGINE_VP] = NV_DEVICE_DISABLE_VP, + [NVDEV_ENGINE_CRYPT] = NV_DEVICE_DISABLE_CRYPT, + [NVDEV_ENGINE_BSP] = NV_DEVICE_DISABLE_BSP, + [NVDEV_ENGINE_PPP] = NV_DEVICE_DISABLE_PPP, + [NVDEV_ENGINE_COPY0] = NV_DEVICE_DISABLE_COPY0, + [NVDEV_ENGINE_COPY1] = NV_DEVICE_DISABLE_COPY1, + [NVDEV_ENGINE_UNK1C1] = NV_DEVICE_DISABLE_UNK1C1, + [NVDEV_ENGINE_FIFO] = NV_DEVICE_DISABLE_FIFO, + [NVDEV_ENGINE_DISP] = NV_DEVICE_DISABLE_DISP, + [NVDEV_SUBDEV_NR] = 0, +}; + +static int +nouveau_devobj_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_client *client = nv_client(parent); + struct nouveau_object *subdev = NULL; + struct nouveau_device *device; + struct nouveau_devobj *devobj; + struct nv_device_class *args = data; + u64 disable, boot0, strap; + u64 mmio_base, mmio_size; + void __iomem *map; + int ret, i; + + if (size < sizeof(struct nv_device_class)) + return -EINVAL; + + /* find the device subdev that matches what the client requested */ + device = nv_device(client->device); + if (args->device != ~0) { + device = nouveau_device_find(args->device); + if (!device) + return -ENODEV; + } + + ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, NULL, + (1ULL << NVDEV_ENGINE_DMAOBJ) | + (1ULL << NVDEV_ENGINE_FIFO) | + (1ULL << NVDEV_ENGINE_DISP), &devobj); + *pobject = nv_object(devobj); + if (ret) + return ret; + + mmio_base = pci_resource_start(device->pdev, 0); + mmio_size = pci_resource_len(device->pdev, 0); + + /* translate api disable mask into internal mapping */ + disable = args->debug0; + for (i = 0; i < NVDEV_SUBDEV_NR; i++) { + if (args->disable & disable_map[i]) + disable |= (1ULL << i); + } + + /* identify the chipset, and determine classes of subdev/engines */ + if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) && + !device->card_type) { + map = ioremap(mmio_base, 0x102000); + if (map == NULL) { + } + + /* switch mmio to cpu's native endianness */ +#ifndef __BIG_ENDIAN + if (ioread32_native(map + 0x000004) != 0x00000000) +#else + if (ioread32_native(map + 0x000004) == 0x00000000) +#endif + iowrite32_native(0x01000001, map + 0x000004); + + /* read boot0 and strapping information */ + boot0 = ioread32_native(map + 0x000000); + strap = ioread32_native(map + 0x101000); + iounmap(map); + + /* determine chipset and derive architecture from it */ + if ((boot0 & 0x0f000000) > 0) { + device->chipset = (boot0 & 0xff00000) >> 20; + switch (device->chipset & 0xf0) { + case 0x10: device->card_type = NV_10; break; + case 0x20: device->card_type = NV_20; break; + case 0x30: device->card_type = NV_30; break; + case 0x40: + case 0x60: device->card_type = NV_40; break; + case 0x50: + case 0x80: + case 0x90: + case 0xa0: device->card_type = NV_50; break; + case 0xc0: device->card_type = NV_C0; break; + case 0xd0: device->card_type = NV_D0; break; + case 0xe0: device->card_type = NV_E0; break; + default: + break; + } + } else + if ((boot0 & 0xff00fff0) == 0x20004000) { + if (boot0 & 0x00f00000) + device->chipset = 0x05; + else + device->chipset = 0x04; + device->card_type = NV_04; + } + + switch (device->card_type) { + case NV_04: ret = nv04_identify(device); break; + case NV_10: ret = nv10_identify(device); break; + case NV_20: ret = nv20_identify(device); break; + case NV_30: ret = nv30_identify(device); break; + case NV_40: ret = nv40_identify(device); break; + case NV_50: ret = nv50_identify(device); break; + case NV_C0: + case NV_D0: ret = nvc0_identify(device); break; + case NV_E0: ret = nve0_identify(device); break; + default: + ret = -EINVAL; + break; + } + + if (ret) { + nv_error(device, "unknown chipset, 0x%08x\n", boot0); + return ret; + } + + nv_info(device, "BOOT0 : 0x%08x\n", boot0); + nv_info(device, "Chipset: NV%02X\n", device->chipset); + nv_info(device, "Family : NV%02X\n", device->card_type); + + /* determine frequency of timing crystal */ + if ( device->chipset < 0x17 || + (device->chipset >= 0x20 && device->chipset <= 0x25)) + strap &= 0x00000040; + else + strap &= 0x00400040; + + switch (strap) { + case 0x00000000: device->crystal = 13500; break; + case 0x00000040: device->crystal = 14318; break; + case 0x00400000: device->crystal = 27000; break; + case 0x00400040: device->crystal = 25000; break; + } + + nv_debug(device, "crystal freq: %dKHz\n", device->crystal); + } + + if (!(args->disable & NV_DEVICE_DISABLE_MMIO) && + !nv_subdev(device)->mmio) { + nv_subdev(device)->mmio = ioremap(mmio_base, mmio_size); + if (!nv_subdev(device)->mmio) { + nv_error(device, "unable to map device registers\n"); + return ret; + } + } + + /* ensure requested subsystems are available for use */ + for (i = 0; i < NVDEV_SUBDEV_NR; i++) { + if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) + continue; + + if (!device->subdev[i]) { + ret = nouveau_object_ctor(nv_object(device), NULL, + oclass, NULL, i, &subdev); + if (ret) + return ret; + + if (nv_iclass(subdev, NV_ENGINE_CLASS)) + nouveau_subdev_reset(subdev); + } else { + nouveau_object_ref(device->subdev[i], &subdev); + } + + if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { + ret = nouveau_object_inc(subdev); + if (ret) { + nouveau_object_ref(NULL, &subdev); + return ret; + } + } + + nouveau_object_ref(subdev, &devobj->subdev[i]); + nouveau_object_ref(NULL, &subdev); + } + + return 0; +} + +static void +nouveau_devobj_dtor(struct nouveau_object *object) +{ + struct nouveau_devobj *devobj = (void *)object; + int i; + + for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) + nouveau_object_ref(NULL, &devobj->subdev[i]); + + nouveau_parent_destroy(&devobj->base); +} + +static int +nouveau_devobj_init(struct nouveau_object *object) +{ + struct nouveau_devobj *devobj = (void *)object; + struct nouveau_object *subdev; + int ret, i; + + ret = nouveau_parent_init(&devobj->base); + if (ret) + return ret; + + for (i = 0; devobj->created && i < NVDEV_SUBDEV_NR; i++) { + if ((subdev = devobj->subdev[i])) { + if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { + ret = nouveau_object_inc(subdev); + if (ret) + goto fail; + } + } + } + + devobj->created = true; + return 0; + +fail: + for (--i; i >= 0; i--) { + if ((subdev = devobj->subdev[i])) { + if (!nv_iclass(subdev, NV_ENGINE_CLASS)) + nouveau_object_dec(subdev, false); + } + } + + return ret; +} + +static int +nouveau_devobj_fini(struct nouveau_object *object, bool suspend) +{ + struct nouveau_devobj *devobj = (void *)object; + struct nouveau_object *subdev; + int ret, i; + + for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) { + if ((subdev = devobj->subdev[i])) { + if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { + ret = nouveau_object_dec(subdev, suspend); + if (ret && suspend) + goto fail; + } + } + } + + ret = nouveau_parent_fini(&devobj->base, suspend); +fail: + for (; ret && suspend && i < NVDEV_SUBDEV_NR; i++) { + if ((subdev = devobj->subdev[i])) { + if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { + ret = nouveau_object_inc(subdev); + if (ret) { + /* XXX */ + } + } + } + } + + return ret; +} + +static u8 +nouveau_devobj_rd08(struct nouveau_object *object, u32 addr) +{ + return nv_rd08(object->engine, addr); +} + +static u16 +nouveau_devobj_rd16(struct nouveau_object *object, u32 addr) +{ + return nv_rd16(object->engine, addr); +} + +static u32 +nouveau_devobj_rd32(struct nouveau_object *object, u32 addr) +{ + return nv_rd32(object->engine, addr); +} + +static void +nouveau_devobj_wr08(struct nouveau_object *object, u32 addr, u8 data) +{ + nv_wr08(object->engine, addr, data); +} + +static void +nouveau_devobj_wr16(struct nouveau_object *object, u32 addr, u16 data) +{ + nv_wr16(object->engine, addr, data); +} + +static void +nouveau_devobj_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + nv_wr32(object->engine, addr, data); +} + +static struct nouveau_ofuncs +nouveau_devobj_ofuncs = { + .ctor = nouveau_devobj_ctor, + .dtor = nouveau_devobj_dtor, + .init = nouveau_devobj_init, + .fini = nouveau_devobj_fini, + .rd08 = nouveau_devobj_rd08, + .rd16 = nouveau_devobj_rd16, + .rd32 = nouveau_devobj_rd32, + .wr08 = nouveau_devobj_wr08, + .wr16 = nouveau_devobj_wr16, + .wr32 = nouveau_devobj_wr32, +}; + +/****************************************************************************** + * nouveau_device: engine functions + *****************************************************************************/ +struct nouveau_oclass +nouveau_device_sclass[] = { + { 0x0080, &nouveau_devobj_ofuncs }, + {} +}; + +static struct nouveau_oclass +nouveau_device_oclass = { + .handle = NV_SUBDEV(DEVICE, 0x00), + .ofuncs = &(struct nouveau_ofuncs) { + }, +}; + +int +nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname, + const char *cfg, const char *dbg, + int length, void **pobject) +{ + struct nouveau_device *device; + int ret = -EEXIST; + + mutex_lock(&nv_devices_mutex); + list_for_each_entry(device, &nv_devices, head) { + if (device->handle == name) + goto done; + } + + ret = nouveau_subdev_create_(NULL, NULL, &nouveau_device_oclass, 0, + "DEVICE", "device", length, pobject); + device = *pobject; + if (ret) + goto done; + + atomic_set(&nv_object(device)->usecount, 2); + device->pdev = pdev; + device->handle = name; + device->cfgopt = cfg; + device->dbgopt = dbg; + device->name = sname; + + nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE"); + list_add(&device->head, &nv_devices); +done: + mutex_unlock(&nv_devices_mutex); + return ret; +} + +void +nouveau_device_destroy(struct nouveau_device **pdevice) +{ + struct nouveau_device *device = *pdevice; + if (device) { + mutex_lock(&nv_devices_mutex); + list_del(&device->head); + mutex_unlock(&nv_devices_mutex); + if (device->base.mmio) + iounmap(device->base.mmio); + nouveau_subdev_destroy(&device->base); + } + *pdevice = NULL; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c new file mode 100644 index 0000000..8ded9d3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -0,0 +1,41 @@ +/* + * 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: + * + * 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 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 + +int +nv04_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0x04: + break; + case 0x05: + break; + default: + nv_fatal(device, "unknown RIVA chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c new file mode 100644 index 0000000..04d14d1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -0,0 +1,53 @@ +/* + * 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: + * + * 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 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 + +int +nv10_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0x10: + break; + case 0x15: + break; + case 0x16: + break; + case 0x1a: + break; + case 0x11: + break; + case 0x17: + break; + case 0x1f: + break; + case 0x18: + break; + default: + nv_fatal(device, "unknown Celsius chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c new file mode 100644 index 0000000..1805bee --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -0,0 +1,45 @@ +/* + * 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: + * + * 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 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 + +int +nv20_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0x20: + break; + case 0x25: + break; + case 0x28: + break; + case 0x2a: + break; + default: + nv_fatal(device, "unknown Kelvin chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c new file mode 100644 index 0000000..1e7a8b1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -0,0 +1,47 @@ +/* + * 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: + * + * 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 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 + +int +nv30_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0x30: + break; + case 0x35: + break; + case 0x31: + break; + case 0x36: + break; + case 0x34: + break; + default: + nv_fatal(device, "unknown Rankine chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c new file mode 100644 index 0000000..5c54f61 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -0,0 +1,69 @@ +/* + * 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: + * + * 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 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 + +int +nv40_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0x40: + break; + case 0x41: + break; + case 0x42: + break; + case 0x43: + break; + case 0x45: + break; + case 0x47: + break; + case 0x49: + break; + case 0x4b: + break; + case 0x44: + break; + case 0x46: + break; + case 0x4a: + break; + case 0x4c: + break; + case 0x4e: + break; + case 0x63: + break; + case 0x67: + break; + case 0x68: + break; + default: + nv_fatal(device, "unknown Curie chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c new file mode 100644 index 0000000..a699bd9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -0,0 +1,65 @@ +/* + * 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: + * + * 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 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 + +int +nv50_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0x50: + break; + case 0x84: + break; + case 0x86: + break; + case 0x92: + break; + case 0x94: + break; + case 0x96: + break; + case 0x98: + break; + case 0xa0: + break; + case 0xaa: + break; + case 0xac: + break; + case 0xa3: + break; + case 0xa5: + break; + case 0xa8: + break; + case 0xaf: + break; + default: + nv_fatal(device, "unknown Tesla chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c new file mode 100644 index 0000000..805268c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -0,0 +1,53 @@ +/* + * 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: + * + * 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 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 + +int +nvc0_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0xc0: + break; + case 0xc4: + break; + case 0xc3: + break; + case 0xce: + break; + case 0xcf: + break; + case 0xc1: + break; + case 0xc8: + break; + case 0xd9: + break; + default: + nv_fatal(device, "unknown Fermi chipset\n"); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c new file mode 100644 index 0000000..3c3fe69 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -0,0 +1,41 @@ +/* + * 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: + * + * 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 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 + +int +nve0_identify(struct nouveau_device *device) +{ + switch (device->chipset) { + case 0xe4: + break; + case 0xe7: + break; + default: + nv_fatal(device, "unknown Kepler chipset\n"); + return -EINVAL; + } + + return 0; +} -- cgit v1.1 From 9458029940ffc64bca0c5a30ea626c377205842e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 6 Jul 2012 12:14:00 +1000 Subject: drm/nouveau: implement module init functions in nouveau_drm.c These currently just call the existing ones in nouveau_drv.c, but will be extended in upcoming commits. This needed to be separated from the current code as there will be some header clashes until things are ported. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/graph/nv04.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c index 353d4d3..7f3a275 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c @@ -24,7 +24,7 @@ #include "drmP.h" #include "drm.h" -#include "nouveau_drm.h" +#include #include "nouveau_drv.h" #include "nouveau_hw.h" #include "nouveau_util.h" diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index fb1d88a..19e303b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -24,7 +24,7 @@ #include "drmP.h" #include "drm.h" -#include "nouveau_drm.h" +#include #include "nouveau_drv.h" #include "nouveau_util.h" diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index e34ea30..718ecf7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include /* * NV20 diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c index d5eedd6..eef4844 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include int nv04_fb_vram_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c index 420b1608..09af63b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include void nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c index 19bd640..a7f056c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include static struct drm_mm_node * nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c index e0135f0..30639a0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -27,7 +27,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include void nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index 7fbcb33..e08c2e1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include void nv40_fb_set_tile_region(struct drm_device *dev, int i) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 3488358..a145b1c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include #include struct nv50_fb_priv { diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index f376c39..f054331 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -25,7 +25,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include struct nvc0_fb_priv { struct page *r100c10_page; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c index 2af43a1..60b146e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include int nv04_mc_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c index 03c0d4c..74cfa03 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include int nv40_mc_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 55c9452..63333dc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -1,7 +1,7 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" -#include "nouveau_drm.h" +#include #include "nouveau_hw.h" int -- cgit v1.1 From 70c0f263cc2eb12e02506eb75f0a71490e7dea4d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 10:49:22 +1000 Subject: drm/nouveau/bios: pull in basic vbios subdev, more to come later v2: Ben Skeggs - use unaligned macros to access vbios image - endianness fixes Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/subdev/bios.h | 34 ++ .../gpu/drm/nouveau/core/include/subdev/bios/bit.h | 13 + .../gpu/drm/nouveau/core/include/subdev/bios/bmp.h | 39 ++ drivers/gpu/drm/nouveau/core/os.h | 2 + drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 451 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/bios/bit.c | 52 +++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 + drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + 14 files changed, 658 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/bit.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/bmp.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/bit.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h new file mode 100644 index 0000000..d145b25 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h @@ -0,0 +1,34 @@ +#ifndef __NOUVEAU_BIOS_H__ +#define __NOUVEAU_BIOS_H__ + +#include +#include + +struct nouveau_bios { + struct nouveau_subdev base; + u32 size; + u8 *data; + + u32 bmp_offset; + u32 bit_offset; + + struct { + u8 major; + u8 chip; + u8 minor; + u8 micro; + } version; +}; + +static inline struct nouveau_bios * +nouveau_bios(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_VBIOS]; +} + +u8 nvbios_checksum(const u8 *data, int size); +u16 nvbios_findstr(const u8 *data, int size, const char *str, int len); + +extern struct nouveau_oclass nouveau_bios_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/bit.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/bit.h new file mode 100644 index 0000000..73f060b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/bit.h @@ -0,0 +1,13 @@ +#ifndef __NVBIOS_BIT_H__ +#define __NVBIOS_BIT_H__ + +struct bit_entry { + u8 id; + u8 version; + u16 length; + u16 offset; +}; + +int bit_entry(struct nouveau_bios *, u8 id, struct bit_entry *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/bmp.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/bmp.h new file mode 100644 index 0000000..10e4dbc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/bmp.h @@ -0,0 +1,39 @@ +#ifndef __NVBIOS_BMP_H__ +#define __NVBIOS_BMP_H__ + +static inline u16 +bmp_version(struct nouveau_bios *bios) +{ + if (bios->bmp_offset) { + return nv_ro08(bios, bios->bmp_offset + 5) << 8 | + nv_ro08(bios, bios->bmp_offset + 6); + } + + return 0x0000; +} + +static inline u16 +bmp_mem_init_table(struct nouveau_bios *bios) +{ + if (bmp_version(bios) >= 0x0300) + return nv_ro16(bios, bios->bmp_offset + 24); + return 0x0000; +} + +static inline u16 +bmp_sdr_seq_table(struct nouveau_bios *bios) +{ + if (bmp_version(bios) >= 0x0300) + return nv_ro16(bios, bios->bmp_offset + 26); + return 0x0000; +} + +static inline u16 +bmp_ddr_seq_table(struct nouveau_bios *bios) +{ + if (bmp_version(bios) >= 0x0300) + return nv_ro16(bios, bios->bmp_offset + 28); + return 0x0000; +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 3bfb478..76bdb0e 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -18,6 +18,8 @@ #include +#include + static inline int ffsll(u64 mask) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c new file mode 100644 index 0000000..e8e46ec --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -0,0 +1,451 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include + +#include +#include +#include + +u8 +nvbios_checksum(const u8 *data, int size) +{ + u8 sum = 0; + while (size--) + sum += *data++; + return sum; +} + +u16 +nvbios_findstr(const u8 *data, int size, const char *str, int len) +{ + int i, j; + + for (i = 0; i <= (size - len); i++) { + for (j = 0; j < len; j++) + if ((char)data[i + j] != str[j]) + break; + if (j == len) + return i; + } + + return 0; +} + +static void +nouveau_bios_shadow_pramin(struct nouveau_bios *bios) +{ + struct nouveau_device *device = nv_device(bios); + u32 bar0 = 0; + int i; + + if (device->card_type >= NV_50) { + u64 addr = (u64)(nv_rd32(bios, 0x619f04) & 0xffffff00) << 8; + if (!addr) { + addr = (u64)nv_rd32(bios, 0x001700) << 16; + addr += 0xf0000; + } + + bar0 = nv_mask(bios, 0x001700, 0xffffffff, addr >> 16); + } + + /* bail if no rom signature */ + if (nv_rd08(bios, 0x700000) != 0x55 || + nv_rd08(bios, 0x700001) != 0xaa) + goto out; + + bios->size = nv_rd08(bios, 0x700002) * 512; + bios->data = kmalloc(bios->size, GFP_KERNEL); + if (bios->data) { + for (i = 0; i < bios->size; i++) + nv_wo08(bios, i, nv_rd08(bios, 0x700000 + i)); + } + +out: + if (device->card_type >= NV_50) + nv_wr32(bios, 0x001700, bar0); +} + +static void +nouveau_bios_shadow_prom(struct nouveau_bios *bios) +{ + struct nouveau_device *device = nv_device(bios); + u32 pcireg, access; + u16 pcir; + int i; + + /* enable access to rom */ + if (device->card_type >= NV_50) + pcireg = 0x088050; + else + pcireg = 0x001850; + access = nv_mask(bios, pcireg, 0x00000001, 0x00000000); + + /* bail if no rom signature, with a workaround for a PROM reading + * issue on some chipsets. the first read after a period of + * inactivity returns the wrong result, so retry the first header + * byte a few times before giving up as a workaround + */ + i = 16; + do { + if (nv_rd08(bios, 0x300000) == 0x55) + break; + } while (i--); + + if (!i || nv_rd08(bios, 0x300001) != 0xaa) + goto out; + + /* additional check (see note below) - read PCI record header */ + pcir = nv_rd08(bios, 0x300018) | + nv_rd08(bios, 0x300019) << 8; + if (nv_rd08(bios, 0x300000 + pcir) != 'P' || + nv_rd08(bios, 0x300001 + pcir) != 'C' || + nv_rd08(bios, 0x300002 + pcir) != 'I' || + nv_rd08(bios, 0x300003 + pcir) != 'R') + goto out; + + /* read entire bios image to system memory */ + bios->size = nv_rd08(bios, 0x300002) * 512; + bios->data = kmalloc(bios->size, GFP_KERNEL); + if (bios->data) { + for (i = 0; i < bios->size; i++) + nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i)); + } + +out: + /* disable access to rom */ + nv_wr32(bios, pcireg, access); +} + +#if defined(CONFIG_ACPI) +int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); +bool nouveau_acpi_rom_supported(struct pci_dev *pdev); +#else +static inline bool +nouveau_acpi_rom_supported(struct pci_dev *pdev) { + return false; +} + +static inline int +nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { + return -EINVAL; +} +#endif + +static void +nouveau_bios_shadow_acpi(struct nouveau_bios *bios) +{ + struct pci_dev *pdev = nv_device(bios)->pdev; + int cnt = 65536 / 4096; + int ret; + + if (!nouveau_acpi_rom_supported(pdev)) + return; + + bios->data = kmalloc(65536, GFP_KERNEL); + bios->size = 0; + if (!bios->data) + return; + + while (cnt--) { + ret = nouveau_acpi_get_bios_chunk(bios->data, bios->size, 4096); + if (ret != 4096) + return; + + bios->size += 4096; + } +} + +static void +nouveau_bios_shadow_pci(struct nouveau_bios *bios) +{ + struct pci_dev *pdev = nv_device(bios)->pdev; + size_t size; + + if (!pci_enable_rom(pdev)) { + void __iomem *rom = pci_map_rom(pdev, &size); + if (rom && size) { + bios->data = kmalloc(size, GFP_KERNEL); + if (bios->data) { + memcpy_fromio(bios->data, rom, size); + bios->size = size; + } + } + if (rom) + pci_unmap_rom(pdev, rom); + + pci_disable_rom(pdev); + } +} + +static int +nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) +{ + if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { + nv_info(bios, "... signature not found\n"); + return 0; + } + + if (nvbios_checksum(bios->data, bios->data[2] * 512)) { + nv_info(bios, "... checksum invalid\n"); + /* if a ro image is somewhat bad, it's probably all rubbish */ + return writeable ? 2 : 1; + } + + nv_info(bios, "... appears to be valid\n"); + return 3; +} + +struct methods { + const char desc[8]; + void (*shadow)(struct nouveau_bios *); + const bool rw; + int score; + u32 size; + u8 *data; +}; + +static int +nouveau_bios_shadow(struct nouveau_bios *bios) +{ + struct methods shadow_methods[] = { + { "PRAMIN", nouveau_bios_shadow_pramin, true, 0, 0, NULL }, + { "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL }, + { "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL }, + { "PCIROM", nouveau_bios_shadow_pci, true, 0, 0, NULL }, + {} + }; + struct methods *mthd, *best; + const struct firmware *fw; + const char *optarg; + int optlen, ret; + char *source; + + optarg = nouveau_stropt(nv_device(bios)->cfgopt, "NvBios", &optlen); + source = optarg ? kstrndup(optarg, optlen, GFP_KERNEL) : NULL; + if (source) { + /* try to match one of the built-in methods */ + mthd = shadow_methods; + do { + if (strcasecmp(source, mthd->desc)) + continue; + nv_info(bios, "source: %s\n", mthd->desc); + + mthd->shadow(bios); + mthd->score = nouveau_bios_score(bios, mthd->rw); + if (mthd->score) { + kfree(source); + return 0; + } + } while ((++mthd)->shadow); + + /* attempt to load firmware image */ + ret = request_firmware(&fw, source, &nv_device(bios)->pdev->dev); + if (ret == 0) { + bios->size = fw->size; + bios->data = kmemdup(fw->data, fw->size, GFP_KERNEL); + release_firmware(fw); + + nv_info(bios, "image: %s\n", source); + if (nouveau_bios_score(bios, 1)) { + kfree(source); + return 0; + } + + kfree(bios->data); + bios->data = NULL; + } + + nv_error(bios, "source \'%s\' invalid\n", source); + kfree(source); + } + + mthd = shadow_methods; + do { + nv_info(bios, "checking %s for image...\n", mthd->desc); + mthd->shadow(bios); + mthd->score = nouveau_bios_score(bios, mthd->rw); + mthd->size = bios->size; + mthd->data = bios->data; + bios->data = NULL; + } while (mthd->score != 3 && (++mthd)->shadow); + + mthd = shadow_methods; + best = mthd; + do { + if (mthd->score > best->score) { + kfree(best->data); + best = mthd; + } + } while ((++mthd)->shadow); + + if (best->score) { + nv_info(bios, "using image from %s\n", best->desc); + bios->size = best->size; + bios->data = best->data; + return 0; + } + + nv_error(bios, "unable to locate usable image\n"); + return -EINVAL; +} + +static u8 +nouveau_bios_rd08(struct nouveau_object *object, u32 addr) +{ + struct nouveau_bios *bios = (void *)object; + return bios->data[addr]; +} + +static u16 +nouveau_bios_rd16(struct nouveau_object *object, u32 addr) +{ + struct nouveau_bios *bios = (void *)object; + return get_unaligned_le16(&bios->data[addr]); +} + +static u32 +nouveau_bios_rd32(struct nouveau_object *object, u32 addr) +{ + struct nouveau_bios *bios = (void *)object; + return get_unaligned_le32(&bios->data[addr]); +} + +static void +nouveau_bios_wr08(struct nouveau_object *object, u32 addr, u8 data) +{ + struct nouveau_bios *bios = (void *)object; + bios->data[addr] = data; +} + +static void +nouveau_bios_wr16(struct nouveau_object *object, u32 addr, u16 data) +{ + struct nouveau_bios *bios = (void *)object; + put_unaligned_le16(data, &bios->data[addr]); +} + +static void +nouveau_bios_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nouveau_bios *bios = (void *)object; + put_unaligned_le32(data, &bios->data[addr]); +} + +static int +nouveau_bios_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bios *bios; + struct bit_entry bit_i; + int ret; + + ret = nouveau_subdev_create(parent, engine, oclass, 0, + "VBIOS", "bios", &bios); + *pobject = nv_object(bios); + if (ret) + return ret; + + ret = nouveau_bios_shadow(bios); + if (ret) + return ret; + + /* detect type of vbios we're dealing with */ + bios->bmp_offset = nvbios_findstr(bios->data, bios->size, + "\xff\x7f""NV\0", 5); + if (bios->bmp_offset) { + nv_info(bios, "BMP version %x.%x\n", + bmp_version(bios) >> 8, + bmp_version(bios) & 0xff); + } + + bios->bit_offset = nvbios_findstr(bios->data, bios->size, + "\xff\xb8""BIT", 5); + if (bios->bit_offset) + nv_info(bios, "BIT signature found\n"); + + /* determine the vbios version number */ + if (!bit_entry(bios, 'i', &bit_i) && bit_i.length >= 4) { + bios->version.major = nv_ro08(bios, bit_i.offset + 3); + bios->version.chip = nv_ro08(bios, bit_i.offset + 2); + bios->version.minor = nv_ro08(bios, bit_i.offset + 1); + bios->version.micro = nv_ro08(bios, bit_i.offset + 0); + } else + if (bmp_version(bios)) { + bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); + bios->version.chip = nv_ro08(bios, bios->bmp_offset + 12); + bios->version.minor = nv_ro08(bios, bios->bmp_offset + 11); + bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); + } + + nv_info(bios, "version %02x.%02x.%02x.%02x\n", + bios->version.major, bios->version.chip, + bios->version.minor, bios->version.micro); + + return 0; +} + +static void +nouveau_bios_dtor(struct nouveau_object *object) +{ + struct nouveau_bios *bios = (void *)object; + kfree(bios->data); + nouveau_subdev_destroy(&bios->base); +} + +static int +nouveau_bios_init(struct nouveau_object *object) +{ + struct nouveau_bios *bios = (void *)object; + return nouveau_subdev_init(&bios->base); +} + +static int +nouveau_bios_fini(struct nouveau_object *object, bool suspend) +{ + struct nouveau_bios *bios = (void *)object; + return nouveau_subdev_fini(&bios->base, suspend); +} + +struct nouveau_oclass +nouveau_bios_oclass = { + .handle = NV_SUBDEV(VBIOS, 0x00), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nouveau_bios_ctor, + .dtor = nouveau_bios_dtor, + .init = nouveau_bios_init, + .fini = nouveau_bios_fini, + .rd08 = nouveau_bios_rd08, + .rd16 = nouveau_bios_rd16, + .rd32 = nouveau_bios_rd32, + .wr08 = nouveau_bios_wr08, + .wr16 = nouveau_bios_wr16, + .wr32 = nouveau_bios_wr32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/bit.c b/drivers/gpu/drm/nouveau/core/subdev/bios/bit.c new file mode 100644 index 0000000..1d03a3f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/bit.c @@ -0,0 +1,52 @@ +/* + * 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: + * + * 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 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 "core/object.h" + +#include "subdev/bios.h" +#include "subdev/bios/bit.h" + +int +bit_entry(struct nouveau_bios *bios, u8 id, struct bit_entry *bit) +{ + if (likely(bios->bit_offset)) { + u8 entries = nv_ro08(bios, bios->bit_offset + 10); + u32 entry = bios->bit_offset + 12; + while (entries--) { + if (nv_ro08(bios, entry + 0) == id) { + bit->id = nv_ro08(bios, entry + 0); + bit->version = nv_ro08(bios, entry + 1); + bit->length = nv_ro16(bios, entry + 2); + bit->offset = nv_ro16(bios, entry + 4); + return 0; + } + + entry += nv_ro08(bios, bios->bit_offset + 9); + } + + return -ENOENT; + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 8ded9d3..d54daa3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -23,14 +23,17 @@ */ #include +#include int nv04_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x04: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x05: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 04d14d1..f9e42887 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -23,26 +23,35 @@ */ #include +#include int nv10_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x10: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x15: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x16: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x1a: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x11: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x17: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x1f: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x18: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 1805bee..b5dfb7e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -23,18 +23,23 @@ */ #include +#include int nv20_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x20: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x25: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x28: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x2a: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 1e7a8b1..b2e50e3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -23,20 +23,26 @@ */ #include +#include int nv30_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x30: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x35: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x31: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x36: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x34: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 5c54f61..4a3e3a8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -23,42 +23,59 @@ */ #include +#include int nv40_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x40: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x41: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x42: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x43: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x45: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x47: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x49: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x4b: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x44: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x46: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x4a: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x4c: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x4e: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x63: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x67: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x68: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index a699bd9..018c711 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -23,38 +23,53 @@ */ #include +#include int nv50_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x50: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x84: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x86: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x92: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x94: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x96: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0x98: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xa0: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xaa: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xac: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xa3: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xa5: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xa8: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xaf: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 805268c..0e81277 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -23,26 +23,35 @@ */ #include +#include int nvc0_identify(struct nouveau_device *device) { switch (device->chipset) { case 0xc0: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xc4: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xc3: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xce: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xcf: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xc1: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xc8: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xd9: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 3c3fe69..15cae43 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -23,14 +23,17 @@ */ #include +#include int nve0_identify(struct nouveau_device *device) { switch (device->chipset) { case 0xe4: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; case 0xe7: + device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); -- cgit v1.1 From e0996aea4c349ba302b63203b7d5cab6034dbdca Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 12:20:17 +1000 Subject: drm/nouveau/gpio: port gpio to subdev interfaces v2: Ben Skeggs - rebase on top of v3.6-rc6 with gpio reset patch integrated already Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/include/subdev/bios/dcb.h | 19 ++ .../drm/nouveau/core/include/subdev/bios/gpio.h | 26 ++ drivers/gpu/drm/nouveau/core/include/subdev/gpio.h | 113 ++++--- drivers/gpu/drm/nouveau/core/os.h | 1 + drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c | 135 +++++++++ drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | 114 +++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | 329 +++++++-------------- drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c | 116 +++++--- drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | 179 ++++++----- drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c | 104 +++++++ drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | 2 +- 18 files changed, 807 insertions(+), 395 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h new file mode 100644 index 0000000..7000dcf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h @@ -0,0 +1,19 @@ +#ifndef __NVBIOS_DCB_H__ +#define __NVBIOS_DCB_H__ + +enum dcb_output_type { + DCB_OUTPUT_ANALOG = 0x0, + DCB_OUTPUT_TV = 0x1, + DCB_OUTPUT_TMDS = 0x2, + DCB_OUTPUT_LVDS = 0x3, + DCB_OUTPUT_DP = 0x4, + DCB_OUTPUT_EOL = 0xe, + DCB_OUTPUT_UNUSED = 0xf, +}; + +u16 dcb_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); +u16 dcb_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); +int dcb_outp_foreach(struct nouveau_bios *, void *data, int (*exec) + (struct nouveau_bios *, void *, int index, u16 entry)); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h new file mode 100644 index 0000000..e9789cf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h @@ -0,0 +1,26 @@ +#ifndef __NVBIOS_GPIO_H__ +#define __NVBIOS_GPIO_H__ + +struct nouveau_bios; + +enum dcb_gpio_func_name { + DCB_GPIO_PANEL_POWER = 0x01, + DCB_GPIO_TVDAC0 = 0x0c, + DCB_GPIO_TVDAC1 = 0x2d, + DCB_GPIO_PWM_FAN = 0x09, + DCB_GPIO_FAN_SENSE = 0x3d, + DCB_GPIO_UNUSED = 0xff +}; + +struct dcb_gpio_func { + u8 func; + u8 line; + u8 log[2]; +}; + +u16 dcb_gpio_table(struct nouveau_bios *); +u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver); +int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line, + struct dcb_gpio_func *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index 64c5cb0..9ea2b12 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h @@ -1,71 +1,64 @@ -/* - * Copyright 2011 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: - * - * 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 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. - */ - #ifndef __NOUVEAU_GPIO_H__ #define __NOUVEAU_GPIO_H__ -struct gpio_func { - u8 func; - u8 line; - u8 log[2]; -}; +#include +#include -/* nouveau_gpio.c */ -int nouveau_gpio_create(struct drm_device *); -void nouveau_gpio_destroy(struct drm_device *); -int nouveau_gpio_init(struct drm_device *); -void nouveau_gpio_fini(struct drm_device *); -void nouveau_gpio_reset(struct drm_device *); -int nouveau_gpio_drive(struct drm_device *, int idx, int line, - int dir, int out); -int nouveau_gpio_sense(struct drm_device *, int idx, int line); -int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line, - struct gpio_func *); -int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state); -int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line); -int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); -void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask); -int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, - void (*)(void *, int state), void *data); -void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, - void (*)(void *, int state), void *data); +#include +#include -static inline bool -nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) -{ - struct gpio_func func; - return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0; -} +struct nouveau_gpio { + struct nouveau_subdev base; -static inline int -nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) -{ - return nouveau_gpio_set(dev, 0, tag, 0xff, state); -} + /* hardware interfaces */ + void (*reset)(struct nouveau_gpio *); + int (*drive)(struct nouveau_gpio *, int line, int dir, int out); + int (*sense)(struct nouveau_gpio *, int line); + void (*irq_enable)(struct nouveau_gpio *, int line, bool); + + /* software interfaces */ + int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + struct dcb_gpio_func *); + int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); + int (*get)(struct nouveau_gpio *, int idx, u8 tag, u8 line); + int (*irq)(struct nouveau_gpio *, int idx, u8 tag, u8 line, bool on); -static inline int -nouveau_gpio_func_get(struct drm_device *dev, u8 tag) + /* interrupt handling */ + struct list_head isr; + spinlock_t lock; + + void (*isr_run)(struct nouveau_gpio *, int idx, u32 mask); + int (*isr_add)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); + void (*isr_del)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); +}; + +static inline struct nouveau_gpio * +nouveau_gpio(void *obj) { - return nouveau_gpio_get(dev, 0, tag, 0xff); + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO]; } +#define nouveau_gpio_create(p,e,o,d) \ + nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_gpio_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_gpio_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_gpio_init(struct nouveau_gpio *); + +extern struct nouveau_oclass nv10_gpio_oclass; +extern struct nouveau_oclass nv50_gpio_oclass; +extern struct nouveau_oclass nvd0_gpio_oclass; + +void nv50_gpio_dtor(struct nouveau_object *); +int nv50_gpio_init(struct nouveau_object *); +int nv50_gpio_fini(struct nouveau_object *, bool); +void nv50_gpio_intr(struct nouveau_subdev *); +void nv50_gpio_irq_enable(struct nouveau_gpio *, int line, bool); + #endif diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 76bdb0e..661b037 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -15,6 +15,7 @@ #include #include #include +#include #include diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c new file mode 100644 index 0000000..9ed6e72 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -0,0 +1,135 @@ +/* + * 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: + * + * 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 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 "core/device.h" + +#include "subdev/bios.h" +#include "subdev/bios/dcb.h" + +u16 +dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct nouveau_device *device = nv_device(bios); + u16 dcb = 0x0000; + + if (device->card_type > NV_04) + dcb = nv_ro16(bios, 0x36); + if (!dcb) { + nv_warn(bios, "DCB table not found\n"); + return dcb; + } + + *ver = nv_ro08(bios, dcb); + + if (*ver >= 0x41) { + nv_warn(bios, "DCB *ver 0x%02x unknown\n", *ver); + return 0x0000; + } else + if (*ver >= 0x30) { + if (nv_ro32(bios, dcb + 6) == 0x4edcbdcb) { + *hdr = nv_ro08(bios, dcb + 1); + *cnt = nv_ro08(bios, dcb + 2); + *len = nv_ro08(bios, dcb + 3); + return dcb; + } + } else + if (*ver >= 0x20) { + if (nv_ro32(bios, dcb + 4) == 0x4edcbdcb) { + u16 i2c = nv_ro16(bios, dcb + 2); + *hdr = 8; + *cnt = (i2c - dcb) / 8; + *len = 8; + return dcb; + } + } else + if (*ver >= 0x15) { + if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) { + u16 i2c = nv_ro16(bios, dcb + 2); + *hdr = 4; + *cnt = (i2c - dcb) / 10; + *len = 10; + return dcb; + } + } else { + /* + * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but + * always has the same single (crt) entry, even when tv-out + * present, so the conclusion is this version cannot really + * be used. + * + * v1.2 tables (some NV6/10, and NV15+) normally have the + * same 5 entries, which are not specific to the card and so + * no use. + * + * v1.2 does have an I2C table that read_dcb_i2c_table can + * handle, but cards exist (nv11 in #14821) with a bad i2c + * table pointer, so use the indices parsed in + * parse_bmp_structure. + * + * v1.1 (NV5+, maybe some NV4) is entirely unhelpful + */ + nv_warn(bios, "DCB contains no useful data\n"); + return 0x0000; + } + + nv_warn(bios, "DCB header validation failed\n"); + return 0x0000; +} + +u16 +dcb_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 dcb = dcb_table(bios, ver, &hdr, &cnt, len); + if (dcb && idx < cnt) + return dcb + hdr + (idx * *len); + return 0x0000; +} + +int +dcb_outp_foreach(struct nouveau_bios *bios, void *data, + int (*exec)(struct nouveau_bios *, void *, int, u16)) +{ + int ret, idx = -1; + u8 ver, len; + u16 outp; + + while ((outp = dcb_outp(bios, ++idx, &ver, &len))) { + if (nv_ro32(bios, outp) == 0x00000000) + break; /* seen on an NV11 with DCB v1.5 */ + if (nv_ro32(bios, outp) == 0xffffffff) + break; /* seen on an NV17 with DCB v2.0 */ + + if (nv_ro08(bios, outp) == DCB_OUTPUT_UNUSED) + continue; + if (nv_ro08(bios, outp) == DCB_OUTPUT_EOL) + break; + + ret = exec(bios, data, idx, outp); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c new file mode 100644 index 0000000..718267d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c @@ -0,0 +1,114 @@ +/* + * 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: + * + * 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 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 +#include +#include + +u16 +dcb_gpio_table(struct nouveau_bios *bios) +{ + u8 ver, hdr, cnt, len; + u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); + if (dcb) { + if (ver >= 0x30 && hdr >= 0x0c) + return nv_ro16(bios, dcb + 0x0a); + if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) + return nv_ro16(bios, dcb - 0x0f); + } + return 0x0000; +} + +u16 +dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver) +{ + u16 gpio = dcb_gpio_table(bios); + if (gpio) { + *ver = nv_ro08(bios, gpio); + if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2)) + return gpio + 3 + (ent * nv_ro08(bios, gpio + 1)); + else if (ent < nv_ro08(bios, gpio + 2)) + return gpio + nv_ro08(bios, gpio + 1) + + (ent * nv_ro08(bios, gpio + 3)); + } + return 0x0000; +} + +int +dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, + struct dcb_gpio_func *gpio) +{ + u8 ver, hdr, cnt, len; + u16 entry; + int i = -1; + + while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) { + if (ver < 0x40) { + u16 data = nv_ro16(bios, entry); + *gpio = (struct dcb_gpio_func) { + .line = (data & 0x001f) >> 0, + .func = (data & 0x07e0) >> 5, + .log[0] = (data & 0x1800) >> 11, + .log[1] = (data & 0x6000) >> 13, + }; + } else + if (ver < 0x41) { + u32 data = nv_ro32(bios, entry); + *gpio = (struct dcb_gpio_func) { + .line = (data & 0x0000001f) >> 0, + .func = (data & 0x0000ff00) >> 8, + .log[0] = (data & 0x18000000) >> 27, + .log[1] = (data & 0x60000000) >> 29, + }; + } else { + u32 data = nv_ro32(bios, entry + 0); + u8 data1 = nv_ro32(bios, entry + 4); + *gpio = (struct dcb_gpio_func) { + .line = (data & 0x0000003f) >> 0, + .func = (data & 0x0000ff00) >> 8, + .log[0] = (data1 & 0x30) >> 4, + .log[1] = (data1 & 0xc0) >> 6, + }; + } + + if ((line == 0xff || line == gpio->line) && + (func == 0xff || func == gpio->func)) + return 0; + } + + /* DCB 2.2, fixed TVDAC GPIO data */ + if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len)) && ver >= 0x22) { + if (func == DCB_GPIO_TVDAC0) { + *gpio = (struct dcb_gpio_func) { + .func = DCB_GPIO_TVDAC0, + .line = nv_ro08(bios, entry - 4) >> 4, + .log[0] = !!(nv_ro08(bios, entry - 5) & 2), + .log[1] = !(nv_ro08(bios, entry - 5) & 2), + }; + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index f9e42887..c0c40cd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -24,6 +24,7 @@ #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -31,27 +32,35 @@ nv10_identify(struct nouveau_device *device) switch (device->chipset) { case 0x10: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index b5dfb7e..1215e3f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -24,6 +24,7 @@ #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -31,15 +32,19 @@ nv20_identify(struct nouveau_device *device) switch (device->chipset) { case 0x20: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index b2e50e3..43eb94e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -24,6 +24,7 @@ #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -31,18 +32,23 @@ nv30_identify(struct nouveau_device *device) switch (device->chipset) { case 0x30: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 4a3e3a8..7c10a3c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -24,6 +24,7 @@ #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -31,51 +32,67 @@ nv40_identify(struct nouveau_device *device) switch (device->chipset) { case 0x40: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 018c711..581dcf1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -24,6 +24,7 @@ #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -31,45 +32,59 @@ nv50_identify(struct nouveau_device *device) switch (device->chipset) { case 0x50: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 0e81277..df31111 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -24,6 +24,7 @@ #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -31,27 +32,35 @@ nvc0_identify(struct nouveau_device *device) switch (device->chipset) { case 0xc0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 15cae43..d321cb4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -24,6 +24,7 @@ #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -31,9 +32,11 @@ nve0_identify(struct nouveau_device *device) switch (device->chipset) { case 0xe4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index 2c48309..abb135f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -22,114 +22,37 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include #include +#include +#include -static u8 * -dcb_gpio_table(struct drm_device *dev) +static int +nouveau_gpio_drive(struct nouveau_gpio *gpio, + int idx, int line, int dir, int out) { - u8 *dcb = dcb_table(dev); - if (dcb) { - if (dcb[0] >= 0x30 && dcb[1] >= 0x0c) - return ROMPTR(dev, dcb[0x0a]); - if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) - return ROMPTR(dev, dcb[-15]); - } - return NULL; -} - -static u8 * -dcb_gpio_entry(struct drm_device *dev, int idx, int ent, u8 *version) -{ - u8 *table = dcb_gpio_table(dev); - if (table) { - *version = table[0]; - if (*version < 0x30 && ent < table[2]) - return table + 3 + (ent * table[1]); - else if (ent < table[2]) - return table + table[1] + (ent * table[3]); - } - return NULL; + return gpio->drive ? gpio->drive(gpio, line, dir, out) : -ENODEV; } -int -nouveau_gpio_drive(struct drm_device *dev, int idx, int line, int dir, int out) +static int +nouveau_gpio_sense(struct nouveau_gpio *gpio, int idx, int line) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - return pgpio->drive ? pgpio->drive(dev, line, dir, out) : -ENODEV; + return gpio->sense ? gpio->sense(gpio, line) : -ENODEV; } -int -nouveau_gpio_sense(struct drm_device *dev, int idx, int line) +static int +nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, + struct dcb_gpio_func *func) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - return pgpio->sense ? pgpio->sense(dev, line) : -ENODEV; -} - -int -nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, - struct gpio_func *gpio) -{ - u8 *table, *entry, version; - int i = -1; - - if (line == 0xff && func == 0xff) + if (line == 0xff && tag == 0xff) return -EINVAL; - while ((entry = dcb_gpio_entry(dev, idx, ++i, &version))) { - if (version < 0x40) { - u16 data = ROM16(entry[0]); - *gpio = (struct gpio_func) { - .line = (data & 0x001f) >> 0, - .func = (data & 0x07e0) >> 5, - .log[0] = (data & 0x1800) >> 11, - .log[1] = (data & 0x6000) >> 13, - }; - } else - if (version < 0x41) { - *gpio = (struct gpio_func) { - .line = entry[0] & 0x1f, - .func = entry[1], - .log[0] = (entry[3] & 0x18) >> 3, - .log[1] = (entry[3] & 0x60) >> 5, - }; - } else { - *gpio = (struct gpio_func) { - .line = entry[0] & 0x3f, - .func = entry[1], - .log[0] = (entry[4] & 0x30) >> 4, - .log[1] = (entry[4] & 0xc0) >> 6, - }; - } - - if ((line == 0xff || line == gpio->line) && - (func == 0xff || func == gpio->func)) - return 0; - } - - /* DCB 2.2, fixed TVDAC GPIO data */ - if ((table = dcb_table(dev)) && table[0] >= 0x22) { - if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct gpio_func) { - .func = DCB_GPIO_TVDAC0, - .line = table[-4] >> 4, - .log[0] = !!(table[-5] & 2), - .log[1] = !(table[-5] & 2), - }; - return 0; - } - } + if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func)) + return 0; /* Apple iMac G4 NV18 */ - if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { - if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct gpio_func) { + if (nv_device_match(nv_object(gpio), 0x0189, 0x10de, 0x0010)) { + if (tag == DCB_GPIO_TVDAC0) { + *func = (struct dcb_gpio_func) { .func = DCB_GPIO_TVDAC0, .line = 4, .log[0] = 0, @@ -142,50 +65,48 @@ nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, return -EINVAL; } -int -nouveau_gpio_set(struct drm_device *dev, int idx, u8 tag, u8 line, int state) +static int +nouveau_gpio_set(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, int state) { - struct gpio_func gpio; + struct dcb_gpio_func func; int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - int dir = !!(gpio.log[state] & 0x02); - int out = !!(gpio.log[state] & 0x01); - ret = nouveau_gpio_drive(dev, idx, gpio.line, dir, out); + int dir = !!(func.log[state] & 0x02); + int out = !!(func.log[state] & 0x01); + ret = nouveau_gpio_drive(gpio, idx, func.line, dir, out); } return ret; } -int -nouveau_gpio_get(struct drm_device *dev, int idx, u8 tag, u8 line) +static int +nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line) { - struct gpio_func gpio; + struct dcb_gpio_func func; int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - ret = nouveau_gpio_sense(dev, idx, gpio.line); + ret = nouveau_gpio_sense(gpio, idx, func.line); if (ret >= 0) - ret = (ret == (gpio.log[1] & 1)); + ret = (ret == (func.log[1] & 1)); } return ret; } -int -nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) +static int +nouveau_gpio_irq(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, bool on) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct gpio_func gpio; + struct dcb_gpio_func func; int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - if (idx == 0 && pgpio->irq_enable) - pgpio->irq_enable(dev, gpio.line, on); + if (idx == 0 && gpio->irq_enable) + gpio->irq_enable(gpio, func.line, on); else ret = -ENODEV; } @@ -194,11 +115,11 @@ nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) } struct gpio_isr { - struct drm_device *dev; + struct nouveau_gpio *gpio; struct list_head head; struct work_struct work; int idx; - struct gpio_func func; + struct dcb_gpio_func func; void (*handler)(void *, int); void *data; bool inhibit; @@ -208,33 +129,30 @@ static void nouveau_gpio_isr_bh(struct work_struct *work) { struct gpio_isr *isr = container_of(work, struct gpio_isr, work); - struct drm_device *dev = isr->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nouveau_gpio *gpio = isr->gpio; unsigned long flags; int state; - state = nouveau_gpio_get(dev, isr->idx, isr->func.func, isr->func.line); + state = nouveau_gpio_get(gpio, isr->idx, isr->func.func, + isr->func.line); if (state >= 0) isr->handler(isr->data, state); - spin_lock_irqsave(&pgpio->lock, flags); + spin_lock_irqsave(&gpio->lock, flags); isr->inhibit = false; - spin_unlock_irqrestore(&pgpio->lock, flags); + spin_unlock_irqrestore(&gpio->lock, flags); } -void -nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) +static void +nouveau_gpio_isr_run(struct nouveau_gpio *gpio, int idx, u32 line_mask) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct gpio_isr *isr; if (idx != 0) return; - spin_lock(&pgpio->lock); - list_for_each_entry(isr, &pgpio->isr, head) { + spin_lock(&gpio->lock); + list_for_each_entry(isr, &gpio->isr, head) { if (line_mask & (1 << isr->func.line)) { if (isr->inhibit) continue; @@ -242,15 +160,13 @@ nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) schedule_work(&isr->work); } } - spin_unlock(&pgpio->lock); + spin_unlock(&gpio->lock); } -int -nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, +static int +nouveau_gpio_isr_add(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, void (*handler)(void *, int), void *data) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct gpio_isr *isr; unsigned long flags; int ret; @@ -259,47 +175,45 @@ nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, if (!isr) return -ENOMEM; - ret = nouveau_gpio_find(dev, idx, tag, line, &isr->func); + ret = nouveau_gpio_find(gpio, idx, tag, line, &isr->func); if (ret) { kfree(isr); return ret; } INIT_WORK(&isr->work, nouveau_gpio_isr_bh); - isr->dev = dev; + isr->gpio = gpio; isr->handler = handler; isr->data = data; isr->idx = idx; - spin_lock_irqsave(&pgpio->lock, flags); - list_add(&isr->head, &pgpio->isr); - spin_unlock_irqrestore(&pgpio->lock, flags); + spin_lock_irqsave(&gpio->lock, flags); + list_add(&isr->head, &gpio->isr); + spin_unlock_irqrestore(&gpio->lock, flags); return 0; } -void -nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, +static void +nouveau_gpio_isr_del(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, void (*handler)(void *, int), void *data) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct gpio_isr *isr, *tmp; - struct gpio_func func; + struct dcb_gpio_func func; unsigned long flags; LIST_HEAD(tofree); int ret; - ret = nouveau_gpio_find(dev, idx, tag, line, &func); + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); if (ret == 0) { - spin_lock_irqsave(&pgpio->lock, flags); - list_for_each_entry_safe(isr, tmp, &pgpio->isr, head) { + spin_lock_irqsave(&gpio->lock, flags); + list_for_each_entry_safe(isr, tmp, &gpio->isr, head) { if (memcmp(&isr->func, &func, sizeof(func)) || isr->idx != idx || isr->handler != handler || isr->data != data) continue; - list_move(&isr->head, &tofree); + list_move_tail(&isr->head, &tofree); } - spin_unlock_irqrestore(&pgpio->lock, flags); + spin_unlock_irqrestore(&gpio->lock, flags); list_for_each_entry_safe(isr, tmp, &tofree, head) { flush_work_sync(&isr->work); @@ -309,92 +223,49 @@ nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, } int -nouveau_gpio_create(struct drm_device *dev) +nouveau_gpio_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, int length, void **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nouveau_gpio *gpio; + int ret; - INIT_LIST_HEAD(&pgpio->isr); - spin_lock_init(&pgpio->lock); + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "GPIO", "gpio", + length, pobject); + gpio = *pobject; + if (ret) + return ret; - return nouveau_gpio_init(dev); + gpio->find = nouveau_gpio_find; + gpio->set = nouveau_gpio_set; + gpio->get = nouveau_gpio_get; + gpio->irq = nouveau_gpio_irq; + gpio->isr_run = nouveau_gpio_isr_run; + gpio->isr_add = nouveau_gpio_isr_add; + gpio->isr_del = nouveau_gpio_isr_del; + INIT_LIST_HEAD(&gpio->isr); + spin_lock_init(&gpio->lock); + return 0; } -void -nouveau_gpio_destroy(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - nouveau_gpio_fini(dev); - BUG_ON(!list_empty(&pgpio->isr)); -} +static struct dmi_system_id gpio_reset_ids[] = { + { + .ident = "Apple Macbook 10,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), + } + }, + { } +}; int -nouveau_gpio_init(struct drm_device *dev) +nouveau_gpio_init(struct nouveau_gpio *gpio) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - int ret = 0; - - if (pgpio->init) - ret = pgpio->init(dev); - - return ret; -} - -void -nouveau_gpio_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - if (pgpio->fini) - pgpio->fini(dev); -} - -void -nouveau_gpio_reset(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u8 *entry, version; - int ent = -1; - - while ((entry = dcb_gpio_entry(dev, 0, ++ent, &version))) { - u8 func = 0xff, line, defs, unk0, unk1; - if (version >= 0x41) { - defs = !!(entry[0] & 0x80); - line = entry[0] & 0x3f; - func = entry[1]; - unk0 = entry[2]; - unk1 = entry[3] & 0x1f; - } else - if (version >= 0x40) { - line = entry[0] & 0x1f; - func = entry[1]; - defs = !!(entry[3] & 0x01); - unk0 = !!(entry[3] & 0x02); - unk1 = !!(entry[3] & 0x04); - } else { - break; - } - - if (func == 0xff) - continue; - - nouveau_gpio_func_set(dev, func, defs); - - if (dev_priv->card_type >= NV_D0) { - nv_mask(dev, 0x00d610 + (line * 4), 0xff, unk0); - if (unk1--) - nv_mask(dev, 0x00d740 + (unk1 * 4), 0xff, line); - } else - if (dev_priv->card_type >= NV_50) { - static const u32 regs[] = { 0xe100, 0xe28c }; - u32 val = (unk1 << 16) | unk0; - u32 reg = regs[line >> 4]; line &= 0x0f; - - nv_mask(dev, reg, 0x00010001 << line, val << line); - } + int ret = nouveau_subdev_init(&gpio->base); + if (ret == 0 && gpio->reset) { + if (dmi_check_system(gpio_reset_ids)) + gpio->reset(gpio); } + return ret; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c index 42e600f..168d16a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c @@ -24,100 +24,146 @@ * */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_hw.h" #include -int -nv10_gpio_sense(struct drm_device *dev, int line) +struct nv10_gpio_priv { + struct nouveau_gpio base; +}; + +static int +nv10_gpio_sense(struct nouveau_gpio *gpio, int line) { if (line < 2) { line = line * 16; - line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line; + line = nv_rd32(gpio, 0x600818) >> line; return !!(line & 0x0100); } else if (line < 10) { line = (line - 2) * 4; - line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line; + line = nv_rd32(gpio, 0x60081c) >> line; return !!(line & 0x04); } else if (line < 14) { line = (line - 10) * 4; - line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line; + line = nv_rd32(gpio, 0x600850) >> line; return !!(line & 0x04); } return -EINVAL; } -int -nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out) +static int +nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) { u32 reg, mask, data; if (line < 2) { line = line * 16; - reg = NV_PCRTC_GPIO; + reg = 0x600818; mask = 0x00000011; data = (dir << 4) | out; } else if (line < 10) { line = (line - 2) * 4; - reg = NV_PCRTC_GPIO_EXT; + reg = 0x60081c; mask = 0x00000003; data = (dir << 1) | out; } else if (line < 14) { line = (line - 10) * 4; - reg = NV_PCRTC_850; + reg = 0x600850; mask = 0x00000003; data = (dir << 1) | out; } else { return -EINVAL; } - mask = NVReadCRTC(dev, 0, reg) & ~(mask << line); - NVWriteCRTC(dev, 0, reg, mask | (data << line)); + nv_mask(gpio, reg, mask << line, data << line); return 0; } -void -nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on) +static void +nv10_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) { u32 mask = 0x00010001 << line; - nv_wr32(dev, 0x001104, mask); - nv_mask(dev, 0x001144, mask, on ? mask : 0); + nv_wr32(gpio, 0x001104, mask); + nv_mask(gpio, 0x001144, mask, on ? mask : 0); } static void -nv10_gpio_isr(struct drm_device *dev) +nv10_gpio_intr(struct nouveau_subdev *subdev) { - u32 intr = nv_rd32(dev, 0x1104); + struct nv10_gpio_priv *priv = (void *)subdev; + u32 intr = nv_rd32(priv, 0x001104); u32 hi = (intr & 0x0000ffff) >> 0; u32 lo = (intr & 0xffff0000) >> 16; - nouveau_gpio_isr(dev, 0, hi | lo); + priv->base.isr_run(&priv->base, 0, hi | lo); - nv_wr32(dev, 0x001104, intr); + nv_wr32(priv, 0x001104, intr); } -int -nv10_gpio_init(struct drm_device *dev) +static int +nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nv_wr32(dev, 0x001140, 0x00000000); - nv_wr32(dev, 0x001100, 0xffffffff); - nv_wr32(dev, 0x001144, 0x00000000); - nv_wr32(dev, 0x001104, 0xffffffff); - nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */ + struct nv10_gpio_priv *priv; + int ret; + + ret = nouveau_gpio_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.drive = nv10_gpio_drive; + priv->base.sense = nv10_gpio_sense; + priv->base.irq_enable = nv10_gpio_irq_enable; + nv_subdev(priv)->intr = nv10_gpio_intr; return 0; } -void -nv10_gpio_fini(struct drm_device *dev) +static void +nv10_gpio_dtor(struct nouveau_object *object) { - nv_wr32(dev, 0x001140, 0x00000000); - nv_wr32(dev, 0x001144, 0x00000000); - nouveau_irq_unregister(dev, 28); + struct nv10_gpio_priv *priv = (void *)object; + nouveau_gpio_destroy(&priv->base); } + +static int +nv10_gpio_init(struct nouveau_object *object) +{ + struct nv10_gpio_priv *priv = (void *)object; + int ret; + + ret = nouveau_gpio_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, 0x001140, 0x00000000); + nv_wr32(priv, 0x001100, 0xffffffff); + nv_wr32(priv, 0x001144, 0x00000000); + nv_wr32(priv, 0x001104, 0xffffffff); + return 0; +} + +static int +nv10_gpio_fini(struct nouveau_object *object, bool suspend) +{ + struct nv10_gpio_priv *priv = (void *)object; + nv_wr32(priv, 0x001140, 0x00000000); + nv_wr32(priv, 0x001144, 0x00000000); + return nouveau_gpio_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv10_gpio_oclass = { + .handle = NV_SUBDEV(GPIO, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_gpio_ctor, + .dtor = nv10_gpio_dtor, + .init = nv10_gpio_init, + .fini = nv10_gpio_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index 48509b0..f3502c9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.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,18 +22,45 @@ * Authors: Ben Skeggs */ -#include -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_hw.h" #include -#include "nv50_display.h" +struct nv50_gpio_priv { + struct nouveau_gpio base; +}; + +static void +nv50_gpio_reset(struct nouveau_gpio *gpio) +{ + struct nouveau_bios *bios = nouveau_bios(gpio); + struct nv50_gpio_priv *priv = (void *)gpio; + u16 entry; + u8 ver; + int ent = -1; + + while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { + static const u32 regs[] = { 0xe100, 0xe28c }; + u32 data = nv_ro32(bios, entry); + u8 line = (data & 0x0000001f); + u8 func = (data & 0x0000ff00) >> 8; + u8 defs = !!(data & 0x01000000); + u8 unk0 = !!(data & 0x02000000); + u8 unk1 = !!(data & 0x04000000); + u32 val = (unk1 << 16) | unk0; + u32 reg = regs[line >> 4]; line &= 0x0f; + + if (func == 0xff) + continue; + + gpio->set(gpio, 0, func, line, defs); + + nv_mask(priv, reg, 0x00010001 << line, val << line); + } +} static int nv50_gpio_location(int line, u32 *reg, u32 *shift) { - const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + const u32 nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; if (line >= 32) return -EINVAL; @@ -43,113 +70,125 @@ nv50_gpio_location(int line, u32 *reg, u32 *shift) return 0; } -int -nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out) +static int +nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) { u32 reg, shift; if (nv50_gpio_location(line, ®, &shift)) return -EINVAL; - nv_mask(dev, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); + nv_mask(gpio, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); return 0; } -int -nv50_gpio_sense(struct drm_device *dev, int line) +static int +nv50_gpio_sense(struct nouveau_gpio *gpio, int line) { u32 reg, shift; if (nv50_gpio_location(line, ®, &shift)) return -EINVAL; - return !!(nv_rd32(dev, reg) & (4 << shift)); + return !!(nv_rd32(gpio, reg) & (4 << shift)); } void -nv50_gpio_irq_enable(struct drm_device *dev, int line, bool on) +nv50_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) { u32 reg = line < 16 ? 0xe050 : 0xe070; u32 mask = 0x00010001 << (line & 0xf); - nv_wr32(dev, reg + 4, mask); - nv_mask(dev, reg + 0, mask, on ? mask : 0); -} - -int -nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out) -{ - u32 data = ((dir ^ 1) << 13) | (out << 12); - nv_mask(dev, 0x00d610 + (line * 4), 0x00003000, data); - nv_mask(dev, 0x00d604, 0x00000001, 0x00000001); /* update? */ - return 0; -} - -int -nvd0_gpio_sense(struct drm_device *dev, int line) -{ - return !!(nv_rd32(dev, 0x00d610 + (line * 4)) & 0x00004000); + nv_wr32(gpio, reg + 4, mask); + nv_mask(gpio, reg + 0, mask, on ? mask : 0); } -static void -nv50_gpio_isr(struct drm_device *dev) +void +nv50_gpio_intr(struct nouveau_subdev *subdev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_gpio_priv *priv = (void *)subdev; u32 intr0, intr1 = 0; u32 hi, lo; - intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); - if (dev_priv->chipset >= 0x90) - intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); + if (nv_device(priv)->chipset >= 0x90) + intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); hi = (intr0 & 0x0000ffff) | (intr1 << 16); lo = (intr0 >> 16) | (intr1 & 0xffff0000); - nouveau_gpio_isr(dev, 0, hi | lo); + priv->base.isr_run(&priv->base, 0, hi | lo); - nv_wr32(dev, 0xe054, intr0); - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe074, intr1); + nv_wr32(priv, 0xe054, intr0); + if (nv_device(priv)->chipset >= 0x90) + nv_wr32(priv, 0xe074, intr1); } -static struct dmi_system_id gpio_reset_ids[] = { - { - .ident = "Apple Macbook 10,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), - } - }, - { } -}; +static int +nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_gpio_priv *priv; + int ret; + + ret = nouveau_gpio_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.reset = nv50_gpio_reset; + priv->base.drive = nv50_gpio_drive; + priv->base.sense = nv50_gpio_sense; + priv->base.irq_enable = nv50_gpio_irq_enable; + nv_subdev(priv)->intr = nv50_gpio_intr; + return 0; +} + +void +nv50_gpio_dtor(struct nouveau_object *object) +{ + struct nv50_gpio_priv *priv = (void *)object; + nouveau_gpio_destroy(&priv->base); +} int -nv50_gpio_init(struct drm_device *dev) +nv50_gpio_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_gpio_priv *priv = (void *)object; + int ret; - /* initialise gpios and routing to vbios defaults */ - if (dmi_check_system(gpio_reset_ids)) - nouveau_gpio_reset(dev); + ret = nouveau_gpio_init(&priv->base); + if (ret) + return ret; /* disable, and ack any pending gpio interrupts */ - nv_wr32(dev, 0xe050, 0x00000000); - nv_wr32(dev, 0xe054, 0xffffffff); - if (dev_priv->chipset >= 0x90) { - nv_wr32(dev, 0xe070, 0x00000000); - nv_wr32(dev, 0xe074, 0xffffffff); + nv_wr32(priv, 0xe050, 0x00000000); + nv_wr32(priv, 0xe054, 0xffffffff); + if (nv_device(priv)->chipset >= 0x90) { + nv_wr32(priv, 0xe070, 0x00000000); + nv_wr32(priv, 0xe074, 0xffffffff); } - nouveau_irq_register(dev, 21, nv50_gpio_isr); return 0; } -void -nv50_gpio_fini(struct drm_device *dev) +int +nv50_gpio_fini(struct nouveau_object *object, bool suspend) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nv_wr32(dev, 0xe050, 0x00000000); - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe070, 0x00000000); - nouveau_irq_unregister(dev, 21); + struct nv50_gpio_priv *priv = (void *)object; + nv_wr32(priv, 0xe050, 0x00000000); + if (nv_device(priv)->chipset >= 0x90) + nv_wr32(priv, 0xe070, 0x00000000); + return nouveau_gpio_fini(&priv->base, suspend); } + +struct nouveau_oclass +nv50_gpio_oclass = { + .handle = NV_SUBDEV(GPIO, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_gpio_ctor, + .dtor = nv50_gpio_dtor, + .init = nv50_gpio_init, + .fini = nv50_gpio_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c new file mode 100644 index 0000000..8d18fca --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c @@ -0,0 +1,104 @@ +/* + * 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: + * + * 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 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 + +struct nvd0_gpio_priv { + struct nouveau_gpio base; +}; + +static void +nvd0_gpio_reset(struct nouveau_gpio *gpio) +{ + struct nouveau_bios *bios = nouveau_bios(gpio); + struct nvd0_gpio_priv *priv = (void *)gpio; + u16 entry; + u8 ver; + int ent = -1; + + while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { + u32 data = nv_ro32(bios, entry); + u8 line = (data & 0x0000003f); + u8 defs = !!(data & 0x00000080); + u8 func = (data & 0x0000ff00) >> 8; + u8 unk0 = (data & 0x00ff0000) >> 16; + u8 unk1 = (data & 0x1f000000) >> 24; + + if (func == 0xff) + continue; + + gpio->set(gpio, 0, func, line, defs); + + nv_mask(priv, 0x00d610 + (line * 4), 0xff, unk0); + if (unk1--) + nv_mask(priv, 0x00d740 + (unk1 * 4), 0xff, line); + } +} + +static int +nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) +{ + u32 data = ((dir ^ 1) << 13) | (out << 12); + nv_mask(gpio, 0x00d610 + (line * 4), 0x00003000, data); + nv_mask(gpio, 0x00d604, 0x00000001, 0x00000001); /* update? */ + return 0; +} + +static int +nvd0_gpio_sense(struct nouveau_gpio *gpio, int line) +{ + return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); +} + +static int +nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvd0_gpio_priv *priv; + int ret; + + ret = nouveau_gpio_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.reset = nvd0_gpio_reset; + priv->base.drive = nvd0_gpio_drive; + priv->base.sense = nvd0_gpio_sense; + priv->base.irq_enable = nv50_gpio_irq_enable; + nv_subdev(priv)->intr = nv50_gpio_intr; + return 0; +} + +struct nouveau_oclass +nvd0_gpio_oclass = { + .handle = NV_SUBDEV(GPIO, 0xd0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvd0_gpio_ctor, + .dtor = nv50_gpio_dtor, + .init = nv50_gpio_init, + .fini = nv50_gpio_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 71e9361..740e399 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -118,7 +118,7 @@ static const uint32_t nv50_i2c_port[] = { static u8 * i2c_table(struct drm_device *dev, u8 *version) { - u8 *dcb = dcb_table(dev), *i2c = NULL; + u8 *dcb = olddcb_table(dev), *i2c = NULL; if (dcb) { if (dcb[0] >= 0x15) i2c = ROMPTR(dev, dcb[2]); -- cgit v1.1 From 4196faa8623264b79279a06fd186654c959f2767 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 14:36:38 +1000 Subject: drm/nouveau/i2c: port to subdev interfaces v2/v3: Ben Skeggs - fix typo in default bus selection - fix accidental loss of destructor v4: Dmitry Eremin-Solenikov - fix typo causing incorrect default i2c port settings when no BMP data Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/disp/vga.c | 214 ++++++++ .../gpu/drm/nouveau/core/include/subdev/bios/i2c.h | 25 + drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | 79 +-- drivers/gpu/drm/nouveau/core/include/subdev/vga.h | 28 ++ drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c | 129 +++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 + drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c | 212 ++++++++ drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | 547 +++++++++++---------- drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c | 230 +++++++++ 16 files changed, 1225 insertions(+), 306 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/vga.c create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/vga.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c new file mode 100644 index 0000000..cec2110 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c @@ -0,0 +1,214 @@ +/* + * 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: + * + * 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 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 +#include + +u8 +nv_rdport(void *obj, int head, u16 port) +{ + struct nouveau_device *device = nv_device(obj); + + if (device->card_type >= NV_50) + return nv_rd08(obj, 0x601000 + port); + + if (port == 0x03c0 || port == 0x03c1 || /* AR */ + port == 0x03c2 || port == 0x03da || /* INP0 */ + port == 0x03d4 || port == 0x03d5) /* CR */ + return nv_rd08(obj, 0x601000 + (head * 0x2000) + port); + + if (port == 0x03c2 || port == 0x03cc || /* MISC */ + port == 0x03c4 || port == 0x03c5 || /* SR */ + port == 0x03ce || port == 0x03cf) { /* GR */ + if (device->card_type < NV_40) + head = 0; /* CR44 selects head */ + return nv_rd08(obj, 0x0c0000 + (head * 0x2000) + port); + } + + nv_error(obj, "unknown vga port 0x%04x\n", port); + return 0x00; +} + +void +nv_wrport(void *obj, int head, u16 port, u8 data) +{ + struct nouveau_device *device = nv_device(obj); + + if (device->card_type >= NV_50) + nv_wr08(obj, 0x601000 + port, data); + else + if (port == 0x03c0 || port == 0x03c1 || /* AR */ + port == 0x03c2 || port == 0x03da || /* INP0 */ + port == 0x03d4 || port == 0x03d5) /* CR */ + nv_wr08(obj, 0x601000 + (head * 0x2000) + port, data); + else + if (port == 0x03c2 || port == 0x03cc || /* MISC */ + port == 0x03c4 || port == 0x03c5 || /* SR */ + port == 0x03ce || port == 0x03cf) { /* GR */ + if (device->card_type < NV_40) + head = 0; /* CR44 selects head */ + nv_wr08(obj, 0x0c0000 + (head * 0x2000) + port, data); + } else + nv_error(obj, "unknown vga port 0x%04x\n", port); +} + +u8 +nv_rdvgas(void *obj, int head, u8 index) +{ + nv_wrport(obj, head, 0x03c4, index); + return nv_rdport(obj, head, 0x03c5); +} + +void +nv_wrvgas(void *obj, int head, u8 index, u8 value) +{ + nv_wrport(obj, head, 0x03c4, index); + nv_wrport(obj, head, 0x03c5, value); +} + +u8 +nv_rdvgag(void *obj, int head, u8 index) +{ + nv_wrport(obj, head, 0x03ce, index); + return nv_rdport(obj, head, 0x03cf); +} + +void +nv_wrvgag(void *obj, int head, u8 index, u8 value) +{ + nv_wrport(obj, head, 0x03ce, index); + nv_wrport(obj, head, 0x03cf, value); +} + +u8 +nv_rdvgac(void *obj, int head, u8 index) +{ + nv_wrport(obj, head, 0x03d4, index); + return nv_rdport(obj, head, 0x03d5); +} + +void +nv_wrvgac(void *obj, int head, u8 index, u8 value) +{ + nv_wrport(obj, head, 0x03d4, index); + nv_wrport(obj, head, 0x03d5, value); +} + +u8 +nv_rdvgai(void *obj, int head, u16 port, u8 index) +{ + if (port == 0x03c4) return nv_rdvgas(obj, head, index); + if (port == 0x03ce) return nv_rdvgag(obj, head, index); + if (port == 0x03d4) return nv_rdvgac(obj, head, index); + nv_error(obj, "unknown indexed vga port 0x%04x\n", port); + return 0x00; +} + +void +nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value) +{ + if (port == 0x03c4) nv_wrvgas(obj, head, index, value); + else if (port == 0x03ce) nv_wrvgag(obj, head, index, value); + else if (port == 0x03d4) nv_wrvgac(obj, head, index, value); + else nv_error(obj, "unknown indexed vga port 0x%04x\n", port); +} + +bool +nv_lockvgac(void *obj, bool lock) +{ + bool locked = !nv_rdvgac(obj, 0, 0x1f); + u8 data = lock ? 0x99 : 0x57; + nv_wrvgac(obj, 0, 0x1f, data); + if (nv_device(obj)->chipset == 0x11) { + if (!(nv_rd32(obj, 0x001084) & 0x10000000)) + nv_wrvgac(obj, 1, 0x1f, data); + } + return locked; +} + +/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied) + * it affects only the 8 bit vga io regs, which we access using mmio at + * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d* + * in general, the set value of cr44 does not matter: reg access works as + * expected and values can be set for the appropriate head by using a 0x2000 + * offset as required + * however: + * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and + * cr44 must be set to 0 or 3 for accessing values on the correct head + * through the common 0xc03c* addresses + * b) in tied mode (4) head B is programmed to the values set on head A, and + * access using the head B addresses can have strange results, ergo we leave + * tied mode in init once we know to what cr44 should be restored on exit + * + * the owner parameter is slightly abused: + * 0 and 1 are treated as head values and so the set value is (owner * 3) + * other values are treated as literal values to set + */ +u8 +nv_rdvgaowner(void *obj) +{ + if (nv_device(obj)->card_type < NV_50) { + if (nv_device(obj)->chipset == 0x11) { + u32 tied = nv_rd32(obj, 0x001084) & 0x10000000; + if (tied == 0) { + u8 slA = nv_rdvgac(obj, 0, 0x28) & 0x80; + u8 tvA = nv_rdvgac(obj, 0, 0x33) & 0x01; + u8 slB = nv_rdvgac(obj, 1, 0x28) & 0x80; + u8 tvB = nv_rdvgac(obj, 1, 0x33) & 0x01; + if (slA && !tvA) return 0x00; + if (slB && !tvB) return 0x03; + if (slA) return 0x00; + if (slB) return 0x03; + return 0x00; + } + return 0x04; + } + + return nv_rdvgac(obj, 0, 0x44); + } + + nv_error(obj, "rdvgaowner after nv4x\n"); + return 0x00; +} + +void +nv_wrvgaowner(void *obj, u8 select) +{ + if (nv_device(obj)->card_type < NV_50) { + u8 owner = (select == 1) ? 3 : select; + if (nv_device(obj)->chipset == 0x11) { + /* workaround hw lockup bug */ + nv_rdvgac(obj, 0, 0x1f); + nv_rdvgac(obj, 1, 0x1f); + } + + nv_wrvgac(obj, 0, 0x44, owner); + + if (nv_device(obj)->chipset == 0x11) { + nv_wrvgac(obj, 0, 0x2e, owner); + nv_wrvgac(obj, 0, 0x2e, owner); + } + } else + nv_error(obj, "wrvgaowner after nv4x\n"); +} diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h new file mode 100644 index 0000000..5079bedf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h @@ -0,0 +1,25 @@ +#ifndef __NVBIOS_I2C_H__ +#define __NVBIOS_I2C_H__ + +struct nouveau_bios; + +enum dcb_i2c_type { + DCB_I2C_NV04_BIT = 0, + DCB_I2C_NV4E_BIT = 4, + DCB_I2C_NVIO_BIT = 5, + DCB_I2C_NVIO_AUX = 6, + DCB_I2C_UNUSED = 0xff +}; + +struct dcb_i2c_entry { + enum dcb_i2c_type type; + u8 drive; + u8 sense; + u32 data; +}; + +u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 dcb_i2c_entry(struct nouveau_bios *, u8 index, u8 *ver, u8 *len); +int dcb_i2c_parse(struct nouveau_bios *, u8 index, struct dcb_i2c_entry *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 1d08389..b93ab01 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -1,39 +1,18 @@ -/* - * Copyright 2009 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: - * - * 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 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. - */ - #ifndef __NOUVEAU_I2C_H__ #define __NOUVEAU_I2C_H__ -#include -#include -#include "drm_dp_helper.h" +#include +#include + +#include +#include #define NV_I2C_PORT(n) (0x00 + (n)) -#define NV_I2C_PORT_NUM 0x10 #define NV_I2C_DEFAULT(n) (0x80 + (n)) -struct nouveau_i2c_chan { +struct nouveau_i2c_port { struct i2c_adapter adapter; - struct drm_device *dev; + struct nouveau_i2c *i2c; struct i2c_algo_bit_data bit; struct list_head head; u8 index; @@ -44,16 +23,38 @@ struct nouveau_i2c_chan { u32 state; }; -int nouveau_i2c_init(struct drm_device *); -void nouveau_i2c_fini(struct drm_device *); -struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index); -bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); -int nouveau_i2c_identify(struct drm_device *dev, const char *what, - struct i2c_board_info *info, - bool (*match)(struct nouveau_i2c_chan *, - struct i2c_board_info *), - int index); +struct nouveau_i2c { + struct nouveau_subdev base; + + struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); + int (*identify)(struct nouveau_i2c *, int index, + const char *what, struct i2c_board_info *, + bool (*match)(struct nouveau_i2c_port *, + struct i2c_board_info *)); + struct list_head ports; +}; + +static inline struct nouveau_i2c * +nouveau_i2c(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; +} + +extern struct nouveau_oclass nouveau_i2c_oclass; + +void nouveau_i2c_drive_scl(void *, int); +void nouveau_i2c_drive_sda(void *, int); +int nouveau_i2c_sense_scl(void *); +int nouveau_i2c_sense_sda(void *); + +int nv_rdi2cr(struct nouveau_i2c_port *, u8 addr, u8 reg); +int nv_wri2cr(struct nouveau_i2c_port *, u8 addr, u8 reg, u8 val); +bool nv_probe_i2c(struct nouveau_i2c_port *, u8 addr); + +int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); +int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); -extern const struct i2c_algorithm nouveau_dp_i2c_algo; +extern const struct i2c_algorithm nouveau_i2c_bit_algo; +extern const struct i2c_algorithm nouveau_i2c_aux_algo; -#endif /* __NOUVEAU_I2C_H__ */ +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h new file mode 100644 index 0000000..d81df1a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h @@ -0,0 +1,28 @@ +#ifndef __NOUVEAU_VGA_H__ +#define __NOUVEAU_VGA_H__ + +/* access to various legacy io ports */ +u8 nv_rdport(void *obj, int head, u16 port); +void nv_wrport(void *obj, int head, u16 port, u8 value); + +/* VGA Sequencer */ +u8 nv_rdvgas(void *obj, int head, u8 index); +void nv_wrvgas(void *obj, int head, u8 index, u8 value); + +/* VGA Graphics */ +u8 nv_rdvgag(void *obj, int head, u8 index); +void nv_wrvgag(void *obj, int head, u8 index, u8 value); + +/* VGA CRTC */ +u8 nv_rdvgac(void *obj, int head, u8 index); +void nv_wrvgac(void *obj, int head, u8 index, u8 value); + +/* VGA indexed port access dispatcher */ +u8 nv_rdvgai(void *obj, int head, u16 port, u8 index); +void nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value); + +bool nv_lockvgac(void *obj, bool lock); +u8 nv_rdvgaowner(void *obj); +void nv_wrvgaowner(void *obj, u8); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c new file mode 100644 index 0000000..ad577db --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c @@ -0,0 +1,129 @@ +/* + * 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: + * + * 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 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 "subdev/bios.h" +#include "subdev/bios/dcb.h" +#include "subdev/bios/i2c.h" + +u16 +dcb_i2c_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + u16 i2c = 0x0000; + u16 dcb = dcb_table(bios, ver, hdr, cnt, len); + if (dcb) { + if (*ver >= 0x15) + i2c = nv_ro16(bios, dcb + 2); + if (*ver >= 0x30) + i2c = nv_ro16(bios, dcb + 4); + } + + if (i2c && *ver >= 0x30) { + *ver = nv_ro08(bios, i2c + 0); + *hdr = nv_ro08(bios, i2c + 1); + *cnt = nv_ro08(bios, i2c + 2); + *len = nv_ro08(bios, i2c + 3); + } else { + *ver = *ver; /* use DCB version */ + *hdr = 0; + *cnt = 16; + *len = 4; + } + + return i2c; +} + +u16 +dcb_i2c_entry(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 i2c = dcb_i2c_table(bios, ver, &hdr, &cnt, len); + if (i2c && idx < cnt) + return i2c + hdr + (idx * *len); + return 0x0000; +} + +int +dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info) +{ + u8 ver, len; + u16 ent = dcb_i2c_entry(bios, idx, &ver, &len); + if (ent) { + info->data = nv_ro32(bios, ent + 0); + info->type = nv_ro08(bios, ent + 3); + if (ver < 0x30) { + info->type &= 0x07; + if (info->type == 0x07) + info->type = 0xff; + } + + switch (info->type) { + case DCB_I2C_NV04_BIT: + info->drive = nv_ro08(bios, ent + 0); + info->sense = nv_ro08(bios, ent + 1); + return 0; + case DCB_I2C_NV4E_BIT: + info->drive = nv_ro08(bios, ent + 1); + return 0; + case DCB_I2C_NVIO_BIT: + case DCB_I2C_NVIO_AUX: + info->drive = nv_ro08(bios, ent + 0); + return 0; + case DCB_I2C_UNUSED: + return 0; + default: + nv_warn(bios, "unknown i2c type %d\n", info->type); + info->type = DCB_I2C_UNUSED; + return 0; + } + } + + if (bios->bmp_offset && idx < 2) { + /* BMP (from v4.0 has i2c info in the structure, it's in a + * fixed location on earlier VBIOS + */ + if (nv_ro08(bios, bios->bmp_offset + 5) < 4) + ent = 0x0048; + else + ent = 0x0036 + bios->bmp_offset; + + if (idx == 0) { + info->drive = nv_ro08(bios, ent + 4); + if (!info->drive) info->drive = 0x3f; + info->sense = nv_ro08(bios, ent + 5); + if (!info->sense) info->sense = 0x3e; + } else + if (idx == 1) { + info->drive = nv_ro08(bios, ent + 6); + if (!info->drive) info->drive = 0x37; + info->sense = nv_ro08(bios, ent + 7); + if (!info->sense) info->sense = 0x36; + } + + info->type = DCB_I2C_NV04_BIT; + return 0; + } + + return -ENOENT; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index d54daa3..e0ebbe1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -24,6 +24,7 @@ #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -31,9 +32,11 @@ nv04_identify(struct nouveau_device *device) switch (device->chipset) { case 0x04: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index c0c40cd..19b1de6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -33,34 +34,42 @@ nv10_identify(struct nouveau_device *device) case 0x10: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 1215e3f..8f73527 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -33,18 +34,22 @@ nv20_identify(struct nouveau_device *device) case 0x20: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 43eb94e..eefc345 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -33,22 +34,27 @@ nv30_identify(struct nouveau_device *device) case 0x30: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 7c10a3c..63047c5b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -33,66 +34,82 @@ nv40_identify(struct nouveau_device *device) case 0x40: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 581dcf1..9f4f6ef 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -33,58 +34,72 @@ nv50_identify(struct nouveau_device *device) case 0x50: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index df31111..f941024 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -25,6 +25,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -33,34 +34,42 @@ nvc0_identify(struct nouveau_device *device) case 0xc0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index d321cb4..21763cf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -25,6 +25,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -33,10 +34,12 @@ nve0_identify(struct nouveau_device *device) case 0xe4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c new file mode 100644 index 0000000..fe1ebf1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c @@ -0,0 +1,212 @@ +/* + * Copyright 2009 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: + * + * 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 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 + +/****************************************************************************** + * aux channel util functions + *****************************************************************************/ +#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) +#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) + +static void +auxch_fini(struct nouveau_i2c *aux, int ch) +{ + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); +} + +static int +auxch_init(struct nouveau_i2c *aux, int ch) +{ + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; + + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("begin idle timeout 0x%08x", ctrl); + return -EBUSY; + } + } while (ctrl & 0x03010000); + + /* set some magic, and wait up to 1ms for it to appear */ + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("magic wait 0x%08x\n", ctrl); + auxch_fini(aux, ch); + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); + + return 0; +} + +static int +auxch_tx(struct nouveau_i2c *aux, int ch, u8 type, u32 addr, u8 *data, u8 size) +{ + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; + + AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + + ret = auxch_init(aux, ch); + if (ret) + goto out; + + stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); + if (!(stat & 0x10000000)) { + AUX_DBG("sink not detected\n"); + ret = -ENXIO; + goto out; + } + + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { + AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); + nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); + } + } + + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); + + /* retry transaction a number of times on failure... */ + ret = -EREMOTEIO; + for (retries = 0; retries < 32; retries++) { + /* reset, and delay a while if this is a retry */ + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); + if (retries) + udelay(400); + + /* transaction request, wait up to 1ms for it to complete */ + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); + + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("tx req timeout 0x%08x\n", ctrl); + goto out; + } + } while (ctrl & 0x00010000); + + /* read status, and check if transaction completed ok */ + stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); + if (!(stat & 0x000f0f00)) { + ret = 0; + break; + } + + AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); + } + + if (type & 1) { + for (i = 0; i < 16; i += 4) { + xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); + AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); + } + memcpy(data, xbuf, size); + } + +out: + auxch_fini(aux, ch); + return ret; +} + +int +nv_rdaux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) +{ + return auxch_tx(auxch->i2c, auxch->drive, 9, addr, data, size); +} + +int +nv_wraux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) +{ + return auxch_tx(auxch->i2c, auxch->drive, 8, addr, data, size); +} + +static int +aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct nouveau_i2c_port *auxch = (struct nouveau_i2c_port *)adap; + struct i2c_msg *msg = msgs; + int ret, mcnt = num; + + while (mcnt--) { + u8 remaining = msg->len; + u8 *ptr = msg->buf; + + while (remaining) { + u8 cnt = (remaining > 16) ? 16 : remaining; + u8 cmd; + + if (msg->flags & I2C_M_RD) + cmd = 1; + else + cmd = 0; + + if (mcnt || remaining > 16) + cmd |= 4; /* MOT */ + + ret = auxch_tx(auxch->i2c, auxch->drive, cmd, + msg->addr, ptr, cnt); + if (ret < 0) + return ret; + + ptr += cnt; + remaining -= cnt; + } + + msg++; + } + + return num; +} + +static u32 +aux_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +const struct i2c_algorithm nouveau_i2c_aux_algo = { + .master_xfer = aux_xfer, + .functionality = aux_func +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 740e399..3d2c883 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -1,5 +1,5 @@ /* - * Copyright 2009 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,204 +22,277 @@ * Authors: Ben Skeggs */ -#include +#include "core/option.h" -#include "drmP.h" -#include "nouveau_drv.h" -#include -#include "nouveau_hw.h" +#include "subdev/i2c.h" +#include "subdev/vga.h" -static void -i2c_drive_scl(void *data, int state) +int +nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) +{ + u8 val; + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, + }; + + int ret = i2c_transfer(&port->adapter, msgs, 2); + if (ret != 2) + return -EIO; + + return val; +} + +int +nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) +{ + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = addr, .flags = 0, .len = 1, .buf = &val }, + }; + + int ret = i2c_transfer(&port->adapter, msgs, 2); + if (ret != 2) + return -EIO; + + return 0; +} + +bool +nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) +{ + u8 buf[] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = buf, + }, + { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + return i2c_transfer(&port->adapter, msgs, 2) == 2; +} + +static struct nouveau_i2c_port * +nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index) +{ + struct nouveau_bios *bios = nouveau_bios(i2c); + struct nouveau_i2c_port *port; + + if (index == NV_I2C_DEFAULT(0) || + index == NV_I2C_DEFAULT(1)) { + u8 ver, hdr, cnt, len; + u16 i2c = dcb_i2c_table(bios, &ver, &hdr, &cnt, &len); + if (i2c && ver >= 0x30) { + u8 auxidx = nv_ro08(bios, i2c + 4); + if (index == NV_I2C_DEFAULT(0)) + index = (auxidx & 0x0f) >> 0; + else + index = (auxidx & 0xf0) >> 4; + } else { + index = 2; + } + } + + list_for_each_entry(port, &i2c->ports, head) { + if (port->index == index) + break; + } + + if (&port->head == &i2c->ports) + return NULL; + + if (nv_device(i2c)->card_type >= NV_50 && (port->dcb & 0x00000100)) { + u32 reg = 0x00e500, val; + if (port->type == 6) { + reg += port->drive * 0x50; + val = 0x2002; + } else { + reg += ((port->dcb & 0x1e00) >> 9) * 0x50; + val = 0xe001; + } + + /* nfi, but neither auxch or i2c work if it's 1 */ + nv_mask(i2c, reg + 0x0c, 0x00000001, 0x00000000); + /* nfi, but switches auxch vs normal i2c */ + nv_mask(i2c, reg + 0x00, 0x0000f003, val); + } + + return port; +} + +static int +nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, + struct i2c_board_info *info, + bool (*match)(struct nouveau_i2c_port *, + struct i2c_board_info *)) { - struct nouveau_i2c_chan *port = data; - if (port->type == 0) { - u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); + int i; + + if (!port) { + nv_debug(i2c, "no bus when probing %s on %d\n", what, index); + return -ENODEV; + } + + nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index); + for (i = 0; info[i].addr; i++) { + if (nv_probe_i2c(port, info[i].addr) && + (!match || match(port, &info[i]))) { + nv_info(i2c, "detected %s: %s\n", what, info[i].type); + return i; + } + } + + nv_debug(i2c, "no devices found.\n"); + return -ENODEV; +} + +void +nouveau_i2c_drive_scl(void *data, int state) +{ + struct nouveau_i2c_port *port = data; + + if (port->type == DCB_I2C_NV04_BIT) { + u8 val = nv_rdvgac(port->i2c, 0, port->drive); if (state) val |= 0x20; else val &= 0xdf; - NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); } else - if (port->type == 4) { - nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01); + if (port->type == DCB_I2C_NV4E_BIT) { + nv_mask(port->i2c, port->drive, 0x2f, state ? 0x21 : 0x01); } else - if (port->type == 5) { + if (port->type == DCB_I2C_NVIO_BIT) { if (state) port->state |= 0x01; else port->state &= 0xfe; - nv_wr32(port->dev, port->drive, 4 | port->state); + nv_wr32(port->i2c, port->drive, 4 | port->state); } } -static void -i2c_drive_sda(void *data, int state) +void +nouveau_i2c_drive_sda(void *data, int state) { - struct nouveau_i2c_chan *port = data; - if (port->type == 0) { - u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); + struct nouveau_i2c_port *port = data; + + if (port->type == DCB_I2C_NV04_BIT) { + u8 val = nv_rdvgac(port->i2c, 0, port->drive); if (state) val |= 0x10; else val &= 0xef; - NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); + nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); } else - if (port->type == 4) { - nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01); + if (port->type == DCB_I2C_NV4E_BIT) { + nv_mask(port->i2c, port->drive, 0x1f, state ? 0x11 : 0x01); } else - if (port->type == 5) { + if (port->type == DCB_I2C_NVIO_BIT) { if (state) port->state |= 0x02; else port->state &= 0xfd; - nv_wr32(port->dev, port->drive, 4 | port->state); + nv_wr32(port->i2c, port->drive, 4 | port->state); } } -static int -i2c_sense_scl(void *data) +int +nouveau_i2c_sense_scl(void *data) { - struct nouveau_i2c_chan *port = data; - struct drm_nouveau_private *dev_priv = port->dev->dev_private; - if (port->type == 0) { - return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04); + struct nouveau_i2c_port *port = data; + struct nouveau_device *device = nv_device(port->i2c); + + if (port->type == DCB_I2C_NV04_BIT) { + return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x04); } else - if (port->type == 4) { - return !!(nv_rd32(port->dev, port->sense) & 0x00040000); + if (port->type == DCB_I2C_NV4E_BIT) { + return !!(nv_rd32(port->i2c, port->sense) & 0x00040000); } else - if (port->type == 5) { - if (dev_priv->card_type < NV_D0) - return !!(nv_rd32(port->dev, port->sense) & 0x01); + if (port->type == DCB_I2C_NVIO_BIT) { + if (device->card_type < NV_D0) + return !!(nv_rd32(port->i2c, port->sense) & 0x01); else - return !!(nv_rd32(port->dev, port->sense) & 0x10); + return !!(nv_rd32(port->i2c, port->sense) & 0x10); } + return 0; } -static int -i2c_sense_sda(void *data) +int +nouveau_i2c_sense_sda(void *data) { - struct nouveau_i2c_chan *port = data; - struct drm_nouveau_private *dev_priv = port->dev->dev_private; - if (port->type == 0) { - return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08); + struct nouveau_i2c_port *port = data; + struct nouveau_device *device = nv_device(port->i2c); + + if (port->type == DCB_I2C_NV04_BIT) { + return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x08); } else - if (port->type == 4) { - return !!(nv_rd32(port->dev, port->sense) & 0x00080000); + if (port->type == DCB_I2C_NV4E_BIT) { + return !!(nv_rd32(port->i2c, port->sense) & 0x00080000); } else - if (port->type == 5) { - if (dev_priv->card_type < NV_D0) - return !!(nv_rd32(port->dev, port->sense) & 0x02); + if (port->type == DCB_I2C_NVIO_BIT) { + if (device->card_type < NV_D0) + return !!(nv_rd32(port->i2c, port->sense) & 0x02); else - return !!(nv_rd32(port->dev, port->sense) & 0x20); + return !!(nv_rd32(port->i2c, port->sense) & 0x20); } + return 0; } -static const uint32_t nv50_i2c_port[] = { +static const u32 nv50_i2c_port[] = { 0x00e138, 0x00e150, 0x00e168, 0x00e180, 0x00e254, 0x00e274, 0x00e764, 0x00e780, 0x00e79c, 0x00e7b8 }; -static u8 * -i2c_table(struct drm_device *dev, u8 *version) -{ - u8 *dcb = olddcb_table(dev), *i2c = NULL; - if (dcb) { - if (dcb[0] >= 0x15) - i2c = ROMPTR(dev, dcb[2]); - if (dcb[0] >= 0x30) - i2c = ROMPTR(dev, dcb[4]); - } - - /* early revisions had no version number, use dcb version */ - if (i2c) { - *version = dcb[0]; - if (*version >= 0x30) - *version = i2c[0]; - } - - return i2c; -} - -int -nouveau_i2c_init(struct drm_device *dev) +static int +nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct nouveau_i2c_chan *port; - u8 version = 0x00, entries, recordlen; - u8 *i2c, *entry, legacy[2][4] = {}; - int ret, i; - - INIT_LIST_HEAD(&dev_priv->i2c_ports); - - i2c = i2c_table(dev, &version); - if (!i2c) { - u8 *bmp = &bios->data[bios->offset]; - if (bios->type != NVBIOS_BMP) - return -ENODEV; - - legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX; - legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX; - legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX; - legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX; - - /* BMP (from v4.0) has i2c info in the structure, it's in a - * fixed location on earlier VBIOS - */ - if (bmp[5] < 4) - i2c = &bios->data[0x48]; - else - i2c = &bmp[0x36]; - - if (i2c[4]) legacy[0][0] = i2c[4]; - if (i2c[5]) legacy[0][1] = i2c[5]; - if (i2c[6]) legacy[1][0] = i2c[6]; - if (i2c[7]) legacy[1][1] = i2c[7]; - } - - if (version >= 0x30) { - entry = i2c[1] + i2c; - entries = i2c[2]; - recordlen = i2c[3]; - } else - if (version) { - entry = i2c; - entries = 16; - recordlen = 4; - } else { - entry = legacy[0]; - entries = 2; - recordlen = 4; - } + struct nouveau_device *device = nv_device(parent); + struct nouveau_bios *bios = nouveau_bios(parent); + struct nouveau_i2c_port *port; + struct nouveau_i2c *i2c; + struct dcb_i2c_entry info; + int ret, i = -1; + + ret = nouveau_subdev_create(parent, engine, oclass, 0, + "I2C", "i2c", &i2c); + *pobject = nv_object(i2c); + if (ret) + return ret; + + i2c->find = nouveau_i2c_find; + i2c->identify = nouveau_i2c_identify; + INIT_LIST_HEAD(&i2c->ports); + + while (!dcb_i2c_parse(bios, ++i, &info)) { + if (info.type == DCB_I2C_UNUSED) + continue; - for (i = 0; i < entries; i++, entry += recordlen) { port = kzalloc(sizeof(*port), GFP_KERNEL); - if (port == NULL) { - nouveau_i2c_fini(dev); - return -ENOMEM; - } - - port->type = entry[3]; - if (version < 0x30) { - port->type &= 0x07; - if (port->type == 0x07) - port->type = 0xff; - } - - if (port->type == 0xff) { - kfree(port); - continue; + if (!port) { + nv_error(i2c, "failed port memory alloc at %d\n", i); + break; } + port->type = info.type; switch (port->type) { - case 0: /* NV04:NV50 */ - port->drive = entry[0]; - port->sense = entry[1]; + case DCB_I2C_NV04_BIT: + port->drive = info.drive; + port->sense = info.sense; break; - case 4: /* NV4E */ - port->drive = 0x600800 + entry[1]; + case DCB_I2C_NV4E_BIT: + port->drive = 0x600800 + info.drive; port->sense = port->drive; break; - case 5: /* NV50- */ - port->drive = entry[0] & 0x0f; - if (dev_priv->card_type < NV_D0) { - if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) + case DCB_I2C_NVIO_BIT: + port->drive = info.drive & 0x0f; + if (device->card_type < NV_D0) { + if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) break; port->drive = nv50_i2c_port[port->drive]; port->sense = port->drive; @@ -228,167 +301,107 @@ nouveau_i2c_init(struct drm_device *dev) port->sense = port->drive; } break; - case 6: /* NV50- DP AUX */ - port->drive = entry[0] & 0x0f; + case DCB_I2C_NVIO_AUX: + port->drive = info.drive & 0x0f; port->sense = port->drive; - port->adapter.algo = &nouveau_dp_i2c_algo; + port->adapter.algo = &nouveau_i2c_aux_algo; break; default: break; } if (!port->adapter.algo && !port->drive) { - NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", + nv_error(i2c, "I2C%d: type %d index %x/%x unknown\n", i, port->type, port->drive, port->sense); kfree(port); continue; } snprintf(port->adapter.name, sizeof(port->adapter.name), - "nouveau-%s-%d", pci_name(dev->pdev), i); + "nouveau-%s-%d", device->name, i); port->adapter.owner = THIS_MODULE; - port->adapter.dev.parent = &dev->pdev->dev; - port->dev = dev; + port->adapter.dev.parent = &device->pdev->dev; + port->i2c = i2c; port->index = i; - port->dcb = ROM32(entry[0]); + port->dcb = info.data; i2c_set_adapdata(&port->adapter, i2c); - if (port->adapter.algo != &nouveau_dp_i2c_algo) { - port->adapter.algo_data = &port->bit; - port->bit.udelay = 10; - port->bit.timeout = usecs_to_jiffies(2200); - port->bit.data = port; - port->bit.setsda = i2c_drive_sda; - port->bit.setscl = i2c_drive_scl; - port->bit.getsda = i2c_sense_sda; - port->bit.getscl = i2c_sense_scl; - - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 1); - i2c_drive_scl(port, 1); - - ret = i2c_bit_add_bus(&port->adapter); + if (port->adapter.algo != &nouveau_i2c_aux_algo) { + nouveau_i2c_drive_scl(port, 0); + nouveau_i2c_drive_sda(port, 1); + nouveau_i2c_drive_scl(port, 1); + +#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT + if (nouveau_boolopt(device->cfgopt, "NvI2C", true)) { +#else + if (nouveau_boolopt(device->cfgopt, "NvI2C", false)) { +#endif + port->adapter.algo = &nouveau_i2c_bit_algo; + ret = i2c_add_adapter(&port->adapter); + } else { + port->adapter.algo_data = &port->bit; + port->bit.udelay = 10; + port->bit.timeout = usecs_to_jiffies(2200); + port->bit.data = port; + port->bit.setsda = nouveau_i2c_drive_sda; + port->bit.setscl = nouveau_i2c_drive_scl; + port->bit.getsda = nouveau_i2c_sense_sda; + port->bit.getscl = nouveau_i2c_sense_scl; + ret = i2c_bit_add_bus(&port->adapter); + } } else { - port->adapter.algo = &nouveau_dp_i2c_algo; + port->adapter.algo = &nouveau_i2c_aux_algo; ret = i2c_add_adapter(&port->adapter); } if (ret) { - NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); + nv_error(i2c, "I2C%d: failed register: %d\n", i, ret); kfree(port); continue; } - list_add_tail(&port->head, &dev_priv->i2c_ports); + list_add_tail(&port->head, &i2c->ports); } return 0; } -void -nouveau_i2c_fini(struct drm_device *dev) +static void +nouveau_i2c_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *port, *tmp; + struct nouveau_i2c *i2c = (void *)object; + struct nouveau_i2c_port *port, *temp; - list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) { + list_for_each_entry_safe(port, temp, &i2c->ports, head) { i2c_del_adapter(&port->adapter); + list_del(&port->head); kfree(port); } -} - -struct nouveau_i2c_chan * -nouveau_i2c_find(struct drm_device *dev, u8 index) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *port; - - if (index == NV_I2C_DEFAULT(0) || - index == NV_I2C_DEFAULT(1)) { - u8 version, *i2c = i2c_table(dev, &version); - if (i2c && version >= 0x30) { - if (index == NV_I2C_DEFAULT(0)) - index = (i2c[4] & 0x0f); - else - index = (i2c[4] & 0xf0) >> 4; - } else { - index = 2; - } - } - - list_for_each_entry(port, &dev_priv->i2c_ports, head) { - if (port->index == index) - break; - } - - if (&port->head == &dev_priv->i2c_ports) - return NULL; - if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { - u32 reg = 0x00e500, val; - if (port->type == 6) { - reg += port->drive * 0x50; - val = 0x2002; - } else { - reg += ((port->dcb & 0x1e00) >> 9) * 0x50; - val = 0xe001; - } - - /* nfi, but neither auxch or i2c work if it's 1 */ - nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); - /* nfi, but switches auxch vs normal i2c */ - nv_mask(dev, reg + 0x00, 0x0000f003, val); - } - - return port; + nouveau_subdev_destroy(&i2c->base); } -bool -nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) +static int +nouveau_i2c_init(struct nouveau_object *object) { - uint8_t buf[] = { 0 }; - struct i2c_msg msgs[] = { - { - .addr = addr, - .flags = 0, - .len = 1, - .buf = buf, - }, - { - .addr = addr, - .flags = I2C_M_RD, - .len = 1, - .buf = buf, - } - }; - - return i2c_transfer(&i2c->adapter, msgs, 2) == 2; + struct nouveau_i2c *i2c = (void *)object; + return nouveau_subdev_init(&i2c->base); } -int -nouveau_i2c_identify(struct drm_device *dev, const char *what, - struct i2c_board_info *info, - bool (*match)(struct nouveau_i2c_chan *, - struct i2c_board_info *), - int index) +static int +nouveau_i2c_fini(struct nouveau_object *object, bool suspend) { - struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); - int i; - - if (!i2c) { - NV_DEBUG(dev, "No bus when probing %s on %d\n", what, index); - return -ENODEV; - } - - NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, i2c->index); - for (i = 0; info[i].addr; i++) { - if (nouveau_probe_i2c_addr(i2c, info[i].addr) && - (!match || match(i2c, &info[i]))) { - NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); - return i; - } - } - - NV_DEBUG(dev, "No devices found.\n"); - return -ENODEV; + struct nouveau_i2c *i2c = (void *)object; + return nouveau_subdev_fini(&i2c->base, suspend); } + +struct nouveau_oclass +nouveau_i2c_oclass = { + .handle = NV_SUBDEV(I2C, 0x00), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nouveau_i2c_ctor, + .dtor = nouveau_i2c_dtor, + .init = nouveau_i2c_init, + .fini = nouveau_i2c_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c new file mode 100644 index 0000000..1c4c9a5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c @@ -0,0 +1,230 @@ +/* + * 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: + * + * 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 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 "subdev/i2c.h" + +#ifdef CONFIG_NOUVEAU_I2C_INTERNAL +#define T_TIMEOUT 2200000 +#define T_RISEFALL 1000 +#define T_HOLD 5000 + +static inline void +i2c_drive_scl(struct nouveau_i2c_port *port, int state) +{ + nouveau_i2c_drive_scl(port, state); +} + +static inline void +i2c_drive_sda(struct nouveau_i2c_port *port, int state) +{ + nouveau_i2c_drive_sda(port, state); +} + +static inline int +i2c_sense_scl(struct nouveau_i2c_port *port) +{ + return nouveau_i2c_sense_scl(port); +} + +static inline int +i2c_sense_sda(struct nouveau_i2c_port *port) +{ + return nouveau_i2c_sense_sda(port); +} + +static void +i2c_delay(struct nouveau_i2c_port *port, u32 nsec) +{ + udelay((nsec + 500) / 1000); +} + +static bool +i2c_raise_scl(struct nouveau_i2c_port *port) +{ + u32 timeout = T_TIMEOUT / T_RISEFALL; + + i2c_drive_scl(port, 1); + do { + i2c_delay(port, T_RISEFALL); + } while (!i2c_sense_scl(port) && --timeout); + + return timeout != 0; +} + +static int +i2c_start(struct nouveau_i2c_port *port) +{ + int ret = 0; + + port->state = i2c_sense_scl(port); + port->state |= i2c_sense_sda(port) << 1; + if (port->state != 3) { + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 1); + if (!i2c_raise_scl(port)) + ret = -EBUSY; + } + + i2c_drive_sda(port, 0); + i2c_delay(port, T_HOLD); + i2c_drive_scl(port, 0); + i2c_delay(port, T_HOLD); + return ret; +} + +static void +i2c_stop(struct nouveau_i2c_port *port) +{ + i2c_drive_scl(port, 0); + i2c_drive_sda(port, 0); + i2c_delay(port, T_RISEFALL); + + i2c_drive_scl(port, 1); + i2c_delay(port, T_HOLD); + i2c_drive_sda(port, 1); + i2c_delay(port, T_HOLD); +} + +static int +i2c_bitw(struct nouveau_i2c_port *port, int sda) +{ + i2c_drive_sda(port, sda); + i2c_delay(port, T_RISEFALL); + + if (!i2c_raise_scl(port)) + return -ETIMEDOUT; + i2c_delay(port, T_HOLD); + + i2c_drive_scl(port, 0); + i2c_delay(port, T_HOLD); + return 0; +} + +static int +i2c_bitr(struct nouveau_i2c_port *port) +{ + int sda; + + i2c_drive_sda(port, 1); + i2c_delay(port, T_RISEFALL); + + if (!i2c_raise_scl(port)) + return -ETIMEDOUT; + i2c_delay(port, T_HOLD); + + sda = i2c_sense_sda(port); + + i2c_drive_scl(port, 0); + i2c_delay(port, T_HOLD); + return sda; +} + +static int +i2c_get_byte(struct nouveau_i2c_port *port, u8 *byte, bool last) +{ + int i, bit; + + *byte = 0; + for (i = 7; i >= 0; i--) { + bit = i2c_bitr(port); + if (bit < 0) + return bit; + *byte |= bit << i; + } + + return i2c_bitw(port, last ? 1 : 0); +} + +static int +i2c_put_byte(struct nouveau_i2c_port *port, u8 byte) +{ + int i, ret; + for (i = 7; i >= 0; i--) { + ret = i2c_bitw(port, !!(byte & (1 << i))); + if (ret < 0) + return ret; + } + + ret = i2c_bitr(port); + if (ret == 1) /* nack */ + ret = -EIO; + return ret; +} + +static int +i2c_addr(struct nouveau_i2c_port *port, struct i2c_msg *msg) +{ + u32 addr = msg->addr << 1; + if (msg->flags & I2C_M_RD) + addr |= 1; + return i2c_put_byte(port, addr); +} + +static int +i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap; + struct i2c_msg *msg = msgs; + int ret = 0, mcnt = num; + + while (!ret && mcnt--) { + u8 remaining = msg->len; + u8 *ptr = msg->buf; + + ret = i2c_start(port); + if (ret == 0) + ret = i2c_addr(port, msg); + + if (msg->flags & I2C_M_RD) { + while (!ret && remaining--) + ret = i2c_get_byte(port, ptr++, !remaining); + } else { + while (!ret && remaining--) + ret = i2c_put_byte(port, *ptr++); + } + + msg++; + } + + i2c_stop(port); + return (ret < 0) ? ret : num; +} +#else +static int +i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + return -ENODEV; +} +#endif + +static u32 +i2c_bit_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +const struct i2c_algorithm nouveau_i2c_bit_algo = { + .master_xfer = i2c_bit_xfer, + .functionality = i2c_bit_func +}; -- cgit v1.1 From 8aceb7de47ea2491abc1a577dc875b19e9947a54 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 16:45:24 +1000 Subject: drm/nouveau/clk: implement stub clock subdev Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/include/subdev/clock.h | 40 +++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | 65 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 +++ drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 ++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 +++++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 +++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + 14 files changed, 432 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/clock.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h new file mode 100644 index 0000000..137c459 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -0,0 +1,40 @@ +#ifndef __NOUVEAU_CLOCK_H__ +#define __NOUVEAU_CLOCK_H__ + +#include +#include + +struct nouveau_clock { + struct nouveau_subdev base; + void (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); +}; + +static inline struct nouveau_clock * +nouveau_clock(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_CLOCK]; +} + +#define nouveau_clock_create(p,e,o,d) \ + nouveau_subdev_create((p), (e), (o), 0, "CLOCK", "clock", d) +#define nouveau_clock_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_clock_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_clock_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, int, void **); + +#define _nouveau_clock_dtor _nouveau_subdev_dtor +#define _nouveau_clock_init _nouveau_subdev_init +#define _nouveau_clock_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_clock_oclass; +extern struct nouveau_oclass nv40_clock_oclass; +extern struct nouveau_oclass nv50_clock_oclass; +extern struct nouveau_oclass nva3_clock_oclass; +extern struct nouveau_oclass nvc0_clock_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c new file mode 100644 index 0000000..3a3b3b1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c @@ -0,0 +1,65 @@ +/* + * 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: + * + * 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 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 + +struct nv04_clock_priv { + struct nouveau_clock base; +}; + +static void +nv04_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) +{ + struct nv04_clock_priv *priv = (void *)clk; + + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +} + +static int +nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_clock_priv *priv; + int ret; + + ret = nouveau_clock_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pll_set = nv04_clock_pll_set; + return 0; +} + +struct nouveau_oclass +nv04_clock_oclass = { + .handle = NV_SUBDEV(CLOCK, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_clock_ctor, + .dtor = _nouveau_clock_dtor, + .init = _nouveau_clock_init, + .fini = _nouveau_clock_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c new file mode 100644 index 0000000..60d1ca4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c @@ -0,0 +1,65 @@ +/* + * 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: + * + * 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 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 + +struct nv40_clock_priv { + struct nouveau_clock base; +}; + +static void +nv40_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) +{ + struct nv40_clock_priv *priv = (void *)clk; + + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +} + +static int +nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv40_clock_priv *priv; + int ret; + + ret = nouveau_clock_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pll_set = nv40_clock_pll_set; + return 0; +} + +struct nouveau_oclass +nv40_clock_oclass = { + .handle = NV_SUBDEV(CLOCK, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_clock_ctor, + .dtor = _nouveau_clock_dtor, + .init = _nouveau_clock_init, + .fini = _nouveau_clock_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c new file mode 100644 index 0000000..82804bd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c @@ -0,0 +1,65 @@ +/* + * 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: + * + * 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 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 + +struct nv50_clock_priv { + struct nouveau_clock base; +}; + +static void +nv50_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) +{ + struct nv50_clock_priv *priv = (void *)clk; + + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +} + +static int +nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_clock_priv *priv; + int ret; + + ret = nouveau_clock_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pll_set = nv50_clock_pll_set; + return 0; +} + +struct nouveau_oclass +nv50_clock_oclass = { + .handle = NV_SUBDEV(CLOCK, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_clock_ctor, + .dtor = _nouveau_clock_dtor, + .init = _nouveau_clock_init, + .fini = _nouveau_clock_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c new file mode 100644 index 0000000..876ec46 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -0,0 +1,65 @@ +/* + * 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: + * + * 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 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 + +struct nva3_clock_priv { + struct nouveau_clock base; +}; + +static void +nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) +{ + struct nva3_clock_priv *priv = (void *)clk; + + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +} + +static int +nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nva3_clock_priv *priv; + int ret; + + ret = nouveau_clock_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pll_set = nva3_clock_pll_set; + return 0; +} + +struct nouveau_oclass +nva3_clock_oclass = { + .handle = NV_SUBDEV(CLOCK, 0xa3), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nva3_clock_ctor, + .dtor = _nouveau_clock_dtor, + .init = _nouveau_clock_init, + .fini = _nouveau_clock_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c new file mode 100644 index 0000000..0064156 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -0,0 +1,65 @@ +/* + * 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: + * + * 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 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 + +struct nvc0_clock_priv { + struct nouveau_clock base; +}; + +static void +nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) +{ + struct nvc0_clock_priv *priv = (void *)clk; + + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +} + +static int +nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_clock_priv *priv; + int ret; + + ret = nouveau_clock_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pll_set = nvc0_clock_pll_set; + return 0; +} + +struct nouveau_oclass +nvc0_clock_oclass = { + .handle = NV_SUBDEV(CLOCK, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_clock_ctor, + .dtor = _nouveau_clock_dtor, + .init = _nouveau_clock_init, + .fini = _nouveau_clock_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index e0ebbe1..e24e74b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -25,6 +25,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -33,10 +34,12 @@ nv04_identify(struct nouveau_device *device) case 0x04: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 19b1de6..0b8eb74 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -35,41 +36,49 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 8f73527..1432ef0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -35,21 +36,25 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index eefc345..7eeab78 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -35,26 +36,31 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 63047c5b..ec7c03f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -35,81 +36,97 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 9f4f6ef..0674163 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -35,71 +36,85 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index f941024..56aae6b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -26,6 +26,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -35,41 +36,49 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 21763cf..8ad51cc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -26,6 +26,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -35,11 +36,13 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; + device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); -- cgit v1.1 From 70790f4f819875e8f390871fd15bbbf823f28e1b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jul 2012 17:26:46 +1000 Subject: drm/nouveau/clock: pull in the implementation from all over the place Still missing the main bits we use to change performance levels, I'll get to it after all the hard yakka has been finished. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/include/subdev/bios/pll.h | 77 ++++ .../gpu/drm/nouveau/core/include/subdev/clock.h | 21 +- drivers/gpu/drm/nouveau/core/include/subdev/vga.h | 2 + drivers/gpu/drm/nouveau/core/subdev/bios/pll.c | 417 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c | 296 ++++++++++++++- drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c | 12 +- drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c | 44 ++- drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c | 34 +- drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | 33 +- drivers/gpu/drm/nouveau/core/subdev/clock/pll.h | 9 + .../gpu/drm/nouveau/core/subdev/clock/pllnv04.c | 242 ++++++++++++ .../gpu/drm/nouveau/core/subdev/clock/pllnva3.c | 80 ++++ 12 files changed, 1250 insertions(+), 17 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/pll.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/pll.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h new file mode 100644 index 0000000..c345097 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h @@ -0,0 +1,77 @@ +#ifndef __NVBIOS_PLL_H__ +#define __NVBIOS_PLL_H__ + +/*XXX: kill me */ +struct nouveau_pll_vals { + union { + struct { +#ifdef __BIG_ENDIAN + uint8_t N1, M1, N2, M2; +#else + uint8_t M1, N1, M2, N2; +#endif + }; + struct { + uint16_t NM1, NM2; + } __attribute__((packed)); + }; + int log2P; + + int refclk; +}; + +struct nouveau_bios; + +/* these match types in pll limits table version 0x40, + * nouveau uses them on all chipsets internally where a + * specific pll needs to be referenced, but the exact + * register isn't known. + */ +enum nvbios_pll_type { + PLL_CORE = 0x01, + PLL_SHADER = 0x02, + PLL_UNK03 = 0x03, + PLL_MEMORY = 0x04, + PLL_VDEC = 0x05, + PLL_UNK40 = 0x40, + PLL_UNK41 = 0x41, + PLL_UNK42 = 0x42, + PLL_VPLL0 = 0x80, + PLL_VPLL1 = 0x81, + PLL_MAX = 0xff +}; + +struct nvbios_pll { + enum nvbios_pll_type type; + u32 reg; + u32 refclk; + + u8 min_p; + u8 max_p; + u8 bias_p; + + /* + * for most pre nv50 cards setting a log2P of 7 (the common max_log2p + * value) is no different to 6 (at least for vplls) so allowing the MNP + * calc to use 7 causes the generated clock to be out by a factor of 2. + * however, max_log2p cannot be fixed-up during parsing as the + * unmodified max_log2p value is still needed for setting mplls, hence + * an additional max_usable_log2p member + */ + u8 max_p_usable; + + struct { + u32 min_freq; + u32 max_freq; + u32 min_inputfreq; + u32 max_inputfreq; + u8 min_m; + u8 max_m; + u8 min_n; + u8 max_n; + } vco1, vco2; +}; + +int nvbios_pll_parse(struct nouveau_bios *, u32 type, struct nvbios_pll *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 137c459..39e73b9 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -4,9 +4,21 @@ #include #include +struct nouveau_pll_vals; +struct nvbios_pll; + struct nouveau_clock { struct nouveau_subdev base; - void (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); + + int (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); + + /*XXX: die, these are here *only* to support the completely + * bat-shit insane what-was-nouveau_hw.c code + */ + int (*pll_calc)(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *pv); + int (*pll_prog)(struct nouveau_clock *, u32 reg1, + struct nouveau_pll_vals *pv); }; static inline struct nouveau_clock * @@ -37,4 +49,11 @@ extern struct nouveau_oclass nv50_clock_oclass; extern struct nouveau_oclass nva3_clock_oclass; extern struct nouveau_oclass nvc0_clock_oclass; +int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq); +int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *); +int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, + struct nouveau_pll_vals *); + + #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h index d81df1a..fee09ad 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h @@ -1,6 +1,8 @@ #ifndef __NOUVEAU_VGA_H__ #define __NOUVEAU_VGA_H__ +#include + /* access to various legacy io ports */ u8 nv_rdport(void *obj, int head, u16 port); void nv_wrport(void *obj, int head, u16 port, u8 value); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c new file mode 100644 index 0000000..5e5f4cd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c @@ -0,0 +1,417 @@ +/* + * Copyright 2005-2006 Erik Waling + * Copyright 2006 Stephane Marchesin + * Copyright 2007-2009 Stuart Bennett + * + * 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 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 AUTHORS 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. + */ + +#include +#include +#include +#include +#include + +struct pll_mapping { + u8 type; + u32 reg; +}; + +static struct pll_mapping +nv04_pll_mapping[] = { + { PLL_CORE , 0x680500 }, + { PLL_MEMORY, 0x680504 }, + { PLL_VPLL0 , 0x680508 }, + { PLL_VPLL1 , 0x680520 }, + {} +}; + +static struct pll_mapping +nv40_pll_mapping[] = { + { PLL_CORE , 0x004000 }, + { PLL_MEMORY, 0x004020 }, + { PLL_VPLL0 , 0x680508 }, + { PLL_VPLL1 , 0x680520 }, + {} +}; + +static struct pll_mapping +nv50_pll_mapping[] = { + { PLL_CORE , 0x004028 }, + { PLL_SHADER, 0x004020 }, + { PLL_UNK03 , 0x004000 }, + { PLL_MEMORY, 0x004008 }, + { PLL_UNK40 , 0x00e810 }, + { PLL_UNK41 , 0x00e818 }, + { PLL_UNK42 , 0x00e824 }, + { PLL_VPLL0 , 0x614100 }, + { PLL_VPLL1 , 0x614900 }, + {} +}; + +static struct pll_mapping +nv84_pll_mapping[] = { + { PLL_CORE , 0x004028 }, + { PLL_SHADER, 0x004020 }, + { PLL_MEMORY, 0x004008 }, + { PLL_VDEC , 0x004030 }, + { PLL_UNK41 , 0x00e818 }, + { PLL_VPLL0 , 0x614100 }, + { PLL_VPLL1 , 0x614900 }, + {} +}; + +static u16 +pll_limits_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct bit_entry bit_C; + + if (!bit_entry(bios, 'C', &bit_C) && bit_C.length >= 10) { + u16 data = nv_ro16(bios, bit_C.offset + 8); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = nv_ro08(bios, data + 1); + *len = nv_ro08(bios, data + 2); + *cnt = nv_ro08(bios, data + 3); + return data; + } + } + + if (bmp_version(bios) >= 0x0524) { + u16 data = nv_ro16(bios, bios->bmp_offset + 142); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = 1; + *cnt = 1; + *len = 0x18; + return data; + } + } + + *ver = 0x00; + return 0x0000; +} + +static struct pll_mapping * +pll_map(struct nouveau_bios *bios) +{ + switch (nv_device(bios)->card_type) { + case NV_04: + case NV_10: + case NV_20: + case NV_30: + return nv04_pll_mapping; + break; + case NV_40: + return nv40_pll_mapping; + case NV_50: + if (nv_device(bios)->chipset == 0x50) + return nv50_pll_mapping; + else + if (nv_device(bios)->chipset < 0xa3 || + nv_device(bios)->chipset == 0xaa || + nv_device(bios)->chipset == 0xac) + return nv84_pll_mapping; + default: + return NULL; + } +} + +static u16 +pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) +{ + struct pll_mapping *map; + u8 hdr, cnt; + u16 data; + + data = pll_limits_table(bios, ver, &hdr, &cnt, len); + if (data && *ver >= 0x30) { + data += hdr; + while (cnt--) { + if (nv_ro32(bios, data + 3) == reg) { + *type = nv_ro08(bios, data + 0); + return data; + } + data += *len; + } + return 0x0000; + } + + map = pll_map(bios); + while (map->reg) { + if (map->reg == reg && *ver >= 0x20) { + u16 addr = (data += hdr); + while (cnt--) { + if (nv_ro32(bios, data) == map->reg) { + *type = map->type; + return data; + } + data += *len; + } + return addr; + } else + if (map->reg == reg) { + *type = map->type; + return data + 1; + } + map++; + } + + return 0x0000; +} + +static u16 +pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) +{ + struct pll_mapping *map; + u8 hdr, cnt; + u16 data; + + data = pll_limits_table(bios, ver, &hdr, &cnt, len); + if (data && *ver >= 0x30) { + data += hdr; + while (cnt--) { + if (nv_ro08(bios, data + 0) == type) { + *reg = nv_ro32(bios, data + 3); + return data; + } + data += *len; + } + return 0x0000; + } + + map = pll_map(bios); + while (map->reg) { + if (map->type == type && *ver >= 0x20) { + u16 addr = (data += hdr); + while (cnt--) { + if (nv_ro32(bios, data) == map->reg) { + *reg = map->reg; + return data; + } + data += *len; + } + return addr; + } else + if (map->type == type) { + *reg = map->reg; + return data + 1; + } + map++; + } + + return 0x0000; +} + +int +nvbios_pll_parse(struct nouveau_bios *bios, u32 type, struct nvbios_pll *info) +{ + u8 ver, len; + u32 reg = type; + u16 data; + + if (type > PLL_MAX) { + reg = type; + data = pll_map_reg(bios, reg, &type, &ver, &len); + } else { + data = pll_map_type(bios, type, ®, &ver, &len); + } + + if (ver && !data) + return -ENOENT; + + memset(info, 0, sizeof(*info)); + info->type = type; + info->reg = reg; + + switch (ver) { + case 0x00: + break; + case 0x10: + case 0x11: + info->vco1.min_freq = nv_ro32(bios, data + 0); + info->vco1.max_freq = nv_ro32(bios, data + 4); + info->vco2.min_freq = nv_ro32(bios, data + 8); + info->vco2.max_freq = nv_ro32(bios, data + 12); + info->vco1.min_inputfreq = nv_ro32(bios, data + 16); + info->vco2.min_inputfreq = nv_ro32(bios, data + 20); + info->vco1.max_inputfreq = INT_MAX; + info->vco2.max_inputfreq = INT_MAX; + + info->max_p = 0x7; + info->max_p_usable = 0x6; + + /* these values taken from nv30/31/36 */ + switch (bios->version.chip) { + case 0x36: + info->vco1.min_n = 0x5; + break; + default: + info->vco1.min_n = 0x1; + break; + } + info->vco1.max_n = 0xff; + info->vco1.min_m = 0x1; + info->vco1.max_m = 0xd; + + /* + * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this + * table version (apart from nv35)), N2 is compared to + * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and + * save a comparison + */ + info->vco2.min_n = 0x4; + switch (bios->version.chip) { + case 0x30: + case 0x35: + info->vco2.max_n = 0x1f; + break; + default: + info->vco2.max_n = 0x28; + break; + } + info->vco2.min_m = 0x1; + info->vco2.max_m = 0x4; + break; + case 0x20: + case 0x21: + info->vco1.min_freq = nv_ro16(bios, data + 4) * 1000; + info->vco1.max_freq = nv_ro16(bios, data + 6) * 1000; + info->vco2.min_freq = nv_ro16(bios, data + 8) * 1000; + info->vco2.max_freq = nv_ro16(bios, data + 10) * 1000; + info->vco1.min_inputfreq = nv_ro16(bios, data + 12) * 1000; + info->vco2.min_inputfreq = nv_ro16(bios, data + 14) * 1000; + info->vco1.max_inputfreq = nv_ro16(bios, data + 16) * 1000; + info->vco2.max_inputfreq = nv_ro16(bios, data + 18) * 1000; + info->vco1.min_n = nv_ro08(bios, data + 20); + info->vco1.max_n = nv_ro08(bios, data + 21); + info->vco1.min_m = nv_ro08(bios, data + 22); + info->vco1.max_m = nv_ro08(bios, data + 23); + info->vco2.min_n = nv_ro08(bios, data + 24); + info->vco2.max_n = nv_ro08(bios, data + 25); + info->vco2.min_m = nv_ro08(bios, data + 26); + info->vco2.max_m = nv_ro08(bios, data + 27); + + info->max_p = nv_ro08(bios, data + 29); + info->max_p_usable = info->max_p; + if (bios->version.chip < 0x60) + info->max_p_usable = 0x6; + info->bias_p = nv_ro08(bios, data + 30); + + if (len > 0x22) + info->refclk = nv_ro32(bios, data + 31); + break; + case 0x30: + data = nv_ro16(bios, data + 1); + + info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; + info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; + info->vco2.min_freq = nv_ro16(bios, data + 4) * 1000; + info->vco2.max_freq = nv_ro16(bios, data + 6) * 1000; + info->vco1.min_inputfreq = nv_ro16(bios, data + 8) * 1000; + info->vco2.min_inputfreq = nv_ro16(bios, data + 10) * 1000; + info->vco1.max_inputfreq = nv_ro16(bios, data + 12) * 1000; + info->vco2.max_inputfreq = nv_ro16(bios, data + 14) * 1000; + info->vco1.min_n = nv_ro08(bios, data + 16); + info->vco1.max_n = nv_ro08(bios, data + 17); + info->vco1.min_m = nv_ro08(bios, data + 18); + info->vco1.max_m = nv_ro08(bios, data + 19); + info->vco2.min_n = nv_ro08(bios, data + 20); + info->vco2.max_n = nv_ro08(bios, data + 21); + info->vco2.min_m = nv_ro08(bios, data + 22); + info->vco2.max_m = nv_ro08(bios, data + 23); + info->max_p_usable = info->max_p = nv_ro08(bios, data + 25); + info->bias_p = nv_ro08(bios, data + 27); + info->refclk = nv_ro32(bios, data + 28); + break; + case 0x40: + info->refclk = nv_ro16(bios, data + 9) * 1000; + data = nv_ro16(bios, data + 1); + + info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; + info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; + info->vco1.min_inputfreq = nv_ro16(bios, data + 4) * 1000; + info->vco1.max_inputfreq = nv_ro16(bios, data + 6) * 1000; + info->vco1.min_m = nv_ro08(bios, data + 8); + info->vco1.max_m = nv_ro08(bios, data + 9); + info->vco1.min_n = nv_ro08(bios, data + 10); + info->vco1.max_n = nv_ro08(bios, data + 11); + info->min_p = nv_ro08(bios, data + 12); + info->max_p = nv_ro08(bios, data + 13); + break; + default: + nv_error(bios, "unknown pll limits version 0x%02x\n", ver); + return -EINVAL; + } + + if (!info->refclk) { + info->refclk = nv_device(bios)->crystal; + if (bios->version.chip == 0x51) { + u32 sel_clk = nv_rd32(bios, 0x680524); + if ((info->reg == 0x680508 && sel_clk & 0x20) || + (info->reg == 0x680520 && sel_clk & 0x80)) { + if (nv_rdvgac(bios, 0, 0x27) < 0xa3) + info->refclk = 200000; + else + info->refclk = 25000; + } + } + } + + /* + * By now any valid limit table ought to have set a max frequency for + * vco1, so if it's zero it's either a pre limit table bios, or one + * with an empty limit table (seen on nv18) + */ + if (!info->vco1.max_freq) { + info->vco1.max_freq = nv_ro32(bios, bios->bmp_offset + 67); + info->vco1.min_freq = nv_ro32(bios, bios->bmp_offset + 71); + if (bmp_version(bios) < 0x0506) { + info->vco1.max_freq = 256000; + info->vco1.min_freq = 128000; + } + + info->vco1.min_inputfreq = 0; + info->vco1.max_inputfreq = INT_MAX; + info->vco1.min_n = 0x1; + info->vco1.max_n = 0xff; + info->vco1.min_m = 0x1; + + if (nv_device(bios)->crystal == 13500) { + /* nv05 does this, nv11 doesn't, nv10 unknown */ + if (bios->version.chip < 0x11) + info->vco1.min_m = 0x7; + info->vco1.max_m = 0xd; + } else { + if (bios->version.chip < 0x11) + info->vco1.min_m = 0x8; + info->vco1.max_m = 0xe; + } + + if (bios->version.chip < 0x17 || + bios->version.chip == 0x1a || + bios->version.chip == 0x20) + info->max_p = 4; + else + info->max_p = 5; + info->max_p_usable = info->max_p; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c index 3a3b3b1..b7fd115 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c @@ -23,17 +23,309 @@ */ #include +#include +#include + +#include "pll.h" struct nv04_clock_priv { struct nouveau_clock base; }; +static int +powerctrl_1_shift(int chip_version, int reg) +{ + int shift = -4; + + if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) + return shift; + + switch (reg) { + case 0x680520: + shift += 4; + case 0x680508: + shift += 4; + case 0x680504: + shift += 4; + case 0x680500: + shift += 4; + } + + /* + * the shift for vpll regs is only used for nv3x chips with a single + * stage pll + */ + if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || + chip_version == 0x36 || chip_version >= 0x40)) + shift = -4; + + return shift; +} + static void +setPLL_single(struct nv04_clock_priv *priv, u32 reg, + struct nouveau_pll_vals *pv) +{ + int chip_version = nouveau_bios(priv)->version.chip; + uint32_t oldpll = nv_rd32(priv, reg); + int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; + uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; + uint32_t saved_powerctrl_1 = 0; + int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); + + if (oldpll == pll) + return; /* already set */ + + if (shift_powerctrl_1 >= 0) { + saved_powerctrl_1 = nv_rd32(priv, 0x001584); + nv_wr32(priv, 0x001584, + (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | + 1 << shift_powerctrl_1); + } + + if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) + /* upclock -- write new post divider first */ + nv_wr32(priv, reg, pv->log2P << 16 | (oldpll & 0xffff)); + else + /* downclock -- write new NM first */ + nv_wr32(priv, reg, (oldpll & 0xffff0000) | pv->NM1); + + if (chip_version < 0x17 && chip_version != 0x11) + /* wait a bit on older chips */ + msleep(64); + nv_rd32(priv, reg); + + /* then write the other half as well */ + nv_wr32(priv, reg, pll); + + if (shift_powerctrl_1 >= 0) + nv_wr32(priv, 0x001584, saved_powerctrl_1); +} + +static uint32_t +new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) +{ + bool head_a = (reg1 == 0x680508); + + if (ss) /* single stage pll mode */ + ramdac580 |= head_a ? 0x00000100 : 0x10000000; + else + ramdac580 &= head_a ? 0xfffffeff : 0xefffffff; + + return ramdac580; +} + +static void +setPLL_double_highregs(struct nv04_clock_priv *priv, u32 reg1, + struct nouveau_pll_vals *pv) +{ + int chip_version = nouveau_bios(priv)->version.chip; + bool nv3035 = chip_version == 0x30 || chip_version == 0x35; + uint32_t reg2 = reg1 + ((reg1 == 0x680520) ? 0x5c : 0x70); + uint32_t oldpll1 = nv_rd32(priv, reg1); + uint32_t oldpll2 = !nv3035 ? nv_rd32(priv, reg2) : 0; + uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; + uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; + uint32_t oldramdac580 = 0, ramdac580 = 0; + bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ + uint32_t saved_powerctrl_1 = 0, savedc040 = 0; + int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); + + /* model specific additions to generic pll1 and pll2 set up above */ + if (nv3035) { + pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | + (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; + pll2 = 0; + } + if (chip_version > 0x40 && reg1 >= 0x680508) { /* !nv40 */ + oldramdac580 = nv_rd32(priv, 0x680580); + ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); + if (oldramdac580 != ramdac580) + oldpll1 = ~0; /* force mismatch */ + if (single_stage) + /* magic value used by nvidia in single stage mode */ + pll2 |= 0x011f; + } + if (chip_version > 0x70) + /* magic bits set by the blob (but not the bios) on g71-73 */ + pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; + + if (oldpll1 == pll1 && oldpll2 == pll2) + return; /* already set */ + + if (shift_powerctrl_1 >= 0) { + saved_powerctrl_1 = nv_rd32(priv, 0x001584); + nv_wr32(priv, 0x001584, + (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | + 1 << shift_powerctrl_1); + } + + if (chip_version >= 0x40) { + int shift_c040 = 14; + + switch (reg1) { + case 0x680504: + shift_c040 += 2; + case 0x680500: + shift_c040 += 2; + case 0x680520: + shift_c040 += 2; + case 0x680508: + shift_c040 += 2; + } + + savedc040 = nv_rd32(priv, 0xc040); + if (shift_c040 != 14) + nv_wr32(priv, 0xc040, savedc040 & ~(3 << shift_c040)); + } + + if (oldramdac580 != ramdac580) + nv_wr32(priv, 0x680580, ramdac580); + + if (!nv3035) + nv_wr32(priv, reg2, pll2); + nv_wr32(priv, reg1, pll1); + + if (shift_powerctrl_1 >= 0) + nv_wr32(priv, 0x001584, saved_powerctrl_1); + if (chip_version >= 0x40) + nv_wr32(priv, 0xc040, savedc040); +} + +static void +setPLL_double_lowregs(struct nv04_clock_priv *priv, u32 NMNMreg, + struct nouveau_pll_vals *pv) +{ + /* When setting PLLs, there is a merry game of disabling and enabling + * various bits of hardware during the process. This function is a + * synthesis of six nv4x traces, nearly each card doing a subtly + * different thing. With luck all the necessary bits for each card are + * combined herein. Without luck it deviates from each card's formula + * so as to not work on any :) + */ + + uint32_t Preg = NMNMreg - 4; + bool mpll = Preg == 0x4020; + uint32_t oldPval = nv_rd32(priv, Preg); + uint32_t NMNM = pv->NM2 << 16 | pv->NM1; + uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | + 0xc << 28 | pv->log2P << 16; + uint32_t saved4600 = 0; + /* some cards have different maskc040s */ + uint32_t maskc040 = ~(3 << 14), savedc040; + bool single_stage = !pv->NM2 || pv->N2 == pv->M2; + + if (nv_rd32(priv, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) + return; + + if (Preg == 0x4000) + maskc040 = ~0x333; + if (Preg == 0x4058) + maskc040 = ~(0xc << 24); + + if (mpll) { + struct nvbios_pll info; + uint8_t Pval2; + + if (nvbios_pll_parse(nouveau_bios(priv), Preg, &info)) + return; + + Pval2 = pv->log2P + info.bias_p; + if (Pval2 > info.max_p) + Pval2 = info.max_p; + Pval |= 1 << 28 | Pval2 << 20; + + saved4600 = nv_rd32(priv, 0x4600); + nv_wr32(priv, 0x4600, saved4600 | 8 << 28); + } + if (single_stage) + Pval |= mpll ? 1 << 12 : 1 << 8; + + nv_wr32(priv, Preg, oldPval | 1 << 28); + nv_wr32(priv, Preg, Pval & ~(4 << 28)); + if (mpll) { + Pval |= 8 << 20; + nv_wr32(priv, 0x4020, Pval & ~(0xc << 28)); + nv_wr32(priv, 0x4038, Pval & ~(0xc << 28)); + } + + savedc040 = nv_rd32(priv, 0xc040); + nv_wr32(priv, 0xc040, savedc040 & maskc040); + + nv_wr32(priv, NMNMreg, NMNM); + if (NMNMreg == 0x4024) + nv_wr32(priv, 0x403c, NMNM); + + nv_wr32(priv, Preg, Pval); + if (mpll) { + Pval &= ~(8 << 20); + nv_wr32(priv, 0x4020, Pval); + nv_wr32(priv, 0x4038, Pval); + nv_wr32(priv, 0x4600, saved4600); + } + + nv_wr32(priv, 0xc040, savedc040); + + if (mpll) { + nv_wr32(priv, 0x4020, Pval & ~(1 << 28)); + nv_wr32(priv, 0x4038, Pval & ~(1 << 28)); + } +} + +int nv04_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nv04_clock_priv *priv = (void *)clk; + struct nouveau_pll_vals pv; + struct nvbios_pll info; + int ret; + + ret = nvbios_pll_parse(nouveau_bios(priv), type > 0x405c ? + type : type - 4, &info); + if (ret) + return ret; + + ret = clk->pll_calc(clk, &info, freq, &pv); + if (!ret) + return ret; + + return clk->pll_prog(clk, type, &pv); +} - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); +int +nv04_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + int clk, struct nouveau_pll_vals *pv) +{ + int N1, M1, N2, M2, P; + int ret = nv04_pll_calc(clock, info, clk, &N1, &M1, &N2, &M2, &P); + if (ret) { + pv->refclk = info->refclk; + pv->N1 = N1; + pv->M1 = M1; + pv->N2 = N2; + pv->M2 = M2; + pv->log2P = P; + } + return ret; +} + +int +nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1, + struct nouveau_pll_vals *pv) +{ + struct nv04_clock_priv *priv = (void *)clk; + int cv = nouveau_bios(clk)->version.chip; + + if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || + cv >= 0x40) { + if (reg1 > 0x405c) + setPLL_double_highregs(priv, reg1, pv); + else + setPLL_double_lowregs(priv, reg1, pv); + } else + setPLL_single(priv, reg1, pv); + + return 0; } static int @@ -50,6 +342,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nv04_clock_pll_set; + priv->base.pll_calc = nv04_clock_pll_calc; + priv->base.pll_prog = nv04_clock_pll_prog; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c index 60d1ca4..a4b2b7e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c @@ -28,14 +28,6 @@ struct nv40_clock_priv { struct nouveau_clock base; }; -static void -nv40_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) -{ - struct nv40_clock_priv *priv = (void *)clk; - - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); -} - static int nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -49,7 +41,9 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.pll_set = nv40_clock_pll_set; + priv->base.pll_set = nv04_clock_pll_set; + priv->base.pll_calc = nv04_clock_pll_calc; + priv->base.pll_prog = nv04_clock_pll_prog; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c index 82804bd..fd181fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c @@ -23,17 +23,57 @@ */ #include +#include +#include + +#include "pll.h" struct nv50_clock_priv { struct nouveau_clock base; }; -static void +static int nv50_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nv50_clock_priv *priv = (void *)clk; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll info; + int N1, M1, N2, M2, P; + int ret; + + ret = nvbios_pll_parse(bios, type, &info); + if (ret) { + nv_error(clk, "failed to retrieve pll data, %d\n", ret); + return ret; + } - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + ret = nv04_pll_calc(clk, &info, freq, &N1, &M1, &N2, &M2, &P); + if (!ret) { + nv_error(clk, "failed pll calculation\n"); + return ret; + } + + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: + nv_wr32(priv, info.reg + 0, 0x10000611); + nv_mask(priv, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1); + nv_mask(priv, info.reg + 8, 0x7fff00ff, (P << 28) | + (M2 << 16) | N2); + break; + case PLL_MEMORY: + nv_mask(priv, info.reg + 0, 0x01ff0000, (P << 22) | + (info.bias_p << 19) | + (P << 16)); + nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); + break; + default: + nv_mask(priv, info.reg + 0, 0x00070000, (P << 16)); + nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); + break; + } + + return 0; } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index 876ec46..cc8d7d1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -23,17 +23,47 @@ */ #include +#include +#include + +#include "pll.h" struct nva3_clock_priv { struct nouveau_clock base; }; -static void +static int nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nva3_clock_priv *priv = (void *)clk; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll info; + int N, fN, M, P; + int ret; + + ret = nvbios_pll_parse(bios, type, &info); + if (ret) + return ret; + + ret = nva3_pll_calc(clk, &info, freq, &N, &fN, &M, &P); + if (ret < 0) + return ret; + + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: + nv_wr32(priv, info.reg + 0, 0x50000610); + nv_mask(priv, info.reg + 4, 0x003fffff, + (P << 16) | (M << 8) | N); + nv_wr32(priv, info.reg + 8, fN); + break; + default: + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + ret = -EINVAL; + break; + } - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + return ret; } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 0064156..5ccce0b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -23,17 +23,46 @@ */ #include +#include +#include + +#include "pll.h" struct nvc0_clock_priv { struct nouveau_clock base; }; -static void +static int nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) { struct nvc0_clock_priv *priv = (void *)clk; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_pll info; + int N, fN, M, P; + int ret; + + ret = nvbios_pll_parse(bios, type, &info); + if (ret) + return ret; + + ret = nva3_pll_calc(clk, &info, freq, &N, &fN, &M, &P); + if (ret < 0) + return ret; + + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: + nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); + nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); + nv_wr32(priv, info.reg + 0x10, fN << 16); + break; + default: + nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + ret = -EINVAL; + break; + } - nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); + return ret; } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h b/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h new file mode 100644 index 0000000..ef2c007 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h @@ -0,0 +1,9 @@ +#ifndef __NOUVEAU_PLL_H__ +#define __NOUVEAU_PLL_H__ + +int nv04_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, + int *N1, int *M1, int *N2, int *M2, int *P); +int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, + int *N, int *fN, int *M, int *P); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c new file mode 100644 index 0000000..a2ab6d0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c @@ -0,0 +1,242 @@ +/* + * Copyright 1993-2003 NVIDIA, Corporation + * Copyright 2007-2009 Stuart Bennett + * + * 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 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 AUTHORS 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. + */ + +#include +#include +#include + +#include "pll.h" + +static int +getMNP_single(struct nouveau_clock *clock, struct nvbios_pll *info, int clk, + int *pN, int *pM, int *pP) +{ + /* Find M, N and P for a single stage PLL + * + * Note that some bioses (NV3x) have lookup tables of precomputed MNP + * values, but we're too lazy to use those atm + * + * "clk" parameter in kHz + * returns calculated clock + */ + int cv = nouveau_bios(clock)->version.chip; + int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq; + int minM = info->vco1.min_m, maxM = info->vco1.max_m; + int minN = info->vco1.min_n, maxN = info->vco1.max_n; + int minU = info->vco1.min_inputfreq; + int maxU = info->vco1.max_inputfreq; + int minP = info->min_p; + int maxP = info->max_p_usable; + int crystal = info->refclk; + int M, N, thisP, P; + int clkP, calcclk; + int delta, bestdelta = INT_MAX; + int bestclk = 0; + + /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ + /* possibly correlated with introduction of 27MHz crystal */ + if (cv < 0x17 || cv == 0x1a || cv == 0x20) { + if (clk > 250000) + maxM = 6; + if (clk > 340000) + maxM = 2; + } else if (cv < 0x40) { + if (clk > 150000) + maxM = 6; + if (clk > 200000) + maxM = 4; + if (clk > 340000) + maxM = 2; + } + + P = 1 << maxP; + if ((clk * P) < minvco) { + minvco = clk * maxP; + maxvco = minvco * 2; + } + + if (clk + clk/200 > maxvco) /* +0.5% */ + maxvco = clk + clk/200; + + /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ + for (thisP = minP; thisP <= maxP; thisP++) { + P = 1 << thisP; + clkP = clk * P; + + if (clkP < minvco) + continue; + if (clkP > maxvco) + return bestclk; + + for (M = minM; M <= maxM; M++) { + if (crystal/M < minU) + return bestclk; + if (crystal/M > maxU) + continue; + + /* add crystal/2 to round better */ + N = (clkP * M + crystal/2) / crystal; + + if (N < minN) + continue; + if (N > maxN) + break; + + /* more rounding additions */ + calcclk = ((N * crystal + P/2) / P + M/2) / M; + delta = abs(calcclk - clk); + /* we do an exhaustive search rather than terminating + * on an optimality condition... + */ + if (delta < bestdelta) { + bestdelta = delta; + bestclk = calcclk; + *pN = N; + *pM = M; + *pP = thisP; + if (delta == 0) /* except this one */ + return bestclk; + } + } + } + + return bestclk; +} + +static int +getMNP_double(struct nouveau_clock *clock, struct nvbios_pll *info, int clk, + int *pN1, int *pM1, int *pN2, int *pM2, int *pP) +{ + /* Find M, N and P for a two stage PLL + * + * Note that some bioses (NV30+) have lookup tables of precomputed MNP + * values, but we're too lazy to use those atm + * + * "clk" parameter in kHz + * returns calculated clock + */ + int chip_version = nouveau_bios(clock)->version.chip; + int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq; + int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq; + int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq; + int maxU1 = info->vco1.max_inputfreq, maxU2 = info->vco2.max_inputfreq; + int minM1 = info->vco1.min_m, maxM1 = info->vco1.max_m; + int minN1 = info->vco1.min_n, maxN1 = info->vco1.max_n; + int minM2 = info->vco2.min_m, maxM2 = info->vco2.max_m; + int minN2 = info->vco2.min_n, maxN2 = info->vco2.max_n; + int maxlog2P = info->max_p_usable; + int crystal = info->refclk; + bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); + int M1, N1, M2, N2, log2P; + int clkP, calcclk1, calcclk2, calcclkout; + int delta, bestdelta = INT_MAX; + int bestclk = 0; + + int vco2 = (maxvco2 - maxvco2/200) / 2; + for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) + ; + clkP = clk << log2P; + + if (maxvco2 < clk + clk/200) /* +0.5% */ + maxvco2 = clk + clk/200; + + for (M1 = minM1; M1 <= maxM1; M1++) { + if (crystal/M1 < minU1) + return bestclk; + if (crystal/M1 > maxU1) + continue; + + for (N1 = minN1; N1 <= maxN1; N1++) { + calcclk1 = crystal * N1 / M1; + if (calcclk1 < minvco1) + continue; + if (calcclk1 > maxvco1) + break; + + for (M2 = minM2; M2 <= maxM2; M2++) { + if (calcclk1/M2 < minU2) + break; + if (calcclk1/M2 > maxU2) + continue; + + /* add calcclk1/2 to round better */ + N2 = (clkP * M2 + calcclk1/2) / calcclk1; + if (N2 < minN2) + continue; + if (N2 > maxN2) + break; + + if (!fixedgain2) { + if (chip_version < 0x60) + if (N2/M2 < 4 || N2/M2 > 10) + continue; + + calcclk2 = calcclk1 * N2 / M2; + if (calcclk2 < minvco2) + break; + if (calcclk2 > maxvco2) + continue; + } else + calcclk2 = calcclk1; + + calcclkout = calcclk2 >> log2P; + delta = abs(calcclkout - clk); + /* we do an exhaustive search rather than terminating + * on an optimality condition... + */ + if (delta < bestdelta) { + bestdelta = delta; + bestclk = calcclkout; + *pN1 = N1; + *pM1 = M1; + *pN2 = N2; + *pM2 = M2; + *pP = log2P; + if (delta == 0) /* except this one */ + return bestclk; + } + } + } + } + + return bestclk; +} + +int +nv04_pll_calc(struct nouveau_clock *clk, struct nvbios_pll *info, u32 freq, + int *N1, int *M1, int *N2, int *M2, int *P) +{ + int ret; + + if (!info->vco2.max_freq) { + ret = getMNP_single(clk, info, freq, N1, M1, P); + *N2 = 1; + *M2 = 1; + } else { + ret = getMNP_double(clk, info, freq, N1, M1, N2, M2, P); + } + + if (!ret) + nv_error(clk, "unable to compute acceptable pll values\n"); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c new file mode 100644 index 0000000..eed5c16 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c @@ -0,0 +1,80 @@ +/* + * Copyright 2010 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: + * + * 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 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 +#include +#include + +#include "pll.h" + +int +nva3_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + u32 freq, int *pN, int *pfN, int *pM, int *P) +{ + u32 best_err = ~0, err; + int M, lM, hM, N, fN; + + *P = info->vco1.max_freq / freq; + if (*P > info->max_p) + *P = info->max_p; + if (*P < info->min_p) + *P = info->min_p; + + lM = (info->refclk + info->vco1.max_inputfreq) / info->vco1.max_inputfreq; + lM = max(lM, (int)info->vco1.min_m); + hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq; + hM = min(hM, (int)info->vco1.max_m); + + for (M = lM; M <= hM; M++) { + u32 tmp = freq * *P * M; + N = tmp / info->refclk; + fN = tmp % info->refclk; + if (!pfN && fN >= info->refclk / 2) + N++; + + if (N < info->vco1.min_n) + continue; + if (N > info->vco1.max_n) + break; + + err = abs(freq - (info->refclk * N / M / *P)); + if (err < best_err) { + best_err = err; + *pN = N; + *pM = M; + } + + if (pfN) { + *pfN = (((fN << 13) / info->refclk) - 4096) & 0xffff; + return freq; + } + } + + if (unlikely(best_err == ~0)) { + nv_error(clock, "unable to find matching pll values\n"); + return -EINVAL; + } + + return info->refclk * *pN / *pM / *P; +} -- cgit v1.1 From cb75d97e9c77743ecfcc43375be135a55a4d9b25 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 10:44:20 +1000 Subject: drm/nouveau: implement devinit subdev, and new init table parser v2: - make sure not to execute display scripts unless resuming Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/include/subdev/bios/conn.h | 27 + .../gpu/drm/nouveau/core/include/subdev/bios/dcb.h | 73 +- .../gpu/drm/nouveau/core/include/subdev/bios/dp.h | 8 + .../drm/nouveau/core/include/subdev/bios/init.h | 21 + .../gpu/drm/nouveau/core/include/subdev/devinit.h | 40 + drivers/gpu/drm/nouveau/core/subdev/bios/conn.c | 55 + drivers/gpu/drm/nouveau/core/subdev/bios/dp.c | 76 + drivers/gpu/drm/nouveau/core/subdev/bios/init.c | 2120 ++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 + drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/devinit/base.c | 69 + .../gpu/drm/nouveau/core/subdev/devinit/fbmem.h | 98 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c | 189 ++ drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c | 159 ++ drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c | 124 ++ drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c | 58 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c | 96 + drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c | 87 + 24 files changed, 3366 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/devinit.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/conn.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/dp.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/init.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h new file mode 100644 index 0000000..c127054 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h @@ -0,0 +1,27 @@ +#ifndef __NVBIOS_CONN_H__ +#define __NVBIOS_CONN_H__ + +enum dcb_connector_type { + DCB_CONNECTOR_VGA = 0x00, + DCB_CONNECTOR_TV_0 = 0x10, + DCB_CONNECTOR_TV_1 = 0x11, + DCB_CONNECTOR_TV_3 = 0x13, + DCB_CONNECTOR_DVI_I = 0x30, + DCB_CONNECTOR_DVI_D = 0x31, + DCB_CONNECTOR_DMS59_0 = 0x38, + DCB_CONNECTOR_DMS59_1 = 0x39, + DCB_CONNECTOR_LVDS = 0x40, + DCB_CONNECTOR_LVDS_SPWG = 0x41, + DCB_CONNECTOR_DP = 0x46, + DCB_CONNECTOR_eDP = 0x47, + DCB_CONNECTOR_HDMI_0 = 0x60, + DCB_CONNECTOR_HDMI_1 = 0x61, + DCB_CONNECTOR_DMS59_DP0 = 0x64, + DCB_CONNECTOR_DMS59_DP1 = 0x65, + DCB_CONNECTOR_NONE = 0xff +}; + +u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h index 7000dcf..d682fb6 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h @@ -1,14 +1,56 @@ #ifndef __NVBIOS_DCB_H__ #define __NVBIOS_DCB_H__ +struct nouveau_bios; + enum dcb_output_type { DCB_OUTPUT_ANALOG = 0x0, DCB_OUTPUT_TV = 0x1, DCB_OUTPUT_TMDS = 0x2, DCB_OUTPUT_LVDS = 0x3, - DCB_OUTPUT_DP = 0x4, + DCB_OUTPUT_DP = 0x6, DCB_OUTPUT_EOL = 0xe, DCB_OUTPUT_UNUSED = 0xf, + DCB_OUTPUT_ANY = -1, +}; + +struct dcb_output { + int index; /* may not be raw dcb index if merging has happened */ + enum dcb_output_type type; + uint8_t i2c_index; + uint8_t heads; + uint8_t connector; + uint8_t bus; + uint8_t location; + uint8_t or; + bool duallink_possible; + union { + struct sor_conf { + int link; + } sorconf; + struct { + int maxfreq; + } crtconf; + struct { + struct sor_conf sor; + bool use_straps_for_mode; + bool use_acpi_for_edid; + bool use_power_scripts; + } lvdsconf; + struct { + bool has_component_output; + } tvconf; + struct { + struct sor_conf sor; + int link_nr; + int link_bw; + } dpconf; + struct { + struct sor_conf sor; + int slave_addr; + } tmdsconf; + }; + bool i2c_upper_default; }; u16 dcb_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); @@ -16,4 +58,33 @@ u16 dcb_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); int dcb_outp_foreach(struct nouveau_bios *, void *data, int (*exec) (struct nouveau_bios *, void *, int index, u16 entry)); + +/* BIT 'U'/'d' table encoder subtables have hashes matching them to + * a particular set of encoders. + * + * This function returns true if a particular DCB entry matches. + */ +static inline bool +dcb_hash_match(struct dcb_output *dcb, u32 hash) +{ + if ((hash & 0x000000f0) != (dcb->location << 4)) + return false; + if ((hash & 0x0000000f) != dcb->type) + return false; + if (!(hash & (dcb->or << 16))) + return false; + + switch (dcb->type) { + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: + if (hash & 0x00c00000) { + if (!(hash & (dcb->sorconf.link << 22))) + return false; + } + default: + return true; + } +} + #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h new file mode 100644 index 0000000..73b5e5d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h @@ -0,0 +1,8 @@ +#ifndef __NVBIOS_DP_H__ +#define __NVBIOS_DP_H__ + +u16 dp_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 dp_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); +u16 dp_outp_match(struct nouveau_bios *, struct dcb_output *, u8 *ver, u8 *len); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h new file mode 100644 index 0000000..e69a8bd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h @@ -0,0 +1,21 @@ +#ifndef __NVBIOS_INIT_H__ +#define __NVBIOS_INIT_H__ + +struct nvbios_init { + struct nouveau_subdev *subdev; + struct nouveau_bios *bios; + u16 offset; + struct dcb_output *outp; + int crtc; + + /* internal state used during parsing */ + u8 execute; + u32 nested; + u16 repeat; + u16 repend; +}; + +int nvbios_exec(struct nvbios_init *); +int nvbios_init(struct nouveau_subdev *, bool execute); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h new file mode 100644 index 0000000..29e4cc1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h @@ -0,0 +1,40 @@ +#ifndef __NOUVEAU_DEVINIT_H__ +#define __NOUVEAU_DEVINIT_H__ + +#include +#include + +struct nouveau_devinit { + struct nouveau_subdev base; + bool post; + void (*meminit)(struct nouveau_devinit *); +}; + +static inline struct nouveau_devinit * +nouveau_devinit(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DEVINIT]; +} + +#define nouveau_devinit_create(p,e,o,d) \ + nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_devinit_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) + +int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_devinit_init(struct nouveau_devinit *); +int nouveau_devinit_fini(struct nouveau_devinit *, bool suspend); + +extern struct nouveau_oclass nv04_devinit_oclass; +extern struct nouveau_oclass nv05_devinit_oclass; +extern struct nouveau_oclass nv10_devinit_oclass; +extern struct nouveau_oclass nv1a_devinit_oclass; +extern struct nouveau_oclass nv20_devinit_oclass; +extern struct nouveau_oclass nv50_devinit_oclass; + +void nv04_devinit_dtor(struct nouveau_object *); +int nv04_devinit_init(struct nouveau_object *); +int nv04_devinit_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c new file mode 100644 index 0000000..ac4026c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c @@ -0,0 +1,55 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +u16 +dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + u16 dcb = dcb_table(bios, ver, hdr, cnt, len); + if (dcb && *ver >= 0x30 && *hdr >= 0x16) { + u16 data = nv_ro16(bios, dcb + 0x14); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = nv_ro08(bios, data + 1); + *cnt = nv_ro08(bios, data + 2); + *len = nv_ro08(bios, data + 3); + return data; + } + } + return 0x0000; +} + +u16 +dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 data = dcb_conntab(bios, ver, &hdr, &cnt, len); + if (data && idx < cnt) + return data + hdr + (idx * *len); + return 0x0000; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c new file mode 100644 index 0000000..3cbc0f3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c @@ -0,0 +1,76 @@ +/* + * 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: + * + * 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 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 "subdev/bios.h" +#include "subdev/bios/bit.h" +#include "subdev/bios/dcb.h" +#include "subdev/bios/dp.h" + +u16 +dp_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct bit_entry bit_d; + + if (!bit_entry(bios, 'd', &bit_d)) { + if (bit_d.version == 1) { + u16 data = nv_ro16(bios, bit_d.offset); + if (data) { + *ver = nv_ro08(bios, data + 0); + *hdr = nv_ro08(bios, data + 1); + *len = nv_ro08(bios, data + 2); + *cnt = nv_ro08(bios, data + 3); + return data; + } + } + } + + return 0x0000; +} + +u16 +dp_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 table = dp_table(bios, ver, &hdr, &cnt, len); + if (table && idx < cnt) + return nv_ro16(bios, table + hdr + (idx * *len)); + return 0xffff; +} + +u16 +dp_outp_match(struct nouveau_bios *bios, struct dcb_output *outp, + u8 *ver, u8 *len) +{ + u8 idx = 0; + u16 data; + while ((data = dp_outp(bios, idx++, ver, len)) != 0xffff) { + if (data) { + u32 hash = nv_ro32(bios, data); + if (dcb_hash_match(outp, hash)) + return data; + } + } + return 0x0000; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c new file mode 100644 index 0000000..6be8c32 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -0,0 +1,2120 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define bioslog(lvl, fmt, args...) do { \ + nv_printk(init->bios, lvl, "0x%04x[%c]: "fmt, init->offset, \ + init_exec(init) ? '0' + (init->nested - 1) : ' ', ##args); \ +} while(0) +#define cont(fmt, args...) do { \ + if (nv_subdev(init->bios)->debug >= NV_DBG_TRACE) \ + printk(fmt, ##args); \ +} while(0) +#define trace(fmt, args...) bioslog(TRACE, fmt, ##args) +#define warn(fmt, args...) bioslog(WARN, fmt, ##args) +#define error(fmt, args...) bioslog(ERROR, fmt, ##args) + +/****************************************************************************** + * init parser control flow helpers + *****************************************************************************/ + +static inline bool +init_exec(struct nvbios_init *init) +{ + return (init->execute == 1) || ((init->execute & 5) == 5); +} + +static inline void +init_exec_set(struct nvbios_init *init, bool exec) +{ + if (exec) init->execute &= 0xfd; + else init->execute |= 0x02; +} + +static inline void +init_exec_inv(struct nvbios_init *init) +{ + init->execute ^= 0x02; +} + +static inline void +init_exec_force(struct nvbios_init *init, bool exec) +{ + if (exec) init->execute |= 0x04; + else init->execute &= 0xfb; +} + +/****************************************************************************** + * init parser wrappers for normal register/i2c/whatever accessors + *****************************************************************************/ + +static inline int +init_or(struct nvbios_init *init) +{ + if (init->outp) + return ffs(init->outp->or) - 1; + error("script needs OR!!\n"); + return 0; +} + +static inline int +init_link(struct nvbios_init *init) +{ + if (init->outp) + return !(init->outp->sorconf.link & 1); + error("script needs OR link\n"); + return 0; +} + +static inline int +init_crtc(struct nvbios_init *init) +{ + if (init->crtc >= 0) + return init->crtc; + error("script needs crtc\n"); + return 0; +} + +static u8 +init_conn(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + + if (init->outp) { + u8 ver, len; + u16 conn = dcb_conn(bios, init->outp->connector, &ver, &len); + if (conn) + return nv_ro08(bios, conn); + } + + error("script needs connector type\n"); + return 0x00; +} + +static inline u32 +init_nvreg(struct nvbios_init *init, u32 reg) +{ + /* C51 (at least) sometimes has the lower bits set which the VBIOS + * interprets to mean that access needs to go through certain IO + * ports instead. The NVIDIA binary driver has been seen to access + * these through the NV register address, so lets assume we can + * do the same + */ + reg &= ~0x00000003; + + /* GF8+ display scripts need register addresses mangled a bit to + * select a specific CRTC/OR + */ + if (nv_device(init->bios)->card_type >= NV_50) { + if (reg & 0x80000000) { + reg += init_crtc(init) * 0x800; + reg &= ~0x80000000; + } + + if (reg & 0x40000000) { + reg += init_or(init) * 0x800; + reg &= ~0x40000000; + if (reg & 0x20000000) { + reg += init_link(init) * 0x80; + reg &= ~0x20000000; + } + } + } + + if (reg & ~0x00fffffc) + warn("unknown bits in register 0x%08x\n", reg); + return reg; +} + +static u32 +init_rd32(struct nvbios_init *init, u32 reg) +{ + reg = init_nvreg(init, reg); + if (init_exec(init)) + return nv_rd32(init->subdev, reg); + return 0x00000000; +} + +static void +init_wr32(struct nvbios_init *init, u32 reg, u32 val) +{ + reg = init_nvreg(init, reg); + if (init_exec(init)) + nv_wr32(init->subdev, reg, val); +} + +static u32 +init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val) +{ + reg = init_nvreg(init, reg); + if (init_exec(init)) { + u32 tmp = nv_rd32(init->subdev, reg); + nv_wr32(init->subdev, reg, (tmp & ~mask) | val); + return tmp; + } + return 0x00000000; +} + +static u8 +init_rdport(struct nvbios_init *init, u16 port) +{ + if (init_exec(init)) + return nv_rdport(init->subdev, init->crtc, port); + return 0x00; +} + +static void +init_wrport(struct nvbios_init *init, u16 port, u8 value) +{ + if (init_exec(init)) + nv_wrport(init->subdev, init->crtc, port, value); +} + +static u8 +init_rdvgai(struct nvbios_init *init, u16 port, u8 index) +{ + struct nouveau_subdev *subdev = init->subdev; + if (init_exec(init)) { + int head = init->crtc < 0 ? 0 : init->crtc; + return nv_rdvgai(subdev, head, port, index); + } + return 0x00; +} + +static void +init_wrvgai(struct nvbios_init *init, u16 port, u8 index, u8 value) +{ + /* force head 0 for updates to cr44, it only exists on first head */ + if (nv_device(init->subdev)->card_type < NV_50) { + if (port == 0x03d4 && index == 0x44) + init->crtc = 0; + } + + if (init_exec(init)) { + int head = init->crtc < 0 ? 0 : init->crtc; + nv_wrvgai(init->subdev, head, port, index, value); + } + + /* select head 1 if cr44 write selected it */ + if (nv_device(init->subdev)->card_type < NV_50) { + if (port == 0x03d4 && index == 0x44 && value == 3) + init->crtc = 1; + } +} + +static struct nouveau_i2c_port * +init_i2c(struct nvbios_init *init, int index) +{ + struct nouveau_i2c *i2c = nouveau_i2c(init->bios); + + if (index == 0xff) { + index = NV_I2C_DEFAULT(0); + if (init->outp && init->outp->i2c_upper_default) + index = NV_I2C_DEFAULT(1); + } else + if (index < 0) { + if (!init->outp) { + error("script needs output for i2c\n"); + return NULL; + } + + index = init->outp->i2c_index; + } + + return i2c->find(i2c, index); +} + +static int +init_rdi2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg) +{ + struct nouveau_i2c_port *port = init_i2c(init, index); + if (port && init_exec(init)) + return nv_rdi2cr(port, addr, reg); + return -ENODEV; +} + +static int +init_wri2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg, u8 val) +{ + struct nouveau_i2c_port *port = init_i2c(init, index); + if (port && init_exec(init)) + return nv_wri2cr(port, addr, reg, val); + return -ENODEV; +} + +static int +init_rdauxr(struct nvbios_init *init, u32 addr) +{ + struct nouveau_i2c_port *port = init_i2c(init, -1); + u8 data; + + if (port && init_exec(init)) { + int ret = nv_rdaux(port, addr, &data, 1); + if (ret) + return ret; + return data; + } + + return -ENODEV; +} + +static int +init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) +{ + struct nouveau_i2c_port *port = init_i2c(init, -1); + if (port && init_exec(init)) + return nv_wraux(port, addr, &data, 1); + return -ENODEV; +} + +static void +init_prog_pll(struct nvbios_init *init, u32 id, u32 freq) +{ + struct nouveau_clock *clk = nouveau_clock(init->bios); + if (clk && clk->pll_set && init_exec(init)) { + int ret = clk->pll_set(clk, id, freq); + if (ret) + warn("failed to prog pll 0x%08x to %dkHz\n", id, freq); + } +} + +/****************************************************************************** + * parsing of bios structures that are required to execute init tables + *****************************************************************************/ + +static u16 +init_table(struct nouveau_bios *bios, u16 *len) +{ + struct bit_entry bit_I; + + if (!bit_entry(bios, 'I', &bit_I)) { + *len = bit_I.length; + return bit_I.offset; + } + + if (bmp_version(bios) >= 0x0510) { + *len = 14; + return bios->bmp_offset + 75; + } + + return 0x0000; +} + +static u16 +init_table_(struct nvbios_init *init, u16 offset, const char *name) +{ + struct nouveau_bios *bios = init->bios; + u16 len, data = init_table(bios, &len); + if (data) { + if (len >= offset + 2) { + data = nv_ro16(bios, data + offset); + if (data) + return data; + + warn("%s pointer invalid\n", name); + return 0x0000; + } + + warn("init data too short for %s pointer", name); + return 0x0000; + } + + warn("init data not found\n"); + return 0x0000; +} + +#define init_script_table(b) init_table_((b), 0x00, "script table") +#define init_macro_index_table(b) init_table_((b), 0x02, "macro index table") +#define init_macro_table(b) init_table_((b), 0x04, "macro table") +#define init_condition_table(b) init_table_((b), 0x06, "condition table") +#define init_io_condition_table(b) init_table_((b), 0x08, "io condition table") +#define init_io_flag_condition_table(b) init_table_((b), 0x0a, "io flag conditon table") +#define init_function_table(b) init_table_((b), 0x0c, "function table") +#define init_xlat_table(b) init_table_((b), 0x10, "xlat table"); + +static u16 +init_script(struct nouveau_bios *bios, int index) +{ + struct nvbios_init init = { .bios = bios }; + u16 data; + + if (bmp_version(bios) && bmp_version(bios) < 0x0510) { + if (index > 1) + return 0x0000; + + data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18); + return nv_ro16(bios, data + (index * 2)); + } + + data = init_script_table(&init); + if (data) + return nv_ro16(bios, data + (index * 2)); + + return 0x0000; +} + +static u16 +init_unknown_script(struct nouveau_bios *bios) +{ + u16 len, data = init_table(bios, &len); + if (data && len >= 16) + return nv_ro16(bios, data + 14); + return 0x0000; +} + +static u16 +init_ram_restrict_table(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + struct bit_entry bit_M; + u16 data = 0x0000; + + if (!bit_entry(bios, 'M', &bit_M)) { + if (bit_M.version == 1 && bit_M.length >= 5) + data = nv_ro16(bios, bit_M.offset + 3); + if (bit_M.version == 2 && bit_M.length >= 3) + data = nv_ro16(bios, bit_M.offset + 1); + } + + if (data == 0x0000) + warn("ram restrict table not found\n"); + return data; +} + +static u8 +init_ram_restrict_group_count(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + struct bit_entry bit_M; + + if (!bit_entry(bios, 'M', &bit_M)) { + if (bit_M.version == 1 && bit_M.length >= 5) + return nv_ro08(bios, bit_M.offset + 2); + if (bit_M.version == 2 && bit_M.length >= 3) + return nv_ro08(bios, bit_M.offset + 0); + } + + return 0x00; +} + +static u8 +init_ram_restrict(struct nvbios_init *init) +{ + u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2; + u16 table = init_ram_restrict_table(init); + if (table) + return nv_ro08(init->bios, table + strap); + return 0x00; +} + +static u8 +init_xlat_(struct nvbios_init *init, u8 index, u8 offset) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_xlat_table(init); + if (table) { + u16 data = nv_ro16(bios, table + (index * 2)); + if (data) + return nv_ro08(bios, data + offset); + warn("xlat table pointer %d invalid\n", index); + } + return 0x00; +} + +/****************************************************************************** + * utility functions used by various init opcode handlers + *****************************************************************************/ + +static bool +init_condition_met(struct nvbios_init *init, u8 cond) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_condition_table(init); + if (table) { + u32 reg = nv_ro32(bios, table + (cond * 12) + 0); + u32 msk = nv_ro32(bios, table + (cond * 12) + 4); + u32 val = nv_ro32(bios, table + (cond * 12) + 8); + trace("\t[0x%02x] (R[0x%06x] & 0x%08x) == 0x%08x\n", + cond, reg, msk, val); + return (init_rd32(init, reg) & msk) == val; + } + return false; +} + +static bool +init_io_condition_met(struct nvbios_init *init, u8 cond) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_io_condition_table(init); + if (table) { + u16 port = nv_ro16(bios, table + (cond * 5) + 0); + u8 index = nv_ro08(bios, table + (cond * 5) + 2); + u8 mask = nv_ro08(bios, table + (cond * 5) + 3); + u8 value = nv_ro08(bios, table + (cond * 5) + 4); + trace("\t[0x%02x] (0x%04x[0x%02x] & 0x%02x) == 0x%02x\n", + cond, port, index, mask, value); + return (init_rdvgai(init, port, index) & mask) == value; + } + return false; +} + +static bool +init_io_flag_condition_met(struct nvbios_init *init, u8 cond) +{ + struct nouveau_bios *bios = init->bios; + u16 table = init_io_flag_condition_table(init); + if (table) { + u16 port = nv_ro16(bios, table + (cond * 9) + 0); + u8 index = nv_ro08(bios, table + (cond * 9) + 2); + u8 mask = nv_ro08(bios, table + (cond * 9) + 3); + u8 shift = nv_ro08(bios, table + (cond * 9) + 4); + u16 data = nv_ro16(bios, table + (cond * 9) + 5); + u8 dmask = nv_ro08(bios, table + (cond * 9) + 7); + u8 value = nv_ro08(bios, table + (cond * 9) + 8); + u8 ioval = (init_rdvgai(init, port, index) & mask) >> shift; + return (nv_ro08(bios, data + ioval) & dmask) == value; + } + return false; +} + +static inline u32 +init_shift(u32 data, u8 shift) +{ + if (shift < 0x80) + return data >> shift; + return data << (0x100 - shift); +} + +static u32 +init_tmds_reg(struct nvbios_init *init, u8 tmds) +{ + /* For mlv < 0x80, it is an index into a table of TMDS base addresses. + * For mlv == 0x80 use the "or" value of the dcb_entry indexed by + * CR58 for CR57 = 0 to index a table of offsets to the basic + * 0x6808b0 address. + * For mlv == 0x81 use the "or" value of the dcb_entry indexed by + * CR58 for CR57 = 0 to index a table of offsets to the basic + * 0x6808b0 address, and then flip the offset by 8. + */ + + const int pramdac_offset[13] = { + 0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 }; + const u32 pramdac_table[4] = { + 0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8 }; + + if (tmds >= 0x80) { + if (init->outp) { + u32 dacoffset = pramdac_offset[init->outp->or]; + if (tmds == 0x81) + dacoffset ^= 8; + return 0x6808b0 + dacoffset; + } + + error("tmds opcodes need dcb\n"); + } else { + if (tmds < ARRAY_SIZE(pramdac_table)) + return pramdac_table[tmds]; + + error("tmds selector 0x%02x unknown\n", tmds); + } + + return 0; +} + +/****************************************************************************** + * init opcode handlers + *****************************************************************************/ + +/** + * init_reserved - stub for various unknown/unused single-byte opcodes + * + */ +static void +init_reserved(struct nvbios_init *init) +{ + u8 opcode = nv_ro08(init->bios, init->offset); + trace("RESERVED\t0x%02x\n", opcode); + init->offset += 1; +} + +/** + * INIT_DONE - opcode 0x71 + * + */ +static void +init_done(struct nvbios_init *init) +{ + trace("DONE\n"); + init->offset = 0x0000; +} + +/** + * INIT_IO_RESTRICT_PROG - opcode 0x32 + * + */ +static void +init_io_restrict_prog(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 shift = nv_ro08(bios, init->offset + 5); + u8 count = nv_ro08(bios, init->offset + 6); + u32 reg = nv_ro32(bios, init->offset + 7); + u8 conf, i; + + trace("IO_RESTRICT_PROG\tR[0x%06x] = " + "((0x%04x[0x%02x] & 0x%02x) >> %d) [{\n", + reg, port, index, mask, shift); + init->offset += 11; + + conf = (init_rdvgai(init, port, index) & mask) >> shift; + for (i = 0; i < count; i++) { + u32 data = nv_ro32(bios, init->offset); + + if (i == conf) { + trace("\t0x%08x *\n", data); + init_wr32(init, reg, data); + } else { + trace("\t0x%08x\n", data); + } + + init->offset += 4; + } + trace("}]\n"); +} + +/** + * INIT_REPEAT - opcode 0x33 + * + */ +static void +init_repeat(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 count = nv_ro08(bios, init->offset + 1); + u16 repeat = init->repeat; + + trace("REPEAT\t0x%02x\n", count); + init->offset += 2; + + init->repeat = init->offset; + init->repend = init->offset; + while (count--) { + init->offset = init->repeat; + nvbios_exec(init); + if (count) + trace("REPEAT\t0x%02x\n", count); + } + init->offset = init->repend; + init->repeat = repeat; +} + +/** + * INIT_IO_RESTRICT_PLL - opcode 0x34 + * + */ +static void +init_io_restrict_pll(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 shift = nv_ro08(bios, init->offset + 5); + s8 iofc = nv_ro08(bios, init->offset + 6); + u8 count = nv_ro08(bios, init->offset + 7); + u32 reg = nv_ro32(bios, init->offset + 8); + u8 conf, i; + + trace("IO_RESTRICT_PLL\tR[0x%06x] =PLL= " + "((0x%04x[0x%02x] & 0x%02x) >> 0x%02x) IOFCOND 0x%02x [{\n", + reg, port, index, mask, shift, iofc); + init->offset += 12; + + conf = (init_rdvgai(init, port, index) & mask) >> shift; + for (i = 0; i < count; i++) { + u32 freq = nv_ro16(bios, init->offset) * 10; + + if (i == conf) { + trace("\t%dkHz *\n", freq); + if (iofc > 0 && init_io_flag_condition_met(init, iofc)) + freq *= 2; + init_prog_pll(init, reg, freq); + } else { + trace("\t%dkHz\n", freq); + } + + init->offset += 2; + } + trace("}]\n"); +} + +/** + * INIT_END_REPEAT - opcode 0x36 + * + */ +static void +init_end_repeat(struct nvbios_init *init) +{ + trace("END_REPEAT\n"); + init->offset += 1; + + if (init->repeat) { + init->repend = init->offset; + init->offset = 0; + } +} + +/** + * INIT_COPY - opcode 0x37 + * + */ +static void +init_copy(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u8 shift = nv_ro08(bios, init->offset + 5); + u8 smask = nv_ro08(bios, init->offset + 6); + u16 port = nv_ro16(bios, init->offset + 7); + u8 index = nv_ro08(bios, init->offset + 9); + u8 mask = nv_ro08(bios, init->offset + 10); + u8 data; + + trace("COPY\t0x%04x[0x%02x] &= 0x%02x |= " + "((R[0x%06x] %s 0x%02x) & 0x%02x)\n", + port, index, mask, reg, (shift & 0x80) ? "<<" : ">>", + (shift & 0x80) ? (0x100 - shift) : shift, smask); + init->offset += 11; + + data = init_rdvgai(init, port, index) & mask; + data |= init_shift(init_rd32(init, reg), shift) & smask; + init_wrvgai(init, port, index, data); +} + +/** + * INIT_NOT - opcode 0x38 + * + */ +static void +init_not(struct nvbios_init *init) +{ + trace("NOT\n"); + init->offset += 1; + init_exec_inv(init); +} + +/** + * INIT_IO_FLAG_CONDITION - opcode 0x39 + * + */ +static void +init_io_flag_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + + trace("IO_FLAG_CONDITION\t0x%02x\n", cond); + init->offset += 2; + + if (!init_io_flag_condition_met(init, cond)) + init_exec_set(init, false); +} + +/** + * INIT_DP_CONDITION - opcode 0x3a + * + */ +static void +init_dp_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + u8 unkn = nv_ro08(bios, init->offset + 2); + u8 ver, len; + u16 data; + + trace("DP_CONDITION\t0x%02x 0x%02x\n", cond, unkn); + init->offset += 3; + + switch (cond) { + case 0: + if (init_conn(init) != DCB_CONNECTOR_eDP) + init_exec_set(init, false); + break; + case 1: + case 2: + if ( init->outp && + (data = dp_outp_match(bios, init->outp, &ver, &len))) { + if (ver <= 0x40 && !(nv_ro08(bios, data + 5) & cond)) + init_exec_set(init, false); + if (ver == 0x40 && !(nv_ro08(bios, data + 4) & cond)) + init_exec_set(init, false); + break; + } + + warn("script needs dp output table data\n"); + break; + case 5: + if (!(init_rdauxr(init, 0x0d) & 1)) + init_exec_set(init, false); + break; + default: + warn("unknown dp condition 0x%02x\n", cond); + break; + } +} + +/** + * INIT_IO_MASK_OR - opcode 0x3b + * + */ +static void +init_io_mask_or(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 or = init_or(init); + u8 data; + + trace("IO_MASK_OR\t0x03d4[0x%02x] &= ~(1 << 0x%02x)", index, or); + init->offset += 2; + + data = init_rdvgai(init, 0x03d4, index); + init_wrvgai(init, 0x03d4, index, data &= ~(1 << or)); +} + +/** + * INIT_IO_OR - opcode 0x3c + * + */ +static void +init_io_or(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 or = init_or(init); + u8 data; + + trace("IO_OR\t0x03d4[0x%02x] |= (1 << 0x%02x)", index, or); + init->offset += 2; + + data = init_rdvgai(init, 0x03d4, index); + init_wrvgai(init, 0x03d4, index, data | (1 << or)); +} + +/** + * INIT_INDEX_ADDRESS_LATCHED - opcode 0x49 + * + */ +static void +init_idx_addr_latched(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 creg = nv_ro32(bios, init->offset + 1); + u32 dreg = nv_ro32(bios, init->offset + 5); + u32 mask = nv_ro32(bios, init->offset + 9); + u32 data = nv_ro32(bios, init->offset + 13); + u8 count = nv_ro08(bios, init->offset + 17); + + trace("INDEX_ADDRESS_LATCHED\t" + "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n", + creg, dreg, mask, data); + init->offset += 18; + + while (count--) { + u8 iaddr = nv_ro08(bios, init->offset + 0); + u8 idata = nv_ro08(bios, init->offset + 1); + + trace("\t[0x%02x] = 0x%02x\n", iaddr, idata); + init->offset += 2; + + init_wr32(init, dreg, idata); + init_mask(init, creg, ~mask, data | idata); + } +} + +/** + * INIT_IO_RESTRICT_PLL2 - opcode 0x4a + * + */ +static void +init_io_restrict_pll2(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 shift = nv_ro08(bios, init->offset + 5); + u8 count = nv_ro08(bios, init->offset + 6); + u32 reg = nv_ro32(bios, init->offset + 7); + u8 conf, i; + + trace("IO_RESTRICT_PLL2\t" + "R[0x%06x] =PLL= ((0x%04x[0x%02x] & 0x%02x) >> 0x%02x) [{\n", + reg, port, index, mask, shift); + init->offset += 11; + + conf = (init_rdvgai(init, port, index) & mask) >> shift; + for (i = 0; i < count; i++) { + u32 freq = nv_ro32(bios, init->offset); + if (i == conf) { + trace("\t%dkHz *\n", freq); + init_prog_pll(init, reg, freq); + } else { + trace("\t%dkHz\n", freq); + } + init->offset += 4; + } + trace("}]\n"); +} + +/** + * INIT_PLL2 - opcode 0x4b + * + */ +static void +init_pll2(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 freq = nv_ro32(bios, init->offset + 5); + + trace("PLL2\tR[0x%06x] =PLL= %dkHz\n", reg, freq); + init->offset += 9; + + init_prog_pll(init, reg, freq); +} + +/** + * INIT_I2C_BYTE - opcode 0x4c + * + */ +static void +init_i2c_byte(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 count = nv_ro08(bios, init->offset + 3); + + trace("I2C_BYTE\tI2C[0x%02x][0x%02x]\n", index, addr); + init->offset += 4; + + while (count--) { + u8 reg = nv_ro08(bios, init->offset + 0); + u8 mask = nv_ro08(bios, init->offset + 1); + u8 data = nv_ro08(bios, init->offset + 2); + int val; + + trace("\t[0x%02x] &= 0x%02x |= 0x%02x\n", reg, mask, data); + init->offset += 3; + + val = init_rdi2cr(init, index, addr, reg); + if (val < 0) + continue; + init_wri2cr(init, index, addr, reg, (val & mask) | data); + } +} + +/** + * INIT_ZM_I2C_BYTE - opcode 0x4d + * + */ +static void +init_zm_i2c_byte(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 count = nv_ro08(bios, init->offset + 3); + + trace("ZM_I2C_BYTE\tI2C[0x%02x][0x%02x]\n", index, addr); + init->offset += 4; + + while (count--) { + u8 reg = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + + trace("\t[0x%02x] = 0x%02x\n", reg, data); + init->offset += 2; + + init_wri2cr(init, index, addr, reg, data); + } + +} + +/** + * INIT_ZM_I2C - opcode 0x4e + * + */ +static void +init_zm_i2c(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 count = nv_ro08(bios, init->offset + 3); + u8 data[256], i; + + trace("ZM_I2C\tI2C[0x%02x][0x%02x]\n", index, addr); + init->offset += 4; + + for (i = 0; i < count; i++) { + data[i] = nv_ro08(bios, init->offset); + trace("\t0x%02x\n", data[i]); + init->offset++; + } + + if (init_exec(init)) { + struct nouveau_i2c_port *port = init_i2c(init, index); + struct i2c_msg msg = { + .addr = addr, .flags = 0, .len = count, .buf = data, + }; + int ret; + + if (port && (ret = i2c_transfer(&port->adapter, &msg, 1)) != 1) + warn("i2c wr failed, %d\n", ret); + } +} + +/** + * INIT_TMDS - opcode 0x4f + * + */ +static void +init_tmds(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 tmds = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2); + u8 mask = nv_ro08(bios, init->offset + 3); + u8 data = nv_ro08(bios, init->offset + 4); + u32 reg = init_tmds_reg(init, tmds); + + trace("TMDS\tT[0x%02x][0x%02x] &= 0x%02x |= 0x%02x\n", + tmds, addr, mask, data); + init->offset += 5; + + if (reg == 0) + return; + + init_wr32(init, reg + 0, addr | 0x00010000); + init_wr32(init, reg + 4, data | (init_rd32(init, reg + 4) & mask)); + init_wr32(init, reg + 0, addr); +} + +/** + * INIT_ZM_TMDS_GROUP - opcode 0x50 + * + */ +static void +init_zm_tmds_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 tmds = nv_ro08(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 2); + u32 reg = init_tmds_reg(init, tmds); + + trace("TMDS_ZM_GROUP\tT[0x%02x]\n", tmds); + init->offset += 3; + + while (count--) { + u8 addr = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + + trace("\t[0x%02x] = 0x%02x\n", addr, data); + init->offset += 2; + + init_wr32(init, reg + 4, data); + init_wr32(init, reg + 0, addr); + } +} + +/** + * INIT_CR_INDEX_ADDRESS_LATCHED - opcode 0x51 + * + */ +static void +init_cr_idx_adr_latch(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 addr0 = nv_ro08(bios, init->offset + 1); + u8 addr1 = nv_ro08(bios, init->offset + 2); + u8 base = nv_ro08(bios, init->offset + 3); + u8 count = nv_ro08(bios, init->offset + 4); + u8 save0; + + trace("CR_INDEX_ADDR C[%02x] C[%02x]\n", addr0, addr1); + init->offset += 5; + + save0 = init_rdvgai(init, 0x03d4, addr0); + while (count--) { + u8 data = nv_ro08(bios, init->offset); + + trace("\t\t[0x%02x] = 0x%02x\n", base, data); + init->offset += 1; + + init_wrvgai(init, 0x03d4, addr0, base++); + init_wrvgai(init, 0x03d4, addr1, data); + } + init_wrvgai(init, 0x03d4, addr0, save0); +} + +/** + * INIT_CR - opcode 0x52 + * + */ +static void +init_cr(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 addr = nv_ro08(bios, init->offset + 1); + u8 mask = nv_ro08(bios, init->offset + 2); + u8 data = nv_ro08(bios, init->offset + 3); + u8 val; + + trace("CR\t\tC[0x%02x] &= 0x%02x |= 0x%02x\n", addr, mask, data); + init->offset += 4; + + val = init_rdvgai(init, 0x03d4, addr) & mask; + init_wrvgai(init, 0x03d4, addr, val | data); +} + +/** + * INIT_ZM_CR - opcode 0x53 + * + */ +static void +init_zm_cr(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 addr = nv_ro08(bios, init->offset + 1); + u8 data = nv_ro08(bios, init->offset + 2); + + trace("ZM_CR\tC[0x%02x] = 0x%02x\n", addr, data); + init->offset += 3; + + init_wrvgai(init, 0x03d4, addr, data); +} + +/** + * INIT_ZM_CR_GROUP - opcode 0x54 + * + */ +static void +init_zm_cr_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 count = nv_ro08(bios, init->offset + 1); + + trace("ZM_CR_GROUP\n"); + init->offset += 2; + + while (count--) { + u8 addr = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + + trace("\t\tC[0x%02x] = 0x%02x\n", addr, data); + init->offset += 2; + + init_wrvgai(init, 0x03d4, addr, data); + } +} + +/** + * INIT_CONDITION_TIME - opcode 0x56 + * + */ +static void +init_condition_time(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + u8 retry = nv_ro08(bios, init->offset + 2); + u8 wait = min((u16)retry * 50, 100); + + trace("CONDITION_TIME\t0x%02x 0x%02x\n", cond, retry); + init->offset += 3; + + if (!init_exec(init)) + return; + + while (wait--) { + if (init_condition_met(init, cond)) + return; + mdelay(20); + } + + init_exec_set(init, false); +} + +/** + * INIT_LTIME - opcode 0x57 + * + */ +static void +init_ltime(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 msec = nv_ro16(bios, init->offset + 1); + + trace("LTIME\t0x%04x\n", msec); + init->offset += 3; + + if (init_exec(init)) + mdelay(msec); +} + +/** + * INIT_ZM_REG_SEQUENCE - opcode 0x58 + * + */ +static void +init_zm_reg_sequence(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 base = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("ZM_REG_SEQUENCE\t0x%02x\n", count); + init->offset += 6; + + while (count--) { + u32 data = nv_ro32(bios, init->offset); + + trace("\t\tR[0x%06x] = 0x%08x\n", base, data); + init->offset += 4; + + init_wr32(init, base, data); + base += 4; + } +} + +/** + * INIT_SUB_DIRECT - opcode 0x5b + * + */ +static void +init_sub_direct(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 addr = nv_ro16(bios, init->offset + 1); + u16 save; + + trace("SUB_DIRECT\t0x%04x\n", addr); + + if (init_exec(init)) { + save = init->offset; + init->offset = addr; + if (nvbios_exec(init)) { + error("error parsing sub-table\n"); + return; + } + init->offset = save; + } + + init->offset += 3; +} + +/** + * INIT_JUMP - opcode 0x5c + * + */ +static void +init_jump(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 offset = nv_ro16(bios, init->offset + 1); + + trace("JUMP\t0x%04x\n", offset); + init->offset = offset; +} + +/** + * INIT_I2C_IF - opcode 0x5e + * + */ +static void +init_i2c_if(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2); + u8 reg = nv_ro08(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 data = nv_ro08(bios, init->offset + 5); + u8 value; + + trace("I2C_IF\tI2C[0x%02x][0x%02x][0x%02x] & 0x%02x == 0x%02x\n", + index, addr, reg, mask, data); + init->offset += 6; + init_exec_force(init, true); + + value = init_rdi2cr(init, index, addr, reg); + if ((value & mask) != data) + init_exec_set(init, false); + + init_exec_force(init, false); +} + +/** + * INIT_COPY_NV_REG - opcode 0x5f + * + */ +static void +init_copy_nv_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 sreg = nv_ro32(bios, init->offset + 1); + u8 shift = nv_ro08(bios, init->offset + 5); + u32 smask = nv_ro32(bios, init->offset + 6); + u32 sxor = nv_ro32(bios, init->offset + 10); + u32 dreg = nv_ro32(bios, init->offset + 14); + u32 dmask = nv_ro32(bios, init->offset + 18); + u32 data; + + trace("COPY_NV_REG\tR[0x%06x] &= 0x%08x |= " + "((R[0x%06x] %s 0x%02x) & 0x%08x ^ 0x%08x)\n", + dreg, dmask, sreg, (shift & 0x80) ? "<<" : ">>", + (shift & 0x80) ? (0x100 - shift) : shift, smask, sxor); + init->offset += 22; + + data = init_shift(init_rd32(init, sreg), shift); + init_mask(init, dreg, ~dmask, (data & smask) ^ sxor); +} + +/** + * INIT_ZM_INDEX_IO - opcode 0x62 + * + */ +static void +init_zm_index_io(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro08(bios, init->offset + 3); + u8 data = nv_ro08(bios, init->offset + 4); + + trace("ZM_INDEX_IO\tI[0x%04x][0x%02x] = 0x%02x\n", port, index, data); + init->offset += 5; + + init_wrvgai(init, port, index, data); +} + +/** + * INIT_COMPUTE_MEM - opcode 0x63 + * + */ +static void +init_compute_mem(struct nvbios_init *init) +{ + struct nouveau_devinit *devinit = nouveau_devinit(init->bios); + + trace("COMPUTE_MEM\n"); + init->offset += 1; + + init_exec_force(init, true); + if (init_exec(init) && devinit->meminit) + devinit->meminit(devinit); + init_exec_force(init, false); +} + +/** + * INIT_RESET - opcode 0x65 + * + */ +static void +init_reset(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 data1 = nv_ro32(bios, init->offset + 5); + u32 data2 = nv_ro32(bios, init->offset + 9); + u32 savepci19; + + trace("RESET\tR[0x%08x] = 0x%08x, 0x%08x", reg, data1, data2); + init->offset += 13; + init_exec_force(init, true); + + savepci19 = init_mask(init, 0x00184c, 0x00000f00, 0x00000000); + init_wr32(init, reg, data1); + udelay(10); + init_wr32(init, reg, data2); + init_wr32(init, 0x00184c, savepci19); + init_mask(init, 0x001850, 0x00000001, 0x00000000); + + init_exec_force(init, false); +} + +/** + * INIT_CONFIGURE_MEM - opcode 0x66 + * + */ +static u16 +init_configure_mem_clk(struct nvbios_init *init) +{ + u16 mdata = bmp_mem_init_table(init->bios); + if (mdata) + mdata += (init_rdvgai(init, 0x03d4, 0x3c) >> 4) * 66; + return mdata; +} + +static void +init_configure_mem(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 mdata, sdata; + u32 addr, data; + + trace("CONFIGURE_MEM\n"); + init->offset += 1; + + if (bios->version.major > 2) { + init_done(init); + return; + } + init_exec_force(init, true); + + mdata = init_configure_mem_clk(init); + sdata = bmp_sdr_seq_table(bios); + if (nv_ro08(bios, mdata) & 0x01) + sdata = bmp_ddr_seq_table(bios); + mdata += 6; /* skip to data */ + + data = init_rdvgai(init, 0x03c4, 0x01); + init_wrvgai(init, 0x03c4, 0x01, data | 0x20); + + while ((addr = nv_ro32(bios, sdata)) != 0xffffffff) { + switch (addr) { + case 0x10021c: /* CKE_NORMAL */ + case 0x1002d0: /* CMD_REFRESH */ + case 0x1002d4: /* CMD_PRECHARGE */ + data = 0x00000001; + break; + default: + data = nv_ro32(bios, mdata); + mdata += 4; + if (data == 0xffffffff) + continue; + break; + } + + init_wr32(init, addr, data); + } + + init_exec_force(init, false); +} + +/** + * INIT_CONFIGURE_CLK - opcode 0x67 + * + */ +static void +init_configure_clk(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 mdata, clock; + + trace("CONFIGURE_CLK\n"); + init->offset += 1; + + if (bios->version.major > 2) { + init_done(init); + return; + } + init_exec_force(init, true); + + mdata = init_configure_mem_clk(init); + + /* NVPLL */ + clock = nv_ro16(bios, mdata + 4) * 10; + init_prog_pll(init, 0x680500, clock); + + /* MPLL */ + clock = nv_ro16(bios, mdata + 2) * 10; + if (nv_ro08(bios, mdata) & 0x01) + clock *= 2; + init_prog_pll(init, 0x680504, clock); + + init_exec_force(init, false); +} + +/** + * INIT_CONFIGURE_PREINIT - opcode 0x68 + * + */ +static void +init_configure_preinit(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 strap; + + trace("CONFIGURE_PREINIT\n"); + init->offset += 1; + + if (bios->version.major > 2) { + init_done(init); + return; + } + init_exec_force(init, true); + + strap = init_rd32(init, 0x101000); + strap = ((strap << 2) & 0xf0) | ((strap & 0x40) >> 6); + init_wrvgai(init, 0x03d4, 0x3c, strap); + + init_exec_force(init, false); +} + +/** + * INIT_IO - opcode 0x69 + * + */ +static void +init_io(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 mask = nv_ro16(bios, init->offset + 3); + u8 data = nv_ro16(bios, init->offset + 4); + u8 value; + + trace("IO\t\tI[0x%04x] &= 0x%02x |= 0x%02x\n", port, mask, data); + init->offset += 5; + + /* ummm.. yes.. should really figure out wtf this is and why it's + * needed some day.. it's almost certainly wrong, but, it also + * somehow makes things work... + */ + if (nv_device(init->bios)->card_type >= NV_50 && + port == 0x03c3 && data == 0x01) { + init_mask(init, 0x614100, 0xf0800000, 0x00800000); + init_mask(init, 0x00e18c, 0x00020000, 0x00020000); + init_mask(init, 0x614900, 0xf0800000, 0x00800000); + init_mask(init, 0x000200, 0x40000000, 0x00000000); + mdelay(10); + init_mask(init, 0x00e18c, 0x00020000, 0x00000000); + init_mask(init, 0x000200, 0x40000000, 0x40000000); + init_wr32(init, 0x614100, 0x00800018); + init_wr32(init, 0x614900, 0x00800018); + mdelay(10); + init_wr32(init, 0x614100, 0x10000018); + init_wr32(init, 0x614900, 0x10000018); + return; + } + + value = init_rdport(init, port) & mask; + init_wrport(init, port, data | value); +} + +/** + * INIT_SUB - opcode 0x6b + * + */ +static void +init_sub(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u16 addr, save; + + trace("SUB\t0x%02x\n", index); + + addr = init_script(bios, index); + if (addr && init_exec(init)) { + save = init->offset; + init->offset = addr; + if (nvbios_exec(init)) { + error("error parsing sub-table\n"); + return; + } + init->offset = save; + } + + init->offset += 2; +} + +/** + * INIT_RAM_CONDITION - opcode 0x6d + * + */ +static void +init_ram_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 mask = nv_ro08(bios, init->offset + 1); + u8 value = nv_ro08(bios, init->offset + 2); + + trace("RAM_CONDITION\t" + "(R[0x100000] & 0x%02x) == 0x%02x\n", mask, value); + init->offset += 3; + + if ((init_rd32(init, 0x100000) & mask) != value) + init_exec_set(init, false); +} + +/** + * INIT_NV_REG - opcode 0x6e + * + */ +static void +init_nv_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 mask = nv_ro32(bios, init->offset + 5); + u32 data = nv_ro32(bios, init->offset + 9); + + trace("NV_REG\tR[0x%06x] &= 0x%08x |= 0x%08x\n", reg, mask, data); + init->offset += 13; + + init_mask(init, reg, ~mask, data); +} + +/** + * INIT_MACRO - opcode 0x6f + * + */ +static void +init_macro(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 macro = nv_ro08(bios, init->offset + 1); + u16 table; + + trace("MACRO\t0x%02x\n", macro); + + table = init_macro_table(init); + if (table) { + u32 addr = nv_ro32(bios, table + (macro * 8) + 0); + u32 data = nv_ro32(bios, table + (macro * 8) + 4); + trace("\t\tR[0x%06x] = 0x%08x\n", addr, data); + init_wr32(init, addr, data); + } + + init->offset += 2; +} + +/** + * INIT_RESUME - opcode 0x72 + * + */ +static void +init_resume(struct nvbios_init *init) +{ + trace("RESUME\n"); + init->offset += 1; + init_exec_set(init, true); +} + +/** + * INIT_TIME - opcode 0x74 + * + */ +static void +init_time(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 usec = nv_ro16(bios, init->offset + 1); + + trace("TIME\t0x%04x\n", usec); + init->offset += 3; + + if (init_exec(init)) { + if (usec < 1000) + udelay(usec); + else + mdelay((usec + 900) / 1000); + } +} + +/** + * INIT_CONDITION - opcode 0x75 + * + */ +static void +init_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + + trace("CONDITION\t0x%02x\n", cond); + init->offset += 2; + + if (!init_condition_met(init, cond)) + init_exec_set(init, false); +} + +/** + * INIT_IO_CONDITION - opcode 0x76 + * + */ +static void +init_io_condition(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 cond = nv_ro08(bios, init->offset + 1); + + trace("IO_CONDITION\t0x%02x\n", cond); + init->offset += 2; + + if (!init_io_condition_met(init, cond)) + init_exec_set(init, false); +} + +/** + * INIT_INDEX_IO - opcode 0x78 + * + */ +static void +init_index_io(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u16 port = nv_ro16(bios, init->offset + 1); + u8 index = nv_ro16(bios, init->offset + 3); + u8 mask = nv_ro08(bios, init->offset + 4); + u8 data = nv_ro08(bios, init->offset + 5); + u8 value; + + trace("INDEX_IO\tI[0x%04x][0x%02x] &= 0x%02x |= 0x%02x\n", + port, index, mask, data); + init->offset += 6; + + value = init_rdvgai(init, port, index) & mask; + init_wrvgai(init, port, index, data | value); +} + +/** + * INIT_PLL - opcode 0x79 + * + */ +static void +init_pll(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u32 freq = nv_ro16(bios, init->offset + 5) * 10; + + trace("PLL\tR[0x%06x] =PLL= %dkHz\n", reg, freq); + init->offset += 7; + + init_prog_pll(init, reg, freq); +} + +/** + * INIT_ZM_REG - opcode 0x7a + * + */ +static void +init_zm_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u32 data = nv_ro32(bios, init->offset + 5); + + trace("ZM_REG\tR[0x%06x] = 0x%08x\n", addr, data); + init->offset += 9; + + if (addr == 0x000200) + data |= 0x00000001; + + init_wr32(init, addr, data); +} + +/** + * INIT_RAM_RESTRICT_PLL - opcde 0x87 + * + */ +static void +init_ram_restrict_pll(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 type = nv_ro08(bios, init->offset + 1); + u8 count = init_ram_restrict_group_count(init); + u8 strap = init_ram_restrict(init); + u8 cconf; + + trace("RAM_RESTRICT_PLL\t0x%02x\n", type); + init->offset += 2; + + for (cconf = 0; cconf < count; cconf++) { + u32 freq = nv_ro32(bios, init->offset); + + if (cconf == strap) { + trace("%dkHz *\n", freq); + init_prog_pll(init, type, freq); + } else { + trace("%dkHz\n", freq); + } + + init->offset += 4; + } +} + +/** + * INIT_GPIO - opcode 0x8e + * + */ +static void +init_gpio(struct nvbios_init *init) +{ + struct nouveau_gpio *gpio = nouveau_gpio(init->bios); + + trace("GPIO\n"); + init->offset += 1; + + if (init_exec(init) && gpio && gpio->reset) + gpio->reset(gpio); +} + +/** + * INIT_RAM_RESTRICT_ZM_GROUP - opcode 0x8f + * + */ +static void +init_ram_restrict_zm_reg_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 incr = nv_ro08(bios, init->offset + 5); + u8 num = nv_ro08(bios, init->offset + 6); + u8 count = init_ram_restrict_group_count(init); + u8 index = init_ram_restrict(init); + u8 i, j; + + trace("RAM_RESTRICT_ZM_REG_GROUP\t" + "R[%08x] 0x%02x 0x%02x\n", addr, incr, num); + init->offset += 7; + + for (i = 0; i < num; i++) { + trace("\tR[0x%06x] = {\n", addr); + for (j = 0; j < count; j++) { + u32 data = nv_ro32(bios, init->offset); + + if (j == index) { + trace("\t\t0x%08x *\n", data); + init_wr32(init, addr, data); + } else { + trace("\t\t0x%08x\n", data); + } + + init->offset += 4; + } + trace("\t}\n"); + addr += incr; + } +} + +/** + * INIT_COPY_ZM_REG - opcode 0x90 + * + */ +static void +init_copy_zm_reg(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 sreg = nv_ro32(bios, init->offset + 1); + u32 dreg = nv_ro32(bios, init->offset + 5); + + trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", sreg, dreg); + init->offset += 9; + + init_wr32(init, dreg, init_rd32(init, sreg)); +} + +/** + * INIT_ZM_REG_GROUP - opcode 0x91 + * + */ +static void +init_zm_reg_group(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("ZM_REG_GROUP\tR[0x%06x] =\n"); + init->offset += 6; + + while (count--) { + u32 data = nv_ro32(bios, init->offset); + trace("\t0x%08x\n", data); + init_wr32(init, addr, data); + init->offset += 4; + } +} + +/** + * INIT_XLAT - opcode 0x96 + * + */ +static void +init_xlat(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 saddr = nv_ro32(bios, init->offset + 1); + u8 sshift = nv_ro08(bios, init->offset + 5); + u8 smask = nv_ro08(bios, init->offset + 6); + u8 index = nv_ro08(bios, init->offset + 7); + u32 daddr = nv_ro32(bios, init->offset + 8); + u32 dmask = nv_ro32(bios, init->offset + 12); + u8 shift = nv_ro08(bios, init->offset + 16); + u32 data; + + trace("INIT_XLAT\tR[0x%06x] &= 0x%08x |= " + "(X%02x((R[0x%06x] %s 0x%02x) & 0x%02x) << 0x%02x)\n", + daddr, dmask, index, saddr, (sshift & 0x80) ? "<<" : ">>", + (sshift & 0x80) ? (0x100 - sshift) : sshift, smask, shift); + init->offset += 17; + + data = init_shift(init_rd32(init, saddr), sshift) & smask; + data = init_xlat_(init, index, data) << shift; + init_mask(init, daddr, ~dmask, data); +} + +/** + * INIT_ZM_MASK_ADD - opcode 0x97 + * + */ +static void +init_zm_mask_add(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u32 mask = nv_ro32(bios, init->offset + 5); + u32 add = nv_ro32(bios, init->offset + 9); + u32 data; + + trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add); + init->offset += 13; + + data = init_rd32(init, addr) & mask; + data |= ((data + add) & ~mask); + init_wr32(init, addr, data); +} + +/** + * INIT_AUXCH - opcode 0x98 + * + */ +static void +init_auxch(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("AUXCH\tAUX[0x%08x] 0x%02x\n", addr, count); + init->offset += 6; + + while (count--) { + u8 mask = nv_ro08(bios, init->offset + 0); + u8 data = nv_ro08(bios, init->offset + 1); + trace("\tAUX[0x%08x] &= 0x%02x |= 0x%02x\n", addr, mask, data); + mask = init_rdauxr(init, addr) & mask; + init_wrauxr(init, addr, mask | data); + init->offset += 2; + } +} + +/** + * INIT_AUXCH - opcode 0x99 + * + */ +static void +init_zm_auxch(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u32 addr = nv_ro32(bios, init->offset + 1); + u8 count = nv_ro08(bios, init->offset + 5); + + trace("ZM_AUXCH\tAUX[0x%08x] 0x%02x\n", addr, count); + init->offset += 6; + + while (count--) { + u8 data = nv_ro08(bios, init->offset + 0); + trace("\tAUX[0x%08x] = 0x%02x\n", addr, data); + init_wrauxr(init, addr, data); + init->offset += 1; + } +} + +/** + * INIT_I2C_LONG_IF - opcode 0x9a + * + */ +static void +init_i2c_long_if(struct nvbios_init *init) +{ + struct nouveau_bios *bios = init->bios; + u8 index = nv_ro08(bios, init->offset + 1); + u8 addr = nv_ro08(bios, init->offset + 2) >> 1; + u8 reglo = nv_ro08(bios, init->offset + 3); + u8 reghi = nv_ro08(bios, init->offset + 4); + u8 mask = nv_ro08(bios, init->offset + 5); + u8 data = nv_ro08(bios, init->offset + 6); + struct nouveau_i2c_port *port; + + trace("I2C_LONG_IF\t" + "I2C[0x%02x][0x%02x][0x%02x%02x] & 0x%02x == 0x%02x\n", + index, addr, reglo, reghi, mask, data); + init->offset += 7; + + port = init_i2c(init, index); + if (port) { + u8 i[2] = { reghi, reglo }; + u8 o[1] = {}; + struct i2c_msg msg[] = { + { .addr = addr, .flags = 0, .len = 2, .buf = i }, + { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = o } + }; + int ret; + + ret = i2c_transfer(&port->adapter, msg, 2); + if (ret == 2 && ((o[0] & mask) == data)) + return; + } + + init_exec_set(init, false); +} + +static struct nvbios_init_opcode { + void (*exec)(struct nvbios_init *); +} init_opcode[] = { + [0x32] = { init_io_restrict_prog }, + [0x33] = { init_repeat }, + [0x34] = { init_io_restrict_pll }, + [0x36] = { init_end_repeat }, + [0x37] = { init_copy }, + [0x38] = { init_not }, + [0x39] = { init_io_flag_condition }, + [0x3a] = { init_dp_condition }, + [0x3b] = { init_io_mask_or }, + [0x3c] = { init_io_or }, + [0x49] = { init_idx_addr_latched }, + [0x4a] = { init_io_restrict_pll2 }, + [0x4b] = { init_pll2 }, + [0x4c] = { init_i2c_byte }, + [0x4d] = { init_zm_i2c_byte }, + [0x4e] = { init_zm_i2c }, + [0x4f] = { init_tmds }, + [0x50] = { init_zm_tmds_group }, + [0x51] = { init_cr_idx_adr_latch }, + [0x52] = { init_cr }, + [0x53] = { init_zm_cr }, + [0x54] = { init_zm_cr_group }, + [0x56] = { init_condition_time }, + [0x57] = { init_ltime }, + [0x58] = { init_zm_reg_sequence }, + [0x5b] = { init_sub_direct }, + [0x5c] = { init_jump }, + [0x5e] = { init_i2c_if }, + [0x5f] = { init_copy_nv_reg }, + [0x62] = { init_zm_index_io }, + [0x63] = { init_compute_mem }, + [0x65] = { init_reset }, + [0x66] = { init_configure_mem }, + [0x67] = { init_configure_clk }, + [0x68] = { init_configure_preinit }, + [0x69] = { init_io }, + [0x6b] = { init_sub }, + [0x6d] = { init_ram_condition }, + [0x6e] = { init_nv_reg }, + [0x6f] = { init_macro }, + [0x71] = { init_done }, + [0x72] = { init_resume }, + [0x74] = { init_time }, + [0x75] = { init_condition }, + [0x76] = { init_io_condition }, + [0x78] = { init_index_io }, + [0x79] = { init_pll }, + [0x7a] = { init_zm_reg }, + [0x87] = { init_ram_restrict_pll }, + [0x8c] = { init_reserved }, + [0x8d] = { init_reserved }, + [0x8e] = { init_gpio }, + [0x8f] = { init_ram_restrict_zm_reg_group }, + [0x90] = { init_copy_zm_reg }, + [0x91] = { init_zm_reg_group }, + [0x92] = { init_reserved }, + [0x96] = { init_xlat }, + [0x97] = { init_zm_mask_add }, + [0x98] = { init_auxch }, + [0x99] = { init_zm_auxch }, + [0x9a] = { init_i2c_long_if }, +}; + +#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) + +int +nvbios_exec(struct nvbios_init *init) +{ + init->nested++; + while (init->offset) { + u8 opcode = nv_ro08(init->bios, init->offset); + if (opcode >= init_opcode_nr || !init_opcode[opcode].exec) { + error("unknown opcode 0x%02x\n", opcode); + return -EINVAL; + } + + init_opcode[opcode].exec(init); + } + init->nested--; + return 0; +} + +int +nvbios_init(struct nouveau_subdev *subdev, bool execute) +{ + struct nouveau_bios *bios = nouveau_bios(subdev); + int ret = 0; + int i = -1; + u16 data; + + if (execute) + nv_info(bios, "running init tables\n"); + while (!ret && (data = (init_script(bios, ++i)))) { + struct nvbios_init init = { + .subdev = subdev, + .bios = bios, + .offset = data, + .outp = NULL, + .crtc = -1, + .execute = execute ? 1 : 0, + }; + + ret = nvbios_exec(&init); + } + + /* the vbios parser will run this right after the normal init + * tables, whereas the binary driver appears to run it later. + */ + if (!ret && (data = init_unknown_script(bios))) { + struct nvbios_init init = { + .subdev = subdev, + .bios = bios, + .offset = data, + .outp = NULL, + .crtc = -1, + .execute = execute ? 1 : 0, + }; + + ret = nvbios_exec(&init); + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index e24e74b..47f7841 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -26,6 +26,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -35,11 +36,13 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 0b8eb74..ad481eb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -37,48 +38,56 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 1432ef0..51ef1f4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -37,24 +38,28 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 7eeab78..e812f71 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -37,30 +38,35 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index ec7c03f..8d2b62c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -37,96 +38,112 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 0674163..cb50d86 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -37,84 +38,98 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 56aae6b..67c46fc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -27,6 +27,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -37,48 +38,56 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 8ad51cc..a1e87df 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -27,6 +27,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -37,12 +38,14 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c new file mode 100644 index 0000000..5a07a39 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c @@ -0,0 +1,69 @@ +/* + * 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: + * + * 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 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 + +#include +#include +#include + +int +nouveau_devinit_init(struct nouveau_devinit *devinit) +{ + int ret = nouveau_subdev_init(&devinit->base); + if (ret) + return ret; + + return nvbios_init(&devinit->base, devinit->post); +} + +int +nouveau_devinit_fini(struct nouveau_devinit *devinit, bool suspend) +{ + /* force full reinit on resume */ + if (suspend) + devinit->post = true; + + return nouveau_subdev_fini(&devinit->base, suspend); +} + +int +nouveau_devinit_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int size, void **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_devinit *devinit; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "DEVINIT", + "init", size, pobject); + devinit = *pobject; + if (ret) + return ret; + + devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h new file mode 100644 index 0000000..6b56a0f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#define NV04_PFB_BOOT_0 0x00100000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 +# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 +# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 +# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 +# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 +#define NV04_PFB_DEBUG_0 0x00100080 +# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001 +# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010 +# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00 +# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000 +# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000 +# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000 +# define NV04_PFB_DEBUG_0_CASOE 0x00100000 +# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000 +# define NV04_PFB_DEBUG_0_REFINC 0x20000000 +# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000 +#define NV04_PFB_CFG0 0x00100200 +# define NV04_PFB_CFG0_SCRAMBLE 0x20000000 +#define NV04_PFB_CFG1 0x00100204 +#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) + +#define NV10_PFB_REFCTRL 0x00100210 +# define NV10_PFB_REFCTRL_VALID_1 (1 << 31) + +static inline struct io_mapping * +fbmem_init(struct pci_dev *pdev) +{ + return io_mapping_create_wc(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); +} + +static inline void +fbmem_fini(struct io_mapping *fb) +{ + io_mapping_free(fb); +} + +static inline u32 +fbmem_peek(struct io_mapping *fb, u32 off) +{ + u8 __iomem *p = io_mapping_map_atomic_wc(fb, off & PAGE_MASK); + u32 val = ioread32(p + (off & ~PAGE_MASK)); + io_mapping_unmap_atomic(p); + return val; +} + +static inline void +fbmem_poke(struct io_mapping *fb, u32 off, u32 val) +{ + u8 __iomem *p = io_mapping_map_atomic_wc(fb, off & PAGE_MASK); + iowrite32(val, p + (off & ~PAGE_MASK)); + wmb(); + io_mapping_unmap_atomic(p); +} + +static inline bool +fbmem_readback(struct io_mapping *fb, u32 off, u32 val) +{ + fbmem_poke(fb, off, val); + return val == fbmem_peek(fb, off); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c new file mode 100644 index 0000000..7a72d93 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include +#include + +#include "fbmem.h" + +struct nv04_devinit_priv { + struct nouveau_devinit base; + int owner; +}; + +static void +nv04_devinit_meminit(struct nouveau_devinit *devinit) +{ + struct nv04_devinit_priv *priv = (void *)devinit; + u32 patt = 0xdeadbeef; + struct io_mapping *fb; + int i; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + /* Sequencer and refresh off */ + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); + nv_mask(priv, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); + + nv_mask(priv, NV04_PFB_BOOT_0, ~0, + NV04_PFB_BOOT_0_RAM_AMOUNT_16MB | + NV04_PFB_BOOT_0_RAM_WIDTH_128 | + NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT); + + for (i = 0; i < 4; i++) + fbmem_poke(fb, 4 * i, patt); + + fbmem_poke(fb, 0x400000, patt + 1); + + if (fbmem_peek(fb, 0) == patt + 1) { + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_TYPE, + NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT); + nv_mask(priv, NV04_PFB_DEBUG_0, + NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + + for (i = 0; i < 4; i++) + fbmem_poke(fb, 4 * i, patt); + + if ((fbmem_peek(fb, 0xc) & 0xffff) != (patt & 0xffff)) + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_WIDTH_128 | + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + } else + if ((fbmem_peek(fb, 0xc) & 0xffff0000) != (patt & 0xffff0000)) { + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_WIDTH_128 | + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); + } else + if (fbmem_peek(fb, 0) != patt) { + if (fbmem_readback(fb, 0x800000, patt)) + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + else + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); + + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, + NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT); + } else + if (!fbmem_readback(fb, 0x800000, patt)) { + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + + } + + /* Refresh on, sequencer on */ + nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); + fbmem_fini(fb); +} + +static int +nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv04_devinit_meminit; + priv->owner = -1; + return 0; +} + +void +nv04_devinit_dtor(struct nouveau_object *object) +{ + struct nv04_devinit_priv *priv = (void *)object; + + /* restore vga owner saved at first init, and lock crtc regs */ + nv_wrvgaowner(priv, priv->owner); + nv_lockvgac(priv, true); + + nouveau_devinit_destroy(&priv->base); +} + +int +nv04_devinit_init(struct nouveau_object *object) +{ + struct nv04_devinit_priv *priv = (void *)object; + + if (!priv->base.post) { + u32 htotal = nv_rdvgac(priv, 0, 0x06); + htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x01) << 8; + htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x20) << 4; + htotal |= (nv_rdvgac(priv, 0, 0x25) & 0x01) << 10; + htotal |= (nv_rdvgac(priv, 0, 0x41) & 0x01) << 11; + if (!htotal) { + nv_info(priv, "adaptor not initialised\n"); + priv->base.post = true; + } + } + + return nouveau_devinit_init(&priv->base); +} + +int +nv04_devinit_fini(struct nouveau_object *object, bool suspend) +{ + struct nv04_devinit_priv *priv = (void *)object; + + /* make i2c busses accessible */ + nv_mask(priv, 0x000200, 0x00000001, 0x00000001); + + /* unlock extended vga crtc regs, and unslave crtcs */ + nv_lockvgac(priv, false); + if (priv->owner < 0) + priv->owner = nv_rdvgaowner(priv); + nv_wrvgaowner(priv, 0); + + return nouveau_devinit_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv04_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c new file mode 100644 index 0000000..191447d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include +#include +#include +#include + +#include "fbmem.h" + +struct nv05_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static void +nv05_devinit_meminit(struct nouveau_devinit *devinit) +{ + static const u8 default_config_tab[][2] = { + { 0x24, 0x00 }, + { 0x28, 0x00 }, + { 0x24, 0x01 }, + { 0x1f, 0x00 }, + { 0x0f, 0x00 }, + { 0x17, 0x00 }, + { 0x06, 0x00 }, + { 0x00, 0x00 } + }; + struct nv05_devinit_priv *priv = (void *)devinit; + struct nouveau_bios *bios = nouveau_bios(priv); + struct io_mapping *fb; + u32 patt = 0xdeadbeef; + u16 data; + u8 strap, ramcfg[2]; + int i, v; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + strap = (nv_rd32(priv, 0x101000) & 0x0000003c) >> 2; + if ((data = bmp_mem_init_table(bios))) { + ramcfg[0] = nv_ro08(bios, data + 2 * strap + 0); + ramcfg[1] = nv_ro08(bios, data + 2 * strap + 1); + } else { + ramcfg[0] = default_config_tab[strap][0]; + ramcfg[1] = default_config_tab[strap][1]; + } + + /* Sequencer off */ + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20); + + if (nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) + goto out; + + nv_mask(priv, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); + + /* If present load the hardcoded scrambling table */ + if (data) { + for (i = 0, data += 0x10; i < 8; i++, data += 4) { + u32 scramble = nv_ro32(bios, data); + nv_wr32(priv, NV04_PFB_SCRAMBLE(i), scramble); + } + } + + /* Set memory type/width/length defaults depending on the straps */ + nv_mask(priv, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); + + if (ramcfg[1] & 0x80) + nv_mask(priv, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); + + nv_mask(priv, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); + nv_mask(priv, NV04_PFB_CFG1, 0, 1); + + /* Probe memory bus width */ + for (i = 0; i < 4; i++) + fbmem_poke(fb, 4 * i, patt); + + if (fbmem_peek(fb, 0xc) != patt) + nv_mask(priv, NV04_PFB_BOOT_0, + NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); + + /* Probe memory length */ + v = nv_rd32(priv, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; + + if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && + (!fbmem_readback(fb, 0x1000000, ++patt) || + !fbmem_readback(fb, 0, ++patt))) + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); + + if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && + !fbmem_readback(fb, 0x800000, ++patt)) + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); + + if (!fbmem_readback(fb, 0x400000, ++patt)) + nv_mask(priv, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, + NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); + +out: + /* Sequencer on */ + nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20); + fbmem_fini(fb); +} + +static int +nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv05_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv05_devinit_meminit; + return 0; +} + +struct nouveau_oclass +nv05_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x05), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv05_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c new file mode 100644 index 0000000..eb76ffa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include +#include + +#include "fbmem.h" + +struct nv10_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static void +nv10_devinit_meminit(struct nouveau_devinit *devinit) +{ + struct nv10_devinit_priv *priv = (void *)devinit; + const int mem_width[] = { 0x10, 0x00, 0x20 }; + const int mem_width_count = nv_device(priv)->chipset >= 0x17 ? 3 : 2; + uint32_t patt = 0xdeadbeef; + struct io_mapping *fb; + int i, j, k; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); + + /* Probe memory bus width */ + for (i = 0; i < mem_width_count; i++) { + nv_mask(priv, NV04_PFB_CFG0, 0x30, mem_width[i]); + + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) + fbmem_poke(fb, 0x1c, 0); + + fbmem_poke(fb, 0x1c, patt); + fbmem_poke(fb, 0x3c, 0); + + if (fbmem_peek(fb, 0x1c) == patt) + goto mem_width_found; + } + } + +mem_width_found: + patt <<= 1; + + /* Probe amount of installed memory */ + for (i = 0; i < 4; i++) { + int off = nv_rd32(priv, 0x10020c) - 0x100000; + + fbmem_poke(fb, off, patt); + fbmem_poke(fb, 0, 0); + + fbmem_peek(fb, 0); + fbmem_peek(fb, 0); + fbmem_peek(fb, 0); + fbmem_peek(fb, 0); + + if (fbmem_peek(fb, off) == patt) + goto amount_found; + } + + /* IC missing - disable the upper half memory space. */ + nv_mask(priv, NV04_PFB_CFG0, 0x1000, 0); + +amount_found: + fbmem_fini(fb); +} + +static int +nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv10_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv10_devinit_meminit; + return 0; +} + +struct nouveau_oclass +nv10_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c new file mode 100644 index 0000000..5b2ba63 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c @@ -0,0 +1,58 @@ +/* + * 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: + * + * 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 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 +#include + +struct nv1a_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static int +nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv1a_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + return 0; +} + +struct nouveau_oclass +nv1a_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x1a), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv1a_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c new file mode 100644 index 0000000..eb32e99 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include +#include + +#include "fbmem.h" + +struct nv20_devinit_priv { + struct nouveau_devinit base; + u8 owner; +}; + +static void +nv20_devinit_meminit(struct nouveau_devinit *devinit) +{ + struct nv20_devinit_priv *priv = (void *)devinit; + struct nouveau_device *device = nv_device(priv); + uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900); + uint32_t amount, off; + struct io_mapping *fb; + + /* Map the framebuffer aperture */ + fb = fbmem_init(nv_device(priv)->pdev); + if (!fb) { + nv_error(priv, "failed to map fb\n"); + return; + } + + nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); + + /* Allow full addressing */ + nv_mask(priv, NV04_PFB_CFG0, 0, mask); + + amount = nv_rd32(priv, 0x10020c); + for (off = amount; off > 0x2000000; off -= 0x2000000) + fbmem_poke(fb, off - 4, off); + + amount = nv_rd32(priv, 0x10020c); + if (amount != fbmem_peek(fb, amount - 4)) + /* IC missing - disable the upper half memory space. */ + nv_mask(priv, NV04_PFB_CFG0, mask, 0); + + fbmem_fini(fb); +} + +static int +nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv20_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.meminit = nv20_devinit_meminit; + return 0; +} + +struct nouveau_oclass +nv20_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_devinit_ctor, + .dtor = nv04_devinit_dtor, + .init = nv04_devinit_init, + .fini = nv04_devinit_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c new file mode 100644 index 0000000..61becfa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c @@ -0,0 +1,87 @@ +/* + * 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: + * + * 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 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 +#include + +struct nv50_devinit_priv { + struct nouveau_devinit base; +}; + +static int +nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_devinit_priv *priv; + int ret; + + ret = nouveau_devinit_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + return 0; +} + +static void +nv50_devinit_dtor(struct nouveau_object *object) +{ + struct nv50_devinit_priv *priv = (void *)object; + nouveau_devinit_destroy(&priv->base); +} + +static int +nv50_devinit_init(struct nouveau_object *object) +{ + struct nv50_devinit_priv *priv = (void *)object; + + if (!priv->base.post) { + if (!nv_rdvgac(priv, 0, 0x00) && + !nv_rdvgac(priv, 0, 0x1a)) { + nv_info(priv, "adaptor not initialised\n"); + priv->base.post = true; + } + } + + return nouveau_devinit_init(&priv->base); +} + +static int +nv50_devinit_fini(struct nouveau_object *object, bool suspend) +{ + struct nv50_devinit_priv *priv = (void *)object; + return nouveau_devinit_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv50_devinit_oclass = { + .handle = NV_SUBDEV(DEVINIT, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_devinit_ctor, + .dtor = nv50_devinit_dtor, + .init = nv50_devinit_init, + .fini = nv50_devinit_fini, + }, +}; -- cgit v1.1 From 7d9115dee978e8540734c456c925d71a37752b8d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 15:58:56 +1000 Subject: drm/nouveau/mc: port to subdev interfaces Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/subdev/mc.h | 49 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 +++ drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 +++++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 ++++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 +++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/mc/base.c | 49 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c | 89 ++++++++++++++++++---- drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c | 28 ------- drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c | 74 ++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c | 92 ++++++++++++++++------- drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | 73 ++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | 73 ++++++++++++++++++ 16 files changed, 525 insertions(+), 69 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/mc.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/base.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h new file mode 100644 index 0000000..fded97c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h @@ -0,0 +1,49 @@ +#ifndef __NOUVEAU_MC_H__ +#define __NOUVEAU_MC_H__ + +#include +#include + +struct nouveau_mc_intr { + u32 stat; + u32 unit; +}; + +struct nouveau_mc { + struct nouveau_subdev base; + const struct nouveau_mc_intr *intr_map; +}; + +static inline struct nouveau_mc * +nouveau_mc(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC]; +} + +#define nouveau_mc_create(p,e,o,d) \ + nouveau_subdev_create_((p), (e), (o), 0, "PMC", "master", \ + sizeof(**d), (void **)d) +#define nouveau_mc_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_mc_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_mc_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_mc_dtor _nouveau_subdev_dtor +#define _nouveau_mc_init _nouveau_subdev_init +#define _nouveau_mc_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_mc_oclass; +extern struct nouveau_oclass nv44_mc_oclass; +extern struct nouveau_oclass nv50_mc_oclass; +extern struct nouveau_oclass nv98_mc_oclass; +extern struct nouveau_oclass nvc0_mc_oclass; + +void nouveau_mc_intr(struct nouveau_subdev *); + +extern const struct nouveau_mc_intr nv04_mc_intr[]; +int nv04_mc_init(struct nouveau_object *); +int nv50_mc_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 47f7841..c3820a8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -27,6 +27,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -37,12 +38,14 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index ad481eb..94686f4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -28,6 +28,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -53,6 +56,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -60,6 +64,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +72,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -74,6 +80,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +88,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +96,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 51ef1f4..d14041e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -28,6 +28,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -53,6 +56,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -60,6 +64,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index e812f71..a04a20d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -28,6 +28,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -53,6 +56,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -60,6 +64,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +72,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 8d2b62c..a8cc408 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -28,6 +28,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -53,6 +56,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -60,6 +64,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +72,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -74,6 +80,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +88,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +96,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +104,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -102,6 +112,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +120,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -116,6 +128,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -123,6 +136,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -130,6 +144,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -137,6 +152,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -144,6 +160,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index cb50d86..eb5dfba 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -28,6 +28,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -53,6 +56,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -60,6 +64,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +72,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -74,6 +80,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +88,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +96,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +104,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -102,6 +112,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +120,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -116,6 +128,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -123,6 +136,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -130,6 +144,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 67c46fc..5efb4aa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -28,6 +28,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -53,6 +56,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -60,6 +64,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +72,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -74,6 +80,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +88,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +96,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index a1e87df..eb6ccba 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -28,6 +28,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c new file mode 100644 index 0000000..de5721c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c @@ -0,0 +1,49 @@ +/* + * 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: + * + * 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 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 + +void +nouveau_mc_intr(struct nouveau_subdev *subdev) +{ + struct nouveau_mc *pmc = nouveau_mc(subdev); + const struct nouveau_mc_intr *map = pmc->intr_map; + struct nouveau_subdev *unit; + u32 stat; + + stat = nv_rd32(pmc, 0x000100); + while (stat && map->stat) { + if (stat & map->stat) { + unit = nouveau_subdev(subdev, map->unit); + if (unit && unit->intr) + unit->intr(unit); + stat &= ~map->stat; + } + map++; + } + + if (stat) { + nv_error(pmc, "unknown intr 0x%08x\n", stat); + } +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c index 60b146e..23ebe47 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c @@ -1,24 +1,83 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +/* + * 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: + * + * 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 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 + */ -int -nv04_mc_init(struct drm_device *dev) -{ - /* Power up everything, resetting each individual unit will - * be done later if needed. - */ +#include + +struct nv04_mc_priv { + struct nouveau_mc base; +}; - nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); +const struct nouveau_mc_intr +nv04_mc_intr[] = { + { 0x00000001, NVDEV_ENGINE_MPEG }, /* NV17- MPEG/ME */ + { 0x00000100, NVDEV_ENGINE_FIFO }, + { 0x00001000, NVDEV_ENGINE_GR }, + { 0x00020000, NVDEV_ENGINE_VP }, /* NV40- */ + { 0x00100000, NVDEV_SUBDEV_TIMER }, + { 0x01000000, NVDEV_ENGINE_DISP }, /* NV04- PCRTC0 */ + { 0x02000000, NVDEV_ENGINE_DISP }, /* NV11- PCRTC1 */ + { 0x10000000, NVDEV_SUBDEV_GPIO }, /* PBUS */ + { 0x80000000, NVDEV_ENGINE_SW }, + {} +}; + +static int +nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_mc_priv *priv; + int ret; - /* Disable PROM access. */ - nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); + ret = nouveau_mc_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + nv_subdev(priv)->intr = nouveau_mc_intr; + priv->base.intr_map = nv04_mc_intr; return 0; } -void -nv04_mc_takedown(struct drm_device *dev) +int +nv04_mc_init(struct nouveau_object *object) { + struct nv04_mc_priv *priv = (void *)object; + + nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ + nv_wr32(priv, 0x001850, 0x00000001); /* disable rom access */ + + return nouveau_mc_init(&priv->base); } + +struct nouveau_oclass +nv04_mc_oclass = { + .handle = NV_SUBDEV(MC, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv04_mc_init, + .fini = _nouveau_mc_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c deleted file mode 100644 index 74cfa03..0000000 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -int -nv40_mc_init(struct drm_device *dev) -{ - /* Power up everything, resetting each individual unit will - * be done later if needed. - */ - nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); - - if (nv44_graph_class(dev)) { - u32 tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA); - nv_wr32(dev, NV40_PMC_1700, tmp); - nv_wr32(dev, NV40_PMC_1704, 0); - nv_wr32(dev, NV40_PMC_1708, 0); - nv_wr32(dev, NV40_PMC_170C, tmp); - } - - return 0; -} - -void -nv40_mc_takedown(struct drm_device *dev) -{ -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c new file mode 100644 index 0000000..397d868 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c @@ -0,0 +1,74 @@ +/* + * 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: + * + * 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 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 + +struct nv44_mc_priv { + struct nouveau_mc base; +}; + +static int +nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv44_mc_priv *priv; + int ret; + + ret = nouveau_mc_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nouveau_mc_intr; + priv->base.intr_map = nv04_mc_intr; + return 0; +} + +static int +nv44_mc_init(struct nouveau_object *object) +{ + struct nv44_mc_priv *priv = (void *)object; + u32 tmp = nv_rd32(priv, 0x10020c); + + nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ + + nv_wr32(priv, 0x001700, tmp); + nv_wr32(priv, 0x001704, 0); + nv_wr32(priv, 0x001708, 0); + nv_wr32(priv, 0x00170c, tmp); + + return nouveau_mc_init(&priv->base); +} + +struct nouveau_oclass +nv44_mc_oclass = { + .handle = NV_SUBDEV(MC, 0x44), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv44_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv44_mc_init, + .fini = _nouveau_mc_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index e0a9c3f..cedf33b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c @@ -1,40 +1,80 @@ /* - * 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 -int -nv50_mc_init(struct drm_device *dev) +struct nv50_mc_priv { + struct nouveau_mc base; +}; + +static const struct nouveau_mc_intr +nv50_mc_intr[] = { + { 0x00000001, NVDEV_ENGINE_MPEG }, + { 0x00000100, NVDEV_ENGINE_FIFO }, + { 0x00001000, NVDEV_ENGINE_GR }, + { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84- */ + { 0x00008000, NVDEV_ENGINE_BSP }, /* NV84- */ + { 0x00100000, NVDEV_SUBDEV_TIMER }, + { 0x00200000, NVDEV_SUBDEV_GPIO }, + { 0x04000000, NVDEV_ENGINE_DISP }, + { 0x80000000, NVDEV_ENGINE_SW }, + {}, +}; + +static int +nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); + struct nv50_mc_priv *priv; + int ret; + + ret = nouveau_mc_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nouveau_mc_intr; + priv->base.intr_map = nv50_mc_intr; return 0; } -void nv50_mc_takedown(struct drm_device *dev) +int +nv50_mc_init(struct nouveau_object *object) { + struct nv50_mc_priv *priv = (void *)object; + nv_wr32(priv, 0x000200, 0xffffffff); /* everything on */ + return nouveau_mc_init(&priv->base); } + +struct nouveau_oclass +nv50_mc_oclass = { + .handle = NV_SUBDEV(MC, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv50_mc_init, + .fini = _nouveau_mc_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c new file mode 100644 index 0000000..a001e4c4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c @@ -0,0 +1,73 @@ +/* + * 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: + * + * 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 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 + +struct nv98_mc_priv { + struct nouveau_mc base; +}; + +static const struct nouveau_mc_intr +nv98_mc_intr[] = { + { 0x00000001, NVDEV_ENGINE_PPP }, + { 0x00000100, NVDEV_ENGINE_FIFO }, + { 0x00001000, NVDEV_ENGINE_GR }, + { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ + { 0x00008000, NVDEV_ENGINE_BSP }, + { 0x00100000, NVDEV_SUBDEV_TIMER }, + { 0x00200000, NVDEV_SUBDEV_GPIO }, + { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */ + { 0x04000000, NVDEV_ENGINE_DISP }, + { 0x80000000, NVDEV_ENGINE_SW }, + {}, +}; + +static int +nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv98_mc_priv *priv; + int ret; + + ret = nouveau_mc_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nouveau_mc_intr; + priv->base.intr_map = nv98_mc_intr; + return 0; +} + +struct nouveau_oclass +nv98_mc_oclass = { + .handle = NV_SUBDEV(MC, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv50_mc_init, + .fini = _nouveau_mc_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c new file mode 100644 index 0000000..3fa39bb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -0,0 +1,73 @@ +/* + * 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: + * + * 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 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 + +struct nvc0_mc_priv { + struct nouveau_mc base; +}; + +static const struct nouveau_mc_intr +nvc0_mc_intr[] = { + { 0x00000001, NVDEV_ENGINE_PPP }, + { 0x00000020, NVDEV_ENGINE_COPY0 }, + { 0x00000040, NVDEV_ENGINE_COPY1 }, + { 0x00000100, NVDEV_ENGINE_FIFO }, + { 0x00001000, NVDEV_ENGINE_GR }, + { 0x00008000, NVDEV_ENGINE_BSP }, + { 0x00100000, NVDEV_SUBDEV_TIMER }, + { 0x00200000, NVDEV_SUBDEV_GPIO }, + { 0x04000000, NVDEV_ENGINE_DISP }, + { 0x80000000, NVDEV_ENGINE_SW }, + {}, +}; + +static int +nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_mc_priv *priv; + int ret; + + ret = nouveau_mc_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nouveau_mc_intr; + priv->base.intr_map = nvc0_mc_intr; + return 0; +} + +struct nouveau_oclass +nvc0_mc_oclass = { + .handle = NV_SUBDEV(MC, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv50_mc_init, + .fini = _nouveau_mc_fini, + }, +}; -- cgit v1.1 From 5a5c7432bbbd2e318dff107b4ff960ab543a7cef Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 16:08:25 +1000 Subject: drm/nouveau/timer: port to subdev interfaces Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 5 +- .../gpu/drm/nouveau/core/include/subdev/timer.h | 53 +++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/timer/base.c | 87 ++++++++ drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 243 +++++++++++++++++---- 12 files changed, 413 insertions(+), 42 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/timer.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/timer/base.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index c22e3a0..b2e9ad4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -224,7 +224,6 @@ static void nv84_graph_tlb_flush(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; bool idle, timeout = false; unsigned long flags; u64 start; @@ -233,7 +232,7 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine) spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x400500, 0x00000001, 0x00000000); - start = ptimer->read(dev); + start = nv_timer_read(dev); do { idle = true; @@ -251,7 +250,7 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine) if ((tmp & 7) == 1) idle = false; } - } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000)); + } while (!idle && !(timeout = nv_timer_read(dev) - start > 2000000000)); if (timeout) { NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: " diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h new file mode 100644 index 0000000..d971b83 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h @@ -0,0 +1,53 @@ +#ifndef __NOUVEAU_TIMER_H__ +#define __NOUVEAU_TIMER_H__ + +#include +#include + +struct nouveau_alarm { + struct list_head head; + u64 timestamp; + void (*func)(struct nouveau_alarm *); +}; + +bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); +bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); +bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); +void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); + +#define NV_WAIT_DEFAULT 2000000000ULL +#define nv_wait(o,a,m,v) \ + nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) +#define nv_wait_ne(o,a,m,v) \ + nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v)) +#define nv_wait_cb(o,a,m,v) \ + nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (a), (m), (v)) + +struct nouveau_timer { + struct nouveau_subdev base; + u64 (*read)(struct nouveau_timer *); + void (*alarm)(struct nouveau_timer *, u32 time, struct nouveau_alarm *); +}; + +static inline struct nouveau_timer * +nouveau_timer(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_TIMER]; +} + +#define nouveau_timer_create(p,e,o,d) \ + nouveau_subdev_create_((p), (e), (o), 0, "PTIMER", "timer", \ + sizeof(**d), (void **)d) +#define nouveau_timer_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_timer_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_timer_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_timer_create_(struct nouveau_object *, struct nouveau_engine *, + struct nouveau_oclass *, int size, void **); + +extern struct nouveau_oclass nv04_timer_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index c3820a8..aa43bd5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -28,6 +28,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -39,6 +40,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -46,6 +48,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 94686f4..1926c33 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -57,6 +60,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +69,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +78,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +87,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -89,6 +96,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +105,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index d14041e..88729c3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -57,6 +60,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +69,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index a04a20d..4feea88 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -57,6 +60,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +69,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +78,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index a8cc408..8f68361 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -57,6 +60,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +69,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +78,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +87,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -89,6 +96,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +105,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +114,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -113,6 +123,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -121,6 +132,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -129,6 +141,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -137,6 +150,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +159,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -153,6 +168,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -161,6 +177,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index eb5dfba..e844525 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -57,6 +60,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +69,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +78,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +87,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -89,6 +96,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +105,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +114,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -113,6 +123,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -121,6 +132,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -129,6 +141,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -137,6 +150,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +159,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 5efb4aa..56d1950 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -29,6 +29,7 @@ #include #include #include +#include int nvc0_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -57,6 +60,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +69,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +78,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +87,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -89,6 +96,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +105,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index eb6ccba..ab5e052 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -29,6 +29,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c new file mode 100644 index 0000000..5d417cc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c @@ -0,0 +1,87 @@ +/* + * 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: + * + * 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 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 "subdev/timer.h" + +bool +nouveau_timer_wait_eq(void *obj, u64 nsec, u32 addr, u32 mask, u32 data) +{ + struct nouveau_timer *ptimer = nouveau_timer(obj); + u64 time0; + + time0 = ptimer->read(ptimer); + do { + if (nv_iclass(obj, NV_SUBDEV_CLASS)) { + if ((nv_rd32(obj, addr) & mask) == data) + return true; + } else { + if ((nv_ro32(obj, addr) & mask) == data) + return true; + } + } while (ptimer->read(ptimer) - time0 < nsec); + + return false; +} + +bool +nouveau_timer_wait_ne(void *obj, u64 nsec, u32 addr, u32 mask, u32 data) +{ + struct nouveau_timer *ptimer = nouveau_timer(obj); + u64 time0; + + time0 = ptimer->read(ptimer); + do { + if (nv_iclass(obj, NV_SUBDEV_CLASS)) { + if ((nv_rd32(obj, addr) & mask) != data) + return true; + } else { + if ((nv_ro32(obj, addr) & mask) != data) + return true; + } + } while (ptimer->read(ptimer) - time0 < nsec); + + return false; +} + +bool +nouveau_timer_wait_cb(void *obj, u64 nsec, bool (*func)(void *), void *data) +{ + struct nouveau_timer *ptimer = nouveau_timer(obj); + u64 time0; + + time0 = ptimer->read(ptimer); + do { + if (func(data) == true) + return true; + } while (ptimer->read(ptimer) - time0 < nsec); + + return false; +} + +void +nouveau_timer_alarm(void *obj, u32 nsec, struct nouveau_alarm *alarm) +{ + struct nouveau_timer *ptimer = nouveau_timer(obj); + ptimer->alarm(ptimer, nsec, alarm); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 63333dc..49976be 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -1,45 +1,201 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include "nouveau_hw.h" - -int -nv04_timer_init(struct drm_device *dev) +/* + * 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: + * + * 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 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 + +#define NV04_PTIMER_INTR_0 0x009100 +#define NV04_PTIMER_INTR_EN_0 0x009140 +#define NV04_PTIMER_NUMERATOR 0x009200 +#define NV04_PTIMER_DENOMINATOR 0x009210 +#define NV04_PTIMER_TIME_0 0x009400 +#define NV04_PTIMER_TIME_1 0x009410 +#define NV04_PTIMER_ALARM_0 0x009420 + +struct nv04_timer_priv { + struct nouveau_timer base; + struct list_head alarms; + spinlock_t lock; +}; + +static u64 +nv04_timer_read(struct nouveau_timer *ptimer) +{ + struct nv04_timer_priv *priv = (void *)ptimer; + u32 hi, lo; + + do { + hi = nv_rd32(priv, NV04_PTIMER_TIME_1); + lo = nv_rd32(priv, NV04_PTIMER_TIME_0); + } while (hi != nv_rd32(priv, NV04_PTIMER_TIME_1)); + + return ((u64)hi << 32 | lo); +} + +static void +nv04_timer_alarm_trigger(struct nouveau_timer *ptimer) +{ + struct nv04_timer_priv *priv = (void *)ptimer; + struct nouveau_alarm *alarm, *atemp; + unsigned long flags; + LIST_HEAD(exec); + + /* move any due alarms off the pending list */ + spin_lock_irqsave(&priv->lock, flags); + list_for_each_entry_safe(alarm, atemp, &priv->alarms, head) { + if (alarm->timestamp <= ptimer->read(ptimer)) + list_move_tail(&alarm->head, &exec); + } + + /* reschedule interrupt for next alarm time */ + if (!list_empty(&priv->alarms)) { + alarm = list_first_entry(&priv->alarms, typeof(*alarm), head); + nv_wr32(priv, NV04_PTIMER_ALARM_0, alarm->timestamp); + nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000001); + } else { + nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); + } + spin_unlock_irqrestore(&priv->lock, flags); + + /* execute any pending alarm handlers */ + list_for_each_entry_safe(alarm, atemp, &exec, head) { + list_del(&alarm->head); + alarm->func(alarm); + } +} + +static void +nv04_timer_alarm(struct nouveau_timer *ptimer, u32 time, + struct nouveau_alarm *alarm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 m, n, d; + struct nv04_timer_priv *priv = (void *)ptimer; + struct nouveau_alarm *list; + unsigned long flags; + + alarm->timestamp = ptimer->read(ptimer) + time; + + /* append new alarm to list, in soonest-alarm-first order */ + spin_lock_irqsave(&priv->lock, flags); + list_for_each_entry(list, &priv->alarms, head) { + if (list->timestamp > alarm->timestamp) + break; + } + list_add_tail(&alarm->head, &list->head); + spin_unlock_irqrestore(&priv->lock, flags); - nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); - nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); + /* process pending alarms */ + nv04_timer_alarm_trigger(ptimer); +} + +static void +nv04_timer_intr(struct nouveau_subdev *subdev) +{ + struct nv04_timer_priv *priv = (void *)subdev; + u32 stat = nv_rd32(priv, NV04_PTIMER_INTR_0); + + if (stat & 0x00000001) { + nv04_timer_alarm_trigger(&priv->base); + nv_wr32(priv, NV04_PTIMER_INTR_0, 0x00000001); + stat &= ~0x00000001; + } + + if (stat) { + nv_error(priv, "unknown stat 0x%08x\n", stat); + nv_wr32(priv, NV04_PTIMER_INTR_0, stat); + } +} + +static int +nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_timer_priv *priv; + int ret; + + ret = nouveau_timer_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.intr = nv04_timer_intr; + priv->base.read = nv04_timer_read; + priv->base.alarm = nv04_timer_alarm; + + INIT_LIST_HEAD(&priv->alarms); + spin_lock_init(&priv->lock); + return 0; +} + +static void +nv04_timer_dtor(struct nouveau_object *object) +{ + struct nv04_timer_priv *priv = (void *)object; + return nouveau_timer_destroy(&priv->base); +} + +static int +nv04_timer_init(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv04_timer_priv *priv = (void *)object; + u32 m = 1, f, n, d; + int ret; + + ret = nouveau_timer_init(&priv->base); + if (ret) + return ret; /* aim for 31.25MHz, which gives us nanosecond timestamps */ d = 1000000 / 32; /* determine base clock for timer source */ - if (dev_priv->chipset < 0x40) { - n = nouveau_hw_get_clock(dev, PLL_CORE); +#if 0 /*XXX*/ + if (device->chipset < 0x40) { + n = nouveau_hw_get_clock(device, PLL_CORE); } else - if (dev_priv->chipset == 0x40) { +#endif + if (device->chipset <= 0x40) { /*XXX: figure this out */ + f = -1; n = 0; } else { - n = dev_priv->crystal; - m = 1; + f = device->crystal; + n = f; while (n < (d * 2)) { n += (n / m); m++; } - nv_wr32(dev, 0x009220, m - 1); + nv_wr32(priv, 0x009220, m - 1); } if (!n) { - NV_WARN(dev, "PTIMER: unknown input clock freq\n"); - if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || - !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { - nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1); - nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1); + nv_warn(priv, "unknown input clock freq\n"); + if (!nv_rd32(priv, NV04_PTIMER_NUMERATOR) || + !nv_rd32(priv, NV04_PTIMER_DENOMINATOR)) { + nv_wr32(priv, NV04_PTIMER_NUMERATOR, 1); + nv_wr32(priv, NV04_PTIMER_DENOMINATOR, 1); } return 0; } @@ -60,25 +216,34 @@ nv04_timer_init(struct drm_device *dev) d >>= 1; } - nv_wr32(dev, NV04_PTIMER_NUMERATOR, n); - nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d); + nv_debug(priv, "input frequency : %dHz\n", f); + nv_debug(priv, "input multiplier: %d\n", m); + nv_debug(priv, "numerator : 0x%08x\n", n); + nv_debug(priv, "denominator : 0x%08x\n", d); + nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); + + nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); + nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); + nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); + nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); return 0; } -u64 -nv04_timer_read(struct drm_device *dev) +static int +nv04_timer_fini(struct nouveau_object *object, bool suspend) { - u32 hi, lo; - - do { - hi = nv_rd32(dev, NV04_PTIMER_TIME_1); - lo = nv_rd32(dev, NV04_PTIMER_TIME_0); - } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1)); - - return ((u64)hi << 32 | lo); + struct nv04_timer_priv *priv = (void *)object; + nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); + return nouveau_timer_fini(&priv->base, suspend); } -void -nv04_timer_takedown(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv04_timer_oclass = { + .handle = NV_SUBDEV(TIMER, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_timer_ctor, + .dtor = nv04_timer_dtor, + .init = nv04_timer_init, + .fini = nv04_timer_fini, + } +}; -- cgit v1.1 From 496734bf0391f38c196e16dbbfaaeda8e6ec5845 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 16:28:19 +1000 Subject: drm/nouveau/core: add support for reverse mm allocations Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/mm.c | 173 +++++++++++++++------ drivers/gpu/drm/nouveau/core/include/core/mm.h | 34 +--- drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c | 18 ++- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c | 13 +- drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 9 +- 5 files changed, 154 insertions(+), 93 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index bf8d4a5..bfddf87 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.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,19 +22,52 @@ * Authors: Ben Skeggs */ -#include -#include +#include "core/os.h" +#include "core/mm.h" -static inline void -region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a) +#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ + list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) + +void +nouveau_mm_free(struct nouveau_mm *mm, struct nouveau_mm_node **pthis) { - list_del(&a->nl_entry); - list_del(&a->fl_entry); - kfree(a); + struct nouveau_mm_node *this = *pthis; + + if (this) { + struct nouveau_mm_node *prev = node(this, prev); + struct nouveau_mm_node *next = node(this, next); + + if (prev && prev->type == 0) { + prev->length += this->length; + list_del(&this->nl_entry); + kfree(this); this = prev; + } + + if (next && next->type == 0) { + next->offset = this->offset; + next->length += this->length; + if (this->type == 0) + list_del(&this->fl_entry); + list_del(&this->nl_entry); + kfree(this); this = NULL; + } + + if (this && this->type != 0) { + list_for_each_entry(prev, &mm->free, fl_entry) { + if (this->offset < prev->offset) + break; + } + + list_add_tail(&this->fl_entry, &prev->fl_entry); + this->type = 0; + } + } + + *pthis = NULL; } static struct nouveau_mm_node * -region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) +region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) { struct nouveau_mm_node *b; @@ -56,38 +89,12 @@ region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) return b; } -#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ - list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) - -void -nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this) -{ - struct nouveau_mm_node *prev = node(this, prev); - struct nouveau_mm_node *next = node(this, next); - - list_add(&this->fl_entry, &mm->free); - this->type = 0; - - if (prev && prev->type == 0) { - prev->length += this->length; - region_put(mm, this); - this = prev; - } - - if (next && next->type == 0) { - next->offset = this->offset; - next->length += this->length; - region_put(mm, this); - } -} - int -nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, - u32 align, struct nouveau_mm_node **pnode) +nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, + u32 align, struct nouveau_mm_node **pnode) { struct nouveau_mm_node *prev, *this, *next; - u32 min = size_nc ? size_nc : size; - u32 align_mask = align - 1; + u32 mask = align - 1; u32 splitoff; u32 s, e; @@ -103,16 +110,86 @@ nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, if (next && next->type != type) e = rounddown(e, mm->block_size); - s = (s + align_mask) & ~align_mask; - e &= ~align_mask; - if (s > e || e - s < min) + s = (s + mask) & ~mask; + e &= ~mask; + if (s > e || e - s < size_min) continue; splitoff = s - this->offset; - if (splitoff && !region_split(mm, this, splitoff)) + if (splitoff && !region_head(mm, this, splitoff)) + return -ENOMEM; + + this = region_head(mm, this, min(size_max, e - s)); + if (!this) + return -ENOMEM; + + this->type = type; + list_del(&this->fl_entry); + *pnode = this; + return 0; + } + + return -ENOSPC; +} + +static struct nouveau_mm_node * +region_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) +{ + struct nouveau_mm_node *b; + + if (a->length == size) + return a; + + b = kmalloc(sizeof(*b), GFP_KERNEL); + if (unlikely(b == NULL)) + return NULL; + + a->length -= size; + b->offset = a->offset + a->length; + b->length = size; + b->type = a->type; + + list_add(&b->nl_entry, &a->nl_entry); + if (b->type == 0) + list_add(&b->fl_entry, &a->fl_entry); + return b; +} + +int +nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, + u32 align, struct nouveau_mm_node **pnode) +{ + struct nouveau_mm_node *prev, *this, *next; + u32 mask = align - 1; + + list_for_each_entry_reverse(this, &mm->free, fl_entry) { + u32 e = this->offset + this->length; + u32 s = this->offset; + u32 c = 0, a; + + prev = node(this, prev); + if (prev && prev->type != type) + s = roundup(s, mm->block_size); + + next = node(this, next); + if (next && next->type != type) { + e = rounddown(e, mm->block_size); + c = next->offset - e; + } + + s = (s + mask) & ~mask; + a = e - s; + if (s > e || a < size_min) + continue; + + a = min(a, size_max); + s = (e - a) & ~mask; + c += (e - s) - a; + + if (c && !region_tail(mm, this, c)) return -ENOMEM; - this = region_split(mm, this, min(size, e - s)); + this = region_tail(mm, this, a); if (!this) return -ENOMEM; @@ -147,6 +224,7 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->fl_entry, &mm->free); mm->heap_nodes++; + mm->heap_size += length; return 0; } @@ -158,15 +236,8 @@ nouveau_mm_fini(struct nouveau_mm *mm) int nodes = 0; list_for_each_entry(node, &mm->nodes, nl_entry) { - if (nodes++ == mm->heap_nodes) { - printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); - list_for_each_entry(node, &mm->nodes, nl_entry) { - printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", - node->type, node->offset, node->length); - } - WARN_ON(1); + if (nodes++ == mm->heap_nodes) return -EBUSY; - } } kfree(heap); diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index b4fd73b..9ee9bf4 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -1,27 +1,3 @@ -/* - * Copyright 2010 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: - * - * 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 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 - */ - #ifndef __NOUVEAU_MM_H__ #define __NOUVEAU_MM_H__ @@ -43,13 +19,15 @@ struct nouveau_mm { u32 block_size; int heap_nodes; + u32 heap_size; }; int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); int nouveau_mm_fini(struct nouveau_mm *); -int nouveau_mm_pre(struct nouveau_mm *); -int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, - u32 align, struct nouveau_mm_node **); -void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); +int nouveau_mm_head(struct nouveau_mm *, u8 type, u32 size_max, u32 size_min, + u32 align, struct nouveau_mm_node **); +int nouveau_mm_tail(struct nouveau_mm *, u8 type, u32 size_max, u32 size_min, + u32 align, struct nouveau_mm_node **); +void nouveau_mm_free(struct nouveau_mm *, struct nouveau_mm_node **); #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c index 029274b..84b99b6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c @@ -65,7 +65,7 @@ nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); list_del(&this->rl_entry); - nouveau_mm_put(mm, this); + nouveau_mm_free(mm, &this); } if (mem->tag) { @@ -78,7 +78,7 @@ nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) } int -nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, +nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, u32 memtype, struct nouveau_mem **pmem) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -87,13 +87,14 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, struct nouveau_mem *mem; int comp = (memtype & 0x300) >> 8; int type = (memtype & 0x07f); + int back = (memtype & 0x800); int ret; - if (!types[type]) - return -EINVAL; size >>= 12; align >>= 12; - size_nc >>= 12; + ncmin >>= 12; + if (!ncmin) + ncmin = size; mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) @@ -119,8 +120,13 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, mem->memtype = (comp << 7) | type; mem->size = size; + type = types[type]; do { - ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); + if (back) + ret = nouveau_mm_tail(mm, type, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, type, size, ncmin, align, &r); + if (ret) { mutex_unlock(&mm->mutex); nv50_vram_del(dev, &mem); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c index 8bb86e5..f363234 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c @@ -58,17 +58,21 @@ nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) int nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 type, struct nouveau_mem **pmem) + u32 memtype, struct nouveau_mem **pmem) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_mm *mm = &dev_priv->engine.vram.mm; struct nouveau_mm_node *r; struct nouveau_mem *mem; + int type = (memtype & 0x0ff); + int back = (memtype & 0x800); int ret; size >>= 12; align >>= 12; ncmin >>= 12; + if (!ncmin) + ncmin = size; mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) @@ -76,12 +80,15 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, INIT_LIST_HEAD(&mem->regions); mem->dev = dev_priv->dev; - mem->memtype = (type & 0xff); + mem->memtype = type; mem->size = size; mutex_lock(&mm->mutex); do { - ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); + if (back) + ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); if (ret) { mutex_unlock(&mm->mutex); nv50_vram_del(dev, &mem); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 3d11a4a..9fb858a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -282,7 +282,8 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, int ret; mutex_lock(&vm->mm.mutex); - ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node); + ret = nouveau_mm_head(&vm->mm, page_shift, msize, msize, align, + &vma->node); if (unlikely(ret != 0)) { mutex_unlock(&vm->mm.mutex); return ret; @@ -303,9 +304,8 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, if (ret) { if (pde != fpde) nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); - nouveau_mm_put(&vm->mm, vma->node); + nouveau_mm_free(&vm->mm, &vma->node); mutex_unlock(&vm->mm.mutex); - vma->node = NULL; return ret; } } @@ -330,8 +330,7 @@ nouveau_vm_put(struct nouveau_vma *vma) mutex_lock(&vm->mm.mutex); nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); - nouveau_mm_put(&vm->mm, vma->node); - vma->node = NULL; + nouveau_mm_free(&vm->mm, &vma->node); mutex_unlock(&vm->mm.mutex); } -- cgit v1.1 From 0134a97979a0abc1c756b0fe491e074693c2bdf5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 18:10:11 +1000 Subject: drm/nv50-/instmem: allocate vram for kernel objects from end of vram Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index d9b3463..5965eb7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -323,7 +323,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, size = (size + 4095) & ~4095; align = max(align, (u32)4096); - ret = vram->get(dev, size, align, 0, 0, &node->vram); + ret = vram->get(dev, size, align, 0, 0x800, &node->vram); if (ret) { kfree(node); return ret; -- cgit v1.1 From 861d21074bbb141b0cc165a61c11f571571cda12 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 11 Jul 2012 19:05:01 +1000 Subject: drm/nouveau/fb: merge fb/vram and port to subdev interfaces Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 4 +- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 5 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 7 +- drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 137 ++++++++ drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h | 33 ++ drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 5 +- drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 3 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 5 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 + drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 18 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 6 + drivers/gpu/drm/nouveau/core/subdev/fb/base.c | 130 +++++++ drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c | 139 ++++++-- drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c | 186 +++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c | 208 ++++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c | 114 +++--- drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 261 ++++++++------ drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 384 ++++++++++++++++----- drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c | 243 ------------- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 252 ++++++++++---- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c | 167 --------- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 10 +- drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | 91 +++++ drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 6 +- 30 files changed, 1497 insertions(+), 969 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/fb.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/base.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 3079f08..23ae459 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -163,7 +163,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) break; default: nv_wr32(dev, 0x002230, 0x00000000); - nv_wr32(dev, 0x002220, ((dev_priv->vram_size - 512 * 1024 + + nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + dev_priv->ramfc->pinst) >> 16) | 0x00030000); break; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index 19e303b..d006658 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -895,9 +895,7 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) static void nv10_graph_set_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[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); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 718ecf7..dd31156 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -472,7 +472,7 @@ static void nv20_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + 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); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 4ad9759..ab3af6d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -125,7 +125,7 @@ static void nv40_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); switch (dev_priv->chipset) { case 0x40: @@ -178,7 +178,6 @@ nv40_graph_init(struct drm_device *dev, int engine) { struct nv40_graph_engine *pgraph = nv_engine(dev, engine); struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; uint32_t vramsz; int i, j; @@ -280,7 +279,7 @@ nv40_graph_init(struct drm_device *dev, int engine) } /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) + for (i = 0; i < nvfb_tile_nr(dev); i++) nv40_graph_set_tile_region(dev, i); /* begin RAM config */ diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 4a14a67..eb5455f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -128,7 +128,6 @@ nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, static int nv31_mpeg_init(struct drm_device *dev, int engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); int i; @@ -138,7 +137,7 @@ nv31_mpeg_init(struct drm_device *dev, int engine) nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) + for (i = 0; i < nvfb_tile_nr(dev); i++) pmpeg->base.set_tile_region(dev, i); /* PMPEG init */ @@ -235,9 +234,7 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) static void nv31_vpe_set_tile_region(struct drm_device *dev, int i) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - + struct nouveau_fb_tile *tile = nvfb_tile(dev, i); nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h new file mode 100644 index 0000000..91dbdc1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -0,0 +1,137 @@ +#ifndef __NOUVEAU_FB_H__ +#define __NOUVEAU_FB_H__ + +#ifndef XXX_THIS_IS_A_HACK +#include +#include +#endif +#include +#include + +/* memory type/access flags, do not match hardware values */ +#define NV_MEM_ACCESS_RO 1 +#define NV_MEM_ACCESS_WO 2 +#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) +#define NV_MEM_ACCESS_SYS 4 +#define NV_MEM_ACCESS_VM 8 +#define NV_MEM_ACCESS_NOSNOOP 16 + +#define NV_MEM_TARGET_VRAM 0 +#define NV_MEM_TARGET_PCI 1 +#define NV_MEM_TARGET_PCI_NOSNOOP 2 +#define NV_MEM_TARGET_VM 3 +#define NV_MEM_TARGET_GART 4 + +#define NV_MEM_TYPE_VM 0x7f +#define NV_MEM_COMP_VM 0x03 + +struct nouveau_mem { + struct drm_device *dev; + + struct nouveau_vma bar_vma; + struct nouveau_vma vma[2]; + u8 page_shift; + + struct nouveau_mm_node *tag; + struct list_head regions; + dma_addr_t *pages; + u32 memtype; + u64 offset; + u64 size; + struct sg_table *sg; +}; + +struct nouveau_fb_tile { + struct nouveau_mm_node *tag; + u32 addr; + u32 limit; + u32 pitch; + u32 zcomp; +}; + +#ifndef XXX_THIS_IS_A_HACK +struct nouveau_fb { + struct nouveau_subdev base; + + bool (*memtype_valid)(struct nouveau_fb *, u32 memtype); + + struct { + enum { + NV_MEM_TYPE_UNKNOWN = 0, + NV_MEM_TYPE_STOLEN, + NV_MEM_TYPE_SGRAM, + NV_MEM_TYPE_SDRAM, + NV_MEM_TYPE_DDR1, + NV_MEM_TYPE_DDR2, + NV_MEM_TYPE_DDR3, + NV_MEM_TYPE_GDDR2, + NV_MEM_TYPE_GDDR3, + NV_MEM_TYPE_GDDR4, + NV_MEM_TYPE_GDDR5 + } type; + u64 stolen; + u64 size; + int ranks; + + int (*get)(struct nouveau_fb *, u64 size, u32 align, + u32 size_nc, u32 type, struct nouveau_mem **); + void (*put)(struct nouveau_fb *, struct nouveau_mem **); + } ram; + + struct nouveau_mm vram; + struct nouveau_mm tags; + + struct { + struct nouveau_fb_tile region[16]; + int regions; + void (*init)(struct nouveau_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nouveau_fb_tile *); + void (*fini)(struct nouveau_fb *, int i, + struct nouveau_fb_tile *); + void (*prog)(struct nouveau_fb *, int i, + struct nouveau_fb_tile *); + } tile; +}; + +static inline struct nouveau_fb * +nouveau_fb(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB]; +} + +#define nouveau_fb_create(p,e,c,d) \ + nouveau_subdev_create((p), (e), (c), 0, "PFB", "fb", (d)) +int nouveau_fb_created(struct nouveau_fb *); +void nouveau_fb_destroy(struct nouveau_fb *); +int nouveau_fb_init(struct nouveau_fb *); +#define nouveau_fb_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +void _nouveau_fb_dtor(struct nouveau_object *); +int _nouveau_fb_init(struct nouveau_object *); +#define _nouveau_fb_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_fb_oclass; +extern struct nouveau_oclass nv10_fb_oclass; +extern struct nouveau_oclass nv20_fb_oclass; +extern struct nouveau_oclass nv30_fb_oclass; +extern struct nouveau_oclass nv40_fb_oclass; +extern struct nouveau_oclass nv50_fb_oclass; +extern struct nouveau_oclass nvc0_fb_oclass; + +struct nouveau_bios; +int nouveau_fb_bios_memtype(struct nouveau_bios *); + +bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype); + +void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, + u32 pitch, u32 flags, struct nouveau_fb_tile *); +void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); + +void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **); +void nv50_fb_trap(struct nouveau_fb *, int display); +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h new file mode 100644 index 0000000..f351f63 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h @@ -0,0 +1,33 @@ +#ifndef __NOUVEAU_LTCG_H__ +#define __NOUVEAU_LTCG_H__ + +#include +#include + +struct nouveau_ltcg { + struct nouveau_subdev base; +}; + +static inline struct nouveau_ltcg * +nouveau_ltcg(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTCG]; +} + +#define nouveau_ltcg_create(p,e,o,d) \ + nouveau_subdev_create_((p), (e), (o), 0, "PLTCG", "level2", \ + sizeof(**d), (void **)d) +#define nouveau_ltcg_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_ltcg_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_ltcg_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_ltcg_dtor _nouveau_subdev_dtor +#define _nouveau_ltcg_init _nouveau_subdev_init +#define _nouveau_ltcg_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nvc0_ltcg_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 7c1fc21..6d3764b 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -25,11 +25,10 @@ #ifndef __NOUVEAU_VM_H__ #define __NOUVEAU_VM_H__ -#include "drmP.h" - -#include "nouveau_drv.h" #include +struct nouveau_mem; + struct nouveau_vm_pgt { struct nouveau_gpuobj *obj[2]; u32 refcount[2]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index aa43bd5..66b7156 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -29,6 +29,7 @@ #include #include #include +#include int nv04_identify(struct nouveau_device *device) @@ -41,6 +42,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -49,6 +51,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index 1926c33..cf81479 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv10_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 88729c3..e97280c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv20_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 4feea88..ddd3ab6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv30_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 8f68361..c7ea921 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv40_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +124,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +134,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +144,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +154,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +164,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -160,6 +174,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -169,6 +184,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -178,6 +194,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index e844525..e60cdf2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -30,6 +30,7 @@ #include #include #include +#include int nv50_identify(struct nouveau_device *device) @@ -43,6 +44,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +54,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +64,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +74,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +84,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +94,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +104,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +114,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +124,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +134,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +144,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +154,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +164,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -160,6 +174,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 56d1950..8de6730 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nvc0_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +67,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -70,6 +78,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -79,6 +89,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -88,6 +100,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +111,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -106,6 +122,8 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index ab5e052..919a102 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nve0_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; + device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c new file mode 100644 index 0000000..f0086de --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c @@ -0,0 +1,130 @@ +/* + * 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: + * + * 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 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 "subdev/fb.h" +#include "subdev/bios.h" +#include "subdev/bios/bit.h" + +int +nouveau_fb_bios_memtype(struct nouveau_bios *bios) +{ + struct bit_entry M; + u8 ramcfg; + + ramcfg = (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2; + if (!bit_entry(bios, 'M', &M) && M.version == 2 && M.length >= 5) { + u16 table = nv_ro16(bios, M.offset + 3); + u8 version = nv_ro08(bios, table + 0); + u8 header = nv_ro08(bios, table + 1); + u8 record = nv_ro08(bios, table + 2); + u8 entries = nv_ro08(bios, table + 3); + if (table && version == 0x10 && ramcfg < entries) { + u16 entry = table + header + (ramcfg * record); + switch (nv_ro08(bios, entry) & 0x0f) { + case 0: return NV_MEM_TYPE_DDR2; + case 1: return NV_MEM_TYPE_DDR3; + case 2: return NV_MEM_TYPE_GDDR3; + case 3: return NV_MEM_TYPE_GDDR5; + default: + break; + } + + } + } + + return NV_MEM_TYPE_UNKNOWN; +} + +int +nouveau_fb_init(struct nouveau_fb *pfb) +{ + int ret, i; + + ret = nouveau_subdev_init(&pfb->base); + if (ret) + return ret; + + for (i = 0; i < pfb->tile.regions; i++) + pfb->tile.prog(pfb, i, &pfb->tile.region[i]); + + return 0; +} + +int +_nouveau_fb_init(struct nouveau_object *object) +{ + struct nouveau_fb *pfb = (void *)object; + return nouveau_fb_init(pfb); +} + +void +nouveau_fb_destroy(struct nouveau_fb *pfb) +{ + int i; + + for (i = 0; i < pfb->tile.regions; i++) + pfb->tile.fini(pfb, i, &pfb->tile.region[i]); + + if (pfb->tags.block_size) + nouveau_mm_fini(&pfb->tags); + + if (pfb->vram.block_size) + nouveau_mm_fini(&pfb->vram); + + nouveau_subdev_destroy(&pfb->base); +} + +void +_nouveau_fb_dtor(struct nouveau_object *object) +{ + struct nouveau_fb *pfb = (void *)object; + nouveau_fb_destroy(pfb); +} + +int +nouveau_fb_created(struct nouveau_fb *pfb) +{ + static const char *name[] = { + [NV_MEM_TYPE_UNKNOWN] = "unknown", + [NV_MEM_TYPE_STOLEN ] = "stolen system memory", + [NV_MEM_TYPE_SGRAM ] = "SGRAM", + [NV_MEM_TYPE_SDRAM ] = "SDRAM", + [NV_MEM_TYPE_DDR1 ] = "DDR1", + [NV_MEM_TYPE_DDR2 ] = "DDR2", + [NV_MEM_TYPE_DDR3 ] = "DDR3", + [NV_MEM_TYPE_GDDR2 ] = "GDDR2", + [NV_MEM_TYPE_GDDR3 ] = "GDDR3", + [NV_MEM_TYPE_GDDR4 ] = "GDDR4", + [NV_MEM_TYPE_GDDR5 ] = "GDDR5", + }; + + if (pfb->ram.size == 0) { + nv_fatal(pfb, "no vram detected!!\n"); + return -ERANGE; + } + + nv_info(pfb, "RAM type: %s\n", name[pfb->ram.type]); + nv_info(pfb, "RAM size: %d MiB\n", (int)(pfb->ram.size >> 20)); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c index eef4844..eb06836 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -1,55 +1,130 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +/* + * 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: + * + * 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 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 + */ -int -nv04_fb_vram_init(struct drm_device *dev) +#include + +#define NV04_PFB_BOOT_0 0x00100000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 +# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 +# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 +# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 +# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 +# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 +# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 +#define NV04_PFB_CFG0 0x00100200 + +struct nv04_fb_priv { + struct nouveau_fb base; +}; + +bool +nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) +{ + if (!(tile_flags & 0xff00)) + return true; + + return false; +} + +static int +nv04_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); + struct nv04_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; + + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows + * nvidia reading PFB_CFG_0, then writing back its original value. + * (which was 0x701114 in this case) + */ + nv_wr32(priv, NV04_PFB_CFG0, 0x1114); + return 0; +} +static int +nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_fb_priv *priv; + u32 boot0; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + boot0 = nv_rd32(priv, NV04_PFB_BOOT_0); if (boot0 & 0x00000100) { - dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2; - dev_priv->vram_size *= 1024 * 1024; + priv->base.ram.size = ((boot0 >> 12) & 0xf) * 2 + 2; + priv->base.ram.size *= 1024 * 1024; } else { switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: - dev_priv->vram_size = 32 * 1024 * 1024; + priv->base.ram.size = 32 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: - dev_priv->vram_size = 16 * 1024 * 1024; + priv->base.ram.size = 16 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: - dev_priv->vram_size = 8 * 1024 * 1024; + priv->base.ram.size = 8 * 1024 * 1024; break; case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: - dev_priv->vram_size = 4 * 1024 * 1024; + priv->base.ram.size = 4 * 1024 * 1024; break; } } if ((boot0 & 0x00000038) <= 0x10) - dev_priv->vram_type = NV_MEM_TYPE_SGRAM; + priv->base.ram.type = NV_MEM_TYPE_SGRAM; else - dev_priv->vram_type = NV_MEM_TYPE_SDRAM; + priv->base.ram.type = NV_MEM_TYPE_SDRAM; - return 0; -} - -int -nv04_fb_init(struct drm_device *dev) -{ - /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows - * nvidia reading PFB_CFG_0, then writing back its original value. - * (which was 0x701114 in this case) - */ - nv_wr32(dev, NV04_PFB_CFG0, 0x1114); - return 0; + priv->base.memtype_valid = nv04_fb_memtype_valid; + return nouveau_fb_created(&priv->base); } -void -nv04_fb_takedown(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv04_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv04_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c index 09af63b..f037a42 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -1,104 +1,120 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -void -nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include + +struct nv10_fb_priv { + struct nouveau_fb base; +}; + +static void +nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - tile->addr = 0x80000000 | addr; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; } -void -nv10_fb_free_tile_region(struct drm_device *dev, int i) +static void +nv10_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; + tile->zcomp = 0; } void -nv10_fb_set_tile_region(struct drm_device *dev, int i) +nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); + nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); } -int -nv1a_fb_vram_init(struct drm_device *dev) +static int +nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pci_dev *bridge; - uint32_t mem, mib; - - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); - if (!bridge) { - NV_ERROR(dev, "no bridge device\n"); - return 0; - } - - if (dev_priv->chipset == 0x1a) { - pci_read_config_dword(bridge, 0x7c, &mem); - mib = ((mem >> 6) & 31) + 1; + struct nouveau_device *device = nv_device(parent); + struct nv10_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + if (device->chipset == 0x1a || device->chipset == 0x1f) { + struct pci_dev *bridge; + u32 mem, mib; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1)); + if (!bridge) { + nv_fatal(device, "no bridge device\n"); + return 0; + } + + if (device->chipset == 0x1a) { + pci_read_config_dword(bridge, 0x7c, &mem); + mib = ((mem >> 6) & 31) + 1; + } else { + pci_read_config_dword(bridge, 0x84, &mem); + mib = ((mem >> 4) & 127) + 1; + } + + priv->base.ram.type = NV_MEM_TYPE_STOLEN; + priv->base.ram.size = mib * 1024 * 1024; } else { - pci_read_config_dword(bridge, 0x84, &mem); - mib = ((mem >> 4) & 127) + 1; - } + u32 cfg0 = nv_rd32(priv, 0x100200); + if (cfg0 & 0x00000001) + priv->base.ram.type = NV_MEM_TYPE_DDR1; + else + priv->base.ram.type = NV_MEM_TYPE_SDRAM; - dev_priv->vram_size = mib * 1024 * 1024; - return 0; -} - -int -nv10_fb_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA); - u32 cfg0 = nv_rd32(dev, 0x100200); - - dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - - if (cfg0 & 0x00000001) - dev_priv->vram_type = NV_MEM_TYPE_DDR1; - else - dev_priv->vram_type = NV_MEM_TYPE_SDRAM; - - return 0; -} - -int -nv10_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - /* Turn all the tiling regions off. */ - pfb->num_tiles = NV10_PFB_TILE__SIZE; - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + } - return 0; + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv10_fb_tile_init; + priv->base.tile.fini = nv10_fb_tile_fini; + priv->base.tile.prog = nv10_fb_tile_prog; + return nouveau_fb_created(&priv->base); } -void -nv10_fb_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - for (i = 0; i < pfb->num_tiles; i++) - pfb->free_tile_region(dev, i); -} +struct nouveau_oclass +nv10_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = _nouveau_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c index a7f056c..4b3578f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -1,49 +1,41 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -static struct drm_mm_node * -nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct drm_mm_node *mem; - int ret; - - ret = drm_mm_pre_get(&pfb->tag_heap); - if (ret) - return NULL; - - spin_lock(&dev_priv->tile.lock); - mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); - if (mem) - mem = drm_mm_get_block_atomic(mem, size, 0); - spin_unlock(&dev_priv->tile.lock); - - return mem; -} +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include + +struct nv20_fb_priv { + struct nouveau_fb base; +}; static void -nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem) +nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_mm_node *mem = *pmem; - if (mem) { - spin_lock(&dev_priv->tile.lock); - drm_mm_put_block(mem); - spin_unlock(&dev_priv->tile.lock); - *pmem = NULL; - } -} - -void -nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); + struct nouveau_device *device = nv_device(pfb); + int bpp = (flags & 2) ? 32 : 16; tile->addr = 0x00000001 | addr; tile->limit = max(1u, addr + size) - 1; @@ -53,20 +45,20 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, * compression meta-data (most likely just a bitmap determining * if a given tile is compressed or not). */ - if (flags & NOUVEAU_GEM_TILE_ZETA) { - tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); - if (tile->tag_mem) { + size /= 256; + if (flags & 4) { + if (!nouveau_mm_head(&pfb->tags, 1, size, size, 1, &tile->tag)) { /* Enable Z compression */ - tile->zcomp = tile->tag_mem->start; - if (dev_priv->chipset >= 0x25) { + tile->zcomp = tile->tag->offset; + if (device->chipset >= 0x25) { if (bpp == 16) - tile->zcomp |= NV25_PFB_ZCOMP_MODE_16; + tile->zcomp |= 0x00100000; else - tile->zcomp |= NV25_PFB_ZCOMP_MODE_32; + tile->zcomp |= 0x00200000; } else { - tile->zcomp |= NV20_PFB_ZCOMP_EN; + tile->zcomp |= 0x80000000; if (bpp != 16) - tile->zcomp |= NV20_PFB_ZCOMP_MODE_32; + tile->zcomp |= 0x04000000; } } @@ -74,75 +66,71 @@ nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, } } -void -nv20_fb_free_tile_region(struct drm_device *dev, int i) +static void +nv20_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; - nv20_fb_free_tag(dev, &tile->tag_mem); + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; + tile->zcomp = 0; + nouveau_mm_free(&pfb->tags, &tile->tag); } -void -nv20_fb_set_tile_region(struct drm_device *dev, int i) +static void +nv20_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); + nv_wr32(pfb, 0x100244 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100248 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100240 + (i * 0x10), tile->addr); + nv_wr32(pfb, 0x100300 + (i * 0x04), tile->zcomp); } -int -nv20_fb_vram_init(struct drm_device *dev) +static int +nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mem_size = nv_rd32(dev, 0x10020c); - u32 pbus1218 = nv_rd32(dev, 0x001218); + struct nouveau_device *device = nv_device(parent); + struct nv20_fb_priv *priv; + u32 pbus1218; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - dev_priv->vram_size = mem_size & 0xff000000; + pbus1218 = nv_rd32(priv, 0x001218); switch (pbus1218 & 0x00000300) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break; } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - return 0; -} - -int -nv20_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - if (dev_priv->chipset >= 0x25) - drm_mm_init(&pfb->tag_heap, 0, 64 * 1024); + if (device->chipset >= 0x25) + ret = nouveau_mm_init(&priv->base.tags, 0, 64 * 1024, 1); else - drm_mm_init(&pfb->tag_heap, 0, 32 * 1024); - - /* Turn all the tiling regions off. */ - pfb->num_tiles = NV10_PFB_TILE__SIZE; - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + ret = nouveau_mm_init(&priv->base.tags, 0, 32 * 1024, 1); + if (ret) + return ret; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv20_fb_tile_init; + priv->base.tile.fini = nv20_fb_tile_fini; + priv->base.tile.prog = nv20_fb_tile_prog; + return nouveau_fb_created(&priv->base); } -void -nv20_fb_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i; - - for (i = 0; i < pfb->num_tiles; i++) - pfb->free_tile_region(dev, i); - - drm_mm_takedown(&pfb->tag_heap); -} +struct nouveau_oclass +nv20_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x20), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv20_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = _nouveau_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c index 30639a0..cba67bc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -24,50 +24,47 @@ * */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include + +struct nv30_fb_priv { + struct nouveau_fb base; +}; void -nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch, uint32_t flags) +nv30_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, + u32 flags, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - tile->addr = addr | 1; tile->limit = max(1u, addr + size) - 1; tile->pitch = pitch; } void -nv30_fb_free_tile_region(struct drm_device *dev, int i) +nv30_fb_tile_fini(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - tile->addr = tile->limit = tile->pitch = 0; + tile->addr = 0; + tile->limit = 0; + tile->pitch = 0; } static int -calc_bias(struct drm_device *dev, int k, int i, int j) +calc_bias(struct nv30_fb_priv *priv, int k, int i, int j) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - int b = (dev_priv->chipset > 0x30 ? - nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : + struct nouveau_device *device = nv_device(priv); + int b = (device->chipset > 0x30 ? + nv_rd32(priv, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : 0) & 0xf; return 2 * (b & 0x8 ? b - 0x10 : b); } static int -calc_ref(struct drm_device *dev, int l, int k, int i) +calc_ref(struct nv30_fb_priv *priv, int l, int k, int i) { int j, x = 0; for (j = 0; j < 4; j++) { - int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); + int m = (l >> (8 * i) & 0xff) + calc_bias(priv, k, i, j); x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); } @@ -75,42 +72,77 @@ calc_ref(struct drm_device *dev, int l, int k, int i) return x; } -int -nv30_fb_init(struct drm_device *dev) +static int +nv30_fb_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int i, j; - - pfb->num_tiles = NV10_PFB_TILE__SIZE; + struct nouveau_device *device = nv_device(object); + struct nv30_fb_priv *priv = (void *)object; + int ret, i, j; - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* Init the memory timing regs at 0x10037c/0x1003ac */ - if (dev_priv->chipset == 0x30 || - dev_priv->chipset == 0x31 || - dev_priv->chipset == 0x35) { + if (device->chipset == 0x30 || + device->chipset == 0x31 || + device->chipset == 0x35) { /* Related to ROP count */ - int n = (dev_priv->chipset == 0x31 ? 2 : 4); - int l = nv_rd32(dev, 0x1003d0); + int n = (device->chipset == 0x31 ? 2 : 4); + int l = nv_rd32(priv, 0x1003d0); for (i = 0; i < n; i++) { for (j = 0; j < 3; j++) - nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, - calc_ref(dev, l, 0, j)); + nv_wr32(priv, 0x10037c + 0xc * i + 0x4 * j, + calc_ref(priv, l, 0, j)); for (j = 0; j < 2; j++) - nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, - calc_ref(dev, l, 1, j)); + nv_wr32(priv, 0x1003ac + 0x8 * i + 0x4 * j, + calc_ref(priv, l, 1, j)); } } return 0; } -void -nv30_fb_takedown(struct drm_device *dev) +static int +nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nv30_fb_priv *priv; + u32 pbus1218; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + pbus1218 = nv_rd32(priv, 0x001218); + switch (pbus1218 & 0x00000300) { + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_GDDR2; break; + } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; + + priv->base.memtype_valid = nv04_fb_memtype_valid; + priv->base.tile.regions = 8; + priv->base.tile.init = nv30_fb_tile_init; + priv->base.tile.fini = nv30_fb_tile_fini; + priv->base.tile.prog = nv10_fb_tile_prog; + return nouveau_fb_created(&priv->base); } + +struct nouveau_oclass +nv30_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x30), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv30_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv30_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index e08c2e1..84aa71c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -1,55 +1,83 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include - -void -nv40_fb_set_tile_region(struct drm_device *dev, int i) +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 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. + * + */ + +#include + +struct nv40_fb_priv { + struct nouveau_fb base; +}; + +static inline int +nv44_graph_class(struct nouveau_device *device) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + if ((device->chipset & 0xf0) == 0x60) + return 1; - switch (dev_priv->chipset) { - case 0x40: - nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - break; + return !(0x0baf & (1 << (device->chipset & 0x0f))); +} - default: - nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit); - nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch); - nv_wr32(dev, NV40_PFB_TILE(i), tile->addr); - break; - } +static void +nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) +{ + nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit); + nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch); + nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr); } static void -nv40_fb_init_gart(struct drm_device *dev) +nv40_fb_init_gart(struct nv40_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; +#if 0 + struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100800, 0x00000001); + if (ndev->gart_info.type != NOUVEAU_GART_HW) { +#endif + nv_wr32(priv, 0x100800, 0x00000001); +#if 0 return; } - nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); - nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); - nv_wr32(dev, 0x100820, 0x00000000); + nv_wr32(ndev, 0x100800, gart->pinst | 0x00000002); + nv_mask(ndev, 0x10008c, 0x00000100, 0x00000100); + nv_wr32(ndev, 0x100820, 0x00000000); +#endif } static void -nv44_fb_init_gart(struct drm_device *dev) +nv44_fb_init_gart(struct nv40_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; +#if 0 + struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; u32 vinst; - if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { - nv_wr32(dev, 0x100850, 0x80000000); - nv_wr32(dev, 0x100800, 0x00000001); + if (ndev->gart_info.type != NOUVEAU_GART_HW) { +#endif + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100800, 0x00000001); +#if 0 return; } @@ -57,24 +85,60 @@ nv44_fb_init_gart(struct drm_device *dev) * must be allocated on 512KiB alignment, and not exceed * a total size of 512KiB for this to work correctly */ - vinst = nv_rd32(dev, 0x10020c); + vinst = nv_rd32(ndev, 0x10020c); vinst -= ((gart->pinst >> 19) + 1) << 19; - nv_wr32(dev, 0x100850, 0x80000000); - nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); + nv_wr32(ndev, 0x100850, 0x80000000); + nv_wr32(ndev, 0x100818, ndev->gart_info.dummy.addr); + + nv_wr32(ndev, 0x100804, ndev->gart_info.aper_size); + nv_wr32(ndev, 0x100850, 0x00008000); + nv_mask(ndev, 0x10008c, 0x00000200, 0x00000200); + nv_wr32(ndev, 0x100820, 0x00000000); + nv_wr32(ndev, 0x10082c, 0x00000001); + nv_wr32(ndev, 0x100800, vinst | 0x00000010); +#endif +} + +static int +nv40_fb_init(struct nouveau_object *object) +{ + struct nv40_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; + + switch (nv_device(priv)->chipset) { + case 0x40: + case 0x45: + nv_mask(priv, 0x10033c, 0x00008000, 0x00000000); + break; + default: + if (nv44_graph_class(nv_device(priv))) + nv44_fb_init_gart(priv); + else + nv40_fb_init_gart(priv); + break; + } - nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); - nv_wr32(dev, 0x100850, 0x00008000); - nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); - nv_wr32(dev, 0x100820, 0x00000000); - nv_wr32(dev, 0x10082c, 0x00000001); - nv_wr32(dev, 0x100800, vinst | 0x00000010); + return 0; } -int -nv40_fb_vram_init(struct drm_device *dev) +static int +nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); + struct nv40_fb_priv *priv; + int ret; + + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; /* 0x001218 is actually present on a few other NV4X I looked at, * and even contains sane values matching 0x100474. From looking @@ -82,82 +146,73 @@ nv40_fb_vram_init(struct drm_device *dev) * So, I chose to use the same regs I've seen NVIDIA reading around * the memory detection, hopefully that'll get us the right numbers */ - if (dev_priv->chipset == 0x40) { - u32 pbus1218 = nv_rd32(dev, 0x001218); + if (device->chipset == 0x40) { + u32 pbus1218 = nv_rd32(priv, 0x001218); switch (pbus1218 & 0x00000300) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; - case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break; } } else - if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { - u32 pfb914 = nv_rd32(dev, 0x100914); + if (device->chipset == 0x49 || device->chipset == 0x4b) { + u32 pfb914 = nv_rd32(priv, 0x100914); switch (pfb914 & 0x00000003) { - case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; - case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break; + case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; case 0x00000003: break; } } else - if (dev_priv->chipset != 0x4e) { - u32 pfb474 = nv_rd32(dev, 0x100474); + if (device->chipset != 0x4e) { + u32 pfb474 = nv_rd32(priv, 0x100474); if (pfb474 & 0x00000004) - dev_priv->vram_type = NV_MEM_TYPE_GDDR3; + priv->base.ram.type = NV_MEM_TYPE_GDDR3; if (pfb474 & 0x00000002) - dev_priv->vram_type = NV_MEM_TYPE_DDR2; + priv->base.ram.type = NV_MEM_TYPE_DDR2; if (pfb474 & 0x00000001) - dev_priv->vram_type = NV_MEM_TYPE_DDR1; + priv->base.ram.type = NV_MEM_TYPE_DDR1; } else { - dev_priv->vram_type = NV_MEM_TYPE_STOLEN; + priv->base.ram.type = NV_MEM_TYPE_STOLEN; } - dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000; - return 0; -} - -int -nv40_fb_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - uint32_t tmp; - int i; - - if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { - if (nv44_graph_class(dev)) - nv44_fb_init_gart(dev); - else - nv40_fb_init_gart(dev); - } + priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000; - switch (dev_priv->chipset) { + priv->base.memtype_valid = nv04_fb_memtype_valid; + switch (device->chipset) { case 0x40: case 0x45: - tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); - nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); - pfb->num_tiles = NV10_PFB_TILE__SIZE; + priv->base.tile.regions = 8; break; - case 0x46: /* G72 */ - case 0x47: /* G70 */ - case 0x49: /* G71 */ - case 0x4b: /* G73 */ - case 0x4c: /* C51 (G7X version) */ - pfb->num_tiles = NV40_PFB_TILE__SIZE_1; + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + case 0x4c: + priv->base.tile.regions = 15; break; default: - pfb->num_tiles = NV40_PFB_TILE__SIZE_0; + priv->base.tile.regions = 12; break; } - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) - pfb->set_tile_region(dev, i); - - return 0; + priv->base.tile.init = nv30_fb_tile_init; + priv->base.tile.fini = nv30_fb_tile_fini; + if (device->chipset == 0x40) + priv->base.tile.prog = nv10_fb_tile_prog; + else + priv->base.tile.prog = nv40_fb_tile_prog; + + return nouveau_fb_created(&priv->base); } -void -nv40_fb_takedown(struct drm_device *dev) -{ -} + +struct nouveau_oclass +nv40_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_fb_ctor, + .dtor = _nouveau_fb_dtor, + .init = nv40_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index a145b1c..eaf18fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -1,119 +1,335 @@ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include -#include +/* + * 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: + * + * 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 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 +#include + +#include +#include struct nv50_fb_priv { + struct nouveau_fb base; struct page *r100c08_page; dma_addr_t r100c08; }; -static void -nv50_fb_destroy(struct drm_device *dev) +static int types[0x80] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 +}; + +static bool +nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv = pfb->priv; + return types[(memtype & 0xff00) >> 8] != 0; +} - if (drm_mm_initialized(&pfb->tag_heap)) - drm_mm_takedown(&pfb->tag_heap); +static int +nv50_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm *heap = &priv->base.vram; + struct nouveau_mm *tags = &priv->base.tags; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; + int type = (memtype & 0x07f); + int back = (memtype & 0x800); + int min, max, ret; + + max = (size >> 12); + min = ncmin ? (ncmin >> 12) : max; + align >>= 12; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; - if (priv->r100c08_page) { - pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->r100c08_page); + mutex_lock(&pfb->base.mutex); + if (comp) { + if (align == 16) { + int n = (max >> 4) * comp; + + ret = nouveau_mm_head(tags, 1, n, n, 1, &mem->tag); + if (ret) + mem->tag = NULL; + } + + if (unlikely(!mem->tag)) + comp = 0; } - kfree(priv); - pfb->priv = NULL; + INIT_LIST_HEAD(&mem->regions); + mem->memtype = (comp << 7) | type; + mem->size = max; + + type = types[type]; + do { + if (back) + ret = nouveau_mm_tail(heap, type, max, min, align, &r); + else + ret = nouveau_mm_head(heap, type, max, min, align, &r); + if (ret) { + mutex_unlock(&pfb->base.mutex); + pfb->ram.put(pfb, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + max -= r->length; + } while (max); + mutex_unlock(&pfb->base.mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; } -static int -nv50_fb_create(struct drm_device *dev) +void +nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv; - u32 tagmem; - int ret; + struct nv50_fb_priv *priv = (void *)pfb; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + mem = *pmem; + *pmem = NULL; + if (unlikely(mem == NULL)) + return; - priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c08_page) { - nv50_fb_destroy(dev); - return -ENOMEM; + mutex_lock(&pfb->base.mutex); + while (!list_empty(&mem->regions)) { + this = list_first_entry(&mem->regions, typeof(*this), rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_free(&priv->base.vram, &this); } - priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { - nv50_fb_destroy(dev); - return -EFAULT; + nouveau_mm_free(&priv->base.tags, &mem->tag); + mutex_unlock(&pfb->base.mutex); + + kfree(mem); +} + +static u32 +nv50_vram_rblock(struct nv50_fb_priv *priv) +{ + int i, parts, colbits, rowbitsa, rowbitsb, banks; + u64 rowsize, predicted; + u32 r0, r4, rt, ru, rblock_size; + + r0 = nv_rd32(priv, 0x100200); + r4 = nv_rd32(priv, 0x100204); + rt = nv_rd32(priv, 0x100250); + ru = nv_rd32(priv, 0x001540); + nv_debug(priv, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); + + for (i = 0, parts = 0; i < 8; i++) { + if (ru & (0x00010000 << i)) + parts++; } - tagmem = nv_rd32(dev, 0x100320); - NV_DEBUG(dev, "%d tags available\n", tagmem); - ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); - if (ret) { - nv50_fb_destroy(dev); - return ret; + colbits = (r4 & 0x0000f000) >> 12; + rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; + rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; + banks = 1 << (((r4 & 0x03000000) >> 24) + 2); + + rowsize = parts * banks * (1 << colbits) * 8; + predicted = rowsize << rowbitsa; + if (r0 & 0x00000004) + predicted += rowsize << rowbitsb; + + if (predicted != priv->base.ram.size) { + nv_warn(priv, "memory controller reports %d MiB VRAM\n", + (u32)(priv->base.ram.size >> 20)); } - return 0; + rblock_size = rowsize; + if (rt & 1) + rblock_size *= 3; + + nv_debug(priv, "rblock %d bytes\n", rblock_size); + return rblock_size; } -int -nv50_fb_init(struct drm_device *dev) +static int +nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); + struct nouveau_bios *bios = nouveau_bios(device); + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ struct nv50_fb_priv *priv; + u32 tags; int ret; - if (!dev_priv->engine.fb.priv) { - ret = nv50_fb_create(dev); + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + switch (nv_rd32(priv, 0x100714) & 0x00000007) { + case 0: priv->base.ram.type = NV_MEM_TYPE_DDR1; break; + case 1: + if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3) + priv->base.ram.type = NV_MEM_TYPE_DDR3; + else + priv->base.ram.type = NV_MEM_TYPE_DDR2; + break; + case 2: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break; + case 3: priv->base.ram.type = NV_MEM_TYPE_GDDR4; break; + case 4: priv->base.ram.type = NV_MEM_TYPE_GDDR5; break; + default: + break; + } + + priv->base.ram.size = nv_rd32(priv, 0x10020c); + priv->base.ram.size = (priv->base.ram.size & 0xffffff00) | + ((priv->base.ram.size & 0x000000ff) << 32); + + tags = nv_rd32(priv, 0x100320); + if (tags) { + ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); if (ret) return ret; + + nv_debug(priv, "%d compression tags\n", tags); + } + + size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; + switch (device->chipset) { + case 0xaa: + case 0xac: + case 0xaf: /* IGPs, no reordering, no real VRAM */ + ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, 1); + if (ret) + return ret; + + priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; + break; + default: + ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, + nv50_vram_rblock(priv) >> 12); + if (ret) + return ret; + + priv->base.ram.ranks = (nv_rd32(priv, 0x100200) & 0x4) ? 2 : 1; + break; + } + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (priv->r100c08_page) { + priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page, + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->r100c08)) + nv_warn(priv, "failed 0x100c08 page map\n"); + } else { + nv_warn(priv, "failed 0x100c08 page alloc\n"); } - priv = dev_priv->engine.fb.priv; + + priv->base.memtype_valid = nv50_fb_memtype_valid; + priv->base.ram.get = nv50_fb_vram_new; + priv->base.ram.put = nv50_fb_vram_del; + return nouveau_fb_created(&priv->base); +} + +static void +nv50_fb_dtor(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + + if (priv->r100c08_page) { + pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c08_page); + } + + nouveau_mm_fini(&priv->base.vram); + nouveau_fb_destroy(&priv->base); +} + +static int +nv50_fb_init(struct nouveau_object *object) +{ + struct nouveau_device *device = nv_device(object); + struct nv50_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; /* Not a clue what this is exactly. Without pointing it at a * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) * cause IOMMU "read from address 0" errors (rh#561267) */ - nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); + nv_wr32(priv, 0x100c08, priv->r100c08 >> 8); /* This is needed to get meaningful information from 100c90 * on traps. No idea what these values mean exactly. */ - switch (dev_priv->chipset) { + switch (device->chipset) { case 0x50: - nv_wr32(dev, 0x100c90, 0x000707ff); + nv_wr32(priv, 0x100c90, 0x000707ff); break; case 0xa3: case 0xa5: case 0xa8: - nv_wr32(dev, 0x100c90, 0x000d0fff); + nv_wr32(priv, 0x100c90, 0x000d0fff); break; case 0xaf: - nv_wr32(dev, 0x100c90, 0x089d1fff); + nv_wr32(priv, 0x100c90, 0x089d1fff); break; default: - nv_wr32(dev, 0x100c90, 0x001d07ff); + nv_wr32(priv, 0x100c90, 0x001d07ff); break; } return 0; } -void -nv50_fb_takedown(struct drm_device *dev) -{ - nv50_fb_destroy(dev); -} +struct nouveau_oclass +nv50_fb_oclass = { + .handle = NV_SUBDEV(FB, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fb_ctor, + .dtor = nv50_fb_dtor, + .init = nv50_fb_init, + .fini = _nouveau_fb_fini, + }, +}; static struct nouveau_enum vm_dispatch_subclients[] = { { 0x00000000, "GRCTX", NULL }, @@ -211,47 +427,32 @@ static struct nouveau_enum vm_fault[] = { }; void -nv50_fb_vm_trap(struct drm_device *dev, int display) +nv50_fb_trap(struct nouveau_fb *pfb, int display) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(pfb); + struct nv50_fb_priv *priv = (void *)pfb; const struct nouveau_enum *en, *cl; - unsigned long flags; - u32 trap[6], idx, chinst; + u32 trap[6], idx, chan; u8 st0, st1, st2, st3; - int i, ch; + int i; - idx = nv_rd32(dev, 0x100c90); + idx = nv_rd32(priv, 0x100c90); if (!(idx & 0x80000000)) return; idx &= 0x00ffffff; for (i = 0; i < 6; i++) { - nv_wr32(dev, 0x100c90, idx | i << 24); - trap[i] = nv_rd32(dev, 0x100c94); + nv_wr32(priv, 0x100c90, idx | i << 24); + trap[i] = nv_rd32(priv, 0x100c94); } - nv_wr32(dev, 0x100c90, idx | 0x80000000); + nv_wr32(priv, 0x100c90, idx | 0x80000000); if (!display) return; - /* lookup channel id */ - chinst = (trap[2] << 16) | trap[1]; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (ch = 0; ch < pfifo->channels; ch++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; - - if (!chan || !chan->ramin) - continue; - - if (chinst == chan->ramin->vinst >> 12) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - /* decode status bits into something more useful */ - if (dev_priv->chipset < 0xa3 || - dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { + if (device->chipset < 0xa3 || + device->chipset == 0xaa || device->chipset == 0xac) { st0 = (trap[0] & 0x0000000f) >> 0; st1 = (trap[0] & 0x000000f0) >> 4; st2 = (trap[0] & 0x00000f00) >> 8; @@ -262,10 +463,11 @@ nv50_fb_vm_trap(struct drm_device *dev, int display) st2 = (trap[0] & 0x00ff0000) >> 16; st3 = (trap[0] & 0xff000000) >> 24; } + chan = (trap[2] << 16) | trap[1]; - NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", - (trap[5] & 0x00000100) ? "read" : "write", - trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); + nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ", + (trap[5] & 0x00000100) ? "read" : "write", + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan); en = nouveau_enum_find(vm_engine, st0); if (en) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c deleted file mode 100644 index 84b99b6..0000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50_vram.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2010 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: - * - * 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 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 "nouveau_drv.h" -#include - -static int types[0x80] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 -}; - -bool -nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; - - if (likely(type < ARRAY_SIZE(types) && types[type])) - return true; - return false; -} - -void -nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *this; - struct nouveau_mem *mem; - - mem = *pmem; - *pmem = NULL; - if (unlikely(mem == NULL)) - return; - - mutex_lock(&mm->mutex); - while (!list_empty(&mem->regions)) { - this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - - list_del(&this->rl_entry); - nouveau_mm_free(mm, &this); - } - - if (mem->tag) { - drm_mm_put_block(mem->tag); - mem->tag = NULL; - } - mutex_unlock(&mm->mutex); - - kfree(mem); -} - -int -nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int comp = (memtype & 0x300) >> 8; - int type = (memtype & 0x07f); - int back = (memtype & 0x800); - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - mutex_lock(&mm->mutex); - if (comp) { - if (align == 16) { - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - int n = (size >> 4) * comp; - - mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); - if (mem->tag) - mem->tag = drm_mm_get_block(mem->tag, n, 0); - } - - if (unlikely(!mem->tag)) - comp = 0; - } - - INIT_LIST_HEAD(&mem->regions); - mem->dev = dev_priv->dev; - mem->memtype = (comp << 7) | type; - mem->size = size; - - type = types[type]; - do { - if (back) - ret = nouveau_mm_tail(mm, type, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, type, size, ncmin, align, &r); - - if (ret) { - mutex_unlock(&mm->mutex); - nv50_vram_del(dev, &mem); - return ret; - } - - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; - *pmem = mem; - return 0; -} - -static u32 -nv50_vram_rblock(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, parts, colbits, rowbitsa, rowbitsb, banks; - u64 rowsize, predicted; - u32 r0, r4, rt, ru, rblock_size; - - r0 = nv_rd32(dev, 0x100200); - r4 = nv_rd32(dev, 0x100204); - rt = nv_rd32(dev, 0x100250); - ru = nv_rd32(dev, 0x001540); - NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); - - for (i = 0, parts = 0; i < 8; i++) { - if (ru & (0x00010000 << i)) - parts++; - } - - colbits = (r4 & 0x0000f000) >> 12; - rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; - rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; - banks = 1 << (((r4 & 0x03000000) >> 24) + 2); - - rowsize = parts * banks * (1 << colbits) * 8; - predicted = rowsize << rowbitsa; - if (r0 & 0x00000004) - predicted += rowsize << rowbitsb; - - if (predicted != dev_priv->vram_size) { - NV_WARN(dev, "memory controller reports %dMiB VRAM\n", - (u32)(dev_priv->vram_size >> 20)); - NV_WARN(dev, "we calculated %dMiB VRAM\n", - (u32)(predicted >> 20)); - } - - rblock_size = rowsize; - if (rt & 1) - rblock_size *= 3; - - NV_DEBUG(dev, "rblock %d bytes\n", rblock_size); - return rblock_size; -} - -int -nv50_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 pfb714 = nv_rd32(dev, 0x100714); - u32 rblock, length; - - switch (pfb714 & 0x00000007) { - case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; - case 1: - if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3) - dev_priv->vram_type = NV_MEM_TYPE_DDR3; - else - dev_priv->vram_type = NV_MEM_TYPE_DDR2; - break; - case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; - case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break; - case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break; - default: - break; - } - - dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4); - dev_priv->vram_size = nv_rd32(dev, 0x10020c); - dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; - dev_priv->vram_size &= 0xffffffff00ULL; - - /* IGPs, no funky reordering happens here, they don't have VRAM */ - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac || - dev_priv->chipset == 0xaf) { - dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; - rblock = 4096 >> 12; - } else { - rblock = nv50_vram_rblock(dev) >> 12; - } - - length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; - - return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock); -} - -void -nv50_vram_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - - nouveau_mm_fini(&vram->mm); -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index f054331..9f59f2b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,114 +22,224 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "drm.h" -#include "nouveau_drv.h" -#include +#include +#include struct nvc0_fb_priv { + struct nouveau_fb base; struct page *r100c10_page; dma_addr_t r100c10; }; -static inline void -nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) +/* 0 = unsupported + * 1 = non-compressed + * 3 = compressed + */ +static const u8 types[256] = { + 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, + 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 +}; + +static bool +nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) { - u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); - u32 stat = nv_rd32(dev, subp_base + 0x020); + u8 memtype = (tile_flags & 0x0000ff00) >> 8; + return likely((types[memtype] == 1)); +} - if (stat) { - NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); - nv_wr32(dev, subp_base + 0x020, stat); - } +static int +nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, + u32 memtype, struct nouveau_mem **pmem) +{ + struct nouveau_mm *mm = &pfb->vram; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int type = (memtype & 0x0ff); + int back = (memtype & 0x800); + int ret; + + size >>= 12; + align >>= 12; + ncmin >>= 12; + if (!ncmin) + ncmin = size; + + mem = kzalloc(sizeof(*mem), GFP_KERNEL); + if (!mem) + return -ENOMEM; + + INIT_LIST_HEAD(&mem->regions); + mem->memtype = type; + mem->size = size; + + mutex_lock(&mm->mutex); + do { + if (back) + ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); + pfb->ram.put(pfb, &mem); + return ret; + } + + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; + *pmem = mem; + return 0; } -static void -nvc0_mfb_isr(struct drm_device *dev) +static int +nvc0_fb_init(struct nouveau_object *object) { - u32 units = nv_rd32(dev, 0x00017c); - while (units) { - u32 subp, unit = ffs(units) - 1; - for (subp = 0; subp < 2; subp++) - nvc0_mfb_subp_isr(dev, unit, subp); - units &= ~(1 << unit); - } + struct nvc0_fb_priv *priv = (void *)object; + int ret; + + ret = nouveau_fb_init(&priv->base); + if (ret) + return ret; - /* we do something horribly wrong and upset PMFB a lot, so mask off - * interrupts from it after the first one until it's fixed - */ - nv_mask(dev, 0x000640, 0x02000000, 0x00000000); + nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); + return 0; } static void -nvc0_fb_destroy(struct drm_device *dev) +nvc0_fb_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv = pfb->priv; - - nouveau_irq_unregister(dev, 25); + struct nouveau_device *device = nv_device(object); + struct nvc0_fb_priv *priv = (void *)object; if (priv->r100c10_page) { - pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, + pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); __free_page(priv->r100c10_page); } - kfree(priv); - pfb->priv = NULL; + nouveau_fb_destroy(&priv->base); } static int -nvc0_fb_create(struct drm_device *dev) +nvc0_vram_detect(struct nvc0_fb_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pfb->priv = priv; + struct nouveau_bios *bios = nouveau_bios(priv); + struct nouveau_fb *pfb = &priv->base; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ + u32 parts = nv_rd32(priv, 0x022438); + u32 pmask = nv_rd32(priv, 0x022554); + u32 bsize = nv_rd32(priv, 0x10f20c); + u32 offset, length; + bool uniform = true; + int ret, part; + + nv_debug(priv, "0x100800: 0x%08x\n", nv_rd32(priv, 0x100800)); + nv_debug(priv, "parts 0x%08x mask 0x%08x\n", parts, pmask); + + priv->base.ram.type = nouveau_fb_bios_memtype(bios); + priv->base.ram.ranks = (nv_rd32(priv, 0x10f200) & 0x00000004) ? 2 : 1; + + /* read amount of vram attached to each memory controller */ + for (part = 0; part < parts; part++) { + if (!(pmask & (1 << part))) { + u32 psize = nv_rd32(priv, 0x11020c + (part * 0x1000)); + if (psize != bsize) { + if (psize < bsize) + bsize = psize; + uniform = false; + } + + nv_debug(priv, "%d: mem_amount 0x%08x\n", part, psize); + priv->base.ram.size += (u64)psize << 20; + } + } - priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c10_page) { - nvc0_fb_destroy(dev); - return -ENOMEM; + /* if all controllers have the same amount attached, there's no holes */ + if (uniform) { + offset = rsvd_head; + length = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; + return nouveau_mm_init(&pfb->vram, offset, length, 1); } - priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { - nvc0_fb_destroy(dev); - return -EFAULT; + /* otherwise, address lowest common amount from 0GiB */ + ret = nouveau_mm_init(&pfb->vram, rsvd_head, (bsize << 8) * parts, 1); + if (ret) + return ret; + + /* and the rest starting from (8GiB + common_size) */ + offset = (0x0200000000ULL >> 12) + (bsize << 8); + length = (priv->base.ram.size >> 12) - (bsize << 8) - rsvd_tail; + + ret = nouveau_mm_init(&pfb->vram, offset, length, 0); + if (ret) { + nouveau_mm_fini(&pfb->vram); + return ret; } - nouveau_irq_register(dev, 25, nvc0_mfb_isr); return 0; } -int -nvc0_fb_init(struct drm_device *dev) +static int +nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_device *device = nv_device(parent); struct nvc0_fb_priv *priv; int ret; - if (!dev_priv->engine.fb.priv) { - ret = nvc0_fb_create(dev); - if (ret) - return ret; - } - priv = dev_priv->engine.fb.priv; + ret = nouveau_fb_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */ - return 0; -} + priv->base.memtype_valid = nvc0_fb_memtype_valid; + priv->base.ram.get = nvc0_fb_vram_new; + priv->base.ram.put = nv50_fb_vram_del; -void -nvc0_fb_takedown(struct drm_device *dev) -{ - nvc0_fb_destroy(dev); + ret = nvc0_vram_detect(priv); + if (ret) + return ret; + + priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c10_page) + return -ENOMEM; + + priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->r100c10)) + return -EFAULT; + + return nouveau_fb_created(&priv->base); } + + +struct nouveau_oclass +nvc0_fb_oclass = { + .handle = NV_SUBDEV(FB, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fb_ctor, + .dtor = nvc0_fb_dtor, + .init = nvc0_fb_init, + .fini = _nouveau_fb_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c deleted file mode 100644 index f363234..0000000 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0_vram.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010 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: - * - * 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 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 "nouveau_drv.h" -#include - -/* 0 = unsupported - * 1 = non-compressed - * 3 = compressed - */ -static const u8 types[256] = { - 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, - 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, - 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, - 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 -}; - -bool -nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -{ - u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; - return likely((types[memtype] == 1)); -} - -int -nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nouveau_mem **pmem) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int type = (memtype & 0x0ff); - int back = (memtype & 0x800); - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - INIT_LIST_HEAD(&mem->regions); - mem->dev = dev_priv->dev; - mem->memtype = type; - mem->size = size; - - mutex_lock(&mm->mutex); - do { - if (back) - ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); - else - ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); - if (ret) { - mutex_unlock(&mm->mutex); - nv50_vram_del(dev, &mem); - return ret; - } - - list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - - r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - mem->offset = (u64)r->offset << 12; - *pmem = mem; - return 0; -} - -int -nvc0_vram_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 parts = nv_rd32(dev, 0x022438); - u32 pmask = nv_rd32(dev, 0x022554); - u32 bsize = nv_rd32(dev, 0x10f20c); - u32 offset, length; - bool uniform = true; - int ret, part; - - NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); - NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask); - - dev_priv->vram_type = nouveau_mem_vbios_type(dev); - dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004); - - /* read amount of vram attached to each memory controller */ - for (part = 0; part < parts; part++) { - if (!(pmask & (1 << part))) { - u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000)); - if (psize != bsize) { - if (psize < bsize) - bsize = psize; - uniform = false; - } - - NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); - dev_priv->vram_size += (u64)psize << 20; - } - } - - /* if all controllers have the same amount attached, there's no holes */ - if (uniform) { - offset = rsvd_head; - length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; - return nouveau_mm_init(&vram->mm, offset, length, 1); - } - - /* otherwise, address lowest common amount from 0GiB */ - ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); - if (ret) - return ret; - - /* and the rest starting from (8GiB + common_size) */ - offset = (0x0200000000ULL >> 12) + (bsize << 8); - length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; - - ret = nouveau_mm_init(&vram->mm, offset, length, 0); - if (ret) { - nouveau_mm_fini(&vram->mm); - return ret; - } - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 5965eb7..24d077a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -310,8 +310,6 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, u32 size, u32 align) { struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node = NULL; int ret; @@ -323,7 +321,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, size = (size + 4095) & ~4095; align = max(align, (u32)4096); - ret = vram->get(dev, size, align, 0, 0x800, &node->vram); + ret = nvfb_vram_get(dev, size, align, 0, 0x800, &node->vram); if (ret) { kfree(node); return ret; @@ -339,7 +337,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, ret = nouveau_vm_get(chan->vm, size, 12, flags, &node->chan_vma); if (ret) { - vram->put(dev, &node->vram); + nvfb_vram_put(dev, &node->vram); kfree(node); return ret; } @@ -357,8 +355,6 @@ void nv50_instmem_put(struct nouveau_gpuobj *gpuobj) { struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nv50_gpuobj_node *node; node = gpuobj->node; @@ -368,7 +364,7 @@ nv50_instmem_put(struct nouveau_gpuobj *gpuobj) nouveau_vm_unmap(&node->chan_vma); nouveau_vm_put(&node->chan_vma); } - vram->put(dev, &node->vram); + nvfb_vram_put(dev, &node->vram); kfree(node); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c new file mode 100644 index 0000000..7c2840c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -0,0 +1,91 @@ +/* + * 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: + * + * 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 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 + +struct nvc0_ltcg_priv { + struct nouveau_ltcg base; +}; + +static void +nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp) +{ + u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); + u32 stat = nv_rd32(priv, subp_base + 0x020); + + if (stat) { + nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat); + nv_wr32(priv, subp_base + 0x020, stat); + } +} + +static void +nvc0_ltcg_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_ltcg_priv *priv = (void *)subdev; + u32 units; + + units = nv_rd32(priv, 0x00017c); + while (units) { + u32 subp, unit = ffs(units) - 1; + for (subp = 0; subp < 2; subp++) + nvc0_ltcg_subp_isr(priv, unit, subp); + units &= ~(1 << unit); + } + + /* we do something horribly wrong and upset PMFB a lot, so mask off + * interrupts from it after the first one until it's fixed + */ + nv_mask(priv, 0x000640, 0x02000000, 0x00000000); +} + +static int +nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_ltcg_priv *priv; + int ret; + + ret = nouveau_ltcg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ + + nv_subdev(priv)->intr = nvc0_ltcg_intr; + return 0; +} + +struct nouveau_oclass +nvc0_ltcg_oclass = { + .handle = NV_SUBDEV(LTCG, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_ltcg_ctor, + .dtor = _nouveau_ltcg_dtor, + .init = _nouveau_ltcg_init, + .fini = _nouveau_ltcg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 3fa39bb..bd9e9946 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -38,6 +38,7 @@ nvc0_mc_intr[] = { { 0x00008000, NVDEV_ENGINE_BSP }, { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x00200000, NVDEV_SUBDEV_GPIO }, + { 0x02000000, NVDEV_SUBDEV_LTCG }, { 0x04000000, NVDEV_ENGINE_DISP }, { 0x80000000, NVDEV_ENGINE_SW }, {}, diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index eeac72f..7e46826d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -80,8 +80,8 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, /* IGPs don't have real VRAM, re-target to stolen system memory */ target = 0; - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; + if (nvfb_vram_sys_base(dev_priv->dev)) { + phys += nvfb_vram_sys_base(dev_priv->dev); target = 3; } @@ -103,7 +103,7 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, phys += block << (vma->node->type - 3); cnt -= block; if (comp) { - u32 tag = mem->tag->start + ((delta >> 16) * comp); + u32 tag = mem->tag->offset + ((delta >> 16) * comp); offset_h |= (tag << 17); delta += block << (vma->node->type - 3); } -- cgit v1.1 From af7afbd2e1409168698bde2f2846848b07d05d12 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2012 16:14:25 +1000 Subject: drm/nv04-nv40/instmem: duplicate nv04 code as nv40, remove alternate paths A ton of duplication for the moment, will go away when they become subdevs. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 47 +----- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h | 11 ++ drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | 167 +++++++++++++++++++++ 3 files changed, 180 insertions(+), 45 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index f01063c..8265ca8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -11,9 +11,6 @@ nouveau_fifo_ctx_size(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->chipset >= 0x40) - return 128 * 32; - else if (dev_priv->chipset >= 0x17) return 64 * 32; else @@ -32,27 +29,7 @@ int nv04_instmem_init(struct drm_device *dev) /* RAMIN always available */ dev_priv->ramin_available = true; - - /* Reserve space at end of VRAM for PRAMIN */ - if (dev_priv->card_type >= NV_40) { - u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); - u32 rsvd; - - /* estimate grctx size, the magics come from nv40_grctx.c */ - if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; - else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; - else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; - else rsvd = 0x4a40 * vs; - rsvd += 16 * 1024; - rsvd *= 32; /* per-channel */ - - rsvd += 512 * 1024; /* pci(e)gart table */ - rsvd += 512 * 1024; /* object storage */ - - dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); - } else { - dev_priv->ramin_rsvd_vram = 512 * 1024; - } + dev_priv->ramin_rsvd_vram = 512 * 1024; /* Setup shared RAMHT */ ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, @@ -73,14 +50,7 @@ int nv04_instmem_init(struct drm_device *dev) /* And RAMFC */ length = nouveau_fifo_ctx_size(dev); - switch (dev_priv->card_type) { - case NV_40: - offset = 0x20000; - break; - default: - offset = 0x11400; - break; - } + offset = 0x11400; ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); @@ -90,19 +60,6 @@ int nv04_instmem_init(struct drm_device *dev) /* Only allow space after RAMFC to be used for object allocation */ offset += length; - /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 - * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 - * ("new style" control) the upper 16-bits of 0x2220 points at this - * other mysterious table that's clobbering important things. - * - * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting - * smashed to pieces on us, so reserve 0x30000-0x40000 too.. - */ - if (dev_priv->card_type >= NV_40) { - if (offset < 0x40000) - offset = 0x40000; - } - ret = drm_mm_init(&dev_priv->ramin_heap, offset, dev_priv->ramin_rsvd_vram - offset); if (ret) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h new file mode 100644 index 0000000..a8c1104 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -0,0 +1,11 @@ +#ifndef __NV04_INSTMEM_H__ +#define __NV04_INSTMEM_H__ + +struct nv04_instmem_priv { + struct nouveau_gpuobj *vbios; + struct nouveau_gpuobj *ramht; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c new file mode 100644 index 0000000..91abf0b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -0,0 +1,167 @@ +#include "drmP.h" +#include "drm.h" + +#include "nouveau_drv.h" +#include +#include + +/* returns the size of fifo context */ +static int +nouveau_fifo_ctx_size(struct drm_device *dev) +{ + return 128 * 32; +} + +int nv40_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramht = NULL; + u32 offset, length, vs, rsvd; + int ret; + + /* RAMIN always available */ + dev_priv->ramin_available = true; + + /* Reserve space at end of VRAM for PRAMIN */ + /* estimate grctx size, the magics come from nv40_grctx.c */ + vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); + if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; + else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; + else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; + else rsvd = 0x4a40 * vs; + rsvd += 16 * 1024; + rsvd *= 32; /* per-channel */ + + rsvd += 512 * 1024; /* pci(e)gart table */ + rsvd += 512 * 1024; /* object storage */ + + dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); + + /* Setup shared RAMHT */ + ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, + NVOBJ_FLAG_ZERO_ALLOC, &ramht); + if (ret) + return ret; + + ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); + nouveau_gpuobj_ref(NULL, &ramht); + if (ret) + return ret; + + /* And RAMRO */ + ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, + NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); + if (ret) + return ret; + + /* And RAMFC */ + length = nouveau_fifo_ctx_size(dev); + offset = 0x20000; + + ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, + NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); + if (ret) + return ret; + + /* Only allow space after RAMFC to be used for object allocation */ + offset += length; + + /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 + * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 + * ("new style" control) the upper 16-bits of 0x2220 points at this + * other mysterious table that's clobbering important things. + * + * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting + * smashed to pieces on us, so reserve 0x30000-0x40000 too.. + */ + if (offset < 0x40000) + offset = 0x40000; + + ret = drm_mm_init(&dev_priv->ramin_heap, offset, + dev_priv->ramin_rsvd_vram - offset); + if (ret) { + NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); + return ret; + } + + return 0; +} + +void +nv40_instmem_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); + nouveau_gpuobj_ref(NULL, &dev_priv->ramro); + nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); + + if (drm_mm_initialized(&dev_priv->ramin_heap)) + drm_mm_takedown(&dev_priv->ramin_heap); +} + +int +nv40_instmem_suspend(struct drm_device *dev) +{ + return 0; +} + +void +nv40_instmem_resume(struct drm_device *dev) +{ +} + +int +nv40_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, + u32 size, u32 align) +{ + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_mm_node *ramin = NULL; + + do { + if (drm_mm_pre_get(&dev_priv->ramin_heap)) + return -ENOMEM; + + spin_lock(&dev_priv->ramin_lock); + ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); + if (ramin == NULL) { + spin_unlock(&dev_priv->ramin_lock); + return -ENOMEM; + } + + ramin = drm_mm_get_block_atomic(ramin, size, align); + spin_unlock(&dev_priv->ramin_lock); + } while (ramin == NULL); + + gpuobj->node = ramin; + gpuobj->vinst = ramin->start; + return 0; +} + +void +nv40_instmem_put(struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + + spin_lock(&dev_priv->ramin_lock); + drm_mm_put_block(gpuobj->node); + gpuobj->node = NULL; + spin_unlock(&dev_priv->ramin_lock); +} + +int +nv40_instmem_map(struct nouveau_gpuobj *gpuobj) +{ + gpuobj->pinst = gpuobj->vinst; + return 0; +} + +void +nv40_instmem_unmap(struct nouveau_gpuobj *gpuobj) +{ +} + +void +nv40_instmem_flush(struct drm_device *dev) +{ +} -- cgit v1.1 From 5787640db6ae722aeadb394d480c7ca21b603e34 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2012 16:42:14 +1000 Subject: drm/nv04-nv40/instmem: remove use of nouveau_gpuobj_new_fake() These type of fake objects will not be supported for much longer. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 17 +++- drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 10 ++- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 14 +++- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 14 +++- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 73 ++++++++--------- drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | 92 +++++++++++----------- 6 files changed, 122 insertions(+), 98 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index bc38087..d7857b7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -32,6 +32,8 @@ #include #include "nouveau_software.h" +#include + static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -53,6 +55,8 @@ static struct ramfc_desc { struct nv04_fifo_priv { struct nouveau_fifo_priv base; struct ramfc_desc *ramfc_desc; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; }; struct nv04_fifo_chan { @@ -112,7 +116,7 @@ nv04_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + chan->id * 32, ~0, 32, NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); if (ret) @@ -207,8 +211,8 @@ nv04_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); + nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->pinst >> 8); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); @@ -478,6 +482,9 @@ nv04_fifo_destroy(struct drm_device *dev, int engine) nouveau_irq_unregister(dev, 8); + nouveau_gpuobj_ref(NULL, &priv->ramfc); + nouveau_gpuobj_ref(NULL, &priv->ramro); + dev_priv->eng[engine] = NULL; kfree(priv); } @@ -486,12 +493,16 @@ int nv04_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv04_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv04_fifo_init; priv->base.base.fini = nv04_fifo_fini; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 9058c31..9c1083a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -31,6 +31,8 @@ #include "nouveau_util.h" #include +#include + static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -53,6 +55,8 @@ static struct ramfc_desc { struct nv10_fifo_priv { struct nouveau_fifo_priv base; struct ramfc_desc *ramfc_desc; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; }; struct nv10_fifo_chan { @@ -83,7 +87,7 @@ nv10_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + chan->id * 32, ~0, 32, NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); if (ret) @@ -118,12 +122,16 @@ int nv10_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv10_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv04_fifo_init; priv->base.base.fini = nv04_fifo_fini; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index c514364..4bf4efa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -31,6 +31,8 @@ #include "nouveau_util.h" #include +#include + static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -58,6 +60,8 @@ static struct ramfc_desc { struct nv17_fifo_priv { struct nouveau_fifo_priv base; struct ramfc_desc *ramfc_desc; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; }; struct nv17_fifo_chan { @@ -88,7 +92,7 @@ nv17_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + chan->id * 64, ~0, 64, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); @@ -132,9 +136,9 @@ nv17_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 | - dev_priv->ramfc->pinst >> 8); + priv->ramfc->pinst >> 8); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); @@ -157,12 +161,16 @@ int nv17_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv17_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv17_fifo_init; priv->base.base.fini = nv04_fifo_fini; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 23ae459..e42498f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -31,6 +31,8 @@ #include "nouveau_util.h" #include +#include + static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -66,6 +68,8 @@ static struct ramfc_desc { struct nv40_fifo_priv { struct nouveau_fifo_priv base; struct ramfc_desc *ramfc_desc; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; }; struct nv40_fifo_chan { @@ -96,7 +100,7 @@ nv40_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst + + ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + chan->id * 128, ~0, 128, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); @@ -146,7 +150,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); switch (dev_priv->chipset) { case 0x47: @@ -164,7 +168,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) default: nv_wr32(dev, 0x002230, 0x00000000); nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + - dev_priv->ramfc->pinst) >> 16) | + priv->ramfc->pinst) >> 16) | 0x00030000); break; } @@ -190,12 +194,16 @@ int nv40_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv40_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv40_fifo_init; priv->base.base.fini = nv04_fifo_fini; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index 8265ca8..46b6963 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -5,67 +5,53 @@ #include #include -/* returns the size of fifo context */ -static int -nouveau_fifo_ctx_size(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->chipset >= 0x17) - return 64 * 32; - else - if (dev_priv->chipset >= 0x10) - return 32 * 32; +#include "nv04.h" - return 32 * 16; -} - -int nv04_instmem_init(struct drm_device *dev) +int +nv04_instmem_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ramht = NULL; - u32 offset, length; + struct nv04_instmem_priv *priv; int ret; - /* RAMIN always available */ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_priv->engine.instmem.priv = priv; + + /* PRAMIN aperture maps over the end of vram, reserve the space */ dev_priv->ramin_available = true; dev_priv->ramin_rsvd_vram = 512 * 1024; - /* Setup shared RAMHT */ - ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &ramht); + ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_rsvd_vram); if (ret) return ret; - ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); - nouveau_gpuobj_ref(NULL, &ramht); + /* 0x00000-0x10000: reserve for probable vbios image */ + ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0, 0, &priv->vbios); if (ret) return ret; - /* And RAMRO */ - ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, - NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); + /* 0x10000-0x18000: reserve for RAMHT */ + ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, NVOBJ_FLAG_ZERO_ALLOC, + &priv->ramht); if (ret) return ret; - /* And RAMFC */ - length = nouveau_fifo_ctx_size(dev); - offset = 0x11400; - - ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, - NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); + /* 0x18000-0x18200: reserve for RAMRO */ + ret = nouveau_gpuobj_new(dev, NULL, 0x00200, 0, 0, &priv->ramro); if (ret) return ret; - /* Only allow space after RAMFC to be used for object allocation */ - offset += length; + /* 0x18200-0x18a00: reserve for RAMFC (enough for 32 nv30 channels) */ + ret = nouveau_gpuobj_new(dev, NULL, 0x00800, 0, NVOBJ_FLAG_ZERO_ALLOC, + &priv->ramfc); + if (ret) + return ret; - ret = drm_mm_init(&dev_priv->ramin_heap, offset, - dev_priv->ramin_rsvd_vram - offset); - if (ret) { - NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); + ret = nouveau_ramht_new(dev, priv->ramht, &dev_priv->ramht); + if (ret) return ret; - } return 0; } @@ -74,13 +60,18 @@ void nv04_instmem_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_instmem_priv *priv = dev_priv->engine.instmem.priv; nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); - nouveau_gpuobj_ref(NULL, &dev_priv->ramro); - nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); + nouveau_gpuobj_ref(NULL, &priv->ramfc); + nouveau_gpuobj_ref(NULL, &priv->ramro); + nouveau_gpuobj_ref(NULL, &priv->ramht); if (drm_mm_initialized(&dev_priv->ramin_heap)) drm_mm_takedown(&dev_priv->ramin_heap); + + kfree(priv); + dev_priv->engine.instmem.priv = NULL; } int diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 91abf0b..7c938ae 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -5,84 +5,77 @@ #include #include -/* returns the size of fifo context */ -static int -nouveau_fifo_ctx_size(struct drm_device *dev) -{ - return 128 * 32; -} +#include "nv04.h" int nv40_instmem_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ramht = NULL; - u32 offset, length, vs, rsvd; + struct nv04_instmem_priv *priv; + u32 vs, rsvd; int ret; - /* RAMIN always available */ - dev_priv->ramin_available = true; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_priv->engine.instmem.priv = priv; - /* Reserve space at end of VRAM for PRAMIN */ - /* estimate grctx size, the magics come from nv40_grctx.c */ + /* PRAMIN aperture maps over the end of vram, reserve enough space + * to fit graphics contexts for every channel, the magics come + * from engine/graph/nv40.c + */ vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; else rsvd = 0x4a40 * vs; rsvd += 16 * 1024; - rsvd *= 32; /* per-channel */ - - rsvd += 512 * 1024; /* pci(e)gart table */ - rsvd += 512 * 1024; /* object storage */ - + rsvd *= 32; /* per-channel */ + rsvd += 512 * 1024; /* pci(e)gart table */ + rsvd += 512 * 1024; /* object storage */ dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); + dev_priv->ramin_available = true; - /* Setup shared RAMHT */ - ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &ramht); + ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_rsvd_vram); if (ret) return ret; - ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); - nouveau_gpuobj_ref(NULL, &ramht); + /* 0x00000-0x10000: reserve for probable vbios image */ + ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0, 0, &priv->vbios); if (ret) return ret; - /* And RAMRO */ - ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, - NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); + /* 0x10000-0x18000: reserve for RAMHT */ + ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, NVOBJ_FLAG_ZERO_ALLOC, + &priv->ramht); if (ret) return ret; - /* And RAMFC */ - length = nouveau_fifo_ctx_size(dev); - offset = 0x20000; - - ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, - NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); + /* 0x18000-0x18200: reserve for RAMRO + * 0x18200-0x20000: padding + */ + ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, 0, &priv->ramro); if (ret) return ret; - /* Only allow space after RAMFC to be used for object allocation */ - offset += length; - - /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 - * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 - * ("new style" control) the upper 16-bits of 0x2220 points at this - * other mysterious table that's clobbering important things. + /* 0x20000-0x21000: reserve for RAMFC + * 0x21000-0x40000: padding + some unknown stuff (see below) + * + * It appears something is controlled by 0x2220/0x2230 on certain + * NV4x chipsets as well as RAMFC. When 0x2230 == 0 ("new style" + * control) the upper 16-bits of 0x2220 points at this other + * mysterious table that's clobbering important things. * * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting * smashed to pieces on us, so reserve 0x30000-0x40000 too.. */ - if (offset < 0x40000) - offset = 0x40000; + ret = nouveau_gpuobj_new(dev, NULL, 0x20000, 0, NVOBJ_FLAG_ZERO_ALLOC, + &priv->ramfc); + if (ret) + return ret; - ret = drm_mm_init(&dev_priv->ramin_heap, offset, - dev_priv->ramin_rsvd_vram - offset); - if (ret) { - NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); + ret = nouveau_ramht_new(dev, priv->ramht, &dev_priv->ramht); + if (ret) return ret; - } return 0; } @@ -91,13 +84,18 @@ void nv40_instmem_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv04_instmem_priv *priv = dev_priv->engine.instmem.priv; nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); - nouveau_gpuobj_ref(NULL, &dev_priv->ramro); - nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); + nouveau_gpuobj_ref(NULL, &priv->ramfc); + nouveau_gpuobj_ref(NULL, &priv->ramro); + nouveau_gpuobj_ref(NULL, &priv->ramht); if (drm_mm_initialized(&dev_priv->ramin_heap)) drm_mm_takedown(&dev_priv->ramin_heap); + + kfree(priv); + dev_priv->engine.instmem.priv = NULL; } int -- cgit v1.1 From 70ee6f1cd6911098ddd4c11ee21b69dbe51fb3f9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2012 16:49:49 +1000 Subject: drm/nv04-nv40/fifo: remove use of nouveau_gpuobj_new_fake() Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 37 ++++++++++--------------- drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 29 ++++++++----------- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 26 ++++++++--------- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 31 +++++++++------------ 4 files changed, 50 insertions(+), 73 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index d7857b7..ba76cf0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -61,7 +61,7 @@ struct nv04_fifo_priv { struct nv04_fifo_chan { struct nouveau_fifo_chan base; - struct nouveau_gpuobj *ramfc; + u32 ramfc; }; bool @@ -107,6 +107,8 @@ nv04_fifo_context_new(struct nouveau_channel *chan, int engine) if (!fctx) return -ENOMEM; + fctx->ramfc = chan->id * 32; + /* map channel control registers */ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV03_USER(chan->id), PAGE_SIZE); @@ -116,25 +118,16 @@ nv04_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + - chan->id * 32, ~0, 32, - NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); - if (ret) - goto error; - - nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x08, chan->pushbuf->pinst >> 4); - nv_wo32(fctx->ramfc, 0x0c, 0x00000000); - nv_wo32(fctx->ramfc, 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x10, + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | + NV_PFIFO_CACHE1_BIG_ENDIAN | #endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nv_wo32(fctx->ramfc, 0x14, 0x00000000); - nv_wo32(fctx->ramfc, 0x18, 0x00000000); - nv_wo32(fctx->ramfc, 0x1c, 0x00000000); + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); /* enable dma mode on the channel */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); @@ -172,6 +165,7 @@ nv04_fifo_context_del(struct nouveau_channel *chan, int engine) do { u32 mask = ((1ULL << c->bits) - 1) << c->regs; nv_mask(dev, c->regp, mask, 0x00000000); + nv_wo32(priv->ramfc, fctx->ramfc + c->ctxp, 0x00000000); } while ((++c)->bits); nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); @@ -187,7 +181,6 @@ nv04_fifo_context_del(struct nouveau_channel *chan, int engine) spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); /* clean up */ - nouveau_gpuobj_ref(NULL, &fctx->ramfc); nouveau_gpuobj_ref(NULL, &chan->ramfc); /*XXX: nv40 */ if (chan->user) { iounmap(chan->user); @@ -250,14 +243,14 @@ nv04_fifo_fini(struct drm_device *dev, int engine, bool suspend) chan = dev_priv->channels.ptr[chid]; if (suspend && chid != priv->base.channels && chan) { struct nv04_fifo_chan *fctx = chan->engctx[engine]; - struct nouveau_gpuobj *ctx = fctx->ramfc; + struct nouveau_gpuobj *ctx = priv->ramfc; struct ramfc_desc *c = priv->ramfc_desc; do { u32 rm = ((1ULL << c->bits) - 1) << c->regs; u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; u32 rv = (nv_rd32(dev, c->regp) & rm) >> c->regs; - u32 cv = (nv_ro32(ctx, c->ctxp) & ~cm); - nv_wo32(ctx, c->ctxp, cv | (rv << c->ctxs)); + u32 cv = (nv_ro32(ctx, c->ctxp + fctx->ramfc) & ~cm); + nv_wo32(ctx, c->ctxp + fctx->ramfc, cv | (rv << c->ctxs)); } while ((++c)->bits); } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 9c1083a..0da287c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -61,7 +61,7 @@ struct nv10_fifo_priv { struct nv10_fifo_chan { struct nouveau_fifo_chan base; - struct nouveau_gpuobj *ramfc; + u32 ramfc; }; static int @@ -78,6 +78,8 @@ nv10_fifo_context_new(struct nouveau_channel *chan, int engine) if (!fctx) return -ENOMEM; + fctx->ramfc = chan->id * 32; + /* map channel control registers */ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV03_USER(chan->id), PAGE_SIZE); @@ -87,25 +89,16 @@ nv10_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + - chan->id * 32, ~0, 32, - NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); - if (ret) - goto error; - - nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x08, 0x00000000); - nv_wo32(fctx->ramfc, 0x0c, chan->pushbuf->pinst >> 4); - nv_wo32(fctx->ramfc, 0x10, 0x00000000); - nv_wo32(fctx->ramfc, 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x14, + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | + NV_PFIFO_CACHE1_BIG_ENDIAN | #endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nv_wo32(fctx->ramfc, 0x18, 0x00000000); - nv_wo32(fctx->ramfc, 0x1c, 0x00000000); + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); /* enable dma mode on the channel */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 4bf4efa..99b88e0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -66,7 +66,7 @@ struct nv17_fifo_priv { struct nv17_fifo_chan { struct nouveau_fifo_chan base; - struct nouveau_gpuobj *ramfc; + u32 ramfc; }; static int @@ -83,6 +83,8 @@ nv17_fifo_context_new(struct nouveau_channel *chan, int engine) if (!fctx) return -ENOMEM; + fctx->ramfc = chan->id * 64; + /* map channel control registers */ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV03_USER(chan->id), PAGE_SIZE); @@ -92,22 +94,16 @@ nv17_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + - chan->id * 64, ~0, 64, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); - if (ret) - goto error; - - nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x0c, chan->pushbuf->pinst >> 4); - nv_wo32(fctx->ramfc, 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x14, + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | + NV_PFIFO_CACHE1_BIG_ENDIAN | #endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); /* enable dma mode on the channel */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index e42498f..df53b9f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -74,7 +74,7 @@ struct nv40_fifo_priv { struct nv40_fifo_chan { struct nouveau_fifo_chan base; - struct nouveau_gpuobj *ramfc; + u32 ramfc; }; static int @@ -91,6 +91,8 @@ nv40_fifo_context_new(struct nouveau_channel *chan, int engine) if (!fctx) return -ENOMEM; + fctx->ramfc = chan->id * 128; + /* map channel control registers */ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV03_USER(chan->id), PAGE_SIZE); @@ -100,24 +102,17 @@ nv40_fifo_context_new(struct nouveau_channel *chan, int engine) } /* initialise default fifo context */ - ret = nouveau_gpuobj_new_fake(dev, priv->ramfc->pinst + - chan->id * 128, ~0, 128, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); - if (ret) - goto error; - - nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base); - nv_wo32(fctx->ramfc, 0x0c, chan->pushbuf->pinst >> 4); - nv_wo32(fctx->ramfc, 0x18, 0x30000000 | - NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x18, 0x30000000 | + NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN - NV_PFIFO_CACHE1_BIG_ENDIAN | + NV_PFIFO_CACHE1_BIG_ENDIAN | #endif - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nv_wo32(fctx->ramfc, 0x3c, 0x0001ffff); + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + nv_wo32(priv->ramfc, fctx->ramfc + 0x3c, 0x0001ffff); /* enable dma mode on the channel */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); @@ -125,7 +120,7 @@ nv40_fifo_context_new(struct nouveau_channel *chan, int engine) spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); /*XXX: remove this later, need fifo engine context commit hook */ - nouveau_gpuobj_ref(fctx->ramfc, &chan->ramfc); + nouveau_gpuobj_ref(priv->ramfc, &chan->ramfc); error: if (ret) -- cgit v1.1 From 9da226f698c01b268b9172050df4150f269a7613 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2012 16:54:45 +1000 Subject: drm/nvc0/fifo: handle bar1 control regs much like fifo/nve0 The partial mapping thing is stupid and pointless... Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 40 +++++++++++++------------ 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 398f32d..8f0e63e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -34,13 +34,15 @@ struct nvc0_fifo_priv { struct nouveau_fifo_priv base; struct nouveau_gpuobj *playlist[2]; int cur_playlist; - struct nouveau_vma user_vma; + struct { + struct nouveau_gpuobj *mem; + struct nouveau_vma bar; + } user; int spoon_nr; }; struct nvc0_fifo_chan { struct nouveau_fifo_chan base; - struct nouveau_gpuobj *user; }; static void @@ -78,6 +80,7 @@ nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_fifo_priv *priv = nv_engine(dev, engine); struct nvc0_fifo_chan *fctx; + u64 usermem = priv->user.mem->vinst + chan->id * 0x1000; u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; int ret, i; @@ -86,26 +89,17 @@ nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) return -ENOMEM; chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + - priv->user_vma.offset + (chan->id * 0x1000), + priv->user.bar.offset + (chan->id * 0x1000), PAGE_SIZE); if (!chan->user) { ret = -ENOMEM; goto error; } - /* allocate vram for control regs, map into polling area */ - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &fctx->user); - if (ret) - goto error; - - nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000, - *(struct nouveau_mem **)fctx->user->node); - for (i = 0; i < 0x100; i += 4) nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x08, lower_32_bits(fctx->user->vinst)); - nv_wo32(chan->ramin, 0x0c, upper_32_bits(fctx->user->vinst)); + nv_wo32(chan->ramin, 0x08, lower_32_bits(usermem)); + nv_wo32(chan->ramin, 0x0c, upper_32_bits(usermem)); nv_wo32(chan->ramin, 0x10, 0x0000face); nv_wo32(chan->ramin, 0x30, 0xfffff902); nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); @@ -147,7 +141,6 @@ nvc0_fifo_context_del(struct nouveau_channel *chan, int engine) nvc0_fifo_playlist_update(dev); nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000); - nouveau_gpuobj_ref(NULL, &fctx->user); if (chan->user) { iounmap(chan->user); chan->user = NULL; @@ -192,7 +185,7 @@ nvc0_fifo_init(struct drm_device *dev, int engine) } nv_mask(dev, 0x002200, 0x00000001, 0x00000001); - nv_wr32(dev, 0x002254, 0x10000000 | priv->user_vma.offset >> 12); + nv_wr32(dev, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ nv_wr32(dev, 0x002100, 0xffffffff); @@ -429,7 +422,9 @@ nvc0_fifo_destroy(struct drm_device *dev, int engine) struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct drm_nouveau_private *dev_priv = dev->dev_private; - nouveau_vm_put(&priv->user_vma); + nouveau_vm_put(&priv->user.bar); + nouveau_gpuobj_ref(NULL, &priv->user.mem); + nouveau_gpuobj_ref(NULL, &priv->playlist[1]); nouveau_gpuobj_ref(NULL, &priv->playlist[0]); @@ -464,11 +459,18 @@ nvc0_fifo_create(struct drm_device *dev) if (ret) goto error; - ret = nouveau_vm_get(dev_priv->bar1_vm, priv->base.channels * 0x1000, - 12, NV_MEM_ACCESS_RW, &priv->user_vma); + ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4096, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); if (ret) goto error; + ret = nouveau_vm_get(dev_priv->bar1_vm, priv->user.mem->size, + 12, NV_MEM_ACCESS_RW, &priv->user.bar); + if (ret) + goto error; + + nouveau_vm_map(&priv->user.bar, *(struct nouveau_mem **)priv->user.mem->node); + nouveau_irq_register(dev, 8, nvc0_fifo_isr); error: if (ret) -- cgit v1.1 From 18c9b959fd8ea6f3602efbedad788f53e305e6f1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2012 17:05:35 +1000 Subject: drm/nouveau/gpuobj: create wrapper functions for mapping gpuobj into vm/bar Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 8 +++----- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 8f0e63e..f60221d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -422,7 +422,7 @@ nvc0_fifo_destroy(struct drm_device *dev, int engine) struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct drm_nouveau_private *dev_priv = dev->dev_private; - nouveau_vm_put(&priv->user.bar); + nouveau_gpuobj_unmap(&priv->user.bar); nouveau_gpuobj_ref(NULL, &priv->user.mem); nouveau_gpuobj_ref(NULL, &priv->playlist[1]); @@ -464,13 +464,11 @@ nvc0_fifo_create(struct drm_device *dev) if (ret) goto error; - ret = nouveau_vm_get(dev_priv->bar1_vm, priv->user.mem->size, - 12, NV_MEM_ACCESS_RW, &priv->user.bar); + ret = nouveau_gpuobj_map_bar(priv->user.mem, NV_MEM_ACCESS_RW, + &priv->user.bar); if (ret) goto error; - nouveau_vm_map(&priv->user.bar, *(struct nouveau_mem **)priv->user.mem->node); - nouveau_irq_register(dev, 8, nvc0_fifo_isr); error: if (ret) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 829959f..1c06bde1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -402,7 +402,7 @@ nve0_fifo_destroy(struct drm_device *dev, int engine) struct nve0_fifo_priv *priv = nv_engine(dev, engine); int i; - nouveau_vm_put(&priv->user.bar); + nouveau_gpuobj_unmap(&priv->user.bar); nouveau_gpuobj_ref(NULL, &priv->user.mem); for (i = 0; i < NVE0_FIFO_ENGINE_NUM; i++) { @@ -438,13 +438,11 @@ nve0_fifo_create(struct drm_device *dev) if (ret) goto error; - ret = nouveau_vm_get(dev_priv->bar1_vm, priv->user.mem->size, - 12, NV_MEM_ACCESS_RW, &priv->user.bar); + ret = nouveau_gpuobj_map_bar(priv->user.mem, NV_MEM_ACCESS_RW, + &priv->user.bar); if (ret) goto error; - nouveau_vm_map(&priv->user.bar, *(struct nouveau_mem **)priv->user.mem->node); - nouveau_irq_register(dev, 8, nve0_fifo_isr); error: if (ret) -- cgit v1.1 From 73a60c0d218a292f8ef29d3467726ff26ed366fc Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2012 17:21:22 +1000 Subject: drm/nouveau/gpuobj: remove flags for vm-mappings Having GPUOBJ and VM intertwined like this makes it *really* hard to continue porting to the new driver architecture, split it out in favour of requiring explit maps be the caller. It's more flexible and obvious this way anyway... Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 36 +++++++---- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 71 +++++++++++++++------- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 5 ++ drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 70 +++++++++++++++------ drivers/gpu/drm/nouveau/core/engine/graph/nve0.h | 5 ++ drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 18 ------ 6 files changed, 135 insertions(+), 70 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index 90a069b..926f21c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -38,27 +38,38 @@ struct nvc0_copy_engine { u32 ctx; }; +struct nvc0_copy_chan { + struct nouveau_gpuobj *mem; + struct nouveau_vma vma; +}; + static int nvc0_copy_context_new(struct nouveau_channel *chan, int engine) { struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); + struct nvc0_copy_chan *cctx; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *ctx = NULL; int ret; - ret = nouveau_gpuobj_new(dev, chan, 256, 256, - NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER | - NVOBJ_FLAG_ZERO_ALLOC, &ctx); + cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL); + if (!cctx) + return -ENOMEM; + + ret = nouveau_gpuobj_new(dev, NULL, 256, 256, + NVOBJ_FLAG_ZERO_ALLOC, &cctx->mem); if (ret) return ret; - nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst)); - nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst)); - dev_priv->engine.instmem.flush(dev); + ret = nouveau_gpuobj_map_vm(cctx->mem, NV_MEM_ACCESS_RW, chan->vm, + &cctx->vma); + if (ret) + return ret; - chan->engctx[engine] = ctx; + nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(cctx->vma.offset)); + nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(cctx->vma.offset)); + dev_priv->engine.instmem.flush(dev); return 0; } @@ -73,7 +84,7 @@ static void nvc0_copy_context_del(struct nouveau_channel *chan, int engine) { struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); - struct nouveau_gpuobj *ctx = chan->engctx[engine]; + struct nvc0_copy_chan *cctx = chan->engctx[engine]; struct drm_device *dev = chan->dev; u32 inst; @@ -93,9 +104,12 @@ nvc0_copy_context_del(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000); nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000); - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = ctx; + nouveau_gpuobj_unmap(&cctx->vma); + nouveau_gpuobj_ref(NULL, &cctx->mem); + + kfree(cctx); + chan->engctx[engine] = NULL; } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 8f515dc..8d6eb89 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -161,50 +161,68 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; int i = 0, gpc, tp, ret; - ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, - &grch->unk408004); + ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, 0, &grch->unk408004); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM, - &grch->unk40800c); + ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->unk408004_vma); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096, - NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER, + ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c); + if (ret) + return ret; + + ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->unk40800c_vma); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0, &grch->unk418810); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM, - &grch->mmio); + ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW, + chan->vm, &grch->unk418810_vma); if (ret) return ret; + ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio); + if (ret) + return ret; + + ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->mmio_vma); + if (ret) + return ret; nv_wo32(grch->mmio, i++ * 4, 0x00408004); - nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, grch->unk408004_vma.offset >> 8); nv_wo32(grch->mmio, i++ * 4, 0x00408008); nv_wo32(grch->mmio, i++ * 4, 0x80000018); nv_wo32(grch->mmio, i++ * 4, 0x0040800c); - nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, grch->unk40800c_vma.offset >> 8); nv_wo32(grch->mmio, i++ * 4, 0x00408010); nv_wo32(grch->mmio, i++ * 4, 0x80000000); nv_wo32(grch->mmio, i++ * 4, 0x00418810); - nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12); + nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810_vma.offset >> 12); nv_wo32(grch->mmio, i++ * 4, 0x00419848); - nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12); + nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810_vma.offset >> 12); nv_wo32(grch->mmio, i++ * 4, 0x00419004); - nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, grch->unk40800c_vma.offset >> 8); nv_wo32(grch->mmio, i++ * 4, 0x00419008); nv_wo32(grch->mmio, i++ * 4, 0x00000000); nv_wo32(grch->mmio, i++ * 4, 0x00418808); - nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, grch->unk408004_vma.offset >> 8); nv_wo32(grch->mmio, i++ * 4, 0x0041880c); nv_wo32(grch->mmio, i++ * 4, 0x80000018); @@ -262,19 +280,25 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) return -ENOMEM; chan->engctx[NVOBJ_ENGINE_GR] = grch; - ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256, - NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, + ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 0, &grch->grctx); if (ret) goto error; + + ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->grctx_vma); + if (ret) + return ret; + grctx = grch->grctx; ret = nvc0_graph_create_context_mmio_list(chan); if (ret) goto error; - nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4); - nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst)); + 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)); pinstmem->flush(dev); if (!priv->grctx_vals) { @@ -288,13 +312,13 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) if (!nouveau_ctxfw) { nv_wo32(grctx, 0x00, grch->mmio_nr); - nv_wo32(grctx, 0x04, grch->mmio->linst >> 8); + nv_wo32(grctx, 0x04, grch->mmio_vma.offset >> 8); } else { nv_wo32(grctx, 0xf4, 0); nv_wo32(grctx, 0xf8, 0); nv_wo32(grctx, 0x10, grch->mmio_nr); - nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst)); - nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst)); + 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); @@ -313,6 +337,11 @@ nvc0_graph_context_del(struct nouveau_channel *chan, int engine) { struct nvc0_graph_chan *grch = chan->engctx[engine]; + nouveau_gpuobj_unmap(&grch->mmio_vma); + nouveau_gpuobj_unmap(&grch->unk418810_vma); + nouveau_gpuobj_unmap(&grch->unk40800c_vma); + nouveau_gpuobj_unmap(&grch->unk408004_vma); + nouveau_gpuobj_unmap(&grch->grctx_vma); nouveau_gpuobj_ref(NULL, &grch->mmio); nouveau_gpuobj_ref(NULL, &grch->unk418810); nouveau_gpuobj_ref(NULL, &grch->unk40800c); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 91d44ea6..ffeb4a0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -62,10 +62,15 @@ struct nvc0_graph_priv { struct nvc0_graph_chan { struct nouveau_gpuobj *grctx; + struct nouveau_vma grctx_vma; struct nouveau_gpuobj *unk408004; /* 0x418810 too */ + struct nouveau_vma unk408004_vma; struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ + struct nouveau_vma unk40800c_vma; struct nouveau_gpuobj *unk418810; /* 0x419848 too */ + struct nouveau_vma unk418810_vma; struct nouveau_gpuobj *mmio; + struct nouveau_vma mmio_vma; int mmio_nr; }; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index a8364b1..5f671a2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -137,24 +137,43 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) int gpc; int ret; - ret = nouveau_gpuobj_new(dev, chan, 0x3000, 256, NVOBJ_FLAG_VM, - &grch->unk408004); + ret = nouveau_gpuobj_new(dev, NULL, 0x3000, 256, 0, &grch->unk408004); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM, - &grch->unk40800c); + ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->unk408004_vma); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096, - NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER, + ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c); + if (ret) + return ret; + + ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->unk40800c_vma); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0, &grch->unk418810); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM, - &grch->mmio); + ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW, + chan->vm, &grch->unk418810_vma); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio); + if (ret) + return ret; + + ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->mmio_vma); if (ret) return ret; @@ -163,18 +182,18 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 4, (v)); \ grch->mmio_nr++; \ } while (0) - mmio(0x40800c, grch->unk40800c->linst >> 8); + mmio(0x40800c, grch->unk40800c_vma.offset >> 8); mmio(0x408010, 0x80000000); - mmio(0x419004, grch->unk40800c->linst >> 8); + mmio(0x419004, grch->unk40800c_vma.offset >> 8); mmio(0x419008, 0x00000000); mmio(0x4064cc, 0x80000000); - mmio(0x408004, grch->unk408004->linst >> 8); + mmio(0x408004, grch->unk408004_vma.offset >> 8); mmio(0x408008, 0x80000030); - mmio(0x418808, grch->unk408004->linst >> 8); + mmio(0x418808, grch->unk408004_vma.offset >> 8); mmio(0x41880c, 0x80000030); mmio(0x4064c8, 0x01800600); - mmio(0x418810, 0x80000000 | grch->unk418810->linst >> 12); - mmio(0x419848, 0x10000000 | grch->unk418810->linst >> 12); + mmio(0x418810, 0x80000000 | grch->unk418810_vma.offset >> 12); + mmio(0x419848, 0x10000000 | grch->unk418810_vma.offset >> 12); mmio(0x405830, 0x02180648); mmio(0x4064c4, 0x0192ffff); @@ -214,19 +233,25 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) return -ENOMEM; chan->engctx[NVOBJ_ENGINE_GR] = grch; - ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256, - NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, + ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 0, &grch->grctx); if (ret) goto error; + + ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, chan->vm, + &grch->grctx_vma); + if (ret) + return ret; + grctx = grch->grctx; ret = nve0_graph_create_context_mmio_list(chan); if (ret) goto error; - nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4); - nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst)); + 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)); pinstmem->flush(dev); if (!priv->grctx_vals) { @@ -240,8 +265,8 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(grctx, 0xf4, 0); nv_wo32(grctx, 0xf8, 0); nv_wo32(grctx, 0x10, grch->mmio_nr); - nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst)); - nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst)); + 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); @@ -260,6 +285,11 @@ nve0_graph_context_del(struct nouveau_channel *chan, int engine) { struct nve0_graph_chan *grch = chan->engctx[engine]; + nouveau_gpuobj_unmap(&grch->mmio_vma); + nouveau_gpuobj_unmap(&grch->unk418810_vma); + nouveau_gpuobj_unmap(&grch->unk40800c_vma); + nouveau_gpuobj_unmap(&grch->unk408004_vma); + nouveau_gpuobj_unmap(&grch->grctx_vma); nouveau_gpuobj_ref(NULL, &grch->mmio); nouveau_gpuobj_ref(NULL, &grch->unk418810); nouveau_gpuobj_ref(NULL, &grch->unk40800c); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h index 2ba7044..b136cd5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h @@ -62,10 +62,15 @@ struct nve0_graph_priv { struct nve0_graph_chan { struct nouveau_gpuobj *grctx; + struct nouveau_vma grctx_vma; struct nouveau_gpuobj *unk408004; /* 0x418810 too */ + struct nouveau_vma unk408004_vma; struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ + struct nouveau_vma unk40800c_vma; struct nouveau_gpuobj *unk418810; /* 0x419848 too */ + struct nouveau_vma unk418810_vma; struct nouveau_gpuobj *mmio; + struct nouveau_vma mmio_vma; int mmio_nr; }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 24d077a..be7344d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -328,24 +328,6 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, } gpuobj->vinst = node->vram->offset; - - if (gpuobj->flags & NVOBJ_FLAG_VM) { - u32 flags = NV_MEM_ACCESS_RW; - if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER)) - flags |= NV_MEM_ACCESS_SYS; - - ret = nouveau_vm_get(chan->vm, size, 12, flags, - &node->chan_vma); - if (ret) { - nvfb_vram_put(dev, &node->vram); - kfree(node); - return ret; - } - - nouveau_vm_map(&node->chan_vma, node->vram); - gpuobj->linst = node->chan_vma.offset; - } - gpuobj->size = size; gpuobj->node = node; return 0; -- cgit v1.1 From 092599da308bf56b96c849ecdd315b8a1a13ca52 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 14 Jul 2012 10:48:12 +1000 Subject: drm/nv50/instmem: remove use of nouveau_gpuobj_new_fake() Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index be7344d..f88530b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -53,7 +53,6 @@ nv50_channel_del(struct nouveau_channel **pchan) if (!chan) return; - nouveau_gpuobj_ref(NULL, &chan->ramfc); nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); nouveau_gpuobj_ref(NULL, &chan->vm_pd); if (drm_mm_initialized(&chan->ramin_heap)) @@ -68,7 +67,6 @@ nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, { struct drm_nouveau_private *dev_priv = dev->dev_private; u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; - u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; struct nouveau_channel *chan; int ret, i; @@ -83,17 +81,13 @@ nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, return ret; } - ret = drm_mm_init(&chan->ramin_heap, 0x6000, chan->ramin->size - 0x6000); + ret = drm_mm_init(&chan->ramin_heap, pgd, chan->ramin->size - pgd); if (ret) { nv50_channel_del(&chan); return ret; } - ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : - chan->ramin->pinst + pgd, - chan->ramin->vinst + pgd, - 0x4000, NVOBJ_FLAG_ZERO_ALLOC, - &chan->vm_pd); + ret = nouveau_gpuobj_new(dev, chan, 0x4000, 0, 0, &chan->vm_pd); if (ret) { nv50_channel_del(&chan); return ret; @@ -110,15 +104,6 @@ nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, return ret; } - ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : - chan->ramin->pinst + fc, - chan->ramin->vinst + fc, 0x100, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramfc); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - *pchan = chan; return 0; } -- cgit v1.1 From 3863c9bc887e9638a9d905d55f6038641ece78d6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 14 Jul 2012 19:09:17 +1000 Subject: drm/nouveau/instmem: completely new implementation, as a subdev module v2 (Ben Skeggs): - some fixes for 64KiB PAGE_SIZE - fix porting issues in (currently unused) nv41/nv44 pciegart code Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/ramht.c | 15 +- drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c | 1 - drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 12 +- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 8 +- drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 17 +- drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 12 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 15 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 9 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 15 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 15 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 22 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 25 +- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 16 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 16 +- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 8 +- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 10 +- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 20 +- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 45 +- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 40 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 8 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c | 10 +- drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | 1 - drivers/gpu/drm/nouveau/core/engine/vp/nv84.c | 1 - drivers/gpu/drm/nouveau/core/include/subdev/bar.h | 55 +++ drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 + .../gpu/drm/nouveau/core/include/subdev/instmem.h | 74 ++++ drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 88 ++-- drivers/gpu/drm/nouveau/core/subdev/bar/base.c | 135 ++++++ drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c | 263 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 215 ++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 6 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 18 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 10 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 12 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 34 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 45 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 27 ++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c | 46 +-- drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | 135 ++++++ drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 254 +++++++----- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h | 21 + drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | 220 +++++----- drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c | 458 ++++++--------------- drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c | 222 ---------- drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 149 +++---- drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c | 150 +++++++ drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h | 13 + drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 149 +++++++ drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 257 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 108 +++-- drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 111 +++-- 52 files changed, 2437 insertions(+), 1189 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bar.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/instmem.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bar/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/base.c delete mode 100644 drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c index 59c1619..5c22864 100644 --- a/drivers/gpu/drm/nouveau/core/core/ramht.c +++ b/drivers/gpu/drm/nouveau/core/core/ramht.c @@ -86,7 +86,6 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; struct nouveau_ramht_entry *entry; struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; unsigned long flags; @@ -104,21 +103,21 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); if (dev_priv->card_type < NV_40) { - ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->pinst >> 4) | + ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->addr >> 4) | (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); } else if (dev_priv->card_type < NV_50) { - ctx = (gpuobj->pinst >> 4) | + ctx = (gpuobj->addr >> 4) | (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); } else { if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { - ctx = (gpuobj->cinst << 10) | + ctx = (gpuobj->node->offset << 10) | (chan->id << 28) | chan->id; /* HASH_TAG */ } else { - ctx = (gpuobj->cinst >> 4) | + ctx = (gpuobj->node->offset >> 4) | ((gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); } @@ -137,7 +136,7 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, nv_wo32(ramht, co + 4, ctx); spin_unlock_irqrestore(&chan->ramht->lock, flags); - instmem->flush(dev); + nvimem_flush(dev); return 0; } NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", @@ -184,8 +183,6 @@ static void nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; unsigned long flags; u32 co, ho; @@ -201,7 +198,7 @@ nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) chan->id, co, handle, nv_ro32(ramht, co + 4)); nv_wo32(ramht, co + 0, 0x00000000); nv_wo32(ramht, co + 4, 0x00000000); - instmem->flush(dev); + nvimem_flush(dev); goto out; } diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c index db3b573..4b80931 100644 --- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include /*XXX: This stub is currently used on NV98+ also, as soon as this becomes diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index fec5246..9150c5e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -26,7 +26,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include #include "fuc/nva3.fuc.h" @@ -38,7 +37,6 @@ static int nva3_copy_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 *ctx = NULL; int ret; @@ -51,14 +49,14 @@ nva3_copy_context_new(struct nouveau_channel *chan, int engine) return ret; nv_wo32(ramin, 0xc0, 0x00190000); - nv_wo32(ramin, 0xc4, ctx->vinst + ctx->size - 1); - nv_wo32(ramin, 0xc8, ctx->vinst); + nv_wo32(ramin, 0xc4, ctx->addr + ctx->size - 1); + nv_wo32(ramin, 0xc8, ctx->addr); nv_wo32(ramin, 0xcc, 0x00000000); nv_wo32(ramin, 0xd0, 0x00000000); nv_wo32(ramin, 0xd4, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->engctx[engine] = ctx; return 0; } @@ -84,7 +82,7 @@ nva3_copy_context_del(struct nouveau_channel *chan, int engine) for (i = 0xc0; i <= 0xd4; i += 4) nv_wo32(chan->ramin, i, 0x00000000); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); nouveau_gpuobj_ref(NULL, &ctx); chan->engctx[engine] = ctx; } diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index 926f21c..f39de5a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -26,7 +26,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include #include "fuc/nvc0.fuc.h" @@ -49,7 +48,6 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine) struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); struct nvc0_copy_chan *cctx; struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *ramin = chan->ramin; int ret; @@ -62,14 +60,14 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(cctx->mem, NV_MEM_ACCESS_RW, chan->vm, + ret = nouveau_gpuobj_map_vm(cctx->mem, chan->vm, NV_MEM_ACCESS_RW, &cctx->vma); if (ret) return ret; nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(cctx->vma.offset)); nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(cctx->vma.offset)); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); return 0; } @@ -88,7 +86,7 @@ nvc0_copy_context_del(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; u32 inst; - inst = (chan->ramin->vinst >> 12); + inst = (chan->ramin->addr >> 12); inst |= 0x40000000; /* disable fifo access */ diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 3881389..63051ab 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include struct nv84_crypt_engine { @@ -36,7 +35,6 @@ static int nv84_crypt_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 *ctx; int ret; @@ -49,14 +47,14 @@ nv84_crypt_context_new(struct nouveau_channel *chan, int engine) return ret; nv_wo32(ramin, 0xa0, 0x00190000); - nv_wo32(ramin, 0xa4, ctx->vinst + ctx->size - 1); - nv_wo32(ramin, 0xa8, ctx->vinst); + nv_wo32(ramin, 0xa4, ctx->addr + ctx->size - 1); + nv_wo32(ramin, 0xa8, ctx->addr); nv_wo32(ramin, 0xac, 0); nv_wo32(ramin, 0xb0, 0); nv_wo32(ramin, 0xb4, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->engctx[engine] = ctx; return 0; } @@ -68,7 +66,7 @@ nv84_crypt_context_del(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; u32 inst; - inst = (chan->ramin->vinst >> 12); + inst = (chan->ramin->addr >> 12); inst |= 0x80000000; /* mark context as invalid if still on the hardware, not @@ -84,7 +82,7 @@ nv84_crypt_context_del(struct nouveau_channel *chan, int engine) nouveau_gpuobj_ref(NULL, &ctx); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; } @@ -93,7 +91,6 @@ nv84_crypt_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *obj = NULL; int ret; @@ -104,7 +101,7 @@ nv84_crypt_object_new(struct nouveau_channel *chan, int engine, obj->class = class; nv_wo32(obj, 0x00, class); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nouveau_ramht_insert(chan, handle, obj); nouveau_gpuobj_ref(NULL, &obj); diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index 563f60d..c9adc1b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -26,7 +26,6 @@ #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include #include "fuc/nv98.fuc.h" @@ -43,7 +42,6 @@ static int nv98_crypt_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv98_crypt_priv *priv = nv_engine(dev, engine); struct nv98_crypt_chan *cctx; int ret; @@ -52,7 +50,7 @@ nv98_crypt_context_new(struct nouveau_channel *chan, int engine) if (!cctx) return -ENOMEM; - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &cctx->mem); @@ -60,12 +58,12 @@ nv98_crypt_context_new(struct nouveau_channel *chan, int engine) goto error; nv_wo32(chan->ramin, 0xa0, 0x00190000); - nv_wo32(chan->ramin, 0xa4, cctx->mem->vinst + cctx->mem->size - 1); - nv_wo32(chan->ramin, 0xa8, cctx->mem->vinst); + nv_wo32(chan->ramin, 0xa4, cctx->mem->addr + cctx->mem->size - 1); + nv_wo32(chan->ramin, 0xa8, cctx->mem->addr); nv_wo32(chan->ramin, 0xac, 0x00000000); nv_wo32(chan->ramin, 0xb0, 0x00000000); nv_wo32(chan->ramin, 0xb4, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); error: if (ret) @@ -84,7 +82,7 @@ nv98_crypt_context_del(struct nouveau_channel *chan, int engine) nouveau_gpuobj_ref(NULL, &cctx->mem); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; kfree(cctx); } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index ba76cf0..6ab7eb0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -32,8 +32,6 @@ #include #include "nouveau_software.h" -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -120,7 +118,7 @@ nv04_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -203,9 +201,9 @@ nv04_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->pinst >> 8); + (dev_priv->ramht->gpuobj->addr >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); @@ -486,15 +484,14 @@ int nv04_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv04_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv04_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 0da287c..2d38fa8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -31,8 +31,6 @@ #include "nouveau_util.h" #include -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -91,7 +89,7 @@ nv10_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -115,15 +113,14 @@ int nv10_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv10_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv04_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 99b88e0..2f700a15e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -31,8 +31,6 @@ #include "nouveau_util.h" #include -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -96,7 +94,7 @@ nv17_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -131,10 +129,10 @@ nv17_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); + (dev_priv->ramht->gpuobj->addr >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 | - priv->ramfc->pinst >> 8); + priv->ramfc->addr >> 8); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); @@ -157,15 +155,14 @@ int nv17_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv17_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv17_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index df53b9f..65a670f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -31,8 +31,6 @@ #include "nouveau_util.h" #include -#include - static struct ramfc_desc { unsigned bits:6; unsigned ctxs:5; @@ -104,7 +102,7 @@ nv40_fifo_context_new(struct nouveau_channel *chan, int engine) /* initialise default fifo context */ nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->pinst >> 4); + nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); nv_wo32(priv->ramfc, fctx->ramfc + 0x18, 0x30000000 | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | @@ -144,8 +142,8 @@ nv40_fifo_init(struct drm_device *dev, int engine) nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->pinst >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->pinst >> 8); + (dev_priv->ramht->gpuobj->addr >> 8)); + nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); switch (dev_priv->chipset) { case 0x47: @@ -163,7 +161,7 @@ nv40_fifo_init(struct drm_device *dev, int engine) default: nv_wr32(dev, 0x002230, 0x00000000); nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + - priv->ramfc->pinst) >> 16) | + priv->ramfc->addr) >> 16) | 0x00030000); break; } @@ -189,15 +187,14 @@ int nv40_fifo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *imem = dev_priv->engine.instmem.priv; struct nv40_fifo_priv *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - nouveau_gpuobj_ref(imem->ramro, &priv->ramro); - nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); + nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); priv->base.base.destroy = nv04_fifo_destroy; priv->base.base.init = nv40_fifo_init; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 2309871..7b5b159 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -29,7 +29,6 @@ #include "nouveau_drv.h" #include #include -#include struct nv50_fifo_priv { struct nouveau_fifo_priv base; @@ -45,7 +44,6 @@ void nv50_fifo_playlist_update(struct drm_device *dev) { struct nv50_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *cur; int i, p; @@ -57,9 +55,9 @@ nv50_fifo_playlist_update(struct drm_device *dev) nv_wo32(cur, p++ * 4, i); } - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - nv_wr32(dev, 0x0032f4, cur->vinst >> 12); + nv_wr32(dev, 0x0032f4, cur->addr >> 12); nv_wr32(dev, 0x0032ec, p); nv_wr32(dev, 0x002500, 0x00000101); } @@ -72,14 +70,14 @@ nv50_fifo_context_new(struct nouveau_channel *chan, int engine) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; - u64 instance = chan->ramin->vinst >> 12; + u64 instance = chan->ramin->addr >> 12; unsigned long flags; int ret = 0, i; fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); if (!fctx) return -ENOMEM; - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV50_USER(chan->id), PAGE_SIZE); @@ -93,7 +91,7 @@ nv50_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0x3c, 0x403f6078); nv_wo32(chan->ramin, 0x40, 0x00000000); nv_wo32(chan->ramin, 0x44, 0x01003fff); - nv_wo32(chan->ramin, 0x48, chan->pushbuf->cinst >> 4); + nv_wo32(chan->ramin, 0x48, chan->pushbuf->node->offset >> 4); nv_wo32(chan->ramin, 0x50, lower_32_bits(ib_offset)); nv_wo32(chan->ramin, 0x54, upper_32_bits(ib_offset) | drm_order(chan->dma.ib_max + 1) << 16); @@ -102,9 +100,9 @@ nv50_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0x7c, 0x30000001); nv_wo32(chan->ramin, 0x80, ((chan->ramht->bits - 9) << 27) | (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->cinst >> 4)); + (chan->ramht->gpuobj->node->offset >> 4)); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); @@ -141,7 +139,7 @@ nv50_fifo_kickoff(struct nouveau_channel *chan) me = nv_mask(dev, 0x00b860, 0x00000001, 0x00000001); /* do the kickoff... */ - nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); done = false; @@ -177,7 +175,7 @@ nv50_fifo_context_del(struct nouveau_channel *chan, int engine) chan->user = NULL; } - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; kfree(fctx); } @@ -200,7 +198,7 @@ nv50_fifo_init(struct drm_device *dev, int engine) for (i = 0; i < 128; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan && chan->engctx[engine]) - instance = 0x80000000 | chan->ramin->vinst >> 12; + instance = 0x80000000 | chan->ramin->addr >> 12; else instance = 0x00000000; nv_wr32(dev, 0x002600 + (i * 4), instance); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index f505d1e..63a4941 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -29,7 +29,6 @@ #include "nouveau_drv.h" #include #include -#include struct nv84_fifo_priv { struct nouveau_fifo_priv base; @@ -58,7 +57,7 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); if (!fctx) return -ENOMEM; - atomic_inc(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, 1); chan->user = ioremap(pci_resource_start(dev->pdev, 0) + NV50_USER(chan->id), PAGE_SIZE); @@ -72,7 +71,7 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) if (ret) goto error; - instance = fctx->ramfc->vinst >> 8; + instance = fctx->ramfc->addr >> 8; ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, 0, &fctx->cache); if (ret) @@ -81,7 +80,7 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(fctx->ramfc, 0x3c, 0x403f6078); nv_wo32(fctx->ramfc, 0x40, 0x00000000); nv_wo32(fctx->ramfc, 0x44, 0x01003fff); - nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->cinst >> 4); + nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->node->offset >> 4); nv_wo32(fctx->ramfc, 0x50, lower_32_bits(ib_offset)); nv_wo32(fctx->ramfc, 0x54, upper_32_bits(ib_offset) | drm_order(chan->dma.ib_max + 1) << 16); @@ -90,14 +89,14 @@ nv84_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(fctx->ramfc, 0x7c, 0x30000001); nv_wo32(fctx->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->cinst >> 4)); - nv_wo32(fctx->ramfc, 0x88, fctx->cache->vinst >> 10); - nv_wo32(fctx->ramfc, 0x98, chan->ramin->vinst >> 12); + (chan->ramht->gpuobj->node->offset >> 4)); + nv_wo32(fctx->ramfc, 0x88, fctx->cache->addr >> 10); + nv_wo32(fctx->ramfc, 0x98, chan->ramin->addr >> 12); nv_wo32(chan->ramin, 0x00, chan->id); - nv_wo32(chan->ramin, 0x04, fctx->ramfc->vinst >> 8); + nv_wo32(chan->ramin, 0x04, fctx->ramfc->addr >> 8); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); @@ -127,7 +126,7 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine) save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); /* tell any engines on this channel to unload their contexts */ - nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); @@ -145,7 +144,7 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine) nouveau_gpuobj_ref(NULL, &fctx->ramfc); nouveau_gpuobj_ref(NULL, &fctx->cache); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); chan->engctx[engine] = NULL; kfree(fctx); } @@ -169,7 +168,7 @@ nv84_fifo_init(struct drm_device *dev, int engine) for (i = 0; i < 128; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan && (fctx = chan->engctx[engine])) - instance = 0x80000000 | fctx->ramfc->vinst >> 8; + instance = 0x80000000 | fctx->ramfc->addr >> 8; else instance = 0x00000000; nv_wr32(dev, 0x002600 + (i * 4), instance); @@ -200,7 +199,7 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) for (i = 0; i < priv->base.channels; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan) - nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12); + nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { NV_INFO(dev, "PFIFO: channel %d unload timeout\n", i); return -EBUSY; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index f60221d..6535a99 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -48,8 +48,6 @@ struct nvc0_fifo_chan { static void nvc0_fifo_playlist_update(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct nouveau_gpuobj *cur; int i, p; @@ -64,9 +62,9 @@ nvc0_fifo_playlist_update(struct drm_device *dev) nv_wo32(cur, p + 4, 0x00000004); p += 8; } - pinstmem->flush(dev); + nvimem_flush(dev); - nv_wr32(dev, 0x002270, cur->vinst >> 12); + nv_wr32(dev, 0x002270, cur->addr >> 12); nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) NV_ERROR(dev, "PFIFO - playlist update failed\n"); @@ -76,11 +74,9 @@ static int nvc0_fifo_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_fifo_priv *priv = nv_engine(dev, engine); struct nvc0_fifo_chan *fctx; - u64 usermem = priv->user.mem->vinst + chan->id * 0x1000; + u64 usermem = priv->user.mem->addr + chan->id * 0x1000; u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; int ret, i; @@ -115,10 +111,10 @@ nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0xb8, 0xf8000000); nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - pinstmem->flush(dev); + nvimem_flush(dev); nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); nvc0_fifo_playlist_update(dev); @@ -198,7 +194,7 @@ nvc0_fifo_init(struct drm_device *dev, int engine) continue; nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001); } nvc0_fifo_playlist_update(dev); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 1c06bde1..461fbf6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -55,8 +55,6 @@ struct nve0_fifo_chan { static void nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); struct nve0_fifo_engine *peng = &priv->engine[engine]; struct nouveau_gpuobj *cur; @@ -84,9 +82,9 @@ nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) nv_wo32(cur, p + 4, 0x00000000); p += 8; } - pinstmem->flush(dev); + nvimem_flush(dev); - nv_wr32(dev, 0x002270, cur->vinst >> 12); + nv_wr32(dev, 0x002270, cur->addr >> 12); nv_wr32(dev, 0x002274, (engine << 20) | (p >> 3)); if (!nv_wait(dev, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) NV_ERROR(dev, "PFIFO: playlist %d update timeout\n", engine); @@ -96,11 +94,9 @@ static int nve0_fifo_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nve0_fifo_priv *priv = nv_engine(dev, engine); struct nve0_fifo_chan *fctx; - u64 usermem = priv->user.mem->vinst + chan->id * 512; + u64 usermem = priv->user.mem->addr + chan->id * 512; u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; int ret = 0, i; @@ -135,10 +131,10 @@ nve0_fifo_context_new(struct nouveau_channel *chan, int engine) nv_wo32(chan->ramin, 0xe8, chan->id); nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - pinstmem->flush(dev); + nvimem_flush(dev); nv_wr32(dev, 0x800000 + (chan->id * 8), 0x80000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); nve0_fifo_playlist_update(dev, fctx->engine); nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); @@ -207,7 +203,7 @@ nve0_fifo_init(struct drm_device *dev, int engine) continue; nv_wr32(dev, 0x800000 + (i * 8), 0x80000000 | - (chan->ramin->vinst >> 12)); + (chan->ramin->addr >> 12)); nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); nve0_fifo_playlist_update(dev, fctx->engine); nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index dd31156..0d874b8b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -52,7 +52,7 @@ nv20_graph_unload_context(struct drm_device *dev) return 0; grctx = chan->engctx[NVOBJ_ENGINE_GR]; - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->pinst >> 4); + 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); @@ -437,7 +437,7 @@ nv20_graph_context_new(struct nouveau_channel *chan, int engine) /* CTX_USER */ nv_wo32(grctx, pgraph->grctx_user, (chan->id << 24) | 0x1); - nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->pinst >> 4); + nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->addr >> 4); chan->engctx[engine] = grctx; return 0; } @@ -505,7 +505,7 @@ nv20_graph_init(struct drm_device *dev, int engine) 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->pinst >> 4); + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->addr >> 4); nv20_graph_rdi(dev); @@ -592,7 +592,7 @@ nv30_graph_init(struct drm_device *dev, int engine) 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->pinst >> 4); + 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); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index ab3af6d..466d215 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -52,16 +52,16 @@ nv40_graph_context_new(struct nouveau_channel *chan, int engine) /* Initialise default context values */ nv40_grctx_fill(dev, grctx); - nv_wo32(grctx, 0, grctx->vinst); + 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->vinst >> 4); + 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->vinst >> 4); + nv_wr32(dev, 0x0032e0, grctx->addr >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -75,7 +75,7 @@ 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->pinst >> 4); + u32 inst = 0x01000000 | (grctx->addr >> 4); unsigned long flags; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); @@ -357,7 +357,7 @@ nv40_graph_isr_chid(struct drm_device *dev, u32 inst) continue; grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; - if (grctx && grctx->pinst == inst) + if (grctx && grctx->addr == inst) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index b2e9ad4..28932c4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -30,7 +30,6 @@ #include #include #include "nouveau_dma.h" -#include #include "nv50_evo.h" struct nv50_graph_engine { @@ -155,18 +154,18 @@ nv50_graph_context_new(struct nouveau_channel *chan, int engine) hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; nv_wo32(ramin, hdr + 0x00, 0x00190002); - nv_wo32(ramin, hdr + 0x04, grctx->vinst + grctx->size - 1); - nv_wo32(ramin, hdr + 0x08, grctx->vinst); + 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); nv50_grctx_fill(dev, grctx); - nv_wo32(grctx, 0x00000, chan->ramin->vinst >> 12); + nv_wo32(grctx, 0x00000, chan->ramin->addr >> 12); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_inc(&chan->vm->engref[NVOBJ_ENGINE_GR]); + nvvm_engref(chan->vm, engine, 1); chan->engctx[NVOBJ_ENGINE_GR] = grctx; return 0; } @@ -181,9 +180,9 @@ nv50_graph_context_del(struct nouveau_channel *chan, int engine) for (i = hdr; i < hdr + 24; i += 4) nv_wo32(chan->ramin, i, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); - atomic_dec(&chan->vm->engref[engine]); + nvvm_engref(chan->vm, engine, -1); nouveau_gpuobj_ref(NULL, &grctx); chan->engctx[engine] = NULL; } @@ -193,7 +192,6 @@ nv50_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *obj = NULL; int ret; @@ -207,7 +205,7 @@ nv50_graph_object_new(struct nouveau_channel *chan, int engine, nv_wo32(obj, 0x04, 0x00000000); nv_wo32(obj, 0x08, 0x00000000); nv_wo32(obj, 0x0c, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nouveau_ramht_insert(chan, handle, obj); nouveau_gpuobj_ref(NULL, &obj); @@ -723,7 +721,7 @@ nv50_graph_isr_chid(struct drm_device *dev, u64 inst) if (!chan || !chan->ramin) continue; - if (inst == chan->ramin->vinst) + if (inst == chan->ramin->addr) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 8d6eb89..b741b03 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -65,7 +65,7 @@ nvc0_graph_load_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); @@ -90,7 +90,6 @@ nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) static int nvc0_graph_construct_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; @@ -103,7 +102,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) if (!nouveau_ctxfw) { nv_wr32(dev, 0x409840, 0x80000000); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000001); if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); @@ -118,7 +117,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) nv_wo32(grch->grctx, 0x20, 0); nv_wo32(grch->grctx, 0x28, 0); nv_wo32(grch->grctx, 0x2c, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); } ret = nvc0_grctx_generate(chan); @@ -127,7 +126,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) if (!nouveau_ctxfw) { nv_wr32(dev, 0x409840, 0x80000000); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000002); if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); @@ -136,7 +135,7 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) goto err; } } else { - ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); + ret = nvc0_graph_unload_context_to(dev, chan->ramin->addr); if (ret) goto err; } @@ -165,8 +164,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk408004_vma); if (ret) return ret; @@ -175,8 +174,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk40800c_vma); if (ret) return ret; @@ -186,8 +185,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW, - chan->vm, &grch->unk418810_vma); + ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, + NV_MEM_ACCESS_RW, &grch->unk418810_vma); if (ret) return ret; @@ -195,9 +194,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, - &grch->mmio_vma); + ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->mmio_vma); if (ret) return ret; @@ -268,8 +266,6 @@ static int nvc0_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nvc0_graph_priv *priv = nv_engine(dev, engine); struct nvc0_graph_chan *grch; struct nouveau_gpuobj *grctx; @@ -285,9 +281,8 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) if (ret) goto error; - ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, - &grch->grctx_vma); + ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->grctx_vma); if (ret) return ret; @@ -299,7 +294,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) 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)); - pinstmem->flush(dev); + nvimem_flush(dev); if (!priv->grctx_vals) { ret = nvc0_graph_construct_context(chan); @@ -324,7 +319,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(grctx, 0x28, 0); nv_wo32(grctx, 0x2c, 0); } - pinstmem->flush(dev); + nvimem_flush(dev); return 0; error: @@ -373,8 +368,8 @@ nvc0_graph_init_obj418880(struct drm_device *dev) nv_wr32(dev, 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->vinst >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); + nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void @@ -662,7 +657,7 @@ nvc0_graph_isr_chid(struct drm_device *dev, u64 inst) if (!chan || !chan->ramin) continue; - if (inst == chan->ramin->vinst) + if (inst == chan->ramin->addr) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 5f671a2..47bda63 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -63,7 +63,7 @@ nve0_graph_load_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); + nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); @@ -88,7 +88,6 @@ nve0_graph_unload_context_to(struct drm_device *dev, u64 chan) static int nve0_graph_construct_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; @@ -105,13 +104,13 @@ nve0_graph_construct_context(struct nouveau_channel *chan) nv_wo32(grch->grctx, 0x20, 0); nv_wo32(grch->grctx, 0x28, 0); nv_wo32(grch->grctx, 0x2c, 0); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nve0_grctx_generate(chan); if (ret) goto err; - ret = nve0_graph_unload_context_to(dev, chan->ramin->vinst); + ret = nve0_graph_unload_context_to(dev, chan->ramin->addr); if (ret) goto err; @@ -141,8 +140,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk408004_vma); if (ret) return ret; @@ -151,8 +150,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->unk40800c_vma); if (ret) return ret; @@ -162,8 +161,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW, - chan->vm, &grch->unk418810_vma); + ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, + NV_MEM_ACCESS_RW, &grch->unk418810_vma); if (ret) return ret; @@ -171,8 +170,8 @@ nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &grch->mmio_vma); if (ret) return ret; @@ -221,8 +220,6 @@ static int nve0_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_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nve0_graph_priv *priv = nv_engine(dev, engine); struct nve0_graph_chan *grch; struct nouveau_gpuobj *grctx; @@ -238,9 +235,8 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) if (ret) goto error; - ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, chan->vm, - &grch->grctx_vma); + ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->grctx_vma); if (ret) return ret; @@ -252,7 +248,7 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) 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)); - pinstmem->flush(dev); + nvimem_flush(dev); if (!priv->grctx_vals) { ret = nve0_graph_construct_context(chan); @@ -272,7 +268,7 @@ nve0_graph_context_new(struct nouveau_channel *chan, int engine) nv_wo32(grctx, 0x28, 0); nv_wo32(grctx, 0x2c, 0); - pinstmem->flush(dev); + nvimem_flush(dev); return 0; error: @@ -321,8 +317,8 @@ nve0_graph_init_obj418880(struct drm_device *dev) nv_wr32(dev, 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->vinst >> 8); - nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); + nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); + nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); } static void @@ -591,7 +587,7 @@ nve0_graph_isr_chid(struct drm_device *dev, u64 inst) if (!chan || !chan->ramin) continue; - if (inst == chan->ramin->vinst) + if (inst == chan->ramin->addr) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index eb5455f..a0258c7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -74,8 +74,8 @@ nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) - nv_wr32(dev, 0x00330c, ctx->pinst >> 4); - nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); + nv_wr32(dev, 0x00330c, ctx->addr >> 4); + nv_wo32(chan->ramfc, 0x54, ctx->addr >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -90,7 +90,7 @@ nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) struct nouveau_gpuobj *ctx = chan->engctx[engine]; struct drm_device *dev = chan->dev; unsigned long flags; - u32 inst = 0x80000000 | (ctx->pinst >> 4); + u32 inst = 0x80000000 | (ctx->addr >> 4); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); @@ -224,7 +224,7 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) continue; ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; - if (ctx && ctx->pinst == inst) + if (ctx && ctx->addr == inst) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c index 47d37a2..4e3292e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c @@ -47,7 +47,6 @@ static int nv50_mpeg_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 *ctx = NULL; int ret; @@ -60,15 +59,15 @@ nv50_mpeg_context_new(struct nouveau_channel *chan, int engine) return ret; nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002); - nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->vinst + ctx->size - 1); - nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->vinst); + nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->addr + ctx->size - 1); + nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->addr); nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0); nv_wo32(ramin, CTX_PTR(dev, 0x10), 0); nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000); nv_wo32(ctx, 0x70, 0x00801ec1); nv_wo32(ctx, 0x7c, 0x0000037c); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); chan->engctx[engine] = ctx; return 0; @@ -93,7 +92,6 @@ nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *obj = NULL; int ret; @@ -107,7 +105,7 @@ nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, nv_wo32(obj, 0x04, 0x00000000); nv_wo32(obj, 0x08, 0x00000000); nv_wo32(obj, 0x0c, 0x00000000); - dev_priv->engine.instmem.flush(dev); + nvimem_flush(dev); ret = nouveau_ramht_insert(chan, handle, obj); nouveau_gpuobj_ref(NULL, &obj); diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c index 20d33dc..384de6d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include struct nv98_ppp_engine { diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c index eb7e196..5e164a6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c @@ -25,7 +25,6 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_util.h" -#include #include /*XXX: This stub is currently used on NV98+ also, as soon as this becomes diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h new file mode 100644 index 0000000..4f4ff45 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h @@ -0,0 +1,55 @@ +#ifndef __NOUVEAU_BAR_H__ +#define __NOUVEAU_BAR_H__ + +#include +#include + +#include + +struct nouveau_vma; + +struct nouveau_bar { + struct nouveau_subdev base; + + int (*alloc)(struct nouveau_bar *, struct nouveau_object *, + struct nouveau_mem *, struct nouveau_object **); + void __iomem *iomem; + + int (*kmap)(struct nouveau_bar *, struct nouveau_mem *, + u32 flags, struct nouveau_vma *); + int (*umap)(struct nouveau_bar *, struct nouveau_mem *, + u32 flags, struct nouveau_vma *); + void (*unmap)(struct nouveau_bar *, struct nouveau_vma *); + void (*flush)(struct nouveau_bar *); +}; + +static inline struct nouveau_bar * +nouveau_bar(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BAR]; +} + +#define nouveau_bar_create(p,e,o,d) \ + nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_bar_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_bar_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void nouveau_bar_destroy(struct nouveau_bar *); + +void _nouveau_bar_dtor(struct nouveau_object *); +#define _nouveau_bar_init _nouveau_subdev_init +#define _nouveau_bar_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv50_bar_oclass; +extern struct nouveau_oclass nvc0_bar_oclass; + +int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *, + struct nouveau_mem *, struct nouveau_object **); + +void nv84_bar_flush(struct nouveau_bar *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index 91dbdc1..f18c1a1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -6,6 +6,7 @@ #include #endif #include + #include /* memory type/access flags, do not match hardware values */ diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h new file mode 100644 index 0000000..2adfcaf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h @@ -0,0 +1,74 @@ +#ifndef __NOUVEAU_INSTMEM_H__ +#define __NOUVEAU_INSTMEM_H__ + +#include +#include +#include + +struct nouveau_instobj { + struct nouveau_object base; + struct list_head head; + struct nouveau_mm heap; + u32 *suspend; + u64 addr; + u32 size; +}; + +static inline struct nouveau_instobj * +nv_memobj(void *obj) +{ +#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA + if (unlikely(!nv_iclass(obj, NV_MEMOBJ_CLASS))) + nv_assert("BAD CAST -> NvMemObj, %08x", nv_hclass(obj)); +#endif + return obj; +} + +#define nouveau_instobj_create(p,e,o,d) \ + nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instobj_init(p) \ + nouveau_object_init(&(p)->base) +#define nouveau_instobj_fini(p,s) \ + nouveau_object_fini(&(p)->base, (s)) + +int nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void nouveau_instobj_destroy(struct nouveau_instobj *); + +void _nouveau_instobj_dtor(struct nouveau_object *); +#define _nouveau_instobj_init nouveau_object_init +#define _nouveau_instobj_fini nouveau_object_fini + +struct nouveau_instmem { + struct nouveau_subdev base; + struct list_head list; + + u32 reserved; + int (*alloc)(struct nouveau_instmem *, struct nouveau_object *, + u32 size, u32 align, struct nouveau_object **); +}; + +static inline struct nouveau_instmem * +nouveau_instmem(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; +} + +#define nouveau_instmem_create(p,e,o,d) \ + nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instmem_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_instmem_init(struct nouveau_instmem *); +int nouveau_instmem_fini(struct nouveau_instmem *, bool); + +#define _nouveau_instmem_dtor _nouveau_subdev_dtor +int _nouveau_instmem_init(struct nouveau_object *); +int _nouveau_instmem_fini(struct nouveau_object *, bool); + +extern struct nouveau_oclass nv04_instmem_oclass; +extern struct nouveau_oclass nv40_instmem_oclass; +extern struct nouveau_oclass nv50_instmem_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 6d3764b..81577bb 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -25,10 +25,14 @@ #ifndef __NOUVEAU_VM_H__ #define __NOUVEAU_VM_H__ +#ifndef XXX_THIS_IS_A_HACK +#include +#include +#include +#endif #include -struct nouveau_mem; - +#ifndef XXX_THIS_IS_A_HACK struct nouveau_vm_pgt { struct nouveau_gpuobj *obj[2]; u32 refcount[2]; @@ -38,6 +42,10 @@ struct nouveau_vm_pgd { struct list_head head; struct nouveau_gpuobj *obj; }; +#endif + +struct nouveau_gpuobj; +struct nouveau_mem; struct nouveau_vma { struct list_head head; @@ -49,21 +57,29 @@ struct nouveau_vma { }; struct nouveau_vm { - struct drm_device *dev; + struct nouveau_vmmgr *vmm; struct nouveau_mm mm; int refcount; struct list_head pgd_list; - atomic_t engref[16]; + atomic_t engref[64]; //NVDEV_SUBDEV_NR]; struct nouveau_vm_pgt *pgt; u32 fpde; u32 lpde; +}; + +#ifndef XXX_THIS_IS_A_HACK +struct nouveau_vmmgr { + struct nouveau_subdev base; u32 pgt_bits; u8 spg_shift; u8 lpg_shift; + int (*create)(struct nouveau_vmmgr *, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **); + void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]); void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, @@ -71,16 +87,48 @@ struct nouveau_vm { u64 phys, u64 delta); void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); - - void (*map_sg_table)(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); void (*flush)(struct nouveau_vm *); }; -/* nouveau_vm.c */ -int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset, +static inline struct nouveau_vmmgr * +nouveau_vmmgr(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_VM]; +} + +#define nouveau_vmmgr_create(p,e,o,i,f,d) \ + nouveau_subdev_create((p), (e), (o), 0, (i), (f), (d)) +#define nouveau_vmmgr_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_vmmgr_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_vmmgr_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_vmmgr_dtor _nouveau_subdev_dtor +#define _nouveau_vmmgr_init _nouveau_subdev_init +#define _nouveau_vmmgr_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv04_vmmgr_oclass; +extern struct nouveau_oclass nv41_vmmgr_oclass; +extern struct nouveau_oclass nv44_vmmgr_oclass; +extern struct nouveau_oclass nv50_vmmgr_oclass; +extern struct nouveau_oclass nvc0_vmmgr_oclass; + +int nv04_vm_create(struct nouveau_vmmgr *, u64, u64, u64, struct nouveau_vm **); +void nv04_vmmgr_dtor(struct nouveau_object *); + +void nv50_vm_flush_engine(struct nouveau_subdev *, int engine); +void nvc0_vm_flush_engine(struct nouveau_subdev *, u64 addr, int type); + +/* nouveau_vm.c */ +int nouveau_vm_create(struct nouveau_vmmgr *, u64 offset, u64 length, + u64 mm_offset, u32 block, struct nouveau_vm **); +int nouveau_vm_new(struct nouveau_device *, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **); +#endif int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, struct nouveau_gpuobj *pgd); int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, @@ -93,26 +141,6 @@ void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, struct nouveau_mem *); void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, - struct nouveau_mem *mem); -/* nv50_vm.c */ -void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); -void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); -void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); -void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nv50_vm_flush(struct nouveau_vm *); -void nv50_vm_flush_engine(struct drm_device *, int engine); - -/* nvc0_vm.c */ -void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); -void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); -void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, - struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); -void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nvc0_vm_flush(struct nouveau_vm *); + struct nouveau_mem *mem); #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c new file mode 100644 index 0000000..cd01c53 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c @@ -0,0 +1,135 @@ +/* + * 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: + * + * 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 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 +#include + +struct nouveau_barobj { + struct nouveau_object base; + struct nouveau_vma vma; + void __iomem *iomem; +}; + +static int +nouveau_barobj_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *mem, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bar *bar = (void *)engine; + struct nouveau_barobj *barobj; + int ret; + + ret = nouveau_object_create(parent, engine, oclass, 0, &barobj); + *pobject = nv_object(barobj); + if (ret) + return ret; + + ret = bar->kmap(bar, mem, NV_MEM_ACCESS_RW, &barobj->vma); + if (ret) + return ret; + + barobj->iomem = bar->iomem + (u32)barobj->vma.offset; + return 0; +} + +static void +nouveau_barobj_dtor(struct nouveau_object *object) +{ + struct nouveau_bar *bar = (void *)object->engine; + struct nouveau_barobj *barobj = (void *)object; + if (barobj->vma.node) + bar->unmap(bar, &barobj->vma); + nouveau_object_destroy(&barobj->base); +} + +static u32 +nouveau_barobj_rd32(struct nouveau_object *object, u32 addr) +{ + struct nouveau_barobj *barobj = (void *)object; + return ioread32_native(barobj->iomem + addr); +} + +static void +nouveau_barobj_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nouveau_barobj *barobj = (void *)object; + iowrite32_native(data, barobj->iomem + addr); +} + +static struct nouveau_oclass +nouveau_barobj_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nouveau_barobj_ctor, + .dtor = nouveau_barobj_dtor, + .init = nouveau_object_init, + .fini = nouveau_object_fini, + .rd32 = nouveau_barobj_rd32, + .wr32 = nouveau_barobj_wr32, + }, +}; + +int +nouveau_bar_alloc(struct nouveau_bar *bar, struct nouveau_object *parent, + struct nouveau_mem *mem, struct nouveau_object **pobject) +{ + struct nouveau_object *engine = nv_object(bar); + return nouveau_object_ctor(parent, engine, &nouveau_barobj_oclass, + mem, 0, pobject); +} + +int +nouveau_bar_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, int length, void **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_bar *bar; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "BARCTL", + "bar", length, pobject); + bar = *pobject; + if (ret) + return ret; + + bar->iomem = ioremap(pci_resource_start(device->pdev, 3), + pci_resource_len(device->pdev, 3)); + return 0; +} + +void +nouveau_bar_destroy(struct nouveau_bar *bar) +{ + if (bar->iomem) + iounmap(bar->iomem); + nouveau_subdev_destroy(&bar->base); +} + +void +_nouveau_bar_dtor(struct nouveau_object *object) +{ + struct nouveau_bar *bar = (void *)object; + nouveau_bar_destroy(bar); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c new file mode 100644 index 0000000..c3acf5b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c @@ -0,0 +1,263 @@ +/* + * 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: + * + * 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 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 + +#include +#include +#include +#include + +struct nv50_bar_priv { + struct nouveau_bar base; + spinlock_t lock; + struct nouveau_gpuobj *mem; + struct nouveau_gpuobj *pad; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *bar1_vm; + struct nouveau_gpuobj *bar1; + struct nouveau_vm *bar3_vm; + struct nouveau_gpuobj *bar3; +}; + +static int +nv50_bar_kmap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nv50_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar3_vm, mem->size << 12, 12, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nv50_vm_flush_engine(nv_subdev(bar), 6); + return 0; +} + +static int +nv50_bar_umap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nv50_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar1_vm, mem->size << 12, 12, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nv50_vm_flush_engine(nv_subdev(bar), 6); + return 0; +} + +static void +nv50_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) +{ + nouveau_vm_unmap(vma); + nv50_vm_flush_engine(nv_subdev(bar), 6); + nouveau_vm_put(vma); +} + +static void +nv50_bar_flush(struct nouveau_bar *bar) +{ + struct nv50_bar_priv *priv = (void *)bar; + unsigned long flags; + spin_lock_irqsave(&priv->lock, flags); + nv_wr32(priv, 0x00330c, 0x00000001); + if (!nv_wait(priv, 0x00330c, 0x00000002, 0x00000000)) + nv_warn(priv, "flush timeout\n"); + spin_unlock_irqrestore(&priv->lock, flags); +} + +void +nv84_bar_flush(struct nouveau_bar *bar) +{ + struct nv50_bar_priv *priv = (void *)bar; + unsigned long flags; + spin_lock_irqsave(&priv->lock, flags); + nv_wr32(bar, 0x070000, 0x00000001); + if (!nv_wait(priv, 0x070000, 0x00000002, 0x00000000)) + nv_warn(priv, "flush timeout\n"); + spin_unlock_irqrestore(&priv->lock, flags); +} + +static int +nv50_bar_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 nouveau_object *heap; + struct nouveau_vm *vm; + struct nv50_bar_priv *priv; + u64 start, limit; + int ret; + + ret = nouveau_bar_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0, NVOBJ_FLAG_HEAP, + &priv->mem); + heap = nv_object(priv->mem); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, (device->chipset == 0x50) ? + 0x1400 : 0x0200, 0, 0, &priv->pad); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, 0x4000, 0, 0, &priv->pgd); + if (ret) + return ret; + + /* BAR3 */ + start = 0x0100000000ULL; + limit = start + pci_resource_len(device->pdev, 3); + + ret = nouveau_vm_new(device, start, limit, start, &vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, ((limit-- - start) >> 12) * 8, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, + &vm->pgt[0].obj[0]); + vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar3_vm, priv->pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, 24, 16, 0, &priv->bar3); + if (ret) + return ret; + + nv_wo32(priv->bar3, 0x00, 0x7fc00000); + nv_wo32(priv->bar3, 0x04, lower_32_bits(limit)); + nv_wo32(priv->bar3, 0x08, lower_32_bits(start)); + nv_wo32(priv->bar3, 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(priv->bar3, 0x10, 0x00000000); + nv_wo32(priv->bar3, 0x14, 0x00000000); + + /* BAR1 */ + start = 0x0000000000ULL; + limit = start + pci_resource_len(device->pdev, 1); + + ret = nouveau_vm_new(device, start, limit--, start, &vm); + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar1_vm, priv->pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, heap, 24, 16, 0, &priv->bar1); + if (ret) + return ret; + + nv_wo32(priv->bar1, 0x00, 0x7fc00000); + nv_wo32(priv->bar1, 0x04, lower_32_bits(limit)); + nv_wo32(priv->bar1, 0x08, lower_32_bits(start)); + nv_wo32(priv->bar1, 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(priv->bar1, 0x10, 0x00000000); + nv_wo32(priv->bar1, 0x14, 0x00000000); + + priv->base.alloc = nouveau_bar_alloc; + priv->base.kmap = nv50_bar_kmap; + priv->base.umap = nv50_bar_umap; + priv->base.unmap = nv50_bar_unmap; + if (device->chipset == 0x50) + priv->base.flush = nv50_bar_flush; + else + priv->base.flush = nv84_bar_flush; + spin_lock_init(&priv->lock); + return 0; +} + +static void +nv50_bar_dtor(struct nouveau_object *object) +{ + struct nv50_bar_priv *priv = (void *)object; + nouveau_gpuobj_ref(NULL, &priv->bar1); + nouveau_vm_ref(NULL, &priv->bar1_vm, priv->pgd); + nouveau_gpuobj_ref(NULL, &priv->bar3); + if (priv->bar3_vm) { + nouveau_gpuobj_ref(NULL, &priv->bar3_vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->bar3_vm, priv->pgd); + } + nouveau_gpuobj_ref(NULL, &priv->pgd); + nouveau_gpuobj_ref(NULL, &priv->pad); + nouveau_gpuobj_ref(NULL, &priv->mem); + nouveau_bar_destroy(&priv->base); +} + +static int +nv50_bar_init(struct nouveau_object *object) +{ + struct nv50_bar_priv *priv = (void *)object; + int ret; + + ret = nouveau_bar_init(&priv->base); + if (ret) + return ret; + + nv_mask(priv, 0x000200, 0x00000100, 0x00000000); + nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + nv50_vm_flush_engine(nv_subdev(priv), 6); + + nv_wr32(priv, 0x001704, 0x00000000 | priv->mem->addr >> 12); + nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12); + nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4); + nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4); + return 0; +} + +static int +nv50_bar_fini(struct nouveau_object *object, bool suspend) +{ + struct nv50_bar_priv *priv = (void *)object; + return nouveau_bar_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv50_bar_oclass = { + .handle = NV_SUBDEV(BAR, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_bar_ctor, + .dtor = nv50_bar_dtor, + .init = nv50_bar_init, + .fini = nv50_bar_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c new file mode 100644 index 0000000..77a6fb7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -0,0 +1,215 @@ +/* + * 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: + * + * 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 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 + +#include +#include +#include +#include + +struct nvc0_bar_priv { + struct nouveau_bar base; + spinlock_t lock; + struct { + struct nouveau_gpuobj *mem; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; + } bar[2]; +}; + +static int +nvc0_bar_kmap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nvc0_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar[0].vm, mem->size << 12, 12, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[0].pgd->addr, 5); + return 0; +} + +static int +nvc0_bar_umap(struct nouveau_bar *bar, struct nouveau_mem *mem, + u32 flags, struct nouveau_vma *vma) +{ + struct nvc0_bar_priv *priv = (void *)bar; + int ret; + + ret = nouveau_vm_get(priv->bar[1].vm, mem->size << 12, + mem->page_shift, flags, vma); + if (ret) + return ret; + + nouveau_vm_map(vma, mem); + nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[1].pgd->addr, 5); + return 0; +} + +static void +nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) +{ + struct nvc0_bar_priv *priv = (void *)bar; + int i = !(vma->vm == priv->bar[0].vm); + + nouveau_vm_unmap(vma); + nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[i].pgd->addr, 5); + nouveau_vm_put(vma); +} + +static int +nvc0_bar_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 pci_dev *pdev = device->pdev; + struct nvc0_bar_priv *priv; + struct nouveau_gpuobj *mem; + struct nouveau_vm *vm; + int ret; + + ret = nouveau_bar_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + /* BAR3 */ + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[0].mem); + mem = priv->bar[0].mem; + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[0].pgd); + if (ret) + return ret; + + ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (pci_resource_len(pdev, 3) >> 12) * 8, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, + &vm->pgt[0].obj[0]); + vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); + nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1)); + + /* BAR1 */ + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[1].mem); + mem = priv->bar[1].mem; + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[1].pgd); + if (ret) + return ret; + + ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm); + if (ret) + return ret; + + ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd); + nouveau_vm_ref(NULL, &vm, NULL); + if (ret) + return ret; + + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); + nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1)); + + priv->base.alloc = nouveau_bar_alloc; + priv->base.kmap = nvc0_bar_kmap; + priv->base.umap = nvc0_bar_umap; + priv->base.unmap = nvc0_bar_unmap; + priv->base.flush = nv84_bar_flush; + spin_lock_init(&priv->lock); + return 0; +} + +static void +nvc0_bar_dtor(struct nouveau_object *object) +{ + struct nvc0_bar_priv *priv = (void *)object; + + nouveau_vm_ref(NULL, &priv->bar[1].vm, priv->bar[1].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[1].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[1].mem); + + if (priv->bar[0].vm) { + nouveau_gpuobj_ref(NULL, &priv->bar[0].vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->bar[0].vm, priv->bar[0].pgd); + } + nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); + + nouveau_bar_destroy(&priv->base); +} + +static int +nvc0_bar_init(struct nouveau_object *object) +{ + struct nvc0_bar_priv *priv = (void *)object; + int ret; + + ret = nouveau_bar_init(&priv->base); + if (ret) + return ret; + + nv_mask(priv, 0x000200, 0x00000100, 0x00000000); + nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); + + nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); + nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12); + return 0; +} + +struct nouveau_oclass +nvc0_bar_oclass = { + .handle = NV_SUBDEV(BAR, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_bar_ctor, + .dtor = nvc0_bar_dtor, + .init = nvc0_bar_init, + .fini = _nouveau_bar_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 66b7156..5173c78 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include int nv04_identify(struct nouveau_device *device) @@ -43,6 +45,8 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -52,6 +56,8 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index cf81479..c4f2c2d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv10_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +95,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +107,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +119,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +131,8 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index e97280c..719b72a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv20_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index ddd3ab6..0a1a728 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv30_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +95,8 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index c7ea921..5e1ef5e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include int nv40_identify(struct nouveau_device *device) @@ -45,6 +47,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +59,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +71,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +83,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +95,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +107,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +119,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +131,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -125,6 +143,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -135,6 +155,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +167,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -155,6 +179,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -165,6 +191,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -175,6 +203,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -185,6 +215,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -195,6 +227,8 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index e60cdf2..5e86a2f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include int nv50_identify(struct nouveau_device *device) @@ -45,6 +48,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -55,6 +61,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -65,6 +74,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -75,6 +87,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +100,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +113,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -105,6 +126,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -115,6 +139,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -125,6 +152,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -135,6 +165,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +178,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -155,6 +191,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -165,6 +204,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -175,6 +217,9 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 8de6730..87f4e16 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include int nvc0_identify(struct nouveau_device *device) @@ -47,6 +50,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -58,6 +64,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -69,6 +78,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -80,6 +92,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -91,6 +106,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -102,6 +120,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -113,6 +134,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -124,6 +148,9 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 919a102..ab8346b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include int nve0_identify(struct nouveau_device *device) @@ -47,6 +50,9 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -58,6 +64,9 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index 84aa71c..347a496 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -50,54 +50,14 @@ nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) static void nv40_fb_init_gart(struct nv40_fb_priv *priv) { -#if 0 - struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - - if (ndev->gart_info.type != NOUVEAU_GART_HW) { -#endif - nv_wr32(priv, 0x100800, 0x00000001); -#if 0 - return; - } - - nv_wr32(ndev, 0x100800, gart->pinst | 0x00000002); - nv_mask(ndev, 0x10008c, 0x00000100, 0x00000100); - nv_wr32(ndev, 0x100820, 0x00000000); -#endif + nv_wr32(priv, 0x100800, 0x00000001); } static void nv44_fb_init_gart(struct nv40_fb_priv *priv) { -#if 0 - struct nouveau_gpuobj *gart = ndev->gart_info.sg_ctxdma; - u32 vinst; - - if (ndev->gart_info.type != NOUVEAU_GART_HW) { -#endif - nv_wr32(priv, 0x100850, 0x80000000); - nv_wr32(priv, 0x100800, 0x00000001); -#if 0 - return; - } - - /* calculate vram address of this PRAMIN block, object - * must be allocated on 512KiB alignment, and not exceed - * a total size of 512KiB for this to work correctly - */ - vinst = nv_rd32(ndev, 0x10020c); - vinst -= ((gart->pinst >> 19) + 1) << 19; - - nv_wr32(ndev, 0x100850, 0x80000000); - nv_wr32(ndev, 0x100818, ndev->gart_info.dummy.addr); - - nv_wr32(ndev, 0x100804, ndev->gart_info.aper_size); - nv_wr32(ndev, 0x100850, 0x00008000); - nv_mask(ndev, 0x10008c, 0x00000200, 0x00000200); - nv_wr32(ndev, 0x100820, 0x00000000); - nv_wr32(ndev, 0x10082c, 0x00000001); - nv_wr32(ndev, 0x100800, vinst | 0x00000010); -#endif + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100800, 0x00000001); } static int diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c new file mode 100644 index 0000000..1188227 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c @@ -0,0 +1,135 @@ +/* + * 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: + * + * 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 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 + +int +nouveau_instobj_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int length, void **pobject) +{ + struct nouveau_instmem *imem = (void *)engine; + struct nouveau_instobj *iobj; + int ret; + + ret = nouveau_object_create_(parent, engine, oclass, NV_MEMOBJ_CLASS, + length, pobject); + iobj = *pobject; + if (ret) + return ret; + + list_add(&iobj->head, &imem->list); + return 0; +} + +void +nouveau_instobj_destroy(struct nouveau_instobj *iobj) +{ + if (iobj->head.prev) + list_del(&iobj->head); + return nouveau_object_destroy(&iobj->base); +} + +void +_nouveau_instobj_dtor(struct nouveau_object *object) +{ + struct nouveau_instobj *iobj = (void *)object; + return nouveau_instobj_destroy(iobj); +} + +int +nouveau_instmem_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int length, void **pobject) +{ + struct nouveau_instmem *imem; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, + "INSTMEM", "instmem", length, pobject); + imem = *pobject; + if (ret) + return ret; + + INIT_LIST_HEAD(&imem->list); + return 0; +} + +int +nouveau_instmem_init(struct nouveau_instmem *imem) +{ + struct nouveau_instobj *iobj; + int ret, i; + + ret = nouveau_subdev_init(&imem->base); + if (ret) + return ret; + + list_for_each_entry(iobj, &imem->list, head) { + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) + nv_wo32(iobj, i, iobj->suspend[i / 4]); + vfree(iobj->suspend); + iobj->suspend = NULL; + } + } + + return 0; +} + +int +nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) +{ + struct nouveau_instobj *iobj; + int i; + + if (suspend) { + list_for_each_entry(iobj, &imem->list, head) { + iobj->suspend = vmalloc(iobj->size); + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) + iobj->suspend[i / 4] = nv_ro32(iobj, i); + } else + return -ENOMEM; + } + } + + return nouveau_subdev_fini(&imem->base, suspend); +} + +int +_nouveau_instmem_init(struct nouveau_object *object) +{ + struct nouveau_instmem *imem = (void *)object; + return nouveau_instmem_init(imem); +} + +int +_nouveau_instmem_fini(struct nouveau_object *object, bool suspend) +{ + struct nouveau_instmem *imem = (void *)object; + return nouveau_instmem_fini(imem, suspend); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index 46b6963..f44f0f0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -1,141 +1,199 @@ -#include "drmP.h" -#include "drm.h" - -#include "nouveau_drv.h" -#include -#include +/* + * 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: + * + * 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 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 #include "nv04.h" +static int +nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_instmem_priv *priv = (void *)engine; + struct nv04_instobj_priv *node; + int ret, align; + + align = (unsigned long)data; + if (!align) + align = 1; + + ret = nouveau_instobj_create(parent, engine, oclass, &node); + *pobject = nv_object(node); + if (ret) + return ret; + + ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem); + if (ret) + return ret; + + node->base.addr = node->mem->offset; + node->base.size = node->mem->length; + return 0; +} + +static void +nv04_instobj_dtor(struct nouveau_object *object) +{ + struct nv04_instmem_priv *priv = (void *)object->engine; + struct nv04_instobj_priv *node = (void *)object; + nouveau_mm_free(&priv->heap, &node->mem); + nouveau_instobj_destroy(&node->base); +} + +static u32 +nv04_instobj_rd32(struct nouveau_object *object, u32 addr) +{ + struct nv04_instobj_priv *node = (void *)object; + return nv_ro32(object->engine, node->mem->offset + addr); +} + +static void +nv04_instobj_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nv04_instobj_priv *node = (void *)object; + nv_wo32(object->engine, node->mem->offset + addr, data); +} + +static struct nouveau_oclass +nv04_instobj_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_instobj_ctor, + .dtor = nv04_instobj_dtor, + .init = _nouveau_instobj_init, + .fini = _nouveau_instobj_fini, + .rd32 = nv04_instobj_rd32, + .wr32 = nv04_instobj_wr32, + }, +}; + int -nv04_instmem_init(struct drm_device *dev) +nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, + u32 size, u32 align, struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *priv; + struct nouveau_object *engine = nv_object(imem); + struct nv04_instmem_priv *priv = (void *)(imem); int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - dev_priv->engine.instmem.priv = priv; + ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass, + (void *)(unsigned long)align, size, pobject); + if (ret) + return ret; + + /* INSTMEM itself creates objects to reserve (and preserve across + * suspend/resume) various fixed data locations, each one of these + * takes a reference on INSTMEM itself, causing it to never be + * freed. We drop all the self-references here to avoid this. + */ + if (unlikely(!priv->created)) + atomic_dec(&engine->refcount); + + return 0; +} - /* PRAMIN aperture maps over the end of vram, reserve the space */ - dev_priv->ramin_available = true; - dev_priv->ramin_rsvd_vram = 512 * 1024; +static int +nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_instmem_priv *priv; + int ret; - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_rsvd_vram); + ret = nouveau_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); if (ret) return ret; - /* 0x00000-0x10000: reserve for probable vbios image */ - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0, 0, &priv->vbios); + /* PRAMIN aperture maps over the end of VRAM, reserve it */ + priv->base.reserved = 512 * 1024; + priv->base.alloc = nv04_instmem_alloc; + + ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); if (ret) return ret; - /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramht); + /* 0x00000-0x10000: reserve for probable vbios image */ + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios); if (ret) return ret; - /* 0x18000-0x18200: reserve for RAMRO */ - ret = nouveau_gpuobj_new(dev, NULL, 0x00200, 0, 0, &priv->ramro); + /* 0x10000-0x18000: reserve for RAMHT */ + ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); if (ret) return ret; - /* 0x18200-0x18a00: reserve for RAMFC (enough for 32 nv30 channels) */ - ret = nouveau_gpuobj_new(dev, NULL, 0x00800, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramfc); + /* 0x18000-0x18800: reserve for RAMFC (enough for 32 nv30 channels) */ + ret = nouveau_gpuobj_new(parent, NULL, 0x00800, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); if (ret) return ret; - ret = nouveau_ramht_new(dev, priv->ramht, &dev_priv->ramht); + /* 0x18800-0x18a00: reserve for RAMRO */ + ret = nouveau_gpuobj_new(parent, NULL, 0x00200, 0, 0, &priv->ramro); if (ret) return ret; + priv->created = true; return 0; } void -nv04_instmem_takedown(struct drm_device *dev) +nv04_instmem_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *priv = dev_priv->engine.instmem.priv; - - nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); + struct nv04_instmem_priv *priv = (void *)object; nouveau_gpuobj_ref(NULL, &priv->ramfc); nouveau_gpuobj_ref(NULL, &priv->ramro); nouveau_gpuobj_ref(NULL, &priv->ramht); - - if (drm_mm_initialized(&dev_priv->ramin_heap)) - drm_mm_takedown(&dev_priv->ramin_heap); - - kfree(priv); - dev_priv->engine.instmem.priv = NULL; + nouveau_gpuobj_ref(NULL, &priv->vbios); + nouveau_mm_fini(&priv->heap); + if (priv->iomem) + iounmap(priv->iomem); + nouveau_instmem_destroy(&priv->base); } -int -nv04_instmem_suspend(struct drm_device *dev) -{ - return 0; -} - -void -nv04_instmem_resume(struct drm_device *dev) +static u32 +nv04_instmem_rd32(struct nouveau_object *object, u32 addr) { + return nv_rd32(object, 0x700000 + addr); } -int -nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, - u32 size, u32 align) +static void +nv04_instmem_wr32(struct nouveau_object *object, u32 addr, u32 data) { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_mm_node *ramin = NULL; - - do { - if (drm_mm_pre_get(&dev_priv->ramin_heap)) - return -ENOMEM; - - spin_lock(&dev_priv->ramin_lock); - ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); - if (ramin == NULL) { - spin_unlock(&dev_priv->ramin_lock); - return -ENOMEM; - } - - ramin = drm_mm_get_block_atomic(ramin, size, align); - spin_unlock(&dev_priv->ramin_lock); - } while (ramin == NULL); - - gpuobj->node = ramin; - gpuobj->vinst = ramin->start; - return 0; + return nv_wr32(object, 0x700000 + addr, data); } -void -nv04_instmem_put(struct nouveau_gpuobj *gpuobj) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - - spin_lock(&dev_priv->ramin_lock); - drm_mm_put_block(gpuobj->node); - gpuobj->node = NULL; - spin_unlock(&dev_priv->ramin_lock); -} - -int -nv04_instmem_map(struct nouveau_gpuobj *gpuobj) -{ - gpuobj->pinst = gpuobj->vinst; - return 0; -} - -void -nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj) -{ -} - -void -nv04_instmem_flush(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv04_instmem_oclass = { + .handle = NV_SUBDEV(INSTMEM, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_instmem_ctor, + .dtor = nv04_instmem_dtor, + .init = _nouveau_instmem_init, + .fini = _nouveau_instmem_fini, + .rd32 = nv04_instmem_rd32, + .wr32 = nv04_instmem_wr32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h index a8c1104..b2f82f9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -1,11 +1,32 @@ #ifndef __NV04_INSTMEM_H__ #define __NV04_INSTMEM_H__ +#include +#include + +#include + struct nv04_instmem_priv { + struct nouveau_instmem base; + bool created; + + void __iomem *iomem; + struct nouveau_mm heap; + struct nouveau_gpuobj *vbios; struct nouveau_gpuobj *ramht; struct nouveau_gpuobj *ramro; struct nouveau_gpuobj *ramfc; }; +struct nv04_instobj_priv { + struct nouveau_instobj base; + struct nouveau_mm_node *mem; +}; + +void nv04_instmem_dtor(struct nouveau_object *); + +int nv04_instmem_alloc(struct nouveau_instmem *, struct nouveau_object *, + u32 size, u32 align, struct nouveau_object **pobject); + #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 7c938ae..6a22160 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -1,165 +1,139 @@ -#include "drmP.h" -#include "drm.h" - -#include "nouveau_drv.h" -#include -#include +/* + * 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: + * + * 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 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 "nv04.h" -int nv40_instmem_init(struct drm_device *dev) +static inline int +nv44_graph_class(struct nv04_instmem_priv *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + if ((nv_device(priv)->chipset & 0xf0) == 0x60) + return 1; + return !(0x0baf & (1 << (nv_device(priv)->chipset & 0x0f))); +} + +static int +nv40_instmem_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 pci_dev *pdev = device->pdev; struct nv04_instmem_priv *priv; - u32 vs, rsvd; - int ret; + int ret, bar, vs; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - dev_priv->engine.instmem.priv = priv; + ret = nouveau_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + /* map bar */ + if (pci_resource_len(pdev, 2)) + bar = 2; + else + bar = 3; + + priv->iomem = ioremap(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar)); + if (!priv->iomem) { + nv_error(priv, "unable to map PRAMIN BAR\n"); + return -EFAULT; + } /* PRAMIN aperture maps over the end of vram, reserve enough space * to fit graphics contexts for every channel, the magics come * from engine/graph/nv40.c */ - vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); - if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; - else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; - else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; - else rsvd = 0x4a40 * vs; - rsvd += 16 * 1024; - rsvd *= 32; /* per-channel */ - rsvd += 512 * 1024; /* pci(e)gart table */ - rsvd += 512 * 1024; /* object storage */ - dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); - dev_priv->ramin_available = true; - - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_rsvd_vram); + vs = hweight8((nv_rd32(priv, 0x001540) & 0x0000ff00) >> 8); + if (device->chipset == 0x40) priv->base.reserved = 0x6aa0 * vs; + else if (device->chipset < 0x43) priv->base.reserved = 0x4f00 * vs; + else if (nv44_graph_class(priv)) priv->base.reserved = 0x4980 * vs; + else priv->base.reserved = 0x4a40 * vs; + priv->base.reserved += 16 * 1024; + priv->base.reserved *= 32; /* per-channel */ + priv->base.reserved += 512 * 1024; /* pci(e)gart table */ + priv->base.reserved += 512 * 1024; /* object storage */ + + priv->base.reserved = round_up(priv->base.reserved, 4096); + priv->base.alloc = nv04_instmem_alloc; + + ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1); if (ret) return ret; /* 0x00000-0x10000: reserve for probable vbios image */ - ret = nouveau_gpuobj_new(dev, NULL, 0x10000, 0, 0, &priv->vbios); + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios); if (ret) return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramht); + ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); if (ret) return ret; /* 0x18000-0x18200: reserve for RAMRO * 0x18200-0x20000: padding */ - ret = nouveau_gpuobj_new(dev, NULL, 0x08000, 0, 0, &priv->ramro); + ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, 0, &priv->ramro); if (ret) return ret; /* 0x20000-0x21000: reserve for RAMFC - * 0x21000-0x40000: padding + some unknown stuff (see below) - * - * It appears something is controlled by 0x2220/0x2230 on certain - * NV4x chipsets as well as RAMFC. When 0x2230 == 0 ("new style" - * control) the upper 16-bits of 0x2220 points at this other - * mysterious table that's clobbering important things. - * - * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting - * smashed to pieces on us, so reserve 0x30000-0x40000 too.. + * 0x21000-0x40000: padding and some unknown crap */ - ret = nouveau_gpuobj_new(dev, NULL, 0x20000, 0, NVOBJ_FLAG_ZERO_ALLOC, - &priv->ramfc); - if (ret) - return ret; - - ret = nouveau_ramht_new(dev, priv->ramht, &dev_priv->ramht); + ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); if (ret) return ret; + priv->created = true; return 0; } -void -nv40_instmem_takedown(struct drm_device *dev) +static u32 +nv40_instmem_rd32(struct nouveau_object *object, u32 addr) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_instmem_priv *priv = dev_priv->engine.instmem.priv; - - nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); - nouveau_gpuobj_ref(NULL, &priv->ramfc); - nouveau_gpuobj_ref(NULL, &priv->ramro); - nouveau_gpuobj_ref(NULL, &priv->ramht); - - if (drm_mm_initialized(&dev_priv->ramin_heap)) - drm_mm_takedown(&dev_priv->ramin_heap); - - kfree(priv); - dev_priv->engine.instmem.priv = NULL; -} - -int -nv40_instmem_suspend(struct drm_device *dev) -{ - return 0; + struct nv04_instmem_priv *priv = (void *)object; + return ioread32_native(priv->iomem + addr); } -void -nv40_instmem_resume(struct drm_device *dev) +static void +nv40_instmem_wr32(struct nouveau_object *object, u32 addr, u32 data) { + struct nv04_instmem_priv *priv = (void *)object; + iowrite32_native(data, priv->iomem + addr); } -int -nv40_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, - u32 size, u32 align) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_mm_node *ramin = NULL; - - do { - if (drm_mm_pre_get(&dev_priv->ramin_heap)) - return -ENOMEM; - - spin_lock(&dev_priv->ramin_lock); - ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); - if (ramin == NULL) { - spin_unlock(&dev_priv->ramin_lock); - return -ENOMEM; - } - - ramin = drm_mm_get_block_atomic(ramin, size, align); - spin_unlock(&dev_priv->ramin_lock); - } while (ramin == NULL); - - gpuobj->node = ramin; - gpuobj->vinst = ramin->start; - return 0; -} - -void -nv40_instmem_put(struct nouveau_gpuobj *gpuobj) -{ - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - - spin_lock(&dev_priv->ramin_lock); - drm_mm_put_block(gpuobj->node); - gpuobj->node = NULL; - spin_unlock(&dev_priv->ramin_lock); -} - -int -nv40_instmem_map(struct nouveau_gpuobj *gpuobj) -{ - gpuobj->pinst = gpuobj->vinst; - return 0; -} - -void -nv40_instmem_unmap(struct nouveau_gpuobj *gpuobj) -{ -} - -void -nv40_instmem_flush(struct drm_device *dev) -{ -} +struct nouveau_oclass +nv40_instmem_oclass = { + .handle = NV_SUBDEV(INSTMEM, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_instmem_ctor, + .dtor = nv04_instmem_dtor, + .init = _nouveau_instmem_init, + .fini = _nouveau_instmem_fini, + .rd32 = nv40_instmem_rd32, + .wr32 = nv40_instmem_wr32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index f88530b..27ef089 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -1,390 +1,172 @@ /* - * Copyright (C) 2007 Ben Skeggs. + * Copyright 2012 Red Hat Inc. * - * All Rights Reserved. + * 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 shall be included in + * all copies or substantial portions of the Software. * - * 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 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 +#include +#include -#define BAR1_VM_BASE 0x0020000000ULL -#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1) -#define BAR3_VM_BASE 0x0000000000ULL -#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3) +#include struct nv50_instmem_priv { - uint32_t save1700[5]; /* 0x1700->0x1710 */ - - struct nouveau_gpuobj *bar1_dmaobj; - struct nouveau_gpuobj *bar3_dmaobj; + struct nouveau_instmem base; + spinlock_t lock; + u64 addr; }; -static void -nv50_channel_del(struct nouveau_channel **pchan) -{ - struct nouveau_channel *chan; - - chan = *pchan; - *pchan = NULL; - if (!chan) - return; - - nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_pd); - if (drm_mm_initialized(&chan->ramin_heap)) - drm_mm_takedown(&chan->ramin_heap); - nouveau_gpuobj_ref(NULL, &chan->ramin); - kfree(chan); -} +struct nv50_instobj_priv { + struct nouveau_instobj base; + struct nouveau_mem *mem; +}; static int -nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, - struct nouveau_channel **pchan) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; - struct nouveau_channel *chan; - int ret, i; - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) - return -ENOMEM; - chan->dev = dev; - - ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - ret = drm_mm_init(&chan->ramin_heap, pgd, chan->ramin->size - pgd); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - ret = nouveau_gpuobj_new(dev, chan, 0x4000, 0, 0, &chan->vm_pd); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - for (i = 0; i < 0x4000; i += 8) { - nv_wo32(chan->vm_pd, i + 0, 0x00000000); - nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); - } - - ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); - if (ret) { - nv50_channel_del(&chan); - return ret; - } - - *pchan = chan; - return 0; -} - -int -nv50_instmem_init(struct drm_device *dev) +nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv; - struct nouveau_channel *chan; - struct nouveau_vm *vm; - int ret, i; - u32 tmp; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - dev_priv->engine.instmem.priv = priv; - - /* Save state, will restore at takedown. */ - for (i = 0x1700; i <= 0x1710; i += 4) - priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); - - /* Global PRAMIN heap */ - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); - if (ret) { - NV_ERROR(dev, "Failed to init RAMIN heap\n"); - goto error; - } - - /* BAR3 */ - ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE, - &dev_priv->bar3_vm); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8, - 0x1000, NVOBJ_FLAG_DONT_MAP | - NVOBJ_FLAG_ZERO_ALLOC, - &dev_priv->bar3_vm->pgt[0].obj[0]); - if (ret) - goto error; - dev_priv->bar3_vm->pgt[0].refcount[0] = 1; - - nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); - - ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan); - if (ret) - goto error; - dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan; - - ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE, - NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, - NV_MEM_TYPE_VM, NV_MEM_COMP_VM, - &priv->bar3_dmaobj); - if (ret) - goto error; - - nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); - nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); - nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4)); - - dev_priv->engine.instmem.flush(dev); - dev_priv->ramin_available = true; - - tmp = nv_ro32(chan->ramin, 0); - nv_wo32(chan->ramin, 0, ~tmp); - if (nv_ro32(chan->ramin, 0) != ~tmp) { - NV_ERROR(dev, "PRAMIN readback failed\n"); - ret = -EIO; - goto error; - } - nv_wo32(chan->ramin, 0, tmp); - - /* BAR1 */ - ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm); - if (ret) - goto error; + struct nouveau_fb *pfb = nouveau_fb(parent); + struct nv50_instobj_priv *node; + u32 align = (unsigned long)data; + int ret; - ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd); - if (ret) - goto error; - nouveau_vm_ref(NULL, &vm, NULL); + size = max((size + 4095) & ~4095, (u32)4096); + align = max((align + 4095) & ~4095, (u32)4096); - ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE, - NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, - NV_MEM_TYPE_VM, NV_MEM_COMP_VM, - &priv->bar1_dmaobj); + ret = nouveau_instobj_create(parent, engine, oclass, &node); + *pobject = nv_object(node); if (ret) - goto error; - - nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4)); - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); + return ret; - /* Create shared channel VM, space is reserved at the beginning - * to catch "NULL pointer" references - */ - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, - &dev_priv->chan_vm); + ret = pfb->ram.get(pfb, size, align, 0, 0x800, &node->mem); if (ret) return ret; + node->base.addr = node->mem->offset; + node->base.size = node->mem->size << 12; + node->mem->page_shift = 12; return 0; - -error: - nv50_instmem_takedown(dev); - return ret; } -void -nv50_instmem_takedown(struct drm_device *dev) +static void +nv50_instobj_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - - NV_DEBUG(dev, "\n"); - - if (!priv) - return; - - dev_priv->ramin_available = false; - - nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); - - for (i = 0x1700; i <= 0x1710; i += 4) - nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); - - nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj); - nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj); - - nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd); - dev_priv->channels.ptr[127] = 0; - nv50_channel_del(&dev_priv->channels.ptr[0]); - - nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); - nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); - - if (drm_mm_initialized(&dev_priv->ramin_heap)) - drm_mm_takedown(&dev_priv->ramin_heap); - - dev_priv->engine.instmem.priv = NULL; - kfree(priv); + struct nv50_instobj_priv *node = (void *)object; + struct nouveau_fb *pfb = nouveau_fb(object); + pfb->ram.put(pfb, &node->mem); + nouveau_instobj_destroy(&node->base); } -int -nv50_instmem_suspend(struct drm_device *dev) +static u32 +nv50_instobj_rd32(struct nouveau_object *object, u32 offset) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - dev_priv->ramin_available = false; - return 0; + struct nv50_instmem_priv *priv = (void *)object->engine; + struct nv50_instobj_priv *node = (void *)object; + unsigned long flags; + u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; + u32 data; + + spin_lock_irqsave(&priv->lock, flags); + if (unlikely(priv->addr != base)) { + nv_wr32(priv, 0x001700, base >> 16); + priv->addr = base; + } + data = nv_rd32(priv, 0x700000 + addr); + spin_unlock_irqrestore(&priv->lock, flags); + return data; } -void -nv50_instmem_resume(struct drm_device *dev) +static void +nv50_instobj_wr32(struct nouveau_object *object, u32 offset, u32 data) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - - /* Poke the relevant regs, and pray it works :) */ - nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12)); - nv_wr32(dev, NV50_PUNK_UNK1710, 0); - nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | - NV50_PUNK_BAR_CFG_BASE_VALID); - nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) | - NV50_PUNK_BAR1_CTXDMA_VALID); - nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) | - NV50_PUNK_BAR3_CTXDMA_VALID); - - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); + struct nv50_instmem_priv *priv = (void *)object->engine; + struct nv50_instobj_priv *node = (void *)object; + unsigned long flags; + u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; - dev_priv->ramin_available = true; + spin_lock_irqsave(&priv->lock, flags); + if (unlikely(priv->addr != base)) { + nv_wr32(priv, 0x001700, base >> 16); + priv->addr = base; + } + nv_wr32(priv, 0x700000 + addr, data); + spin_unlock_irqrestore(&priv->lock, flags); } -struct nv50_gpuobj_node { - struct nouveau_mem *vram; - struct nouveau_vma chan_vma; - u32 align; +static struct nouveau_oclass +nv50_instobj_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_instobj_ctor, + .dtor = nv50_instobj_dtor, + .init = _nouveau_instobj_init, + .fini = _nouveau_instobj_fini, + .rd32 = nv50_instobj_rd32, + .wr32 = nv50_instobj_wr32, + }, }; -int -nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, - u32 size, u32 align) -{ - struct drm_device *dev = gpuobj->dev; - struct nv50_gpuobj_node *node = NULL; - int ret; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; - node->align = align; - - size = (size + 4095) & ~4095; - align = max(align, (u32)4096); - - ret = nvfb_vram_get(dev, size, align, 0, 0x800, &node->vram); - if (ret) { - kfree(node); - return ret; - } - - gpuobj->vinst = node->vram->offset; - gpuobj->size = size; - gpuobj->node = node; - return 0; -} - -void -nv50_instmem_put(struct nouveau_gpuobj *gpuobj) +static int +nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, + u32 size, u32 align, struct nouveau_object **pobject) { - struct drm_device *dev = gpuobj->dev; - struct nv50_gpuobj_node *node; - - node = gpuobj->node; - gpuobj->node = NULL; - - if (node->chan_vma.node) { - nouveau_vm_unmap(&node->chan_vma); - nouveau_vm_put(&node->chan_vma); - } - nvfb_vram_put(dev, &node->vram); - kfree(node); + struct nouveau_object *engine = nv_object(imem); + return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass, + (void *)(unsigned long)align, size, pobject); } -int -nv50_instmem_map(struct nouveau_gpuobj *gpuobj) +static int +nv50_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct nv50_gpuobj_node *node = gpuobj->node; + struct nv50_instmem_priv *priv; int ret; - ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12, - NV_MEM_ACCESS_RW, &node->vram->bar_vma); + ret = nouveau_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); if (ret) return ret; - nouveau_vm_map(&node->vram->bar_vma, node->vram); - gpuobj->pinst = node->vram->bar_vma.offset; + spin_lock_init(&priv->lock); + priv->base.alloc = nv50_instmem_alloc; return 0; } -void -nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) +static int +nv50_instmem_fini(struct nouveau_object *object, bool suspend) { - struct nv50_gpuobj_node *node = gpuobj->node; - - if (node->vram->bar_vma.node) { - nouveau_vm_unmap(&node->vram->bar_vma); - nouveau_vm_put(&node->vram->bar_vma); - } + struct nv50_instmem_priv *priv = (void *)object; + priv->addr = ~0ULL; + return nouveau_instmem_fini(&priv->base, suspend); } -void -nv50_instmem_flush(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x00330c, 0x00000001); - if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); -} - -void -nv84_instmem_flush(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x070000, 0x00000001); - if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); -} +struct nouveau_oclass +nv50_instmem_oclass = { + .handle = NV_SUBDEV(INSTMEM, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_instmem_ctor, + .dtor = _nouveau_instmem_dtor, + .init = _nouveau_instmem_init, + .fini = nv50_instmem_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c deleted file mode 100644 index 0ce9869..0000000 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nvc0.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2010 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: - * - * 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 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 "nouveau_drv.h" -#include - -struct nvc0_instmem_priv { - struct nouveau_gpuobj *bar1_pgd; - struct nouveau_channel *bar1; - struct nouveau_gpuobj *bar3_pgd; - struct nouveau_channel *bar3; -}; - -int -nvc0_instmem_suspend(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - dev_priv->ramin_available = false; - return 0; -} - -void -nvc0_instmem_resume(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; - - nv_mask(dev, 0x100c80, 0x00000001, 0x00000000); - nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12); - nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12); - dev_priv->ramin_available = true; -} - -static void -nvc0_channel_del(struct nouveau_channel **pchan) -{ - struct nouveau_channel *chan; - - chan = *pchan; - *pchan = NULL; - if (!chan) - return; - - nouveau_vm_ref(NULL, &chan->vm, NULL); - if (drm_mm_initialized(&chan->ramin_heap)) - drm_mm_takedown(&chan->ramin_heap); - nouveau_gpuobj_ref(NULL, &chan->ramin); - kfree(chan); -} - -static int -nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, - struct nouveau_channel **pchan, - struct nouveau_gpuobj *pgd, u64 vm_size) -{ - struct nouveau_channel *chan; - int ret; - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) - return -ENOMEM; - chan->dev = dev; - - ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); - if (ret) { - nvc0_channel_del(&chan); - return ret; - } - - ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000); - if (ret) { - nvc0_channel_del(&chan); - return ret; - } - - ret = nouveau_vm_ref(vm, &chan->vm, NULL); - if (ret) { - nvc0_channel_del(&chan); - return ret; - } - - nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst)); - nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst)); - nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1)); - nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1)); - - *pchan = chan; - return 0; -} - -int -nvc0_instmem_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct pci_dev *pdev = dev->pdev; - struct nvc0_instmem_priv *priv; - struct nouveau_vm *vm = NULL; - int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - pinstmem->priv = priv; - - /* BAR3 VM */ - ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0, - &dev_priv->bar3_vm); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, - (pci_resource_len(pdev, 3) >> 12) * 8, 0, - NVOBJ_FLAG_DONT_MAP | - NVOBJ_FLAG_ZERO_ALLOC, - &dev_priv->bar3_vm->pgt[0].obj[0]); - if (ret) - goto error; - dev_priv->bar3_vm->pgt[0].refcount[0] = 1; - - nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); - - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd); - if (ret) - goto error; - - ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd); - if (ret) - goto error; - nouveau_vm_ref(NULL, &vm, NULL); - - ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3, - priv->bar3_pgd, pci_resource_len(dev->pdev, 3)); - if (ret) - goto error; - - /* BAR1 VM */ - ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm); - if (ret) - goto error; - - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd); - if (ret) - goto error; - - ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd); - if (ret) - goto error; - nouveau_vm_ref(NULL, &vm, NULL); - - ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1, - priv->bar1_pgd, pci_resource_len(dev->pdev, 1)); - if (ret) - goto error; - - /* channel vm */ - ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, - &dev_priv->chan_vm); - if (ret) - goto error; - - nvc0_instmem_resume(dev); - return 0; -error: - nvc0_instmem_takedown(dev); - return ret; -} - -void -nvc0_instmem_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_vm *vm = NULL; - - nvc0_instmem_suspend(dev); - - nv_wr32(dev, 0x1704, 0x00000000); - nv_wr32(dev, 0x1714, 0x00000000); - - nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); - - nvc0_channel_del(&priv->bar1); - nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd); - nouveau_gpuobj_ref(NULL, &priv->bar1_pgd); - - nvc0_channel_del(&priv->bar3); - nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL); - nouveau_vm_ref(NULL, &vm, priv->bar3_pgd); - nouveau_gpuobj_ref(NULL, &priv->bar3_pgd); - nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); - nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); - - dev_priv->engine.instmem.priv = NULL; - kfree(priv); -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 9fb858a..b92b3d4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -22,22 +22,24 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" +#include #include + +#include #include void nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) { struct nouveau_vm *vm = vma->vm; + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_mm_node *r; - int big = vma->node->type != vm->spg_shift; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; delta = 0; @@ -53,7 +55,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) end = max; len = end - pte; - vm->map(vma, pgt, node, pte, len, phys, delta); + vmm->map(vma, pgt, node, pte, len, phys, delta); num -= len; pte += len; @@ -67,7 +69,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) } } - vm->flush(vm); + vmm->flush(vm); } void @@ -81,13 +83,14 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { struct nouveau_vm *vm = vma->vm; - int big = vma->node->type != vm->spg_shift; + struct nouveau_vmmgr *vmm = vm->vmm; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); unsigned m, sglen; u32 end, len; int i; @@ -105,7 +108,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, for (m = 0; m < len; m++) { dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - vm->map_sg(vma, pgt, mem, pte, 1, &addr); + vmm->map_sg(vma, pgt, mem, pte, 1, &addr); num--; pte++; @@ -120,7 +123,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, for (; m < sglen; m++) { dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - vm->map_sg(vma, pgt, mem, pte, 1, &addr); + vmm->map_sg(vma, pgt, mem, pte, 1, &addr); num--; pte++; if (num == 0) @@ -130,7 +133,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, } finish: - vm->flush(vm); + vmm->flush(vm); } void @@ -138,14 +141,15 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { struct nouveau_vm *vm = vma->vm; + struct nouveau_vmmgr *vmm = vm->vmm; dma_addr_t *list = mem->pages; - int big = vma->node->type != vm->spg_shift; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; while (num) { @@ -156,7 +160,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, end = max; len = end - pte; - vm->map_sg(vma, pgt, mem, pte, len, list); + vmm->map_sg(vma, pgt, mem, pte, len, list); num -= len; pte += len; @@ -167,20 +171,21 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, } } - vm->flush(vm); + vmm->flush(vm); } void nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) { struct nouveau_vm *vm = vma->vm; - int big = vma->node->type != vm->spg_shift; + struct nouveau_vmmgr *vmm = vm->vmm; + int big = vma->node->type != vmm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; u32 num = length >> vma->node->type; - u32 pde = (offset >> vm->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; - u32 max = 1 << (vm->pgt_bits - bits); + u32 pde = (offset >> vmm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vmm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vmm->pgt_bits - bits); u32 end, len; while (num) { @@ -191,7 +196,7 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) end = max; len = end - pte; - vm->unmap(pgt, pte, len); + vmm->unmap(pgt, pte, len); num -= len; pte += len; @@ -201,7 +206,7 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) } } - vm->flush(vm); + vmm->flush(vm); } void @@ -213,6 +218,7 @@ nouveau_vm_unmap(struct nouveau_vma *vma) static void nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) { + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_vm_pgd *vpgd; struct nouveau_vm_pgt *vpgt; struct nouveau_gpuobj *pgt; @@ -227,7 +233,7 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) vpgt->obj[big] = NULL; list_for_each_entry(vpgd, &vm->pgd_list, head) { - vm->map_pgt(vpgd->obj, pde, vpgt->obj); + vmm->map_pgt(vpgd->obj, pde, vpgt->obj); } mutex_unlock(&vm->mm.mutex); @@ -239,18 +245,19 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) static int nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) { + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; struct nouveau_vm_pgd *vpgd; struct nouveau_gpuobj *pgt; - int big = (type != vm->spg_shift); + int big = (type != vmm->spg_shift); u32 pgt_size; int ret; - pgt_size = (1 << (vm->pgt_bits + 12)) >> type; + pgt_size = (1 << (vmm->pgt_bits + 12)) >> type; pgt_size *= 8; mutex_unlock(&vm->mm.mutex); - ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, + ret = nouveau_gpuobj_new(nv_object(vm->vmm), NULL, pgt_size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &pgt); mutex_lock(&vm->mm.mutex); if (unlikely(ret)) @@ -266,7 +273,7 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) vpgt->obj[big] = pgt; list_for_each_entry(vpgd, &vm->pgd_list, head) { - vm->map_pgt(vpgd->obj, pde, vpgt->obj); + vmm->map_pgt(vpgd->obj, pde, vpgt->obj); } return 0; @@ -276,6 +283,7 @@ int nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, u32 access, struct nouveau_vma *vma) { + struct nouveau_vmmgr *vmm = vm->vmm; u32 align = (1 << page_shift) >> 12; u32 msize = size >> 12; u32 fpde, lpde, pde; @@ -289,11 +297,11 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, return ret; } - fpde = (vma->node->offset >> vm->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + fpde = (vma->node->offset >> vmm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vmm->pgt_bits; for (pde = fpde; pde <= lpde; pde++) { struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; - int big = (vma->node->type != vm->spg_shift); + int big = (vma->node->type != vmm->spg_shift); if (likely(vpgt->refcount[big])) { vpgt->refcount[big]++; @@ -321,90 +329,67 @@ void nouveau_vm_put(struct nouveau_vma *vma) { struct nouveau_vm *vm = vma->vm; + struct nouveau_vmmgr *vmm = vm->vmm; u32 fpde, lpde; if (unlikely(vma->node == NULL)) return; - fpde = (vma->node->offset >> vm->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + fpde = (vma->node->offset >> vmm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vmm->pgt_bits; mutex_lock(&vm->mm.mutex); - nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); + nouveau_vm_unmap_pgt(vm, vma->node->type != vmm->spg_shift, fpde, lpde); nouveau_mm_free(&vm->mm, &vma->node); mutex_unlock(&vm->mm.mutex); } int -nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, - struct nouveau_vm **pvm) +nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, + u64 mm_offset, u32 block, struct nouveau_vm **pvm) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_vm *vm; u64 mm_length = (offset + length) - mm_offset; - u32 block, pgt_bits; int ret; - vm = kzalloc(sizeof(*vm), GFP_KERNEL); + vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL); if (!vm) return -ENOMEM; - if (dev_priv->card_type == NV_50) { - vm->map_pgt = nv50_vm_map_pgt; - vm->map = nv50_vm_map; - vm->map_sg = nv50_vm_map_sg; - vm->unmap = nv50_vm_unmap; - vm->flush = nv50_vm_flush; - vm->spg_shift = 12; - vm->lpg_shift = 16; - - pgt_bits = 29; - block = (1 << pgt_bits); - if (length < block) - block = length; - - } else - if (dev_priv->card_type >= NV_C0) { - vm->map_pgt = nvc0_vm_map_pgt; - vm->map = nvc0_vm_map; - vm->map_sg = nvc0_vm_map_sg; - vm->unmap = nvc0_vm_unmap; - vm->flush = nvc0_vm_flush; - vm->spg_shift = 12; - vm->lpg_shift = 17; - pgt_bits = 27; - block = 4096; - } else { - kfree(vm); - return -ENOSYS; - } + INIT_LIST_HEAD(&vm->pgd_list); + vm->vmm = vmm; + vm->refcount = 1; + vm->fpde = offset >> (vmm->pgt_bits + 12); + vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); - vm->fpde = offset >> pgt_bits; - vm->lpde = (offset + length - 1) >> pgt_bits; - vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); + vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); if (!vm->pgt) { kfree(vm); return -ENOMEM; } - INIT_LIST_HEAD(&vm->pgd_list); - vm->dev = dev; - vm->refcount = 1; - vm->pgt_bits = pgt_bits - 12; - ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12, block >> 12); if (ret) { + kfree(vm->pgt); kfree(vm); return ret; } - *pvm = vm; return 0; } +int +nouveau_vm_new(struct nouveau_device *device, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **pvm) +{ + struct nouveau_vmmgr *vmm = nouveau_vmmgr(device); + return vmm->create(vmm, offset, length, mm_offset, pvm); +} + static int nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) { + struct nouveau_vmmgr *vmm = vm->vmm; struct nouveau_vm_pgd *vpgd; int i; @@ -419,7 +404,7 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) mutex_lock(&vm->mm.mutex); for (i = vm->fpde; i <= vm->lpde; i++) - vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); + vmm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); list_add(&vpgd->head, &vm->pgd_list); mutex_unlock(&vm->mm.mutex); return 0; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c new file mode 100644 index 0000000..6475c02 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -0,0 +1,150 @@ +/* + * 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: + * + * 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 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 + +#include "nv04.h" + +#define NV04_PDMA_SIZE (128 * 1024 * 1024) +#define NV04_PDMA_PAGE ( 4 * 1024) + +/******************************************************************************* + * VM map/unmap callbacks + ******************************************************************************/ + +static void +nv04_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + pte = 0x00008 + (pte * 4); + while (cnt) { + u32 page = PAGE_SIZE / NV04_PDMA_PAGE; + u32 phys = (u32)*list++; + while (cnt && page--) { + nv_wo32(pgt, pte, phys | 3); + phys += NV04_PDMA_PAGE; + pte += 4; + cnt -= 1; + } + } +} + +static void +nv04_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte = 0x00008 + (pte * 4); + while (cnt--) { + nv_wo32(pgt, pte, 0x00000000); + pte += 4; + } +} + +static void +nv04_vm_flush(struct nouveau_vm *vm) +{ +} + +/******************************************************************************* + * VM object + ******************************************************************************/ + +int +nv04_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, u64 mmstart, + struct nouveau_vm **pvm) +{ + return -EINVAL; +} + +/******************************************************************************* + * VMMGR subdev + ******************************************************************************/ + +static int +nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_vmmgr_priv *priv; + struct nouveau_gpuobj *dma; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIGART", + "pcigart", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.create = nv04_vm_create; + priv->base.pgt_bits = 32 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 12; + priv->base.map_sg = nv04_vm_map_sg; + priv->base.unmap = nv04_vm_unmap; + priv->base.flush = nv04_vm_flush; + + ret = nouveau_vm_create(&priv->base, 0, NV04_PDMA_SIZE, 0, 4096, + &priv->vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + + 8, 16, NVOBJ_FLAG_ZERO_ALLOC, + &priv->vm->pgt[0].obj[0]); + dma = priv->vm->pgt[0].obj[0]; + priv->vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + nv_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */ + nv_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1); + return 0; +} + +void +nv04_vmmgr_dtor(struct nouveau_object *object) +{ + struct nv04_vmmgr_priv *priv = (void *)object; + if (priv->vm) { + nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->vm, NULL); + } + if (priv->page) { + pci_unmap_page(nv_device(priv)->pdev, priv->null, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + __free_page(priv->page); + } + nouveau_vmmgr_destroy(&priv->base); +} + +struct nouveau_oclass +nv04_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_vmmgr_ctor, + .dtor = nv04_vmmgr_dtor, + .init = _nouveau_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h new file mode 100644 index 0000000..5309303 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h @@ -0,0 +1,13 @@ +#ifndef __NV04_VMMGR_PRIV__ +#define __NV04_VMMGR_PRIV__ + +#include + +struct nv04_vmmgr_priv { + struct nouveau_vmmgr base; + struct nouveau_vm *vm; + struct page *page; + dma_addr_t null; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c new file mode 100644 index 0000000..f036770 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -0,0 +1,149 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +#include "nv04.h" + +#define NV41_GART_SIZE (512 * 1024 * 1024) +#define NV41_GART_PAGE ( 4 * 1024) + +/******************************************************************************* + * VM map/unmap callbacks + ******************************************************************************/ + +static void +nv41_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + pte = pte * 4; + while (cnt) { + u32 page = PAGE_SIZE / NV41_GART_PAGE; + u64 phys = (u64)*list++; + while (cnt && page--) { + nv_wo32(pgt, pte, (phys >> 7) | 1); + phys += NV41_GART_PAGE; + pte += 4; + cnt -= 1; + } + } +} + +static void +nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte = pte * 4; + while (cnt--) { + nv_wo32(pgt, pte, 0x00000000); + pte += 4; + } +} + +static void +nv41_vm_flush(struct nouveau_vm *vm) +{ + struct nv04_vm_priv *priv = (void *)vm->vmm; + + mutex_lock(&nv_subdev(priv)->mutex); + nv_wr32(priv, 0x100810, 0x00000022); + if (!nv_wait(priv, 0x100810, 0x00000100, 0x00000100)) { + nv_warn(priv, "flush timeout, 0x%08x\n", + nv_rd32(priv, 0x100810)); + } + nv_wr32(priv, 0x100810, 0x00000000); + mutex_unlock(&nv_subdev(priv)->mutex); +} + +/******************************************************************************* + * VMMGR subdev + ******************************************************************************/ + +static int +nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", + "pciegart", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.create = nv04_vm_create; + priv->base.pgt_bits = 32 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 12; + priv->base.map_sg = nv41_vm_map_sg; + priv->base.unmap = nv41_vm_unmap; + priv->base.flush = nv41_vm_flush; + + ret = nouveau_vm_create(&priv->base, 0, NV41_GART_SIZE, 0, 4096, + &priv->vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (NV41_GART_SIZE / NV41_GART_PAGE) * 4, + 16, NVOBJ_FLAG_ZERO_ALLOC, + &priv->vm->pgt[0].obj[0]); + priv->vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + return 0; +} + +static int +nv41_vmmgr_init(struct nouveau_object *object) +{ + struct nv04_vmmgr_priv *priv = (void *)object; + struct nouveau_gpuobj *dma = priv->vm->pgt[0].obj[0]; + int ret; + + ret = nouveau_vmmgr_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, 0x100800, dma->addr | 0x00000002); + nv_mask(priv, 0x10008c, 0x00000100, 0x00000100); + nv_wr32(priv, 0x100820, 0x00000000); + return 0; +} + +struct nouveau_oclass +nv41_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x41), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv41_vmmgr_ctor, + .dtor = nv04_vmmgr_dtor, + .init = nv41_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c new file mode 100644 index 0000000..d17f761 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -0,0 +1,257 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +#include "nv04.h" + +#define NV44_GART_SIZE (512 * 1024 * 1024) +#define NV44_GART_PAGE ( 4 * 1024) + +/******************************************************************************* + * VM map/unmap callbacks + ******************************************************************************/ + +static void +nv44_vm_flush_priv(struct nv04_vmmgr_priv *priv, u32 base, u32 size) +{ + nv_wr32(priv, 0x100814, (size - 1) << 12); + nv_wr32(priv, 0x100808, base | 0x20); + if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001)) + nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808)); + nv_wr32(priv, 0x100808, 0x00000000); +} + +static void +nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null, + dma_addr_t *list, u32 pte, u32 cnt) +{ + u32 base = (pte << 2) & ~0x0000000f; + u32 tmp[4]; + + tmp[0] = nv_ro32(pgt, base + 0x0); + tmp[1] = nv_ro32(pgt, base + 0x4); + tmp[2] = nv_ro32(pgt, base + 0x8); + tmp[3] = nv_ro32(pgt, base + 0xc); + while (cnt--) { + u32 addr = list ? (*list++ >> 12) : (null >> 12); + switch (pte++ & 0x3) { + case 0: + tmp[0] &= ~0x07ffffff; + tmp[0] |= addr; + break; + case 1: + tmp[0] &= ~0xf8000000; + tmp[0] |= addr << 27; + tmp[1] &= ~0x003fffff; + tmp[1] |= addr >> 5; + break; + case 2: + tmp[1] &= ~0xffc00000; + tmp[1] |= addr << 22; + tmp[2] &= ~0x0001ffff; + tmp[2] |= addr >> 10; + break; + case 3: + tmp[2] &= ~0xfffe0000; + tmp[2] |= addr << 17; + tmp[3] &= ~0x00000fff; + tmp[3] |= addr >> 15; + break; + } + } + + nv_wo32(pgt, base + 0x0, tmp[0]); + nv_wo32(pgt, base + 0x4, tmp[1]); + nv_wo32(pgt, base + 0x8, tmp[2]); + nv_wo32(pgt, base + 0xc, tmp[3] | 0x40000000); +} + +static void +nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) +{ + struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm; + u32 base = pte << 12; + u32 size = cnt; + u32 tmp[4]; + int i; + + if (pte & 3) { + u32 max = 4 - (pte & 3); + u32 part = (cnt > max) ? max : cnt; + nv44_vm_fill(pgt, priv->null, list, pte, part); + pte += part; + list += part; + cnt -= part; + } + + while (cnt >= 4) { + for (i = 0; i < 4; i++) + tmp[i] = *list++ >> 12; + nv_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27); + nv_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22); + nv_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17); + nv_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000); + cnt -= 4; + } + + if (cnt) + nv44_vm_fill(pgt, priv->null, list, pte, cnt); + nv44_vm_flush_priv(priv, base, size); +} + +static void +nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt); + u32 base = pte << 12; + u32 size = cnt; + + if (pte & 3) { + u32 max = 4 - (pte & 3); + u32 part = (cnt > max) ? max : cnt; + nv44_vm_fill(pgt, priv->null, NULL, pte, part); + pte += part; + cnt -= part; + } + + while (cnt >= 4) { + nv_wo32(pgt, pte++ * 4, 0x00000000); + nv_wo32(pgt, pte++ * 4, 0x00000000); + nv_wo32(pgt, pte++ * 4, 0x00000000); + nv_wo32(pgt, pte++ * 4, 0x00000000); + cnt -= 4; + } + + if (cnt) + nv44_vm_fill(pgt, priv->null, NULL, pte, cnt); + nv44_vm_flush_priv(priv, base, size); +} + +static void +nv44_vm_flush(struct nouveau_vm *vm) +{ +} + +/******************************************************************************* + * VMMGR subdev + ******************************************************************************/ + +static int +nv44_vmmgr_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 nv04_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", + "pciegart", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.create = nv04_vm_create; + priv->base.pgt_bits = 32 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 12; + priv->base.map_sg = nv44_vm_map_sg; + priv->base.unmap = nv44_vm_unmap; + priv->base.flush = nv44_vm_flush; + + priv->page = alloc_page(GFP_DMA32 | GFP_KERNEL); + if (priv->page) { + priv->null = pci_map_page(device->pdev, priv->page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, priv->null)) { + __free_page(priv->page); + priv->page = NULL; + priv->null = 0; + } + } + + if (!priv->page) + nv_warn(priv, "unable to allocate dummy page\n"); + + ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096, + &priv->vm); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, + (NV44_GART_SIZE / NV44_GART_PAGE) * 4, + 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC, + &priv->vm->pgt[0].obj[0]); + priv->vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + + return 0; +} + +static int +nv44_vmmgr_init(struct nouveau_object *object) +{ + struct nv04_vmmgr_priv *priv = (void *)object; + struct nouveau_gpuobj *gart = priv->vm->pgt[0].obj[0]; + u32 addr; + int ret; + + ret = nouveau_vmmgr_init(&priv->base); + if (ret) + return ret; + + /* calculate vram address of this PRAMIN block, object must be + * allocated on 512KiB alignment, and not exceed a total size + * of 512KiB for this to work correctly + */ + addr = nv_rd32(priv, 0x10020c); + addr -= ((gart->addr >> 19) + 1) << 19; + + nv_wr32(priv, 0x100850, 0x80000000); + nv_wr32(priv, 0x100818, priv->null); + nv_wr32(priv, 0x100804, NV44_GART_SIZE); + nv_wr32(priv, 0x100850, 0x00008000); + nv_mask(priv, 0x10008c, 0x00000200, 0x00000200); + nv_wr32(priv, 0x100820, 0x00000000); + nv_wr32(priv, 0x10082c, 0x00000001); + nv_wr32(priv, 0x100800, addr | 0x00000010); + return 0; +} + +struct nouveau_oclass +nv44_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x44), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv44_vmmgr_ctor, + .dtor = nv04_vmmgr_dtor, + .init = nv44_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 7e46826d..6e9bcd2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -22,11 +22,18 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include -#include "nouveau_drv.h" +#include +#include #include +struct nv50_vmmgr_priv { + struct nouveau_vmmgr base; + spinlock_t lock; +}; + void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]) @@ -35,11 +42,11 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, u32 coverage = 0; if (pgt[0]) { - phys = 0x00000003 | pgt[0]->vinst; /* present, 4KiB pages */ + phys = 0x00000003 | pgt[0]->addr; /* present, 4KiB pages */ coverage = (pgt[0]->size >> 3) << 12; } else if (pgt[1]) { - phys = 0x00000001 | pgt[1]->vinst; /* present */ + phys = 0x00000001 | pgt[1]->addr; /* present */ coverage = (pgt[1]->size >> 3) << 16; } @@ -73,15 +80,14 @@ void nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { - struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; u32 comp = (mem->memtype & 0x180) >> 7; u32 block, target; int i; /* IGPs don't have real VRAM, re-target to stolen system memory */ target = 0; - if (nvfb_vram_sys_base(dev_priv->dev)) { - phys += nvfb_vram_sys_base(dev_priv->dev); + if (nouveau_fb(vma->vm->vmm)->ram.stolen) { + phys += nouveau_fb(vma->vm->vmm)->ram.stolen; target = 3; } @@ -145,33 +151,81 @@ nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) void nv50_vm_flush(struct nouveau_vm *vm) { - struct drm_nouveau_private *dev_priv = vm->dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nouveau_engine *engine; int i; - pinstmem->flush(vm->dev); - - /* BAR */ - if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) { - nv50_vm_flush_engine(vm->dev, 6); - return; - } - - for (i = 0; i < NVOBJ_ENGINE_NR; i++) { - if (atomic_read(&vm->engref[i])) - dev_priv->eng[i]->tlb_flush(vm->dev, i); +#if 0 + for (i = 0; i < NVDEV_SUBDEV_NR; i++) { + if (atomic_read(&vm->engref[i])) { + engine = nouveau_engine(vm->vmm, i); + if (engine && engine->tlb_flush) + engine->tlb_flush(engine); + } } +#else + nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x06); /* bar */ + nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x05); /* fifo */ + nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x00); /* gr */ +#endif } void -nv50_vm_flush_engine(struct drm_device *dev, int engine) +nv50_vm_flush_engine(struct nouveau_subdev *subdev, int engine) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_vmmgr_priv *priv = (void *)nouveau_vmmgr(subdev); unsigned long flags; - spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) - NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + spin_lock_irqsave(&priv->lock, flags); + nv_wr32(subdev, 0x100c80, (engine << 16) | 1); + if (!nv_wait(subdev, 0x100c80, 0x00000001, 0x00000000)) + nv_error(subdev, "vm flush timeout: engine %d\n", engine); + spin_unlock_irqrestore(&priv->lock, flags); } + +static int +nv50_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **pvm) +{ + u32 block = (1 << (vmm->pgt_bits + 12)); + if (block > length) + block = length; + + return nouveau_vm_create(vmm, offset, length, mm_offset, block, pvm); +} + +static int +nv50_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "VM", "vm", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pgt_bits = 29 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 16; + priv->base.create = nv50_vm_create; + priv->base.map_pgt = nv50_vm_map_pgt; + priv->base.map = nv50_vm_map; + priv->base.map_sg = nv50_vm_map_sg; + priv->base.unmap = nv50_vm_unmap; + priv->base.flush = nv50_vm_flush; + spin_lock_init(&priv->lock); + return 0; +} + +struct nouveau_oclass +nv50_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_vmmgr_ctor, + .dtor = _nouveau_vmmgr_dtor, + .init = _nouveau_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index 734877a..a0bc0f6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -22,11 +22,18 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include -#include "nouveau_drv.h" +#include +#include #include +struct nvc0_vmmgr_priv { + struct nouveau_vmmgr base; + spinlock_t lock; +}; + void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, struct nouveau_gpuobj *pgt[2]) @@ -34,9 +41,9 @@ nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, u32 pde[2] = { 0, 0 }; if (pgt[0]) - pde[1] = 0x00000001 | (pgt[0]->vinst >> 8); + pde[1] = 0x00000001 | (pgt[0]->addr >> 8); if (pgt[1]) - pde[0] = 0x00000001 | (pgt[1]->vinst >> 8); + pde[0] = 0x00000001 | (pgt[1]->addr >> 8); nv_wo32(pgd, (index * 8) + 0, pde[0]); nv_wo32(pgd, (index * 8) + 4, pde[1]); @@ -100,37 +107,81 @@ nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } void -nvc0_vm_flush(struct nouveau_vm *vm) +nvc0_vm_flush_engine(struct nouveau_subdev *subdev, u64 addr, int type) { - struct drm_nouveau_private *dev_priv = vm->dev->dev_private; - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct drm_device *dev = vm->dev; - struct nouveau_vm_pgd *vpgd; + struct nvc0_vmmgr_priv *priv = (void *)nouveau_vmmgr(subdev); unsigned long flags; - u32 engine; - engine = 1; - if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) - engine |= 4; + /* looks like maybe a "free flush slots" counter, the + * faster you write to 0x100cbc to more it decreases + */ + spin_lock_irqsave(&priv->lock, flags); + if (!nv_wait_ne(subdev, 0x100c80, 0x00ff0000, 0x00000000)) { + nv_error(subdev, "vm timeout 0: 0x%08x %d\n", + nv_rd32(subdev, 0x100c80), type); + } + + nv_wr32(subdev, 0x100cb8, addr >> 8); + nv_wr32(subdev, 0x100cbc, 0x80000000 | type); - pinstmem->flush(vm->dev); + /* wait for flush to be queued? */ + if (!nv_wait(subdev, 0x100c80, 0x00008000, 0x00008000)) { + nv_error(subdev, "vm timeout 1: 0x%08x %d\n", + nv_rd32(subdev, 0x100c80), type); + } + spin_unlock_irqrestore(&priv->lock, flags); +} + +void +nvc0_vm_flush(struct nouveau_vm *vm) +{ + struct nouveau_vm_pgd *vpgd; - spin_lock_irqsave(&dev_priv->vm_lock, flags); list_for_each_entry(vpgd, &vm->pgd_list, head) { - /* looks like maybe a "free flush slots" counter, the - * faster you write to 0x100cbc to more it decreases - */ - if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { - NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", - nv_rd32(dev, 0x100c80), engine); - } - nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); - nv_wr32(dev, 0x100cbc, 0x80000000 | engine); - /* wait for flush to be queued? */ - if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { - NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", - nv_rd32(dev, 0x100c80), engine); - } + nvc0_vm_flush_engine(nv_subdev(vm->vmm), vpgd->obj->addr, 1); } - spin_unlock_irqrestore(&dev_priv->vm_lock, flags); } + +static int +nvc0_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, + u64 mm_offset, struct nouveau_vm **pvm) +{ + return nouveau_vm_create(vmm, offset, length, mm_offset, 4096, pvm); +} + +static int +nvc0_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_vmmgr_priv *priv; + int ret; + + ret = nouveau_vmmgr_create(parent, engine, oclass, "VM", "vm", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.pgt_bits = 27 - 12; + priv->base.spg_shift = 12; + priv->base.lpg_shift = 17; + priv->base.create = nvc0_vm_create; + priv->base.map_pgt = nvc0_vm_map_pgt; + priv->base.map = nvc0_vm_map; + priv->base.map_sg = nvc0_vm_map_sg; + priv->base.unmap = nvc0_vm_unmap; + priv->base.flush = nvc0_vm_flush; + spin_lock_init(&priv->lock); + return 0; +} + +struct nouveau_oclass +nvc0_vmmgr_oclass = { + .handle = NV_SUBDEV(VM, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_vmmgr_ctor, + .dtor = _nouveau_vmmgr_dtor, + .init = _nouveau_vmmgr_init, + .fini = _nouveau_vmmgr_fini, + }, +}; -- cgit v1.1 From a73c5c526a8a39b2e61709c753d44be597c9a4c0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 19 Jul 2012 17:32:01 +1000 Subject: drm/nvc0-nve0/graph: rename dev to priv, no code changes There's a *lot* of code in here, and it's all going to use the PGRAPH priv pointer rather than drm_device after the engine rework. This is handling all the rename-only parts of the change. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 5156 +++++++++---------- .../gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 5184 ++++++++++---------- 2 files changed, 5170 insertions(+), 5170 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index 5083fda..af6167a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -28,1844 +28,1844 @@ #include "nvc0.h" static void -nv_icmd(struct drm_device *dev, u32 icmd, u32 data) +nv_icmd(struct drm_device *priv, u32 icmd, u32 data) { - nv_wr32(dev, 0x400204, data); - nv_wr32(dev, 0x400200, icmd); - while (nv_rd32(dev, 0x400700) & 2) {} + nv_wr32(priv, 0x400204, data); + nv_wr32(priv, 0x400200, icmd); + while (nv_rd32(priv, 0x400700) & 2) {} } static void -nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data) +nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) { - nv_wr32(dev, 0x40448c, data); - nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class); + nv_wr32(priv, 0x40448c, data); + nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); } static void -nvc0_grctx_generate_9097(struct drm_device *dev) +nvc0_grctx_generate_9097(struct drm_device *priv) { - u32 fermi = nvc0_graph_class(dev); + u32 fermi = nvc0_graph_class(priv); u32 mthd; - nv_mthd(dev, 0x9097, 0x0800, 0x00000000); - nv_mthd(dev, 0x9097, 0x0840, 0x00000000); - nv_mthd(dev, 0x9097, 0x0880, 0x00000000); - nv_mthd(dev, 0x9097, 0x08c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0900, 0x00000000); - nv_mthd(dev, 0x9097, 0x0940, 0x00000000); - nv_mthd(dev, 0x9097, 0x0980, 0x00000000); - nv_mthd(dev, 0x9097, 0x09c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0804, 0x00000000); - nv_mthd(dev, 0x9097, 0x0844, 0x00000000); - nv_mthd(dev, 0x9097, 0x0884, 0x00000000); - nv_mthd(dev, 0x9097, 0x08c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0904, 0x00000000); - nv_mthd(dev, 0x9097, 0x0944, 0x00000000); - nv_mthd(dev, 0x9097, 0x0984, 0x00000000); - nv_mthd(dev, 0x9097, 0x09c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0808, 0x00000400); - nv_mthd(dev, 0x9097, 0x0848, 0x00000400); - nv_mthd(dev, 0x9097, 0x0888, 0x00000400); - nv_mthd(dev, 0x9097, 0x08c8, 0x00000400); - nv_mthd(dev, 0x9097, 0x0908, 0x00000400); - nv_mthd(dev, 0x9097, 0x0948, 0x00000400); - nv_mthd(dev, 0x9097, 0x0988, 0x00000400); - nv_mthd(dev, 0x9097, 0x09c8, 0x00000400); - nv_mthd(dev, 0x9097, 0x080c, 0x00000300); - nv_mthd(dev, 0x9097, 0x084c, 0x00000300); - nv_mthd(dev, 0x9097, 0x088c, 0x00000300); - nv_mthd(dev, 0x9097, 0x08cc, 0x00000300); - nv_mthd(dev, 0x9097, 0x090c, 0x00000300); - nv_mthd(dev, 0x9097, 0x094c, 0x00000300); - nv_mthd(dev, 0x9097, 0x098c, 0x00000300); - nv_mthd(dev, 0x9097, 0x09cc, 0x00000300); - nv_mthd(dev, 0x9097, 0x0810, 0x000000cf); - nv_mthd(dev, 0x9097, 0x0850, 0x00000000); - nv_mthd(dev, 0x9097, 0x0890, 0x00000000); - nv_mthd(dev, 0x9097, 0x08d0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0910, 0x00000000); - nv_mthd(dev, 0x9097, 0x0950, 0x00000000); - nv_mthd(dev, 0x9097, 0x0990, 0x00000000); - nv_mthd(dev, 0x9097, 0x09d0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0814, 0x00000040); - nv_mthd(dev, 0x9097, 0x0854, 0x00000040); - nv_mthd(dev, 0x9097, 0x0894, 0x00000040); - nv_mthd(dev, 0x9097, 0x08d4, 0x00000040); - nv_mthd(dev, 0x9097, 0x0914, 0x00000040); - nv_mthd(dev, 0x9097, 0x0954, 0x00000040); - nv_mthd(dev, 0x9097, 0x0994, 0x00000040); - nv_mthd(dev, 0x9097, 0x09d4, 0x00000040); - nv_mthd(dev, 0x9097, 0x0818, 0x00000001); - nv_mthd(dev, 0x9097, 0x0858, 0x00000001); - nv_mthd(dev, 0x9097, 0x0898, 0x00000001); - nv_mthd(dev, 0x9097, 0x08d8, 0x00000001); - nv_mthd(dev, 0x9097, 0x0918, 0x00000001); - nv_mthd(dev, 0x9097, 0x0958, 0x00000001); - nv_mthd(dev, 0x9097, 0x0998, 0x00000001); - nv_mthd(dev, 0x9097, 0x09d8, 0x00000001); - nv_mthd(dev, 0x9097, 0x081c, 0x00000000); - nv_mthd(dev, 0x9097, 0x085c, 0x00000000); - nv_mthd(dev, 0x9097, 0x089c, 0x00000000); - nv_mthd(dev, 0x9097, 0x08dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x091c, 0x00000000); - nv_mthd(dev, 0x9097, 0x095c, 0x00000000); - nv_mthd(dev, 0x9097, 0x099c, 0x00000000); - nv_mthd(dev, 0x9097, 0x09dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0820, 0x00000000); - nv_mthd(dev, 0x9097, 0x0860, 0x00000000); - nv_mthd(dev, 0x9097, 0x08a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x08e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0920, 0x00000000); - nv_mthd(dev, 0x9097, 0x0960, 0x00000000); - nv_mthd(dev, 0x9097, 0x09a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x09e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x2700, 0x00000000); - nv_mthd(dev, 0x9097, 0x2720, 0x00000000); - nv_mthd(dev, 0x9097, 0x2740, 0x00000000); - nv_mthd(dev, 0x9097, 0x2760, 0x00000000); - nv_mthd(dev, 0x9097, 0x2780, 0x00000000); - nv_mthd(dev, 0x9097, 0x27a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x27c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x27e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x2704, 0x00000000); - nv_mthd(dev, 0x9097, 0x2724, 0x00000000); - nv_mthd(dev, 0x9097, 0x2744, 0x00000000); - nv_mthd(dev, 0x9097, 0x2764, 0x00000000); - nv_mthd(dev, 0x9097, 0x2784, 0x00000000); - nv_mthd(dev, 0x9097, 0x27a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x27c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x27e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x2708, 0x00000000); - nv_mthd(dev, 0x9097, 0x2728, 0x00000000); - nv_mthd(dev, 0x9097, 0x2748, 0x00000000); - nv_mthd(dev, 0x9097, 0x2768, 0x00000000); - nv_mthd(dev, 0x9097, 0x2788, 0x00000000); - nv_mthd(dev, 0x9097, 0x27a8, 0x00000000); - nv_mthd(dev, 0x9097, 0x27c8, 0x00000000); - nv_mthd(dev, 0x9097, 0x27e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x270c, 0x00000000); - nv_mthd(dev, 0x9097, 0x272c, 0x00000000); - nv_mthd(dev, 0x9097, 0x274c, 0x00000000); - nv_mthd(dev, 0x9097, 0x276c, 0x00000000); - nv_mthd(dev, 0x9097, 0x278c, 0x00000000); - nv_mthd(dev, 0x9097, 0x27ac, 0x00000000); - nv_mthd(dev, 0x9097, 0x27cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x27ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x2710, 0x00014000); - nv_mthd(dev, 0x9097, 0x2730, 0x00014000); - nv_mthd(dev, 0x9097, 0x2750, 0x00014000); - nv_mthd(dev, 0x9097, 0x2770, 0x00014000); - nv_mthd(dev, 0x9097, 0x2790, 0x00014000); - nv_mthd(dev, 0x9097, 0x27b0, 0x00014000); - nv_mthd(dev, 0x9097, 0x27d0, 0x00014000); - nv_mthd(dev, 0x9097, 0x27f0, 0x00014000); - nv_mthd(dev, 0x9097, 0x2714, 0x00000040); - nv_mthd(dev, 0x9097, 0x2734, 0x00000040); - nv_mthd(dev, 0x9097, 0x2754, 0x00000040); - nv_mthd(dev, 0x9097, 0x2774, 0x00000040); - nv_mthd(dev, 0x9097, 0x2794, 0x00000040); - nv_mthd(dev, 0x9097, 0x27b4, 0x00000040); - nv_mthd(dev, 0x9097, 0x27d4, 0x00000040); - nv_mthd(dev, 0x9097, 0x27f4, 0x00000040); - nv_mthd(dev, 0x9097, 0x1c00, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c10, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c20, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c30, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c40, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c50, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c60, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c70, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c80, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c90, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ca0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cb0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cc0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cd0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ce0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cf0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c04, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c14, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c24, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c34, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c44, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c54, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c64, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c74, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c84, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c94, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ca4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cb4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cc4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cd4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ce4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cf4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c08, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c18, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c28, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c38, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c48, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c58, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c68, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c78, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c88, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c98, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ca8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cb8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cc8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cd8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ce8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cf8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c0c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c1c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c2c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c3c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c4c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c5c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c6c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c7c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1c9c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cac, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cbc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ccc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cdc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cec, 0x00000000); - nv_mthd(dev, 0x9097, 0x1cfc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d00, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d10, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d20, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d30, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d40, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d50, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d60, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d70, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d80, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d90, 0x00000000); - nv_mthd(dev, 0x9097, 0x1da0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1db0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dc0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dd0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1de0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1df0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d04, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d14, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d24, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d34, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d44, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d54, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d64, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d74, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d84, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d94, 0x00000000); - nv_mthd(dev, 0x9097, 0x1da4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1db4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dc4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dd4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1de4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1df4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d08, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d18, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d28, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d38, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d48, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d58, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d68, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d78, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d88, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d98, 0x00000000); - nv_mthd(dev, 0x9097, 0x1da8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1db8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dc8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dd8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1de8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1df8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d0c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d1c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d2c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d3c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d4c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d5c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d6c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d7c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1d9c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dac, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dbc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dcc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ddc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dec, 0x00000000); - nv_mthd(dev, 0x9097, 0x1dfc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f00, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f08, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f10, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f18, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f20, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f28, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f30, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f38, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f40, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f48, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f50, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f58, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f60, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f68, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f70, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f78, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f04, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f0c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f14, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f1c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f24, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f2c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f34, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f3c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f44, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f4c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f54, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f5c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f64, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f6c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f74, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f7c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f80, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f88, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f90, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f98, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fa0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fa8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fb0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fb8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fc0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fc8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fd0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fd8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fe0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fe8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ff0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ff8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f84, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f94, 0x00000000); - nv_mthd(dev, 0x9097, 0x1f9c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fa4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fac, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fb4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fbc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fc4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fcc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fd4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fdc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fe4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1fec, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ff4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1ffc, 0x00000000); - nv_mthd(dev, 0x9097, 0x2200, 0x00000022); - nv_mthd(dev, 0x9097, 0x2210, 0x00000022); - nv_mthd(dev, 0x9097, 0x2220, 0x00000022); - nv_mthd(dev, 0x9097, 0x2230, 0x00000022); - nv_mthd(dev, 0x9097, 0x2240, 0x00000022); - nv_mthd(dev, 0x9097, 0x2000, 0x00000000); - nv_mthd(dev, 0x9097, 0x2040, 0x00000011); - nv_mthd(dev, 0x9097, 0x2080, 0x00000020); - nv_mthd(dev, 0x9097, 0x20c0, 0x00000030); - nv_mthd(dev, 0x9097, 0x2100, 0x00000040); - nv_mthd(dev, 0x9097, 0x2140, 0x00000051); - nv_mthd(dev, 0x9097, 0x200c, 0x00000001); - nv_mthd(dev, 0x9097, 0x204c, 0x00000001); - nv_mthd(dev, 0x9097, 0x208c, 0x00000001); - nv_mthd(dev, 0x9097, 0x20cc, 0x00000001); - nv_mthd(dev, 0x9097, 0x210c, 0x00000001); - nv_mthd(dev, 0x9097, 0x214c, 0x00000001); - nv_mthd(dev, 0x9097, 0x2010, 0x00000000); - nv_mthd(dev, 0x9097, 0x2050, 0x00000000); - nv_mthd(dev, 0x9097, 0x2090, 0x00000001); - nv_mthd(dev, 0x9097, 0x20d0, 0x00000002); - nv_mthd(dev, 0x9097, 0x2110, 0x00000003); - nv_mthd(dev, 0x9097, 0x2150, 0x00000004); - nv_mthd(dev, 0x9097, 0x0380, 0x00000000); - nv_mthd(dev, 0x9097, 0x03a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x03c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x03e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0384, 0x00000000); - nv_mthd(dev, 0x9097, 0x03a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x03c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x03e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0388, 0x00000000); - nv_mthd(dev, 0x9097, 0x03a8, 0x00000000); - nv_mthd(dev, 0x9097, 0x03c8, 0x00000000); - nv_mthd(dev, 0x9097, 0x03e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x038c, 0x00000000); - nv_mthd(dev, 0x9097, 0x03ac, 0x00000000); - nv_mthd(dev, 0x9097, 0x03cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x03ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x0700, 0x00000000); - nv_mthd(dev, 0x9097, 0x0710, 0x00000000); - nv_mthd(dev, 0x9097, 0x0720, 0x00000000); - nv_mthd(dev, 0x9097, 0x0730, 0x00000000); - nv_mthd(dev, 0x9097, 0x0704, 0x00000000); - nv_mthd(dev, 0x9097, 0x0714, 0x00000000); - nv_mthd(dev, 0x9097, 0x0724, 0x00000000); - nv_mthd(dev, 0x9097, 0x0734, 0x00000000); - nv_mthd(dev, 0x9097, 0x0708, 0x00000000); - nv_mthd(dev, 0x9097, 0x0718, 0x00000000); - nv_mthd(dev, 0x9097, 0x0728, 0x00000000); - nv_mthd(dev, 0x9097, 0x0738, 0x00000000); - nv_mthd(dev, 0x9097, 0x2800, 0x00000000); - nv_mthd(dev, 0x9097, 0x2804, 0x00000000); - nv_mthd(dev, 0x9097, 0x2808, 0x00000000); - nv_mthd(dev, 0x9097, 0x280c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2810, 0x00000000); - nv_mthd(dev, 0x9097, 0x2814, 0x00000000); - nv_mthd(dev, 0x9097, 0x2818, 0x00000000); - nv_mthd(dev, 0x9097, 0x281c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2820, 0x00000000); - nv_mthd(dev, 0x9097, 0x2824, 0x00000000); - nv_mthd(dev, 0x9097, 0x2828, 0x00000000); - nv_mthd(dev, 0x9097, 0x282c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2830, 0x00000000); - nv_mthd(dev, 0x9097, 0x2834, 0x00000000); - nv_mthd(dev, 0x9097, 0x2838, 0x00000000); - nv_mthd(dev, 0x9097, 0x283c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2840, 0x00000000); - nv_mthd(dev, 0x9097, 0x2844, 0x00000000); - nv_mthd(dev, 0x9097, 0x2848, 0x00000000); - nv_mthd(dev, 0x9097, 0x284c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2850, 0x00000000); - nv_mthd(dev, 0x9097, 0x2854, 0x00000000); - nv_mthd(dev, 0x9097, 0x2858, 0x00000000); - nv_mthd(dev, 0x9097, 0x285c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2860, 0x00000000); - nv_mthd(dev, 0x9097, 0x2864, 0x00000000); - nv_mthd(dev, 0x9097, 0x2868, 0x00000000); - nv_mthd(dev, 0x9097, 0x286c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2870, 0x00000000); - nv_mthd(dev, 0x9097, 0x2874, 0x00000000); - nv_mthd(dev, 0x9097, 0x2878, 0x00000000); - nv_mthd(dev, 0x9097, 0x287c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2880, 0x00000000); - nv_mthd(dev, 0x9097, 0x2884, 0x00000000); - nv_mthd(dev, 0x9097, 0x2888, 0x00000000); - nv_mthd(dev, 0x9097, 0x288c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2890, 0x00000000); - nv_mthd(dev, 0x9097, 0x2894, 0x00000000); - nv_mthd(dev, 0x9097, 0x2898, 0x00000000); - nv_mthd(dev, 0x9097, 0x289c, 0x00000000); - nv_mthd(dev, 0x9097, 0x28a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x28a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x28a8, 0x00000000); - nv_mthd(dev, 0x9097, 0x28ac, 0x00000000); - nv_mthd(dev, 0x9097, 0x28b0, 0x00000000); - nv_mthd(dev, 0x9097, 0x28b4, 0x00000000); - nv_mthd(dev, 0x9097, 0x28b8, 0x00000000); - nv_mthd(dev, 0x9097, 0x28bc, 0x00000000); - nv_mthd(dev, 0x9097, 0x28c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x28c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x28c8, 0x00000000); - nv_mthd(dev, 0x9097, 0x28cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x28d0, 0x00000000); - nv_mthd(dev, 0x9097, 0x28d4, 0x00000000); - nv_mthd(dev, 0x9097, 0x28d8, 0x00000000); - nv_mthd(dev, 0x9097, 0x28dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x28e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x28e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x28e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x28ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x28f0, 0x00000000); - nv_mthd(dev, 0x9097, 0x28f4, 0x00000000); - nv_mthd(dev, 0x9097, 0x28f8, 0x00000000); - nv_mthd(dev, 0x9097, 0x28fc, 0x00000000); - nv_mthd(dev, 0x9097, 0x2900, 0x00000000); - nv_mthd(dev, 0x9097, 0x2904, 0x00000000); - nv_mthd(dev, 0x9097, 0x2908, 0x00000000); - nv_mthd(dev, 0x9097, 0x290c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2910, 0x00000000); - nv_mthd(dev, 0x9097, 0x2914, 0x00000000); - nv_mthd(dev, 0x9097, 0x2918, 0x00000000); - nv_mthd(dev, 0x9097, 0x291c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2920, 0x00000000); - nv_mthd(dev, 0x9097, 0x2924, 0x00000000); - nv_mthd(dev, 0x9097, 0x2928, 0x00000000); - nv_mthd(dev, 0x9097, 0x292c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2930, 0x00000000); - nv_mthd(dev, 0x9097, 0x2934, 0x00000000); - nv_mthd(dev, 0x9097, 0x2938, 0x00000000); - nv_mthd(dev, 0x9097, 0x293c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2940, 0x00000000); - nv_mthd(dev, 0x9097, 0x2944, 0x00000000); - nv_mthd(dev, 0x9097, 0x2948, 0x00000000); - nv_mthd(dev, 0x9097, 0x294c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2950, 0x00000000); - nv_mthd(dev, 0x9097, 0x2954, 0x00000000); - nv_mthd(dev, 0x9097, 0x2958, 0x00000000); - nv_mthd(dev, 0x9097, 0x295c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2960, 0x00000000); - nv_mthd(dev, 0x9097, 0x2964, 0x00000000); - nv_mthd(dev, 0x9097, 0x2968, 0x00000000); - nv_mthd(dev, 0x9097, 0x296c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2970, 0x00000000); - nv_mthd(dev, 0x9097, 0x2974, 0x00000000); - nv_mthd(dev, 0x9097, 0x2978, 0x00000000); - nv_mthd(dev, 0x9097, 0x297c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2980, 0x00000000); - nv_mthd(dev, 0x9097, 0x2984, 0x00000000); - nv_mthd(dev, 0x9097, 0x2988, 0x00000000); - nv_mthd(dev, 0x9097, 0x298c, 0x00000000); - nv_mthd(dev, 0x9097, 0x2990, 0x00000000); - nv_mthd(dev, 0x9097, 0x2994, 0x00000000); - nv_mthd(dev, 0x9097, 0x2998, 0x00000000); - nv_mthd(dev, 0x9097, 0x299c, 0x00000000); - nv_mthd(dev, 0x9097, 0x29a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x29a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x29a8, 0x00000000); - nv_mthd(dev, 0x9097, 0x29ac, 0x00000000); - nv_mthd(dev, 0x9097, 0x29b0, 0x00000000); - nv_mthd(dev, 0x9097, 0x29b4, 0x00000000); - nv_mthd(dev, 0x9097, 0x29b8, 0x00000000); - nv_mthd(dev, 0x9097, 0x29bc, 0x00000000); - nv_mthd(dev, 0x9097, 0x29c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x29c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x29c8, 0x00000000); - nv_mthd(dev, 0x9097, 0x29cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x29d0, 0x00000000); - nv_mthd(dev, 0x9097, 0x29d4, 0x00000000); - nv_mthd(dev, 0x9097, 0x29d8, 0x00000000); - nv_mthd(dev, 0x9097, 0x29dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x29e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x29e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x29e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x29ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x29f0, 0x00000000); - nv_mthd(dev, 0x9097, 0x29f4, 0x00000000); - nv_mthd(dev, 0x9097, 0x29f8, 0x00000000); - nv_mthd(dev, 0x9097, 0x29fc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a00, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a20, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a40, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a60, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a80, 0x00000000); - nv_mthd(dev, 0x9097, 0x0aa0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ac0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ae0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b00, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b20, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b40, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b60, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b80, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ba0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bc0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0be0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a04, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a24, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a44, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a64, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a84, 0x00000000); - nv_mthd(dev, 0x9097, 0x0aa4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ac4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ae4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b04, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b24, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b44, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b64, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b84, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ba4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bc4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0be4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a08, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a28, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a48, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a68, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a88, 0x00000000); - nv_mthd(dev, 0x9097, 0x0aa8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ac8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ae8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b08, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b28, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b48, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b68, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b88, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ba8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bc8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0be8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a0c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a2c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a4c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a6c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0aac, 0x00000000); - nv_mthd(dev, 0x9097, 0x0acc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0aec, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b0c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b2c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b4c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b6c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bac, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bcc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bec, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a10, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a30, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a50, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a70, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a90, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ab0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ad0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0af0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b10, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b30, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b50, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b70, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b90, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bb0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bd0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bf0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a14, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a34, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a54, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a74, 0x00000000); - nv_mthd(dev, 0x9097, 0x0a94, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ab4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ad4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0af4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b14, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b34, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b54, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b74, 0x00000000); - nv_mthd(dev, 0x9097, 0x0b94, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bb4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bd4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0bf4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c00, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c10, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c20, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c30, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c40, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c50, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c60, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c70, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c80, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c90, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ca0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cb0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cc0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cd0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ce0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cf0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c04, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c14, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c24, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c34, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c44, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c54, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c64, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c74, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c84, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c94, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ca4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cb4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cc4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cd4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ce4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cf4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c08, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c18, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c28, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c38, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c48, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c58, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c68, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c78, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c88, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c98, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ca8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cb8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cc8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cd8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ce8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0cf8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0c0c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c1c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c2c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c3c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c4c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c5c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c6c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c7c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c8c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0c9c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0cac, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0cbc, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0ccc, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0cdc, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0cec, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0cfc, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0d00, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d08, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d10, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d18, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d20, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d28, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d30, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d38, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d04, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d0c, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d14, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d1c, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d24, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d2c, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d34, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d3c, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e00, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e10, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e20, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e30, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e40, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e50, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e60, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e70, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e80, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e90, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ea0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0eb0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ec0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ed0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ee0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ef0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0e04, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e14, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e24, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e34, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e44, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e54, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e64, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e74, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e84, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e94, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ea4, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0eb4, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ec4, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ed4, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ee4, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ef4, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e08, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e18, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e28, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e38, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e48, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e58, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e68, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e78, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e88, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0e98, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ea8, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0eb8, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ec8, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ed8, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ee8, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0ef8, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d40, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d48, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d50, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d58, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d44, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d4c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d54, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d5c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1e00, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e20, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e40, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e60, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e80, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ea0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ec0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ee0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e04, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e24, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e44, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e64, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e84, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ea4, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ec4, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ee4, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e08, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e28, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e48, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e68, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e88, 0x00000002); - nv_mthd(dev, 0x9097, 0x1ea8, 0x00000002); - nv_mthd(dev, 0x9097, 0x1ec8, 0x00000002); - nv_mthd(dev, 0x9097, 0x1ee8, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e0c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e2c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e4c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e6c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e8c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1eac, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ecc, 0x00000001); - nv_mthd(dev, 0x9097, 0x1eec, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e10, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e30, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e50, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e70, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e90, 0x00000001); - nv_mthd(dev, 0x9097, 0x1eb0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ed0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ef0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e14, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e34, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e54, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e74, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e94, 0x00000002); - nv_mthd(dev, 0x9097, 0x1eb4, 0x00000002); - nv_mthd(dev, 0x9097, 0x1ed4, 0x00000002); - nv_mthd(dev, 0x9097, 0x1ef4, 0x00000002); - nv_mthd(dev, 0x9097, 0x1e18, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e38, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e58, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e78, 0x00000001); - nv_mthd(dev, 0x9097, 0x1e98, 0x00000001); - nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001); + nv_mthd(priv, 0x9097, 0x0800, 0x00000000); + nv_mthd(priv, 0x9097, 0x0840, 0x00000000); + nv_mthd(priv, 0x9097, 0x0880, 0x00000000); + nv_mthd(priv, 0x9097, 0x08c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0900, 0x00000000); + nv_mthd(priv, 0x9097, 0x0940, 0x00000000); + nv_mthd(priv, 0x9097, 0x0980, 0x00000000); + nv_mthd(priv, 0x9097, 0x09c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0804, 0x00000000); + nv_mthd(priv, 0x9097, 0x0844, 0x00000000); + nv_mthd(priv, 0x9097, 0x0884, 0x00000000); + nv_mthd(priv, 0x9097, 0x08c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0904, 0x00000000); + nv_mthd(priv, 0x9097, 0x0944, 0x00000000); + nv_mthd(priv, 0x9097, 0x0984, 0x00000000); + nv_mthd(priv, 0x9097, 0x09c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0808, 0x00000400); + nv_mthd(priv, 0x9097, 0x0848, 0x00000400); + nv_mthd(priv, 0x9097, 0x0888, 0x00000400); + nv_mthd(priv, 0x9097, 0x08c8, 0x00000400); + nv_mthd(priv, 0x9097, 0x0908, 0x00000400); + nv_mthd(priv, 0x9097, 0x0948, 0x00000400); + nv_mthd(priv, 0x9097, 0x0988, 0x00000400); + nv_mthd(priv, 0x9097, 0x09c8, 0x00000400); + nv_mthd(priv, 0x9097, 0x080c, 0x00000300); + nv_mthd(priv, 0x9097, 0x084c, 0x00000300); + nv_mthd(priv, 0x9097, 0x088c, 0x00000300); + nv_mthd(priv, 0x9097, 0x08cc, 0x00000300); + nv_mthd(priv, 0x9097, 0x090c, 0x00000300); + nv_mthd(priv, 0x9097, 0x094c, 0x00000300); + nv_mthd(priv, 0x9097, 0x098c, 0x00000300); + nv_mthd(priv, 0x9097, 0x09cc, 0x00000300); + nv_mthd(priv, 0x9097, 0x0810, 0x000000cf); + nv_mthd(priv, 0x9097, 0x0850, 0x00000000); + nv_mthd(priv, 0x9097, 0x0890, 0x00000000); + nv_mthd(priv, 0x9097, 0x08d0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0910, 0x00000000); + nv_mthd(priv, 0x9097, 0x0950, 0x00000000); + nv_mthd(priv, 0x9097, 0x0990, 0x00000000); + nv_mthd(priv, 0x9097, 0x09d0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0814, 0x00000040); + nv_mthd(priv, 0x9097, 0x0854, 0x00000040); + nv_mthd(priv, 0x9097, 0x0894, 0x00000040); + nv_mthd(priv, 0x9097, 0x08d4, 0x00000040); + nv_mthd(priv, 0x9097, 0x0914, 0x00000040); + nv_mthd(priv, 0x9097, 0x0954, 0x00000040); + nv_mthd(priv, 0x9097, 0x0994, 0x00000040); + nv_mthd(priv, 0x9097, 0x09d4, 0x00000040); + nv_mthd(priv, 0x9097, 0x0818, 0x00000001); + nv_mthd(priv, 0x9097, 0x0858, 0x00000001); + nv_mthd(priv, 0x9097, 0x0898, 0x00000001); + nv_mthd(priv, 0x9097, 0x08d8, 0x00000001); + nv_mthd(priv, 0x9097, 0x0918, 0x00000001); + nv_mthd(priv, 0x9097, 0x0958, 0x00000001); + nv_mthd(priv, 0x9097, 0x0998, 0x00000001); + nv_mthd(priv, 0x9097, 0x09d8, 0x00000001); + nv_mthd(priv, 0x9097, 0x081c, 0x00000000); + nv_mthd(priv, 0x9097, 0x085c, 0x00000000); + nv_mthd(priv, 0x9097, 0x089c, 0x00000000); + nv_mthd(priv, 0x9097, 0x08dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x091c, 0x00000000); + nv_mthd(priv, 0x9097, 0x095c, 0x00000000); + nv_mthd(priv, 0x9097, 0x099c, 0x00000000); + nv_mthd(priv, 0x9097, 0x09dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0820, 0x00000000); + nv_mthd(priv, 0x9097, 0x0860, 0x00000000); + nv_mthd(priv, 0x9097, 0x08a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x08e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0920, 0x00000000); + nv_mthd(priv, 0x9097, 0x0960, 0x00000000); + nv_mthd(priv, 0x9097, 0x09a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x09e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x2700, 0x00000000); + nv_mthd(priv, 0x9097, 0x2720, 0x00000000); + nv_mthd(priv, 0x9097, 0x2740, 0x00000000); + nv_mthd(priv, 0x9097, 0x2760, 0x00000000); + nv_mthd(priv, 0x9097, 0x2780, 0x00000000); + nv_mthd(priv, 0x9097, 0x27a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x27c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x27e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x2704, 0x00000000); + nv_mthd(priv, 0x9097, 0x2724, 0x00000000); + nv_mthd(priv, 0x9097, 0x2744, 0x00000000); + nv_mthd(priv, 0x9097, 0x2764, 0x00000000); + nv_mthd(priv, 0x9097, 0x2784, 0x00000000); + nv_mthd(priv, 0x9097, 0x27a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x27c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x27e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x2708, 0x00000000); + nv_mthd(priv, 0x9097, 0x2728, 0x00000000); + nv_mthd(priv, 0x9097, 0x2748, 0x00000000); + nv_mthd(priv, 0x9097, 0x2768, 0x00000000); + nv_mthd(priv, 0x9097, 0x2788, 0x00000000); + nv_mthd(priv, 0x9097, 0x27a8, 0x00000000); + nv_mthd(priv, 0x9097, 0x27c8, 0x00000000); + nv_mthd(priv, 0x9097, 0x27e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x270c, 0x00000000); + nv_mthd(priv, 0x9097, 0x272c, 0x00000000); + nv_mthd(priv, 0x9097, 0x274c, 0x00000000); + nv_mthd(priv, 0x9097, 0x276c, 0x00000000); + nv_mthd(priv, 0x9097, 0x278c, 0x00000000); + nv_mthd(priv, 0x9097, 0x27ac, 0x00000000); + nv_mthd(priv, 0x9097, 0x27cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x27ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x2710, 0x00014000); + nv_mthd(priv, 0x9097, 0x2730, 0x00014000); + nv_mthd(priv, 0x9097, 0x2750, 0x00014000); + nv_mthd(priv, 0x9097, 0x2770, 0x00014000); + nv_mthd(priv, 0x9097, 0x2790, 0x00014000); + nv_mthd(priv, 0x9097, 0x27b0, 0x00014000); + nv_mthd(priv, 0x9097, 0x27d0, 0x00014000); + nv_mthd(priv, 0x9097, 0x27f0, 0x00014000); + nv_mthd(priv, 0x9097, 0x2714, 0x00000040); + nv_mthd(priv, 0x9097, 0x2734, 0x00000040); + nv_mthd(priv, 0x9097, 0x2754, 0x00000040); + nv_mthd(priv, 0x9097, 0x2774, 0x00000040); + nv_mthd(priv, 0x9097, 0x2794, 0x00000040); + nv_mthd(priv, 0x9097, 0x27b4, 0x00000040); + nv_mthd(priv, 0x9097, 0x27d4, 0x00000040); + nv_mthd(priv, 0x9097, 0x27f4, 0x00000040); + nv_mthd(priv, 0x9097, 0x1c00, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c10, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c20, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c30, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c40, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c50, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c60, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c70, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c80, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c90, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ca0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cb0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cc0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cd0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ce0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cf0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c04, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c14, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c24, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c34, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c44, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c54, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c64, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c74, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c84, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c94, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ca4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cb4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cc4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cd4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ce4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cf4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c08, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c18, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c28, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c38, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c48, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c58, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c68, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c78, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c88, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c98, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ca8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cb8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cc8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cd8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ce8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cf8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c0c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c1c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c2c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c3c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c4c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c5c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c6c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c7c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1c9c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cac, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cbc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ccc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cdc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cec, 0x00000000); + nv_mthd(priv, 0x9097, 0x1cfc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d00, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d10, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d20, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d30, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d40, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d50, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d60, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d70, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d80, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d90, 0x00000000); + nv_mthd(priv, 0x9097, 0x1da0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1db0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dc0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dd0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1de0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1df0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d04, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d14, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d24, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d34, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d44, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d54, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d64, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d74, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d84, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d94, 0x00000000); + nv_mthd(priv, 0x9097, 0x1da4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1db4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dc4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dd4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1de4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1df4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d08, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d18, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d28, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d38, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d48, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d58, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d68, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d78, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d88, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d98, 0x00000000); + nv_mthd(priv, 0x9097, 0x1da8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1db8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dc8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dd8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1de8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1df8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d0c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d1c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d2c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d3c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d4c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d5c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d6c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d7c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1d9c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dac, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dbc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dcc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ddc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dec, 0x00000000); + nv_mthd(priv, 0x9097, 0x1dfc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f00, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f08, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f10, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f18, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f20, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f28, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f30, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f38, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f40, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f48, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f50, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f58, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f60, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f68, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f70, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f78, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f04, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f0c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f14, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f1c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f24, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f2c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f34, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f3c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f44, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f4c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f54, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f5c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f64, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f6c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f74, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f7c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f80, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f88, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f90, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f98, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fa0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fa8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fb0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fb8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fc0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fc8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fd0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fd8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fe0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fe8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ff0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ff8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f84, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f94, 0x00000000); + nv_mthd(priv, 0x9097, 0x1f9c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fa4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fac, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fb4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fbc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fc4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fcc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fd4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fdc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fe4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1fec, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ff4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1ffc, 0x00000000); + nv_mthd(priv, 0x9097, 0x2200, 0x00000022); + nv_mthd(priv, 0x9097, 0x2210, 0x00000022); + nv_mthd(priv, 0x9097, 0x2220, 0x00000022); + nv_mthd(priv, 0x9097, 0x2230, 0x00000022); + nv_mthd(priv, 0x9097, 0x2240, 0x00000022); + nv_mthd(priv, 0x9097, 0x2000, 0x00000000); + nv_mthd(priv, 0x9097, 0x2040, 0x00000011); + nv_mthd(priv, 0x9097, 0x2080, 0x00000020); + nv_mthd(priv, 0x9097, 0x20c0, 0x00000030); + nv_mthd(priv, 0x9097, 0x2100, 0x00000040); + nv_mthd(priv, 0x9097, 0x2140, 0x00000051); + nv_mthd(priv, 0x9097, 0x200c, 0x00000001); + nv_mthd(priv, 0x9097, 0x204c, 0x00000001); + nv_mthd(priv, 0x9097, 0x208c, 0x00000001); + nv_mthd(priv, 0x9097, 0x20cc, 0x00000001); + nv_mthd(priv, 0x9097, 0x210c, 0x00000001); + nv_mthd(priv, 0x9097, 0x214c, 0x00000001); + nv_mthd(priv, 0x9097, 0x2010, 0x00000000); + nv_mthd(priv, 0x9097, 0x2050, 0x00000000); + nv_mthd(priv, 0x9097, 0x2090, 0x00000001); + nv_mthd(priv, 0x9097, 0x20d0, 0x00000002); + nv_mthd(priv, 0x9097, 0x2110, 0x00000003); + nv_mthd(priv, 0x9097, 0x2150, 0x00000004); + nv_mthd(priv, 0x9097, 0x0380, 0x00000000); + nv_mthd(priv, 0x9097, 0x03a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x03c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x03e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0384, 0x00000000); + nv_mthd(priv, 0x9097, 0x03a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x03c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x03e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0388, 0x00000000); + nv_mthd(priv, 0x9097, 0x03a8, 0x00000000); + nv_mthd(priv, 0x9097, 0x03c8, 0x00000000); + nv_mthd(priv, 0x9097, 0x03e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x038c, 0x00000000); + nv_mthd(priv, 0x9097, 0x03ac, 0x00000000); + nv_mthd(priv, 0x9097, 0x03cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x03ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x0700, 0x00000000); + nv_mthd(priv, 0x9097, 0x0710, 0x00000000); + nv_mthd(priv, 0x9097, 0x0720, 0x00000000); + nv_mthd(priv, 0x9097, 0x0730, 0x00000000); + nv_mthd(priv, 0x9097, 0x0704, 0x00000000); + nv_mthd(priv, 0x9097, 0x0714, 0x00000000); + nv_mthd(priv, 0x9097, 0x0724, 0x00000000); + nv_mthd(priv, 0x9097, 0x0734, 0x00000000); + nv_mthd(priv, 0x9097, 0x0708, 0x00000000); + nv_mthd(priv, 0x9097, 0x0718, 0x00000000); + nv_mthd(priv, 0x9097, 0x0728, 0x00000000); + nv_mthd(priv, 0x9097, 0x0738, 0x00000000); + nv_mthd(priv, 0x9097, 0x2800, 0x00000000); + nv_mthd(priv, 0x9097, 0x2804, 0x00000000); + nv_mthd(priv, 0x9097, 0x2808, 0x00000000); + nv_mthd(priv, 0x9097, 0x280c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2810, 0x00000000); + nv_mthd(priv, 0x9097, 0x2814, 0x00000000); + nv_mthd(priv, 0x9097, 0x2818, 0x00000000); + nv_mthd(priv, 0x9097, 0x281c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2820, 0x00000000); + nv_mthd(priv, 0x9097, 0x2824, 0x00000000); + nv_mthd(priv, 0x9097, 0x2828, 0x00000000); + nv_mthd(priv, 0x9097, 0x282c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2830, 0x00000000); + nv_mthd(priv, 0x9097, 0x2834, 0x00000000); + nv_mthd(priv, 0x9097, 0x2838, 0x00000000); + nv_mthd(priv, 0x9097, 0x283c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2840, 0x00000000); + nv_mthd(priv, 0x9097, 0x2844, 0x00000000); + nv_mthd(priv, 0x9097, 0x2848, 0x00000000); + nv_mthd(priv, 0x9097, 0x284c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2850, 0x00000000); + nv_mthd(priv, 0x9097, 0x2854, 0x00000000); + nv_mthd(priv, 0x9097, 0x2858, 0x00000000); + nv_mthd(priv, 0x9097, 0x285c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2860, 0x00000000); + nv_mthd(priv, 0x9097, 0x2864, 0x00000000); + nv_mthd(priv, 0x9097, 0x2868, 0x00000000); + nv_mthd(priv, 0x9097, 0x286c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2870, 0x00000000); + nv_mthd(priv, 0x9097, 0x2874, 0x00000000); + nv_mthd(priv, 0x9097, 0x2878, 0x00000000); + nv_mthd(priv, 0x9097, 0x287c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2880, 0x00000000); + nv_mthd(priv, 0x9097, 0x2884, 0x00000000); + nv_mthd(priv, 0x9097, 0x2888, 0x00000000); + nv_mthd(priv, 0x9097, 0x288c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2890, 0x00000000); + nv_mthd(priv, 0x9097, 0x2894, 0x00000000); + nv_mthd(priv, 0x9097, 0x2898, 0x00000000); + nv_mthd(priv, 0x9097, 0x289c, 0x00000000); + nv_mthd(priv, 0x9097, 0x28a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x28a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x28a8, 0x00000000); + nv_mthd(priv, 0x9097, 0x28ac, 0x00000000); + nv_mthd(priv, 0x9097, 0x28b0, 0x00000000); + nv_mthd(priv, 0x9097, 0x28b4, 0x00000000); + nv_mthd(priv, 0x9097, 0x28b8, 0x00000000); + nv_mthd(priv, 0x9097, 0x28bc, 0x00000000); + nv_mthd(priv, 0x9097, 0x28c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x28c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x28c8, 0x00000000); + nv_mthd(priv, 0x9097, 0x28cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x28d0, 0x00000000); + nv_mthd(priv, 0x9097, 0x28d4, 0x00000000); + nv_mthd(priv, 0x9097, 0x28d8, 0x00000000); + nv_mthd(priv, 0x9097, 0x28dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x28e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x28e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x28e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x28ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x28f0, 0x00000000); + nv_mthd(priv, 0x9097, 0x28f4, 0x00000000); + nv_mthd(priv, 0x9097, 0x28f8, 0x00000000); + nv_mthd(priv, 0x9097, 0x28fc, 0x00000000); + nv_mthd(priv, 0x9097, 0x2900, 0x00000000); + nv_mthd(priv, 0x9097, 0x2904, 0x00000000); + nv_mthd(priv, 0x9097, 0x2908, 0x00000000); + nv_mthd(priv, 0x9097, 0x290c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2910, 0x00000000); + nv_mthd(priv, 0x9097, 0x2914, 0x00000000); + nv_mthd(priv, 0x9097, 0x2918, 0x00000000); + nv_mthd(priv, 0x9097, 0x291c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2920, 0x00000000); + nv_mthd(priv, 0x9097, 0x2924, 0x00000000); + nv_mthd(priv, 0x9097, 0x2928, 0x00000000); + nv_mthd(priv, 0x9097, 0x292c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2930, 0x00000000); + nv_mthd(priv, 0x9097, 0x2934, 0x00000000); + nv_mthd(priv, 0x9097, 0x2938, 0x00000000); + nv_mthd(priv, 0x9097, 0x293c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2940, 0x00000000); + nv_mthd(priv, 0x9097, 0x2944, 0x00000000); + nv_mthd(priv, 0x9097, 0x2948, 0x00000000); + nv_mthd(priv, 0x9097, 0x294c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2950, 0x00000000); + nv_mthd(priv, 0x9097, 0x2954, 0x00000000); + nv_mthd(priv, 0x9097, 0x2958, 0x00000000); + nv_mthd(priv, 0x9097, 0x295c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2960, 0x00000000); + nv_mthd(priv, 0x9097, 0x2964, 0x00000000); + nv_mthd(priv, 0x9097, 0x2968, 0x00000000); + nv_mthd(priv, 0x9097, 0x296c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2970, 0x00000000); + nv_mthd(priv, 0x9097, 0x2974, 0x00000000); + nv_mthd(priv, 0x9097, 0x2978, 0x00000000); + nv_mthd(priv, 0x9097, 0x297c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2980, 0x00000000); + nv_mthd(priv, 0x9097, 0x2984, 0x00000000); + nv_mthd(priv, 0x9097, 0x2988, 0x00000000); + nv_mthd(priv, 0x9097, 0x298c, 0x00000000); + nv_mthd(priv, 0x9097, 0x2990, 0x00000000); + nv_mthd(priv, 0x9097, 0x2994, 0x00000000); + nv_mthd(priv, 0x9097, 0x2998, 0x00000000); + nv_mthd(priv, 0x9097, 0x299c, 0x00000000); + nv_mthd(priv, 0x9097, 0x29a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x29a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x29a8, 0x00000000); + nv_mthd(priv, 0x9097, 0x29ac, 0x00000000); + nv_mthd(priv, 0x9097, 0x29b0, 0x00000000); + nv_mthd(priv, 0x9097, 0x29b4, 0x00000000); + nv_mthd(priv, 0x9097, 0x29b8, 0x00000000); + nv_mthd(priv, 0x9097, 0x29bc, 0x00000000); + nv_mthd(priv, 0x9097, 0x29c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x29c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x29c8, 0x00000000); + nv_mthd(priv, 0x9097, 0x29cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x29d0, 0x00000000); + nv_mthd(priv, 0x9097, 0x29d4, 0x00000000); + nv_mthd(priv, 0x9097, 0x29d8, 0x00000000); + nv_mthd(priv, 0x9097, 0x29dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x29e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x29e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x29e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x29ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x29f0, 0x00000000); + nv_mthd(priv, 0x9097, 0x29f4, 0x00000000); + nv_mthd(priv, 0x9097, 0x29f8, 0x00000000); + nv_mthd(priv, 0x9097, 0x29fc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a00, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a20, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a40, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a60, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a80, 0x00000000); + nv_mthd(priv, 0x9097, 0x0aa0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ac0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ae0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b00, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b20, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b40, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b60, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b80, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ba0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bc0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0be0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a04, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a24, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a44, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a64, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a84, 0x00000000); + nv_mthd(priv, 0x9097, 0x0aa4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ac4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ae4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b04, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b24, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b44, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b64, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b84, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ba4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bc4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0be4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a08, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a28, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a48, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a68, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a88, 0x00000000); + nv_mthd(priv, 0x9097, 0x0aa8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ac8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ae8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b08, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b28, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b48, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b68, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b88, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ba8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bc8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0be8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a0c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a2c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a4c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a6c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0aac, 0x00000000); + nv_mthd(priv, 0x9097, 0x0acc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0aec, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b0c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b2c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b4c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b6c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bac, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bcc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bec, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a10, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a30, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a50, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a70, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a90, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ab0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ad0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0af0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b10, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b30, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b50, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b70, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b90, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bb0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bd0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bf0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a14, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a34, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a54, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a74, 0x00000000); + nv_mthd(priv, 0x9097, 0x0a94, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ab4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ad4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0af4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b14, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b34, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b54, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b74, 0x00000000); + nv_mthd(priv, 0x9097, 0x0b94, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bb4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bd4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0bf4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c00, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c10, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c20, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c30, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c40, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c50, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c60, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c70, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c80, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c90, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ca0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cb0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cc0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cd0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ce0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cf0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c04, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c14, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c24, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c34, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c44, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c54, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c64, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c74, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c84, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c94, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ca4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cb4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cc4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cd4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ce4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cf4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c08, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c18, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c28, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c38, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c48, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c58, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c68, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c78, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c88, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c98, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ca8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cb8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cc8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cd8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ce8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0cf8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0c0c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c1c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c2c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c3c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c4c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c5c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c6c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c7c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c8c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0c9c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0cac, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0cbc, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0ccc, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0cdc, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0cec, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0cfc, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0d00, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d08, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d10, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d18, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d20, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d28, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d30, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d38, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d04, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d0c, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d14, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d1c, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d24, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d2c, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d34, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d3c, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e00, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e10, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e20, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e30, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e40, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e50, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e60, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e70, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e80, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e90, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ea0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0eb0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ec0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ed0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ee0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ef0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0e04, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e14, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e24, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e34, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e44, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e54, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e64, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e74, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e84, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e94, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ea4, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0eb4, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ec4, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ed4, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ee4, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ef4, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e08, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e18, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e28, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e38, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e48, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e58, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e68, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e78, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e88, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0e98, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ea8, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0eb8, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ec8, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ed8, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ee8, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0ef8, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d40, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d48, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d50, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d58, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d44, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d4c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d54, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d5c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1e00, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e20, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e40, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e60, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e80, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ea0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ec0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ee0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e04, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e24, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e44, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e64, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e84, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ea4, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ec4, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ee4, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e08, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e28, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e48, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e68, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e88, 0x00000002); + nv_mthd(priv, 0x9097, 0x1ea8, 0x00000002); + nv_mthd(priv, 0x9097, 0x1ec8, 0x00000002); + nv_mthd(priv, 0x9097, 0x1ee8, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e0c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e2c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e4c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e6c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e8c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1eac, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ecc, 0x00000001); + nv_mthd(priv, 0x9097, 0x1eec, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e10, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e30, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e50, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e70, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e90, 0x00000001); + nv_mthd(priv, 0x9097, 0x1eb0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ed0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ef0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e14, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e34, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e54, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e74, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e94, 0x00000002); + nv_mthd(priv, 0x9097, 0x1eb4, 0x00000002); + nv_mthd(priv, 0x9097, 0x1ed4, 0x00000002); + nv_mthd(priv, 0x9097, 0x1ef4, 0x00000002); + nv_mthd(priv, 0x9097, 0x1e18, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e38, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e58, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e78, 0x00000001); + nv_mthd(priv, 0x9097, 0x1e98, 0x00000001); + nv_mthd(priv, 0x9097, 0x1eb8, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ed8, 0x00000001); + nv_mthd(priv, 0x9097, 0x1ef8, 0x00000001); if (fermi == 0x9097) { for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) - nv_mthd(dev, 0x9097, mthd, 0x00000000); + nv_mthd(priv, 0x9097, mthd, 0x00000000); } - nv_mthd(dev, 0x9097, 0x030c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1944, 0x00000000); - nv_mthd(dev, 0x9097, 0x1514, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d68, 0x0000ffff); - nv_mthd(dev, 0x9097, 0x121c, 0x0fac6881); - nv_mthd(dev, 0x9097, 0x0fac, 0x00000001); - nv_mthd(dev, 0x9097, 0x1538, 0x00000001); - nv_mthd(dev, 0x9097, 0x0fe0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0fe4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0fe8, 0x00000014); - nv_mthd(dev, 0x9097, 0x0fec, 0x00000040); - nv_mthd(dev, 0x9097, 0x0ff0, 0x00000000); - nv_mthd(dev, 0x9097, 0x179c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1228, 0x00000400); - nv_mthd(dev, 0x9097, 0x122c, 0x00000300); - nv_mthd(dev, 0x9097, 0x1230, 0x00010001); - nv_mthd(dev, 0x9097, 0x07f8, 0x00000000); - nv_mthd(dev, 0x9097, 0x15b4, 0x00000001); - nv_mthd(dev, 0x9097, 0x15cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1534, 0x00000000); - nv_mthd(dev, 0x9097, 0x0fb0, 0x00000000); - nv_mthd(dev, 0x9097, 0x15d0, 0x00000000); - nv_mthd(dev, 0x9097, 0x153c, 0x00000000); - nv_mthd(dev, 0x9097, 0x16b4, 0x00000003); - nv_mthd(dev, 0x9097, 0x0fbc, 0x0000ffff); - nv_mthd(dev, 0x9097, 0x0fc0, 0x0000ffff); - nv_mthd(dev, 0x9097, 0x0fc4, 0x0000ffff); - nv_mthd(dev, 0x9097, 0x0fc8, 0x0000ffff); - nv_mthd(dev, 0x9097, 0x0df8, 0x00000000); - nv_mthd(dev, 0x9097, 0x0dfc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1948, 0x00000000); - nv_mthd(dev, 0x9097, 0x1970, 0x00000001); - nv_mthd(dev, 0x9097, 0x161c, 0x000009f0); - nv_mthd(dev, 0x9097, 0x0dcc, 0x00000010); - nv_mthd(dev, 0x9097, 0x163c, 0x00000000); - nv_mthd(dev, 0x9097, 0x15e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1160, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1164, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1168, 0x25e00040); - nv_mthd(dev, 0x9097, 0x116c, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1170, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1174, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1178, 0x25e00040); - nv_mthd(dev, 0x9097, 0x117c, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1180, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1184, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1188, 0x25e00040); - nv_mthd(dev, 0x9097, 0x118c, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1190, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1194, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1198, 0x25e00040); - nv_mthd(dev, 0x9097, 0x119c, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11a0, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11a4, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11a8, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11ac, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11b0, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11b4, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11b8, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11bc, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11c0, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11c4, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11c8, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11cc, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11d0, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11d4, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11d8, 0x25e00040); - nv_mthd(dev, 0x9097, 0x11dc, 0x25e00040); - nv_mthd(dev, 0x9097, 0x1880, 0x00000000); - nv_mthd(dev, 0x9097, 0x1884, 0x00000000); - nv_mthd(dev, 0x9097, 0x1888, 0x00000000); - nv_mthd(dev, 0x9097, 0x188c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1890, 0x00000000); - nv_mthd(dev, 0x9097, 0x1894, 0x00000000); - nv_mthd(dev, 0x9097, 0x1898, 0x00000000); - nv_mthd(dev, 0x9097, 0x189c, 0x00000000); - nv_mthd(dev, 0x9097, 0x18a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x18a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x18a8, 0x00000000); - nv_mthd(dev, 0x9097, 0x18ac, 0x00000000); - nv_mthd(dev, 0x9097, 0x18b0, 0x00000000); - nv_mthd(dev, 0x9097, 0x18b4, 0x00000000); - nv_mthd(dev, 0x9097, 0x18b8, 0x00000000); - nv_mthd(dev, 0x9097, 0x18bc, 0x00000000); - nv_mthd(dev, 0x9097, 0x18c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x18c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x18c8, 0x00000000); - nv_mthd(dev, 0x9097, 0x18cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x18d0, 0x00000000); - nv_mthd(dev, 0x9097, 0x18d4, 0x00000000); - nv_mthd(dev, 0x9097, 0x18d8, 0x00000000); - nv_mthd(dev, 0x9097, 0x18dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x18e0, 0x00000000); - nv_mthd(dev, 0x9097, 0x18e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x18e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x18ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x18f0, 0x00000000); - nv_mthd(dev, 0x9097, 0x18f4, 0x00000000); - nv_mthd(dev, 0x9097, 0x18f8, 0x00000000); - nv_mthd(dev, 0x9097, 0x18fc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f84, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f88, 0x00000000); - nv_mthd(dev, 0x9097, 0x17c8, 0x00000000); - nv_mthd(dev, 0x9097, 0x17cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x17d0, 0x000000ff); - nv_mthd(dev, 0x9097, 0x17d4, 0xffffffff); - nv_mthd(dev, 0x9097, 0x17d8, 0x00000002); - nv_mthd(dev, 0x9097, 0x17dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x15f4, 0x00000000); - nv_mthd(dev, 0x9097, 0x15f8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1434, 0x00000000); - nv_mthd(dev, 0x9097, 0x1438, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d74, 0x00000000); - nv_mthd(dev, 0x9097, 0x0dec, 0x00000001); - nv_mthd(dev, 0x9097, 0x13a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1318, 0x00000001); - nv_mthd(dev, 0x9097, 0x1644, 0x00000000); - nv_mthd(dev, 0x9097, 0x0748, 0x00000000); - nv_mthd(dev, 0x9097, 0x0de8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1648, 0x00000000); - nv_mthd(dev, 0x9097, 0x12a4, 0x00000000); - nv_mthd(dev, 0x9097, 0x1120, 0x00000000); - nv_mthd(dev, 0x9097, 0x1124, 0x00000000); - nv_mthd(dev, 0x9097, 0x1128, 0x00000000); - nv_mthd(dev, 0x9097, 0x112c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1118, 0x00000000); - nv_mthd(dev, 0x9097, 0x164c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1658, 0x00000000); - nv_mthd(dev, 0x9097, 0x1910, 0x00000290); - nv_mthd(dev, 0x9097, 0x1518, 0x00000000); - nv_mthd(dev, 0x9097, 0x165c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1520, 0x00000000); - nv_mthd(dev, 0x9097, 0x1604, 0x00000000); - nv_mthd(dev, 0x9097, 0x1570, 0x00000000); - nv_mthd(dev, 0x9097, 0x13b0, 0x3f800000); - nv_mthd(dev, 0x9097, 0x13b4, 0x3f800000); - nv_mthd(dev, 0x9097, 0x020c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1670, 0x30201000); - nv_mthd(dev, 0x9097, 0x1674, 0x70605040); - nv_mthd(dev, 0x9097, 0x1678, 0xb8a89888); - nv_mthd(dev, 0x9097, 0x167c, 0xf8e8d8c8); - nv_mthd(dev, 0x9097, 0x166c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1680, 0x00ffff00); - nv_mthd(dev, 0x9097, 0x12d0, 0x00000003); - nv_mthd(dev, 0x9097, 0x12d4, 0x00000002); - nv_mthd(dev, 0x9097, 0x1684, 0x00000000); - nv_mthd(dev, 0x9097, 0x1688, 0x00000000); - nv_mthd(dev, 0x9097, 0x0dac, 0x00001b02); - nv_mthd(dev, 0x9097, 0x0db0, 0x00001b02); - nv_mthd(dev, 0x9097, 0x0db4, 0x00000000); - nv_mthd(dev, 0x9097, 0x168c, 0x00000000); - nv_mthd(dev, 0x9097, 0x15bc, 0x00000000); - nv_mthd(dev, 0x9097, 0x156c, 0x00000000); - nv_mthd(dev, 0x9097, 0x187c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1110, 0x00000001); - nv_mthd(dev, 0x9097, 0x0dc0, 0x00000000); - nv_mthd(dev, 0x9097, 0x0dc4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0dc8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1234, 0x00000000); - nv_mthd(dev, 0x9097, 0x1690, 0x00000000); - nv_mthd(dev, 0x9097, 0x12ac, 0x00000001); - nv_mthd(dev, 0x9097, 0x02c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0790, 0x00000000); - nv_mthd(dev, 0x9097, 0x0794, 0x00000000); - nv_mthd(dev, 0x9097, 0x0798, 0x00000000); - nv_mthd(dev, 0x9097, 0x079c, 0x00000000); - nv_mthd(dev, 0x9097, 0x07a0, 0x00000000); - nv_mthd(dev, 0x9097, 0x077c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1000, 0x00000010); - nv_mthd(dev, 0x9097, 0x10fc, 0x00000000); - nv_mthd(dev, 0x9097, 0x1290, 0x00000000); - nv_mthd(dev, 0x9097, 0x0218, 0x00000010); - nv_mthd(dev, 0x9097, 0x12d8, 0x00000000); - nv_mthd(dev, 0x9097, 0x12dc, 0x00000010); - nv_mthd(dev, 0x9097, 0x0d94, 0x00000001); - nv_mthd(dev, 0x9097, 0x155c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1560, 0x00000000); - nv_mthd(dev, 0x9097, 0x1564, 0x00001fff); - nv_mthd(dev, 0x9097, 0x1574, 0x00000000); - nv_mthd(dev, 0x9097, 0x1578, 0x00000000); - nv_mthd(dev, 0x9097, 0x157c, 0x003fffff); - nv_mthd(dev, 0x9097, 0x1354, 0x00000000); - nv_mthd(dev, 0x9097, 0x1664, 0x00000000); - nv_mthd(dev, 0x9097, 0x1610, 0x00000012); - nv_mthd(dev, 0x9097, 0x1608, 0x00000000); - nv_mthd(dev, 0x9097, 0x160c, 0x00000000); - nv_mthd(dev, 0x9097, 0x162c, 0x00000003); - nv_mthd(dev, 0x9097, 0x0210, 0x00000000); - nv_mthd(dev, 0x9097, 0x0320, 0x00000000); - nv_mthd(dev, 0x9097, 0x0324, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0328, 0x3f800000); - nv_mthd(dev, 0x9097, 0x032c, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0330, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0334, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0338, 0x3f800000); - nv_mthd(dev, 0x9097, 0x0750, 0x00000000); - nv_mthd(dev, 0x9097, 0x0760, 0x39291909); - nv_mthd(dev, 0x9097, 0x0764, 0x79695949); - nv_mthd(dev, 0x9097, 0x0768, 0xb9a99989); - nv_mthd(dev, 0x9097, 0x076c, 0xf9e9d9c9); - nv_mthd(dev, 0x9097, 0x0770, 0x30201000); - nv_mthd(dev, 0x9097, 0x0774, 0x70605040); - nv_mthd(dev, 0x9097, 0x0778, 0x00009080); - nv_mthd(dev, 0x9097, 0x0780, 0x39291909); - nv_mthd(dev, 0x9097, 0x0784, 0x79695949); - nv_mthd(dev, 0x9097, 0x0788, 0xb9a99989); - nv_mthd(dev, 0x9097, 0x078c, 0xf9e9d9c9); - nv_mthd(dev, 0x9097, 0x07d0, 0x30201000); - nv_mthd(dev, 0x9097, 0x07d4, 0x70605040); - nv_mthd(dev, 0x9097, 0x07d8, 0x00009080); - nv_mthd(dev, 0x9097, 0x037c, 0x00000001); - nv_mthd(dev, 0x9097, 0x0740, 0x00000000); - nv_mthd(dev, 0x9097, 0x0744, 0x00000000); - nv_mthd(dev, 0x9097, 0x2600, 0x00000000); - nv_mthd(dev, 0x9097, 0x1918, 0x00000000); - nv_mthd(dev, 0x9097, 0x191c, 0x00000900); - nv_mthd(dev, 0x9097, 0x1920, 0x00000405); - nv_mthd(dev, 0x9097, 0x1308, 0x00000001); - nv_mthd(dev, 0x9097, 0x1924, 0x00000000); - nv_mthd(dev, 0x9097, 0x13ac, 0x00000000); - nv_mthd(dev, 0x9097, 0x192c, 0x00000001); - nv_mthd(dev, 0x9097, 0x193c, 0x00002c1c); - nv_mthd(dev, 0x9097, 0x0d7c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x02c0, 0x00000001); - nv_mthd(dev, 0x9097, 0x1510, 0x00000000); - nv_mthd(dev, 0x9097, 0x1940, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ff4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0ff8, 0x00000000); - nv_mthd(dev, 0x9097, 0x194c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1950, 0x00000000); - nv_mthd(dev, 0x9097, 0x1968, 0x00000000); - nv_mthd(dev, 0x9097, 0x1590, 0x0000003f); - nv_mthd(dev, 0x9097, 0x07e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x07ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x07f0, 0x00000000); - nv_mthd(dev, 0x9097, 0x07f4, 0x00000000); - nv_mthd(dev, 0x9097, 0x196c, 0x00000011); - nv_mthd(dev, 0x9097, 0x197c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0fcc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0fd0, 0x00000000); - nv_mthd(dev, 0x9097, 0x02d8, 0x00000040); - nv_mthd(dev, 0x9097, 0x1980, 0x00000080); - nv_mthd(dev, 0x9097, 0x1504, 0x00000080); - nv_mthd(dev, 0x9097, 0x1984, 0x00000000); - nv_mthd(dev, 0x9097, 0x0300, 0x00000001); - nv_mthd(dev, 0x9097, 0x13a8, 0x00000000); - nv_mthd(dev, 0x9097, 0x12ec, 0x00000000); - nv_mthd(dev, 0x9097, 0x1310, 0x00000000); - nv_mthd(dev, 0x9097, 0x1314, 0x00000001); - nv_mthd(dev, 0x9097, 0x1380, 0x00000000); - nv_mthd(dev, 0x9097, 0x1384, 0x00000001); - nv_mthd(dev, 0x9097, 0x1388, 0x00000001); - nv_mthd(dev, 0x9097, 0x138c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1390, 0x00000001); - nv_mthd(dev, 0x9097, 0x1394, 0x00000000); - nv_mthd(dev, 0x9097, 0x139c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1398, 0x00000000); - nv_mthd(dev, 0x9097, 0x1594, 0x00000000); - nv_mthd(dev, 0x9097, 0x1598, 0x00000001); - nv_mthd(dev, 0x9097, 0x159c, 0x00000001); - nv_mthd(dev, 0x9097, 0x15a0, 0x00000001); - nv_mthd(dev, 0x9097, 0x15a4, 0x00000001); - nv_mthd(dev, 0x9097, 0x0f54, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f58, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f5c, 0x00000000); - nv_mthd(dev, 0x9097, 0x19bc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f9c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0fa0, 0x00000000); - nv_mthd(dev, 0x9097, 0x12cc, 0x00000000); - nv_mthd(dev, 0x9097, 0x12e8, 0x00000000); - nv_mthd(dev, 0x9097, 0x130c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1360, 0x00000000); - nv_mthd(dev, 0x9097, 0x1364, 0x00000000); - nv_mthd(dev, 0x9097, 0x1368, 0x00000000); - nv_mthd(dev, 0x9097, 0x136c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1370, 0x00000000); - nv_mthd(dev, 0x9097, 0x1374, 0x00000000); - nv_mthd(dev, 0x9097, 0x1378, 0x00000000); - nv_mthd(dev, 0x9097, 0x137c, 0x00000000); - nv_mthd(dev, 0x9097, 0x133c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1340, 0x00000001); - nv_mthd(dev, 0x9097, 0x1344, 0x00000002); - nv_mthd(dev, 0x9097, 0x1348, 0x00000001); - nv_mthd(dev, 0x9097, 0x134c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1350, 0x00000002); - nv_mthd(dev, 0x9097, 0x1358, 0x00000001); - nv_mthd(dev, 0x9097, 0x12e4, 0x00000000); - nv_mthd(dev, 0x9097, 0x131c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1320, 0x00000000); - nv_mthd(dev, 0x9097, 0x1324, 0x00000000); - nv_mthd(dev, 0x9097, 0x1328, 0x00000000); - nv_mthd(dev, 0x9097, 0x19c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1140, 0x00000000); - nv_mthd(dev, 0x9097, 0x19c4, 0x00000000); - nv_mthd(dev, 0x9097, 0x19c8, 0x00001500); - nv_mthd(dev, 0x9097, 0x135c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f90, 0x00000000); - nv_mthd(dev, 0x9097, 0x19e0, 0x00000001); - nv_mthd(dev, 0x9097, 0x19e4, 0x00000001); - nv_mthd(dev, 0x9097, 0x19e8, 0x00000001); - nv_mthd(dev, 0x9097, 0x19ec, 0x00000001); - nv_mthd(dev, 0x9097, 0x19f0, 0x00000001); - nv_mthd(dev, 0x9097, 0x19f4, 0x00000001); - nv_mthd(dev, 0x9097, 0x19f8, 0x00000001); - nv_mthd(dev, 0x9097, 0x19fc, 0x00000001); - nv_mthd(dev, 0x9097, 0x19cc, 0x00000001); - nv_mthd(dev, 0x9097, 0x15b8, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a00, 0x00001111); - nv_mthd(dev, 0x9097, 0x1a04, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a08, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a0c, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a10, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a14, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a18, 0x00000000); - nv_mthd(dev, 0x9097, 0x1a1c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d6c, 0xffff0000); - nv_mthd(dev, 0x9097, 0x0d70, 0xffff0000); - nv_mthd(dev, 0x9097, 0x10f8, 0x00001010); - nv_mthd(dev, 0x9097, 0x0d80, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d84, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d88, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d8c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0d90, 0x00000000); - nv_mthd(dev, 0x9097, 0x0da0, 0x00000000); - nv_mthd(dev, 0x9097, 0x1508, 0x80000000); - nv_mthd(dev, 0x9097, 0x150c, 0x40000000); - nv_mthd(dev, 0x9097, 0x1668, 0x00000000); - nv_mthd(dev, 0x9097, 0x0318, 0x00000008); - nv_mthd(dev, 0x9097, 0x031c, 0x00000008); - nv_mthd(dev, 0x9097, 0x0d9c, 0x00000001); - nv_mthd(dev, 0x9097, 0x07dc, 0x00000000); - nv_mthd(dev, 0x9097, 0x074c, 0x00000055); - nv_mthd(dev, 0x9097, 0x1420, 0x00000003); - nv_mthd(dev, 0x9097, 0x17bc, 0x00000000); - nv_mthd(dev, 0x9097, 0x17c0, 0x00000000); - nv_mthd(dev, 0x9097, 0x17c4, 0x00000001); - nv_mthd(dev, 0x9097, 0x1008, 0x00000008); - nv_mthd(dev, 0x9097, 0x100c, 0x00000040); - nv_mthd(dev, 0x9097, 0x1010, 0x0000012c); - nv_mthd(dev, 0x9097, 0x0d60, 0x00000040); - nv_mthd(dev, 0x9097, 0x075c, 0x00000003); - nv_mthd(dev, 0x9097, 0x1018, 0x00000020); - nv_mthd(dev, 0x9097, 0x101c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1020, 0x00000020); - nv_mthd(dev, 0x9097, 0x1024, 0x00000001); - nv_mthd(dev, 0x9097, 0x1444, 0x00000000); - nv_mthd(dev, 0x9097, 0x1448, 0x00000000); - nv_mthd(dev, 0x9097, 0x144c, 0x00000000); - nv_mthd(dev, 0x9097, 0x0360, 0x20164010); - nv_mthd(dev, 0x9097, 0x0364, 0x00000020); - nv_mthd(dev, 0x9097, 0x0368, 0x00000000); - nv_mthd(dev, 0x9097, 0x0de4, 0x00000000); - nv_mthd(dev, 0x9097, 0x0204, 0x00000006); - nv_mthd(dev, 0x9097, 0x0208, 0x00000000); - nv_mthd(dev, 0x9097, 0x02cc, 0x003fffff); - nv_mthd(dev, 0x9097, 0x02d0, 0x00000c48); - nv_mthd(dev, 0x9097, 0x1220, 0x00000005); - nv_mthd(dev, 0x9097, 0x0fdc, 0x00000000); - nv_mthd(dev, 0x9097, 0x0f98, 0x00300008); - nv_mthd(dev, 0x9097, 0x1284, 0x04000080); - nv_mthd(dev, 0x9097, 0x1450, 0x00300008); - nv_mthd(dev, 0x9097, 0x1454, 0x04000080); - nv_mthd(dev, 0x9097, 0x0214, 0x00000000); + nv_mthd(priv, 0x9097, 0x030c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1944, 0x00000000); + nv_mthd(priv, 0x9097, 0x1514, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d68, 0x0000ffff); + nv_mthd(priv, 0x9097, 0x121c, 0x0fac6881); + nv_mthd(priv, 0x9097, 0x0fac, 0x00000001); + nv_mthd(priv, 0x9097, 0x1538, 0x00000001); + nv_mthd(priv, 0x9097, 0x0fe0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0fe4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0fe8, 0x00000014); + nv_mthd(priv, 0x9097, 0x0fec, 0x00000040); + nv_mthd(priv, 0x9097, 0x0ff0, 0x00000000); + nv_mthd(priv, 0x9097, 0x179c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1228, 0x00000400); + nv_mthd(priv, 0x9097, 0x122c, 0x00000300); + nv_mthd(priv, 0x9097, 0x1230, 0x00010001); + nv_mthd(priv, 0x9097, 0x07f8, 0x00000000); + nv_mthd(priv, 0x9097, 0x15b4, 0x00000001); + nv_mthd(priv, 0x9097, 0x15cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1534, 0x00000000); + nv_mthd(priv, 0x9097, 0x0fb0, 0x00000000); + nv_mthd(priv, 0x9097, 0x15d0, 0x00000000); + nv_mthd(priv, 0x9097, 0x153c, 0x00000000); + nv_mthd(priv, 0x9097, 0x16b4, 0x00000003); + nv_mthd(priv, 0x9097, 0x0fbc, 0x0000ffff); + nv_mthd(priv, 0x9097, 0x0fc0, 0x0000ffff); + nv_mthd(priv, 0x9097, 0x0fc4, 0x0000ffff); + nv_mthd(priv, 0x9097, 0x0fc8, 0x0000ffff); + nv_mthd(priv, 0x9097, 0x0df8, 0x00000000); + nv_mthd(priv, 0x9097, 0x0dfc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1948, 0x00000000); + nv_mthd(priv, 0x9097, 0x1970, 0x00000001); + nv_mthd(priv, 0x9097, 0x161c, 0x000009f0); + nv_mthd(priv, 0x9097, 0x0dcc, 0x00000010); + nv_mthd(priv, 0x9097, 0x163c, 0x00000000); + nv_mthd(priv, 0x9097, 0x15e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1160, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1164, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1168, 0x25e00040); + nv_mthd(priv, 0x9097, 0x116c, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1170, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1174, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1178, 0x25e00040); + nv_mthd(priv, 0x9097, 0x117c, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1180, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1184, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1188, 0x25e00040); + nv_mthd(priv, 0x9097, 0x118c, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1190, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1194, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1198, 0x25e00040); + nv_mthd(priv, 0x9097, 0x119c, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11a0, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11a4, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11a8, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11ac, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11b0, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11b4, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11b8, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11bc, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11c0, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11c4, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11c8, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11cc, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11d0, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11d4, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11d8, 0x25e00040); + nv_mthd(priv, 0x9097, 0x11dc, 0x25e00040); + nv_mthd(priv, 0x9097, 0x1880, 0x00000000); + nv_mthd(priv, 0x9097, 0x1884, 0x00000000); + nv_mthd(priv, 0x9097, 0x1888, 0x00000000); + nv_mthd(priv, 0x9097, 0x188c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1890, 0x00000000); + nv_mthd(priv, 0x9097, 0x1894, 0x00000000); + nv_mthd(priv, 0x9097, 0x1898, 0x00000000); + nv_mthd(priv, 0x9097, 0x189c, 0x00000000); + nv_mthd(priv, 0x9097, 0x18a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x18a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x18a8, 0x00000000); + nv_mthd(priv, 0x9097, 0x18ac, 0x00000000); + nv_mthd(priv, 0x9097, 0x18b0, 0x00000000); + nv_mthd(priv, 0x9097, 0x18b4, 0x00000000); + nv_mthd(priv, 0x9097, 0x18b8, 0x00000000); + nv_mthd(priv, 0x9097, 0x18bc, 0x00000000); + nv_mthd(priv, 0x9097, 0x18c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x18c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x18c8, 0x00000000); + nv_mthd(priv, 0x9097, 0x18cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x18d0, 0x00000000); + nv_mthd(priv, 0x9097, 0x18d4, 0x00000000); + nv_mthd(priv, 0x9097, 0x18d8, 0x00000000); + nv_mthd(priv, 0x9097, 0x18dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x18e0, 0x00000000); + nv_mthd(priv, 0x9097, 0x18e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x18e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x18ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x18f0, 0x00000000); + nv_mthd(priv, 0x9097, 0x18f4, 0x00000000); + nv_mthd(priv, 0x9097, 0x18f8, 0x00000000); + nv_mthd(priv, 0x9097, 0x18fc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f84, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f88, 0x00000000); + nv_mthd(priv, 0x9097, 0x17c8, 0x00000000); + nv_mthd(priv, 0x9097, 0x17cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x17d0, 0x000000ff); + nv_mthd(priv, 0x9097, 0x17d4, 0xffffffff); + nv_mthd(priv, 0x9097, 0x17d8, 0x00000002); + nv_mthd(priv, 0x9097, 0x17dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x15f4, 0x00000000); + nv_mthd(priv, 0x9097, 0x15f8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1434, 0x00000000); + nv_mthd(priv, 0x9097, 0x1438, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d74, 0x00000000); + nv_mthd(priv, 0x9097, 0x0dec, 0x00000001); + nv_mthd(priv, 0x9097, 0x13a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1318, 0x00000001); + nv_mthd(priv, 0x9097, 0x1644, 0x00000000); + nv_mthd(priv, 0x9097, 0x0748, 0x00000000); + nv_mthd(priv, 0x9097, 0x0de8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1648, 0x00000000); + nv_mthd(priv, 0x9097, 0x12a4, 0x00000000); + nv_mthd(priv, 0x9097, 0x1120, 0x00000000); + nv_mthd(priv, 0x9097, 0x1124, 0x00000000); + nv_mthd(priv, 0x9097, 0x1128, 0x00000000); + nv_mthd(priv, 0x9097, 0x112c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1118, 0x00000000); + nv_mthd(priv, 0x9097, 0x164c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1658, 0x00000000); + nv_mthd(priv, 0x9097, 0x1910, 0x00000290); + nv_mthd(priv, 0x9097, 0x1518, 0x00000000); + nv_mthd(priv, 0x9097, 0x165c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1520, 0x00000000); + nv_mthd(priv, 0x9097, 0x1604, 0x00000000); + nv_mthd(priv, 0x9097, 0x1570, 0x00000000); + nv_mthd(priv, 0x9097, 0x13b0, 0x3f800000); + nv_mthd(priv, 0x9097, 0x13b4, 0x3f800000); + nv_mthd(priv, 0x9097, 0x020c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1670, 0x30201000); + nv_mthd(priv, 0x9097, 0x1674, 0x70605040); + nv_mthd(priv, 0x9097, 0x1678, 0xb8a89888); + nv_mthd(priv, 0x9097, 0x167c, 0xf8e8d8c8); + nv_mthd(priv, 0x9097, 0x166c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1680, 0x00ffff00); + nv_mthd(priv, 0x9097, 0x12d0, 0x00000003); + nv_mthd(priv, 0x9097, 0x12d4, 0x00000002); + nv_mthd(priv, 0x9097, 0x1684, 0x00000000); + nv_mthd(priv, 0x9097, 0x1688, 0x00000000); + nv_mthd(priv, 0x9097, 0x0dac, 0x00001b02); + nv_mthd(priv, 0x9097, 0x0db0, 0x00001b02); + nv_mthd(priv, 0x9097, 0x0db4, 0x00000000); + nv_mthd(priv, 0x9097, 0x168c, 0x00000000); + nv_mthd(priv, 0x9097, 0x15bc, 0x00000000); + nv_mthd(priv, 0x9097, 0x156c, 0x00000000); + nv_mthd(priv, 0x9097, 0x187c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1110, 0x00000001); + nv_mthd(priv, 0x9097, 0x0dc0, 0x00000000); + nv_mthd(priv, 0x9097, 0x0dc4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0dc8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1234, 0x00000000); + nv_mthd(priv, 0x9097, 0x1690, 0x00000000); + nv_mthd(priv, 0x9097, 0x12ac, 0x00000001); + nv_mthd(priv, 0x9097, 0x02c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0790, 0x00000000); + nv_mthd(priv, 0x9097, 0x0794, 0x00000000); + nv_mthd(priv, 0x9097, 0x0798, 0x00000000); + nv_mthd(priv, 0x9097, 0x079c, 0x00000000); + nv_mthd(priv, 0x9097, 0x07a0, 0x00000000); + nv_mthd(priv, 0x9097, 0x077c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1000, 0x00000010); + nv_mthd(priv, 0x9097, 0x10fc, 0x00000000); + nv_mthd(priv, 0x9097, 0x1290, 0x00000000); + nv_mthd(priv, 0x9097, 0x0218, 0x00000010); + nv_mthd(priv, 0x9097, 0x12d8, 0x00000000); + nv_mthd(priv, 0x9097, 0x12dc, 0x00000010); + nv_mthd(priv, 0x9097, 0x0d94, 0x00000001); + nv_mthd(priv, 0x9097, 0x155c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1560, 0x00000000); + nv_mthd(priv, 0x9097, 0x1564, 0x00001fff); + nv_mthd(priv, 0x9097, 0x1574, 0x00000000); + nv_mthd(priv, 0x9097, 0x1578, 0x00000000); + nv_mthd(priv, 0x9097, 0x157c, 0x003fffff); + nv_mthd(priv, 0x9097, 0x1354, 0x00000000); + nv_mthd(priv, 0x9097, 0x1664, 0x00000000); + nv_mthd(priv, 0x9097, 0x1610, 0x00000012); + nv_mthd(priv, 0x9097, 0x1608, 0x00000000); + nv_mthd(priv, 0x9097, 0x160c, 0x00000000); + nv_mthd(priv, 0x9097, 0x162c, 0x00000003); + nv_mthd(priv, 0x9097, 0x0210, 0x00000000); + nv_mthd(priv, 0x9097, 0x0320, 0x00000000); + nv_mthd(priv, 0x9097, 0x0324, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0328, 0x3f800000); + nv_mthd(priv, 0x9097, 0x032c, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0330, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0334, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0338, 0x3f800000); + nv_mthd(priv, 0x9097, 0x0750, 0x00000000); + nv_mthd(priv, 0x9097, 0x0760, 0x39291909); + nv_mthd(priv, 0x9097, 0x0764, 0x79695949); + nv_mthd(priv, 0x9097, 0x0768, 0xb9a99989); + nv_mthd(priv, 0x9097, 0x076c, 0xf9e9d9c9); + nv_mthd(priv, 0x9097, 0x0770, 0x30201000); + nv_mthd(priv, 0x9097, 0x0774, 0x70605040); + nv_mthd(priv, 0x9097, 0x0778, 0x00009080); + nv_mthd(priv, 0x9097, 0x0780, 0x39291909); + nv_mthd(priv, 0x9097, 0x0784, 0x79695949); + nv_mthd(priv, 0x9097, 0x0788, 0xb9a99989); + nv_mthd(priv, 0x9097, 0x078c, 0xf9e9d9c9); + nv_mthd(priv, 0x9097, 0x07d0, 0x30201000); + nv_mthd(priv, 0x9097, 0x07d4, 0x70605040); + nv_mthd(priv, 0x9097, 0x07d8, 0x00009080); + nv_mthd(priv, 0x9097, 0x037c, 0x00000001); + nv_mthd(priv, 0x9097, 0x0740, 0x00000000); + nv_mthd(priv, 0x9097, 0x0744, 0x00000000); + nv_mthd(priv, 0x9097, 0x2600, 0x00000000); + nv_mthd(priv, 0x9097, 0x1918, 0x00000000); + nv_mthd(priv, 0x9097, 0x191c, 0x00000900); + nv_mthd(priv, 0x9097, 0x1920, 0x00000405); + nv_mthd(priv, 0x9097, 0x1308, 0x00000001); + nv_mthd(priv, 0x9097, 0x1924, 0x00000000); + nv_mthd(priv, 0x9097, 0x13ac, 0x00000000); + nv_mthd(priv, 0x9097, 0x192c, 0x00000001); + nv_mthd(priv, 0x9097, 0x193c, 0x00002c1c); + nv_mthd(priv, 0x9097, 0x0d7c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x02c0, 0x00000001); + nv_mthd(priv, 0x9097, 0x1510, 0x00000000); + nv_mthd(priv, 0x9097, 0x1940, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ff4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0ff8, 0x00000000); + nv_mthd(priv, 0x9097, 0x194c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1950, 0x00000000); + nv_mthd(priv, 0x9097, 0x1968, 0x00000000); + nv_mthd(priv, 0x9097, 0x1590, 0x0000003f); + nv_mthd(priv, 0x9097, 0x07e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x07ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x07f0, 0x00000000); + nv_mthd(priv, 0x9097, 0x07f4, 0x00000000); + nv_mthd(priv, 0x9097, 0x196c, 0x00000011); + nv_mthd(priv, 0x9097, 0x197c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0fcc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0fd0, 0x00000000); + nv_mthd(priv, 0x9097, 0x02d8, 0x00000040); + nv_mthd(priv, 0x9097, 0x1980, 0x00000080); + nv_mthd(priv, 0x9097, 0x1504, 0x00000080); + nv_mthd(priv, 0x9097, 0x1984, 0x00000000); + nv_mthd(priv, 0x9097, 0x0300, 0x00000001); + nv_mthd(priv, 0x9097, 0x13a8, 0x00000000); + nv_mthd(priv, 0x9097, 0x12ec, 0x00000000); + nv_mthd(priv, 0x9097, 0x1310, 0x00000000); + nv_mthd(priv, 0x9097, 0x1314, 0x00000001); + nv_mthd(priv, 0x9097, 0x1380, 0x00000000); + nv_mthd(priv, 0x9097, 0x1384, 0x00000001); + nv_mthd(priv, 0x9097, 0x1388, 0x00000001); + nv_mthd(priv, 0x9097, 0x138c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1390, 0x00000001); + nv_mthd(priv, 0x9097, 0x1394, 0x00000000); + nv_mthd(priv, 0x9097, 0x139c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1398, 0x00000000); + nv_mthd(priv, 0x9097, 0x1594, 0x00000000); + nv_mthd(priv, 0x9097, 0x1598, 0x00000001); + nv_mthd(priv, 0x9097, 0x159c, 0x00000001); + nv_mthd(priv, 0x9097, 0x15a0, 0x00000001); + nv_mthd(priv, 0x9097, 0x15a4, 0x00000001); + nv_mthd(priv, 0x9097, 0x0f54, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f58, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f5c, 0x00000000); + nv_mthd(priv, 0x9097, 0x19bc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f9c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0fa0, 0x00000000); + nv_mthd(priv, 0x9097, 0x12cc, 0x00000000); + nv_mthd(priv, 0x9097, 0x12e8, 0x00000000); + nv_mthd(priv, 0x9097, 0x130c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1360, 0x00000000); + nv_mthd(priv, 0x9097, 0x1364, 0x00000000); + nv_mthd(priv, 0x9097, 0x1368, 0x00000000); + nv_mthd(priv, 0x9097, 0x136c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1370, 0x00000000); + nv_mthd(priv, 0x9097, 0x1374, 0x00000000); + nv_mthd(priv, 0x9097, 0x1378, 0x00000000); + nv_mthd(priv, 0x9097, 0x137c, 0x00000000); + nv_mthd(priv, 0x9097, 0x133c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1340, 0x00000001); + nv_mthd(priv, 0x9097, 0x1344, 0x00000002); + nv_mthd(priv, 0x9097, 0x1348, 0x00000001); + nv_mthd(priv, 0x9097, 0x134c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1350, 0x00000002); + nv_mthd(priv, 0x9097, 0x1358, 0x00000001); + nv_mthd(priv, 0x9097, 0x12e4, 0x00000000); + nv_mthd(priv, 0x9097, 0x131c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1320, 0x00000000); + nv_mthd(priv, 0x9097, 0x1324, 0x00000000); + nv_mthd(priv, 0x9097, 0x1328, 0x00000000); + nv_mthd(priv, 0x9097, 0x19c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1140, 0x00000000); + nv_mthd(priv, 0x9097, 0x19c4, 0x00000000); + nv_mthd(priv, 0x9097, 0x19c8, 0x00001500); + nv_mthd(priv, 0x9097, 0x135c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f90, 0x00000000); + nv_mthd(priv, 0x9097, 0x19e0, 0x00000001); + nv_mthd(priv, 0x9097, 0x19e4, 0x00000001); + nv_mthd(priv, 0x9097, 0x19e8, 0x00000001); + nv_mthd(priv, 0x9097, 0x19ec, 0x00000001); + nv_mthd(priv, 0x9097, 0x19f0, 0x00000001); + nv_mthd(priv, 0x9097, 0x19f4, 0x00000001); + nv_mthd(priv, 0x9097, 0x19f8, 0x00000001); + nv_mthd(priv, 0x9097, 0x19fc, 0x00000001); + nv_mthd(priv, 0x9097, 0x19cc, 0x00000001); + nv_mthd(priv, 0x9097, 0x15b8, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a00, 0x00001111); + nv_mthd(priv, 0x9097, 0x1a04, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a08, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a0c, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a10, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a14, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a18, 0x00000000); + nv_mthd(priv, 0x9097, 0x1a1c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d6c, 0xffff0000); + nv_mthd(priv, 0x9097, 0x0d70, 0xffff0000); + nv_mthd(priv, 0x9097, 0x10f8, 0x00001010); + nv_mthd(priv, 0x9097, 0x0d80, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d84, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d88, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d8c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0d90, 0x00000000); + nv_mthd(priv, 0x9097, 0x0da0, 0x00000000); + nv_mthd(priv, 0x9097, 0x1508, 0x80000000); + nv_mthd(priv, 0x9097, 0x150c, 0x40000000); + nv_mthd(priv, 0x9097, 0x1668, 0x00000000); + nv_mthd(priv, 0x9097, 0x0318, 0x00000008); + nv_mthd(priv, 0x9097, 0x031c, 0x00000008); + nv_mthd(priv, 0x9097, 0x0d9c, 0x00000001); + nv_mthd(priv, 0x9097, 0x07dc, 0x00000000); + nv_mthd(priv, 0x9097, 0x074c, 0x00000055); + nv_mthd(priv, 0x9097, 0x1420, 0x00000003); + nv_mthd(priv, 0x9097, 0x17bc, 0x00000000); + nv_mthd(priv, 0x9097, 0x17c0, 0x00000000); + nv_mthd(priv, 0x9097, 0x17c4, 0x00000001); + nv_mthd(priv, 0x9097, 0x1008, 0x00000008); + nv_mthd(priv, 0x9097, 0x100c, 0x00000040); + nv_mthd(priv, 0x9097, 0x1010, 0x0000012c); + nv_mthd(priv, 0x9097, 0x0d60, 0x00000040); + nv_mthd(priv, 0x9097, 0x075c, 0x00000003); + nv_mthd(priv, 0x9097, 0x1018, 0x00000020); + nv_mthd(priv, 0x9097, 0x101c, 0x00000001); + nv_mthd(priv, 0x9097, 0x1020, 0x00000020); + nv_mthd(priv, 0x9097, 0x1024, 0x00000001); + nv_mthd(priv, 0x9097, 0x1444, 0x00000000); + nv_mthd(priv, 0x9097, 0x1448, 0x00000000); + nv_mthd(priv, 0x9097, 0x144c, 0x00000000); + nv_mthd(priv, 0x9097, 0x0360, 0x20164010); + nv_mthd(priv, 0x9097, 0x0364, 0x00000020); + nv_mthd(priv, 0x9097, 0x0368, 0x00000000); + nv_mthd(priv, 0x9097, 0x0de4, 0x00000000); + nv_mthd(priv, 0x9097, 0x0204, 0x00000006); + nv_mthd(priv, 0x9097, 0x0208, 0x00000000); + nv_mthd(priv, 0x9097, 0x02cc, 0x003fffff); + nv_mthd(priv, 0x9097, 0x02d0, 0x00000c48); + nv_mthd(priv, 0x9097, 0x1220, 0x00000005); + nv_mthd(priv, 0x9097, 0x0fdc, 0x00000000); + nv_mthd(priv, 0x9097, 0x0f98, 0x00300008); + nv_mthd(priv, 0x9097, 0x1284, 0x04000080); + nv_mthd(priv, 0x9097, 0x1450, 0x00300008); + nv_mthd(priv, 0x9097, 0x1454, 0x04000080); + nv_mthd(priv, 0x9097, 0x0214, 0x00000000); /* in trace, right after 0x90c0, not here */ - nv_mthd(dev, 0x9097, 0x3410, 0x80002006); + nv_mthd(priv, 0x9097, 0x3410, 0x80002006); } static void -nvc0_grctx_generate_9197(struct drm_device *dev) +nvc0_grctx_generate_9197(struct drm_device *priv) { - u32 fermi = nvc0_graph_class(dev); + u32 fermi = nvc0_graph_class(priv); u32 mthd; if (fermi == 0x9197) { for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) - nv_mthd(dev, 0x9197, mthd, 0x00000000); + nv_mthd(priv, 0x9197, mthd, 0x00000000); } - nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001); + nv_mthd(priv, 0x9197, 0x02e4, 0x0000b001); } static void -nvc0_grctx_generate_9297(struct drm_device *dev) +nvc0_grctx_generate_9297(struct drm_device *priv) { - u32 fermi = nvc0_graph_class(dev); + u32 fermi = nvc0_graph_class(priv); u32 mthd; if (fermi == 0x9297) { for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) - nv_mthd(dev, 0x9297, mthd, 0x00000000); + nv_mthd(priv, 0x9297, mthd, 0x00000000); } - nv_mthd(dev, 0x9297, 0x036c, 0x00000000); - nv_mthd(dev, 0x9297, 0x0370, 0x00000000); - nv_mthd(dev, 0x9297, 0x07a4, 0x00000000); - nv_mthd(dev, 0x9297, 0x07a8, 0x00000000); - nv_mthd(dev, 0x9297, 0x0374, 0x00000000); - nv_mthd(dev, 0x9297, 0x0378, 0x00000020); + nv_mthd(priv, 0x9297, 0x036c, 0x00000000); + nv_mthd(priv, 0x9297, 0x0370, 0x00000000); + nv_mthd(priv, 0x9297, 0x07a4, 0x00000000); + nv_mthd(priv, 0x9297, 0x07a8, 0x00000000); + nv_mthd(priv, 0x9297, 0x0374, 0x00000000); + nv_mthd(priv, 0x9297, 0x0378, 0x00000020); } static void -nvc0_grctx_generate_902d(struct drm_device *dev) +nvc0_grctx_generate_902d(struct drm_device *priv) { - nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); - nv_mthd(dev, 0x902d, 0x0204, 0x00000001); - nv_mthd(dev, 0x902d, 0x0208, 0x00000020); - nv_mthd(dev, 0x902d, 0x020c, 0x00000001); - nv_mthd(dev, 0x902d, 0x0210, 0x00000000); - nv_mthd(dev, 0x902d, 0x0214, 0x00000080); - nv_mthd(dev, 0x902d, 0x0218, 0x00000100); - nv_mthd(dev, 0x902d, 0x021c, 0x00000100); - nv_mthd(dev, 0x902d, 0x0220, 0x00000000); - nv_mthd(dev, 0x902d, 0x0224, 0x00000000); - nv_mthd(dev, 0x902d, 0x0230, 0x000000cf); - nv_mthd(dev, 0x902d, 0x0234, 0x00000001); - nv_mthd(dev, 0x902d, 0x0238, 0x00000020); - nv_mthd(dev, 0x902d, 0x023c, 0x00000001); - nv_mthd(dev, 0x902d, 0x0244, 0x00000080); - nv_mthd(dev, 0x902d, 0x0248, 0x00000100); - nv_mthd(dev, 0x902d, 0x024c, 0x00000100); + nv_mthd(priv, 0x902d, 0x0200, 0x000000cf); + nv_mthd(priv, 0x902d, 0x0204, 0x00000001); + nv_mthd(priv, 0x902d, 0x0208, 0x00000020); + nv_mthd(priv, 0x902d, 0x020c, 0x00000001); + nv_mthd(priv, 0x902d, 0x0210, 0x00000000); + nv_mthd(priv, 0x902d, 0x0214, 0x00000080); + nv_mthd(priv, 0x902d, 0x0218, 0x00000100); + nv_mthd(priv, 0x902d, 0x021c, 0x00000100); + nv_mthd(priv, 0x902d, 0x0220, 0x00000000); + nv_mthd(priv, 0x902d, 0x0224, 0x00000000); + nv_mthd(priv, 0x902d, 0x0230, 0x000000cf); + nv_mthd(priv, 0x902d, 0x0234, 0x00000001); + nv_mthd(priv, 0x902d, 0x0238, 0x00000020); + nv_mthd(priv, 0x902d, 0x023c, 0x00000001); + nv_mthd(priv, 0x902d, 0x0244, 0x00000080); + nv_mthd(priv, 0x902d, 0x0248, 0x00000100); + nv_mthd(priv, 0x902d, 0x024c, 0x00000100); } static void -nvc0_grctx_generate_9039(struct drm_device *dev) +nvc0_grctx_generate_9039(struct drm_device *priv) { - nv_mthd(dev, 0x9039, 0x030c, 0x00000000); - nv_mthd(dev, 0x9039, 0x0310, 0x00000000); - nv_mthd(dev, 0x9039, 0x0314, 0x00000000); - nv_mthd(dev, 0x9039, 0x0320, 0x00000000); - nv_mthd(dev, 0x9039, 0x0238, 0x00000000); - nv_mthd(dev, 0x9039, 0x023c, 0x00000000); - nv_mthd(dev, 0x9039, 0x0318, 0x00000000); - nv_mthd(dev, 0x9039, 0x031c, 0x00000000); + nv_mthd(priv, 0x9039, 0x030c, 0x00000000); + nv_mthd(priv, 0x9039, 0x0310, 0x00000000); + nv_mthd(priv, 0x9039, 0x0314, 0x00000000); + nv_mthd(priv, 0x9039, 0x0320, 0x00000000); + nv_mthd(priv, 0x9039, 0x0238, 0x00000000); + nv_mthd(priv, 0x9039, 0x023c, 0x00000000); + nv_mthd(priv, 0x9039, 0x0318, 0x00000000); + nv_mthd(priv, 0x9039, 0x031c, 0x00000000); } static void -nvc0_grctx_generate_90c0(struct drm_device *dev) +nvc0_grctx_generate_90c0(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; int i; for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { - nv_mthd(dev, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2724 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2708 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2728 + (i * 0x40), 0x00000000); + nv_mthd(priv, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); + nv_mthd(priv, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); + nv_mthd(priv, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); + nv_mthd(priv, 0x90c0, 0x2724 + (i * 0x40), 0x00000000); + nv_mthd(priv, 0x90c0, 0x2708 + (i * 0x40), 0x00000000); + nv_mthd(priv, 0x90c0, 0x2728 + (i * 0x40), 0x00000000); } - nv_mthd(dev, 0x90c0, 0x270c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x272c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x274c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x276c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x278c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000); - nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000); - nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000); + nv_mthd(priv, 0x90c0, 0x270c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x272c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x274c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x276c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x278c, 0x00000000); + 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++) { - nv_mthd(dev, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); - nv_mthd(dev, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); - nv_mthd(dev, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); - nv_mthd(dev, 0x90c0, 0x2734 + (i * 0x40), 0x00000040); + nv_mthd(priv, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); + nv_mthd(priv, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); + nv_mthd(priv, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); + nv_mthd(priv, 0x90c0, 0x2734 + (i * 0x40), 0x00000040); } - nv_mthd(dev, 0x90c0, 0x030c, 0x00000001); - nv_mthd(dev, 0x90c0, 0x1944, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0758, 0x00000100); - nv_mthd(dev, 0x90c0, 0x02c4, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0790, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0794, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0798, 0x00000000); - nv_mthd(dev, 0x90c0, 0x079c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x07a0, 0x00000000); - nv_mthd(dev, 0x90c0, 0x077c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0204, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0208, 0x00000000); - nv_mthd(dev, 0x90c0, 0x020c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0214, 0x00000000); - nv_mthd(dev, 0x90c0, 0x024c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x0d94, 0x00000001); - nv_mthd(dev, 0x90c0, 0x1608, 0x00000000); - nv_mthd(dev, 0x90c0, 0x160c, 0x00000000); - nv_mthd(dev, 0x90c0, 0x1664, 0x00000000); + nv_mthd(priv, 0x90c0, 0x030c, 0x00000001); + nv_mthd(priv, 0x90c0, 0x1944, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0758, 0x00000100); + nv_mthd(priv, 0x90c0, 0x02c4, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0790, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0794, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0798, 0x00000000); + nv_mthd(priv, 0x90c0, 0x079c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x07a0, 0x00000000); + nv_mthd(priv, 0x90c0, 0x077c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0204, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0208, 0x00000000); + nv_mthd(priv, 0x90c0, 0x020c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0214, 0x00000000); + nv_mthd(priv, 0x90c0, 0x024c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x0d94, 0x00000001); + nv_mthd(priv, 0x90c0, 0x1608, 0x00000000); + nv_mthd(priv, 0x90c0, 0x160c, 0x00000000); + nv_mthd(priv, 0x90c0, 0x1664, 0x00000000); } static void -nvc0_grctx_generate_dispatch(struct drm_device *dev) +nvc0_grctx_generate_dispatch(struct drm_device *priv) { int i; - nv_wr32(dev, 0x404004, 0x00000000); - nv_wr32(dev, 0x404008, 0x00000000); - nv_wr32(dev, 0x40400c, 0x00000000); - nv_wr32(dev, 0x404010, 0x00000000); - nv_wr32(dev, 0x404014, 0x00000000); - nv_wr32(dev, 0x404018, 0x00000000); - nv_wr32(dev, 0x40401c, 0x00000000); - nv_wr32(dev, 0x404020, 0x00000000); - nv_wr32(dev, 0x404024, 0x00000000); - nv_wr32(dev, 0x404028, 0x00000000); - nv_wr32(dev, 0x40402c, 0x00000000); - nv_wr32(dev, 0x404044, 0x00000000); - nv_wr32(dev, 0x404094, 0x00000000); - nv_wr32(dev, 0x404098, 0x00000000); - nv_wr32(dev, 0x40409c, 0x00000000); - nv_wr32(dev, 0x4040a0, 0x00000000); - nv_wr32(dev, 0x4040a4, 0x00000000); - nv_wr32(dev, 0x4040a8, 0x00000000); - nv_wr32(dev, 0x4040ac, 0x00000000); - nv_wr32(dev, 0x4040b0, 0x00000000); - nv_wr32(dev, 0x4040b4, 0x00000000); - nv_wr32(dev, 0x4040b8, 0x00000000); - nv_wr32(dev, 0x4040bc, 0x00000000); - nv_wr32(dev, 0x4040c0, 0x00000000); - nv_wr32(dev, 0x4040c4, 0x00000000); - nv_wr32(dev, 0x4040c8, 0xf0000087); - nv_wr32(dev, 0x4040d4, 0x00000000); - nv_wr32(dev, 0x4040d8, 0x00000000); - nv_wr32(dev, 0x4040dc, 0x00000000); - nv_wr32(dev, 0x4040e0, 0x00000000); - nv_wr32(dev, 0x4040e4, 0x00000000); - nv_wr32(dev, 0x4040e8, 0x00001000); - nv_wr32(dev, 0x4040f8, 0x00000000); - nv_wr32(dev, 0x404130, 0x00000000); - nv_wr32(dev, 0x404134, 0x00000000); - nv_wr32(dev, 0x404138, 0x20000040); - nv_wr32(dev, 0x404150, 0x0000002e); - nv_wr32(dev, 0x404154, 0x00000400); - nv_wr32(dev, 0x404158, 0x00000200); - nv_wr32(dev, 0x404164, 0x00000055); - nv_wr32(dev, 0x404168, 0x00000000); - nv_wr32(dev, 0x404174, 0x00000000); - nv_wr32(dev, 0x404178, 0x00000000); - nv_wr32(dev, 0x40417c, 0x00000000); + nv_wr32(priv, 0x404004, 0x00000000); + nv_wr32(priv, 0x404008, 0x00000000); + nv_wr32(priv, 0x40400c, 0x00000000); + nv_wr32(priv, 0x404010, 0x00000000); + nv_wr32(priv, 0x404014, 0x00000000); + nv_wr32(priv, 0x404018, 0x00000000); + nv_wr32(priv, 0x40401c, 0x00000000); + nv_wr32(priv, 0x404020, 0x00000000); + nv_wr32(priv, 0x404024, 0x00000000); + nv_wr32(priv, 0x404028, 0x00000000); + nv_wr32(priv, 0x40402c, 0x00000000); + nv_wr32(priv, 0x404044, 0x00000000); + nv_wr32(priv, 0x404094, 0x00000000); + nv_wr32(priv, 0x404098, 0x00000000); + nv_wr32(priv, 0x40409c, 0x00000000); + nv_wr32(priv, 0x4040a0, 0x00000000); + nv_wr32(priv, 0x4040a4, 0x00000000); + nv_wr32(priv, 0x4040a8, 0x00000000); + nv_wr32(priv, 0x4040ac, 0x00000000); + nv_wr32(priv, 0x4040b0, 0x00000000); + nv_wr32(priv, 0x4040b4, 0x00000000); + nv_wr32(priv, 0x4040b8, 0x00000000); + nv_wr32(priv, 0x4040bc, 0x00000000); + nv_wr32(priv, 0x4040c0, 0x00000000); + nv_wr32(priv, 0x4040c4, 0x00000000); + nv_wr32(priv, 0x4040c8, 0xf0000087); + nv_wr32(priv, 0x4040d4, 0x00000000); + nv_wr32(priv, 0x4040d8, 0x00000000); + nv_wr32(priv, 0x4040dc, 0x00000000); + nv_wr32(priv, 0x4040e0, 0x00000000); + nv_wr32(priv, 0x4040e4, 0x00000000); + nv_wr32(priv, 0x4040e8, 0x00001000); + nv_wr32(priv, 0x4040f8, 0x00000000); + nv_wr32(priv, 0x404130, 0x00000000); + nv_wr32(priv, 0x404134, 0x00000000); + nv_wr32(priv, 0x404138, 0x20000040); + nv_wr32(priv, 0x404150, 0x0000002e); + nv_wr32(priv, 0x404154, 0x00000400); + nv_wr32(priv, 0x404158, 0x00000200); + nv_wr32(priv, 0x404164, 0x00000055); + nv_wr32(priv, 0x404168, 0x00000000); + nv_wr32(priv, 0x404174, 0x00000000); + nv_wr32(priv, 0x404178, 0x00000000); + nv_wr32(priv, 0x40417c, 0x00000000); for (i = 0; i < 8; i++) - nv_wr32(dev, 0x404200 + (i * 4), 0x00000000); /* subc */ + nv_wr32(priv, 0x404200 + (i * 4), 0x00000000); /* subc */ } static void -nvc0_grctx_generate_macro(struct drm_device *dev) +nvc0_grctx_generate_macro(struct drm_device *priv) { - nv_wr32(dev, 0x404404, 0x00000000); - nv_wr32(dev, 0x404408, 0x00000000); - nv_wr32(dev, 0x40440c, 0x00000000); - nv_wr32(dev, 0x404410, 0x00000000); - nv_wr32(dev, 0x404414, 0x00000000); - nv_wr32(dev, 0x404418, 0x00000000); - nv_wr32(dev, 0x40441c, 0x00000000); - nv_wr32(dev, 0x404420, 0x00000000); - nv_wr32(dev, 0x404424, 0x00000000); - nv_wr32(dev, 0x404428, 0x00000000); - nv_wr32(dev, 0x40442c, 0x00000000); - nv_wr32(dev, 0x404430, 0x00000000); - nv_wr32(dev, 0x404434, 0x00000000); - nv_wr32(dev, 0x404438, 0x00000000); - nv_wr32(dev, 0x404460, 0x00000000); - nv_wr32(dev, 0x404464, 0x00000000); - nv_wr32(dev, 0x404468, 0x00ffffff); - nv_wr32(dev, 0x40446c, 0x00000000); - nv_wr32(dev, 0x404480, 0x00000001); - nv_wr32(dev, 0x404498, 0x00000001); + nv_wr32(priv, 0x404404, 0x00000000); + nv_wr32(priv, 0x404408, 0x00000000); + nv_wr32(priv, 0x40440c, 0x00000000); + nv_wr32(priv, 0x404410, 0x00000000); + nv_wr32(priv, 0x404414, 0x00000000); + nv_wr32(priv, 0x404418, 0x00000000); + nv_wr32(priv, 0x40441c, 0x00000000); + nv_wr32(priv, 0x404420, 0x00000000); + nv_wr32(priv, 0x404424, 0x00000000); + nv_wr32(priv, 0x404428, 0x00000000); + nv_wr32(priv, 0x40442c, 0x00000000); + nv_wr32(priv, 0x404430, 0x00000000); + nv_wr32(priv, 0x404434, 0x00000000); + nv_wr32(priv, 0x404438, 0x00000000); + nv_wr32(priv, 0x404460, 0x00000000); + nv_wr32(priv, 0x404464, 0x00000000); + nv_wr32(priv, 0x404468, 0x00ffffff); + nv_wr32(priv, 0x40446c, 0x00000000); + nv_wr32(priv, 0x404480, 0x00000001); + nv_wr32(priv, 0x404498, 0x00000001); } static void -nvc0_grctx_generate_m2mf(struct drm_device *dev) +nvc0_grctx_generate_m2mf(struct drm_device *priv) { - nv_wr32(dev, 0x404604, 0x00000015); - nv_wr32(dev, 0x404608, 0x00000000); - nv_wr32(dev, 0x40460c, 0x00002e00); - nv_wr32(dev, 0x404610, 0x00000100); - nv_wr32(dev, 0x404618, 0x00000000); - nv_wr32(dev, 0x40461c, 0x00000000); - nv_wr32(dev, 0x404620, 0x00000000); - nv_wr32(dev, 0x404624, 0x00000000); - nv_wr32(dev, 0x404628, 0x00000000); - nv_wr32(dev, 0x40462c, 0x00000000); - nv_wr32(dev, 0x404630, 0x00000000); - nv_wr32(dev, 0x404634, 0x00000000); - nv_wr32(dev, 0x404638, 0x00000004); - nv_wr32(dev, 0x40463c, 0x00000000); - nv_wr32(dev, 0x404640, 0x00000000); - nv_wr32(dev, 0x404644, 0x00000000); - nv_wr32(dev, 0x404648, 0x00000000); - nv_wr32(dev, 0x40464c, 0x00000000); - nv_wr32(dev, 0x404650, 0x00000000); - nv_wr32(dev, 0x404654, 0x00000000); - nv_wr32(dev, 0x404658, 0x00000000); - nv_wr32(dev, 0x40465c, 0x007f0100); - nv_wr32(dev, 0x404660, 0x00000000); - nv_wr32(dev, 0x404664, 0x00000000); - nv_wr32(dev, 0x404668, 0x00000000); - nv_wr32(dev, 0x40466c, 0x00000000); - nv_wr32(dev, 0x404670, 0x00000000); - nv_wr32(dev, 0x404674, 0x00000000); - nv_wr32(dev, 0x404678, 0x00000000); - nv_wr32(dev, 0x40467c, 0x00000002); - nv_wr32(dev, 0x404680, 0x00000000); - nv_wr32(dev, 0x404684, 0x00000000); - nv_wr32(dev, 0x404688, 0x00000000); - nv_wr32(dev, 0x40468c, 0x00000000); - nv_wr32(dev, 0x404690, 0x00000000); - nv_wr32(dev, 0x404694, 0x00000000); - nv_wr32(dev, 0x404698, 0x00000000); - nv_wr32(dev, 0x40469c, 0x00000000); - nv_wr32(dev, 0x4046a0, 0x007f0080); - nv_wr32(dev, 0x4046a4, 0x00000000); - nv_wr32(dev, 0x4046a8, 0x00000000); - nv_wr32(dev, 0x4046ac, 0x00000000); - nv_wr32(dev, 0x4046b0, 0x00000000); - nv_wr32(dev, 0x4046b4, 0x00000000); - nv_wr32(dev, 0x4046b8, 0x00000000); - nv_wr32(dev, 0x4046bc, 0x00000000); - nv_wr32(dev, 0x4046c0, 0x00000000); - nv_wr32(dev, 0x4046c4, 0x00000000); - nv_wr32(dev, 0x4046c8, 0x00000000); - nv_wr32(dev, 0x4046cc, 0x00000000); - nv_wr32(dev, 0x4046d0, 0x00000000); - nv_wr32(dev, 0x4046d4, 0x00000000); - nv_wr32(dev, 0x4046d8, 0x00000000); - nv_wr32(dev, 0x4046dc, 0x00000000); - nv_wr32(dev, 0x4046e0, 0x00000000); - nv_wr32(dev, 0x4046e4, 0x00000000); - nv_wr32(dev, 0x4046e8, 0x00000000); - nv_wr32(dev, 0x4046f0, 0x00000000); - nv_wr32(dev, 0x4046f4, 0x00000000); + nv_wr32(priv, 0x404604, 0x00000015); + nv_wr32(priv, 0x404608, 0x00000000); + nv_wr32(priv, 0x40460c, 0x00002e00); + nv_wr32(priv, 0x404610, 0x00000100); + nv_wr32(priv, 0x404618, 0x00000000); + nv_wr32(priv, 0x40461c, 0x00000000); + nv_wr32(priv, 0x404620, 0x00000000); + nv_wr32(priv, 0x404624, 0x00000000); + nv_wr32(priv, 0x404628, 0x00000000); + nv_wr32(priv, 0x40462c, 0x00000000); + nv_wr32(priv, 0x404630, 0x00000000); + nv_wr32(priv, 0x404634, 0x00000000); + nv_wr32(priv, 0x404638, 0x00000004); + nv_wr32(priv, 0x40463c, 0x00000000); + nv_wr32(priv, 0x404640, 0x00000000); + nv_wr32(priv, 0x404644, 0x00000000); + nv_wr32(priv, 0x404648, 0x00000000); + nv_wr32(priv, 0x40464c, 0x00000000); + nv_wr32(priv, 0x404650, 0x00000000); + nv_wr32(priv, 0x404654, 0x00000000); + nv_wr32(priv, 0x404658, 0x00000000); + nv_wr32(priv, 0x40465c, 0x007f0100); + nv_wr32(priv, 0x404660, 0x00000000); + nv_wr32(priv, 0x404664, 0x00000000); + nv_wr32(priv, 0x404668, 0x00000000); + nv_wr32(priv, 0x40466c, 0x00000000); + nv_wr32(priv, 0x404670, 0x00000000); + nv_wr32(priv, 0x404674, 0x00000000); + nv_wr32(priv, 0x404678, 0x00000000); + nv_wr32(priv, 0x40467c, 0x00000002); + nv_wr32(priv, 0x404680, 0x00000000); + nv_wr32(priv, 0x404684, 0x00000000); + nv_wr32(priv, 0x404688, 0x00000000); + nv_wr32(priv, 0x40468c, 0x00000000); + nv_wr32(priv, 0x404690, 0x00000000); + nv_wr32(priv, 0x404694, 0x00000000); + nv_wr32(priv, 0x404698, 0x00000000); + nv_wr32(priv, 0x40469c, 0x00000000); + nv_wr32(priv, 0x4046a0, 0x007f0080); + nv_wr32(priv, 0x4046a4, 0x00000000); + nv_wr32(priv, 0x4046a8, 0x00000000); + nv_wr32(priv, 0x4046ac, 0x00000000); + nv_wr32(priv, 0x4046b0, 0x00000000); + nv_wr32(priv, 0x4046b4, 0x00000000); + nv_wr32(priv, 0x4046b8, 0x00000000); + nv_wr32(priv, 0x4046bc, 0x00000000); + nv_wr32(priv, 0x4046c0, 0x00000000); + nv_wr32(priv, 0x4046c4, 0x00000000); + nv_wr32(priv, 0x4046c8, 0x00000000); + nv_wr32(priv, 0x4046cc, 0x00000000); + nv_wr32(priv, 0x4046d0, 0x00000000); + nv_wr32(priv, 0x4046d4, 0x00000000); + nv_wr32(priv, 0x4046d8, 0x00000000); + nv_wr32(priv, 0x4046dc, 0x00000000); + nv_wr32(priv, 0x4046e0, 0x00000000); + nv_wr32(priv, 0x4046e4, 0x00000000); + nv_wr32(priv, 0x4046e8, 0x00000000); + nv_wr32(priv, 0x4046f0, 0x00000000); + nv_wr32(priv, 0x4046f4, 0x00000000); } static void -nvc0_grctx_generate_unk47xx(struct drm_device *dev) +nvc0_grctx_generate_unk47xx(struct drm_device *priv) { - nv_wr32(dev, 0x404700, 0x00000000); - nv_wr32(dev, 0x404704, 0x00000000); - nv_wr32(dev, 0x404708, 0x00000000); - nv_wr32(dev, 0x40470c, 0x00000000); - nv_wr32(dev, 0x404710, 0x00000000); - nv_wr32(dev, 0x404714, 0x00000000); - nv_wr32(dev, 0x404718, 0x00000000); - nv_wr32(dev, 0x40471c, 0x00000000); - nv_wr32(dev, 0x404720, 0x00000000); - nv_wr32(dev, 0x404724, 0x00000000); - nv_wr32(dev, 0x404728, 0x00000000); - nv_wr32(dev, 0x40472c, 0x00000000); - nv_wr32(dev, 0x404730, 0x00000000); - nv_wr32(dev, 0x404734, 0x00000100); - nv_wr32(dev, 0x404738, 0x00000000); - nv_wr32(dev, 0x40473c, 0x00000000); - nv_wr32(dev, 0x404740, 0x00000000); - nv_wr32(dev, 0x404744, 0x00000000); - nv_wr32(dev, 0x404748, 0x00000000); - nv_wr32(dev, 0x40474c, 0x00000000); - nv_wr32(dev, 0x404750, 0x00000000); - nv_wr32(dev, 0x404754, 0x00000000); + nv_wr32(priv, 0x404700, 0x00000000); + nv_wr32(priv, 0x404704, 0x00000000); + nv_wr32(priv, 0x404708, 0x00000000); + nv_wr32(priv, 0x40470c, 0x00000000); + nv_wr32(priv, 0x404710, 0x00000000); + nv_wr32(priv, 0x404714, 0x00000000); + nv_wr32(priv, 0x404718, 0x00000000); + nv_wr32(priv, 0x40471c, 0x00000000); + nv_wr32(priv, 0x404720, 0x00000000); + nv_wr32(priv, 0x404724, 0x00000000); + nv_wr32(priv, 0x404728, 0x00000000); + nv_wr32(priv, 0x40472c, 0x00000000); + nv_wr32(priv, 0x404730, 0x00000000); + nv_wr32(priv, 0x404734, 0x00000100); + nv_wr32(priv, 0x404738, 0x00000000); + nv_wr32(priv, 0x40473c, 0x00000000); + nv_wr32(priv, 0x404740, 0x00000000); + nv_wr32(priv, 0x404744, 0x00000000); + nv_wr32(priv, 0x404748, 0x00000000); + nv_wr32(priv, 0x40474c, 0x00000000); + nv_wr32(priv, 0x404750, 0x00000000); + nv_wr32(priv, 0x404754, 0x00000000); } static void -nvc0_grctx_generate_shaders(struct drm_device *dev) +nvc0_grctx_generate_shaders(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; if (dev_priv->chipset == 0xd9) { - nv_wr32(dev, 0x405800, 0x0f8000bf); - nv_wr32(dev, 0x405830, 0x02180218); - nv_wr32(dev, 0x405834, 0x08000000); + nv_wr32(priv, 0x405800, 0x0f8000bf); + nv_wr32(priv, 0x405830, 0x02180218); + nv_wr32(priv, 0x405834, 0x08000000); } else if (dev_priv->chipset == 0xc1) { - nv_wr32(dev, 0x405800, 0x0f8000bf); - nv_wr32(dev, 0x405830, 0x02180218); - nv_wr32(dev, 0x405834, 0x00000000); + nv_wr32(priv, 0x405800, 0x0f8000bf); + nv_wr32(priv, 0x405830, 0x02180218); + nv_wr32(priv, 0x405834, 0x00000000); } else { - nv_wr32(dev, 0x405800, 0x078000bf); - nv_wr32(dev, 0x405830, 0x02180000); - nv_wr32(dev, 0x405834, 0x00000000); + nv_wr32(priv, 0x405800, 0x078000bf); + nv_wr32(priv, 0x405830, 0x02180000); + nv_wr32(priv, 0x405834, 0x00000000); } - nv_wr32(dev, 0x405838, 0x00000000); - nv_wr32(dev, 0x405854, 0x00000000); - nv_wr32(dev, 0x405870, 0x00000001); - nv_wr32(dev, 0x405874, 0x00000001); - nv_wr32(dev, 0x405878, 0x00000001); - nv_wr32(dev, 0x40587c, 0x00000001); - nv_wr32(dev, 0x405a00, 0x00000000); - nv_wr32(dev, 0x405a04, 0x00000000); - nv_wr32(dev, 0x405a18, 0x00000000); + nv_wr32(priv, 0x405838, 0x00000000); + nv_wr32(priv, 0x405854, 0x00000000); + nv_wr32(priv, 0x405870, 0x00000001); + nv_wr32(priv, 0x405874, 0x00000001); + nv_wr32(priv, 0x405878, 0x00000001); + nv_wr32(priv, 0x40587c, 0x00000001); + nv_wr32(priv, 0x405a00, 0x00000000); + nv_wr32(priv, 0x405a04, 0x00000000); + nv_wr32(priv, 0x405a18, 0x00000000); } static void -nvc0_grctx_generate_unk60xx(struct drm_device *dev) +nvc0_grctx_generate_unk60xx(struct drm_device *priv) { - nv_wr32(dev, 0x406020, 0x000103c1); - nv_wr32(dev, 0x406028, 0x00000001); - nv_wr32(dev, 0x40602c, 0x00000001); - nv_wr32(dev, 0x406030, 0x00000001); - nv_wr32(dev, 0x406034, 0x00000001); + nv_wr32(priv, 0x406020, 0x000103c1); + nv_wr32(priv, 0x406028, 0x00000001); + nv_wr32(priv, 0x40602c, 0x00000001); + nv_wr32(priv, 0x406030, 0x00000001); + nv_wr32(priv, 0x406034, 0x00000001); } static void -nvc0_grctx_generate_unk64xx(struct drm_device *dev) +nvc0_grctx_generate_unk64xx(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; - nv_wr32(dev, 0x4064a8, 0x00000000); - nv_wr32(dev, 0x4064ac, 0x00003fff); - nv_wr32(dev, 0x4064b4, 0x00000000); - nv_wr32(dev, 0x4064b8, 0x00000000); + 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) - nv_wr32(dev, 0x4064bc, 0x00000000); + nv_wr32(priv, 0x4064bc, 0x00000000); if (dev_priv->chipset == 0xc1 || dev_priv->chipset == 0xd9) { - nv_wr32(dev, 0x4064c0, 0x80140078); - nv_wr32(dev, 0x4064c4, 0x0086ffff); + nv_wr32(priv, 0x4064c0, 0x80140078); + nv_wr32(priv, 0x4064c4, 0x0086ffff); } } static void -nvc0_grctx_generate_tpbus(struct drm_device *dev) +nvc0_grctx_generate_tpbus(struct drm_device *priv) { - nv_wr32(dev, 0x407804, 0x00000023); - nv_wr32(dev, 0x40780c, 0x0a418820); - nv_wr32(dev, 0x407810, 0x062080e6); - nv_wr32(dev, 0x407814, 0x020398a4); - nv_wr32(dev, 0x407818, 0x0e629062); - nv_wr32(dev, 0x40781c, 0x0a418820); - nv_wr32(dev, 0x407820, 0x000000e6); - nv_wr32(dev, 0x4078bc, 0x00000103); + nv_wr32(priv, 0x407804, 0x00000023); + nv_wr32(priv, 0x40780c, 0x0a418820); + nv_wr32(priv, 0x407810, 0x062080e6); + nv_wr32(priv, 0x407814, 0x020398a4); + nv_wr32(priv, 0x407818, 0x0e629062); + nv_wr32(priv, 0x40781c, 0x0a418820); + nv_wr32(priv, 0x407820, 0x000000e6); + nv_wr32(priv, 0x4078bc, 0x00000103); } static void -nvc0_grctx_generate_ccache(struct drm_device *dev) +nvc0_grctx_generate_ccache(struct drm_device *priv) { - nv_wr32(dev, 0x408000, 0x00000000); - nv_wr32(dev, 0x408004, 0x00000000); - nv_wr32(dev, 0x408008, 0x00000018); - nv_wr32(dev, 0x40800c, 0x00000000); - nv_wr32(dev, 0x408010, 0x00000000); - nv_wr32(dev, 0x408014, 0x00000069); - nv_wr32(dev, 0x408018, 0xe100e100); - nv_wr32(dev, 0x408064, 0x00000000); + nv_wr32(priv, 0x408000, 0x00000000); + nv_wr32(priv, 0x408004, 0x00000000); + nv_wr32(priv, 0x408008, 0x00000018); + nv_wr32(priv, 0x40800c, 0x00000000); + nv_wr32(priv, 0x408010, 0x00000000); + nv_wr32(priv, 0x408014, 0x00000069); + nv_wr32(priv, 0x408018, 0xe100e100); + nv_wr32(priv, 0x408064, 0x00000000); } static void -nvc0_grctx_generate_rop(struct drm_device *dev) +nvc0_grctx_generate_rop(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; int chipset = dev_priv->chipset; /* ROPC_BROADCAST */ - nv_wr32(dev, 0x408800, 0x02802a3c); - nv_wr32(dev, 0x408804, 0x00000040); + nv_wr32(priv, 0x408800, 0x02802a3c); + nv_wr32(priv, 0x408804, 0x00000040); if (chipset == 0xd9) { - nv_wr32(dev, 0x408808, 0x1043e005); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x1043e005); - nv_wr32(dev, 0x408908, 0x00c8102f); + nv_wr32(priv, 0x408808, 0x1043e005); + nv_wr32(priv, 0x408900, 0x3080b801); + nv_wr32(priv, 0x408904, 0x1043e005); + nv_wr32(priv, 0x408908, 0x00c8102f); } else if (chipset == 0xc1) { - nv_wr32(dev, 0x408808, 0x1003e005); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x62000001); - nv_wr32(dev, 0x408908, 0x00c80929); + nv_wr32(priv, 0x408808, 0x1003e005); + nv_wr32(priv, 0x408900, 0x3080b801); + nv_wr32(priv, 0x408904, 0x62000001); + nv_wr32(priv, 0x408908, 0x00c80929); } else { - nv_wr32(dev, 0x408808, 0x0003e00d); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x02000001); - nv_wr32(dev, 0x408908, 0x00c80929); + nv_wr32(priv, 0x408808, 0x0003e00d); + nv_wr32(priv, 0x408900, 0x3080b801); + nv_wr32(priv, 0x408904, 0x02000001); + nv_wr32(priv, 0x408908, 0x00c80929); } - nv_wr32(dev, 0x40890c, 0x00000000); - nv_wr32(dev, 0x408980, 0x0000011d); + nv_wr32(priv, 0x40890c, 0x00000000); + nv_wr32(priv, 0x408980, 0x0000011d); } static void -nvc0_grctx_generate_gpc(struct drm_device *dev) +nvc0_grctx_generate_gpc(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; int chipset = dev_priv->chipset; int i; /* GPC_BROADCAST */ - nv_wr32(dev, 0x418380, 0x00000016); - nv_wr32(dev, 0x418400, 0x38004e00); - nv_wr32(dev, 0x418404, 0x71e0ffff); - nv_wr32(dev, 0x418408, 0x00000000); - nv_wr32(dev, 0x41840c, 0x00001008); - nv_wr32(dev, 0x418410, 0x0fff0fff); - nv_wr32(dev, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff); - nv_wr32(dev, 0x418450, 0x00000000); - nv_wr32(dev, 0x418454, 0x00000000); - nv_wr32(dev, 0x418458, 0x00000000); - nv_wr32(dev, 0x41845c, 0x00000000); - nv_wr32(dev, 0x418460, 0x00000000); - nv_wr32(dev, 0x418464, 0x00000000); - nv_wr32(dev, 0x418468, 0x00000001); - nv_wr32(dev, 0x41846c, 0x00000000); - nv_wr32(dev, 0x418470, 0x00000000); - nv_wr32(dev, 0x418600, 0x0000001f); - nv_wr32(dev, 0x418684, 0x0000000f); - nv_wr32(dev, 0x418700, 0x00000002); - nv_wr32(dev, 0x418704, 0x00000080); - nv_wr32(dev, 0x418708, 0x00000000); - nv_wr32(dev, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000); - nv_wr32(dev, 0x418710, 0x00000000); - nv_wr32(dev, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a); - nv_wr32(dev, 0x418808, 0x00000000); - nv_wr32(dev, 0x41880c, 0x00000000); - nv_wr32(dev, 0x418810, 0x00000000); - nv_wr32(dev, 0x418828, 0x00008442); + nv_wr32(priv, 0x418380, 0x00000016); + nv_wr32(priv, 0x418400, 0x38004e00); + nv_wr32(priv, 0x418404, 0x71e0ffff); + nv_wr32(priv, 0x418408, 0x00000000); + nv_wr32(priv, 0x41840c, 0x00001008); + nv_wr32(priv, 0x418410, 0x0fff0fff); + nv_wr32(priv, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff); + nv_wr32(priv, 0x418450, 0x00000000); + nv_wr32(priv, 0x418454, 0x00000000); + nv_wr32(priv, 0x418458, 0x00000000); + nv_wr32(priv, 0x41845c, 0x00000000); + nv_wr32(priv, 0x418460, 0x00000000); + nv_wr32(priv, 0x418464, 0x00000000); + nv_wr32(priv, 0x418468, 0x00000001); + nv_wr32(priv, 0x41846c, 0x00000000); + nv_wr32(priv, 0x418470, 0x00000000); + nv_wr32(priv, 0x418600, 0x0000001f); + nv_wr32(priv, 0x418684, 0x0000000f); + nv_wr32(priv, 0x418700, 0x00000002); + nv_wr32(priv, 0x418704, 0x00000080); + nv_wr32(priv, 0x418708, 0x00000000); + nv_wr32(priv, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000); + nv_wr32(priv, 0x418710, 0x00000000); + nv_wr32(priv, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a); + nv_wr32(priv, 0x418808, 0x00000000); + nv_wr32(priv, 0x41880c, 0x00000000); + nv_wr32(priv, 0x418810, 0x00000000); + nv_wr32(priv, 0x418828, 0x00008442); if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x418830, 0x10000001); + nv_wr32(priv, 0x418830, 0x10000001); else - nv_wr32(dev, 0x418830, 0x00000001); - nv_wr32(dev, 0x4188d8, 0x00000008); - nv_wr32(dev, 0x4188e0, 0x01000000); - nv_wr32(dev, 0x4188e8, 0x00000000); - nv_wr32(dev, 0x4188ec, 0x00000000); - nv_wr32(dev, 0x4188f0, 0x00000000); - nv_wr32(dev, 0x4188f4, 0x00000000); - nv_wr32(dev, 0x4188f8, 0x00000000); + nv_wr32(priv, 0x418830, 0x00000001); + nv_wr32(priv, 0x4188d8, 0x00000008); + nv_wr32(priv, 0x4188e0, 0x01000000); + nv_wr32(priv, 0x4188e8, 0x00000000); + nv_wr32(priv, 0x4188ec, 0x00000000); + nv_wr32(priv, 0x4188f0, 0x00000000); + nv_wr32(priv, 0x4188f4, 0x00000000); + nv_wr32(priv, 0x4188f8, 0x00000000); if (chipset == 0xd9) - nv_wr32(dev, 0x4188fc, 0x20100008); + nv_wr32(priv, 0x4188fc, 0x20100008); else if (chipset == 0xc1) - nv_wr32(dev, 0x4188fc, 0x00100018); + nv_wr32(priv, 0x4188fc, 0x00100018); else - nv_wr32(dev, 0x4188fc, 0x00100000); - nv_wr32(dev, 0x41891c, 0x00ff00ff); - nv_wr32(dev, 0x418924, 0x00000000); - nv_wr32(dev, 0x418928, 0x00ffff00); - nv_wr32(dev, 0x41892c, 0x0000ff00); + nv_wr32(priv, 0x4188fc, 0x00100000); + nv_wr32(priv, 0x41891c, 0x00ff00ff); + nv_wr32(priv, 0x418924, 0x00000000); + nv_wr32(priv, 0x418928, 0x00ffff00); + nv_wr32(priv, 0x41892c, 0x0000ff00); for (i = 0; i < 8; i++) { - nv_wr32(dev, 0x418a00 + (i * 0x20), 0x00000000); - nv_wr32(dev, 0x418a04 + (i * 0x20), 0x00000000); - nv_wr32(dev, 0x418a08 + (i * 0x20), 0x00000000); - nv_wr32(dev, 0x418a0c + (i * 0x20), 0x00010000); - nv_wr32(dev, 0x418a10 + (i * 0x20), 0x00000000); - nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000); - nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000); + nv_wr32(priv, 0x418a00 + (i * 0x20), 0x00000000); + nv_wr32(priv, 0x418a04 + (i * 0x20), 0x00000000); + nv_wr32(priv, 0x418a08 + (i * 0x20), 0x00000000); + nv_wr32(priv, 0x418a0c + (i * 0x20), 0x00010000); + nv_wr32(priv, 0x418a10 + (i * 0x20), 0x00000000); + nv_wr32(priv, 0x418a14 + (i * 0x20), 0x00000000); + nv_wr32(priv, 0x418a18 + (i * 0x20), 0x00000000); } - nv_wr32(dev, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); - nv_wr32(dev, 0x418b08, 0x0a418820); - nv_wr32(dev, 0x418b0c, 0x062080e6); - nv_wr32(dev, 0x418b10, 0x020398a4); - nv_wr32(dev, 0x418b14, 0x0e629062); - nv_wr32(dev, 0x418b18, 0x0a418820); - nv_wr32(dev, 0x418b1c, 0x000000e6); - nv_wr32(dev, 0x418bb8, 0x00000103); - nv_wr32(dev, 0x418c08, 0x00000001); - nv_wr32(dev, 0x418c10, 0x00000000); - nv_wr32(dev, 0x418c14, 0x00000000); - nv_wr32(dev, 0x418c18, 0x00000000); - nv_wr32(dev, 0x418c1c, 0x00000000); - nv_wr32(dev, 0x418c20, 0x00000000); - nv_wr32(dev, 0x418c24, 0x00000000); - nv_wr32(dev, 0x418c28, 0x00000000); - nv_wr32(dev, 0x418c2c, 0x00000000); + nv_wr32(priv, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); + nv_wr32(priv, 0x418b08, 0x0a418820); + nv_wr32(priv, 0x418b0c, 0x062080e6); + nv_wr32(priv, 0x418b10, 0x020398a4); + nv_wr32(priv, 0x418b14, 0x0e629062); + nv_wr32(priv, 0x418b18, 0x0a418820); + nv_wr32(priv, 0x418b1c, 0x000000e6); + nv_wr32(priv, 0x418bb8, 0x00000103); + nv_wr32(priv, 0x418c08, 0x00000001); + nv_wr32(priv, 0x418c10, 0x00000000); + nv_wr32(priv, 0x418c14, 0x00000000); + nv_wr32(priv, 0x418c18, 0x00000000); + nv_wr32(priv, 0x418c1c, 0x00000000); + nv_wr32(priv, 0x418c20, 0x00000000); + nv_wr32(priv, 0x418c24, 0x00000000); + nv_wr32(priv, 0x418c28, 0x00000000); + nv_wr32(priv, 0x418c2c, 0x00000000); if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x418c6c, 0x00000001); - nv_wr32(dev, 0x418c80, 0x20200004); - nv_wr32(dev, 0x418c8c, 0x00000001); - nv_wr32(dev, 0x419000, 0x00000780); - nv_wr32(dev, 0x419004, 0x00000000); - nv_wr32(dev, 0x419008, 0x00000000); - nv_wr32(dev, 0x419014, 0x00000004); + nv_wr32(priv, 0x418c6c, 0x00000001); + nv_wr32(priv, 0x418c80, 0x20200004); + nv_wr32(priv, 0x418c8c, 0x00000001); + nv_wr32(priv, 0x419000, 0x00000780); + nv_wr32(priv, 0x419004, 0x00000000); + nv_wr32(priv, 0x419008, 0x00000000); + nv_wr32(priv, 0x419014, 0x00000004); } static void -nvc0_grctx_generate_tp(struct drm_device *dev) +nvc0_grctx_generate_tp(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; int chipset = dev_priv->chipset; /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(dev, 0x419818, 0x00000000); - nv_wr32(dev, 0x41983c, 0x00038bc7); - nv_wr32(dev, 0x419848, 0x00000000); + nv_wr32(priv, 0x419818, 0x00000000); + nv_wr32(priv, 0x41983c, 0x00038bc7); + nv_wr32(priv, 0x419848, 0x00000000); if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419864, 0x00000129); + nv_wr32(priv, 0x419864, 0x00000129); else - nv_wr32(dev, 0x419864, 0x0000012a); - nv_wr32(dev, 0x419888, 0x00000000); - nv_wr32(dev, 0x419a00, 0x000001f0); - nv_wr32(dev, 0x419a04, 0x00000001); - nv_wr32(dev, 0x419a08, 0x00000023); - nv_wr32(dev, 0x419a0c, 0x00020000); - nv_wr32(dev, 0x419a10, 0x00000000); - nv_wr32(dev, 0x419a14, 0x00000200); - nv_wr32(dev, 0x419a1c, 0x00000000); - nv_wr32(dev, 0x419a20, 0x00000800); + nv_wr32(priv, 0x419864, 0x0000012a); + nv_wr32(priv, 0x419888, 0x00000000); + nv_wr32(priv, 0x419a00, 0x000001f0); + nv_wr32(priv, 0x419a04, 0x00000001); + nv_wr32(priv, 0x419a08, 0x00000023); + nv_wr32(priv, 0x419a0c, 0x00020000); + nv_wr32(priv, 0x419a10, 0x00000000); + nv_wr32(priv, 0x419a14, 0x00000200); + nv_wr32(priv, 0x419a1c, 0x00000000); + nv_wr32(priv, 0x419a20, 0x00000800); if (chipset == 0xd9) - nv_wr32(dev, 0x00419ac4, 0x0017f440); + nv_wr32(priv, 0x00419ac4, 0x0017f440); else if (chipset != 0xc0 && chipset != 0xc8) - nv_wr32(dev, 0x00419ac4, 0x0007f440); - nv_wr32(dev, 0x419b00, 0x0a418820); - nv_wr32(dev, 0x419b04, 0x062080e6); - nv_wr32(dev, 0x419b08, 0x020398a4); - nv_wr32(dev, 0x419b0c, 0x0e629062); - nv_wr32(dev, 0x419b10, 0x0a418820); - nv_wr32(dev, 0x419b14, 0x000000e6); - nv_wr32(dev, 0x419bd0, 0x00900103); + nv_wr32(priv, 0x00419ac4, 0x0007f440); + nv_wr32(priv, 0x419b00, 0x0a418820); + nv_wr32(priv, 0x419b04, 0x062080e6); + nv_wr32(priv, 0x419b08, 0x020398a4); + nv_wr32(priv, 0x419b0c, 0x0e629062); + nv_wr32(priv, 0x419b10, 0x0a418820); + nv_wr32(priv, 0x419b14, 0x000000e6); + nv_wr32(priv, 0x419bd0, 0x00900103); if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419be0, 0x00400001); + nv_wr32(priv, 0x419be0, 0x00400001); else - nv_wr32(dev, 0x419be0, 0x00000001); - nv_wr32(dev, 0x419be4, 0x00000000); - nv_wr32(dev, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a); - nv_wr32(dev, 0x419c04, 0x00000006); - nv_wr32(dev, 0x419c08, 0x00000002); - nv_wr32(dev, 0x419c20, 0x00000000); + nv_wr32(priv, 0x419be0, 0x00000001); + nv_wr32(priv, 0x419be4, 0x00000000); + nv_wr32(priv, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a); + nv_wr32(priv, 0x419c04, 0x00000006); + nv_wr32(priv, 0x419c08, 0x00000002); + nv_wr32(priv, 0x419c20, 0x00000000); if (dev_priv->chipset == 0xd9) { - nv_wr32(dev, 0x419c24, 0x00084210); - nv_wr32(dev, 0x419c28, 0x3cf3cf3c); - nv_wr32(dev, 0x419cb0, 0x00020048); + nv_wr32(priv, 0x419c24, 0x00084210); + nv_wr32(priv, 0x419c28, 0x3cf3cf3c); + nv_wr32(priv, 0x419cb0, 0x00020048); } else if (chipset == 0xce || chipset == 0xcf) { - nv_wr32(dev, 0x419cb0, 0x00020048); + nv_wr32(priv, 0x419cb0, 0x00020048); } else { - nv_wr32(dev, 0x419cb0, 0x00060048); + nv_wr32(priv, 0x419cb0, 0x00060048); } - nv_wr32(dev, 0x419ce8, 0x00000000); - nv_wr32(dev, 0x419cf4, 0x00000183); + nv_wr32(priv, 0x419ce8, 0x00000000); + nv_wr32(priv, 0x419cf4, 0x00000183); if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419d20, 0x12180000); + nv_wr32(priv, 0x419d20, 0x12180000); else - nv_wr32(dev, 0x419d20, 0x02180000); - nv_wr32(dev, 0x419d24, 0x00001fff); + nv_wr32(priv, 0x419d20, 0x02180000); + nv_wr32(priv, 0x419d24, 0x00001fff); if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419d44, 0x02180218); - nv_wr32(dev, 0x419e04, 0x00000000); - nv_wr32(dev, 0x419e08, 0x00000000); - nv_wr32(dev, 0x419e0c, 0x00000000); - nv_wr32(dev, 0x419e10, 0x00000002); - nv_wr32(dev, 0x419e44, 0x001beff2); - nv_wr32(dev, 0x419e48, 0x00000000); - nv_wr32(dev, 0x419e4c, 0x0000000f); - nv_wr32(dev, 0x419e50, 0x00000000); - nv_wr32(dev, 0x419e54, 0x00000000); - nv_wr32(dev, 0x419e58, 0x00000000); - nv_wr32(dev, 0x419e5c, 0x00000000); - nv_wr32(dev, 0x419e60, 0x00000000); - nv_wr32(dev, 0x419e64, 0x00000000); - nv_wr32(dev, 0x419e68, 0x00000000); - nv_wr32(dev, 0x419e6c, 0x00000000); - nv_wr32(dev, 0x419e70, 0x00000000); - nv_wr32(dev, 0x419e74, 0x00000000); - nv_wr32(dev, 0x419e78, 0x00000000); - nv_wr32(dev, 0x419e7c, 0x00000000); - nv_wr32(dev, 0x419e80, 0x00000000); - nv_wr32(dev, 0x419e84, 0x00000000); - nv_wr32(dev, 0x419e88, 0x00000000); - nv_wr32(dev, 0x419e8c, 0x00000000); - nv_wr32(dev, 0x419e90, 0x00000000); - nv_wr32(dev, 0x419e98, 0x00000000); + nv_wr32(priv, 0x419d44, 0x02180218); + nv_wr32(priv, 0x419e04, 0x00000000); + nv_wr32(priv, 0x419e08, 0x00000000); + nv_wr32(priv, 0x419e0c, 0x00000000); + nv_wr32(priv, 0x419e10, 0x00000002); + nv_wr32(priv, 0x419e44, 0x001beff2); + nv_wr32(priv, 0x419e48, 0x00000000); + nv_wr32(priv, 0x419e4c, 0x0000000f); + nv_wr32(priv, 0x419e50, 0x00000000); + nv_wr32(priv, 0x419e54, 0x00000000); + nv_wr32(priv, 0x419e58, 0x00000000); + nv_wr32(priv, 0x419e5c, 0x00000000); + nv_wr32(priv, 0x419e60, 0x00000000); + nv_wr32(priv, 0x419e64, 0x00000000); + nv_wr32(priv, 0x419e68, 0x00000000); + nv_wr32(priv, 0x419e6c, 0x00000000); + nv_wr32(priv, 0x419e70, 0x00000000); + nv_wr32(priv, 0x419e74, 0x00000000); + nv_wr32(priv, 0x419e78, 0x00000000); + nv_wr32(priv, 0x419e7c, 0x00000000); + nv_wr32(priv, 0x419e80, 0x00000000); + nv_wr32(priv, 0x419e84, 0x00000000); + nv_wr32(priv, 0x419e88, 0x00000000); + nv_wr32(priv, 0x419e8c, 0x00000000); + nv_wr32(priv, 0x419e90, 0x00000000); + nv_wr32(priv, 0x419e98, 0x00000000); if (chipset != 0xc0 && chipset != 0xc8) - nv_wr32(dev, 0x419ee0, 0x00011110); - nv_wr32(dev, 0x419f50, 0x00000000); - nv_wr32(dev, 0x419f54, 0x00000000); + nv_wr32(priv, 0x419ee0, 0x00011110); + nv_wr32(priv, 0x419f50, 0x00000000); + nv_wr32(priv, 0x419f54, 0x00000000); if (chipset != 0xc0 && chipset != 0xc8) - nv_wr32(dev, 0x419f58, 0x00000000); + nv_wr32(priv, 0x419f58, 0x00000000); } int nvc0_grctx_generate(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; + struct drm_device *priv = chan->dev; int i, gpc, tp, id; - u32 fermi = nvc0_graph_class(dev); + u32 fermi = nvc0_graph_class(priv); u32 r000260, tmp; - r000260 = nv_rd32(dev, 0x000260); - nv_wr32(dev, 0x000260, r000260 & ~1); - nv_wr32(dev, 0x400208, 0x00000000); + r000260 = nv_rd32(priv, 0x000260); + nv_wr32(priv, 0x000260, r000260 & ~1); + nv_wr32(priv, 0x400208, 0x00000000); - nvc0_grctx_generate_dispatch(dev); - nvc0_grctx_generate_macro(dev); - nvc0_grctx_generate_m2mf(dev); - nvc0_grctx_generate_unk47xx(dev); - nvc0_grctx_generate_shaders(dev); - nvc0_grctx_generate_unk60xx(dev); - nvc0_grctx_generate_unk64xx(dev); - nvc0_grctx_generate_tpbus(dev); - nvc0_grctx_generate_ccache(dev); - nvc0_grctx_generate_rop(dev); - nvc0_grctx_generate_gpc(dev); - nvc0_grctx_generate_tp(dev); + nvc0_grctx_generate_dispatch(priv); + nvc0_grctx_generate_macro(priv); + nvc0_grctx_generate_m2mf(priv); + nvc0_grctx_generate_unk47xx(priv); + nvc0_grctx_generate_shaders(priv); + nvc0_grctx_generate_unk60xx(priv); + nvc0_grctx_generate_unk64xx(priv); + nvc0_grctx_generate_tpbus(priv); + nvc0_grctx_generate_ccache(priv); + nvc0_grctx_generate_rop(priv); + nvc0_grctx_generate_gpc(priv); + nvc0_grctx_generate_tp(priv); - nv_wr32(dev, 0x404154, 0x00000000); + nv_wr32(priv, 0x404154, 0x00000000); /* fuc "mmio list" writes */ for (i = 0; i < grch->mmio_nr * 8; i += 8) { u32 reg = nv_ro32(grch->mmio, i + 0); - nv_wr32(dev, reg, nv_ro32(grch->mmio, i + 4)); + nv_wr32(priv, reg, nv_ro32(grch->mmio, i + 4)); } for (tp = 0, id = 0; tp < 4; tp++) { - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tp < priv->tp_nr[gpc]) { - nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id); - nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x088), id); + for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { + if (tp < oprv->tp_nr[gpc]) { + nv_wr32(priv, TP_UNIT(gpc, tp, 0x698), id); + nv_wr32(priv, TP_UNIT(gpc, tp, 0x4e8), id); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); + nv_wr32(priv, TP_UNIT(gpc, tp, 0x088), id); id++; } - nv_wr32(dev, GPC_UNIT(gpc, 0x0c08), priv->tp_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tp_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tp_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tp_nr[gpc]); } } tmp = 0; - for (i = 0; i < priv->gpc_nr; i++) - tmp |= priv->tp_nr[i] << (i * 4); - nv_wr32(dev, 0x406028, tmp); - nv_wr32(dev, 0x405870, tmp); + for (i = 0; i < oprv->gpc_nr; i++) + tmp |= oprv->tp_nr[i] << (i * 4); + nv_wr32(priv, 0x406028, tmp); + nv_wr32(priv, 0x405870, tmp); - nv_wr32(dev, 0x40602c, 0x00000000); - nv_wr32(dev, 0x405874, 0x00000000); - nv_wr32(dev, 0x406030, 0x00000000); - nv_wr32(dev, 0x405878, 0x00000000); - nv_wr32(dev, 0x406034, 0x00000000); - nv_wr32(dev, 0x40587c, 0x00000000); + nv_wr32(priv, 0x40602c, 0x00000000); + nv_wr32(priv, 0x405874, 0x00000000); + nv_wr32(priv, 0x406030, 0x00000000); + nv_wr32(priv, 0x405878, 0x00000000); + nv_wr32(priv, 0x406034, 0x00000000); + nv_wr32(priv, 0x40587c, 0x00000000); if (1) { u8 tpnr[GPC_MAX], data[TP_MAX]; - memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + memcpy(tpnr, oprv->tp_nr, sizeof(oprv->tp_nr)); memset(data, 0x1f, sizeof(data)); gpc = -1; - for (tp = 0; tp < priv->tp_total; tp++) { + for (tp = 0; tp < oprv->tp_total; tp++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpnr[gpc]); tpnr[gpc]--; data[tp] = gpc; } for (i = 0; i < 4; i++) - nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); + nv_wr32(priv, 0x4060a8 + (i * 4), ((u32 *)data)[i]); } if (1) { @@ -1874,12 +1874,12 @@ nvc0_grctx_generate(struct nouveau_channel *chan) u8 shift, ntpcv; /* calculate first set of magics */ - memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + memcpy(tpnr, oprv->tp_nr, sizeof(oprv->tp_nr)); gpc = -1; - for (tp = 0; tp < priv->tp_total; tp++) { + for (tp = 0; tp < oprv->tp_total; tp++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpnr[gpc]); tpnr[gpc]--; @@ -1891,7 +1891,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) /* and the second... */ shift = 0; - ntpcv = priv->tp_total; + ntpcv = oprv->tp_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -1904,975 +1904,975 @@ nvc0_grctx_generate(struct nouveau_channel *chan) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* GPC_BROADCAST */ - nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) | - priv->magic_not_rop_nr); + nv_wr32(priv, 0x418bb8, (oprv->tp_total << 8) | + oprv->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(dev, 0x418b08 + (i * 4), data[i]); + nv_wr32(priv, 0x418b08 + (i * 4), data[i]); /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) | - priv->magic_not_rop_nr | + nv_wr32(priv, 0x419bd0, (oprv->tp_total << 8) | + oprv->magic_not_rop_nr | data2[0]); - nv_wr32(dev, 0x419be4, data2[1]); + nv_wr32(priv, 0x419be4, data2[1]); for (i = 0; i < 6; i++) - nv_wr32(dev, 0x419b00 + (i * 4), data[i]); + nv_wr32(priv, 0x419b00 + (i * 4), data[i]); /* UNK78xx */ - nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) | - priv->magic_not_rop_nr); + nv_wr32(priv, 0x4078bc, (oprv->tp_total << 8) | + oprv->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(dev, 0x40780c + (i * 4), data[i]); + nv_wr32(priv, 0x40780c + (i * 4), data[i]); } if (1) { u32 tp_mask = 0, tp_set = 0; u8 tpnr[GPC_MAX], a, b; - memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) - tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8); + memcpy(tpnr, oprv->tp_nr, sizeof(oprv->tp_nr)); + for (gpc = 0; gpc < oprv->gpc_nr; gpc++) + tp_mask |= ((1 << oprv->tp_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (priv->tp_total - 1)) / 32; + a = (i * (oprv->tp_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpnr[gpc]); - tp = priv->tp_nr[gpc] - tpnr[gpc]--; + tp = oprv->tp_nr[gpc] - tpnr[gpc]--; tp_set |= 1 << ((gpc * 8) + tp); } - nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); - nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); + nv_wr32(priv, 0x406800 + (i * 0x20), tp_set); + nv_wr32(priv, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); } } - nv_wr32(dev, 0x400208, 0x80000000); + nv_wr32(priv, 0x400208, 0x80000000); - nv_icmd(dev, 0x00001000, 0x00000004); - nv_icmd(dev, 0x000000a9, 0x0000ffff); - nv_icmd(dev, 0x00000038, 0x0fac6881); - nv_icmd(dev, 0x0000003d, 0x00000001); - nv_icmd(dev, 0x000000e8, 0x00000400); - nv_icmd(dev, 0x000000e9, 0x00000400); - nv_icmd(dev, 0x000000ea, 0x00000400); - nv_icmd(dev, 0x000000eb, 0x00000400); - nv_icmd(dev, 0x000000ec, 0x00000400); - nv_icmd(dev, 0x000000ed, 0x00000400); - nv_icmd(dev, 0x000000ee, 0x00000400); - nv_icmd(dev, 0x000000ef, 0x00000400); - nv_icmd(dev, 0x00000078, 0x00000300); - nv_icmd(dev, 0x00000079, 0x00000300); - nv_icmd(dev, 0x0000007a, 0x00000300); - nv_icmd(dev, 0x0000007b, 0x00000300); - nv_icmd(dev, 0x0000007c, 0x00000300); - nv_icmd(dev, 0x0000007d, 0x00000300); - nv_icmd(dev, 0x0000007e, 0x00000300); - nv_icmd(dev, 0x0000007f, 0x00000300); - nv_icmd(dev, 0x00000050, 0x00000011); - nv_icmd(dev, 0x00000058, 0x00000008); - nv_icmd(dev, 0x00000059, 0x00000008); - nv_icmd(dev, 0x0000005a, 0x00000008); - nv_icmd(dev, 0x0000005b, 0x00000008); - nv_icmd(dev, 0x0000005c, 0x00000008); - nv_icmd(dev, 0x0000005d, 0x00000008); - nv_icmd(dev, 0x0000005e, 0x00000008); - nv_icmd(dev, 0x0000005f, 0x00000008); - nv_icmd(dev, 0x00000208, 0x00000001); - nv_icmd(dev, 0x00000209, 0x00000001); - nv_icmd(dev, 0x0000020a, 0x00000001); - nv_icmd(dev, 0x0000020b, 0x00000001); - nv_icmd(dev, 0x0000020c, 0x00000001); - nv_icmd(dev, 0x0000020d, 0x00000001); - nv_icmd(dev, 0x0000020e, 0x00000001); - nv_icmd(dev, 0x0000020f, 0x00000001); - nv_icmd(dev, 0x00000081, 0x00000001); - nv_icmd(dev, 0x00000085, 0x00000004); - nv_icmd(dev, 0x00000088, 0x00000400); - nv_icmd(dev, 0x00000090, 0x00000300); - nv_icmd(dev, 0x00000098, 0x00001001); - nv_icmd(dev, 0x000000e3, 0x00000001); - nv_icmd(dev, 0x000000da, 0x00000001); - nv_icmd(dev, 0x000000f8, 0x00000003); - nv_icmd(dev, 0x000000fa, 0x00000001); - nv_icmd(dev, 0x0000009f, 0x0000ffff); - nv_icmd(dev, 0x000000a0, 0x0000ffff); - nv_icmd(dev, 0x000000a1, 0x0000ffff); - nv_icmd(dev, 0x000000a2, 0x0000ffff); - nv_icmd(dev, 0x000000b1, 0x00000001); - nv_icmd(dev, 0x000000b2, 0x00000000); - nv_icmd(dev, 0x000000b3, 0x00000000); - nv_icmd(dev, 0x000000b4, 0x00000000); - nv_icmd(dev, 0x000000b5, 0x00000000); - nv_icmd(dev, 0x000000b6, 0x00000000); - nv_icmd(dev, 0x000000b7, 0x00000000); - nv_icmd(dev, 0x000000b8, 0x00000000); - nv_icmd(dev, 0x000000b9, 0x00000000); - nv_icmd(dev, 0x000000ba, 0x00000000); - nv_icmd(dev, 0x000000bb, 0x00000000); - nv_icmd(dev, 0x000000bc, 0x00000000); - nv_icmd(dev, 0x000000bd, 0x00000000); - nv_icmd(dev, 0x000000be, 0x00000000); - nv_icmd(dev, 0x000000bf, 0x00000000); - nv_icmd(dev, 0x000000c0, 0x00000000); - nv_icmd(dev, 0x000000c1, 0x00000000); - nv_icmd(dev, 0x000000c2, 0x00000000); - nv_icmd(dev, 0x000000c3, 0x00000000); - nv_icmd(dev, 0x000000c4, 0x00000000); - nv_icmd(dev, 0x000000c5, 0x00000000); - nv_icmd(dev, 0x000000c6, 0x00000000); - nv_icmd(dev, 0x000000c7, 0x00000000); - nv_icmd(dev, 0x000000c8, 0x00000000); - nv_icmd(dev, 0x000000c9, 0x00000000); - nv_icmd(dev, 0x000000ca, 0x00000000); - nv_icmd(dev, 0x000000cb, 0x00000000); - nv_icmd(dev, 0x000000cc, 0x00000000); - nv_icmd(dev, 0x000000cd, 0x00000000); - nv_icmd(dev, 0x000000ce, 0x00000000); - nv_icmd(dev, 0x000000cf, 0x00000000); - nv_icmd(dev, 0x000000d0, 0x00000000); - nv_icmd(dev, 0x000000d1, 0x00000000); - nv_icmd(dev, 0x000000d2, 0x00000000); - nv_icmd(dev, 0x000000d3, 0x00000000); - nv_icmd(dev, 0x000000d4, 0x00000000); - nv_icmd(dev, 0x000000d5, 0x00000000); - nv_icmd(dev, 0x000000d6, 0x00000000); - nv_icmd(dev, 0x000000d7, 0x00000000); - nv_icmd(dev, 0x000000d8, 0x00000000); - nv_icmd(dev, 0x000000d9, 0x00000000); - nv_icmd(dev, 0x00000210, 0x00000040); - nv_icmd(dev, 0x00000211, 0x00000040); - nv_icmd(dev, 0x00000212, 0x00000040); - nv_icmd(dev, 0x00000213, 0x00000040); - nv_icmd(dev, 0x00000214, 0x00000040); - nv_icmd(dev, 0x00000215, 0x00000040); - nv_icmd(dev, 0x00000216, 0x00000040); - nv_icmd(dev, 0x00000217, 0x00000040); + nv_icmd(priv, 0x00001000, 0x00000004); + nv_icmd(priv, 0x000000a9, 0x0000ffff); + nv_icmd(priv, 0x00000038, 0x0fac6881); + nv_icmd(priv, 0x0000003d, 0x00000001); + nv_icmd(priv, 0x000000e8, 0x00000400); + nv_icmd(priv, 0x000000e9, 0x00000400); + nv_icmd(priv, 0x000000ea, 0x00000400); + nv_icmd(priv, 0x000000eb, 0x00000400); + nv_icmd(priv, 0x000000ec, 0x00000400); + nv_icmd(priv, 0x000000ed, 0x00000400); + nv_icmd(priv, 0x000000ee, 0x00000400); + nv_icmd(priv, 0x000000ef, 0x00000400); + nv_icmd(priv, 0x00000078, 0x00000300); + nv_icmd(priv, 0x00000079, 0x00000300); + nv_icmd(priv, 0x0000007a, 0x00000300); + nv_icmd(priv, 0x0000007b, 0x00000300); + nv_icmd(priv, 0x0000007c, 0x00000300); + nv_icmd(priv, 0x0000007d, 0x00000300); + nv_icmd(priv, 0x0000007e, 0x00000300); + nv_icmd(priv, 0x0000007f, 0x00000300); + nv_icmd(priv, 0x00000050, 0x00000011); + nv_icmd(priv, 0x00000058, 0x00000008); + nv_icmd(priv, 0x00000059, 0x00000008); + nv_icmd(priv, 0x0000005a, 0x00000008); + nv_icmd(priv, 0x0000005b, 0x00000008); + nv_icmd(priv, 0x0000005c, 0x00000008); + nv_icmd(priv, 0x0000005d, 0x00000008); + nv_icmd(priv, 0x0000005e, 0x00000008); + nv_icmd(priv, 0x0000005f, 0x00000008); + nv_icmd(priv, 0x00000208, 0x00000001); + nv_icmd(priv, 0x00000209, 0x00000001); + nv_icmd(priv, 0x0000020a, 0x00000001); + nv_icmd(priv, 0x0000020b, 0x00000001); + nv_icmd(priv, 0x0000020c, 0x00000001); + nv_icmd(priv, 0x0000020d, 0x00000001); + nv_icmd(priv, 0x0000020e, 0x00000001); + nv_icmd(priv, 0x0000020f, 0x00000001); + nv_icmd(priv, 0x00000081, 0x00000001); + nv_icmd(priv, 0x00000085, 0x00000004); + nv_icmd(priv, 0x00000088, 0x00000400); + nv_icmd(priv, 0x00000090, 0x00000300); + nv_icmd(priv, 0x00000098, 0x00001001); + nv_icmd(priv, 0x000000e3, 0x00000001); + nv_icmd(priv, 0x000000da, 0x00000001); + nv_icmd(priv, 0x000000f8, 0x00000003); + nv_icmd(priv, 0x000000fa, 0x00000001); + nv_icmd(priv, 0x0000009f, 0x0000ffff); + nv_icmd(priv, 0x000000a0, 0x0000ffff); + nv_icmd(priv, 0x000000a1, 0x0000ffff); + nv_icmd(priv, 0x000000a2, 0x0000ffff); + nv_icmd(priv, 0x000000b1, 0x00000001); + nv_icmd(priv, 0x000000b2, 0x00000000); + nv_icmd(priv, 0x000000b3, 0x00000000); + nv_icmd(priv, 0x000000b4, 0x00000000); + nv_icmd(priv, 0x000000b5, 0x00000000); + nv_icmd(priv, 0x000000b6, 0x00000000); + nv_icmd(priv, 0x000000b7, 0x00000000); + nv_icmd(priv, 0x000000b8, 0x00000000); + nv_icmd(priv, 0x000000b9, 0x00000000); + nv_icmd(priv, 0x000000ba, 0x00000000); + nv_icmd(priv, 0x000000bb, 0x00000000); + nv_icmd(priv, 0x000000bc, 0x00000000); + nv_icmd(priv, 0x000000bd, 0x00000000); + nv_icmd(priv, 0x000000be, 0x00000000); + nv_icmd(priv, 0x000000bf, 0x00000000); + nv_icmd(priv, 0x000000c0, 0x00000000); + nv_icmd(priv, 0x000000c1, 0x00000000); + nv_icmd(priv, 0x000000c2, 0x00000000); + nv_icmd(priv, 0x000000c3, 0x00000000); + nv_icmd(priv, 0x000000c4, 0x00000000); + nv_icmd(priv, 0x000000c5, 0x00000000); + nv_icmd(priv, 0x000000c6, 0x00000000); + nv_icmd(priv, 0x000000c7, 0x00000000); + nv_icmd(priv, 0x000000c8, 0x00000000); + nv_icmd(priv, 0x000000c9, 0x00000000); + nv_icmd(priv, 0x000000ca, 0x00000000); + nv_icmd(priv, 0x000000cb, 0x00000000); + nv_icmd(priv, 0x000000cc, 0x00000000); + nv_icmd(priv, 0x000000cd, 0x00000000); + nv_icmd(priv, 0x000000ce, 0x00000000); + nv_icmd(priv, 0x000000cf, 0x00000000); + nv_icmd(priv, 0x000000d0, 0x00000000); + nv_icmd(priv, 0x000000d1, 0x00000000); + nv_icmd(priv, 0x000000d2, 0x00000000); + nv_icmd(priv, 0x000000d3, 0x00000000); + nv_icmd(priv, 0x000000d4, 0x00000000); + nv_icmd(priv, 0x000000d5, 0x00000000); + nv_icmd(priv, 0x000000d6, 0x00000000); + nv_icmd(priv, 0x000000d7, 0x00000000); + nv_icmd(priv, 0x000000d8, 0x00000000); + nv_icmd(priv, 0x000000d9, 0x00000000); + nv_icmd(priv, 0x00000210, 0x00000040); + nv_icmd(priv, 0x00000211, 0x00000040); + nv_icmd(priv, 0x00000212, 0x00000040); + nv_icmd(priv, 0x00000213, 0x00000040); + nv_icmd(priv, 0x00000214, 0x00000040); + nv_icmd(priv, 0x00000215, 0x00000040); + nv_icmd(priv, 0x00000216, 0x00000040); + nv_icmd(priv, 0x00000217, 0x00000040); if (dev_priv->chipset == 0xd9) { for (i = 0x0400; i <= 0x0417; i++) - nv_icmd(dev, i, 0x00000040); + nv_icmd(priv, i, 0x00000040); } - nv_icmd(dev, 0x00000218, 0x0000c080); - nv_icmd(dev, 0x00000219, 0x0000c080); - nv_icmd(dev, 0x0000021a, 0x0000c080); - nv_icmd(dev, 0x0000021b, 0x0000c080); - nv_icmd(dev, 0x0000021c, 0x0000c080); - nv_icmd(dev, 0x0000021d, 0x0000c080); - nv_icmd(dev, 0x0000021e, 0x0000c080); - nv_icmd(dev, 0x0000021f, 0x0000c080); + nv_icmd(priv, 0x00000218, 0x0000c080); + nv_icmd(priv, 0x00000219, 0x0000c080); + nv_icmd(priv, 0x0000021a, 0x0000c080); + nv_icmd(priv, 0x0000021b, 0x0000c080); + nv_icmd(priv, 0x0000021c, 0x0000c080); + nv_icmd(priv, 0x0000021d, 0x0000c080); + nv_icmd(priv, 0x0000021e, 0x0000c080); + nv_icmd(priv, 0x0000021f, 0x0000c080); if (dev_priv->chipset == 0xd9) { for (i = 0x0440; i <= 0x0457; i++) - nv_icmd(dev, i, 0x0000c080); + nv_icmd(priv, i, 0x0000c080); } - nv_icmd(dev, 0x000000ad, 0x0000013e); - nv_icmd(dev, 0x000000e1, 0x00000010); - nv_icmd(dev, 0x00000290, 0x00000000); - nv_icmd(dev, 0x00000291, 0x00000000); - nv_icmd(dev, 0x00000292, 0x00000000); - nv_icmd(dev, 0x00000293, 0x00000000); - nv_icmd(dev, 0x00000294, 0x00000000); - nv_icmd(dev, 0x00000295, 0x00000000); - nv_icmd(dev, 0x00000296, 0x00000000); - nv_icmd(dev, 0x00000297, 0x00000000); - nv_icmd(dev, 0x00000298, 0x00000000); - nv_icmd(dev, 0x00000299, 0x00000000); - nv_icmd(dev, 0x0000029a, 0x00000000); - nv_icmd(dev, 0x0000029b, 0x00000000); - nv_icmd(dev, 0x0000029c, 0x00000000); - nv_icmd(dev, 0x0000029d, 0x00000000); - nv_icmd(dev, 0x0000029e, 0x00000000); - nv_icmd(dev, 0x0000029f, 0x00000000); - nv_icmd(dev, 0x000003b0, 0x00000000); - nv_icmd(dev, 0x000003b1, 0x00000000); - nv_icmd(dev, 0x000003b2, 0x00000000); - nv_icmd(dev, 0x000003b3, 0x00000000); - nv_icmd(dev, 0x000003b4, 0x00000000); - nv_icmd(dev, 0x000003b5, 0x00000000); - nv_icmd(dev, 0x000003b6, 0x00000000); - nv_icmd(dev, 0x000003b7, 0x00000000); - nv_icmd(dev, 0x000003b8, 0x00000000); - nv_icmd(dev, 0x000003b9, 0x00000000); - nv_icmd(dev, 0x000003ba, 0x00000000); - nv_icmd(dev, 0x000003bb, 0x00000000); - nv_icmd(dev, 0x000003bc, 0x00000000); - nv_icmd(dev, 0x000003bd, 0x00000000); - nv_icmd(dev, 0x000003be, 0x00000000); - nv_icmd(dev, 0x000003bf, 0x00000000); - nv_icmd(dev, 0x000002a0, 0x00000000); - nv_icmd(dev, 0x000002a1, 0x00000000); - nv_icmd(dev, 0x000002a2, 0x00000000); - nv_icmd(dev, 0x000002a3, 0x00000000); - nv_icmd(dev, 0x000002a4, 0x00000000); - nv_icmd(dev, 0x000002a5, 0x00000000); - nv_icmd(dev, 0x000002a6, 0x00000000); - nv_icmd(dev, 0x000002a7, 0x00000000); - nv_icmd(dev, 0x000002a8, 0x00000000); - nv_icmd(dev, 0x000002a9, 0x00000000); - nv_icmd(dev, 0x000002aa, 0x00000000); - nv_icmd(dev, 0x000002ab, 0x00000000); - nv_icmd(dev, 0x000002ac, 0x00000000); - nv_icmd(dev, 0x000002ad, 0x00000000); - nv_icmd(dev, 0x000002ae, 0x00000000); - nv_icmd(dev, 0x000002af, 0x00000000); - nv_icmd(dev, 0x00000420, 0x00000000); - nv_icmd(dev, 0x00000421, 0x00000000); - nv_icmd(dev, 0x00000422, 0x00000000); - nv_icmd(dev, 0x00000423, 0x00000000); - nv_icmd(dev, 0x00000424, 0x00000000); - nv_icmd(dev, 0x00000425, 0x00000000); - nv_icmd(dev, 0x00000426, 0x00000000); - nv_icmd(dev, 0x00000427, 0x00000000); - nv_icmd(dev, 0x00000428, 0x00000000); - nv_icmd(dev, 0x00000429, 0x00000000); - nv_icmd(dev, 0x0000042a, 0x00000000); - nv_icmd(dev, 0x0000042b, 0x00000000); - nv_icmd(dev, 0x0000042c, 0x00000000); - nv_icmd(dev, 0x0000042d, 0x00000000); - nv_icmd(dev, 0x0000042e, 0x00000000); - nv_icmd(dev, 0x0000042f, 0x00000000); - nv_icmd(dev, 0x000002b0, 0x00000000); - nv_icmd(dev, 0x000002b1, 0x00000000); - nv_icmd(dev, 0x000002b2, 0x00000000); - nv_icmd(dev, 0x000002b3, 0x00000000); - nv_icmd(dev, 0x000002b4, 0x00000000); - nv_icmd(dev, 0x000002b5, 0x00000000); - nv_icmd(dev, 0x000002b6, 0x00000000); - nv_icmd(dev, 0x000002b7, 0x00000000); - nv_icmd(dev, 0x000002b8, 0x00000000); - nv_icmd(dev, 0x000002b9, 0x00000000); - nv_icmd(dev, 0x000002ba, 0x00000000); - nv_icmd(dev, 0x000002bb, 0x00000000); - nv_icmd(dev, 0x000002bc, 0x00000000); - nv_icmd(dev, 0x000002bd, 0x00000000); - nv_icmd(dev, 0x000002be, 0x00000000); - nv_icmd(dev, 0x000002bf, 0x00000000); - nv_icmd(dev, 0x00000430, 0x00000000); - nv_icmd(dev, 0x00000431, 0x00000000); - nv_icmd(dev, 0x00000432, 0x00000000); - nv_icmd(dev, 0x00000433, 0x00000000); - nv_icmd(dev, 0x00000434, 0x00000000); - nv_icmd(dev, 0x00000435, 0x00000000); - nv_icmd(dev, 0x00000436, 0x00000000); - nv_icmd(dev, 0x00000437, 0x00000000); - nv_icmd(dev, 0x00000438, 0x00000000); - nv_icmd(dev, 0x00000439, 0x00000000); - nv_icmd(dev, 0x0000043a, 0x00000000); - nv_icmd(dev, 0x0000043b, 0x00000000); - nv_icmd(dev, 0x0000043c, 0x00000000); - nv_icmd(dev, 0x0000043d, 0x00000000); - nv_icmd(dev, 0x0000043e, 0x00000000); - nv_icmd(dev, 0x0000043f, 0x00000000); - nv_icmd(dev, 0x000002c0, 0x00000000); - nv_icmd(dev, 0x000002c1, 0x00000000); - nv_icmd(dev, 0x000002c2, 0x00000000); - nv_icmd(dev, 0x000002c3, 0x00000000); - nv_icmd(dev, 0x000002c4, 0x00000000); - nv_icmd(dev, 0x000002c5, 0x00000000); - nv_icmd(dev, 0x000002c6, 0x00000000); - nv_icmd(dev, 0x000002c7, 0x00000000); - nv_icmd(dev, 0x000002c8, 0x00000000); - nv_icmd(dev, 0x000002c9, 0x00000000); - nv_icmd(dev, 0x000002ca, 0x00000000); - nv_icmd(dev, 0x000002cb, 0x00000000); - nv_icmd(dev, 0x000002cc, 0x00000000); - nv_icmd(dev, 0x000002cd, 0x00000000); - nv_icmd(dev, 0x000002ce, 0x00000000); - nv_icmd(dev, 0x000002cf, 0x00000000); - nv_icmd(dev, 0x000004d0, 0x00000000); - nv_icmd(dev, 0x000004d1, 0x00000000); - nv_icmd(dev, 0x000004d2, 0x00000000); - nv_icmd(dev, 0x000004d3, 0x00000000); - nv_icmd(dev, 0x000004d4, 0x00000000); - nv_icmd(dev, 0x000004d5, 0x00000000); - nv_icmd(dev, 0x000004d6, 0x00000000); - nv_icmd(dev, 0x000004d7, 0x00000000); - nv_icmd(dev, 0x000004d8, 0x00000000); - nv_icmd(dev, 0x000004d9, 0x00000000); - nv_icmd(dev, 0x000004da, 0x00000000); - nv_icmd(dev, 0x000004db, 0x00000000); - nv_icmd(dev, 0x000004dc, 0x00000000); - nv_icmd(dev, 0x000004dd, 0x00000000); - nv_icmd(dev, 0x000004de, 0x00000000); - nv_icmd(dev, 0x000004df, 0x00000000); - nv_icmd(dev, 0x00000720, 0x00000000); - nv_icmd(dev, 0x00000721, 0x00000000); - nv_icmd(dev, 0x00000722, 0x00000000); - nv_icmd(dev, 0x00000723, 0x00000000); - nv_icmd(dev, 0x00000724, 0x00000000); - nv_icmd(dev, 0x00000725, 0x00000000); - nv_icmd(dev, 0x00000726, 0x00000000); - nv_icmd(dev, 0x00000727, 0x00000000); - nv_icmd(dev, 0x00000728, 0x00000000); - nv_icmd(dev, 0x00000729, 0x00000000); - nv_icmd(dev, 0x0000072a, 0x00000000); - nv_icmd(dev, 0x0000072b, 0x00000000); - nv_icmd(dev, 0x0000072c, 0x00000000); - nv_icmd(dev, 0x0000072d, 0x00000000); - nv_icmd(dev, 0x0000072e, 0x00000000); - nv_icmd(dev, 0x0000072f, 0x00000000); - nv_icmd(dev, 0x000008c0, 0x00000000); - nv_icmd(dev, 0x000008c1, 0x00000000); - nv_icmd(dev, 0x000008c2, 0x00000000); - nv_icmd(dev, 0x000008c3, 0x00000000); - nv_icmd(dev, 0x000008c4, 0x00000000); - nv_icmd(dev, 0x000008c5, 0x00000000); - nv_icmd(dev, 0x000008c6, 0x00000000); - nv_icmd(dev, 0x000008c7, 0x00000000); - nv_icmd(dev, 0x000008c8, 0x00000000); - nv_icmd(dev, 0x000008c9, 0x00000000); - nv_icmd(dev, 0x000008ca, 0x00000000); - nv_icmd(dev, 0x000008cb, 0x00000000); - nv_icmd(dev, 0x000008cc, 0x00000000); - nv_icmd(dev, 0x000008cd, 0x00000000); - nv_icmd(dev, 0x000008ce, 0x00000000); - nv_icmd(dev, 0x000008cf, 0x00000000); - nv_icmd(dev, 0x00000890, 0x00000000); - nv_icmd(dev, 0x00000891, 0x00000000); - nv_icmd(dev, 0x00000892, 0x00000000); - nv_icmd(dev, 0x00000893, 0x00000000); - nv_icmd(dev, 0x00000894, 0x00000000); - nv_icmd(dev, 0x00000895, 0x00000000); - nv_icmd(dev, 0x00000896, 0x00000000); - nv_icmd(dev, 0x00000897, 0x00000000); - nv_icmd(dev, 0x00000898, 0x00000000); - nv_icmd(dev, 0x00000899, 0x00000000); - nv_icmd(dev, 0x0000089a, 0x00000000); - nv_icmd(dev, 0x0000089b, 0x00000000); - nv_icmd(dev, 0x0000089c, 0x00000000); - nv_icmd(dev, 0x0000089d, 0x00000000); - nv_icmd(dev, 0x0000089e, 0x00000000); - nv_icmd(dev, 0x0000089f, 0x00000000); - nv_icmd(dev, 0x000008e0, 0x00000000); - nv_icmd(dev, 0x000008e1, 0x00000000); - nv_icmd(dev, 0x000008e2, 0x00000000); - nv_icmd(dev, 0x000008e3, 0x00000000); - nv_icmd(dev, 0x000008e4, 0x00000000); - nv_icmd(dev, 0x000008e5, 0x00000000); - nv_icmd(dev, 0x000008e6, 0x00000000); - nv_icmd(dev, 0x000008e7, 0x00000000); - nv_icmd(dev, 0x000008e8, 0x00000000); - nv_icmd(dev, 0x000008e9, 0x00000000); - nv_icmd(dev, 0x000008ea, 0x00000000); - nv_icmd(dev, 0x000008eb, 0x00000000); - nv_icmd(dev, 0x000008ec, 0x00000000); - nv_icmd(dev, 0x000008ed, 0x00000000); - nv_icmd(dev, 0x000008ee, 0x00000000); - nv_icmd(dev, 0x000008ef, 0x00000000); - nv_icmd(dev, 0x000008a0, 0x00000000); - nv_icmd(dev, 0x000008a1, 0x00000000); - nv_icmd(dev, 0x000008a2, 0x00000000); - nv_icmd(dev, 0x000008a3, 0x00000000); - nv_icmd(dev, 0x000008a4, 0x00000000); - nv_icmd(dev, 0x000008a5, 0x00000000); - nv_icmd(dev, 0x000008a6, 0x00000000); - nv_icmd(dev, 0x000008a7, 0x00000000); - nv_icmd(dev, 0x000008a8, 0x00000000); - nv_icmd(dev, 0x000008a9, 0x00000000); - nv_icmd(dev, 0x000008aa, 0x00000000); - nv_icmd(dev, 0x000008ab, 0x00000000); - nv_icmd(dev, 0x000008ac, 0x00000000); - nv_icmd(dev, 0x000008ad, 0x00000000); - nv_icmd(dev, 0x000008ae, 0x00000000); - nv_icmd(dev, 0x000008af, 0x00000000); - nv_icmd(dev, 0x000008f0, 0x00000000); - nv_icmd(dev, 0x000008f1, 0x00000000); - nv_icmd(dev, 0x000008f2, 0x00000000); - nv_icmd(dev, 0x000008f3, 0x00000000); - nv_icmd(dev, 0x000008f4, 0x00000000); - nv_icmd(dev, 0x000008f5, 0x00000000); - nv_icmd(dev, 0x000008f6, 0x00000000); - nv_icmd(dev, 0x000008f7, 0x00000000); - nv_icmd(dev, 0x000008f8, 0x00000000); - nv_icmd(dev, 0x000008f9, 0x00000000); - nv_icmd(dev, 0x000008fa, 0x00000000); - nv_icmd(dev, 0x000008fb, 0x00000000); - nv_icmd(dev, 0x000008fc, 0x00000000); - nv_icmd(dev, 0x000008fd, 0x00000000); - nv_icmd(dev, 0x000008fe, 0x00000000); - nv_icmd(dev, 0x000008ff, 0x00000000); - nv_icmd(dev, 0x0000094c, 0x000000ff); - nv_icmd(dev, 0x0000094d, 0xffffffff); - nv_icmd(dev, 0x0000094e, 0x00000002); - nv_icmd(dev, 0x000002ec, 0x00000001); - nv_icmd(dev, 0x00000303, 0x00000001); - nv_icmd(dev, 0x000002e6, 0x00000001); - nv_icmd(dev, 0x00000466, 0x00000052); - nv_icmd(dev, 0x00000301, 0x3f800000); - nv_icmd(dev, 0x00000304, 0x30201000); - nv_icmd(dev, 0x00000305, 0x70605040); - nv_icmd(dev, 0x00000306, 0xb8a89888); - nv_icmd(dev, 0x00000307, 0xf8e8d8c8); - nv_icmd(dev, 0x0000030a, 0x00ffff00); - nv_icmd(dev, 0x0000030b, 0x0000001a); - nv_icmd(dev, 0x0000030c, 0x00000001); - nv_icmd(dev, 0x00000318, 0x00000001); - nv_icmd(dev, 0x00000340, 0x00000000); - nv_icmd(dev, 0x00000375, 0x00000001); - nv_icmd(dev, 0x00000351, 0x00000100); - nv_icmd(dev, 0x0000037d, 0x00000006); - nv_icmd(dev, 0x000003a0, 0x00000002); - nv_icmd(dev, 0x000003aa, 0x00000001); - nv_icmd(dev, 0x000003a9, 0x00000001); - nv_icmd(dev, 0x00000380, 0x00000001); - nv_icmd(dev, 0x00000360, 0x00000040); - nv_icmd(dev, 0x00000366, 0x00000000); - nv_icmd(dev, 0x00000367, 0x00000000); - nv_icmd(dev, 0x00000368, 0x00001fff); - nv_icmd(dev, 0x00000370, 0x00000000); - nv_icmd(dev, 0x00000371, 0x00000000); - nv_icmd(dev, 0x00000372, 0x003fffff); - nv_icmd(dev, 0x0000037a, 0x00000012); - nv_icmd(dev, 0x000005e0, 0x00000022); - nv_icmd(dev, 0x000005e1, 0x00000022); - nv_icmd(dev, 0x000005e2, 0x00000022); - nv_icmd(dev, 0x000005e3, 0x00000022); - nv_icmd(dev, 0x000005e4, 0x00000022); - nv_icmd(dev, 0x00000619, 0x00000003); - nv_icmd(dev, 0x00000811, 0x00000003); - nv_icmd(dev, 0x00000812, 0x00000004); - nv_icmd(dev, 0x00000813, 0x00000006); - nv_icmd(dev, 0x00000814, 0x00000008); - nv_icmd(dev, 0x00000815, 0x0000000b); - nv_icmd(dev, 0x00000800, 0x00000001); - nv_icmd(dev, 0x00000801, 0x00000001); - nv_icmd(dev, 0x00000802, 0x00000001); - nv_icmd(dev, 0x00000803, 0x00000001); - nv_icmd(dev, 0x00000804, 0x00000001); - nv_icmd(dev, 0x00000805, 0x00000001); - nv_icmd(dev, 0x00000632, 0x00000001); - nv_icmd(dev, 0x00000633, 0x00000002); - nv_icmd(dev, 0x00000634, 0x00000003); - nv_icmd(dev, 0x00000635, 0x00000004); - nv_icmd(dev, 0x00000654, 0x3f800000); - nv_icmd(dev, 0x00000657, 0x3f800000); - nv_icmd(dev, 0x00000655, 0x3f800000); - nv_icmd(dev, 0x00000656, 0x3f800000); - nv_icmd(dev, 0x000006cd, 0x3f800000); - nv_icmd(dev, 0x000007f5, 0x3f800000); - nv_icmd(dev, 0x000007dc, 0x39291909); - nv_icmd(dev, 0x000007dd, 0x79695949); - nv_icmd(dev, 0x000007de, 0xb9a99989); - nv_icmd(dev, 0x000007df, 0xf9e9d9c9); - nv_icmd(dev, 0x000007e8, 0x00003210); - nv_icmd(dev, 0x000007e9, 0x00007654); - nv_icmd(dev, 0x000007ea, 0x00000098); - nv_icmd(dev, 0x000007ec, 0x39291909); - nv_icmd(dev, 0x000007ed, 0x79695949); - nv_icmd(dev, 0x000007ee, 0xb9a99989); - nv_icmd(dev, 0x000007ef, 0xf9e9d9c9); - nv_icmd(dev, 0x000007f0, 0x00003210); - nv_icmd(dev, 0x000007f1, 0x00007654); - nv_icmd(dev, 0x000007f2, 0x00000098); - nv_icmd(dev, 0x000005a5, 0x00000001); - nv_icmd(dev, 0x00000980, 0x00000000); - nv_icmd(dev, 0x00000981, 0x00000000); - nv_icmd(dev, 0x00000982, 0x00000000); - nv_icmd(dev, 0x00000983, 0x00000000); - nv_icmd(dev, 0x00000984, 0x00000000); - nv_icmd(dev, 0x00000985, 0x00000000); - nv_icmd(dev, 0x00000986, 0x00000000); - nv_icmd(dev, 0x00000987, 0x00000000); - nv_icmd(dev, 0x00000988, 0x00000000); - nv_icmd(dev, 0x00000989, 0x00000000); - nv_icmd(dev, 0x0000098a, 0x00000000); - nv_icmd(dev, 0x0000098b, 0x00000000); - nv_icmd(dev, 0x0000098c, 0x00000000); - nv_icmd(dev, 0x0000098d, 0x00000000); - nv_icmd(dev, 0x0000098e, 0x00000000); - nv_icmd(dev, 0x0000098f, 0x00000000); - nv_icmd(dev, 0x00000990, 0x00000000); - nv_icmd(dev, 0x00000991, 0x00000000); - nv_icmd(dev, 0x00000992, 0x00000000); - nv_icmd(dev, 0x00000993, 0x00000000); - nv_icmd(dev, 0x00000994, 0x00000000); - nv_icmd(dev, 0x00000995, 0x00000000); - nv_icmd(dev, 0x00000996, 0x00000000); - nv_icmd(dev, 0x00000997, 0x00000000); - nv_icmd(dev, 0x00000998, 0x00000000); - nv_icmd(dev, 0x00000999, 0x00000000); - nv_icmd(dev, 0x0000099a, 0x00000000); - nv_icmd(dev, 0x0000099b, 0x00000000); - nv_icmd(dev, 0x0000099c, 0x00000000); - nv_icmd(dev, 0x0000099d, 0x00000000); - nv_icmd(dev, 0x0000099e, 0x00000000); - nv_icmd(dev, 0x0000099f, 0x00000000); - nv_icmd(dev, 0x000009a0, 0x00000000); - nv_icmd(dev, 0x000009a1, 0x00000000); - nv_icmd(dev, 0x000009a2, 0x00000000); - nv_icmd(dev, 0x000009a3, 0x00000000); - nv_icmd(dev, 0x000009a4, 0x00000000); - nv_icmd(dev, 0x000009a5, 0x00000000); - nv_icmd(dev, 0x000009a6, 0x00000000); - nv_icmd(dev, 0x000009a7, 0x00000000); - nv_icmd(dev, 0x000009a8, 0x00000000); - nv_icmd(dev, 0x000009a9, 0x00000000); - nv_icmd(dev, 0x000009aa, 0x00000000); - nv_icmd(dev, 0x000009ab, 0x00000000); - nv_icmd(dev, 0x000009ac, 0x00000000); - nv_icmd(dev, 0x000009ad, 0x00000000); - nv_icmd(dev, 0x000009ae, 0x00000000); - nv_icmd(dev, 0x000009af, 0x00000000); - nv_icmd(dev, 0x000009b0, 0x00000000); - nv_icmd(dev, 0x000009b1, 0x00000000); - nv_icmd(dev, 0x000009b2, 0x00000000); - nv_icmd(dev, 0x000009b3, 0x00000000); - nv_icmd(dev, 0x000009b4, 0x00000000); - nv_icmd(dev, 0x000009b5, 0x00000000); - nv_icmd(dev, 0x000009b6, 0x00000000); - nv_icmd(dev, 0x000009b7, 0x00000000); - nv_icmd(dev, 0x000009b8, 0x00000000); - nv_icmd(dev, 0x000009b9, 0x00000000); - nv_icmd(dev, 0x000009ba, 0x00000000); - nv_icmd(dev, 0x000009bb, 0x00000000); - nv_icmd(dev, 0x000009bc, 0x00000000); - nv_icmd(dev, 0x000009bd, 0x00000000); - nv_icmd(dev, 0x000009be, 0x00000000); - nv_icmd(dev, 0x000009bf, 0x00000000); - nv_icmd(dev, 0x000009c0, 0x00000000); - nv_icmd(dev, 0x000009c1, 0x00000000); - nv_icmd(dev, 0x000009c2, 0x00000000); - nv_icmd(dev, 0x000009c3, 0x00000000); - nv_icmd(dev, 0x000009c4, 0x00000000); - nv_icmd(dev, 0x000009c5, 0x00000000); - nv_icmd(dev, 0x000009c6, 0x00000000); - nv_icmd(dev, 0x000009c7, 0x00000000); - nv_icmd(dev, 0x000009c8, 0x00000000); - nv_icmd(dev, 0x000009c9, 0x00000000); - nv_icmd(dev, 0x000009ca, 0x00000000); - nv_icmd(dev, 0x000009cb, 0x00000000); - nv_icmd(dev, 0x000009cc, 0x00000000); - nv_icmd(dev, 0x000009cd, 0x00000000); - nv_icmd(dev, 0x000009ce, 0x00000000); - nv_icmd(dev, 0x000009cf, 0x00000000); - nv_icmd(dev, 0x000009d0, 0x00000000); - nv_icmd(dev, 0x000009d1, 0x00000000); - nv_icmd(dev, 0x000009d2, 0x00000000); - nv_icmd(dev, 0x000009d3, 0x00000000); - nv_icmd(dev, 0x000009d4, 0x00000000); - nv_icmd(dev, 0x000009d5, 0x00000000); - nv_icmd(dev, 0x000009d6, 0x00000000); - nv_icmd(dev, 0x000009d7, 0x00000000); - nv_icmd(dev, 0x000009d8, 0x00000000); - nv_icmd(dev, 0x000009d9, 0x00000000); - nv_icmd(dev, 0x000009da, 0x00000000); - nv_icmd(dev, 0x000009db, 0x00000000); - nv_icmd(dev, 0x000009dc, 0x00000000); - nv_icmd(dev, 0x000009dd, 0x00000000); - nv_icmd(dev, 0x000009de, 0x00000000); - nv_icmd(dev, 0x000009df, 0x00000000); - nv_icmd(dev, 0x000009e0, 0x00000000); - nv_icmd(dev, 0x000009e1, 0x00000000); - nv_icmd(dev, 0x000009e2, 0x00000000); - nv_icmd(dev, 0x000009e3, 0x00000000); - nv_icmd(dev, 0x000009e4, 0x00000000); - nv_icmd(dev, 0x000009e5, 0x00000000); - nv_icmd(dev, 0x000009e6, 0x00000000); - nv_icmd(dev, 0x000009e7, 0x00000000); - nv_icmd(dev, 0x000009e8, 0x00000000); - nv_icmd(dev, 0x000009e9, 0x00000000); - nv_icmd(dev, 0x000009ea, 0x00000000); - nv_icmd(dev, 0x000009eb, 0x00000000); - nv_icmd(dev, 0x000009ec, 0x00000000); - nv_icmd(dev, 0x000009ed, 0x00000000); - nv_icmd(dev, 0x000009ee, 0x00000000); - nv_icmd(dev, 0x000009ef, 0x00000000); - nv_icmd(dev, 0x000009f0, 0x00000000); - nv_icmd(dev, 0x000009f1, 0x00000000); - nv_icmd(dev, 0x000009f2, 0x00000000); - nv_icmd(dev, 0x000009f3, 0x00000000); - nv_icmd(dev, 0x000009f4, 0x00000000); - nv_icmd(dev, 0x000009f5, 0x00000000); - nv_icmd(dev, 0x000009f6, 0x00000000); - nv_icmd(dev, 0x000009f7, 0x00000000); - nv_icmd(dev, 0x000009f8, 0x00000000); - nv_icmd(dev, 0x000009f9, 0x00000000); - nv_icmd(dev, 0x000009fa, 0x00000000); - nv_icmd(dev, 0x000009fb, 0x00000000); - nv_icmd(dev, 0x000009fc, 0x00000000); - nv_icmd(dev, 0x000009fd, 0x00000000); - nv_icmd(dev, 0x000009fe, 0x00000000); - nv_icmd(dev, 0x000009ff, 0x00000000); - nv_icmd(dev, 0x00000468, 0x00000004); - nv_icmd(dev, 0x0000046c, 0x00000001); - nv_icmd(dev, 0x00000470, 0x00000000); - nv_icmd(dev, 0x00000471, 0x00000000); - nv_icmd(dev, 0x00000472, 0x00000000); - nv_icmd(dev, 0x00000473, 0x00000000); - nv_icmd(dev, 0x00000474, 0x00000000); - nv_icmd(dev, 0x00000475, 0x00000000); - nv_icmd(dev, 0x00000476, 0x00000000); - nv_icmd(dev, 0x00000477, 0x00000000); - nv_icmd(dev, 0x00000478, 0x00000000); - nv_icmd(dev, 0x00000479, 0x00000000); - nv_icmd(dev, 0x0000047a, 0x00000000); - nv_icmd(dev, 0x0000047b, 0x00000000); - nv_icmd(dev, 0x0000047c, 0x00000000); - nv_icmd(dev, 0x0000047d, 0x00000000); - nv_icmd(dev, 0x0000047e, 0x00000000); - nv_icmd(dev, 0x0000047f, 0x00000000); - nv_icmd(dev, 0x00000480, 0x00000000); - nv_icmd(dev, 0x00000481, 0x00000000); - nv_icmd(dev, 0x00000482, 0x00000000); - nv_icmd(dev, 0x00000483, 0x00000000); - nv_icmd(dev, 0x00000484, 0x00000000); - nv_icmd(dev, 0x00000485, 0x00000000); - nv_icmd(dev, 0x00000486, 0x00000000); - nv_icmd(dev, 0x00000487, 0x00000000); - nv_icmd(dev, 0x00000488, 0x00000000); - nv_icmd(dev, 0x00000489, 0x00000000); - nv_icmd(dev, 0x0000048a, 0x00000000); - nv_icmd(dev, 0x0000048b, 0x00000000); - nv_icmd(dev, 0x0000048c, 0x00000000); - nv_icmd(dev, 0x0000048d, 0x00000000); - nv_icmd(dev, 0x0000048e, 0x00000000); - nv_icmd(dev, 0x0000048f, 0x00000000); - nv_icmd(dev, 0x00000490, 0x00000000); - nv_icmd(dev, 0x00000491, 0x00000000); - nv_icmd(dev, 0x00000492, 0x00000000); - nv_icmd(dev, 0x00000493, 0x00000000); - nv_icmd(dev, 0x00000494, 0x00000000); - nv_icmd(dev, 0x00000495, 0x00000000); - nv_icmd(dev, 0x00000496, 0x00000000); - nv_icmd(dev, 0x00000497, 0x00000000); - nv_icmd(dev, 0x00000498, 0x00000000); - nv_icmd(dev, 0x00000499, 0x00000000); - nv_icmd(dev, 0x0000049a, 0x00000000); - nv_icmd(dev, 0x0000049b, 0x00000000); - nv_icmd(dev, 0x0000049c, 0x00000000); - nv_icmd(dev, 0x0000049d, 0x00000000); - nv_icmd(dev, 0x0000049e, 0x00000000); - nv_icmd(dev, 0x0000049f, 0x00000000); - nv_icmd(dev, 0x000004a0, 0x00000000); - nv_icmd(dev, 0x000004a1, 0x00000000); - nv_icmd(dev, 0x000004a2, 0x00000000); - nv_icmd(dev, 0x000004a3, 0x00000000); - nv_icmd(dev, 0x000004a4, 0x00000000); - nv_icmd(dev, 0x000004a5, 0x00000000); - nv_icmd(dev, 0x000004a6, 0x00000000); - nv_icmd(dev, 0x000004a7, 0x00000000); - nv_icmd(dev, 0x000004a8, 0x00000000); - nv_icmd(dev, 0x000004a9, 0x00000000); - nv_icmd(dev, 0x000004aa, 0x00000000); - nv_icmd(dev, 0x000004ab, 0x00000000); - nv_icmd(dev, 0x000004ac, 0x00000000); - nv_icmd(dev, 0x000004ad, 0x00000000); - nv_icmd(dev, 0x000004ae, 0x00000000); - nv_icmd(dev, 0x000004af, 0x00000000); - nv_icmd(dev, 0x000004b0, 0x00000000); - nv_icmd(dev, 0x000004b1, 0x00000000); - nv_icmd(dev, 0x000004b2, 0x00000000); - nv_icmd(dev, 0x000004b3, 0x00000000); - nv_icmd(dev, 0x000004b4, 0x00000000); - nv_icmd(dev, 0x000004b5, 0x00000000); - nv_icmd(dev, 0x000004b6, 0x00000000); - nv_icmd(dev, 0x000004b7, 0x00000000); - nv_icmd(dev, 0x000004b8, 0x00000000); - nv_icmd(dev, 0x000004b9, 0x00000000); - nv_icmd(dev, 0x000004ba, 0x00000000); - nv_icmd(dev, 0x000004bb, 0x00000000); - nv_icmd(dev, 0x000004bc, 0x00000000); - nv_icmd(dev, 0x000004bd, 0x00000000); - nv_icmd(dev, 0x000004be, 0x00000000); - nv_icmd(dev, 0x000004bf, 0x00000000); - nv_icmd(dev, 0x000004c0, 0x00000000); - nv_icmd(dev, 0x000004c1, 0x00000000); - nv_icmd(dev, 0x000004c2, 0x00000000); - nv_icmd(dev, 0x000004c3, 0x00000000); - nv_icmd(dev, 0x000004c4, 0x00000000); - nv_icmd(dev, 0x000004c5, 0x00000000); - nv_icmd(dev, 0x000004c6, 0x00000000); - nv_icmd(dev, 0x000004c7, 0x00000000); - nv_icmd(dev, 0x000004c8, 0x00000000); - nv_icmd(dev, 0x000004c9, 0x00000000); - nv_icmd(dev, 0x000004ca, 0x00000000); - nv_icmd(dev, 0x000004cb, 0x00000000); - nv_icmd(dev, 0x000004cc, 0x00000000); - nv_icmd(dev, 0x000004cd, 0x00000000); - nv_icmd(dev, 0x000004ce, 0x00000000); - nv_icmd(dev, 0x000004cf, 0x00000000); - nv_icmd(dev, 0x00000510, 0x3f800000); - nv_icmd(dev, 0x00000511, 0x3f800000); - nv_icmd(dev, 0x00000512, 0x3f800000); - nv_icmd(dev, 0x00000513, 0x3f800000); - nv_icmd(dev, 0x00000514, 0x3f800000); - nv_icmd(dev, 0x00000515, 0x3f800000); - nv_icmd(dev, 0x00000516, 0x3f800000); - nv_icmd(dev, 0x00000517, 0x3f800000); - nv_icmd(dev, 0x00000518, 0x3f800000); - nv_icmd(dev, 0x00000519, 0x3f800000); - nv_icmd(dev, 0x0000051a, 0x3f800000); - nv_icmd(dev, 0x0000051b, 0x3f800000); - nv_icmd(dev, 0x0000051c, 0x3f800000); - nv_icmd(dev, 0x0000051d, 0x3f800000); - nv_icmd(dev, 0x0000051e, 0x3f800000); - nv_icmd(dev, 0x0000051f, 0x3f800000); - nv_icmd(dev, 0x00000520, 0x000002b6); - nv_icmd(dev, 0x00000529, 0x00000001); - nv_icmd(dev, 0x00000530, 0xffff0000); - nv_icmd(dev, 0x00000531, 0xffff0000); - nv_icmd(dev, 0x00000532, 0xffff0000); - nv_icmd(dev, 0x00000533, 0xffff0000); - nv_icmd(dev, 0x00000534, 0xffff0000); - nv_icmd(dev, 0x00000535, 0xffff0000); - nv_icmd(dev, 0x00000536, 0xffff0000); - nv_icmd(dev, 0x00000537, 0xffff0000); - nv_icmd(dev, 0x00000538, 0xffff0000); - nv_icmd(dev, 0x00000539, 0xffff0000); - nv_icmd(dev, 0x0000053a, 0xffff0000); - nv_icmd(dev, 0x0000053b, 0xffff0000); - nv_icmd(dev, 0x0000053c, 0xffff0000); - nv_icmd(dev, 0x0000053d, 0xffff0000); - nv_icmd(dev, 0x0000053e, 0xffff0000); - nv_icmd(dev, 0x0000053f, 0xffff0000); - nv_icmd(dev, 0x00000585, 0x0000003f); - nv_icmd(dev, 0x00000576, 0x00000003); + nv_icmd(priv, 0x000000ad, 0x0000013e); + nv_icmd(priv, 0x000000e1, 0x00000010); + nv_icmd(priv, 0x00000290, 0x00000000); + nv_icmd(priv, 0x00000291, 0x00000000); + nv_icmd(priv, 0x00000292, 0x00000000); + nv_icmd(priv, 0x00000293, 0x00000000); + nv_icmd(priv, 0x00000294, 0x00000000); + nv_icmd(priv, 0x00000295, 0x00000000); + nv_icmd(priv, 0x00000296, 0x00000000); + nv_icmd(priv, 0x00000297, 0x00000000); + nv_icmd(priv, 0x00000298, 0x00000000); + nv_icmd(priv, 0x00000299, 0x00000000); + nv_icmd(priv, 0x0000029a, 0x00000000); + nv_icmd(priv, 0x0000029b, 0x00000000); + nv_icmd(priv, 0x0000029c, 0x00000000); + nv_icmd(priv, 0x0000029d, 0x00000000); + nv_icmd(priv, 0x0000029e, 0x00000000); + nv_icmd(priv, 0x0000029f, 0x00000000); + nv_icmd(priv, 0x000003b0, 0x00000000); + nv_icmd(priv, 0x000003b1, 0x00000000); + nv_icmd(priv, 0x000003b2, 0x00000000); + nv_icmd(priv, 0x000003b3, 0x00000000); + nv_icmd(priv, 0x000003b4, 0x00000000); + nv_icmd(priv, 0x000003b5, 0x00000000); + nv_icmd(priv, 0x000003b6, 0x00000000); + nv_icmd(priv, 0x000003b7, 0x00000000); + nv_icmd(priv, 0x000003b8, 0x00000000); + nv_icmd(priv, 0x000003b9, 0x00000000); + nv_icmd(priv, 0x000003ba, 0x00000000); + nv_icmd(priv, 0x000003bb, 0x00000000); + nv_icmd(priv, 0x000003bc, 0x00000000); + nv_icmd(priv, 0x000003bd, 0x00000000); + nv_icmd(priv, 0x000003be, 0x00000000); + nv_icmd(priv, 0x000003bf, 0x00000000); + nv_icmd(priv, 0x000002a0, 0x00000000); + nv_icmd(priv, 0x000002a1, 0x00000000); + nv_icmd(priv, 0x000002a2, 0x00000000); + nv_icmd(priv, 0x000002a3, 0x00000000); + nv_icmd(priv, 0x000002a4, 0x00000000); + nv_icmd(priv, 0x000002a5, 0x00000000); + nv_icmd(priv, 0x000002a6, 0x00000000); + nv_icmd(priv, 0x000002a7, 0x00000000); + nv_icmd(priv, 0x000002a8, 0x00000000); + nv_icmd(priv, 0x000002a9, 0x00000000); + nv_icmd(priv, 0x000002aa, 0x00000000); + nv_icmd(priv, 0x000002ab, 0x00000000); + nv_icmd(priv, 0x000002ac, 0x00000000); + nv_icmd(priv, 0x000002ad, 0x00000000); + nv_icmd(priv, 0x000002ae, 0x00000000); + nv_icmd(priv, 0x000002af, 0x00000000); + nv_icmd(priv, 0x00000420, 0x00000000); + nv_icmd(priv, 0x00000421, 0x00000000); + nv_icmd(priv, 0x00000422, 0x00000000); + nv_icmd(priv, 0x00000423, 0x00000000); + nv_icmd(priv, 0x00000424, 0x00000000); + nv_icmd(priv, 0x00000425, 0x00000000); + nv_icmd(priv, 0x00000426, 0x00000000); + nv_icmd(priv, 0x00000427, 0x00000000); + nv_icmd(priv, 0x00000428, 0x00000000); + nv_icmd(priv, 0x00000429, 0x00000000); + nv_icmd(priv, 0x0000042a, 0x00000000); + nv_icmd(priv, 0x0000042b, 0x00000000); + nv_icmd(priv, 0x0000042c, 0x00000000); + nv_icmd(priv, 0x0000042d, 0x00000000); + nv_icmd(priv, 0x0000042e, 0x00000000); + nv_icmd(priv, 0x0000042f, 0x00000000); + nv_icmd(priv, 0x000002b0, 0x00000000); + nv_icmd(priv, 0x000002b1, 0x00000000); + nv_icmd(priv, 0x000002b2, 0x00000000); + nv_icmd(priv, 0x000002b3, 0x00000000); + nv_icmd(priv, 0x000002b4, 0x00000000); + nv_icmd(priv, 0x000002b5, 0x00000000); + nv_icmd(priv, 0x000002b6, 0x00000000); + nv_icmd(priv, 0x000002b7, 0x00000000); + nv_icmd(priv, 0x000002b8, 0x00000000); + nv_icmd(priv, 0x000002b9, 0x00000000); + nv_icmd(priv, 0x000002ba, 0x00000000); + nv_icmd(priv, 0x000002bb, 0x00000000); + nv_icmd(priv, 0x000002bc, 0x00000000); + nv_icmd(priv, 0x000002bd, 0x00000000); + nv_icmd(priv, 0x000002be, 0x00000000); + nv_icmd(priv, 0x000002bf, 0x00000000); + nv_icmd(priv, 0x00000430, 0x00000000); + nv_icmd(priv, 0x00000431, 0x00000000); + nv_icmd(priv, 0x00000432, 0x00000000); + nv_icmd(priv, 0x00000433, 0x00000000); + nv_icmd(priv, 0x00000434, 0x00000000); + nv_icmd(priv, 0x00000435, 0x00000000); + nv_icmd(priv, 0x00000436, 0x00000000); + nv_icmd(priv, 0x00000437, 0x00000000); + nv_icmd(priv, 0x00000438, 0x00000000); + nv_icmd(priv, 0x00000439, 0x00000000); + nv_icmd(priv, 0x0000043a, 0x00000000); + nv_icmd(priv, 0x0000043b, 0x00000000); + nv_icmd(priv, 0x0000043c, 0x00000000); + nv_icmd(priv, 0x0000043d, 0x00000000); + nv_icmd(priv, 0x0000043e, 0x00000000); + nv_icmd(priv, 0x0000043f, 0x00000000); + nv_icmd(priv, 0x000002c0, 0x00000000); + nv_icmd(priv, 0x000002c1, 0x00000000); + nv_icmd(priv, 0x000002c2, 0x00000000); + nv_icmd(priv, 0x000002c3, 0x00000000); + nv_icmd(priv, 0x000002c4, 0x00000000); + nv_icmd(priv, 0x000002c5, 0x00000000); + nv_icmd(priv, 0x000002c6, 0x00000000); + nv_icmd(priv, 0x000002c7, 0x00000000); + nv_icmd(priv, 0x000002c8, 0x00000000); + nv_icmd(priv, 0x000002c9, 0x00000000); + nv_icmd(priv, 0x000002ca, 0x00000000); + nv_icmd(priv, 0x000002cb, 0x00000000); + nv_icmd(priv, 0x000002cc, 0x00000000); + nv_icmd(priv, 0x000002cd, 0x00000000); + nv_icmd(priv, 0x000002ce, 0x00000000); + nv_icmd(priv, 0x000002cf, 0x00000000); + nv_icmd(priv, 0x000004d0, 0x00000000); + nv_icmd(priv, 0x000004d1, 0x00000000); + nv_icmd(priv, 0x000004d2, 0x00000000); + nv_icmd(priv, 0x000004d3, 0x00000000); + nv_icmd(priv, 0x000004d4, 0x00000000); + nv_icmd(priv, 0x000004d5, 0x00000000); + nv_icmd(priv, 0x000004d6, 0x00000000); + nv_icmd(priv, 0x000004d7, 0x00000000); + nv_icmd(priv, 0x000004d8, 0x00000000); + nv_icmd(priv, 0x000004d9, 0x00000000); + nv_icmd(priv, 0x000004da, 0x00000000); + nv_icmd(priv, 0x000004db, 0x00000000); + nv_icmd(priv, 0x000004dc, 0x00000000); + nv_icmd(priv, 0x000004dd, 0x00000000); + nv_icmd(priv, 0x000004de, 0x00000000); + nv_icmd(priv, 0x000004df, 0x00000000); + nv_icmd(priv, 0x00000720, 0x00000000); + nv_icmd(priv, 0x00000721, 0x00000000); + nv_icmd(priv, 0x00000722, 0x00000000); + nv_icmd(priv, 0x00000723, 0x00000000); + nv_icmd(priv, 0x00000724, 0x00000000); + nv_icmd(priv, 0x00000725, 0x00000000); + nv_icmd(priv, 0x00000726, 0x00000000); + nv_icmd(priv, 0x00000727, 0x00000000); + nv_icmd(priv, 0x00000728, 0x00000000); + nv_icmd(priv, 0x00000729, 0x00000000); + nv_icmd(priv, 0x0000072a, 0x00000000); + nv_icmd(priv, 0x0000072b, 0x00000000); + nv_icmd(priv, 0x0000072c, 0x00000000); + nv_icmd(priv, 0x0000072d, 0x00000000); + nv_icmd(priv, 0x0000072e, 0x00000000); + nv_icmd(priv, 0x0000072f, 0x00000000); + nv_icmd(priv, 0x000008c0, 0x00000000); + nv_icmd(priv, 0x000008c1, 0x00000000); + nv_icmd(priv, 0x000008c2, 0x00000000); + nv_icmd(priv, 0x000008c3, 0x00000000); + nv_icmd(priv, 0x000008c4, 0x00000000); + nv_icmd(priv, 0x000008c5, 0x00000000); + nv_icmd(priv, 0x000008c6, 0x00000000); + nv_icmd(priv, 0x000008c7, 0x00000000); + nv_icmd(priv, 0x000008c8, 0x00000000); + nv_icmd(priv, 0x000008c9, 0x00000000); + nv_icmd(priv, 0x000008ca, 0x00000000); + nv_icmd(priv, 0x000008cb, 0x00000000); + nv_icmd(priv, 0x000008cc, 0x00000000); + nv_icmd(priv, 0x000008cd, 0x00000000); + nv_icmd(priv, 0x000008ce, 0x00000000); + nv_icmd(priv, 0x000008cf, 0x00000000); + nv_icmd(priv, 0x00000890, 0x00000000); + nv_icmd(priv, 0x00000891, 0x00000000); + nv_icmd(priv, 0x00000892, 0x00000000); + nv_icmd(priv, 0x00000893, 0x00000000); + nv_icmd(priv, 0x00000894, 0x00000000); + nv_icmd(priv, 0x00000895, 0x00000000); + nv_icmd(priv, 0x00000896, 0x00000000); + nv_icmd(priv, 0x00000897, 0x00000000); + nv_icmd(priv, 0x00000898, 0x00000000); + nv_icmd(priv, 0x00000899, 0x00000000); + nv_icmd(priv, 0x0000089a, 0x00000000); + nv_icmd(priv, 0x0000089b, 0x00000000); + nv_icmd(priv, 0x0000089c, 0x00000000); + nv_icmd(priv, 0x0000089d, 0x00000000); + nv_icmd(priv, 0x0000089e, 0x00000000); + nv_icmd(priv, 0x0000089f, 0x00000000); + nv_icmd(priv, 0x000008e0, 0x00000000); + nv_icmd(priv, 0x000008e1, 0x00000000); + nv_icmd(priv, 0x000008e2, 0x00000000); + nv_icmd(priv, 0x000008e3, 0x00000000); + nv_icmd(priv, 0x000008e4, 0x00000000); + nv_icmd(priv, 0x000008e5, 0x00000000); + nv_icmd(priv, 0x000008e6, 0x00000000); + nv_icmd(priv, 0x000008e7, 0x00000000); + nv_icmd(priv, 0x000008e8, 0x00000000); + nv_icmd(priv, 0x000008e9, 0x00000000); + nv_icmd(priv, 0x000008ea, 0x00000000); + nv_icmd(priv, 0x000008eb, 0x00000000); + nv_icmd(priv, 0x000008ec, 0x00000000); + nv_icmd(priv, 0x000008ed, 0x00000000); + nv_icmd(priv, 0x000008ee, 0x00000000); + nv_icmd(priv, 0x000008ef, 0x00000000); + nv_icmd(priv, 0x000008a0, 0x00000000); + nv_icmd(priv, 0x000008a1, 0x00000000); + nv_icmd(priv, 0x000008a2, 0x00000000); + nv_icmd(priv, 0x000008a3, 0x00000000); + nv_icmd(priv, 0x000008a4, 0x00000000); + nv_icmd(priv, 0x000008a5, 0x00000000); + nv_icmd(priv, 0x000008a6, 0x00000000); + nv_icmd(priv, 0x000008a7, 0x00000000); + nv_icmd(priv, 0x000008a8, 0x00000000); + nv_icmd(priv, 0x000008a9, 0x00000000); + nv_icmd(priv, 0x000008aa, 0x00000000); + nv_icmd(priv, 0x000008ab, 0x00000000); + nv_icmd(priv, 0x000008ac, 0x00000000); + nv_icmd(priv, 0x000008ad, 0x00000000); + nv_icmd(priv, 0x000008ae, 0x00000000); + nv_icmd(priv, 0x000008af, 0x00000000); + nv_icmd(priv, 0x000008f0, 0x00000000); + nv_icmd(priv, 0x000008f1, 0x00000000); + nv_icmd(priv, 0x000008f2, 0x00000000); + nv_icmd(priv, 0x000008f3, 0x00000000); + nv_icmd(priv, 0x000008f4, 0x00000000); + nv_icmd(priv, 0x000008f5, 0x00000000); + nv_icmd(priv, 0x000008f6, 0x00000000); + nv_icmd(priv, 0x000008f7, 0x00000000); + nv_icmd(priv, 0x000008f8, 0x00000000); + nv_icmd(priv, 0x000008f9, 0x00000000); + nv_icmd(priv, 0x000008fa, 0x00000000); + nv_icmd(priv, 0x000008fb, 0x00000000); + nv_icmd(priv, 0x000008fc, 0x00000000); + nv_icmd(priv, 0x000008fd, 0x00000000); + nv_icmd(priv, 0x000008fe, 0x00000000); + nv_icmd(priv, 0x000008ff, 0x00000000); + nv_icmd(priv, 0x0000094c, 0x000000ff); + nv_icmd(priv, 0x0000094d, 0xffffffff); + nv_icmd(priv, 0x0000094e, 0x00000002); + nv_icmd(priv, 0x000002ec, 0x00000001); + nv_icmd(priv, 0x00000303, 0x00000001); + nv_icmd(priv, 0x000002e6, 0x00000001); + nv_icmd(priv, 0x00000466, 0x00000052); + nv_icmd(priv, 0x00000301, 0x3f800000); + nv_icmd(priv, 0x00000304, 0x30201000); + nv_icmd(priv, 0x00000305, 0x70605040); + nv_icmd(priv, 0x00000306, 0xb8a89888); + nv_icmd(priv, 0x00000307, 0xf8e8d8c8); + nv_icmd(priv, 0x0000030a, 0x00ffff00); + nv_icmd(priv, 0x0000030b, 0x0000001a); + nv_icmd(priv, 0x0000030c, 0x00000001); + nv_icmd(priv, 0x00000318, 0x00000001); + nv_icmd(priv, 0x00000340, 0x00000000); + nv_icmd(priv, 0x00000375, 0x00000001); + nv_icmd(priv, 0x00000351, 0x00000100); + nv_icmd(priv, 0x0000037d, 0x00000006); + nv_icmd(priv, 0x000003a0, 0x00000002); + nv_icmd(priv, 0x000003aa, 0x00000001); + nv_icmd(priv, 0x000003a9, 0x00000001); + nv_icmd(priv, 0x00000380, 0x00000001); + nv_icmd(priv, 0x00000360, 0x00000040); + nv_icmd(priv, 0x00000366, 0x00000000); + nv_icmd(priv, 0x00000367, 0x00000000); + nv_icmd(priv, 0x00000368, 0x00001fff); + nv_icmd(priv, 0x00000370, 0x00000000); + nv_icmd(priv, 0x00000371, 0x00000000); + nv_icmd(priv, 0x00000372, 0x003fffff); + nv_icmd(priv, 0x0000037a, 0x00000012); + nv_icmd(priv, 0x000005e0, 0x00000022); + nv_icmd(priv, 0x000005e1, 0x00000022); + nv_icmd(priv, 0x000005e2, 0x00000022); + nv_icmd(priv, 0x000005e3, 0x00000022); + nv_icmd(priv, 0x000005e4, 0x00000022); + nv_icmd(priv, 0x00000619, 0x00000003); + nv_icmd(priv, 0x00000811, 0x00000003); + nv_icmd(priv, 0x00000812, 0x00000004); + nv_icmd(priv, 0x00000813, 0x00000006); + nv_icmd(priv, 0x00000814, 0x00000008); + nv_icmd(priv, 0x00000815, 0x0000000b); + nv_icmd(priv, 0x00000800, 0x00000001); + nv_icmd(priv, 0x00000801, 0x00000001); + nv_icmd(priv, 0x00000802, 0x00000001); + nv_icmd(priv, 0x00000803, 0x00000001); + nv_icmd(priv, 0x00000804, 0x00000001); + nv_icmd(priv, 0x00000805, 0x00000001); + nv_icmd(priv, 0x00000632, 0x00000001); + nv_icmd(priv, 0x00000633, 0x00000002); + nv_icmd(priv, 0x00000634, 0x00000003); + nv_icmd(priv, 0x00000635, 0x00000004); + nv_icmd(priv, 0x00000654, 0x3f800000); + nv_icmd(priv, 0x00000657, 0x3f800000); + nv_icmd(priv, 0x00000655, 0x3f800000); + nv_icmd(priv, 0x00000656, 0x3f800000); + nv_icmd(priv, 0x000006cd, 0x3f800000); + nv_icmd(priv, 0x000007f5, 0x3f800000); + nv_icmd(priv, 0x000007dc, 0x39291909); + nv_icmd(priv, 0x000007dd, 0x79695949); + nv_icmd(priv, 0x000007de, 0xb9a99989); + nv_icmd(priv, 0x000007df, 0xf9e9d9c9); + nv_icmd(priv, 0x000007e8, 0x00003210); + nv_icmd(priv, 0x000007e9, 0x00007654); + nv_icmd(priv, 0x000007ea, 0x00000098); + nv_icmd(priv, 0x000007ec, 0x39291909); + nv_icmd(priv, 0x000007ed, 0x79695949); + nv_icmd(priv, 0x000007ee, 0xb9a99989); + nv_icmd(priv, 0x000007ef, 0xf9e9d9c9); + nv_icmd(priv, 0x000007f0, 0x00003210); + nv_icmd(priv, 0x000007f1, 0x00007654); + nv_icmd(priv, 0x000007f2, 0x00000098); + nv_icmd(priv, 0x000005a5, 0x00000001); + nv_icmd(priv, 0x00000980, 0x00000000); + nv_icmd(priv, 0x00000981, 0x00000000); + nv_icmd(priv, 0x00000982, 0x00000000); + nv_icmd(priv, 0x00000983, 0x00000000); + nv_icmd(priv, 0x00000984, 0x00000000); + nv_icmd(priv, 0x00000985, 0x00000000); + nv_icmd(priv, 0x00000986, 0x00000000); + nv_icmd(priv, 0x00000987, 0x00000000); + nv_icmd(priv, 0x00000988, 0x00000000); + nv_icmd(priv, 0x00000989, 0x00000000); + nv_icmd(priv, 0x0000098a, 0x00000000); + nv_icmd(priv, 0x0000098b, 0x00000000); + nv_icmd(priv, 0x0000098c, 0x00000000); + nv_icmd(priv, 0x0000098d, 0x00000000); + nv_icmd(priv, 0x0000098e, 0x00000000); + nv_icmd(priv, 0x0000098f, 0x00000000); + nv_icmd(priv, 0x00000990, 0x00000000); + nv_icmd(priv, 0x00000991, 0x00000000); + nv_icmd(priv, 0x00000992, 0x00000000); + nv_icmd(priv, 0x00000993, 0x00000000); + nv_icmd(priv, 0x00000994, 0x00000000); + nv_icmd(priv, 0x00000995, 0x00000000); + nv_icmd(priv, 0x00000996, 0x00000000); + nv_icmd(priv, 0x00000997, 0x00000000); + nv_icmd(priv, 0x00000998, 0x00000000); + nv_icmd(priv, 0x00000999, 0x00000000); + nv_icmd(priv, 0x0000099a, 0x00000000); + nv_icmd(priv, 0x0000099b, 0x00000000); + nv_icmd(priv, 0x0000099c, 0x00000000); + nv_icmd(priv, 0x0000099d, 0x00000000); + nv_icmd(priv, 0x0000099e, 0x00000000); + nv_icmd(priv, 0x0000099f, 0x00000000); + nv_icmd(priv, 0x000009a0, 0x00000000); + nv_icmd(priv, 0x000009a1, 0x00000000); + nv_icmd(priv, 0x000009a2, 0x00000000); + nv_icmd(priv, 0x000009a3, 0x00000000); + nv_icmd(priv, 0x000009a4, 0x00000000); + nv_icmd(priv, 0x000009a5, 0x00000000); + nv_icmd(priv, 0x000009a6, 0x00000000); + nv_icmd(priv, 0x000009a7, 0x00000000); + nv_icmd(priv, 0x000009a8, 0x00000000); + nv_icmd(priv, 0x000009a9, 0x00000000); + nv_icmd(priv, 0x000009aa, 0x00000000); + nv_icmd(priv, 0x000009ab, 0x00000000); + nv_icmd(priv, 0x000009ac, 0x00000000); + nv_icmd(priv, 0x000009ad, 0x00000000); + nv_icmd(priv, 0x000009ae, 0x00000000); + nv_icmd(priv, 0x000009af, 0x00000000); + nv_icmd(priv, 0x000009b0, 0x00000000); + nv_icmd(priv, 0x000009b1, 0x00000000); + nv_icmd(priv, 0x000009b2, 0x00000000); + nv_icmd(priv, 0x000009b3, 0x00000000); + nv_icmd(priv, 0x000009b4, 0x00000000); + nv_icmd(priv, 0x000009b5, 0x00000000); + nv_icmd(priv, 0x000009b6, 0x00000000); + nv_icmd(priv, 0x000009b7, 0x00000000); + nv_icmd(priv, 0x000009b8, 0x00000000); + nv_icmd(priv, 0x000009b9, 0x00000000); + nv_icmd(priv, 0x000009ba, 0x00000000); + nv_icmd(priv, 0x000009bb, 0x00000000); + nv_icmd(priv, 0x000009bc, 0x00000000); + nv_icmd(priv, 0x000009bd, 0x00000000); + nv_icmd(priv, 0x000009be, 0x00000000); + nv_icmd(priv, 0x000009bf, 0x00000000); + nv_icmd(priv, 0x000009c0, 0x00000000); + nv_icmd(priv, 0x000009c1, 0x00000000); + nv_icmd(priv, 0x000009c2, 0x00000000); + nv_icmd(priv, 0x000009c3, 0x00000000); + nv_icmd(priv, 0x000009c4, 0x00000000); + nv_icmd(priv, 0x000009c5, 0x00000000); + nv_icmd(priv, 0x000009c6, 0x00000000); + nv_icmd(priv, 0x000009c7, 0x00000000); + nv_icmd(priv, 0x000009c8, 0x00000000); + nv_icmd(priv, 0x000009c9, 0x00000000); + nv_icmd(priv, 0x000009ca, 0x00000000); + nv_icmd(priv, 0x000009cb, 0x00000000); + nv_icmd(priv, 0x000009cc, 0x00000000); + nv_icmd(priv, 0x000009cd, 0x00000000); + nv_icmd(priv, 0x000009ce, 0x00000000); + nv_icmd(priv, 0x000009cf, 0x00000000); + nv_icmd(priv, 0x000009d0, 0x00000000); + nv_icmd(priv, 0x000009d1, 0x00000000); + nv_icmd(priv, 0x000009d2, 0x00000000); + nv_icmd(priv, 0x000009d3, 0x00000000); + nv_icmd(priv, 0x000009d4, 0x00000000); + nv_icmd(priv, 0x000009d5, 0x00000000); + nv_icmd(priv, 0x000009d6, 0x00000000); + nv_icmd(priv, 0x000009d7, 0x00000000); + nv_icmd(priv, 0x000009d8, 0x00000000); + nv_icmd(priv, 0x000009d9, 0x00000000); + nv_icmd(priv, 0x000009da, 0x00000000); + nv_icmd(priv, 0x000009db, 0x00000000); + nv_icmd(priv, 0x000009dc, 0x00000000); + nv_icmd(priv, 0x000009dd, 0x00000000); + nv_icmd(priv, 0x000009de, 0x00000000); + nv_icmd(priv, 0x000009df, 0x00000000); + nv_icmd(priv, 0x000009e0, 0x00000000); + nv_icmd(priv, 0x000009e1, 0x00000000); + nv_icmd(priv, 0x000009e2, 0x00000000); + nv_icmd(priv, 0x000009e3, 0x00000000); + nv_icmd(priv, 0x000009e4, 0x00000000); + nv_icmd(priv, 0x000009e5, 0x00000000); + nv_icmd(priv, 0x000009e6, 0x00000000); + nv_icmd(priv, 0x000009e7, 0x00000000); + nv_icmd(priv, 0x000009e8, 0x00000000); + nv_icmd(priv, 0x000009e9, 0x00000000); + nv_icmd(priv, 0x000009ea, 0x00000000); + nv_icmd(priv, 0x000009eb, 0x00000000); + nv_icmd(priv, 0x000009ec, 0x00000000); + nv_icmd(priv, 0x000009ed, 0x00000000); + nv_icmd(priv, 0x000009ee, 0x00000000); + nv_icmd(priv, 0x000009ef, 0x00000000); + nv_icmd(priv, 0x000009f0, 0x00000000); + nv_icmd(priv, 0x000009f1, 0x00000000); + nv_icmd(priv, 0x000009f2, 0x00000000); + nv_icmd(priv, 0x000009f3, 0x00000000); + nv_icmd(priv, 0x000009f4, 0x00000000); + nv_icmd(priv, 0x000009f5, 0x00000000); + nv_icmd(priv, 0x000009f6, 0x00000000); + nv_icmd(priv, 0x000009f7, 0x00000000); + nv_icmd(priv, 0x000009f8, 0x00000000); + nv_icmd(priv, 0x000009f9, 0x00000000); + nv_icmd(priv, 0x000009fa, 0x00000000); + nv_icmd(priv, 0x000009fb, 0x00000000); + nv_icmd(priv, 0x000009fc, 0x00000000); + nv_icmd(priv, 0x000009fd, 0x00000000); + nv_icmd(priv, 0x000009fe, 0x00000000); + nv_icmd(priv, 0x000009ff, 0x00000000); + nv_icmd(priv, 0x00000468, 0x00000004); + nv_icmd(priv, 0x0000046c, 0x00000001); + nv_icmd(priv, 0x00000470, 0x00000000); + nv_icmd(priv, 0x00000471, 0x00000000); + nv_icmd(priv, 0x00000472, 0x00000000); + nv_icmd(priv, 0x00000473, 0x00000000); + nv_icmd(priv, 0x00000474, 0x00000000); + nv_icmd(priv, 0x00000475, 0x00000000); + nv_icmd(priv, 0x00000476, 0x00000000); + nv_icmd(priv, 0x00000477, 0x00000000); + nv_icmd(priv, 0x00000478, 0x00000000); + nv_icmd(priv, 0x00000479, 0x00000000); + nv_icmd(priv, 0x0000047a, 0x00000000); + nv_icmd(priv, 0x0000047b, 0x00000000); + nv_icmd(priv, 0x0000047c, 0x00000000); + nv_icmd(priv, 0x0000047d, 0x00000000); + nv_icmd(priv, 0x0000047e, 0x00000000); + nv_icmd(priv, 0x0000047f, 0x00000000); + nv_icmd(priv, 0x00000480, 0x00000000); + nv_icmd(priv, 0x00000481, 0x00000000); + nv_icmd(priv, 0x00000482, 0x00000000); + nv_icmd(priv, 0x00000483, 0x00000000); + nv_icmd(priv, 0x00000484, 0x00000000); + nv_icmd(priv, 0x00000485, 0x00000000); + nv_icmd(priv, 0x00000486, 0x00000000); + nv_icmd(priv, 0x00000487, 0x00000000); + nv_icmd(priv, 0x00000488, 0x00000000); + nv_icmd(priv, 0x00000489, 0x00000000); + nv_icmd(priv, 0x0000048a, 0x00000000); + nv_icmd(priv, 0x0000048b, 0x00000000); + nv_icmd(priv, 0x0000048c, 0x00000000); + nv_icmd(priv, 0x0000048d, 0x00000000); + nv_icmd(priv, 0x0000048e, 0x00000000); + nv_icmd(priv, 0x0000048f, 0x00000000); + nv_icmd(priv, 0x00000490, 0x00000000); + nv_icmd(priv, 0x00000491, 0x00000000); + nv_icmd(priv, 0x00000492, 0x00000000); + nv_icmd(priv, 0x00000493, 0x00000000); + nv_icmd(priv, 0x00000494, 0x00000000); + nv_icmd(priv, 0x00000495, 0x00000000); + nv_icmd(priv, 0x00000496, 0x00000000); + nv_icmd(priv, 0x00000497, 0x00000000); + nv_icmd(priv, 0x00000498, 0x00000000); + nv_icmd(priv, 0x00000499, 0x00000000); + nv_icmd(priv, 0x0000049a, 0x00000000); + nv_icmd(priv, 0x0000049b, 0x00000000); + nv_icmd(priv, 0x0000049c, 0x00000000); + nv_icmd(priv, 0x0000049d, 0x00000000); + nv_icmd(priv, 0x0000049e, 0x00000000); + nv_icmd(priv, 0x0000049f, 0x00000000); + nv_icmd(priv, 0x000004a0, 0x00000000); + nv_icmd(priv, 0x000004a1, 0x00000000); + nv_icmd(priv, 0x000004a2, 0x00000000); + nv_icmd(priv, 0x000004a3, 0x00000000); + nv_icmd(priv, 0x000004a4, 0x00000000); + nv_icmd(priv, 0x000004a5, 0x00000000); + nv_icmd(priv, 0x000004a6, 0x00000000); + nv_icmd(priv, 0x000004a7, 0x00000000); + nv_icmd(priv, 0x000004a8, 0x00000000); + nv_icmd(priv, 0x000004a9, 0x00000000); + nv_icmd(priv, 0x000004aa, 0x00000000); + nv_icmd(priv, 0x000004ab, 0x00000000); + nv_icmd(priv, 0x000004ac, 0x00000000); + nv_icmd(priv, 0x000004ad, 0x00000000); + nv_icmd(priv, 0x000004ae, 0x00000000); + nv_icmd(priv, 0x000004af, 0x00000000); + nv_icmd(priv, 0x000004b0, 0x00000000); + nv_icmd(priv, 0x000004b1, 0x00000000); + nv_icmd(priv, 0x000004b2, 0x00000000); + nv_icmd(priv, 0x000004b3, 0x00000000); + nv_icmd(priv, 0x000004b4, 0x00000000); + nv_icmd(priv, 0x000004b5, 0x00000000); + nv_icmd(priv, 0x000004b6, 0x00000000); + nv_icmd(priv, 0x000004b7, 0x00000000); + nv_icmd(priv, 0x000004b8, 0x00000000); + nv_icmd(priv, 0x000004b9, 0x00000000); + nv_icmd(priv, 0x000004ba, 0x00000000); + nv_icmd(priv, 0x000004bb, 0x00000000); + nv_icmd(priv, 0x000004bc, 0x00000000); + nv_icmd(priv, 0x000004bd, 0x00000000); + nv_icmd(priv, 0x000004be, 0x00000000); + nv_icmd(priv, 0x000004bf, 0x00000000); + nv_icmd(priv, 0x000004c0, 0x00000000); + nv_icmd(priv, 0x000004c1, 0x00000000); + nv_icmd(priv, 0x000004c2, 0x00000000); + nv_icmd(priv, 0x000004c3, 0x00000000); + nv_icmd(priv, 0x000004c4, 0x00000000); + nv_icmd(priv, 0x000004c5, 0x00000000); + nv_icmd(priv, 0x000004c6, 0x00000000); + nv_icmd(priv, 0x000004c7, 0x00000000); + nv_icmd(priv, 0x000004c8, 0x00000000); + nv_icmd(priv, 0x000004c9, 0x00000000); + nv_icmd(priv, 0x000004ca, 0x00000000); + nv_icmd(priv, 0x000004cb, 0x00000000); + nv_icmd(priv, 0x000004cc, 0x00000000); + nv_icmd(priv, 0x000004cd, 0x00000000); + nv_icmd(priv, 0x000004ce, 0x00000000); + nv_icmd(priv, 0x000004cf, 0x00000000); + nv_icmd(priv, 0x00000510, 0x3f800000); + nv_icmd(priv, 0x00000511, 0x3f800000); + nv_icmd(priv, 0x00000512, 0x3f800000); + nv_icmd(priv, 0x00000513, 0x3f800000); + nv_icmd(priv, 0x00000514, 0x3f800000); + nv_icmd(priv, 0x00000515, 0x3f800000); + nv_icmd(priv, 0x00000516, 0x3f800000); + nv_icmd(priv, 0x00000517, 0x3f800000); + nv_icmd(priv, 0x00000518, 0x3f800000); + nv_icmd(priv, 0x00000519, 0x3f800000); + nv_icmd(priv, 0x0000051a, 0x3f800000); + nv_icmd(priv, 0x0000051b, 0x3f800000); + nv_icmd(priv, 0x0000051c, 0x3f800000); + nv_icmd(priv, 0x0000051d, 0x3f800000); + nv_icmd(priv, 0x0000051e, 0x3f800000); + nv_icmd(priv, 0x0000051f, 0x3f800000); + nv_icmd(priv, 0x00000520, 0x000002b6); + nv_icmd(priv, 0x00000529, 0x00000001); + nv_icmd(priv, 0x00000530, 0xffff0000); + nv_icmd(priv, 0x00000531, 0xffff0000); + nv_icmd(priv, 0x00000532, 0xffff0000); + nv_icmd(priv, 0x00000533, 0xffff0000); + nv_icmd(priv, 0x00000534, 0xffff0000); + nv_icmd(priv, 0x00000535, 0xffff0000); + nv_icmd(priv, 0x00000536, 0xffff0000); + nv_icmd(priv, 0x00000537, 0xffff0000); + nv_icmd(priv, 0x00000538, 0xffff0000); + nv_icmd(priv, 0x00000539, 0xffff0000); + nv_icmd(priv, 0x0000053a, 0xffff0000); + nv_icmd(priv, 0x0000053b, 0xffff0000); + nv_icmd(priv, 0x0000053c, 0xffff0000); + nv_icmd(priv, 0x0000053d, 0xffff0000); + nv_icmd(priv, 0x0000053e, 0xffff0000); + nv_icmd(priv, 0x0000053f, 0xffff0000); + nv_icmd(priv, 0x00000585, 0x0000003f); + nv_icmd(priv, 0x00000576, 0x00000003); if (dev_priv->chipset == 0xc1 || dev_priv->chipset == 0xd9) - nv_icmd(dev, 0x0000057b, 0x00000059); - nv_icmd(dev, 0x00000586, 0x00000040); - nv_icmd(dev, 0x00000582, 0x00000080); - nv_icmd(dev, 0x00000583, 0x00000080); - nv_icmd(dev, 0x000005c2, 0x00000001); - nv_icmd(dev, 0x00000638, 0x00000001); - nv_icmd(dev, 0x00000639, 0x00000001); - nv_icmd(dev, 0x0000063a, 0x00000002); - nv_icmd(dev, 0x0000063b, 0x00000001); - nv_icmd(dev, 0x0000063c, 0x00000001); - nv_icmd(dev, 0x0000063d, 0x00000002); - nv_icmd(dev, 0x0000063e, 0x00000001); - nv_icmd(dev, 0x000008b8, 0x00000001); - nv_icmd(dev, 0x000008b9, 0x00000001); - nv_icmd(dev, 0x000008ba, 0x00000001); - nv_icmd(dev, 0x000008bb, 0x00000001); - nv_icmd(dev, 0x000008bc, 0x00000001); - nv_icmd(dev, 0x000008bd, 0x00000001); - nv_icmd(dev, 0x000008be, 0x00000001); - nv_icmd(dev, 0x000008bf, 0x00000001); - nv_icmd(dev, 0x00000900, 0x00000001); - nv_icmd(dev, 0x00000901, 0x00000001); - nv_icmd(dev, 0x00000902, 0x00000001); - nv_icmd(dev, 0x00000903, 0x00000001); - nv_icmd(dev, 0x00000904, 0x00000001); - nv_icmd(dev, 0x00000905, 0x00000001); - nv_icmd(dev, 0x00000906, 0x00000001); - nv_icmd(dev, 0x00000907, 0x00000001); - nv_icmd(dev, 0x00000908, 0x00000002); - nv_icmd(dev, 0x00000909, 0x00000002); - nv_icmd(dev, 0x0000090a, 0x00000002); - nv_icmd(dev, 0x0000090b, 0x00000002); - nv_icmd(dev, 0x0000090c, 0x00000002); - nv_icmd(dev, 0x0000090d, 0x00000002); - nv_icmd(dev, 0x0000090e, 0x00000002); - nv_icmd(dev, 0x0000090f, 0x00000002); - nv_icmd(dev, 0x00000910, 0x00000001); - nv_icmd(dev, 0x00000911, 0x00000001); - nv_icmd(dev, 0x00000912, 0x00000001); - nv_icmd(dev, 0x00000913, 0x00000001); - nv_icmd(dev, 0x00000914, 0x00000001); - nv_icmd(dev, 0x00000915, 0x00000001); - nv_icmd(dev, 0x00000916, 0x00000001); - nv_icmd(dev, 0x00000917, 0x00000001); - nv_icmd(dev, 0x00000918, 0x00000001); - nv_icmd(dev, 0x00000919, 0x00000001); - nv_icmd(dev, 0x0000091a, 0x00000001); - nv_icmd(dev, 0x0000091b, 0x00000001); - nv_icmd(dev, 0x0000091c, 0x00000001); - nv_icmd(dev, 0x0000091d, 0x00000001); - nv_icmd(dev, 0x0000091e, 0x00000001); - nv_icmd(dev, 0x0000091f, 0x00000001); - nv_icmd(dev, 0x00000920, 0x00000002); - nv_icmd(dev, 0x00000921, 0x00000002); - nv_icmd(dev, 0x00000922, 0x00000002); - nv_icmd(dev, 0x00000923, 0x00000002); - nv_icmd(dev, 0x00000924, 0x00000002); - nv_icmd(dev, 0x00000925, 0x00000002); - nv_icmd(dev, 0x00000926, 0x00000002); - nv_icmd(dev, 0x00000927, 0x00000002); - nv_icmd(dev, 0x00000928, 0x00000001); - nv_icmd(dev, 0x00000929, 0x00000001); - nv_icmd(dev, 0x0000092a, 0x00000001); - nv_icmd(dev, 0x0000092b, 0x00000001); - nv_icmd(dev, 0x0000092c, 0x00000001); - nv_icmd(dev, 0x0000092d, 0x00000001); - nv_icmd(dev, 0x0000092e, 0x00000001); - nv_icmd(dev, 0x0000092f, 0x00000001); - nv_icmd(dev, 0x00000648, 0x00000001); - nv_icmd(dev, 0x00000649, 0x00000001); - nv_icmd(dev, 0x0000064a, 0x00000001); - nv_icmd(dev, 0x0000064b, 0x00000001); - nv_icmd(dev, 0x0000064c, 0x00000001); - nv_icmd(dev, 0x0000064d, 0x00000001); - nv_icmd(dev, 0x0000064e, 0x00000001); - nv_icmd(dev, 0x0000064f, 0x00000001); - nv_icmd(dev, 0x00000650, 0x00000001); - nv_icmd(dev, 0x00000658, 0x0000000f); - nv_icmd(dev, 0x000007ff, 0x0000000a); - nv_icmd(dev, 0x0000066a, 0x40000000); - nv_icmd(dev, 0x0000066b, 0x10000000); - nv_icmd(dev, 0x0000066c, 0xffff0000); - nv_icmd(dev, 0x0000066d, 0xffff0000); - nv_icmd(dev, 0x000007af, 0x00000008); - nv_icmd(dev, 0x000007b0, 0x00000008); - nv_icmd(dev, 0x000007f6, 0x00000001); - nv_icmd(dev, 0x000006b2, 0x00000055); - nv_icmd(dev, 0x000007ad, 0x00000003); - nv_icmd(dev, 0x00000937, 0x00000001); - nv_icmd(dev, 0x00000971, 0x00000008); - nv_icmd(dev, 0x00000972, 0x00000040); - nv_icmd(dev, 0x00000973, 0x0000012c); - nv_icmd(dev, 0x0000097c, 0x00000040); - nv_icmd(dev, 0x00000979, 0x00000003); - nv_icmd(dev, 0x00000975, 0x00000020); - nv_icmd(dev, 0x00000976, 0x00000001); - nv_icmd(dev, 0x00000977, 0x00000020); - nv_icmd(dev, 0x00000978, 0x00000001); - nv_icmd(dev, 0x00000957, 0x00000003); - nv_icmd(dev, 0x0000095e, 0x20164010); - nv_icmd(dev, 0x0000095f, 0x00000020); + nv_icmd(priv, 0x0000057b, 0x00000059); + nv_icmd(priv, 0x00000586, 0x00000040); + nv_icmd(priv, 0x00000582, 0x00000080); + nv_icmd(priv, 0x00000583, 0x00000080); + nv_icmd(priv, 0x000005c2, 0x00000001); + nv_icmd(priv, 0x00000638, 0x00000001); + nv_icmd(priv, 0x00000639, 0x00000001); + nv_icmd(priv, 0x0000063a, 0x00000002); + nv_icmd(priv, 0x0000063b, 0x00000001); + nv_icmd(priv, 0x0000063c, 0x00000001); + nv_icmd(priv, 0x0000063d, 0x00000002); + nv_icmd(priv, 0x0000063e, 0x00000001); + nv_icmd(priv, 0x000008b8, 0x00000001); + nv_icmd(priv, 0x000008b9, 0x00000001); + nv_icmd(priv, 0x000008ba, 0x00000001); + nv_icmd(priv, 0x000008bb, 0x00000001); + nv_icmd(priv, 0x000008bc, 0x00000001); + nv_icmd(priv, 0x000008bd, 0x00000001); + nv_icmd(priv, 0x000008be, 0x00000001); + nv_icmd(priv, 0x000008bf, 0x00000001); + nv_icmd(priv, 0x00000900, 0x00000001); + nv_icmd(priv, 0x00000901, 0x00000001); + nv_icmd(priv, 0x00000902, 0x00000001); + nv_icmd(priv, 0x00000903, 0x00000001); + nv_icmd(priv, 0x00000904, 0x00000001); + nv_icmd(priv, 0x00000905, 0x00000001); + nv_icmd(priv, 0x00000906, 0x00000001); + nv_icmd(priv, 0x00000907, 0x00000001); + nv_icmd(priv, 0x00000908, 0x00000002); + nv_icmd(priv, 0x00000909, 0x00000002); + nv_icmd(priv, 0x0000090a, 0x00000002); + nv_icmd(priv, 0x0000090b, 0x00000002); + nv_icmd(priv, 0x0000090c, 0x00000002); + nv_icmd(priv, 0x0000090d, 0x00000002); + nv_icmd(priv, 0x0000090e, 0x00000002); + nv_icmd(priv, 0x0000090f, 0x00000002); + nv_icmd(priv, 0x00000910, 0x00000001); + nv_icmd(priv, 0x00000911, 0x00000001); + nv_icmd(priv, 0x00000912, 0x00000001); + nv_icmd(priv, 0x00000913, 0x00000001); + nv_icmd(priv, 0x00000914, 0x00000001); + nv_icmd(priv, 0x00000915, 0x00000001); + nv_icmd(priv, 0x00000916, 0x00000001); + nv_icmd(priv, 0x00000917, 0x00000001); + nv_icmd(priv, 0x00000918, 0x00000001); + nv_icmd(priv, 0x00000919, 0x00000001); + nv_icmd(priv, 0x0000091a, 0x00000001); + nv_icmd(priv, 0x0000091b, 0x00000001); + nv_icmd(priv, 0x0000091c, 0x00000001); + nv_icmd(priv, 0x0000091d, 0x00000001); + nv_icmd(priv, 0x0000091e, 0x00000001); + nv_icmd(priv, 0x0000091f, 0x00000001); + nv_icmd(priv, 0x00000920, 0x00000002); + nv_icmd(priv, 0x00000921, 0x00000002); + nv_icmd(priv, 0x00000922, 0x00000002); + nv_icmd(priv, 0x00000923, 0x00000002); + nv_icmd(priv, 0x00000924, 0x00000002); + nv_icmd(priv, 0x00000925, 0x00000002); + nv_icmd(priv, 0x00000926, 0x00000002); + nv_icmd(priv, 0x00000927, 0x00000002); + nv_icmd(priv, 0x00000928, 0x00000001); + nv_icmd(priv, 0x00000929, 0x00000001); + nv_icmd(priv, 0x0000092a, 0x00000001); + nv_icmd(priv, 0x0000092b, 0x00000001); + nv_icmd(priv, 0x0000092c, 0x00000001); + nv_icmd(priv, 0x0000092d, 0x00000001); + nv_icmd(priv, 0x0000092e, 0x00000001); + nv_icmd(priv, 0x0000092f, 0x00000001); + nv_icmd(priv, 0x00000648, 0x00000001); + nv_icmd(priv, 0x00000649, 0x00000001); + nv_icmd(priv, 0x0000064a, 0x00000001); + nv_icmd(priv, 0x0000064b, 0x00000001); + nv_icmd(priv, 0x0000064c, 0x00000001); + nv_icmd(priv, 0x0000064d, 0x00000001); + nv_icmd(priv, 0x0000064e, 0x00000001); + nv_icmd(priv, 0x0000064f, 0x00000001); + nv_icmd(priv, 0x00000650, 0x00000001); + nv_icmd(priv, 0x00000658, 0x0000000f); + nv_icmd(priv, 0x000007ff, 0x0000000a); + nv_icmd(priv, 0x0000066a, 0x40000000); + nv_icmd(priv, 0x0000066b, 0x10000000); + nv_icmd(priv, 0x0000066c, 0xffff0000); + nv_icmd(priv, 0x0000066d, 0xffff0000); + nv_icmd(priv, 0x000007af, 0x00000008); + nv_icmd(priv, 0x000007b0, 0x00000008); + nv_icmd(priv, 0x000007f6, 0x00000001); + nv_icmd(priv, 0x000006b2, 0x00000055); + nv_icmd(priv, 0x000007ad, 0x00000003); + nv_icmd(priv, 0x00000937, 0x00000001); + nv_icmd(priv, 0x00000971, 0x00000008); + nv_icmd(priv, 0x00000972, 0x00000040); + nv_icmd(priv, 0x00000973, 0x0000012c); + nv_icmd(priv, 0x0000097c, 0x00000040); + nv_icmd(priv, 0x00000979, 0x00000003); + nv_icmd(priv, 0x00000975, 0x00000020); + nv_icmd(priv, 0x00000976, 0x00000001); + nv_icmd(priv, 0x00000977, 0x00000020); + nv_icmd(priv, 0x00000978, 0x00000001); + nv_icmd(priv, 0x00000957, 0x00000003); + nv_icmd(priv, 0x0000095e, 0x20164010); + nv_icmd(priv, 0x0000095f, 0x00000020); if (dev_priv->chipset == 0xd9) - nv_icmd(dev, 0x0000097d, 0x00000020); - nv_icmd(dev, 0x00000683, 0x00000006); - nv_icmd(dev, 0x00000685, 0x003fffff); - nv_icmd(dev, 0x00000687, 0x00000c48); - nv_icmd(dev, 0x000006a0, 0x00000005); - nv_icmd(dev, 0x00000840, 0x00300008); - nv_icmd(dev, 0x00000841, 0x04000080); - nv_icmd(dev, 0x00000842, 0x00300008); - nv_icmd(dev, 0x00000843, 0x04000080); - nv_icmd(dev, 0x00000818, 0x00000000); - nv_icmd(dev, 0x00000819, 0x00000000); - nv_icmd(dev, 0x0000081a, 0x00000000); - nv_icmd(dev, 0x0000081b, 0x00000000); - nv_icmd(dev, 0x0000081c, 0x00000000); - nv_icmd(dev, 0x0000081d, 0x00000000); - nv_icmd(dev, 0x0000081e, 0x00000000); - nv_icmd(dev, 0x0000081f, 0x00000000); - nv_icmd(dev, 0x00000848, 0x00000000); - nv_icmd(dev, 0x00000849, 0x00000000); - nv_icmd(dev, 0x0000084a, 0x00000000); - nv_icmd(dev, 0x0000084b, 0x00000000); - nv_icmd(dev, 0x0000084c, 0x00000000); - nv_icmd(dev, 0x0000084d, 0x00000000); - nv_icmd(dev, 0x0000084e, 0x00000000); - nv_icmd(dev, 0x0000084f, 0x00000000); - nv_icmd(dev, 0x00000850, 0x00000000); - nv_icmd(dev, 0x00000851, 0x00000000); - nv_icmd(dev, 0x00000852, 0x00000000); - nv_icmd(dev, 0x00000853, 0x00000000); - nv_icmd(dev, 0x00000854, 0x00000000); - nv_icmd(dev, 0x00000855, 0x00000000); - nv_icmd(dev, 0x00000856, 0x00000000); - nv_icmd(dev, 0x00000857, 0x00000000); - nv_icmd(dev, 0x00000738, 0x00000000); - nv_icmd(dev, 0x000006aa, 0x00000001); - nv_icmd(dev, 0x000006ab, 0x00000002); - nv_icmd(dev, 0x000006ac, 0x00000080); - nv_icmd(dev, 0x000006ad, 0x00000100); - nv_icmd(dev, 0x000006ae, 0x00000100); - nv_icmd(dev, 0x000006b1, 0x00000011); - nv_icmd(dev, 0x000006bb, 0x000000cf); - nv_icmd(dev, 0x000006ce, 0x2a712488); - nv_icmd(dev, 0x00000739, 0x4085c000); - nv_icmd(dev, 0x0000073a, 0x00000080); - nv_icmd(dev, 0x00000786, 0x80000100); - nv_icmd(dev, 0x0000073c, 0x00010100); - nv_icmd(dev, 0x0000073d, 0x02800000); - nv_icmd(dev, 0x00000787, 0x000000cf); - nv_icmd(dev, 0x0000078c, 0x00000008); - nv_icmd(dev, 0x00000792, 0x00000001); - nv_icmd(dev, 0x00000794, 0x00000001); - nv_icmd(dev, 0x00000795, 0x00000001); - nv_icmd(dev, 0x00000796, 0x00000001); - nv_icmd(dev, 0x00000797, 0x000000cf); - nv_icmd(dev, 0x00000836, 0x00000001); - nv_icmd(dev, 0x0000079a, 0x00000002); - nv_icmd(dev, 0x00000833, 0x04444480); - nv_icmd(dev, 0x000007a1, 0x00000001); - nv_icmd(dev, 0x000007a3, 0x00000001); - nv_icmd(dev, 0x000007a4, 0x00000001); - nv_icmd(dev, 0x000007a5, 0x00000001); - nv_icmd(dev, 0x00000831, 0x00000004); - nv_icmd(dev, 0x0000080c, 0x00000002); - nv_icmd(dev, 0x0000080d, 0x00000100); - nv_icmd(dev, 0x0000080e, 0x00000100); - nv_icmd(dev, 0x0000080f, 0x00000001); - nv_icmd(dev, 0x00000823, 0x00000002); - nv_icmd(dev, 0x00000824, 0x00000100); - nv_icmd(dev, 0x00000825, 0x00000100); - nv_icmd(dev, 0x00000826, 0x00000001); - nv_icmd(dev, 0x0000095d, 0x00000001); - nv_icmd(dev, 0x0000082b, 0x00000004); - nv_icmd(dev, 0x00000942, 0x00010001); - nv_icmd(dev, 0x00000943, 0x00000001); - nv_icmd(dev, 0x00000944, 0x00000022); - nv_icmd(dev, 0x000007c5, 0x00010001); - nv_icmd(dev, 0x00000834, 0x00000001); - nv_icmd(dev, 0x000007c7, 0x00000001); - nv_icmd(dev, 0x0000c1b0, 0x0000000f); - nv_icmd(dev, 0x0000c1b1, 0x0000000f); - nv_icmd(dev, 0x0000c1b2, 0x0000000f); - nv_icmd(dev, 0x0000c1b3, 0x0000000f); - nv_icmd(dev, 0x0000c1b4, 0x0000000f); - nv_icmd(dev, 0x0000c1b5, 0x0000000f); - nv_icmd(dev, 0x0000c1b6, 0x0000000f); - nv_icmd(dev, 0x0000c1b7, 0x0000000f); - nv_icmd(dev, 0x0000c1b8, 0x0fac6881); - nv_icmd(dev, 0x0000c1b9, 0x00fac688); - nv_icmd(dev, 0x0001e100, 0x00000001); - nv_icmd(dev, 0x00001000, 0x00000002); - nv_icmd(dev, 0x000006aa, 0x00000001); - nv_icmd(dev, 0x000006ad, 0x00000100); - nv_icmd(dev, 0x000006ae, 0x00000100); - nv_icmd(dev, 0x000006b1, 0x00000011); - nv_icmd(dev, 0x0000078c, 0x00000008); - nv_icmd(dev, 0x00000792, 0x00000001); - nv_icmd(dev, 0x00000794, 0x00000001); - nv_icmd(dev, 0x00000795, 0x00000001); - nv_icmd(dev, 0x00000796, 0x00000001); - nv_icmd(dev, 0x00000797, 0x000000cf); - nv_icmd(dev, 0x0000079a, 0x00000002); - nv_icmd(dev, 0x00000833, 0x04444480); - nv_icmd(dev, 0x000007a1, 0x00000001); - nv_icmd(dev, 0x000007a3, 0x00000001); - nv_icmd(dev, 0x000007a4, 0x00000001); - nv_icmd(dev, 0x000007a5, 0x00000001); - nv_icmd(dev, 0x00000831, 0x00000004); - nv_icmd(dev, 0x0001e100, 0x00000001); - nv_icmd(dev, 0x00001000, 0x00000014); - nv_icmd(dev, 0x00000351, 0x00000100); - nv_icmd(dev, 0x00000957, 0x00000003); - nv_icmd(dev, 0x0000095d, 0x00000001); - nv_icmd(dev, 0x0000082b, 0x00000004); - nv_icmd(dev, 0x00000942, 0x00010001); - nv_icmd(dev, 0x00000943, 0x00000001); - nv_icmd(dev, 0x000007c5, 0x00010001); - nv_icmd(dev, 0x00000834, 0x00000001); - nv_icmd(dev, 0x000007c7, 0x00000001); - nv_icmd(dev, 0x0001e100, 0x00000001); - nv_icmd(dev, 0x00001000, 0x00000001); - nv_icmd(dev, 0x0000080c, 0x00000002); - nv_icmd(dev, 0x0000080d, 0x00000100); - nv_icmd(dev, 0x0000080e, 0x00000100); - nv_icmd(dev, 0x0000080f, 0x00000001); - nv_icmd(dev, 0x00000823, 0x00000002); - nv_icmd(dev, 0x00000824, 0x00000100); - nv_icmd(dev, 0x00000825, 0x00000100); - nv_icmd(dev, 0x00000826, 0x00000001); - nv_icmd(dev, 0x0001e100, 0x00000001); - nv_wr32(dev, 0x400208, 0x00000000); - nv_wr32(dev, 0x404154, 0x00000400); + nv_icmd(priv, 0x0000097d, 0x00000020); + nv_icmd(priv, 0x00000683, 0x00000006); + nv_icmd(priv, 0x00000685, 0x003fffff); + nv_icmd(priv, 0x00000687, 0x00000c48); + nv_icmd(priv, 0x000006a0, 0x00000005); + nv_icmd(priv, 0x00000840, 0x00300008); + nv_icmd(priv, 0x00000841, 0x04000080); + nv_icmd(priv, 0x00000842, 0x00300008); + nv_icmd(priv, 0x00000843, 0x04000080); + nv_icmd(priv, 0x00000818, 0x00000000); + nv_icmd(priv, 0x00000819, 0x00000000); + nv_icmd(priv, 0x0000081a, 0x00000000); + nv_icmd(priv, 0x0000081b, 0x00000000); + nv_icmd(priv, 0x0000081c, 0x00000000); + nv_icmd(priv, 0x0000081d, 0x00000000); + nv_icmd(priv, 0x0000081e, 0x00000000); + nv_icmd(priv, 0x0000081f, 0x00000000); + nv_icmd(priv, 0x00000848, 0x00000000); + nv_icmd(priv, 0x00000849, 0x00000000); + nv_icmd(priv, 0x0000084a, 0x00000000); + nv_icmd(priv, 0x0000084b, 0x00000000); + nv_icmd(priv, 0x0000084c, 0x00000000); + nv_icmd(priv, 0x0000084d, 0x00000000); + nv_icmd(priv, 0x0000084e, 0x00000000); + nv_icmd(priv, 0x0000084f, 0x00000000); + nv_icmd(priv, 0x00000850, 0x00000000); + nv_icmd(priv, 0x00000851, 0x00000000); + nv_icmd(priv, 0x00000852, 0x00000000); + nv_icmd(priv, 0x00000853, 0x00000000); + nv_icmd(priv, 0x00000854, 0x00000000); + nv_icmd(priv, 0x00000855, 0x00000000); + nv_icmd(priv, 0x00000856, 0x00000000); + nv_icmd(priv, 0x00000857, 0x00000000); + nv_icmd(priv, 0x00000738, 0x00000000); + nv_icmd(priv, 0x000006aa, 0x00000001); + nv_icmd(priv, 0x000006ab, 0x00000002); + nv_icmd(priv, 0x000006ac, 0x00000080); + nv_icmd(priv, 0x000006ad, 0x00000100); + nv_icmd(priv, 0x000006ae, 0x00000100); + nv_icmd(priv, 0x000006b1, 0x00000011); + nv_icmd(priv, 0x000006bb, 0x000000cf); + nv_icmd(priv, 0x000006ce, 0x2a712488); + nv_icmd(priv, 0x00000739, 0x4085c000); + nv_icmd(priv, 0x0000073a, 0x00000080); + nv_icmd(priv, 0x00000786, 0x80000100); + nv_icmd(priv, 0x0000073c, 0x00010100); + nv_icmd(priv, 0x0000073d, 0x02800000); + nv_icmd(priv, 0x00000787, 0x000000cf); + nv_icmd(priv, 0x0000078c, 0x00000008); + nv_icmd(priv, 0x00000792, 0x00000001); + nv_icmd(priv, 0x00000794, 0x00000001); + nv_icmd(priv, 0x00000795, 0x00000001); + nv_icmd(priv, 0x00000796, 0x00000001); + nv_icmd(priv, 0x00000797, 0x000000cf); + nv_icmd(priv, 0x00000836, 0x00000001); + nv_icmd(priv, 0x0000079a, 0x00000002); + nv_icmd(priv, 0x00000833, 0x04444480); + nv_icmd(priv, 0x000007a1, 0x00000001); + nv_icmd(priv, 0x000007a3, 0x00000001); + nv_icmd(priv, 0x000007a4, 0x00000001); + nv_icmd(priv, 0x000007a5, 0x00000001); + nv_icmd(priv, 0x00000831, 0x00000004); + nv_icmd(priv, 0x0000080c, 0x00000002); + nv_icmd(priv, 0x0000080d, 0x00000100); + nv_icmd(priv, 0x0000080e, 0x00000100); + nv_icmd(priv, 0x0000080f, 0x00000001); + nv_icmd(priv, 0x00000823, 0x00000002); + nv_icmd(priv, 0x00000824, 0x00000100); + nv_icmd(priv, 0x00000825, 0x00000100); + nv_icmd(priv, 0x00000826, 0x00000001); + nv_icmd(priv, 0x0000095d, 0x00000001); + nv_icmd(priv, 0x0000082b, 0x00000004); + nv_icmd(priv, 0x00000942, 0x00010001); + nv_icmd(priv, 0x00000943, 0x00000001); + nv_icmd(priv, 0x00000944, 0x00000022); + nv_icmd(priv, 0x000007c5, 0x00010001); + nv_icmd(priv, 0x00000834, 0x00000001); + nv_icmd(priv, 0x000007c7, 0x00000001); + nv_icmd(priv, 0x0000c1b0, 0x0000000f); + nv_icmd(priv, 0x0000c1b1, 0x0000000f); + nv_icmd(priv, 0x0000c1b2, 0x0000000f); + nv_icmd(priv, 0x0000c1b3, 0x0000000f); + nv_icmd(priv, 0x0000c1b4, 0x0000000f); + nv_icmd(priv, 0x0000c1b5, 0x0000000f); + nv_icmd(priv, 0x0000c1b6, 0x0000000f); + nv_icmd(priv, 0x0000c1b7, 0x0000000f); + nv_icmd(priv, 0x0000c1b8, 0x0fac6881); + nv_icmd(priv, 0x0000c1b9, 0x00fac688); + nv_icmd(priv, 0x0001e100, 0x00000001); + nv_icmd(priv, 0x00001000, 0x00000002); + nv_icmd(priv, 0x000006aa, 0x00000001); + nv_icmd(priv, 0x000006ad, 0x00000100); + nv_icmd(priv, 0x000006ae, 0x00000100); + nv_icmd(priv, 0x000006b1, 0x00000011); + nv_icmd(priv, 0x0000078c, 0x00000008); + nv_icmd(priv, 0x00000792, 0x00000001); + nv_icmd(priv, 0x00000794, 0x00000001); + nv_icmd(priv, 0x00000795, 0x00000001); + nv_icmd(priv, 0x00000796, 0x00000001); + nv_icmd(priv, 0x00000797, 0x000000cf); + nv_icmd(priv, 0x0000079a, 0x00000002); + nv_icmd(priv, 0x00000833, 0x04444480); + nv_icmd(priv, 0x000007a1, 0x00000001); + nv_icmd(priv, 0x000007a3, 0x00000001); + nv_icmd(priv, 0x000007a4, 0x00000001); + nv_icmd(priv, 0x000007a5, 0x00000001); + nv_icmd(priv, 0x00000831, 0x00000004); + nv_icmd(priv, 0x0001e100, 0x00000001); + nv_icmd(priv, 0x00001000, 0x00000014); + nv_icmd(priv, 0x00000351, 0x00000100); + nv_icmd(priv, 0x00000957, 0x00000003); + nv_icmd(priv, 0x0000095d, 0x00000001); + nv_icmd(priv, 0x0000082b, 0x00000004); + nv_icmd(priv, 0x00000942, 0x00010001); + nv_icmd(priv, 0x00000943, 0x00000001); + nv_icmd(priv, 0x000007c5, 0x00010001); + nv_icmd(priv, 0x00000834, 0x00000001); + nv_icmd(priv, 0x000007c7, 0x00000001); + nv_icmd(priv, 0x0001e100, 0x00000001); + nv_icmd(priv, 0x00001000, 0x00000001); + nv_icmd(priv, 0x0000080c, 0x00000002); + nv_icmd(priv, 0x0000080d, 0x00000100); + nv_icmd(priv, 0x0000080e, 0x00000100); + nv_icmd(priv, 0x0000080f, 0x00000001); + nv_icmd(priv, 0x00000823, 0x00000002); + nv_icmd(priv, 0x00000824, 0x00000100); + nv_icmd(priv, 0x00000825, 0x00000100); + nv_icmd(priv, 0x00000826, 0x00000001); + nv_icmd(priv, 0x0001e100, 0x00000001); + nv_wr32(priv, 0x400208, 0x00000000); + nv_wr32(priv, 0x404154, 0x00000400); - nvc0_grctx_generate_9097(dev); + nvc0_grctx_generate_9097(priv); if (fermi >= 0x9197) - nvc0_grctx_generate_9197(dev); + nvc0_grctx_generate_9197(priv); if (fermi >= 0x9297) - nvc0_grctx_generate_9297(dev); - nvc0_grctx_generate_902d(dev); - nvc0_grctx_generate_9039(dev); - nvc0_grctx_generate_90c0(dev); + nvc0_grctx_generate_9297(priv); + nvc0_grctx_generate_902d(priv); + nvc0_grctx_generate_9039(priv); + nvc0_grctx_generate_90c0(priv); - nv_wr32(dev, 0x000260, r000260); + nv_wr32(priv, 0x000260, r000260); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c index bd40bd9..f03c667 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -28,2676 +28,2676 @@ #include "nve0.h" static void -nv_icmd(struct drm_device *dev, u32 icmd, u32 data) +nv_icmd(struct drm_device *priv, u32 icmd, u32 data) { - nv_wr32(dev, 0x400204, data); - nv_wr32(dev, 0x400200, icmd); - while (nv_rd32(dev, 0x400700) & 0x00000002) {} + nv_wr32(priv, 0x400204, data); + nv_wr32(priv, 0x400200, icmd); + while (nv_rd32(priv, 0x400700) & 0x00000002) {} } static void -nve0_grctx_generate_icmd(struct drm_device *dev) +nve0_grctx_generate_icmd(struct drm_device *priv) { - nv_wr32(dev, 0x400208, 0x80000000); - nv_icmd(dev, 0x001000, 0x00000004); - nv_icmd(dev, 0x000039, 0x00000000); - nv_icmd(dev, 0x00003a, 0x00000000); - nv_icmd(dev, 0x00003b, 0x00000000); - nv_icmd(dev, 0x0000a9, 0x0000ffff); - nv_icmd(dev, 0x000038, 0x0fac6881); - nv_icmd(dev, 0x00003d, 0x00000001); - nv_icmd(dev, 0x0000e8, 0x00000400); - nv_icmd(dev, 0x0000e9, 0x00000400); - nv_icmd(dev, 0x0000ea, 0x00000400); - nv_icmd(dev, 0x0000eb, 0x00000400); - nv_icmd(dev, 0x0000ec, 0x00000400); - nv_icmd(dev, 0x0000ed, 0x00000400); - nv_icmd(dev, 0x0000ee, 0x00000400); - nv_icmd(dev, 0x0000ef, 0x00000400); - nv_icmd(dev, 0x000078, 0x00000300); - nv_icmd(dev, 0x000079, 0x00000300); - nv_icmd(dev, 0x00007a, 0x00000300); - nv_icmd(dev, 0x00007b, 0x00000300); - nv_icmd(dev, 0x00007c, 0x00000300); - nv_icmd(dev, 0x00007d, 0x00000300); - nv_icmd(dev, 0x00007e, 0x00000300); - nv_icmd(dev, 0x00007f, 0x00000300); - nv_icmd(dev, 0x000050, 0x00000011); - nv_icmd(dev, 0x000058, 0x00000008); - nv_icmd(dev, 0x000059, 0x00000008); - nv_icmd(dev, 0x00005a, 0x00000008); - nv_icmd(dev, 0x00005b, 0x00000008); - nv_icmd(dev, 0x00005c, 0x00000008); - nv_icmd(dev, 0x00005d, 0x00000008); - nv_icmd(dev, 0x00005e, 0x00000008); - nv_icmd(dev, 0x00005f, 0x00000008); - nv_icmd(dev, 0x000208, 0x00000001); - nv_icmd(dev, 0x000209, 0x00000001); - nv_icmd(dev, 0x00020a, 0x00000001); - nv_icmd(dev, 0x00020b, 0x00000001); - nv_icmd(dev, 0x00020c, 0x00000001); - nv_icmd(dev, 0x00020d, 0x00000001); - nv_icmd(dev, 0x00020e, 0x00000001); - nv_icmd(dev, 0x00020f, 0x00000001); - nv_icmd(dev, 0x000081, 0x00000001); - nv_icmd(dev, 0x000085, 0x00000004); - nv_icmd(dev, 0x000088, 0x00000400); - nv_icmd(dev, 0x000090, 0x00000300); - nv_icmd(dev, 0x000098, 0x00001001); - nv_icmd(dev, 0x0000e3, 0x00000001); - nv_icmd(dev, 0x0000da, 0x00000001); - nv_icmd(dev, 0x0000f8, 0x00000003); - nv_icmd(dev, 0x0000fa, 0x00000001); - nv_icmd(dev, 0x00009f, 0x0000ffff); - nv_icmd(dev, 0x0000a0, 0x0000ffff); - nv_icmd(dev, 0x0000a1, 0x0000ffff); - nv_icmd(dev, 0x0000a2, 0x0000ffff); - nv_icmd(dev, 0x0000b1, 0x00000001); - nv_icmd(dev, 0x0000ad, 0x0000013e); - nv_icmd(dev, 0x0000e1, 0x00000010); - nv_icmd(dev, 0x000290, 0x00000000); - nv_icmd(dev, 0x000291, 0x00000000); - nv_icmd(dev, 0x000292, 0x00000000); - nv_icmd(dev, 0x000293, 0x00000000); - nv_icmd(dev, 0x000294, 0x00000000); - nv_icmd(dev, 0x000295, 0x00000000); - nv_icmd(dev, 0x000296, 0x00000000); - nv_icmd(dev, 0x000297, 0x00000000); - nv_icmd(dev, 0x000298, 0x00000000); - nv_icmd(dev, 0x000299, 0x00000000); - nv_icmd(dev, 0x00029a, 0x00000000); - nv_icmd(dev, 0x00029b, 0x00000000); - nv_icmd(dev, 0x00029c, 0x00000000); - nv_icmd(dev, 0x00029d, 0x00000000); - nv_icmd(dev, 0x00029e, 0x00000000); - nv_icmd(dev, 0x00029f, 0x00000000); - nv_icmd(dev, 0x0003b0, 0x00000000); - nv_icmd(dev, 0x0003b1, 0x00000000); - nv_icmd(dev, 0x0003b2, 0x00000000); - nv_icmd(dev, 0x0003b3, 0x00000000); - nv_icmd(dev, 0x0003b4, 0x00000000); - nv_icmd(dev, 0x0003b5, 0x00000000); - nv_icmd(dev, 0x0003b6, 0x00000000); - nv_icmd(dev, 0x0003b7, 0x00000000); - nv_icmd(dev, 0x0003b8, 0x00000000); - nv_icmd(dev, 0x0003b9, 0x00000000); - nv_icmd(dev, 0x0003ba, 0x00000000); - nv_icmd(dev, 0x0003bb, 0x00000000); - nv_icmd(dev, 0x0003bc, 0x00000000); - nv_icmd(dev, 0x0003bd, 0x00000000); - nv_icmd(dev, 0x0003be, 0x00000000); - nv_icmd(dev, 0x0003bf, 0x00000000); - nv_icmd(dev, 0x0002a0, 0x00000000); - nv_icmd(dev, 0x0002a1, 0x00000000); - nv_icmd(dev, 0x0002a2, 0x00000000); - nv_icmd(dev, 0x0002a3, 0x00000000); - nv_icmd(dev, 0x0002a4, 0x00000000); - nv_icmd(dev, 0x0002a5, 0x00000000); - nv_icmd(dev, 0x0002a6, 0x00000000); - nv_icmd(dev, 0x0002a7, 0x00000000); - nv_icmd(dev, 0x0002a8, 0x00000000); - nv_icmd(dev, 0x0002a9, 0x00000000); - nv_icmd(dev, 0x0002aa, 0x00000000); - nv_icmd(dev, 0x0002ab, 0x00000000); - nv_icmd(dev, 0x0002ac, 0x00000000); - nv_icmd(dev, 0x0002ad, 0x00000000); - nv_icmd(dev, 0x0002ae, 0x00000000); - nv_icmd(dev, 0x0002af, 0x00000000); - nv_icmd(dev, 0x000420, 0x00000000); - nv_icmd(dev, 0x000421, 0x00000000); - nv_icmd(dev, 0x000422, 0x00000000); - nv_icmd(dev, 0x000423, 0x00000000); - nv_icmd(dev, 0x000424, 0x00000000); - nv_icmd(dev, 0x000425, 0x00000000); - nv_icmd(dev, 0x000426, 0x00000000); - nv_icmd(dev, 0x000427, 0x00000000); - nv_icmd(dev, 0x000428, 0x00000000); - nv_icmd(dev, 0x000429, 0x00000000); - nv_icmd(dev, 0x00042a, 0x00000000); - nv_icmd(dev, 0x00042b, 0x00000000); - nv_icmd(dev, 0x00042c, 0x00000000); - nv_icmd(dev, 0x00042d, 0x00000000); - nv_icmd(dev, 0x00042e, 0x00000000); - nv_icmd(dev, 0x00042f, 0x00000000); - nv_icmd(dev, 0x0002b0, 0x00000000); - nv_icmd(dev, 0x0002b1, 0x00000000); - nv_icmd(dev, 0x0002b2, 0x00000000); - nv_icmd(dev, 0x0002b3, 0x00000000); - nv_icmd(dev, 0x0002b4, 0x00000000); - nv_icmd(dev, 0x0002b5, 0x00000000); - nv_icmd(dev, 0x0002b6, 0x00000000); - nv_icmd(dev, 0x0002b7, 0x00000000); - nv_icmd(dev, 0x0002b8, 0x00000000); - nv_icmd(dev, 0x0002b9, 0x00000000); - nv_icmd(dev, 0x0002ba, 0x00000000); - nv_icmd(dev, 0x0002bb, 0x00000000); - nv_icmd(dev, 0x0002bc, 0x00000000); - nv_icmd(dev, 0x0002bd, 0x00000000); - nv_icmd(dev, 0x0002be, 0x00000000); - nv_icmd(dev, 0x0002bf, 0x00000000); - nv_icmd(dev, 0x000430, 0x00000000); - nv_icmd(dev, 0x000431, 0x00000000); - nv_icmd(dev, 0x000432, 0x00000000); - nv_icmd(dev, 0x000433, 0x00000000); - nv_icmd(dev, 0x000434, 0x00000000); - nv_icmd(dev, 0x000435, 0x00000000); - nv_icmd(dev, 0x000436, 0x00000000); - nv_icmd(dev, 0x000437, 0x00000000); - nv_icmd(dev, 0x000438, 0x00000000); - nv_icmd(dev, 0x000439, 0x00000000); - nv_icmd(dev, 0x00043a, 0x00000000); - nv_icmd(dev, 0x00043b, 0x00000000); - nv_icmd(dev, 0x00043c, 0x00000000); - nv_icmd(dev, 0x00043d, 0x00000000); - nv_icmd(dev, 0x00043e, 0x00000000); - nv_icmd(dev, 0x00043f, 0x00000000); - nv_icmd(dev, 0x0002c0, 0x00000000); - nv_icmd(dev, 0x0002c1, 0x00000000); - nv_icmd(dev, 0x0002c2, 0x00000000); - nv_icmd(dev, 0x0002c3, 0x00000000); - nv_icmd(dev, 0x0002c4, 0x00000000); - nv_icmd(dev, 0x0002c5, 0x00000000); - nv_icmd(dev, 0x0002c6, 0x00000000); - nv_icmd(dev, 0x0002c7, 0x00000000); - nv_icmd(dev, 0x0002c8, 0x00000000); - nv_icmd(dev, 0x0002c9, 0x00000000); - nv_icmd(dev, 0x0002ca, 0x00000000); - nv_icmd(dev, 0x0002cb, 0x00000000); - nv_icmd(dev, 0x0002cc, 0x00000000); - nv_icmd(dev, 0x0002cd, 0x00000000); - nv_icmd(dev, 0x0002ce, 0x00000000); - nv_icmd(dev, 0x0002cf, 0x00000000); - nv_icmd(dev, 0x0004d0, 0x00000000); - nv_icmd(dev, 0x0004d1, 0x00000000); - nv_icmd(dev, 0x0004d2, 0x00000000); - nv_icmd(dev, 0x0004d3, 0x00000000); - nv_icmd(dev, 0x0004d4, 0x00000000); - nv_icmd(dev, 0x0004d5, 0x00000000); - nv_icmd(dev, 0x0004d6, 0x00000000); - nv_icmd(dev, 0x0004d7, 0x00000000); - nv_icmd(dev, 0x0004d8, 0x00000000); - nv_icmd(dev, 0x0004d9, 0x00000000); - nv_icmd(dev, 0x0004da, 0x00000000); - nv_icmd(dev, 0x0004db, 0x00000000); - nv_icmd(dev, 0x0004dc, 0x00000000); - nv_icmd(dev, 0x0004dd, 0x00000000); - nv_icmd(dev, 0x0004de, 0x00000000); - nv_icmd(dev, 0x0004df, 0x00000000); - nv_icmd(dev, 0x000720, 0x00000000); - nv_icmd(dev, 0x000721, 0x00000000); - nv_icmd(dev, 0x000722, 0x00000000); - nv_icmd(dev, 0x000723, 0x00000000); - nv_icmd(dev, 0x000724, 0x00000000); - nv_icmd(dev, 0x000725, 0x00000000); - nv_icmd(dev, 0x000726, 0x00000000); - nv_icmd(dev, 0x000727, 0x00000000); - nv_icmd(dev, 0x000728, 0x00000000); - nv_icmd(dev, 0x000729, 0x00000000); - nv_icmd(dev, 0x00072a, 0x00000000); - nv_icmd(dev, 0x00072b, 0x00000000); - nv_icmd(dev, 0x00072c, 0x00000000); - nv_icmd(dev, 0x00072d, 0x00000000); - nv_icmd(dev, 0x00072e, 0x00000000); - nv_icmd(dev, 0x00072f, 0x00000000); - nv_icmd(dev, 0x0008c0, 0x00000000); - nv_icmd(dev, 0x0008c1, 0x00000000); - nv_icmd(dev, 0x0008c2, 0x00000000); - nv_icmd(dev, 0x0008c3, 0x00000000); - nv_icmd(dev, 0x0008c4, 0x00000000); - nv_icmd(dev, 0x0008c5, 0x00000000); - nv_icmd(dev, 0x0008c6, 0x00000000); - nv_icmd(dev, 0x0008c7, 0x00000000); - nv_icmd(dev, 0x0008c8, 0x00000000); - nv_icmd(dev, 0x0008c9, 0x00000000); - nv_icmd(dev, 0x0008ca, 0x00000000); - nv_icmd(dev, 0x0008cb, 0x00000000); - nv_icmd(dev, 0x0008cc, 0x00000000); - nv_icmd(dev, 0x0008cd, 0x00000000); - nv_icmd(dev, 0x0008ce, 0x00000000); - nv_icmd(dev, 0x0008cf, 0x00000000); - nv_icmd(dev, 0x000890, 0x00000000); - nv_icmd(dev, 0x000891, 0x00000000); - nv_icmd(dev, 0x000892, 0x00000000); - nv_icmd(dev, 0x000893, 0x00000000); - nv_icmd(dev, 0x000894, 0x00000000); - nv_icmd(dev, 0x000895, 0x00000000); - nv_icmd(dev, 0x000896, 0x00000000); - nv_icmd(dev, 0x000897, 0x00000000); - nv_icmd(dev, 0x000898, 0x00000000); - nv_icmd(dev, 0x000899, 0x00000000); - nv_icmd(dev, 0x00089a, 0x00000000); - nv_icmd(dev, 0x00089b, 0x00000000); - nv_icmd(dev, 0x00089c, 0x00000000); - nv_icmd(dev, 0x00089d, 0x00000000); - nv_icmd(dev, 0x00089e, 0x00000000); - nv_icmd(dev, 0x00089f, 0x00000000); - nv_icmd(dev, 0x0008e0, 0x00000000); - nv_icmd(dev, 0x0008e1, 0x00000000); - nv_icmd(dev, 0x0008e2, 0x00000000); - nv_icmd(dev, 0x0008e3, 0x00000000); - nv_icmd(dev, 0x0008e4, 0x00000000); - nv_icmd(dev, 0x0008e5, 0x00000000); - nv_icmd(dev, 0x0008e6, 0x00000000); - nv_icmd(dev, 0x0008e7, 0x00000000); - nv_icmd(dev, 0x0008e8, 0x00000000); - nv_icmd(dev, 0x0008e9, 0x00000000); - nv_icmd(dev, 0x0008ea, 0x00000000); - nv_icmd(dev, 0x0008eb, 0x00000000); - nv_icmd(dev, 0x0008ec, 0x00000000); - nv_icmd(dev, 0x0008ed, 0x00000000); - nv_icmd(dev, 0x0008ee, 0x00000000); - nv_icmd(dev, 0x0008ef, 0x00000000); - nv_icmd(dev, 0x0008a0, 0x00000000); - nv_icmd(dev, 0x0008a1, 0x00000000); - nv_icmd(dev, 0x0008a2, 0x00000000); - nv_icmd(dev, 0x0008a3, 0x00000000); - nv_icmd(dev, 0x0008a4, 0x00000000); - nv_icmd(dev, 0x0008a5, 0x00000000); - nv_icmd(dev, 0x0008a6, 0x00000000); - nv_icmd(dev, 0x0008a7, 0x00000000); - nv_icmd(dev, 0x0008a8, 0x00000000); - nv_icmd(dev, 0x0008a9, 0x00000000); - nv_icmd(dev, 0x0008aa, 0x00000000); - nv_icmd(dev, 0x0008ab, 0x00000000); - nv_icmd(dev, 0x0008ac, 0x00000000); - nv_icmd(dev, 0x0008ad, 0x00000000); - nv_icmd(dev, 0x0008ae, 0x00000000); - nv_icmd(dev, 0x0008af, 0x00000000); - nv_icmd(dev, 0x0008f0, 0x00000000); - nv_icmd(dev, 0x0008f1, 0x00000000); - nv_icmd(dev, 0x0008f2, 0x00000000); - nv_icmd(dev, 0x0008f3, 0x00000000); - nv_icmd(dev, 0x0008f4, 0x00000000); - nv_icmd(dev, 0x0008f5, 0x00000000); - nv_icmd(dev, 0x0008f6, 0x00000000); - nv_icmd(dev, 0x0008f7, 0x00000000); - nv_icmd(dev, 0x0008f8, 0x00000000); - nv_icmd(dev, 0x0008f9, 0x00000000); - nv_icmd(dev, 0x0008fa, 0x00000000); - nv_icmd(dev, 0x0008fb, 0x00000000); - nv_icmd(dev, 0x0008fc, 0x00000000); - nv_icmd(dev, 0x0008fd, 0x00000000); - nv_icmd(dev, 0x0008fe, 0x00000000); - nv_icmd(dev, 0x0008ff, 0x00000000); - nv_icmd(dev, 0x00094c, 0x000000ff); - nv_icmd(dev, 0x00094d, 0xffffffff); - nv_icmd(dev, 0x00094e, 0x00000002); - nv_icmd(dev, 0x0002ec, 0x00000001); - nv_icmd(dev, 0x000303, 0x00000001); - nv_icmd(dev, 0x0002e6, 0x00000001); - nv_icmd(dev, 0x000466, 0x00000052); - nv_icmd(dev, 0x000301, 0x3f800000); - nv_icmd(dev, 0x000304, 0x30201000); - nv_icmd(dev, 0x000305, 0x70605040); - nv_icmd(dev, 0x000306, 0xb8a89888); - nv_icmd(dev, 0x000307, 0xf8e8d8c8); - nv_icmd(dev, 0x00030a, 0x00ffff00); - nv_icmd(dev, 0x00030b, 0x0000001a); - nv_icmd(dev, 0x00030c, 0x00000001); - nv_icmd(dev, 0x000318, 0x00000001); - nv_icmd(dev, 0x000340, 0x00000000); - nv_icmd(dev, 0x000375, 0x00000001); - nv_icmd(dev, 0x00037d, 0x00000006); - nv_icmd(dev, 0x0003a0, 0x00000002); - nv_icmd(dev, 0x0003aa, 0x00000001); - nv_icmd(dev, 0x0003a9, 0x00000001); - nv_icmd(dev, 0x000380, 0x00000001); - nv_icmd(dev, 0x000383, 0x00000011); - nv_icmd(dev, 0x000360, 0x00000040); - nv_icmd(dev, 0x000366, 0x00000000); - nv_icmd(dev, 0x000367, 0x00000000); - nv_icmd(dev, 0x000368, 0x00000fff); - nv_icmd(dev, 0x000370, 0x00000000); - nv_icmd(dev, 0x000371, 0x00000000); - nv_icmd(dev, 0x000372, 0x000fffff); - nv_icmd(dev, 0x00037a, 0x00000012); - nv_icmd(dev, 0x000619, 0x00000003); - nv_icmd(dev, 0x000811, 0x00000003); - nv_icmd(dev, 0x000812, 0x00000004); - nv_icmd(dev, 0x000813, 0x00000006); - nv_icmd(dev, 0x000814, 0x00000008); - nv_icmd(dev, 0x000815, 0x0000000b); - nv_icmd(dev, 0x000800, 0x00000001); - nv_icmd(dev, 0x000801, 0x00000001); - nv_icmd(dev, 0x000802, 0x00000001); - nv_icmd(dev, 0x000803, 0x00000001); - nv_icmd(dev, 0x000804, 0x00000001); - nv_icmd(dev, 0x000805, 0x00000001); - nv_icmd(dev, 0x000632, 0x00000001); - nv_icmd(dev, 0x000633, 0x00000002); - nv_icmd(dev, 0x000634, 0x00000003); - nv_icmd(dev, 0x000635, 0x00000004); - nv_icmd(dev, 0x000654, 0x3f800000); - nv_icmd(dev, 0x000657, 0x3f800000); - nv_icmd(dev, 0x000655, 0x3f800000); - nv_icmd(dev, 0x000656, 0x3f800000); - nv_icmd(dev, 0x0006cd, 0x3f800000); - nv_icmd(dev, 0x0007f5, 0x3f800000); - nv_icmd(dev, 0x0007dc, 0x39291909); - nv_icmd(dev, 0x0007dd, 0x79695949); - nv_icmd(dev, 0x0007de, 0xb9a99989); - nv_icmd(dev, 0x0007df, 0xf9e9d9c9); - nv_icmd(dev, 0x0007e8, 0x00003210); - nv_icmd(dev, 0x0007e9, 0x00007654); - nv_icmd(dev, 0x0007ea, 0x00000098); - nv_icmd(dev, 0x0007ec, 0x39291909); - nv_icmd(dev, 0x0007ed, 0x79695949); - nv_icmd(dev, 0x0007ee, 0xb9a99989); - nv_icmd(dev, 0x0007ef, 0xf9e9d9c9); - nv_icmd(dev, 0x0007f0, 0x00003210); - nv_icmd(dev, 0x0007f1, 0x00007654); - nv_icmd(dev, 0x0007f2, 0x00000098); - nv_icmd(dev, 0x0005a5, 0x00000001); - nv_icmd(dev, 0x000980, 0x00000000); - nv_icmd(dev, 0x000981, 0x00000000); - nv_icmd(dev, 0x000982, 0x00000000); - nv_icmd(dev, 0x000983, 0x00000000); - nv_icmd(dev, 0x000984, 0x00000000); - nv_icmd(dev, 0x000985, 0x00000000); - nv_icmd(dev, 0x000986, 0x00000000); - nv_icmd(dev, 0x000987, 0x00000000); - nv_icmd(dev, 0x000988, 0x00000000); - nv_icmd(dev, 0x000989, 0x00000000); - nv_icmd(dev, 0x00098a, 0x00000000); - nv_icmd(dev, 0x00098b, 0x00000000); - nv_icmd(dev, 0x00098c, 0x00000000); - nv_icmd(dev, 0x00098d, 0x00000000); - nv_icmd(dev, 0x00098e, 0x00000000); - nv_icmd(dev, 0x00098f, 0x00000000); - nv_icmd(dev, 0x000990, 0x00000000); - nv_icmd(dev, 0x000991, 0x00000000); - nv_icmd(dev, 0x000992, 0x00000000); - nv_icmd(dev, 0x000993, 0x00000000); - nv_icmd(dev, 0x000994, 0x00000000); - nv_icmd(dev, 0x000995, 0x00000000); - nv_icmd(dev, 0x000996, 0x00000000); - nv_icmd(dev, 0x000997, 0x00000000); - nv_icmd(dev, 0x000998, 0x00000000); - nv_icmd(dev, 0x000999, 0x00000000); - nv_icmd(dev, 0x00099a, 0x00000000); - nv_icmd(dev, 0x00099b, 0x00000000); - nv_icmd(dev, 0x00099c, 0x00000000); - nv_icmd(dev, 0x00099d, 0x00000000); - nv_icmd(dev, 0x00099e, 0x00000000); - nv_icmd(dev, 0x00099f, 0x00000000); - nv_icmd(dev, 0x0009a0, 0x00000000); - nv_icmd(dev, 0x0009a1, 0x00000000); - nv_icmd(dev, 0x0009a2, 0x00000000); - nv_icmd(dev, 0x0009a3, 0x00000000); - nv_icmd(dev, 0x0009a4, 0x00000000); - nv_icmd(dev, 0x0009a5, 0x00000000); - nv_icmd(dev, 0x0009a6, 0x00000000); - nv_icmd(dev, 0x0009a7, 0x00000000); - nv_icmd(dev, 0x0009a8, 0x00000000); - nv_icmd(dev, 0x0009a9, 0x00000000); - nv_icmd(dev, 0x0009aa, 0x00000000); - nv_icmd(dev, 0x0009ab, 0x00000000); - nv_icmd(dev, 0x0009ac, 0x00000000); - nv_icmd(dev, 0x0009ad, 0x00000000); - nv_icmd(dev, 0x0009ae, 0x00000000); - nv_icmd(dev, 0x0009af, 0x00000000); - nv_icmd(dev, 0x0009b0, 0x00000000); - nv_icmd(dev, 0x0009b1, 0x00000000); - nv_icmd(dev, 0x0009b2, 0x00000000); - nv_icmd(dev, 0x0009b3, 0x00000000); - nv_icmd(dev, 0x0009b4, 0x00000000); - nv_icmd(dev, 0x0009b5, 0x00000000); - nv_icmd(dev, 0x0009b6, 0x00000000); - nv_icmd(dev, 0x0009b7, 0x00000000); - nv_icmd(dev, 0x0009b8, 0x00000000); - nv_icmd(dev, 0x0009b9, 0x00000000); - nv_icmd(dev, 0x0009ba, 0x00000000); - nv_icmd(dev, 0x0009bb, 0x00000000); - nv_icmd(dev, 0x0009bc, 0x00000000); - nv_icmd(dev, 0x0009bd, 0x00000000); - nv_icmd(dev, 0x0009be, 0x00000000); - nv_icmd(dev, 0x0009bf, 0x00000000); - nv_icmd(dev, 0x0009c0, 0x00000000); - nv_icmd(dev, 0x0009c1, 0x00000000); - nv_icmd(dev, 0x0009c2, 0x00000000); - nv_icmd(dev, 0x0009c3, 0x00000000); - nv_icmd(dev, 0x0009c4, 0x00000000); - nv_icmd(dev, 0x0009c5, 0x00000000); - nv_icmd(dev, 0x0009c6, 0x00000000); - nv_icmd(dev, 0x0009c7, 0x00000000); - nv_icmd(dev, 0x0009c8, 0x00000000); - nv_icmd(dev, 0x0009c9, 0x00000000); - nv_icmd(dev, 0x0009ca, 0x00000000); - nv_icmd(dev, 0x0009cb, 0x00000000); - nv_icmd(dev, 0x0009cc, 0x00000000); - nv_icmd(dev, 0x0009cd, 0x00000000); - nv_icmd(dev, 0x0009ce, 0x00000000); - nv_icmd(dev, 0x0009cf, 0x00000000); - nv_icmd(dev, 0x0009d0, 0x00000000); - nv_icmd(dev, 0x0009d1, 0x00000000); - nv_icmd(dev, 0x0009d2, 0x00000000); - nv_icmd(dev, 0x0009d3, 0x00000000); - nv_icmd(dev, 0x0009d4, 0x00000000); - nv_icmd(dev, 0x0009d5, 0x00000000); - nv_icmd(dev, 0x0009d6, 0x00000000); - nv_icmd(dev, 0x0009d7, 0x00000000); - nv_icmd(dev, 0x0009d8, 0x00000000); - nv_icmd(dev, 0x0009d9, 0x00000000); - nv_icmd(dev, 0x0009da, 0x00000000); - nv_icmd(dev, 0x0009db, 0x00000000); - nv_icmd(dev, 0x0009dc, 0x00000000); - nv_icmd(dev, 0x0009dd, 0x00000000); - nv_icmd(dev, 0x0009de, 0x00000000); - nv_icmd(dev, 0x0009df, 0x00000000); - nv_icmd(dev, 0x0009e0, 0x00000000); - nv_icmd(dev, 0x0009e1, 0x00000000); - nv_icmd(dev, 0x0009e2, 0x00000000); - nv_icmd(dev, 0x0009e3, 0x00000000); - nv_icmd(dev, 0x0009e4, 0x00000000); - nv_icmd(dev, 0x0009e5, 0x00000000); - nv_icmd(dev, 0x0009e6, 0x00000000); - nv_icmd(dev, 0x0009e7, 0x00000000); - nv_icmd(dev, 0x0009e8, 0x00000000); - nv_icmd(dev, 0x0009e9, 0x00000000); - nv_icmd(dev, 0x0009ea, 0x00000000); - nv_icmd(dev, 0x0009eb, 0x00000000); - nv_icmd(dev, 0x0009ec, 0x00000000); - nv_icmd(dev, 0x0009ed, 0x00000000); - nv_icmd(dev, 0x0009ee, 0x00000000); - nv_icmd(dev, 0x0009ef, 0x00000000); - nv_icmd(dev, 0x0009f0, 0x00000000); - nv_icmd(dev, 0x0009f1, 0x00000000); - nv_icmd(dev, 0x0009f2, 0x00000000); - nv_icmd(dev, 0x0009f3, 0x00000000); - nv_icmd(dev, 0x0009f4, 0x00000000); - nv_icmd(dev, 0x0009f5, 0x00000000); - nv_icmd(dev, 0x0009f6, 0x00000000); - nv_icmd(dev, 0x0009f7, 0x00000000); - nv_icmd(dev, 0x0009f8, 0x00000000); - nv_icmd(dev, 0x0009f9, 0x00000000); - nv_icmd(dev, 0x0009fa, 0x00000000); - nv_icmd(dev, 0x0009fb, 0x00000000); - nv_icmd(dev, 0x0009fc, 0x00000000); - nv_icmd(dev, 0x0009fd, 0x00000000); - nv_icmd(dev, 0x0009fe, 0x00000000); - nv_icmd(dev, 0x0009ff, 0x00000000); - nv_icmd(dev, 0x000468, 0x00000004); - nv_icmd(dev, 0x00046c, 0x00000001); - nv_icmd(dev, 0x000470, 0x00000000); - nv_icmd(dev, 0x000471, 0x00000000); - nv_icmd(dev, 0x000472, 0x00000000); - nv_icmd(dev, 0x000473, 0x00000000); - nv_icmd(dev, 0x000474, 0x00000000); - nv_icmd(dev, 0x000475, 0x00000000); - nv_icmd(dev, 0x000476, 0x00000000); - nv_icmd(dev, 0x000477, 0x00000000); - nv_icmd(dev, 0x000478, 0x00000000); - nv_icmd(dev, 0x000479, 0x00000000); - nv_icmd(dev, 0x00047a, 0x00000000); - nv_icmd(dev, 0x00047b, 0x00000000); - nv_icmd(dev, 0x00047c, 0x00000000); - nv_icmd(dev, 0x00047d, 0x00000000); - nv_icmd(dev, 0x00047e, 0x00000000); - nv_icmd(dev, 0x00047f, 0x00000000); - nv_icmd(dev, 0x000480, 0x00000000); - nv_icmd(dev, 0x000481, 0x00000000); - nv_icmd(dev, 0x000482, 0x00000000); - nv_icmd(dev, 0x000483, 0x00000000); - nv_icmd(dev, 0x000484, 0x00000000); - nv_icmd(dev, 0x000485, 0x00000000); - nv_icmd(dev, 0x000486, 0x00000000); - nv_icmd(dev, 0x000487, 0x00000000); - nv_icmd(dev, 0x000488, 0x00000000); - nv_icmd(dev, 0x000489, 0x00000000); - nv_icmd(dev, 0x00048a, 0x00000000); - nv_icmd(dev, 0x00048b, 0x00000000); - nv_icmd(dev, 0x00048c, 0x00000000); - nv_icmd(dev, 0x00048d, 0x00000000); - nv_icmd(dev, 0x00048e, 0x00000000); - nv_icmd(dev, 0x00048f, 0x00000000); - nv_icmd(dev, 0x000490, 0x00000000); - nv_icmd(dev, 0x000491, 0x00000000); - nv_icmd(dev, 0x000492, 0x00000000); - nv_icmd(dev, 0x000493, 0x00000000); - nv_icmd(dev, 0x000494, 0x00000000); - nv_icmd(dev, 0x000495, 0x00000000); - nv_icmd(dev, 0x000496, 0x00000000); - nv_icmd(dev, 0x000497, 0x00000000); - nv_icmd(dev, 0x000498, 0x00000000); - nv_icmd(dev, 0x000499, 0x00000000); - nv_icmd(dev, 0x00049a, 0x00000000); - nv_icmd(dev, 0x00049b, 0x00000000); - nv_icmd(dev, 0x00049c, 0x00000000); - nv_icmd(dev, 0x00049d, 0x00000000); - nv_icmd(dev, 0x00049e, 0x00000000); - nv_icmd(dev, 0x00049f, 0x00000000); - nv_icmd(dev, 0x0004a0, 0x00000000); - nv_icmd(dev, 0x0004a1, 0x00000000); - nv_icmd(dev, 0x0004a2, 0x00000000); - nv_icmd(dev, 0x0004a3, 0x00000000); - nv_icmd(dev, 0x0004a4, 0x00000000); - nv_icmd(dev, 0x0004a5, 0x00000000); - nv_icmd(dev, 0x0004a6, 0x00000000); - nv_icmd(dev, 0x0004a7, 0x00000000); - nv_icmd(dev, 0x0004a8, 0x00000000); - nv_icmd(dev, 0x0004a9, 0x00000000); - nv_icmd(dev, 0x0004aa, 0x00000000); - nv_icmd(dev, 0x0004ab, 0x00000000); - nv_icmd(dev, 0x0004ac, 0x00000000); - nv_icmd(dev, 0x0004ad, 0x00000000); - nv_icmd(dev, 0x0004ae, 0x00000000); - nv_icmd(dev, 0x0004af, 0x00000000); - nv_icmd(dev, 0x0004b0, 0x00000000); - nv_icmd(dev, 0x0004b1, 0x00000000); - nv_icmd(dev, 0x0004b2, 0x00000000); - nv_icmd(dev, 0x0004b3, 0x00000000); - nv_icmd(dev, 0x0004b4, 0x00000000); - nv_icmd(dev, 0x0004b5, 0x00000000); - nv_icmd(dev, 0x0004b6, 0x00000000); - nv_icmd(dev, 0x0004b7, 0x00000000); - nv_icmd(dev, 0x0004b8, 0x00000000); - nv_icmd(dev, 0x0004b9, 0x00000000); - nv_icmd(dev, 0x0004ba, 0x00000000); - nv_icmd(dev, 0x0004bb, 0x00000000); - nv_icmd(dev, 0x0004bc, 0x00000000); - nv_icmd(dev, 0x0004bd, 0x00000000); - nv_icmd(dev, 0x0004be, 0x00000000); - nv_icmd(dev, 0x0004bf, 0x00000000); - nv_icmd(dev, 0x0004c0, 0x00000000); - nv_icmd(dev, 0x0004c1, 0x00000000); - nv_icmd(dev, 0x0004c2, 0x00000000); - nv_icmd(dev, 0x0004c3, 0x00000000); - nv_icmd(dev, 0x0004c4, 0x00000000); - nv_icmd(dev, 0x0004c5, 0x00000000); - nv_icmd(dev, 0x0004c6, 0x00000000); - nv_icmd(dev, 0x0004c7, 0x00000000); - nv_icmd(dev, 0x0004c8, 0x00000000); - nv_icmd(dev, 0x0004c9, 0x00000000); - nv_icmd(dev, 0x0004ca, 0x00000000); - nv_icmd(dev, 0x0004cb, 0x00000000); - nv_icmd(dev, 0x0004cc, 0x00000000); - nv_icmd(dev, 0x0004cd, 0x00000000); - nv_icmd(dev, 0x0004ce, 0x00000000); - nv_icmd(dev, 0x0004cf, 0x00000000); - nv_icmd(dev, 0x000510, 0x3f800000); - nv_icmd(dev, 0x000511, 0x3f800000); - nv_icmd(dev, 0x000512, 0x3f800000); - nv_icmd(dev, 0x000513, 0x3f800000); - nv_icmd(dev, 0x000514, 0x3f800000); - nv_icmd(dev, 0x000515, 0x3f800000); - nv_icmd(dev, 0x000516, 0x3f800000); - nv_icmd(dev, 0x000517, 0x3f800000); - nv_icmd(dev, 0x000518, 0x3f800000); - nv_icmd(dev, 0x000519, 0x3f800000); - nv_icmd(dev, 0x00051a, 0x3f800000); - nv_icmd(dev, 0x00051b, 0x3f800000); - nv_icmd(dev, 0x00051c, 0x3f800000); - nv_icmd(dev, 0x00051d, 0x3f800000); - nv_icmd(dev, 0x00051e, 0x3f800000); - nv_icmd(dev, 0x00051f, 0x3f800000); - nv_icmd(dev, 0x000520, 0x000002b6); - nv_icmd(dev, 0x000529, 0x00000001); - nv_icmd(dev, 0x000530, 0xffff0000); - nv_icmd(dev, 0x000531, 0xffff0000); - nv_icmd(dev, 0x000532, 0xffff0000); - nv_icmd(dev, 0x000533, 0xffff0000); - nv_icmd(dev, 0x000534, 0xffff0000); - nv_icmd(dev, 0x000535, 0xffff0000); - nv_icmd(dev, 0x000536, 0xffff0000); - nv_icmd(dev, 0x000537, 0xffff0000); - nv_icmd(dev, 0x000538, 0xffff0000); - nv_icmd(dev, 0x000539, 0xffff0000); - nv_icmd(dev, 0x00053a, 0xffff0000); - nv_icmd(dev, 0x00053b, 0xffff0000); - nv_icmd(dev, 0x00053c, 0xffff0000); - nv_icmd(dev, 0x00053d, 0xffff0000); - nv_icmd(dev, 0x00053e, 0xffff0000); - nv_icmd(dev, 0x00053f, 0xffff0000); - nv_icmd(dev, 0x000585, 0x0000003f); - nv_icmd(dev, 0x000576, 0x00000003); - nv_icmd(dev, 0x00057b, 0x00000059); - nv_icmd(dev, 0x000586, 0x00000040); - nv_icmd(dev, 0x000582, 0x00000080); - nv_icmd(dev, 0x000583, 0x00000080); - nv_icmd(dev, 0x0005c2, 0x00000001); - nv_icmd(dev, 0x000638, 0x00000001); - nv_icmd(dev, 0x000639, 0x00000001); - nv_icmd(dev, 0x00063a, 0x00000002); - nv_icmd(dev, 0x00063b, 0x00000001); - nv_icmd(dev, 0x00063c, 0x00000001); - nv_icmd(dev, 0x00063d, 0x00000002); - nv_icmd(dev, 0x00063e, 0x00000001); - nv_icmd(dev, 0x0008b8, 0x00000001); - nv_icmd(dev, 0x0008b9, 0x00000001); - nv_icmd(dev, 0x0008ba, 0x00000001); - nv_icmd(dev, 0x0008bb, 0x00000001); - nv_icmd(dev, 0x0008bc, 0x00000001); - nv_icmd(dev, 0x0008bd, 0x00000001); - nv_icmd(dev, 0x0008be, 0x00000001); - nv_icmd(dev, 0x0008bf, 0x00000001); - nv_icmd(dev, 0x000900, 0x00000001); - nv_icmd(dev, 0x000901, 0x00000001); - nv_icmd(dev, 0x000902, 0x00000001); - nv_icmd(dev, 0x000903, 0x00000001); - nv_icmd(dev, 0x000904, 0x00000001); - nv_icmd(dev, 0x000905, 0x00000001); - nv_icmd(dev, 0x000906, 0x00000001); - nv_icmd(dev, 0x000907, 0x00000001); - nv_icmd(dev, 0x000908, 0x00000002); - nv_icmd(dev, 0x000909, 0x00000002); - nv_icmd(dev, 0x00090a, 0x00000002); - nv_icmd(dev, 0x00090b, 0x00000002); - nv_icmd(dev, 0x00090c, 0x00000002); - nv_icmd(dev, 0x00090d, 0x00000002); - nv_icmd(dev, 0x00090e, 0x00000002); - nv_icmd(dev, 0x00090f, 0x00000002); - nv_icmd(dev, 0x000910, 0x00000001); - nv_icmd(dev, 0x000911, 0x00000001); - nv_icmd(dev, 0x000912, 0x00000001); - nv_icmd(dev, 0x000913, 0x00000001); - nv_icmd(dev, 0x000914, 0x00000001); - nv_icmd(dev, 0x000915, 0x00000001); - nv_icmd(dev, 0x000916, 0x00000001); - nv_icmd(dev, 0x000917, 0x00000001); - nv_icmd(dev, 0x000918, 0x00000001); - nv_icmd(dev, 0x000919, 0x00000001); - nv_icmd(dev, 0x00091a, 0x00000001); - nv_icmd(dev, 0x00091b, 0x00000001); - nv_icmd(dev, 0x00091c, 0x00000001); - nv_icmd(dev, 0x00091d, 0x00000001); - nv_icmd(dev, 0x00091e, 0x00000001); - nv_icmd(dev, 0x00091f, 0x00000001); - nv_icmd(dev, 0x000920, 0x00000002); - nv_icmd(dev, 0x000921, 0x00000002); - nv_icmd(dev, 0x000922, 0x00000002); - nv_icmd(dev, 0x000923, 0x00000002); - nv_icmd(dev, 0x000924, 0x00000002); - nv_icmd(dev, 0x000925, 0x00000002); - nv_icmd(dev, 0x000926, 0x00000002); - nv_icmd(dev, 0x000927, 0x00000002); - nv_icmd(dev, 0x000928, 0x00000001); - nv_icmd(dev, 0x000929, 0x00000001); - nv_icmd(dev, 0x00092a, 0x00000001); - nv_icmd(dev, 0x00092b, 0x00000001); - nv_icmd(dev, 0x00092c, 0x00000001); - nv_icmd(dev, 0x00092d, 0x00000001); - nv_icmd(dev, 0x00092e, 0x00000001); - nv_icmd(dev, 0x00092f, 0x00000001); - nv_icmd(dev, 0x000648, 0x00000001); - nv_icmd(dev, 0x000649, 0x00000001); - nv_icmd(dev, 0x00064a, 0x00000001); - nv_icmd(dev, 0x00064b, 0x00000001); - nv_icmd(dev, 0x00064c, 0x00000001); - nv_icmd(dev, 0x00064d, 0x00000001); - nv_icmd(dev, 0x00064e, 0x00000001); - nv_icmd(dev, 0x00064f, 0x00000001); - nv_icmd(dev, 0x000650, 0x00000001); - nv_icmd(dev, 0x000658, 0x0000000f); - nv_icmd(dev, 0x0007ff, 0x0000000a); - nv_icmd(dev, 0x00066a, 0x40000000); - nv_icmd(dev, 0x00066b, 0x10000000); - nv_icmd(dev, 0x00066c, 0xffff0000); - nv_icmd(dev, 0x00066d, 0xffff0000); - nv_icmd(dev, 0x0007af, 0x00000008); - nv_icmd(dev, 0x0007b0, 0x00000008); - nv_icmd(dev, 0x0007f6, 0x00000001); - nv_icmd(dev, 0x0006b2, 0x00000055); - nv_icmd(dev, 0x0007ad, 0x00000003); - nv_icmd(dev, 0x000937, 0x00000001); - nv_icmd(dev, 0x000971, 0x00000008); - nv_icmd(dev, 0x000972, 0x00000040); - nv_icmd(dev, 0x000973, 0x0000012c); - nv_icmd(dev, 0x00097c, 0x00000040); - nv_icmd(dev, 0x000979, 0x00000003); - nv_icmd(dev, 0x000975, 0x00000020); - nv_icmd(dev, 0x000976, 0x00000001); - nv_icmd(dev, 0x000977, 0x00000020); - nv_icmd(dev, 0x000978, 0x00000001); - nv_icmd(dev, 0x000957, 0x00000003); - nv_icmd(dev, 0x00095e, 0x20164010); - nv_icmd(dev, 0x00095f, 0x00000020); - nv_icmd(dev, 0x00097d, 0x00000020); - nv_icmd(dev, 0x000683, 0x00000006); - nv_icmd(dev, 0x000685, 0x003fffff); - nv_icmd(dev, 0x000687, 0x003fffff); - nv_icmd(dev, 0x0006a0, 0x00000005); - nv_icmd(dev, 0x000840, 0x00400008); - nv_icmd(dev, 0x000841, 0x08000080); - nv_icmd(dev, 0x000842, 0x00400008); - nv_icmd(dev, 0x000843, 0x08000080); - nv_icmd(dev, 0x000818, 0x00000000); - nv_icmd(dev, 0x000819, 0x00000000); - nv_icmd(dev, 0x00081a, 0x00000000); - nv_icmd(dev, 0x00081b, 0x00000000); - nv_icmd(dev, 0x00081c, 0x00000000); - nv_icmd(dev, 0x00081d, 0x00000000); - nv_icmd(dev, 0x00081e, 0x00000000); - nv_icmd(dev, 0x00081f, 0x00000000); - nv_icmd(dev, 0x000848, 0x00000000); - nv_icmd(dev, 0x000849, 0x00000000); - nv_icmd(dev, 0x00084a, 0x00000000); - nv_icmd(dev, 0x00084b, 0x00000000); - nv_icmd(dev, 0x00084c, 0x00000000); - nv_icmd(dev, 0x00084d, 0x00000000); - nv_icmd(dev, 0x00084e, 0x00000000); - nv_icmd(dev, 0x00084f, 0x00000000); - nv_icmd(dev, 0x000850, 0x00000000); - nv_icmd(dev, 0x000851, 0x00000000); - nv_icmd(dev, 0x000852, 0x00000000); - nv_icmd(dev, 0x000853, 0x00000000); - nv_icmd(dev, 0x000854, 0x00000000); - nv_icmd(dev, 0x000855, 0x00000000); - nv_icmd(dev, 0x000856, 0x00000000); - nv_icmd(dev, 0x000857, 0x00000000); - nv_icmd(dev, 0x000738, 0x00000000); - nv_icmd(dev, 0x0006aa, 0x00000001); - nv_icmd(dev, 0x0006ab, 0x00000002); - nv_icmd(dev, 0x0006ac, 0x00000080); - nv_icmd(dev, 0x0006ad, 0x00000100); - nv_icmd(dev, 0x0006ae, 0x00000100); - nv_icmd(dev, 0x0006b1, 0x00000011); - nv_icmd(dev, 0x0006bb, 0x000000cf); - nv_icmd(dev, 0x0006ce, 0x2a712488); - nv_icmd(dev, 0x000739, 0x4085c000); - nv_icmd(dev, 0x00073a, 0x00000080); - nv_icmd(dev, 0x000786, 0x80000100); - nv_icmd(dev, 0x00073c, 0x00010100); - nv_icmd(dev, 0x00073d, 0x02800000); - nv_icmd(dev, 0x000787, 0x000000cf); - nv_icmd(dev, 0x00078c, 0x00000008); - nv_icmd(dev, 0x000792, 0x00000001); - nv_icmd(dev, 0x000794, 0x00000001); - nv_icmd(dev, 0x000795, 0x00000001); - nv_icmd(dev, 0x000796, 0x00000001); - nv_icmd(dev, 0x000797, 0x000000cf); - nv_icmd(dev, 0x000836, 0x00000001); - nv_icmd(dev, 0x00079a, 0x00000002); - nv_icmd(dev, 0x000833, 0x04444480); - nv_icmd(dev, 0x0007a1, 0x00000001); - nv_icmd(dev, 0x0007a3, 0x00000001); - nv_icmd(dev, 0x0007a4, 0x00000001); - nv_icmd(dev, 0x0007a5, 0x00000001); - nv_icmd(dev, 0x000831, 0x00000004); - nv_icmd(dev, 0x000b07, 0x00000002); - nv_icmd(dev, 0x000b08, 0x00000100); - nv_icmd(dev, 0x000b09, 0x00000100); - nv_icmd(dev, 0x000b0a, 0x00000001); - nv_icmd(dev, 0x000a04, 0x000000ff); - nv_icmd(dev, 0x000a0b, 0x00000040); - nv_icmd(dev, 0x00097f, 0x00000100); - nv_icmd(dev, 0x000a02, 0x00000001); - nv_icmd(dev, 0x000809, 0x00000007); - nv_icmd(dev, 0x00c221, 0x00000040); - nv_icmd(dev, 0x00c1b0, 0x0000000f); - nv_icmd(dev, 0x00c1b1, 0x0000000f); - nv_icmd(dev, 0x00c1b2, 0x0000000f); - nv_icmd(dev, 0x00c1b3, 0x0000000f); - nv_icmd(dev, 0x00c1b4, 0x0000000f); - nv_icmd(dev, 0x00c1b5, 0x0000000f); - nv_icmd(dev, 0x00c1b6, 0x0000000f); - nv_icmd(dev, 0x00c1b7, 0x0000000f); - nv_icmd(dev, 0x00c1b8, 0x0fac6881); - nv_icmd(dev, 0x00c1b9, 0x00fac688); - nv_icmd(dev, 0x00c401, 0x00000001); - nv_icmd(dev, 0x00c402, 0x00010001); - nv_icmd(dev, 0x00c403, 0x00000001); - nv_icmd(dev, 0x00c404, 0x00000001); - nv_icmd(dev, 0x00c40e, 0x00000020); - nv_icmd(dev, 0x00c500, 0x00000003); - nv_icmd(dev, 0x01e100, 0x00000001); - nv_icmd(dev, 0x001000, 0x00000002); - nv_icmd(dev, 0x0006aa, 0x00000001); - nv_icmd(dev, 0x0006ad, 0x00000100); - nv_icmd(dev, 0x0006ae, 0x00000100); - nv_icmd(dev, 0x0006b1, 0x00000011); - nv_icmd(dev, 0x00078c, 0x00000008); - nv_icmd(dev, 0x000792, 0x00000001); - nv_icmd(dev, 0x000794, 0x00000001); - nv_icmd(dev, 0x000795, 0x00000001); - nv_icmd(dev, 0x000796, 0x00000001); - nv_icmd(dev, 0x000797, 0x000000cf); - nv_icmd(dev, 0x00079a, 0x00000002); - nv_icmd(dev, 0x000833, 0x04444480); - nv_icmd(dev, 0x0007a1, 0x00000001); - nv_icmd(dev, 0x0007a3, 0x00000001); - nv_icmd(dev, 0x0007a4, 0x00000001); - nv_icmd(dev, 0x0007a5, 0x00000001); - nv_icmd(dev, 0x000831, 0x00000004); - nv_icmd(dev, 0x01e100, 0x00000001); - nv_icmd(dev, 0x001000, 0x00000008); - nv_icmd(dev, 0x000039, 0x00000000); - nv_icmd(dev, 0x00003a, 0x00000000); - nv_icmd(dev, 0x00003b, 0x00000000); - nv_icmd(dev, 0x000380, 0x00000001); - nv_icmd(dev, 0x000366, 0x00000000); - nv_icmd(dev, 0x000367, 0x00000000); - nv_icmd(dev, 0x000368, 0x00000fff); - nv_icmd(dev, 0x000370, 0x00000000); - nv_icmd(dev, 0x000371, 0x00000000); - nv_icmd(dev, 0x000372, 0x000fffff); - nv_icmd(dev, 0x000813, 0x00000006); - nv_icmd(dev, 0x000814, 0x00000008); - nv_icmd(dev, 0x000957, 0x00000003); - nv_icmd(dev, 0x000818, 0x00000000); - nv_icmd(dev, 0x000819, 0x00000000); - nv_icmd(dev, 0x00081a, 0x00000000); - nv_icmd(dev, 0x00081b, 0x00000000); - nv_icmd(dev, 0x00081c, 0x00000000); - nv_icmd(dev, 0x00081d, 0x00000000); - nv_icmd(dev, 0x00081e, 0x00000000); - nv_icmd(dev, 0x00081f, 0x00000000); - nv_icmd(dev, 0x000848, 0x00000000); - nv_icmd(dev, 0x000849, 0x00000000); - nv_icmd(dev, 0x00084a, 0x00000000); - nv_icmd(dev, 0x00084b, 0x00000000); - nv_icmd(dev, 0x00084c, 0x00000000); - nv_icmd(dev, 0x00084d, 0x00000000); - nv_icmd(dev, 0x00084e, 0x00000000); - nv_icmd(dev, 0x00084f, 0x00000000); - nv_icmd(dev, 0x000850, 0x00000000); - nv_icmd(dev, 0x000851, 0x00000000); - nv_icmd(dev, 0x000852, 0x00000000); - nv_icmd(dev, 0x000853, 0x00000000); - nv_icmd(dev, 0x000854, 0x00000000); - nv_icmd(dev, 0x000855, 0x00000000); - nv_icmd(dev, 0x000856, 0x00000000); - nv_icmd(dev, 0x000857, 0x00000000); - nv_icmd(dev, 0x000738, 0x00000000); - nv_icmd(dev, 0x000b07, 0x00000002); - nv_icmd(dev, 0x000b08, 0x00000100); - nv_icmd(dev, 0x000b09, 0x00000100); - nv_icmd(dev, 0x000b0a, 0x00000001); - nv_icmd(dev, 0x000a04, 0x000000ff); - nv_icmd(dev, 0x00097f, 0x00000100); - nv_icmd(dev, 0x000a02, 0x00000001); - nv_icmd(dev, 0x000809, 0x00000007); - nv_icmd(dev, 0x00c221, 0x00000040); - nv_icmd(dev, 0x00c401, 0x00000001); - nv_icmd(dev, 0x00c402, 0x00010001); - nv_icmd(dev, 0x00c403, 0x00000001); - nv_icmd(dev, 0x00c404, 0x00000001); - nv_icmd(dev, 0x00c40e, 0x00000020); - nv_icmd(dev, 0x00c500, 0x00000003); - nv_icmd(dev, 0x01e100, 0x00000001); - nv_icmd(dev, 0x001000, 0x00000001); - nv_icmd(dev, 0x000b07, 0x00000002); - nv_icmd(dev, 0x000b08, 0x00000100); - nv_icmd(dev, 0x000b09, 0x00000100); - nv_icmd(dev, 0x000b0a, 0x00000001); - nv_icmd(dev, 0x01e100, 0x00000001); - nv_wr32(dev, 0x400208, 0x00000000); + nv_wr32(priv, 0x400208, 0x80000000); + nv_icmd(priv, 0x001000, 0x00000004); + nv_icmd(priv, 0x000039, 0x00000000); + nv_icmd(priv, 0x00003a, 0x00000000); + nv_icmd(priv, 0x00003b, 0x00000000); + nv_icmd(priv, 0x0000a9, 0x0000ffff); + nv_icmd(priv, 0x000038, 0x0fac6881); + nv_icmd(priv, 0x00003d, 0x00000001); + nv_icmd(priv, 0x0000e8, 0x00000400); + nv_icmd(priv, 0x0000e9, 0x00000400); + nv_icmd(priv, 0x0000ea, 0x00000400); + nv_icmd(priv, 0x0000eb, 0x00000400); + nv_icmd(priv, 0x0000ec, 0x00000400); + nv_icmd(priv, 0x0000ed, 0x00000400); + nv_icmd(priv, 0x0000ee, 0x00000400); + nv_icmd(priv, 0x0000ef, 0x00000400); + nv_icmd(priv, 0x000078, 0x00000300); + nv_icmd(priv, 0x000079, 0x00000300); + nv_icmd(priv, 0x00007a, 0x00000300); + nv_icmd(priv, 0x00007b, 0x00000300); + nv_icmd(priv, 0x00007c, 0x00000300); + nv_icmd(priv, 0x00007d, 0x00000300); + nv_icmd(priv, 0x00007e, 0x00000300); + nv_icmd(priv, 0x00007f, 0x00000300); + nv_icmd(priv, 0x000050, 0x00000011); + nv_icmd(priv, 0x000058, 0x00000008); + nv_icmd(priv, 0x000059, 0x00000008); + nv_icmd(priv, 0x00005a, 0x00000008); + nv_icmd(priv, 0x00005b, 0x00000008); + nv_icmd(priv, 0x00005c, 0x00000008); + nv_icmd(priv, 0x00005d, 0x00000008); + nv_icmd(priv, 0x00005e, 0x00000008); + nv_icmd(priv, 0x00005f, 0x00000008); + nv_icmd(priv, 0x000208, 0x00000001); + nv_icmd(priv, 0x000209, 0x00000001); + nv_icmd(priv, 0x00020a, 0x00000001); + nv_icmd(priv, 0x00020b, 0x00000001); + nv_icmd(priv, 0x00020c, 0x00000001); + nv_icmd(priv, 0x00020d, 0x00000001); + nv_icmd(priv, 0x00020e, 0x00000001); + nv_icmd(priv, 0x00020f, 0x00000001); + nv_icmd(priv, 0x000081, 0x00000001); + nv_icmd(priv, 0x000085, 0x00000004); + nv_icmd(priv, 0x000088, 0x00000400); + nv_icmd(priv, 0x000090, 0x00000300); + nv_icmd(priv, 0x000098, 0x00001001); + nv_icmd(priv, 0x0000e3, 0x00000001); + nv_icmd(priv, 0x0000da, 0x00000001); + nv_icmd(priv, 0x0000f8, 0x00000003); + nv_icmd(priv, 0x0000fa, 0x00000001); + nv_icmd(priv, 0x00009f, 0x0000ffff); + nv_icmd(priv, 0x0000a0, 0x0000ffff); + nv_icmd(priv, 0x0000a1, 0x0000ffff); + nv_icmd(priv, 0x0000a2, 0x0000ffff); + nv_icmd(priv, 0x0000b1, 0x00000001); + nv_icmd(priv, 0x0000ad, 0x0000013e); + nv_icmd(priv, 0x0000e1, 0x00000010); + nv_icmd(priv, 0x000290, 0x00000000); + nv_icmd(priv, 0x000291, 0x00000000); + nv_icmd(priv, 0x000292, 0x00000000); + nv_icmd(priv, 0x000293, 0x00000000); + nv_icmd(priv, 0x000294, 0x00000000); + nv_icmd(priv, 0x000295, 0x00000000); + nv_icmd(priv, 0x000296, 0x00000000); + nv_icmd(priv, 0x000297, 0x00000000); + nv_icmd(priv, 0x000298, 0x00000000); + nv_icmd(priv, 0x000299, 0x00000000); + nv_icmd(priv, 0x00029a, 0x00000000); + nv_icmd(priv, 0x00029b, 0x00000000); + nv_icmd(priv, 0x00029c, 0x00000000); + nv_icmd(priv, 0x00029d, 0x00000000); + nv_icmd(priv, 0x00029e, 0x00000000); + nv_icmd(priv, 0x00029f, 0x00000000); + nv_icmd(priv, 0x0003b0, 0x00000000); + nv_icmd(priv, 0x0003b1, 0x00000000); + nv_icmd(priv, 0x0003b2, 0x00000000); + nv_icmd(priv, 0x0003b3, 0x00000000); + nv_icmd(priv, 0x0003b4, 0x00000000); + nv_icmd(priv, 0x0003b5, 0x00000000); + nv_icmd(priv, 0x0003b6, 0x00000000); + nv_icmd(priv, 0x0003b7, 0x00000000); + nv_icmd(priv, 0x0003b8, 0x00000000); + nv_icmd(priv, 0x0003b9, 0x00000000); + nv_icmd(priv, 0x0003ba, 0x00000000); + nv_icmd(priv, 0x0003bb, 0x00000000); + nv_icmd(priv, 0x0003bc, 0x00000000); + nv_icmd(priv, 0x0003bd, 0x00000000); + nv_icmd(priv, 0x0003be, 0x00000000); + nv_icmd(priv, 0x0003bf, 0x00000000); + nv_icmd(priv, 0x0002a0, 0x00000000); + nv_icmd(priv, 0x0002a1, 0x00000000); + nv_icmd(priv, 0x0002a2, 0x00000000); + nv_icmd(priv, 0x0002a3, 0x00000000); + nv_icmd(priv, 0x0002a4, 0x00000000); + nv_icmd(priv, 0x0002a5, 0x00000000); + nv_icmd(priv, 0x0002a6, 0x00000000); + nv_icmd(priv, 0x0002a7, 0x00000000); + nv_icmd(priv, 0x0002a8, 0x00000000); + nv_icmd(priv, 0x0002a9, 0x00000000); + nv_icmd(priv, 0x0002aa, 0x00000000); + nv_icmd(priv, 0x0002ab, 0x00000000); + nv_icmd(priv, 0x0002ac, 0x00000000); + nv_icmd(priv, 0x0002ad, 0x00000000); + nv_icmd(priv, 0x0002ae, 0x00000000); + nv_icmd(priv, 0x0002af, 0x00000000); + nv_icmd(priv, 0x000420, 0x00000000); + nv_icmd(priv, 0x000421, 0x00000000); + nv_icmd(priv, 0x000422, 0x00000000); + nv_icmd(priv, 0x000423, 0x00000000); + nv_icmd(priv, 0x000424, 0x00000000); + nv_icmd(priv, 0x000425, 0x00000000); + nv_icmd(priv, 0x000426, 0x00000000); + nv_icmd(priv, 0x000427, 0x00000000); + nv_icmd(priv, 0x000428, 0x00000000); + nv_icmd(priv, 0x000429, 0x00000000); + nv_icmd(priv, 0x00042a, 0x00000000); + nv_icmd(priv, 0x00042b, 0x00000000); + nv_icmd(priv, 0x00042c, 0x00000000); + nv_icmd(priv, 0x00042d, 0x00000000); + nv_icmd(priv, 0x00042e, 0x00000000); + nv_icmd(priv, 0x00042f, 0x00000000); + nv_icmd(priv, 0x0002b0, 0x00000000); + nv_icmd(priv, 0x0002b1, 0x00000000); + nv_icmd(priv, 0x0002b2, 0x00000000); + nv_icmd(priv, 0x0002b3, 0x00000000); + nv_icmd(priv, 0x0002b4, 0x00000000); + nv_icmd(priv, 0x0002b5, 0x00000000); + nv_icmd(priv, 0x0002b6, 0x00000000); + nv_icmd(priv, 0x0002b7, 0x00000000); + nv_icmd(priv, 0x0002b8, 0x00000000); + nv_icmd(priv, 0x0002b9, 0x00000000); + nv_icmd(priv, 0x0002ba, 0x00000000); + nv_icmd(priv, 0x0002bb, 0x00000000); + nv_icmd(priv, 0x0002bc, 0x00000000); + nv_icmd(priv, 0x0002bd, 0x00000000); + nv_icmd(priv, 0x0002be, 0x00000000); + nv_icmd(priv, 0x0002bf, 0x00000000); + nv_icmd(priv, 0x000430, 0x00000000); + nv_icmd(priv, 0x000431, 0x00000000); + nv_icmd(priv, 0x000432, 0x00000000); + nv_icmd(priv, 0x000433, 0x00000000); + nv_icmd(priv, 0x000434, 0x00000000); + nv_icmd(priv, 0x000435, 0x00000000); + nv_icmd(priv, 0x000436, 0x00000000); + nv_icmd(priv, 0x000437, 0x00000000); + nv_icmd(priv, 0x000438, 0x00000000); + nv_icmd(priv, 0x000439, 0x00000000); + nv_icmd(priv, 0x00043a, 0x00000000); + nv_icmd(priv, 0x00043b, 0x00000000); + nv_icmd(priv, 0x00043c, 0x00000000); + nv_icmd(priv, 0x00043d, 0x00000000); + nv_icmd(priv, 0x00043e, 0x00000000); + nv_icmd(priv, 0x00043f, 0x00000000); + nv_icmd(priv, 0x0002c0, 0x00000000); + nv_icmd(priv, 0x0002c1, 0x00000000); + nv_icmd(priv, 0x0002c2, 0x00000000); + nv_icmd(priv, 0x0002c3, 0x00000000); + nv_icmd(priv, 0x0002c4, 0x00000000); + nv_icmd(priv, 0x0002c5, 0x00000000); + nv_icmd(priv, 0x0002c6, 0x00000000); + nv_icmd(priv, 0x0002c7, 0x00000000); + nv_icmd(priv, 0x0002c8, 0x00000000); + nv_icmd(priv, 0x0002c9, 0x00000000); + nv_icmd(priv, 0x0002ca, 0x00000000); + nv_icmd(priv, 0x0002cb, 0x00000000); + nv_icmd(priv, 0x0002cc, 0x00000000); + nv_icmd(priv, 0x0002cd, 0x00000000); + nv_icmd(priv, 0x0002ce, 0x00000000); + nv_icmd(priv, 0x0002cf, 0x00000000); + nv_icmd(priv, 0x0004d0, 0x00000000); + nv_icmd(priv, 0x0004d1, 0x00000000); + nv_icmd(priv, 0x0004d2, 0x00000000); + nv_icmd(priv, 0x0004d3, 0x00000000); + nv_icmd(priv, 0x0004d4, 0x00000000); + nv_icmd(priv, 0x0004d5, 0x00000000); + nv_icmd(priv, 0x0004d6, 0x00000000); + nv_icmd(priv, 0x0004d7, 0x00000000); + nv_icmd(priv, 0x0004d8, 0x00000000); + nv_icmd(priv, 0x0004d9, 0x00000000); + nv_icmd(priv, 0x0004da, 0x00000000); + nv_icmd(priv, 0x0004db, 0x00000000); + nv_icmd(priv, 0x0004dc, 0x00000000); + nv_icmd(priv, 0x0004dd, 0x00000000); + nv_icmd(priv, 0x0004de, 0x00000000); + nv_icmd(priv, 0x0004df, 0x00000000); + nv_icmd(priv, 0x000720, 0x00000000); + nv_icmd(priv, 0x000721, 0x00000000); + nv_icmd(priv, 0x000722, 0x00000000); + nv_icmd(priv, 0x000723, 0x00000000); + nv_icmd(priv, 0x000724, 0x00000000); + nv_icmd(priv, 0x000725, 0x00000000); + nv_icmd(priv, 0x000726, 0x00000000); + nv_icmd(priv, 0x000727, 0x00000000); + nv_icmd(priv, 0x000728, 0x00000000); + nv_icmd(priv, 0x000729, 0x00000000); + nv_icmd(priv, 0x00072a, 0x00000000); + nv_icmd(priv, 0x00072b, 0x00000000); + nv_icmd(priv, 0x00072c, 0x00000000); + nv_icmd(priv, 0x00072d, 0x00000000); + nv_icmd(priv, 0x00072e, 0x00000000); + nv_icmd(priv, 0x00072f, 0x00000000); + nv_icmd(priv, 0x0008c0, 0x00000000); + nv_icmd(priv, 0x0008c1, 0x00000000); + nv_icmd(priv, 0x0008c2, 0x00000000); + nv_icmd(priv, 0x0008c3, 0x00000000); + nv_icmd(priv, 0x0008c4, 0x00000000); + nv_icmd(priv, 0x0008c5, 0x00000000); + nv_icmd(priv, 0x0008c6, 0x00000000); + nv_icmd(priv, 0x0008c7, 0x00000000); + nv_icmd(priv, 0x0008c8, 0x00000000); + nv_icmd(priv, 0x0008c9, 0x00000000); + nv_icmd(priv, 0x0008ca, 0x00000000); + nv_icmd(priv, 0x0008cb, 0x00000000); + nv_icmd(priv, 0x0008cc, 0x00000000); + nv_icmd(priv, 0x0008cd, 0x00000000); + nv_icmd(priv, 0x0008ce, 0x00000000); + nv_icmd(priv, 0x0008cf, 0x00000000); + nv_icmd(priv, 0x000890, 0x00000000); + nv_icmd(priv, 0x000891, 0x00000000); + nv_icmd(priv, 0x000892, 0x00000000); + nv_icmd(priv, 0x000893, 0x00000000); + nv_icmd(priv, 0x000894, 0x00000000); + nv_icmd(priv, 0x000895, 0x00000000); + nv_icmd(priv, 0x000896, 0x00000000); + nv_icmd(priv, 0x000897, 0x00000000); + nv_icmd(priv, 0x000898, 0x00000000); + nv_icmd(priv, 0x000899, 0x00000000); + nv_icmd(priv, 0x00089a, 0x00000000); + nv_icmd(priv, 0x00089b, 0x00000000); + nv_icmd(priv, 0x00089c, 0x00000000); + nv_icmd(priv, 0x00089d, 0x00000000); + nv_icmd(priv, 0x00089e, 0x00000000); + nv_icmd(priv, 0x00089f, 0x00000000); + nv_icmd(priv, 0x0008e0, 0x00000000); + nv_icmd(priv, 0x0008e1, 0x00000000); + nv_icmd(priv, 0x0008e2, 0x00000000); + nv_icmd(priv, 0x0008e3, 0x00000000); + nv_icmd(priv, 0x0008e4, 0x00000000); + nv_icmd(priv, 0x0008e5, 0x00000000); + nv_icmd(priv, 0x0008e6, 0x00000000); + nv_icmd(priv, 0x0008e7, 0x00000000); + nv_icmd(priv, 0x0008e8, 0x00000000); + nv_icmd(priv, 0x0008e9, 0x00000000); + nv_icmd(priv, 0x0008ea, 0x00000000); + nv_icmd(priv, 0x0008eb, 0x00000000); + nv_icmd(priv, 0x0008ec, 0x00000000); + nv_icmd(priv, 0x0008ed, 0x00000000); + nv_icmd(priv, 0x0008ee, 0x00000000); + nv_icmd(priv, 0x0008ef, 0x00000000); + nv_icmd(priv, 0x0008a0, 0x00000000); + nv_icmd(priv, 0x0008a1, 0x00000000); + nv_icmd(priv, 0x0008a2, 0x00000000); + nv_icmd(priv, 0x0008a3, 0x00000000); + nv_icmd(priv, 0x0008a4, 0x00000000); + nv_icmd(priv, 0x0008a5, 0x00000000); + nv_icmd(priv, 0x0008a6, 0x00000000); + nv_icmd(priv, 0x0008a7, 0x00000000); + nv_icmd(priv, 0x0008a8, 0x00000000); + nv_icmd(priv, 0x0008a9, 0x00000000); + nv_icmd(priv, 0x0008aa, 0x00000000); + nv_icmd(priv, 0x0008ab, 0x00000000); + nv_icmd(priv, 0x0008ac, 0x00000000); + nv_icmd(priv, 0x0008ad, 0x00000000); + nv_icmd(priv, 0x0008ae, 0x00000000); + nv_icmd(priv, 0x0008af, 0x00000000); + nv_icmd(priv, 0x0008f0, 0x00000000); + nv_icmd(priv, 0x0008f1, 0x00000000); + nv_icmd(priv, 0x0008f2, 0x00000000); + nv_icmd(priv, 0x0008f3, 0x00000000); + nv_icmd(priv, 0x0008f4, 0x00000000); + nv_icmd(priv, 0x0008f5, 0x00000000); + nv_icmd(priv, 0x0008f6, 0x00000000); + nv_icmd(priv, 0x0008f7, 0x00000000); + nv_icmd(priv, 0x0008f8, 0x00000000); + nv_icmd(priv, 0x0008f9, 0x00000000); + nv_icmd(priv, 0x0008fa, 0x00000000); + nv_icmd(priv, 0x0008fb, 0x00000000); + nv_icmd(priv, 0x0008fc, 0x00000000); + nv_icmd(priv, 0x0008fd, 0x00000000); + nv_icmd(priv, 0x0008fe, 0x00000000); + nv_icmd(priv, 0x0008ff, 0x00000000); + nv_icmd(priv, 0x00094c, 0x000000ff); + nv_icmd(priv, 0x00094d, 0xffffffff); + nv_icmd(priv, 0x00094e, 0x00000002); + nv_icmd(priv, 0x0002ec, 0x00000001); + nv_icmd(priv, 0x000303, 0x00000001); + nv_icmd(priv, 0x0002e6, 0x00000001); + nv_icmd(priv, 0x000466, 0x00000052); + nv_icmd(priv, 0x000301, 0x3f800000); + nv_icmd(priv, 0x000304, 0x30201000); + nv_icmd(priv, 0x000305, 0x70605040); + nv_icmd(priv, 0x000306, 0xb8a89888); + nv_icmd(priv, 0x000307, 0xf8e8d8c8); + nv_icmd(priv, 0x00030a, 0x00ffff00); + nv_icmd(priv, 0x00030b, 0x0000001a); + nv_icmd(priv, 0x00030c, 0x00000001); + nv_icmd(priv, 0x000318, 0x00000001); + nv_icmd(priv, 0x000340, 0x00000000); + nv_icmd(priv, 0x000375, 0x00000001); + nv_icmd(priv, 0x00037d, 0x00000006); + nv_icmd(priv, 0x0003a0, 0x00000002); + nv_icmd(priv, 0x0003aa, 0x00000001); + nv_icmd(priv, 0x0003a9, 0x00000001); + nv_icmd(priv, 0x000380, 0x00000001); + nv_icmd(priv, 0x000383, 0x00000011); + nv_icmd(priv, 0x000360, 0x00000040); + nv_icmd(priv, 0x000366, 0x00000000); + nv_icmd(priv, 0x000367, 0x00000000); + nv_icmd(priv, 0x000368, 0x00000fff); + nv_icmd(priv, 0x000370, 0x00000000); + nv_icmd(priv, 0x000371, 0x00000000); + nv_icmd(priv, 0x000372, 0x000fffff); + nv_icmd(priv, 0x00037a, 0x00000012); + nv_icmd(priv, 0x000619, 0x00000003); + nv_icmd(priv, 0x000811, 0x00000003); + nv_icmd(priv, 0x000812, 0x00000004); + nv_icmd(priv, 0x000813, 0x00000006); + nv_icmd(priv, 0x000814, 0x00000008); + nv_icmd(priv, 0x000815, 0x0000000b); + nv_icmd(priv, 0x000800, 0x00000001); + nv_icmd(priv, 0x000801, 0x00000001); + nv_icmd(priv, 0x000802, 0x00000001); + nv_icmd(priv, 0x000803, 0x00000001); + nv_icmd(priv, 0x000804, 0x00000001); + nv_icmd(priv, 0x000805, 0x00000001); + nv_icmd(priv, 0x000632, 0x00000001); + nv_icmd(priv, 0x000633, 0x00000002); + nv_icmd(priv, 0x000634, 0x00000003); + nv_icmd(priv, 0x000635, 0x00000004); + nv_icmd(priv, 0x000654, 0x3f800000); + nv_icmd(priv, 0x000657, 0x3f800000); + nv_icmd(priv, 0x000655, 0x3f800000); + nv_icmd(priv, 0x000656, 0x3f800000); + nv_icmd(priv, 0x0006cd, 0x3f800000); + nv_icmd(priv, 0x0007f5, 0x3f800000); + nv_icmd(priv, 0x0007dc, 0x39291909); + nv_icmd(priv, 0x0007dd, 0x79695949); + nv_icmd(priv, 0x0007de, 0xb9a99989); + nv_icmd(priv, 0x0007df, 0xf9e9d9c9); + nv_icmd(priv, 0x0007e8, 0x00003210); + nv_icmd(priv, 0x0007e9, 0x00007654); + nv_icmd(priv, 0x0007ea, 0x00000098); + nv_icmd(priv, 0x0007ec, 0x39291909); + nv_icmd(priv, 0x0007ed, 0x79695949); + nv_icmd(priv, 0x0007ee, 0xb9a99989); + nv_icmd(priv, 0x0007ef, 0xf9e9d9c9); + nv_icmd(priv, 0x0007f0, 0x00003210); + nv_icmd(priv, 0x0007f1, 0x00007654); + nv_icmd(priv, 0x0007f2, 0x00000098); + nv_icmd(priv, 0x0005a5, 0x00000001); + nv_icmd(priv, 0x000980, 0x00000000); + nv_icmd(priv, 0x000981, 0x00000000); + nv_icmd(priv, 0x000982, 0x00000000); + nv_icmd(priv, 0x000983, 0x00000000); + nv_icmd(priv, 0x000984, 0x00000000); + nv_icmd(priv, 0x000985, 0x00000000); + nv_icmd(priv, 0x000986, 0x00000000); + nv_icmd(priv, 0x000987, 0x00000000); + nv_icmd(priv, 0x000988, 0x00000000); + nv_icmd(priv, 0x000989, 0x00000000); + nv_icmd(priv, 0x00098a, 0x00000000); + nv_icmd(priv, 0x00098b, 0x00000000); + nv_icmd(priv, 0x00098c, 0x00000000); + nv_icmd(priv, 0x00098d, 0x00000000); + nv_icmd(priv, 0x00098e, 0x00000000); + nv_icmd(priv, 0x00098f, 0x00000000); + nv_icmd(priv, 0x000990, 0x00000000); + nv_icmd(priv, 0x000991, 0x00000000); + nv_icmd(priv, 0x000992, 0x00000000); + nv_icmd(priv, 0x000993, 0x00000000); + nv_icmd(priv, 0x000994, 0x00000000); + nv_icmd(priv, 0x000995, 0x00000000); + nv_icmd(priv, 0x000996, 0x00000000); + nv_icmd(priv, 0x000997, 0x00000000); + nv_icmd(priv, 0x000998, 0x00000000); + nv_icmd(priv, 0x000999, 0x00000000); + nv_icmd(priv, 0x00099a, 0x00000000); + nv_icmd(priv, 0x00099b, 0x00000000); + nv_icmd(priv, 0x00099c, 0x00000000); + nv_icmd(priv, 0x00099d, 0x00000000); + nv_icmd(priv, 0x00099e, 0x00000000); + nv_icmd(priv, 0x00099f, 0x00000000); + nv_icmd(priv, 0x0009a0, 0x00000000); + nv_icmd(priv, 0x0009a1, 0x00000000); + nv_icmd(priv, 0x0009a2, 0x00000000); + nv_icmd(priv, 0x0009a3, 0x00000000); + nv_icmd(priv, 0x0009a4, 0x00000000); + nv_icmd(priv, 0x0009a5, 0x00000000); + nv_icmd(priv, 0x0009a6, 0x00000000); + nv_icmd(priv, 0x0009a7, 0x00000000); + nv_icmd(priv, 0x0009a8, 0x00000000); + nv_icmd(priv, 0x0009a9, 0x00000000); + nv_icmd(priv, 0x0009aa, 0x00000000); + nv_icmd(priv, 0x0009ab, 0x00000000); + nv_icmd(priv, 0x0009ac, 0x00000000); + nv_icmd(priv, 0x0009ad, 0x00000000); + nv_icmd(priv, 0x0009ae, 0x00000000); + nv_icmd(priv, 0x0009af, 0x00000000); + nv_icmd(priv, 0x0009b0, 0x00000000); + nv_icmd(priv, 0x0009b1, 0x00000000); + nv_icmd(priv, 0x0009b2, 0x00000000); + nv_icmd(priv, 0x0009b3, 0x00000000); + nv_icmd(priv, 0x0009b4, 0x00000000); + nv_icmd(priv, 0x0009b5, 0x00000000); + nv_icmd(priv, 0x0009b6, 0x00000000); + nv_icmd(priv, 0x0009b7, 0x00000000); + nv_icmd(priv, 0x0009b8, 0x00000000); + nv_icmd(priv, 0x0009b9, 0x00000000); + nv_icmd(priv, 0x0009ba, 0x00000000); + nv_icmd(priv, 0x0009bb, 0x00000000); + nv_icmd(priv, 0x0009bc, 0x00000000); + nv_icmd(priv, 0x0009bd, 0x00000000); + nv_icmd(priv, 0x0009be, 0x00000000); + nv_icmd(priv, 0x0009bf, 0x00000000); + nv_icmd(priv, 0x0009c0, 0x00000000); + nv_icmd(priv, 0x0009c1, 0x00000000); + nv_icmd(priv, 0x0009c2, 0x00000000); + nv_icmd(priv, 0x0009c3, 0x00000000); + nv_icmd(priv, 0x0009c4, 0x00000000); + nv_icmd(priv, 0x0009c5, 0x00000000); + nv_icmd(priv, 0x0009c6, 0x00000000); + nv_icmd(priv, 0x0009c7, 0x00000000); + nv_icmd(priv, 0x0009c8, 0x00000000); + nv_icmd(priv, 0x0009c9, 0x00000000); + nv_icmd(priv, 0x0009ca, 0x00000000); + nv_icmd(priv, 0x0009cb, 0x00000000); + nv_icmd(priv, 0x0009cc, 0x00000000); + nv_icmd(priv, 0x0009cd, 0x00000000); + nv_icmd(priv, 0x0009ce, 0x00000000); + nv_icmd(priv, 0x0009cf, 0x00000000); + nv_icmd(priv, 0x0009d0, 0x00000000); + nv_icmd(priv, 0x0009d1, 0x00000000); + nv_icmd(priv, 0x0009d2, 0x00000000); + nv_icmd(priv, 0x0009d3, 0x00000000); + nv_icmd(priv, 0x0009d4, 0x00000000); + nv_icmd(priv, 0x0009d5, 0x00000000); + nv_icmd(priv, 0x0009d6, 0x00000000); + nv_icmd(priv, 0x0009d7, 0x00000000); + nv_icmd(priv, 0x0009d8, 0x00000000); + nv_icmd(priv, 0x0009d9, 0x00000000); + nv_icmd(priv, 0x0009da, 0x00000000); + nv_icmd(priv, 0x0009db, 0x00000000); + nv_icmd(priv, 0x0009dc, 0x00000000); + nv_icmd(priv, 0x0009dd, 0x00000000); + nv_icmd(priv, 0x0009de, 0x00000000); + nv_icmd(priv, 0x0009df, 0x00000000); + nv_icmd(priv, 0x0009e0, 0x00000000); + nv_icmd(priv, 0x0009e1, 0x00000000); + nv_icmd(priv, 0x0009e2, 0x00000000); + nv_icmd(priv, 0x0009e3, 0x00000000); + nv_icmd(priv, 0x0009e4, 0x00000000); + nv_icmd(priv, 0x0009e5, 0x00000000); + nv_icmd(priv, 0x0009e6, 0x00000000); + nv_icmd(priv, 0x0009e7, 0x00000000); + nv_icmd(priv, 0x0009e8, 0x00000000); + nv_icmd(priv, 0x0009e9, 0x00000000); + nv_icmd(priv, 0x0009ea, 0x00000000); + nv_icmd(priv, 0x0009eb, 0x00000000); + nv_icmd(priv, 0x0009ec, 0x00000000); + nv_icmd(priv, 0x0009ed, 0x00000000); + nv_icmd(priv, 0x0009ee, 0x00000000); + nv_icmd(priv, 0x0009ef, 0x00000000); + nv_icmd(priv, 0x0009f0, 0x00000000); + nv_icmd(priv, 0x0009f1, 0x00000000); + nv_icmd(priv, 0x0009f2, 0x00000000); + nv_icmd(priv, 0x0009f3, 0x00000000); + nv_icmd(priv, 0x0009f4, 0x00000000); + nv_icmd(priv, 0x0009f5, 0x00000000); + nv_icmd(priv, 0x0009f6, 0x00000000); + nv_icmd(priv, 0x0009f7, 0x00000000); + nv_icmd(priv, 0x0009f8, 0x00000000); + nv_icmd(priv, 0x0009f9, 0x00000000); + nv_icmd(priv, 0x0009fa, 0x00000000); + nv_icmd(priv, 0x0009fb, 0x00000000); + nv_icmd(priv, 0x0009fc, 0x00000000); + nv_icmd(priv, 0x0009fd, 0x00000000); + nv_icmd(priv, 0x0009fe, 0x00000000); + nv_icmd(priv, 0x0009ff, 0x00000000); + nv_icmd(priv, 0x000468, 0x00000004); + nv_icmd(priv, 0x00046c, 0x00000001); + nv_icmd(priv, 0x000470, 0x00000000); + nv_icmd(priv, 0x000471, 0x00000000); + nv_icmd(priv, 0x000472, 0x00000000); + nv_icmd(priv, 0x000473, 0x00000000); + nv_icmd(priv, 0x000474, 0x00000000); + nv_icmd(priv, 0x000475, 0x00000000); + nv_icmd(priv, 0x000476, 0x00000000); + nv_icmd(priv, 0x000477, 0x00000000); + nv_icmd(priv, 0x000478, 0x00000000); + nv_icmd(priv, 0x000479, 0x00000000); + nv_icmd(priv, 0x00047a, 0x00000000); + nv_icmd(priv, 0x00047b, 0x00000000); + nv_icmd(priv, 0x00047c, 0x00000000); + nv_icmd(priv, 0x00047d, 0x00000000); + nv_icmd(priv, 0x00047e, 0x00000000); + nv_icmd(priv, 0x00047f, 0x00000000); + nv_icmd(priv, 0x000480, 0x00000000); + nv_icmd(priv, 0x000481, 0x00000000); + nv_icmd(priv, 0x000482, 0x00000000); + nv_icmd(priv, 0x000483, 0x00000000); + nv_icmd(priv, 0x000484, 0x00000000); + nv_icmd(priv, 0x000485, 0x00000000); + nv_icmd(priv, 0x000486, 0x00000000); + nv_icmd(priv, 0x000487, 0x00000000); + nv_icmd(priv, 0x000488, 0x00000000); + nv_icmd(priv, 0x000489, 0x00000000); + nv_icmd(priv, 0x00048a, 0x00000000); + nv_icmd(priv, 0x00048b, 0x00000000); + nv_icmd(priv, 0x00048c, 0x00000000); + nv_icmd(priv, 0x00048d, 0x00000000); + nv_icmd(priv, 0x00048e, 0x00000000); + nv_icmd(priv, 0x00048f, 0x00000000); + nv_icmd(priv, 0x000490, 0x00000000); + nv_icmd(priv, 0x000491, 0x00000000); + nv_icmd(priv, 0x000492, 0x00000000); + nv_icmd(priv, 0x000493, 0x00000000); + nv_icmd(priv, 0x000494, 0x00000000); + nv_icmd(priv, 0x000495, 0x00000000); + nv_icmd(priv, 0x000496, 0x00000000); + nv_icmd(priv, 0x000497, 0x00000000); + nv_icmd(priv, 0x000498, 0x00000000); + nv_icmd(priv, 0x000499, 0x00000000); + nv_icmd(priv, 0x00049a, 0x00000000); + nv_icmd(priv, 0x00049b, 0x00000000); + nv_icmd(priv, 0x00049c, 0x00000000); + nv_icmd(priv, 0x00049d, 0x00000000); + nv_icmd(priv, 0x00049e, 0x00000000); + nv_icmd(priv, 0x00049f, 0x00000000); + nv_icmd(priv, 0x0004a0, 0x00000000); + nv_icmd(priv, 0x0004a1, 0x00000000); + nv_icmd(priv, 0x0004a2, 0x00000000); + nv_icmd(priv, 0x0004a3, 0x00000000); + nv_icmd(priv, 0x0004a4, 0x00000000); + nv_icmd(priv, 0x0004a5, 0x00000000); + nv_icmd(priv, 0x0004a6, 0x00000000); + nv_icmd(priv, 0x0004a7, 0x00000000); + nv_icmd(priv, 0x0004a8, 0x00000000); + nv_icmd(priv, 0x0004a9, 0x00000000); + nv_icmd(priv, 0x0004aa, 0x00000000); + nv_icmd(priv, 0x0004ab, 0x00000000); + nv_icmd(priv, 0x0004ac, 0x00000000); + nv_icmd(priv, 0x0004ad, 0x00000000); + nv_icmd(priv, 0x0004ae, 0x00000000); + nv_icmd(priv, 0x0004af, 0x00000000); + nv_icmd(priv, 0x0004b0, 0x00000000); + nv_icmd(priv, 0x0004b1, 0x00000000); + nv_icmd(priv, 0x0004b2, 0x00000000); + nv_icmd(priv, 0x0004b3, 0x00000000); + nv_icmd(priv, 0x0004b4, 0x00000000); + nv_icmd(priv, 0x0004b5, 0x00000000); + nv_icmd(priv, 0x0004b6, 0x00000000); + nv_icmd(priv, 0x0004b7, 0x00000000); + nv_icmd(priv, 0x0004b8, 0x00000000); + nv_icmd(priv, 0x0004b9, 0x00000000); + nv_icmd(priv, 0x0004ba, 0x00000000); + nv_icmd(priv, 0x0004bb, 0x00000000); + nv_icmd(priv, 0x0004bc, 0x00000000); + nv_icmd(priv, 0x0004bd, 0x00000000); + nv_icmd(priv, 0x0004be, 0x00000000); + nv_icmd(priv, 0x0004bf, 0x00000000); + nv_icmd(priv, 0x0004c0, 0x00000000); + nv_icmd(priv, 0x0004c1, 0x00000000); + nv_icmd(priv, 0x0004c2, 0x00000000); + nv_icmd(priv, 0x0004c3, 0x00000000); + nv_icmd(priv, 0x0004c4, 0x00000000); + nv_icmd(priv, 0x0004c5, 0x00000000); + nv_icmd(priv, 0x0004c6, 0x00000000); + nv_icmd(priv, 0x0004c7, 0x00000000); + nv_icmd(priv, 0x0004c8, 0x00000000); + nv_icmd(priv, 0x0004c9, 0x00000000); + nv_icmd(priv, 0x0004ca, 0x00000000); + nv_icmd(priv, 0x0004cb, 0x00000000); + nv_icmd(priv, 0x0004cc, 0x00000000); + nv_icmd(priv, 0x0004cd, 0x00000000); + nv_icmd(priv, 0x0004ce, 0x00000000); + nv_icmd(priv, 0x0004cf, 0x00000000); + nv_icmd(priv, 0x000510, 0x3f800000); + nv_icmd(priv, 0x000511, 0x3f800000); + nv_icmd(priv, 0x000512, 0x3f800000); + nv_icmd(priv, 0x000513, 0x3f800000); + nv_icmd(priv, 0x000514, 0x3f800000); + nv_icmd(priv, 0x000515, 0x3f800000); + nv_icmd(priv, 0x000516, 0x3f800000); + nv_icmd(priv, 0x000517, 0x3f800000); + nv_icmd(priv, 0x000518, 0x3f800000); + nv_icmd(priv, 0x000519, 0x3f800000); + nv_icmd(priv, 0x00051a, 0x3f800000); + nv_icmd(priv, 0x00051b, 0x3f800000); + nv_icmd(priv, 0x00051c, 0x3f800000); + nv_icmd(priv, 0x00051d, 0x3f800000); + nv_icmd(priv, 0x00051e, 0x3f800000); + nv_icmd(priv, 0x00051f, 0x3f800000); + nv_icmd(priv, 0x000520, 0x000002b6); + nv_icmd(priv, 0x000529, 0x00000001); + nv_icmd(priv, 0x000530, 0xffff0000); + nv_icmd(priv, 0x000531, 0xffff0000); + nv_icmd(priv, 0x000532, 0xffff0000); + nv_icmd(priv, 0x000533, 0xffff0000); + nv_icmd(priv, 0x000534, 0xffff0000); + nv_icmd(priv, 0x000535, 0xffff0000); + nv_icmd(priv, 0x000536, 0xffff0000); + nv_icmd(priv, 0x000537, 0xffff0000); + nv_icmd(priv, 0x000538, 0xffff0000); + nv_icmd(priv, 0x000539, 0xffff0000); + nv_icmd(priv, 0x00053a, 0xffff0000); + nv_icmd(priv, 0x00053b, 0xffff0000); + nv_icmd(priv, 0x00053c, 0xffff0000); + nv_icmd(priv, 0x00053d, 0xffff0000); + nv_icmd(priv, 0x00053e, 0xffff0000); + nv_icmd(priv, 0x00053f, 0xffff0000); + nv_icmd(priv, 0x000585, 0x0000003f); + nv_icmd(priv, 0x000576, 0x00000003); + nv_icmd(priv, 0x00057b, 0x00000059); + nv_icmd(priv, 0x000586, 0x00000040); + nv_icmd(priv, 0x000582, 0x00000080); + nv_icmd(priv, 0x000583, 0x00000080); + nv_icmd(priv, 0x0005c2, 0x00000001); + nv_icmd(priv, 0x000638, 0x00000001); + nv_icmd(priv, 0x000639, 0x00000001); + nv_icmd(priv, 0x00063a, 0x00000002); + nv_icmd(priv, 0x00063b, 0x00000001); + nv_icmd(priv, 0x00063c, 0x00000001); + nv_icmd(priv, 0x00063d, 0x00000002); + nv_icmd(priv, 0x00063e, 0x00000001); + nv_icmd(priv, 0x0008b8, 0x00000001); + nv_icmd(priv, 0x0008b9, 0x00000001); + nv_icmd(priv, 0x0008ba, 0x00000001); + nv_icmd(priv, 0x0008bb, 0x00000001); + nv_icmd(priv, 0x0008bc, 0x00000001); + nv_icmd(priv, 0x0008bd, 0x00000001); + nv_icmd(priv, 0x0008be, 0x00000001); + nv_icmd(priv, 0x0008bf, 0x00000001); + nv_icmd(priv, 0x000900, 0x00000001); + nv_icmd(priv, 0x000901, 0x00000001); + nv_icmd(priv, 0x000902, 0x00000001); + nv_icmd(priv, 0x000903, 0x00000001); + nv_icmd(priv, 0x000904, 0x00000001); + nv_icmd(priv, 0x000905, 0x00000001); + nv_icmd(priv, 0x000906, 0x00000001); + nv_icmd(priv, 0x000907, 0x00000001); + nv_icmd(priv, 0x000908, 0x00000002); + nv_icmd(priv, 0x000909, 0x00000002); + nv_icmd(priv, 0x00090a, 0x00000002); + nv_icmd(priv, 0x00090b, 0x00000002); + nv_icmd(priv, 0x00090c, 0x00000002); + nv_icmd(priv, 0x00090d, 0x00000002); + nv_icmd(priv, 0x00090e, 0x00000002); + nv_icmd(priv, 0x00090f, 0x00000002); + nv_icmd(priv, 0x000910, 0x00000001); + nv_icmd(priv, 0x000911, 0x00000001); + nv_icmd(priv, 0x000912, 0x00000001); + nv_icmd(priv, 0x000913, 0x00000001); + nv_icmd(priv, 0x000914, 0x00000001); + nv_icmd(priv, 0x000915, 0x00000001); + nv_icmd(priv, 0x000916, 0x00000001); + nv_icmd(priv, 0x000917, 0x00000001); + nv_icmd(priv, 0x000918, 0x00000001); + nv_icmd(priv, 0x000919, 0x00000001); + nv_icmd(priv, 0x00091a, 0x00000001); + nv_icmd(priv, 0x00091b, 0x00000001); + nv_icmd(priv, 0x00091c, 0x00000001); + nv_icmd(priv, 0x00091d, 0x00000001); + nv_icmd(priv, 0x00091e, 0x00000001); + nv_icmd(priv, 0x00091f, 0x00000001); + nv_icmd(priv, 0x000920, 0x00000002); + nv_icmd(priv, 0x000921, 0x00000002); + nv_icmd(priv, 0x000922, 0x00000002); + nv_icmd(priv, 0x000923, 0x00000002); + nv_icmd(priv, 0x000924, 0x00000002); + nv_icmd(priv, 0x000925, 0x00000002); + nv_icmd(priv, 0x000926, 0x00000002); + nv_icmd(priv, 0x000927, 0x00000002); + nv_icmd(priv, 0x000928, 0x00000001); + nv_icmd(priv, 0x000929, 0x00000001); + nv_icmd(priv, 0x00092a, 0x00000001); + nv_icmd(priv, 0x00092b, 0x00000001); + nv_icmd(priv, 0x00092c, 0x00000001); + nv_icmd(priv, 0x00092d, 0x00000001); + nv_icmd(priv, 0x00092e, 0x00000001); + nv_icmd(priv, 0x00092f, 0x00000001); + nv_icmd(priv, 0x000648, 0x00000001); + nv_icmd(priv, 0x000649, 0x00000001); + nv_icmd(priv, 0x00064a, 0x00000001); + nv_icmd(priv, 0x00064b, 0x00000001); + nv_icmd(priv, 0x00064c, 0x00000001); + nv_icmd(priv, 0x00064d, 0x00000001); + nv_icmd(priv, 0x00064e, 0x00000001); + nv_icmd(priv, 0x00064f, 0x00000001); + nv_icmd(priv, 0x000650, 0x00000001); + nv_icmd(priv, 0x000658, 0x0000000f); + nv_icmd(priv, 0x0007ff, 0x0000000a); + nv_icmd(priv, 0x00066a, 0x40000000); + nv_icmd(priv, 0x00066b, 0x10000000); + nv_icmd(priv, 0x00066c, 0xffff0000); + nv_icmd(priv, 0x00066d, 0xffff0000); + nv_icmd(priv, 0x0007af, 0x00000008); + nv_icmd(priv, 0x0007b0, 0x00000008); + nv_icmd(priv, 0x0007f6, 0x00000001); + nv_icmd(priv, 0x0006b2, 0x00000055); + nv_icmd(priv, 0x0007ad, 0x00000003); + nv_icmd(priv, 0x000937, 0x00000001); + nv_icmd(priv, 0x000971, 0x00000008); + nv_icmd(priv, 0x000972, 0x00000040); + nv_icmd(priv, 0x000973, 0x0000012c); + nv_icmd(priv, 0x00097c, 0x00000040); + nv_icmd(priv, 0x000979, 0x00000003); + nv_icmd(priv, 0x000975, 0x00000020); + nv_icmd(priv, 0x000976, 0x00000001); + nv_icmd(priv, 0x000977, 0x00000020); + nv_icmd(priv, 0x000978, 0x00000001); + nv_icmd(priv, 0x000957, 0x00000003); + nv_icmd(priv, 0x00095e, 0x20164010); + nv_icmd(priv, 0x00095f, 0x00000020); + nv_icmd(priv, 0x00097d, 0x00000020); + nv_icmd(priv, 0x000683, 0x00000006); + nv_icmd(priv, 0x000685, 0x003fffff); + nv_icmd(priv, 0x000687, 0x003fffff); + nv_icmd(priv, 0x0006a0, 0x00000005); + nv_icmd(priv, 0x000840, 0x00400008); + nv_icmd(priv, 0x000841, 0x08000080); + nv_icmd(priv, 0x000842, 0x00400008); + nv_icmd(priv, 0x000843, 0x08000080); + nv_icmd(priv, 0x000818, 0x00000000); + nv_icmd(priv, 0x000819, 0x00000000); + nv_icmd(priv, 0x00081a, 0x00000000); + nv_icmd(priv, 0x00081b, 0x00000000); + nv_icmd(priv, 0x00081c, 0x00000000); + nv_icmd(priv, 0x00081d, 0x00000000); + nv_icmd(priv, 0x00081e, 0x00000000); + nv_icmd(priv, 0x00081f, 0x00000000); + nv_icmd(priv, 0x000848, 0x00000000); + nv_icmd(priv, 0x000849, 0x00000000); + nv_icmd(priv, 0x00084a, 0x00000000); + nv_icmd(priv, 0x00084b, 0x00000000); + nv_icmd(priv, 0x00084c, 0x00000000); + nv_icmd(priv, 0x00084d, 0x00000000); + nv_icmd(priv, 0x00084e, 0x00000000); + nv_icmd(priv, 0x00084f, 0x00000000); + nv_icmd(priv, 0x000850, 0x00000000); + nv_icmd(priv, 0x000851, 0x00000000); + nv_icmd(priv, 0x000852, 0x00000000); + nv_icmd(priv, 0x000853, 0x00000000); + nv_icmd(priv, 0x000854, 0x00000000); + nv_icmd(priv, 0x000855, 0x00000000); + nv_icmd(priv, 0x000856, 0x00000000); + nv_icmd(priv, 0x000857, 0x00000000); + nv_icmd(priv, 0x000738, 0x00000000); + nv_icmd(priv, 0x0006aa, 0x00000001); + nv_icmd(priv, 0x0006ab, 0x00000002); + nv_icmd(priv, 0x0006ac, 0x00000080); + nv_icmd(priv, 0x0006ad, 0x00000100); + nv_icmd(priv, 0x0006ae, 0x00000100); + nv_icmd(priv, 0x0006b1, 0x00000011); + nv_icmd(priv, 0x0006bb, 0x000000cf); + nv_icmd(priv, 0x0006ce, 0x2a712488); + nv_icmd(priv, 0x000739, 0x4085c000); + nv_icmd(priv, 0x00073a, 0x00000080); + nv_icmd(priv, 0x000786, 0x80000100); + nv_icmd(priv, 0x00073c, 0x00010100); + nv_icmd(priv, 0x00073d, 0x02800000); + nv_icmd(priv, 0x000787, 0x000000cf); + nv_icmd(priv, 0x00078c, 0x00000008); + nv_icmd(priv, 0x000792, 0x00000001); + nv_icmd(priv, 0x000794, 0x00000001); + nv_icmd(priv, 0x000795, 0x00000001); + nv_icmd(priv, 0x000796, 0x00000001); + nv_icmd(priv, 0x000797, 0x000000cf); + nv_icmd(priv, 0x000836, 0x00000001); + nv_icmd(priv, 0x00079a, 0x00000002); + nv_icmd(priv, 0x000833, 0x04444480); + nv_icmd(priv, 0x0007a1, 0x00000001); + nv_icmd(priv, 0x0007a3, 0x00000001); + nv_icmd(priv, 0x0007a4, 0x00000001); + nv_icmd(priv, 0x0007a5, 0x00000001); + nv_icmd(priv, 0x000831, 0x00000004); + nv_icmd(priv, 0x000b07, 0x00000002); + nv_icmd(priv, 0x000b08, 0x00000100); + nv_icmd(priv, 0x000b09, 0x00000100); + nv_icmd(priv, 0x000b0a, 0x00000001); + nv_icmd(priv, 0x000a04, 0x000000ff); + nv_icmd(priv, 0x000a0b, 0x00000040); + nv_icmd(priv, 0x00097f, 0x00000100); + nv_icmd(priv, 0x000a02, 0x00000001); + nv_icmd(priv, 0x000809, 0x00000007); + nv_icmd(priv, 0x00c221, 0x00000040); + nv_icmd(priv, 0x00c1b0, 0x0000000f); + nv_icmd(priv, 0x00c1b1, 0x0000000f); + nv_icmd(priv, 0x00c1b2, 0x0000000f); + nv_icmd(priv, 0x00c1b3, 0x0000000f); + nv_icmd(priv, 0x00c1b4, 0x0000000f); + nv_icmd(priv, 0x00c1b5, 0x0000000f); + nv_icmd(priv, 0x00c1b6, 0x0000000f); + nv_icmd(priv, 0x00c1b7, 0x0000000f); + nv_icmd(priv, 0x00c1b8, 0x0fac6881); + nv_icmd(priv, 0x00c1b9, 0x00fac688); + nv_icmd(priv, 0x00c401, 0x00000001); + nv_icmd(priv, 0x00c402, 0x00010001); + nv_icmd(priv, 0x00c403, 0x00000001); + nv_icmd(priv, 0x00c404, 0x00000001); + nv_icmd(priv, 0x00c40e, 0x00000020); + nv_icmd(priv, 0x00c500, 0x00000003); + nv_icmd(priv, 0x01e100, 0x00000001); + nv_icmd(priv, 0x001000, 0x00000002); + nv_icmd(priv, 0x0006aa, 0x00000001); + nv_icmd(priv, 0x0006ad, 0x00000100); + nv_icmd(priv, 0x0006ae, 0x00000100); + nv_icmd(priv, 0x0006b1, 0x00000011); + nv_icmd(priv, 0x00078c, 0x00000008); + nv_icmd(priv, 0x000792, 0x00000001); + nv_icmd(priv, 0x000794, 0x00000001); + nv_icmd(priv, 0x000795, 0x00000001); + nv_icmd(priv, 0x000796, 0x00000001); + nv_icmd(priv, 0x000797, 0x000000cf); + nv_icmd(priv, 0x00079a, 0x00000002); + nv_icmd(priv, 0x000833, 0x04444480); + nv_icmd(priv, 0x0007a1, 0x00000001); + nv_icmd(priv, 0x0007a3, 0x00000001); + nv_icmd(priv, 0x0007a4, 0x00000001); + nv_icmd(priv, 0x0007a5, 0x00000001); + nv_icmd(priv, 0x000831, 0x00000004); + nv_icmd(priv, 0x01e100, 0x00000001); + nv_icmd(priv, 0x001000, 0x00000008); + nv_icmd(priv, 0x000039, 0x00000000); + nv_icmd(priv, 0x00003a, 0x00000000); + nv_icmd(priv, 0x00003b, 0x00000000); + nv_icmd(priv, 0x000380, 0x00000001); + nv_icmd(priv, 0x000366, 0x00000000); + nv_icmd(priv, 0x000367, 0x00000000); + nv_icmd(priv, 0x000368, 0x00000fff); + nv_icmd(priv, 0x000370, 0x00000000); + nv_icmd(priv, 0x000371, 0x00000000); + nv_icmd(priv, 0x000372, 0x000fffff); + nv_icmd(priv, 0x000813, 0x00000006); + nv_icmd(priv, 0x000814, 0x00000008); + nv_icmd(priv, 0x000957, 0x00000003); + nv_icmd(priv, 0x000818, 0x00000000); + nv_icmd(priv, 0x000819, 0x00000000); + nv_icmd(priv, 0x00081a, 0x00000000); + nv_icmd(priv, 0x00081b, 0x00000000); + nv_icmd(priv, 0x00081c, 0x00000000); + nv_icmd(priv, 0x00081d, 0x00000000); + nv_icmd(priv, 0x00081e, 0x00000000); + nv_icmd(priv, 0x00081f, 0x00000000); + nv_icmd(priv, 0x000848, 0x00000000); + nv_icmd(priv, 0x000849, 0x00000000); + nv_icmd(priv, 0x00084a, 0x00000000); + nv_icmd(priv, 0x00084b, 0x00000000); + nv_icmd(priv, 0x00084c, 0x00000000); + nv_icmd(priv, 0x00084d, 0x00000000); + nv_icmd(priv, 0x00084e, 0x00000000); + nv_icmd(priv, 0x00084f, 0x00000000); + nv_icmd(priv, 0x000850, 0x00000000); + nv_icmd(priv, 0x000851, 0x00000000); + nv_icmd(priv, 0x000852, 0x00000000); + nv_icmd(priv, 0x000853, 0x00000000); + nv_icmd(priv, 0x000854, 0x00000000); + nv_icmd(priv, 0x000855, 0x00000000); + nv_icmd(priv, 0x000856, 0x00000000); + nv_icmd(priv, 0x000857, 0x00000000); + nv_icmd(priv, 0x000738, 0x00000000); + nv_icmd(priv, 0x000b07, 0x00000002); + nv_icmd(priv, 0x000b08, 0x00000100); + nv_icmd(priv, 0x000b09, 0x00000100); + nv_icmd(priv, 0x000b0a, 0x00000001); + nv_icmd(priv, 0x000a04, 0x000000ff); + nv_icmd(priv, 0x00097f, 0x00000100); + nv_icmd(priv, 0x000a02, 0x00000001); + nv_icmd(priv, 0x000809, 0x00000007); + nv_icmd(priv, 0x00c221, 0x00000040); + nv_icmd(priv, 0x00c401, 0x00000001); + nv_icmd(priv, 0x00c402, 0x00010001); + nv_icmd(priv, 0x00c403, 0x00000001); + nv_icmd(priv, 0x00c404, 0x00000001); + nv_icmd(priv, 0x00c40e, 0x00000020); + nv_icmd(priv, 0x00c500, 0x00000003); + nv_icmd(priv, 0x01e100, 0x00000001); + nv_icmd(priv, 0x001000, 0x00000001); + nv_icmd(priv, 0x000b07, 0x00000002); + nv_icmd(priv, 0x000b08, 0x00000100); + nv_icmd(priv, 0x000b09, 0x00000100); + nv_icmd(priv, 0x000b0a, 0x00000001); + nv_icmd(priv, 0x01e100, 0x00000001); + nv_wr32(priv, 0x400208, 0x00000000); } static void -nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data) +nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) { - nv_wr32(dev, 0x40448c, data); - nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class); + nv_wr32(priv, 0x40448c, data); + nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); } static void -nve0_grctx_generate_a097(struct drm_device *dev) +nve0_grctx_generate_a097(struct drm_device *priv) { - nv_mthd(dev, 0xa097, 0x0800, 0x00000000); - nv_mthd(dev, 0xa097, 0x0840, 0x00000000); - nv_mthd(dev, 0xa097, 0x0880, 0x00000000); - nv_mthd(dev, 0xa097, 0x08c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0900, 0x00000000); - nv_mthd(dev, 0xa097, 0x0940, 0x00000000); - nv_mthd(dev, 0xa097, 0x0980, 0x00000000); - nv_mthd(dev, 0xa097, 0x09c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0804, 0x00000000); - nv_mthd(dev, 0xa097, 0x0844, 0x00000000); - nv_mthd(dev, 0xa097, 0x0884, 0x00000000); - nv_mthd(dev, 0xa097, 0x08c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0904, 0x00000000); - nv_mthd(dev, 0xa097, 0x0944, 0x00000000); - nv_mthd(dev, 0xa097, 0x0984, 0x00000000); - nv_mthd(dev, 0xa097, 0x09c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0808, 0x00000400); - nv_mthd(dev, 0xa097, 0x0848, 0x00000400); - nv_mthd(dev, 0xa097, 0x0888, 0x00000400); - nv_mthd(dev, 0xa097, 0x08c8, 0x00000400); - nv_mthd(dev, 0xa097, 0x0908, 0x00000400); - nv_mthd(dev, 0xa097, 0x0948, 0x00000400); - nv_mthd(dev, 0xa097, 0x0988, 0x00000400); - nv_mthd(dev, 0xa097, 0x09c8, 0x00000400); - nv_mthd(dev, 0xa097, 0x080c, 0x00000300); - nv_mthd(dev, 0xa097, 0x084c, 0x00000300); - nv_mthd(dev, 0xa097, 0x088c, 0x00000300); - nv_mthd(dev, 0xa097, 0x08cc, 0x00000300); - nv_mthd(dev, 0xa097, 0x090c, 0x00000300); - nv_mthd(dev, 0xa097, 0x094c, 0x00000300); - nv_mthd(dev, 0xa097, 0x098c, 0x00000300); - nv_mthd(dev, 0xa097, 0x09cc, 0x00000300); - nv_mthd(dev, 0xa097, 0x0810, 0x000000cf); - nv_mthd(dev, 0xa097, 0x0850, 0x00000000); - nv_mthd(dev, 0xa097, 0x0890, 0x00000000); - nv_mthd(dev, 0xa097, 0x08d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0910, 0x00000000); - nv_mthd(dev, 0xa097, 0x0950, 0x00000000); - nv_mthd(dev, 0xa097, 0x0990, 0x00000000); - nv_mthd(dev, 0xa097, 0x09d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0814, 0x00000040); - nv_mthd(dev, 0xa097, 0x0854, 0x00000040); - nv_mthd(dev, 0xa097, 0x0894, 0x00000040); - nv_mthd(dev, 0xa097, 0x08d4, 0x00000040); - nv_mthd(dev, 0xa097, 0x0914, 0x00000040); - nv_mthd(dev, 0xa097, 0x0954, 0x00000040); - nv_mthd(dev, 0xa097, 0x0994, 0x00000040); - nv_mthd(dev, 0xa097, 0x09d4, 0x00000040); - nv_mthd(dev, 0xa097, 0x0818, 0x00000001); - nv_mthd(dev, 0xa097, 0x0858, 0x00000001); - nv_mthd(dev, 0xa097, 0x0898, 0x00000001); - nv_mthd(dev, 0xa097, 0x08d8, 0x00000001); - nv_mthd(dev, 0xa097, 0x0918, 0x00000001); - nv_mthd(dev, 0xa097, 0x0958, 0x00000001); - nv_mthd(dev, 0xa097, 0x0998, 0x00000001); - nv_mthd(dev, 0xa097, 0x09d8, 0x00000001); - nv_mthd(dev, 0xa097, 0x081c, 0x00000000); - nv_mthd(dev, 0xa097, 0x085c, 0x00000000); - nv_mthd(dev, 0xa097, 0x089c, 0x00000000); - nv_mthd(dev, 0xa097, 0x08dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x091c, 0x00000000); - nv_mthd(dev, 0xa097, 0x095c, 0x00000000); - nv_mthd(dev, 0xa097, 0x099c, 0x00000000); - nv_mthd(dev, 0xa097, 0x09dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0820, 0x00000000); - nv_mthd(dev, 0xa097, 0x0860, 0x00000000); - nv_mthd(dev, 0xa097, 0x08a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x08e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0920, 0x00000000); - nv_mthd(dev, 0xa097, 0x0960, 0x00000000); - nv_mthd(dev, 0xa097, 0x09a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x09e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c00, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c10, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c20, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c30, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c40, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c50, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c60, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c70, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c80, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c90, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ca0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cb0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cc0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cd0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ce0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cf0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c04, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c14, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c24, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c34, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c44, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c54, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c64, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c74, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c84, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c94, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ca4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cb4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cc4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cd4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ce4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cf4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c08, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c18, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c28, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c38, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c48, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c58, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c68, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c78, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c88, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c98, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ca8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cb8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cc8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cd8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ce8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cf8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c0c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c1c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c2c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c3c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c4c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c5c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c6c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c7c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1c9c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cac, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cbc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ccc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cdc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cec, 0x00000000); - nv_mthd(dev, 0xa097, 0x1cfc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d00, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d10, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d20, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d30, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d40, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d50, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d60, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d70, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d80, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d90, 0x00000000); - nv_mthd(dev, 0xa097, 0x1da0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1db0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dc0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dd0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1de0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1df0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d04, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d14, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d24, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d34, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d44, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d54, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d64, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d74, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d84, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d94, 0x00000000); - nv_mthd(dev, 0xa097, 0x1da4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1db4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dc4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dd4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1de4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1df4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d08, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d18, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d28, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d38, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d48, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d58, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d68, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d78, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d88, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d98, 0x00000000); - nv_mthd(dev, 0xa097, 0x1da8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1db8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dc8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dd8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1de8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1df8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d0c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d1c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d2c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d3c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d4c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d5c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d6c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d7c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1d9c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dac, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dbc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dcc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ddc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dec, 0x00000000); - nv_mthd(dev, 0xa097, 0x1dfc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f00, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f08, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f10, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f18, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f20, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f28, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f30, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f38, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f40, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f48, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f50, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f58, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f60, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f68, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f70, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f78, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f04, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f0c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f14, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f1c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f24, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f2c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f34, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f3c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f44, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f4c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f54, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f5c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f64, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f6c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f74, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f7c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f80, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f88, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f90, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f98, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fa0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fa8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fb0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fb8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fc0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fc8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fd0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fd8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fe0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fe8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ff0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ff8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f84, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f94, 0x00000000); - nv_mthd(dev, 0xa097, 0x1f9c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fa4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fac, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fb4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fbc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fc4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fcc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fd4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fdc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fe4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1fec, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ff4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1ffc, 0x00000000); - nv_mthd(dev, 0xa097, 0x2000, 0x00000000); - nv_mthd(dev, 0xa097, 0x2040, 0x00000011); - nv_mthd(dev, 0xa097, 0x2080, 0x00000020); - nv_mthd(dev, 0xa097, 0x20c0, 0x00000030); - nv_mthd(dev, 0xa097, 0x2100, 0x00000040); - nv_mthd(dev, 0xa097, 0x2140, 0x00000051); - nv_mthd(dev, 0xa097, 0x200c, 0x00000001); - nv_mthd(dev, 0xa097, 0x204c, 0x00000001); - nv_mthd(dev, 0xa097, 0x208c, 0x00000001); - nv_mthd(dev, 0xa097, 0x20cc, 0x00000001); - nv_mthd(dev, 0xa097, 0x210c, 0x00000001); - nv_mthd(dev, 0xa097, 0x214c, 0x00000001); - nv_mthd(dev, 0xa097, 0x2010, 0x00000000); - nv_mthd(dev, 0xa097, 0x2050, 0x00000000); - nv_mthd(dev, 0xa097, 0x2090, 0x00000001); - nv_mthd(dev, 0xa097, 0x20d0, 0x00000002); - nv_mthd(dev, 0xa097, 0x2110, 0x00000003); - nv_mthd(dev, 0xa097, 0x2150, 0x00000004); - nv_mthd(dev, 0xa097, 0x0380, 0x00000000); - nv_mthd(dev, 0xa097, 0x03a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x03c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x03e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0384, 0x00000000); - nv_mthd(dev, 0xa097, 0x03a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x03c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x03e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0388, 0x00000000); - nv_mthd(dev, 0xa097, 0x03a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x03c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x03e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x038c, 0x00000000); - nv_mthd(dev, 0xa097, 0x03ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x03cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x03ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x0700, 0x00000000); - nv_mthd(dev, 0xa097, 0x0710, 0x00000000); - nv_mthd(dev, 0xa097, 0x0720, 0x00000000); - nv_mthd(dev, 0xa097, 0x0730, 0x00000000); - nv_mthd(dev, 0xa097, 0x0704, 0x00000000); - nv_mthd(dev, 0xa097, 0x0714, 0x00000000); - nv_mthd(dev, 0xa097, 0x0724, 0x00000000); - nv_mthd(dev, 0xa097, 0x0734, 0x00000000); - nv_mthd(dev, 0xa097, 0x0708, 0x00000000); - nv_mthd(dev, 0xa097, 0x0718, 0x00000000); - nv_mthd(dev, 0xa097, 0x0728, 0x00000000); - nv_mthd(dev, 0xa097, 0x0738, 0x00000000); - nv_mthd(dev, 0xa097, 0x2800, 0x00000000); - nv_mthd(dev, 0xa097, 0x2804, 0x00000000); - nv_mthd(dev, 0xa097, 0x2808, 0x00000000); - nv_mthd(dev, 0xa097, 0x280c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2810, 0x00000000); - nv_mthd(dev, 0xa097, 0x2814, 0x00000000); - nv_mthd(dev, 0xa097, 0x2818, 0x00000000); - nv_mthd(dev, 0xa097, 0x281c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2820, 0x00000000); - nv_mthd(dev, 0xa097, 0x2824, 0x00000000); - nv_mthd(dev, 0xa097, 0x2828, 0x00000000); - nv_mthd(dev, 0xa097, 0x282c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2830, 0x00000000); - nv_mthd(dev, 0xa097, 0x2834, 0x00000000); - nv_mthd(dev, 0xa097, 0x2838, 0x00000000); - nv_mthd(dev, 0xa097, 0x283c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2840, 0x00000000); - nv_mthd(dev, 0xa097, 0x2844, 0x00000000); - nv_mthd(dev, 0xa097, 0x2848, 0x00000000); - nv_mthd(dev, 0xa097, 0x284c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2850, 0x00000000); - nv_mthd(dev, 0xa097, 0x2854, 0x00000000); - nv_mthd(dev, 0xa097, 0x2858, 0x00000000); - nv_mthd(dev, 0xa097, 0x285c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2860, 0x00000000); - nv_mthd(dev, 0xa097, 0x2864, 0x00000000); - nv_mthd(dev, 0xa097, 0x2868, 0x00000000); - nv_mthd(dev, 0xa097, 0x286c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2870, 0x00000000); - nv_mthd(dev, 0xa097, 0x2874, 0x00000000); - nv_mthd(dev, 0xa097, 0x2878, 0x00000000); - nv_mthd(dev, 0xa097, 0x287c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2880, 0x00000000); - nv_mthd(dev, 0xa097, 0x2884, 0x00000000); - nv_mthd(dev, 0xa097, 0x2888, 0x00000000); - nv_mthd(dev, 0xa097, 0x288c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2890, 0x00000000); - nv_mthd(dev, 0xa097, 0x2894, 0x00000000); - nv_mthd(dev, 0xa097, 0x2898, 0x00000000); - nv_mthd(dev, 0xa097, 0x289c, 0x00000000); - nv_mthd(dev, 0xa097, 0x28a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x28a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x28a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x28ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x28b0, 0x00000000); - nv_mthd(dev, 0xa097, 0x28b4, 0x00000000); - nv_mthd(dev, 0xa097, 0x28b8, 0x00000000); - nv_mthd(dev, 0xa097, 0x28bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x28c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x28c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x28c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x28cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x28d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x28d4, 0x00000000); - nv_mthd(dev, 0xa097, 0x28d8, 0x00000000); - nv_mthd(dev, 0xa097, 0x28dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x28e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x28e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x28e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x28ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x28f0, 0x00000000); - nv_mthd(dev, 0xa097, 0x28f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x28f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x28fc, 0x00000000); - nv_mthd(dev, 0xa097, 0x2900, 0x00000000); - nv_mthd(dev, 0xa097, 0x2904, 0x00000000); - nv_mthd(dev, 0xa097, 0x2908, 0x00000000); - nv_mthd(dev, 0xa097, 0x290c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2910, 0x00000000); - nv_mthd(dev, 0xa097, 0x2914, 0x00000000); - nv_mthd(dev, 0xa097, 0x2918, 0x00000000); - nv_mthd(dev, 0xa097, 0x291c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2920, 0x00000000); - nv_mthd(dev, 0xa097, 0x2924, 0x00000000); - nv_mthd(dev, 0xa097, 0x2928, 0x00000000); - nv_mthd(dev, 0xa097, 0x292c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2930, 0x00000000); - nv_mthd(dev, 0xa097, 0x2934, 0x00000000); - nv_mthd(dev, 0xa097, 0x2938, 0x00000000); - nv_mthd(dev, 0xa097, 0x293c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2940, 0x00000000); - nv_mthd(dev, 0xa097, 0x2944, 0x00000000); - nv_mthd(dev, 0xa097, 0x2948, 0x00000000); - nv_mthd(dev, 0xa097, 0x294c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2950, 0x00000000); - nv_mthd(dev, 0xa097, 0x2954, 0x00000000); - nv_mthd(dev, 0xa097, 0x2958, 0x00000000); - nv_mthd(dev, 0xa097, 0x295c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2960, 0x00000000); - nv_mthd(dev, 0xa097, 0x2964, 0x00000000); - nv_mthd(dev, 0xa097, 0x2968, 0x00000000); - nv_mthd(dev, 0xa097, 0x296c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2970, 0x00000000); - nv_mthd(dev, 0xa097, 0x2974, 0x00000000); - nv_mthd(dev, 0xa097, 0x2978, 0x00000000); - nv_mthd(dev, 0xa097, 0x297c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2980, 0x00000000); - nv_mthd(dev, 0xa097, 0x2984, 0x00000000); - nv_mthd(dev, 0xa097, 0x2988, 0x00000000); - nv_mthd(dev, 0xa097, 0x298c, 0x00000000); - nv_mthd(dev, 0xa097, 0x2990, 0x00000000); - nv_mthd(dev, 0xa097, 0x2994, 0x00000000); - nv_mthd(dev, 0xa097, 0x2998, 0x00000000); - nv_mthd(dev, 0xa097, 0x299c, 0x00000000); - nv_mthd(dev, 0xa097, 0x29a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x29a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x29a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x29ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x29b0, 0x00000000); - nv_mthd(dev, 0xa097, 0x29b4, 0x00000000); - nv_mthd(dev, 0xa097, 0x29b8, 0x00000000); - nv_mthd(dev, 0xa097, 0x29bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x29c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x29c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x29c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x29cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x29d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x29d4, 0x00000000); - nv_mthd(dev, 0xa097, 0x29d8, 0x00000000); - nv_mthd(dev, 0xa097, 0x29dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x29e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x29e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x29e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x29ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x29f0, 0x00000000); - nv_mthd(dev, 0xa097, 0x29f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x29f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x29fc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a00, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a20, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a40, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a60, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a80, 0x00000000); - nv_mthd(dev, 0xa097, 0x0aa0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ac0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ae0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b00, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b20, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b40, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b60, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b80, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ba0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bc0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0be0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a04, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a24, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a44, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a64, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a84, 0x00000000); - nv_mthd(dev, 0xa097, 0x0aa4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ac4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ae4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b04, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b24, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b44, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b64, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b84, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ba4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bc4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0be4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a08, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a28, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a48, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a68, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a88, 0x00000000); - nv_mthd(dev, 0xa097, 0x0aa8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ac8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ae8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b08, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b28, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b48, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b68, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b88, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ba8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bc8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0be8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a0c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a2c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a4c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a6c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0aac, 0x00000000); - nv_mthd(dev, 0xa097, 0x0acc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0aec, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b0c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b2c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b4c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b6c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bac, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bcc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bec, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a10, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a30, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a50, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a70, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a90, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ab0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ad0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0af0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b10, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b30, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b50, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b70, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b90, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bb0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bd0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bf0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a14, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a34, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a54, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a74, 0x00000000); - nv_mthd(dev, 0xa097, 0x0a94, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ab4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ad4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0af4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b14, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b34, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b54, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b74, 0x00000000); - nv_mthd(dev, 0xa097, 0x0b94, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bb4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bd4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0bf4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c00, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c10, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c20, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c30, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c40, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c50, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c60, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c70, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c80, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c90, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ca0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cb0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cc0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cd0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ce0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cf0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c04, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c14, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c24, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c34, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c44, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c54, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c64, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c74, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c84, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c94, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ca4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cb4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cc4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cd4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ce4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cf4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c08, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c18, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c28, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c38, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c48, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c58, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c68, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c78, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c88, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c98, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ca8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cb8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cc8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cd8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ce8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0cf8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0c0c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c1c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c2c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c3c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c4c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c5c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c6c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c7c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c8c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0c9c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0cac, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0cbc, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0ccc, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0cdc, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0cec, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0cfc, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0d00, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d08, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d10, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d18, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d20, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d28, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d30, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d38, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d04, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d0c, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d14, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d1c, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d24, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d2c, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d34, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d3c, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e00, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e10, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e20, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e30, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e40, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e50, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e60, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e70, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e80, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e90, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ea0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0eb0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ec0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ed0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ee0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ef0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0e04, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e14, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e24, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e34, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e44, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e54, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e64, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e74, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e84, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e94, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ea4, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0eb4, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ec4, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ed4, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ee4, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ef4, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e08, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e18, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e28, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e38, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e48, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e58, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e68, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e78, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e88, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0e98, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ea8, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0eb8, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ec8, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ed8, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ee8, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0ef8, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d40, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d48, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d50, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d58, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d44, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d4c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d54, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d5c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1e00, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e20, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e40, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e60, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e80, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ea0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ec0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ee0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e04, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e24, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e44, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e64, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e84, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ea4, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ec4, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ee4, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e08, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e28, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e48, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e68, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e88, 0x00000002); - nv_mthd(dev, 0xa097, 0x1ea8, 0x00000002); - nv_mthd(dev, 0xa097, 0x1ec8, 0x00000002); - nv_mthd(dev, 0xa097, 0x1ee8, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e0c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e2c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e4c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e6c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e8c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1eac, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ecc, 0x00000001); - nv_mthd(dev, 0xa097, 0x1eec, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e10, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e30, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e50, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e70, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e90, 0x00000001); - nv_mthd(dev, 0xa097, 0x1eb0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ed0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ef0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e14, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e34, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e54, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e74, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e94, 0x00000002); - nv_mthd(dev, 0xa097, 0x1eb4, 0x00000002); - nv_mthd(dev, 0xa097, 0x1ed4, 0x00000002); - nv_mthd(dev, 0xa097, 0x1ef4, 0x00000002); - nv_mthd(dev, 0xa097, 0x1e18, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e38, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e58, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e78, 0x00000001); - nv_mthd(dev, 0xa097, 0x1e98, 0x00000001); - nv_mthd(dev, 0xa097, 0x1eb8, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ed8, 0x00000001); - nv_mthd(dev, 0xa097, 0x1ef8, 0x00000001); - nv_mthd(dev, 0xa097, 0x3400, 0x00000000); - nv_mthd(dev, 0xa097, 0x3404, 0x00000000); - nv_mthd(dev, 0xa097, 0x3408, 0x00000000); - nv_mthd(dev, 0xa097, 0x340c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3410, 0x00000000); - nv_mthd(dev, 0xa097, 0x3414, 0x00000000); - nv_mthd(dev, 0xa097, 0x3418, 0x00000000); - nv_mthd(dev, 0xa097, 0x341c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3420, 0x00000000); - nv_mthd(dev, 0xa097, 0x3424, 0x00000000); - nv_mthd(dev, 0xa097, 0x3428, 0x00000000); - nv_mthd(dev, 0xa097, 0x342c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3430, 0x00000000); - nv_mthd(dev, 0xa097, 0x3434, 0x00000000); - nv_mthd(dev, 0xa097, 0x3438, 0x00000000); - nv_mthd(dev, 0xa097, 0x343c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3440, 0x00000000); - nv_mthd(dev, 0xa097, 0x3444, 0x00000000); - nv_mthd(dev, 0xa097, 0x3448, 0x00000000); - nv_mthd(dev, 0xa097, 0x344c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3450, 0x00000000); - nv_mthd(dev, 0xa097, 0x3454, 0x00000000); - nv_mthd(dev, 0xa097, 0x3458, 0x00000000); - nv_mthd(dev, 0xa097, 0x345c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3460, 0x00000000); - nv_mthd(dev, 0xa097, 0x3464, 0x00000000); - nv_mthd(dev, 0xa097, 0x3468, 0x00000000); - nv_mthd(dev, 0xa097, 0x346c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3470, 0x00000000); - nv_mthd(dev, 0xa097, 0x3474, 0x00000000); - nv_mthd(dev, 0xa097, 0x3478, 0x00000000); - nv_mthd(dev, 0xa097, 0x347c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3480, 0x00000000); - nv_mthd(dev, 0xa097, 0x3484, 0x00000000); - nv_mthd(dev, 0xa097, 0x3488, 0x00000000); - nv_mthd(dev, 0xa097, 0x348c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3490, 0x00000000); - nv_mthd(dev, 0xa097, 0x3494, 0x00000000); - nv_mthd(dev, 0xa097, 0x3498, 0x00000000); - nv_mthd(dev, 0xa097, 0x349c, 0x00000000); - nv_mthd(dev, 0xa097, 0x34a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x34a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x34a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x34ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x34b0, 0x00000000); - nv_mthd(dev, 0xa097, 0x34b4, 0x00000000); - nv_mthd(dev, 0xa097, 0x34b8, 0x00000000); - nv_mthd(dev, 0xa097, 0x34bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x34c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x34c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x34c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x34cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x34d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x34d4, 0x00000000); - nv_mthd(dev, 0xa097, 0x34d8, 0x00000000); - nv_mthd(dev, 0xa097, 0x34dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x34e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x34e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x34e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x34ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x34f0, 0x00000000); - nv_mthd(dev, 0xa097, 0x34f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x34f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x34fc, 0x00000000); - nv_mthd(dev, 0xa097, 0x3500, 0x00000000); - nv_mthd(dev, 0xa097, 0x3504, 0x00000000); - nv_mthd(dev, 0xa097, 0x3508, 0x00000000); - nv_mthd(dev, 0xa097, 0x350c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3510, 0x00000000); - nv_mthd(dev, 0xa097, 0x3514, 0x00000000); - nv_mthd(dev, 0xa097, 0x3518, 0x00000000); - nv_mthd(dev, 0xa097, 0x351c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3520, 0x00000000); - nv_mthd(dev, 0xa097, 0x3524, 0x00000000); - nv_mthd(dev, 0xa097, 0x3528, 0x00000000); - nv_mthd(dev, 0xa097, 0x352c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3530, 0x00000000); - nv_mthd(dev, 0xa097, 0x3534, 0x00000000); - nv_mthd(dev, 0xa097, 0x3538, 0x00000000); - nv_mthd(dev, 0xa097, 0x353c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3540, 0x00000000); - nv_mthd(dev, 0xa097, 0x3544, 0x00000000); - nv_mthd(dev, 0xa097, 0x3548, 0x00000000); - nv_mthd(dev, 0xa097, 0x354c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3550, 0x00000000); - nv_mthd(dev, 0xa097, 0x3554, 0x00000000); - nv_mthd(dev, 0xa097, 0x3558, 0x00000000); - nv_mthd(dev, 0xa097, 0x355c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3560, 0x00000000); - nv_mthd(dev, 0xa097, 0x3564, 0x00000000); - nv_mthd(dev, 0xa097, 0x3568, 0x00000000); - nv_mthd(dev, 0xa097, 0x356c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3570, 0x00000000); - nv_mthd(dev, 0xa097, 0x3574, 0x00000000); - nv_mthd(dev, 0xa097, 0x3578, 0x00000000); - nv_mthd(dev, 0xa097, 0x357c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3580, 0x00000000); - nv_mthd(dev, 0xa097, 0x3584, 0x00000000); - nv_mthd(dev, 0xa097, 0x3588, 0x00000000); - nv_mthd(dev, 0xa097, 0x358c, 0x00000000); - nv_mthd(dev, 0xa097, 0x3590, 0x00000000); - nv_mthd(dev, 0xa097, 0x3594, 0x00000000); - nv_mthd(dev, 0xa097, 0x3598, 0x00000000); - nv_mthd(dev, 0xa097, 0x359c, 0x00000000); - nv_mthd(dev, 0xa097, 0x35a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x35a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x35a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x35ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x35b0, 0x00000000); - nv_mthd(dev, 0xa097, 0x35b4, 0x00000000); - nv_mthd(dev, 0xa097, 0x35b8, 0x00000000); - nv_mthd(dev, 0xa097, 0x35bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x35c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x35c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x35c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x35cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x35d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x35d4, 0x00000000); - nv_mthd(dev, 0xa097, 0x35d8, 0x00000000); - nv_mthd(dev, 0xa097, 0x35dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x35e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x35e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x35e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x35ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x35f0, 0x00000000); - nv_mthd(dev, 0xa097, 0x35f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x35f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x35fc, 0x00000000); - nv_mthd(dev, 0xa097, 0x030c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1944, 0x00000000); - nv_mthd(dev, 0xa097, 0x1514, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d68, 0x0000ffff); - nv_mthd(dev, 0xa097, 0x121c, 0x0fac6881); - nv_mthd(dev, 0xa097, 0x0fac, 0x00000001); - nv_mthd(dev, 0xa097, 0x1538, 0x00000001); - nv_mthd(dev, 0xa097, 0x0fe0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0fe4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0fe8, 0x00000014); - nv_mthd(dev, 0xa097, 0x0fec, 0x00000040); - nv_mthd(dev, 0xa097, 0x0ff0, 0x00000000); - nv_mthd(dev, 0xa097, 0x179c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1228, 0x00000400); - nv_mthd(dev, 0xa097, 0x122c, 0x00000300); - nv_mthd(dev, 0xa097, 0x1230, 0x00010001); - nv_mthd(dev, 0xa097, 0x07f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x15b4, 0x00000001); - nv_mthd(dev, 0xa097, 0x15cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1534, 0x00000000); - nv_mthd(dev, 0xa097, 0x0fb0, 0x00000000); - nv_mthd(dev, 0xa097, 0x15d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x153c, 0x00000000); - nv_mthd(dev, 0xa097, 0x16b4, 0x00000003); - nv_mthd(dev, 0xa097, 0x0fbc, 0x0000ffff); - nv_mthd(dev, 0xa097, 0x0fc0, 0x0000ffff); - nv_mthd(dev, 0xa097, 0x0fc4, 0x0000ffff); - nv_mthd(dev, 0xa097, 0x0fc8, 0x0000ffff); - nv_mthd(dev, 0xa097, 0x0df8, 0x00000000); - nv_mthd(dev, 0xa097, 0x0dfc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1948, 0x00000000); - nv_mthd(dev, 0xa097, 0x1970, 0x00000001); - nv_mthd(dev, 0xa097, 0x161c, 0x000009f0); - nv_mthd(dev, 0xa097, 0x0dcc, 0x00000010); - nv_mthd(dev, 0xa097, 0x163c, 0x00000000); - nv_mthd(dev, 0xa097, 0x15e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1160, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1164, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1168, 0x25e00040); - nv_mthd(dev, 0xa097, 0x116c, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1170, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1174, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1178, 0x25e00040); - nv_mthd(dev, 0xa097, 0x117c, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1180, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1184, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1188, 0x25e00040); - nv_mthd(dev, 0xa097, 0x118c, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1190, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1194, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1198, 0x25e00040); - nv_mthd(dev, 0xa097, 0x119c, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11a0, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11a4, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11a8, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11ac, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11b0, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11b4, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11b8, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11bc, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11c0, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11c4, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11c8, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11cc, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11d0, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11d4, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11d8, 0x25e00040); - nv_mthd(dev, 0xa097, 0x11dc, 0x25e00040); - nv_mthd(dev, 0xa097, 0x1880, 0x00000000); - nv_mthd(dev, 0xa097, 0x1884, 0x00000000); - nv_mthd(dev, 0xa097, 0x1888, 0x00000000); - nv_mthd(dev, 0xa097, 0x188c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1890, 0x00000000); - nv_mthd(dev, 0xa097, 0x1894, 0x00000000); - nv_mthd(dev, 0xa097, 0x1898, 0x00000000); - nv_mthd(dev, 0xa097, 0x189c, 0x00000000); - nv_mthd(dev, 0xa097, 0x18a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x18a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x18a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x18ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x18b0, 0x00000000); - nv_mthd(dev, 0xa097, 0x18b4, 0x00000000); - nv_mthd(dev, 0xa097, 0x18b8, 0x00000000); - nv_mthd(dev, 0xa097, 0x18bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x18c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x18c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x18c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x18cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x18d0, 0x00000000); - nv_mthd(dev, 0xa097, 0x18d4, 0x00000000); - nv_mthd(dev, 0xa097, 0x18d8, 0x00000000); - nv_mthd(dev, 0xa097, 0x18dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x18e0, 0x00000000); - nv_mthd(dev, 0xa097, 0x18e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x18e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x18ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x18f0, 0x00000000); - nv_mthd(dev, 0xa097, 0x18f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x18f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x18fc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f84, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f88, 0x00000000); - nv_mthd(dev, 0xa097, 0x17c8, 0x00000000); - nv_mthd(dev, 0xa097, 0x17cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x17d0, 0x000000ff); - nv_mthd(dev, 0xa097, 0x17d4, 0xffffffff); - nv_mthd(dev, 0xa097, 0x17d8, 0x00000002); - nv_mthd(dev, 0xa097, 0x17dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x15f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x15f8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1434, 0x00000000); - nv_mthd(dev, 0xa097, 0x1438, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d74, 0x00000000); - nv_mthd(dev, 0xa097, 0x0dec, 0x00000001); - nv_mthd(dev, 0xa097, 0x13a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1318, 0x00000001); - nv_mthd(dev, 0xa097, 0x1644, 0x00000000); - nv_mthd(dev, 0xa097, 0x0748, 0x00000000); - nv_mthd(dev, 0xa097, 0x0de8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1648, 0x00000000); - nv_mthd(dev, 0xa097, 0x12a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x1120, 0x00000000); - nv_mthd(dev, 0xa097, 0x1124, 0x00000000); - nv_mthd(dev, 0xa097, 0x1128, 0x00000000); - nv_mthd(dev, 0xa097, 0x112c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1118, 0x00000000); - nv_mthd(dev, 0xa097, 0x164c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1658, 0x00000000); - nv_mthd(dev, 0xa097, 0x1910, 0x00000290); - nv_mthd(dev, 0xa097, 0x1518, 0x00000000); - nv_mthd(dev, 0xa097, 0x165c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1520, 0x00000000); - nv_mthd(dev, 0xa097, 0x1604, 0x00000000); - nv_mthd(dev, 0xa097, 0x1570, 0x00000000); - nv_mthd(dev, 0xa097, 0x13b0, 0x3f800000); - nv_mthd(dev, 0xa097, 0x13b4, 0x3f800000); - nv_mthd(dev, 0xa097, 0x020c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1670, 0x30201000); - nv_mthd(dev, 0xa097, 0x1674, 0x70605040); - nv_mthd(dev, 0xa097, 0x1678, 0xb8a89888); - nv_mthd(dev, 0xa097, 0x167c, 0xf8e8d8c8); - nv_mthd(dev, 0xa097, 0x166c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1680, 0x00ffff00); - nv_mthd(dev, 0xa097, 0x12d0, 0x00000003); - nv_mthd(dev, 0xa097, 0x12d4, 0x00000002); - nv_mthd(dev, 0xa097, 0x1684, 0x00000000); - nv_mthd(dev, 0xa097, 0x1688, 0x00000000); - nv_mthd(dev, 0xa097, 0x0dac, 0x00001b02); - nv_mthd(dev, 0xa097, 0x0db0, 0x00001b02); - nv_mthd(dev, 0xa097, 0x0db4, 0x00000000); - nv_mthd(dev, 0xa097, 0x168c, 0x00000000); - nv_mthd(dev, 0xa097, 0x15bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x156c, 0x00000000); - nv_mthd(dev, 0xa097, 0x187c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1110, 0x00000001); - nv_mthd(dev, 0xa097, 0x0dc0, 0x00000000); - nv_mthd(dev, 0xa097, 0x0dc4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0dc8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1234, 0x00000000); - nv_mthd(dev, 0xa097, 0x1690, 0x00000000); - nv_mthd(dev, 0xa097, 0x12ac, 0x00000001); - nv_mthd(dev, 0xa097, 0x0790, 0x00000000); - nv_mthd(dev, 0xa097, 0x0794, 0x00000000); - nv_mthd(dev, 0xa097, 0x0798, 0x00000000); - nv_mthd(dev, 0xa097, 0x079c, 0x00000000); - nv_mthd(dev, 0xa097, 0x07a0, 0x00000000); - nv_mthd(dev, 0xa097, 0x077c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1000, 0x00000010); - nv_mthd(dev, 0xa097, 0x10fc, 0x00000000); - nv_mthd(dev, 0xa097, 0x1290, 0x00000000); - nv_mthd(dev, 0xa097, 0x0218, 0x00000010); - nv_mthd(dev, 0xa097, 0x12d8, 0x00000000); - nv_mthd(dev, 0xa097, 0x12dc, 0x00000010); - nv_mthd(dev, 0xa097, 0x0d94, 0x00000001); - nv_mthd(dev, 0xa097, 0x155c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1560, 0x00000000); - nv_mthd(dev, 0xa097, 0x1564, 0x00000fff); - nv_mthd(dev, 0xa097, 0x1574, 0x00000000); - nv_mthd(dev, 0xa097, 0x1578, 0x00000000); - nv_mthd(dev, 0xa097, 0x157c, 0x000fffff); - nv_mthd(dev, 0xa097, 0x1354, 0x00000000); - nv_mthd(dev, 0xa097, 0x1610, 0x00000012); - nv_mthd(dev, 0xa097, 0x1608, 0x00000000); - nv_mthd(dev, 0xa097, 0x160c, 0x00000000); - nv_mthd(dev, 0xa097, 0x260c, 0x00000000); - nv_mthd(dev, 0xa097, 0x07ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x162c, 0x00000003); - nv_mthd(dev, 0xa097, 0x0210, 0x00000000); - nv_mthd(dev, 0xa097, 0x0320, 0x00000000); - nv_mthd(dev, 0xa097, 0x0324, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0328, 0x3f800000); - nv_mthd(dev, 0xa097, 0x032c, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0330, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0334, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0338, 0x3f800000); - nv_mthd(dev, 0xa097, 0x0750, 0x00000000); - nv_mthd(dev, 0xa097, 0x0760, 0x39291909); - nv_mthd(dev, 0xa097, 0x0764, 0x79695949); - nv_mthd(dev, 0xa097, 0x0768, 0xb9a99989); - nv_mthd(dev, 0xa097, 0x076c, 0xf9e9d9c9); - nv_mthd(dev, 0xa097, 0x0770, 0x30201000); - nv_mthd(dev, 0xa097, 0x0774, 0x70605040); - nv_mthd(dev, 0xa097, 0x0778, 0x00009080); - nv_mthd(dev, 0xa097, 0x0780, 0x39291909); - nv_mthd(dev, 0xa097, 0x0784, 0x79695949); - nv_mthd(dev, 0xa097, 0x0788, 0xb9a99989); - nv_mthd(dev, 0xa097, 0x078c, 0xf9e9d9c9); - nv_mthd(dev, 0xa097, 0x07d0, 0x30201000); - nv_mthd(dev, 0xa097, 0x07d4, 0x70605040); - nv_mthd(dev, 0xa097, 0x07d8, 0x00009080); - nv_mthd(dev, 0xa097, 0x037c, 0x00000001); - nv_mthd(dev, 0xa097, 0x0740, 0x00000000); - nv_mthd(dev, 0xa097, 0x0744, 0x00000000); - nv_mthd(dev, 0xa097, 0x2600, 0x00000000); - nv_mthd(dev, 0xa097, 0x1918, 0x00000000); - nv_mthd(dev, 0xa097, 0x191c, 0x00000900); - nv_mthd(dev, 0xa097, 0x1920, 0x00000405); - nv_mthd(dev, 0xa097, 0x1308, 0x00000001); - nv_mthd(dev, 0xa097, 0x1924, 0x00000000); - nv_mthd(dev, 0xa097, 0x13ac, 0x00000000); - nv_mthd(dev, 0xa097, 0x192c, 0x00000001); - nv_mthd(dev, 0xa097, 0x193c, 0x00002c1c); - nv_mthd(dev, 0xa097, 0x0d7c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x02c0, 0x00000001); - nv_mthd(dev, 0xa097, 0x1510, 0x00000000); - nv_mthd(dev, 0xa097, 0x1940, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ff4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0ff8, 0x00000000); - nv_mthd(dev, 0xa097, 0x194c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1950, 0x00000000); - nv_mthd(dev, 0xa097, 0x1968, 0x00000000); - nv_mthd(dev, 0xa097, 0x1590, 0x0000003f); - nv_mthd(dev, 0xa097, 0x07e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x07ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x07f0, 0x00000000); - nv_mthd(dev, 0xa097, 0x07f4, 0x00000000); - nv_mthd(dev, 0xa097, 0x196c, 0x00000011); - nv_mthd(dev, 0xa097, 0x02e4, 0x0000b001); - nv_mthd(dev, 0xa097, 0x036c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0370, 0x00000000); - nv_mthd(dev, 0xa097, 0x197c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0fcc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0fd0, 0x00000000); - nv_mthd(dev, 0xa097, 0x02d8, 0x00000040); - nv_mthd(dev, 0xa097, 0x1980, 0x00000080); - nv_mthd(dev, 0xa097, 0x1504, 0x00000080); - nv_mthd(dev, 0xa097, 0x1984, 0x00000000); - nv_mthd(dev, 0xa097, 0x0300, 0x00000001); - nv_mthd(dev, 0xa097, 0x13a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x12ec, 0x00000000); - nv_mthd(dev, 0xa097, 0x1310, 0x00000000); - nv_mthd(dev, 0xa097, 0x1314, 0x00000001); - nv_mthd(dev, 0xa097, 0x1380, 0x00000000); - nv_mthd(dev, 0xa097, 0x1384, 0x00000001); - nv_mthd(dev, 0xa097, 0x1388, 0x00000001); - nv_mthd(dev, 0xa097, 0x138c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1390, 0x00000001); - nv_mthd(dev, 0xa097, 0x1394, 0x00000000); - nv_mthd(dev, 0xa097, 0x139c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1398, 0x00000000); - nv_mthd(dev, 0xa097, 0x1594, 0x00000000); - nv_mthd(dev, 0xa097, 0x1598, 0x00000001); - nv_mthd(dev, 0xa097, 0x159c, 0x00000001); - nv_mthd(dev, 0xa097, 0x15a0, 0x00000001); - nv_mthd(dev, 0xa097, 0x15a4, 0x00000001); - nv_mthd(dev, 0xa097, 0x0f54, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f58, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f5c, 0x00000000); - nv_mthd(dev, 0xa097, 0x19bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f9c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0fa0, 0x00000000); - nv_mthd(dev, 0xa097, 0x12cc, 0x00000000); - nv_mthd(dev, 0xa097, 0x12e8, 0x00000000); - nv_mthd(dev, 0xa097, 0x130c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1360, 0x00000000); - nv_mthd(dev, 0xa097, 0x1364, 0x00000000); - nv_mthd(dev, 0xa097, 0x1368, 0x00000000); - nv_mthd(dev, 0xa097, 0x136c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1370, 0x00000000); - nv_mthd(dev, 0xa097, 0x1374, 0x00000000); - nv_mthd(dev, 0xa097, 0x1378, 0x00000000); - nv_mthd(dev, 0xa097, 0x137c, 0x00000000); - nv_mthd(dev, 0xa097, 0x133c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1340, 0x00000001); - nv_mthd(dev, 0xa097, 0x1344, 0x00000002); - nv_mthd(dev, 0xa097, 0x1348, 0x00000001); - nv_mthd(dev, 0xa097, 0x134c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1350, 0x00000002); - nv_mthd(dev, 0xa097, 0x1358, 0x00000001); - nv_mthd(dev, 0xa097, 0x12e4, 0x00000000); - nv_mthd(dev, 0xa097, 0x131c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1320, 0x00000000); - nv_mthd(dev, 0xa097, 0x1324, 0x00000000); - nv_mthd(dev, 0xa097, 0x1328, 0x00000000); - nv_mthd(dev, 0xa097, 0x19c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x1140, 0x00000000); - nv_mthd(dev, 0xa097, 0x19c4, 0x00000000); - nv_mthd(dev, 0xa097, 0x19c8, 0x00001500); - nv_mthd(dev, 0xa097, 0x135c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f90, 0x00000000); - nv_mthd(dev, 0xa097, 0x19e0, 0x00000001); - nv_mthd(dev, 0xa097, 0x19e4, 0x00000001); - nv_mthd(dev, 0xa097, 0x19e8, 0x00000001); - nv_mthd(dev, 0xa097, 0x19ec, 0x00000001); - nv_mthd(dev, 0xa097, 0x19f0, 0x00000001); - nv_mthd(dev, 0xa097, 0x19f4, 0x00000001); - nv_mthd(dev, 0xa097, 0x19f8, 0x00000001); - nv_mthd(dev, 0xa097, 0x19fc, 0x00000001); - nv_mthd(dev, 0xa097, 0x19cc, 0x00000001); - nv_mthd(dev, 0xa097, 0x15b8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a00, 0x00001111); - nv_mthd(dev, 0xa097, 0x1a04, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a08, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a0c, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a10, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a14, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a18, 0x00000000); - nv_mthd(dev, 0xa097, 0x1a1c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d6c, 0xffff0000); - nv_mthd(dev, 0xa097, 0x0d70, 0xffff0000); - nv_mthd(dev, 0xa097, 0x10f8, 0x00001010); - nv_mthd(dev, 0xa097, 0x0d80, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d84, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d88, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d8c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0d90, 0x00000000); - nv_mthd(dev, 0xa097, 0x0da0, 0x00000000); - nv_mthd(dev, 0xa097, 0x07a4, 0x00000000); - nv_mthd(dev, 0xa097, 0x07a8, 0x00000000); - nv_mthd(dev, 0xa097, 0x1508, 0x80000000); - nv_mthd(dev, 0xa097, 0x150c, 0x40000000); - nv_mthd(dev, 0xa097, 0x1668, 0x00000000); - nv_mthd(dev, 0xa097, 0x0318, 0x00000008); - nv_mthd(dev, 0xa097, 0x031c, 0x00000008); - nv_mthd(dev, 0xa097, 0x0d9c, 0x00000001); - nv_mthd(dev, 0xa097, 0x0374, 0x00000000); - nv_mthd(dev, 0xa097, 0x0378, 0x00000020); - nv_mthd(dev, 0xa097, 0x07dc, 0x00000000); - nv_mthd(dev, 0xa097, 0x074c, 0x00000055); - nv_mthd(dev, 0xa097, 0x1420, 0x00000003); - nv_mthd(dev, 0xa097, 0x17bc, 0x00000000); - nv_mthd(dev, 0xa097, 0x17c0, 0x00000000); - nv_mthd(dev, 0xa097, 0x17c4, 0x00000001); - nv_mthd(dev, 0xa097, 0x1008, 0x00000008); - nv_mthd(dev, 0xa097, 0x100c, 0x00000040); - nv_mthd(dev, 0xa097, 0x1010, 0x0000012c); - nv_mthd(dev, 0xa097, 0x0d60, 0x00000040); - nv_mthd(dev, 0xa097, 0x075c, 0x00000003); - nv_mthd(dev, 0xa097, 0x1018, 0x00000020); - nv_mthd(dev, 0xa097, 0x101c, 0x00000001); - nv_mthd(dev, 0xa097, 0x1020, 0x00000020); - nv_mthd(dev, 0xa097, 0x1024, 0x00000001); - nv_mthd(dev, 0xa097, 0x1444, 0x00000000); - nv_mthd(dev, 0xa097, 0x1448, 0x00000000); - nv_mthd(dev, 0xa097, 0x144c, 0x00000000); - nv_mthd(dev, 0xa097, 0x0360, 0x20164010); - nv_mthd(dev, 0xa097, 0x0364, 0x00000020); - nv_mthd(dev, 0xa097, 0x0368, 0x00000000); - nv_mthd(dev, 0xa097, 0x0de4, 0x00000000); - nv_mthd(dev, 0xa097, 0x0204, 0x00000006); - nv_mthd(dev, 0xa097, 0x0208, 0x00000000); - nv_mthd(dev, 0xa097, 0x02cc, 0x003fffff); - nv_mthd(dev, 0xa097, 0x02d0, 0x003fffff); - nv_mthd(dev, 0xa097, 0x1220, 0x00000005); - nv_mthd(dev, 0xa097, 0x0fdc, 0x00000000); - nv_mthd(dev, 0xa097, 0x0f98, 0x00400008); - nv_mthd(dev, 0xa097, 0x1284, 0x08000080); - nv_mthd(dev, 0xa097, 0x1450, 0x00400008); - nv_mthd(dev, 0xa097, 0x1454, 0x08000080); - nv_mthd(dev, 0xa097, 0x0214, 0x00000000); + nv_mthd(priv, 0xa097, 0x0800, 0x00000000); + nv_mthd(priv, 0xa097, 0x0840, 0x00000000); + nv_mthd(priv, 0xa097, 0x0880, 0x00000000); + nv_mthd(priv, 0xa097, 0x08c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0900, 0x00000000); + nv_mthd(priv, 0xa097, 0x0940, 0x00000000); + nv_mthd(priv, 0xa097, 0x0980, 0x00000000); + nv_mthd(priv, 0xa097, 0x09c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0804, 0x00000000); + nv_mthd(priv, 0xa097, 0x0844, 0x00000000); + nv_mthd(priv, 0xa097, 0x0884, 0x00000000); + nv_mthd(priv, 0xa097, 0x08c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0904, 0x00000000); + nv_mthd(priv, 0xa097, 0x0944, 0x00000000); + nv_mthd(priv, 0xa097, 0x0984, 0x00000000); + nv_mthd(priv, 0xa097, 0x09c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0808, 0x00000400); + nv_mthd(priv, 0xa097, 0x0848, 0x00000400); + nv_mthd(priv, 0xa097, 0x0888, 0x00000400); + nv_mthd(priv, 0xa097, 0x08c8, 0x00000400); + nv_mthd(priv, 0xa097, 0x0908, 0x00000400); + nv_mthd(priv, 0xa097, 0x0948, 0x00000400); + nv_mthd(priv, 0xa097, 0x0988, 0x00000400); + nv_mthd(priv, 0xa097, 0x09c8, 0x00000400); + nv_mthd(priv, 0xa097, 0x080c, 0x00000300); + nv_mthd(priv, 0xa097, 0x084c, 0x00000300); + nv_mthd(priv, 0xa097, 0x088c, 0x00000300); + nv_mthd(priv, 0xa097, 0x08cc, 0x00000300); + nv_mthd(priv, 0xa097, 0x090c, 0x00000300); + nv_mthd(priv, 0xa097, 0x094c, 0x00000300); + nv_mthd(priv, 0xa097, 0x098c, 0x00000300); + nv_mthd(priv, 0xa097, 0x09cc, 0x00000300); + nv_mthd(priv, 0xa097, 0x0810, 0x000000cf); + nv_mthd(priv, 0xa097, 0x0850, 0x00000000); + nv_mthd(priv, 0xa097, 0x0890, 0x00000000); + nv_mthd(priv, 0xa097, 0x08d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0910, 0x00000000); + nv_mthd(priv, 0xa097, 0x0950, 0x00000000); + nv_mthd(priv, 0xa097, 0x0990, 0x00000000); + nv_mthd(priv, 0xa097, 0x09d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0814, 0x00000040); + nv_mthd(priv, 0xa097, 0x0854, 0x00000040); + nv_mthd(priv, 0xa097, 0x0894, 0x00000040); + nv_mthd(priv, 0xa097, 0x08d4, 0x00000040); + nv_mthd(priv, 0xa097, 0x0914, 0x00000040); + nv_mthd(priv, 0xa097, 0x0954, 0x00000040); + nv_mthd(priv, 0xa097, 0x0994, 0x00000040); + nv_mthd(priv, 0xa097, 0x09d4, 0x00000040); + nv_mthd(priv, 0xa097, 0x0818, 0x00000001); + nv_mthd(priv, 0xa097, 0x0858, 0x00000001); + nv_mthd(priv, 0xa097, 0x0898, 0x00000001); + nv_mthd(priv, 0xa097, 0x08d8, 0x00000001); + nv_mthd(priv, 0xa097, 0x0918, 0x00000001); + nv_mthd(priv, 0xa097, 0x0958, 0x00000001); + nv_mthd(priv, 0xa097, 0x0998, 0x00000001); + nv_mthd(priv, 0xa097, 0x09d8, 0x00000001); + nv_mthd(priv, 0xa097, 0x081c, 0x00000000); + nv_mthd(priv, 0xa097, 0x085c, 0x00000000); + nv_mthd(priv, 0xa097, 0x089c, 0x00000000); + nv_mthd(priv, 0xa097, 0x08dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x091c, 0x00000000); + nv_mthd(priv, 0xa097, 0x095c, 0x00000000); + nv_mthd(priv, 0xa097, 0x099c, 0x00000000); + nv_mthd(priv, 0xa097, 0x09dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0820, 0x00000000); + nv_mthd(priv, 0xa097, 0x0860, 0x00000000); + nv_mthd(priv, 0xa097, 0x08a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x08e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0920, 0x00000000); + nv_mthd(priv, 0xa097, 0x0960, 0x00000000); + nv_mthd(priv, 0xa097, 0x09a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x09e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c00, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c10, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c20, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c30, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c40, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c50, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c60, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c70, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c80, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c90, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ca0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cb0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cc0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cd0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ce0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cf0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c04, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c14, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c24, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c34, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c44, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c54, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c64, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c74, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c84, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c94, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ca4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cb4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cc4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cd4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ce4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cf4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c08, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c18, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c28, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c38, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c48, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c58, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c68, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c78, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c88, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c98, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ca8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cb8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cc8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cd8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ce8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cf8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c0c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c1c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c2c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c3c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c4c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c5c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c6c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c7c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1c9c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cac, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cbc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ccc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cdc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cec, 0x00000000); + nv_mthd(priv, 0xa097, 0x1cfc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d00, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d10, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d20, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d30, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d40, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d50, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d60, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d70, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d80, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d90, 0x00000000); + nv_mthd(priv, 0xa097, 0x1da0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1db0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dc0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dd0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1de0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1df0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d04, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d14, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d24, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d34, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d44, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d54, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d64, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d74, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d84, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d94, 0x00000000); + nv_mthd(priv, 0xa097, 0x1da4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1db4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dc4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dd4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1de4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1df4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d08, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d18, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d28, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d38, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d48, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d58, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d68, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d78, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d88, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d98, 0x00000000); + nv_mthd(priv, 0xa097, 0x1da8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1db8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dc8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dd8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1de8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1df8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d0c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d1c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d2c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d3c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d4c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d5c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d6c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d7c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1d9c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dac, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dbc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dcc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ddc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dec, 0x00000000); + nv_mthd(priv, 0xa097, 0x1dfc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f00, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f08, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f10, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f18, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f20, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f28, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f30, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f38, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f40, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f48, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f50, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f58, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f60, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f68, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f70, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f78, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f04, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f0c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f14, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f1c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f24, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f2c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f34, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f3c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f44, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f4c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f54, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f5c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f64, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f6c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f74, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f7c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f80, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f88, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f90, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f98, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fa0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fa8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fb0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fb8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fc0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fc8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fd0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fd8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fe0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fe8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ff0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ff8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f84, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f94, 0x00000000); + nv_mthd(priv, 0xa097, 0x1f9c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fa4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fac, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fb4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fbc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fc4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fcc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fd4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fdc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fe4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1fec, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ff4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1ffc, 0x00000000); + nv_mthd(priv, 0xa097, 0x2000, 0x00000000); + nv_mthd(priv, 0xa097, 0x2040, 0x00000011); + nv_mthd(priv, 0xa097, 0x2080, 0x00000020); + nv_mthd(priv, 0xa097, 0x20c0, 0x00000030); + nv_mthd(priv, 0xa097, 0x2100, 0x00000040); + nv_mthd(priv, 0xa097, 0x2140, 0x00000051); + nv_mthd(priv, 0xa097, 0x200c, 0x00000001); + nv_mthd(priv, 0xa097, 0x204c, 0x00000001); + nv_mthd(priv, 0xa097, 0x208c, 0x00000001); + nv_mthd(priv, 0xa097, 0x20cc, 0x00000001); + nv_mthd(priv, 0xa097, 0x210c, 0x00000001); + nv_mthd(priv, 0xa097, 0x214c, 0x00000001); + nv_mthd(priv, 0xa097, 0x2010, 0x00000000); + nv_mthd(priv, 0xa097, 0x2050, 0x00000000); + nv_mthd(priv, 0xa097, 0x2090, 0x00000001); + nv_mthd(priv, 0xa097, 0x20d0, 0x00000002); + nv_mthd(priv, 0xa097, 0x2110, 0x00000003); + nv_mthd(priv, 0xa097, 0x2150, 0x00000004); + nv_mthd(priv, 0xa097, 0x0380, 0x00000000); + nv_mthd(priv, 0xa097, 0x03a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x03c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x03e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0384, 0x00000000); + nv_mthd(priv, 0xa097, 0x03a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x03c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x03e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0388, 0x00000000); + nv_mthd(priv, 0xa097, 0x03a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x03c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x03e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x038c, 0x00000000); + nv_mthd(priv, 0xa097, 0x03ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x03cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x03ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x0700, 0x00000000); + nv_mthd(priv, 0xa097, 0x0710, 0x00000000); + nv_mthd(priv, 0xa097, 0x0720, 0x00000000); + nv_mthd(priv, 0xa097, 0x0730, 0x00000000); + nv_mthd(priv, 0xa097, 0x0704, 0x00000000); + nv_mthd(priv, 0xa097, 0x0714, 0x00000000); + nv_mthd(priv, 0xa097, 0x0724, 0x00000000); + nv_mthd(priv, 0xa097, 0x0734, 0x00000000); + nv_mthd(priv, 0xa097, 0x0708, 0x00000000); + nv_mthd(priv, 0xa097, 0x0718, 0x00000000); + nv_mthd(priv, 0xa097, 0x0728, 0x00000000); + nv_mthd(priv, 0xa097, 0x0738, 0x00000000); + nv_mthd(priv, 0xa097, 0x2800, 0x00000000); + nv_mthd(priv, 0xa097, 0x2804, 0x00000000); + nv_mthd(priv, 0xa097, 0x2808, 0x00000000); + nv_mthd(priv, 0xa097, 0x280c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2810, 0x00000000); + nv_mthd(priv, 0xa097, 0x2814, 0x00000000); + nv_mthd(priv, 0xa097, 0x2818, 0x00000000); + nv_mthd(priv, 0xa097, 0x281c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2820, 0x00000000); + nv_mthd(priv, 0xa097, 0x2824, 0x00000000); + nv_mthd(priv, 0xa097, 0x2828, 0x00000000); + nv_mthd(priv, 0xa097, 0x282c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2830, 0x00000000); + nv_mthd(priv, 0xa097, 0x2834, 0x00000000); + nv_mthd(priv, 0xa097, 0x2838, 0x00000000); + nv_mthd(priv, 0xa097, 0x283c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2840, 0x00000000); + nv_mthd(priv, 0xa097, 0x2844, 0x00000000); + nv_mthd(priv, 0xa097, 0x2848, 0x00000000); + nv_mthd(priv, 0xa097, 0x284c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2850, 0x00000000); + nv_mthd(priv, 0xa097, 0x2854, 0x00000000); + nv_mthd(priv, 0xa097, 0x2858, 0x00000000); + nv_mthd(priv, 0xa097, 0x285c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2860, 0x00000000); + nv_mthd(priv, 0xa097, 0x2864, 0x00000000); + nv_mthd(priv, 0xa097, 0x2868, 0x00000000); + nv_mthd(priv, 0xa097, 0x286c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2870, 0x00000000); + nv_mthd(priv, 0xa097, 0x2874, 0x00000000); + nv_mthd(priv, 0xa097, 0x2878, 0x00000000); + nv_mthd(priv, 0xa097, 0x287c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2880, 0x00000000); + nv_mthd(priv, 0xa097, 0x2884, 0x00000000); + nv_mthd(priv, 0xa097, 0x2888, 0x00000000); + nv_mthd(priv, 0xa097, 0x288c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2890, 0x00000000); + nv_mthd(priv, 0xa097, 0x2894, 0x00000000); + nv_mthd(priv, 0xa097, 0x2898, 0x00000000); + nv_mthd(priv, 0xa097, 0x289c, 0x00000000); + nv_mthd(priv, 0xa097, 0x28a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x28a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x28a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x28ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x28b0, 0x00000000); + nv_mthd(priv, 0xa097, 0x28b4, 0x00000000); + nv_mthd(priv, 0xa097, 0x28b8, 0x00000000); + nv_mthd(priv, 0xa097, 0x28bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x28c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x28c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x28c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x28cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x28d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x28d4, 0x00000000); + nv_mthd(priv, 0xa097, 0x28d8, 0x00000000); + nv_mthd(priv, 0xa097, 0x28dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x28e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x28e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x28e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x28ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x28f0, 0x00000000); + nv_mthd(priv, 0xa097, 0x28f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x28f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x28fc, 0x00000000); + nv_mthd(priv, 0xa097, 0x2900, 0x00000000); + nv_mthd(priv, 0xa097, 0x2904, 0x00000000); + nv_mthd(priv, 0xa097, 0x2908, 0x00000000); + nv_mthd(priv, 0xa097, 0x290c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2910, 0x00000000); + nv_mthd(priv, 0xa097, 0x2914, 0x00000000); + nv_mthd(priv, 0xa097, 0x2918, 0x00000000); + nv_mthd(priv, 0xa097, 0x291c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2920, 0x00000000); + nv_mthd(priv, 0xa097, 0x2924, 0x00000000); + nv_mthd(priv, 0xa097, 0x2928, 0x00000000); + nv_mthd(priv, 0xa097, 0x292c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2930, 0x00000000); + nv_mthd(priv, 0xa097, 0x2934, 0x00000000); + nv_mthd(priv, 0xa097, 0x2938, 0x00000000); + nv_mthd(priv, 0xa097, 0x293c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2940, 0x00000000); + nv_mthd(priv, 0xa097, 0x2944, 0x00000000); + nv_mthd(priv, 0xa097, 0x2948, 0x00000000); + nv_mthd(priv, 0xa097, 0x294c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2950, 0x00000000); + nv_mthd(priv, 0xa097, 0x2954, 0x00000000); + nv_mthd(priv, 0xa097, 0x2958, 0x00000000); + nv_mthd(priv, 0xa097, 0x295c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2960, 0x00000000); + nv_mthd(priv, 0xa097, 0x2964, 0x00000000); + nv_mthd(priv, 0xa097, 0x2968, 0x00000000); + nv_mthd(priv, 0xa097, 0x296c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2970, 0x00000000); + nv_mthd(priv, 0xa097, 0x2974, 0x00000000); + nv_mthd(priv, 0xa097, 0x2978, 0x00000000); + nv_mthd(priv, 0xa097, 0x297c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2980, 0x00000000); + nv_mthd(priv, 0xa097, 0x2984, 0x00000000); + nv_mthd(priv, 0xa097, 0x2988, 0x00000000); + nv_mthd(priv, 0xa097, 0x298c, 0x00000000); + nv_mthd(priv, 0xa097, 0x2990, 0x00000000); + nv_mthd(priv, 0xa097, 0x2994, 0x00000000); + nv_mthd(priv, 0xa097, 0x2998, 0x00000000); + nv_mthd(priv, 0xa097, 0x299c, 0x00000000); + nv_mthd(priv, 0xa097, 0x29a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x29a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x29a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x29ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x29b0, 0x00000000); + nv_mthd(priv, 0xa097, 0x29b4, 0x00000000); + nv_mthd(priv, 0xa097, 0x29b8, 0x00000000); + nv_mthd(priv, 0xa097, 0x29bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x29c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x29c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x29c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x29cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x29d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x29d4, 0x00000000); + nv_mthd(priv, 0xa097, 0x29d8, 0x00000000); + nv_mthd(priv, 0xa097, 0x29dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x29e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x29e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x29e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x29ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x29f0, 0x00000000); + nv_mthd(priv, 0xa097, 0x29f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x29f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x29fc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a00, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a20, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a40, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a60, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a80, 0x00000000); + nv_mthd(priv, 0xa097, 0x0aa0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ac0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ae0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b00, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b20, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b40, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b60, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b80, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ba0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bc0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0be0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a04, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a24, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a44, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a64, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a84, 0x00000000); + nv_mthd(priv, 0xa097, 0x0aa4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ac4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ae4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b04, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b24, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b44, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b64, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b84, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ba4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bc4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0be4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a08, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a28, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a48, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a68, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a88, 0x00000000); + nv_mthd(priv, 0xa097, 0x0aa8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ac8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ae8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b08, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b28, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b48, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b68, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b88, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ba8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bc8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0be8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a0c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a2c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a4c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a6c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0aac, 0x00000000); + nv_mthd(priv, 0xa097, 0x0acc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0aec, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b0c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b2c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b4c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b6c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bac, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bcc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bec, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a10, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a30, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a50, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a70, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a90, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ab0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ad0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0af0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b10, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b30, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b50, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b70, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b90, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bb0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bd0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bf0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a14, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a34, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a54, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a74, 0x00000000); + nv_mthd(priv, 0xa097, 0x0a94, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ab4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ad4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0af4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b14, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b34, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b54, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b74, 0x00000000); + nv_mthd(priv, 0xa097, 0x0b94, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bb4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bd4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0bf4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c00, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c10, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c20, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c30, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c40, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c50, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c60, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c70, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c80, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c90, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ca0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cb0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cc0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cd0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ce0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cf0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c04, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c14, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c24, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c34, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c44, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c54, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c64, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c74, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c84, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c94, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ca4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cb4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cc4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cd4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ce4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cf4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c08, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c18, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c28, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c38, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c48, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c58, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c68, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c78, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c88, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c98, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ca8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cb8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cc8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cd8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ce8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0cf8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0c0c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c1c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c2c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c3c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c4c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c5c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c6c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c7c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c8c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0c9c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0cac, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0cbc, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0ccc, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0cdc, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0cec, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0cfc, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0d00, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d08, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d10, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d18, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d20, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d28, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d30, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d38, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d04, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d0c, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d14, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d1c, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d24, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d2c, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d34, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d3c, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e00, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e10, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e20, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e30, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e40, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e50, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e60, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e70, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e80, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e90, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ea0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0eb0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ec0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ed0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ee0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ef0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0e04, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e14, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e24, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e34, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e44, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e54, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e64, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e74, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e84, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e94, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ea4, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0eb4, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ec4, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ed4, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ee4, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ef4, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e08, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e18, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e28, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e38, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e48, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e58, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e68, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e78, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e88, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0e98, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ea8, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0eb8, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ec8, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ed8, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ee8, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0ef8, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d40, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d48, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d50, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d58, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d44, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d4c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d54, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d5c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1e00, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e20, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e40, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e60, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e80, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ea0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ec0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ee0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e04, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e24, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e44, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e64, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e84, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ea4, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ec4, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ee4, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e08, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e28, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e48, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e68, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e88, 0x00000002); + nv_mthd(priv, 0xa097, 0x1ea8, 0x00000002); + nv_mthd(priv, 0xa097, 0x1ec8, 0x00000002); + nv_mthd(priv, 0xa097, 0x1ee8, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e0c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e2c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e4c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e6c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e8c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1eac, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ecc, 0x00000001); + nv_mthd(priv, 0xa097, 0x1eec, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e10, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e30, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e50, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e70, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e90, 0x00000001); + nv_mthd(priv, 0xa097, 0x1eb0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ed0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ef0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e14, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e34, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e54, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e74, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e94, 0x00000002); + nv_mthd(priv, 0xa097, 0x1eb4, 0x00000002); + nv_mthd(priv, 0xa097, 0x1ed4, 0x00000002); + nv_mthd(priv, 0xa097, 0x1ef4, 0x00000002); + nv_mthd(priv, 0xa097, 0x1e18, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e38, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e58, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e78, 0x00000001); + nv_mthd(priv, 0xa097, 0x1e98, 0x00000001); + nv_mthd(priv, 0xa097, 0x1eb8, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ed8, 0x00000001); + nv_mthd(priv, 0xa097, 0x1ef8, 0x00000001); + nv_mthd(priv, 0xa097, 0x3400, 0x00000000); + nv_mthd(priv, 0xa097, 0x3404, 0x00000000); + nv_mthd(priv, 0xa097, 0x3408, 0x00000000); + nv_mthd(priv, 0xa097, 0x340c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3410, 0x00000000); + nv_mthd(priv, 0xa097, 0x3414, 0x00000000); + nv_mthd(priv, 0xa097, 0x3418, 0x00000000); + nv_mthd(priv, 0xa097, 0x341c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3420, 0x00000000); + nv_mthd(priv, 0xa097, 0x3424, 0x00000000); + nv_mthd(priv, 0xa097, 0x3428, 0x00000000); + nv_mthd(priv, 0xa097, 0x342c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3430, 0x00000000); + nv_mthd(priv, 0xa097, 0x3434, 0x00000000); + nv_mthd(priv, 0xa097, 0x3438, 0x00000000); + nv_mthd(priv, 0xa097, 0x343c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3440, 0x00000000); + nv_mthd(priv, 0xa097, 0x3444, 0x00000000); + nv_mthd(priv, 0xa097, 0x3448, 0x00000000); + nv_mthd(priv, 0xa097, 0x344c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3450, 0x00000000); + nv_mthd(priv, 0xa097, 0x3454, 0x00000000); + nv_mthd(priv, 0xa097, 0x3458, 0x00000000); + nv_mthd(priv, 0xa097, 0x345c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3460, 0x00000000); + nv_mthd(priv, 0xa097, 0x3464, 0x00000000); + nv_mthd(priv, 0xa097, 0x3468, 0x00000000); + nv_mthd(priv, 0xa097, 0x346c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3470, 0x00000000); + nv_mthd(priv, 0xa097, 0x3474, 0x00000000); + nv_mthd(priv, 0xa097, 0x3478, 0x00000000); + nv_mthd(priv, 0xa097, 0x347c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3480, 0x00000000); + nv_mthd(priv, 0xa097, 0x3484, 0x00000000); + nv_mthd(priv, 0xa097, 0x3488, 0x00000000); + nv_mthd(priv, 0xa097, 0x348c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3490, 0x00000000); + nv_mthd(priv, 0xa097, 0x3494, 0x00000000); + nv_mthd(priv, 0xa097, 0x3498, 0x00000000); + nv_mthd(priv, 0xa097, 0x349c, 0x00000000); + nv_mthd(priv, 0xa097, 0x34a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x34a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x34a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x34ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x34b0, 0x00000000); + nv_mthd(priv, 0xa097, 0x34b4, 0x00000000); + nv_mthd(priv, 0xa097, 0x34b8, 0x00000000); + nv_mthd(priv, 0xa097, 0x34bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x34c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x34c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x34c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x34cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x34d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x34d4, 0x00000000); + nv_mthd(priv, 0xa097, 0x34d8, 0x00000000); + nv_mthd(priv, 0xa097, 0x34dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x34e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x34e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x34e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x34ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x34f0, 0x00000000); + nv_mthd(priv, 0xa097, 0x34f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x34f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x34fc, 0x00000000); + nv_mthd(priv, 0xa097, 0x3500, 0x00000000); + nv_mthd(priv, 0xa097, 0x3504, 0x00000000); + nv_mthd(priv, 0xa097, 0x3508, 0x00000000); + nv_mthd(priv, 0xa097, 0x350c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3510, 0x00000000); + nv_mthd(priv, 0xa097, 0x3514, 0x00000000); + nv_mthd(priv, 0xa097, 0x3518, 0x00000000); + nv_mthd(priv, 0xa097, 0x351c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3520, 0x00000000); + nv_mthd(priv, 0xa097, 0x3524, 0x00000000); + nv_mthd(priv, 0xa097, 0x3528, 0x00000000); + nv_mthd(priv, 0xa097, 0x352c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3530, 0x00000000); + nv_mthd(priv, 0xa097, 0x3534, 0x00000000); + nv_mthd(priv, 0xa097, 0x3538, 0x00000000); + nv_mthd(priv, 0xa097, 0x353c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3540, 0x00000000); + nv_mthd(priv, 0xa097, 0x3544, 0x00000000); + nv_mthd(priv, 0xa097, 0x3548, 0x00000000); + nv_mthd(priv, 0xa097, 0x354c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3550, 0x00000000); + nv_mthd(priv, 0xa097, 0x3554, 0x00000000); + nv_mthd(priv, 0xa097, 0x3558, 0x00000000); + nv_mthd(priv, 0xa097, 0x355c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3560, 0x00000000); + nv_mthd(priv, 0xa097, 0x3564, 0x00000000); + nv_mthd(priv, 0xa097, 0x3568, 0x00000000); + nv_mthd(priv, 0xa097, 0x356c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3570, 0x00000000); + nv_mthd(priv, 0xa097, 0x3574, 0x00000000); + nv_mthd(priv, 0xa097, 0x3578, 0x00000000); + nv_mthd(priv, 0xa097, 0x357c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3580, 0x00000000); + nv_mthd(priv, 0xa097, 0x3584, 0x00000000); + nv_mthd(priv, 0xa097, 0x3588, 0x00000000); + nv_mthd(priv, 0xa097, 0x358c, 0x00000000); + nv_mthd(priv, 0xa097, 0x3590, 0x00000000); + nv_mthd(priv, 0xa097, 0x3594, 0x00000000); + nv_mthd(priv, 0xa097, 0x3598, 0x00000000); + nv_mthd(priv, 0xa097, 0x359c, 0x00000000); + nv_mthd(priv, 0xa097, 0x35a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x35a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x35a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x35ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x35b0, 0x00000000); + nv_mthd(priv, 0xa097, 0x35b4, 0x00000000); + nv_mthd(priv, 0xa097, 0x35b8, 0x00000000); + nv_mthd(priv, 0xa097, 0x35bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x35c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x35c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x35c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x35cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x35d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x35d4, 0x00000000); + nv_mthd(priv, 0xa097, 0x35d8, 0x00000000); + nv_mthd(priv, 0xa097, 0x35dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x35e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x35e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x35e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x35ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x35f0, 0x00000000); + nv_mthd(priv, 0xa097, 0x35f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x35f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x35fc, 0x00000000); + nv_mthd(priv, 0xa097, 0x030c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1944, 0x00000000); + nv_mthd(priv, 0xa097, 0x1514, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d68, 0x0000ffff); + nv_mthd(priv, 0xa097, 0x121c, 0x0fac6881); + nv_mthd(priv, 0xa097, 0x0fac, 0x00000001); + nv_mthd(priv, 0xa097, 0x1538, 0x00000001); + nv_mthd(priv, 0xa097, 0x0fe0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0fe4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0fe8, 0x00000014); + nv_mthd(priv, 0xa097, 0x0fec, 0x00000040); + nv_mthd(priv, 0xa097, 0x0ff0, 0x00000000); + nv_mthd(priv, 0xa097, 0x179c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1228, 0x00000400); + nv_mthd(priv, 0xa097, 0x122c, 0x00000300); + nv_mthd(priv, 0xa097, 0x1230, 0x00010001); + nv_mthd(priv, 0xa097, 0x07f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x15b4, 0x00000001); + nv_mthd(priv, 0xa097, 0x15cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1534, 0x00000000); + nv_mthd(priv, 0xa097, 0x0fb0, 0x00000000); + nv_mthd(priv, 0xa097, 0x15d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x153c, 0x00000000); + nv_mthd(priv, 0xa097, 0x16b4, 0x00000003); + nv_mthd(priv, 0xa097, 0x0fbc, 0x0000ffff); + nv_mthd(priv, 0xa097, 0x0fc0, 0x0000ffff); + nv_mthd(priv, 0xa097, 0x0fc4, 0x0000ffff); + nv_mthd(priv, 0xa097, 0x0fc8, 0x0000ffff); + nv_mthd(priv, 0xa097, 0x0df8, 0x00000000); + nv_mthd(priv, 0xa097, 0x0dfc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1948, 0x00000000); + nv_mthd(priv, 0xa097, 0x1970, 0x00000001); + nv_mthd(priv, 0xa097, 0x161c, 0x000009f0); + nv_mthd(priv, 0xa097, 0x0dcc, 0x00000010); + nv_mthd(priv, 0xa097, 0x163c, 0x00000000); + nv_mthd(priv, 0xa097, 0x15e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1160, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1164, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1168, 0x25e00040); + nv_mthd(priv, 0xa097, 0x116c, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1170, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1174, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1178, 0x25e00040); + nv_mthd(priv, 0xa097, 0x117c, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1180, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1184, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1188, 0x25e00040); + nv_mthd(priv, 0xa097, 0x118c, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1190, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1194, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1198, 0x25e00040); + nv_mthd(priv, 0xa097, 0x119c, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11a0, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11a4, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11a8, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11ac, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11b0, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11b4, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11b8, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11bc, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11c0, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11c4, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11c8, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11cc, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11d0, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11d4, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11d8, 0x25e00040); + nv_mthd(priv, 0xa097, 0x11dc, 0x25e00040); + nv_mthd(priv, 0xa097, 0x1880, 0x00000000); + nv_mthd(priv, 0xa097, 0x1884, 0x00000000); + nv_mthd(priv, 0xa097, 0x1888, 0x00000000); + nv_mthd(priv, 0xa097, 0x188c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1890, 0x00000000); + nv_mthd(priv, 0xa097, 0x1894, 0x00000000); + nv_mthd(priv, 0xa097, 0x1898, 0x00000000); + nv_mthd(priv, 0xa097, 0x189c, 0x00000000); + nv_mthd(priv, 0xa097, 0x18a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x18a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x18a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x18ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x18b0, 0x00000000); + nv_mthd(priv, 0xa097, 0x18b4, 0x00000000); + nv_mthd(priv, 0xa097, 0x18b8, 0x00000000); + nv_mthd(priv, 0xa097, 0x18bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x18c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x18c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x18c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x18cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x18d0, 0x00000000); + nv_mthd(priv, 0xa097, 0x18d4, 0x00000000); + nv_mthd(priv, 0xa097, 0x18d8, 0x00000000); + nv_mthd(priv, 0xa097, 0x18dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x18e0, 0x00000000); + nv_mthd(priv, 0xa097, 0x18e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x18e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x18ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x18f0, 0x00000000); + nv_mthd(priv, 0xa097, 0x18f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x18f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x18fc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f84, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f88, 0x00000000); + nv_mthd(priv, 0xa097, 0x17c8, 0x00000000); + nv_mthd(priv, 0xa097, 0x17cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x17d0, 0x000000ff); + nv_mthd(priv, 0xa097, 0x17d4, 0xffffffff); + nv_mthd(priv, 0xa097, 0x17d8, 0x00000002); + nv_mthd(priv, 0xa097, 0x17dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x15f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x15f8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1434, 0x00000000); + nv_mthd(priv, 0xa097, 0x1438, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d74, 0x00000000); + nv_mthd(priv, 0xa097, 0x0dec, 0x00000001); + nv_mthd(priv, 0xa097, 0x13a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1318, 0x00000001); + nv_mthd(priv, 0xa097, 0x1644, 0x00000000); + nv_mthd(priv, 0xa097, 0x0748, 0x00000000); + nv_mthd(priv, 0xa097, 0x0de8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1648, 0x00000000); + nv_mthd(priv, 0xa097, 0x12a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x1120, 0x00000000); + nv_mthd(priv, 0xa097, 0x1124, 0x00000000); + nv_mthd(priv, 0xa097, 0x1128, 0x00000000); + nv_mthd(priv, 0xa097, 0x112c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1118, 0x00000000); + nv_mthd(priv, 0xa097, 0x164c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1658, 0x00000000); + nv_mthd(priv, 0xa097, 0x1910, 0x00000290); + nv_mthd(priv, 0xa097, 0x1518, 0x00000000); + nv_mthd(priv, 0xa097, 0x165c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1520, 0x00000000); + nv_mthd(priv, 0xa097, 0x1604, 0x00000000); + nv_mthd(priv, 0xa097, 0x1570, 0x00000000); + nv_mthd(priv, 0xa097, 0x13b0, 0x3f800000); + nv_mthd(priv, 0xa097, 0x13b4, 0x3f800000); + nv_mthd(priv, 0xa097, 0x020c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1670, 0x30201000); + nv_mthd(priv, 0xa097, 0x1674, 0x70605040); + nv_mthd(priv, 0xa097, 0x1678, 0xb8a89888); + nv_mthd(priv, 0xa097, 0x167c, 0xf8e8d8c8); + nv_mthd(priv, 0xa097, 0x166c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1680, 0x00ffff00); + nv_mthd(priv, 0xa097, 0x12d0, 0x00000003); + nv_mthd(priv, 0xa097, 0x12d4, 0x00000002); + nv_mthd(priv, 0xa097, 0x1684, 0x00000000); + nv_mthd(priv, 0xa097, 0x1688, 0x00000000); + nv_mthd(priv, 0xa097, 0x0dac, 0x00001b02); + nv_mthd(priv, 0xa097, 0x0db0, 0x00001b02); + nv_mthd(priv, 0xa097, 0x0db4, 0x00000000); + nv_mthd(priv, 0xa097, 0x168c, 0x00000000); + nv_mthd(priv, 0xa097, 0x15bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x156c, 0x00000000); + nv_mthd(priv, 0xa097, 0x187c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1110, 0x00000001); + nv_mthd(priv, 0xa097, 0x0dc0, 0x00000000); + nv_mthd(priv, 0xa097, 0x0dc4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0dc8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1234, 0x00000000); + nv_mthd(priv, 0xa097, 0x1690, 0x00000000); + nv_mthd(priv, 0xa097, 0x12ac, 0x00000001); + nv_mthd(priv, 0xa097, 0x0790, 0x00000000); + nv_mthd(priv, 0xa097, 0x0794, 0x00000000); + nv_mthd(priv, 0xa097, 0x0798, 0x00000000); + nv_mthd(priv, 0xa097, 0x079c, 0x00000000); + nv_mthd(priv, 0xa097, 0x07a0, 0x00000000); + nv_mthd(priv, 0xa097, 0x077c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1000, 0x00000010); + nv_mthd(priv, 0xa097, 0x10fc, 0x00000000); + nv_mthd(priv, 0xa097, 0x1290, 0x00000000); + nv_mthd(priv, 0xa097, 0x0218, 0x00000010); + nv_mthd(priv, 0xa097, 0x12d8, 0x00000000); + nv_mthd(priv, 0xa097, 0x12dc, 0x00000010); + nv_mthd(priv, 0xa097, 0x0d94, 0x00000001); + nv_mthd(priv, 0xa097, 0x155c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1560, 0x00000000); + nv_mthd(priv, 0xa097, 0x1564, 0x00000fff); + nv_mthd(priv, 0xa097, 0x1574, 0x00000000); + nv_mthd(priv, 0xa097, 0x1578, 0x00000000); + nv_mthd(priv, 0xa097, 0x157c, 0x000fffff); + nv_mthd(priv, 0xa097, 0x1354, 0x00000000); + nv_mthd(priv, 0xa097, 0x1610, 0x00000012); + nv_mthd(priv, 0xa097, 0x1608, 0x00000000); + nv_mthd(priv, 0xa097, 0x160c, 0x00000000); + nv_mthd(priv, 0xa097, 0x260c, 0x00000000); + nv_mthd(priv, 0xa097, 0x07ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x162c, 0x00000003); + nv_mthd(priv, 0xa097, 0x0210, 0x00000000); + nv_mthd(priv, 0xa097, 0x0320, 0x00000000); + nv_mthd(priv, 0xa097, 0x0324, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0328, 0x3f800000); + nv_mthd(priv, 0xa097, 0x032c, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0330, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0334, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0338, 0x3f800000); + nv_mthd(priv, 0xa097, 0x0750, 0x00000000); + nv_mthd(priv, 0xa097, 0x0760, 0x39291909); + nv_mthd(priv, 0xa097, 0x0764, 0x79695949); + nv_mthd(priv, 0xa097, 0x0768, 0xb9a99989); + nv_mthd(priv, 0xa097, 0x076c, 0xf9e9d9c9); + nv_mthd(priv, 0xa097, 0x0770, 0x30201000); + nv_mthd(priv, 0xa097, 0x0774, 0x70605040); + nv_mthd(priv, 0xa097, 0x0778, 0x00009080); + nv_mthd(priv, 0xa097, 0x0780, 0x39291909); + nv_mthd(priv, 0xa097, 0x0784, 0x79695949); + nv_mthd(priv, 0xa097, 0x0788, 0xb9a99989); + nv_mthd(priv, 0xa097, 0x078c, 0xf9e9d9c9); + nv_mthd(priv, 0xa097, 0x07d0, 0x30201000); + nv_mthd(priv, 0xa097, 0x07d4, 0x70605040); + nv_mthd(priv, 0xa097, 0x07d8, 0x00009080); + nv_mthd(priv, 0xa097, 0x037c, 0x00000001); + nv_mthd(priv, 0xa097, 0x0740, 0x00000000); + nv_mthd(priv, 0xa097, 0x0744, 0x00000000); + nv_mthd(priv, 0xa097, 0x2600, 0x00000000); + nv_mthd(priv, 0xa097, 0x1918, 0x00000000); + nv_mthd(priv, 0xa097, 0x191c, 0x00000900); + nv_mthd(priv, 0xa097, 0x1920, 0x00000405); + nv_mthd(priv, 0xa097, 0x1308, 0x00000001); + nv_mthd(priv, 0xa097, 0x1924, 0x00000000); + nv_mthd(priv, 0xa097, 0x13ac, 0x00000000); + nv_mthd(priv, 0xa097, 0x192c, 0x00000001); + nv_mthd(priv, 0xa097, 0x193c, 0x00002c1c); + nv_mthd(priv, 0xa097, 0x0d7c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x02c0, 0x00000001); + nv_mthd(priv, 0xa097, 0x1510, 0x00000000); + nv_mthd(priv, 0xa097, 0x1940, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ff4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0ff8, 0x00000000); + nv_mthd(priv, 0xa097, 0x194c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1950, 0x00000000); + nv_mthd(priv, 0xa097, 0x1968, 0x00000000); + nv_mthd(priv, 0xa097, 0x1590, 0x0000003f); + nv_mthd(priv, 0xa097, 0x07e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x07ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x07f0, 0x00000000); + nv_mthd(priv, 0xa097, 0x07f4, 0x00000000); + nv_mthd(priv, 0xa097, 0x196c, 0x00000011); + nv_mthd(priv, 0xa097, 0x02e4, 0x0000b001); + nv_mthd(priv, 0xa097, 0x036c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0370, 0x00000000); + nv_mthd(priv, 0xa097, 0x197c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0fcc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0fd0, 0x00000000); + nv_mthd(priv, 0xa097, 0x02d8, 0x00000040); + nv_mthd(priv, 0xa097, 0x1980, 0x00000080); + nv_mthd(priv, 0xa097, 0x1504, 0x00000080); + nv_mthd(priv, 0xa097, 0x1984, 0x00000000); + nv_mthd(priv, 0xa097, 0x0300, 0x00000001); + nv_mthd(priv, 0xa097, 0x13a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x12ec, 0x00000000); + nv_mthd(priv, 0xa097, 0x1310, 0x00000000); + nv_mthd(priv, 0xa097, 0x1314, 0x00000001); + nv_mthd(priv, 0xa097, 0x1380, 0x00000000); + nv_mthd(priv, 0xa097, 0x1384, 0x00000001); + nv_mthd(priv, 0xa097, 0x1388, 0x00000001); + nv_mthd(priv, 0xa097, 0x138c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1390, 0x00000001); + nv_mthd(priv, 0xa097, 0x1394, 0x00000000); + nv_mthd(priv, 0xa097, 0x139c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1398, 0x00000000); + nv_mthd(priv, 0xa097, 0x1594, 0x00000000); + nv_mthd(priv, 0xa097, 0x1598, 0x00000001); + nv_mthd(priv, 0xa097, 0x159c, 0x00000001); + nv_mthd(priv, 0xa097, 0x15a0, 0x00000001); + nv_mthd(priv, 0xa097, 0x15a4, 0x00000001); + nv_mthd(priv, 0xa097, 0x0f54, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f58, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f5c, 0x00000000); + nv_mthd(priv, 0xa097, 0x19bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f9c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0fa0, 0x00000000); + nv_mthd(priv, 0xa097, 0x12cc, 0x00000000); + nv_mthd(priv, 0xa097, 0x12e8, 0x00000000); + nv_mthd(priv, 0xa097, 0x130c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1360, 0x00000000); + nv_mthd(priv, 0xa097, 0x1364, 0x00000000); + nv_mthd(priv, 0xa097, 0x1368, 0x00000000); + nv_mthd(priv, 0xa097, 0x136c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1370, 0x00000000); + nv_mthd(priv, 0xa097, 0x1374, 0x00000000); + nv_mthd(priv, 0xa097, 0x1378, 0x00000000); + nv_mthd(priv, 0xa097, 0x137c, 0x00000000); + nv_mthd(priv, 0xa097, 0x133c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1340, 0x00000001); + nv_mthd(priv, 0xa097, 0x1344, 0x00000002); + nv_mthd(priv, 0xa097, 0x1348, 0x00000001); + nv_mthd(priv, 0xa097, 0x134c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1350, 0x00000002); + nv_mthd(priv, 0xa097, 0x1358, 0x00000001); + nv_mthd(priv, 0xa097, 0x12e4, 0x00000000); + nv_mthd(priv, 0xa097, 0x131c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1320, 0x00000000); + nv_mthd(priv, 0xa097, 0x1324, 0x00000000); + nv_mthd(priv, 0xa097, 0x1328, 0x00000000); + nv_mthd(priv, 0xa097, 0x19c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x1140, 0x00000000); + nv_mthd(priv, 0xa097, 0x19c4, 0x00000000); + nv_mthd(priv, 0xa097, 0x19c8, 0x00001500); + nv_mthd(priv, 0xa097, 0x135c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f90, 0x00000000); + nv_mthd(priv, 0xa097, 0x19e0, 0x00000001); + nv_mthd(priv, 0xa097, 0x19e4, 0x00000001); + nv_mthd(priv, 0xa097, 0x19e8, 0x00000001); + nv_mthd(priv, 0xa097, 0x19ec, 0x00000001); + nv_mthd(priv, 0xa097, 0x19f0, 0x00000001); + nv_mthd(priv, 0xa097, 0x19f4, 0x00000001); + nv_mthd(priv, 0xa097, 0x19f8, 0x00000001); + nv_mthd(priv, 0xa097, 0x19fc, 0x00000001); + nv_mthd(priv, 0xa097, 0x19cc, 0x00000001); + nv_mthd(priv, 0xa097, 0x15b8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a00, 0x00001111); + nv_mthd(priv, 0xa097, 0x1a04, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a08, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a0c, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a10, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a14, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a18, 0x00000000); + nv_mthd(priv, 0xa097, 0x1a1c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d6c, 0xffff0000); + nv_mthd(priv, 0xa097, 0x0d70, 0xffff0000); + nv_mthd(priv, 0xa097, 0x10f8, 0x00001010); + nv_mthd(priv, 0xa097, 0x0d80, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d84, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d88, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d8c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0d90, 0x00000000); + nv_mthd(priv, 0xa097, 0x0da0, 0x00000000); + nv_mthd(priv, 0xa097, 0x07a4, 0x00000000); + nv_mthd(priv, 0xa097, 0x07a8, 0x00000000); + nv_mthd(priv, 0xa097, 0x1508, 0x80000000); + nv_mthd(priv, 0xa097, 0x150c, 0x40000000); + nv_mthd(priv, 0xa097, 0x1668, 0x00000000); + nv_mthd(priv, 0xa097, 0x0318, 0x00000008); + nv_mthd(priv, 0xa097, 0x031c, 0x00000008); + nv_mthd(priv, 0xa097, 0x0d9c, 0x00000001); + nv_mthd(priv, 0xa097, 0x0374, 0x00000000); + nv_mthd(priv, 0xa097, 0x0378, 0x00000020); + nv_mthd(priv, 0xa097, 0x07dc, 0x00000000); + nv_mthd(priv, 0xa097, 0x074c, 0x00000055); + nv_mthd(priv, 0xa097, 0x1420, 0x00000003); + nv_mthd(priv, 0xa097, 0x17bc, 0x00000000); + nv_mthd(priv, 0xa097, 0x17c0, 0x00000000); + nv_mthd(priv, 0xa097, 0x17c4, 0x00000001); + nv_mthd(priv, 0xa097, 0x1008, 0x00000008); + nv_mthd(priv, 0xa097, 0x100c, 0x00000040); + nv_mthd(priv, 0xa097, 0x1010, 0x0000012c); + nv_mthd(priv, 0xa097, 0x0d60, 0x00000040); + nv_mthd(priv, 0xa097, 0x075c, 0x00000003); + nv_mthd(priv, 0xa097, 0x1018, 0x00000020); + nv_mthd(priv, 0xa097, 0x101c, 0x00000001); + nv_mthd(priv, 0xa097, 0x1020, 0x00000020); + nv_mthd(priv, 0xa097, 0x1024, 0x00000001); + nv_mthd(priv, 0xa097, 0x1444, 0x00000000); + nv_mthd(priv, 0xa097, 0x1448, 0x00000000); + nv_mthd(priv, 0xa097, 0x144c, 0x00000000); + nv_mthd(priv, 0xa097, 0x0360, 0x20164010); + nv_mthd(priv, 0xa097, 0x0364, 0x00000020); + nv_mthd(priv, 0xa097, 0x0368, 0x00000000); + nv_mthd(priv, 0xa097, 0x0de4, 0x00000000); + nv_mthd(priv, 0xa097, 0x0204, 0x00000006); + nv_mthd(priv, 0xa097, 0x0208, 0x00000000); + nv_mthd(priv, 0xa097, 0x02cc, 0x003fffff); + nv_mthd(priv, 0xa097, 0x02d0, 0x003fffff); + nv_mthd(priv, 0xa097, 0x1220, 0x00000005); + nv_mthd(priv, 0xa097, 0x0fdc, 0x00000000); + nv_mthd(priv, 0xa097, 0x0f98, 0x00400008); + nv_mthd(priv, 0xa097, 0x1284, 0x08000080); + nv_mthd(priv, 0xa097, 0x1450, 0x00400008); + nv_mthd(priv, 0xa097, 0x1454, 0x08000080); + nv_mthd(priv, 0xa097, 0x0214, 0x00000000); } static void -nve0_grctx_generate_902d(struct drm_device *dev) +nve0_grctx_generate_902d(struct drm_device *priv) { - nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); - nv_mthd(dev, 0x902d, 0x0204, 0x00000001); - nv_mthd(dev, 0x902d, 0x0208, 0x00000020); - nv_mthd(dev, 0x902d, 0x020c, 0x00000001); - nv_mthd(dev, 0x902d, 0x0210, 0x00000000); - nv_mthd(dev, 0x902d, 0x0214, 0x00000080); - nv_mthd(dev, 0x902d, 0x0218, 0x00000100); - nv_mthd(dev, 0x902d, 0x021c, 0x00000100); - nv_mthd(dev, 0x902d, 0x0220, 0x00000000); - nv_mthd(dev, 0x902d, 0x0224, 0x00000000); - nv_mthd(dev, 0x902d, 0x0230, 0x000000cf); - nv_mthd(dev, 0x902d, 0x0234, 0x00000001); - nv_mthd(dev, 0x902d, 0x0238, 0x00000020); - nv_mthd(dev, 0x902d, 0x023c, 0x00000001); - nv_mthd(dev, 0x902d, 0x0244, 0x00000080); - nv_mthd(dev, 0x902d, 0x0248, 0x00000100); - nv_mthd(dev, 0x902d, 0x024c, 0x00000100); - nv_mthd(dev, 0x902d, 0x3410, 0x00000000); + nv_mthd(priv, 0x902d, 0x0200, 0x000000cf); + nv_mthd(priv, 0x902d, 0x0204, 0x00000001); + nv_mthd(priv, 0x902d, 0x0208, 0x00000020); + nv_mthd(priv, 0x902d, 0x020c, 0x00000001); + nv_mthd(priv, 0x902d, 0x0210, 0x00000000); + nv_mthd(priv, 0x902d, 0x0214, 0x00000080); + nv_mthd(priv, 0x902d, 0x0218, 0x00000100); + nv_mthd(priv, 0x902d, 0x021c, 0x00000100); + nv_mthd(priv, 0x902d, 0x0220, 0x00000000); + nv_mthd(priv, 0x902d, 0x0224, 0x00000000); + nv_mthd(priv, 0x902d, 0x0230, 0x000000cf); + nv_mthd(priv, 0x902d, 0x0234, 0x00000001); + nv_mthd(priv, 0x902d, 0x0238, 0x00000020); + nv_mthd(priv, 0x902d, 0x023c, 0x00000001); + nv_mthd(priv, 0x902d, 0x0244, 0x00000080); + nv_mthd(priv, 0x902d, 0x0248, 0x00000100); + nv_mthd(priv, 0x902d, 0x024c, 0x00000100); + nv_mthd(priv, 0x902d, 0x3410, 0x00000000); } static void -nve0_graph_generate_unk40xx(struct drm_device *dev) +nve0_graph_generate_unk40xx(struct drm_device *priv) { - nv_wr32(dev, 0x404010, 0x0); - nv_wr32(dev, 0x404014, 0x0); - nv_wr32(dev, 0x404018, 0x0); - nv_wr32(dev, 0x40401c, 0x0); - nv_wr32(dev, 0x404020, 0x0); - nv_wr32(dev, 0x404024, 0xe000); - nv_wr32(dev, 0x404028, 0x0); - nv_wr32(dev, 0x4040a8, 0x0); - nv_wr32(dev, 0x4040ac, 0x0); - nv_wr32(dev, 0x4040b0, 0x0); - nv_wr32(dev, 0x4040b4, 0x0); - nv_wr32(dev, 0x4040b8, 0x0); - nv_wr32(dev, 0x4040bc, 0x0); - nv_wr32(dev, 0x4040c0, 0x0); - nv_wr32(dev, 0x4040c4, 0x0); - nv_wr32(dev, 0x4040c8, 0xf800008f); - nv_wr32(dev, 0x4040d0, 0x0); - nv_wr32(dev, 0x4040d4, 0x0); - nv_wr32(dev, 0x4040d8, 0x0); - nv_wr32(dev, 0x4040dc, 0x0); - nv_wr32(dev, 0x4040e0, 0x0); - nv_wr32(dev, 0x4040e4, 0x0); - nv_wr32(dev, 0x4040e8, 0x1000); - nv_wr32(dev, 0x4040f8, 0x0); - nv_wr32(dev, 0x404130, 0x0); - nv_wr32(dev, 0x404134, 0x0); - nv_wr32(dev, 0x404138, 0x20000040); - nv_wr32(dev, 0x404150, 0x2e); - nv_wr32(dev, 0x404154, 0x400); - nv_wr32(dev, 0x404158, 0x200); - nv_wr32(dev, 0x404164, 0x55); - nv_wr32(dev, 0x4041a0, 0x0); - nv_wr32(dev, 0x4041a4, 0x0); - nv_wr32(dev, 0x4041a8, 0x0); - nv_wr32(dev, 0x4041ac, 0x0); - nv_wr32(dev, 0x404200, 0x0); - nv_wr32(dev, 0x404204, 0x0); - nv_wr32(dev, 0x404208, 0x0); - nv_wr32(dev, 0x40420c, 0x0); + nv_wr32(priv, 0x404010, 0x0); + nv_wr32(priv, 0x404014, 0x0); + nv_wr32(priv, 0x404018, 0x0); + nv_wr32(priv, 0x40401c, 0x0); + nv_wr32(priv, 0x404020, 0x0); + nv_wr32(priv, 0x404024, 0xe000); + nv_wr32(priv, 0x404028, 0x0); + nv_wr32(priv, 0x4040a8, 0x0); + nv_wr32(priv, 0x4040ac, 0x0); + nv_wr32(priv, 0x4040b0, 0x0); + nv_wr32(priv, 0x4040b4, 0x0); + nv_wr32(priv, 0x4040b8, 0x0); + nv_wr32(priv, 0x4040bc, 0x0); + nv_wr32(priv, 0x4040c0, 0x0); + nv_wr32(priv, 0x4040c4, 0x0); + nv_wr32(priv, 0x4040c8, 0xf800008f); + nv_wr32(priv, 0x4040d0, 0x0); + nv_wr32(priv, 0x4040d4, 0x0); + nv_wr32(priv, 0x4040d8, 0x0); + nv_wr32(priv, 0x4040dc, 0x0); + nv_wr32(priv, 0x4040e0, 0x0); + nv_wr32(priv, 0x4040e4, 0x0); + nv_wr32(priv, 0x4040e8, 0x1000); + nv_wr32(priv, 0x4040f8, 0x0); + nv_wr32(priv, 0x404130, 0x0); + nv_wr32(priv, 0x404134, 0x0); + nv_wr32(priv, 0x404138, 0x20000040); + nv_wr32(priv, 0x404150, 0x2e); + nv_wr32(priv, 0x404154, 0x400); + nv_wr32(priv, 0x404158, 0x200); + nv_wr32(priv, 0x404164, 0x55); + nv_wr32(priv, 0x4041a0, 0x0); + nv_wr32(priv, 0x4041a4, 0x0); + nv_wr32(priv, 0x4041a8, 0x0); + nv_wr32(priv, 0x4041ac, 0x0); + nv_wr32(priv, 0x404200, 0x0); + nv_wr32(priv, 0x404204, 0x0); + nv_wr32(priv, 0x404208, 0x0); + nv_wr32(priv, 0x40420c, 0x0); } static void -nve0_graph_generate_unk44xx(struct drm_device *dev) +nve0_graph_generate_unk44xx(struct drm_device *priv) { - nv_wr32(dev, 0x404404, 0x0); - nv_wr32(dev, 0x404408, 0x0); - nv_wr32(dev, 0x40440c, 0x0); - nv_wr32(dev, 0x404410, 0x0); - nv_wr32(dev, 0x404414, 0x0); - nv_wr32(dev, 0x404418, 0x0); - nv_wr32(dev, 0x40441c, 0x0); - nv_wr32(dev, 0x404420, 0x0); - nv_wr32(dev, 0x404424, 0x0); - nv_wr32(dev, 0x404428, 0x0); - nv_wr32(dev, 0x40442c, 0x0); - nv_wr32(dev, 0x404430, 0x0); - nv_wr32(dev, 0x404434, 0x0); - nv_wr32(dev, 0x404438, 0x0); - nv_wr32(dev, 0x404460, 0x0); - nv_wr32(dev, 0x404464, 0x0); - nv_wr32(dev, 0x404468, 0xffffff); - nv_wr32(dev, 0x40446c, 0x0); - nv_wr32(dev, 0x404480, 0x1); - nv_wr32(dev, 0x404498, 0x1); + nv_wr32(priv, 0x404404, 0x0); + nv_wr32(priv, 0x404408, 0x0); + nv_wr32(priv, 0x40440c, 0x0); + nv_wr32(priv, 0x404410, 0x0); + nv_wr32(priv, 0x404414, 0x0); + nv_wr32(priv, 0x404418, 0x0); + nv_wr32(priv, 0x40441c, 0x0); + nv_wr32(priv, 0x404420, 0x0); + nv_wr32(priv, 0x404424, 0x0); + nv_wr32(priv, 0x404428, 0x0); + nv_wr32(priv, 0x40442c, 0x0); + nv_wr32(priv, 0x404430, 0x0); + nv_wr32(priv, 0x404434, 0x0); + nv_wr32(priv, 0x404438, 0x0); + nv_wr32(priv, 0x404460, 0x0); + nv_wr32(priv, 0x404464, 0x0); + nv_wr32(priv, 0x404468, 0xffffff); + nv_wr32(priv, 0x40446c, 0x0); + nv_wr32(priv, 0x404480, 0x1); + nv_wr32(priv, 0x404498, 0x1); } static void -nve0_graph_generate_unk46xx(struct drm_device *dev) +nve0_graph_generate_unk46xx(struct drm_device *priv) { - nv_wr32(dev, 0x404604, 0x14); - nv_wr32(dev, 0x404608, 0x0); - nv_wr32(dev, 0x40460c, 0x3fff); - nv_wr32(dev, 0x404610, 0x100); - nv_wr32(dev, 0x404618, 0x0); - nv_wr32(dev, 0x40461c, 0x0); - nv_wr32(dev, 0x404620, 0x0); - nv_wr32(dev, 0x404624, 0x0); - nv_wr32(dev, 0x40462c, 0x0); - nv_wr32(dev, 0x404630, 0x0); - nv_wr32(dev, 0x404640, 0x0); - nv_wr32(dev, 0x404654, 0x0); - nv_wr32(dev, 0x404660, 0x0); - nv_wr32(dev, 0x404678, 0x0); - nv_wr32(dev, 0x40467c, 0x2); - nv_wr32(dev, 0x404680, 0x0); - nv_wr32(dev, 0x404684, 0x0); - nv_wr32(dev, 0x404688, 0x0); - nv_wr32(dev, 0x40468c, 0x0); - nv_wr32(dev, 0x404690, 0x0); - nv_wr32(dev, 0x404694, 0x0); - nv_wr32(dev, 0x404698, 0x0); - nv_wr32(dev, 0x40469c, 0x0); - nv_wr32(dev, 0x4046a0, 0x7f0080); - nv_wr32(dev, 0x4046a4, 0x0); - nv_wr32(dev, 0x4046a8, 0x0); - nv_wr32(dev, 0x4046ac, 0x0); - nv_wr32(dev, 0x4046b0, 0x0); - nv_wr32(dev, 0x4046b4, 0x0); - nv_wr32(dev, 0x4046b8, 0x0); - nv_wr32(dev, 0x4046bc, 0x0); - nv_wr32(dev, 0x4046c0, 0x0); - nv_wr32(dev, 0x4046c8, 0x0); - nv_wr32(dev, 0x4046cc, 0x0); - nv_wr32(dev, 0x4046d0, 0x0); + nv_wr32(priv, 0x404604, 0x14); + nv_wr32(priv, 0x404608, 0x0); + nv_wr32(priv, 0x40460c, 0x3fff); + nv_wr32(priv, 0x404610, 0x100); + nv_wr32(priv, 0x404618, 0x0); + nv_wr32(priv, 0x40461c, 0x0); + nv_wr32(priv, 0x404620, 0x0); + nv_wr32(priv, 0x404624, 0x0); + nv_wr32(priv, 0x40462c, 0x0); + nv_wr32(priv, 0x404630, 0x0); + nv_wr32(priv, 0x404640, 0x0); + nv_wr32(priv, 0x404654, 0x0); + nv_wr32(priv, 0x404660, 0x0); + nv_wr32(priv, 0x404678, 0x0); + nv_wr32(priv, 0x40467c, 0x2); + nv_wr32(priv, 0x404680, 0x0); + nv_wr32(priv, 0x404684, 0x0); + nv_wr32(priv, 0x404688, 0x0); + nv_wr32(priv, 0x40468c, 0x0); + nv_wr32(priv, 0x404690, 0x0); + nv_wr32(priv, 0x404694, 0x0); + nv_wr32(priv, 0x404698, 0x0); + nv_wr32(priv, 0x40469c, 0x0); + nv_wr32(priv, 0x4046a0, 0x7f0080); + nv_wr32(priv, 0x4046a4, 0x0); + nv_wr32(priv, 0x4046a8, 0x0); + nv_wr32(priv, 0x4046ac, 0x0); + nv_wr32(priv, 0x4046b0, 0x0); + nv_wr32(priv, 0x4046b4, 0x0); + nv_wr32(priv, 0x4046b8, 0x0); + nv_wr32(priv, 0x4046bc, 0x0); + nv_wr32(priv, 0x4046c0, 0x0); + nv_wr32(priv, 0x4046c8, 0x0); + nv_wr32(priv, 0x4046cc, 0x0); + nv_wr32(priv, 0x4046d0, 0x0); } static void -nve0_graph_generate_unk47xx(struct drm_device *dev) +nve0_graph_generate_unk47xx(struct drm_device *priv) { - nv_wr32(dev, 0x404700, 0x0); - nv_wr32(dev, 0x404704, 0x0); - nv_wr32(dev, 0x404708, 0x0); - nv_wr32(dev, 0x404718, 0x0); - nv_wr32(dev, 0x40471c, 0x0); - nv_wr32(dev, 0x404720, 0x0); - nv_wr32(dev, 0x404724, 0x0); - nv_wr32(dev, 0x404728, 0x0); - nv_wr32(dev, 0x40472c, 0x0); - nv_wr32(dev, 0x404730, 0x0); - nv_wr32(dev, 0x404734, 0x100); - nv_wr32(dev, 0x404738, 0x0); - nv_wr32(dev, 0x40473c, 0x0); - nv_wr32(dev, 0x404744, 0x0); - nv_wr32(dev, 0x404748, 0x0); - nv_wr32(dev, 0x404754, 0x0); + nv_wr32(priv, 0x404700, 0x0); + nv_wr32(priv, 0x404704, 0x0); + nv_wr32(priv, 0x404708, 0x0); + nv_wr32(priv, 0x404718, 0x0); + nv_wr32(priv, 0x40471c, 0x0); + nv_wr32(priv, 0x404720, 0x0); + nv_wr32(priv, 0x404724, 0x0); + nv_wr32(priv, 0x404728, 0x0); + nv_wr32(priv, 0x40472c, 0x0); + nv_wr32(priv, 0x404730, 0x0); + nv_wr32(priv, 0x404734, 0x100); + nv_wr32(priv, 0x404738, 0x0); + nv_wr32(priv, 0x40473c, 0x0); + nv_wr32(priv, 0x404744, 0x0); + nv_wr32(priv, 0x404748, 0x0); + nv_wr32(priv, 0x404754, 0x0); } static void -nve0_graph_generate_unk58xx(struct drm_device *dev) +nve0_graph_generate_unk58xx(struct drm_device *priv) { - nv_wr32(dev, 0x405800, 0xf8000bf); - nv_wr32(dev, 0x405830, 0x2180648); - nv_wr32(dev, 0x405834, 0x8000000); - nv_wr32(dev, 0x405838, 0x0); - nv_wr32(dev, 0x405854, 0x0); - nv_wr32(dev, 0x405870, 0x1); - nv_wr32(dev, 0x405874, 0x1); - nv_wr32(dev, 0x405878, 0x1); - nv_wr32(dev, 0x40587c, 0x1); - nv_wr32(dev, 0x405a00, 0x0); - nv_wr32(dev, 0x405a04, 0x0); - nv_wr32(dev, 0x405a18, 0x0); - nv_wr32(dev, 0x405b00, 0x0); - nv_wr32(dev, 0x405b10, 0x1000); + nv_wr32(priv, 0x405800, 0xf8000bf); + nv_wr32(priv, 0x405830, 0x2180648); + nv_wr32(priv, 0x405834, 0x8000000); + nv_wr32(priv, 0x405838, 0x0); + nv_wr32(priv, 0x405854, 0x0); + nv_wr32(priv, 0x405870, 0x1); + nv_wr32(priv, 0x405874, 0x1); + nv_wr32(priv, 0x405878, 0x1); + nv_wr32(priv, 0x40587c, 0x1); + nv_wr32(priv, 0x405a00, 0x0); + nv_wr32(priv, 0x405a04, 0x0); + nv_wr32(priv, 0x405a18, 0x0); + nv_wr32(priv, 0x405b00, 0x0); + nv_wr32(priv, 0x405b10, 0x1000); } static void -nve0_graph_generate_unk60xx(struct drm_device *dev) +nve0_graph_generate_unk60xx(struct drm_device *priv) { - nv_wr32(dev, 0x406020, 0x4103c1); - nv_wr32(dev, 0x406028, 0x1); - nv_wr32(dev, 0x40602c, 0x1); - nv_wr32(dev, 0x406030, 0x1); - nv_wr32(dev, 0x406034, 0x1); + nv_wr32(priv, 0x406020, 0x4103c1); + nv_wr32(priv, 0x406028, 0x1); + nv_wr32(priv, 0x40602c, 0x1); + nv_wr32(priv, 0x406030, 0x1); + nv_wr32(priv, 0x406034, 0x1); } static void -nve0_graph_generate_unk64xx(struct drm_device *dev) +nve0_graph_generate_unk64xx(struct drm_device *priv) { - nv_wr32(dev, 0x4064a8, 0x0); - nv_wr32(dev, 0x4064ac, 0x3fff); - nv_wr32(dev, 0x4064b4, 0x0); - nv_wr32(dev, 0x4064b8, 0x0); - nv_wr32(dev, 0x4064c0, 0x801a00f0); - nv_wr32(dev, 0x4064c4, 0x192ffff); - nv_wr32(dev, 0x4064c8, 0x1800600); - nv_wr32(dev, 0x4064cc, 0x0); - nv_wr32(dev, 0x4064d0, 0x0); - nv_wr32(dev, 0x4064d4, 0x0); - nv_wr32(dev, 0x4064d8, 0x0); - nv_wr32(dev, 0x4064dc, 0x0); - nv_wr32(dev, 0x4064e0, 0x0); - nv_wr32(dev, 0x4064e4, 0x0); - nv_wr32(dev, 0x4064e8, 0x0); - nv_wr32(dev, 0x4064ec, 0x0); - nv_wr32(dev, 0x4064fc, 0x22a); + nv_wr32(priv, 0x4064a8, 0x0); + nv_wr32(priv, 0x4064ac, 0x3fff); + nv_wr32(priv, 0x4064b4, 0x0); + nv_wr32(priv, 0x4064b8, 0x0); + nv_wr32(priv, 0x4064c0, 0x801a00f0); + nv_wr32(priv, 0x4064c4, 0x192ffff); + nv_wr32(priv, 0x4064c8, 0x1800600); + nv_wr32(priv, 0x4064cc, 0x0); + nv_wr32(priv, 0x4064d0, 0x0); + nv_wr32(priv, 0x4064d4, 0x0); + nv_wr32(priv, 0x4064d8, 0x0); + nv_wr32(priv, 0x4064dc, 0x0); + nv_wr32(priv, 0x4064e0, 0x0); + nv_wr32(priv, 0x4064e4, 0x0); + nv_wr32(priv, 0x4064e8, 0x0); + nv_wr32(priv, 0x4064ec, 0x0); + nv_wr32(priv, 0x4064fc, 0x22a); } static void -nve0_graph_generate_unk70xx(struct drm_device *dev) +nve0_graph_generate_unk70xx(struct drm_device *priv) { - nv_wr32(dev, 0x407040, 0x0); + nv_wr32(priv, 0x407040, 0x0); } static void -nve0_graph_generate_unk78xx(struct drm_device *dev) +nve0_graph_generate_unk78xx(struct drm_device *priv) { - nv_wr32(dev, 0x407804, 0x23); - nv_wr32(dev, 0x40780c, 0xa418820); - nv_wr32(dev, 0x407810, 0x62080e6); - nv_wr32(dev, 0x407814, 0x20398a4); - nv_wr32(dev, 0x407818, 0xe629062); - nv_wr32(dev, 0x40781c, 0xa418820); - nv_wr32(dev, 0x407820, 0xe6); - nv_wr32(dev, 0x4078bc, 0x103); + nv_wr32(priv, 0x407804, 0x23); + nv_wr32(priv, 0x40780c, 0xa418820); + nv_wr32(priv, 0x407810, 0x62080e6); + nv_wr32(priv, 0x407814, 0x20398a4); + nv_wr32(priv, 0x407818, 0xe629062); + nv_wr32(priv, 0x40781c, 0xa418820); + nv_wr32(priv, 0x407820, 0xe6); + nv_wr32(priv, 0x4078bc, 0x103); } static void -nve0_graph_generate_unk80xx(struct drm_device *dev) +nve0_graph_generate_unk80xx(struct drm_device *priv) { - nv_wr32(dev, 0x408000, 0x0); - nv_wr32(dev, 0x408004, 0x0); - nv_wr32(dev, 0x408008, 0x30); - nv_wr32(dev, 0x40800c, 0x0); - nv_wr32(dev, 0x408010, 0x0); - nv_wr32(dev, 0x408014, 0x69); - nv_wr32(dev, 0x408018, 0xe100e100); - nv_wr32(dev, 0x408064, 0x0); + nv_wr32(priv, 0x408000, 0x0); + nv_wr32(priv, 0x408004, 0x0); + nv_wr32(priv, 0x408008, 0x30); + nv_wr32(priv, 0x40800c, 0x0); + nv_wr32(priv, 0x408010, 0x0); + nv_wr32(priv, 0x408014, 0x69); + nv_wr32(priv, 0x408018, 0xe100e100); + nv_wr32(priv, 0x408064, 0x0); } static void -nve0_graph_generate_unk88xx(struct drm_device *dev) +nve0_graph_generate_unk88xx(struct drm_device *priv) { - nv_wr32(dev, 0x408800, 0x2802a3c); - nv_wr32(dev, 0x408804, 0x40); - nv_wr32(dev, 0x408808, 0x1043e005); - nv_wr32(dev, 0x408840, 0xb); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x62000001); - nv_wr32(dev, 0x408908, 0xc8102f); - nv_wr32(dev, 0x408980, 0x11d); + nv_wr32(priv, 0x408800, 0x2802a3c); + nv_wr32(priv, 0x408804, 0x40); + nv_wr32(priv, 0x408808, 0x1043e005); + nv_wr32(priv, 0x408840, 0xb); + nv_wr32(priv, 0x408900, 0x3080b801); + nv_wr32(priv, 0x408904, 0x62000001); + nv_wr32(priv, 0x408908, 0xc8102f); + nv_wr32(priv, 0x408980, 0x11d); } static void -nve0_graph_generate_gpc(struct drm_device *dev) +nve0_graph_generate_gpc(struct drm_device *priv) { - nv_wr32(dev, 0x418380, 0x16); - nv_wr32(dev, 0x418400, 0x38004e00); - nv_wr32(dev, 0x418404, 0x71e0ffff); - nv_wr32(dev, 0x41840c, 0x1008); - nv_wr32(dev, 0x418410, 0xfff0fff); - nv_wr32(dev, 0x418414, 0x2200fff); - nv_wr32(dev, 0x418450, 0x0); - nv_wr32(dev, 0x418454, 0x0); - nv_wr32(dev, 0x418458, 0x0); - nv_wr32(dev, 0x41845c, 0x0); - nv_wr32(dev, 0x418460, 0x0); - nv_wr32(dev, 0x418464, 0x0); - nv_wr32(dev, 0x418468, 0x1); - nv_wr32(dev, 0x41846c, 0x0); - nv_wr32(dev, 0x418470, 0x0); - nv_wr32(dev, 0x418600, 0x1f); - nv_wr32(dev, 0x418684, 0xf); - nv_wr32(dev, 0x418700, 0x2); - nv_wr32(dev, 0x418704, 0x80); - nv_wr32(dev, 0x418708, 0x0); - nv_wr32(dev, 0x41870c, 0x0); - nv_wr32(dev, 0x418710, 0x0); - nv_wr32(dev, 0x418800, 0x7006860a); - nv_wr32(dev, 0x418808, 0x0); - nv_wr32(dev, 0x41880c, 0x0); - nv_wr32(dev, 0x418810, 0x0); - nv_wr32(dev, 0x418828, 0x44); - nv_wr32(dev, 0x418830, 0x10000001); - nv_wr32(dev, 0x4188d8, 0x8); - nv_wr32(dev, 0x4188e0, 0x1000000); - nv_wr32(dev, 0x4188e8, 0x0); - nv_wr32(dev, 0x4188ec, 0x0); - nv_wr32(dev, 0x4188f0, 0x0); - nv_wr32(dev, 0x4188f4, 0x0); - nv_wr32(dev, 0x4188f8, 0x0); - nv_wr32(dev, 0x4188fc, 0x20100018); - nv_wr32(dev, 0x41891c, 0xff00ff); - nv_wr32(dev, 0x418924, 0x0); - nv_wr32(dev, 0x418928, 0xffff00); - nv_wr32(dev, 0x41892c, 0xff00); - nv_wr32(dev, 0x418a00, 0x0); - nv_wr32(dev, 0x418a04, 0x0); - nv_wr32(dev, 0x418a08, 0x0); - nv_wr32(dev, 0x418a0c, 0x10000); - nv_wr32(dev, 0x418a10, 0x0); - nv_wr32(dev, 0x418a14, 0x0); - nv_wr32(dev, 0x418a18, 0x0); - nv_wr32(dev, 0x418a20, 0x0); - nv_wr32(dev, 0x418a24, 0x0); - nv_wr32(dev, 0x418a28, 0x0); - nv_wr32(dev, 0x418a2c, 0x10000); - nv_wr32(dev, 0x418a30, 0x0); - nv_wr32(dev, 0x418a34, 0x0); - nv_wr32(dev, 0x418a38, 0x0); - nv_wr32(dev, 0x418a40, 0x0); - nv_wr32(dev, 0x418a44, 0x0); - nv_wr32(dev, 0x418a48, 0x0); - nv_wr32(dev, 0x418a4c, 0x10000); - nv_wr32(dev, 0x418a50, 0x0); - nv_wr32(dev, 0x418a54, 0x0); - nv_wr32(dev, 0x418a58, 0x0); - nv_wr32(dev, 0x418a60, 0x0); - nv_wr32(dev, 0x418a64, 0x0); - nv_wr32(dev, 0x418a68, 0x0); - nv_wr32(dev, 0x418a6c, 0x10000); - nv_wr32(dev, 0x418a70, 0x0); - nv_wr32(dev, 0x418a74, 0x0); - nv_wr32(dev, 0x418a78, 0x0); - nv_wr32(dev, 0x418a80, 0x0); - nv_wr32(dev, 0x418a84, 0x0); - nv_wr32(dev, 0x418a88, 0x0); - nv_wr32(dev, 0x418a8c, 0x10000); - nv_wr32(dev, 0x418a90, 0x0); - nv_wr32(dev, 0x418a94, 0x0); - nv_wr32(dev, 0x418a98, 0x0); - nv_wr32(dev, 0x418aa0, 0x0); - nv_wr32(dev, 0x418aa4, 0x0); - nv_wr32(dev, 0x418aa8, 0x0); - nv_wr32(dev, 0x418aac, 0x10000); - nv_wr32(dev, 0x418ab0, 0x0); - nv_wr32(dev, 0x418ab4, 0x0); - nv_wr32(dev, 0x418ab8, 0x0); - nv_wr32(dev, 0x418ac0, 0x0); - nv_wr32(dev, 0x418ac4, 0x0); - nv_wr32(dev, 0x418ac8, 0x0); - nv_wr32(dev, 0x418acc, 0x10000); - nv_wr32(dev, 0x418ad0, 0x0); - nv_wr32(dev, 0x418ad4, 0x0); - nv_wr32(dev, 0x418ad8, 0x0); - nv_wr32(dev, 0x418ae0, 0x0); - nv_wr32(dev, 0x418ae4, 0x0); - nv_wr32(dev, 0x418ae8, 0x0); - nv_wr32(dev, 0x418aec, 0x10000); - nv_wr32(dev, 0x418af0, 0x0); - nv_wr32(dev, 0x418af4, 0x0); - nv_wr32(dev, 0x418af8, 0x0); - nv_wr32(dev, 0x418b00, 0x6); - nv_wr32(dev, 0x418b08, 0xa418820); - nv_wr32(dev, 0x418b0c, 0x62080e6); - nv_wr32(dev, 0x418b10, 0x20398a4); - nv_wr32(dev, 0x418b14, 0xe629062); - nv_wr32(dev, 0x418b18, 0xa418820); - nv_wr32(dev, 0x418b1c, 0xe6); - nv_wr32(dev, 0x418bb8, 0x103); - nv_wr32(dev, 0x418c08, 0x1); - nv_wr32(dev, 0x418c10, 0x0); - nv_wr32(dev, 0x418c14, 0x0); - nv_wr32(dev, 0x418c18, 0x0); - nv_wr32(dev, 0x418c1c, 0x0); - nv_wr32(dev, 0x418c20, 0x0); - nv_wr32(dev, 0x418c24, 0x0); - nv_wr32(dev, 0x418c28, 0x0); - nv_wr32(dev, 0x418c2c, 0x0); - nv_wr32(dev, 0x418c40, 0xffffffff); - nv_wr32(dev, 0x418c6c, 0x1); - nv_wr32(dev, 0x418c80, 0x20200004); - nv_wr32(dev, 0x418c8c, 0x1); - nv_wr32(dev, 0x419000, 0x780); - nv_wr32(dev, 0x419004, 0x0); - nv_wr32(dev, 0x419008, 0x0); - nv_wr32(dev, 0x419014, 0x4); + nv_wr32(priv, 0x418380, 0x16); + nv_wr32(priv, 0x418400, 0x38004e00); + nv_wr32(priv, 0x418404, 0x71e0ffff); + nv_wr32(priv, 0x41840c, 0x1008); + nv_wr32(priv, 0x418410, 0xfff0fff); + nv_wr32(priv, 0x418414, 0x2200fff); + nv_wr32(priv, 0x418450, 0x0); + nv_wr32(priv, 0x418454, 0x0); + nv_wr32(priv, 0x418458, 0x0); + nv_wr32(priv, 0x41845c, 0x0); + nv_wr32(priv, 0x418460, 0x0); + nv_wr32(priv, 0x418464, 0x0); + nv_wr32(priv, 0x418468, 0x1); + nv_wr32(priv, 0x41846c, 0x0); + nv_wr32(priv, 0x418470, 0x0); + nv_wr32(priv, 0x418600, 0x1f); + nv_wr32(priv, 0x418684, 0xf); + nv_wr32(priv, 0x418700, 0x2); + nv_wr32(priv, 0x418704, 0x80); + nv_wr32(priv, 0x418708, 0x0); + nv_wr32(priv, 0x41870c, 0x0); + nv_wr32(priv, 0x418710, 0x0); + nv_wr32(priv, 0x418800, 0x7006860a); + nv_wr32(priv, 0x418808, 0x0); + nv_wr32(priv, 0x41880c, 0x0); + nv_wr32(priv, 0x418810, 0x0); + nv_wr32(priv, 0x418828, 0x44); + nv_wr32(priv, 0x418830, 0x10000001); + nv_wr32(priv, 0x4188d8, 0x8); + nv_wr32(priv, 0x4188e0, 0x1000000); + nv_wr32(priv, 0x4188e8, 0x0); + nv_wr32(priv, 0x4188ec, 0x0); + nv_wr32(priv, 0x4188f0, 0x0); + nv_wr32(priv, 0x4188f4, 0x0); + nv_wr32(priv, 0x4188f8, 0x0); + nv_wr32(priv, 0x4188fc, 0x20100018); + nv_wr32(priv, 0x41891c, 0xff00ff); + nv_wr32(priv, 0x418924, 0x0); + nv_wr32(priv, 0x418928, 0xffff00); + nv_wr32(priv, 0x41892c, 0xff00); + nv_wr32(priv, 0x418a00, 0x0); + nv_wr32(priv, 0x418a04, 0x0); + nv_wr32(priv, 0x418a08, 0x0); + nv_wr32(priv, 0x418a0c, 0x10000); + nv_wr32(priv, 0x418a10, 0x0); + nv_wr32(priv, 0x418a14, 0x0); + nv_wr32(priv, 0x418a18, 0x0); + nv_wr32(priv, 0x418a20, 0x0); + nv_wr32(priv, 0x418a24, 0x0); + nv_wr32(priv, 0x418a28, 0x0); + nv_wr32(priv, 0x418a2c, 0x10000); + nv_wr32(priv, 0x418a30, 0x0); + nv_wr32(priv, 0x418a34, 0x0); + nv_wr32(priv, 0x418a38, 0x0); + nv_wr32(priv, 0x418a40, 0x0); + nv_wr32(priv, 0x418a44, 0x0); + nv_wr32(priv, 0x418a48, 0x0); + nv_wr32(priv, 0x418a4c, 0x10000); + nv_wr32(priv, 0x418a50, 0x0); + nv_wr32(priv, 0x418a54, 0x0); + nv_wr32(priv, 0x418a58, 0x0); + nv_wr32(priv, 0x418a60, 0x0); + nv_wr32(priv, 0x418a64, 0x0); + nv_wr32(priv, 0x418a68, 0x0); + nv_wr32(priv, 0x418a6c, 0x10000); + nv_wr32(priv, 0x418a70, 0x0); + nv_wr32(priv, 0x418a74, 0x0); + nv_wr32(priv, 0x418a78, 0x0); + nv_wr32(priv, 0x418a80, 0x0); + nv_wr32(priv, 0x418a84, 0x0); + nv_wr32(priv, 0x418a88, 0x0); + nv_wr32(priv, 0x418a8c, 0x10000); + nv_wr32(priv, 0x418a90, 0x0); + nv_wr32(priv, 0x418a94, 0x0); + nv_wr32(priv, 0x418a98, 0x0); + nv_wr32(priv, 0x418aa0, 0x0); + nv_wr32(priv, 0x418aa4, 0x0); + nv_wr32(priv, 0x418aa8, 0x0); + nv_wr32(priv, 0x418aac, 0x10000); + nv_wr32(priv, 0x418ab0, 0x0); + nv_wr32(priv, 0x418ab4, 0x0); + nv_wr32(priv, 0x418ab8, 0x0); + nv_wr32(priv, 0x418ac0, 0x0); + nv_wr32(priv, 0x418ac4, 0x0); + nv_wr32(priv, 0x418ac8, 0x0); + nv_wr32(priv, 0x418acc, 0x10000); + nv_wr32(priv, 0x418ad0, 0x0); + nv_wr32(priv, 0x418ad4, 0x0); + nv_wr32(priv, 0x418ad8, 0x0); + nv_wr32(priv, 0x418ae0, 0x0); + nv_wr32(priv, 0x418ae4, 0x0); + nv_wr32(priv, 0x418ae8, 0x0); + nv_wr32(priv, 0x418aec, 0x10000); + nv_wr32(priv, 0x418af0, 0x0); + nv_wr32(priv, 0x418af4, 0x0); + nv_wr32(priv, 0x418af8, 0x0); + nv_wr32(priv, 0x418b00, 0x6); + nv_wr32(priv, 0x418b08, 0xa418820); + nv_wr32(priv, 0x418b0c, 0x62080e6); + nv_wr32(priv, 0x418b10, 0x20398a4); + nv_wr32(priv, 0x418b14, 0xe629062); + nv_wr32(priv, 0x418b18, 0xa418820); + nv_wr32(priv, 0x418b1c, 0xe6); + nv_wr32(priv, 0x418bb8, 0x103); + nv_wr32(priv, 0x418c08, 0x1); + nv_wr32(priv, 0x418c10, 0x0); + nv_wr32(priv, 0x418c14, 0x0); + nv_wr32(priv, 0x418c18, 0x0); + nv_wr32(priv, 0x418c1c, 0x0); + nv_wr32(priv, 0x418c20, 0x0); + nv_wr32(priv, 0x418c24, 0x0); + nv_wr32(priv, 0x418c28, 0x0); + nv_wr32(priv, 0x418c2c, 0x0); + nv_wr32(priv, 0x418c40, 0xffffffff); + nv_wr32(priv, 0x418c6c, 0x1); + nv_wr32(priv, 0x418c80, 0x20200004); + nv_wr32(priv, 0x418c8c, 0x1); + nv_wr32(priv, 0x419000, 0x780); + nv_wr32(priv, 0x419004, 0x0); + nv_wr32(priv, 0x419008, 0x0); + nv_wr32(priv, 0x419014, 0x4); } static void -nve0_graph_generate_tpc(struct drm_device *dev) +nve0_graph_generate_tpc(struct drm_device *priv) { - nv_wr32(dev, 0x419848, 0x0); - nv_wr32(dev, 0x419864, 0x129); - nv_wr32(dev, 0x419888, 0x0); - nv_wr32(dev, 0x419a00, 0xf0); - nv_wr32(dev, 0x419a04, 0x1); - nv_wr32(dev, 0x419a08, 0x21); - nv_wr32(dev, 0x419a0c, 0x20000); - nv_wr32(dev, 0x419a10, 0x0); - nv_wr32(dev, 0x419a14, 0x200); - nv_wr32(dev, 0x419a1c, 0xc000); - nv_wr32(dev, 0x419a20, 0x800); - nv_wr32(dev, 0x419a30, 0x1); - nv_wr32(dev, 0x419ac4, 0x37f440); - nv_wr32(dev, 0x419c00, 0xa); - nv_wr32(dev, 0x419c04, 0x80000006); - nv_wr32(dev, 0x419c08, 0x2); - nv_wr32(dev, 0x419c20, 0x0); - nv_wr32(dev, 0x419c24, 0x84210); - nv_wr32(dev, 0x419c28, 0x3efbefbe); - nv_wr32(dev, 0x419ce8, 0x0); - nv_wr32(dev, 0x419cf4, 0x3203); - nv_wr32(dev, 0x419e04, 0x0); - nv_wr32(dev, 0x419e08, 0x0); - nv_wr32(dev, 0x419e0c, 0x0); - nv_wr32(dev, 0x419e10, 0x402); - nv_wr32(dev, 0x419e44, 0x13eff2); - nv_wr32(dev, 0x419e48, 0x0); - nv_wr32(dev, 0x419e4c, 0x7f); - nv_wr32(dev, 0x419e50, 0x0); - nv_wr32(dev, 0x419e54, 0x0); - nv_wr32(dev, 0x419e58, 0x0); - nv_wr32(dev, 0x419e5c, 0x0); - nv_wr32(dev, 0x419e60, 0x0); - nv_wr32(dev, 0x419e64, 0x0); - nv_wr32(dev, 0x419e68, 0x0); - nv_wr32(dev, 0x419e6c, 0x0); - nv_wr32(dev, 0x419e70, 0x0); - nv_wr32(dev, 0x419e74, 0x0); - nv_wr32(dev, 0x419e78, 0x0); - nv_wr32(dev, 0x419e7c, 0x0); - nv_wr32(dev, 0x419e80, 0x0); - nv_wr32(dev, 0x419e84, 0x0); - nv_wr32(dev, 0x419e88, 0x0); - nv_wr32(dev, 0x419e8c, 0x0); - nv_wr32(dev, 0x419e90, 0x0); - nv_wr32(dev, 0x419e94, 0x0); - nv_wr32(dev, 0x419e98, 0x0); - nv_wr32(dev, 0x419eac, 0x1fcf); - nv_wr32(dev, 0x419eb0, 0xd3f); - nv_wr32(dev, 0x419ec8, 0x1304f); - nv_wr32(dev, 0x419f30, 0x0); - nv_wr32(dev, 0x419f34, 0x0); - nv_wr32(dev, 0x419f38, 0x0); - nv_wr32(dev, 0x419f3c, 0x0); - nv_wr32(dev, 0x419f40, 0x0); - nv_wr32(dev, 0x419f44, 0x0); - nv_wr32(dev, 0x419f48, 0x0); - nv_wr32(dev, 0x419f4c, 0x0); - nv_wr32(dev, 0x419f58, 0x0); - nv_wr32(dev, 0x419f78, 0xb); + nv_wr32(priv, 0x419848, 0x0); + nv_wr32(priv, 0x419864, 0x129); + nv_wr32(priv, 0x419888, 0x0); + nv_wr32(priv, 0x419a00, 0xf0); + nv_wr32(priv, 0x419a04, 0x1); + nv_wr32(priv, 0x419a08, 0x21); + nv_wr32(priv, 0x419a0c, 0x20000); + nv_wr32(priv, 0x419a10, 0x0); + nv_wr32(priv, 0x419a14, 0x200); + nv_wr32(priv, 0x419a1c, 0xc000); + nv_wr32(priv, 0x419a20, 0x800); + nv_wr32(priv, 0x419a30, 0x1); + nv_wr32(priv, 0x419ac4, 0x37f440); + nv_wr32(priv, 0x419c00, 0xa); + nv_wr32(priv, 0x419c04, 0x80000006); + nv_wr32(priv, 0x419c08, 0x2); + nv_wr32(priv, 0x419c20, 0x0); + nv_wr32(priv, 0x419c24, 0x84210); + nv_wr32(priv, 0x419c28, 0x3efbefbe); + nv_wr32(priv, 0x419ce8, 0x0); + nv_wr32(priv, 0x419cf4, 0x3203); + nv_wr32(priv, 0x419e04, 0x0); + nv_wr32(priv, 0x419e08, 0x0); + nv_wr32(priv, 0x419e0c, 0x0); + nv_wr32(priv, 0x419e10, 0x402); + nv_wr32(priv, 0x419e44, 0x13eff2); + nv_wr32(priv, 0x419e48, 0x0); + nv_wr32(priv, 0x419e4c, 0x7f); + nv_wr32(priv, 0x419e50, 0x0); + nv_wr32(priv, 0x419e54, 0x0); + nv_wr32(priv, 0x419e58, 0x0); + nv_wr32(priv, 0x419e5c, 0x0); + nv_wr32(priv, 0x419e60, 0x0); + nv_wr32(priv, 0x419e64, 0x0); + nv_wr32(priv, 0x419e68, 0x0); + nv_wr32(priv, 0x419e6c, 0x0); + nv_wr32(priv, 0x419e70, 0x0); + nv_wr32(priv, 0x419e74, 0x0); + nv_wr32(priv, 0x419e78, 0x0); + nv_wr32(priv, 0x419e7c, 0x0); + nv_wr32(priv, 0x419e80, 0x0); + nv_wr32(priv, 0x419e84, 0x0); + nv_wr32(priv, 0x419e88, 0x0); + nv_wr32(priv, 0x419e8c, 0x0); + nv_wr32(priv, 0x419e90, 0x0); + nv_wr32(priv, 0x419e94, 0x0); + nv_wr32(priv, 0x419e98, 0x0); + nv_wr32(priv, 0x419eac, 0x1fcf); + nv_wr32(priv, 0x419eb0, 0xd3f); + nv_wr32(priv, 0x419ec8, 0x1304f); + nv_wr32(priv, 0x419f30, 0x0); + nv_wr32(priv, 0x419f34, 0x0); + nv_wr32(priv, 0x419f38, 0x0); + nv_wr32(priv, 0x419f3c, 0x0); + nv_wr32(priv, 0x419f40, 0x0); + nv_wr32(priv, 0x419f44, 0x0); + nv_wr32(priv, 0x419f48, 0x0); + nv_wr32(priv, 0x419f4c, 0x0); + nv_wr32(priv, 0x419f58, 0x0); + nv_wr32(priv, 0x419f78, 0xb); } static void -nve0_graph_generate_tpcunk(struct drm_device *dev) +nve0_graph_generate_tpcunk(struct drm_device *priv) { - nv_wr32(dev, 0x41be24, 0x6); - nv_wr32(dev, 0x41bec0, 0x12180000); - nv_wr32(dev, 0x41bec4, 0x37f7f); - nv_wr32(dev, 0x41bee4, 0x6480430); - nv_wr32(dev, 0x41bf00, 0xa418820); - nv_wr32(dev, 0x41bf04, 0x62080e6); - nv_wr32(dev, 0x41bf08, 0x20398a4); - nv_wr32(dev, 0x41bf0c, 0xe629062); - nv_wr32(dev, 0x41bf10, 0xa418820); - nv_wr32(dev, 0x41bf14, 0xe6); - nv_wr32(dev, 0x41bfd0, 0x900103); - nv_wr32(dev, 0x41bfe0, 0x400001); - nv_wr32(dev, 0x41bfe4, 0x0); + nv_wr32(priv, 0x41be24, 0x6); + nv_wr32(priv, 0x41bec0, 0x12180000); + nv_wr32(priv, 0x41bec4, 0x37f7f); + nv_wr32(priv, 0x41bee4, 0x6480430); + nv_wr32(priv, 0x41bf00, 0xa418820); + nv_wr32(priv, 0x41bf04, 0x62080e6); + nv_wr32(priv, 0x41bf08, 0x20398a4); + nv_wr32(priv, 0x41bf0c, 0xe629062); + nv_wr32(priv, 0x41bf10, 0xa418820); + nv_wr32(priv, 0x41bf14, 0xe6); + nv_wr32(priv, 0x41bfd0, 0x900103); + nv_wr32(priv, 0x41bfe0, 0x400001); + nv_wr32(priv, 0x41bfe4, 0x0); } int nve0_grctx_generate(struct nouveau_channel *chan) { - struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nve0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; + struct drm_device *priv = chan->dev; u32 data[6] = {}, data2[2] = {}, tmp; u32 tpc_set = 0, tpc_mask = 0; u8 tpcnr[GPC_MAX], a, b; u8 shift, ntpcv; int i, gpc, tpc, id; - nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nv_wr32(dev, 0x400204, 0x00000000); - nv_wr32(dev, 0x400208, 0x00000000); + nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nv_wr32(priv, 0x400204, 0x00000000); + nv_wr32(priv, 0x400208, 0x00000000); - nve0_graph_generate_unk40xx(dev); - nve0_graph_generate_unk44xx(dev); - nve0_graph_generate_unk46xx(dev); - nve0_graph_generate_unk47xx(dev); - nve0_graph_generate_unk58xx(dev); - nve0_graph_generate_unk60xx(dev); - nve0_graph_generate_unk64xx(dev); - nve0_graph_generate_unk70xx(dev); - nve0_graph_generate_unk78xx(dev); - nve0_graph_generate_unk80xx(dev); - nve0_graph_generate_unk88xx(dev); - nve0_graph_generate_gpc(dev); - nve0_graph_generate_tpc(dev); - nve0_graph_generate_tpcunk(dev); + nve0_graph_generate_unk40xx(priv); + nve0_graph_generate_unk44xx(priv); + nve0_graph_generate_unk46xx(priv); + nve0_graph_generate_unk47xx(priv); + nve0_graph_generate_unk58xx(priv); + nve0_graph_generate_unk60xx(priv); + nve0_graph_generate_unk64xx(priv); + nve0_graph_generate_unk70xx(priv); + nve0_graph_generate_unk78xx(priv); + nve0_graph_generate_unk80xx(priv); + nve0_graph_generate_unk88xx(priv); + nve0_graph_generate_gpc(priv); + nve0_graph_generate_tpc(priv); + nve0_graph_generate_tpcunk(priv); - nv_wr32(dev, 0x404154, 0x0); + nv_wr32(priv, 0x404154, 0x0); for (i = 0; i < grch->mmio_nr * 8; i += 8) { u32 reg = nv_ro32(grch->mmio, i + 0); u32 val = nv_ro32(grch->mmio, i + 4); - nv_wr32(dev, reg, val); + nv_wr32(priv, reg, val); } - nv_wr32(dev, 0x418c6c, 0x1); - nv_wr32(dev, 0x41980c, 0x10); - nv_wr32(dev, 0x41be08, 0x4); - nv_wr32(dev, 0x4064c0, 0x801a00f0); - nv_wr32(dev, 0x405800, 0xf8000bf); - nv_wr32(dev, 0x419c00, 0xa); + nv_wr32(priv, 0x418c6c, 0x1); + nv_wr32(priv, 0x41980c, 0x10); + nv_wr32(priv, 0x41be08, 0x4); + nv_wr32(priv, 0x4064c0, 0x801a00f0); + nv_wr32(priv, 0x405800, 0xf8000bf); + nv_wr32(priv, 0x419c00, 0xa); for (tpc = 0, id = 0; tpc < 4; tpc++) { - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tpc < priv->tpc_nr[gpc]) { - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x0698), id); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x04e8), id); - nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); - nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x0088), id++); + for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { + if (tpc < oprv->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(dev, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tpc_nr[gpc]); } } tmp = 0; - for (i = 0; i < priv->gpc_nr; i++) - tmp |= priv->tpc_nr[i] << (i * 4); - nv_wr32(dev, 0x406028, tmp); - nv_wr32(dev, 0x405870, tmp); + for (i = 0; i < oprv->gpc_nr; i++) + tmp |= oprv->tpc_nr[i] << (i * 4); + nv_wr32(priv, 0x406028, tmp); + nv_wr32(priv, 0x405870, tmp); - nv_wr32(dev, 0x40602c, 0x0); - nv_wr32(dev, 0x405874, 0x0); - nv_wr32(dev, 0x406030, 0x0); - nv_wr32(dev, 0x405878, 0x0); - nv_wr32(dev, 0x406034, 0x0); - nv_wr32(dev, 0x40587c, 0x0); + nv_wr32(priv, 0x40602c, 0x0); + nv_wr32(priv, 0x405874, 0x0); + nv_wr32(priv, 0x406030, 0x0); + nv_wr32(priv, 0x405878, 0x0); + nv_wr32(priv, 0x406034, 0x0); + nv_wr32(priv, 0x40587c, 0x0); /* calculate first set of magics */ - memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); gpc = -1; - for (tpc = 0; tpc < priv->tpc_total; tpc++) { + for (tpc = 0; tpc < oprv->tpc_total; tpc++) { do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpcnr[gpc]); tpcnr[gpc]--; @@ -2709,7 +2709,7 @@ nve0_grctx_generate(struct nouveau_channel *chan) /* and the second... */ shift = 0; - ntpcv = priv->tpc_total; + ntpcv = oprv->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -2718,60 +2718,60 @@ nve0_grctx_generate(struct nouveau_channel *chan) data2[0] = ntpcv << 16; data2[0] |= shift << 21; data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24); - data2[0] |= priv->tpc_total << 8; - data2[0] |= priv->magic_not_rop_nr; + data2[0] |= oprv->tpc_total << 8; + data2[0] |= oprv->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(dev, 0x418bb8, (priv->tpc_total << 8) | priv->magic_not_rop_nr); + nv_wr32(priv, 0x418bb8, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(dev, 0x418b08 + (i * 4), data[i]); + nv_wr32(priv, 0x418b08 + (i * 4), data[i]); - nv_wr32(dev, 0x41bfd0, data2[0]); - nv_wr32(dev, 0x41bfe4, data2[1]); + nv_wr32(priv, 0x41bfd0, data2[0]); + nv_wr32(priv, 0x41bfe4, data2[1]); for (i = 0; i < 6; i++) - nv_wr32(dev, 0x41bf00 + (i * 4), data[i]); + nv_wr32(priv, 0x41bf00 + (i * 4), data[i]); - nv_wr32(dev, 0x4078bc, (priv->tpc_total << 8) | priv->magic_not_rop_nr); + nv_wr32(priv, 0x4078bc, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); for (i = 0; i < 6; i++) - nv_wr32(dev, 0x40780c + (i * 4), data[i]); + nv_wr32(priv, 0x40780c + (i * 4), data[i]); - 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); + 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); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (priv->tpc_total - 1)) / 32; + a = (i * (oprv->tpc_total - 1)) / 32; if (a != b) { b = a; do { - gpc = (gpc + 1) % priv->gpc_nr; + gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpcnr[gpc]); - tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; tpc_set |= 1 << ((gpc * 8) + tpc); } - nv_wr32(dev, 0x406800 + (i * 0x20), tpc_set); - nv_wr32(dev, 0x406c00 + (i * 0x20), tpc_set ^ tpc_mask); + nv_wr32(priv, 0x406800 + (i * 0x20), tpc_set); + nv_wr32(priv, 0x406c00 + (i * 0x20), tpc_set ^ tpc_mask); } for (i = 0; i < 8; i++) - nv_wr32(dev, 0x4064d0 + (i * 0x04), 0x00000000); + nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); - nv_wr32(dev, 0x405b00, 0x201); - nv_wr32(dev, 0x408850, 0x2); - nv_wr32(dev, 0x408958, 0x2); - nv_wr32(dev, 0x419f78, 0xa); + nv_wr32(priv, 0x405b00, 0x201); + nv_wr32(priv, 0x408850, 0x2); + nv_wr32(priv, 0x408958, 0x2); + nv_wr32(priv, 0x419f78, 0xa); - nve0_grctx_generate_icmd(dev); - nve0_grctx_generate_a097(dev); - nve0_grctx_generate_902d(dev); + nve0_grctx_generate_icmd(priv); + nve0_grctx_generate_a097(priv); + nve0_grctx_generate_902d(priv); - nv_mask(dev, 0x000260, 0x00000001, 0x00000001); - nv_wr32(dev, 0x418800, 0x7026860a); //XXX - nv_wr32(dev, 0x41be10, 0x00bb8bc7); //XXX + nv_mask(priv, 0x000260, 0x00000001, 0x00000001); + nv_wr32(priv, 0x418800, 0x7026860a); //XXX + nv_wr32(priv, 0x41be10, 0x00bb8bc7); //XXX return 0; } -- cgit v1.1 From f589be88caf32501a734e531180d5df5d6089ef3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 22 Jul 2012 11:55:54 +1000 Subject: drm/nouveau/pageflip: kick flip handling out of engsw and into fence This is all very much a policy thing, and hence will not belong in SW after the rework. engsw now only handles receiving the event to say "can flip now" and makes a callback to perform the actual work. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 8 ++++++-- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 10 +++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 6535a99..b99d976 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -27,6 +27,7 @@ #include "nouveau_drv.h" #include #include +#include "nouveau_software.h" static void nvc0_fifo_isr(struct drm_device *); @@ -323,8 +324,11 @@ nvc0_fifo_page_flip(struct drm_device *dev, u32 chid) spin_lock_irqsave(&dev_priv->channels.lock, flags); if (likely(chid >= 0 && chid < priv->base.channels)) { chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) - ret = nouveau_finish_page_flip(chan, NULL); + if (likely(chan)) { + struct nouveau_software_chan *swch = + chan->engctx[NVOBJ_ENGINE_SW]; + ret = swch->flip(swch->flip_data); + } } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 461fbf6..0b356f1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -27,6 +27,7 @@ #include "nouveau_drv.h" #include #include +#include "nouveau_software.h" #define NVE0_FIFO_ENGINE_NUM 32 @@ -302,8 +303,11 @@ nve0_fifo_page_flip(struct drm_device *dev, u32 chid) spin_lock_irqsave(&dev_priv->channels.lock, flags); if (likely(chid >= 0 && chid < priv->base.channels)) { chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) - ret = nouveau_finish_page_flip(chan, NULL); + if (likely(chan)) { + struct nouveau_software_chan *swch = + chan->engctx[NVOBJ_ENGINE_SW]; + ret = swch->flip(swch->flip_data); + } } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); return ret; @@ -315,7 +319,7 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0xfff; u32 subc = (addr & 0x00070000); u32 mthd = (addr & 0x00003ffc); u32 show = stat; -- cgit v1.1 From c4afbe74cebf887d3d8e7a11aa93bebcb6a3e2e1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 4 Aug 2012 18:26:50 +1000 Subject: drm/nvc0-/gr: share headers between fermi and kepler graphics code v2: Ben Skeggs - de-inline nv_icmd, triggers some gcc issue causing ctxnv[ce]0.c to take a *very* *very* long time to build on some configs. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 49 +++++------ .../gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 21 +---- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 58 ++++++------- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 85 +++++++++++++++---- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 40 ++++----- drivers/gpu/drm/nouveau/core/engine/graph/nve0.h | 94 ---------------------- 6 files changed, 143 insertions(+), 204 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nve0.h (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index af6167a..5735301 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -27,7 +27,7 @@ #include #include "nvc0.h" -static void +void nv_icmd(struct drm_device *priv, u32 icmd, u32 data) { nv_wr32(priv, 0x400204, data); @@ -36,13 +36,6 @@ nv_icmd(struct drm_device *priv, u32 icmd, u32 data) } static void -nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) -{ - nv_wr32(priv, 0x40448c, data); - nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); -} - -static void nvc0_grctx_generate_9097(struct drm_device *priv) { u32 fermi = nvc0_graph_class(priv); @@ -1823,22 +1816,22 @@ nvc0_grctx_generate(struct nouveau_channel *chan) for (tp = 0, id = 0; tp < 4; tp++) { for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - if (tp < oprv->tp_nr[gpc]) { - nv_wr32(priv, TP_UNIT(gpc, tp, 0x698), id); - nv_wr32(priv, TP_UNIT(gpc, tp, 0x4e8), id); + if (tp < oprv->tpc_nr[gpc]) { + nv_wr32(priv, TPC_UNIT(gpc, tp, 0x698), id); + nv_wr32(priv, TPC_UNIT(gpc, tp, 0x4e8), id); nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); - nv_wr32(priv, TP_UNIT(gpc, tp, 0x088), id); + nv_wr32(priv, TPC_UNIT(gpc, tp, 0x088), id); id++; } - nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tp_nr[gpc]); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tp_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), oprv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), oprv->tpc_nr[gpc]); } } tmp = 0; for (i = 0; i < oprv->gpc_nr; i++) - tmp |= oprv->tp_nr[i] << (i * 4); + tmp |= oprv->tpc_nr[i] << (i * 4); nv_wr32(priv, 0x406028, tmp); nv_wr32(priv, 0x405870, tmp); @@ -1850,13 +1843,13 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_wr32(priv, 0x40587c, 0x00000000); if (1) { - u8 tpnr[GPC_MAX], data[TP_MAX]; + u8 tpnr[GPC_MAX], data[TPC_MAX]; - memcpy(tpnr, oprv->tp_nr, sizeof(oprv->tp_nr)); + memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); memset(data, 0x1f, sizeof(data)); gpc = -1; - for (tp = 0; tp < oprv->tp_total; tp++) { + for (tp = 0; tp < oprv->tpc_total; tp++) { do { gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpnr[gpc]); @@ -1874,10 +1867,10 @@ nvc0_grctx_generate(struct nouveau_channel *chan) u8 shift, ntpcv; /* calculate first set of magics */ - memcpy(tpnr, oprv->tp_nr, sizeof(oprv->tp_nr)); + memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); gpc = -1; - for (tp = 0; tp < oprv->tp_total; tp++) { + for (tp = 0; tp < oprv->tpc_total; tp++) { do { gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpnr[gpc]); @@ -1891,7 +1884,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) /* and the second... */ shift = 0; - ntpcv = oprv->tp_total; + ntpcv = oprv->tpc_total; while (!(ntpcv & (1 << 4))) { ntpcv <<= 1; shift++; @@ -1904,13 +1897,13 @@ nvc0_grctx_generate(struct nouveau_channel *chan) data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); /* GPC_BROADCAST */ - nv_wr32(priv, 0x418bb8, (oprv->tp_total << 8) | + nv_wr32(priv, 0x418bb8, (oprv->tpc_total << 8) | oprv->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->tp_total << 8) | + nv_wr32(priv, 0x419bd0, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr | data2[0]); nv_wr32(priv, 0x419be4, data2[1]); @@ -1918,7 +1911,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_wr32(priv, 0x419b00 + (i * 4), data[i]); /* UNK78xx */ - nv_wr32(priv, 0x4078bc, (oprv->tp_total << 8) | + nv_wr32(priv, 0x4078bc, (oprv->tpc_total << 8) | oprv->magic_not_rop_nr); for (i = 0; i < 6; i++) nv_wr32(priv, 0x40780c + (i * 4), data[i]); @@ -1928,18 +1921,18 @@ nvc0_grctx_generate(struct nouveau_channel *chan) u32 tp_mask = 0, tp_set = 0; u8 tpnr[GPC_MAX], a, b; - memcpy(tpnr, oprv->tp_nr, sizeof(oprv->tp_nr)); + memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); for (gpc = 0; gpc < oprv->gpc_nr; gpc++) - tp_mask |= ((1 << oprv->tp_nr[gpc]) - 1) << (gpc * 8); + tp_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { - a = (i * (oprv->tp_total - 1)) / 32; + a = (i * (oprv->tpc_total - 1)) / 32; if (a != b) { b = a; do { gpc = (gpc + 1) % oprv->gpc_nr; } while (!tpnr[gpc]); - tp = oprv->tp_nr[gpc] - tpnr[gpc]--; + tp = oprv->tpc_nr[gpc] - tpnr[gpc]--; tp_set |= 1 << ((gpc * 8) + tp); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c index f03c667..47bea8a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -25,15 +25,7 @@ #include "drmP.h" #include "nouveau_drv.h" #include -#include "nve0.h" - -static void -nv_icmd(struct drm_device *priv, u32 icmd, u32 data) -{ - nv_wr32(priv, 0x400204, data); - nv_wr32(priv, 0x400200, icmd); - while (nv_rd32(priv, 0x400700) & 0x00000002) {} -} +#include "nvc0.h" static void nve0_grctx_generate_icmd(struct drm_device *priv) @@ -924,13 +916,6 @@ nve0_grctx_generate_icmd(struct drm_device *priv) } static void -nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) -{ - nv_wr32(priv, 0x40448c, data); - nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); -} - -static void nve0_grctx_generate_a097(struct drm_device *priv) { nv_mthd(priv, 0xa097, 0x0800, 0x00000000); @@ -2621,8 +2606,8 @@ nve0_graph_generate_tpcunk(struct drm_device *priv) int nve0_grctx_generate(struct nouveau_channel *chan) { - struct nve0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct nvc0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *priv = chan->dev; u32 data[6] = {}, data2[2] = {}, tmp; u32 tpc_set = 0, tpc_mask = 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index b741b03..158d576 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -229,8 +229,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) nv_wo32(grch->mmio, i++ * 4, 0x00405830); nv_wo32(grch->mmio, i++ * 4, magic); for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { - u32 reg = TP_UNIT(gpc, tp, 0x520); + for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { + u32 reg = TPC_UNIT(gpc, tp, 0x520); nv_wo32(grch->mmio, i++ * 4, reg); nv_wo32(grch->mmio, i++ * 4, magic); magic += 0x0324; @@ -243,14 +243,14 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) nv_wo32(grch->mmio, i++ * 4, 0x004064c4); nv_wo32(grch->mmio, i++ * 4, 0x0086ffff); for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { - u32 reg = TP_UNIT(gpc, tp, 0x520); + for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { + u32 reg = TPC_UNIT(gpc, tp, 0x520); nv_wo32(grch->mmio, i++ * 4, reg); nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic); magic += 0x0324; } - for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { - u32 reg = TP_UNIT(gpc, tp, 0x544); + for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { + u32 reg = TPC_UNIT(gpc, tp, 0x544); nv_wo32(grch->mmio, i++ * 4, reg); nv_wo32(grch->mmio, i++ * 4, magic); magic += 0x0324; @@ -393,12 +393,12 @@ static void nvc0_graph_init_gpc_0(struct drm_device *dev) { struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); - const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total); - u32 data[TP_MAX / 8]; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); + u32 data[TPC_MAX / 8]; u8 tpnr[GPC_MAX]; int i, gpc, tpc; - nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ + nv_wr32(dev, TPC_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ /* * TP ROP UNKVAL(magic_not_rop_nr) @@ -410,12 +410,12 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) */ memset(data, 0x00, sizeof(data)); - memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); - for (i = 0, gpc = -1; i < priv->tp_total; i++) { + memcpy(tpnr, 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->tp_nr[gpc] - tpnr[gpc]--; + tpc = priv->tpc_nr[gpc] - tpnr[gpc]--; data[i / 8] |= tpc << ((i % 8) * 4); } @@ -427,8 +427,8 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) for (gpc = 0; gpc < priv->gpc_nr; gpc++) { nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | - priv->tp_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total); + priv->tpc_nr[gpc]); + nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); } @@ -463,14 +463,14 @@ nvc0_graph_init_gpc_1(struct drm_device *dev) 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->tp_nr[gpc]; tp++) { - nv_wr32(dev, TP_UNIT(gpc, tp, 0x508), 0xffffffff); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x50c), 0xffffffff); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe); - nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f); + 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(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); @@ -858,20 +858,20 @@ nvc0_graph_create(struct drm_device *dev) 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->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); - priv->tp_total += priv->tp_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->tp_total == 11) { /* 465, 3/4/4/0, 4 */ + if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */ priv->magic_not_rop_nr = 0x07; } else - if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ + if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */ priv->magic_not_rop_nr = 0x05; } else - if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ + if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */ priv->magic_not_rop_nr = 0x06; } break; @@ -900,8 +900,8 @@ nvc0_graph_create(struct drm_device *dev) if (!priv->magic_not_rop_nr) { NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", - priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], - priv->tp_nr[3], priv->rop_nr); + 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; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index ffeb4a0..ba9b80f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -26,13 +26,26 @@ #define __NVC0_GRAPH_H__ #define GPC_MAX 4 -#define TP_MAX 32 +#define TPC_MAX 32 -#define ROP_BCAST(r) (0x408800 + (r)) -#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) -#define GPC_BCAST(r) (0x418000 + (r)) -#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) -#define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) +#define ROP_BCAST(r) (0x408800 + (r)) +#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) +#define GPC_BCAST(r) (0x418000 + (r)) +#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) +#define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) + +struct nvc0_graph_data { + u32 size; + u32 align; + u32 access; +}; + +struct nvc0_graph_mmio { + u32 addr; + u32 data; + u32 shift; + u32 buffer; +}; struct nvc0_graph_fuc { u32 *data; @@ -46,11 +59,12 @@ struct nvc0_graph_priv { struct nvc0_graph_fuc fuc409d; struct nvc0_graph_fuc fuc41ac; struct nvc0_graph_fuc fuc41ad; + bool firmware; - u8 gpc_nr; u8 rop_nr; - u8 tp_nr[GPC_MAX]; - u8 tp_total; + u8 gpc_nr; + u8 tpc_nr[GPC_MAX]; + u8 tpc_total; u32 grctx_size; u32 *grctx_vals; @@ -63,24 +77,22 @@ struct nvc0_graph_priv { struct nvc0_graph_chan { struct nouveau_gpuobj *grctx; struct nouveau_vma grctx_vma; - struct nouveau_gpuobj *unk408004; /* 0x418810 too */ + struct nouveau_gpuobj *unk408004; /* 0x418808 too */ struct nouveau_vma unk408004_vma; struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ struct nouveau_vma unk40800c_vma; struct nouveau_gpuobj *unk418810; /* 0x419848 too */ struct nouveau_vma unk418810_vma; + struct nouveau_gpuobj *mmio; struct nouveau_vma mmio_vma; int mmio_nr; }; -int nvc0_grctx_generate(struct nouveau_channel *); - -/* nvc0_graph.c uses this also to determine supported chipsets */ static inline u32 -nvc0_graph_class(struct drm_device *dev) +nvc0_graph_class(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = priv->dev_private; switch (dev_priv->chipset) { case 0xc0: @@ -94,9 +106,52 @@ nvc0_graph_class(struct drm_device *dev) case 0xc8: case 0xd9: return 0x9297; + case 0xe4: + case 0xe7: + return 0xa097; default: return 0; } } +void nv_icmd(struct drm_device *priv, u32 icmd, u32 data); + +static inline void +nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) +{ + nv_wr32(priv, 0x40448c, data); + nv_wr32(priv, 0x404488, 0x80000000 | (mthd << 14) | class); +} + +struct nvc0_grctx { + struct nvc0_graph_priv *priv; + struct nvc0_graph_data *data; + struct nvc0_graph_mmio *mmio; + struct nouveau_gpuobj *chan; + int buffer_nr; + u64 buffer[4]; + u64 addr; +}; + +int nvc0_grctx_generate(struct nouveau_channel *); +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 nouveau_channel *); + +#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)) + +int nvc0_graph_ctor_fw(struct nvc0_graph_priv *, const char *, + struct nvc0_graph_fuc *); +void nvc0_graph_dtor(struct nouveau_object *); +void nvc0_graph_init_fw(struct nvc0_graph_priv *, u32 base, + struct nvc0_graph_fuc *, struct nvc0_graph_fuc *); +int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +void nvc0_graph_context_dtor(struct nouveau_object *); + #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 47bda63..2bd55d8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -31,7 +31,7 @@ #include #include -#include "nve0.h" +#include "nvc0.h" static void nve0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) @@ -88,8 +88,8 @@ nve0_graph_unload_context_to(struct drm_device *dev, u64 chan) static int nve0_graph_construct_context(struct nouveau_channel *chan) { - struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int ret, i; u32 *ctx; @@ -128,8 +128,8 @@ err: static int nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) { - struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; u32 magic[GPC_MAX][2]; u16 offset = 0x0000; @@ -220,8 +220,8 @@ static int nve0_graph_context_new(struct nouveau_channel *chan, int engine) { struct drm_device *dev = chan->dev; - struct nve0_graph_priv *priv = nv_engine(dev, engine); - struct nve0_graph_chan *grch; + struct nvc0_graph_priv *priv = nv_engine(dev, engine); + struct nvc0_graph_chan *grch; struct nouveau_gpuobj *grctx; int ret, i; @@ -279,7 +279,7 @@ error: static void nve0_graph_context_del(struct nouveau_channel *chan, int engine) { - struct nve0_graph_chan *grch = chan->engctx[engine]; + struct nvc0_graph_chan *grch = chan->engctx[engine]; nouveau_gpuobj_unmap(&grch->mmio_vma); nouveau_gpuobj_unmap(&grch->unk418810_vma); @@ -310,7 +310,7 @@ nve0_graph_fini(struct drm_device *dev, int engine, bool suspend) static void nve0_graph_init_obj418880(struct drm_device *dev) { - struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); @@ -362,7 +362,7 @@ nve0_graph_init_units(struct drm_device *dev) static void nve0_graph_init_gpc_0(struct drm_device *dev) { - struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + 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]; @@ -400,7 +400,7 @@ nve0_graph_init_gpc_0(struct drm_device *dev) static void nve0_graph_init_gpc_1(struct drm_device *dev) { - struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc, tpc; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { @@ -426,7 +426,7 @@ nve0_graph_init_gpc_1(struct drm_device *dev) static void nve0_graph_init_rop(struct drm_device *dev) { - struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { @@ -439,7 +439,7 @@ nve0_graph_init_rop(struct drm_device *dev) static void nve0_graph_init_fuc(struct drm_device *dev, u32 fuc_base, - struct nve0_graph_fuc *code, struct nve0_graph_fuc *data) + struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data) { int i; @@ -458,7 +458,7 @@ nve0_graph_init_fuc(struct drm_device *dev, u32 fuc_base, static int nve0_graph_init_ctxctl(struct drm_device *dev) { - struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; /* load fuc microcode */ @@ -613,7 +613,7 @@ nve0_graph_ctxctl_isr(struct drm_device *dev) static void nve0_graph_trap_isr(struct drm_device *dev, int chid) { - struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 trap = nv_rd32(dev, 0x400108); int rop; @@ -716,7 +716,7 @@ nve0_graph_isr(struct drm_device *dev) static int nve0_graph_create_fw(struct drm_device *dev, const char *fwname, - struct nve0_graph_fuc *fuc) + struct nvc0_graph_fuc *fuc) { struct drm_nouveau_private *dev_priv = dev->dev_private; const struct firmware *fw; @@ -735,7 +735,7 @@ nve0_graph_create_fw(struct drm_device *dev, const char *fwname, } static void -nve0_graph_destroy_fw(struct nve0_graph_fuc *fuc) +nve0_graph_destroy_fw(struct nvc0_graph_fuc *fuc) { if (fuc->data) { kfree(fuc->data); @@ -746,7 +746,7 @@ nve0_graph_destroy_fw(struct nve0_graph_fuc *fuc) static void nve0_graph_destroy(struct drm_device *dev, int engine) { - struct nve0_graph_priv *priv = nv_engine(dev, engine); + struct nvc0_graph_priv *priv = nv_engine(dev, engine); nve0_graph_destroy_fw(&priv->fuc409c); nve0_graph_destroy_fw(&priv->fuc409d); @@ -769,11 +769,11 @@ int nve0_graph_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nve0_graph_priv *priv; + struct nvc0_graph_priv *priv; int ret, gpc, i; u32 kepler; - kepler = nve0_graph_class(dev); + kepler = nvc0_graph_class(dev); if (!kepler) { NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); return 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h deleted file mode 100644 index b136cd5..0000000 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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: - * - * 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 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 - */ - -#ifndef __NVE0_GRAPH_H__ -#define __NVE0_GRAPH_H__ - -#define GPC_MAX 4 -#define TPC_MAX 32 - -#define ROP_BCAST(r) (0x408800 + (r)) -#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) -#define GPC_BCAST(r) (0x418000 + (r)) -#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) -#define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) - -struct nve0_graph_fuc { - u32 *data; - u32 size; -}; - -struct nve0_graph_priv { - struct nouveau_exec_engine base; - - struct nve0_graph_fuc fuc409c; - struct nve0_graph_fuc fuc409d; - struct nve0_graph_fuc fuc41ac; - struct nve0_graph_fuc fuc41ad; - - u8 gpc_nr; - u8 rop_nr; - u8 tpc_nr[GPC_MAX]; - u8 tpc_total; - - u32 grctx_size; - u32 *grctx_vals; - struct nouveau_gpuobj *unk4188b4; - struct nouveau_gpuobj *unk4188b8; - - u8 magic_not_rop_nr; -}; - -struct nve0_graph_chan { - struct nouveau_gpuobj *grctx; - struct nouveau_vma grctx_vma; - struct nouveau_gpuobj *unk408004; /* 0x418810 too */ - struct nouveau_vma unk408004_vma; - struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ - struct nouveau_vma unk40800c_vma; - struct nouveau_gpuobj *unk418810; /* 0x419848 too */ - struct nouveau_vma unk418810_vma; - struct nouveau_gpuobj *mmio; - struct nouveau_vma mmio_vma; - int mmio_nr; -}; - -int nve0_grctx_generate(struct nouveau_channel *); - -/* nve0_graph.c uses this also to determine supported chipsets */ -static inline u32 -nve0_graph_class(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - switch (dev_priv->chipset) { - case 0xe4: - case 0xe7: - return 0xa097; - default: - return 0; - } -} - -#endif -- cgit v1.1 From ac1499d9573f4aadd1d2beac11fe23af8ce90c24 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 4 Aug 2012 18:40:45 +1000 Subject: drm/nvc0-/gr: generate grctx template at init time, not first context ctor Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 269 ++++++++++-- .../gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 50 ++- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 450 +++++++-------------- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 30 +- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 265 +----------- 5 files changed, 460 insertions(+), 604 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index 5735301..b19a406 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -35,6 +35,156 @@ nv_icmd(struct drm_device *priv, u32 icmd, u32 data) while (nv_rd32(priv, 0x400700) & 2) {} } +int +nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, + struct nvc0_grctx *info) +{ + struct nouveau_gpuobj *chan; + u32 size = (0x80000 + oprv->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, + NVOBJ_FLAG_ZERO_ALLOC, &info->chan); + chan = info->chan; + if (ret) { + NV_ERROR(priv, "failed to allocate channel memory, %d\n", ret); + return ret; + } + + /* PGD pointer */ + nv_wo32(chan, 0x0200, lower_32_bits(chan->addr + 0x1000)); + nv_wo32(chan, 0x0204, upper_32_bits(chan->addr + 0x1000)); + nv_wo32(chan, 0x0208, 0xffffffff); + nv_wo32(chan, 0x020c, 0x000000ff); + + /* PGT[0] pointer */ + nv_wo32(chan, 0x1000, 0x00000000); + nv_wo32(chan, 0x1004, 0x00000001 | (chan->addr + 0x2000) >> 8); + + /* identity-map the whole "channel" into its own vm */ + for (i = 0; i < size / 4096; i++) { + u64 addr = ((chan->addr + (i * 4096)) >> 8) | 1; + nv_wo32(chan, 0x2000 + (i * 8), lower_32_bits(addr)); + nv_wo32(chan, 0x2004 + (i * 8), upper_32_bits(addr)); + } + + /* context pointer (virt) */ + nv_wo32(chan, 0x0210, 0x00080004); + nv_wo32(chan, 0x0214, 0x00000000); + + nvimem_flush(priv); + + 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->addr = 0x2000 + (i * 8); + info->priv = oprv; + info->buffer_nr = 0; + + if (oprv->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_wo32(chan, 0x8001c, 1); + nv_wo32(chan, 0x80020, 0); + nv_wo32(chan, 0x80028, 0); + nv_wo32(chan, 0x8002c, 0); + nvimem_flush(priv); + return 0; + } + + /* HUB_FUC(SET_CHAN) */ + nv_wr32(priv, 0x409840, 0x80000000); + 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"); + nvc0_graph_ctxctl_debug(priv); + nouveau_gpuobj_ref(NULL, &info->chan); + return -EBUSY; + } + + return 0; +} + +void +nvc0_grctx_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access) +{ + info->buffer[info->buffer_nr] = info->addr; + info->buffer[info->buffer_nr] += (align - 1); + info->buffer[info->buffer_nr] &= ~(align - 1); + info->addr = info->buffer[info->buffer_nr++] + size; + + info->data->size = size; + info->data->align = align; + info->data->access = access; + info->data++; +} + +void +nvc0_grctx_mmio(struct nvc0_grctx *info, u32 addr, u32 data, u32 shift, u32 buf) +{ + info->mmio->addr = addr; + info->mmio->data = data; + info->mmio->shift = shift; + info->mmio->buffer = buf; + info->mmio++; + + if (shift) + data |= info->buffer[buf] >> shift; + nv_wr32(info->dev, addr, data); +} + +int +nvc0_grctx_fini(struct nvc0_grctx *info) +{ + struct nvc0_graph_priv *priv = info->priv; + 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"); + return -EBUSY; + } + + goto save; + } + + /* 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); + return -EBUSY; + } + +save: + priv->data = kmalloc(priv->size, GFP_KERNEL); + if (priv->data) { + for (i = 0; i < priv->size; i += 4) + priv->data[i / 4] = nv_ro32(info->chan, 0x80000 + i); + } + + nouveau_gpuobj_ref(NULL, &info->chan); + return priv->data ? 0 : -ENOMEM; +} + static void nvc0_grctx_generate_9097(struct drm_device *priv) { @@ -1779,16 +1929,19 @@ nvc0_grctx_generate_tp(struct drm_device *priv) } int -nvc0_grctx_generate(struct nouveau_channel *chan) +nvc0_grctx_generate(struct drm_device *priv) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nvc0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *priv = chan->dev; - int i, gpc, tp, id; + 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); + if (ret) + return ret; + r000260 = nv_rd32(priv, 0x000260); nv_wr32(priv, 0x000260, r000260 & ~1); nv_wr32(priv, 0x400208, 0x00000000); @@ -1808,19 +1961,55 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_wr32(priv, 0x404154, 0x00000000); - /* fuc "mmio list" writes */ - for (i = 0; i < grch->mmio_nr * 8; i += 8) { - u32 reg = nv_ro32(grch->mmio, i + 0); - nv_wr32(priv, reg, nv_ro32(grch->mmio, i + 4)); + /* generate per-context mmio list data */ + mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); + mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); + mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); + mmio_list(0x408004, 0x00000000, 8, 0); + mmio_list(0x408008, 0x80000018, 0, 0); + mmio_list(0x40800c, 0x00000000, 8, 1); + mmio_list(0x408010, 0x80000000, 0, 0); + mmio_list(0x418810, 0x80000000, 12, 2); + mmio_list(0x419848, 0x10000000, 12, 2); + mmio_list(0x419004, 0x00000000, 8, 1); + mmio_list(0x419008, 0x00000000, 0, 0); + mmio_list(0x418808, 0x00000000, 8, 0); + mmio_list(0x41880c, 0x80000018, 0, 0); + if (dev_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++) { + u32 reg = TPC_UNIT(gpc, tpc, 0x0520); + mmio_list(reg, tmp, 0, 0); + tmp += 0x0324; + } + } + } else { + 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++) { + 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++) { + u32 reg = TPC_UNIT(gpc, tpc, 0x0544); + mmio_list(reg, tmp, 0, 0); + tmp += 0x0324; + } + } } - for (tp = 0, id = 0; tp < 4; tp++) { + for (tpc = 0, id = 0; tpc < 4; tpc++) { for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { - if (tp < oprv->tpc_nr[gpc]) { - nv_wr32(priv, TPC_UNIT(gpc, tp, 0x698), id); - nv_wr32(priv, TPC_UNIT(gpc, tp, 0x4e8), id); - nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); - nv_wr32(priv, TPC_UNIT(gpc, tp, 0x088), id); + if (tpc < oprv->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); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); id++; } @@ -1843,18 +2032,18 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_wr32(priv, 0x40587c, 0x00000000); if (1) { - u8 tpnr[GPC_MAX], data[TPC_MAX]; + u8 tpcnr[GPC_MAX], data[TPC_MAX]; - memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); memset(data, 0x1f, sizeof(data)); gpc = -1; - for (tp = 0; tp < oprv->tpc_total; tp++) { + for (tpc = 0; tpc < oprv->tpc_total; tpc++) { do { gpc = (gpc + 1) % oprv->gpc_nr; - } while (!tpnr[gpc]); - tpnr[gpc]--; - data[tp] = gpc; + } while (!tpcnr[gpc]); + tpcnr[gpc]--; + data[tpc] = gpc; } for (i = 0; i < 4; i++) @@ -1863,24 +2052,24 @@ nvc0_grctx_generate(struct nouveau_channel *chan) if (1) { u32 data[6] = {}, data2[2] = {}; - u8 tpnr[GPC_MAX]; + u8 tpcnr[GPC_MAX]; u8 shift, ntpcv; /* calculate first set of magics */ - memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); gpc = -1; - for (tp = 0; tp < oprv->tpc_total; tp++) { + for (tpc = 0; tpc < oprv->tpc_total; tpc++) { do { gpc = (gpc + 1) % oprv->gpc_nr; - } while (!tpnr[gpc]); - tpnr[gpc]--; + } while (!tpcnr[gpc]); + tpcnr[gpc]--; - data[tp / 6] |= gpc << ((tp % 6) * 5); + data[tpc / 6] |= gpc << ((tpc % 6) * 5); } - for (; tp < 32; tp++) - data[tp / 6] |= 7 << ((tp % 6) * 5); + for (; tpc < 32; tpc++) + data[tpc / 6] |= 7 << ((tpc % 6) * 5); /* and the second... */ shift = 0; @@ -1918,12 +2107,12 @@ nvc0_grctx_generate(struct nouveau_channel *chan) } if (1) { - u32 tp_mask = 0, tp_set = 0; - u8 tpnr[GPC_MAX], a, b; + u32 tpc_mask = 0, tpc_set = 0; + u8 tpcnr[GPC_MAX], a, b; - memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); for (gpc = 0; gpc < oprv->gpc_nr; gpc++) - tp_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); + tpc_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); for (i = 0, gpc = -1, b = -1; i < 32; i++) { a = (i * (oprv->tpc_total - 1)) / 32; @@ -1931,14 +2120,14 @@ nvc0_grctx_generate(struct nouveau_channel *chan) b = a; do { gpc = (gpc + 1) % oprv->gpc_nr; - } while (!tpnr[gpc]); - tp = oprv->tpc_nr[gpc] - tpnr[gpc]--; + } while (!tpcnr[gpc]); + tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; - tp_set |= 1 << ((gpc * 8) + tp); + tpc_set |= 1 << ((gpc * 8) + tpc); } - nv_wr32(priv, 0x406800 + (i * 0x20), tp_set); - nv_wr32(priv, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); + nv_wr32(priv, 0x406800 + (i * 0x20), tpc_set); + nv_wr32(priv, 0x406c00 + (i * 0x20), tpc_set ^ tpc_mask); } } @@ -2867,5 +3056,5 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nvc0_grctx_generate_90c0(priv); nv_wr32(priv, 0x000260, r000260); - return 0; + 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 47bea8a..e550317 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -2604,16 +2604,20 @@ nve0_graph_generate_tpcunk(struct drm_device *priv) } int -nve0_grctx_generate(struct nouveau_channel *chan) +nve0_grctx_generate(struct drm_device *priv) { - struct nvc0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *priv = chan->dev; + 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; u32 tpc_set = 0, tpc_mask = 0; + u32 magic[GPC_MAX][2], offset; u8 tpcnr[GPC_MAX], a, b; u8 shift, ntpcv; - int i, gpc, tpc, id; + + ret = nvc0_grctx_init(priv, oprv, &info); + if (ret) + return ret; nv_mask(priv, 0x000260, 0x00000001, 0x00000000); nv_wr32(priv, 0x400204, 0x00000000); @@ -2636,11 +2640,37 @@ nve0_grctx_generate(struct nouveau_channel *chan) nv_wr32(priv, 0x404154, 0x0); - for (i = 0; i < grch->mmio_nr * 8; i += 8) { - u32 reg = nv_ro32(grch->mmio, i + 0); - u32 val = nv_ro32(grch->mmio, i + 4); - nv_wr32(priv, reg, val); + mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); + mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); + mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); + mmio_list(0x40800c, 0x00000000, 8, 1); + mmio_list(0x408010, 0x80000000, 0, 0); + mmio_list(0x419004, 0x00000000, 8, 1); + mmio_list(0x419008, 0x00000000, 0, 0); + mmio_list(0x4064cc, 0x80000000, 0, 0); + mmio_list(0x408004, 0x00000000, 8, 0); + mmio_list(0x408008, 0x80000030, 0, 0); + mmio_list(0x418808, 0x00000000, 8, 0); + mmio_list(0x41880c, 0x80000030, 0, 0); + mmio_list(0x4064c8, 0x01800600, 0, 0); + mmio_list(0x418810, 0x80000000, 12, 2); + 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]; + magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset; + magic[gpc][1] = 0x00000000 | (magic1 << 16); + offset += 0x0324 * oprv->tpc_nr[gpc]; + } + for (gpc = 0; gpc < oprv->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]; } + mmio_list(0x17e91c, 0x06060609, 0, 0); + mmio_list(0x17e920, 0x00090a05, 0, 0); nv_wr32(priv, 0x418c6c, 0x1); nv_wr32(priv, 0x41980c, 0x10); @@ -2758,5 +2788,5 @@ nve0_grctx_generate(struct nouveau_channel *chan) nv_mask(priv, 0x000260, 0x00000001, 0x00000001); nv_wr32(priv, 0x418800, 0x7026860a); //XXX nv_wr32(priv, 0x41be10, 0x00bb8bc7); //XXX - return 0; + return nvc0_grctx_fini(&info); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 158d576..f994d2f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -48,7 +48,7 @@ nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); } -static void +void nvc0_graph_ctxctl_debug(struct drm_device *dev) { u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; @@ -59,259 +59,92 @@ nvc0_graph_ctxctl_debug(struct drm_device *dev) nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); } -static int -nvc0_graph_load_context(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - - nv_wr32(dev, 0x409840, 0x00000030); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); - nv_wr32(dev, 0x409504, 0x00000003); - if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) - NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); - - return 0; -} - -static int -nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) -{ - nv_wr32(dev, 0x409840, 0x00000003); - nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); - nv_wr32(dev, 0x409504, 0x00000009); - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); - return -EBUSY; - } - - return 0; -} - -static int -nvc0_graph_construct_context(struct nouveau_channel *chan) +int +nvc0_graph_context_new(struct nouveau_channel *chan, int engine) { - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; + struct nvc0_graph_priv *priv = nv_engine(dev, 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; int ret, i; - u32 *ctx; - ctx = kmalloc(priv->grctx_size, GFP_KERNEL); - if (!ctx) + grch = kzalloc(sizeof(*grch), GFP_KERNEL); + if (!grch) return -ENOMEM; + chan->engctx[NVOBJ_ENGINE_GR] = grch; - if (!nouveau_ctxfw) { - nv_wr32(dev, 0x409840, 0x80000000); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); - nv_wr32(dev, 0x409504, 0x00000001); - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); - nvc0_graph_ctxctl_debug(dev); - ret = -EBUSY; - goto err; - } - } else { - nvc0_graph_load_context(chan); - - nv_wo32(grch->grctx, 0x1c, 1); - nv_wo32(grch->grctx, 0x20, 0); - nv_wo32(grch->grctx, 0x28, 0); - nv_wo32(grch->grctx, 0x2c, 0); - nvimem_flush(dev); - } - - ret = nvc0_grctx_generate(chan); + ret = nouveau_gpuobj_new(dev, NULL, priv->size, 256, 0, &grch->grctx); if (ret) - goto err; - - if (!nouveau_ctxfw) { - nv_wr32(dev, 0x409840, 0x80000000); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); - nv_wr32(dev, 0x409504, 0x00000002); - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { - NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); - nvc0_graph_ctxctl_debug(dev); - ret = -EBUSY; - goto err; - } - } else { - ret = nvc0_graph_unload_context_to(dev, chan->ramin->addr); - if (ret) - goto err; - } - - for (i = 0; i < priv->grctx_size; i += 4) - ctx[i / 4] = nv_ro32(grch->grctx, i); - - priv->grctx_vals = ctx; - return 0; - -err: - kfree(ctx); - return ret; -} - -static int -nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) -{ - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i = 0, gpc, tp, ret; + goto error; - ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, 0, &grch->unk408004); + ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | + NV_MEM_ACCESS_SYS, &grch->grctx_vma); if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->unk408004_vma); - if (ret) - return ret; + grctx = grch->grctx; - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c); + /* 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); if (ret) return ret; - ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, + ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->unk40800c_vma); + &grch->mmio_vma); if (ret) return ret; - ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0, - &grch->unk418810); - if (ret) - return ret; - - ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, - NV_MEM_ACCESS_RW, &grch->unk418810_vma); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio); - 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); + if (ret) + return ret; - ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, &grch->mmio_vma); - if (ret) - return ret; + ret = nouveau_gpuobj_map_vm(grch->data[i].mem, chan->vm, + data->access, + &grch->data[i].vma); + if (ret) + return ret; - nv_wo32(grch->mmio, i++ * 4, 0x00408004); - nv_wo32(grch->mmio, i++ * 4, grch->unk408004_vma.offset >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x00408008); - nv_wo32(grch->mmio, i++ * 4, 0x80000018); - - nv_wo32(grch->mmio, i++ * 4, 0x0040800c); - nv_wo32(grch->mmio, i++ * 4, grch->unk40800c_vma.offset >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x00408010); - nv_wo32(grch->mmio, i++ * 4, 0x80000000); - - nv_wo32(grch->mmio, i++ * 4, 0x00418810); - nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810_vma.offset >> 12); - nv_wo32(grch->mmio, i++ * 4, 0x00419848); - nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810_vma.offset >> 12); - - nv_wo32(grch->mmio, i++ * 4, 0x00419004); - nv_wo32(grch->mmio, i++ * 4, grch->unk40800c_vma.offset >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x00419008); - nv_wo32(grch->mmio, i++ * 4, 0x00000000); - - nv_wo32(grch->mmio, i++ * 4, 0x00418808); - nv_wo32(grch->mmio, i++ * 4, grch->unk408004_vma.offset >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x0041880c); - nv_wo32(grch->mmio, i++ * 4, 0x80000018); - - if (dev_priv->chipset != 0xc1) { - u32 magic = 0x02180000; - nv_wo32(grch->mmio, i++ * 4, 0x00405830); - nv_wo32(grch->mmio, i++ * 4, magic); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { - u32 reg = TPC_UNIT(gpc, tp, 0x520); - nv_wo32(grch->mmio, i++ * 4, reg); - nv_wo32(grch->mmio, i++ * 4, magic); - magic += 0x0324; - } - } - } else { - u32 magic = 0x02180000; - nv_wo32(grch->mmio, i++ * 4, 0x00405830); - nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218); - nv_wo32(grch->mmio, i++ * 4, 0x004064c4); - nv_wo32(grch->mmio, i++ * 4, 0x0086ffff); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { - u32 reg = TPC_UNIT(gpc, tp, 0x520); - nv_wo32(grch->mmio, i++ * 4, reg); - nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic); - magic += 0x0324; - } - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { - u32 reg = TPC_UNIT(gpc, tp, 0x544); - nv_wo32(grch->mmio, i++ * 4, reg); - nv_wo32(grch->mmio, i++ * 4, magic); - magic += 0x0324; - } - } + data++; } - grch->mmio_nr = i / 2; - return 0; -} - -static int -nvc0_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - struct nvc0_graph_chan *grch; - struct nouveau_gpuobj *grctx; - int ret, i; - - grch = kzalloc(sizeof(*grch), GFP_KERNEL); - if (!grch) - return -ENOMEM; - chan->engctx[NVOBJ_ENGINE_GR] = grch; + /* finally, fill in the mmio list and point the context at it */ + for (i = 0; mmio->addr && i < ARRAY_SIZE(priv->mmio_list); i++) { + u32 addr = mmio->addr; + u32 data = mmio->data; - ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 0, - &grch->grctx); - if (ret) - goto error; + if (mmio->shift) { + u64 info = grch->data[mmio->buffer].vma.offset; + data |= info >> mmio->shift; + } - ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, &grch->grctx_vma); - if (ret) - return ret; + nv_wo32(grch->mmio, grch->mmio_nr++ * 4, addr); + nv_wo32(grch->mmio, grch->mmio_nr++ * 4, data); + mmio++; + } - grctx = grch->grctx; - - ret = nvc0_graph_create_context_mmio_list(chan); - if (ret) - goto error; + 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); - if (!priv->grctx_vals) { - ret = nvc0_graph_construct_context(chan); - if (ret) - goto error; - } - - for (i = 0; i < priv->grctx_size; i += 4) - nv_wo32(grctx, i, priv->grctx_vals[i / 4]); - - if (!nouveau_ctxfw) { - nv_wo32(grctx, 0x00, grch->mmio_nr); + if (!priv->firmware) { + nv_wo32(grctx, 0x00, grch->mmio_nr / 2); nv_wo32(grctx, 0x04, grch->mmio_vma.offset >> 8); } else { nv_wo32(grctx, 0xf4, 0); nv_wo32(grctx, 0xf8, 0); - nv_wo32(grctx, 0x10, grch->mmio_nr); + 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); @@ -327,20 +160,21 @@ error: return ret; } -static void +void nvc0_graph_context_del(struct nouveau_channel *chan, int engine) { struct nvc0_graph_chan *grch = chan->engctx[engine]; + 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); + } nouveau_gpuobj_unmap(&grch->mmio_vma); - nouveau_gpuobj_unmap(&grch->unk418810_vma); - nouveau_gpuobj_unmap(&grch->unk40800c_vma); - nouveau_gpuobj_unmap(&grch->unk408004_vma); - nouveau_gpuobj_unmap(&grch->grctx_vma); nouveau_gpuobj_ref(NULL, &grch->mmio); - nouveau_gpuobj_ref(NULL, &grch->unk418810); - nouveau_gpuobj_ref(NULL, &grch->unk40800c); - nouveau_gpuobj_ref(NULL, &grch->unk408004); + + nouveau_gpuobj_unmap(&grch->grctx_vma); nouveau_gpuobj_ref(NULL, &grch->grctx); chan->engctx[engine] = NULL; } @@ -517,89 +351,102 @@ nvc0_graph_init_ctxctl(struct drm_device *dev) u32 r000260; int i; - if (!nouveau_ctxfw) { - /* load HUB microcode */ + if (priv->firmware) { + /* load fuc microcode */ r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nv_wr32(dev, 0x4091c0, 0x01000000); - for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) - nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); - - nv_wr32(dev, 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]); - } - - /* load GPC microcode */ - nv_wr32(dev, 0x41a1c0, 0x01000000); - for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) - nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); - - nv_wr32(dev, 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]); - } + nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, + &priv->fuc409d); + nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, + &priv->fuc41ad); nv_wr32(dev, 0x000260, r000260); - /* start HUB ucode running, it'll init the GPCs */ - nv_wr32(dev, 0x409800, dev_priv->chipset); + /* 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, 0x80000000, 0x80000000)) { - NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); - nvc0_graph_ctxctl_debug(dev); + 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"); return -EBUSY; } + priv->size = nv_rd32(dev, 0x409800); - priv->grctx_size = nv_rd32(dev, 0x409804); - return 0; + 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"); + 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"); + return -EBUSY; + } + + goto done; } - /* load fuc microcode */ + /* load HUB microcode */ r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); - nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d); - nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); + nv_wr32(dev, 0x4091c0, 0x01000000); + for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) + nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); + + nv_wr32(dev, 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]); + } + + /* load GPC microcode */ + nv_wr32(dev, 0x41a1c0, 0x01000000); + for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) + nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); + + nv_wr32(dev, 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(dev, 0x000260, r000260); - /* start both of them running */ - nv_wr32(dev, 0x409840, 0xffffffff); - nv_wr32(dev, 0x41a10c, 0x00000000); + /* start HUB ucode running, it'll init the GPCs */ + nv_wr32(dev, 0x409800, dev_priv->chipset); 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"); + if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { + NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); + nvc0_graph_ctxctl_debug(dev); return -EBUSY; } - priv->grctx_size = nv_rd32(dev, 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"); - return -EBUSY; - } + priv->size = nv_rd32(dev, 0x409804); +done: + if (priv->data == NULL) { + int ret = nvc0_grctx_generate(dev); + if (ret) { + NV_ERROR(dev, "PGRAPH: failed to construct context\n"); + return ret; + } - 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"); - return -EBUSY; + return 1; } return 0; @@ -610,6 +457,7 @@ nvc0_graph_init(struct drm_device *dev, int engine) { int ret; +reset: nv_mask(dev, 0x000200, 0x18001000, 0x00000000); nv_mask(dev, 0x000200, 0x18001000, 0x18001000); @@ -636,8 +484,11 @@ nvc0_graph_init(struct drm_device *dev, int engine) nv_wr32(dev, 0x400054, 0x34ce3464); ret = nvc0_graph_init_ctxctl(dev); - if (ret) + if (ret) { + if (ret == 1) + goto reset; return ret; + } return 0; } @@ -784,20 +635,18 @@ nvc0_graph_destroy(struct drm_device *dev, int engine) { struct nvc0_graph_priv *priv = nv_engine(dev, engine); - if (nouveau_ctxfw) { - nvc0_graph_destroy_fw(&priv->fuc409c); - nvc0_graph_destroy_fw(&priv->fuc409d); - nvc0_graph_destroy_fw(&priv->fuc41ac); - nvc0_graph_destroy_fw(&priv->fuc41ad); - } + 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->grctx_vals) - kfree(priv->grctx_vals); + if (priv->data) + kfree(priv->data); NVOBJ_ENGINE_DEL(dev, GR); kfree(priv); @@ -840,6 +689,7 @@ nvc0_graph_create(struct drm_device *dev) ret = 0; goto error; } + priv->firmware = true; } ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index ba9b80f..30ea3ab 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -66,27 +66,28 @@ struct nvc0_graph_priv { u8 tpc_nr[GPC_MAX]; u8 tpc_total; - u32 grctx_size; - u32 *grctx_vals; struct nouveau_gpuobj *unk4188b4; struct nouveau_gpuobj *unk4188b8; + struct nvc0_graph_data mmio_data[4]; + struct nvc0_graph_mmio mmio_list[4096/8]; + u32 size; + u32 *data; + u8 magic_not_rop_nr; }; struct nvc0_graph_chan { struct nouveau_gpuobj *grctx; struct nouveau_vma grctx_vma; - struct nouveau_gpuobj *unk408004; /* 0x418808 too */ - struct nouveau_vma unk408004_vma; - struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ - struct nouveau_vma unk40800c_vma; - struct nouveau_gpuobj *unk418810; /* 0x419848 too */ - struct nouveau_vma unk418810_vma; struct nouveau_gpuobj *mmio; struct nouveau_vma mmio_vma; int mmio_nr; + struct { + struct nouveau_gpuobj *mem; + struct nouveau_vma vma; + } data[4]; }; static inline u32 @@ -124,6 +125,7 @@ nv_mthd(struct drm_device *priv, u32 class, u32 mthd, u32 data) } struct nvc0_grctx { + struct drm_device *dev; struct nvc0_graph_priv *priv; struct nvc0_graph_data *data; struct nvc0_graph_mmio *mmio; @@ -133,13 +135,14 @@ struct nvc0_grctx { u64 addr; }; -int nvc0_grctx_generate(struct nouveau_channel *); -int nvc0_grctx_init(struct nvc0_graph_priv *, struct nvc0_grctx *); +int nvc0_grctx_generate(struct drm_device *); +int nvc0_grctx_init(struct drm_device *, 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 nouveau_channel *); +int nve0_grctx_generate(struct drm_device *); #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)) @@ -154,4 +157,9 @@ 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 2bd55d8..a3a4ee7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -58,243 +58,6 @@ nve0_graph_ctxctl_debug(struct drm_device *dev) } static int -nve0_graph_load_context(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - - nv_wr32(dev, 0x409840, 0x00000030); - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); - nv_wr32(dev, 0x409504, 0x00000003); - if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) - NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); - - return 0; -} - -static int -nve0_graph_unload_context_to(struct drm_device *dev, u64 chan) -{ - nv_wr32(dev, 0x409840, 0x00000003); - nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); - nv_wr32(dev, 0x409504, 0x00000009); - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); - return -EBUSY; - } - - return 0; -} - -static int -nve0_graph_construct_context(struct nouveau_channel *chan) -{ - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - int ret, i; - u32 *ctx; - - ctx = kmalloc(priv->grctx_size, GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - nve0_graph_load_context(chan); - - nv_wo32(grch->grctx, 0x1c, 1); - nv_wo32(grch->grctx, 0x20, 0); - nv_wo32(grch->grctx, 0x28, 0); - nv_wo32(grch->grctx, 0x2c, 0); - nvimem_flush(dev); - - ret = nve0_grctx_generate(chan); - if (ret) - goto err; - - ret = nve0_graph_unload_context_to(dev, chan->ramin->addr); - if (ret) - goto err; - - for (i = 0; i < priv->grctx_size; i += 4) - ctx[i / 4] = nv_ro32(grch->grctx, i); - - priv->grctx_vals = ctx; - return 0; - -err: - kfree(ctx); - return ret; -} - -static int -nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) -{ - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - u32 magic[GPC_MAX][2]; - u16 offset = 0x0000; - int gpc; - int ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x3000, 256, 0, &grch->unk408004); - if (ret) - return ret; - - ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->unk408004_vma); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c); - if (ret) - return ret; - - ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->unk40800c_vma); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0, - &grch->unk418810); - if (ret) - return ret; - - ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, - NV_MEM_ACCESS_RW, &grch->unk418810_vma); - if (ret) - return ret; - - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio); - if (ret) - return ret; - - ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, - &grch->mmio_vma); - if (ret) - return ret; - -#define mmio(r,v) do { \ - nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 0, (r)); \ - nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 4, (v)); \ - grch->mmio_nr++; \ -} while (0) - mmio(0x40800c, grch->unk40800c_vma.offset >> 8); - mmio(0x408010, 0x80000000); - mmio(0x419004, grch->unk40800c_vma.offset >> 8); - mmio(0x419008, 0x00000000); - mmio(0x4064cc, 0x80000000); - mmio(0x408004, grch->unk408004_vma.offset >> 8); - mmio(0x408008, 0x80000030); - mmio(0x418808, grch->unk408004_vma.offset >> 8); - mmio(0x41880c, 0x80000030); - mmio(0x4064c8, 0x01800600); - mmio(0x418810, 0x80000000 | grch->unk418810_vma.offset >> 12); - mmio(0x419848, 0x10000000 | grch->unk418810_vma.offset >> 12); - mmio(0x405830, 0x02180648); - mmio(0x4064c4, 0x0192ffff); - - for (gpc = 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 * priv->tpc_nr[gpc]; - } - - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - mmio(GPC_UNIT(gpc, 0x30c0), magic[gpc][0]); - mmio(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset); - offset += 0x07ff * priv->tpc_nr[gpc]; - } - - mmio(0x17e91c, 0x06060609); - mmio(0x17e920, 0x00090a05); -#undef mmio - return 0; -} - -static int -nve0_graph_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - struct nvc0_graph_chan *grch; - struct nouveau_gpuobj *grctx; - 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->grctx_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); - if (ret) - return ret; - - grctx = grch->grctx; - - ret = nve0_graph_create_context_mmio_list(chan); - if (ret) - goto error; - - 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); - - if (!priv->grctx_vals) { - ret = nve0_graph_construct_context(chan); - if (ret) - goto error; - } - - for (i = 0; i < priv->grctx_size; i += 4) - nv_wo32(grctx, i, priv->grctx_vals[i / 4]); - nv_wo32(grctx, 0xf4, 0); - nv_wo32(grctx, 0xf8, 0); - nv_wo32(grctx, 0x10, grch->mmio_nr); - 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); - - nvimem_flush(dev); - return 0; - -error: - priv->base.context_del(chan, engine); - return ret; -} - -static void -nve0_graph_context_del(struct nouveau_channel *chan, int engine) -{ - struct nvc0_graph_chan *grch = chan->engctx[engine]; - - nouveau_gpuobj_unmap(&grch->mmio_vma); - nouveau_gpuobj_unmap(&grch->unk418810_vma); - nouveau_gpuobj_unmap(&grch->unk40800c_vma); - nouveau_gpuobj_unmap(&grch->unk408004_vma); - nouveau_gpuobj_unmap(&grch->grctx_vma); - nouveau_gpuobj_ref(NULL, &grch->mmio); - nouveau_gpuobj_ref(NULL, &grch->unk418810); - nouveau_gpuobj_ref(NULL, &grch->unk40800c); - nouveau_gpuobj_ref(NULL, &grch->unk408004); - nouveau_gpuobj_ref(NULL, &grch->grctx); - chan->engctx[engine] = NULL; -} - -static int nve0_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { @@ -487,7 +250,7 @@ nve0_graph_init_ctxctl(struct drm_device *dev) NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); return -EBUSY; } - priv->grctx_size = nv_rd32(dev, 0x409800); + priv->size = nv_rd32(dev, 0x409800); nv_wr32(dev, 0x409840, 0xffffffff); nv_wr32(dev, 0x409500, 0x00000000); @@ -534,6 +297,17 @@ nve0_graph_init_ctxctl(struct drm_device *dev) nv_wr32(dev, 0x409614, 0x00000070); nv_wr32(dev, 0x409614, 0x00000770); nv_wr32(dev, 0x40802c, 0x00000001); + + if (priv->data == NULL) { + int ret = nve0_grctx_generate(dev); + if (ret) { + NV_ERROR(dev, "PGRAPH: failed to construct context\n"); + return ret; + } + + return 1; + } + return 0; } @@ -542,6 +316,7 @@ nve0_graph_init(struct drm_device *dev, int engine) { int ret; +reset: nv_mask(dev, 0x000200, 0x18001000, 0x00000000); nv_mask(dev, 0x000200, 0x18001000, 0x18001000); @@ -566,8 +341,11 @@ nve0_graph_init(struct drm_device *dev, int engine) nv_wr32(dev, 0x400054, 0x34ce3464); ret = nve0_graph_init_ctxctl(dev); - if (ret) + if (ret) { + if (ret == 1) + goto reset; return ret; + } return 0; } @@ -758,8 +536,8 @@ nve0_graph_destroy(struct drm_device *dev, int engine) nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); - if (priv->grctx_vals) - kfree(priv->grctx_vals); + if (priv->data) + kfree(priv->data); NVOBJ_ENGINE_DEL(dev, GR); kfree(priv); @@ -786,8 +564,8 @@ nve0_graph_create(struct drm_device *dev) priv->base.destroy = nve0_graph_destroy; priv->base.init = nve0_graph_init; priv->base.fini = nve0_graph_fini; - priv->base.context_new = nve0_graph_context_new; - priv->base.context_del = nve0_graph_context_del; + 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); @@ -801,6 +579,7 @@ nve0_graph_create(struct drm_device *dev) ret = 0; goto error; } + priv->firmware = true; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); if (ret) -- cgit v1.1 From ebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 20 Jul 2012 08:17:34 +1000 Subject: drm/nouveau: port all engines to new engine module format This is a HUGE commit, but it's not nearly as bad as it looks - any problems can be isolated to a particular chipset and engine combination. It was simply too difficult to port each one at a time, the compat layers are *already* ridiculous. Most of the changes here are simply to the glue, the process for each of the engine modules was to start with a standard skeleton and copy+paste the old code into the appropriate places, fixing up variable names etc as needed. v2: Marcin Slusarz - fix find/replace bug in license header v3: Ben Skeggs - bump indirect pushbuf size to 8KiB, 4KiB barely enough for userspace and left no space for kernel's requirements during GEM pushbuf submission. - fix duplicate assignments noticed by clang v4: Marcin Slusarz - add sparse annotations to nv04_fifo_pause/nv04_fifo_start - use ioread32_native/iowrite32_native for fifo control registers v5: Ben Skeggs - rebase on v3.6-rc4, modified to keep copy engine fix intact - nv10/fence: unmap fence bo before destroying - fixed fermi regression when using nvidia gr fuc - fixed typo in supported dma_mask checking Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/ramht.c | 297 +---- drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c | 157 ++- drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 268 ++-- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 350 +++--- drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 252 ++-- drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 255 ++-- drivers/gpu/drm/nouveau/core/engine/disp/nv04.c | 90 ++ drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 125 ++ drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 118 ++ drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c | 87 ++ drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c | 176 +++ drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c | 168 +++ drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c | 99 ++ drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 165 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 736 ++++++----- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h | 178 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 228 ++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 279 +++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 394 ++++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 554 +++++--- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h | 36 + drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 490 +++++--- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 604 +++++---- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 594 +++++---- drivers/gpu/drm/nouveau/core/engine/graph/ctx.h | 26 +- .../gpu/drm/nouveau/core/engine/graph/ctxnv40.c | 131 +- .../gpu/drm/nouveau/core/engine/graph/ctxnv50.c | 559 ++++----- .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 202 ++- .../gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 94 +- drivers/gpu/drm/nouveau/core/engine/graph/nv04.c | 1325 ++++++++++---------- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 1053 +++++++++------- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 1072 +++++----------- drivers/gpu/drm/nouveau/core/engine/graph/nv20.h | 31 + drivers/gpu/drm/nouveau/core/engine/graph/nv25.c | 167 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c | 134 ++ drivers/gpu/drm/nouveau/core/engine/graph/nv30.c | 238 ++++ drivers/gpu/drm/nouveau/core/engine/graph/nv34.c | 168 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv35.c | 166 +++ drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 681 +++++----- drivers/gpu/drm/nouveau/core/engine/graph/nv40.h | 21 + drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 907 +++++++------- drivers/gpu/drm/nouveau/core/engine/graph/nv50.h | 7 + drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 1074 ++++++++-------- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 43 +- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 843 ++++++------- drivers/gpu/drm/nouveau/core/engine/graph/regs.h | 269 ++++ drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 448 +++---- drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c | 144 +++ drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c | 305 ++--- drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c | 104 ++ drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | 154 ++- .../gpu/drm/nouveau/core/engine/software/nv04.c | 140 +++ .../gpu/drm/nouveau/core/engine/software/nv10.c | 128 ++ .../gpu/drm/nouveau/core/engine/software/nv50.c | 198 +++ .../gpu/drm/nouveau/core/engine/software/nvc0.c | 180 +++ drivers/gpu/drm/nouveau/core/engine/vp/nv84.c | 157 ++- drivers/gpu/drm/nouveau/core/include/core/ramht.h | 56 +- drivers/gpu/drm/nouveau/core/include/engine/bsp.h | 45 + drivers/gpu/drm/nouveau/core/include/engine/copy.h | 47 + .../gpu/drm/nouveau/core/include/engine/crypt.h | 46 + drivers/gpu/drm/nouveau/core/include/engine/disp.h | 44 + .../gpu/drm/nouveau/core/include/engine/dmaobj.h | 57 + drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 123 +- .../gpu/drm/nouveau/core/include/engine/graph.h | 72 ++ drivers/gpu/drm/nouveau/core/include/engine/mpeg.h | 61 + drivers/gpu/drm/nouveau/core/include/engine/ppp.h | 45 + .../gpu/drm/nouveau/core/include/engine/software.h | 58 + drivers/gpu/drm/nouveau/core/include/engine/vp.h | 45 + .../gpu/drm/nouveau/core/include/subdev/device.h | 1 - .../gpu/drm/nouveau/core/include/subdev/instmem.h | 1 - drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 1 + drivers/gpu/drm/nouveau/core/subdev/device/base.c | 33 +- drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 16 + drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 44 + drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 26 + drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 35 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 103 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 136 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 89 ++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 16 + drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c | 5 +- drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h | 9 +- drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | 3 +- drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h | 6 + drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 7 +- drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 1 + 90 files changed, 12000 insertions(+), 7104 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/base.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv20.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv25.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv30.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv34.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv35.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv40.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/nv50.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/regs.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nv04.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nv10.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/engine/software/nvc0.c create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/bsp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/copy.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/crypt.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/disp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/graph.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/mpeg.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/ppp.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/software.h create mode 100644 drivers/gpu/drm/nouveau/core/include/engine/vp.h (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c index 5c22864..86a6404 100644 --- a/drivers/gpu/drm/nouveau/core/core/ramht.c +++ b/drivers/gpu/drm/nouveau/core/core/ramht.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"), @@ -18,289 +18,92 @@ * 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 "nouveau_drv.h" +#include #include +#include + +#include static u32 -nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle) +nouveau_ramht_hash(struct nouveau_ramht *ramht, int chid, u32 handle) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_ramht *ramht = chan->ramht; u32 hash = 0; - int i; - NV_DEBUG(dev, "ch%d handle=0x%08x\n", chan->id, handle); - - for (i = 32; i > 0; i -= ramht->bits) { + while (handle) { hash ^= (handle & ((1 << ramht->bits) - 1)); handle >>= ramht->bits; } - if (dev_priv->card_type < NV_50) - hash ^= chan->id << (ramht->bits - 4); - hash <<= 3; - - NV_DEBUG(dev, "hash=0x%08x\n", hash); + hash ^= chid << (ramht->bits - 4); + hash = hash << 3; return hash; } -static int -nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, - u32 offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 ctx = nv_ro32(ramht, offset + 4); - - if (dev_priv->card_type < NV_40) - return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); - return (ctx != 0); -} - -static int -nouveau_ramht_entry_same_channel(struct nouveau_channel *chan, - struct nouveau_gpuobj *ramht, u32 offset) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - u32 ctx = nv_ro32(ramht, offset + 4); - - if (dev_priv->card_type >= NV_50) - return true; - else if (dev_priv->card_type >= NV_40) - return chan->id == - ((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); - else - return chan->id == - ((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); -} - int -nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, - struct nouveau_gpuobj *gpuobj) +nouveau_ramht_insert(struct nouveau_ramht *ramht, int chid, + u32 handle, u32 context) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_ramht_entry *entry; - struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; - unsigned long flags; - u32 ctx, co, ho; - - if (nouveau_ramht_find(chan, handle)) - return -EEXIST; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - entry->channel = chan; - entry->gpuobj = NULL; - entry->handle = handle; - nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); - - if (dev_priv->card_type < NV_40) { - ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->addr >> 4) | - (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | - (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); - } else - if (dev_priv->card_type < NV_50) { - ctx = (gpuobj->addr >> 4) | - (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | - (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); - } else { - if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { - ctx = (gpuobj->node->offset << 10) | - (chan->id << 28) | - chan->id; /* HASH_TAG */ - } else { - ctx = (gpuobj->node->offset >> 4) | - ((gpuobj->engine << - NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); - } - } - - spin_lock_irqsave(&chan->ramht->lock, flags); - list_add(&entry->head, &chan->ramht->entries); + struct nouveau_bar *bar = nouveau_bar(ramht); + u32 co, ho; - co = ho = nouveau_ramht_hash_handle(chan, handle); + co = ho = nouveau_ramht_hash(ramht, chid, handle); do { - if (!nouveau_ramht_entry_valid(dev, ramht, co)) { - NV_DEBUG(dev, - "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", - chan->id, co, handle, ctx); + if (!nv_ro32(ramht, co + 4)) { nv_wo32(ramht, co + 0, handle); - nv_wo32(ramht, co + 4, ctx); - - spin_unlock_irqrestore(&chan->ramht->lock, flags); - nvimem_flush(dev); - return 0; + nv_wo32(ramht, co + 4, context); + if (bar) + bar->flush(bar); + return co; } - NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", - chan->id, co, nv_ro32(ramht, co)); co += 8; - if (co >= ramht->size) + if (co >= nv_gpuobj(ramht)->size) co = 0; } while (co != ho); - NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); - list_del(&entry->head); - spin_unlock_irqrestore(&chan->ramht->lock, flags); - kfree(entry); return -ENOMEM; } -static struct nouveau_ramht_entry * -nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle) -{ - struct nouveau_ramht *ramht = chan ? chan->ramht : NULL; - struct nouveau_ramht_entry *entry; - unsigned long flags; - - if (!ramht) - return NULL; - - spin_lock_irqsave(&ramht->lock, flags); - list_for_each_entry(entry, &ramht->entries, head) { - if (entry->channel == chan && - (!handle || entry->handle == handle)) { - list_del(&entry->head); - spin_unlock_irqrestore(&ramht->lock, flags); - - return entry; - } - } - spin_unlock_irqrestore(&ramht->lock, flags); - - return NULL; -} - -static void -nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; - unsigned long flags; - u32 co, ho; - - spin_lock_irqsave(&chan->ramht->lock, flags); - co = ho = nouveau_ramht_hash_handle(chan, handle); - do { - if (nouveau_ramht_entry_valid(dev, ramht, co) && - nouveau_ramht_entry_same_channel(chan, ramht, co) && - (handle == nv_ro32(ramht, co))) { - NV_DEBUG(dev, - "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", - chan->id, co, handle, nv_ro32(ramht, co + 4)); - nv_wo32(ramht, co + 0, 0x00000000); - nv_wo32(ramht, co + 4, 0x00000000); - nvimem_flush(dev); - goto out; - } - - co += 8; - if (co >= ramht->size) - co = 0; - } while (co != ho); - - NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", - chan->id, handle); -out: - spin_unlock_irqrestore(&chan->ramht->lock, flags); -} - -int -nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) +void +nouveau_ramht_remove(struct nouveau_ramht *ramht, int cookie) { - struct nouveau_ramht_entry *entry; - - entry = nouveau_ramht_remove_entry(chan, handle); - if (!entry) - return -ENOENT; - - nouveau_ramht_remove_hash(chan, entry->handle); - nouveau_gpuobj_ref(NULL, &entry->gpuobj); - kfree(entry); - return 0; + struct nouveau_bar *bar = nouveau_bar(ramht); + nv_wo32(ramht, cookie + 0, 0x00000000); + nv_wo32(ramht, cookie + 4, 0x00000000); + if (bar) + bar->flush(bar); } -struct nouveau_gpuobj * -nouveau_ramht_find(struct nouveau_channel *chan, u32 handle) -{ - struct nouveau_ramht *ramht = chan->ramht; - struct nouveau_ramht_entry *entry; - struct nouveau_gpuobj *gpuobj = NULL; - unsigned long flags; - - if (unlikely(!chan->ramht)) - return NULL; - - spin_lock_irqsave(&ramht->lock, flags); - list_for_each_entry(entry, &chan->ramht->entries, head) { - if (entry->channel == chan && entry->handle == handle) { - gpuobj = entry->gpuobj; - break; - } - } - spin_unlock_irqrestore(&ramht->lock, flags); - - return gpuobj; -} +static struct nouveau_oclass +nouveau_ramht_oclass = { + .handle = 0x0000abcd, + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = NULL, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, + }, +}; int -nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, - struct nouveau_ramht **pramht) +nouveau_ramht_new(struct nouveau_object *parent, struct nouveau_object *pargpu, + u32 size, u32 align, struct nouveau_ramht **pramht) { struct nouveau_ramht *ramht; + int ret; - ramht = kzalloc(sizeof(*ramht), GFP_KERNEL); - if (!ramht) - return -ENOMEM; - - ramht->dev = dev; - kref_init(&ramht->refcount); - ramht->bits = drm_order(gpuobj->size / 8); - INIT_LIST_HEAD(&ramht->entries); - spin_lock_init(&ramht->lock); - nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj); - + ret = nouveau_gpuobj_create(parent, parent->engine ? + parent->engine : parent, /* gpuobj); - kfree(ramht); -} - -void -nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, - struct nouveau_channel *chan) -{ - struct nouveau_ramht_entry *entry; - struct nouveau_ramht *ramht; - - if (ref) - kref_get(&ref->refcount); - - ramht = *ptr; - if (ramht) { - while ((entry = nouveau_ramht_remove_entry(chan, 0))) { - nouveau_ramht_remove_hash(chan, entry->handle); - nouveau_gpuobj_ref(NULL, &entry->gpuobj); - kfree(entry); - } - - kref_put(&ramht->refcount, nouveau_ramht_del); - } - *ptr = ref; + ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3); + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c index 4b80931..66f7dfd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,61 +22,154 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include -/*XXX: This stub is currently used on NV98+ also, as soon as this becomes - * more than just an enable/disable stub this needs to be split out to - * nv98_bsp.c... - */ +#include + +struct nv84_bsp_priv { + struct nouveau_bsp base; +}; -struct nv84_bsp_engine { - struct nouveau_exec_engine base; +struct nv84_bsp_chan { + struct nouveau_bsp_chan base; }; +/******************************************************************************* + * BSP object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv84_bsp_sclass[] = { + {}, +}; + +/******************************************************************************* + * BSP context + ******************************************************************************/ + static int -nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend) +nv84_bsp_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (!(nv_rd32(dev, 0x000200) & 0x00008000)) - return 0; + struct nv84_bsp_chan *priv; + int ret; + + ret = nouveau_bsp_context_create(parent, engine, oclass, NULL, + 0, 0, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_mask(dev, 0x000200, 0x00008000, 0x00000000); return 0; } +static void +nv84_bsp_context_dtor(struct nouveau_object *object) +{ + struct nv84_bsp_chan *priv = (void *)object; + nouveau_bsp_context_destroy(&priv->base); +} + static int -nv84_bsp_init(struct drm_device *dev, int engine) +nv84_bsp_context_init(struct nouveau_object *object) { - nv_mask(dev, 0x000200, 0x00008000, 0x00000000); - nv_mask(dev, 0x000200, 0x00008000, 0x00008000); + struct nv84_bsp_chan *priv = (void *)object; + int ret; + + ret = nouveau_bsp_context_init(&priv->base); + if (ret) + return ret; + return 0; } +static int +nv84_bsp_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_bsp_chan *priv = (void *)object; + return nouveau_bsp_context_fini(&priv->base, suspend); +} + +static struct nouveau_oclass +nv84_bsp_cclass = { + .handle = NV_ENGCTX(BSP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_bsp_context_ctor, + .dtor = nv84_bsp_context_dtor, + .init = nv84_bsp_context_init, + .fini = nv84_bsp_context_fini, + .rd32 = _nouveau_bsp_context_rd32, + .wr32 = _nouveau_bsp_context_wr32, + }, +}; + +/******************************************************************************* + * BSP engine/subdev functions + ******************************************************************************/ + static void -nv84_bsp_destroy(struct drm_device *dev, int engine) +nv84_bsp_intr(struct nouveau_subdev *subdev) { - struct nv84_bsp_engine *pbsp = nv_engine(dev, engine); +} - NVOBJ_ENGINE_DEL(dev, BSP); +static int +nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv84_bsp_priv *priv; + int ret; + + ret = nouveau_bsp_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - kfree(pbsp); + nv_subdev(priv)->unit = 0x04008000; + nv_subdev(priv)->intr = nv84_bsp_intr; + nv_engine(priv)->cclass = &nv84_bsp_cclass; + nv_engine(priv)->sclass = nv84_bsp_sclass; + return 0; } -int -nv84_bsp_create(struct drm_device *dev) +static void +nv84_bsp_dtor(struct nouveau_object *object) { - struct nv84_bsp_engine *pbsp; + struct nv84_bsp_priv *priv = (void *)object; + nouveau_bsp_destroy(&priv->base); +} - pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL); - if (!pbsp) - return -ENOMEM; +static int +nv84_bsp_init(struct nouveau_object *object) +{ + struct nv84_bsp_priv *priv = (void *)object; + int ret; - pbsp->base.destroy = nv84_bsp_destroy; - pbsp->base.init = nv84_bsp_init; - pbsp->base.fini = nv84_bsp_fini; + ret = nouveau_bsp_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, BSP, &pbsp->base); return 0; } + +static int +nv84_bsp_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_bsp_priv *priv = (void *)object; + return nouveau_bsp_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv84_bsp_oclass = { + .handle = NV_ENGINE(BSP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_bsp_ctor, + .dtor = nv84_bsp_dtor, + .init = nv84_bsp_init, + .fini = nv84_bsp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index 9150c5e..debb828 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,112 +22,75 @@ * Authors: Ben Skeggs */ -#include -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include -#include "fuc/nva3.fuc.h" - -struct nva3_copy_engine { - struct nouveau_exec_engine base; -}; - -static int -nva3_copy_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramin = chan->ramin; - struct nouveau_gpuobj *ctx = NULL; - int ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); +#include +#include +#include +#include - ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); - if (ret) - return ret; +#include +#include - nv_wo32(ramin, 0xc0, 0x00190000); - nv_wo32(ramin, 0xc4, ctx->addr + ctx->size - 1); - nv_wo32(ramin, 0xc8, ctx->addr); - nv_wo32(ramin, 0xcc, 0x00000000); - nv_wo32(ramin, 0xd0, 0x00000000); - nv_wo32(ramin, 0xd4, 0x00000000); - nvimem_flush(dev); +#include - nvvm_engref(chan->vm, engine, 1); - chan->engctx[engine] = ctx; - return 0; -} - -static int -nva3_copy_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; +#include "fuc/nva3.fuc.h" - /* fuc engine doesn't need an object, our ramht code does.. */ - ctx->engine = 3; - ctx->class = class; - return nouveau_ramht_insert(chan, handle, ctx); -} +struct nva3_copy_priv { + struct nouveau_copy base; +}; -static void -nva3_copy_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - int i; +struct nva3_copy_chan { + struct nouveau_copy_chan base; +}; - for (i = 0xc0; i <= 0xd4; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); +/******************************************************************************* + * Copy object classes + ******************************************************************************/ - nvvm_engref(chan->vm, engine, -1); - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = ctx; -} +static struct nouveau_oclass +nva3_copy_sclass[] = { + { 0x85b5, &nouveau_object_ofuncs }, + {} +}; -static void -nva3_copy_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x0d); -} +/******************************************************************************* + * PCOPY context + ******************************************************************************/ static int -nva3_copy_init(struct drm_device *dev, int engine) +nva3_copy_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - int i; - - nv_mask(dev, 0x000200, 0x00002000, 0x00000000); - nv_mask(dev, 0x000200, 0x00002000, 0x00002000); - nv_wr32(dev, 0x104014, 0xffffffff); /* disable all interrupts */ - - /* upload ucode */ - nv_wr32(dev, 0x1041c0, 0x01000000); - for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++) - nv_wr32(dev, 0x1041c4, nva3_pcopy_data[i]); + struct nva3_copy_chan *priv; + int ret; - nv_wr32(dev, 0x104180, 0x01000000); - for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) { - if ((i & 0x3f) == 0) - nv_wr32(dev, 0x104188, i >> 6); - nv_wr32(dev, 0x104184, nva3_pcopy_code[i]); - } + ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256, 0, + NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - /* start it running */ - nv_wr32(dev, 0x10410c, 0x00000000); - nv_wr32(dev, 0x104104, 0x00000000); /* ENTRY */ - nv_wr32(dev, 0x104100, 0x00000002); /* TRIGGER */ return 0; } -static int -nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, 0x104048, 0x00000003, 0x00000000); - nv_wr32(dev, 0x104014, 0xffffffff); - return 0; -} +static struct nouveau_oclass +nva3_copy_cclass = { + .handle = NV_ENGCTX(COPY0, 0xa3), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nva3_copy_context_ctor, + .dtor = _nouveau_copy_context_dtor, + .init = _nouveau_copy_context_init, + .fini = _nouveau_copy_context_fini, + .rd32 = _nouveau_copy_context_rd32, + .wr32 = _nouveau_copy_context_wr32, + + }, +}; + +/******************************************************************************* + * PCOPY engine/subdev functions + ******************************************************************************/ static struct nouveau_enum nva3_copy_isr_error_name[] = { { 0x0001, "ILLEGAL_MTHD" }, @@ -137,65 +100,114 @@ static struct nouveau_enum nva3_copy_isr_error_name[] = { }; static void -nva3_copy_isr(struct drm_device *dev) +nva3_copy_intr(struct nouveau_subdev *subdev) { - u32 dispatch = nv_rd32(dev, 0x10401c); - u32 stat = nv_rd32(dev, 0x104008) & dispatch & ~(dispatch >> 16); - u32 inst = nv_rd32(dev, 0x104050) & 0x3fffffff; - u32 ssta = nv_rd32(dev, 0x104040) & 0x0000ffff; - u32 addr = nv_rd32(dev, 0x104040) >> 16; + struct nva3_copy_priv *priv = (void *)subdev; + u32 dispatch = nv_rd32(priv, 0x10401c); + u32 stat = nv_rd32(priv, 0x104008) & dispatch & ~(dispatch >> 16); + u32 inst = nv_rd32(priv, 0x104050) & 0x3fffffff; + u32 ssta = nv_rd32(priv, 0x104040) & 0x0000ffff; + u32 addr = nv_rd32(priv, 0x104040) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(dev, 0x104044); - int chid = nv50_graph_isr_chid(dev, inst); + u32 data = nv_rd32(priv, 0x104044); if (stat & 0x00000040) { - NV_INFO(dev, "PCOPY: DISPATCH_ERROR ["); + nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nva3_copy_isr_error_name, ssta); - printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst, subc, mthd, data); - nv_wr32(dev, 0x104004, 0x00000040); + printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n", + inst, subc, mthd, data); + nv_wr32(priv, 0x104004, 0x00000040); stat &= ~0x00000040; } if (stat) { - NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat); - nv_wr32(dev, 0x104004, stat); + nv_error(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x104004, stat); } - nv50_fb_vm_trap(dev, 1); + + nv50_fb_trap(nouveau_fb(priv), 1); } -static void -nva3_copy_destroy(struct drm_device *dev, int engine) +static int +nva3_copy_tlb_flush(struct nouveau_engine *engine) { - struct nva3_copy_engine *pcopy = nv_engine(dev, engine); + nv50_vm_flush_engine(&engine->base, 0x0d); + return 0; +} - nouveau_irq_unregister(dev, 22); +static int +nva3_copy_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + bool enable = (nv_device(parent)->chipset != 0xaf); + struct nva3_copy_priv *priv; + int ret; - NVOBJ_ENGINE_DEL(dev, COPY0); - kfree(pcopy); + ret = nouveau_copy_create(parent, engine, oclass, enable, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00802000; + nv_subdev(priv)->intr = nva3_copy_intr; + nv_engine(priv)->cclass = &nva3_copy_cclass; + nv_engine(priv)->sclass = nva3_copy_sclass; + nv_engine(priv)->tlb_flush = nva3_copy_tlb_flush; + return 0; } -int -nva3_copy_create(struct drm_device *dev) +static int +nva3_copy_init(struct nouveau_object *object) { - struct nva3_copy_engine *pcopy; + struct nva3_copy_priv *priv = (void *)object; + int ret, i; - pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL); - if (!pcopy) - return -ENOMEM; + ret = nouveau_copy_init(&priv->base); + if (ret) + return ret; - pcopy->base.destroy = nva3_copy_destroy; - pcopy->base.init = nva3_copy_init; - pcopy->base.fini = nva3_copy_fini; - pcopy->base.context_new = nva3_copy_context_new; - pcopy->base.context_del = nva3_copy_context_del; - pcopy->base.object_new = nva3_copy_object_new; - pcopy->base.tlb_flush = nva3_copy_tlb_flush; + /* disable all interrupts */ + nv_wr32(priv, 0x104014, 0xffffffff); - nouveau_irq_register(dev, 22, nva3_copy_isr); + /* upload ucode */ + nv_wr32(priv, 0x1041c0, 0x01000000); + for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++) + nv_wr32(priv, 0x1041c4, nva3_pcopy_data[i]); + + nv_wr32(priv, 0x104180, 0x01000000); + for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(priv, 0x104188, i >> 6); + nv_wr32(priv, 0x104184, nva3_pcopy_code[i]); + } - NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base); - NVOBJ_CLASS(dev, 0x85b5, COPY0); + /* start it running */ + nv_wr32(priv, 0x10410c, 0x00000000); + nv_wr32(priv, 0x104104, 0x00000000); /* ENTRY */ + nv_wr32(priv, 0x104100, 0x00000002); /* TRIGGER */ return 0; } + +static int +nva3_copy_fini(struct nouveau_object *object, bool suspend) +{ + struct nva3_copy_priv *priv = (void *)object; + + nv_mask(priv, 0x104048, 0x00000003, 0x00000000); + nv_wr32(priv, 0x104014, 0xffffffff); + + return nouveau_copy_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nva3_copy_oclass = { + .handle = NV_ENGINE(COPY0, 0xa3), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nva3_copy_ctor, + .dtor = _nouveau_copy_dtor, + .init = nva3_copy_init, + .fini = nva3_copy_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index f39de5a..ecc8faa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,138 +22,86 @@ * Authors: Ben Skeggs */ -#include -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include +#include + +#include + #include "fuc/nvc0.fuc.h" -struct nvc0_copy_engine { - struct nouveau_exec_engine base; - u32 irq; - u32 pmc; - u32 fuc; - u32 ctx; +struct nvc0_copy_priv { + struct nouveau_copy base; }; struct nvc0_copy_chan { - struct nouveau_gpuobj *mem; - struct nouveau_vma vma; + struct nouveau_copy_chan base; }; -static int -nvc0_copy_context_new(struct nouveau_channel *chan, int engine) -{ - struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); - struct nvc0_copy_chan *cctx; - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *ramin = chan->ramin; - int ret; - - cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL); - if (!cctx) - return -ENOMEM; +/******************************************************************************* + * Copy object classes + ******************************************************************************/ - ret = nouveau_gpuobj_new(dev, NULL, 256, 256, - NVOBJ_FLAG_ZERO_ALLOC, &cctx->mem); - if (ret) - return ret; +static struct nouveau_oclass +nvc0_copy0_sclass[] = { + { 0x90b5, &nouveau_object_ofuncs }, + {}, +}; - ret = nouveau_gpuobj_map_vm(cctx->mem, chan->vm, NV_MEM_ACCESS_RW, - &cctx->vma); - if (ret) - return ret; +static struct nouveau_oclass +nvc0_copy1_sclass[] = { + { 0x90b8, &nouveau_object_ofuncs }, + {}, +}; - nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(cctx->vma.offset)); - nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(cctx->vma.offset)); - nvimem_flush(dev); - return 0; -} +/******************************************************************************* + * PCOPY context + ******************************************************************************/ static int -nvc0_copy_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) -{ - return 0; -} - -static void -nvc0_copy_context_del(struct nouveau_channel *chan, int engine) +nvc0_copy_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine); - struct nvc0_copy_chan *cctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - u32 inst; - - inst = (chan->ramin->addr >> 12); - inst |= 0x40000000; - - /* disable fifo access */ - nv_wr32(dev, pcopy->fuc + 0x048, 0x00000000); - /* mark channel as unloaded if it's currently active */ - if (nv_rd32(dev, pcopy->fuc + 0x050) == inst) - nv_mask(dev, pcopy->fuc + 0x050, 0x40000000, 0x00000000); - /* mark next channel as invalid if it's about to be loaded */ - if (nv_rd32(dev, pcopy->fuc + 0x054) == inst) - nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000); - /* restore fifo access */ - nv_wr32(dev, pcopy->fuc + 0x048, 0x00000003); - - nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000); - nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000); - - nouveau_gpuobj_unmap(&cctx->vma); - nouveau_gpuobj_ref(NULL, &cctx->mem); - - kfree(cctx); - chan->engctx[engine] = NULL; -} - -static int -nvc0_copy_init(struct drm_device *dev, int engine) -{ - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); - int i; - - nv_mask(dev, 0x000200, pcopy->pmc, 0x00000000); - nv_mask(dev, 0x000200, pcopy->pmc, pcopy->pmc); - nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff); - - nv_wr32(dev, pcopy->fuc + 0x1c0, 0x01000000); - for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++) - nv_wr32(dev, pcopy->fuc + 0x1c4, nvc0_pcopy_data[i]); + struct nvc0_copy_chan *priv; + int ret; - nv_wr32(dev, pcopy->fuc + 0x180, 0x01000000); - for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) { - if ((i & 0x3f) == 0) - nv_wr32(dev, pcopy->fuc + 0x188, i >> 6); - nv_wr32(dev, pcopy->fuc + 0x184, nvc0_pcopy_code[i]); - } + ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256, + 256, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, pcopy->fuc + 0x084, engine - NVOBJ_ENGINE_COPY0); - nv_wr32(dev, pcopy->fuc + 0x10c, 0x00000000); - nv_wr32(dev, pcopy->fuc + 0x104, 0x00000000); /* ENTRY */ - nv_wr32(dev, pcopy->fuc + 0x100, 0x00000002); /* TRIGGER */ return 0; } -static int -nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) -{ - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); +static struct nouveau_ofuncs +nvc0_copy_context_ofuncs = { + .ctor = nvc0_copy_context_ctor, + .dtor = _nouveau_copy_context_dtor, + .init = _nouveau_copy_context_init, + .fini = _nouveau_copy_context_fini, + .rd32 = _nouveau_copy_context_rd32, + .wr32 = _nouveau_copy_context_wr32, +}; - nv_mask(dev, pcopy->fuc + 0x048, 0x00000003, 0x00000000); +static struct nouveau_oclass +nvc0_copy0_cclass = { + .handle = NV_ENGCTX(COPY0, 0xc0), + .ofuncs = &nvc0_copy_context_ofuncs, +}; - /* trigger fuc context unload */ - nv_wait(dev, pcopy->fuc + 0x008, 0x0000000c, 0x00000000); - nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000); - nv_wr32(dev, pcopy->fuc + 0x000, 0x00000008); - nv_wait(dev, pcopy->fuc + 0x008, 0x00000008, 0x00000000); +static struct nouveau_oclass +nvc0_copy1_cclass = { + .handle = NV_ENGCTX(COPY1, 0xc0), + .ofuncs = &nvc0_copy_context_ofuncs, +}; - nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff); - return 0; -} +/******************************************************************************* + * PCOPY engine/subdev functions + ******************************************************************************/ static struct nouveau_enum nvc0_copy_isr_error_name[] = { { 0x0001, "ILLEGAL_MTHD" }, @@ -163,93 +111,145 @@ static struct nouveau_enum nvc0_copy_isr_error_name[] = { }; static void -nvc0_copy_isr(struct drm_device *dev, int engine) +nvc0_copy_intr(struct nouveau_subdev *subdev) { - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); - u32 disp = nv_rd32(dev, pcopy->fuc + 0x01c); - u32 stat = nv_rd32(dev, pcopy->fuc + 0x008) & disp & ~(disp >> 16); - u64 inst = (u64)(nv_rd32(dev, pcopy->fuc + 0x050) & 0x0fffffff) << 12; - u32 chid = nvc0_graph_isr_chid(dev, inst); - u32 ssta = nv_rd32(dev, pcopy->fuc + 0x040) & 0x0000ffff; - u32 addr = nv_rd32(dev, pcopy->fuc + 0x040) >> 16; + int idx = nv_engidx(nv_object(subdev)) - NVDEV_ENGINE_COPY0; + struct nvc0_copy_priv *priv = (void *)subdev; + u32 disp = nv_rd32(priv, 0x10401c + (idx * 0x1000)); + u32 intr = nv_rd32(priv, 0x104008 + (idx * 0x1000)); + u32 stat = intr & disp & ~(disp >> 16); + u64 inst = nv_rd32(priv, 0x104050 + (idx * 0x1000)) & 0x0fffffff; + u32 ssta = nv_rd32(priv, 0x104040 + (idx * 0x1000)) & 0x0000ffff; + u32 addr = nv_rd32(priv, 0x104040 + (idx * 0x1000)) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(dev, pcopy->fuc + 0x044); + u32 data = nv_rd32(priv, 0x104044 + (idx * 0x1000)); if (stat & 0x00000040) { - NV_INFO(dev, "PCOPY: DISPATCH_ERROR ["); + nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nvc0_copy_isr_error_name, ssta); - printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst, subc, mthd, data); - nv_wr32(dev, pcopy->fuc + 0x004, 0x00000040); + printk("] ch 0x%010llx subc %d mthd 0x%04x data 0x%08x\n", + (u64)inst << 12, subc, mthd, data); + nv_wr32(priv, 0x104004 + (idx * 0x1000), 0x00000040); stat &= ~0x00000040; } if (stat) { - NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat); - nv_wr32(dev, pcopy->fuc + 0x004, stat); + nv_error(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x104004 + (idx * 0x1000), stat); } } -static void -nvc0_copy_isr_0(struct drm_device *dev) +static int +nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY0); -} + struct nvc0_copy_priv *priv; + int ret; -static void -nvc0_copy_isr_1(struct drm_device *dev) -{ - nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY1); + if (nv_rd32(parent, 0x022500) & 0x00000100) + return -ENODEV; + + ret = nouveau_copy_create(parent, engine, oclass, true, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000040; + nv_subdev(priv)->intr = nvc0_copy_intr; + nv_engine(priv)->cclass = &nvc0_copy0_cclass; + nv_engine(priv)->sclass = nvc0_copy0_sclass; + return 0; } -static void -nvc0_copy_destroy(struct drm_device *dev, int engine) +static int +nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + struct nvc0_copy_priv *priv; + int ret; - nouveau_irq_unregister(dev, pcopy->irq); + if (nv_rd32(parent, 0x022500) & 0x00000200) + return -ENODEV; - if (engine == NVOBJ_ENGINE_COPY0) - NVOBJ_ENGINE_DEL(dev, COPY0); - else - NVOBJ_ENGINE_DEL(dev, COPY1); - kfree(pcopy); + ret = nouveau_copy_create(parent, engine, oclass, true, 1, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000080; + nv_subdev(priv)->intr = nvc0_copy_intr; + nv_engine(priv)->cclass = &nvc0_copy1_cclass; + nv_engine(priv)->sclass = nvc0_copy1_sclass; + return 0; } -int -nvc0_copy_create(struct drm_device *dev, int engine) +static int +nvc0_copy_init(struct nouveau_object *object) { - struct nvc0_copy_engine *pcopy; - - pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL); - if (!pcopy) - return -ENOMEM; - - pcopy->base.destroy = nvc0_copy_destroy; - pcopy->base.init = nvc0_copy_init; - pcopy->base.fini = nvc0_copy_fini; - pcopy->base.context_new = nvc0_copy_context_new; - pcopy->base.context_del = nvc0_copy_context_del; - pcopy->base.object_new = nvc0_copy_object_new; - - if (engine == 0) { - pcopy->irq = 5; - pcopy->pmc = 0x00000040; - pcopy->fuc = 0x104000; - pcopy->ctx = 0x0230; - nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_0); - NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base); - NVOBJ_CLASS(dev, 0x90b5, COPY0); - } else { - pcopy->irq = 6; - pcopy->pmc = 0x00000080; - pcopy->fuc = 0x105000; - pcopy->ctx = 0x0240; - nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_1); - NVOBJ_ENGINE_ADD(dev, COPY1, &pcopy->base); - NVOBJ_CLASS(dev, 0x90b8, COPY1); + int idx = nv_engidx(object) - NVDEV_ENGINE_COPY0; + struct nvc0_copy_priv *priv = (void *)object; + int ret, i; + + ret = nouveau_copy_init(&priv->base); + if (ret) + return ret; + + /* disable all interrupts */ + nv_wr32(priv, 0x104014 + (idx * 0x1000), 0xffffffff); + + /* upload ucode */ + nv_wr32(priv, 0x1041c0 + (idx * 0x1000), 0x01000000); + for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++) + nv_wr32(priv, 0x1041c4 + (idx * 0x1000), nvc0_pcopy_data[i]); + + nv_wr32(priv, 0x104180 + (idx * 0x1000), 0x01000000); + for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(priv, 0x104188 + (idx * 0x1000), i >> 6); + nv_wr32(priv, 0x104184 + (idx * 0x1000), nvc0_pcopy_code[i]); } + /* start it running */ + nv_wr32(priv, 0x104084 + (idx * 0x1000), idx); + nv_wr32(priv, 0x10410c + (idx * 0x1000), 0x00000000); + nv_wr32(priv, 0x104104 + (idx * 0x1000), 0x00000000); /* ENTRY */ + nv_wr32(priv, 0x104100 + (idx * 0x1000), 0x00000002); /* TRIGGER */ return 0; } + +static int +nvc0_copy_fini(struct nouveau_object *object, bool suspend) +{ + int idx = nv_engidx(object) - NVDEV_ENGINE_COPY0; + struct nvc0_copy_priv *priv = (void *)object; + + nv_mask(priv, 0x104048 + (idx * 0x1000), 0x00000003, 0x00000000); + nv_wr32(priv, 0x104014 + (idx * 0x1000), 0xffffffff); + + return nouveau_copy_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nvc0_copy0_oclass = { + .handle = NV_ENGINE(COPY0, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_copy0_ctor, + .dtor = _nouveau_copy_dtor, + .init = nvc0_copy_init, + .fini = nvc0_copy_fini, + }, +}; + +struct nouveau_oclass +nvc0_copy1_oclass = { + .handle = NV_ENGINE(COPY1, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_copy1_ctor, + .dtor = _nouveau_copy_dtor, + .init = nvc0_copy_init, + .fini = nvc0_copy_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 63051ab..a0e5e39 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.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,99 +22,106 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include +#include +#include -struct nv84_crypt_engine { - struct nouveau_exec_engine base; +#include + +#include + +struct nv84_crypt_priv { + struct nouveau_crypt base; }; +struct nv84_crypt_chan { + struct nouveau_crypt_chan base; +}; + +/******************************************************************************* + * Crypt object classes + ******************************************************************************/ + static int -nv84_crypt_context_new(struct nouveau_channel *chan, int engine) +nv84_crypt_object_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 *ramin = chan->ramin; - struct nouveau_gpuobj *ctx; + struct nouveau_gpuobj *obj; int ret; - NV_DEBUG(dev, "ch%d\n", chan->id); - - ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - nv_wo32(ramin, 0xa0, 0x00190000); - nv_wo32(ramin, 0xa4, ctx->addr + ctx->size - 1); - nv_wo32(ramin, 0xa8, ctx->addr); - nv_wo32(ramin, 0xac, 0); - nv_wo32(ramin, 0xb0, 0); - nv_wo32(ramin, 0xb4, 0); - nvimem_flush(dev); - - nvvm_engref(chan->vm, engine, 1); - chan->engctx[engine] = ctx; + 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 void -nv84_crypt_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - u32 inst; - - inst = (chan->ramin->addr >> 12); - inst |= 0x80000000; - - /* mark context as invalid if still on the hardware, not - * doing this causes issues the next time PCRYPT is used, - * unsurprisingly :) - */ - nv_wr32(dev, 0x10200c, 0x00000000); - if (nv_rd32(dev, 0x102188) == inst) - nv_mask(dev, 0x102188, 0x80000000, 0x00000000); - if (nv_rd32(dev, 0x10218c) == inst) - nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); - nv_wr32(dev, 0x10200c, 0x00000010); - - nouveau_gpuobj_ref(NULL, &ctx); - - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; -} +static struct nouveau_ofuncs +nv84_crypt_ofuncs = { + .ctor = nv84_crypt_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 +nv84_crypt_sclass[] = { + { 0x74c1, &nv84_crypt_ofuncs }, + {} +}; + +/******************************************************************************* + * PCRYPT context + ******************************************************************************/ static int -nv84_crypt_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv84_crypt_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 nv84_crypt_chan *priv; int ret; - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_crypt_context_create(parent, engine, oclass, NULL, 256, + 0, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); if (ret) return ret; - obj->engine = 5; - obj->class = class; - nv_wo32(obj, 0x00, class); - nvimem_flush(dev); - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; + return 0; } -static void -nv84_crypt_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x0a); -} +static struct nouveau_oclass +nv84_crypt_cclass = { + .handle = NV_ENGCTX(CRYPT, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_crypt_context_ctor, + .dtor = _nouveau_crypt_context_dtor, + .init = _nouveau_crypt_context_init, + .fini = _nouveau_crypt_context_fini, + .rd32 = _nouveau_crypt_context_rd32, + .wr32 = _nouveau_crypt_context_wr32, + }, +}; + +/******************************************************************************* + * PCRYPT engine/subdev functions + ******************************************************************************/ -static struct nouveau_bitfield nv84_crypt_intr[] = { +static struct nouveau_bitfield nv84_crypt_intr_mask[] = { { 0x00000001, "INVALID_STATE" }, { 0x00000002, "ILLEGAL_MTHD" }, { 0x00000004, "ILLEGAL_CLASS" }, @@ -124,79 +131,78 @@ static struct nouveau_bitfield nv84_crypt_intr[] = { }; static void -nv84_crypt_isr(struct drm_device *dev) +nv84_crypt_intr(struct nouveau_subdev *subdev) { - u32 stat = nv_rd32(dev, 0x102130); - u32 mthd = nv_rd32(dev, 0x102190); - u32 data = nv_rd32(dev, 0x102194); - u64 inst = (u64)(nv_rd32(dev, 0x102188) & 0x7fffffff) << 12; - int show = nouveau_ratelimit(); - int chid = nv50_graph_isr_chid(dev, inst); - - if (show) { - NV_INFO(dev, "PCRYPT:"); - nouveau_bitfield_print(nv84_crypt_intr, stat); - printk(KERN_CONT " ch %d (0x%010llx) mthd 0x%04x data 0x%08x\n", - chid, inst, mthd, data); + struct nv84_crypt_priv *priv = (void *)subdev; + u32 stat = nv_rd32(priv, 0x102130); + u32 mthd = nv_rd32(priv, 0x102190); + u32 data = nv_rd32(priv, 0x102194); + u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff; + + if (stat) { + nv_error(priv, ""); + nouveau_bitfield_print(nv84_crypt_intr_mask, stat); + printk(" ch 0x%010llx mthd 0x%04x data 0x%08x\n", + (u64)inst << 12, mthd, data); } - nv_wr32(dev, 0x102130, stat); - nv_wr32(dev, 0x10200c, 0x10); + nv_wr32(priv, 0x102130, stat); + nv_wr32(priv, 0x10200c, 0x10); - nv50_fb_vm_trap(dev, show); + nv50_fb_trap(nouveau_fb(priv), 1); } static int -nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) +nv84_crypt_tlb_flush(struct nouveau_engine *engine) { - nv_wr32(dev, 0x102140, 0x00000000); + nv50_vm_flush_engine(&engine->base, 0x0a); return 0; } static int -nv84_crypt_init(struct drm_device *dev, int engine) +nv84_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); - nv_mask(dev, 0x000200, 0x00004000, 0x00004000); + struct nv84_crypt_priv *priv; + int ret; - nv_wr32(dev, 0x102130, 0xffffffff); - nv_wr32(dev, 0x102140, 0xffffffbf); + ret = nouveau_crypt_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_wr32(dev, 0x10200c, 0x00000010); + nv_subdev(priv)->unit = 0x00004000; + nv_subdev(priv)->intr = nv84_crypt_intr; + nv_engine(priv)->cclass = &nv84_crypt_cclass; + nv_engine(priv)->sclass = nv84_crypt_sclass; + nv_engine(priv)->tlb_flush = nv84_crypt_tlb_flush; return 0; } -static void -nv84_crypt_destroy(struct drm_device *dev, int engine) -{ - struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, CRYPT); - - nouveau_irq_unregister(dev, 14); - kfree(pcrypt); -} - -int -nv84_crypt_create(struct drm_device *dev) +static int +nv84_crypt_init(struct nouveau_object *object) { - struct nv84_crypt_engine *pcrypt; - - pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL); - if (!pcrypt) - return -ENOMEM; - - pcrypt->base.destroy = nv84_crypt_destroy; - pcrypt->base.init = nv84_crypt_init; - pcrypt->base.fini = nv84_crypt_fini; - pcrypt->base.context_new = nv84_crypt_context_new; - pcrypt->base.context_del = nv84_crypt_context_del; - pcrypt->base.object_new = nv84_crypt_object_new; - pcrypt->base.tlb_flush = nv84_crypt_tlb_flush; + struct nv84_crypt_priv *priv = (void *)object; + int ret; - nouveau_irq_register(dev, 14, nv84_crypt_isr); + ret = nouveau_crypt_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base); - NVOBJ_CLASS (dev, 0x74c1, CRYPT); + nv_wr32(priv, 0x102130, 0xffffffff); + nv_wr32(priv, 0x102140, 0xffffffbf); + nv_wr32(priv, 0x10200c, 0x00000010); return 0; } + +struct nouveau_oclass +nv84_crypt_oclass = { + .handle = NV_ENGINE(CRYPT, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_crypt_ctor, + .dtor = _nouveau_crypt_dtor, + .init = nv84_crypt_init, + .fini = _nouveau_crypt_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index c9adc1b..559a1b1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,124 +22,74 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include +#include +#include -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include + +#include #include "fuc/nv98.fuc.h" struct nv98_crypt_priv { - struct nouveau_exec_engine base; + struct nouveau_crypt base; }; struct nv98_crypt_chan { - struct nouveau_gpuobj *mem; + struct nouveau_crypt_chan base; }; -static int -nv98_crypt_context_new(struct nouveau_channel *chan, int engine) -{ - struct drm_device *dev = chan->dev; - struct nv98_crypt_priv *priv = nv_engine(dev, engine); - struct nv98_crypt_chan *cctx; - int ret; - - cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL); - if (!cctx) - return -ENOMEM; - - nvvm_engref(chan->vm, engine, 1); - - ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &cctx->mem); - if (ret) - goto error; - - nv_wo32(chan->ramin, 0xa0, 0x00190000); - nv_wo32(chan->ramin, 0xa4, cctx->mem->addr + cctx->mem->size - 1); - nv_wo32(chan->ramin, 0xa8, cctx->mem->addr); - nv_wo32(chan->ramin, 0xac, 0x00000000); - nv_wo32(chan->ramin, 0xb0, 0x00000000); - nv_wo32(chan->ramin, 0xb4, 0x00000000); - nvimem_flush(dev); - -error: - if (ret) - priv->base.context_del(chan, engine); - return ret; -} - -static void -nv98_crypt_context_del(struct nouveau_channel *chan, int engine) -{ - struct nv98_crypt_chan *cctx = chan->engctx[engine]; - int i; - - for (i = 0xa0; i < 0xb4; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); +/******************************************************************************* + * Crypt object classes + ******************************************************************************/ - nouveau_gpuobj_ref(NULL, &cctx->mem); +static struct nouveau_oclass +nv98_crypt_sclass[] = { + { 0x88b4, &nouveau_object_ofuncs }, + {}, +}; - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; - kfree(cctx); -} +/******************************************************************************* + * PCRYPT context + ******************************************************************************/ static int -nv98_crypt_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv98_crypt_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv98_crypt_chan *cctx = chan->engctx[engine]; - - /* fuc engine doesn't need an object, our ramht code does.. */ - cctx->mem->engine = 5; - cctx->mem->class = class; - return nouveau_ramht_insert(chan, handle, cctx->mem); -} + struct nv98_crypt_chan *priv; + int ret; -static void -nv98_crypt_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x0a); -} + ret = nouveau_crypt_context_create(parent, engine, oclass, NULL, 256, + 256, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; -static int -nv98_crypt_fini(struct drm_device *dev, int engine, bool suspend) -{ - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); return 0; } -static int -nv98_crypt_init(struct drm_device *dev, int engine) -{ - int i; - - /* reset! */ - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); - nv_mask(dev, 0x000200, 0x00004000, 0x00004000); - - /* wait for exit interrupt to signal */ - nv_wait(dev, 0x087008, 0x00000010, 0x00000010); - nv_wr32(dev, 0x087004, 0x00000010); - - /* upload microcode code and data segments */ - nv_wr32(dev, 0x087ff8, 0x00100000); - for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_code); i++) - nv_wr32(dev, 0x087ff4, nv98_pcrypt_code[i]); - - nv_wr32(dev, 0x087ff8, 0x00000000); - for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_data); i++) - nv_wr32(dev, 0x087ff4, nv98_pcrypt_data[i]); +static struct nouveau_oclass +nv98_crypt_cclass = { + .handle = NV_ENGCTX(CRYPT, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_crypt_context_ctor, + .dtor = _nouveau_crypt_context_dtor, + .init = _nouveau_crypt_context_init, + .fini = _nouveau_crypt_context_fini, + .rd32 = _nouveau_crypt_context_rd32, + .wr32 = _nouveau_crypt_context_wr32, + }, +}; - /* start it running */ - nv_wr32(dev, 0x08710c, 0x00000000); - nv_wr32(dev, 0x087104, 0x00000000); /* ENTRY */ - nv_wr32(dev, 0x087100, 0x00000002); /* TRIGGER */ - return 0; -} +/******************************************************************************* + * PCRYPT engine/subdev functions + ******************************************************************************/ static struct nouveau_enum nv98_crypt_isr_error_name[] = { { 0x0000, "ILLEGAL_MTHD" }, @@ -150,65 +100,100 @@ static struct nouveau_enum nv98_crypt_isr_error_name[] = { }; static void -nv98_crypt_isr(struct drm_device *dev) +nv98_crypt_intr(struct nouveau_subdev *subdev) { - u32 disp = nv_rd32(dev, 0x08701c); - u32 stat = nv_rd32(dev, 0x087008) & disp & ~(disp >> 16); - u32 inst = nv_rd32(dev, 0x087050) & 0x3fffffff; - u32 ssta = nv_rd32(dev, 0x087040) & 0x0000ffff; - u32 addr = nv_rd32(dev, 0x087040) >> 16; + struct nv98_crypt_priv *priv = (void *)subdev; + u32 disp = nv_rd32(priv, 0x08701c); + u32 stat = nv_rd32(priv, 0x087008) & disp & ~(disp >> 16); + u32 inst = nv_rd32(priv, 0x087050) & 0x3fffffff; + u32 ssta = nv_rd32(priv, 0x087040) & 0x0000ffff; + u32 addr = nv_rd32(priv, 0x087040) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; - u32 data = nv_rd32(dev, 0x087044); - int chid = nv50_graph_isr_chid(dev, inst); + u32 data = nv_rd32(priv, 0x087044); if (stat & 0x00000040) { - NV_INFO(dev, "PCRYPT: DISPATCH_ERROR ["); + nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nv98_crypt_isr_error_name, ssta); - printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst, subc, mthd, data); - nv_wr32(dev, 0x087004, 0x00000040); + printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n", + inst, subc, mthd, data); + nv_wr32(priv, 0x087004, 0x00000040); stat &= ~0x00000040; } if (stat) { - NV_INFO(dev, "PCRYPT: unhandled intr 0x%08x\n", stat); - nv_wr32(dev, 0x087004, stat); + nv_error(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x087004, stat); } - nv50_fb_vm_trap(dev, 1); + nv50_fb_trap(nouveau_fb(priv), 1); } -static void -nv98_crypt_destroy(struct drm_device *dev, int engine) +static int +nv98_crypt_tlb_flush(struct nouveau_engine *engine) { - struct nv98_crypt_priv *priv = nv_engine(dev, engine); - - nouveau_irq_unregister(dev, 14); - NVOBJ_ENGINE_DEL(dev, CRYPT); - kfree(priv); + nv50_vm_flush_engine(&engine->base, 0x0a); + return 0; } -int -nv98_crypt_create(struct drm_device *dev) +static int +nv98_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { struct nv98_crypt_priv *priv; + int ret; + + ret = nouveau_crypt_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00004000; + nv_subdev(priv)->intr = nv98_crypt_intr; + nv_engine(priv)->cclass = &nv98_crypt_cclass; + nv_engine(priv)->sclass = nv98_crypt_sclass; + nv_engine(priv)->tlb_flush = nv98_crypt_tlb_flush; + return 0; +} + +static int +nv98_crypt_init(struct nouveau_object *object) +{ + struct nv98_crypt_priv *priv = (void *)object; + int ret, i; + + ret = nouveau_crypt_init(&priv->base); + if (ret) + return ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + /* wait for exit interrupt to signal */ + nv_wait(priv, 0x087008, 0x00000010, 0x00000010); + nv_wr32(priv, 0x087004, 0x00000010); - priv->base.destroy = nv98_crypt_destroy; - priv->base.init = nv98_crypt_init; - priv->base.fini = nv98_crypt_fini; - priv->base.context_new = nv98_crypt_context_new; - priv->base.context_del = nv98_crypt_context_del; - priv->base.object_new = nv98_crypt_object_new; - priv->base.tlb_flush = nv98_crypt_tlb_flush; + /* upload microcode code and data segments */ + nv_wr32(priv, 0x087ff8, 0x00100000); + for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_code); i++) + nv_wr32(priv, 0x087ff4, nv98_pcrypt_code[i]); - nouveau_irq_register(dev, 14, nv98_crypt_isr); + nv_wr32(priv, 0x087ff8, 0x00000000); + for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_data); i++) + nv_wr32(priv, 0x087ff4, nv98_pcrypt_data[i]); - NVOBJ_ENGINE_ADD(dev, CRYPT, &priv->base); - NVOBJ_CLASS(dev, 0x88b4, CRYPT); + /* start it running */ + nv_wr32(priv, 0x08710c, 0x00000000); + nv_wr32(priv, 0x087104, 0x00000000); /* ENTRY */ + nv_wr32(priv, 0x087100, 0x00000002); /* TRIGGER */ return 0; } + +struct nouveau_oclass +nv98_crypt_oclass = { + .handle = NV_ENGINE(CRYPT, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_crypt_ctor, + .dtor = _nouveau_crypt_dtor, + .init = nv98_crypt_init, + .fini = _nouveau_crypt_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c new file mode 100644 index 0000000..1c919f2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c @@ -0,0 +1,90 @@ +/* + * 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: + * + * 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 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 + +struct nv04_disp_priv { + struct nouveau_disp base; +}; + +static struct nouveau_oclass +nv04_disp_sclass[] = { + {}, +}; + +static void +nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc) +{ + struct nouveau_disp *disp = &priv->base; + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + +static void +nv04_disp_intr(struct nouveau_subdev *subdev) +{ + struct nv04_disp_priv *priv = (void *)subdev; + u32 crtc0 = nv_rd32(priv, 0x600100); + u32 crtc1 = nv_rd32(priv, 0x602100); + + if (crtc0 & 0x00000001) { + nv04_disp_intr_vblank(priv, 0); + nv_wr32(priv, 0x600100, 0x00000001); + } + + if (crtc1 & 0x00000001) { + nv04_disp_intr_vblank(priv, 1); + nv_wr32(priv, 0x602100, 0x00000001); + } +} + +static int +nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_disp_priv *priv; + int ret; + + ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY", + "display", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->sclass = nv04_disp_sclass; + nv_subdev(priv)->intr = nv04_disp_intr; + return 0; +} + +struct nouveau_oclass +nv04_disp_oclass = { + .handle = NV_ENGINE(DISP, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_disp_ctor, + .dtor = _nouveau_disp_dtor, + .init = _nouveau_disp_init, + .fini = _nouveau_disp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c new file mode 100644 index 0000000..16a9afb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -0,0 +1,125 @@ +/* + * 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: + * + * 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 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 +#include + +struct nv50_disp_priv { + struct nouveau_disp base; +}; + +static struct nouveau_oclass +nv50_disp_sclass[] = { + {}, +}; + +static void +nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) +{ + struct nouveau_disp *disp = &priv->base; + struct nouveau_software_chan *chan, *temp; + unsigned long flags; + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { + if (chan->vblank.crtc != crtc) + continue; + + nv_wr32(priv, 0x001704, chan->vblank.channel); + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); + + if (nv_device(priv)->chipset == 0x50) { + nv_wr32(priv, 0x001570, chan->vblank.offset); + nv_wr32(priv, 0x001574, chan->vblank.value); + } else { + if (nv_device(priv)->chipset >= 0xc0) { + nv_wr32(priv, 0x06000c, + upper_32_bits(chan->vblank.offset)); + } + nv_wr32(priv, 0x060010, chan->vblank.offset); + nv_wr32(priv, 0x060014, chan->vblank.value); + } + + list_del(&chan->vblank.head); + if (disp->vblank.put) + disp->vblank.put(disp->vblank.data, crtc); + } + spin_unlock_irqrestore(&disp->vblank.lock, flags); + + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + +static void +nv50_disp_intr(struct nouveau_subdev *subdev) +{ + struct nv50_disp_priv *priv = (void *)subdev; + u32 stat1 = nv_rd32(priv, 0x610024); + + if (stat1 & 0x00000004) { + nv50_disp_intr_vblank(priv, 0); + nv_wr32(priv, 0x610024, 0x00000004); + stat1 &= ~0x00000004; + } + + if (stat1 & 0x00000008) { + nv50_disp_intr_vblank(priv, 1); + nv_wr32(priv, 0x610024, 0x00000008); + stat1 &= ~0x00000008; + } + +} + +static int +nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_disp_priv *priv; + int ret; + + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", + "display", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->sclass = nv50_disp_sclass; + nv_subdev(priv)->intr = nv50_disp_intr; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); + return 0; +} + +struct nouveau_oclass +nv50_disp_oclass = { + .handle = NV_ENGINE(DISP, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_disp_ctor, + .dtor = _nouveau_disp_dtor, + .init = _nouveau_disp_init, + .fini = _nouveau_disp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c new file mode 100644 index 0000000..d93efbc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -0,0 +1,118 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +struct nvd0_disp_priv { + struct nouveau_disp base; +}; + +static struct nouveau_oclass +nvd0_disp_sclass[] = { + {}, +}; + +static void +nvd0_disp_intr_vblank(struct nvd0_disp_priv *priv, int crtc) +{ + struct nouveau_bar *bar = nouveau_bar(priv); + struct nouveau_disp *disp = &priv->base; + struct nouveau_software_chan *chan, *temp; + unsigned long flags; + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { + if (chan->vblank.crtc != crtc) + continue; + + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); + bar->flush(bar); + nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060014, chan->vblank.value); + + list_del(&chan->vblank.head); + if (disp->vblank.put) + disp->vblank.put(disp->vblank.data, crtc); + } + spin_unlock_irqrestore(&disp->vblank.lock, flags); + + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + +static void +nvd0_disp_intr(struct nouveau_subdev *subdev) +{ + struct nvd0_disp_priv *priv = (void *)subdev; + u32 intr = nv_rd32(priv, 0x610088); + int i; + + for (i = 0; i < 4; i++) { + u32 mask = 0x01000000 << i; + if (mask & intr) { + u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); + if (stat & 0x00000001) + nvd0_disp_intr_vblank(priv, i); + nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); + nv_rd32(priv, 0x6100c0 + (i * 0x800)); + } + } +} + +static int +nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvd0_disp_priv *priv; + int ret; + + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", + "display", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->sclass = nvd0_disp_sclass; + nv_subdev(priv)->intr = nvd0_disp_intr; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); + return 0; +} + +struct nouveau_oclass +nvd0_disp_oclass = { + .handle = NV_ENGINE(DISP, 0xd0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvd0_disp_ctor, + .dtor = _nouveau_disp_dtor, + .init = _nouveau_disp_init, + .fini = _nouveau_disp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c new file mode 100644 index 0000000..e1f013d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c @@ -0,0 +1,87 @@ +/* + * 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: + * + * 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 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 +#include + +#include +#include + +int +nouveau_dmaobj_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + void *data, u32 size, int len, void **pobject) +{ + struct nv_dma_class *args = data; + struct nouveau_dmaobj *object; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_object_create_(parent, engine, oclass, 0, len, pobject); + object = *pobject; + if (ret) + return ret; + + switch (args->flags & NV_DMA_TARGET_MASK) { + case NV_DMA_TARGET_VM: + object->target = NV_MEM_TARGET_VM; + break; + case NV_DMA_TARGET_VRAM: + object->target = NV_MEM_TARGET_VRAM; + break; + case NV_DMA_TARGET_PCI: + object->target = NV_MEM_TARGET_PCI; + break; + case NV_DMA_TARGET_PCI_US: + case NV_DMA_TARGET_AGP: + object->target = NV_MEM_TARGET_PCI_NOSNOOP; + break; + default: + return -EINVAL; + } + + switch (args->flags & NV_DMA_ACCESS_MASK) { + case NV_DMA_ACCESS_VM: + object->access = NV_MEM_ACCESS_VM; + break; + case NV_DMA_ACCESS_RD: + object->access = NV_MEM_ACCESS_RO; + break; + case NV_DMA_ACCESS_WR: + object->access = NV_MEM_ACCESS_WO; + break; + case NV_DMA_ACCESS_RDWR: + object->access = NV_MEM_ACCESS_RW; + break; + default: + return -EINVAL; + } + + object->start = args->start; + object->limit = args->limit; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c new file mode 100644 index 0000000..b0d3651 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c @@ -0,0 +1,176 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +#include + +struct nv04_dmaeng_priv { + struct nouveau_dmaeng base; +}; + +struct nv04_dmaobj_priv { + struct nouveau_dmaobj base; +}; + +static int +nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, + struct nouveau_object *parent, + struct nouveau_dmaobj *dmaobj, + struct nouveau_gpuobj **pgpuobj) +{ + struct nouveau_gpuobj *gpuobj; + u32 flags0 = nv_mclass(dmaobj); + u32 flags2 = 0x00000000; + u32 offset = (dmaobj->start & 0xfffff000); + u32 adjust = (dmaobj->start & 0x00000fff); + u32 length = dmaobj->limit - dmaobj->start; + int ret; + + if (dmaobj->target == NV_MEM_TARGET_VM) { + gpuobj = nv04_vmmgr(dmaeng)->vm->pgt[0].obj[0]; + if (dmaobj->start == 0) + return nouveau_gpuobj_dup(parent, gpuobj, pgpuobj); + + offset = nv_ro32(gpuobj, 8 + (offset >> 10)); + offset &= 0xfffff000; + dmaobj->target = NV_MEM_TARGET_PCI; + dmaobj->access = NV_MEM_ACCESS_RW; + } + + switch (dmaobj->target) { + case NV_MEM_TARGET_VRAM: + flags0 |= 0x00003000; + break; + case NV_MEM_TARGET_PCI: + flags0 |= 0x00023000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags0 |= 0x00033000; + break; + default: + return -EINVAL; + } + + switch (dmaobj->access) { + case NV_MEM_ACCESS_RO: + flags0 |= 0x00004000; + break; + case NV_MEM_ACCESS_WO: + flags0 |= 0x00008000; + case NV_MEM_ACCESS_RW: + flags2 |= 0x00000002; + break; + default: + return -EINVAL; + } + + ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj); + *pgpuobj = gpuobj; + if (ret == 0) { + nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20)); + nv_wo32(*pgpuobj, 0x04, length); + nv_wo32(*pgpuobj, 0x08, flags2 | offset); + nv_wo32(*pgpuobj, 0x0c, flags2 | offset); + } + + return ret; +} + +static int +nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_dmaeng *dmaeng = (void *)engine; + struct nv04_dmaobj_priv *dmaobj; + struct nouveau_gpuobj *gpuobj; + int ret; + + ret = nouveau_dmaobj_create(parent, engine, oclass, + data, size, &dmaobj); + *pobject = nv_object(dmaobj); + if (ret) + return ret; + + switch (nv_mclass(parent)) { + case 0x006e: + ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); + nouveau_object_ref(NULL, pobject); + *pobject = nv_object(gpuobj); + break; + default: + break; + } + + return ret; +} + +static struct nouveau_ofuncs +nv04_dmaobj_ofuncs = { + .ctor = nv04_dmaobj_ctor, + .dtor = _nouveau_dmaobj_dtor, + .init = _nouveau_dmaobj_init, + .fini = _nouveau_dmaobj_fini, +}; + +static struct nouveau_oclass +nv04_dmaobj_sclass[] = { + { 0x0002, &nv04_dmaobj_ofuncs }, + { 0x0003, &nv04_dmaobj_ofuncs }, + { 0x003d, &nv04_dmaobj_ofuncs }, + {} +}; + +static int +nv04_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_dmaeng_priv *priv; + int ret; + + ret = nouveau_dmaeng_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.sclass = nv04_dmaobj_sclass; + priv->base.bind = nv04_dmaobj_bind; + return 0; +} + +struct nouveau_oclass +nv04_dmaeng_oclass = { + .handle = NV_ENGINE(DMAOBJ, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_dmaeng_ctor, + .dtor = _nouveau_dmaeng_dtor, + .init = _nouveau_dmaeng_init, + .fini = _nouveau_dmaeng_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c new file mode 100644 index 0000000..8207ac9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c @@ -0,0 +1,168 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +struct nv50_dmaeng_priv { + struct nouveau_dmaeng base; +}; + +struct nv50_dmaobj_priv { + struct nouveau_dmaobj base; +}; + +static int +nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng, + struct nouveau_object *parent, + struct nouveau_dmaobj *dmaobj, + struct nouveau_gpuobj **pgpuobj) +{ + u32 flags = nv_mclass(dmaobj); + int ret; + + switch (dmaobj->target) { + case NV_MEM_TARGET_VM: + flags |= 0x00000000; + flags |= 0x60000000; /* COMPRESSION_USEVM */ + flags |= 0x1fc00000; /* STORAGE_TYPE_USEVM */ + break; + case NV_MEM_TARGET_VRAM: + flags |= 0x00010000; + flags |= 0x00100000; /* ACCESSUS_USER_SYSTEM */ + break; + case NV_MEM_TARGET_PCI: + flags |= 0x00020000; + flags |= 0x00100000; /* ACCESSUS_USER_SYSTEM */ + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags |= 0x00030000; + flags |= 0x00100000; /* ACCESSUS_USER_SYSTEM */ + break; + default: + return -EINVAL; + } + + switch (dmaobj->access) { + case NV_MEM_ACCESS_VM: + break; + case NV_MEM_ACCESS_RO: + flags |= 0x00040000; + break; + case NV_MEM_ACCESS_WO: + case NV_MEM_ACCESS_RW: + flags |= 0x00080000; + break; + } + + ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj); + if (ret == 0) { + nv_wo32(*pgpuobj, 0x00, flags); + nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit)); + nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start)); + nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 | + upper_32_bits(dmaobj->start)); + nv_wo32(*pgpuobj, 0x10, 0x00000000); + nv_wo32(*pgpuobj, 0x14, 0x00000000); + } + + return ret; +} + +static int +nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_dmaeng *dmaeng = (void *)engine; + struct nv50_dmaobj_priv *dmaobj; + struct nouveau_gpuobj *gpuobj; + int ret; + + ret = nouveau_dmaobj_create(parent, engine, oclass, + data, size, &dmaobj); + *pobject = nv_object(dmaobj); + if (ret) + return ret; + + switch (nv_mclass(parent)) { + case 0x506f: + case 0x826f: + ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); + nouveau_object_ref(NULL, pobject); + *pobject = nv_object(gpuobj); + break; + default: + break; + } + + return ret; +} + +static struct nouveau_ofuncs +nv50_dmaobj_ofuncs = { + .ctor = nv50_dmaobj_ctor, + .dtor = _nouveau_dmaobj_dtor, + .init = _nouveau_dmaobj_init, + .fini = _nouveau_dmaobj_fini, +}; + +static struct nouveau_oclass +nv50_dmaobj_sclass[] = { + { 0x0002, &nv50_dmaobj_ofuncs }, + { 0x0003, &nv50_dmaobj_ofuncs }, + { 0x003d, &nv50_dmaobj_ofuncs }, + {} +}; + +static int +nv50_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_dmaeng_priv *priv; + int ret; + + ret = nouveau_dmaeng_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.sclass = nv50_dmaobj_sclass; + priv->base.bind = nv50_dmaobj_bind; + return 0; +} + +struct nouveau_oclass +nv50_dmaeng_oclass = { + .handle = NV_ENGINE(DMAOBJ, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_dmaeng_ctor, + .dtor = _nouveau_dmaeng_dtor, + .init = _nouveau_dmaeng_init, + .fini = _nouveau_dmaeng_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c new file mode 100644 index 0000000..5baa086 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c @@ -0,0 +1,99 @@ +/* + * 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: + * + * 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 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 + +#include +#include + +struct nvc0_dmaeng_priv { + struct nouveau_dmaeng base; +}; + +struct nvc0_dmaobj_priv { + struct nouveau_dmaobj base; +}; + +static int +nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_dmaobj_priv *dmaobj; + int ret; + + ret = nouveau_dmaobj_create(parent, engine, oclass, data, size, &dmaobj); + *pobject = nv_object(dmaobj); + if (ret) + return ret; + + if (dmaobj->base.target != NV_MEM_TARGET_VM || dmaobj->base.start) + return -EINVAL; + + return 0; +} + +static struct nouveau_ofuncs +nvc0_dmaobj_ofuncs = { + .ctor = nvc0_dmaobj_ctor, + .dtor = _nouveau_dmaobj_dtor, + .init = _nouveau_dmaobj_init, + .fini = _nouveau_dmaobj_fini, +}; + +static struct nouveau_oclass +nvc0_dmaobj_sclass[] = { + { 0x0002, &nvc0_dmaobj_ofuncs }, + { 0x0003, &nvc0_dmaobj_ofuncs }, + { 0x003d, &nvc0_dmaobj_ofuncs }, + {} +}; + +static int +nvc0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_dmaeng_priv *priv; + int ret; + + ret = nouveau_dmaeng_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.sclass = nvc0_dmaobj_sclass; + return 0; +} + +struct nouveau_oclass +nvc0_dmaeng_oclass = { + .handle = NV_ENGINE(DMAOBJ, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_dmaeng_ctor, + .dtor = _nouveau_dmaeng_dtor, + .init = _nouveau_dmaeng_init, + .fini = _nouveau_dmaeng_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c new file mode 100644 index 0000000..edeb76e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -0,0 +1,165 @@ +/* + * 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: + * + * 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 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 +#include + +#include +#include + +int +nouveau_fifo_channel_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int bar, u32 addr, u32 size, u32 pushbuf, + u32 engmask, int len, void **ptr) +{ + struct nouveau_device *device = nv_device(engine); + struct nouveau_fifo *priv = (void *)engine; + struct nouveau_fifo_chan *chan; + struct nouveau_dmaeng *dmaeng; + unsigned long flags; + int ret; + + /* create base object class */ + ret = nouveau_namedb_create_(parent, engine, oclass, 0, NULL, + engmask, len, ptr); + chan = *ptr; + if (ret) + return ret; + + /* validate dma object representing push buffer */ + chan->pushdma = (void *)nouveau_handle_ref(parent, pushbuf); + if (!chan->pushdma) + return -ENOENT; + + dmaeng = (void *)chan->pushdma->base.engine; + switch (chan->pushdma->base.oclass->handle) { + case 0x0002: + case 0x003d: + break; + default: + return -EINVAL; + } + + if (dmaeng->bind) { + ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu); + if (ret) + return ret; + } + + /* find a free fifo channel */ + spin_lock_irqsave(&priv->lock, flags); + for (chan->chid = priv->min; chan->chid < priv->max; chan->chid++) { + if (!priv->channel[chan->chid]) { + priv->channel[chan->chid] = nv_object(chan); + break; + } + } + spin_unlock_irqrestore(&priv->lock, flags); + + if (chan->chid == priv->max) { + nv_error(priv, "no free channels\n"); + return -ENOSPC; + } + + /* map fifo control registers */ + chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr + + (chan->chid * size), size); + if (!chan->user) + return -EFAULT; + + chan->size = size; + return 0; +} + +void +nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan) +{ + struct nouveau_fifo *priv = (void *)nv_object(chan)->engine; + unsigned long flags; + + iounmap(chan->user); + + spin_lock_irqsave(&priv->lock, flags); + priv->channel[chan->chid] = NULL; + spin_unlock_irqrestore(&priv->lock, flags); + + nouveau_gpuobj_ref(NULL, &chan->pushgpu); + nouveau_object_ref(NULL, (struct nouveau_object **)&chan->pushdma); + nouveau_namedb_destroy(&chan->base); +} + +void +_nouveau_fifo_channel_dtor(struct nouveau_object *object) +{ + struct nouveau_fifo_chan *chan = (void *)object; + nouveau_fifo_channel_destroy(chan); +} + +u32 +_nouveau_fifo_channel_rd32(struct nouveau_object *object, u32 addr) +{ + struct nouveau_fifo_chan *chan = (void *)object; + return ioread32_native(chan->user + addr); +} + +void +_nouveau_fifo_channel_wr32(struct nouveau_object *object, u32 addr, u32 data) +{ + struct nouveau_fifo_chan *chan = (void *)object; + iowrite32_native(data, chan->user + addr); +} + +void +nouveau_fifo_destroy(struct nouveau_fifo *priv) +{ + kfree(priv->channel); + nouveau_engine_destroy(&priv->base); +} + +int +nouveau_fifo_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, + int min, int max, int length, void **pobject) +{ + struct nouveau_fifo *priv; + int ret; + + ret = nouveau_engine_create_(parent, engine, oclass, true, "PFIFO", + "fifo", length, pobject); + priv = *pobject; + if (ret) + return ret; + + priv->min = min; + priv->max = max; + priv->channel = kzalloc(sizeof(*priv->channel) * (max + 1), GFP_KERNEL); + if (!priv->channel) + return -ENOMEM; + + spin_lock_init(&priv->lock); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index 6ab7eb0..8b7513f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -1,44 +1,45 @@ /* - * Copyright (C) 2012 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 -#include "nouveau_util.h" +#include +#include +#include +#include +#include #include -#include "nouveau_software.h" - -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv04_ramfc[] = { + +#include +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv04_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE }, @@ -50,283 +51,360 @@ static struct ramfc_desc { {} }; -struct nv04_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ -struct nv04_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; - -bool -nv04_fifo_cache_pull(struct drm_device *dev, bool enable) +int +nv04_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) { - int pull = nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 1, enable); - - if (!enable) { - /* In some cases the PFIFO puller may be left in an - * inconsistent state if you try to stop it when it's - * busy translating handles. Sometimes you get a - * PFIFO_CACHE_ERROR, sometimes it just fails silently - * sending incorrect instance offsets to PGRAPH after - * it's started up again. To avoid the latter we - * invalidate the most recently calculated instance. - */ - if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0, - NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0)) - NV_ERROR(dev, "Timeout idling the PFIFO puller.\n"); - - if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) & - NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) - nv_wr32(dev, NV03_PFIFO_INTR_0, - NV_PFIFO_INTR_CACHE_ERROR); - - nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; + u32 context, chid = chan->base.chid; + int ret; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->addr >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW: + context |= 0x00000000; + break; + case NVDEV_ENGINE_GR: + context |= 0x00010000; + break; + case NVDEV_ENGINE_MPEG: + context |= 0x00020000; + break; + default: + return -EINVAL; } - return pull & 1; + context |= 0x80000000; /* valid */ + context |= chid << 24; + + mutex_lock(&nv_subdev(priv)->mutex); + ret = nouveau_ramht_insert(priv->ramht, chid, handle, context); + mutex_unlock(&nv_subdev(priv)->mutex); + return ret; +} + +void +nv04_fifo_object_detach(struct nouveau_object *parent, int cookie) +{ + struct nv04_fifo_priv *priv = (void *)parent->engine; + mutex_lock(&nv_subdev(priv)->mutex); + nouveau_ramht_remove(priv->ramht, cookie); + mutex_unlock(&nv_subdev(priv)->mutex); } static int -nv04_fifo_context_new(struct nouveau_channel *chan, int engine) +nv04_fifo_chan_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 nv04_fifo_priv *priv = nv_engine(dev, engine); - struct nv04_fifo_chan *fctx; - unsigned long flags; + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; + if (size < sizeof(*args)) + return -EINVAL; - fctx->ramfc = chan->id * 32; + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, + 0x10000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; - } + nv_parent(chan)->object_attach = nv04_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 32; - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x08, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x10, + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + return 0; +} + +void +nv04_fifo_chan_dtor(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object->engine; + struct nv04_fifo_chan *chan = (void *)object; + struct ramfc_desc *c = priv->ramfc_desc; - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + do { + nv_wo32(priv->ramfc, chan->ramfc + c->ctxp, 0x00000000); + } while ((++c)->bits); + + nouveau_fifo_channel_destroy(&chan->base); +} -error: +int +nv04_fifo_chan_init(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object->engine; + struct nv04_fifo_chan *chan = (void *)object; + u32 mask = 1 << chan->base.chid; + unsigned long flags; + int ret; + + ret = nouveau_fifo_channel_init(&chan->base); if (ret) - priv->base.base.context_del(chan, engine); - return ret; + return ret; + + spin_lock_irqsave(&priv->base.lock, flags); + nv_mask(priv, NV04_PFIFO_MODE, mask, mask); + spin_unlock_irqrestore(&priv->base.lock, flags); + return 0; } -void -nv04_fifo_context_del(struct nouveau_channel *chan, int engine) +int +nv04_fifo_chan_fini(struct nouveau_object *object, bool suspend) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(chan->dev, engine); - struct nv04_fifo_chan *fctx = chan->engctx[engine]; - struct ramfc_desc *c = priv->ramfc_desc; + struct nv04_fifo_priv *priv = (void *)object->engine; + struct nv04_fifo_chan *chan = (void *)object; + struct nouveau_gpuobj *fctx = priv->ramfc; + struct ramfc_desc *c; unsigned long flags; - int chid; + u32 data = chan->ramfc; + u32 chid; /* prevent fifo context switches */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, NV03_PFIFO_CACHES, 0); + spin_lock_irqsave(&priv->base.lock, flags); + nv_wr32(priv, NV03_PFIFO_CACHES, 0); /* if this channel is active, replace it with a null context */ - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels; - if (chid == chan->id) { - nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); - nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max; + if (chid == chan->base.chid) { + nv_mask(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 0); + nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); + c = priv->ramfc_desc; do { - u32 mask = ((1ULL << c->bits) - 1) << c->regs; - nv_mask(dev, c->regp, mask, 0x00000000); - nv_wo32(priv->ramfc, fctx->ramfc + c->ctxp, 0x00000000); + u32 rm = ((1ULL << c->bits) - 1) << c->regs; + u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; + u32 rv = (nv_rd32(priv, c->regp) & rm) >> c->regs; + u32 cv = (nv_ro32(fctx, c->ctxp + data) & ~cm); + nv_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); + } while ((++c)->bits); + + c = priv->ramfc_desc; + do { + nv_wr32(priv, c->regp, 0x00000000); } while ((++c)->bits); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUT, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); } /* restore normal operation, after disabling dma mode */ - nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* clean up */ - nouveau_gpuobj_ref(NULL, &chan->ramfc); /*XXX: nv40 */ - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; - } + nv_mask(priv, NV04_PFIFO_MODE, 1 << chan->base.chid, 0); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); + spin_unlock_irqrestore(&priv->base.lock, flags); + + return nouveau_fifo_channel_fini(&chan->base, suspend); } +static struct nouveau_ofuncs +nv04_fifo_ofuncs = { + .ctor = nv04_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_oclass +nv04_fifo_sclass[] = { + { 0x006e, &nv04_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + int -nv04_fifo_init(struct drm_device *dev, int engine) +nv04_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nv04_fifo_base *base; + int ret; - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x1000, + 0x1000, NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff); - nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); + return 0; +} - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->addr >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); +static struct nouveau_oclass +nv04_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); +void +nv04_fifo_pause(struct nouveau_fifo *pfifo, unsigned long *pflags) +__acquires(priv->base.lock) +{ + struct nv04_fifo_priv *priv = (void *)pfifo; + unsigned long flags; - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); + spin_lock_irqsave(&priv->base.lock, flags); + *pflags = flags; + + nv_wr32(priv, NV03_PFIFO_CACHES, 0x00000000); + nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000000); + + /* in some cases the puller may be left in an inconsistent state + * if you try to stop it while it's busy translating handles. + * sometimes you get a CACHE_ERROR, sometimes it just fails + * silently; sending incorrect instance offsets to PGRAPH after + * it's started up again. + * + * to avoid this, we invalidate the most recently calculated + * instance. + */ + if (!nv_wait(priv, NV04_PFIFO_CACHE1_PULL0, + NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0x00000000)) + nv_warn(priv, "timeout idling puller\n"); + + if (nv_rd32(priv, NV04_PFIFO_CACHE1_PULL0) & + NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0x00000000); +} - for (i = 0; i < priv->base.channels; i++) { - if (dev_priv->channels.ptr[i]) - nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); - } +void +nv04_fifo_start(struct nouveau_fifo *pfifo, unsigned long *pflags) +__releases(priv->base.lock) +{ + struct nv04_fifo_priv *priv = (void *)pfifo; + unsigned long flags = *pflags; - return 0; + nv_mask(priv, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001); + nv_wr32(priv, NV03_PFIFO_CACHES, 0x00000001); + + spin_unlock_irqrestore(&priv->base.lock, flags); } -int -nv04_fifo_fini(struct drm_device *dev, int engine, bool suspend) +static const char * +nv_dma_state_err(u32 state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(dev, engine); - struct nouveau_channel *chan; - int chid; - - /* prevent context switches and halt fifo operation */ - nv_wr32(dev, NV03_PFIFO_CACHES, 0); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 0); - - /* store current fifo context in ramfc */ - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels; - chan = dev_priv->channels.ptr[chid]; - if (suspend && chid != priv->base.channels && chan) { - struct nv04_fifo_chan *fctx = chan->engctx[engine]; - struct nouveau_gpuobj *ctx = priv->ramfc; - struct ramfc_desc *c = priv->ramfc_desc; - do { - u32 rm = ((1ULL << c->bits) - 1) << c->regs; - u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; - u32 rv = (nv_rd32(dev, c->regp) & rm) >> c->regs; - u32 cv = (nv_ro32(ctx, c->ctxp + fctx->ramfc) & ~cm); - nv_wo32(ctx, c->ctxp + fctx->ramfc, cv | (rv << c->ctxs)); - } while ((++c)->bits); - } - - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0x00000000); - return 0; + static const char * const desc[] = { + "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", + "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" + }; + return desc[(state >> 29) & 0x7]; } static bool -nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) +nv04_fifo_swmthd(struct nv04_fifo_priv *priv, u32 chid, u32 addr, u32 data) { - struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; - struct nouveau_gpuobj *obj; - unsigned long flags; + struct nv04_fifo_chan *chan = NULL; + struct nouveau_handle *bind; const int subc = (addr >> 13) & 0x7; const int mthd = addr & 0x1ffc; bool handled = false; + unsigned long flags; u32 engine; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < pfifo->channels)) - chan = dev_priv->channels.ptr[chid]; + spin_lock_irqsave(&priv->base.lock, flags); + if (likely(chid >= priv->base.min && chid <= priv->base.max)) + chan = (void *)priv->base.channel[chid]; if (unlikely(!chan)) goto out; switch (mthd) { - case 0x0000: /* bind object to subchannel */ - obj = nouveau_ramht_find(chan, data); - if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW)) + case 0x0000: + bind = nouveau_namedb_get(nv_namedb(chan), data); + if (unlikely(!bind)) break; - engine = 0x0000000f << (subc * 4); + if (nv_engidx(bind->object->engine) == NVDEV_ENGINE_SW) { + engine = 0x0000000f << (subc * 4); + chan->subc[subc] = data; + handled = true; + + nv_mask(priv, NV04_PFIFO_CACHE1_ENGINE, engine, 0); + } - nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); - handled = true; + nouveau_namedb_put(bind); break; default: - engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE); + engine = nv_rd32(priv, NV04_PFIFO_CACHE1_ENGINE); if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) break; - if (!nouveau_gpuobj_mthd_call(chan, nouveau_software_class(dev), - mthd, data)) - handled = true; + bind = nouveau_namedb_get(nv_namedb(chan), chan->subc[subc]); + if (likely(bind)) { + if (!nv_call(bind->object, mthd, data)) + handled = true; + nouveau_namedb_put(bind); + } break; } out: - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + spin_unlock_irqrestore(&priv->base.lock, flags); return handled; } -static const char *nv_dma_state_err(u32 state) -{ - static const char * const desc[] = { - "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", - "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" - }; - return desc[(state >> 29) & 0x7]; -} - void -nv04_fifo_isr(struct drm_device *dev) +nv04_fifo_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_device *device = nv_device(subdev); + struct nv04_fifo_priv *priv = (void *)subdev; uint32_t status, reassign; int cnt = 0; - reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; - while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { + reassign = nv_rd32(priv, NV03_PFIFO_CACHES) & 1; + while ((status = nv_rd32(priv, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { uint32_t chid, get; - nv_wr32(dev, NV03_PFIFO_CACHES, 0); + nv_wr32(priv, NV03_PFIFO_CACHES, 0); - chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & pfifo->channels; - get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); + chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max; + get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET); if (status & NV_PFIFO_INTR_CACHE_ERROR) { uint32_t mthd, data; @@ -340,86 +418,85 @@ nv04_fifo_isr(struct drm_device *dev) */ ptr = (get & 0x7ff) >> 2; - if (dev_priv->card_type < NV_40) { - mthd = nv_rd32(dev, + if (device->card_type < NV_40) { + mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(dev, + data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr)); } else { - mthd = nv_rd32(dev, + mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(dev, + data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr)); } - if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) { - NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " - "Mthd 0x%04x Data 0x%08x\n", + if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { + nv_info(priv, "CACHE_ERROR - Ch %d/%d " + "Mthd 0x%04x Data 0x%08x\n", chid, (mthd >> 13) & 7, mthd & 0x1ffc, data); } - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(dev, NV03_PFIFO_INTR_0, + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, - nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, + nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); status &= ~NV_PFIFO_INTR_CACHE_ERROR; } if (status & NV_PFIFO_INTR_DMA_PUSHER) { - u32 dma_get = nv_rd32(dev, 0x003244); - u32 dma_put = nv_rd32(dev, 0x003240); - u32 push = nv_rd32(dev, 0x003220); - u32 state = nv_rd32(dev, 0x003228); - - if (dev_priv->card_type == NV_50) { - u32 ho_get = nv_rd32(dev, 0x003328); - u32 ho_put = nv_rd32(dev, 0x003320); - u32 ib_get = nv_rd32(dev, 0x003334); - u32 ib_put = nv_rd32(dev, 0x003330); - - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " - "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " - "State 0x%08x (err: %s) Push 0x%08x\n", - chid, ho_get, dma_get, ho_put, - dma_put, ib_get, ib_put, state, - nv_dma_state_err(state), - push); + u32 dma_get = nv_rd32(priv, 0x003244); + u32 dma_put = nv_rd32(priv, 0x003240); + u32 push = nv_rd32(priv, 0x003220); + u32 state = nv_rd32(priv, 0x003228); + + if (device->card_type == NV_50) { + u32 ho_get = nv_rd32(priv, 0x003328); + u32 ho_put = nv_rd32(priv, 0x003320); + u32 ib_get = nv_rd32(priv, 0x003334); + u32 ib_put = nv_rd32(priv, 0x003330); + + nv_info(priv, "DMA_PUSHER - Ch %d Get 0x%02x%08x " + "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " + "State 0x%08x (err: %s) Push 0x%08x\n", + chid, ho_get, dma_get, ho_put, + dma_put, ib_get, ib_put, state, + nv_dma_state_err(state), + push); /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ - nv_wr32(dev, 0x003364, 0x00000000); + nv_wr32(priv, 0x003364, 0x00000000); if (dma_get != dma_put || ho_get != ho_put) { - nv_wr32(dev, 0x003244, dma_put); - nv_wr32(dev, 0x003328, ho_put); + nv_wr32(priv, 0x003244, dma_put); + nv_wr32(priv, 0x003328, ho_put); } else if (ib_get != ib_put) { - nv_wr32(dev, 0x003334, ib_put); + nv_wr32(priv, 0x003334, ib_put); } } else { - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " + nv_info(priv, "DMA_PUSHER - Ch %d Get 0x%08x " "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", chid, dma_get, dma_put, state, nv_dma_state_err(state), push); if (dma_get != dma_put) - nv_wr32(dev, 0x003244, dma_put); + nv_wr32(priv, 0x003244, dma_put); } - nv_wr32(dev, 0x003228, 0x00000000); - nv_wr32(dev, 0x003220, 0x00000001); - nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); + nv_wr32(priv, 0x003228, 0x00000000); + nv_wr32(priv, 0x003220, 0x00000001); + nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); status &= ~NV_PFIFO_INTR_DMA_PUSHER; } @@ -427,81 +504,118 @@ nv04_fifo_isr(struct drm_device *dev) uint32_t sem; status &= ~NV_PFIFO_INTR_SEMAPHORE; - nv_wr32(dev, NV03_PFIFO_INTR_0, + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_SEMAPHORE); - sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); - nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); + sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE); + nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); } - if (dev_priv->card_type == NV_50) { + if (device->card_type == NV_50) { if (status & 0x00000010) { - nv50_fb_vm_trap(dev, nouveau_ratelimit()); + nv50_fb_trap(nouveau_fb(priv), 1); status &= ~0x00000010; - nv_wr32(dev, 0x002100, 0x00000010); + nv_wr32(priv, 0x002100, 0x00000010); } } if (status) { - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", - status, chid); - nv_wr32(dev, NV03_PFIFO_INTR_0, status); + nv_info(priv, "unknown intr 0x%08x, ch %d\n", + status, chid); + nv_wr32(priv, NV03_PFIFO_INTR_0, status); status = 0; } - nv_wr32(dev, NV03_PFIFO_CACHES, reassign); + nv_wr32(priv, NV03_PFIFO_CACHES, reassign); } if (status) { - NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); - nv_wr32(dev, 0x2140, 0); - nv_wr32(dev, 0x140, 0); + nv_info(priv, "still angry after %d spins, halt\n", cnt); + nv_wr32(priv, 0x002140, 0); + nv_wr32(priv, 0x000140, 0); } - nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); + nv_wr32(priv, 0x000100, 0x00000100); } -void -nv04_fifo_destroy(struct drm_device *dev, int engine) +static int +nv04_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv = nv_engine(dev, engine); + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; - nouveau_irq_unregister(dev, 8); + ret = nouveau_fifo_create(parent, engine, oclass, 0, 15, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv04_fifo_cclass; + nv_engine(priv)->sclass = nv04_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv04_ramfc; + return 0; +} +void +nv04_fifo_dtor(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object; nouveau_gpuobj_ref(NULL, &priv->ramfc); nouveau_gpuobj_ref(NULL, &priv->ramro); - - dev_priv->eng[engine] = NULL; - kfree(priv); + nouveau_ramht_ref(NULL, &priv->ramht); + nouveau_fifo_destroy(&priv->base); } int -nv04_fifo_create(struct drm_device *dev) +nv04_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv04_fifo_priv *priv; + struct nv04_fifo_priv *priv = (void *)object; + int ret; + + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff); + nv_wr32(priv, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); + nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((priv->ramht->bits - 9) << 16) | + (priv->ramht->base.addr >> 8)); + nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8); - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv04_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv04_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 15; - priv->ramfc_desc = nv04_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - nouveau_irq_register(dev, 8, nv04_fifo_isr); + nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); return 0; } + +struct nouveau_oclass +nv04_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv04_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h new file mode 100644 index 0000000..496a4b4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h @@ -0,0 +1,178 @@ +#ifndef __NV04_FIFO_H__ +#define __NV04_FIFO_H__ + +#include + +#define NV04_PFIFO_DELAY_0 0x00002040 +#define NV04_PFIFO_DMA_TIMESLICE 0x00002044 +#define NV04_PFIFO_NEXT_CHANNEL 0x00002050 +#define NV03_PFIFO_INTR_0 0x00002100 +#define NV03_PFIFO_INTR_EN_0 0x00002140 +# define NV_PFIFO_INTR_CACHE_ERROR (1<<0) +# define NV_PFIFO_INTR_RUNOUT (1<<4) +# define NV_PFIFO_INTR_RUNOUT_OVERFLOW (1<<8) +# define NV_PFIFO_INTR_DMA_PUSHER (1<<12) +# define NV_PFIFO_INTR_DMA_PT (1<<16) +# define NV_PFIFO_INTR_SEMAPHORE (1<<20) +# define NV_PFIFO_INTR_ACQUIRE_TIMEOUT (1<<24) +#define NV03_PFIFO_RAMHT 0x00002210 +#define NV03_PFIFO_RAMFC 0x00002214 +#define NV03_PFIFO_RAMRO 0x00002218 +#define NV40_PFIFO_RAMFC 0x00002220 +#define NV03_PFIFO_CACHES 0x00002500 +#define NV04_PFIFO_MODE 0x00002504 +#define NV04_PFIFO_DMA 0x00002508 +#define NV04_PFIFO_SIZE 0x0000250c +#define NV50_PFIFO_CTX_TABLE(c) (0x2600+(c)*4) +#define NV50_PFIFO_CTX_TABLE__SIZE 128 +#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED (1<<31) +#define NV50_PFIFO_CTX_TABLE_UNK30_BAD (1<<30) +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 0x0FFFFFFF +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 0x00FFFFFF +#define NV03_PFIFO_CACHE0_PUSH0 0x00003000 +#define NV03_PFIFO_CACHE0_PULL0 0x00003040 +#define NV04_PFIFO_CACHE0_PULL0 0x00003050 +#define NV04_PFIFO_CACHE0_PULL1 0x00003054 +#define NV03_PFIFO_CACHE1_PUSH0 0x00003200 +#define NV03_PFIFO_CACHE1_PUSH1 0x00003204 +#define NV03_PFIFO_CACHE1_PUSH1_DMA (1<<8) +#define NV40_PFIFO_CACHE1_PUSH1_DMA (1<<16) +#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000000f +#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000001f +#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000007f +#define NV03_PFIFO_CACHE1_PUT 0x00003210 +#define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 +#define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000008 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000010 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000018 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000020 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000028 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000030 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000038 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000040 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000048 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x00000050 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x00000058 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x00000060 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x00000068 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x00000070 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x00000078 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000080 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000088 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000090 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000098 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x000000A0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x000000A8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x000000B0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x000000B8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x000000C0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x000000C8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x000000D0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x000000D8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x000000E0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x000000E8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x000000F0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x000000F8 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00002000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00004000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00006000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00008000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x0000A000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x0000C000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00010000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00020000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00030000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00040000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00050000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00060000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00070000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00080000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00090000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x000A0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x000B0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x000C0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x000D0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x000E0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x000F0000 +# define NV_PFIFO_CACHE1_ENDIAN 0x80000000 +# define NV_PFIFO_CACHE1_LITTLE_ENDIAN 0x7FFFFFFF +# define NV_PFIFO_CACHE1_BIG_ENDIAN 0x80000000 +#define NV04_PFIFO_CACHE1_DMA_STATE 0x00003228 +#define NV04_PFIFO_CACHE1_DMA_INSTANCE 0x0000322c +#define NV04_PFIFO_CACHE1_DMA_CTL 0x00003230 +#define NV04_PFIFO_CACHE1_DMA_PUT 0x00003240 +#define NV04_PFIFO_CACHE1_DMA_GET 0x00003244 +#define NV10_PFIFO_CACHE1_REF_CNT 0x00003248 +#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C +#define NV03_PFIFO_CACHE1_PULL0 0x00003240 +#define NV04_PFIFO_CACHE1_PULL0 0x00003250 +# define NV04_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000010 +# define NV04_PFIFO_CACHE1_PULL0_HASH_BUSY 0x00001000 +#define NV03_PFIFO_CACHE1_PULL1 0x00003250 +#define NV04_PFIFO_CACHE1_PULL1 0x00003254 +#define NV04_PFIFO_CACHE1_HASH 0x00003258 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT 0x00003260 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP 0x00003264 +#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE 0x00003268 +#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C +#define NV03_PFIFO_CACHE1_GET 0x00003270 +#define NV04_PFIFO_CACHE1_ENGINE 0x00003280 +#define NV04_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0 +#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0 +#define NV40_PFIFO_UNK32E4 0x000032E4 +#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8)) +#define NV04_PFIFO_CACHE1_DATA(i) (0x00003804+(i*8)) +#define NV40_PFIFO_CACHE1_METHOD(i) (0x00090000+(i*8)) +#define NV40_PFIFO_CACHE1_DATA(i) (0x00090004+(i*8)) + +struct ramfc_desc { + unsigned bits:6; + unsigned ctxs:5; + unsigned ctxp:8; + unsigned regs:5; + unsigned regp; +}; + +struct nv04_fifo_priv { + struct nouveau_fifo base; + struct ramfc_desc *ramfc_desc; + struct nouveau_ramht *ramht; + struct nouveau_gpuobj *ramro; + struct nouveau_gpuobj *ramfc; +}; + +struct nv04_fifo_base { + struct nouveau_fifo_base base; +}; + +struct nv04_fifo_chan { + struct nouveau_fifo_chan base; + u32 subc[8]; + u32 ramfc; +}; + +int nv04_fifo_object_attach(struct nouveau_object *, + struct nouveau_object *, u32); +void nv04_fifo_object_detach(struct nouveau_object *, int); + +void nv04_fifo_chan_dtor(struct nouveau_object *); +int nv04_fifo_chan_init(struct nouveau_object *); +int nv04_fifo_chan_fini(struct nouveau_object *, bool suspend); + +int nv04_fifo_context_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); + +void nv04_fifo_dtor(struct nouveau_object *); +int nv04_fifo_init(struct nouveau_object *); +void nv04_fifo_pause(struct nouveau_fifo *, unsigned long *); +void nv04_fifo_start(struct nouveau_fifo *, unsigned long *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 2d38fa8..391fefa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -1,43 +1,42 @@ /* - * Copyright (C) 2012 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 -#include "nouveau_util.h" +#include +#include +#include #include -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv10_ramfc[] = { +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv10_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -50,87 +49,122 @@ static struct ramfc_desc { {} }; -struct nv10_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; - -struct nv10_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ static int -nv10_fifo_context_new(struct nouveau_channel *chan, int engine) +nv10_fifo_chan_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 nv10_fifo_priv *priv = nv_engine(dev, engine); - struct nv10_fifo_chan *fctx; - unsigned long flags; + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - fctx->ramfc = chan->id * 32; - - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; - } - - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x14, + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, + 0x10000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->object_attach = nv04_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 32; + + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + return 0; +} - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +static struct nouveau_ofuncs +nv10_fifo_ofuncs = { + .ctor = nv10_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; -} +static struct nouveau_oclass +nv10_fifo_sclass[] = { + { 0x006e, &nv10_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + +static struct nouveau_oclass +nv10_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ -int -nv10_fifo_create(struct drm_device *dev) +static int +nv10_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv10_fifo_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); - - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv04_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv10_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 31; - priv->ramfc_desc = nv10_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; - nouveau_irq_register(dev, 8, nv04_fifo_isr); + ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv10_fifo_cclass; + nv_engine(priv)->sclass = nv10_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv10_ramfc; return 0; } + +struct nouveau_oclass +nv10_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv04_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 2f700a15e..3b9d6c9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -1,43 +1,42 @@ /* - * Copyright (C) 2012 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 -#include "nouveau_util.h" +#include +#include +#include #include -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv17_ramfc[] = { +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv17_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -55,124 +54,154 @@ static struct ramfc_desc { {} }; -struct nv17_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; - -struct nv17_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ static int -nv17_fifo_context_new(struct nouveau_channel *chan, int engine) +nv17_fifo_chan_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 nv17_fifo_priv *priv = nv_engine(dev, engine); - struct nv17_fifo_chan *fctx; - unsigned long flags; + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - fctx->ramfc = chan->id * 64; - - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; - } - - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x14, + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, + 0x10000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), /* NV31- */ + &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->object_attach = nv04_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 64; + + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); + return 0; +} - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +static struct nouveau_ofuncs +nv17_fifo_ofuncs = { + .ctor = nv17_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; -} +static struct nouveau_oclass +nv17_fifo_sclass[] = { + { 0x006e, &nv17_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + +static struct nouveau_oclass +nv17_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x17), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ static int -nv17_fifo_init(struct drm_device *dev, int engine) +nv17_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv17_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv17_fifo_cclass; + nv_engine(priv)->sclass = nv17_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv17_ramfc; + return 0; +} - nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff); - nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); +static int +nv17_fifo_init(struct nouveau_object *object) +{ + struct nv04_fifo_priv *priv = (void *)object; + int ret; - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->addr >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 | - priv->ramfc->addr >> 8); + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff); + nv_wr32(priv, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff); - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((priv->ramht->bits - 9) << 16) | + (priv->ramht->base.addr >> 8)); + nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8 | 0x00010000); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - for (i = 0; i < priv->base.channels; i++) { - if (dev_priv->channels.ptr[i]) - nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); - } + nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); return 0; } -int -nv17_fifo_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv17_fifo_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); - - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv17_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv17_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 31; - priv->ramfc_desc = nv17_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - nouveau_irq_register(dev, 8, nv04_fifo_isr); - return 0; -} +struct nouveau_oclass +nv17_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x17), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv17_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv17_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 65a670f..43d5c9e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -1,43 +1,42 @@ /* - * Copyright (C) 2012 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 -#include "nouveau_util.h" +#include +#include +#include #include -static struct ramfc_desc { - unsigned bits:6; - unsigned ctxs:5; - unsigned ctxp:8; - unsigned regs:5; - unsigned regp; -} nv40_ramfc[] = { +#include +#include +#include + +#include + +#include "nv04.h" + +static struct ramfc_desc +nv40_ramfc[] = { { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT }, { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET }, { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT }, @@ -63,148 +62,287 @@ static struct ramfc_desc { {} }; -struct nv40_fifo_priv { - struct nouveau_fifo_priv base; - struct ramfc_desc *ramfc_desc; - struct nouveau_gpuobj *ramro; - struct nouveau_gpuobj *ramfc; -}; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ -struct nv40_fifo_chan { - struct nouveau_fifo_chan base; - u32 ramfc; -}; +static int +nv40_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) +{ + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; + u32 context, chid = chan->base.chid; + int ret; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->addr >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW: + context |= 0x00000000; + break; + case NVDEV_ENGINE_GR: + context |= 0x00100000; + break; + case NVDEV_ENGINE_MPEG: + context |= 0x00200000; + break; + default: + return -EINVAL; + } + + context |= chid << 23; + + mutex_lock(&nv_subdev(priv)->mutex); + ret = nouveau_ramht_insert(priv->ramht, chid, handle, context); + mutex_unlock(&nv_subdev(priv)->mutex); + return ret; +} static int -nv40_fifo_context_new(struct nouveau_channel *chan, int engine) +nv40_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *engctx) { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv40_fifo_priv *priv = nv_engine(dev, engine); - struct nv40_fifo_chan *fctx; + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; unsigned long flags; - int ret; + u32 reg, ctx; + + switch (nv_engidx(engctx->engine)) { + case NVDEV_ENGINE_SW: + return 0; + case NVDEV_ENGINE_GR: + reg = 0x32e0; + ctx = 0x38; + break; + case NVDEV_ENGINE_MPEG: + reg = 0x330c; + ctx = 0x54; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&priv->base.lock, flags); + nv_mask(priv, 0x002500, 0x00000001, 0x00000000); - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; + if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) + nv_wr32(priv, reg, nv_gpuobj(engctx)->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + ctx, nv_gpuobj(engctx)->addr >> 4); + + nv_mask(priv, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->base.lock, flags); + return 0; +} - fctx->ramfc = chan->id * 128; +static int +nv40_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *engctx) +{ + struct nv04_fifo_priv *priv = (void *)parent->engine; + struct nv04_fifo_chan *chan = (void *)parent; + unsigned long flags; + u32 reg, ctx; - /* map channel control registers */ - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV03_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; + switch (nv_engidx(engctx->engine)) { + case NVDEV_ENGINE_SW: + return 0; + case NVDEV_ENGINE_GR: + reg = 0x32e0; + ctx = 0x38; + break; + case NVDEV_ENGINE_MPEG: + reg = 0x330c; + ctx = 0x54; + break; + default: + return -EINVAL; } - /* initialise default fifo context */ - nv_wo32(priv->ramfc, fctx->ramfc + 0x00, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x04, chan->pushbuf_base); - nv_wo32(priv->ramfc, fctx->ramfc + 0x0c, chan->pushbuf->addr >> 4); - nv_wo32(priv->ramfc, fctx->ramfc + 0x18, 0x30000000 | + spin_lock_irqsave(&priv->base.lock, flags); + nv_mask(priv, 0x002500, 0x00000001, 0x00000000); + + if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) + nv_wr32(priv, reg, 0x00000000); + nv_wo32(priv->ramfc, chan->ramfc + ctx, 0x00000000); + + nv_mask(priv, 0x002500, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&priv->base.lock, flags); + return 0; +} + +static int +nv40_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_fifo_priv *priv = (void *)engine; + struct nv04_fifo_chan *chan; + struct nv_channel_dma_class *args = data; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x1000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nv40_fifo_context_attach; + nv_parent(chan)->context_detach = nv40_fifo_context_detach; + nv_parent(chan)->object_attach = nv40_fifo_object_attach; + nv_parent(chan)->object_detach = nv04_fifo_object_detach; + chan->ramfc = chan->base.chid * 128; + + nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); + nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); + nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | #ifdef __BIG_ENDIAN NV_PFIFO_CACHE1_BIG_ENDIAN | #endif NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8); - nv_wo32(priv->ramfc, fctx->ramfc + 0x3c, 0x0001ffff); + nv_wo32(priv->ramfc, chan->ramfc + 0x3c, 0x0001ffff); + return 0; +} + +static struct nouveau_ofuncs +nv40_fifo_ofuncs = { + .ctor = nv40_fifo_chan_ctor, + .dtor = nv04_fifo_chan_dtor, + .init = nv04_fifo_chan_init, + .fini = nv04_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_oclass +nv40_fifo_sclass[] = { + { 0x006e, &nv40_fifo_ofuncs }, + {} +}; - /* enable dma mode on the channel */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id)); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ - /*XXX: remove this later, need fifo engine context commit hook */ - nouveau_gpuobj_ref(priv->ramfc, &chan->ramfc); +static struct nouveau_oclass +nv40_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_fifo_context_ctor, + .dtor = _nouveau_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; -error: +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ + +static int +nv40_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_instmem_priv *imem = nv04_instmem(parent); + struct nv04_fifo_priv *priv; + int ret; + + ret = nouveau_fifo_create(parent, engine, oclass, 0, 31, &priv); + *pobject = nv_object(priv); if (ret) - priv->base.base.context_del(chan, engine); - return ret; + return ret; + + nouveau_ramht_ref(imem->ramht, &priv->ramht); + nouveau_gpuobj_ref(imem->ramro, &priv->ramro); + nouveau_gpuobj_ref(imem->ramfc, &priv->ramfc); + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv40_fifo_cclass; + nv_engine(priv)->sclass = nv40_fifo_sclass; + priv->base.pause = nv04_fifo_pause; + priv->base.start = nv04_fifo_start; + priv->ramfc_desc = nv40_ramfc; + return 0; } static int -nv40_fifo_init(struct drm_device *dev, int engine) +nv40_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv40_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nv04_fifo_priv *priv = (void *)object; + struct nouveau_fb *pfb = nouveau_fb(object); + int ret; - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0); - nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO); + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - nv_wr32(dev, 0x002040, 0x000000ff); - nv_wr32(dev, 0x002044, 0x2101ffff); - nv_wr32(dev, 0x002058, 0x00000001); + nv_wr32(priv, 0x002040, 0x000000ff); + nv_wr32(priv, 0x002044, 0x2101ffff); + nv_wr32(priv, 0x002058, 0x00000001); - nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | - ((dev_priv->ramht->bits - 9) << 16) | - (dev_priv->ramht->gpuobj->addr >> 8)); - nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); + nv_wr32(priv, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | + ((priv->ramht->bits - 9) << 16) | + (priv->ramht->base.addr >> 8)); + nv_wr32(priv, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8); - switch (dev_priv->chipset) { + switch (nv_device(priv)->chipset) { case 0x47: case 0x49: case 0x4b: - nv_wr32(dev, 0x002230, 0x00000001); + nv_wr32(priv, 0x002230, 0x00000001); case 0x40: case 0x41: case 0x42: case 0x43: case 0x45: case 0x48: - nv_wr32(dev, 0x002220, 0x00030002); + nv_wr32(priv, 0x002220, 0x00030002); break; default: - nv_wr32(dev, 0x002230, 0x00000000); - nv_wr32(dev, 0x002220, ((nvfb_vram_size(dev) - 512 * 1024 + + nv_wr32(priv, 0x002230, 0x00000000); + nv_wr32(priv, 0x002220, ((pfb->ram.size - 512 * 1024 + priv->ramfc->addr) >> 16) | - 0x00030000); + 0x00030000); break; } - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH1, priv->base.max); - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff); - - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - nv_wr32(dev, NV03_PFIFO_CACHES, 1); - - for (i = 0; i < priv->base.channels; i++) { - if (dev_priv->channels.ptr[i]) - nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i)); - } + nv_wr32(priv, NV03_PFIFO_INTR_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_INTR_EN_0, 0xffffffff); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + nv_wr32(priv, NV03_PFIFO_CACHES, 1); return 0; } -int -nv40_fifo_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv40_fifo_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_gpuobj_ref(nvimem_ramro(dev), &priv->ramro); - nouveau_gpuobj_ref(nvimem_ramfc(dev), &priv->ramfc); - - priv->base.base.destroy = nv04_fifo_destroy; - priv->base.base.init = nv40_fifo_init; - priv->base.base.fini = nv04_fifo_fini; - priv->base.base.context_new = nv40_fifo_context_new; - priv->base.base.context_del = nv04_fifo_context_del; - priv->base.channels = 31; - priv->ramfc_desc = nv40_ramfc; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - nouveau_irq_register(dev, 8, nv04_fifo_isr); - return 0; -} +struct nouveau_oclass +nv40_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_fifo_ctor, + .dtor = nv04_fifo_dtor, + .init = nv40_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 7b5b159..4914c3b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -1,126 +1,123 @@ /* - * Copyright (C) 2012 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 +#include +#include #include +#include +#include -struct nv50_fifo_priv { - struct nouveau_fifo_priv base; - struct nouveau_gpuobj *playlist[2]; - int cur_playlist; -}; +#include +#include -struct nv50_fifo_chan { - struct nouveau_fifo_chan base; -}; +#include +#include + +#include "nv50.h" + +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ void -nv50_fifo_playlist_update(struct drm_device *dev) +nv50_fifo_playlist_update(struct nv50_fifo_priv *priv) { - struct nv50_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nouveau_bar *bar = nouveau_bar(priv); struct nouveau_gpuobj *cur; int i, p; cur = priv->playlist[priv->cur_playlist]; priv->cur_playlist = !priv->cur_playlist; - for (i = 0, p = 0; i < priv->base.channels; i++) { - if (nv_rd32(dev, 0x002600 + (i * 4)) & 0x80000000) + for (i = priv->base.min, p = 0; i < priv->base.max; i++) { + if (nv_rd32(priv, 0x002600 + (i * 4)) & 0x80000000) nv_wo32(cur, p++ * 4, i); } - nvimem_flush(dev); + bar->flush(bar); - nv_wr32(dev, 0x0032f4, cur->addr >> 12); - nv_wr32(dev, 0x0032ec, p); - nv_wr32(dev, 0x002500, 0x00000101); + nv_wr32(priv, 0x0032f4, cur->addr >> 12); + nv_wr32(priv, 0x0032ec, p); + nv_wr32(priv, 0x002500, 0x00000101); } static int -nv50_fifo_context_new(struct nouveau_channel *chan, int engine) +nv50_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct nv50_fifo_priv *priv = nv_engine(chan->dev, engine); - struct nv50_fifo_chan *fctx; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; - u64 instance = chan->ramin->addr >> 12; - unsigned long flags; - int ret = 0, i; - - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - nvvm_engref(chan->vm, engine, 1); - - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV50_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent->parent; + struct nouveau_gpuobj *ectx = (void *)object; + u64 limit = ectx->addr + ectx->size - 1; + u64 start = ectx->addr; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0000; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + default: + return -EINVAL; } - for (i = 0; i < 0x100; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x3c, 0x403f6078); - nv_wo32(chan->ramin, 0x40, 0x00000000); - nv_wo32(chan->ramin, 0x44, 0x01003fff); - nv_wo32(chan->ramin, 0x48, chan->pushbuf->node->offset >> 4); - nv_wo32(chan->ramin, 0x50, lower_32_bits(ib_offset)); - nv_wo32(chan->ramin, 0x54, upper_32_bits(ib_offset) | - drm_order(chan->dma.ib_max + 1) << 16); - nv_wo32(chan->ramin, 0x60, 0x7fffffff); - nv_wo32(chan->ramin, 0x78, 0x00000000); - nv_wo32(chan->ramin, 0x7c, 0x30000001); - nv_wo32(chan->ramin, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->node->offset >> 4)); - - nvimem_flush(dev); - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); - nv50_fifo_playlist_update(dev); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; + nv_wo32(base->eng, addr + 0x00, 0x00190000); + nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); + nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); + nv_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); + return 0; } -static bool -nv50_fifo_kickoff(struct nouveau_channel *chan) +static int +nv50_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - bool done = true; - u32 me; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_priv *priv = (void *)parent->engine; + struct nv50_fifo_base *base = (void *)parent->parent; + struct nv50_fifo_chan *chan = (void *)parent; + u32 addr, me; + int ret = 0; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0000; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + default: + return -EINVAL; + } + + nv_wo32(base->eng, addr + 0x00, 0x00000000); + nv_wo32(base->eng, addr + 0x04, 0x00000000); + nv_wo32(base->eng, addr + 0x08, 0x00000000); + nv_wo32(base->eng, addr + 0x0c, 0x00000000); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); /* HW bug workaround: * @@ -134,159 +131,308 @@ nv50_fifo_kickoff(struct nouveau_channel *chan) * there's also a "ignore these engines" bitmask reg we can use * if we hit the issue there.. */ - - /* PME: make sure engine is enabled */ - me = nv_mask(dev, 0x00b860, 0x00000001, 0x00000001); + me = nv_mask(priv, 0x00b860, 0x00000001, 0x00000001); /* do the kickoff... */ - nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); - if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { - NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); - done = false; + nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); + if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { + nv_error(priv, "channel %d unload timeout\n", chan->base.chid); + if (suspend) + ret = -EBUSY; } - /* restore any engine states we changed, and exit */ - nv_wr32(dev, 0x00b860, me); - return done; + nv_wr32(priv, 0x00b860, me); + return ret; } -static void -nv50_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nv50_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) { - struct nv50_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - - /* remove channel from playlist, will context switch if active */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); - nv50_fifo_playlist_update(dev); - - /* tell any engines on this channel to unload their contexts */ - nv50_fifo_kickoff(chan); - - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* clean up */ - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; + struct nv50_fifo_chan *chan = (void *)parent; + u32 context; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->node->offset >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW : context |= 0x00000000; break; + case NVDEV_ENGINE_GR : context |= 0x00100000; break; + case NVDEV_ENGINE_MPEG : context |= 0x00200000; break; + default: + return -EINVAL; } - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; - kfree(fctx); + return nouveau_ramht_insert(chan->ramht, 0, handle, context); +} + +void +nv50_fifo_object_detach(struct nouveau_object *parent, int cookie) +{ + struct nv50_fifo_chan *chan = (void *)parent; + nouveau_ramht_remove(chan->ramht, cookie); } static int -nv50_fifo_init(struct drm_device *dev, int engine) +nv50_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 instance; - int i; - - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x00250c, 0x6f3cfc34); - nv_wr32(dev, 0x002044, 0x01003fff); - - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - - for (i = 0; i < 128; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan && chan->engctx[engine]) - instance = 0x80000000 | chan->ramin->addr >> 12; - else - instance = 0x00000000; - nv_wr32(dev, 0x002600 + (i * 4), instance); - } + struct nv_channel_ind_class *args = data; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent; + struct nv50_fifo_chan *chan; + u64 ioffset, ilength; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x2000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; - nv50_fifo_playlist_update(dev); + nv_parent(chan)->context_attach = nv50_fifo_context_attach; + nv_parent(chan)->context_detach = nv50_fifo_context_detach; + nv_parent(chan)->object_attach = nv50_fifo_object_attach; + nv_parent(chan)->object_detach = nv50_fifo_object_detach; - nv_wr32(dev, 0x003200, 1); - nv_wr32(dev, 0x003250, 1); - nv_wr32(dev, 0x002500, 1); + ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht); + if (ret) + return ret; + + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + nv_wo32(base->ramfc, 0x3c, 0x403f6078); + nv_wo32(base->ramfc, 0x44, 0x01003fff); + nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); + nv_wo32(base->ramfc, 0x50, lower_32_bits(ioffset)); + nv_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base->ramfc, 0x60, 0x7fffffff); + nv_wo32(base->ramfc, 0x78, 0x00000000); + nv_wo32(base->ramfc, 0x7c, 0x30000001); + nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->base.node->offset >> 4)); + bar->flush(bar); return 0; } +void +nv50_fifo_chan_dtor(struct nouveau_object *object) +{ + struct nv50_fifo_chan *chan = (void *)object; + nouveau_ramht_ref(NULL, &chan->ramht); + nouveau_fifo_channel_destroy(&chan->base); +} + static int -nv50_fifo_fini(struct drm_device *dev, int engine, bool suspend) +nv50_fifo_chan_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_fifo_priv *priv = nv_engine(dev, engine); - int i; - - /* set playlist length to zero, fifo will unload context */ - nv_wr32(dev, 0x0032ec, 0); - - /* tell all connected engines to unload their contexts */ - for (i = 0; i < priv->base.channels; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan && !nv50_fifo_kickoff(chan)) - return -EBUSY; - } + struct nv50_fifo_priv *priv = (void *)object->engine; + struct nv50_fifo_base *base = (void *)object->parent; + struct nv50_fifo_chan *chan = (void *)object; + struct nouveau_gpuobj *ramfc = base->ramfc; + u32 chid = chan->base.chid; + int ret; - nv_wr32(dev, 0x002140, 0); + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; + + nv_wr32(priv, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 12); + nv50_fifo_playlist_update(priv); return 0; } -void -nv50_fifo_tlb_flush(struct drm_device *dev, int engine) +int +nv50_fifo_chan_fini(struct nouveau_object *object, bool suspend) { - nv50_vm_flush_engine(dev, 5); + struct nv50_fifo_priv *priv = (void *)object->engine; + struct nv50_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; + + /* remove channel from playlist, fifo will unload context */ + nv_mask(priv, 0x002600 + (chid * 4), 0x80000000, 0x00000000); + nv50_fifo_playlist_update(priv); + nv_wr32(priv, 0x002600 + (chid * 4), 0x00000000); + + return nouveau_fifo_channel_fini(&chan->base, suspend); } -void -nv50_fifo_destroy(struct drm_device *dev, int engine) +static struct nouveau_ofuncs +nv50_fifo_ofuncs = { + .ctor = nv50_fifo_chan_ctor, + .dtor = nv50_fifo_chan_dtor, + .init = nv50_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_oclass +nv50_fifo_sclass[] = { + { 0x506f, &nv50_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ + +static int +nv50_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_fifo_priv *priv = nv_engine(dev, engine); + struct nv50_fifo_base *base; + int ret; - nouveau_irq_unregister(dev, 8); + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x10000, + 0x1000, NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nouveau_gpuobj_ref(NULL, &priv->playlist[0]); - nouveau_gpuobj_ref(NULL, &priv->playlist[1]); + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0200, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x1200, 0, + NVOBJ_FLAG_ZERO_ALLOC, &base->eng); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x4000, 0, 0, + &base->pgd); + if (ret) + return ret; + + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - dev_priv->eng[engine] = NULL; - kfree(priv); + return 0; } -int -nv50_fifo_create(struct drm_device *dev) +void +nv50_fifo_context_dtor(struct nouveau_object *object) +{ + struct nv50_fifo_base *base = (void *)object; + nouveau_vm_ref(NULL, &base->vm, base->pgd); + nouveau_gpuobj_ref(NULL, &base->pgd); + nouveau_gpuobj_ref(NULL, &base->eng); + nouveau_gpuobj_ref(NULL, &base->ramfc); + nouveau_gpuobj_ref(NULL, &base->cache); + nouveau_fifo_context_destroy(&base->base); +} + +static struct nouveau_oclass +nv50_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fifo_context_ctor, + .dtor = nv50_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ + +static int +nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_fifo_priv *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.base.destroy = nv50_fifo_destroy; - priv->base.base.init = nv50_fifo_init; - priv->base.base.fini = nv50_fifo_fini; - priv->base.base.context_new = nv50_fifo_context_new; - priv->base.base.context_del = nv50_fifo_context_del; - priv->base.base.tlb_flush = nv50_fifo_tlb_flush; - priv->base.channels = 127; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[0]); + ret = nouveau_fifo_create(parent, engine, oclass, 1, 127, &priv); + *pobject = nv_object(priv); if (ret) - goto error; + return ret; - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[1]); + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[0]); if (ret) - goto error; + return ret; - nouveau_irq_register(dev, 8, nv04_fifo_isr); -error: + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[1]); if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv50_fifo_cclass; + nv_engine(priv)->sclass = nv50_fifo_sclass; + return 0; +} + +void +nv50_fifo_dtor(struct nouveau_object *object) +{ + struct nv50_fifo_priv *priv = (void *)object; + + nouveau_gpuobj_ref(NULL, &priv->playlist[1]); + nouveau_gpuobj_ref(NULL, &priv->playlist[0]); + + nouveau_fifo_destroy(&priv->base); } + +int +nv50_fifo_init(struct nouveau_object *object) +{ + struct nv50_fifo_priv *priv = (void *)object; + int ret, i; + + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; + + nv_mask(priv, 0x000200, 0x00000100, 0x00000000); + nv_mask(priv, 0x000200, 0x00000100, 0x00000100); + nv_wr32(priv, 0x00250c, 0x6f3cfc34); + nv_wr32(priv, 0x002044, 0x01003fff); + + nv_wr32(priv, 0x002100, 0xffffffff); + nv_wr32(priv, 0x002140, 0xffffffff); + + for (i = 0; i < 128; i++) + nv_wr32(priv, 0x002600 + (i * 4), 0x00000000); + nv50_fifo_playlist_update(priv); + + nv_wr32(priv, 0x003200, 0x00000001); + nv_wr32(priv, 0x003250, 0x00000001); + nv_wr32(priv, 0x002500, 0x00000001); + return 0; +} + +struct nouveau_oclass +nv50_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_fifo_ctor, + .dtor = nv50_fifo_dtor, + .init = nv50_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h new file mode 100644 index 0000000..3a9ceb3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.h @@ -0,0 +1,36 @@ +#ifndef __NV50_FIFO_H__ +#define __NV50_FIFO_H__ + +struct nv50_fifo_priv { + struct nouveau_fifo base; + struct nouveau_gpuobj *playlist[2]; + int cur_playlist; +}; + +struct nv50_fifo_base { + struct nouveau_fifo_base base; + struct nouveau_gpuobj *ramfc; + struct nouveau_gpuobj *cache; + struct nouveau_gpuobj *eng; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; +}; + +struct nv50_fifo_chan { + struct nouveau_fifo_chan base; + u32 subc[8]; + struct nouveau_ramht *ramht; +}; + +void nv50_fifo_playlist_update(struct nv50_fifo_priv *); + +void nv50_fifo_object_detach(struct nouveau_object *, int); +void nv50_fifo_chan_dtor(struct nouveau_object *); +int nv50_fifo_chan_fini(struct nouveau_object *, bool); + +void nv50_fifo_context_dtor(struct nouveau_object *); + +void nv50_fifo_dtor(struct nouveau_object *); +int nv50_fifo_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 63a4941..765affb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -1,249 +1,343 @@ /* - * Copyright (C) 2012 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 +#include +#include +#include #include +#include +#include -struct nv84_fifo_priv { - struct nouveau_fifo_priv base; - struct nouveau_gpuobj *playlist[2]; - int cur_playlist; -}; +#include +#include -struct nv84_fifo_chan { - struct nouveau_fifo_chan base; - struct nouveau_gpuobj *ramfc; - struct nouveau_gpuobj *cache; -}; +#include +#include + +#include "nv50.h" + +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ static int -nv84_fifo_context_new(struct nouveau_channel *chan, int engine) +nv84_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct nv84_fifo_priv *priv = nv_engine(chan->dev, engine); - struct nv84_fifo_chan *fctx; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - u64 ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; - u64 instance; - unsigned long flags; - int ret; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent->parent; + struct nouveau_gpuobj *ectx = (void *)object; + u64 limit = ectx->addr + ectx->size - 1; + u64 start = ectx->addr; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0020; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; + case NVDEV_ENGINE_COPY0: addr = 0x00c0; break; + default: + return -EINVAL; + } - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - nvvm_engref(chan->vm, engine, 1); + nv_wo32(base->eng, addr + 0x00, 0x00190000); + nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); + nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); + nv_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 | + upper_32_bits(start)); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); + return 0; +} - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV50_USER(chan->id), PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; +static int +nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) +{ + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_priv *priv = (void *)parent->engine; + struct nv50_fifo_base *base = (void *)parent->parent; + struct nv50_fifo_chan *chan = (void *)parent; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0020; break; + case NVDEV_ENGINE_MPEG : addr = 0x0060; break; + case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; + case NVDEV_ENGINE_COPY0: addr = 0x00c0; break; + default: + return -EINVAL; } - ret = nouveau_gpuobj_new(dev, chan, 256, 256, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc); - if (ret) - goto error; - - instance = fctx->ramfc->addr >> 8; + nv_wo32(base->eng, addr + 0x00, 0x00000000); + nv_wo32(base->eng, addr + 0x04, 0x00000000); + nv_wo32(base->eng, addr + 0x08, 0x00000000); + nv_wo32(base->eng, addr + 0x0c, 0x00000000); + nv_wo32(base->eng, addr + 0x10, 0x00000000); + nv_wo32(base->eng, addr + 0x14, 0x00000000); + bar->flush(bar); + + nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); + if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { + nv_error(priv, "channel %d unload timeout\n", chan->base.chid); + if (suspend) + return -EBUSY; + } + return 0; +} - ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, 0, &fctx->cache); - if (ret) - goto error; - - nv_wo32(fctx->ramfc, 0x3c, 0x403f6078); - nv_wo32(fctx->ramfc, 0x40, 0x00000000); - nv_wo32(fctx->ramfc, 0x44, 0x01003fff); - nv_wo32(fctx->ramfc, 0x48, chan->pushbuf->node->offset >> 4); - nv_wo32(fctx->ramfc, 0x50, lower_32_bits(ib_offset)); - nv_wo32(fctx->ramfc, 0x54, upper_32_bits(ib_offset) | - drm_order(chan->dma.ib_max + 1) << 16); - nv_wo32(fctx->ramfc, 0x60, 0x7fffffff); - nv_wo32(fctx->ramfc, 0x78, 0x00000000); - nv_wo32(fctx->ramfc, 0x7c, 0x30000001); - nv_wo32(fctx->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->node->offset >> 4)); - nv_wo32(fctx->ramfc, 0x88, fctx->cache->addr >> 10); - nv_wo32(fctx->ramfc, 0x98, chan->ramin->addr >> 12); +static int +nv84_fifo_object_attach(struct nouveau_object *parent, + struct nouveau_object *object, u32 handle) +{ + struct nv50_fifo_chan *chan = (void *)parent; + u32 context; + + if (nv_iclass(object, NV_GPUOBJ_CLASS)) + context = nv_gpuobj(object)->node->offset >> 4; + else + context = 0x00000004; /* just non-zero */ + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_DMAOBJ: + case NVDEV_ENGINE_SW : context |= 0x00000000; break; + case NVDEV_ENGINE_GR : context |= 0x00100000; break; + case NVDEV_ENGINE_MPEG : + case NVDEV_ENGINE_PPP : context |= 0x00200000; break; + case NVDEV_ENGINE_ME : + case NVDEV_ENGINE_COPY0 : context |= 0x00300000; break; + case NVDEV_ENGINE_VP : context |= 0x00400000; break; + case NVDEV_ENGINE_CRYPT : + case NVDEV_ENGINE_UNK1C1: context |= 0x00500000; break; + case NVDEV_ENGINE_BSP : context |= 0x00600000; break; + default: + return -EINVAL; + } - nv_wo32(chan->ramin, 0x00, chan->id); - nv_wo32(chan->ramin, 0x04, fctx->ramfc->addr >> 8); + return nouveau_ramht_insert(chan->ramht, 0, handle, context); +} - nvimem_flush(dev); +static int +nv84_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent; + struct nv50_fifo_chan *chan; + struct nv_channel_ind_class *args = data; + u64 ioffset, ilength; + int ret; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x80000000 | instance); - nv50_fifo_playlist_update(dev); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x2000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG) | + (1 << NVDEV_ENGINE_ME) | + (1 << NVDEV_ENGINE_VP) | + (1 << NVDEV_ENGINE_CRYPT) | + (1 << NVDEV_ENGINE_BSP) | + (1 << NVDEV_ENGINE_PPP) | + (1 << NVDEV_ENGINE_COPY0) | + (1 << NVDEV_ENGINE_UNK1C1), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; -error: + ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht); if (ret) - priv->base.base.context_del(chan, engine); - return ret; + return ret; + + nv_parent(chan)->context_attach = nv84_fifo_context_attach; + nv_parent(chan)->context_detach = nv84_fifo_context_detach; + nv_parent(chan)->object_attach = nv84_fifo_object_attach; + nv_parent(chan)->object_detach = nv50_fifo_object_detach; + + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + nv_wo32(base->ramfc, 0x3c, 0x403f6078); + nv_wo32(base->ramfc, 0x44, 0x01003fff); + nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); + nv_wo32(base->ramfc, 0x50, lower_32_bits(ioffset)); + nv_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base->ramfc, 0x60, 0x7fffffff); + nv_wo32(base->ramfc, 0x78, 0x00000000); + nv_wo32(base->ramfc, 0x7c, 0x30000001); + nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->base.node->offset >> 4)); + nv_wo32(base->ramfc, 0x88, base->cache->addr >> 10); + nv_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12); + bar->flush(bar); + return 0; } -static void -nv84_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nv84_fifo_chan_init(struct nouveau_object *object) { - struct nv84_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned long flags; - u32 save; + struct nv50_fifo_priv *priv = (void *)object->engine; + struct nv50_fifo_base *base = (void *)object->parent; + struct nv50_fifo_chan *chan = (void *)object; + struct nouveau_gpuobj *ramfc = base->ramfc; + u32 chid = chan->base.chid; + int ret; + + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; - /* remove channel from playlist, will context switch if active */ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000); - nv50_fifo_playlist_update(dev); + nv_wr32(priv, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 8); + nv50_fifo_playlist_update(priv); + return 0; +} - save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); +static struct nouveau_ofuncs +nv84_fifo_ofuncs = { + .ctor = nv84_fifo_chan_ctor, + .dtor = nv50_fifo_chan_dtor, + .init = nv84_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; - /* tell any engines on this channel to unload their contexts */ - nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); - if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) - NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); +static struct nouveau_oclass +nv84_fifo_sclass[] = { + { 0x826f, &nv84_fifo_ofuncs }, + {} +}; - nv_wr32(dev, 0x002520, save); +/******************************************************************************* + * FIFO context - basically just the instmem reserved for the channel + ******************************************************************************/ - nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +int +nv84_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_fifo_base *base; + int ret; - /* clean up */ - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; - } + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x10000, + 0x1000, NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nouveau_gpuobj_ref(NULL, &fctx->ramfc); - nouveau_gpuobj_ref(NULL, &fctx->cache); + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0200, 0, + NVOBJ_FLAG_ZERO_ALLOC, &base->eng); + if (ret) + return ret; - nvvm_engref(chan->vm, engine, -1); - chan->engctx[engine] = NULL; - kfree(fctx); -} + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x4000, 0, + 0, &base->pgd); + if (ret) + return ret; -static int -nv84_fifo_init(struct drm_device *dev, int engine) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv84_fifo_chan *fctx; - u32 instance; - int i; - - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x00250c, 0x6f3cfc34); - nv_wr32(dev, 0x002044, 0x01003fff); - - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - - for (i = 0; i < 128; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan && (fctx = chan->engctx[engine])) - instance = 0x80000000 | fctx->ramfc->addr >> 8; - else - instance = 0x00000000; - nv_wr32(dev, 0x002600 + (i * 4), instance); - } + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - nv50_fifo_playlist_update(dev); + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x1000, 0x400, + NVOBJ_FLAG_ZERO_ALLOC, &base->cache); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0100, 0x100, + NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc); + if (ret) + return ret; - nv_wr32(dev, 0x003200, 1); - nv_wr32(dev, 0x003250, 1); - nv_wr32(dev, 0x002500, 1); return 0; } -static int -nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv84_fifo_priv *priv = nv_engine(dev, engine); - int i; - u32 save; - - /* set playlist length to zero, fifo will unload context */ - nv_wr32(dev, 0x0032ec, 0); - - save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); - - /* tell all connected engines to unload their contexts */ - for (i = 0; i < priv->base.channels; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (chan) - nv_wr32(dev, 0x0032fc, chan->ramin->addr >> 12); - if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff)) { - NV_INFO(dev, "PFIFO: channel %d unload timeout\n", i); - return -EBUSY; - } - } +static struct nouveau_oclass +nv84_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_fifo_context_ctor, + .dtor = nv50_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; - nv_wr32(dev, 0x002520, save); - nv_wr32(dev, 0x002140, 0); - return 0; -} +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ -int -nv84_fifo_create(struct drm_device *dev) +static int +nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv84_fifo_priv *priv; + struct nv50_fifo_priv *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.base.destroy = nv50_fifo_destroy; - priv->base.base.init = nv84_fifo_init; - priv->base.base.fini = nv84_fifo_fini; - priv->base.base.context_new = nv84_fifo_context_new; - priv->base.base.context_del = nv84_fifo_context_del; - priv->base.base.tlb_flush = nv50_fifo_tlb_flush; - priv->base.channels = 127; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; - - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[0]); + ret = nouveau_fifo_create(parent, engine, oclass, 1, 127, &priv); + *pobject = nv_object(priv); if (ret) - goto error; + return ret; - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->playlist[1]); + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[0]); if (ret) - goto error; + return ret; - nouveau_irq_register(dev, 8, nv04_fifo_isr); -error: + ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0, + &priv->playlist[1]); if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nv04_fifo_intr; + nv_engine(priv)->cclass = &nv84_fifo_cclass; + nv_engine(priv)->sclass = nv84_fifo_sclass; + return 0; } + +struct nouveau_oclass +nv84_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_fifo_ctor, + .dtor = nv50_fifo_dtor, + .init = nv50_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index b99d976..ef403fe 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/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,17 +22,24 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "nouveau_drv.h" -#include -#include -#include "nouveau_software.h" +#include +#include +#include -static void nvc0_fifo_isr(struct drm_device *); +#include +#include struct nvc0_fifo_priv { - struct nouveau_fifo_priv base; + struct nouveau_fifo base; struct nouveau_gpuobj *playlist[2]; int cur_playlist; struct { @@ -42,14 +49,24 @@ struct nvc0_fifo_priv { int spoon_nr; }; +struct nvc0_fifo_base { + struct nouveau_fifo_base base; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; +}; + struct nvc0_fifo_chan { struct nouveau_fifo_chan base; }; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ + static void -nvc0_fifo_playlist_update(struct drm_device *dev) +nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv) { - struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nouveau_bar *bar = nouveau_bar(priv); struct nouveau_gpuobj *cur; int i, p; @@ -57,174 +74,253 @@ nvc0_fifo_playlist_update(struct drm_device *dev) priv->cur_playlist = !priv->cur_playlist; for (i = 0, p = 0; i < 128; i++) { - if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1)) + if (!(nv_rd32(priv, 0x003004 + (i * 8)) & 1)) continue; nv_wo32(cur, p + 0, i); nv_wo32(cur, p + 4, 0x00000004); p += 8; } - nvimem_flush(dev); + bar->flush(bar); - nv_wr32(dev, 0x002270, cur->addr >> 12); - nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); - if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) - NV_ERROR(dev, "PFIFO - playlist update failed\n"); + nv_wr32(priv, 0x002270, cur->addr >> 12); + nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3)); + if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000)) + nv_error(priv, "playlist update failed\n"); } static int -nvc0_fifo_context_new(struct nouveau_channel *chan, int engine) +nvc0_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - struct nvc0_fifo_priv *priv = nv_engine(dev, engine); - struct nvc0_fifo_chan *fctx; - u64 usermem = priv->user.mem->addr + chan->id * 0x1000; - u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; - int ret, i; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nvc0_fifo_base *base = (void *)parent->parent; + struct nouveau_engctx *ectx = (void *)object; + u32 addr; + int ret; - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + case NVDEV_ENGINE_COPY0: addr = 0x0230; break; + case NVDEV_ENGINE_COPY1: addr = 0x0240; break; + default: + return -EINVAL; + } - chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + - priv->user.bar.offset + (chan->id * 0x1000), - PAGE_SIZE); - if (!chan->user) { - ret = -ENOMEM; - goto error; + if (!ectx->vma.node) { + ret = nouveau_gpuobj_map_vm(nv_gpuobj(ectx), base->vm, + NV_MEM_ACCESS_RW, &ectx->vma); + if (ret) + return ret; } - for (i = 0; i < 0x100; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x08, lower_32_bits(usermem)); - nv_wo32(chan->ramin, 0x0c, upper_32_bits(usermem)); - nv_wo32(chan->ramin, 0x10, 0x0000face); - nv_wo32(chan->ramin, 0x30, 0xfffff902); - nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | - upper_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x54, 0x00000002); - nv_wo32(chan->ramin, 0x84, 0x20400000); - nv_wo32(chan->ramin, 0x94, 0x30000001); - nv_wo32(chan->ramin, 0x9c, 0x00000100); - nv_wo32(chan->ramin, 0xa4, 0x1f1f1f1f); - nv_wo32(chan->ramin, 0xa8, 0x1f1f1f1f); - nv_wo32(chan->ramin, 0xac, 0x0000001f); - nv_wo32(chan->ramin, 0xb8, 0xf8000000); - nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ - nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - nvimem_flush(dev); - - nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | - (chan->ramin->addr >> 12)); - nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); - nvc0_fifo_playlist_update(dev); - -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; + nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); + nv_wo32(base, addr + 0x04, upper_32_bits(ectx->vma.offset)); + bar->flush(bar); + return 0; } -static void -nvc0_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nvc0_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) { - struct nvc0_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - - nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000); - nv_wr32(dev, 0x002634, chan->id); - if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) - NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); - nvc0_fifo_playlist_update(dev); - nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000); - - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nvc0_fifo_priv *priv = (void *)parent->engine; + struct nvc0_fifo_base *base = (void *)parent->parent; + struct nvc0_fifo_chan *chan = (void *)parent; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + case NVDEV_ENGINE_COPY0: addr = 0x0230; break; + case NVDEV_ENGINE_COPY1: addr = 0x0240; break; + default: + return -EINVAL; } - chan->engctx[engine] = NULL; - kfree(fctx); + nv_wo32(base, addr + 0x00, 0x00000000); + nv_wo32(base, addr + 0x04, 0x00000000); + bar->flush(bar); + + nv_wr32(priv, 0x002634, chan->base.chid); + if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { + nv_error(priv, "channel %d kick timeout\n", chan->base.chid); + if (suspend) + return -EBUSY; + } + + return 0; } static int -nvc0_fifo_init(struct drm_device *dev, int engine) +nvc0_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fifo_priv *priv = nv_engine(dev, engine); - struct nouveau_channel *chan; - int i; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nvc0_fifo_priv *priv = (void *)engine; + struct nvc0_fifo_base *base = (void *)parent; + struct nvc0_fifo_chan *chan; + struct nv_channel_ind_class *args = data; + u64 usermem, ioffset, ilength; + int ret, i; - /* reset PFIFO, enable all available PSUBFIFO areas */ - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x000204, 0xffffffff); - nv_wr32(dev, 0x002204, 0xffffffff); + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, + priv->user.bar.offset, 0x1000, + args->pushbuf, + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_COPY0) | + (1 << NVDEV_ENGINE_COPY1), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nvc0_fifo_context_attach; + nv_parent(chan)->context_detach = nvc0_fifo_context_detach; + + usermem = chan->base.chid * 0x1000; + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + for (i = 0; i < 0x1000; i += 4) + nv_wo32(priv->user.mem, usermem + i, 0x00000000); + + nv_wo32(base, 0x08, lower_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x0c, upper_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x10, 0x0000face); + nv_wo32(base, 0x30, 0xfffff902); + nv_wo32(base, 0x48, lower_32_bits(ioffset)); + nv_wo32(base, 0x4c, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base, 0x54, 0x00000002); + nv_wo32(base, 0x84, 0x20400000); + nv_wo32(base, 0x94, 0x30000001); + nv_wo32(base, 0x9c, 0x00000100); + nv_wo32(base, 0xa4, 0x1f1f1f1f); + nv_wo32(base, 0xa8, 0x1f1f1f1f); + nv_wo32(base, 0xac, 0x0000001f); + nv_wo32(base, 0xb8, 0xf8000000); + nv_wo32(base, 0xf8, 0x10003080); /* 0x002310 */ + nv_wo32(base, 0xfc, 0x10000010); /* 0x002350 */ + bar->flush(bar); + return 0; +} - priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204)); - NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); +static int +nvc0_fifo_chan_init(struct nouveau_object *object) +{ + struct nouveau_gpuobj *base = nv_gpuobj(object->parent); + struct nvc0_fifo_priv *priv = (void *)object->engine; + struct nvc0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; + int ret; - /* assign engines to subfifos */ - if (priv->spoon_nr >= 3) { - nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */ - nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */ - nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */ - nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */ - nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */ - nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */ - } + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; - /* PSUBFIFO[n] */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ - } + nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12); + nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001); + nvc0_fifo_playlist_update(priv); + return 0; +} - nv_mask(dev, 0x002200, 0x00000001, 0x00000001); - nv_wr32(dev, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); +static int +nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend) +{ + struct nvc0_fifo_priv *priv = (void *)object->engine; + struct nvc0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; - nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xbfffffff); + nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); + nvc0_fifo_playlist_update(priv); + nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000); - /* restore PFIFO context table */ - for (i = 0; i < 128; i++) { - chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->engctx[engine]) - continue; + return nouveau_fifo_channel_fini(&chan->base, suspend); +} - nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 | - (chan->ramin->addr >> 12)); - nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001); - } - nvc0_fifo_playlist_update(dev); +static struct nouveau_ofuncs +nvc0_fifo_ofuncs = { + .ctor = nvc0_fifo_chan_ctor, + .dtor = _nouveau_fifo_channel_dtor, + .init = nvc0_fifo_chan_init, + .fini = nvc0_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; - return 0; -} +static struct nouveau_oclass +nvc0_fifo_sclass[] = { + { 0x906f, &nvc0_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - instmem heap and vm setup + ******************************************************************************/ static int -nvc0_fifo_fini(struct drm_device *dev, int engine, bool suspend) +nvc0_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - int i; + struct nvc0_fifo_base *base; + int ret; - for (i = 0; i < 128; i++) { - if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1)) - continue; + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x1000, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_HEAP, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000); - nv_wr32(dev, 0x002634, i); - if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { - NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", - i, nv_rd32(dev, 0x002634)); - return -EBUSY; - } - } + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0x1000, 0, &base->pgd); + if (ret) + return ret; + + nv_wo32(base, 0x0200, lower_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0204, upper_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0208, 0xffffffff); + nv_wo32(base, 0x020c, 0x000000ff); + + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - nv_wr32(dev, 0x002140, 0x00000000); return 0; } +static void +nvc0_fifo_context_dtor(struct nouveau_object *object) +{ + struct nvc0_fifo_base *base = (void *)object; + nouveau_vm_ref(NULL, &base->vm, base->pgd); + nouveau_gpuobj_ref(NULL, &base->pgd); + nouveau_fifo_context_destroy(&base->base); +} + +static struct nouveau_oclass +nvc0_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fifo_context_ctor, + .dtor = nvc0_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ struct nouveau_enum nvc0_fifo_fault_unit[] = { { 0x00, "PGRAPH" }, @@ -289,16 +385,16 @@ struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { }; static void -nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) +nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) { - u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); - u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); - u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); - u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); + u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10)); + u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; - NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", - (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? + "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); printk("] from "); nouveau_enum_print(nvc0_fifo_fault_unit, unit); @@ -313,165 +409,223 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) } static int -nvc0_fifo_page_flip(struct drm_device *dev, u32 chid) +nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) { - struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; + struct nvc0_fifo_chan *chan = NULL; + struct nouveau_handle *bind; unsigned long flags; int ret = -EINVAL; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < priv->base.channels)) { - chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) { - struct nouveau_software_chan *swch = - chan->engctx[NVOBJ_ENGINE_SW]; - ret = swch->flip(swch->flip_data); - } + spin_lock_irqsave(&priv->base.lock, flags); + if (likely(chid >= priv->base.min && chid <= priv->base.max)) + chan = (void *)priv->base.channel[chid]; + if (unlikely(!chan)) + goto out; + + bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e); + if (likely(bind)) { + if (!mthd || !nv_call(bind->object, mthd, data)) + ret = 0; + nouveau_namedb_put(bind); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + +out: + spin_unlock_irqrestore(&priv->base.lock, flags); return ret; } static void -nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) +nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit) { - u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); - u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); - u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; - u32 subc = (addr & 0x00070000); + u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); + u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); + u32 data = nv_rd32(priv, 0x0400c4 + (unit * 0x2000)); + u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0x7f; + u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); u32 show = stat; if (stat & 0x00200000) { if (mthd == 0x0054) { - if (!nvc0_fifo_page_flip(dev, chid)) + if (!nvc0_fifo_swmthd(priv, chid, 0x0500, 0x00000000)) show &= ~0x00200000; } } + if (stat & 0x00800000) { + if (!nvc0_fifo_swmthd(priv, chid, mthd, data)) + show &= ~0x00800000; + } + if (show) { - NV_INFO(dev, "PFIFO%d:", unit); + nv_error(priv, "SUBFIFO%d:", unit); nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); - NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, subc, mthd, data); + printk("\n"); + nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " + "data 0x%08x\n", + unit, chid, subc, mthd, data); } - nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); - nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); + nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(priv, 0x040108 + (unit * 0x2000), stat); } static void -nvc0_fifo_isr(struct drm_device *dev) +nvc0_fifo_intr(struct nouveau_subdev *subdev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + struct nvc0_fifo_priv *priv = (void *)subdev; + u32 mask = nv_rd32(priv, 0x002140); + u32 stat = nv_rd32(priv, 0x002100) & mask; if (stat & 0x00000100) { - NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); - nv_wr32(dev, 0x002100, 0x00000100); + nv_info(priv, "unknown status 0x00000100\n"); + nv_wr32(priv, 0x002100, 0x00000100); stat &= ~0x00000100; } if (stat & 0x10000000) { - u32 units = nv_rd32(dev, 0x00259c); + u32 units = nv_rd32(priv, 0x00259c); u32 u = units; while (u) { int i = ffs(u) - 1; - nvc0_fifo_isr_vm_fault(dev, i); + nvc0_fifo_isr_vm_fault(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x00259c, units); + nv_wr32(priv, 0x00259c, units); stat &= ~0x10000000; } if (stat & 0x20000000) { - u32 units = nv_rd32(dev, 0x0025a0); + u32 units = nv_rd32(priv, 0x0025a0); u32 u = units; while (u) { int i = ffs(u) - 1; - nvc0_fifo_isr_subfifo_intr(dev, i); + nvc0_fifo_isr_subfifo_intr(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x0025a0, units); + nv_wr32(priv, 0x0025a0, units); stat &= ~0x20000000; } if (stat & 0x40000000) { - NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); - nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); + nv_warn(priv, "unknown status 0x40000000\n"); + nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); stat &= ~0x40000000; } if (stat) { - NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); - nv_wr32(dev, 0x002100, stat); - nv_wr32(dev, 0x002140, 0); + nv_fatal(priv, "unhandled status 0x%08x\n", stat); + nv_wr32(priv, 0x002100, stat); + nv_wr32(priv, 0x002140, 0); } } +static int +nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_fifo_priv *priv; + int ret; + + ret = nouveau_fifo_create(parent, engine, oclass, 0, 127, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0, + &priv->playlist[0]); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0, + &priv->playlist[1]); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 128 * 0x1000, 0x1000, 0, + &priv->user.mem); + if (ret) + return ret; + + ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, + &priv->user.bar); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nvc0_fifo_intr; + nv_engine(priv)->cclass = &nvc0_fifo_cclass; + nv_engine(priv)->sclass = nvc0_fifo_sclass; + return 0; +} + static void -nvc0_fifo_destroy(struct drm_device *dev, int engine) +nvc0_fifo_dtor(struct nouveau_object *object) { - struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_fifo_priv *priv = (void *)object; nouveau_gpuobj_unmap(&priv->user.bar); nouveau_gpuobj_ref(NULL, &priv->user.mem); - nouveau_gpuobj_ref(NULL, &priv->playlist[1]); nouveau_gpuobj_ref(NULL, &priv->playlist[0]); - dev_priv->eng[engine] = NULL; - kfree(priv); + nouveau_fifo_destroy(&priv->base); } -int -nvc0_fifo_create(struct drm_device *dev) +static int +nvc0_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_fifo_priv *priv; - int ret; + struct nvc0_fifo_priv *priv = (void *)object; + int ret, i; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - priv->base.base.destroy = nvc0_fifo_destroy; - priv->base.base.init = nvc0_fifo_init; - priv->base.base.fini = nvc0_fifo_fini; - priv->base.base.context_new = nvc0_fifo_context_new; - priv->base.base.context_del = nvc0_fifo_context_del; - priv->base.channels = 128; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + nv_wr32(priv, 0x000204, 0xffffffff); + nv_wr32(priv, 0x002204, 0xffffffff); - ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[0]); - if (ret) - goto error; + priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204)); + nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); - ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[1]); - if (ret) - goto error; + /* assign engines to subfifos */ + if (priv->spoon_nr >= 3) { + nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */ + nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */ + nv_wr32(priv, 0x002210, ~(1 << 1)); /* PPP */ + nv_wr32(priv, 0x002214, ~(1 << 1)); /* PBSP */ + nv_wr32(priv, 0x002218, ~(1 << 2)); /* PCE0 */ + nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */ + } - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 4096, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); - if (ret) - goto error; + /* PSUBFIFO[n] */ + for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + } - ret = nouveau_gpuobj_map_bar(priv->user.mem, NV_MEM_ACCESS_RW, - &priv->user.bar); - if (ret) - goto error; + nv_mask(priv, 0x002200, 0x00000001, 0x00000001); + nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); - nouveau_irq_register(dev, 8, nvc0_fifo_isr); -error: - if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ + nv_wr32(priv, 0x002100, 0xffffffff); + nv_wr32(priv, 0x002140, 0xbfffffff); + return 0; } + +struct nouveau_oclass +nvc0_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fifo_ctor, + .dtor = nvc0_fifo_dtor, + .init = nvc0_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 0b356f1..aaff086 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/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,25 +22,30 @@ * Authors: Ben Skeggs */ -#include "drmP.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "nouveau_drv.h" -#include -#include -#include "nouveau_software.h" - -#define NVE0_FIFO_ENGINE_NUM 32 +#include +#include +#include -static void nve0_fifo_isr(struct drm_device *); +#include +#include -struct nve0_fifo_engine { +struct nve0_fifo_engn { struct nouveau_gpuobj *playlist[2]; int cur_playlist; }; struct nve0_fifo_priv { - struct nouveau_fifo_priv base; - struct nve0_fifo_engine engine[NVE0_FIFO_ENGINE_NUM]; + struct nouveau_fifo base; + struct nve0_fifo_engn engine[16]; struct { struct nouveau_gpuobj *mem; struct nouveau_vma bar; @@ -48,194 +53,286 @@ struct nve0_fifo_priv { int spoon_nr; }; +struct nve0_fifo_base { + struct nouveau_fifo_base base; + struct nouveau_gpuobj *pgd; + struct nouveau_vm *vm; +}; + struct nve0_fifo_chan { struct nouveau_fifo_chan base; u32 engine; }; +/******************************************************************************* + * FIFO channel objects + ******************************************************************************/ + static void -nve0_fifo_playlist_update(struct drm_device *dev, u32 engine) +nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine) { - struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct nve0_fifo_engine *peng = &priv->engine[engine]; + struct nouveau_bar *bar = nouveau_bar(priv); + struct nve0_fifo_engn *engn = &priv->engine[engine]; struct nouveau_gpuobj *cur; u32 match = (engine << 16) | 0x00000001; - int ret, i, p; + int i, p; - cur = peng->playlist[peng->cur_playlist]; + cur = engn->playlist[engn->cur_playlist]; if (unlikely(cur == NULL)) { - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 0x1000, 0, &cur); + int ret = nouveau_gpuobj_new(nv_object(priv)->parent, NULL, + 0x8000, 0x1000, 0, &cur); if (ret) { - NV_ERROR(dev, "PFIFO: playlist alloc failed\n"); + nv_error(priv, "playlist alloc failed\n"); return; } - peng->playlist[peng->cur_playlist] = cur; + engn->playlist[engn->cur_playlist] = cur; } - peng->cur_playlist = !peng->cur_playlist; + engn->cur_playlist = !engn->cur_playlist; - for (i = 0, p = 0; i < priv->base.channels; i++) { - u32 ctrl = nv_rd32(dev, 0x800004 + (i * 8)) & 0x001f0001; + for (i = 0, p = 0; i < priv->base.max; i++) { + u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001; if (ctrl != match) continue; nv_wo32(cur, p + 0, i); nv_wo32(cur, p + 4, 0x00000000); p += 8; } - nvimem_flush(dev); + bar->flush(bar); - nv_wr32(dev, 0x002270, cur->addr >> 12); - nv_wr32(dev, 0x002274, (engine << 20) | (p >> 3)); - if (!nv_wait(dev, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) - NV_ERROR(dev, "PFIFO: playlist %d update timeout\n", engine); + nv_wr32(priv, 0x002270, cur->addr >> 12); + nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); + if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) + nv_error(priv, "playlist %d update timeout\n", engine); } static int -nve0_fifo_context_new(struct nouveau_channel *chan, int engine) +nve0_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) { - struct drm_device *dev = chan->dev; - struct nve0_fifo_priv *priv = nv_engine(dev, engine); - struct nve0_fifo_chan *fctx; - u64 usermem = priv->user.mem->addr + chan->id * 512; - u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; - int ret = 0, i; - - fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - fctx->engine = 0; /* PGRAPH */ - - /* allocate vram for control regs, map into polling area */ - chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + - priv->user.bar.offset + (chan->id * 512), 512); - if (!chan->user) { - ret = -ENOMEM; - goto error; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nve0_fifo_base *base = (void *)parent->parent; + struct nouveau_engctx *ectx = (void *)object; + u32 addr; + int ret; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + default: + return -EINVAL; } - for (i = 0; i < 0x100; i += 4) - nv_wo32(chan->ramin, i, 0x00000000); - nv_wo32(chan->ramin, 0x08, lower_32_bits(usermem)); - nv_wo32(chan->ramin, 0x0c, upper_32_bits(usermem)); - nv_wo32(chan->ramin, 0x10, 0x0000face); - nv_wo32(chan->ramin, 0x30, 0xfffff902); - nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | - upper_32_bits(ib_virt)); - nv_wo32(chan->ramin, 0x84, 0x20400000); - nv_wo32(chan->ramin, 0x94, 0x30000001); - nv_wo32(chan->ramin, 0x9c, 0x00000100); - nv_wo32(chan->ramin, 0xac, 0x0000001f); - nv_wo32(chan->ramin, 0xe4, 0x00000000); - nv_wo32(chan->ramin, 0xe8, chan->id); - nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */ - nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */ - nvimem_flush(dev); - - nv_wr32(dev, 0x800000 + (chan->id * 8), 0x80000000 | - (chan->ramin->addr >> 12)); - nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); - nve0_fifo_playlist_update(dev, fctx->engine); - nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400); - -error: - if (ret) - priv->base.base.context_del(chan, engine); - return ret; + if (!ectx->vma.node) { + ret = nouveau_gpuobj_map_vm(nv_gpuobj(ectx), base->vm, + NV_MEM_ACCESS_RW, &ectx->vma); + if (ret) + return ret; + } + + nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); + nv_wo32(base, addr + 0x04, upper_32_bits(ectx->vma.offset)); + bar->flush(bar); + return 0; } -static void -nve0_fifo_context_del(struct nouveau_channel *chan, int engine) +static int +nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, + struct nouveau_object *object) { - struct nve0_fifo_chan *fctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - - nv_mask(dev, 0x800004 + (chan->id * 8), 0x00000800, 0x00000800); - nv_wr32(dev, 0x002634, chan->id); - if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) - NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); - nve0_fifo_playlist_update(dev, fctx->engine); - nv_wr32(dev, 0x800000 + (chan->id * 8), 0x00000000); - - if (chan->user) { - iounmap(chan->user); - chan->user = NULL; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nve0_fifo_priv *priv = (void *)parent->engine; + struct nve0_fifo_base *base = (void *)parent->parent; + struct nve0_fifo_chan *chan = (void *)parent; + u32 addr; + + switch (nv_engidx(object->engine)) { + case NVDEV_ENGINE_SW : return 0; + case NVDEV_ENGINE_GR : addr = 0x0210; break; + default: + return -EINVAL; + } + + nv_wo32(base, addr + 0x00, 0x00000000); + nv_wo32(base, addr + 0x04, 0x00000000); + bar->flush(bar); + + nv_wr32(priv, 0x002634, chan->base.chid); + if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { + nv_error(priv, "channel %d kick timeout\n", chan->base.chid); + if (suspend) + return -EBUSY; } - chan->engctx[NVOBJ_ENGINE_FIFO] = NULL; - kfree(fctx); + return 0; } static int -nve0_fifo_init(struct drm_device *dev, int engine) +nve0_fifo_chan_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nve0_fifo_priv *priv = nv_engine(dev, engine); - struct nve0_fifo_chan *fctx; - int i; + struct nouveau_bar *bar = nouveau_bar(parent); + struct nve0_fifo_priv *priv = (void *)engine; + struct nve0_fifo_base *base = (void *)parent; + struct nve0_fifo_chan *chan; + struct nv_channel_ind_class *args = data; + u64 usermem, ioffset, ilength; + int ret, i; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, + priv->user.bar.offset, 0x200, + args->pushbuf, + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nve0_fifo_context_attach; + nv_parent(chan)->context_detach = nve0_fifo_context_detach; + + usermem = chan->base.chid * 0x200; + ioffset = args->ioffset; + ilength = log2i(args->ilength / 8); + + for (i = 0; i < 0x200; i += 4) + nv_wo32(priv->user.mem, usermem + i, 0x00000000); + + nv_wo32(base, 0x08, lower_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x0c, upper_32_bits(priv->user.mem->addr + usermem)); + nv_wo32(base, 0x10, 0x0000face); + nv_wo32(base, 0x30, 0xfffff902); + nv_wo32(base, 0x48, lower_32_bits(ioffset)); + nv_wo32(base, 0x4c, upper_32_bits(ioffset) | (ilength << 16)); + nv_wo32(base, 0x84, 0x20400000); + nv_wo32(base, 0x94, 0x30000001); + nv_wo32(base, 0x9c, 0x00000100); + nv_wo32(base, 0xac, 0x0000001f); + nv_wo32(base, 0xe8, chan->base.chid); + nv_wo32(base, 0xb8, 0xf8000000); + nv_wo32(base, 0xf8, 0x10003080); /* 0x002310 */ + nv_wo32(base, 0xfc, 0x10000010); /* 0x002350 */ + bar->flush(bar); + return 0; +} - /* reset PFIFO, enable all available PSUBFIFO areas */ - nv_mask(dev, 0x000200, 0x00000100, 0x00000000); - nv_mask(dev, 0x000200, 0x00000100, 0x00000100); - nv_wr32(dev, 0x000204, 0xffffffff); +static int +nve0_fifo_chan_init(struct nouveau_object *object) +{ + struct nouveau_gpuobj *base = nv_gpuobj(object->parent); + struct nve0_fifo_priv *priv = (void *)object->engine; + struct nve0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; + int ret; - priv->spoon_nr = hweight32(nv_rd32(dev, 0x000204)); - NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); + ret = nouveau_fifo_channel_init(&chan->base); + if (ret) + return ret; - /* PSUBFIFO[n] */ - for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ - } + nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); + nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); + nve0_fifo_playlist_update(priv, chan->engine); + nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); + return 0; +} - nv_wr32(dev, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); +static int +nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend) +{ + struct nve0_fifo_priv *priv = (void *)object->engine; + struct nve0_fifo_chan *chan = (void *)object; + u32 chid = chan->base.chid; - nv_wr32(dev, 0x002a00, 0xffffffff); - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xbfffffff); + nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800); + nve0_fifo_playlist_update(priv, chan->engine); + nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); - /* restore PFIFO context table */ - for (i = 0; i < priv->base.channels; i++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - if (!chan || !(fctx = chan->engctx[engine])) - continue; + return nouveau_fifo_channel_fini(&chan->base, suspend); +} - nv_wr32(dev, 0x800000 + (i * 8), 0x80000000 | - (chan->ramin->addr >> 12)); - nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); - nve0_fifo_playlist_update(dev, fctx->engine); - nv_mask(dev, 0x800004 + (i * 8), 0x00000400, 0x00000400); - } +static struct nouveau_ofuncs +nve0_fifo_ofuncs = { + .ctor = nve0_fifo_chan_ctor, + .dtor = _nouveau_fifo_channel_dtor, + .init = nve0_fifo_chan_init, + .fini = nve0_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; - return 0; -} +static struct nouveau_oclass +nve0_fifo_sclass[] = { + { 0xa06f, &nve0_fifo_ofuncs }, + {} +}; + +/******************************************************************************* + * FIFO context - instmem heap and vm setup + ******************************************************************************/ static int -nve0_fifo_fini(struct drm_device *dev, int engine, bool suspend) +nve0_fifo_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nve0_fifo_priv *priv = nv_engine(dev, engine); - int i; + struct nve0_fifo_base *base; + int ret; - for (i = 0; i < priv->base.channels; i++) { - if (!(nv_rd32(dev, 0x800004 + (i * 8)) & 1)) - continue; + ret = nouveau_fifo_context_create(parent, engine, oclass, NULL, 0x1000, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base); + *pobject = nv_object(base); + if (ret) + return ret; - nv_mask(dev, 0x800004 + (i * 8), 0x00000800, 0x00000800); - nv_wr32(dev, 0x002634, i); - if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { - NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", - i, nv_rd32(dev, 0x002634)); - return -EBUSY; - } - } + ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0x1000, 0, &base->pgd); + if (ret) + return ret; + + nv_wo32(base, 0x0200, lower_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0204, upper_32_bits(base->pgd->addr)); + nv_wo32(base, 0x0208, 0xffffffff); + nv_wo32(base, 0x020c, 0x000000ff); + + ret = nouveau_vm_ref(nouveau_client(parent)->vm, &base->vm, base->pgd); + if (ret) + return ret; - nv_wr32(dev, 0x002140, 0x00000000); return 0; } +static void +nve0_fifo_context_dtor(struct nouveau_object *object) +{ + struct nve0_fifo_base *base = (void *)object; + nouveau_vm_ref(NULL, &base->vm, base->pgd); + nouveau_gpuobj_ref(NULL, &base->pgd); + nouveau_fifo_context_destroy(&base->base); +} + +static struct nouveau_oclass +nve0_fifo_cclass = { + .handle = NV_ENGCTX(FIFO, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_fifo_context_ctor, + .dtor = nve0_fifo_context_dtor, + .init = _nouveau_fifo_context_init, + .fini = _nouveau_fifo_context_fini, + .rd32 = _nouveau_fifo_context_rd32, + .wr32 = _nouveau_fifo_context_wr32, + }, +}; + +/******************************************************************************* + * PFIFO engine + ******************************************************************************/ + struct nouveau_enum nve0_fifo_fault_unit[] = { {} }; @@ -268,16 +365,16 @@ struct nouveau_bitfield nve0_fifo_subfifo_intr[] = { }; static void -nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) +nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit) { - u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); - u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); - u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); - u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); + u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10)); + u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; - NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", - (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ? + "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); printk("] from "); nouveau_enum_print(nve0_fifo_fault_unit, unit); @@ -292,160 +389,205 @@ nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit) } static int -nve0_fifo_page_flip(struct drm_device *dev, u32 chid) +nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) { - struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = NULL; + struct nve0_fifo_chan *chan = NULL; + struct nouveau_handle *bind; unsigned long flags; int ret = -EINVAL; - spin_lock_irqsave(&dev_priv->channels.lock, flags); - if (likely(chid >= 0 && chid < priv->base.channels)) { - chan = dev_priv->channels.ptr[chid]; - if (likely(chan)) { - struct nouveau_software_chan *swch = - chan->engctx[NVOBJ_ENGINE_SW]; - ret = swch->flip(swch->flip_data); - } + spin_lock_irqsave(&priv->base.lock, flags); + if (likely(chid >= priv->base.min && chid <= priv->base.max)) + chan = (void *)priv->base.channel[chid]; + if (unlikely(!chan)) + goto out; + + bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e); + if (likely(bind)) { + if (!mthd || !nv_call(bind->object, mthd, data)) + ret = 0; + nouveau_namedb_put(bind); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + +out: + spin_unlock_irqrestore(&priv->base.lock, flags); return ret; } static void -nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) +nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit) { - u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); - u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); - u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); - u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0xfff; - u32 subc = (addr & 0x00070000); + u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000)); + u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); + u32 data = nv_rd32(priv, 0x0400c4 + (unit * 0x2000)); + u32 chid = nv_rd32(priv, 0x040120 + (unit * 0x2000)) & 0xfff; + u32 subc = (addr & 0x00070000) >> 16; u32 mthd = (addr & 0x00003ffc); u32 show = stat; if (stat & 0x00200000) { if (mthd == 0x0054) { - if (!nve0_fifo_page_flip(dev, chid)) + if (!nve0_fifo_swmthd(priv, chid, 0x0500, 0x00000000)) show &= ~0x00200000; } } + if (stat & 0x00800000) { + if (!nve0_fifo_swmthd(priv, chid, mthd, data)) + show &= ~0x00800000; + } + if (show) { - NV_INFO(dev, "PFIFO%d:", unit); + nv_error(priv, "SUBFIFO%d:", unit); nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); - NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, subc, mthd, data); + printk("\n"); + nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " + "data 0x%08x\n", + unit, chid, subc, mthd, data); } - nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); - nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); + nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); + nv_wr32(priv, 0x040108 + (unit * 0x2000), stat); } static void -nve0_fifo_isr(struct drm_device *dev) +nve0_fifo_intr(struct nouveau_subdev *subdev) { - u32 mask = nv_rd32(dev, 0x002140); - u32 stat = nv_rd32(dev, 0x002100) & mask; + struct nve0_fifo_priv *priv = (void *)subdev; + u32 mask = nv_rd32(priv, 0x002140); + u32 stat = nv_rd32(priv, 0x002100) & mask; if (stat & 0x00000100) { - NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); - nv_wr32(dev, 0x002100, 0x00000100); + nv_warn(priv, "unknown status 0x00000100\n"); + nv_wr32(priv, 0x002100, 0x00000100); stat &= ~0x00000100; } if (stat & 0x10000000) { - u32 units = nv_rd32(dev, 0x00259c); + u32 units = nv_rd32(priv, 0x00259c); u32 u = units; while (u) { int i = ffs(u) - 1; - nve0_fifo_isr_vm_fault(dev, i); + nve0_fifo_isr_vm_fault(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x00259c, units); + nv_wr32(priv, 0x00259c, units); stat &= ~0x10000000; } if (stat & 0x20000000) { - u32 units = nv_rd32(dev, 0x0025a0); + u32 units = nv_rd32(priv, 0x0025a0); u32 u = units; while (u) { int i = ffs(u) - 1; - nve0_fifo_isr_subfifo_intr(dev, i); + nve0_fifo_isr_subfifo_intr(priv, i); u &= ~(1 << i); } - nv_wr32(dev, 0x0025a0, units); + nv_wr32(priv, 0x0025a0, units); stat &= ~0x20000000; } if (stat & 0x40000000) { - NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); - nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); + nv_warn(priv, "unknown status 0x40000000\n"); + nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); stat &= ~0x40000000; } if (stat) { - NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); - nv_wr32(dev, 0x002100, stat); - nv_wr32(dev, 0x002140, 0); + nv_fatal(priv, "unhandled status 0x%08x\n", stat); + nv_wr32(priv, 0x002100, stat); + nv_wr32(priv, 0x002140, 0); } } +static int +nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nve0_fifo_priv *priv; + int ret; + + ret = nouveau_fifo_create(parent, engine, oclass, 0, 4095, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + ret = nouveau_gpuobj_new(parent, NULL, 4096 * 0x200, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); + if (ret) + return ret; + + ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, + &priv->user.bar); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000100; + nv_subdev(priv)->intr = nve0_fifo_intr; + nv_engine(priv)->cclass = &nve0_fifo_cclass; + nv_engine(priv)->sclass = nve0_fifo_sclass; + return 0; +} + static void -nve0_fifo_destroy(struct drm_device *dev, int engine) +nve0_fifo_dtor(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nve0_fifo_priv *priv = nv_engine(dev, engine); + struct nve0_fifo_priv *priv = (void *)object; int i; nouveau_gpuobj_unmap(&priv->user.bar); nouveau_gpuobj_ref(NULL, &priv->user.mem); - for (i = 0; i < NVE0_FIFO_ENGINE_NUM; i++) { - nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]); + for (i = 0; i < ARRAY_SIZE(priv->engine); i++) { nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]); + nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]); } - dev_priv->eng[engine] = NULL; - kfree(priv); + nouveau_fifo_destroy(&priv->base); } -int -nve0_fifo_create(struct drm_device *dev) +static int +nve0_fifo_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nve0_fifo_priv *priv; - int ret; + struct nve0_fifo_priv *priv = (void *)object; + int ret, i; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + ret = nouveau_fifo_init(&priv->base); + if (ret) + return ret; - priv->base.base.destroy = nve0_fifo_destroy; - priv->base.base.init = nve0_fifo_init; - priv->base.base.fini = nve0_fifo_fini; - priv->base.base.context_new = nve0_fifo_context_new; - priv->base.base.context_del = nve0_fifo_context_del; - priv->base.channels = 4096; - dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base; + /* enable all available PSUBFIFOs */ + nv_wr32(priv, 0x000204, 0xffffffff); + priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204)); + nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); - ret = nouveau_gpuobj_new(dev, NULL, priv->base.channels * 512, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); - if (ret) - goto error; + /* PSUBFIFO[n] */ + for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ + } - ret = nouveau_gpuobj_map_bar(priv->user.mem, NV_MEM_ACCESS_RW, - &priv->user.bar); - if (ret) - goto error; + nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); - nouveau_irq_register(dev, 8, nve0_fifo_isr); -error: - if (ret) - priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO); - return ret; + nv_wr32(priv, 0x002a00, 0xffffffff); + nv_wr32(priv, 0x002100, 0xffffffff); + nv_wr32(priv, 0x002140, 0xbfffffff); + return 0; } + +struct nouveau_oclass +nve0_fifo_oclass = { + .handle = NV_ENGINE(FIFO, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_fifo_ctor, + .dtor = nve0_fifo_dtor, + .init = nve0_fifo_init, + .fini = _nouveau_fifo_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctx.h index b0795ec..e194701 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 b17506d..e45035e 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 + /* 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 e17c17b..552fdbd 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 + #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<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 b19a406..c12e766 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 #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 e550317..6d8c639 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 #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 7f3a275..e5b0189 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 -#include "nouveau_drv.h" -#include "nouveau_hw.h" -#include "nouveau_util.h" -#include - -struct nv04_graph_engine { - struct nouveau_exec_engine base; -}; +#include +#include +#include +#include + +#include +#include +#include + +#include +#include -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 d006658..ce38196 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 -#include "nouveau_drv.h" -#include "nouveau_util.h" - -struct nv10_graph_engine { - struct nouveau_exec_engine base; -}; +#include +#include +#include + +#include + +#include +#include + +#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 0d874b8b..61faef9 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 - -/* - * 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 +#include +#include +#include +#include + +#include +#include + +#include +#include + +#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 0000000..2bea731 --- /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 + +#include +#include + +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 0000000..b2b650d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#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 0000000..700462f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#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 0000000..cedadaa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#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 0000000..273f632 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#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 0000000..f40ee21 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include + +#include +#include + +#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 466d215..2f9f2c6 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 +#include +#include +#include + +#include +#include + +#include #include -#include -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 0000000..d2ac975 --- /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 28932c4..8955bdd 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 -#include -#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 +#include +#include +#include +#include - NV_DEBUG(dev, "\n"); +#include +#include +#include - /* 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 - 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 0000000..0505fb4 --- /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 f994d2f..db8aefc 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 -#include - -#include "drmP.h" - -#include "nouveau_drv.h" -#include -#include - #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 30ea3ab..26f8268 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 +#include +#include +#include + +#include +#include +#include +#include + +#include + #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 a3a4ee7..c79748a 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 -#include - -#include "drmP.h" - -#include "nouveau_drv.h" -#include -#include - #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 0000000..9c715a2 --- /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 diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index a0258c7..7a1bc76 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,159 +22,62 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include -#include +#include +#include +#include +#include +#include -struct nv31_mpeg_engine { - struct nouveau_exec_engine base; - atomic_t refcount; -}; - - -static int -nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) -{ - struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); - - if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) - return -EBUSY; - - chan->engctx[engine] = (void *)0xdeadcafe; - return 0; -} - -static void -nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) -{ - struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); - atomic_dec(&pmpeg->refcount); - chan->engctx[engine] = NULL; -} +#include +#include +#include -static int -nv40_mpeg_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 *ctx = NULL; - unsigned long flags; - int ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); +#include - ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); - if (ret) - return ret; - - nv_wo32(ctx, 0x78, 0x02001ec1); - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x002500, 0x00000001, 0x00000000); - if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) - nv_wr32(dev, 0x00330c, ctx->addr >> 4); - nv_wo32(chan->ramfc, 0x54, ctx->addr >> 4); - nv_mask(dev, 0x002500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +struct nv31_mpeg_priv { + struct nouveau_mpeg base; + atomic_t refcount; +}; - chan->engctx[engine] = ctx; - return 0; -} +struct nv31_mpeg_chan { + struct nouveau_object base; +}; -static void -nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - unsigned long flags; - u32 inst = 0x80000000 | (ctx->addr >> 4); - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); - if (nv_rd32(dev, 0x00b318) == inst) - nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = NULL; -} +/******************************************************************************* + * MPEG object classes + ******************************************************************************/ static int -nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +nv31_mpeg_object_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 nouveau_gpuobj *obj; int ret; - ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 20, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - obj->engine = 2; - obj->class = class; - - nv_wo32(obj, 0x00, class); - - ret = nouveau_ramht_insert(chan, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; -} - -static int -nv31_mpeg_init(struct drm_device *dev, int engine) -{ - struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); - int i; - - /* VPE init */ - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); - nv_mask(dev, 0x000200, 0x00000002, 0x00000002); - nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ - for (i = 0; i < nvfb_tile_nr(dev); i++) - pmpeg->base.set_tile_region(dev, i); - - /* PMPEG init */ - nv_wr32(dev, 0x00b32c, 0x00000000); - nv_wr32(dev, 0x00b314, 0x00000100); - nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); - nv_wr32(dev, 0x00b300, 0x02001ec1); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); - - nv_wr32(dev, 0x00b100, 0xffffffff); - nv_wr32(dev, 0x00b140, 0xffffffff); - - if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); - return -EBUSY; - } - - return 0; -} - -static int -nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) -{ - /*XXX: context save? */ - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); - nv_wr32(dev, 0x00b140, 0x00000000); + 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 -nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) +nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len) { - struct drm_device *dev = chan->dev; - u32 inst = data << 4; - u32 dma0 = nv_ri32(dev, inst + 0); - u32 dma1 = nv_ri32(dev, inst + 4); - u32 dma2 = nv_ri32(dev, inst + 8); + struct nouveau_instmem *imem = nouveau_instmem(object); + struct nv31_mpeg_priv *priv = (void *)object->engine; + u32 inst = *(u32 *)arg << 4; + u32 dma0 = nv_ro32(imem, inst + 0); + u32 dma1 = nv_ro32(imem, inst + 4); + u32 dma2 = nv_ro32(imem, inst + 8); u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); u32 size = dma1 + 1; @@ -184,160 +87,215 @@ nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) if (mthd == 0x0190) { /* DMA_CMD */ - nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); - nv_wr32(dev, 0x00b334, base); - nv_wr32(dev, 0x00b324, size); + nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000)); + nv_wr32(priv, 0x00b334, base); + nv_wr32(priv, 0x00b324, size); } else if (mthd == 0x01a0) { /* DMA_DATA */ - nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); - nv_wr32(dev, 0x00b360, base); - nv_wr32(dev, 0x00b364, size); + nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); + nv_wr32(priv, 0x00b360, base); + nv_wr32(priv, 0x00b364, size); } else { /* DMA_IMAGE, VRAM only */ if (dma0 & 0x000c0000) return -EINVAL; - nv_wr32(dev, 0x00b370, base); - nv_wr32(dev, 0x00b374, size); + nv_wr32(priv, 0x00b370, base); + nv_wr32(priv, 0x00b374, size); } return 0; } +struct nouveau_ofuncs +nv31_mpeg_ofuncs = { + .ctor = nv31_mpeg_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; + +struct nouveau_omthds +nv31_mpeg_omthds[] = { + { 0x0190, nv31_mpeg_mthd_dma }, + { 0x01a0, nv31_mpeg_mthd_dma }, + { 0x01b0, nv31_mpeg_mthd_dma }, + {} +}; + +struct nouveau_oclass +nv31_mpeg_sclass[] = { + { 0x3174, &nv31_mpeg_ofuncs, nv31_mpeg_omthds }, + {} +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + static int -nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) +nv31_mpeg_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_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ctx; - unsigned long flags; - int i; - - /* hardcode drm channel id on nv3x, so swmthd lookup works */ - if (dev_priv->card_type < NV_40) - return 0; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (i = 0; i < pfifo->channels; i++) { - if (!dev_priv->channels.ptr[i]) - continue; - - ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; - if (ctx && ctx->addr == inst) - break; - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - return i; + struct nv31_mpeg_priv *priv = (void *)engine; + struct nv31_mpeg_chan *chan; + int ret; + + if (!atomic_add_unless(&priv->refcount, 1, 1)) + return -EBUSY; + + ret = nouveau_object_create(parent, engine, oclass, 0, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; } static void -nv31_vpe_set_tile_region(struct drm_device *dev, int i) +nv31_mpeg_context_dtor(struct nouveau_object *object) { - struct nouveau_fb_tile *tile = nvfb_tile(dev, i); - nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); - nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); - nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); + struct nv31_mpeg_priv *priv = (void *)object->engine; + struct nv31_mpeg_chan *chan = (void *)object; + atomic_dec(&priv->refcount); + nouveau_object_destroy(&chan->base); } -static void -nv31_mpeg_isr(struct drm_device *dev) +static struct nouveau_oclass +nv31_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x31), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv31_mpeg_context_ctor, + .dtor = nv31_mpeg_context_dtor, + .init = nouveau_object_init, + .fini = nouveau_object_fini, + }, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +void +nv31_mpeg_tile_prog(struct nouveau_engine *engine, int i) { - u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; - u32 chid = nv31_mpeg_isr_chid(dev, inst); - u32 stat = nv_rd32(dev, 0x00b100); - u32 type = nv_rd32(dev, 0x00b230); - u32 mthd = nv_rd32(dev, 0x00b234); - u32 data = nv_rd32(dev, 0x00b238); + struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i]; + struct nv31_mpeg_priv *priv = (void *)engine; + + nv_wr32(priv, 0x00b008 + (i * 0x10), tile->pitch); + nv_wr32(priv, 0x00b004 + (i * 0x10), tile->limit); + nv_wr32(priv, 0x00b000 + (i * 0x10), tile->addr); +} + +void +nv31_mpeg_intr(struct nouveau_subdev *subdev) +{ + struct nv31_mpeg_priv *priv = (void *)subdev; + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_handle *handle = NULL; + u32 inst = (nv_rd32(priv, 0x00b318) & 0x000fffff) << 4; + u32 stat = nv_rd32(priv, 0x00b100); + u32 type = nv_rd32(priv, 0x00b230); + u32 mthd = nv_rd32(priv, 0x00b234); + u32 data = nv_rd32(priv, 0x00b238); u32 show = stat; if (stat & 0x01000000) { /* happens on initial binding of the object */ - if (type == 0x00000020 && mthd == 0x0000) { - nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); + if (handle && type == 0x00000020 && mthd == 0x0000) { + nv_mask(priv, 0x00b308, 0x00000000, 0x00000000); show &= ~0x01000000; } - if (type == 0x00000010) { - if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) + if (handle && type == 0x00000010) { + handle = nouveau_engctx_lookup_class(engine, inst, 0x3174); + + if (handle && !nv_call(handle->object, mthd, data)) { + nouveau_engctx_handle_put(handle); show &= ~0x01000000; + } } } - nv_wr32(dev, 0x00b100, stat); - nv_wr32(dev, 0x00b230, 0x00000001); + nv_wr32(priv, 0x00b100, stat); + nv_wr32(priv, 0x00b230, 0x00000001); - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", - chid, inst, stat, type, mthd, data); + if (show) { + nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", + inst, stat, type, mthd, data); } } -static void -nv31_vpe_isr(struct drm_device *dev) +static int +nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (nv_rd32(dev, 0x00b100)) - nv31_mpeg_isr(dev); + struct nv31_mpeg_priv *priv; + int ret; - if (nv_rd32(dev, 0x00b800)) { - u32 stat = nv_rd32(dev, 0x00b800); - NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); - nv_wr32(dev, 0xb800, stat); - } + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000002; + nv_subdev(priv)->intr = nv31_mpeg_intr; + nv_engine(priv)->cclass = &nv31_mpeg_cclass; + nv_engine(priv)->sclass = nv31_mpeg_sclass; + nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; + return 0; } -static void -nv31_mpeg_destroy(struct drm_device *dev, int engine) +int +nv31_mpeg_init(struct nouveau_object *object) { - struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); + struct nouveau_engine *engine = nv_engine(object->engine); + struct nv31_mpeg_priv *priv = (void *)engine; + struct nouveau_fb *pfb = nouveau_fb(object); + int ret, i; - nouveau_irq_unregister(dev, 0); + ret = nouveau_mpeg_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_DEL(dev, MPEG); - kfree(pmpeg); -} + /* VPE init */ + nv_wr32(priv, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ + nv_wr32(priv, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -int -nv31_mpeg_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv31_mpeg_engine *pmpeg; - - pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); - if (!pmpeg) - return -ENOMEM; - atomic_set(&pmpeg->refcount, 0); - - pmpeg->base.destroy = nv31_mpeg_destroy; - pmpeg->base.init = nv31_mpeg_init; - pmpeg->base.fini = nv31_mpeg_fini; - if (dev_priv->card_type < NV_40) { - pmpeg->base.context_new = nv31_mpeg_context_new; - pmpeg->base.context_del = nv31_mpeg_context_del; - } else { - pmpeg->base.context_new = nv40_mpeg_context_new; - pmpeg->base.context_del = nv40_mpeg_context_del; + for (i = 0; i < pfb->tile.regions; i++) + engine->tile_prog(engine, i); + + /* PMPEG init */ + nv_wr32(priv, 0x00b32c, 0x00000000); + nv_wr32(priv, 0x00b314, 0x00000100); + nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031); + nv_wr32(priv, 0x00b300, 0x02001ec1); + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + + nv_wr32(priv, 0x00b100, 0xffffffff); + nv_wr32(priv, 0x00b140, 0xffffffff); + + if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) { + nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200)); + return -EBUSY; } - pmpeg->base.object_new = nv31_mpeg_object_new; - - /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between - * all VPE engines, for this driver's purposes the PMPEG engine - * will be treated as the "master" and handle the global VPE - * bits too - */ - pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; - nouveau_irq_register(dev, 0, nv31_vpe_isr); - - NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); - NVOBJ_CLASS(dev, 0x3174, MPEG); - NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); - NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); - NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); - -#if 0 - NVOBJ_ENGINE_ADD(dev, ME, &pme->base); - NVOBJ_CLASS(dev, 0x4075, ME); -#endif - return 0; + return 0; } + +struct nouveau_oclass +nv31_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x31), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv31_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv31_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c new file mode 100644 index 0000000..1241857 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c @@ -0,0 +1,144 @@ +/* + * 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: + * + * 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 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 +#include +#include + +#include +#include +#include + +#include +#include + +struct nv40_mpeg_priv { + struct nouveau_mpeg base; +}; + +struct nv40_mpeg_chan { + struct nouveau_mpeg base; +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + +static int +nv40_mpeg_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv40_mpeg_chan *chan; + int ret; + + ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL, + 264 * 4, 16, + NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; +} + +static int +nv40_mpeg_context_fini(struct nouveau_object *object, bool suspend) +{ + + struct nv40_mpeg_priv *priv = (void *)object->engine; + struct nv40_mpeg_chan *chan = (void *)object; + u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4; + + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000); + if (nv_rd32(priv, 0x00b318) == inst) + nv_mask(priv, 0x00b318, 0x80000000, 0x00000000); + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + return 0; +} + +static struct nouveau_oclass +nv40_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_mpeg_context_ctor, + .dtor = _nouveau_mpeg_context_dtor, + .init = _nouveau_mpeg_context_init, + .fini = nv40_mpeg_context_fini, + .rd32 = _nouveau_mpeg_context_rd32, + .wr32 = _nouveau_mpeg_context_wr32, + }, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +static void +nv40_mpeg_intr(struct nouveau_subdev *subdev) +{ + struct nv40_mpeg_priv *priv = (void *)subdev; + u32 stat; + + if ((stat = nv_rd32(priv, 0x00b100))) + nv31_mpeg_intr(subdev); + + if ((stat = nv_rd32(priv, 0x00b800))) { + nv_error(priv, "PMSRCH 0x%08x\n", stat); + nv_wr32(priv, 0x00b800, stat); + } +} + +static int +nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv40_mpeg_priv *priv; + int ret; + + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000002; + nv_subdev(priv)->intr = nv40_mpeg_intr; + nv_engine(priv)->cclass = &nv40_mpeg_cclass; + nv_engine(priv)->sclass = nv31_mpeg_sclass; + nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; + return 0; +} + +struct nouveau_oclass +nv40_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv31_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c index 4e3292e..8678a99 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,218 +22,219 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include +#include +#include +#include -struct nv50_mpeg_engine { - struct nouveau_exec_engine base; -}; +#include +#include +#include -static inline u32 -CTX_PTR(struct drm_device *dev, u32 offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; +#include - if (dev_priv->chipset == 0x50) - offset += 0x0260; - else - offset += 0x0060; +struct nv50_mpeg_priv { + struct nouveau_mpeg base; +}; - return offset; -} +struct nv50_mpeg_chan { + struct nouveau_mpeg_chan base; +}; + +/******************************************************************************* + * MPEG object classes + ******************************************************************************/ static int -nv50_mpeg_context_new(struct nouveau_channel *chan, int engine) +nv50_mpeg_object_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 *ramin = chan->ramin; - struct nouveau_gpuobj *ctx = NULL; + struct nouveau_gpuobj *obj; int ret; - NV_DEBUG(dev, "ch%d\n", chan->id); - - ret = nouveau_gpuobj_new(dev, chan, 128 * 4, 0, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &ctx); + ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent, + 16, 16, 0, &obj); + *pobject = nv_object(obj); if (ret) return ret; - nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002); - nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->addr + ctx->size - 1); - nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->addr); - nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0); - nv_wo32(ramin, CTX_PTR(dev, 0x10), 0); - nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000); - - nv_wo32(ctx, 0x70, 0x00801ec1); - nv_wo32(ctx, 0x7c, 0x0000037c); - nvimem_flush(dev); - - chan->engctx[engine] = ctx; + 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 void -nv50_mpeg_context_del(struct nouveau_channel *chan, int engine) -{ - struct nouveau_gpuobj *ctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - int i; +struct nouveau_ofuncs +nv50_mpeg_ofuncs = { + .ctor = nv50_mpeg_object_ctor, + .dtor = _nouveau_gpuobj_dtor, + .init = _nouveau_gpuobj_init, + .fini = _nouveau_gpuobj_fini, + .rd32 = _nouveau_gpuobj_rd32, + .wr32 = _nouveau_gpuobj_wr32, +}; - for (i = 0x00; i <= 0x14; i += 4) - nv_wo32(chan->ramin, CTX_PTR(dev, i), 0x00000000); +static struct nouveau_oclass +nv50_mpeg_sclass[] = { + { 0x3174, &nv50_mpeg_ofuncs }, + {} +}; - nouveau_gpuobj_ref(NULL, &ctx); - chan->engctx[engine] = NULL; -} +/******************************************************************************* + * PMPEG context + ******************************************************************************/ -static int -nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, - u32 handle, u16 class) +int +nv50_mpeg_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 nouveau_bar *bar = nouveau_bar(parent); + struct nv50_mpeg_chan *chan; int ret; - ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL, 128 * 4, + 0, NVOBJ_FLAG_ZERO_ALLOC, &chan); + *pobject = nv_object(chan); if (ret) return ret; - obj->engine = 2; - 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; -} -static void -nv50_mpeg_tlb_flush(struct drm_device *dev, int engine) -{ - nv50_vm_flush_engine(dev, 0x08); + nv_wo32(chan, 0x0070, 0x00801ec1); + nv_wo32(chan, 0x007c, 0x0000037c); + bar->flush(bar); + return 0; } -static int -nv50_mpeg_init(struct drm_device *dev, int engine) -{ - nv_wr32(dev, 0x00b32c, 0x00000000); - nv_wr32(dev, 0x00b314, 0x00000100); - nv_wr32(dev, 0x00b0e0, 0x0000001a); - - nv_wr32(dev, 0x00b220, 0x00000044); - nv_wr32(dev, 0x00b300, 0x00801ec1); - nv_wr32(dev, 0x00b390, 0x00000000); - nv_wr32(dev, 0x00b394, 0x00000000); - nv_wr32(dev, 0x00b398, 0x00000000); - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); - - nv_wr32(dev, 0x00b100, 0xffffffff); - nv_wr32(dev, 0x00b140, 0xffffffff); - - if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); - return -EBUSY; - } +static struct nouveau_oclass +nv50_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mpeg_context_ctor, + .dtor = _nouveau_mpeg_context_dtor, + .init = _nouveau_mpeg_context_init, + .fini = _nouveau_mpeg_context_fini, + .rd32 = _nouveau_mpeg_context_rd32, + .wr32 = _nouveau_mpeg_context_wr32, + }, +}; - return 0; -} +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ -static int -nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) +int +nv50_mpeg_tlb_flush(struct nouveau_engine *engine) { - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); - nv_wr32(dev, 0x00b140, 0x00000000); + nv50_vm_flush_engine(&engine->base, 0x08); return 0; } -static void -nv50_mpeg_isr(struct drm_device *dev) +void +nv50_mpeg_intr(struct nouveau_subdev *subdev) { - u32 stat = nv_rd32(dev, 0x00b100); - u32 type = nv_rd32(dev, 0x00b230); - u32 mthd = nv_rd32(dev, 0x00b234); - u32 data = nv_rd32(dev, 0x00b238); + struct nv50_mpeg_priv *priv = (void *)subdev; + u32 stat = nv_rd32(priv, 0x00b100); + u32 type = nv_rd32(priv, 0x00b230); + u32 mthd = nv_rd32(priv, 0x00b234); + u32 data = nv_rd32(priv, 0x00b238); u32 show = stat; if (stat & 0x01000000) { /* happens on initial binding of the object */ if (type == 0x00000020 && mthd == 0x0000) { - nv_wr32(dev, 0x00b308, 0x00000100); + nv_wr32(priv, 0x00b308, 0x00000100); show &= ~0x01000000; } } - if (show && nouveau_ratelimit()) { - NV_INFO(dev, "PMPEG - 0x%08x 0x%08x 0x%08x 0x%08x\n", + if (show) { + nv_info(priv, "0x%08x 0x%08x 0x%08x 0x%08x\n", stat, type, mthd, data); } - nv_wr32(dev, 0x00b100, stat); - nv_wr32(dev, 0x00b230, 0x00000001); - nv50_fb_vm_trap(dev, 1); + nv_wr32(priv, 0x00b100, stat); + nv_wr32(priv, 0x00b230, 0x00000001); + nv50_fb_trap(nouveau_fb(priv), 1); } static void -nv50_vpe_isr(struct drm_device *dev) +nv50_vpe_intr(struct nouveau_subdev *subdev) { - if (nv_rd32(dev, 0x00b100)) - nv50_mpeg_isr(dev); + struct nv50_mpeg_priv *priv = (void *)subdev; - if (nv_rd32(dev, 0x00b800)) { - u32 stat = nv_rd32(dev, 0x00b800); - NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); - nv_wr32(dev, 0xb800, stat); + if (nv_rd32(priv, 0x00b100)) + nv50_mpeg_intr(subdev); + + if (nv_rd32(priv, 0x00b800)) { + u32 stat = nv_rd32(priv, 0x00b800); + nv_info(priv, "PMSRCH: 0x%08x\n", stat); + nv_wr32(priv, 0xb800, stat); } } -static void -nv50_mpeg_destroy(struct drm_device *dev, int engine) +static int +nv50_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv50_mpeg_engine *pmpeg = nv_engine(dev, engine); + struct nv50_mpeg_priv *priv; + int ret; - nouveau_irq_unregister(dev, 0); + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - NVOBJ_ENGINE_DEL(dev, MPEG); - kfree(pmpeg); + nv_subdev(priv)->unit = 0x00400002; + nv_subdev(priv)->intr = nv50_vpe_intr; + nv_engine(priv)->cclass = &nv50_mpeg_cclass; + nv_engine(priv)->sclass = nv50_mpeg_sclass; + nv_engine(priv)->tlb_flush = nv50_mpeg_tlb_flush; + return 0; } int -nv50_mpeg_create(struct drm_device *dev) +nv50_mpeg_init(struct nouveau_object *object) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_mpeg_engine *pmpeg; - - pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); - if (!pmpeg) - return -ENOMEM; - - pmpeg->base.destroy = nv50_mpeg_destroy; - pmpeg->base.init = nv50_mpeg_init; - pmpeg->base.fini = nv50_mpeg_fini; - pmpeg->base.context_new = nv50_mpeg_context_new; - pmpeg->base.context_del = nv50_mpeg_context_del; - pmpeg->base.object_new = nv50_mpeg_object_new; - pmpeg->base.tlb_flush = nv50_mpeg_tlb_flush; - - if (dev_priv->chipset == 0x50) { - nouveau_irq_register(dev, 0, nv50_vpe_isr); - NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); - NVOBJ_CLASS(dev, 0x3174, MPEG); -#if 0 - NVOBJ_ENGINE_ADD(dev, ME, &pme->base); - NVOBJ_CLASS(dev, 0x4075, ME); -#endif - } else { - nouveau_irq_register(dev, 0, nv50_mpeg_isr); - NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); - NVOBJ_CLASS(dev, 0x8274, MPEG); + struct nv50_mpeg_priv *priv = (void *)object; + int ret; + + ret = nouveau_mpeg_init(&priv->base); + if (ret) + return ret; + + nv_wr32(priv, 0x00b32c, 0x00000000); + nv_wr32(priv, 0x00b314, 0x00000100); + nv_wr32(priv, 0x00b0e0, 0x0000001a); + + nv_wr32(priv, 0x00b220, 0x00000044); + nv_wr32(priv, 0x00b300, 0x00801ec1); + nv_wr32(priv, 0x00b390, 0x00000000); + nv_wr32(priv, 0x00b394, 0x00000000); + nv_wr32(priv, 0x00b398, 0x00000000); + nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); + + nv_wr32(priv, 0x00b100, 0xffffffff); + nv_wr32(priv, 0x00b140, 0xffffffff); + + if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) { + nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200)); + return -EBUSY; } return 0; - } + +struct nouveau_oclass +nv50_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv50_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c new file mode 100644 index 0000000..8f805b4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c @@ -0,0 +1,104 @@ +/* + * 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: + * + * 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 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 +#include +#include + +#include +#include +#include + +#include + +struct nv84_mpeg_priv { + struct nouveau_mpeg base; +}; + +struct nv84_mpeg_chan { + struct nouveau_mpeg_chan base; +}; + +/******************************************************************************* + * MPEG object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv84_mpeg_sclass[] = { + { 0x8274, &nv50_mpeg_ofuncs }, + {} +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + +static struct nouveau_oclass +nv84_mpeg_cclass = { + .handle = NV_ENGCTX(MPEG, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mpeg_context_ctor, + .dtor = _nouveau_mpeg_context_dtor, + .init = _nouveau_mpeg_context_init, + .fini = _nouveau_mpeg_context_fini, + .rd32 = _nouveau_mpeg_context_rd32, + .wr32 = _nouveau_mpeg_context_wr32, + }, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +static int +nv84_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv84_mpeg_priv *priv; + int ret; + + ret = nouveau_mpeg_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000002; + nv_subdev(priv)->intr = nv50_mpeg_intr; + nv_engine(priv)->cclass = &nv84_mpeg_cclass; + nv_engine(priv)->sclass = nv84_mpeg_sclass; + nv_engine(priv)->tlb_flush = nv50_mpeg_tlb_flush; + return 0; +} + +struct nouveau_oclass +nv84_mpeg_oclass = { + .handle = NV_ENGINE(MPEG, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_mpeg_ctor, + .dtor = _nouveau_mpeg_dtor, + .init = nv50_mpeg_init, + .fini = _nouveau_mpeg_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c index 384de6d..50e7e0d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,56 +22,154 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include -struct nv98_ppp_engine { - struct nouveau_exec_engine base; +#include + +struct nv98_ppp_priv { + struct nouveau_ppp base; +}; + +struct nv98_ppp_chan { + struct nouveau_ppp_chan base; }; +/******************************************************************************* + * PPP object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv98_ppp_sclass[] = { + {}, +}; + +/******************************************************************************* + * PPPP context + ******************************************************************************/ + static int -nv98_ppp_fini(struct drm_device *dev, int engine, bool suspend) +nv98_ppp_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (!(nv_rd32(dev, 0x000200) & 0x00000002)) - return 0; + struct nv98_ppp_chan *priv; + int ret; + + ret = nouveau_ppp_context_create(parent, engine, oclass, NULL, + 0, 0, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); return 0; } +static void +nv98_ppp_context_dtor(struct nouveau_object *object) +{ + struct nv98_ppp_chan *priv = (void *)object; + nouveau_ppp_context_destroy(&priv->base); +} + static int -nv98_ppp_init(struct drm_device *dev, int engine) +nv98_ppp_context_init(struct nouveau_object *object) { - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); - nv_mask(dev, 0x000200, 0x00000002, 0x00000002); + struct nv98_ppp_chan *priv = (void *)object; + int ret; + + ret = nouveau_ppp_context_init(&priv->base); + if (ret) + return ret; + return 0; } +static int +nv98_ppp_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv98_ppp_chan *priv = (void *)object; + return nouveau_ppp_context_fini(&priv->base, suspend); +} + +static struct nouveau_oclass +nv98_ppp_cclass = { + .handle = NV_ENGCTX(PPP, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_ppp_context_ctor, + .dtor = nv98_ppp_context_dtor, + .init = nv98_ppp_context_init, + .fini = nv98_ppp_context_fini, + .rd32 = _nouveau_ppp_context_rd32, + .wr32 = _nouveau_ppp_context_wr32, + }, +}; + +/******************************************************************************* + * PPPP engine/subdev functions + ******************************************************************************/ + static void -nv98_ppp_destroy(struct drm_device *dev, int engine) +nv98_ppp_intr(struct nouveau_subdev *subdev) { - struct nv98_ppp_engine *pppp = nv_engine(dev, engine); +} - NVOBJ_ENGINE_DEL(dev, PPP); +static int +nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv98_ppp_priv *priv; + int ret; + + ret = nouveau_ppp_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - kfree(pppp); + nv_subdev(priv)->unit = 0x00400002; + nv_subdev(priv)->intr = nv98_ppp_intr; + nv_engine(priv)->cclass = &nv98_ppp_cclass; + nv_engine(priv)->sclass = nv98_ppp_sclass; + return 0; } -int -nv98_ppp_create(struct drm_device *dev) +static void +nv98_ppp_dtor(struct nouveau_object *object) { - struct nv98_ppp_engine *pppp; + struct nv98_ppp_priv *priv = (void *)object; + nouveau_ppp_destroy(&priv->base); +} - pppp = kzalloc(sizeof(*pppp), GFP_KERNEL); - if (!pppp) - return -ENOMEM; +static int +nv98_ppp_init(struct nouveau_object *object) +{ + struct nv98_ppp_priv *priv = (void *)object; + int ret; - pppp->base.destroy = nv98_ppp_destroy; - pppp->base.init = nv98_ppp_init; - pppp->base.fini = nv98_ppp_fini; + ret = nouveau_ppp_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, PPP, &pppp->base); return 0; } + +static int +nv98_ppp_fini(struct nouveau_object *object, bool suspend) +{ + struct nv98_ppp_priv *priv = (void *)object; + return nouveau_ppp_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv98_ppp_oclass = { + .handle = NV_ENGINE(PPP, 0x98), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv98_ppp_ctor, + .dtor = nv98_ppp_dtor, + .init = nv98_ppp_init, + .fini = nv98_ppp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c new file mode 100644 index 0000000..f48da75 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c @@ -0,0 +1,140 @@ +/* + * 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: + * + * 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 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 +#include +#include + +#include +#include + +struct nv04_software_priv { + struct nouveau_software base; +}; + +struct nv04_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nv04_software_set_ref(struct nouveau_object *object, u32 mthd, + void *data, u32 size) +{ + struct nouveau_object *channel = (void *)nv_engctx(object->parent); + struct nouveau_fifo_chan *fifo = (void *)channel->parent; + atomic_set(&fifo->refcnt, *(u32*)data); + return 0; +} + +static int +nv04_software_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv04_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nv04_software_omthds[] = { + { 0x0150, nv04_software_set_ref }, + { 0x0500, nv04_software_flip }, + {} +}; + +static struct nouveau_oclass +nv04_software_sclass[] = { + { 0x006e, &nouveau_object_ofuncs, nv04_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nv04_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; +} + +static struct nouveau_oclass +nv04_software_cclass = { + .handle = NV_ENGCTX(SW, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nv04_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nv04_software_cclass; + nv_engine(priv)->sclass = nv04_software_sclass; + return 0; +} + +struct nouveau_oclass +nv04_software_oclass = { + .handle = NV_ENGINE(SW, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c new file mode 100644 index 0000000..46dada5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c @@ -0,0 +1,128 @@ +/* + * 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: + * + * 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 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 +#include +#include + +#include + +struct nv10_software_priv { + struct nouveau_software base; +}; + +struct nv10_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nv10_software_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv10_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nv10_software_omthds[] = { + { 0x0500, nv10_software_flip }, + {} +}; + +static struct nouveau_oclass +nv10_software_sclass[] = { + { 0x016e, &nouveau_object_ofuncs, nv10_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nv10_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv10_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + return 0; +} + +static struct nouveau_oclass +nv10_software_cclass = { + .handle = NV_ENGCTX(SW, 0x04), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nv10_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv10_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nv10_software_cclass; + nv_engine(priv)->sclass = nv10_software_sclass; + return 0; +} + +struct nouveau_oclass +nv10_software_oclass = { + .handle = NV_ENGINE(SW, 0x10), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv10_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c new file mode 100644 index 0000000..6b88971 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -0,0 +1,198 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include +#include +#include + +#include +#include + +struct nv50_software_priv { + struct nouveau_software base; +}; + +struct nv50_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nv50_software_mthd_dma_vblsem(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + struct nouveau_fifo_chan *fifo = (void *)nv_object(chan)->parent; + struct nouveau_handle *handle; + int ret = -EINVAL; + + handle = nouveau_namedb_get(nv_namedb(fifo), *(u32 *)args); + if (!handle) + return -ENOENT; + + if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { + struct nouveau_gpuobj *gpuobj = nv_gpuobj(handle->object); + chan->base.vblank.ctxdma = gpuobj->node->offset >> 4; + ret = 0; + } + nouveau_namedb_put(handle); + return ret; +} + +static int +nv50_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + chan->base.vblank.offset = *(u32 *)args; + return 0; +} + +static int +nv50_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + chan->base.vblank.value = *(u32 *)args; + return 0; +} + +static int +nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + struct nouveau_disp *disp = nouveau_disp(object); + unsigned long flags; + u32 crtc = *(u32 *)args; + + if (crtc > 1) + return -EINVAL; + + disp->vblank.get(disp->vblank.data, crtc); + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_add(&chan->base.vblank.head, &disp->vblank.list); + chan->base.vblank.crtc = crtc; + spin_unlock_irqrestore(&disp->vblank.lock, flags); + return 0; +} + +static int +nv50_software_mthd_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nv50_software_omthds[] = { + { 0x018c, nv50_software_mthd_dma_vblsem }, + { 0x0400, nv50_software_mthd_vblsem_offset }, + { 0x0404, nv50_software_mthd_vblsem_value }, + { 0x0408, nv50_software_mthd_vblsem_release }, + { 0x0500, nv50_software_mthd_flip }, + {} +}; + +static struct nouveau_oclass +nv50_software_sclass[] = { + { 0x506e, &nouveau_object_ofuncs, nv50_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nv50_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; + return 0; +} + +static struct nouveau_oclass +nv50_software_cclass = { + .handle = NV_ENGCTX(SW, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nv50_software_cclass; + nv_engine(priv)->sclass = nv50_software_sclass; + return 0; +} + +struct nouveau_oclass +nv50_software_oclass = { + .handle = NV_ENGINE(SW, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c new file mode 100644 index 0000000..e3be78f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -0,0 +1,180 @@ +/* + * 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: + * + * 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 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 +#include +#include + +#include +#include + +struct nvc0_software_priv { + struct nouveau_software base; +}; + +struct nvc0_software_chan { + struct nouveau_software_chan base; +}; + +/******************************************************************************* + * software object classes + ******************************************************************************/ + +static int +nvc0_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + u64 data = *(u32 *)args; + if (mthd == 0x0400) { + chan->base.vblank.offset &= 0x00ffffffffULL; + chan->base.vblank.offset |= data << 32; + } else { + chan->base.vblank.offset &= 0xff00000000ULL; + chan->base.vblank.offset |= data; + } + return 0; +} + +static int +nvc0_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + chan->base.vblank.value = *(u32 *)args; + return 0; +} + +static int +nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + struct nouveau_disp *disp = nouveau_disp(object); + unsigned long flags; + u32 crtc = *(u32 *)args; + + if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) + return -EINVAL; + + disp->vblank.get(disp->vblank.data, crtc); + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_add(&chan->base.vblank.head, &disp->vblank.list); + chan->base.vblank.crtc = crtc; + spin_unlock_irqrestore(&disp->vblank.lock, flags); + return 0; +} + +static int +nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd, + void *args, u32 size) +{ + struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); + if (chan->base.flip) + return chan->base.flip(chan->base.flip_data); + return -EINVAL; +} + +static struct nouveau_omthds +nvc0_software_omthds[] = { + { 0x0400, nvc0_software_mthd_vblsem_offset }, + { 0x0404, nvc0_software_mthd_vblsem_offset }, + { 0x0408, nvc0_software_mthd_vblsem_value }, + { 0x040c, nvc0_software_mthd_vblsem_release }, + { 0x0500, nvc0_software_mthd_flip }, + {} +}; + +static struct nouveau_oclass +nvc0_software_sclass[] = { + { 0x906e, &nouveau_object_ofuncs, nvc0_software_omthds }, + {} +}; + +/******************************************************************************* + * software context + ******************************************************************************/ + +static int +nvc0_software_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_software_chan *chan; + int ret; + + ret = nouveau_software_context_create(parent, engine, oclass, &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; + return 0; +} + +static struct nouveau_oclass +nvc0_software_cclass = { + .handle = NV_ENGCTX(SW, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_software_context_ctor, + .dtor = _nouveau_software_context_dtor, + .init = _nouveau_software_context_init, + .fini = _nouveau_software_context_fini, + }, +}; + +/******************************************************************************* + * software engine/subdev functions + ******************************************************************************/ + +static int +nvc0_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_software_priv *priv; + int ret; + + ret = nouveau_software_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_engine(priv)->cclass = &nvc0_software_cclass; + nv_engine(priv)->sclass = nvc0_software_sclass; + return 0; +} + +struct nouveau_oclass +nvc0_software_oclass = { + .handle = NV_ENGINE(SW, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_software_ctor, + .dtor = _nouveau_software_dtor, + .init = _nouveau_software_init, + .fini = _nouveau_software_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c index 5e164a6..dd23c80 100644 --- a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 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,61 +22,154 @@ * Authors: Ben Skeggs */ -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include +#include +#include +#include -/*XXX: This stub is currently used on NV98+ also, as soon as this becomes - * more than just an enable/disable stub this needs to be split out to - * nv98_vp.c... - */ +#include + +struct nv84_vp_priv { + struct nouveau_vp base; +}; -struct nv84_vp_engine { - struct nouveau_exec_engine base; +struct nv84_vp_chan { + struct nouveau_vp_chan base; }; +/******************************************************************************* + * VP object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv84_vp_sclass[] = { + {}, +}; + +/******************************************************************************* + * PVP context + ******************************************************************************/ + static int -nv84_vp_fini(struct drm_device *dev, int engine, bool suspend) +nv84_vp_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - if (!(nv_rd32(dev, 0x000200) & 0x00020000)) - return 0; + struct nv84_vp_chan *priv; + int ret; + + ret = nouveau_vp_context_create(parent, engine, oclass, NULL, + 0, 0, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - nv_mask(dev, 0x000200, 0x00020000, 0x00000000); return 0; } +static void +nv84_vp_context_dtor(struct nouveau_object *object) +{ + struct nv84_vp_chan *priv = (void *)object; + nouveau_vp_context_destroy(&priv->base); +} + static int -nv84_vp_init(struct drm_device *dev, int engine) +nv84_vp_context_init(struct nouveau_object *object) { - nv_mask(dev, 0x000200, 0x00020000, 0x00000000); - nv_mask(dev, 0x000200, 0x00020000, 0x00020000); + struct nv84_vp_chan *priv = (void *)object; + int ret; + + ret = nouveau_vp_context_init(&priv->base); + if (ret) + return ret; + return 0; } +static int +nv84_vp_context_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_vp_chan *priv = (void *)object; + return nouveau_vp_context_fini(&priv->base, suspend); +} + +static struct nouveau_oclass +nv84_vp_cclass = { + .handle = NV_ENGCTX(VP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_vp_context_ctor, + .dtor = nv84_vp_context_dtor, + .init = nv84_vp_context_init, + .fini = nv84_vp_context_fini, + .rd32 = _nouveau_vp_context_rd32, + .wr32 = _nouveau_vp_context_wr32, + }, +}; + +/******************************************************************************* + * PVP engine/subdev functions + ******************************************************************************/ + static void -nv84_vp_destroy(struct drm_device *dev, int engine) +nv84_vp_intr(struct nouveau_subdev *subdev) { - struct nv84_vp_engine *pvp = nv_engine(dev, engine); +} - NVOBJ_ENGINE_DEL(dev, VP); +static int +nv84_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv84_vp_priv *priv; + int ret; + + ret = nouveau_vp_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; - kfree(pvp); + nv_subdev(priv)->unit = 0x01020000; + nv_subdev(priv)->intr = nv84_vp_intr; + nv_engine(priv)->cclass = &nv84_vp_cclass; + nv_engine(priv)->sclass = nv84_vp_sclass; + return 0; } -int -nv84_vp_create(struct drm_device *dev) +static void +nv84_vp_dtor(struct nouveau_object *object) { - struct nv84_vp_engine *pvp; + struct nv84_vp_priv *priv = (void *)object; + nouveau_vp_destroy(&priv->base); +} - pvp = kzalloc(sizeof(*pvp), GFP_KERNEL); - if (!pvp) - return -ENOMEM; +static int +nv84_vp_init(struct nouveau_object *object) +{ + struct nv84_vp_priv *priv = (void *)object; + int ret; - pvp->base.destroy = nv84_vp_destroy; - pvp->base.init = nv84_vp_init; - pvp->base.fini = nv84_vp_fini; + ret = nouveau_vp_init(&priv->base); + if (ret) + return ret; - NVOBJ_ENGINE_ADD(dev, VP, &pvp->base); return 0; } + +static int +nv84_vp_fini(struct nouveau_object *object, bool suspend) +{ + struct nv84_vp_priv *priv = (void *)object; + return nouveau_vp_fini(&priv->base, suspend); +} + +struct nouveau_oclass +nv84_vp_oclass = { + .handle = NV_ENGINE(VP, 0x84), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv84_vp_ctor, + .dtor = nv84_vp_dtor, + .init = nv84_vp_init, + .fini = nv84_vp_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/include/core/ramht.h b/drivers/gpu/drm/nouveau/core/include/core/ramht.h index c82de98..47e4cac 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/ramht.h +++ b/drivers/gpu/drm/nouveau/core/include/core/ramht.h @@ -1,55 +1,23 @@ -/* - * Copyright 2010 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: - * - * 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 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 - */ - #ifndef __NOUVEAU_RAMHT_H__ #define __NOUVEAU_RAMHT_H__ -struct nouveau_ramht_entry { - struct list_head head; - struct nouveau_channel *channel; - struct nouveau_gpuobj *gpuobj; - u32 handle; -}; +#include struct nouveau_ramht { - struct drm_device *dev; - struct kref refcount; - spinlock_t lock; - struct nouveau_gpuobj *gpuobj; - struct list_head entries; + struct nouveau_gpuobj base; int bits; }; -extern int nouveau_ramht_new(struct drm_device *, struct nouveau_gpuobj *, - struct nouveau_ramht **); -extern void nouveau_ramht_ref(struct nouveau_ramht *, struct nouveau_ramht **, - struct nouveau_channel *unref_channel); +int nouveau_ramht_insert(struct nouveau_ramht *, int chid, + u32 handle, u32 context); +void nouveau_ramht_remove(struct nouveau_ramht *, int cookie); +int nouveau_ramht_new(struct nouveau_object *, struct nouveau_object *, + u32 size, u32 align, struct nouveau_ramht **); -extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, - struct nouveau_gpuobj *); -extern int nouveau_ramht_remove(struct nouveau_channel *, u32 handle); -extern struct nouveau_gpuobj * -nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); +static inline void +nouveau_ramht_ref(struct nouveau_ramht *obj, struct nouveau_ramht **ref) +{ + nouveau_gpuobj_ref(&obj->base, (struct nouveau_gpuobj **)ref); +} #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/bsp.h b/drivers/gpu/drm/nouveau/core/include/engine/bsp.h new file mode 100644 index 0000000..75d1ed5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/bsp.h @@ -0,0 +1,45 @@ +#ifndef __NOUVEAU_BSP_H__ +#define __NOUVEAU_BSP_H__ + +#include +#include + +struct nouveau_bsp_chan { + struct nouveau_engctx base; +}; + +#define nouveau_bsp_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_bsp_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_bsp_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_bsp_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_bsp_context_dtor _nouveau_engctx_dtor +#define _nouveau_bsp_context_init _nouveau_engctx_init +#define _nouveau_bsp_context_fini _nouveau_engctx_fini +#define _nouveau_bsp_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_bsp_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_bsp { + struct nouveau_engine base; +}; + +#define nouveau_bsp_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PBSP", "bsp", (d)) +#define nouveau_bsp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_bsp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_bsp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_bsp_dtor _nouveau_engine_dtor +#define _nouveau_bsp_init _nouveau_engine_init +#define _nouveau_bsp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv84_bsp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/copy.h b/drivers/gpu/drm/nouveau/core/include/engine/copy.h new file mode 100644 index 0000000..23bb9df --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/copy.h @@ -0,0 +1,47 @@ +#ifndef __NOUVEAU_COPY_H__ +#define __NOUVEAU_COPY_H__ + +#include +#include + +struct nouveau_copy_chan { + struct nouveau_engctx base; +}; + +#define nouveau_copy_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_copy_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_copy_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_copy_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_copy_context_dtor _nouveau_engctx_dtor +#define _nouveau_copy_context_init _nouveau_engctx_init +#define _nouveau_copy_context_fini _nouveau_engctx_fini +#define _nouveau_copy_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_copy_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_copy { + struct nouveau_engine base; +}; + +#define nouveau_copy_create(p,e,c,y,i,d) \ + nouveau_engine_create((p), (e), (c), (y), "PCE"#i, "copy"#i, (d)) +#define nouveau_copy_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_copy_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_copy_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_copy_dtor _nouveau_engine_dtor +#define _nouveau_copy_init _nouveau_engine_init +#define _nouveau_copy_fini _nouveau_engine_fini + +extern struct nouveau_oclass nva3_copy_oclass; +extern struct nouveau_oclass nvc0_copy0_oclass; +extern struct nouveau_oclass nvc0_copy1_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/crypt.h b/drivers/gpu/drm/nouveau/core/include/engine/crypt.h new file mode 100644 index 0000000..e3674743 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/crypt.h @@ -0,0 +1,46 @@ +#ifndef __NOUVEAU_CRYPT_H__ +#define __NOUVEAU_CRYPT_H__ + +#include +#include + +struct nouveau_crypt_chan { + struct nouveau_engctx base; +}; + +#define nouveau_crypt_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_crypt_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_crypt_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_crypt_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_crypt_context_dtor _nouveau_engctx_dtor +#define _nouveau_crypt_context_init _nouveau_engctx_init +#define _nouveau_crypt_context_fini _nouveau_engctx_fini +#define _nouveau_crypt_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_crypt_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_crypt { + struct nouveau_engine base; +}; + +#define nouveau_crypt_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PCRYPT", "crypt", (d)) +#define nouveau_crypt_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_crypt_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_crypt_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_crypt_dtor _nouveau_engine_dtor +#define _nouveau_crypt_init _nouveau_engine_init +#define _nouveau_crypt_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv84_crypt_oclass; +extern struct nouveau_oclass nv98_crypt_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h new file mode 100644 index 0000000..38ec125 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h @@ -0,0 +1,44 @@ +#ifndef __NOUVEAU_DISP_H__ +#define __NOUVEAU_DISP_H__ + +#include +#include +#include + +struct nouveau_disp { + struct nouveau_engine base; + + struct { + struct list_head list; + spinlock_t lock; + void (*notify)(void *, int); + void (*get)(void *, int); + void (*put)(void *, int); + void *data; + } vblank; +}; + +static inline struct nouveau_disp * +nouveau_disp(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP]; +} + +#define nouveau_disp_create(p,e,c,i,x,d) \ + nouveau_engine_create((p), (e), (c), true, (i), (x), (d)) +#define nouveau_disp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_disp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_disp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_disp_dtor _nouveau_engine_dtor +#define _nouveau_disp_init _nouveau_engine_init +#define _nouveau_disp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_disp_oclass; +extern struct nouveau_oclass nv50_disp_oclass; +extern struct nouveau_oclass nvd0_disp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h new file mode 100644 index 0000000..700ccbb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h @@ -0,0 +1,57 @@ +#ifndef __NOUVEAU_DMAOBJ_H__ +#define __NOUVEAU_DMAOBJ_H__ + +#include +#include + +struct nouveau_gpuobj; + +struct nouveau_dmaobj { + struct nouveau_object base; + u32 target; + u32 access; + u64 start; + u64 limit; +}; + +#define nouveau_dmaobj_create(p,e,c,a,s,d) \ + nouveau_dmaobj_create_((p), (e), (c), (a), (s), sizeof(**d), (void **)d) +#define nouveau_dmaobj_destroy(p) \ + nouveau_object_destroy(&(p)->base) +#define nouveau_dmaobj_init(p) \ + nouveau_object_init(&(p)->base) +#define nouveau_dmaobj_fini(p,s) \ + nouveau_object_fini(&(p)->base, (s)) + +int nouveau_dmaobj_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *data, u32 size, + int length, void **); + +#define _nouveau_dmaobj_dtor nouveau_object_destroy +#define _nouveau_dmaobj_init nouveau_object_init +#define _nouveau_dmaobj_fini nouveau_object_fini + +struct nouveau_dmaeng { + struct nouveau_engine base; + int (*bind)(struct nouveau_dmaeng *, struct nouveau_object *parent, + struct nouveau_dmaobj *, struct nouveau_gpuobj **); +}; + +#define nouveau_dmaeng_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "DMAOBJ", "dmaobj", (d)) +#define nouveau_dmaeng_destroy(p) \ + nouveau_engine_destroy(&(p)->base) +#define nouveau_dmaeng_init(p) \ + nouveau_engine_init(&(p)->base) +#define nouveau_dmaeng_fini(p,s) \ + nouveau_engine_fini(&(p)->base, (s)) + +#define _nouveau_dmaeng_dtor _nouveau_engine_dtor +#define _nouveau_dmaeng_init _nouveau_engine_init +#define _nouveau_dmaeng_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_dmaeng_oclass; +extern struct nouveau_oclass nv50_dmaeng_oclass; +extern struct nouveau_oclass nvc0_dmaeng_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index ce99cab..65ee929 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -1,32 +1,109 @@ #ifndef __NOUVEAU_FIFO_H__ #define __NOUVEAU_FIFO_H__ -struct nouveau_fifo_priv { - struct nouveau_exec_engine base; - u32 channels; -}; +#include +#include +#include struct nouveau_fifo_chan { + struct nouveau_namedb base; + struct nouveau_dmaobj *pushdma; + struct nouveau_gpuobj *pushgpu; + void __iomem *user; + u32 size; + u16 chid; + atomic_t refcnt; /* NV04_NVSW_SET_REF */ +}; + +static inline struct nouveau_fifo_chan * +nouveau_fifo_chan(void *obj) +{ + return (void *)nv_namedb(obj); +} + +#define nouveau_fifo_channel_create(p,e,c,b,a,s,n,m,d) \ + nouveau_fifo_channel_create_((p), (e), (c), (b), (a), (s), (n), \ + (m), sizeof(**d), (void **)d) +#define nouveau_fifo_channel_init(p) \ + nouveau_namedb_init(&(p)->base) +#define nouveau_fifo_channel_fini(p,s) \ + nouveau_namedb_fini(&(p)->base, (s)) + +int nouveau_fifo_channel_create_(struct nouveau_object *, + struct nouveau_object *, + struct nouveau_oclass *, + int bar, u32 addr, u32 size, u32 push, + u32 engmask, int len, void **); +void nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *); + +#define _nouveau_fifo_channel_init _nouveau_namedb_init +#define _nouveau_fifo_channel_fini _nouveau_namedb_fini + +void _nouveau_fifo_channel_dtor(struct nouveau_object *); +u32 _nouveau_fifo_channel_rd32(struct nouveau_object *, u32); +void _nouveau_fifo_channel_wr32(struct nouveau_object *, u32, u32); + +struct nouveau_fifo_base { + struct nouveau_gpuobj base; }; -bool nv04_fifo_cache_pull(struct drm_device *, bool); -void nv04_fifo_context_del(struct nouveau_channel *, int); -int nv04_fifo_fini(struct drm_device *, int, bool); -int nv04_fifo_init(struct drm_device *, int); -void nv04_fifo_isr(struct drm_device *); -void nv04_fifo_destroy(struct drm_device *, int); - -void nv50_fifo_playlist_update(struct drm_device *); -void nv50_fifo_destroy(struct drm_device *, int); -void nv50_fifo_tlb_flush(struct drm_device *, int); - -int nv04_fifo_create(struct drm_device *); -int nv10_fifo_create(struct drm_device *); -int nv17_fifo_create(struct drm_device *); -int nv40_fifo_create(struct drm_device *); -int nv50_fifo_create(struct drm_device *); -int nv84_fifo_create(struct drm_device *); -int nvc0_fifo_create(struct drm_device *); -int nve0_fifo_create(struct drm_device *); +#define nouveau_fifo_context_create(p,e,c,g,s,a,f,d) \ + nouveau_gpuobj_create((p), (e), (c), 0, (g), (s), (a), (f), (d)) +#define nouveau_fifo_context_destroy(p) \ + nouveau_gpuobj_destroy(&(p)->base) +#define nouveau_fifo_context_init(p) \ + nouveau_gpuobj_init(&(p)->base) +#define nouveau_fifo_context_fini(p,s) \ + nouveau_gpuobj_fini(&(p)->base, (s)) + +#define _nouveau_fifo_context_dtor _nouveau_gpuobj_dtor +#define _nouveau_fifo_context_init _nouveau_gpuobj_init +#define _nouveau_fifo_context_fini _nouveau_gpuobj_fini +#define _nouveau_fifo_context_rd32 _nouveau_gpuobj_rd32 +#define _nouveau_fifo_context_wr32 _nouveau_gpuobj_wr32 + +struct nouveau_fifo { + struct nouveau_engine base; + + struct nouveau_object **channel; + spinlock_t lock; + u16 min; + u16 max; + + void (*pause)(struct nouveau_fifo *, unsigned long *); + void (*start)(struct nouveau_fifo *, unsigned long *); +}; + +static inline struct nouveau_fifo * +nouveau_fifo(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_FIFO]; +} + +#define nouveau_fifo_create(o,e,c,fc,lc,d) \ + nouveau_fifo_create_((o), (e), (c), (fc), (lc), sizeof(**d), (void **)d) +#define nouveau_fifo_init(p) \ + nouveau_engine_init(&(p)->base) +#define nouveau_fifo_fini(p,s) \ + nouveau_engine_fini(&(p)->base, (s)) + +int nouveau_fifo_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int min, int max, + int size, void **); +void nouveau_fifo_destroy(struct nouveau_fifo *); + +#define _nouveau_fifo_init _nouveau_engine_init +#define _nouveau_fifo_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_fifo_oclass; +extern struct nouveau_oclass nv10_fifo_oclass; +extern struct nouveau_oclass nv17_fifo_oclass; +extern struct nouveau_oclass nv40_fifo_oclass; +extern struct nouveau_oclass nv50_fifo_oclass; +extern struct nouveau_oclass nv84_fifo_oclass; +extern struct nouveau_oclass nvc0_fifo_oclass; +extern struct nouveau_oclass nve0_fifo_oclass; + +void nv04_fifo_intr(struct nouveau_subdev *); #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h new file mode 100644 index 0000000..388cfcf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h @@ -0,0 +1,72 @@ +#ifndef __NOUVEAU_GRAPH_H__ +#define __NOUVEAU_GRAPH_H__ + +#include +#include +#include + +struct nouveau_graph_chan { + struct nouveau_engctx base; +}; + +#define nouveau_graph_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_graph_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_graph_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_graph_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_graph_context_dtor _nouveau_engctx_dtor +#define _nouveau_graph_context_init _nouveau_engctx_init +#define _nouveau_graph_context_fini _nouveau_engctx_fini +#define _nouveau_graph_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_graph_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_graph { + struct nouveau_engine base; +}; + +static inline struct nouveau_graph * +nouveau_graph(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_GR]; +} + +#define nouveau_graph_create(p,e,c,y,d) \ + nouveau_engine_create((p), (e), (c), (y), "PGRAPH", "graphics", (d)) +#define nouveau_graph_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_graph_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_graph_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_graph_dtor _nouveau_engine_dtor +#define _nouveau_graph_init _nouveau_engine_init +#define _nouveau_graph_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_graph_oclass; +extern struct nouveau_oclass nv10_graph_oclass; +extern struct nouveau_oclass nv20_graph_oclass; +extern struct nouveau_oclass nv25_graph_oclass; +extern struct nouveau_oclass nv2a_graph_oclass; +extern struct nouveau_oclass nv30_graph_oclass; +extern struct nouveau_oclass nv34_graph_oclass; +extern struct nouveau_oclass nv35_graph_oclass; +extern struct nouveau_oclass nv40_graph_oclass; +extern struct nouveau_oclass nv50_graph_oclass; +extern struct nouveau_oclass nvc0_graph_oclass; +extern struct nouveau_oclass nve0_graph_oclass; + +extern struct nouveau_bitfield nv04_graph_nsource[]; +extern struct nouveau_ofuncs nv04_graph_ofuncs; +bool nv04_graph_idle(void *obj); + +extern struct nouveau_bitfield nv10_graph_intr_name[]; +extern struct nouveau_bitfield nv10_graph_nstatus[]; + +extern struct nouveau_enum nv50_data_error_names[]; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h new file mode 100644 index 0000000..bbf0d4a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h @@ -0,0 +1,61 @@ +#ifndef __NOUVEAU_MPEG_H__ +#define __NOUVEAU_MPEG_H__ + +#include +#include + +struct nouveau_mpeg_chan { + struct nouveau_engctx base; +}; + +#define nouveau_mpeg_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_mpeg_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_mpeg_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_mpeg_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_mpeg_context_dtor _nouveau_engctx_dtor +#define _nouveau_mpeg_context_init _nouveau_engctx_init +#define _nouveau_mpeg_context_fini _nouveau_engctx_fini +#define _nouveau_mpeg_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_mpeg_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_mpeg { + struct nouveau_engine base; +}; + +#define nouveau_mpeg_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PMPEG", "mpeg", (d)) +#define nouveau_mpeg_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_mpeg_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_mpeg_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_mpeg_dtor _nouveau_engine_dtor +#define _nouveau_mpeg_init _nouveau_engine_init +#define _nouveau_mpeg_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv31_mpeg_oclass; +extern struct nouveau_oclass nv40_mpeg_oclass; +extern struct nouveau_oclass nv50_mpeg_oclass; +extern struct nouveau_oclass nv84_mpeg_oclass; + +extern struct nouveau_oclass nv31_mpeg_sclass[]; +void nv31_mpeg_intr(struct nouveau_subdev *); +void nv31_mpeg_tile_prog(struct nouveau_engine *, int); +int nv31_mpeg_init(struct nouveau_object *); + +extern struct nouveau_ofuncs nv50_mpeg_ofuncs; +int nv50_mpeg_context_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +int nv50_mpeg_tlb_flush(struct nouveau_engine *); +void nv50_mpeg_intr(struct nouveau_subdev *); +int nv50_mpeg_init(struct nouveau_object *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/ppp.h b/drivers/gpu/drm/nouveau/core/include/engine/ppp.h new file mode 100644 index 0000000..74d554f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/ppp.h @@ -0,0 +1,45 @@ +#ifndef __NOUVEAU_PPP_H__ +#define __NOUVEAU_PPP_H__ + +#include +#include + +struct nouveau_ppp_chan { + struct nouveau_engctx base; +}; + +#define nouveau_ppp_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_ppp_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_ppp_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_ppp_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_ppp_context_dtor _nouveau_engctx_dtor +#define _nouveau_ppp_context_init _nouveau_engctx_init +#define _nouveau_ppp_context_fini _nouveau_engctx_fini +#define _nouveau_ppp_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_ppp_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_ppp { + struct nouveau_engine base; +}; + +#define nouveau_ppp_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PPPP", "ppp", (d)) +#define nouveau_ppp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_ppp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_ppp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_ppp_dtor _nouveau_engine_dtor +#define _nouveau_ppp_init _nouveau_engine_init +#define _nouveau_ppp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv98_ppp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/software.h b/drivers/gpu/drm/nouveau/core/include/engine/software.h new file mode 100644 index 0000000..8d74079 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/software.h @@ -0,0 +1,58 @@ +#ifndef __NOUVEAU_SOFTWARE_H__ +#define __NOUVEAU_SOFTWARE_H__ + +#include +#include + +struct nouveau_software_chan { + struct nouveau_engctx base; + + struct { + struct list_head head; + u32 channel; + u32 ctxdma; + u64 offset; + u32 value; + u32 crtc; + } vblank; + + int (*flip)(void *); + void *flip_data; +}; + +#define nouveau_software_context_create(p,e,c,d) \ + nouveau_engctx_create((p), (e), (c), (p), 0, 0, 0, (d)) +#define nouveau_software_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_software_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_software_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_software_context_dtor _nouveau_engctx_dtor +#define _nouveau_software_context_init _nouveau_engctx_init +#define _nouveau_software_context_fini _nouveau_engctx_fini + +struct nouveau_software { + struct nouveau_engine base; +}; + +#define nouveau_software_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "SW", "software", (d)) +#define nouveau_software_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_software_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_software_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_software_dtor _nouveau_engine_dtor +#define _nouveau_software_init _nouveau_engine_init +#define _nouveau_software_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv04_software_oclass; +extern struct nouveau_oclass nv10_software_oclass; +extern struct nouveau_oclass nv50_software_oclass; +extern struct nouveau_oclass nvc0_software_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/vp.h b/drivers/gpu/drm/nouveau/core/include/engine/vp.h new file mode 100644 index 0000000..05cd08f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/vp.h @@ -0,0 +1,45 @@ +#ifndef __NOUVEAU_VP_H__ +#define __NOUVEAU_VP_H__ + +#include +#include + +struct nouveau_vp_chan { + struct nouveau_engctx base; +}; + +#define nouveau_vp_context_create(p,e,c,g,s,a,f,d) \ + nouveau_engctx_create((p), (e), (c), (g), (s), (a), (f), (d)) +#define nouveau_vp_context_destroy(d) \ + nouveau_engctx_destroy(&(d)->base) +#define nouveau_vp_context_init(d) \ + nouveau_engctx_init(&(d)->base) +#define nouveau_vp_context_fini(d,s) \ + nouveau_engctx_fini(&(d)->base, (s)) + +#define _nouveau_vp_context_dtor _nouveau_engctx_dtor +#define _nouveau_vp_context_init _nouveau_engctx_init +#define _nouveau_vp_context_fini _nouveau_engctx_fini +#define _nouveau_vp_context_rd32 _nouveau_engctx_rd32 +#define _nouveau_vp_context_wr32 _nouveau_engctx_wr32 + +struct nouveau_vp { + struct nouveau_engine base; +}; + +#define nouveau_vp_create(p,e,c,d) \ + nouveau_engine_create((p), (e), (c), true, "PVP", "vp", (d)) +#define nouveau_vp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) +#define nouveau_vp_init(d) \ + nouveau_engine_init(&(d)->base) +#define nouveau_vp_fini(d,s) \ + nouveau_engine_fini(&(d)->base, (s)) + +#define _nouveau_vp_dtor _nouveau_engine_dtor +#define _nouveau_vp_init _nouveau_engine_init +#define _nouveau_vp_fini _nouveau_engine_fini + +extern struct nouveau_oclass nv84_vp_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/device.h b/drivers/gpu/drm/nouveau/core/include/subdev/device.h index 5eec03a..c9e4c4a 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/device.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/device.h @@ -8,7 +8,6 @@ int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname, const char *cfg, const char *dbg, int, void **); -void nouveau_device_destroy(struct nouveau_device **); int nv04_identify(struct nouveau_device *); int nv10_identify(struct nouveau_device *); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index 2adfcaf..ec7a54e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h @@ -8,7 +8,6 @@ struct nouveau_instobj { struct nouveau_object base; struct list_head head; - struct nouveau_mm heap; u32 *suspend; u64 addr; u32 size; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 81577bb..747781c 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -73,6 +73,7 @@ struct nouveau_vm { struct nouveau_vmmgr { struct nouveau_subdev base; + u64 limit; u32 pgt_bits; u8 spg_shift; u8 lpg_shift; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index 40456b9..d8d1016 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -241,6 +241,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, if (!device->subdev[i]) { ret = nouveau_object_ctor(nv_object(device), NULL, oclass, NULL, i, &subdev); + if (ret == -ENODEV) + continue; if (ret) return ret; @@ -404,10 +406,26 @@ nouveau_device_sclass[] = { {} }; +static void +nouveau_device_dtor(struct nouveau_object *object) +{ + struct nouveau_device *device = (void *)object; + + mutex_lock(&nv_devices_mutex); + list_del(&device->head); + mutex_unlock(&nv_devices_mutex); + + if (device->base.mmio) + iounmap(device->base.mmio); + + nouveau_subdev_destroy(&device->base); +} + static struct nouveau_oclass nouveau_device_oclass = { .handle = NV_SUBDEV(DEVICE, 0x00), .ofuncs = &(struct nouveau_ofuncs) { + .dtor = nouveau_device_dtor, }, }; @@ -444,18 +462,3 @@ done: mutex_unlock(&nv_devices_mutex); return ret; } - -void -nouveau_device_destroy(struct nouveau_device **pdevice) -{ - struct nouveau_device *device = *pdevice; - if (device) { - mutex_lock(&nv_devices_mutex); - list_del(&device->head); - mutex_unlock(&nv_devices_mutex); - if (device->base.mmio) - iounmap(device->base.mmio); - nouveau_subdev_destroy(&device->base); - } - *pdevice = NULL; -} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 5173c78..693d200 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -33,6 +33,12 @@ #include #include +#include +#include +#include +#include +#include + int nv04_identify(struct nouveau_device *device) { @@ -47,6 +53,11 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv04_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv04_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x05: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -58,6 +69,11 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv04_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv04_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; default: nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index c4f2c2d..de6ce89 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -34,6 +34,12 @@ #include #include +#include +#include +#include +#include +#include + int nv10_identify(struct nouveau_device *device) { @@ -49,6 +55,9 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x15: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +70,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x16: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +87,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x1a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +104,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x11: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +121,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv10_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x17: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +138,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x1f: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -121,6 +155,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x18: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +172,11 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; default: nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 719b72a..0b30143 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -34,6 +34,12 @@ #include #include +#include +#include +#include +#include +#include + int nv20_identify(struct nouveau_device *device) { @@ -49,6 +55,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x25: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +72,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x28: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +89,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x2a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +106,11 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; default: nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 0a1a728..1d5c697 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -34,6 +34,13 @@ #include #include +#include +#include +#include +#include +#include +#include + int nv30_identify(struct nouveau_device *device) { @@ -49,6 +56,11 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x35: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +73,11 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x31: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +90,12 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x36: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +108,12 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x34: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +126,12 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv17_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; default: nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 5e1ef5e..2e071fa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -34,6 +34,13 @@ #include #include +#include +#include +#include +#include +#include +#include + int nv40_identify(struct nouveau_device *device) { @@ -49,6 +56,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x41: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -61,6 +74,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x42: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -73,6 +92,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x43: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -85,6 +110,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x45: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -97,6 +128,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x47: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +146,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x49: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -121,6 +164,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4b: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -133,6 +182,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x44: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -145,6 +200,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x46: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -157,6 +218,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4a: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -169,6 +236,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4c: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -181,6 +254,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4e: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -193,6 +272,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x63: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -205,6 +290,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x67: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -217,6 +308,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x68: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -229,6 +326,12 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; default: nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 5e86a2f..5d44b2a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -35,6 +35,18 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + int nv50_identify(struct nouveau_device *device) { @@ -51,6 +63,12 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv50_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x84: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -64,6 +82,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x86: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -77,6 +104,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x92: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -90,6 +126,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x94: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -103,6 +148,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x96: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -116,6 +170,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x98: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -129,6 +192,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa0: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -142,6 +214,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xaa: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -155,6 +236,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xac: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -168,6 +258,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -181,6 +280,16 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa5: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -194,6 +303,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -207,6 +325,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xaf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -220,6 +347,15 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nv84_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nv50_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; default: nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 87f4e16..81d6ed5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -36,6 +36,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + int nvc0_identify(struct nouveau_device *device) { @@ -53,6 +63,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc4: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +87,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc3: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -81,6 +111,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xce: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -95,6 +135,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xcf: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -109,6 +159,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc1: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -123,6 +183,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc8: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -137,6 +207,16 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xd9: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -151,6 +231,15 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass; + device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass; + device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; + device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; break; default: nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index ab8346b..f4f5a5a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -36,6 +36,12 @@ #include #include +#include +#include +#include +#include +#include + int nve0_identify(struct nouveau_device *device) { @@ -53,6 +59,11 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; break; case 0xe7: device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; @@ -67,6 +78,11 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass; + device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; + device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; + device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index f44f0f0..ba4d28b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -139,8 +139,7 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); + ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht); if (ret) return ret; @@ -165,7 +164,7 @@ nv04_instmem_dtor(struct nouveau_object *object) struct nv04_instmem_priv *priv = (void *)object; nouveau_gpuobj_ref(NULL, &priv->ramfc); nouveau_gpuobj_ref(NULL, &priv->ramro); - nouveau_gpuobj_ref(NULL, &priv->ramht); + nouveau_ramht_ref(NULL, &priv->ramht); nouveau_gpuobj_ref(NULL, &priv->vbios); nouveau_mm_fini(&priv->heap); if (priv->iomem) diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h index b2f82f9..7983d8d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -2,6 +2,7 @@ #define __NV04_INSTMEM_H__ #include +#include #include #include @@ -14,11 +15,17 @@ struct nv04_instmem_priv { struct nouveau_mm heap; struct nouveau_gpuobj *vbios; - struct nouveau_gpuobj *ramht; + struct nouveau_ramht *ramht; struct nouveau_gpuobj *ramro; struct nouveau_gpuobj *ramfc; }; +static inline struct nv04_instmem_priv * +nv04_instmem(void *obj) +{ + return (void *)nouveau_instmem(obj); +} + struct nv04_instobj_priv { struct nouveau_instobj base; struct nouveau_mm_node *mem; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 6a22160..73c52eb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -87,8 +87,7 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 0x10000-0x18000: reserve for RAMHT */ - ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, - NVOBJ_FLAG_ZERO_ALLOC, &priv->ramht); + ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index b92b3d4..082c11b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -299,6 +299,7 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, fpde = (vma->node->offset >> vmm->pgt_bits); lpde = (vma->node->offset + vma->node->length - 1) >> vmm->pgt_bits; + for (pde = fpde; pde <= lpde; pde++) { struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; int big = (vma->node->type != vmm->spg_shift); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c index 6475c02..bfe6766 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -96,6 +96,7 @@ nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.create = nv04_vm_create; + priv->base.limit = NV04_PDMA_SIZE; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h index 5309303..e21369c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h @@ -10,4 +10,10 @@ struct nv04_vmmgr_priv { dma_addr_t null; }; +static inline struct nv04_vmmgr_priv * +nv04_vmmgr(void *obj) +{ + return (void *)nouveau_vmmgr(obj); +} + #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index f036770..bbeac8d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -97,6 +97,7 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.create = nv04_vm_create; + priv->base.limit = NV41_GART_SIZE; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index d17f761..d099cde 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -178,6 +178,7 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.create = nv04_vm_create; + priv->base.limit = NV44_GART_SIZE; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 6e9bcd2..0f0d3a5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -154,7 +154,6 @@ nv50_vm_flush(struct nouveau_vm *vm) struct nouveau_engine *engine; int i; -#if 0 for (i = 0; i < NVDEV_SUBDEV_NR; i++) { if (atomic_read(&vm->engref[i])) { engine = nouveau_engine(vm->vmm, i); @@ -162,11 +161,6 @@ nv50_vm_flush(struct nouveau_vm *vm) engine->tlb_flush(engine); } } -#else - nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x06); /* bar */ - nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x05); /* fifo */ - nv50_vm_flush_engine(nv_subdev(vm->vmm), 0x00); /* gr */ -#endif } void @@ -206,6 +200,7 @@ nv50_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; + priv->base.limit = 1ULL << 40; priv->base.pgt_bits = 29 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 16; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index a0bc0f6..e48ece2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -162,6 +162,7 @@ nvc0_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; + priv->base.limit = 1ULL << 40; priv->base.pgt_bits = 27 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 17; -- cgit v1.1 From d38ac5217ab43cf61e8ebe6d7114fb2d1ca9a3a4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 22 Jul 2012 16:41:26 +1000 Subject: drm/nouveau/mxm: split up into bios code and a subdev module Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/include/subdev/bios/mxm.h | 9 + drivers/gpu/drm/nouveau/core/include/subdev/mxm.h | 37 +++ drivers/gpu/drm/nouveau/core/os.h | 2 - drivers/gpu/drm/nouveau/core/subdev/bios/mxm.c | 135 ++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | 290 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c | 193 ++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.h | 22 ++ drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c | 233 +++++++++++++++++ 11 files changed, 946 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/mxm.h create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/mxm.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/mxm.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mxm/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/mxm.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/mxm.h new file mode 100644 index 0000000..5572e60 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/mxm.h @@ -0,0 +1,9 @@ +#ifndef __NVBIOS_MXM_H__ +#define __NVBIOS_MXM_H__ + +u16 mxm_table(struct nouveau_bios *, u8 *ver, u8 *hdr); + +u8 mxm_sor_map(struct nouveau_bios *, u8 conn); +u8 mxm_ddc_map(struct nouveau_bios *, u8 port); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mxm.h b/drivers/gpu/drm/nouveau/core/include/subdev/mxm.h new file mode 100644 index 0000000..b93b152 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mxm.h @@ -0,0 +1,37 @@ +#ifndef __NOUVEAU_MXM_H__ +#define __NOUVEAU_MXM_H__ + +#include +#include + +#define MXM_SANITISE_DCB 0x00000001 + +struct nouveau_mxm { + struct nouveau_subdev base; + u32 action; + u8 *mxms; +}; + +static inline struct nouveau_mxm * +nouveau_mxm(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MXM]; +} + +#define nouveau_mxm_create(p,e,o,d) \ + nouveau_mxm_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_mxm_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_mxm_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) +int nouveau_mxm_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void nouveau_mxm_destroy(struct nouveau_mxm *); + +#define _nouveau_mxm_dtor _nouveau_subdev_dtor +#define _nouveau_mxm_init _nouveau_subdev_init +#define _nouveau_mxm_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv50_mxm_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 661b037..cfe3b9c 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -19,8 +19,6 @@ #include -#include - static inline int ffsll(u64 mask) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/mxm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/mxm.c new file mode 100644 index 0000000..2610b11 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/mxm.c @@ -0,0 +1,135 @@ +/* + * 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: + * + * 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 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 +#include +#include + +u16 +mxm_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr) +{ + struct bit_entry x; + + if (bit_entry(bios, 'x', &x)) { + nv_debug(bios, "BIT 'x' table not present\n"); + return 0x0000; + } + + *ver = x.version; + *hdr = x.length; + if (*ver != 1 || *hdr < 3) { + nv_warn(bios, "BIT 'x' table %d/%d unknown\n", *ver, *hdr); + return 0x0000; + } + + return x.offset; +} + +/* These map MXM v2.x digital connection values to the appropriate SOR/link, + * hopefully they're correct for all boards within the same chipset... + * + * MXM v3.x VBIOS are nicer and provide pointers to these tables. + */ +static u8 nv84_sor_map[16] = { + 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static u8 nv92_sor_map[16] = { + 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, + 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static u8 nv94_sor_map[16] = { + 0x00, 0x14, 0x24, 0x11, 0x34, 0x31, 0x11, 0x31, + 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static u8 nv98_sor_map[16] = { + 0x00, 0x14, 0x12, 0x11, 0x00, 0x31, 0x11, 0x31, + 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +u8 +mxm_sor_map(struct nouveau_bios *bios, u8 conn) +{ + u8 ver, hdr; + u16 mxm = mxm_table(bios, &ver, &hdr); + if (mxm && hdr >= 6) { + u16 map = nv_ro16(bios, mxm + 4); + if (map) { + ver = nv_ro08(bios, map); + if (ver == 0x10) { + if (conn < nv_ro08(bios, map + 3)) { + map += nv_ro08(bios, map + 1); + map += conn; + return nv_ro08(bios, map); + } + + return 0x00; + } + + nv_warn(bios, "unknown sor map v%02x\n", ver); + } + } + + if (bios->version.chip == 0x84 || bios->version.chip == 0x86) + return nv84_sor_map[conn]; + if (bios->version.chip == 0x92) + return nv92_sor_map[conn]; + if (bios->version.chip == 0x94 || bios->version.chip == 0x96) + return nv94_sor_map[conn]; + if (bios->version.chip == 0x98) + return nv98_sor_map[conn]; + + nv_warn(bios, "missing sor map\n"); + return 0x00; +} + +u8 +mxm_ddc_map(struct nouveau_bios *bios, u8 port) +{ + u8 ver, hdr; + u16 mxm = mxm_table(bios, &ver, &hdr); + if (mxm && hdr >= 8) { + u16 map = nv_ro16(bios, mxm + 6); + if (map) { + ver = nv_ro08(bios, map); + if (ver == 0x10) { + if (port < nv_ro08(bios, map + 3)) { + map += nv_ro08(bios, map + 1); + map += port; + return nv_ro08(bios, map); + } + + return 0x00; + } + + nv_warn(bios, "unknown ddc map v%02x\n", ver); + } + } + + /* v2.x: directly write port as dcb i2cidx */ + return (port << 4) | port; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 5d44b2a..cec477b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -75,6 +77,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -97,6 +100,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -119,6 +123,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -141,6 +146,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -163,6 +169,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -185,6 +192,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -207,6 +215,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -229,6 +238,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -251,6 +261,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -273,6 +284,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -296,6 +308,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -318,6 +331,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -340,6 +354,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 81d6ed5..6168436 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -79,6 +81,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -103,6 +106,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -127,6 +131,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -151,6 +156,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -175,6 +181,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -199,6 +206,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -223,6 +231,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index f4f5a5a..1ce0570 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -70,6 +72,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c new file mode 100644 index 0000000..684f396 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -0,0 +1,290 @@ +/* + * Copyright 2011 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: + * + * 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 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 + +#include +#include +#include +#include + +#include "mxms.h" + +static bool +mxm_shadow_rom_fetch(struct nouveau_i2c_port *i2c, u8 addr, + u8 offset, u8 size, u8 *data) +{ + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = &offset }, + { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, }, + }; + + return i2c_transfer(&i2c->adapter, msgs, 2) == 2; +} + +static bool +mxm_shadow_rom(struct nouveau_mxm *mxm, u8 version) +{ + struct nouveau_bios *bios = nouveau_bios(mxm); + struct nouveau_i2c *i2c = nouveau_i2c(mxm); + struct nouveau_i2c_port *port = NULL; + u8 i2cidx, mxms[6], addr, size; + + i2cidx = mxm_ddc_map(bios, 1 /* LVDS_DDC */) & 0x0f; + if (i2cidx < 0x0f) + port = i2c->find(i2c, i2cidx); + if (!port) + return false; + + addr = 0x54; + if (!mxm_shadow_rom_fetch(port, addr, 0, 6, mxms)) { + addr = 0x56; + if (!mxm_shadow_rom_fetch(port, addr, 0, 6, mxms)) + return false; + } + + mxm->mxms = mxms; + size = mxms_headerlen(mxm) + mxms_structlen(mxm); + mxm->mxms = kmalloc(size, GFP_KERNEL); + + if (mxm->mxms && + mxm_shadow_rom_fetch(port, addr, 0, size, mxm->mxms)) + return true; + + kfree(mxm->mxms); + mxm->mxms = NULL; + return false; +} + +#if defined(CONFIG_ACPI) +static bool +mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version) +{ + struct nouveau_device *device = nv_device(mxm); + static char muid[] = { + 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, + 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 + }; + u32 mxms_args[] = { 0x00000000 }; + union acpi_object args[4] = { + /* _DSM MUID */ + { .buffer.type = 3, + .buffer.length = sizeof(muid), + .buffer.pointer = muid, + }, + /* spec says this can be zero to mean "highest revision", but + * of course there's at least one bios out there which fails + * unless you pass in exactly the version it supports.. + */ + { .integer.type = ACPI_TYPE_INTEGER, + .integer.value = (version & 0xf0) << 4 | (version & 0x0f), + }, + /* MXMS function */ + { .integer.type = ACPI_TYPE_INTEGER, + .integer.value = 0x00000010, + }, + /* Pointer to MXMS arguments */ + { .buffer.type = ACPI_TYPE_BUFFER, + .buffer.length = sizeof(mxms_args), + .buffer.pointer = (char *)mxms_args, + }, + }; + struct acpi_object_list list = { ARRAY_SIZE(args), args }; + struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_handle handle; + int ret; + + handle = DEVICE_ACPI_HANDLE(&device->pdev->dev); + if (!handle) + return false; + + ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); + if (ret) { + nv_debug(mxm, "DSM MXMS failed: %d\n", ret); + return false; + } + + obj = retn.pointer; + if (obj->type == ACPI_TYPE_BUFFER) { + mxm->mxms = kmemdup(obj->buffer.pointer, + obj->buffer.length, GFP_KERNEL); + } else + if (obj->type == ACPI_TYPE_INTEGER) { + nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); + } + + kfree(obj); + return mxm->mxms != NULL; +} +#endif + +#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) + +#define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0" + +static u8 +wmi_wmmx_mxmi(struct nouveau_mxm *mxm, u8 version) +{ + u32 mxmi_args[] = { 0x494D584D /* MXMI */, version, 0 }; + struct acpi_buffer args = { sizeof(mxmi_args), mxmi_args }; + struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_status status; + + status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); + if (ACPI_FAILURE(status)) { + nv_debug(mxm, "WMMX MXMI returned %d\n", status); + return 0x00; + } + + obj = retn.pointer; + if (obj->type == ACPI_TYPE_INTEGER) { + version = obj->integer.value; + nv_debug(mxm, "WMMX MXMI version %d.%d\n", + (version >> 4), version & 0x0f); + } else { + version = 0; + nv_debug(mxm, "WMMX MXMI returned non-integer\n"); + } + + kfree(obj); + return version; +} + +static bool +mxm_shadow_wmi(struct nouveau_mxm *mxm, u8 version) +{ + u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 }; + struct acpi_buffer args = { sizeof(mxms_args), mxms_args }; + struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_status status; + + if (!wmi_has_guid(WMI_WMMX_GUID)) { + nv_debug(mxm, "WMMX GUID not found\n"); + return false; + } + + mxms_args[1] = wmi_wmmx_mxmi(mxm, 0x00); + if (!mxms_args[1]) + mxms_args[1] = wmi_wmmx_mxmi(mxm, version); + if (!mxms_args[1]) + return false; + + status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); + if (ACPI_FAILURE(status)) { + nv_debug(mxm, "WMMX MXMS returned %d\n", status); + return false; + } + + obj = retn.pointer; + if (obj->type == ACPI_TYPE_BUFFER) { + mxm->mxms = kmemdup(obj->buffer.pointer, + obj->buffer.length, GFP_KERNEL); + } + + kfree(obj); + return mxm->mxms != NULL; +} +#endif + +struct mxm_shadow_h { + const char *name; + bool (*exec)(struct nouveau_mxm *, u8 version); +} _mxm_shadow[] = { + { "ROM", mxm_shadow_rom }, +#if defined(CONFIG_ACPI) + { "DSM", mxm_shadow_dsm }, +#endif +#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) + { "WMI", mxm_shadow_wmi }, +#endif + {} +}; + +static int +mxm_shadow(struct nouveau_mxm *mxm, u8 version) +{ + struct mxm_shadow_h *shadow = _mxm_shadow; + do { + nv_debug(mxm, "checking %s\n", shadow->name); + if (shadow->exec(mxm, version)) { + if (mxms_valid(mxm)) + return 0; + kfree(mxm->mxms); + mxm->mxms = NULL; + } + } while ((++shadow)->name); + return -ENOENT; +} + +int +nouveau_mxm_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, int length, void **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nouveau_bios *bios = nouveau_bios(device); + struct nouveau_mxm *mxm; + u8 ver, len; + u16 data; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "MXM", "mxm", + length, pobject); + mxm = *pobject; + if (ret) + return ret; + + data = mxm_table(bios, &ver, &len); + if (!data || !(ver = nv_ro08(bios, data))) { + nv_info(mxm, "no VBIOS data, nothing to do\n"); + return 0; + } + + nv_info(mxm, "BIOS version %d.%d\n", ver >> 4, ver & 0x0f); + + if (mxm_shadow(mxm, ver)) { + nv_info(mxm, "failed to locate valid SIS\n"); +#if 0 + /* we should, perhaps, fall back to some kind of limited + * mode here if the x86 vbios hasn't already done the + * work for us (so we prevent loading with completely + * whacked vbios tables). + */ + return -EINVAL; +#else + return 0; +#endif + } + + nv_info(mxm, "MXMS Version %d.%d\n", + mxms_version(mxm) >> 8, mxms_version(mxm) & 0xff); + mxms_foreach(mxm, 0, NULL, NULL); + + if (nouveau_boolopt(device->cfgopt, "NvMXMDCB", true)) + mxm->action |= MXM_SANITISE_DCB; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c new file mode 100644 index 0000000..839ca1e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c @@ -0,0 +1,193 @@ +/* + * 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: + * + * 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 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 +#include "mxms.h" + +#define ROM16(x) le16_to_cpu(*(u16 *)&(x)) +#define ROM32(x) le32_to_cpu(*(u32 *)&(x)) + +static u8 * +mxms_data(struct nouveau_mxm *mxm) +{ + return mxm->mxms; + +} + +u16 +mxms_version(struct nouveau_mxm *mxm) +{ + u8 *mxms = mxms_data(mxm); + u16 version = (mxms[4] << 8) | mxms[5]; + switch (version ) { + case 0x0200: + case 0x0201: + case 0x0300: + return version; + default: + break; + } + + nv_debug(mxm, "unknown version %d.%d\n", mxms[4], mxms[5]); + return 0x0000; +} + +u16 +mxms_headerlen(struct nouveau_mxm *mxm) +{ + return 8; +} + +u16 +mxms_structlen(struct nouveau_mxm *mxm) +{ + return *(u16 *)&mxms_data(mxm)[6]; +} + +bool +mxms_checksum(struct nouveau_mxm *mxm) +{ + u16 size = mxms_headerlen(mxm) + mxms_structlen(mxm); + u8 *mxms = mxms_data(mxm), sum = 0; + while (size--) + sum += *mxms++; + if (sum) { + nv_debug(mxm, "checksum invalid\n"); + return false; + } + return true; +} + +bool +mxms_valid(struct nouveau_mxm *mxm) +{ + u8 *mxms = mxms_data(mxm); + if (*(u32 *)mxms != 0x5f4d584d) { + nv_debug(mxm, "signature invalid\n"); + return false; + } + + if (!mxms_version(mxm) || !mxms_checksum(mxm)) + return false; + + return true; +} + +bool +mxms_foreach(struct nouveau_mxm *mxm, u8 types, + bool (*exec)(struct nouveau_mxm *, u8 *, void *), void *info) +{ + u8 *mxms = mxms_data(mxm); + u8 *desc = mxms + mxms_headerlen(mxm); + u8 *fini = desc + mxms_structlen(mxm) - 1; + while (desc < fini) { + u8 type = desc[0] & 0x0f; + u8 headerlen = 0; + u8 recordlen = 0; + u8 entries = 0; + + switch (type) { + case 0: /* Output Device Structure */ + if (mxms_version(mxm) >= 0x0300) + headerlen = 8; + else + headerlen = 6; + break; + case 1: /* System Cooling Capability Structure */ + case 2: /* Thermal Structure */ + case 3: /* Input Power Structure */ + headerlen = 4; + break; + case 4: /* GPIO Device Structure */ + headerlen = 4; + recordlen = 2; + entries = (ROM32(desc[0]) & 0x01f00000) >> 20; + break; + case 5: /* Vendor Specific Structure */ + headerlen = 8; + break; + case 6: /* Backlight Control Structure */ + if (mxms_version(mxm) >= 0x0300) { + headerlen = 4; + recordlen = 8; + entries = (desc[1] & 0xf0) >> 4; + } else { + headerlen = 8; + } + break; + case 7: /* Fan Control Structure */ + headerlen = 8; + recordlen = 4; + entries = desc[1] & 0x07; + break; + default: + nv_debug(mxm, "unknown descriptor type %d\n", type); + return false; + } + + if (nv_subdev(mxm)->debug >= NV_DBG_DEBUG && (exec == NULL)) { + static const char * mxms_desc_name[] = { + "ODS", "SCCS", "TS", "IPS", + "GSD", "VSS", "BCS", "FCS", + }; + u8 *dump = desc; + int i, j; + + nv_debug(mxm, "%4s: ", mxms_desc_name[type]); + for (j = headerlen - 1; j >= 0; j--) + printk("%02x", dump[j]); + printk("\n"); + dump += headerlen; + + for (i = 0; i < entries; i++, dump += recordlen) { + nv_debug(mxm, " "); + for (j = recordlen - 1; j >= 0; j--) + printk("%02x", dump[j]); + printk("\n"); + } + } + + if (types & (1 << type)) { + if (!exec(mxm, desc, info)) + return false; + } + + desc += headerlen + (entries * recordlen); + } + + return true; +} + +void +mxms_output_device(struct nouveau_mxm *mxm, u8 *pdata, struct mxms_odev *desc) +{ + u64 data = ROM32(pdata[0]); + if (mxms_version(mxm) >= 0x0300) + data |= (u64)ROM16(pdata[4]) << 32; + + desc->outp_type = (data & 0x00000000000000f0ULL) >> 4; + desc->ddc_port = (data & 0x0000000000000f00ULL) >> 8; + desc->conn_type = (data & 0x000000000001f000ULL) >> 12; + desc->dig_conn = (data & 0x0000000000780000ULL) >> 19; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.h b/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.h new file mode 100644 index 0000000..5e0be0c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.h @@ -0,0 +1,22 @@ +#ifndef __NVMXM_MXMS_H__ +#define __NVMXM_MXMS_H__ + +struct mxms_odev { + u8 outp_type; + u8 conn_type; + u8 ddc_port; + u8 dig_conn; +}; + +void mxms_output_device(struct nouveau_mxm *, u8 *, struct mxms_odev *); + +u16 mxms_version(struct nouveau_mxm *); +u16 mxms_headerlen(struct nouveau_mxm *); +u16 mxms_structlen(struct nouveau_mxm *); +bool mxms_checksum(struct nouveau_mxm *); +bool mxms_valid(struct nouveau_mxm *); + +bool mxms_foreach(struct nouveau_mxm *, u8, + bool (*)(struct nouveau_mxm *, u8 *, void *), void *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c new file mode 100644 index 0000000..af129c2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c @@ -0,0 +1,233 @@ +/* + * Copyright 2011 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: + * + * 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 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 +#include +#include +#include +#include + +#include "mxms.h" + +struct nv50_mxm_priv { + struct nouveau_mxm base; +}; + +struct context { + u32 *outp; + struct mxms_odev desc; +}; + +static bool +mxm_match_tmds_partner(struct nouveau_mxm *mxm, u8 *data, void *info) +{ + struct context *ctx = info; + struct mxms_odev desc; + + mxms_output_device(mxm, data, &desc); + if (desc.outp_type == 2 && + desc.dig_conn == ctx->desc.dig_conn) + return false; + return true; +} + +static bool +mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info) +{ + struct nouveau_bios *bios = nouveau_bios(mxm); + struct context *ctx = info; + u64 desc = *(u64 *)data; + + mxms_output_device(mxm, data, &ctx->desc); + + /* match dcb encoder type to mxm-ods device type */ + if ((ctx->outp[0] & 0x0000000f) != ctx->desc.outp_type) + return true; + + /* digital output, have some extra stuff to match here, there's a + * table in the vbios that provides a mapping from the mxm digital + * connection enum values to SOR/link + */ + if ((desc & 0x00000000000000f0) >= 0x20) { + /* check against sor index */ + u8 link = mxm_sor_map(bios, ctx->desc.dig_conn); + if ((ctx->outp[0] & 0x0f000000) != (link & 0x0f) << 24) + return true; + + /* check dcb entry has a compatible link field */ + link = (link & 0x30) >> 4; + if ((link & ((ctx->outp[1] & 0x00000030) >> 4)) != link) + return true; + } + + /* mark this descriptor accounted for by setting invalid device type, + * except of course some manufactures don't follow specs properly and + * we need to avoid killing off the TMDS function on DP connectors + * if MXM-SIS is missing an entry for it. + */ + data[0] &= ~0xf0; + if (ctx->desc.outp_type == 6 && ctx->desc.conn_type == 6 && + mxms_foreach(mxm, 0x01, mxm_match_tmds_partner, ctx)) { + data[0] |= 0x20; /* modify descriptor to match TMDS now */ + } else { + data[0] |= 0xf0; + } + + return false; +} + +static int +mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb) +{ + struct nouveau_mxm *mxm = nouveau_mxm(bios); + struct context ctx = { .outp = (u32 *)(bios->data + pdcb) }; + u8 type, i2cidx, link, ver, len; + u8 *conn; + + /* look for an output device structure that matches this dcb entry. + * if one isn't found, disable it. + */ + if (mxms_foreach(mxm, 0x01, mxm_match_dcb, &ctx)) { + nv_debug(mxm, "disable %d: 0x%08x 0x%08x\n", + idx, ctx.outp[0], ctx.outp[1]); + ctx.outp[0] |= 0x0000000f; + return 0; + } + + /* modify the output's ddc/aux port, there's a pointer to a table + * with the mapping from mxm ddc/aux port to dcb i2c_index in the + * vbios mxm table + */ + i2cidx = mxm_ddc_map(bios, ctx.desc.ddc_port); + if ((ctx.outp[0] & 0x0000000f) != DCB_OUTPUT_DP) + i2cidx = (i2cidx & 0x0f) << 4; + else + i2cidx = (i2cidx & 0xf0); + + if (i2cidx != 0xf0) { + ctx.outp[0] &= ~0x000000f0; + ctx.outp[0] |= i2cidx; + } + + /* override dcb sorconf.link, based on what mxm data says */ + switch (ctx.desc.outp_type) { + case 0x00: /* Analog CRT */ + case 0x01: /* Analog TV/HDTV */ + break; + default: + link = mxm_sor_map(bios, ctx.desc.dig_conn) & 0x30; + ctx.outp[1] &= ~0x00000030; + ctx.outp[1] |= link; + break; + } + + /* we may need to fixup various other vbios tables based on what + * the descriptor says the connector type should be. + * + * in a lot of cases, the vbios tables will claim DVI-I is possible, + * and the mxm data says the connector is really HDMI. another + * common example is DP->eDP. + */ + conn = bios->data; + conn += dcb_conn(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len); + type = conn[0]; + switch (ctx.desc.conn_type) { + case 0x01: /* LVDS */ + ctx.outp[1] |= 0x00000004; /* use_power_scripts */ + /* XXX: modify default link width in LVDS table */ + break; + case 0x02: /* HDMI */ + type = DCB_CONNECTOR_HDMI_1; + break; + case 0x03: /* DVI-D */ + type = DCB_CONNECTOR_DVI_D; + break; + case 0x0e: /* eDP, falls through to DPint */ + ctx.outp[1] |= 0x00010000; + case 0x07: /* DP internal, wtf is this?? HP8670w */ + ctx.outp[1] |= 0x00000004; /* use_power_scripts? */ + type = DCB_CONNECTOR_eDP; + break; + default: + break; + } + + if (mxms_version(mxm) >= 0x0300) + conn[0] = type; + + return 0; +} + +static bool +mxm_show_unmatched(struct nouveau_mxm *mxm, u8 *data, void *info) +{ + u64 desc = *(u64 *)data; + if ((desc & 0xf0) != 0xf0) + nv_info(mxm, "unmatched output device 0x%016llx\n", desc); + return true; +} + +static void +mxm_dcb_sanitise(struct nouveau_mxm *mxm) +{ + struct nouveau_bios *bios = nouveau_bios(mxm); + u8 ver, hdr, cnt, len; + u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); + if (dcb == 0x0000 || ver != 0x40) { + nv_debug(mxm, "unsupported DCB version\n"); + return; + } + + dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry); + mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL); +} + +static int +nv50_mxm_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv50_mxm_priv *priv; + int ret; + + ret = nouveau_mxm_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + if (priv->base.action & MXM_SANITISE_DCB) + mxm_dcb_sanitise(&priv->base); + return 0; +} + +struct nouveau_oclass +nv50_mxm_oclass = { + .handle = NV_SUBDEV(MXM, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_mxm_ctor, + .dtor = _nouveau_mxm_dtor, + .init = _nouveau_mxm_init, + .fini = _nouveau_mxm_fini, + }, +}; -- cgit v1.1 From 2094dd82eddc468b53ee99d92c38b23a65efac03 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 27 Jul 2012 08:28:20 +1000 Subject: drm/nouveau/device: include the official chipset names Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/device/base.c | 3 ++- drivers/gpu/drm/nouveau/core/subdev/device/nv04.c | 2 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv10.c | 8 ++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 4 ++++ drivers/gpu/drm/nouveau/core/subdev/device/nv30.c | 5 +++++ drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 16 ++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 14 ++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 8 ++++++++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 2 ++ 9 files changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index d8d1016..42faa65 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -204,7 +204,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, } nv_info(device, "BOOT0 : 0x%08x\n", boot0); - nv_info(device, "Chipset: NV%02X\n", device->chipset); + nv_info(device, "Chipset: %s (NV%02X)\n", + device->cname, device->chipset); nv_info(device, "Family : NV%02X\n", device->card_type); /* determine frequency of timing crystal */ diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 693d200..8626d0d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -44,6 +44,7 @@ nv04_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x04: + device->cname = "NV04"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; @@ -60,6 +61,7 @@ nv04_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x05: + device->cname = "NV05"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index de6ce89..f09accf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -45,6 +45,7 @@ nv10_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x10: + device->cname = "NV10"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -60,6 +61,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x15: + device->cname = "NV15"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -77,6 +79,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x16: + device->cname = "NV16"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -94,6 +97,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x1a: + device->cname = "nForce"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -111,6 +115,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x11: + device->cname = "NV11"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -128,6 +133,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x17: + device->cname = "NV17"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -145,6 +151,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x1f: + device->cname = "nForce2"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -162,6 +169,7 @@ nv10_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x18: + device->cname = "NV18"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 0b30143..1c8681f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -45,6 +45,7 @@ nv20_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x20: + device->cname = "NV20"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -62,6 +63,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x25: + device->cname = "NV25"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -79,6 +81,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x28: + device->cname = "NV28"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -96,6 +99,7 @@ nv20_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x2a: + device->cname = "NV2A"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 1d5c697..7f4b8fe 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -46,6 +46,7 @@ nv30_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x30: + device->cname = "NV30"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -63,6 +64,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x35: + device->cname = "NV35"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -80,6 +82,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x31: + device->cname = "NV31"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -98,6 +101,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x36: + device->cname = "NV36"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -116,6 +120,7 @@ nv30_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x34: + device->cname = "NV34"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 2e071fa..c6005c2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -46,6 +46,7 @@ nv40_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x40: + device->cname = "NV40"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -64,6 +65,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x41: + device->cname = "NV41"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -82,6 +84,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x42: + device->cname = "NV42"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -100,6 +103,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x43: + device->cname = "NV43"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -118,6 +122,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x45: + device->cname = "NV45"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -136,6 +141,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x47: + device->cname = "G70"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -154,6 +160,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x49: + device->cname = "G71"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -172,6 +179,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4b: + device->cname = "G73"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -190,6 +198,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x44: + device->cname = "NV44"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -208,6 +217,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x46: + device->cname = "G72"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -226,6 +236,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4a: + device->cname = "NV44A"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -244,6 +255,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4c: + device->cname = "C61"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -262,6 +274,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x4e: + device->cname = "C51"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -280,6 +293,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x63: + device->cname = "C73"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -298,6 +312,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x67: + device->cname = "C67"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -316,6 +331,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; break; case 0x68: + device->cname = "C68"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index cec477b..252e13c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -53,6 +53,7 @@ nv50_identify(struct nouveau_device *device) { switch (device->chipset) { case 0x50: + device->cname = "G80"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -73,6 +74,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x84: + device->cname = "G84"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -96,6 +98,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x86: + device->cname = "G86"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -119,6 +122,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x92: + device->cname = "G92"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -142,6 +146,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x94: + device->cname = "G94"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -165,6 +170,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x96: + device->cname = "G96"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -188,6 +194,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0x98: + device->cname = "G98"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -211,6 +218,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa0: + device->cname = "G200"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -234,6 +242,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xaa: + device->cname = "MCP77/MCP78"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -257,6 +266,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xac: + device->cname = "MCP79/MCP7A"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -280,6 +290,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa3: + device->cname = "GT215"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -304,6 +315,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa5: + device->cname = "GT216"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -327,6 +339,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xa8: + device->cname = "GT218"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -350,6 +363,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xaf: + device->cname = "MCP89"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 6168436..8c14b38 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -52,6 +52,7 @@ nvc0_identify(struct nouveau_device *device) { switch (device->chipset) { case 0xc0: + device->cname = "GF100"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -77,6 +78,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc4: + device->cname = "GF104"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -102,6 +104,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc3: + device->cname = "GF106"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -127,6 +130,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xce: + device->cname = "GF114"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -152,6 +156,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xcf: + device->cname = "GF116"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -177,6 +182,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc1: + device->cname = "GF108"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -202,6 +208,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xc8: + device->cname = "GF110"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -227,6 +234,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; break; case 0xd9: + device->cname = "GF119"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 1ce0570..2547ac0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -48,6 +48,7 @@ nve0_identify(struct nouveau_device *device) { switch (device->chipset) { case 0xe4: + device->cname = "GK104"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; @@ -68,6 +69,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; break; case 0xe7: + device->cname = "GK107"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; -- cgit v1.1 From 77145f1cbdf8d28b46ff8070ca749bad821e0774 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 31 Jul 2012 16:16:21 +1000 Subject: drm/nouveau: port remainder of drm code, and rip out compat layer v2: Ben Skeggs - fill in nouveau_pm.dev to prevent oops - fix ppc issues (build + OF shadow) Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/include/subdev/timer.h | 4 +-- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 30 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index d971b83..49bff90 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h @@ -20,8 +20,8 @@ void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) #define nv_wait_ne(o,a,m,v) \ nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v)) -#define nv_wait_cb(o,a,m,v) \ - nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (a), (m), (v)) +#define nv_wait_cb(o,c,d) \ + nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (c), (d)) struct nouveau_timer { struct nouveau_subdev base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e8e46ec..2fbb6df 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -56,6 +56,31 @@ nvbios_findstr(const u8 *data, int size, const char *str, int len) return 0; } +#if defined(__powerpc__) +static void +nouveau_bios_shadow_of(struct nouveau_bios *bios) +{ + struct pci_dev *pdev = nv_device(bios)->pdev; + struct device_node *dn; + const u32 *data; + int size, i; + + dn = pci_device_to_OF_node(pdev); + if (!dn) { + nv_info(bios, "Unable to get the OF node\n"); + return; + } + + data = of_get_property(dn, "NVDA,BMP", &size); + if (data) { + bios->size = size; + bios->data = kmalloc(bios->size, GFP_KERNEL); + if (bios->data) + memcpy(bios->data, data, size); + } +} +#endif + static void nouveau_bios_shadow_pramin(struct nouveau_bios *bios) { @@ -221,7 +246,7 @@ nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) } struct methods { - const char desc[8]; + const char desc[16]; void (*shadow)(struct nouveau_bios *); const bool rw; int score; @@ -233,6 +258,9 @@ static int nouveau_bios_shadow(struct nouveau_bios *bios) { struct methods shadow_methods[] = { +#if defined(__powerpc__) + { "OpenFirmware", nouveau_bios_shadow_of, true, 0, 0, NULL }, +#endif { "PRAMIN", nouveau_bios_shadow_pramin, true, 0, 0, NULL }, { "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL }, { "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL }, -- cgit v1.1 From b10f20d590aa040e4028c04a70a27b9ad6650ba8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 5 Aug 2012 11:29:10 +1000 Subject: drm/nvc0-/gr: remove reset-after-grctx-construction hack Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 27 ++++++---------------- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 8 +------ drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 8 +------ 3 files changed, 9 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index c12e766..0b7951a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -151,29 +151,16 @@ nvc0_grctx_fini(struct nvc0_grctx *info) struct nvc0_graph_priv *priv = info->priv; int i; - if (priv->firmware) { - 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; - } - - goto save; - } - - /* HUB_FUC(CTX_SAVE) */ - 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); + /* trigger a context unload by unsetting the "next channel valid" bit + * and faking a context switch interrupt + */ + nv_mask(priv, 0x409b04, 0x80000000, 0x00000000); + nv_wr32(priv, 0x409000, 0x00000100); + if (!nv_wait(priv, 0x409b00, 0x80000000, 0x00000000)) { + nv_error(priv, "grctx template channel unload timeout\n"); return -EBUSY; } -save: priv->data = kmalloc(priv->size, GFP_KERNEL); if (priv->data) { for (i = 0; i < priv->size; i += 4) diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index db8aefc..e2f1bea 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -707,8 +707,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv) nv_error(priv, "failed to construct context\n"); return ret; } - - return 1; } return 0; @@ -720,7 +718,6 @@ nvc0_graph_init(struct nouveau_object *object) struct nvc0_graph_priv *priv = (void *)object; int ret; -reset: ret = nouveau_graph_init(&priv->base); if (ret) return ret; @@ -748,11 +745,8 @@ reset: nv_wr32(priv, 0x400054, 0x34ce3464); ret = nvc0_graph_init_ctxctl(priv); - if (ret) { - if (ret == 1) - goto reset; + if (ret) return ret; - } return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index c79748a..7ef692b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -457,8 +457,6 @@ nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv) nv_error(priv, "failed to construct context\n"); return ret; } - - return 1; } return 0; @@ -470,7 +468,6 @@ nve0_graph_init(struct nouveau_object *object) struct nvc0_graph_priv *priv = (void *)object; int ret; -reset: ret = nouveau_graph_init(&priv->base); if (ret) return ret; @@ -496,11 +493,8 @@ reset: nv_wr32(priv, 0x400054, 0x34ce3464); ret = nve0_graph_init_ctxctl(priv); - if (ret) { - if (ret == 1) - goto reset; + if (ret) return ret; - } return 0; } -- cgit v1.1 From c4837d27945b9b607b5a7274a33059e73d1a7831 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2012 16:30:10 +1000 Subject: drm/nouveau/core: remove some left-over pieces from the porting process Reported-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/core/gpuobj.h | 11 ----------- drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 4 ---- drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 6 ------ 3 files changed, 21 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h b/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h index 7394a5e..6eaff79 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h +++ b/drivers/gpu/drm/nouveau/core/include/core/gpuobj.h @@ -2,11 +2,9 @@ #define __NOUVEAU_GPUOBJ_H__ #include -#ifndef XXX_THIS_IS_A_HACK #include #include #include -#endif struct nouveau_vma; struct nouveau_vm; @@ -24,14 +22,8 @@ struct nouveau_gpuobj { u32 flags; u64 addr; u32 size; - - /*XXX*/ - struct drm_device *dev; - u32 engine; - u32 class; }; -#ifndef XXX_THIS_IS_A_HACK static inline struct nouveau_gpuobj * nv_gpuobj(void *obj) { @@ -63,7 +55,6 @@ int nouveau_gpuobj_map(struct nouveau_gpuobj *, u32 acc, struct nouveau_vma *); int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *, struct nouveau_vm *, u32 access, struct nouveau_vma *); void nouveau_gpuobj_unmap(struct nouveau_vma *); -#endif static inline void nouveau_gpuobj_ref(struct nouveau_gpuobj *obj, struct nouveau_gpuobj **ref) @@ -71,12 +62,10 @@ nouveau_gpuobj_ref(struct nouveau_gpuobj *obj, struct nouveau_gpuobj **ref) nouveau_object_ref(&obj->base, (struct nouveau_object **)ref); } -#ifndef XXX_THIS_IS_A_HACK void _nouveau_gpuobj_dtor(struct nouveau_object *); int _nouveau_gpuobj_init(struct nouveau_object *); int _nouveau_gpuobj_fini(struct nouveau_object *, bool); u32 _nouveau_gpuobj_rd32(struct nouveau_object *, u32); void _nouveau_gpuobj_wr32(struct nouveau_object *, u32, u32); -#endif #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index f18c1a1..5c1b5e1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -1,10 +1,8 @@ #ifndef __NOUVEAU_FB_H__ #define __NOUVEAU_FB_H__ -#ifndef XXX_THIS_IS_A_HACK #include #include -#endif #include #include @@ -50,7 +48,6 @@ struct nouveau_fb_tile { u32 zcomp; }; -#ifndef XXX_THIS_IS_A_HACK struct nouveau_fb { struct nouveau_subdev base; @@ -133,6 +130,5 @@ void nv30_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **); void nv50_fb_trap(struct nouveau_fb *, int display); -#endif #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 747781c..66a4473 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -25,14 +25,11 @@ #ifndef __NOUVEAU_VM_H__ #define __NOUVEAU_VM_H__ -#ifndef XXX_THIS_IS_A_HACK #include #include #include -#endif #include -#ifndef XXX_THIS_IS_A_HACK struct nouveau_vm_pgt { struct nouveau_gpuobj *obj[2]; u32 refcount[2]; @@ -42,7 +39,6 @@ struct nouveau_vm_pgd { struct list_head head; struct nouveau_gpuobj *obj; }; -#endif struct nouveau_gpuobj; struct nouveau_mem; @@ -69,7 +65,6 @@ struct nouveau_vm { u32 lpde; }; -#ifndef XXX_THIS_IS_A_HACK struct nouveau_vmmgr { struct nouveau_subdev base; @@ -129,7 +124,6 @@ int nouveau_vm_create(struct nouveau_vmmgr *, u64 offset, u64 length, u64 mm_offset, u32 block, struct nouveau_vm **); int nouveau_vm_new(struct nouveau_device *, u64 offset, u64 length, u64 mm_offset, struct nouveau_vm **); -#endif int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, struct nouveau_gpuobj *pgd); int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, -- cgit v1.1 From 43b1e9c9899ece92c1f68d45ae0d7b98d009f5d0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2012 16:31:26 +1000 Subject: drm/nouveau/device: return proper error codes if ioremap fails Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/device/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index 42faa65..cac67dc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -139,8 +139,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) && !device->card_type) { map = ioremap(mmio_base, 0x102000); - if (map == NULL) { - } + if (map == NULL) + return -ENOMEM; /* switch mmio to cpu's native endianness */ #ifndef __BIG_ENDIAN @@ -230,7 +230,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent, nv_subdev(device)->mmio = ioremap(mmio_base, mmio_size); if (!nv_subdev(device)->mmio) { nv_error(device, "unable to map device registers\n"); - return ret; + return -ENOMEM; } } -- cgit v1.1 From dbff2dee9f8561710fcfe7f6623dd272ddca5a27 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2012 18:16:37 +1000 Subject: drm/nve0/fifo: support engine selection when creating fifo channels Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 45 +++++++++++++++++++--- drivers/gpu/drm/nouveau/core/include/core/class.h | 21 +++++++++- drivers/gpu/drm/nouveau/core/include/core/device.h | 2 +- 6 files changed, 62 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 4914c3b..5b80f3e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -182,7 +182,7 @@ nv50_fifo_chan_ctor(struct nouveau_object *parent, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { - struct nv_channel_ind_class *args = data; + struct nv50_channel_ind_class *args = data; struct nouveau_bar *bar = nouveau_bar(parent); struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_chan *chan; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 765affb..d3b0356 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -150,7 +150,7 @@ nv84_fifo_chan_ctor(struct nouveau_object *parent, struct nouveau_bar *bar = nouveau_bar(parent); struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_chan *chan; - struct nv_channel_ind_class *args = data; + struct nv50_channel_ind_class *args = data; u64 ioffset, ilength; int ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index ef403fe..a4ae2bf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -163,7 +163,7 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent, struct nvc0_fifo_priv *priv = (void *)engine; struct nvc0_fifo_base *base = (void *)parent; struct nvc0_fifo_chan *chan; - struct nv_channel_ind_class *args = data; + struct nv50_channel_ind_class *args = data; u64 usermem, ioffset, ilength; int ret, i; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index aaff086..c3f4955 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -38,6 +38,22 @@ #include #include +#define _(a,b) { (a), ((1 << (a)) | (b)) } +static const struct { + int subdev; + u32 mask; +} fifo_engine[] = { + _(NVDEV_ENGINE_GR , (1 << NVDEV_ENGINE_SW)), + _(NVDEV_ENGINE_VP , 0), + _(NVDEV_ENGINE_PPP , 0), + _(NVDEV_ENGINE_BSP , 0), + _(NVDEV_ENGINE_COPY0 , 0), + _(NVDEV_ENGINE_COPY1 , 0), + _(NVDEV_ENGINE_VENC , 0), +}; +#undef _ +#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine) + struct nve0_fifo_engn { struct nouveau_gpuobj *playlist[2]; int cur_playlist; @@ -45,7 +61,7 @@ struct nve0_fifo_engn { struct nve0_fifo_priv { struct nouveau_fifo base; - struct nve0_fifo_engn engine[16]; + struct nve0_fifo_engn engine[FIFO_ENGINE_NR]; struct { struct nouveau_gpuobj *mem; struct nouveau_vma bar; @@ -119,7 +135,9 @@ nve0_fifo_context_attach(struct nouveau_object *parent, switch (nv_engidx(object->engine)) { case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0210; break; + case NVDEV_ENGINE_GR : + case NVDEV_ENGINE_COPY0: + case NVDEV_ENGINE_COPY1: addr = 0x0210; break; default: return -EINVAL; } @@ -149,7 +167,9 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, switch (nv_engidx(object->engine)) { case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0210; break; + case NVDEV_ENGINE_GR : + case NVDEV_ENGINE_COPY0: + case NVDEV_ENGINE_COPY1: addr = 0x0210; break; default: return -EINVAL; } @@ -178,24 +198,36 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent, struct nve0_fifo_priv *priv = (void *)engine; struct nve0_fifo_base *base = (void *)parent; struct nve0_fifo_chan *chan; - struct nv_channel_ind_class *args = data; + struct nve0_channel_ind_class *args = data; u64 usermem, ioffset, ilength; int ret, i; if (size < sizeof(*args)) return -EINVAL; + for (i = 0; i < FIFO_ENGINE_NR; i++) { + if (args->engine & (1 << i)) { + if (nouveau_engine(parent, fifo_engine[i].subdev)) { + args->engine = (1 << i); + break; + } + } + } + + if (i == FIFO_ENGINE_NR) + return -ENODEV; + ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, priv->user.bar.offset, 0x200, args->pushbuf, - (1 << NVDEV_ENGINE_SW) | - (1 << NVDEV_ENGINE_GR), &chan); + fifo_engine[i].mask, &chan); *pobject = nv_object(chan); if (ret) return ret; nv_parent(chan)->context_attach = nve0_fifo_context_attach; nv_parent(chan)->context_detach = nve0_fifo_context_detach; + chan->engine = i; usermem = chan->base.chid * 0x200; ioffset = args->ioffset; @@ -235,6 +267,7 @@ nve0_fifo_chan_init(struct nouveau_object *object) if (ret) return ret; + nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16); nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); nve0_fifo_playlist_update(priv, chan->engine); diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 17326dd..9c6b0eb 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -65,13 +65,30 @@ struct nv_channel_dma_class { /* 506f: NV50_CHANNEL_IND * 826f: NV84_CHANNEL_IND * 906f: NVC0_CHANNEL_IND - * a06f: NVE0_CHANNEL_IND */ -struct nv_channel_ind_class { +struct nv50_channel_ind_class { u32 pushbuf; u32 ilength; u64 ioffset; }; +/* a06f: NVE0_CHANNEL_IND + */ + +#define NVE0_CHANNEL_IND_ENGINE_GR 0x00000001 +#define NVE0_CHANNEL_IND_ENGINE_VP 0x00000002 +#define NVE0_CHANNEL_IND_ENGINE_PPP 0x00000004 +#define NVE0_CHANNEL_IND_ENGINE_BSP 0x00000008 +#define NVE0_CHANNEL_IND_ENGINE_CE0 0x00000010 +#define NVE0_CHANNEL_IND_ENGINE_CE1 0x00000020 +#define NVE0_CHANNEL_IND_ENGINE_ENC 0x00000040 + +struct nve0_channel_ind_class { + u32 pushbuf; + u32 ilength; + u64 ioffset; + u32 engine; +}; + #endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 4db7b01..1305593 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -36,7 +36,7 @@ enum nv_subdev_type { NVDEV_ENGINE_COPY0, NVDEV_ENGINE_COPY1, NVDEV_ENGINE_UNK1C1, - NVDEV_ENGINE_FENCE, + NVDEV_ENGINE_VENC, NVDEV_ENGINE_DISP, NVDEV_SUBDEV_NR, }; -- cgit v1.1 From 4f32656dc786b402944dbdd7c5b74ed061468895 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2012 19:28:02 +1000 Subject: drm/nve0/copy: add initial support for the async copy engines Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/copy/nve0.c | 156 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/include/engine/copy.h | 2 + drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 5 + 3 files changed, 163 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/engine/copy/nve0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c new file mode 100644 index 0000000..2017c15 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c @@ -0,0 +1,156 @@ +/* + * 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: + * + * 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 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 +#include +#include +#include + +#include + +struct nve0_copy_priv { + struct nouveau_copy base; +}; + +struct nve0_copy_chan { + struct nouveau_copy_chan base; +}; + +/******************************************************************************* + * Copy object classes + ******************************************************************************/ + +static struct nouveau_oclass +nve0_copy_sclass[] = { + { 0xa0b5, &nouveau_object_ofuncs }, + {}, +}; + +/******************************************************************************* + * PCOPY context + ******************************************************************************/ + +static int +nve0_copy_context_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nve0_copy_chan *priv; + int ret; + + ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256, + 256, NVOBJ_FLAG_ZERO_ALLOC, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + return 0; +} + +static struct nouveau_ofuncs +nve0_copy_context_ofuncs = { + .ctor = nve0_copy_context_ctor, + .dtor = _nouveau_copy_context_dtor, + .init = _nouveau_copy_context_init, + .fini = _nouveau_copy_context_fini, + .rd32 = _nouveau_copy_context_rd32, + .wr32 = _nouveau_copy_context_wr32, +}; + +static struct nouveau_oclass +nve0_copy_cclass = { + .handle = NV_ENGCTX(COPY0, 0xc0), + .ofuncs = &nve0_copy_context_ofuncs, +}; + +/******************************************************************************* + * PCOPY engine/subdev functions + ******************************************************************************/ + +static int +nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nve0_copy_priv *priv; + int ret; + + if (nv_rd32(parent, 0x022500) & 0x00000100) + return -ENODEV; + + ret = nouveau_copy_create(parent, engine, oclass, true, 0, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000040; + nv_engine(priv)->cclass = &nve0_copy_cclass; + nv_engine(priv)->sclass = nve0_copy_sclass; + return 0; +} + +static int +nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nve0_copy_priv *priv; + int ret; + + if (nv_rd32(parent, 0x022500) & 0x00000200) + return -ENODEV; + + ret = nouveau_copy_create(parent, engine, oclass, true, 1, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000080; + nv_engine(priv)->cclass = &nve0_copy_cclass; + nv_engine(priv)->sclass = nve0_copy_sclass; + return 0; +} + +struct nouveau_oclass +nve0_copy0_oclass = { + .handle = NV_ENGINE(COPY0, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_copy0_ctor, + .dtor = _nouveau_copy_dtor, + .init = _nouveau_copy_init, + .fini = _nouveau_copy_fini, + }, +}; + +struct nouveau_oclass +nve0_copy1_oclass = { + .handle = NV_ENGINE(COPY1, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_copy1_ctor, + .dtor = _nouveau_copy_dtor, + .init = _nouveau_copy_init, + .fini = _nouveau_copy_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/include/engine/copy.h b/drivers/gpu/drm/nouveau/core/include/engine/copy.h index 23bb9df..70b9d8c 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/copy.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/copy.h @@ -43,5 +43,7 @@ struct nouveau_copy { extern struct nouveau_oclass nva3_copy_oclass; extern struct nouveau_oclass nvc0_copy0_oclass; extern struct nouveau_oclass nvc0_copy1_oclass; +extern struct nouveau_oclass nve0_copy0_oclass; +extern struct nouveau_oclass nve0_copy1_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 2547ac0..efb8ddc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -42,6 +42,7 @@ #include #include #include +#include int nve0_identify(struct nouveau_device *device) @@ -67,6 +68,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; break; case 0xe7: device->cname = "GK107"; @@ -88,6 +91,8 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; + device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; + device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; break; default: nv_fatal(device, "unknown Kepler chipset\n"); -- cgit v1.1 From 6fa8e62937687cb2db10d0e7c7f91eb73a20365c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2012 21:56:18 +1000 Subject: drm/nv84/fifo: mask only the engine we're waiting on for channel unload Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index d3b0356..694a9bb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -81,14 +81,15 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, struct nv50_fifo_priv *priv = (void *)parent->engine; struct nv50_fifo_base *base = (void *)parent->parent; struct nv50_fifo_chan *chan = (void *)parent; - u32 addr; + u32 addr, save, engn; + bool done; switch (nv_engidx(object->engine)) { case NVDEV_ENGINE_SW : return 0; - case NVDEV_ENGINE_GR : addr = 0x0020; break; - case NVDEV_ENGINE_MPEG : addr = 0x0060; break; - case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; - case NVDEV_ENGINE_COPY0: addr = 0x00c0; break; + case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break; + case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break; + case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break; + case NVDEV_ENGINE_COPY0: engn = 2; addr = 0x00c0; break; default: return -EINVAL; } @@ -101,8 +102,11 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, nv_wo32(base->eng, addr + 0x14, 0x00000000); bar->flush(bar); + save = nv_mask(priv, 0x002520, 0x0000003f, 1 << engn); nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); - if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { + done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); + nv_wr32(priv, 0x002520, save); + if (!done) { nv_error(priv, "channel %d unload timeout\n", chan->base.chid); if (suspend) return -EBUSY; -- cgit v1.1 From 3acec63aee5d082f86218973912e682e84ec2a05 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 10 Aug 2012 13:47:56 +1000 Subject: drm/nouveau/core: protect engine context list with hardirq-safe spinlock IRQ handlers will need access to engine contexts. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/engctx.c | 74 ++++++++++++++++------ drivers/gpu/drm/nouveau/core/core/engine.c | 1 + drivers/gpu/drm/nouveau/core/include/core/engctx.h | 2 +- drivers/gpu/drm/nouveau/core/include/core/engine.h | 3 + 4 files changed, 60 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/engctx.c b/drivers/gpu/drm/nouveau/core/core/engctx.c index 50dc16d..38c0612 100644 --- a/drivers/gpu/drm/nouveau/core/core/engctx.c +++ b/drivers/gpu/drm/nouveau/core/core/engctx.c @@ -30,6 +30,25 @@ #include +static inline int +nouveau_engctx_exists(struct nouveau_object *parent, + struct nouveau_engine *engine, void **pobject) +{ + struct nouveau_engctx *engctx; + struct nouveau_object *parctx; + + list_for_each_entry(engctx, &engine->contexts, head) { + parctx = nv_pclass(nv_object(engctx), NV_PARENT_CLASS); + if (parctx == parent) { + atomic_inc(&nv_object(engctx)->refcount); + *pobject = engctx; + return 1; + } + } + + return 0; +} + int nouveau_engctx_create_(struct nouveau_object *parent, struct nouveau_object *engobj, @@ -41,23 +60,22 @@ nouveau_engctx_create_(struct nouveau_object *parent, struct nouveau_client *client = nouveau_client(parent); struct nouveau_engine *engine = nv_engine(engobj); struct nouveau_subdev *subdev = nv_subdev(engine); - struct nouveau_engctx *engctx; - struct nouveau_object *ctxpar; + struct nouveau_object *engctx; + unsigned long save; int ret; - /* use existing context for the engine if one is available */ - mutex_lock(&subdev->mutex); - list_for_each_entry(engctx, &engine->contexts, head) { - ctxpar = nv_pclass(nv_object(engctx), NV_PARENT_CLASS); - if (ctxpar == parent) { - atomic_inc(&nv_object(engctx)->refcount); - *pobject = engctx; - mutex_unlock(&subdev->mutex); - return 1; - } - } - mutex_unlock(&subdev->mutex); + /* check if this engine already has a context for the parent object, + * and reference it instead of creating a new one + */ + spin_lock_irqsave(&engine->lock, save); + ret = nouveau_engctx_exists(parent, engine, pobject); + spin_unlock_irqrestore(&engine->lock, save); + if (ret) + return ret; + /* create the new context, supports creating both raw objects and + * objects backed by instance memory + */ if (size) { ret = nouveau_gpuobj_create_(parent, engobj, oclass, NV_ENGCTX_CLASS, @@ -69,25 +87,43 @@ nouveau_engctx_create_(struct nouveau_object *parent, } engctx = *pobject; - if (engctx && client->vm) - atomic_inc(&client->vm->engref[nv_engidx(engobj)]); if (ret) return ret; - list_add(&engctx->head, &engine->contexts); + /* must take the lock again and re-check a context doesn't already + * exist (in case of a race) - the lock had to be dropped before as + * it's not possible to allocate the object with it held. + */ + spin_lock_irqsave(&engine->lock, save); + ret = nouveau_engctx_exists(parent, engine, pobject); + if (ret) { + spin_unlock_irqrestore(&engine->lock, save); + nouveau_object_ref(NULL, &engctx); + return ret; + } + + if (client->vm) + atomic_inc(&client->vm->engref[nv_engidx(engobj)]); + list_add(&nv_engctx(engctx)->head, &engine->contexts); + spin_unlock_irqrestore(&engine->lock, save); return 0; } void nouveau_engctx_destroy(struct nouveau_engctx *engctx) { - struct nouveau_object *engine = nv_object(engctx)->engine; + struct nouveau_object *engobj = nv_object(engctx)->engine; + struct nouveau_engine *engine = nv_engine(engobj); struct nouveau_client *client = nouveau_client(engctx); + unsigned long save; nouveau_gpuobj_unmap(&engctx->vma); + spin_lock_irqsave(&engine->lock, save); list_del(&engctx->head); + spin_unlock_irqrestore(&engine->lock, save); + if (client->vm) - atomic_dec(&client->vm->engref[nv_engidx(engine)]); + atomic_dec(&client->vm->engref[nv_engidx(engobj)]); if (engctx->base.size) nouveau_gpuobj_destroy(&engctx->base); diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c index ee2905b..09b3bd5 100644 --- a/drivers/gpu/drm/nouveau/core/core/engine.c +++ b/drivers/gpu/drm/nouveau/core/core/engine.c @@ -50,5 +50,6 @@ nouveau_engine_create_(struct nouveau_object *parent, } INIT_LIST_HEAD(&engine->contexts); + spin_lock_init(&engine->lock); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/include/core/engctx.h b/drivers/gpu/drm/nouveau/core/include/core/engctx.h index cbc9eb3..3bc6ccd 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/engctx.h +++ b/drivers/gpu/drm/nouveau/core/include/core/engctx.h @@ -15,7 +15,7 @@ struct nouveau_engctx { struct list_head head; }; -static inline void * +static inline struct nouveau_engctx * nv_engctx(void *obj) { #if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA diff --git a/drivers/gpu/drm/nouveau/core/include/core/engine.h b/drivers/gpu/drm/nouveau/core/include/core/engine.h index 1a7b0a7..666d06d 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/engine.h +++ b/drivers/gpu/drm/nouveau/core/include/core/engine.h @@ -11,7 +11,10 @@ struct nouveau_engine { struct nouveau_subdev base; struct nouveau_oclass *cclass; struct nouveau_oclass *sclass; + struct list_head contexts; + spinlock_t lock; + void (*tile_prog)(struct nouveau_engine *, int region); int (*tlb_flush)(struct nouveau_engine *); }; -- cgit v1.1 From 0c5b8cecf34d6b25e577475cc5e8c7169d63ba92 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 10 Aug 2012 14:02:44 +1000 Subject: drm/nouveau/fifo: add method to lookup fifo chid related to a given object Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 16 ++++++++++++++++ drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 1 + 2 files changed, 17 insertions(+) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index edeb76e..2a7c13d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -132,6 +132,21 @@ _nouveau_fifo_channel_wr32(struct nouveau_object *object, u32 addr, u32 data) iowrite32_native(data, chan->user + addr); } +int +nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object) +{ + int engidx = nv_hclass(priv) & 0xff; + + while (object && object->parent) { + if ( nv_iclass(object->parent, NV_ENGCTX_CLASS) && + (nv_hclass(object->parent) & 0xff) == engidx) + return nouveau_fifo_chan(object)->chid; + object = object->parent; + } + + return -1; +} + void nouveau_fifo_destroy(struct nouveau_fifo *priv) { @@ -160,6 +175,7 @@ nouveau_fifo_create_(struct nouveau_object *parent, if (!priv->channel) return -ENOMEM; + priv->chid = nouveau_fifo_chid; spin_lock_init(&priv->lock); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index 65ee929..f213387 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -70,6 +70,7 @@ struct nouveau_fifo { u16 min; u16 max; + int (*chid)(struct nouveau_fifo *, struct nouveau_object *); void (*pause)(struct nouveau_fifo *, unsigned long *); void (*start)(struct nouveau_fifo *, unsigned long *); }; -- cgit v1.1 From 4c2d42225b5024ad88f736608f44b51f702bd4e4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 10 Aug 2012 15:10:34 +1000 Subject: drm/nouveau/core: have fifo store a unique context identifier at attach time This value will match something that's easily available from the engine IRQ handlers, and used to lookup the relevant context. Since the changes in how this is done on each generation match when the major PFIFO changes happened, fifo is responsible for calculating the correct value to avoid duplicating the same code among many engine modules. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/engctx.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 9 +++++++++ drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 5 +++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 2 ++ drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 2 ++ drivers/gpu/drm/nouveau/core/include/core/engctx.h | 1 + drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 1 + 11 files changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/engctx.c b/drivers/gpu/drm/nouveau/core/core/engctx.c index 38c0612..ad4bbe1 100644 --- a/drivers/gpu/drm/nouveau/core/core/engctx.c +++ b/drivers/gpu/drm/nouveau/core/core/engctx.c @@ -105,6 +105,7 @@ nouveau_engctx_create_(struct nouveau_object *parent, if (client->vm) atomic_inc(&client->vm->engref[nv_engidx(engobj)]); list_add(&nv_engctx(engctx)->head, &engine->contexts); + nv_engctx(engctx)->addr = ~0ULL; spin_unlock_irqrestore(&engine->lock, save); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index 8b7513f..7cd5d76 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -102,6 +102,14 @@ nv04_fifo_object_detach(struct nouveau_object *parent, int cookie) mutex_unlock(&nv_subdev(priv)->mutex); } +int +nv04_fifo_context_attach(struct nouveau_object *parent, + struct nouveau_object *object) +{ + nv_engctx(object)->addr = nouveau_fifo_chan(parent)->chid; + return 0; +} + static int nv04_fifo_chan_ctor(struct nouveau_object *parent, struct nouveau_object *engine, @@ -127,6 +135,7 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent, nv_parent(chan)->object_attach = nv04_fifo_object_attach; nv_parent(chan)->object_detach = nv04_fifo_object_detach; + nv_parent(chan)->context_attach = nv04_fifo_context_attach; chan->ramfc = chan->base.chid * 32; nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 391fefa..5d3638b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -78,6 +78,7 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent, nv_parent(chan)->object_attach = nv04_fifo_object_attach; nv_parent(chan)->object_detach = nv04_fifo_object_detach; + nv_parent(chan)->context_attach = nv04_fifo_context_attach; chan->ramfc = chan->base.chid * 32; nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 3b9d6c9..f223eb9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -85,6 +85,7 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent, nv_parent(chan)->object_attach = nv04_fifo_object_attach; nv_parent(chan)->object_detach = nv04_fifo_object_detach; + nv_parent(chan)->context_attach = nv04_fifo_context_attach; chan->ramfc = chan->base.chid * 64; nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 43d5c9e..ce97c5e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -128,11 +128,12 @@ nv40_fifo_context_attach(struct nouveau_object *parent, } spin_lock_irqsave(&priv->base.lock, flags); + nv_engctx(engctx)->addr = nv_gpuobj(engctx)->addr >> 4; nv_mask(priv, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(priv, 0x003204) & priv->base.max) == chan->base.chid) - nv_wr32(priv, reg, nv_gpuobj(engctx)->addr >> 4); - nv_wo32(priv->ramfc, chan->ramfc + ctx, nv_gpuobj(engctx)->addr >> 4); + nv_wr32(priv, reg, nv_engctx(engctx)->addr); + nv_wo32(priv->ramfc, chan->ramfc + ctx, nv_engctx(engctx)->addr); nv_mask(priv, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&priv->base.lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 5b80f3e..452f224 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -81,6 +81,7 @@ nv50_fifo_context_attach(struct nouveau_object *parent, return -EINVAL; } + nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; nv_wo32(base->eng, addr + 0x00, 0x00190000); nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 694a9bb..80c3927 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -62,6 +62,7 @@ nv84_fifo_context_attach(struct nouveau_object *parent, return -EINVAL; } + nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; nv_wo32(base->eng, addr + 0x00, 0x00190000); nv_wo32(base->eng, addr + 0x04, lower_32_bits(limit)); nv_wo32(base->eng, addr + 0x08, lower_32_bits(start)); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index a4ae2bf..d10dca2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -112,6 +112,8 @@ nvc0_fifo_context_attach(struct nouveau_object *parent, NV_MEM_ACCESS_RW, &ectx->vma); if (ret) return ret; + + nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; } nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index c3f4955..042afad 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -147,6 +147,8 @@ nve0_fifo_context_attach(struct nouveau_object *parent, NV_MEM_ACCESS_RW, &ectx->vma); if (ret) return ret; + + nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12; } nv_wo32(base, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4); diff --git a/drivers/gpu/drm/nouveau/core/include/core/engctx.h b/drivers/gpu/drm/nouveau/core/include/core/engctx.h index 3bc6ccd..227b2c1 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/engctx.h +++ b/drivers/gpu/drm/nouveau/core/include/core/engctx.h @@ -13,6 +13,7 @@ struct nouveau_engctx { struct nouveau_gpuobj base; struct nouveau_vma vma; struct list_head head; + u64 addr; }; static inline struct nouveau_engctx * diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index f213387..d67fed1e 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -106,5 +106,6 @@ extern struct nouveau_oclass nvc0_fifo_oclass; extern struct nouveau_oclass nve0_fifo_oclass; void nv04_fifo_intr(struct nouveau_subdev *); +int nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *); #endif -- cgit v1.1 From 72a148277701acf56bcec486a1124499600812e1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 13 Aug 2012 16:26:07 +1000 Subject: drm/nouveau: restore fifo chid information in engine error messages Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/engctx.c | 57 +++++----------------- drivers/gpu/drm/nouveau/core/core/handle.c | 34 +++++++++++++ drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 15 ++++-- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 14 +++++- drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 13 ++++- drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 13 ++++- drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 13 +++-- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 20 +++++--- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 34 ++++++++----- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 32 +++++++----- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 1 + drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 46 ++++++++++------- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 31 +++++++----- drivers/gpu/drm/nouveau/core/include/core/engctx.h | 17 ++----- drivers/gpu/drm/nouveau/core/include/core/handle.h | 5 ++ 15 files changed, 213 insertions(+), 132 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/engctx.c b/drivers/gpu/drm/nouveau/core/core/engctx.c index ad4bbe1..e41b10d 100644 --- a/drivers/gpu/drm/nouveau/core/core/engctx.c +++ b/drivers/gpu/drm/nouveau/core/core/engctx.c @@ -59,7 +59,6 @@ nouveau_engctx_create_(struct nouveau_object *parent, { struct nouveau_client *client = nouveau_client(parent); struct nouveau_engine *engine = nv_engine(engobj); - struct nouveau_subdev *subdev = nv_subdev(engine); struct nouveau_object *engctx; unsigned long save; int ret; @@ -210,58 +209,28 @@ _nouveau_engctx_fini(struct nouveau_object *object, bool suspend) } struct nouveau_object * -nouveau_engctx_lookup(struct nouveau_engine *engine, u64 addr) +nouveau_engctx_get(struct nouveau_engine *engine, u64 addr) { struct nouveau_engctx *engctx; + unsigned long flags; + spin_lock_irqsave(&engine->lock, flags); list_for_each_entry(engctx, &engine->contexts, head) { - if (engctx->base.size && - nv_gpuobj(engctx)->addr == addr) + if (engctx->addr == addr) { + engctx->save = flags; return nv_object(engctx); + } } - - return NULL; -} - -struct nouveau_handle * -nouveau_engctx_lookup_class(struct nouveau_engine *engine, u64 addr, u16 oclass) -{ - struct nouveau_object *engctx = nouveau_engctx_lookup(engine, addr); - struct nouveau_namedb *namedb; - - if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) - return nouveau_namedb_get_class(namedb, oclass); - - return NULL; -} - -struct nouveau_handle * -nouveau_engctx_lookup_vinst(struct nouveau_engine *engine, u64 addr, u64 vinst) -{ - struct nouveau_object *engctx = nouveau_engctx_lookup(engine, addr); - struct nouveau_namedb *namedb; - - if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) - return nouveau_namedb_get_vinst(namedb, vinst); - - return NULL; -} - -struct nouveau_handle * -nouveau_engctx_lookup_cinst(struct nouveau_engine *engine, u64 addr, u32 cinst) -{ - struct nouveau_object *engctx = nouveau_engctx_lookup(engine, addr); - struct nouveau_namedb *namedb; - - if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) - return nouveau_namedb_get_cinst(namedb, cinst); - + spin_unlock_irqrestore(&engine->lock, flags); return NULL; } void -nouveau_engctx_handle_put(struct nouveau_handle *handle) +nouveau_engctx_put(struct nouveau_object *object) { - if (handle) - nouveau_namedb_put(handle); + if (object) { + struct nouveau_engine *engine = nv_engine(object->engine); + struct nouveau_engctx *engctx = nv_engctx(object); + spin_unlock_irqrestore(&engine->lock, engctx->save); + } } diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c index f2ab2e8..b8d2cbf 100644 --- a/drivers/gpu/drm/nouveau/core/core/handle.c +++ b/drivers/gpu/drm/nouveau/core/core/handle.c @@ -187,3 +187,37 @@ nouveau_handle_ref(struct nouveau_object *parent, u32 name) return object; } + +struct nouveau_handle * +nouveau_handle_get_class(struct nouveau_object *engctx, u16 oclass) +{ + struct nouveau_namedb *namedb; + if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) + return nouveau_namedb_get_class(namedb, oclass); + return NULL; +} + +struct nouveau_handle * +nouveau_handle_get_vinst(struct nouveau_object *engctx, u64 vinst) +{ + struct nouveau_namedb *namedb; + if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) + return nouveau_namedb_get_vinst(namedb, vinst); + return NULL; +} + +struct nouveau_handle * +nouveau_handle_get_cinst(struct nouveau_object *engctx, u32 cinst) +{ + struct nouveau_namedb *namedb; + if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS))) + return nouveau_namedb_get_cinst(namedb, cinst); + return NULL; +} + +void +nouveau_handle_put(struct nouveau_handle *handle) +{ + if (handle) + nouveau_namedb_put(handle); +} diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index debb828..c43c334 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -30,6 +30,7 @@ #include #include +#include #include #include "fuc/nva3.fuc.h" @@ -102,21 +103,28 @@ static struct nouveau_enum nva3_copy_isr_error_name[] = { static void nva3_copy_intr(struct nouveau_subdev *subdev) { + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_object *engctx; struct nva3_copy_priv *priv = (void *)subdev; u32 dispatch = nv_rd32(priv, 0x10401c); u32 stat = nv_rd32(priv, 0x104008) & dispatch & ~(dispatch >> 16); - u32 inst = nv_rd32(priv, 0x104050) & 0x3fffffff; + u64 inst = nv_rd32(priv, 0x104050) & 0x3fffffff; u32 ssta = nv_rd32(priv, 0x104040) & 0x0000ffff; u32 addr = nv_rd32(priv, 0x104040) >> 16; u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; u32 data = nv_rd32(priv, 0x104044); + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x00000040) { nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nva3_copy_isr_error_name, ssta); - printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n", - inst, subc, mthd, data); + printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", + chid, inst << 12, subc, mthd, data); nv_wr32(priv, 0x104004, 0x00000040); stat &= ~0x00000040; } @@ -127,6 +135,7 @@ nva3_copy_intr(struct nouveau_subdev *subdev) } nv50_fb_trap(nouveau_fb(priv), 1); + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index ecc8faa..0c0ce0f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -27,6 +27,7 @@ #include #include +#include #include #include "fuc/nvc0.fuc.h" @@ -113,6 +114,9 @@ static struct nouveau_enum nvc0_copy_isr_error_name[] = { static void nvc0_copy_intr(struct nouveau_subdev *subdev) { + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_object *engctx; int idx = nv_engidx(nv_object(subdev)) - NVDEV_ENGINE_COPY0; struct nvc0_copy_priv *priv = (void *)subdev; u32 disp = nv_rd32(priv, 0x10401c + (idx * 0x1000)); @@ -124,12 +128,16 @@ nvc0_copy_intr(struct nouveau_subdev *subdev) u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; u32 data = nv_rd32(priv, 0x104044 + (idx * 0x1000)); + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x00000040) { nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nvc0_copy_isr_error_name, ssta); - printk("] ch 0x%010llx subc %d mthd 0x%04x data 0x%08x\n", - (u64)inst << 12, subc, mthd, data); + printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", + chid, (u64)inst << 12, subc, mthd, data); nv_wr32(priv, 0x104004 + (idx * 0x1000), 0x00000040); stat &= ~0x00000040; } @@ -138,6 +146,8 @@ nvc0_copy_intr(struct nouveau_subdev *subdev) nv_error(priv, "unhandled intr 0x%08x\n", stat); nv_wr32(priv, 0x104004 + (idx * 0x1000), stat); } + + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index a0e5e39..198989b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -30,6 +30,7 @@ #include +#include #include struct nv84_crypt_priv { @@ -133,23 +134,31 @@ static struct nouveau_bitfield nv84_crypt_intr_mask[] = { static void nv84_crypt_intr(struct nouveau_subdev *subdev) { + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_object *engctx; struct nv84_crypt_priv *priv = (void *)subdev; u32 stat = nv_rd32(priv, 0x102130); u32 mthd = nv_rd32(priv, 0x102190); u32 data = nv_rd32(priv, 0x102194); u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff; + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat) { nv_error(priv, ""); nouveau_bitfield_print(nv84_crypt_intr_mask, stat); - printk(" ch 0x%010llx mthd 0x%04x data 0x%08x\n", - (u64)inst << 12, mthd, data); + printk(" ch %d [0x%010llx] mthd 0x%04x data 0x%08x\n", + chid, (u64)inst << 12, mthd, data); } nv_wr32(priv, 0x102130, stat); nv_wr32(priv, 0x10200c, 0x10); nv50_fb_trap(nouveau_fb(priv), 1); + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index 559a1b1..835b8eb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -30,6 +30,7 @@ #include #include +#include #include #include "fuc/nv98.fuc.h" @@ -102,6 +103,9 @@ static struct nouveau_enum nv98_crypt_isr_error_name[] = { static void nv98_crypt_intr(struct nouveau_subdev *subdev) { + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); + struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_object *engctx; struct nv98_crypt_priv *priv = (void *)subdev; u32 disp = nv_rd32(priv, 0x08701c); u32 stat = nv_rd32(priv, 0x087008) & disp & ~(disp >> 16); @@ -111,12 +115,16 @@ nv98_crypt_intr(struct nouveau_subdev *subdev) u32 mthd = (addr & 0x07ff) << 2; u32 subc = (addr & 0x3800) >> 11; u32 data = nv_rd32(priv, 0x087044); + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x00000040) { nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nv98_crypt_isr_error_name, ssta); - printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n", - inst, subc, mthd, data); + printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", + chid, (u64)inst << 12, subc, mthd, data); nv_wr32(priv, 0x087004, 0x00000040); stat &= ~0x00000040; } @@ -127,6 +135,7 @@ nv98_crypt_intr(struct nouveau_subdev *subdev) } nv50_fb_trap(nouveau_fb(priv), 1); + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 61faef9..8f3f619 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -195,9 +195,10 @@ nv20_graph_tile_prog(struct nouveau_engine *engine, int i) void nv20_graph_intr(struct nouveau_subdev *subdev) { - struct nv20_graph_priv *priv = (void *)subdev; struct nouveau_engine *engine = nv_engine(subdev); - struct nouveau_handle *handle = NULL; + struct nouveau_object *engctx; + struct nouveau_handle *handle; + struct nv20_graph_priv *priv = (void *)subdev; u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR); u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE); u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS); @@ -207,15 +208,15 @@ nv20_graph_intr(struct nouveau_subdev *subdev) 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; + engctx = nouveau_engctx_get(engine, chid); if (stat & NV_PGRAPH_INTR_ERROR) { if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - handle = nouveau_engctx_lookup_class(engine, inst, class); + handle = nouveau_handle_get_class(engctx, class); if (handle && !nv_call(handle->object, mthd, data)) show &= ~NV_PGRAPH_INTR_ERROR; - nouveau_engctx_handle_put(handle); + nouveau_handle_put(handle); } } @@ -233,6 +234,8 @@ nv20_graph_intr(struct nouveau_subdev *subdev) nv_info(priv, "ch %d/%d class 0x%04x mthd 0x%04x data 0x%08x\n", chid, subc, class, mthd, data); } + + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 2f9f2c6..5690fe3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -256,26 +256,32 @@ nv40_graph_tile_prog(struct nouveau_engine *engine, int i) static void nv40_graph_intr(struct nouveau_subdev *subdev) { - struct nv40_graph_priv *priv = (void *)subdev; + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_object *engctx; struct nouveau_handle *handle = NULL; + struct nv40_graph_priv *priv = (void *)subdev; 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 inst = nv_rd32(priv, 0x40032c) & 0x000fffff; 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; + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & NV_PGRAPH_INTR_ERROR) { if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - handle = nouveau_engctx_lookup_class(engine, inst, class); + handle = nouveau_handle_get_class(engctx, class); if (handle && !nv_call(handle->object, mthd, data)) show &= ~NV_PGRAPH_INTR_ERROR; - nouveau_engctx_handle_put(handle); + nouveau_handle_put(handle); } if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { @@ -294,10 +300,12 @@ nv40_graph_intr(struct nouveau_subdev *subdev) printk(" nstatus:"); nouveau_bitfield_print(nv10_graph_nstatus, nstatus); printk("\n"); - nv_error(priv, "ch 0x%08x subc %d class 0x%04x " + nv_error(priv, "ch %d [0x%08x] subc %d class 0x%04x " "mthd 0x%04x data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst << 4, subc, class, mthd, data); } + + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 8955bdd..c93b525 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -32,6 +32,7 @@ #include #include +#include #include #include "nv50.h" @@ -462,7 +463,8 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old, } static int -nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, u64 inst) +nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, + int chid, u64 inst) { u32 status = nv_rd32(priv, 0x400108); u32 ustatus; @@ -495,11 +497,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, u64 inst) nv_error(priv, "TRAP DISPATCH_FAULT\n"); if (display && (addr & 0x80000000)) { - nv_error(priv, "ch 0x%010llx " + nv_error(priv, "ch %d [0x%010llx] " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x%08x " "400808 0x%08x 400848 0x%08x\n", - inst, subc, class, mthd, datah, + chid, inst, subc, class, mthd, datah, datal, addr, r848); } else if (display) { @@ -521,10 +523,10 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, u64 inst) nv_error(priv, "TRAP DISPATCH_QUERY\n"); if (display && (addr & 0x80000000)) { - nv_error(priv, "ch 0x%010llx " + nv_error(priv, "ch %d [0x%010llx] " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x 40084c 0x%08x\n", - inst, subc, class, mthd, + chid, inst, subc, class, mthd, data, addr); } else if (display) { @@ -675,23 +677,29 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, u64 inst) static void nv50_graph_intr(struct nouveau_subdev *subdev) { - struct nv50_graph_priv *priv = (void *)subdev; + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); + struct nouveau_object *engctx; struct nouveau_handle *handle = NULL; + struct nv50_graph_priv *priv = (void *)subdev; u32 stat = nv_rd32(priv, 0x400100); - u64 inst = (u64)(nv_rd32(priv, 0x40032c) & 0x0fffffff) << 12; + u32 inst = nv_rd32(priv, 0x40032c) & 0x0fffffff; 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; + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x00000010) { - handle = nouveau_engctx_lookup_class(engine, inst, class); + handle = nouveau_handle_get_class(engctx, class); if (handle && !nv_call(handle->object, mthd, data)) show &= ~0x00000010; - nouveau_engctx_handle_put(handle); + nouveau_handle_put(handle); } if (show & 0x00100000) { @@ -702,7 +710,7 @@ nv50_graph_intr(struct nouveau_subdev *subdev) } if (stat & 0x00200000) { - if (!nv50_graph_trap_handler(priv, show, inst)) + if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12)) show &= ~0x00200000; } @@ -713,14 +721,16 @@ nv50_graph_intr(struct nouveau_subdev *subdev) nv_info(priv, ""); nouveau_bitfield_print(nv50_graph_intr_name, show); printk("\n"); - nv_error(priv, "ch 0x%010llx subc %d class 0x%04x " + nv_error(priv, "ch %d [0x%010llx] subc %d class 0x%04x " "mthd 0x%04x data 0x%08x\n", - inst, subc, class, mthd, data); + chid, (u64)inst << 12, subc, class, mthd, data); nv50_fb_trap(nouveau_fb(priv), 1); } if (nv_rd32(priv, 0x400824) & (1 << 31)) nv_wr32(priv, 0x400824, nv_rd32(priv, 0x400824) & ~(1 << 31)); + + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index e2f1bea..f002e7e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -226,10 +226,12 @@ nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) static void nvc0_graph_intr(struct nouveau_subdev *subdev) { - struct nvc0_graph_priv *priv = (void *)subdev; + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); - struct nouveau_handle *handle = NULL; - u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; + struct nouveau_object *engctx; + struct nouveau_handle *handle; + struct nvc0_graph_priv *priv = (void *)subdev; + u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff; u32 stat = nv_rd32(priv, 0x400100); u32 addr = nv_rd32(priv, 0x400704); u32 mthd = (addr & 0x00003ffc); @@ -237,24 +239,28 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) u32 data = nv_rd32(priv, 0x400708); u32 code = nv_rd32(priv, 0x400110); u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x00000010) { - handle = nouveau_engctx_lookup_class(engine, inst, class); + handle = nouveau_handle_get_class(engctx, class); if (!handle || nv_call(handle->object, mthd, data)) { - nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " + nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst << 12, subc, class, mthd, data); } - nouveau_engctx_handle_put(handle); + nouveau_handle_put(handle); nv_wr32(priv, 0x400100, 0x00000010); stat &= ~0x00000010; } if (stat & 0x00000020) { - nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " + nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " "class 0x%04x mthd 0x%04x data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst << 12, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00000020); stat &= ~0x00000020; } @@ -262,16 +268,17 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) 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 " + printk("] ch %d [0x%010llx] subc %d class 0x%04x " "mthd 0x%04x data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst << 12, 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_error(priv, "TRAP ch %d [0x%010llx] status 0x%08x\n", + chid, inst << 12, trap); nv_wr32(priv, 0x400108, trap); nv_wr32(priv, 0x400100, 0x00200000); stat &= ~0x00200000; @@ -289,6 +296,7 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) } nv_wr32(priv, 0x400500, 0x00010001); + nouveau_engctx_put(engctx); } int diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 26f8268..18d2210 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -35,6 +35,7 @@ #include #include +#include #include #define GPC_MAX 4 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 7ef692b..2ba125b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -76,14 +76,15 @@ nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) } static void -nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) +nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst) { 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_error(priv, "DISPATCH ch %d [0x%010llx] 0x%08x\n", + chid, inst, stat); nv_wr32(priv, 0x404000, 0xc0000000); nv_wr32(priv, 0x400108, 0x00000001); trap &= ~0x00000001; @@ -91,7 +92,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) if (trap & 0x00000010) { u32 stat = nv_rd32(priv, 0x405840); - nv_error(priv, "SHADER ch 0x%010llx 0x%08x\n", inst, stat); + nv_error(priv, "SHADER ch %d [0x%010llx] 0x%08x\n", + chid, inst, stat); nv_wr32(priv, 0x405840, 0xc0000000); nv_wr32(priv, 0x400108, 0x00000010); trap &= ~0x00000010; @@ -101,8 +103,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) 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_error(priv, "ROP%d ch %d [0x%010llx] 0x%08x 0x%08x\n", + rop, chid, inst, statz, statc); nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); } @@ -111,7 +113,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) } if (trap) { - nv_error(priv, "TRAP ch 0x%010llx 0x%08x\n", inst, trap); + nv_error(priv, "TRAP ch %d [0x%010llx] 0x%08x\n", + chid, inst, trap); nv_wr32(priv, 0x400108, trap); } } @@ -119,10 +122,12 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) static void nve0_graph_intr(struct nouveau_subdev *subdev) { - struct nvc0_graph_priv *priv = (void *)subdev; + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); - struct nouveau_handle *handle = NULL; - u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; + struct nouveau_object *engctx; + struct nouveau_handle *handle; + struct nvc0_graph_priv *priv = (void *)subdev; + u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff; u32 stat = nv_rd32(priv, 0x400100); u32 addr = nv_rd32(priv, 0x400704); u32 mthd = (addr & 0x00003ffc); @@ -130,24 +135,28 @@ nve0_graph_intr(struct nouveau_subdev *subdev) u32 data = nv_rd32(priv, 0x400708); u32 code = nv_rd32(priv, 0x400110); u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x00000010) { - handle = nouveau_engctx_lookup_class(engine, inst, class); + handle = nouveau_handle_get_class(engctx, class); if (!handle || nv_call(handle->object, mthd, data)) { - nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " + nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " "subc %d class 0x%04x mthd 0x%04x " "data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst, subc, class, mthd, data); } - nouveau_engctx_handle_put(handle); + nouveau_handle_put(handle); nv_wr32(priv, 0x400100, 0x00000010); stat &= ~0x00000010; } if (stat & 0x00000020) { - nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " + nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " "class 0x%04x mthd 0x%04x data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00000020); stat &= ~0x00000020; } @@ -155,15 +164,15 @@ nve0_graph_intr(struct nouveau_subdev *subdev) 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 " + printk("] ch %d [0x%010llx] subc %d class 0x%04x " "mthd 0x%04x data 0x%08x\n", - inst, subc, class, mthd, data); + chid, inst, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00100000); stat &= ~0x00100000; } if (stat & 0x00200000) { - nve0_graph_trap_isr(priv, inst); + nve0_graph_trap_isr(priv, chid, inst); nv_wr32(priv, 0x400100, 0x00200000); stat &= ~0x00200000; } @@ -180,6 +189,7 @@ nve0_graph_intr(struct nouveau_subdev *subdev) } nv_wr32(priv, 0x400500, 0x00010001); + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 7a1bc76..9adcefc 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -26,13 +26,14 @@ #include #include #include -#include #include #include #include +#include #include +#include struct nv31_mpeg_priv { struct nouveau_mpeg base; @@ -195,30 +196,34 @@ nv31_mpeg_tile_prog(struct nouveau_engine *engine, int i) void nv31_mpeg_intr(struct nouveau_subdev *subdev) { - struct nv31_mpeg_priv *priv = (void *)subdev; + struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); - struct nouveau_handle *handle = NULL; - u32 inst = (nv_rd32(priv, 0x00b318) & 0x000fffff) << 4; + struct nouveau_object *engctx; + struct nouveau_handle *handle; + struct nv31_mpeg_priv *priv = (void *)subdev; + u32 inst = nv_rd32(priv, 0x00b318) & 0x000fffff; u32 stat = nv_rd32(priv, 0x00b100); u32 type = nv_rd32(priv, 0x00b230); u32 mthd = nv_rd32(priv, 0x00b234); u32 data = nv_rd32(priv, 0x00b238); u32 show = stat; + int chid; + + engctx = nouveau_engctx_get(engine, inst); + chid = pfifo->chid(pfifo, engctx); if (stat & 0x01000000) { /* happens on initial binding of the object */ - if (handle && type == 0x00000020 && mthd == 0x0000) { + if (type == 0x00000020 && mthd == 0x0000) { nv_mask(priv, 0x00b308, 0x00000000, 0x00000000); show &= ~0x01000000; } - if (handle && type == 0x00000010) { - handle = nouveau_engctx_lookup_class(engine, inst, 0x3174); - - if (handle && !nv_call(handle->object, mthd, data)) { - nouveau_engctx_handle_put(handle); + if (type == 0x00000010) { + handle = nouveau_handle_get_class(engctx, 0x3174); + if (handle && !nv_call(handle->object, mthd, data)) show &= ~0x01000000; - } + nouveau_handle_put(handle); } } @@ -227,8 +232,10 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev) if (show) { nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", - inst, stat, type, mthd, data); + chid, inst << 4, stat, type, mthd, data); } + + nouveau_engctx_put(engctx); } static int diff --git a/drivers/gpu/drm/nouveau/core/include/core/engctx.h b/drivers/gpu/drm/nouveau/core/include/core/engctx.h index 227b2c1..8a947b6 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/engctx.h +++ b/drivers/gpu/drm/nouveau/core/include/core/engctx.h @@ -13,6 +13,7 @@ struct nouveau_engctx { struct nouveau_gpuobj base; struct nouveau_vma vma; struct list_head head; + unsigned long save; u64 addr; }; @@ -44,19 +45,7 @@ int _nouveau_engctx_fini(struct nouveau_object *, bool suspend); #define _nouveau_engctx_rd32 _nouveau_gpuobj_rd32 #define _nouveau_engctx_wr32 _nouveau_gpuobj_wr32 -struct nouveau_object * -nouveau_engctx_lookup(struct nouveau_engine *, u64 addr); - -struct nouveau_handle * -nouveau_engctx_lookup_class(struct nouveau_engine *, u64, u16); - -struct nouveau_handle * -nouveau_engctx_lookup_vinst(struct nouveau_engine *, u64, u64); - -struct nouveau_handle * -nouveau_engctx_lookup_cinst(struct nouveau_engine *, u64, u32); - -void -nouveau_engctx_handle_put(struct nouveau_handle *); +struct nouveau_object *nouveau_engctx_get(struct nouveau_engine *, u64 addr); +void nouveau_engctx_put(struct nouveau_object *); #endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/handle.h b/drivers/gpu/drm/nouveau/core/include/core/handle.h index fbfbe55..363674c 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/handle.h +++ b/drivers/gpu/drm/nouveau/core/include/core/handle.h @@ -23,4 +23,9 @@ int nouveau_handle_fini(struct nouveau_handle *, bool suspend); struct nouveau_object * nouveau_handle_ref(struct nouveau_object *, u32 name); +struct nouveau_handle *nouveau_handle_get_class(struct nouveau_object *, u16); +struct nouveau_handle *nouveau_handle_get_vinst(struct nouveau_object *, u64); +struct nouveau_handle *nouveau_handle_get_cinst(struct nouveau_object *, u32); +void nouveau_handle_put(struct nouveau_handle *); + #endif -- cgit v1.1 From 503b0f1cd66c54dd88e644fa1a521ebd764bf54e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Aug 2012 14:53:51 +1000 Subject: drm/nouveau/fifo: separate object classes for dma channels Future code will use the object class rather than chipset checks in order to identify available channel features. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c | 3 +++ drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/include/core/class.h | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c index b0d3651..848aa3b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c @@ -118,7 +118,10 @@ nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; switch (nv_mclass(parent)) { + case 0x006b: case 0x006e: + case 0x176e: + case 0x406e: ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); nouveau_object_ref(NULL, pobject); *pobject = nv_object(gpuobj); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index 7cd5d76..ed77192 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -247,7 +247,7 @@ nv04_fifo_ofuncs = { static struct nouveau_oclass nv04_fifo_sclass[] = { - { 0x006e, &nv04_fifo_ofuncs }, + { 0x006b, &nv04_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index f223eb9..347b91e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -113,7 +113,7 @@ nv17_fifo_ofuncs = { static struct nouveau_oclass nv17_fifo_sclass[] = { - { 0x006e, &nv17_fifo_ofuncs }, + { 0x176e, &nv17_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index ce97c5e..48114e6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -232,7 +232,7 @@ nv40_fifo_ofuncs = { static struct nouveau_oclass nv40_fifo_sclass[] = { - { 0x006e, &nv40_fifo_ofuncs }, + { 0x406e, &nv40_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 9c6b0eb..55b53ed 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -53,6 +53,7 @@ struct nv_dma_class { /* 006b: NV03_CHANNEL_DMA * 006e: NV10_CHANNEL_DMA + * 176e: NV17_CHANNEL_DMA * 406e: NV40_CHANNEL_DMA */ -- cgit v1.1 From a7c6e75eb28d18ed8d53182891330f5c1fa4477c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Aug 2012 15:02:29 +1000 Subject: drm/nouveau/fifo: version the dma channel class struct Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/include/core/class.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index ed77192..cc49284 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -118,7 +118,7 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent, { struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_chan *chan; - struct nv_channel_dma_class *args = data; + struct nv03_channel_dma_class *args = data; int ret; if (size < sizeof(*args)) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 5d3638b..c4c78d5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -61,7 +61,7 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent, { struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_chan *chan; - struct nv_channel_dma_class *args = data; + struct nv03_channel_dma_class *args = data; int ret; if (size < sizeof(*args)) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 347b91e..1733765 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -66,7 +66,7 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent, { struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_chan *chan; - struct nv_channel_dma_class *args = data; + struct nv03_channel_dma_class *args = data; int ret; if (size < sizeof(*args)) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 48114e6..aef8ca1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -184,7 +184,7 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent, { struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_chan *chan; - struct nv_channel_dma_class *args = data; + struct nv03_channel_dma_class *args = data; int ret; if (size < sizeof(*args)) diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 55b53ed..10279d2 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -57,7 +57,7 @@ struct nv_dma_class { * 406e: NV40_CHANNEL_DMA */ -struct nv_channel_dma_class { +struct nv03_channel_dma_class { u32 pushbuf; u32 pad0; u64 offset; -- cgit v1.1 From ab2858928b09911b7ab21051d7fc3f973d630bff Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Aug 2012 15:30:14 +1000 Subject: drm/nv84/fifo: add support for dma channel class Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 86 +++++++++++++++++++++-- drivers/gpu/drm/nouveau/core/include/core/class.h | 1 + 3 files changed, 81 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c index 8207ac9..fbcd9d0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c @@ -110,6 +110,7 @@ nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, switch (nv_mclass(parent)) { case 0x506f: + case 0x826e: case 0x826f: ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); nouveau_object_ref(NULL, pobject); diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 80c3927..88ca9e8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -147,10 +147,71 @@ nv84_fifo_object_attach(struct nouveau_object *parent, } static int -nv84_fifo_chan_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) +nv84_fifo_chan_ctor_dma(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent; + struct nv50_fifo_chan *chan; + struct nv03_channel_dma_class *args = data; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x2000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG) | + (1 << NVDEV_ENGINE_ME) | + (1 << NVDEV_ENGINE_VP) | + (1 << NVDEV_ENGINE_CRYPT) | + (1 << NVDEV_ENGINE_BSP) | + (1 << NVDEV_ENGINE_PPP) | + (1 << NVDEV_ENGINE_COPY0) | + (1 << NVDEV_ENGINE_UNK1C1), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nv84_fifo_context_attach; + nv_parent(chan)->context_detach = nv84_fifo_context_detach; + nv_parent(chan)->object_attach = nv84_fifo_object_attach; + nv_parent(chan)->object_detach = nv50_fifo_object_detach; + + nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x3c, 0x003f6078); + nv_wo32(base->ramfc, 0x44, 0x01003fff); + nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); + nv_wo32(base->ramfc, 0x4c, 0xffffffff); + nv_wo32(base->ramfc, 0x60, 0x7fffffff); + nv_wo32(base->ramfc, 0x78, 0x00000000); + nv_wo32(base->ramfc, 0x7c, 0x30000001); + nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->base.node->offset >> 4)); + nv_wo32(base->ramfc, 0x88, base->cache->addr >> 10); + nv_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12); + bar->flush(bar); + return 0; +} + +static int +nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { struct nouveau_bar *bar = nouveau_bar(parent); struct nv50_fifo_base *base = (void *)parent; @@ -228,8 +289,18 @@ nv84_fifo_chan_init(struct nouveau_object *object) } static struct nouveau_ofuncs -nv84_fifo_ofuncs = { - .ctor = nv84_fifo_chan_ctor, +nv84_fifo_ofuncs_dma = { + .ctor = nv84_fifo_chan_ctor_dma, + .dtor = nv50_fifo_chan_dtor, + .init = nv84_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_ofuncs +nv84_fifo_ofuncs_ind = { + .ctor = nv84_fifo_chan_ctor_ind, .dtor = nv50_fifo_chan_dtor, .init = nv84_fifo_chan_init, .fini = nv50_fifo_chan_fini, @@ -239,7 +310,8 @@ nv84_fifo_ofuncs = { static struct nouveau_oclass nv84_fifo_sclass[] = { - { 0x826f, &nv84_fifo_ofuncs }, + { 0x826e, &nv84_fifo_ofuncs_dma }, + { 0x826f, &nv84_fifo_ofuncs_ind }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 10279d2..3675915 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -55,6 +55,7 @@ struct nv_dma_class { * 006e: NV10_CHANNEL_DMA * 176e: NV17_CHANNEL_DMA * 406e: NV40_CHANNEL_DMA + * 826e: NV84_CHANNEL_DMA */ struct nv03_channel_dma_class { -- cgit v1.1 From 368be5f1b84b3356eb03ad2ccaf073e2fbb7fc4e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Aug 2012 15:33:20 +1000 Subject: drm/nv50/fifo: add support for dma channel class Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 77 ++++++++++++++++++++--- drivers/gpu/drm/nouveau/core/include/core/class.h | 1 + 3 files changed, 72 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c index fbcd9d0..be5c0df 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c @@ -109,6 +109,7 @@ nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; switch (nv_mclass(parent)) { + case 0x506e: case 0x506f: case 0x826e: case 0x826f: diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 452f224..44a0dce 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -178,10 +178,62 @@ nv50_fifo_object_detach(struct nouveau_object *parent, int cookie) } static int -nv50_fifo_chan_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) +nv50_fifo_chan_ctor_dma(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_bar *bar = nouveau_bar(parent); + struct nv50_fifo_base *base = (void *)parent; + struct nv50_fifo_chan *chan; + struct nv03_channel_dma_class *args = data; + int ret; + + if (size < sizeof(*args)) + return -EINVAL; + + ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, + 0x2000, args->pushbuf, + (1 << NVDEV_ENGINE_DMAOBJ) | + (1 << NVDEV_ENGINE_SW) | + (1 << NVDEV_ENGINE_GR) | + (1 << NVDEV_ENGINE_MPEG), &chan); + *pobject = nv_object(chan); + if (ret) + return ret; + + nv_parent(chan)->context_attach = nv50_fifo_context_attach; + nv_parent(chan)->context_detach = nv50_fifo_context_detach; + nv_parent(chan)->object_attach = nv50_fifo_object_attach; + nv_parent(chan)->object_detach = nv50_fifo_object_detach; + + ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht); + if (ret) + return ret; + + nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset)); + nv_wo32(base->ramfc, 0x3c, 0x003f6078); + nv_wo32(base->ramfc, 0x44, 0x01003fff); + nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); + nv_wo32(base->ramfc, 0x4c, 0xffffffff); + nv_wo32(base->ramfc, 0x60, 0x7fffffff); + nv_wo32(base->ramfc, 0x78, 0x00000000); + nv_wo32(base->ramfc, 0x7c, 0x30000001); + nv_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->base.node->offset >> 4)); + bar->flush(bar); + return 0; +} + +static int +nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { struct nv50_channel_ind_class *args = data; struct nouveau_bar *bar = nouveau_bar(parent); @@ -273,8 +325,18 @@ nv50_fifo_chan_fini(struct nouveau_object *object, bool suspend) } static struct nouveau_ofuncs -nv50_fifo_ofuncs = { - .ctor = nv50_fifo_chan_ctor, +nv50_fifo_ofuncs_dma = { + .ctor = nv50_fifo_chan_ctor_dma, + .dtor = nv50_fifo_chan_dtor, + .init = nv50_fifo_chan_init, + .fini = nv50_fifo_chan_fini, + .rd32 = _nouveau_fifo_channel_rd32, + .wr32 = _nouveau_fifo_channel_wr32, +}; + +static struct nouveau_ofuncs +nv50_fifo_ofuncs_ind = { + .ctor = nv50_fifo_chan_ctor_ind, .dtor = nv50_fifo_chan_dtor, .init = nv50_fifo_chan_init, .fini = nv50_fifo_chan_fini, @@ -284,7 +346,8 @@ nv50_fifo_ofuncs = { static struct nouveau_oclass nv50_fifo_sclass[] = { - { 0x506f, &nv50_fifo_ofuncs }, + { 0x506e, &nv50_fifo_ofuncs_dma }, + { 0x506f, &nv50_fifo_ofuncs_ind }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 3675915..b0e1948 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -55,6 +55,7 @@ struct nv_dma_class { * 006e: NV10_CHANNEL_DMA * 176e: NV17_CHANNEL_DMA * 406e: NV40_CHANNEL_DMA + * 506e: NV50_CHANNEL_DMA * 826e: NV84_CHANNEL_DMA */ -- cgit v1.1 From 9456f7d1beb8f7cfd99300e6028b3b2667c2ebd5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 19 Aug 2012 15:53:15 +1000 Subject: drm/nouveau: add defines for internal class names Will probably flesh the documentation of the classes out a bit too at some later point. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/core/class.h | 49 ++++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index b0e1948..6180ae9 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -1,8 +1,11 @@ #ifndef __NOUVEAU_CLASS_H__ #define __NOUVEAU_CLASS_H__ -/* 0080: NV_DEVICE +/* Device class + * + * 0080: NV_DEVICE */ +#define NV_DEVICE_CLASS 0x00000080 #define NV_DEVICE_DISABLE_IDENTIFY 0x0000000000000001ULL #define NV_DEVICE_DISABLE_MMIO 0x0000000000000002ULL @@ -27,10 +30,15 @@ struct nv_device_class { u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */ }; -/* 0002: NV_DMA_FROM_MEMORY +/* DMA object classes + * + * 0002: NV_DMA_FROM_MEMORY * 0003: NV_DMA_TO_MEMORY * 003d: NV_DMA_IN_MEMORY */ +#define NV_DMA_FROM_MEMORY_CLASS 0x00000002 +#define NV_DMA_TO_MEMORY_CLASS 0x00000003 +#define NV_DMA_IN_MEMORY_CLASS 0x0000003d #define NV_DMA_TARGET_MASK 0x000000ff #define NV_DMA_TARGET_VM 0x00000000 @@ -51,13 +59,21 @@ struct nv_dma_class { u64 limit; }; -/* 006b: NV03_CHANNEL_DMA +/* DMA FIFO channel classes + * + * 006b: NV03_CHANNEL_DMA * 006e: NV10_CHANNEL_DMA * 176e: NV17_CHANNEL_DMA * 406e: NV40_CHANNEL_DMA * 506e: NV50_CHANNEL_DMA * 826e: NV84_CHANNEL_DMA */ +#define NV03_CHANNEL_DMA_CLASS 0x0000006b +#define NV10_CHANNEL_DMA_CLASS 0x0000006e +#define NV17_CHANNEL_DMA_CLASS 0x0000176e +#define NV40_CHANNEL_DMA_CLASS 0x0000406e +#define NV50_CHANNEL_DMA_CLASS 0x0000506e +#define NV84_CHANNEL_DMA_CLASS 0x0000826e struct nv03_channel_dma_class { u32 pushbuf; @@ -65,27 +81,32 @@ struct nv03_channel_dma_class { u64 offset; }; -/* 506f: NV50_CHANNEL_IND +/* Indirect FIFO channel classes + * + * 506f: NV50_CHANNEL_IND * 826f: NV84_CHANNEL_IND * 906f: NVC0_CHANNEL_IND + * a06f: NVE0_CHANNEL_IND */ +#define NV50_CHANNEL_IND_CLASS 0x0000506f +#define NV84_CHANNEL_IND_CLASS 0x0000826f +#define NVC0_CHANNEL_IND_CLASS 0x0000906f +#define NVE0_CHANNEL_IND_CLASS 0x0000a06f + struct nv50_channel_ind_class { u32 pushbuf; u32 ilength; u64 ioffset; }; -/* a06f: NVE0_CHANNEL_IND - */ - -#define NVE0_CHANNEL_IND_ENGINE_GR 0x00000001 -#define NVE0_CHANNEL_IND_ENGINE_VP 0x00000002 -#define NVE0_CHANNEL_IND_ENGINE_PPP 0x00000004 -#define NVE0_CHANNEL_IND_ENGINE_BSP 0x00000008 -#define NVE0_CHANNEL_IND_ENGINE_CE0 0x00000010 -#define NVE0_CHANNEL_IND_ENGINE_CE1 0x00000020 -#define NVE0_CHANNEL_IND_ENGINE_ENC 0x00000040 +#define NVE0_CHANNEL_IND_ENGINE_GR 0x00000001 +#define NVE0_CHANNEL_IND_ENGINE_VP 0x00000002 +#define NVE0_CHANNEL_IND_ENGINE_PPP 0x00000004 +#define NVE0_CHANNEL_IND_ENGINE_BSP 0x00000008 +#define NVE0_CHANNEL_IND_ENGINE_CE0 0x00000010 +#define NVE0_CHANNEL_IND_ENGINE_CE1 0x00000020 +#define NVE0_CHANNEL_IND_ENGINE_ENC 0x00000040 struct nve0_channel_ind_class { u32 pushbuf; -- cgit v1.1 From 1971f04e16172db79b8b0eed75fb2cb82adfbb83 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 19 Aug 2012 15:58:38 +1000 Subject: drm/nouveau/dmaobj: reject unsupported parent types instead of half-succeeding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c | 13 ++++++++----- drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c index 848aa3b..5ad76f7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c @@ -23,6 +23,7 @@ */ #include +#include #include #include @@ -118,16 +119,18 @@ nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; switch (nv_mclass(parent)) { - case 0x006b: - case 0x006e: - case 0x176e: - case 0x406e: + case NV_DEVICE_CLASS: + break; + case NV03_CHANNEL_DMA_CLASS: + case NV10_CHANNEL_DMA_CLASS: + case NV17_CHANNEL_DMA_CLASS: + case NV40_CHANNEL_DMA_CLASS: ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); nouveau_object_ref(NULL, pobject); *pobject = nv_object(gpuobj); break; default: - break; + return -EINVAL; } return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c index be5c0df..045d256 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c @@ -23,6 +23,7 @@ */ #include +#include #include #include @@ -109,16 +110,18 @@ nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; switch (nv_mclass(parent)) { - case 0x506e: - case 0x506f: - case 0x826e: - case 0x826f: + case NV_DEVICE_CLASS: + break; + case NV50_CHANNEL_DMA_CLASS: + case NV84_CHANNEL_DMA_CLASS: + case NV50_CHANNEL_IND_CLASS: + case NV84_CHANNEL_IND_CLASS: ret = dmaeng->bind(dmaeng, *pobject, &dmaobj->base, &gpuobj); nouveau_object_ref(NULL, pobject); *pobject = nv_object(gpuobj); break; default: - break; + return -EINVAL; } return ret; -- cgit v1.1 From c97f8c922ea78195aa7d833d639d2963cc11af8e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 19 Aug 2012 16:03:00 +1000 Subject: drm/nouveau/fifo: use defines instead of hardcoded class ids Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 4 ++-- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 4 ++-- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index cc49284..ea76e3e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -247,7 +247,7 @@ nv04_fifo_ofuncs = { static struct nouveau_oclass nv04_fifo_sclass[] = { - { 0x006b, &nv04_fifo_ofuncs }, + { NV03_CHANNEL_DMA_CLASS, &nv04_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index c4c78d5..4ba7542 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -106,7 +106,7 @@ nv10_fifo_ofuncs = { static struct nouveau_oclass nv10_fifo_sclass[] = { - { 0x006e, &nv10_fifo_ofuncs }, + { NV10_CHANNEL_DMA_CLASS, &nv10_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 1733765..b96e6b0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -113,7 +113,7 @@ nv17_fifo_ofuncs = { static struct nouveau_oclass nv17_fifo_sclass[] = { - { 0x176e, &nv17_fifo_ofuncs }, + { NV17_CHANNEL_DMA_CLASS, &nv17_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index aef8ca1..559c3b4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -232,7 +232,7 @@ nv40_fifo_ofuncs = { static struct nouveau_oclass nv40_fifo_sclass[] = { - { 0x406e, &nv40_fifo_ofuncs }, + { NV40_CHANNEL_DMA_CLASS, &nv40_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 44a0dce..536e763 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -346,8 +346,8 @@ nv50_fifo_ofuncs_ind = { static struct nouveau_oclass nv50_fifo_sclass[] = { - { 0x506e, &nv50_fifo_ofuncs_dma }, - { 0x506f, &nv50_fifo_ofuncs_ind }, + { NV50_CHANNEL_DMA_CLASS, &nv50_fifo_ofuncs_dma }, + { NV50_CHANNEL_IND_CLASS, &nv50_fifo_ofuncs_ind }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 88ca9e8..55620fb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -310,8 +310,8 @@ nv84_fifo_ofuncs_ind = { static struct nouveau_oclass nv84_fifo_sclass[] = { - { 0x826e, &nv84_fifo_ofuncs_dma }, - { 0x826f, &nv84_fifo_ofuncs_ind }, + { NV84_CHANNEL_DMA_CLASS, &nv84_fifo_ofuncs_dma }, + { NV84_CHANNEL_IND_CLASS, &nv84_fifo_ofuncs_ind }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index d10dca2..dda0a44 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -258,7 +258,7 @@ nvc0_fifo_ofuncs = { static struct nouveau_oclass nvc0_fifo_sclass[] = { - { 0x906f, &nvc0_fifo_ofuncs }, + { NVC0_CHANNEL_IND_CLASS, &nvc0_fifo_ofuncs }, {} }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 042afad..f480323 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -303,7 +303,7 @@ nve0_fifo_ofuncs = { static struct nouveau_oclass nve0_fifo_sclass[] = { - { 0xa06f, &nve0_fifo_ofuncs }, + { NVE0_CHANNEL_IND_CLASS, &nve0_fifo_ofuncs }, {} }; -- cgit v1.1 From e6626254f99be74bdae291a12c3981b996de6409 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 19 Aug 2012 22:59:59 +0200 Subject: drm/nouveau: constify instances of nouveau_bitfield and nouveau_enum structs Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 2 +- drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c | 2 +- drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 2 +- drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 10 +++++----- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 10 +++++----- drivers/gpu/drm/nouveau/core/engine/graph/nv04.c | 6 +++--- drivers/gpu/drm/nouveau/core/engine/graph/nv10.c | 4 ++-- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 14 +++++++------- drivers/gpu/drm/nouveau/core/include/core/enum.h | 2 +- drivers/gpu/drm/nouveau/core/include/engine/graph.h | 8 ++++---- drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 16 ++++++++-------- 12 files changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index c43c334..4df6da0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -93,7 +93,7 @@ nva3_copy_cclass = { * PCOPY engine/subdev functions ******************************************************************************/ -static struct nouveau_enum nva3_copy_isr_error_name[] = { +static const struct nouveau_enum nva3_copy_isr_error_name[] = { { 0x0001, "ILLEGAL_MTHD" }, { 0x0002, "INVALID_ENUM" }, { 0x0003, "INVALID_BITFIELD" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index 0c0ce0f..06d4a87 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -104,7 +104,7 @@ nvc0_copy1_cclass = { * PCOPY engine/subdev functions ******************************************************************************/ -static struct nouveau_enum nvc0_copy_isr_error_name[] = { +static const struct nouveau_enum nvc0_copy_isr_error_name[] = { { 0x0001, "ILLEGAL_MTHD" }, { 0x0002, "INVALID_ENUM" }, { 0x0003, "INVALID_BITFIELD" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 198989b..1d85e5b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -122,7 +122,7 @@ nv84_crypt_cclass = { * PCRYPT engine/subdev functions ******************************************************************************/ -static struct nouveau_bitfield nv84_crypt_intr_mask[] = { +static const struct nouveau_bitfield nv84_crypt_intr_mask[] = { { 0x00000001, "INVALID_STATE" }, { 0x00000002, "ILLEGAL_MTHD" }, { 0x00000004, "ILLEGAL_CLASS" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index 835b8eb..9e3876c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -92,7 +92,7 @@ nv98_crypt_cclass = { * PCRYPT engine/subdev functions ******************************************************************************/ -static struct nouveau_enum nv98_crypt_isr_error_name[] = { +static const struct nouveau_enum nv98_crypt_isr_error_name[] = { { 0x0000, "ILLEGAL_MTHD" }, { 0x0001, "INVALID_BITFIELD" }, { 0x0002, "INVALID_ENUM" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index dda0a44..2dd6812 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -324,7 +324,7 @@ nvc0_fifo_cclass = { * PFIFO engine ******************************************************************************/ -struct nouveau_enum nvc0_fifo_fault_unit[] = { +static const struct nouveau_enum nvc0_fifo_fault_unit[] = { { 0x00, "PGRAPH" }, { 0x03, "PEEPHOLE" }, { 0x04, "BAR1" }, @@ -340,7 +340,7 @@ struct nouveau_enum nvc0_fifo_fault_unit[] = { {} }; -struct nouveau_enum nvc0_fifo_fault_reason[] = { +static const struct nouveau_enum nvc0_fifo_fault_reason[] = { { 0x00, "PT_NOT_PRESENT" }, { 0x01, "PT_TOO_SHORT" }, { 0x02, "PAGE_NOT_PRESENT" }, @@ -353,7 +353,7 @@ struct nouveau_enum nvc0_fifo_fault_reason[] = { {} }; -struct nouveau_enum nvc0_fifo_fault_hubclient[] = { +static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = { { 0x01, "PCOPY0" }, { 0x02, "PCOPY1" }, { 0x04, "DISPATCH" }, @@ -371,7 +371,7 @@ struct nouveau_enum nvc0_fifo_fault_hubclient[] = { {} }; -struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { +static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { { 0x01, "TEX" }, { 0x0c, "ESETUP" }, { 0x0e, "CTXCTL" }, @@ -379,7 +379,7 @@ struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { {} }; -struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { +static const struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { /* { 0x00008000, "" } seen with null ib push */ { 0x00200000, "ILLEGAL_MTHD" }, { 0x00800000, "EMPTY_SUBC" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index f480323..36e81b6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -368,11 +368,11 @@ nve0_fifo_cclass = { * PFIFO engine ******************************************************************************/ -struct nouveau_enum nve0_fifo_fault_unit[] = { +static const struct nouveau_enum nve0_fifo_fault_unit[] = { {} }; -struct nouveau_enum nve0_fifo_fault_reason[] = { +static const struct nouveau_enum nve0_fifo_fault_reason[] = { { 0x00, "PT_NOT_PRESENT" }, { 0x01, "PT_TOO_SHORT" }, { 0x02, "PAGE_NOT_PRESENT" }, @@ -385,15 +385,15 @@ struct nouveau_enum nve0_fifo_fault_reason[] = { {} }; -struct nouveau_enum nve0_fifo_fault_hubclient[] = { +static const struct nouveau_enum nve0_fifo_fault_hubclient[] = { {} }; -struct nouveau_enum nve0_fifo_fault_gpcclient[] = { +static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = { {} }; -struct nouveau_bitfield nve0_fifo_subfifo_intr[] = { +static const struct nouveau_bitfield nve0_fifo_subfifo_intr[] = { { 0x00200000, "ILLEGAL_MTHD" }, { 0x00800000, "EMPTY_SUBC" }, {} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c index e5b0189..6185282 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c @@ -1213,13 +1213,13 @@ nv04_graph_idle(void *obj) return true; } -static struct nouveau_bitfield +static const struct nouveau_bitfield nv04_graph_intr_name[] = { { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, {} }; -static struct nouveau_bitfield +static const struct nouveau_bitfield nv04_graph_nstatus[] = { { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, @@ -1228,7 +1228,7 @@ nv04_graph_nstatus[] = { {} }; -struct nouveau_bitfield +const struct nouveau_bitfield nv04_graph_nsource[] = { { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index ce38196..92521c8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -1135,13 +1135,13 @@ nv10_graph_tile_prog(struct nouveau_engine *engine, int i) pfifo->start(pfifo, &flags); } -struct nouveau_bitfield nv10_graph_intr_name[] = { +const struct nouveau_bitfield nv10_graph_intr_name[] = { { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, { NV_PGRAPH_INTR_ERROR, "ERROR" }, {} }; -struct nouveau_bitfield nv10_graph_nstatus[] = { +const struct nouveau_bitfield nv10_graph_nstatus[] = { { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index c93b525..7d30d02 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -232,7 +232,7 @@ nv84_graph_tlb_flush(struct nouveau_engine *engine) return timeout ? -EBUSY : 0; } -static struct nouveau_enum nv50_mp_exec_error_names[] = { +static const struct nouveau_enum nv50_mp_exec_error_names[] = { { 3, "STACK_UNDERFLOW", NULL }, { 4, "QUADON_ACTIVE", NULL }, { 8, "TIMEOUT", NULL }, @@ -241,30 +241,30 @@ static struct nouveau_enum nv50_mp_exec_error_names[] = { {} }; -static struct nouveau_bitfield nv50_graph_trap_m2mf[] = { +static const struct nouveau_bitfield nv50_graph_trap_m2mf[] = { { 0x00000001, "NOTIFY" }, { 0x00000002, "IN" }, { 0x00000004, "OUT" }, {} }; -static struct nouveau_bitfield nv50_graph_trap_vfetch[] = { +static const struct nouveau_bitfield nv50_graph_trap_vfetch[] = { { 0x00000001, "FAULT" }, {} }; -static struct nouveau_bitfield nv50_graph_trap_strmout[] = { +static const struct nouveau_bitfield nv50_graph_trap_strmout[] = { { 0x00000001, "FAULT" }, {} }; -static struct nouveau_bitfield nv50_graph_trap_ccache[] = { +static const struct nouveau_bitfield nv50_graph_trap_ccache[] = { { 0x00000001, "FAULT" }, {} }; /* There must be a *lot* of these. Will take some time to gather them up. */ -struct nouveau_enum nv50_data_error_names[] = { +const struct nouveau_enum nv50_data_error_names[] = { { 0x00000003, "INVALID_OPERATION", NULL }, { 0x00000004, "INVALID_VALUE", NULL }, { 0x00000005, "INVALID_ENUM", NULL }, @@ -310,7 +310,7 @@ struct nouveau_enum nv50_data_error_names[] = { {} }; -static struct nouveau_bitfield nv50_graph_intr_name[] = { +static const struct nouveau_bitfield nv50_graph_intr_name[] = { { 0x00000001, "NOTIFY" }, { 0x00000002, "COMPUTE_QUERY" }, { 0x00000010, "ILLEGAL_MTHD" }, diff --git a/drivers/gpu/drm/nouveau/core/include/core/enum.h b/drivers/gpu/drm/nouveau/core/include/core/enum.h index 62ec041..e7b1e18 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/enum.h +++ b/drivers/gpu/drm/nouveau/core/include/core/enum.h @@ -4,7 +4,7 @@ struct nouveau_enum { u32 value; const char *name; - void *data; + const void *data; }; const struct nouveau_enum * diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h index 388cfcf..6943b40 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h @@ -60,13 +60,13 @@ extern struct nouveau_oclass nv50_graph_oclass; extern struct nouveau_oclass nvc0_graph_oclass; extern struct nouveau_oclass nve0_graph_oclass; -extern struct nouveau_bitfield nv04_graph_nsource[]; +extern const struct nouveau_bitfield nv04_graph_nsource[]; extern struct nouveau_ofuncs nv04_graph_ofuncs; bool nv04_graph_idle(void *obj); -extern struct nouveau_bitfield nv10_graph_intr_name[]; -extern struct nouveau_bitfield nv10_graph_nstatus[]; +extern const struct nouveau_bitfield nv10_graph_intr_name[]; +extern const struct nouveau_bitfield nv10_graph_nstatus[]; -extern struct nouveau_enum nv50_data_error_names[]; +extern const struct nouveau_enum nv50_data_error_names[]; #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index eaf18fb..436e9ef 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -331,7 +331,7 @@ nv50_fb_oclass = { }, }; -static struct nouveau_enum vm_dispatch_subclients[] = { +static const struct nouveau_enum vm_dispatch_subclients[] = { { 0x00000000, "GRCTX", NULL }, { 0x00000001, "NOTIFY", NULL }, { 0x00000002, "QUERY", NULL }, @@ -342,14 +342,14 @@ static struct nouveau_enum vm_dispatch_subclients[] = { {} }; -static struct nouveau_enum vm_ccache_subclients[] = { +static const struct nouveau_enum vm_ccache_subclients[] = { { 0x00000000, "CB", NULL }, { 0x00000001, "TIC", NULL }, { 0x00000002, "TSC", NULL }, {} }; -static struct nouveau_enum vm_prop_subclients[] = { +static const struct nouveau_enum vm_prop_subclients[] = { { 0x00000000, "RT0", NULL }, { 0x00000001, "RT1", NULL }, { 0x00000002, "RT2", NULL }, @@ -366,19 +366,19 @@ static struct nouveau_enum vm_prop_subclients[] = { {} }; -static struct nouveau_enum vm_pfifo_subclients[] = { +static const struct nouveau_enum vm_pfifo_subclients[] = { { 0x00000000, "PUSHBUF", NULL }, { 0x00000001, "SEMAPHORE", NULL }, {} }; -static struct nouveau_enum vm_bar_subclients[] = { +static const struct nouveau_enum vm_bar_subclients[] = { { 0x00000000, "FB", NULL }, { 0x00000001, "IN", NULL }, {} }; -static struct nouveau_enum vm_client[] = { +static const struct nouveau_enum vm_client[] = { { 0x00000000, "STRMOUT", NULL }, { 0x00000003, "DISPATCH", vm_dispatch_subclients }, { 0x00000004, "PFIFO_WRITE", NULL }, @@ -397,7 +397,7 @@ static struct nouveau_enum vm_client[] = { {} }; -static struct nouveau_enum vm_engine[] = { +static const struct nouveau_enum vm_engine[] = { { 0x00000000, "PGRAPH", NULL }, { 0x00000001, "PVP", NULL }, { 0x00000004, "PEEPHOLE", NULL }, @@ -413,7 +413,7 @@ static struct nouveau_enum vm_engine[] = { {} }; -static struct nouveau_enum vm_fault[] = { +static const struct nouveau_enum vm_fault[] = { { 0x00000000, "PT_NOT_PRESENT", NULL }, { 0x00000001, "PT_TOO_SHORT", NULL }, { 0x00000002, "PAGE_NOT_PRESENT", NULL }, -- cgit v1.1 From 5b8a43aeb9cbf6b965f67f6c850382788076325a Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 19 Aug 2012 23:00:00 +0200 Subject: drm/nouveau: quiet some static-related sparse noise Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/gpuobj.c | 2 +- drivers/gpu/drm/nouveau/core/core/object.c | 8 ++++---- drivers/gpu/drm/nouveau/core/core/option.c | 2 +- drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/disp/vga.c | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h | 4 ++-- drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 2 +- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 2 +- drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | 4 ++-- drivers/gpu/drm/nouveau/core/subdev/bios/conn.c | 1 + drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 10 +++++----- drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 10 +++++----- 18 files changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/gpuobj.c b/drivers/gpu/drm/nouveau/core/core/gpuobj.c index 715fd31..1f34549 100644 --- a/drivers/gpu/drm/nouveau/core/core/gpuobj.c +++ b/drivers/gpu/drm/nouveau/core/core/gpuobj.c @@ -139,7 +139,7 @@ struct nouveau_gpuobj_class { u32 flags; }; -int +static int _nouveau_gpuobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c index f37598e..0daab62 100644 --- a/drivers/gpu/drm/nouveau/core/core/object.c +++ b/drivers/gpu/drm/nouveau/core/core/object.c @@ -61,7 +61,7 @@ nouveau_object_create_(struct nouveau_object *parent, return 0; } -int +static int _nouveau_object_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -91,7 +91,7 @@ nouveau_object_destroy(struct nouveau_object *object) kfree(object); } -void +static void _nouveau_object_dtor(struct nouveau_object *object) { nouveau_object_destroy(object); @@ -103,7 +103,7 @@ nouveau_object_init(struct nouveau_object *object) return 0; } -int +static int _nouveau_object_init(struct nouveau_object *object) { return nouveau_object_init(object); @@ -115,7 +115,7 @@ nouveau_object_fini(struct nouveau_object *object, bool suspend) return 0; } -int +static int _nouveau_object_fini(struct nouveau_object *object, bool suspend) { return nouveau_object_fini(object, suspend); diff --git a/drivers/gpu/drm/nouveau/core/core/option.c b/drivers/gpu/drm/nouveau/core/core/option.c index 1b53ebb..62a432e 100644 --- a/drivers/gpu/drm/nouveau/core/core/option.c +++ b/drivers/gpu/drm/nouveau/core/core/option.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ -#include +#include #include /* compares unterminated string 'str' with zero-terminated string 'cmp' */ diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h index 37d6de3..c92520f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h @@ -1,4 +1,4 @@ -u32 nva3_pcopy_data[] = { +static u32 nva3_pcopy_data[] = { /* 0x0000: ctx_object */ 0x00000000, /* 0x0004: ctx_dma */ @@ -183,7 +183,7 @@ u32 nva3_pcopy_data[] = { 0x00000800, }; -u32 nva3_pcopy_code[] = { +static u32 nva3_pcopy_code[] = { /* 0x0000: main */ 0x04fe04bd, 0x3517f000, diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h index cd879f3..0d98c6c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h @@ -1,4 +1,4 @@ -u32 nvc0_pcopy_data[] = { +static u32 nvc0_pcopy_data[] = { /* 0x0000: ctx_object */ 0x00000000, /* 0x0004: ctx_query_address_high */ @@ -171,7 +171,7 @@ u32 nvc0_pcopy_data[] = { 0x00000800, }; -u32 nvc0_pcopy_code[] = { +static u32 nvc0_pcopy_code[] = { /* 0x0000: main */ 0x04fe04bd, 0x3517f000, diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h index 38676c7..09962e4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h @@ -1,4 +1,4 @@ -uint32_t nv98_pcrypt_data[] = { +static uint32_t nv98_pcrypt_data[] = { /* 0x0000: ctx_dma */ /* 0x0000: ctx_dma_query */ 0x00000000, @@ -150,7 +150,7 @@ uint32_t nv98_pcrypt_data[] = { 0x00000000, }; -uint32_t nv98_pcrypt_code[] = { +static uint32_t nv98_pcrypt_code[] = { 0x17f004bd, 0x0010fe35, 0xf10004fe, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c index cec2110..5a1c684 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c @@ -24,6 +24,7 @@ #include #include +#include u8 nv_rdport(void *obj, int head, u16 port) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index 2a7c13d..bbb43c6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -132,7 +132,7 @@ _nouveau_fifo_channel_wr32(struct nouveau_object *object, u32 addr, u32 data) iowrite32_native(data, chan->user + addr); } -int +static int nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object) { int engidx = nv_hclass(priv) & 0xff; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 55620fb..b4fd26d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -319,7 +319,7 @@ nv84_fifo_sclass[] = { * FIFO context - basically just the instmem reserved for the channel ******************************************************************************/ -int +static int nv84_fifo_context_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h index a988b8a..826a7b3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h @@ -1,4 +1,4 @@ -uint32_t nvc0_grgpc_data[] = { +static uint32_t nvc0_grgpc_data[] = { 0x00000000, 0x00000000, 0x00000000, @@ -150,7 +150,7 @@ uint32_t nvc0_grgpc_data[] = { 0x08000750, }; -uint32_t nvc0_grgpc_code[] = { +static uint32_t nvc0_grgpc_code[] = { 0x03060ef5, 0x9800d898, 0x86f001d9, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index c5ed307..db0c0ee 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h @@ -1,4 +1,4 @@ -uint32_t nvc0_grhub_data[] = { +static uint32_t nvc0_grhub_data[] = { 0x00000000, 0x00000000, 0x00000000, @@ -194,7 +194,7 @@ uint32_t nvc0_grhub_data[] = { 0x00000000, }; -uint32_t nvc0_grhub_code[] = { +static uint32_t nvc0_grhub_code[] = { 0x03090ef5, 0x9800d898, 0x86f001d9, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 5690fe3..8d00210 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -75,7 +75,7 @@ nv40_graph_object_ctor(struct nouveau_object *parent, return 0; } -struct nouveau_ofuncs +static struct nouveau_ofuncs nv40_graph_ofuncs = { .ctor = nv40_graph_object_ctor, .dtor = _nouveau_gpuobj_dtor, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 7d30d02..ab3b9dc 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -73,7 +73,7 @@ nv50_graph_object_ctor(struct nouveau_object *parent, return 0; } -struct nouveau_ofuncs +static struct nouveau_ofuncs nv50_graph_ofuncs = { .ctor = nv50_graph_object_ctor, .dtor = _nouveau_gpuobj_dtor, diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 9adcefc..1f394a2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -109,7 +109,7 @@ nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len) return 0; } -struct nouveau_ofuncs +static struct nouveau_ofuncs nv31_mpeg_ofuncs = { .ctor = nv31_mpeg_object_ctor, .dtor = _nouveau_gpuobj_dtor, @@ -119,7 +119,7 @@ nv31_mpeg_ofuncs = { .wr32 = _nouveau_gpuobj_wr32, }; -struct nouveau_omthds +static struct nouveau_omthds nv31_mpeg_omthds[] = { { 0x0190, nv31_mpeg_mthd_dma }, { 0x01a0, nv31_mpeg_mthd_dma }, diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c index ac4026c..5ac010e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c @@ -26,6 +26,7 @@ #include #include +#include u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 684f396..93e3ddf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -210,7 +210,7 @@ mxm_shadow_wmi(struct nouveau_mxm *mxm, u8 version) } #endif -struct mxm_shadow_h { +static struct mxm_shadow_h { const char *name; bool (*exec)(struct nouveau_mxm *, u8 version); } _mxm_shadow[] = { diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 0f0d3a5..d83489c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -34,7 +34,7 @@ struct nv50_vmmgr_priv { spinlock_t lock; }; -void +static void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]) { @@ -76,7 +76,7 @@ vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) return phys; } -void +static void nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { @@ -123,7 +123,7 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { @@ -137,7 +137,7 @@ nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) { pte <<= 3; @@ -148,7 +148,7 @@ nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } } -void +static void nv50_vm_flush(struct nouveau_vm *vm) { struct nouveau_engine *engine; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index e48ece2..44721a4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -34,7 +34,7 @@ struct nvc0_vmmgr_priv { spinlock_t lock; }; -void +static void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, struct nouveau_gpuobj *pgt[2]) { @@ -64,7 +64,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) return phys; } -void +static void nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { @@ -80,7 +80,7 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { @@ -95,7 +95,7 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, } } -void +static void nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) { pte <<= 3; @@ -132,7 +132,7 @@ nvc0_vm_flush_engine(struct nouveau_subdev *subdev, u64 addr, int type) spin_unlock_irqrestore(&priv->lock, flags); } -void +static void nvc0_vm_flush(struct nouveau_vm *vm) { struct nouveau_vm_pgd *vpgd; -- cgit v1.1 From 757833cc9f0c334ecf739836f4e052c11bf81264 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Aug 2012 01:14:21 -0400 Subject: drm/nouveau/sw: trap and clear PMC_INTR_0_SOFTWARE Came in useful for debugging another issue earlier, so keep it around. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/software/nv04.c | 7 +++++++ drivers/gpu/drm/nouveau/core/engine/software/nv10.c | 1 + drivers/gpu/drm/nouveau/core/engine/software/nv50.c | 1 + drivers/gpu/drm/nouveau/core/engine/software/nvc0.c | 1 + drivers/gpu/drm/nouveau/core/include/engine/software.h | 2 ++ 5 files changed, 12 insertions(+) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c index f48da75..3ca4c3a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c @@ -110,6 +110,12 @@ nv04_software_cclass = { * software engine/subdev functions ******************************************************************************/ +void +nv04_software_intr(struct nouveau_subdev *subdev) +{ + nv_mask(subdev, 0x000100, 0x80000000, 0x00000000); +} + static int nv04_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -125,6 +131,7 @@ nv04_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nv04_software_cclass; nv_engine(priv)->sclass = nv04_software_sclass; + nv_subdev(priv)->intr = nv04_software_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c index 46dada5..6e699af 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c @@ -113,6 +113,7 @@ nv10_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nv10_software_cclass; nv_engine(priv)->sclass = nv10_software_sclass; + nv_subdev(priv)->intr = nv04_software_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c index 6b88971..a2edcd3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -183,6 +183,7 @@ nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nv50_software_cclass; nv_engine(priv)->sclass = nv50_software_sclass; + nv_subdev(priv)->intr = nv04_software_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c index e3be78f..b7b0d7e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -165,6 +165,7 @@ nvc0_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nvc0_software_cclass; nv_engine(priv)->sclass = nvc0_software_sclass; + nv_subdev(priv)->intr = nv04_software_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/include/engine/software.h b/drivers/gpu/drm/nouveau/core/include/engine/software.h index 8d74079..c945691 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/software.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/software.h @@ -55,4 +55,6 @@ extern struct nouveau_oclass nv10_software_oclass; extern struct nouveau_oclass nv50_software_oclass; extern struct nouveau_oclass nvc0_software_oclass; +void nv04_software_intr(struct nouveau_subdev *); + #endif -- cgit v1.1 From 2c1a425e7d537ea655fa276f267c0b1cd100ff34 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 22 Aug 2012 23:55:42 -0400 Subject: drm/nve0/ibus: handle PIBUS interrupts to prevent storm Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/core/device.h | 1 + drivers/gpu/drm/nouveau/core/include/subdev/ibus.h | 33 ++++++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c | 123 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | 1 + 5 files changed, 161 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/ibus.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 1305593..c32f96a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -17,6 +17,7 @@ enum nv_subdev_type { NVDEV_SUBDEV_TIMER, NVDEV_SUBDEV_FB, NVDEV_SUBDEV_LTCG, + NVDEV_SUBDEV_IBUS, NVDEV_SUBDEV_INSTMEM, NVDEV_SUBDEV_VM, NVDEV_SUBDEV_BAR, diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h new file mode 100644 index 0000000..f014594 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h @@ -0,0 +1,33 @@ +#ifndef __NOUVEAU_IBUS_H__ +#define __NOUVEAU_IBUS_H__ + +#include +#include + +struct nouveau_ibus { + struct nouveau_subdev base; +}; + +static inline struct nouveau_ibus * +nouveau_ibus(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_IBUS]; +} + +#define nouveau_ibus_create(p,e,o,d) \ + nouveau_subdev_create_((p), (e), (o), 0, "PIBUS", "ibus", \ + sizeof(**d), (void **)d) +#define nouveau_ibus_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) +#define nouveau_ibus_init(p) \ + nouveau_subdev_init(&(p)->base) +#define nouveau_ibus_fini(p,s) \ + nouveau_subdev_fini(&(p)->base, (s)) + +#define _nouveau_ibus_dtor _nouveau_subdev_dtor +#define _nouveau_ibus_init _nouveau_subdev_init +#define _nouveau_ibus_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nve0_ibus_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index efb8ddc..0d9d86b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -83,6 +85,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c new file mode 100644 index 0000000..7120124 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c @@ -0,0 +1,123 @@ +/* + * 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: + * + * 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 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 + +struct nve0_ibus_priv { + struct nouveau_ibus base; +}; + +static void +nve0_ibus_intr_hub(struct nve0_ibus_priv *priv, int i) +{ + u32 addr = nv_rd32(priv, 0x122120 + (i * 0x0800)); + u32 data = nv_rd32(priv, 0x122124 + (i * 0x0800)); + u32 stat = nv_rd32(priv, 0x122128 + (i * 0x0800)); + nv_error(priv, "HUB%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); + nv_mask(priv, 0x122128 + (i * 0x0800), 0x00000200, 0x00000000); +} + +static void +nve0_ibus_intr_rop(struct nve0_ibus_priv *priv, int i) +{ + u32 addr = nv_rd32(priv, 0x124120 + (i * 0x0800)); + u32 data = nv_rd32(priv, 0x124124 + (i * 0x0800)); + u32 stat = nv_rd32(priv, 0x124128 + (i * 0x0800)); + nv_error(priv, "ROP%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); + nv_mask(priv, 0x124128 + (i * 0x0800), 0x00000200, 0x00000000); +} + +static void +nve0_ibus_intr_gpc(struct nve0_ibus_priv *priv, int i) +{ + u32 addr = nv_rd32(priv, 0x128120 + (i * 0x0800)); + u32 data = nv_rd32(priv, 0x128124 + (i * 0x0800)); + u32 stat = nv_rd32(priv, 0x128128 + (i * 0x0800)); + nv_error(priv, "GPC%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); + nv_mask(priv, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000); +} + +static void +nve0_ibus_intr(struct nouveau_subdev *subdev) +{ + struct nve0_ibus_priv *priv = (void *)subdev; + u32 intr0 = nv_rd32(priv, 0x120058); + u32 intr1 = nv_rd32(priv, 0x12005c); + u32 hubnr = nv_rd32(priv, 0x120070); + u32 ropnr = nv_rd32(priv, 0x120074); + u32 gpcnr = nv_rd32(priv, 0x120078); + u32 i; + + for (i = 0; (intr0 & 0x0000ff00) && i < hubnr; i++) { + u32 stat = 0x00000100 << i; + if (intr0 & stat) { + nve0_ibus_intr_hub(priv, i); + intr0 &= ~stat; + } + } + + for (i = 0; (intr0 & 0xffff0000) && i < ropnr; i++) { + u32 stat = 0x00010000 << i; + if (intr0 & stat) { + nve0_ibus_intr_rop(priv, i); + intr0 &= ~stat; + } + } + + for (i = 0; intr1 && i < gpcnr; i++) { + u32 stat = 0x00000001 << i; + if (intr1 & stat) { + nve0_ibus_intr_gpc(priv, i); + intr1 &= ~stat; + } + } +} + +static int +nve0_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nve0_ibus_priv *priv; + int ret; + + ret = nouveau_ibus_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nve0_ibus_intr; + return 0; +} + +struct nouveau_oclass +nve0_ibus_oclass = { + .handle = NV_SUBDEV(IBUS, 0xe0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_ibus_ctor, + .dtor = _nouveau_ibus_dtor, + .init = _nouveau_ibus_init, + .fini = _nouveau_ibus_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index bd9e9946..c2b81e3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -40,6 +40,7 @@ nvc0_mc_intr[] = { { 0x00200000, NVDEV_SUBDEV_GPIO }, { 0x02000000, NVDEV_SUBDEV_LTCG }, { 0x04000000, NVDEV_ENGINE_DISP }, + { 0x40000000, NVDEV_SUBDEV_IBUS }, { 0x80000000, NVDEV_ENGINE_SW }, {}, }; -- cgit v1.1 From 1978a2f280563427bb675b3197391745aef73424 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 22 Aug 2012 20:47:40 -0400 Subject: drm/nve0/gr: initial fuc implementation, based on fermi's code Currently identical except the available chipset register lists. This will *not* currently work and is disabled by default because of this. May get merged again later, remains to be seen what further changes will be required. Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc | 451 ++++++++++ .../nouveau/core/engine/graph/fuc/gpcnve0.fuc.h | 530 ++++++++++++ .../drm/nouveau/core/engine/graph/fuc/hubnve0.fuc | 806 ++++++++++++++++++ .../nouveau/core/engine/graph/fuc/hubnve0.fuc.h | 924 +++++++++++++++++++++ .../gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc | 400 +++++++++ drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 193 +++-- 6 files changed, 3235 insertions(+), 69 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h create mode 100644 drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc new file mode 100644 index 0000000..7b715fd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc @@ -0,0 +1,451 @@ +/* fuc microcode for nve0 PGRAPH/GPC + * + * Copyright 2011 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: + * + * 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 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 + */ + +/* To build: + * m4 nve0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nve0_grgpc.fuc.h + */ + +/* TODO + * - bracket certain functions with scratch writes, useful for debugging + * - watchdog timer around ctx operations + */ + +.section #nve0_grgpc_data +include(`nve0.fuc') +gpc_id: .b32 0 +gpc_mmio_list_head: .b32 0 +gpc_mmio_list_tail: .b32 0 + +tpc_count: .b32 0 +tpc_mask: .b32 0 +tpc_mmio_list_head: .b32 0 +tpc_mmio_list_tail: .b32 0 + +cmd_queue: queue_init + +// chipset descriptions +chipsets: +.b8 0xe4 0 0 0 +.b16 #nve4_gpc_mmio_head +.b16 #nve4_gpc_mmio_tail +.b16 #nve4_tpc_mmio_head +.b16 #nve4_tpc_mmio_tail +.b8 0xe7 0 0 0 +.b16 #nve4_gpc_mmio_head +.b16 #nve4_gpc_mmio_tail +.b16 #nve4_tpc_mmio_head +.b16 #nve4_tpc_mmio_tail +.b8 0 0 0 0 + +// GPC mmio lists +nve4_gpc_mmio_head: +mmctx_data(0x000380, 1) +mmctx_data(0x000400, 2) +mmctx_data(0x00040c, 3) +mmctx_data(0x000450, 9) +mmctx_data(0x000600, 1) +mmctx_data(0x000684, 1) +mmctx_data(0x000700, 5) +mmctx_data(0x000800, 1) +mmctx_data(0x000808, 3) +mmctx_data(0x000828, 1) +mmctx_data(0x000830, 1) +mmctx_data(0x0008d8, 1) +mmctx_data(0x0008e0, 1) +mmctx_data(0x0008e8, 6) +mmctx_data(0x00091c, 1) +mmctx_data(0x000924, 3) +mmctx_data(0x000b00, 1) +mmctx_data(0x000b08, 6) +mmctx_data(0x000bb8, 1) +mmctx_data(0x000c08, 1) +mmctx_data(0x000c10, 8) +mmctx_data(0x000c40, 1) +mmctx_data(0x000c6c, 1) +mmctx_data(0x000c80, 1) +mmctx_data(0x000c8c, 1) +mmctx_data(0x001000, 3) +mmctx_data(0x001014, 1) +mmctx_data(0x003024, 1) +mmctx_data(0x0030c0, 2) +mmctx_data(0x0030e4, 1) +mmctx_data(0x003100, 6) +mmctx_data(0x0031d0, 1) +mmctx_data(0x0031e0, 2) +nve4_gpc_mmio_tail: + +// TPC mmio lists +nve4_tpc_mmio_head: +mmctx_data(0x000048, 1) +mmctx_data(0x000064, 1) +mmctx_data(0x000088, 1) +mmctx_data(0x000200, 6) +mmctx_data(0x00021c, 2) +mmctx_data(0x000230, 1) +mmctx_data(0x0002c4, 1) +mmctx_data(0x000400, 3) +mmctx_data(0x000420, 3) +mmctx_data(0x0004e8, 1) +mmctx_data(0x0004f4, 1) +mmctx_data(0x000604, 4) +mmctx_data(0x000644, 22) +mmctx_data(0x0006ac, 2) +mmctx_data(0x0006c8, 1) +mmctx_data(0x000730, 8) +mmctx_data(0x000758, 1) +mmctx_data(0x000778, 1) +nve4_tpc_mmio_tail: + +.section #nve0_grgpc_code +bra #init +define(`include_code') +include(`nve0.fuc') + +// reports an exception to the host +// +// In: $r15 error code (see nve0.fuc) +// +error: + push $r14 + mov $r14 -0x67ec // 0x9814 + sethi $r14 0x400000 + call #nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code + add b32 $r14 0x41c + mov $r15 1 + call #nv_wr32 // HUB_CTXCTL_INTR_UP_SET + pop $r14 + ret + +// GPC fuc initialisation, executed by triggering ucode start, will +// fall through to main loop after completion. +// +// Input: +// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) +// CC_SCRATCH[1]: context base +// +// Output: +// CC_SCRATCH[0]: +// 31:31: set to signal completion +// CC_SCRATCH[1]: +// 31:0: GPC context size +// +init: + clear b32 $r0 + mov $sp $r0 + + // enable fifo access + mov $r1 0x1200 + mov $r2 2 + iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE + + // setup i0 handler, and route all interrupts to it + mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH + + // enable fifo interrupt + mov $r2 4 + iowr I[$r1 + 0x000] $r2 // INTR_EN_SET + + // enable interrupts + bset $flags ie0 + + // figure out which GPC we are, and how many TPCs we have + mov $r1 0x608 + shl b32 $r1 6 + iord $r2 I[$r1 + 0x000] // UNITS + mov $r3 1 + and $r2 0x1f + shl b32 $r3 $r2 + sub b32 $r3 1 + st b32 D[$r0 + #tpc_count] $r2 + st b32 D[$r0 + #tpc_mask] $r3 + add b32 $r1 0x400 + iord $r2 I[$r1 + 0x000] // MYINDEX + st b32 D[$r0 + #gpc_id] $r2 + + // find context data for this chipset + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] + mov $r1 #chipsets - 12 + init_find_chipset: + add b32 $r1 12 + ld b32 $r3 D[$r1 + 0x00] + cmpu b32 $r3 $r2 + bra e #init_context + cmpu b32 $r3 0 + bra ne #init_find_chipset + // unknown chipset + ret + + // initialise context base, and size tracking + init_context: + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base + clear b32 $r3 // track GPC context size here + + // set mmctx base addresses now so we don't have to do it later, + // they don't currently ever change + mov $r4 0x700 + shl b32 $r4 6 + shr b32 $r5 $r2 8 + iowr I[$r4 + 0x000] $r5 // MMCTX_SAVE_SWBASE + iowr I[$r4 + 0x100] $r5 // MMCTX_LOAD_SWBASE + + // calculate GPC mmio context size, store the chipset-specific + // mmio list pointers somewhere we can get at them later without + // re-parsing the chipset list + clear b32 $r14 + clear b32 $r15 + ld b16 $r14 D[$r1 + 4] + ld b16 $r15 D[$r1 + 6] + st b16 D[$r0 + #gpc_mmio_list_head] $r14 + st b16 D[$r0 + #gpc_mmio_list_tail] $r15 + call #mmctx_size + add b32 $r2 $r15 + add b32 $r3 $r15 + + // calculate per-TPC mmio context size, store the list pointers + ld b16 $r14 D[$r1 + 8] + ld b16 $r15 D[$r1 + 10] + st b16 D[$r0 + #tpc_mmio_list_head] $r14 + st b16 D[$r0 + #tpc_mmio_list_tail] $r15 + call #mmctx_size + ld b32 $r14 D[$r0 + #tpc_count] + mulu $r14 $r15 + add b32 $r2 $r14 + add b32 $r3 $r14 + + // round up base/size to 256 byte boundary (for strand SWBASE) + add b32 $r4 0x1300 + shr b32 $r3 2 + iowr I[$r4 + 0x000] $r3 // MMCTX_LOAD_COUNT, wtf for?!? + shr b32 $r2 8 + shr b32 $r3 6 + add b32 $r2 1 + add b32 $r3 1 + shl b32 $r2 8 + shl b32 $r3 8 + + // calculate size of strand context data + mov b32 $r15 $r2 + call #strand_ctx_init + add b32 $r3 $r15 + + // save context size, and tell HUB we're done + mov $r1 0x800 + shl b32 $r1 6 + iowr I[$r1 + 0x100] $r3 // CC_SCRATCH[1] = context size + add b32 $r1 0x800 + clear b32 $r2 + bset $r2 31 + iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 + +// Main program loop, very simple, sleeps until woken up by the interrupt +// handler, pulls a command from the queue and executes its handler +// +main: + bset $flags $p0 + sleep $p0 + mov $r13 #cmd_queue + call #queue_get + bra $p1 #main + + // 0x0000-0x0003 are all context transfers + cmpu b32 $r14 0x04 + bra nc #main_not_ctx_xfer + // fetch $flags and mask off $p1/$p2 + mov $r1 $flags + mov $r2 0x0006 + not b32 $r2 + and $r1 $r2 + // set $p1/$p2 according to transfer type + shl b32 $r14 1 + or $r1 $r14 + mov $flags $r1 + // transfer context data + call #ctx_xfer + bra #main + + main_not_ctx_xfer: + shl b32 $r15 $r14 16 + or $r15 E_BAD_COMMAND + call #error + bra #main + +// interrupt handler +ih: + push $r8 + mov $r8 $flags + push $r8 + push $r9 + push $r10 + push $r11 + push $r13 + push $r14 + push $r15 + + // incoming fifo command? + iord $r10 I[$r0 + 0x200] // INTR + and $r11 $r10 0x00000004 + bra e #ih_no_fifo + // queue incoming fifo command for later processing + mov $r11 0x1900 + mov $r13 #cmd_queue + iord $r14 I[$r11 + 0x100] // FIFO_CMD + iord $r15 I[$r11 + 0x000] // FIFO_DATA + call #queue_put + add b32 $r11 0x400 + mov $r14 1 + iowr I[$r11 + 0x000] $r14 // FIFO_ACK + + // ack, and wake up main() + ih_no_fifo: + iowr I[$r0 + 0x100] $r10 // INTR_ACK + + pop $r15 + pop $r14 + pop $r13 + pop $r11 + pop $r10 + pop $r9 + pop $r8 + mov $flags $r8 + pop $r8 + bclr $flags $p0 + iret + +// Set this GPC's bit in HUB_BAR, used to signal completion of various +// activities to the HUB fuc +// +hub_barrier_done: + mov $r15 1 + ld b32 $r14 D[$r0 + #gpc_id] + shl b32 $r15 $r14 + mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET + sethi $r14 0x400000 + call #nv_wr32 + ret + +// Disables various things, waits a bit, and re-enables them.. +// +// Not sure how exactly this helps, perhaps "ENABLE" is not such a +// good description for the bits we turn off? Anyways, without this, +// funny things happen. +// +ctx_redswitch: + mov $r14 0x614 + shl b32 $r14 6 + mov $r15 0x020 + iowr I[$r14] $r15 // GPC_RED_SWITCH = POWER + mov $r15 8 + ctx_redswitch_delay: + sub b32 $r15 1 + bra ne #ctx_redswitch_delay + mov $r15 0xa20 + iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER + ret + +// Transfer GPC context data between GPU and storage area +// +// In: $r15 context base address +// $p1 clear on save, set on load +// $p2 set if opposite direction done/will be done, so: +// on save it means: "a load will follow this save" +// on load it means: "a save preceeded this load" +// +ctx_xfer: + // set context base address + mov $r1 0xa04 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r15// MEM_BASE + bra not $p1 #ctx_xfer_not_load + call #ctx_redswitch + ctx_xfer_not_load: + + // strands + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xc + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c + call #strand_wait + mov $r2 0x47fc + sethi $r2 0x20000 + iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 + xbit $r2 $flags $p1 + add b32 $r2 3 + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) + + // mmio context + xbit $r10 $flags $p1 // direction + or $r10 2 // first + mov $r11 0x0000 + sethi $r11 0x500000 + ld b32 $r12 D[$r0 + #gpc_id] + shl b32 $r12 15 + add b32 $r11 $r12 // base = NV_PGRAPH_GPCn + ld b32 $r12 D[$r0 + #gpc_mmio_list_head] + ld b32 $r13 D[$r0 + #gpc_mmio_list_tail] + mov $r14 0 // not multi + call #mmctx_xfer + + // per-TPC mmio context + xbit $r10 $flags $p1 // direction + or $r10 4 // last + mov $r11 0x4000 + sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0 + ld b32 $r12 D[$r0 + #gpc_id] + shl b32 $r12 15 + add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0 + ld b32 $r12 D[$r0 + #tpc_mmio_list_head] + ld b32 $r13 D[$r0 + #tpc_mmio_list_tail] + ld b32 $r15 D[$r0 + #tpc_mask] + mov $r14 0x800 // stride = 0x800 + call #mmctx_xfer + + // wait for strands to finish + call #strand_wait + + // if load, or a save without a load following, do some + // unknown stuff that's done after finishing a block of + // strand commands + bra $p1 #ctx_xfer_post + bra not $p2 #ctx_xfer_done + ctx_xfer_post: + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xd + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d + call #strand_wait + + // mark completion in HUB's barrier + ctx_xfer_done: + call #hub_barrier_done + ret + +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h new file mode 100644 index 0000000..26c2165 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h @@ -0,0 +1,530 @@ +uint32_t nve0_grgpc_data[] = { +/* 0x0000: gpc_id */ + 0x00000000, +/* 0x0004: gpc_mmio_list_head */ + 0x00000000, +/* 0x0008: gpc_mmio_list_tail */ + 0x00000000, +/* 0x000c: tpc_count */ + 0x00000000, +/* 0x0010: tpc_mask */ + 0x00000000, +/* 0x0014: tpc_mmio_list_head */ + 0x00000000, +/* 0x0018: tpc_mmio_list_tail */ + 0x00000000, +/* 0x001c: cmd_queue */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0064: chipsets */ + 0x000000e4, + 0x01040080, + 0x014c0104, + 0x000000e7, + 0x01040080, + 0x014c0104, + 0x00000000, +/* 0x0080: nve4_gpc_mmio_head */ + 0x00000380, + 0x04000400, + 0x0800040c, + 0x20000450, + 0x00000600, + 0x00000684, + 0x10000700, + 0x00000800, + 0x08000808, + 0x00000828, + 0x00000830, + 0x000008d8, + 0x000008e0, + 0x140008e8, + 0x0000091c, + 0x08000924, + 0x00000b00, + 0x14000b08, + 0x00000bb8, + 0x00000c08, + 0x1c000c10, + 0x00000c40, + 0x00000c6c, + 0x00000c80, + 0x00000c8c, + 0x08001000, + 0x00001014, + 0x00003024, + 0x040030c0, + 0x000030e4, + 0x14003100, + 0x000031d0, + 0x040031e0, +/* 0x0104: nve4_gpc_mmio_tail */ +/* 0x0104: nve4_tpc_mmio_head */ + 0x00000048, + 0x00000064, + 0x00000088, + 0x14000200, + 0x0400021c, + 0x00000230, + 0x000002c4, + 0x08000400, + 0x08000420, + 0x000004e8, + 0x000004f4, + 0x0c000604, + 0x54000644, + 0x040006ac, + 0x000006c8, + 0x1c000730, + 0x00000758, + 0x00000778, +}; + +uint32_t nve0_grgpc_code[] = { + 0x03060ef5, +/* 0x0004: queue_put */ + 0x9800d898, + 0x86f001d9, + 0x0489b808, + 0xf00c1bf4, + 0x21f502f7, + 0x00f802ec, +/* 0x001c: queue_put_next */ + 0xb60798c4, + 0x8dbb0384, + 0x0880b600, + 0x80008e80, + 0x90b6018f, + 0x0f94f001, + 0xf801d980, +/* 0x0039: queue_get */ + 0x0131f400, + 0x9800d898, + 0x89b801d9, + 0x210bf404, + 0xb60789c4, + 0x9dbb0394, + 0x0890b600, + 0x98009e98, + 0x80b6019f, + 0x0f84f001, + 0xf400d880, +/* 0x0066: queue_get_done */ + 0x00f80132, +/* 0x0068: nv_rd32 */ + 0x0728b7f1, + 0xb906b4b6, + 0xc9f002ec, + 0x00bcd01f, +/* 0x0078: nv_rd32_wait */ + 0xc800bccf, + 0x1bf41fcc, + 0x06a7f0fa, + 0x010321f5, + 0xf840bfcf, +/* 0x008d: nv_wr32 */ + 0x28b7f100, + 0x06b4b607, + 0xb980bfd0, + 0xc9f002ec, + 0x1ec9f01f, +/* 0x00a3: nv_wr32_wait */ + 0xcf00bcd0, + 0xccc800bc, + 0xfa1bf41f, +/* 0x00ae: watchdog_reset */ + 0x87f100f8, + 0x84b60430, + 0x1ff9f006, + 0xf8008fd0, +/* 0x00bd: watchdog_clear */ + 0x3087f100, + 0x0684b604, + 0xf80080d0, +/* 0x00c9: wait_donez */ + 0x3c87f100, + 0x0684b608, + 0x99f094bd, + 0x0089d000, + 0x081887f1, + 0xd00684b6, +/* 0x00e2: wait_done_wait_donez */ + 0x87f1008a, + 0x84b60400, + 0x0088cf06, + 0xf4888aff, + 0x87f1f31b, + 0x84b6085c, + 0xf094bd06, + 0x89d00099, +/* 0x0103: wait_doneo */ + 0xf100f800, + 0xb6083c87, + 0x94bd0684, + 0xd00099f0, + 0x87f10089, + 0x84b60818, + 0x008ad006, +/* 0x011c: wait_done_wait_doneo */ + 0x040087f1, + 0xcf0684b6, + 0x8aff0088, + 0xf30bf488, + 0x085c87f1, + 0xbd0684b6, + 0x0099f094, + 0xf80089d0, +/* 0x013d: mmctx_size */ +/* 0x013f: nv_mmctx_size_loop */ + 0x9894bd00, + 0x85b600e8, + 0x0180b61a, + 0xbb0284b6, + 0xe0b60098, + 0x04efb804, + 0xb9eb1bf4, + 0x00f8029f, +/* 0x015c: mmctx_xfer */ + 0x083c87f1, + 0xbd0684b6, + 0x0199f094, + 0xf10089d0, + 0xb6071087, + 0x94bd0684, + 0xf405bbfd, + 0x8bd0090b, + 0x0099f000, +/* 0x0180: mmctx_base_disabled */ + 0xf405eefd, + 0x8ed00c0b, + 0xc08fd080, +/* 0x018f: mmctx_multi_disabled */ + 0xb70199f0, + 0xc8010080, + 0xb4b600ab, + 0x0cb9f010, + 0xb601aec8, + 0xbefd11e4, + 0x008bd005, +/* 0x01a8: mmctx_exec_loop */ +/* 0x01a8: mmctx_wait_free */ + 0xf0008ecf, + 0x0bf41fe4, + 0x00ce98fa, + 0xd005e9fd, + 0xc0b6c08e, + 0x04cdb804, + 0xc8e81bf4, + 0x1bf402ab, +/* 0x01c9: mmctx_fini_wait */ + 0x008bcf18, + 0xb01fb4f0, + 0x1bf410b4, + 0x02a7f0f7, + 0xf4c921f4, +/* 0x01de: mmctx_stop */ + 0xabc81b0e, + 0x10b4b600, + 0xf00cb9f0, + 0x8bd012b9, +/* 0x01ed: mmctx_stop_wait */ + 0x008bcf00, + 0xf412bbc8, +/* 0x01f6: mmctx_done */ + 0x87f1fa1b, + 0x84b6085c, + 0xf094bd06, + 0x89d00199, +/* 0x0207: strand_wait */ + 0xf900f800, + 0x02a7f0a0, + 0xfcc921f4, +/* 0x0213: strand_pre */ + 0xf100f8a0, + 0xf04afc87, + 0x97f00283, + 0x0089d00c, + 0x020721f5, +/* 0x0226: strand_post */ + 0x87f100f8, + 0x83f04afc, + 0x0d97f002, + 0xf50089d0, + 0xf8020721, +/* 0x0239: strand_set */ + 0xfca7f100, + 0x02a3f04f, + 0x0500aba2, + 0xd00fc7f0, + 0xc7f000ac, + 0x00bcd00b, + 0x020721f5, + 0xf000aed0, + 0xbcd00ac7, + 0x0721f500, +/* 0x0263: strand_ctx_init */ + 0xf100f802, + 0xb6083c87, + 0x94bd0684, + 0xd00399f0, + 0x21f50089, + 0xe7f00213, + 0x3921f503, + 0xfca7f102, + 0x02a3f046, + 0x0400aba0, + 0xf040a0d0, + 0xbcd001c7, + 0x0721f500, + 0x010c9202, + 0xf000acd0, + 0xbcd002c7, + 0x0721f500, + 0x2621f502, + 0x8087f102, + 0x0684b608, + 0xb70089cf, + 0x95220080, +/* 0x02ba: ctx_init_strand_loop */ + 0x8ed008fe, + 0x408ed000, + 0xb6808acf, + 0xa0b606a5, + 0x00eabb01, + 0xb60480b6, + 0x1bf40192, + 0x08e4b6e8, + 0xf1f2efbc, + 0xb6085c87, + 0x94bd0684, + 0xd00399f0, + 0x00f80089, +/* 0x02ec: error */ + 0xe7f1e0f9, + 0xe3f09814, + 0x8d21f440, + 0x041ce0b7, + 0xf401f7f0, + 0xe0fc8d21, +/* 0x0306: init */ + 0x04bd00f8, + 0xf10004fe, + 0xf0120017, + 0x12d00227, + 0x3e17f100, + 0x0010fe04, + 0x040017f1, + 0xf0c010d0, + 0x12d00427, + 0x1031f400, + 0x060817f1, + 0xcf0614b6, + 0x37f00012, + 0x1f24f001, + 0xb60432bb, + 0x02800132, + 0x04038003, + 0x040010b7, + 0x800012cf, + 0x27f10002, + 0x24b60800, + 0x0022cf06, +/* 0x035f: init_find_chipset */ + 0xb65817f0, + 0x13980c10, + 0x0432b800, + 0xb00b0bf4, + 0x1bf40034, +/* 0x0373: init_context */ + 0xf100f8f1, + 0xb6080027, + 0x22cf0624, + 0xf134bd40, + 0xb6070047, + 0x25950644, + 0x0045d008, + 0xbd4045d0, + 0x58f4bde4, + 0x1f58021e, + 0x020e4003, + 0xf5040f40, + 0xbb013d21, + 0x3fbb002f, + 0x041e5800, + 0x40051f58, + 0x0f400a0e, + 0x3d21f50c, + 0x030e9801, + 0xbb00effd, + 0x3ebb002e, + 0x0040b700, + 0x0235b613, + 0xb60043d0, + 0x35b60825, + 0x0120b606, + 0xb60130b6, + 0x34b60824, + 0x022fb908, + 0x026321f5, + 0xf1003fbb, + 0xb6080017, + 0x13d00614, + 0x0010b740, + 0xf024bd08, + 0x12d01f29, +/* 0x0401: main */ + 0x0031f400, + 0xf00028f4, + 0x21f41cd7, + 0xf401f439, + 0xf404e4b0, + 0x81fe1e18, + 0x0627f001, + 0x12fd20bd, + 0x01e4b604, + 0xfe051efd, + 0x21f50018, + 0x0ef404c3, +/* 0x0431: main_not_ctx_xfer */ + 0x10ef94d3, + 0xf501f5f0, + 0xf402ec21, +/* 0x043e: ih */ + 0x80f9c60e, + 0xf90188fe, + 0xf990f980, + 0xf9b0f9a0, + 0xf9e0f9d0, + 0x800acff0, + 0xf404abc4, + 0xb7f11d0b, + 0xd7f01900, + 0x40becf1c, + 0xf400bfcf, + 0xb0b70421, + 0xe7f00400, + 0x00bed001, +/* 0x0474: ih_no_fifo */ + 0xfc400ad0, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x32f480fc, +/* 0x048f: hub_barrier_done */ + 0xf001f800, + 0x0e9801f7, + 0x04febb00, + 0x9418e7f1, + 0xf440e3f0, + 0x00f88d21, +/* 0x04a4: ctx_redswitch */ + 0x0614e7f1, + 0xf006e4b6, + 0xefd020f7, + 0x08f7f000, +/* 0x04b4: ctx_redswitch_delay */ + 0xf401f2b6, + 0xf7f1fd1b, + 0xefd00a20, +/* 0x04c3: ctx_xfer */ + 0xf100f800, + 0xb60a0417, + 0x1fd00614, + 0x0711f400, + 0x04a421f5, +/* 0x04d4: ctx_xfer_not_load */ + 0x4afc17f1, + 0xf00213f0, + 0x12d00c27, + 0x0721f500, + 0xfc27f102, + 0x0223f047, + 0xf00020d0, + 0x20b6012c, + 0x0012d003, + 0xf001acf0, + 0xb7f002a5, + 0x50b3f000, + 0xb6000c98, + 0xbcbb0fc4, + 0x010c9800, + 0xf0020d98, + 0x21f500e7, + 0xacf0015c, + 0x04a5f001, + 0x4000b7f1, + 0x9850b3f0, + 0xc4b6000c, + 0x00bcbb0f, + 0x98050c98, + 0x0f98060d, + 0x00e7f104, + 0x5c21f508, + 0x0721f501, + 0x0601f402, +/* 0x054b: ctx_xfer_post */ + 0xf11412f4, + 0xf04afc17, + 0x27f00213, + 0x0012d00d, + 0x020721f5, +/* 0x055c: ctx_xfer_done */ + 0x048f21f5, + 0x000000f8, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc new file mode 100644 index 0000000..816ae57 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc @@ -0,0 +1,806 @@ +/* fuc microcode for nve0 PGRAPH/HUB + * + * Copyright 2011 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: + * + * 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 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 + */ + +/* To build: + * m4 nve0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nve0_grhub.fuc.h + */ + +.section #nve0_grhub_data +include(`nve0.fuc') +gpc_count: .b32 0 +rop_count: .b32 0 +cmd_queue: queue_init +hub_mmio_list_head: .b32 0 +hub_mmio_list_tail: .b32 0 + +ctx_current: .b32 0 + +chipsets: +.b8 0xe4 0 0 0 +.b16 #nve4_hub_mmio_head +.b16 #nve4_hub_mmio_tail +.b8 0xe7 0 0 0 +.b16 #nve4_hub_mmio_head +.b16 #nve4_hub_mmio_tail +.b8 0 0 0 0 + +nve4_hub_mmio_head: +mmctx_data(0x17e91c, 2) +mmctx_data(0x400204, 2) +mmctx_data(0x404010, 7) +mmctx_data(0x4040a8, 9) +mmctx_data(0x4040d0, 7) +mmctx_data(0x4040f8, 1) +mmctx_data(0x404130, 3) +mmctx_data(0x404150, 3) +mmctx_data(0x404164, 1) +mmctx_data(0x4041a0, 4) +mmctx_data(0x404200, 4) +mmctx_data(0x404404, 14) +mmctx_data(0x404460, 4) +mmctx_data(0x404480, 1) +mmctx_data(0x404498, 1) +mmctx_data(0x404604, 4) +mmctx_data(0x404618, 4) +mmctx_data(0x40462c, 2) +mmctx_data(0x404640, 1) +mmctx_data(0x404654, 1) +mmctx_data(0x404660, 1) +mmctx_data(0x404678, 19) +mmctx_data(0x4046c8, 3) +mmctx_data(0x404700, 3) +mmctx_data(0x404718, 10) +mmctx_data(0x404744, 2) +mmctx_data(0x404754, 1) +mmctx_data(0x405800, 1) +mmctx_data(0x405830, 3) +mmctx_data(0x405854, 1) +mmctx_data(0x405870, 4) +mmctx_data(0x405a00, 2) +mmctx_data(0x405a18, 1) +mmctx_data(0x405b00, 1) +mmctx_data(0x405b10, 1) +mmctx_data(0x406020, 1) +mmctx_data(0x406028, 4) +mmctx_data(0x4064a8, 2) +mmctx_data(0x4064b4, 2) +mmctx_data(0x4064c0, 12) +mmctx_data(0x4064fc, 1) +mmctx_data(0x407040, 1) +mmctx_data(0x407804, 1) +mmctx_data(0x40780c, 6) +mmctx_data(0x4078bc, 1) +mmctx_data(0x408000, 7) +mmctx_data(0x408064, 1) +mmctx_data(0x408800, 3) +mmctx_data(0x408840, 1) +mmctx_data(0x408900, 3) +mmctx_data(0x408980, 1) +nve4_hub_mmio_tail: + +.align 256 +chan_data: +chan_mmio_count: .b32 0 +chan_mmio_address: .b32 0 + +.align 256 +xfer_data: .b32 0 + +.section #nve0_grhub_code +bra #init +define(`include_code') +include(`nve0.fuc') + +// reports an exception to the host +// +// In: $r15 error code (see nve0.fuc) +// +error: + push $r14 + mov $r14 0x814 + shl b32 $r14 6 + iowr I[$r14 + 0x000] $r15 // CC_SCRATCH[5] = error code + mov $r14 0xc1c + shl b32 $r14 6 + mov $r15 1 + iowr I[$r14 + 0x000] $r15 // INTR_UP_SET + pop $r14 + ret + +// HUB fuc initialisation, executed by triggering ucode start, will +// fall through to main loop after completion. +// +// Input: +// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) +// +// Output: +// CC_SCRATCH[0]: +// 31:31: set to signal completion +// CC_SCRATCH[1]: +// 31:0: total PGRAPH context size +// +init: + clear b32 $r0 + mov $sp $r0 + mov $xdbase $r0 + + // enable fifo access + mov $r1 0x1200 + mov $r2 2 + iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE + + // setup i0 handler, and route all interrupts to it + mov $r1 #ih + mov $iv0 $r1 + mov $r1 0x400 + iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH + + // route HUB_CHANNEL_SWITCH to fuc interrupt 8 + mov $r3 0x404 + shl b32 $r3 6 + mov $r2 0x2003 // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8 + iowr I[$r3 + 0x000] $r2 + + // not sure what these are, route them because NVIDIA does, and + // the IRQ handler will signal the host if we ever get one.. we + // may find out if/why we need to handle these if so.. + // + mov $r2 0x2004 + iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9 + mov $r2 0x200b + iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10 + mov $r2 0x200c + iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15 + + // enable all INTR_UP interrupts + mov $r2 0xc24 + shl b32 $r2 6 + not b32 $r3 $r0 + iowr I[$r2] $r3 + + // enable fifo, ctxsw, 9, 10, 15 interrupts + mov $r2 -0x78fc // 0x8704 + sethi $r2 0 + iowr I[$r1 + 0x000] $r2 // INTR_EN_SET + + // fifo level triggered, rest edge + sub b32 $r1 0x100 + mov $r2 4 + iowr I[$r1] $r2 + + // enable interrupts + bset $flags ie0 + + // fetch enabled GPC/ROP counts + mov $r14 -0x69fc // 0x409604 + sethi $r14 0x400000 + call #nv_rd32 + extr $r1 $r15 16:20 + st b32 D[$r0 + #rop_count] $r1 + and $r15 0x1f + st b32 D[$r0 + #gpc_count] $r15 + + // set BAR_REQMASK to GPC mask + mov $r1 1 + shl b32 $r1 $r15 + sub b32 $r1 1 + mov $r2 0x40c + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r1 + iowr I[$r2 + 0x100] $r1 + + // find context data for this chipset + mov $r2 0x800 + shl b32 $r2 6 + iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] + mov $r15 #chipsets - 8 + init_find_chipset: + add b32 $r15 8 + ld b32 $r3 D[$r15 + 0x00] + cmpu b32 $r3 $r2 + bra e #init_context + cmpu b32 $r3 0 + bra ne #init_find_chipset + // unknown chipset + ret + + // context size calculation, reserve first 256 bytes for use by fuc + init_context: + mov $r1 256 + + // calculate size of mmio context data + ld b16 $r14 D[$r15 + 4] + ld b16 $r15 D[$r15 + 6] + sethi $r14 0 + st b32 D[$r0 + #hub_mmio_list_head] $r14 + st b32 D[$r0 + #hub_mmio_list_tail] $r15 + call #mmctx_size + + // set mmctx base addresses now so we don't have to do it later, + // they don't (currently) ever change + mov $r3 0x700 + shl b32 $r3 6 + shr b32 $r4 $r1 8 + iowr I[$r3 + 0x000] $r4 // MMCTX_SAVE_SWBASE + iowr I[$r3 + 0x100] $r4 // MMCTX_LOAD_SWBASE + add b32 $r3 0x1300 + add b32 $r1 $r15 + shr b32 $r15 2 + iowr I[$r3 + 0x000] $r15 // MMCTX_LOAD_COUNT, wtf for?!? + + // strands, base offset needs to be aligned to 256 bytes + shr b32 $r1 8 + add b32 $r1 1 + shl b32 $r1 8 + mov b32 $r15 $r1 + call #strand_ctx_init + add b32 $r1 $r15 + + // initialise each GPC in sequence by passing in the offset of its + // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which + // has previously been uploaded by the host) running. + // + // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31 + // when it has completed, and return the size of its context data + // in GPCn_CC_SCRATCH[1] + // + ld b32 $r3 D[$r0 + #gpc_count] + mov $r4 0x2000 + sethi $r4 0x500000 + init_gpc: + // setup, and start GPC ucode running + add b32 $r14 $r4 0x804 + mov b32 $r15 $r1 + call #nv_wr32 // CC_SCRATCH[1] = ctx offset + add b32 $r14 $r4 0x800 + mov b32 $r15 $r2 + call #nv_wr32 // CC_SCRATCH[0] = chipset + add b32 $r14 $r4 0x10c + clear b32 $r15 + call #nv_wr32 + add b32 $r14 $r4 0x104 + call #nv_wr32 // ENTRY + add b32 $r14 $r4 0x100 + mov $r15 2 // CTRL_START_TRIGGER + call #nv_wr32 // CTRL + + // wait for it to complete, and adjust context size + add b32 $r14 $r4 0x800 + init_gpc_wait: + call #nv_rd32 + xbit $r15 $r15 31 + bra e #init_gpc_wait + add b32 $r14 $r4 0x804 + call #nv_rd32 + add b32 $r1 $r15 + + // next! + add b32 $r4 0x8000 + sub b32 $r3 1 + bra ne #init_gpc + + // save context size, and tell host we're ready + mov $r2 0x800 + shl b32 $r2 6 + iowr I[$r2 + 0x100] $r1 // CC_SCRATCH[1] = context size + add b32 $r2 0x800 + clear b32 $r1 + bset $r1 31 + iowr I[$r2 + 0x000] $r1 // CC_SCRATCH[0] |= 0x80000000 + +// Main program loop, very simple, sleeps until woken up by the interrupt +// handler, pulls a command from the queue and executes its handler +// +main: + // sleep until we have something to do + bset $flags $p0 + sleep $p0 + mov $r13 #cmd_queue + call #queue_get + bra $p1 #main + + // context switch, requested by GPU? + cmpu b32 $r14 0x4001 + bra ne #main_not_ctx_switch + trace_set(T_AUTO) + mov $r1 0xb00 + shl b32 $r1 6 + iord $r2 I[$r1 + 0x100] // CHAN_NEXT + iord $r1 I[$r1 + 0x000] // CHAN_CUR + + xbit $r3 $r1 31 + bra e #chsw_no_prev + xbit $r3 $r2 31 + bra e #chsw_prev_no_next + push $r2 + mov b32 $r2 $r1 + trace_set(T_SAVE) + bclr $flags $p1 + bset $flags $p2 + call #ctx_xfer + trace_clr(T_SAVE); + pop $r2 + trace_set(T_LOAD); + bset $flags $p1 + call #ctx_xfer + trace_clr(T_LOAD); + bra #chsw_done + chsw_prev_no_next: + push $r2 + mov b32 $r2 $r1 + bclr $flags $p1 + bclr $flags $p2 + call #ctx_xfer + pop $r2 + mov $r1 0xb00 + shl b32 $r1 6 + iowr I[$r1] $r2 + bra #chsw_done + chsw_no_prev: + xbit $r3 $r2 31 + bra e #chsw_done + bset $flags $p1 + bclr $flags $p2 + call #ctx_xfer + + // ack the context switch request + chsw_done: + mov $r1 0xb0c + shl b32 $r1 6 + mov $r2 1 + iowr I[$r1 + 0x000] $r2 // 0x409b0c + trace_clr(T_AUTO) + bra #main + + // request to set current channel? (*not* a context switch) + main_not_ctx_switch: + cmpu b32 $r14 0x0001 + bra ne #main_not_ctx_chan + mov b32 $r2 $r15 + call #ctx_chan + bra #main_done + + // request to store current channel context? + main_not_ctx_chan: + cmpu b32 $r14 0x0002 + bra ne #main_not_ctx_save + trace_set(T_SAVE) + bclr $flags $p1 + bclr $flags $p2 + call #ctx_xfer + trace_clr(T_SAVE) + bra #main_done + + main_not_ctx_save: + shl b32 $r15 $r14 16 + or $r15 E_BAD_COMMAND + call #error + bra #main + + main_done: + mov $r1 0x820 + shl b32 $r1 6 + clear b32 $r2 + bset $r2 31 + iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 + bra #main + +// interrupt handler +ih: + push $r8 + mov $r8 $flags + push $r8 + push $r9 + push $r10 + push $r11 + push $r13 + push $r14 + push $r15 + + // incoming fifo command? + iord $r10 I[$r0 + 0x200] // INTR + and $r11 $r10 0x00000004 + bra e #ih_no_fifo + // queue incoming fifo command for later processing + mov $r11 0x1900 + mov $r13 #cmd_queue + iord $r14 I[$r11 + 0x100] // FIFO_CMD + iord $r15 I[$r11 + 0x000] // FIFO_DATA + call #queue_put + add b32 $r11 0x400 + mov $r14 1 + iowr I[$r11 + 0x000] $r14 // FIFO_ACK + + // context switch request? + ih_no_fifo: + and $r11 $r10 0x00000100 + bra e #ih_no_ctxsw + // enqueue a context switch for later processing + mov $r13 #cmd_queue + mov $r14 0x4001 + call #queue_put + + // anything we didn't handle, bring it to the host's attention + ih_no_ctxsw: + mov $r11 0x104 + not b32 $r11 + and $r11 $r10 $r11 + bra e #ih_no_other + mov $r10 0xc1c + shl b32 $r10 6 + iowr I[$r10] $r11 // INTR_UP_SET + + // ack, and wake up main() + ih_no_other: + iowr I[$r0 + 0x100] $r10 // INTR_ACK + + pop $r15 + pop $r14 + pop $r13 + pop $r11 + pop $r10 + pop $r9 + pop $r8 + mov $flags $r8 + pop $r8 + bclr $flags $p0 + iret + +// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done +ctx_4160s: + mov $r14 0x4160 + sethi $r14 0x400000 + mov $r15 1 + call #nv_wr32 + ctx_4160s_wait: + call #nv_rd32 + xbit $r15 $r15 4 + bra e #ctx_4160s_wait + ret + +// Without clearing again at end of xfer, some things cause PGRAPH +// to hang with STATUS=0x00000007 until it's cleared.. fbcon can +// still function with it set however... +ctx_4160c: + mov $r14 0x4160 + sethi $r14 0x400000 + clear b32 $r15 + call #nv_wr32 + ret + +// Again, not real sure +// +// In: $r15 value to set 0x404170 to +// +ctx_4170s: + mov $r14 0x4170 + sethi $r14 0x400000 + or $r15 0x10 + call #nv_wr32 + ret + +// Waits for a ctx_4170s() call to complete +// +ctx_4170w: + mov $r14 0x4170 + sethi $r14 0x400000 + call #nv_rd32 + and $r15 0x10 + bra ne #ctx_4170w + ret + +// Disables various things, waits a bit, and re-enables them.. +// +// Not sure how exactly this helps, perhaps "ENABLE" is not such a +// good description for the bits we turn off? Anyways, without this, +// funny things happen. +// +ctx_redswitch: + mov $r14 0x614 + shl b32 $r14 6 + mov $r15 0x270 + iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL + mov $r15 8 + ctx_redswitch_delay: + sub b32 $r15 1 + bra ne #ctx_redswitch_delay + mov $r15 0x770 + iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL + ret + +// Not a clue what this is for, except that unless the value is 0x10, the +// strand context is saved (and presumably restored) incorrectly.. +// +// In: $r15 value to set to (0x00/0x10 are used) +// +ctx_86c: + mov $r14 0x86c + shl b32 $r14 6 + iowr I[$r14] $r15 // HUB(0x86c) = val + mov $r14 -0x75ec + sethi $r14 0x400000 + call #nv_wr32 // ROP(0xa14) = val + mov $r14 -0x5794 + sethi $r14 0x410000 + call #nv_wr32 // GPC(0x86c) = val + ret + +// ctx_load - load's a channel's ctxctl data, and selects its vm +// +// In: $r2 channel address +// +ctx_load: + trace_set(T_CHAN) + + // switch to channel, somewhat magic in parts.. + mov $r10 12 // DONE_UNK12 + call #wait_donez + mov $r1 0xa24 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r0 // 0x409a24 + mov $r3 0xb00 + shl b32 $r3 6 + iowr I[$r3 + 0x100] $r2 // CHAN_NEXT + mov $r1 0xa0c + shl b32 $r1 6 + mov $r4 7 + iowr I[$r1 + 0x000] $r2 // MEM_CHAN + iowr I[$r1 + 0x100] $r4 // MEM_CMD + ctx_chan_wait_0: + iord $r4 I[$r1 + 0x100] + and $r4 0x1f + bra ne #ctx_chan_wait_0 + iowr I[$r3 + 0x000] $r2 // CHAN_CUR + + // load channel header, fetch PGRAPH context pointer + mov $xtargets $r0 + bclr $r2 31 + shl b32 $r2 4 + add b32 $r2 2 + + trace_set(T_LCHAN) + mov $r1 0xa04 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r2 // MEM_BASE + mov $r1 0xa20 + shl b32 $r1 6 + mov $r2 0x0002 + sethi $r2 0x80000000 + iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram + mov $r1 0x10 // chan + 0x0210 + mov $r2 #xfer_data + sethi $r2 0x00020000 // 16 bytes + xdld $r1 $r2 + xdwait + trace_clr(T_LCHAN) + + // update current context + ld b32 $r1 D[$r0 + #xfer_data + 4] + shl b32 $r1 24 + ld b32 $r2 D[$r0 + #xfer_data + 0] + shr b32 $r2 8 + or $r1 $r2 + st b32 D[$r0 + #ctx_current] $r1 + + // set transfer base to start of context, and fetch context header + trace_set(T_LCTXH) + mov $r2 0xa04 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r1 // MEM_BASE + mov $r2 1 + mov $r1 0xa20 + shl b32 $r1 6 + iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm + mov $r1 #chan_data + sethi $r1 0x00060000 // 256 bytes + xdld $r0 $r1 + xdwait + trace_clr(T_LCTXH) + + trace_clr(T_CHAN) + ret + +// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as +// the active channel for ctxctl, but not actually transfer +// any context data. intended for use only during initial +// context construction. +// +// In: $r2 channel address +// +ctx_chan: + call #ctx_4160s + call #ctx_load + mov $r10 12 // DONE_UNK12 + call #wait_donez + mov $r1 0xa10 + shl b32 $r1 6 + mov $r2 5 + iowr I[$r1 + 0x000] $r2 // MEM_CMD = 5 (???) + ctx_chan_wait: + iord $r2 I[$r1 + 0x000] + or $r2 $r2 + bra ne #ctx_chan_wait + call #ctx_4160c + ret + +// Execute per-context state overrides list +// +// Only executed on the first load of a channel. Might want to look into +// removing this and having the host directly modify the channel's context +// to change this state... The nouveau DRM already builds this list as +// it's definitely needed for NVIDIA's, so we may as well use it for now +// +// Input: $r1 mmio list length +// +ctx_mmio_exec: + // set transfer base to be the mmio list + ld b32 $r3 D[$r0 + #chan_mmio_address] + mov $r2 0xa04 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r3 // MEM_BASE + + clear b32 $r3 + ctx_mmio_loop: + // fetch next 256 bytes of mmio list if necessary + and $r4 $r3 0xff + bra ne #ctx_mmio_pull + mov $r5 #xfer_data + sethi $r5 0x00060000 // 256 bytes + xdld $r3 $r5 + xdwait + + // execute a single list entry + ctx_mmio_pull: + ld b32 $r14 D[$r4 + #xfer_data + 0x00] + ld b32 $r15 D[$r4 + #xfer_data + 0x04] + call #nv_wr32 + + // next! + add b32 $r3 8 + sub b32 $r1 1 + bra ne #ctx_mmio_loop + + // set transfer base back to the current context + ctx_mmio_done: + ld b32 $r3 D[$r0 + #ctx_current] + iowr I[$r2 + 0x000] $r3 // MEM_BASE + + // disable the mmio list now, we don't need/want to execute it again + st b32 D[$r0 + #chan_mmio_count] $r0 + mov $r1 #chan_data + sethi $r1 0x00060000 // 256 bytes + xdst $r0 $r1 + xdwait + ret + +// Transfer HUB context data between GPU and storage area +// +// In: $r2 channel address +// $p1 clear on save, set on load +// $p2 set if opposite direction done/will be done, so: +// on save it means: "a load will follow this save" +// on load it means: "a save preceeded this load" +// +ctx_xfer: + bra not $p1 #ctx_xfer_pre + bra $p2 #ctx_xfer_pre_load + ctx_xfer_pre: + mov $r15 0x10 + call #ctx_86c + call #ctx_4160s + bra not $p1 #ctx_xfer_exec + + ctx_xfer_pre_load: + mov $r15 2 + call #ctx_4170s + call #ctx_4170w + call #ctx_redswitch + clear b32 $r15 + call #ctx_4170s + call #ctx_load + + // fetch context pointer, and initiate xfer on all GPCs + ctx_xfer_exec: + ld b32 $r1 D[$r0 + #ctx_current] + mov $r2 0x414 + shl b32 $r2 6 + iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset + mov $r14 -0x5b00 + sethi $r14 0x410000 + mov b32 $r15 $r1 + call #nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer + add b32 $r14 4 + xbit $r15 $flags $p1 + xbit $r2 $flags $p2 + shl b32 $r2 1 + or $r15 $r2 + call #nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) + + // strands + mov $r1 0x4afc + sethi $r1 0x20000 + mov $r2 0xc + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c + call #strand_wait + mov $r2 0x47fc + sethi $r2 0x20000 + iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 + xbit $r2 $flags $p1 + add b32 $r2 3 + iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) + + // mmio context + xbit $r10 $flags $p1 // direction + or $r10 6 // first, last + mov $r11 0 // base = 0 + ld b32 $r12 D[$r0 + #hub_mmio_list_head] + ld b32 $r13 D[$r0 + #hub_mmio_list_tail] + mov $r14 0 // not multi + call #mmctx_xfer + + // wait for GPCs to all complete + mov $r10 8 // DONE_BAR + call #wait_doneo + + // wait for strand xfer to complete + call #strand_wait + + // post-op + bra $p1 #ctx_xfer_post + mov $r10 12 // DONE_UNK12 + call #wait_donez + mov $r1 0xa10 + shl b32 $r1 6 + mov $r2 5 + iowr I[$r1] $r2 // MEM_CMD + ctx_xfer_post_save_wait: + iord $r2 I[$r1] + or $r2 $r2 + bra ne #ctx_xfer_post_save_wait + + bra $p2 #ctx_xfer_done + ctx_xfer_post: + mov $r15 2 + call #ctx_4170s + clear b32 $r15 + call #ctx_86c + call #strand_post + call #ctx_4170w + clear b32 $r15 + call #ctx_4170s + + bra not $p1 #ctx_xfer_no_post_mmio + ld b32 $r1 D[$r0 + #chan_mmio_count] + or $r1 $r1 + bra e #ctx_xfer_no_post_mmio + call #ctx_mmio_exec + + ctx_xfer_no_post_mmio: + call #ctx_4160c + + ctx_xfer_done: + ret + +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h new file mode 100644 index 0000000..05c3995 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h @@ -0,0 +1,924 @@ +uint32_t nve0_grhub_data[] = { +/* 0x0000: gpc_count */ + 0x00000000, +/* 0x0004: rop_count */ + 0x00000000, +/* 0x0008: cmd_queue */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0050: hub_mmio_list_head */ + 0x00000000, +/* 0x0054: hub_mmio_list_tail */ + 0x00000000, +/* 0x0058: ctx_current */ + 0x00000000, +/* 0x005c: chipsets */ + 0x000000e4, + 0x013c0070, + 0x000000e7, + 0x013c0070, + 0x00000000, +/* 0x0070: nve4_hub_mmio_head */ + 0x0417e91c, + 0x04400204, + 0x18404010, + 0x204040a8, + 0x184040d0, + 0x004040f8, + 0x08404130, + 0x08404150, + 0x00404164, + 0x0c4041a0, + 0x0c404200, + 0x34404404, + 0x0c404460, + 0x00404480, + 0x00404498, + 0x0c404604, + 0x0c404618, + 0x0440462c, + 0x00404640, + 0x00404654, + 0x00404660, + 0x48404678, + 0x084046c8, + 0x08404700, + 0x24404718, + 0x04404744, + 0x00404754, + 0x00405800, + 0x08405830, + 0x00405854, + 0x0c405870, + 0x04405a00, + 0x00405a18, + 0x00405b00, + 0x00405b10, + 0x00406020, + 0x0c406028, + 0x044064a8, + 0x044064b4, + 0x2c4064c0, + 0x004064fc, + 0x00407040, + 0x00407804, + 0x1440780c, + 0x004078bc, + 0x18408000, + 0x00408064, + 0x08408800, + 0x00408840, + 0x08408900, + 0x00408980, +/* 0x013c: nve4_hub_mmio_tail */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0200: chan_data */ +/* 0x0200: chan_mmio_count */ + 0x00000000, +/* 0x0204: chan_mmio_address */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +/* 0x0300: xfer_data */ + 0x00000000, +}; + +uint32_t nve0_grhub_code[] = { + 0x03090ef5, +/* 0x0004: queue_put */ + 0x9800d898, + 0x86f001d9, + 0x0489b808, + 0xf00c1bf4, + 0x21f502f7, + 0x00f802ec, +/* 0x001c: queue_put_next */ + 0xb60798c4, + 0x8dbb0384, + 0x0880b600, + 0x80008e80, + 0x90b6018f, + 0x0f94f001, + 0xf801d980, +/* 0x0039: queue_get */ + 0x0131f400, + 0x9800d898, + 0x89b801d9, + 0x210bf404, + 0xb60789c4, + 0x9dbb0394, + 0x0890b600, + 0x98009e98, + 0x80b6019f, + 0x0f84f001, + 0xf400d880, +/* 0x0066: queue_get_done */ + 0x00f80132, +/* 0x0068: nv_rd32 */ + 0x0728b7f1, + 0xb906b4b6, + 0xc9f002ec, + 0x00bcd01f, +/* 0x0078: nv_rd32_wait */ + 0xc800bccf, + 0x1bf41fcc, + 0x06a7f0fa, + 0x010321f5, + 0xf840bfcf, +/* 0x008d: nv_wr32 */ + 0x28b7f100, + 0x06b4b607, + 0xb980bfd0, + 0xc9f002ec, + 0x1ec9f01f, +/* 0x00a3: nv_wr32_wait */ + 0xcf00bcd0, + 0xccc800bc, + 0xfa1bf41f, +/* 0x00ae: watchdog_reset */ + 0x87f100f8, + 0x84b60430, + 0x1ff9f006, + 0xf8008fd0, +/* 0x00bd: watchdog_clear */ + 0x3087f100, + 0x0684b604, + 0xf80080d0, +/* 0x00c9: wait_donez */ + 0x3c87f100, + 0x0684b608, + 0x99f094bd, + 0x0089d000, + 0x081887f1, + 0xd00684b6, +/* 0x00e2: wait_done_wait_donez */ + 0x87f1008a, + 0x84b60400, + 0x0088cf06, + 0xf4888aff, + 0x87f1f31b, + 0x84b6085c, + 0xf094bd06, + 0x89d00099, +/* 0x0103: wait_doneo */ + 0xf100f800, + 0xb6083c87, + 0x94bd0684, + 0xd00099f0, + 0x87f10089, + 0x84b60818, + 0x008ad006, +/* 0x011c: wait_done_wait_doneo */ + 0x040087f1, + 0xcf0684b6, + 0x8aff0088, + 0xf30bf488, + 0x085c87f1, + 0xbd0684b6, + 0x0099f094, + 0xf80089d0, +/* 0x013d: mmctx_size */ +/* 0x013f: nv_mmctx_size_loop */ + 0x9894bd00, + 0x85b600e8, + 0x0180b61a, + 0xbb0284b6, + 0xe0b60098, + 0x04efb804, + 0xb9eb1bf4, + 0x00f8029f, +/* 0x015c: mmctx_xfer */ + 0x083c87f1, + 0xbd0684b6, + 0x0199f094, + 0xf10089d0, + 0xb6071087, + 0x94bd0684, + 0xf405bbfd, + 0x8bd0090b, + 0x0099f000, +/* 0x0180: mmctx_base_disabled */ + 0xf405eefd, + 0x8ed00c0b, + 0xc08fd080, +/* 0x018f: mmctx_multi_disabled */ + 0xb70199f0, + 0xc8010080, + 0xb4b600ab, + 0x0cb9f010, + 0xb601aec8, + 0xbefd11e4, + 0x008bd005, +/* 0x01a8: mmctx_exec_loop */ +/* 0x01a8: mmctx_wait_free */ + 0xf0008ecf, + 0x0bf41fe4, + 0x00ce98fa, + 0xd005e9fd, + 0xc0b6c08e, + 0x04cdb804, + 0xc8e81bf4, + 0x1bf402ab, +/* 0x01c9: mmctx_fini_wait */ + 0x008bcf18, + 0xb01fb4f0, + 0x1bf410b4, + 0x02a7f0f7, + 0xf4c921f4, +/* 0x01de: mmctx_stop */ + 0xabc81b0e, + 0x10b4b600, + 0xf00cb9f0, + 0x8bd012b9, +/* 0x01ed: mmctx_stop_wait */ + 0x008bcf00, + 0xf412bbc8, +/* 0x01f6: mmctx_done */ + 0x87f1fa1b, + 0x84b6085c, + 0xf094bd06, + 0x89d00199, +/* 0x0207: strand_wait */ + 0xf900f800, + 0x02a7f0a0, + 0xfcc921f4, +/* 0x0213: strand_pre */ + 0xf100f8a0, + 0xf04afc87, + 0x97f00283, + 0x0089d00c, + 0x020721f5, +/* 0x0226: strand_post */ + 0x87f100f8, + 0x83f04afc, + 0x0d97f002, + 0xf50089d0, + 0xf8020721, +/* 0x0239: strand_set */ + 0xfca7f100, + 0x02a3f04f, + 0x0500aba2, + 0xd00fc7f0, + 0xc7f000ac, + 0x00bcd00b, + 0x020721f5, + 0xf000aed0, + 0xbcd00ac7, + 0x0721f500, +/* 0x0263: strand_ctx_init */ + 0xf100f802, + 0xb6083c87, + 0x94bd0684, + 0xd00399f0, + 0x21f50089, + 0xe7f00213, + 0x3921f503, + 0xfca7f102, + 0x02a3f046, + 0x0400aba0, + 0xf040a0d0, + 0xbcd001c7, + 0x0721f500, + 0x010c9202, + 0xf000acd0, + 0xbcd002c7, + 0x0721f500, + 0x2621f502, + 0x8087f102, + 0x0684b608, + 0xb70089cf, + 0x95220080, +/* 0x02ba: ctx_init_strand_loop */ + 0x8ed008fe, + 0x408ed000, + 0xb6808acf, + 0xa0b606a5, + 0x00eabb01, + 0xb60480b6, + 0x1bf40192, + 0x08e4b6e8, + 0xf1f2efbc, + 0xb6085c87, + 0x94bd0684, + 0xd00399f0, + 0x00f80089, +/* 0x02ec: error */ + 0xe7f1e0f9, + 0xe4b60814, + 0x00efd006, + 0x0c1ce7f1, + 0xf006e4b6, + 0xefd001f7, + 0xf8e0fc00, +/* 0x0309: init */ + 0xfe04bd00, + 0x07fe0004, + 0x0017f100, + 0x0227f012, + 0xf10012d0, + 0xfe05b917, + 0x17f10010, + 0x10d00400, + 0x0437f1c0, + 0x0634b604, + 0x200327f1, + 0xf10032d0, + 0xd0200427, + 0x27f10132, + 0x32d0200b, + 0x0c27f102, + 0x0732d020, + 0x0c2427f1, + 0xb90624b6, + 0x23d00003, + 0x0427f100, + 0x0023f087, + 0xb70012d0, + 0xf0010012, + 0x12d00427, + 0x1031f400, + 0x9604e7f1, + 0xf440e3f0, + 0xf1c76821, + 0x01018090, + 0x801ff4f0, + 0x17f0000f, + 0x041fbb01, + 0xf10112b6, + 0xb6040c27, + 0x21d00624, + 0x4021d000, + 0x080027f1, + 0xcf0624b6, + 0xf7f00022, +/* 0x03a9: init_find_chipset */ + 0x08f0b654, + 0xb800f398, + 0x0bf40432, + 0x0034b00b, + 0xf8f11bf4, +/* 0x03bd: init_context */ + 0x0017f100, + 0x02fe5801, + 0xf003ff58, + 0x0e8000e3, + 0x150f8014, + 0x013d21f5, + 0x070037f1, + 0x950634b6, + 0x34d00814, + 0x4034d000, + 0x130030b7, + 0xb6001fbb, + 0x3fd002f5, + 0x0815b600, + 0xb60110b6, + 0x1fb90814, + 0x6321f502, + 0x001fbb02, + 0xf1000398, + 0xf0200047, +/* 0x040e: init_gpc */ + 0x4ea05043, + 0x1fb90804, + 0x8d21f402, + 0x08004ea0, + 0xf4022fb9, + 0x4ea08d21, + 0xf4bd010c, + 0xa08d21f4, + 0xf401044e, + 0x4ea08d21, + 0xf7f00100, + 0x8d21f402, + 0x08004ea0, +/* 0x0440: init_gpc_wait */ + 0xc86821f4, + 0x0bf41fff, + 0x044ea0fa, + 0x6821f408, + 0xb7001fbb, + 0xb6800040, + 0x1bf40132, + 0x0027f1b4, + 0x0624b608, + 0xb74021d0, + 0xbd080020, + 0x1f19f014, +/* 0x0473: main */ + 0xf40021d0, + 0x28f40031, + 0x08d7f000, + 0xf43921f4, + 0xe4b1f401, + 0x1bf54001, + 0x87f100d1, + 0x84b6083c, + 0xf094bd06, + 0x89d00499, + 0x0017f100, + 0x0614b60b, + 0xcf4012cf, + 0x13c80011, + 0x7e0bf41f, + 0xf41f23c8, + 0x20f95a0b, + 0xf10212b9, + 0xb6083c87, + 0x94bd0684, + 0xd00799f0, + 0x32f40089, + 0x0231f401, + 0x082921f5, + 0x085c87f1, + 0xbd0684b6, + 0x0799f094, + 0xfc0089d0, + 0x3c87f120, + 0x0684b608, + 0x99f094bd, + 0x0089d006, + 0xf50131f4, + 0xf1082921, + 0xb6085c87, + 0x94bd0684, + 0xd00699f0, + 0x0ef40089, +/* 0x0509: chsw_prev_no_next */ + 0xb920f931, + 0x32f40212, + 0x0232f401, + 0x082921f5, + 0x17f120fc, + 0x14b60b00, + 0x0012d006, +/* 0x0527: chsw_no_prev */ + 0xc8130ef4, + 0x0bf41f23, + 0x0131f40d, + 0xf50232f4, +/* 0x0537: chsw_done */ + 0xf1082921, + 0xb60b0c17, + 0x27f00614, + 0x0012d001, + 0x085c87f1, + 0xbd0684b6, + 0x0499f094, + 0xf50089d0, +/* 0x0557: main_not_ctx_switch */ + 0xb0ff200e, + 0x1bf401e4, + 0x02f2b90d, + 0x07b521f5, +/* 0x0567: main_not_ctx_chan */ + 0xb0420ef4, + 0x1bf402e4, + 0x3c87f12e, + 0x0684b608, + 0x99f094bd, + 0x0089d007, + 0xf40132f4, + 0x21f50232, + 0x87f10829, + 0x84b6085c, + 0xf094bd06, + 0x89d00799, + 0x110ef400, +/* 0x0598: main_not_ctx_save */ + 0xf010ef94, + 0x21f501f5, + 0x0ef502ec, +/* 0x05a6: main_done */ + 0x17f1fed1, + 0x14b60820, + 0xf024bd06, + 0x12d01f29, + 0xbe0ef500, +/* 0x05b9: ih */ + 0xfe80f9fe, + 0x80f90188, + 0xa0f990f9, + 0xd0f9b0f9, + 0xf0f9e0f9, + 0xc4800acf, + 0x0bf404ab, + 0x00b7f11d, + 0x08d7f019, + 0xcf40becf, + 0x21f400bf, + 0x00b0b704, + 0x01e7f004, +/* 0x05ef: ih_no_fifo */ + 0xe400bed0, + 0xf40100ab, + 0xd7f00d0b, + 0x01e7f108, + 0x0421f440, +/* 0x0600: ih_no_ctxsw */ + 0x0104b7f1, + 0xabffb0bd, + 0x0d0bf4b4, + 0x0c1ca7f1, + 0xd006a4b6, +/* 0x0616: ih_no_other */ + 0x0ad000ab, + 0xfcf0fc40, + 0xfcd0fce0, + 0xfca0fcb0, + 0xfe80fc90, + 0x80fc0088, + 0xf80032f4, +/* 0x0631: ctx_4160s */ + 0x60e7f101, + 0x40e3f041, + 0xf401f7f0, +/* 0x063e: ctx_4160s_wait */ + 0x21f48d21, + 0x04ffc868, + 0xf8fa0bf4, +/* 0x0649: ctx_4160c */ + 0x60e7f100, + 0x40e3f041, + 0x21f4f4bd, +/* 0x0657: ctx_4170s */ + 0xf100f88d, + 0xf04170e7, + 0xf5f040e3, + 0x8d21f410, +/* 0x0666: ctx_4170w */ + 0xe7f100f8, + 0xe3f04170, + 0x6821f440, + 0xf410f4f0, + 0x00f8f31b, +/* 0x0678: ctx_redswitch */ + 0x0614e7f1, + 0xf106e4b6, + 0xd00270f7, + 0xf7f000ef, +/* 0x0689: ctx_redswitch_delay */ + 0x01f2b608, + 0xf1fd1bf4, + 0xd00770f7, + 0x00f800ef, +/* 0x0698: ctx_86c */ + 0x086ce7f1, + 0xd006e4b6, + 0xe7f100ef, + 0xe3f08a14, + 0x8d21f440, + 0xa86ce7f1, + 0xf441e3f0, + 0x00f88d21, +/* 0x06b8: ctx_load */ + 0x083c87f1, + 0xbd0684b6, + 0x0599f094, + 0xf00089d0, + 0x21f40ca7, + 0x2417f1c9, + 0x0614b60a, + 0xf10010d0, + 0xb60b0037, + 0x32d00634, + 0x0c17f140, + 0x0614b60a, + 0xd00747f0, + 0x14d00012, +/* 0x06f1: ctx_chan_wait_0 */ + 0x4014cf40, + 0xf41f44f0, + 0x32d0fa1b, + 0x000bfe00, + 0xb61f2af0, + 0x20b60424, + 0x3c87f102, + 0x0684b608, + 0x99f094bd, + 0x0089d008, + 0x0a0417f1, + 0xd00614b6, + 0x17f10012, + 0x14b60a20, + 0x0227f006, + 0x800023f1, + 0xf00012d0, + 0x27f11017, + 0x23f00300, + 0x0512fa02, + 0x87f103f8, + 0x84b6085c, + 0xf094bd06, + 0x89d00899, + 0xc1019800, + 0x981814b6, + 0x25b6c002, + 0x0512fd08, + 0xf1160180, + 0xb6083c87, + 0x94bd0684, + 0xd00999f0, + 0x27f10089, + 0x24b60a04, + 0x0021d006, + 0xf10127f0, + 0xb60a2017, + 0x12d00614, + 0x0017f100, + 0x0613f002, + 0xf80501fa, + 0x5c87f103, + 0x0684b608, + 0x99f094bd, + 0x0089d009, + 0x085c87f1, + 0xbd0684b6, + 0x0599f094, + 0xf80089d0, +/* 0x07b5: ctx_chan */ + 0x3121f500, + 0xb821f506, + 0x0ca7f006, + 0xf1c921f4, + 0xb60a1017, + 0x27f00614, + 0x0012d005, +/* 0x07d0: ctx_chan_wait */ + 0xfd0012cf, + 0x1bf40522, + 0x4921f5fa, +/* 0x07df: ctx_mmio_exec */ + 0x9800f806, + 0x27f18103, + 0x24b60a04, + 0x0023d006, +/* 0x07ee: ctx_mmio_loop */ + 0x34c434bd, + 0x0f1bf4ff, + 0x030057f1, + 0xfa0653f0, + 0x03f80535, +/* 0x0800: ctx_mmio_pull */ + 0x98c04e98, + 0x21f4c14f, + 0x0830b68d, + 0xf40112b6, +/* 0x0812: ctx_mmio_done */ + 0x0398df1b, + 0x0023d016, + 0xf1800080, + 0xf0020017, + 0x01fa0613, + 0xf803f806, +/* 0x0829: ctx_xfer */ + 0x0611f400, +/* 0x082f: ctx_xfer_pre */ + 0xf01102f4, + 0x21f510f7, + 0x21f50698, + 0x11f40631, +/* 0x083d: ctx_xfer_pre_load */ + 0x02f7f01c, + 0x065721f5, + 0x066621f5, + 0x067821f5, + 0x21f5f4bd, + 0x21f50657, +/* 0x0856: ctx_xfer_exec */ + 0x019806b8, + 0x1427f116, + 0x0624b604, + 0xf10020d0, + 0xf0a500e7, + 0x1fb941e3, + 0x8d21f402, + 0xf004e0b6, + 0x2cf001fc, + 0x0124b602, + 0xf405f2fd, + 0x17f18d21, + 0x13f04afc, + 0x0c27f002, + 0xf50012d0, + 0xf1020721, + 0xf047fc27, + 0x20d00223, + 0x012cf000, + 0xd00320b6, + 0xacf00012, + 0x06a5f001, + 0x9800b7f0, + 0x0d98140c, + 0x00e7f015, + 0x015c21f5, + 0xf508a7f0, + 0xf5010321, + 0xf4020721, + 0xa7f02201, + 0xc921f40c, + 0x0a1017f1, + 0xf00614b6, + 0x12d00527, +/* 0x08dd: ctx_xfer_post_save_wait */ + 0x0012cf00, + 0xf40522fd, + 0x02f4fa1b, +/* 0x08e9: ctx_xfer_post */ + 0x02f7f032, + 0x065721f5, + 0x21f5f4bd, + 0x21f50698, + 0x21f50226, + 0xf4bd0666, + 0x065721f5, + 0x981011f4, + 0x11fd8001, + 0x070bf405, + 0x07df21f5, +/* 0x0914: ctx_xfer_no_post_mmio */ + 0x064921f5, +/* 0x0918: ctx_xfer_done */ + 0x000000f8, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc new file mode 100644 index 0000000..f16a5d5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc @@ -0,0 +1,400 @@ +/* fuc microcode util functions for nve0 PGRAPH + * + * Copyright 2011 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: + * + * 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 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 + */ + +define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)') +define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))') + +ifdef(`include_code', ` +// Error codes +define(`E_BAD_COMMAND', 0x01) +define(`E_CMD_OVERFLOW', 0x02) + +// Util macros to help with debugging ucode hangs etc +define(`T_WAIT', 0) +define(`T_MMCTX', 1) +define(`T_STRWAIT', 2) +define(`T_STRINIT', 3) +define(`T_AUTO', 4) +define(`T_CHAN', 5) +define(`T_LOAD', 6) +define(`T_SAVE', 7) +define(`T_LCHAN', 8) +define(`T_LCTXH', 9) + +define(`trace_set', ` + mov $r8 0x83c + shl b32 $r8 6 + clear b32 $r9 + bset $r9 $1 + iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] +') + +define(`trace_clr', ` + mov $r8 0x85c + shl b32 $r8 6 + clear b32 $r9 + bset $r9 $1 + iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] +') + +// queue_put - add request to queue +// +// In : $r13 queue pointer +// $r14 command +// $r15 data +// +queue_put: + // make sure we have space.. + ld b32 $r8 D[$r13 + 0x0] // GET + ld b32 $r9 D[$r13 + 0x4] // PUT + xor $r8 8 + cmpu b32 $r8 $r9 + bra ne #queue_put_next + mov $r15 E_CMD_OVERFLOW + call #error + ret + + // store cmd/data on queue + queue_put_next: + and $r8 $r9 7 + shl b32 $r8 3 + add b32 $r8 $r13 + add b32 $r8 8 + st b32 D[$r8 + 0x0] $r14 + st b32 D[$r8 + 0x4] $r15 + + // update PUT + add b32 $r9 1 + and $r9 0xf + st b32 D[$r13 + 0x4] $r9 + ret + +// queue_get - fetch request from queue +// +// In : $r13 queue pointer +// +// Out: $p1 clear on success (data available) +// $r14 command +// $r15 data +// +queue_get: + bset $flags $p1 + ld b32 $r8 D[$r13 + 0x0] // GET + ld b32 $r9 D[$r13 + 0x4] // PUT + cmpu b32 $r8 $r9 + bra e #queue_get_done + // fetch first cmd/data pair + and $r9 $r8 7 + shl b32 $r9 3 + add b32 $r9 $r13 + add b32 $r9 8 + ld b32 $r14 D[$r9 + 0x0] + ld b32 $r15 D[$r9 + 0x4] + + // update GET + add b32 $r8 1 + and $r8 0xf + st b32 D[$r13 + 0x0] $r8 + bclr $flags $p1 +queue_get_done: + ret + +// nv_rd32 - read 32-bit value from nv register +// +// In : $r14 register +// Out: $r15 value +// +nv_rd32: + mov $r11 0x728 + shl b32 $r11 6 + mov b32 $r12 $r14 + bset $r12 31 // MMIO_CTRL_PENDING + iowr I[$r11 + 0x000] $r12 // MMIO_CTRL + nv_rd32_wait: + iord $r12 I[$r11 + 0x000] + xbit $r12 $r12 31 + bra ne #nv_rd32_wait + mov $r10 6 // DONE_MMIO_RD + call #wait_doneo + iord $r15 I[$r11 + 0x100] // MMIO_RDVAL + ret + +// nv_wr32 - write 32-bit value to nv register +// +// In : $r14 register +// $r15 value +// +nv_wr32: + mov $r11 0x728 + shl b32 $r11 6 + iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL + mov b32 $r12 $r14 + bset $r12 31 // MMIO_CTRL_PENDING + bset $r12 30 // MMIO_CTRL_WRITE + iowr I[$r11 + 0x000] $r12 // MMIO_CTRL + nv_wr32_wait: + iord $r12 I[$r11 + 0x000] + xbit $r12 $r12 31 + bra ne #nv_wr32_wait + ret + +// (re)set watchdog timer +// +// In : $r15 timeout +// +watchdog_reset: + mov $r8 0x430 + shl b32 $r8 6 + bset $r15 31 + iowr I[$r8 + 0x000] $r15 + ret + +// clear watchdog timer +watchdog_clear: + mov $r8 0x430 + shl b32 $r8 6 + iowr I[$r8 + 0x000] $r0 + ret + +// wait_done{z,o} - wait on FUC_DONE bit to become clear/set +// +// In : $r10 bit to wait on +// +define(`wait_done', ` +$1: + trace_set(T_WAIT); + mov $r8 0x818 + shl b32 $r8 6 + iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit + wait_done_$1: + mov $r8 0x400 + shl b32 $r8 6 + iord $r8 I[$r8 + 0x000] // DONE + xbit $r8 $r8 $r10 + bra $2 #wait_done_$1 + trace_clr(T_WAIT) + ret +') +wait_done(wait_donez, ne) +wait_done(wait_doneo, e) + +// mmctx_size - determine size of a mmio list transfer +// +// In : $r14 mmio list head +// $r15 mmio list tail +// Out: $r15 transfer size (in bytes) +// +mmctx_size: + clear b32 $r9 + nv_mmctx_size_loop: + ld b32 $r8 D[$r14] + shr b32 $r8 26 + add b32 $r8 1 + shl b32 $r8 2 + add b32 $r9 $r8 + add b32 $r14 4 + cmpu b32 $r14 $r15 + bra ne #nv_mmctx_size_loop + mov b32 $r15 $r9 + ret + +// mmctx_xfer - execute a list of mmio transfers +// +// In : $r10 flags +// bit 0: direction (0 = save, 1 = load) +// bit 1: set if first transfer +// bit 2: set if last transfer +// $r11 base +// $r12 mmio list head +// $r13 mmio list tail +// $r14 multi_stride +// $r15 multi_mask +// +mmctx_xfer: + trace_set(T_MMCTX) + mov $r8 0x710 + shl b32 $r8 6 + clear b32 $r9 + or $r11 $r11 + bra e #mmctx_base_disabled + iowr I[$r8 + 0x000] $r11 // MMCTX_BASE + bset $r9 0 // BASE_EN + mmctx_base_disabled: + or $r14 $r14 + bra e #mmctx_multi_disabled + iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE + iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK + bset $r9 1 // MULTI_EN + mmctx_multi_disabled: + add b32 $r8 0x100 + + xbit $r11 $r10 0 + shl b32 $r11 16 // DIR + bset $r11 12 // QLIMIT = 0x10 + xbit $r14 $r10 1 + shl b32 $r14 17 + or $r11 $r14 // START_TRIGGER + iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL + + // loop over the mmio list, and send requests to the hw + mmctx_exec_loop: + // wait for space in mmctx queue + mmctx_wait_free: + iord $r14 I[$r8 + 0x000] // MMCTX_CTRL + and $r14 0x1f + bra e #mmctx_wait_free + + // queue up an entry + ld b32 $r14 D[$r12] + or $r14 $r9 + iowr I[$r8 + 0x300] $r14 + add b32 $r12 4 + cmpu b32 $r12 $r13 + bra ne #mmctx_exec_loop + + xbit $r11 $r10 2 + bra ne #mmctx_stop + // wait for queue to empty + mmctx_fini_wait: + iord $r11 I[$r8 + 0x000] // MMCTX_CTRL + and $r11 0x1f + cmpu b32 $r11 0x10 + bra ne #mmctx_fini_wait + mov $r10 2 // DONE_MMCTX + call #wait_donez + bra #mmctx_done + mmctx_stop: + xbit $r11 $r10 0 + shl b32 $r11 16 // DIR + bset $r11 12 // QLIMIT = 0x10 + bset $r11 18 // STOP_TRIGGER + iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL + mmctx_stop_wait: + // wait for STOP_TRIGGER to clear + iord $r11 I[$r8 + 0x000] // MMCTX_CTRL + xbit $r11 $r11 18 + bra ne #mmctx_stop_wait + mmctx_done: + trace_clr(T_MMCTX) + ret + +// Wait for DONE_STRAND +// +strand_wait: + push $r10 + mov $r10 2 + call #wait_donez + pop $r10 + ret + +// unknown - call before issuing strand commands +// +strand_pre: + mov $r8 0x4afc + sethi $r8 0x20000 + mov $r9 0xc + iowr I[$r8] $r9 + call #strand_wait + ret + +// unknown - call after issuing strand commands +// +strand_post: + mov $r8 0x4afc + sethi $r8 0x20000 + mov $r9 0xd + iowr I[$r8] $r9 + call #strand_wait + ret + +// Selects strand set?! +// +// In: $r14 id +// +strand_set: + mov $r10 0x4ffc + sethi $r10 0x20000 + sub b32 $r11 $r10 0x500 + mov $r12 0xf + iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf + mov $r12 0xb + iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb + call #strand_wait + iowr I[$r10 + 0x000] $r14 // 0x93c = + mov $r12 0xa + iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa + call #strand_wait + ret + +// Initialise strand context data +// +// In : $r15 context base +// Out: $r15 context size (in bytes) +// +// Strandset(?) 3 hardcoded currently +// +strand_ctx_init: + trace_set(T_STRINIT) + call #strand_pre + mov $r14 3 + call #strand_set + mov $r10 0x46fc + sethi $r10 0x20000 + add b32 $r11 $r10 0x400 + iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 + mov $r12 1 + iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE + call #strand_wait + sub b32 $r12 $r0 1 + iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff + mov $r12 2 + iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT + call #strand_wait + call #strand_post + + // read the size of each strand, poke the context offset of + // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry + // about it later then. + mov $r8 0x880 + shl b32 $r8 6 + iord $r9 I[$r8 + 0x000] // STRANDS + add b32 $r8 0x2200 + shr b32 $r14 $r15 8 + ctx_init_strand_loop: + iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE + iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE + iord $r10 I[$r8 + 0x200] // STRAND_SIZE + shr b32 $r10 6 + add b32 $r10 1 + add b32 $r14 $r10 + add b32 $r8 4 + sub b32 $r9 1 + bra ne #ctx_init_strand_loop + + shl b32 $r14 8 + sub b32 $r15 $r14 $r15 + trace_clr(T_STRINIT) + ret +') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 2ba125b..7d38112 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -23,6 +23,8 @@ */ #include "nvc0.h" +#include "fuc/hubnve0.fuc.h" +#include "fuc/gpcnve0.fuc.h" /******************************************************************************* * Graphics object classes @@ -197,6 +199,7 @@ nve0_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; int ret, i; @@ -210,13 +213,15 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 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; + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", true)) { + 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) @@ -386,81 +391,131 @@ static int nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv) { u32 r000260; + int i; - /* load fuc microcode */ - 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); + if (priv->firmware) { + /* load fuc microcode */ + 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(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(priv, 0x409800); + + 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; + } - /* start both of them running */ - 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(priv, 0x409800); + 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(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(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(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(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(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(priv, 0x409614, 0x00000070); + nv_wr32(priv, 0x409614, 0x00000770); + nv_wr32(priv, 0x40802c, 0x00000001); + + if (priv->data == NULL) { + int ret = nve0_grctx_generate(priv); + if (ret) { + nv_error(priv, "failed to construct context\n"); + return ret; + } + } + + return 0; } - 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; + /* load HUB microcode */ + r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); + nv_wr32(priv, 0x4091c0, 0x01000000); + for (i = 0; i < sizeof(nve0_grhub_data) / 4; i++) + nv_wr32(priv, 0x4091c4, nve0_grhub_data[i]); + + nv_wr32(priv, 0x409180, 0x01000000); + for (i = 0; i < sizeof(nve0_grhub_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(priv, 0x409188, i >> 6); + nv_wr32(priv, 0x409184, nve0_grhub_code[i]); } - 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; + /* load GPC microcode */ + nv_wr32(priv, 0x41a1c0, 0x01000000); + for (i = 0; i < sizeof(nve0_grgpc_data) / 4; i++) + nv_wr32(priv, 0x41a1c4, nve0_grgpc_data[i]); + + nv_wr32(priv, 0x41a180, 0x01000000); + for (i = 0; i < sizeof(nve0_grgpc_code) / 4; i++) { + if ((i & 0x3f) == 0) + nv_wr32(priv, 0x41a188, i >> 6); + nv_wr32(priv, 0x41a184, nve0_grgpc_code[i]); } + nv_wr32(priv, 0x000260, r000260); - 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"); + /* start HUB ucode running, it'll init the GPCs */ + 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; } - nv_wr32(priv, 0x409614, 0x00000070); - nv_wr32(priv, 0x409614, 0x00000770); - nv_wr32(priv, 0x40802c, 0x00000001); - + priv->size = nv_rd32(priv, 0x409804); if (priv->data == NULL) { int ret = nve0_grctx_generate(priv); if (ret) { -- cgit v1.1 From ec6566f3230474131f6bd6d1503a7eeeda4657b9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Aug 2012 01:32:38 -0400 Subject: drm/nve0/gr: remove 0x404160 bashing from hub fuc Triggers PIBUS interrupts due to register not existing anymore, and as a result HUB_SET_CHAN times out. After this commit, our fuc loads and can accelerate at least fbcon, X, glxgears and OA on NVE4. NVE7 not tested as of yet. Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/engine/graph/fuc/hubnve0.fuc | 26 -- .../nouveau/core/engine/graph/fuc/hubnve0.fuc.h | 445 +++++++++------------ 2 files changed, 189 insertions(+), 282 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc index 816ae57..138eeaa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc @@ -468,28 +468,6 @@ ih: bclr $flags $p0 iret -// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done -ctx_4160s: - mov $r14 0x4160 - sethi $r14 0x400000 - mov $r15 1 - call #nv_wr32 - ctx_4160s_wait: - call #nv_rd32 - xbit $r15 $r15 4 - bra e #ctx_4160s_wait - ret - -// Without clearing again at end of xfer, some things cause PGRAPH -// to hang with STATUS=0x00000007 until it's cleared.. fbcon can -// still function with it set however... -ctx_4160c: - mov $r14 0x4160 - sethi $r14 0x400000 - clear b32 $r15 - call #nv_wr32 - ret - // Again, not real sure // // In: $r15 value to set 0x404170 to @@ -630,7 +608,6 @@ ctx_load: // In: $r2 channel address // ctx_chan: - call #ctx_4160s call #ctx_load mov $r10 12 // DONE_UNK12 call #wait_donez @@ -642,7 +619,6 @@ ctx_chan: iord $r2 I[$r1 + 0x000] or $r2 $r2 bra ne #ctx_chan_wait - call #ctx_4160c ret // Execute per-context state overrides list @@ -709,7 +685,6 @@ ctx_xfer: ctx_xfer_pre: mov $r15 0x10 call #ctx_86c - call #ctx_4160s bra not $p1 #ctx_xfer_exec ctx_xfer_pre_load: @@ -798,7 +773,6 @@ ctx_xfer: call #ctx_mmio_exec ctx_xfer_no_post_mmio: - call #ctx_4160c ctx_xfer_done: ret diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h index 05c3995..decf0c6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h @@ -553,7 +553,7 @@ uint32_t nve0_grhub_code[] = { 0xd00799f0, 0x32f40089, 0x0231f401, - 0x082921f5, + 0x07fb21f5, 0x085c87f1, 0xbd0684b6, 0x0799f094, @@ -563,7 +563,7 @@ uint32_t nve0_grhub_code[] = { 0x99f094bd, 0x0089d006, 0xf50131f4, - 0xf1082921, + 0xf107fb21, 0xb6085c87, 0x94bd0684, 0xd00699f0, @@ -572,7 +572,7 @@ uint32_t nve0_grhub_code[] = { 0xb920f931, 0x32f40212, 0x0232f401, - 0x082921f5, + 0x07fb21f5, 0x17f120fc, 0x14b60b00, 0x0012d006, @@ -582,7 +582,7 @@ uint32_t nve0_grhub_code[] = { 0x0131f40d, 0xf50232f4, /* 0x0537: chsw_done */ - 0xf1082921, + 0xf107fb21, 0xb60b0c17, 0x27f00614, 0x0012d001, @@ -594,7 +594,7 @@ uint32_t nve0_grhub_code[] = { 0xb0ff200e, 0x1bf401e4, 0x02f2b90d, - 0x07b521f5, + 0x078f21f5, /* 0x0567: main_not_ctx_chan */ 0xb0420ef4, 0x1bf402e4, @@ -604,7 +604,7 @@ uint32_t nve0_grhub_code[] = { 0x0089d007, 0xf40132f4, 0x21f50232, - 0x87f10829, + 0x87f107fb, 0x84b6085c, 0xf094bd06, 0x89d00799, @@ -653,267 +653,200 @@ uint32_t nve0_grhub_code[] = { 0xfe80fc90, 0x80fc0088, 0xf80032f4, -/* 0x0631: ctx_4160s */ - 0x60e7f101, +/* 0x0631: ctx_4170s */ + 0x70e7f101, 0x40e3f041, - 0xf401f7f0, -/* 0x063e: ctx_4160s_wait */ - 0x21f48d21, - 0x04ffc868, - 0xf8fa0bf4, -/* 0x0649: ctx_4160c */ - 0x60e7f100, - 0x40e3f041, - 0x21f4f4bd, -/* 0x0657: ctx_4170s */ - 0xf100f88d, - 0xf04170e7, - 0xf5f040e3, - 0x8d21f410, -/* 0x0666: ctx_4170w */ - 0xe7f100f8, - 0xe3f04170, - 0x6821f440, - 0xf410f4f0, - 0x00f8f31b, -/* 0x0678: ctx_redswitch */ - 0x0614e7f1, - 0xf106e4b6, - 0xd00270f7, - 0xf7f000ef, -/* 0x0689: ctx_redswitch_delay */ - 0x01f2b608, - 0xf1fd1bf4, - 0xd00770f7, - 0x00f800ef, -/* 0x0698: ctx_86c */ - 0x086ce7f1, - 0xd006e4b6, - 0xe7f100ef, - 0xe3f08a14, - 0x8d21f440, - 0xa86ce7f1, - 0xf441e3f0, + 0xf410f5f0, 0x00f88d21, -/* 0x06b8: ctx_load */ - 0x083c87f1, - 0xbd0684b6, - 0x0599f094, - 0xf00089d0, - 0x21f40ca7, - 0x2417f1c9, - 0x0614b60a, - 0xf10010d0, - 0xb60b0037, - 0x32d00634, - 0x0c17f140, - 0x0614b60a, - 0xd00747f0, - 0x14d00012, -/* 0x06f1: ctx_chan_wait_0 */ - 0x4014cf40, - 0xf41f44f0, - 0x32d0fa1b, - 0x000bfe00, - 0xb61f2af0, - 0x20b60424, - 0x3c87f102, - 0x0684b608, - 0x99f094bd, - 0x0089d008, - 0x0a0417f1, - 0xd00614b6, - 0x17f10012, - 0x14b60a20, - 0x0227f006, - 0x800023f1, - 0xf00012d0, - 0x27f11017, - 0x23f00300, - 0x0512fa02, - 0x87f103f8, - 0x84b6085c, +/* 0x0640: ctx_4170w */ + 0x4170e7f1, + 0xf440e3f0, + 0xf4f06821, + 0xf31bf410, +/* 0x0652: ctx_redswitch */ + 0xe7f100f8, + 0xe4b60614, + 0x70f7f106, + 0x00efd002, +/* 0x0663: ctx_redswitch_delay */ + 0xb608f7f0, + 0x1bf401f2, + 0x70f7f1fd, + 0x00efd007, +/* 0x0672: ctx_86c */ + 0xe7f100f8, + 0xe4b6086c, + 0x00efd006, + 0x8a14e7f1, + 0xf440e3f0, + 0xe7f18d21, + 0xe3f0a86c, + 0x8d21f441, +/* 0x0692: ctx_load */ + 0x87f100f8, + 0x84b6083c, 0xf094bd06, - 0x89d00899, - 0xc1019800, - 0x981814b6, - 0x25b6c002, - 0x0512fd08, - 0xf1160180, + 0x89d00599, + 0x0ca7f000, + 0xf1c921f4, + 0xb60a2417, + 0x10d00614, + 0x0037f100, + 0x0634b60b, + 0xf14032d0, + 0xb60a0c17, + 0x47f00614, + 0x0012d007, +/* 0x06cb: ctx_chan_wait_0 */ + 0xcf4014d0, + 0x44f04014, + 0xfa1bf41f, + 0xfe0032d0, + 0x2af0000b, + 0x0424b61f, + 0xf10220b6, 0xb6083c87, 0x94bd0684, - 0xd00999f0, - 0x27f10089, - 0x24b60a04, - 0x0021d006, - 0xf10127f0, - 0xb60a2017, - 0x12d00614, - 0x0017f100, - 0x0613f002, - 0xf80501fa, - 0x5c87f103, + 0xd00899f0, + 0x17f10089, + 0x14b60a04, + 0x0012d006, + 0x0a2017f1, + 0xf00614b6, + 0x23f10227, + 0x12d08000, + 0x1017f000, + 0x030027f1, + 0xfa0223f0, + 0x03f80512, + 0x085c87f1, + 0xbd0684b6, + 0x0899f094, + 0x980089d0, + 0x14b6c101, + 0xc0029818, + 0xfd0825b6, + 0x01800512, + 0x3c87f116, 0x0684b608, 0x99f094bd, 0x0089d009, - 0x085c87f1, - 0xbd0684b6, - 0x0599f094, - 0xf80089d0, -/* 0x07b5: ctx_chan */ - 0x3121f500, - 0xb821f506, - 0x0ca7f006, - 0xf1c921f4, - 0xb60a1017, - 0x27f00614, - 0x0012d005, -/* 0x07d0: ctx_chan_wait */ - 0xfd0012cf, - 0x1bf40522, - 0x4921f5fa, -/* 0x07df: ctx_mmio_exec */ - 0x9800f806, - 0x27f18103, - 0x24b60a04, - 0x0023d006, -/* 0x07ee: ctx_mmio_loop */ - 0x34c434bd, - 0x0f1bf4ff, - 0x030057f1, - 0xfa0653f0, - 0x03f80535, -/* 0x0800: ctx_mmio_pull */ - 0x98c04e98, - 0x21f4c14f, - 0x0830b68d, - 0xf40112b6, -/* 0x0812: ctx_mmio_done */ - 0x0398df1b, - 0x0023d016, - 0xf1800080, + 0x0a0427f1, + 0xd00624b6, + 0x27f00021, + 0x2017f101, + 0x0614b60a, + 0xf10012d0, 0xf0020017, 0x01fa0613, - 0xf803f806, -/* 0x0829: ctx_xfer */ - 0x0611f400, -/* 0x082f: ctx_xfer_pre */ - 0xf01102f4, - 0x21f510f7, - 0x21f50698, - 0x11f40631, -/* 0x083d: ctx_xfer_pre_load */ - 0x02f7f01c, - 0x065721f5, - 0x066621f5, - 0x067821f5, - 0x21f5f4bd, - 0x21f50657, -/* 0x0856: ctx_xfer_exec */ - 0x019806b8, - 0x1427f116, - 0x0624b604, - 0xf10020d0, - 0xf0a500e7, - 0x1fb941e3, - 0x8d21f402, - 0xf004e0b6, - 0x2cf001fc, - 0x0124b602, - 0xf405f2fd, - 0x17f18d21, - 0x13f04afc, - 0x0c27f002, - 0xf50012d0, - 0xf1020721, - 0xf047fc27, - 0x20d00223, - 0x012cf000, - 0xd00320b6, - 0xacf00012, - 0x06a5f001, - 0x9800b7f0, - 0x0d98140c, - 0x00e7f015, - 0x015c21f5, - 0xf508a7f0, - 0xf5010321, - 0xf4020721, - 0xa7f02201, - 0xc921f40c, - 0x0a1017f1, - 0xf00614b6, - 0x12d00527, -/* 0x08dd: ctx_xfer_post_save_wait */ - 0x0012cf00, - 0xf40522fd, - 0x02f4fa1b, -/* 0x08e9: ctx_xfer_post */ - 0x02f7f032, - 0x065721f5, + 0xf103f805, + 0xb6085c87, + 0x94bd0684, + 0xd00999f0, + 0x87f10089, + 0x84b6085c, + 0xf094bd06, + 0x89d00599, +/* 0x078f: ctx_chan */ + 0xf500f800, + 0xf0069221, + 0x21f40ca7, + 0x1017f1c9, + 0x0614b60a, + 0xd00527f0, +/* 0x07a6: ctx_chan_wait */ + 0x12cf0012, + 0x0522fd00, + 0xf8fa1bf4, +/* 0x07b1: ctx_mmio_exec */ + 0x81039800, + 0x0a0427f1, + 0xd00624b6, + 0x34bd0023, +/* 0x07c0: ctx_mmio_loop */ + 0xf4ff34c4, + 0x57f10f1b, + 0x53f00300, + 0x0535fa06, +/* 0x07d2: ctx_mmio_pull */ + 0x4e9803f8, + 0xc14f98c0, + 0xb68d21f4, + 0x12b60830, + 0xdf1bf401, +/* 0x07e4: ctx_mmio_done */ + 0xd0160398, + 0x00800023, + 0x0017f180, + 0x0613f002, + 0xf80601fa, +/* 0x07fb: ctx_xfer */ + 0xf400f803, + 0x02f40611, +/* 0x0801: ctx_xfer_pre */ + 0x10f7f00d, + 0x067221f5, +/* 0x080b: ctx_xfer_pre_load */ + 0xf01c11f4, + 0x21f502f7, + 0x21f50631, + 0x21f50640, + 0xf4bd0652, + 0x063121f5, + 0x069221f5, +/* 0x0824: ctx_xfer_exec */ + 0xf1160198, + 0xb6041427, + 0x20d00624, + 0x00e7f100, + 0x41e3f0a5, + 0xf4021fb9, + 0xe0b68d21, + 0x01fcf004, + 0xb6022cf0, + 0xf2fd0124, + 0x8d21f405, + 0x4afc17f1, + 0xf00213f0, + 0x12d00c27, + 0x0721f500, + 0xfc27f102, + 0x0223f047, + 0xf00020d0, + 0x20b6012c, + 0x0012d003, + 0xf001acf0, + 0xb7f006a5, + 0x140c9800, + 0xf0150d98, + 0x21f500e7, + 0xa7f0015c, + 0x0321f508, + 0x0721f501, + 0x2201f402, + 0xf40ca7f0, + 0x17f1c921, + 0x14b60a10, + 0x0527f006, +/* 0x08ab: ctx_xfer_post_save_wait */ + 0xcf0012d0, + 0x22fd0012, + 0xfa1bf405, +/* 0x08b7: ctx_xfer_post */ + 0xf02e02f4, + 0x21f502f7, + 0xf4bd0631, + 0x067221f5, + 0x022621f5, + 0x064021f5, 0x21f5f4bd, - 0x21f50698, - 0x21f50226, - 0xf4bd0666, - 0x065721f5, - 0x981011f4, - 0x11fd8001, - 0x070bf405, - 0x07df21f5, -/* 0x0914: ctx_xfer_no_post_mmio */ - 0x064921f5, -/* 0x0918: ctx_xfer_done */ - 0x000000f8, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x11f40631, + 0x80019810, + 0xf40511fd, + 0x21f5070b, +/* 0x08e2: ctx_xfer_no_post_mmio */ +/* 0x08e2: ctx_xfer_done */ + 0x00f807b1, 0x00000000, 0x00000000, 0x00000000, -- cgit v1.1 From e5bf578ce61aecd4612d16e60235c11ed5f92c0e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Aug 2012 01:52:28 -0400 Subject: drm/nve0/gr: enable use of our fuc by default Graphics acceleration is still disabled by default due to lingering issues that need to be solved. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 7d38112..539d4c7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -213,7 +213,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nve0_graph_cclass; nv_engine(priv)->sclass = nve0_graph_sclass; - if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", true)) { + 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) || -- cgit v1.1 From cd8c14b407d59ac4b8d324f5f9cdf223a2079c88 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 5 Sep 2012 12:19:26 +1000 Subject: drm/nvc0/ltcg: read LTS count at startup Not really sure how to confirm this 100%, but, the numbers match on all the traces I have for NVCx (2 LTS), NVD9 (1LTS) and NVEx (4LTS). Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c index 7c2840c..078a2b9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -26,6 +26,7 @@ struct nvc0_ltcg_priv { struct nouveau_ltcg base; + u32 subp_nr; }; static void @@ -49,7 +50,7 @@ nvc0_ltcg_intr(struct nouveau_subdev *subdev) units = nv_rd32(priv, 0x00017c); while (units) { u32 subp, unit = ffs(units) - 1; - for (subp = 0; subp < 2; subp++) + for (subp = 0; subp < priv->subp_nr; subp++) nvc0_ltcg_subp_isr(priv, unit, subp); units &= ~(1 << unit); } @@ -73,6 +74,7 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; + priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 24; nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ nv_subdev(priv)->intr = nvc0_ltcg_intr; -- cgit v1.1 From d66b9d9a6839129e11b94c90ec415b244b44414d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 6 Sep 2012 13:09:22 +1000 Subject: drm/nvc0/gr: rebuild fuc with latest envyas Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc | 8 +- .../nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h | 70 +++++++++++++++- .../drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc | 8 +- .../nouveau/core/engine/graph/fuc/hubnvc0.fuc.h | 93 +++++++++++++++++++++- 4 files changed, 167 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc index 15272be..b86cc60 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc @@ -24,7 +24,7 @@ */ /* To build: - * m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h + * m4 gpcnvc0.fuc | envyas -a -w -m fuc -V fuc3 -o gpcnvc0.fuc.h */ /* TODO @@ -33,7 +33,7 @@ */ .section #nvc0_grgpc_data -include(`nvc0_graph.fuc') +include(`nvc0.fuc') gpc_id: .b32 0 gpc_mmio_list_head: .b32 0 gpc_mmio_list_tail: .b32 0 @@ -209,11 +209,11 @@ nvd9_tpc_mmio_tail: .section #nvc0_grgpc_code bra #init define(`include_code') -include(`nvc0_graph.fuc') +include(`nvc0.fuc') // reports an exception to the host // -// In: $r15 error code (see nvc0_graph.fuc) +// In: $r15 error code (see nvc0.fuc) // error: push $r14 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h index 826a7b3..96050dd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h @@ -1,11 +1,19 @@ -static uint32_t nvc0_grgpc_data[] = { +uint32_t nvc0_grgpc_data[] = { +/* 0x0000: gpc_id */ 0x00000000, +/* 0x0004: gpc_mmio_list_head */ 0x00000000, +/* 0x0008: gpc_mmio_list_tail */ 0x00000000, +/* 0x000c: tpc_count */ 0x00000000, +/* 0x0010: tpc_mask */ 0x00000000, +/* 0x0014: tpc_mmio_list_head */ 0x00000000, +/* 0x0018: tpc_mmio_list_tail */ 0x00000000, +/* 0x001c: cmd_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -24,6 +32,7 @@ static uint32_t nvc0_grgpc_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0064: chipsets */ 0x000000c0, 0x012800c8, 0x01e40194, @@ -49,6 +58,7 @@ static uint32_t nvc0_grgpc_data[] = { 0x0194012c, 0x025401f8, 0x00000000, +/* 0x00c8: nvc0_gpc_mmio_head */ 0x00000380, 0x14000400, 0x20000450, @@ -73,7 +83,10 @@ static uint32_t nvc0_grgpc_data[] = { 0x00000c8c, 0x08001000, 0x00001014, +/* 0x0128: nvc0_gpc_mmio_tail */ 0x00000c6c, +/* 0x012c: nvc1_gpc_mmio_tail */ +/* 0x012c: nvd9_gpc_mmio_head */ 0x00000380, 0x04000400, 0x0800040c, @@ -100,6 +113,8 @@ static uint32_t nvc0_grgpc_data[] = { 0x00000c8c, 0x08001000, 0x00001014, +/* 0x0194: nvd9_gpc_mmio_tail */ +/* 0x0194: nvc0_tpc_mmio_head */ 0x00000018, 0x0000003c, 0x00000048, @@ -120,11 +135,16 @@ static uint32_t nvc0_grgpc_data[] = { 0x4c000644, 0x00000698, 0x04000750, +/* 0x01e4: nvc0_tpc_mmio_tail */ 0x00000758, 0x000002c4, 0x000006e0, +/* 0x01f0: nvcf_tpc_mmio_tail */ 0x000004bc, +/* 0x01f4: nvc3_tpc_mmio_tail */ 0x00000544, +/* 0x01f8: nvc1_tpc_mmio_tail */ +/* 0x01f8: nvd9_tpc_mmio_head */ 0x00000018, 0x0000003c, 0x00000048, @@ -150,14 +170,16 @@ static uint32_t nvc0_grgpc_data[] = { 0x08000750, }; -static uint32_t nvc0_grgpc_code[] = { +uint32_t nvc0_grgpc_code[] = { 0x03060ef5, +/* 0x0004: queue_put */ 0x9800d898, 0x86f001d9, 0x0489b808, 0xf00c1bf4, 0x21f502f7, 0x00f802ec, +/* 0x001c: queue_put_next */ 0xb60798c4, 0x8dbb0384, 0x0880b600, @@ -165,6 +187,7 @@ static uint32_t nvc0_grgpc_code[] = { 0x90b6018f, 0x0f94f001, 0xf801d980, +/* 0x0039: queue_get */ 0x0131f400, 0x9800d898, 0x89b801d9, @@ -176,37 +199,46 @@ static uint32_t nvc0_grgpc_code[] = { 0x80b6019f, 0x0f84f001, 0xf400d880, +/* 0x0066: queue_get_done */ 0x00f80132, +/* 0x0068: nv_rd32 */ 0x0728b7f1, 0xb906b4b6, 0xc9f002ec, 0x00bcd01f, +/* 0x0078: nv_rd32_wait */ 0xc800bccf, 0x1bf41fcc, 0x06a7f0fa, 0x010321f5, 0xf840bfcf, +/* 0x008d: nv_wr32 */ 0x28b7f100, 0x06b4b607, 0xb980bfd0, 0xc9f002ec, 0x1ec9f01f, +/* 0x00a3: nv_wr32_wait */ 0xcf00bcd0, 0xccc800bc, 0xfa1bf41f, +/* 0x00ae: watchdog_reset */ 0x87f100f8, 0x84b60430, 0x1ff9f006, 0xf8008fd0, +/* 0x00bd: watchdog_clear */ 0x3087f100, 0x0684b604, 0xf80080d0, +/* 0x00c9: wait_donez */ 0x3c87f100, 0x0684b608, 0x99f094bd, 0x0089d000, 0x081887f1, 0xd00684b6, +/* 0x00e2: wait_done_wait_donez */ 0x87f1008a, 0x84b60400, 0x0088cf06, @@ -215,6 +247,7 @@ static uint32_t nvc0_grgpc_code[] = { 0x84b6085c, 0xf094bd06, 0x89d00099, +/* 0x0103: wait_doneo */ 0xf100f800, 0xb6083c87, 0x94bd0684, @@ -222,6 +255,7 @@ static uint32_t nvc0_grgpc_code[] = { 0x87f10089, 0x84b60818, 0x008ad006, +/* 0x011c: wait_done_wait_doneo */ 0x040087f1, 0xcf0684b6, 0x8aff0088, @@ -230,6 +264,8 @@ static uint32_t nvc0_grgpc_code[] = { 0xbd0684b6, 0x0099f094, 0xf80089d0, +/* 0x013d: mmctx_size */ +/* 0x013f: nv_mmctx_size_loop */ 0x9894bd00, 0x85b600e8, 0x0180b61a, @@ -238,6 +274,7 @@ static uint32_t nvc0_grgpc_code[] = { 0x04efb804, 0xb9eb1bf4, 0x00f8029f, +/* 0x015c: mmctx_xfer */ 0x083c87f1, 0xbd0684b6, 0x0199f094, @@ -247,9 +284,11 @@ static uint32_t nvc0_grgpc_code[] = { 0xf405bbfd, 0x8bd0090b, 0x0099f000, +/* 0x0180: mmctx_base_disabled */ 0xf405eefd, 0x8ed00c0b, 0xc08fd080, +/* 0x018f: mmctx_multi_disabled */ 0xb70199f0, 0xc8010080, 0xb4b600ab, @@ -257,6 +296,8 @@ static uint32_t nvc0_grgpc_code[] = { 0xb601aec8, 0xbefd11e4, 0x008bd005, +/* 0x01a8: mmctx_exec_loop */ +/* 0x01a8: mmctx_wait_free */ 0xf0008ecf, 0x0bf41fe4, 0x00ce98fa, @@ -265,34 +306,42 @@ static uint32_t nvc0_grgpc_code[] = { 0x04cdb804, 0xc8e81bf4, 0x1bf402ab, +/* 0x01c9: mmctx_fini_wait */ 0x008bcf18, 0xb01fb4f0, 0x1bf410b4, 0x02a7f0f7, 0xf4c921f4, +/* 0x01de: mmctx_stop */ 0xabc81b0e, 0x10b4b600, 0xf00cb9f0, 0x8bd012b9, +/* 0x01ed: mmctx_stop_wait */ 0x008bcf00, 0xf412bbc8, +/* 0x01f6: mmctx_done */ 0x87f1fa1b, 0x84b6085c, 0xf094bd06, 0x89d00199, +/* 0x0207: strand_wait */ 0xf900f800, 0x02a7f0a0, 0xfcc921f4, +/* 0x0213: strand_pre */ 0xf100f8a0, 0xf04afc87, 0x97f00283, 0x0089d00c, 0x020721f5, +/* 0x0226: strand_post */ 0x87f100f8, 0x83f04afc, 0x0d97f002, 0xf50089d0, 0xf8020721, +/* 0x0239: strand_set */ 0xfca7f100, 0x02a3f04f, 0x0500aba2, @@ -303,6 +352,7 @@ static uint32_t nvc0_grgpc_code[] = { 0xf000aed0, 0xbcd00ac7, 0x0721f500, +/* 0x0263: strand_ctx_init */ 0xf100f802, 0xb6083c87, 0x94bd0684, @@ -325,6 +375,7 @@ static uint32_t nvc0_grgpc_code[] = { 0x0684b608, 0xb70089cf, 0x95220080, +/* 0x02ba: ctx_init_strand_loop */ 0x8ed008fe, 0x408ed000, 0xb6808acf, @@ -338,12 +389,14 @@ static uint32_t nvc0_grgpc_code[] = { 0x94bd0684, 0xd00399f0, 0x00f80089, +/* 0x02ec: error */ 0xe7f1e0f9, 0xe3f09814, 0x8d21f440, 0x041ce0b7, 0xf401f7f0, 0xe0fc8d21, +/* 0x0306: init */ 0x04bd00f8, 0xf10004fe, 0xf0120017, @@ -366,11 +419,13 @@ static uint32_t nvc0_grgpc_code[] = { 0x27f10002, 0x24b60800, 0x0022cf06, +/* 0x035f: init_find_chipset */ 0xb65817f0, 0x13980c10, 0x0432b800, 0xb00b0bf4, 0x1bf40034, +/* 0x0373: init_context */ 0xf100f8f1, 0xb6080027, 0x22cf0624, @@ -407,6 +462,7 @@ static uint32_t nvc0_grgpc_code[] = { 0x0010b740, 0xf024bd08, 0x12d01f29, +/* 0x0401: main */ 0x0031f400, 0xf00028f4, 0x21f41cd7, @@ -419,9 +475,11 @@ static uint32_t nvc0_grgpc_code[] = { 0xfe051efd, 0x21f50018, 0x0ef404c3, +/* 0x0431: main_not_ctx_xfer */ 0x10ef94d3, 0xf501f5f0, 0xf402ec21, +/* 0x043e: ih */ 0x80f9c60e, 0xf90188fe, 0xf990f980, @@ -436,30 +494,36 @@ static uint32_t nvc0_grgpc_code[] = { 0xb0b70421, 0xe7f00400, 0x00bed001, +/* 0x0474: ih_no_fifo */ 0xfc400ad0, 0xfce0fcf0, 0xfcb0fcd0, 0xfc90fca0, 0x0088fe80, 0x32f480fc, +/* 0x048f: hub_barrier_done */ 0xf001f800, 0x0e9801f7, 0x04febb00, 0x9418e7f1, 0xf440e3f0, 0x00f88d21, +/* 0x04a4: ctx_redswitch */ 0x0614e7f1, 0xf006e4b6, 0xefd020f7, 0x08f7f000, +/* 0x04b4: ctx_redswitch_delay */ 0xf401f2b6, 0xf7f1fd1b, 0xefd00a20, +/* 0x04c3: ctx_xfer */ 0xf100f800, 0xb60a0417, 0x1fd00614, 0x0711f400, 0x04a421f5, +/* 0x04d4: ctx_xfer_not_load */ 0x4afc17f1, 0xf00213f0, 0x12d00c27, @@ -489,11 +553,13 @@ static uint32_t nvc0_grgpc_code[] = { 0x5c21f508, 0x0721f501, 0x0601f402, +/* 0x054b: ctx_xfer_post */ 0xf11412f4, 0xf04afc17, 0x27f00213, 0x0012d00d, 0x020721f5, +/* 0x055c: ctx_xfer_done */ 0x048f21f5, 0x000000f8, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc index 98acddb..acfc457 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc @@ -24,11 +24,11 @@ */ /* To build: - * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h + * m4 hubnvc0.fuc | envyas -a -w -m fuc -V fuc3 -o hubnvc0.fuc.h */ .section #nvc0_grhub_data -include(`nvc0_graph.fuc') +include(`nvc0.fuc') gpc_count: .b32 0 rop_count: .b32 0 cmd_queue: queue_init @@ -161,11 +161,11 @@ xfer_data: .b32 0 .section #nvc0_grhub_code bra #init define(`include_code') -include(`nvc0_graph.fuc') +include(`nvc0.fuc') // reports an exception to the host // -// In: $r15 error code (see nvc0_graph.fuc) +// In: $r15 error code (see nvc0.fuc) // error: push $r14 diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index db0c0ee..85a8d55 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h @@ -1,6 +1,9 @@ -static uint32_t nvc0_grhub_data[] = { +uint32_t nvc0_grhub_data[] = { +/* 0x0000: gpc_count */ 0x00000000, +/* 0x0004: rop_count */ 0x00000000, +/* 0x0008: cmd_queue */ 0x00000000, 0x00000000, 0x00000000, @@ -19,9 +22,13 @@ static uint32_t nvc0_grhub_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0050: hub_mmio_list_head */ 0x00000000, +/* 0x0054: hub_mmio_list_tail */ 0x00000000, +/* 0x0058: ctx_current */ 0x00000000, +/* 0x005c: chipsets */ 0x000000c0, 0x013c00a0, 0x000000c1, @@ -39,6 +46,7 @@ static uint32_t nvc0_grhub_data[] = { 0x000000d9, 0x01dc0140, 0x00000000, +/* 0x00a0: nvc0_hub_mmio_head */ 0x0417e91c, 0x04400204, 0x28404004, @@ -78,7 +86,10 @@ static uint32_t nvc0_grhub_data[] = { 0x08408800, 0x0c408900, 0x00408980, +/* 0x013c: nvc0_hub_mmio_tail */ 0x044064c0, +/* 0x0140: nvc1_hub_mmio_tail */ +/* 0x0140: nvd9_hub_mmio_head */ 0x0417e91c, 0x04400204, 0x24404004, @@ -118,6 +129,7 @@ static uint32_t nvc0_grhub_data[] = { 0x08408800, 0x0c408900, 0x00408980, +/* 0x01dc: nvd9_hub_mmio_tail */ 0x00000000, 0x00000000, 0x00000000, @@ -127,7 +139,10 @@ static uint32_t nvc0_grhub_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0200: chan_data */ +/* 0x0200: chan_mmio_count */ 0x00000000, +/* 0x0204: chan_mmio_address */ 0x00000000, 0x00000000, 0x00000000, @@ -191,17 +206,20 @@ static uint32_t nvc0_grhub_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0300: xfer_data */ 0x00000000, }; -static uint32_t nvc0_grhub_code[] = { +uint32_t nvc0_grhub_code[] = { 0x03090ef5, +/* 0x0004: queue_put */ 0x9800d898, 0x86f001d9, 0x0489b808, 0xf00c1bf4, 0x21f502f7, 0x00f802ec, +/* 0x001c: queue_put_next */ 0xb60798c4, 0x8dbb0384, 0x0880b600, @@ -209,6 +227,7 @@ static uint32_t nvc0_grhub_code[] = { 0x90b6018f, 0x0f94f001, 0xf801d980, +/* 0x0039: queue_get */ 0x0131f400, 0x9800d898, 0x89b801d9, @@ -220,37 +239,46 @@ static uint32_t nvc0_grhub_code[] = { 0x80b6019f, 0x0f84f001, 0xf400d880, +/* 0x0066: queue_get_done */ 0x00f80132, +/* 0x0068: nv_rd32 */ 0x0728b7f1, 0xb906b4b6, 0xc9f002ec, 0x00bcd01f, +/* 0x0078: nv_rd32_wait */ 0xc800bccf, 0x1bf41fcc, 0x06a7f0fa, 0x010321f5, 0xf840bfcf, +/* 0x008d: nv_wr32 */ 0x28b7f100, 0x06b4b607, 0xb980bfd0, 0xc9f002ec, 0x1ec9f01f, +/* 0x00a3: nv_wr32_wait */ 0xcf00bcd0, 0xccc800bc, 0xfa1bf41f, +/* 0x00ae: watchdog_reset */ 0x87f100f8, 0x84b60430, 0x1ff9f006, 0xf8008fd0, +/* 0x00bd: watchdog_clear */ 0x3087f100, 0x0684b604, 0xf80080d0, +/* 0x00c9: wait_donez */ 0x3c87f100, 0x0684b608, 0x99f094bd, 0x0089d000, 0x081887f1, 0xd00684b6, +/* 0x00e2: wait_done_wait_donez */ 0x87f1008a, 0x84b60400, 0x0088cf06, @@ -259,6 +287,7 @@ static uint32_t nvc0_grhub_code[] = { 0x84b6085c, 0xf094bd06, 0x89d00099, +/* 0x0103: wait_doneo */ 0xf100f800, 0xb6083c87, 0x94bd0684, @@ -266,6 +295,7 @@ static uint32_t nvc0_grhub_code[] = { 0x87f10089, 0x84b60818, 0x008ad006, +/* 0x011c: wait_done_wait_doneo */ 0x040087f1, 0xcf0684b6, 0x8aff0088, @@ -274,6 +304,8 @@ static uint32_t nvc0_grhub_code[] = { 0xbd0684b6, 0x0099f094, 0xf80089d0, +/* 0x013d: mmctx_size */ +/* 0x013f: nv_mmctx_size_loop */ 0x9894bd00, 0x85b600e8, 0x0180b61a, @@ -282,6 +314,7 @@ static uint32_t nvc0_grhub_code[] = { 0x04efb804, 0xb9eb1bf4, 0x00f8029f, +/* 0x015c: mmctx_xfer */ 0x083c87f1, 0xbd0684b6, 0x0199f094, @@ -291,9 +324,11 @@ static uint32_t nvc0_grhub_code[] = { 0xf405bbfd, 0x8bd0090b, 0x0099f000, +/* 0x0180: mmctx_base_disabled */ 0xf405eefd, 0x8ed00c0b, 0xc08fd080, +/* 0x018f: mmctx_multi_disabled */ 0xb70199f0, 0xc8010080, 0xb4b600ab, @@ -301,6 +336,8 @@ static uint32_t nvc0_grhub_code[] = { 0xb601aec8, 0xbefd11e4, 0x008bd005, +/* 0x01a8: mmctx_exec_loop */ +/* 0x01a8: mmctx_wait_free */ 0xf0008ecf, 0x0bf41fe4, 0x00ce98fa, @@ -309,34 +346,42 @@ static uint32_t nvc0_grhub_code[] = { 0x04cdb804, 0xc8e81bf4, 0x1bf402ab, +/* 0x01c9: mmctx_fini_wait */ 0x008bcf18, 0xb01fb4f0, 0x1bf410b4, 0x02a7f0f7, 0xf4c921f4, +/* 0x01de: mmctx_stop */ 0xabc81b0e, 0x10b4b600, 0xf00cb9f0, 0x8bd012b9, +/* 0x01ed: mmctx_stop_wait */ 0x008bcf00, 0xf412bbc8, +/* 0x01f6: mmctx_done */ 0x87f1fa1b, 0x84b6085c, 0xf094bd06, 0x89d00199, +/* 0x0207: strand_wait */ 0xf900f800, 0x02a7f0a0, 0xfcc921f4, +/* 0x0213: strand_pre */ 0xf100f8a0, 0xf04afc87, 0x97f00283, 0x0089d00c, 0x020721f5, +/* 0x0226: strand_post */ 0x87f100f8, 0x83f04afc, 0x0d97f002, 0xf50089d0, 0xf8020721, +/* 0x0239: strand_set */ 0xfca7f100, 0x02a3f04f, 0x0500aba2, @@ -347,6 +392,7 @@ static uint32_t nvc0_grhub_code[] = { 0xf000aed0, 0xbcd00ac7, 0x0721f500, +/* 0x0263: strand_ctx_init */ 0xf100f802, 0xb6083c87, 0x94bd0684, @@ -369,6 +415,7 @@ static uint32_t nvc0_grhub_code[] = { 0x0684b608, 0xb70089cf, 0x95220080, +/* 0x02ba: ctx_init_strand_loop */ 0x8ed008fe, 0x408ed000, 0xb6808acf, @@ -382,6 +429,7 @@ static uint32_t nvc0_grhub_code[] = { 0x94bd0684, 0xd00399f0, 0x00f80089, +/* 0x02ec: error */ 0xe7f1e0f9, 0xe4b60814, 0x00efd006, @@ -389,6 +437,7 @@ static uint32_t nvc0_grhub_code[] = { 0xf006e4b6, 0xefd001f7, 0xf8e0fc00, +/* 0x0309: init */ 0xfe04bd00, 0x07fe0004, 0x0017f100, @@ -429,11 +478,13 @@ static uint32_t nvc0_grhub_code[] = { 0x080027f1, 0xcf0624b6, 0xf7f00022, +/* 0x03a9: init_find_chipset */ 0x08f0b654, 0xb800f398, 0x0bf40432, 0x0034b00b, 0xf8f11bf4, +/* 0x03bd: init_context */ 0x0017f100, 0x02fe5801, 0xf003ff58, @@ -454,6 +505,7 @@ static uint32_t nvc0_grhub_code[] = { 0x001fbb02, 0xf1000398, 0xf0200047, +/* 0x040e: init_gpc */ 0x4ea05043, 0x1fb90804, 0x8d21f402, @@ -467,6 +519,7 @@ static uint32_t nvc0_grhub_code[] = { 0xf7f00100, 0x8d21f402, 0x08004ea0, +/* 0x0440: init_gpc_wait */ 0xc86821f4, 0x0bf41fff, 0x044ea0fa, @@ -479,6 +532,7 @@ static uint32_t nvc0_grhub_code[] = { 0xb74021d0, 0xbd080020, 0x1f19f014, +/* 0x0473: main */ 0xf40021d0, 0x28f40031, 0x08d7f000, @@ -517,6 +571,7 @@ static uint32_t nvc0_grhub_code[] = { 0x94bd0684, 0xd00699f0, 0x0ef40089, +/* 0x0509: chsw_prev_no_next */ 0xb920f931, 0x32f40212, 0x0232f401, @@ -524,10 +579,12 @@ static uint32_t nvc0_grhub_code[] = { 0x17f120fc, 0x14b60b00, 0x0012d006, +/* 0x0527: chsw_no_prev */ 0xc8130ef4, 0x0bf41f23, 0x0131f40d, 0xf50232f4, +/* 0x0537: chsw_done */ 0xf1082921, 0xb60b0c17, 0x27f00614, @@ -536,10 +593,12 @@ static uint32_t nvc0_grhub_code[] = { 0xbd0684b6, 0x0499f094, 0xf50089d0, +/* 0x0557: main_not_ctx_switch */ 0xb0ff200e, 0x1bf401e4, 0x02f2b90d, 0x07b521f5, +/* 0x0567: main_not_ctx_chan */ 0xb0420ef4, 0x1bf402e4, 0x3c87f12e, @@ -553,14 +612,17 @@ static uint32_t nvc0_grhub_code[] = { 0xf094bd06, 0x89d00799, 0x110ef400, +/* 0x0598: main_not_ctx_save */ 0xf010ef94, 0x21f501f5, 0x0ef502ec, +/* 0x05a6: main_done */ 0x17f1fed1, 0x14b60820, 0xf024bd06, 0x12d01f29, 0xbe0ef500, +/* 0x05b9: ih */ 0xfe80f9fe, 0x80f90188, 0xa0f990f9, @@ -574,16 +636,19 @@ static uint32_t nvc0_grhub_code[] = { 0x21f400bf, 0x00b0b704, 0x01e7f004, +/* 0x05ef: ih_no_fifo */ 0xe400bed0, 0xf40100ab, 0xd7f00d0b, 0x01e7f108, 0x0421f440, +/* 0x0600: ih_no_ctxsw */ 0x0104b7f1, 0xabffb0bd, 0x0d0bf4b4, 0x0c1ca7f1, 0xd006a4b6, +/* 0x0616: ih_no_other */ 0x0ad000ab, 0xfcf0fc40, 0xfcd0fce0, @@ -591,32 +656,40 @@ static uint32_t nvc0_grhub_code[] = { 0xfe80fc90, 0x80fc0088, 0xf80032f4, +/* 0x0631: ctx_4160s */ 0x60e7f101, 0x40e3f041, 0xf401f7f0, +/* 0x063e: ctx_4160s_wait */ 0x21f48d21, 0x04ffc868, 0xf8fa0bf4, +/* 0x0649: ctx_4160c */ 0x60e7f100, 0x40e3f041, 0x21f4f4bd, +/* 0x0657: ctx_4170s */ 0xf100f88d, 0xf04170e7, 0xf5f040e3, 0x8d21f410, +/* 0x0666: ctx_4170w */ 0xe7f100f8, 0xe3f04170, 0x6821f440, 0xf410f4f0, 0x00f8f31b, +/* 0x0678: ctx_redswitch */ 0x0614e7f1, 0xf106e4b6, 0xd00270f7, 0xf7f000ef, +/* 0x0689: ctx_redswitch_delay */ 0x01f2b608, 0xf1fd1bf4, 0xd00770f7, 0x00f800ef, +/* 0x0698: ctx_86c */ 0x086ce7f1, 0xd006e4b6, 0xe7f100ef, @@ -625,6 +698,7 @@ static uint32_t nvc0_grhub_code[] = { 0xa86ce7f1, 0xf441e3f0, 0x00f88d21, +/* 0x06b8: ctx_load */ 0x083c87f1, 0xbd0684b6, 0x0599f094, @@ -639,6 +713,7 @@ static uint32_t nvc0_grhub_code[] = { 0x0614b60a, 0xd00747f0, 0x14d00012, +/* 0x06f1: ctx_chan_wait_0 */ 0x4014cf40, 0xf41f44f0, 0x32d0fa1b, @@ -688,6 +763,7 @@ static uint32_t nvc0_grhub_code[] = { 0xbd0684b6, 0x0599f094, 0xf80089d0, +/* 0x07b5: ctx_chan */ 0x3121f500, 0xb821f506, 0x0ca7f006, @@ -695,39 +771,48 @@ static uint32_t nvc0_grhub_code[] = { 0xb60a1017, 0x27f00614, 0x0012d005, +/* 0x07d0: ctx_chan_wait */ 0xfd0012cf, 0x1bf40522, 0x4921f5fa, +/* 0x07df: ctx_mmio_exec */ 0x9800f806, 0x27f18103, 0x24b60a04, 0x0023d006, +/* 0x07ee: ctx_mmio_loop */ 0x34c434bd, 0x0f1bf4ff, 0x030057f1, 0xfa0653f0, 0x03f80535, +/* 0x0800: ctx_mmio_pull */ 0x98c04e98, 0x21f4c14f, 0x0830b68d, 0xf40112b6, +/* 0x0812: ctx_mmio_done */ 0x0398df1b, 0x0023d016, 0xf1800080, 0xf0020017, 0x01fa0613, 0xf803f806, +/* 0x0829: ctx_xfer */ 0x0611f400, +/* 0x082f: ctx_xfer_pre */ 0xf01102f4, 0x21f510f7, 0x21f50698, 0x11f40631, +/* 0x083d: ctx_xfer_pre_load */ 0x02f7f01c, 0x065721f5, 0x066621f5, 0x067821f5, 0x21f5f4bd, 0x21f50657, +/* 0x0856: ctx_xfer_exec */ 0x019806b8, 0x1427f116, 0x0624b604, @@ -762,9 +847,11 @@ static uint32_t nvc0_grhub_code[] = { 0x0a1017f1, 0xf00614b6, 0x12d00527, +/* 0x08dd: ctx_xfer_post_save_wait */ 0x0012cf00, 0xf40522fd, 0x02f4fa1b, +/* 0x08e9: ctx_xfer_post */ 0x02f7f032, 0x065721f5, 0x21f5f4bd, @@ -776,7 +863,9 @@ static uint32_t nvc0_grhub_code[] = { 0x11fd8001, 0x070bf405, 0x07df21f5, +/* 0x0914: ctx_xfer_no_post_mmio */ 0x064921f5, +/* 0x0918: ctx_xfer_done */ 0x000000f8, 0x00000000, 0x00000000, -- cgit v1.1 From f73221e4aa766a58b784729968159013cc73459d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 6 Sep 2012 01:03:47 -0400 Subject: drm/nvc0/gr: implement initial trap handler Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 192 ++++++++++++++++++++++- 1 file changed, 188 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index f002e7e..c62f2d0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -224,6 +224,192 @@ nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) } static void +nvc0_graph_trap_tpc(struct nvc0_graph_priv *priv, int gpc, int tpc) +{ + u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0508)); + + if (stat & 0x00000001) { + u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0224)); + nv_error(priv, "GPC%d/TPC%d/TEX: 0x%08x\n", gpc, tpc, trap); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000001); + stat &= ~0x00000001; + } + + if (stat & 0x00000002) { + u32 trap0 = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0644)); + u32 trap1 = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x064c)); + nv_error(priv, "GPC%d/TPC%d/MP: 0x%08x 0x%08x\n", + gpc, tpc, trap0, trap1); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0644), 0x001ffffe); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x064c), 0x0000000f); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000002); + stat &= ~0x00000002; + } + + if (stat & 0x00000004) { + u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0084)); + nv_error(priv, "GPC%d/TPC%d/POLY: 0x%08x\n", gpc, tpc, trap); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000004); + stat &= ~0x00000004; + } + + if (stat & 0x00000008) { + u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x048c)); + nv_error(priv, "GPC%d/TPC%d/L1C: 0x%08x\n", gpc, tpc, trap); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000008); + stat &= ~0x00000008; + } + + if (stat) { + nv_error(priv, "GPC%d/TPC%d/0x%08x: unknown\n", gpc, tpc, stat); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), stat); + } +} + +static void +nvc0_graph_trap_gpc(struct nvc0_graph_priv *priv, int gpc) +{ + u32 stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90)); + int tpc; + + if (stat & 0x00000001) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0420)); + nv_error(priv, "GPC%d/PROP: 0x%08x\n", gpc, trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000001); + stat &= ~0x00000001; + } + + if (stat & 0x00000002) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900)); + nv_error(priv, "GPC%d/ZCULL: 0x%08x\n", gpc, trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000002); + stat &= ~0x00000002; + } + + if (stat & 0x00000004) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028)); + nv_error(priv, "GPC%d/CCACHE: 0x%08x\n", gpc, trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000004); + stat &= ~0x00000004; + } + + if (stat & 0x00000008) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824)); + nv_error(priv, "GPC%d/ESETUP: 0x%08x\n", gpc, trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000008); + stat &= ~0x00000009; + } + + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + u32 mask = 0x00010000 << tpc; + if (stat & mask) { + nvc0_graph_trap_tpc(priv, gpc, tpc); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), mask); + stat &= ~mask; + } + } + + if (stat) { + nv_error(priv, "GPC%d/0x%08x: unknown\n", gpc, stat); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), stat); + } +} + +static void +nvc0_graph_trap_intr(struct nvc0_graph_priv *priv) +{ + u32 trap = nv_rd32(priv, 0x400108); + int rop, gpc; + + if (trap & 0x00000001) { + u32 stat = nv_rd32(priv, 0x404000); + nv_error(priv, "DISPATCH 0x%08x\n", stat); + nv_wr32(priv, 0x404000, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000001); + trap &= ~0x00000001; + } + + if (trap & 0x00000002) { + u32 stat = nv_rd32(priv, 0x404600); + nv_error(priv, "M2MF 0x%08x\n", stat); + nv_wr32(priv, 0x404600, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000002); + trap &= ~0x00000002; + } + + if (trap & 0x00000008) { + u32 stat = nv_rd32(priv, 0x408030); + nv_error(priv, "CCACHE 0x%08x\n", stat); + nv_wr32(priv, 0x408030, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000008); + trap &= ~0x00000008; + } + + if (trap & 0x00000010) { + u32 stat = nv_rd32(priv, 0x405840); + nv_error(priv, "SHADER 0x%08x\n", stat); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000010); + trap &= ~0x00000010; + } + + if (trap & 0x00000040) { + u32 stat = nv_rd32(priv, 0x40601c); + nv_error(priv, "UNK6 0x%08x\n", stat); + nv_wr32(priv, 0x40601c, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000040); + trap &= ~0x00000040; + } + + if (trap & 0x00000080) { + u32 stat = nv_rd32(priv, 0x404490); + nv_error(priv, "MACRO 0x%08x\n", stat); + nv_wr32(priv, 0x404490, 0xc0000000); + nv_wr32(priv, 0x400108, 0x00000080); + trap &= ~0x00000080; + } + + if (trap & 0x01000000) { + u32 stat = nv_rd32(priv, 0x400118); + for (gpc = 0; stat && gpc < priv->gpc_nr; gpc++) { + u32 mask = 0x00000001 << gpc; + if (stat & mask) { + nvc0_graph_trap_gpc(priv, gpc); + nv_wr32(priv, 0x400118, mask); + stat &= ~mask; + } + } + nv_wr32(priv, 0x400108, 0x01000000); + trap &= ~0x01000000; + } + + 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 0x%08x 0x%08x\n", + rop, 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 UNHANDLED 0x%08x\n", trap); + nv_wr32(priv, 0x400108, trap); + } +} + +static void nvc0_graph_intr(struct nouveau_subdev *subdev) { struct nouveau_fifo *pfifo = nouveau_fifo(subdev); @@ -276,10 +462,8 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) } if (stat & 0x00200000) { - u32 trap = nv_rd32(priv, 0x400108); - nv_error(priv, "TRAP ch %d [0x%010llx] status 0x%08x\n", - chid, inst << 12, trap); - nv_wr32(priv, 0x400108, trap); + nv_error(priv, "TRAP ch %d [0x%010llx]\n", chid, inst << 12); + nvc0_graph_trap_intr(priv); nv_wr32(priv, 0x400100, 0x00200000); stat &= ~0x00200000; } -- cgit v1.1 From b3ccd34ded3e730bba33cd4bd4b7ab78b4a0bb03 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 6 Sep 2012 20:26:38 -0400 Subject: drm/nvc0/fifo: re-bash PBUS regs after vm-fault to BARs/PEEPHOLE Seems to be required to "re-arm" the engines after a vm fault. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 2dd6812..6f21be6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -389,12 +389,26 @@ static const struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { static void nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) { - u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10)); - u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10)); - u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); - u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); + u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10)); + u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10)); + u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); + u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; + switch (unit) { + case 3: /* PEEPHOLE */ + nv_mask(priv, 0x001718, 0x00000000, 0x00000000); + break; + case 4: /* BAR1 */ + nv_mask(priv, 0x001704, 0x00000000, 0x00000000); + break; + case 5: /* BAR3 */ + nv_mask(priv, 0x001714, 0x00000000, 0x00000000); + break; + default: + break; + } + nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); -- cgit v1.1 From fa6df8c163ddf1fba658059695ab9587f344712c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 12 Sep 2012 13:09:23 +1000 Subject: drm/nouveau/core: have client-id be a string, rather than an integer Can be somewhat more informative that way... Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/client.c | 6 +++--- drivers/gpu/drm/nouveau/core/core/printk.c | 4 ++-- drivers/gpu/drm/nouveau/core/include/core/client.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index e190f18..c617f04 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c @@ -46,8 +46,8 @@ nouveau_client_oclass = { }; int -nouveau_client_create_(u32 name, u64 devname, const char *cfg, const char *dbg, - int length, void **pobject) +nouveau_client_create_(const char *name, u64 devname, const char *cfg, + const char *dbg, int length, void **pobject) { struct nouveau_object *device; struct nouveau_client *client; @@ -75,7 +75,7 @@ nouveau_client_create_(u32 name, u64 devname, const char *cfg, const char *dbg, atomic_set(&nv_object(client)->usecount, 2); nouveau_object_ref(device, &client->device); - client->handle = name; + snprintf(client->name, sizeof(client->name), "%s", name); client->debug = nouveau_dbgopt(dbg, "CLIENT"); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/core/printk.c b/drivers/gpu/drm/nouveau/core/core/printk.c index 134dd6d..6161eaf 100644 --- a/drivers/gpu/drm/nouveau/core/core/printk.c +++ b/drivers/gpu/drm/nouveau/core/core/printk.c @@ -62,8 +62,8 @@ nv_printk_(struct nouveau_object *object, const char *pfx, int level, if (level > nv_client(object)->debug) return; - snprintf(mfmt, sizeof(mfmt), "%snouveau %c[%8d] %s", pfx, - name[level], nv_client(object)->handle, fmt); + snprintf(mfmt, sizeof(mfmt), "%snouveau %c[%8s] %s", pfx, + name[level], nv_client(object)->name, fmt); } else { snprintf(mfmt, sizeof(mfmt), "%snouveau: %s", pfx, fmt); } diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h index f5f45f2..0193532 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h @@ -7,7 +7,7 @@ struct nouveau_client { struct nouveau_namedb base; struct nouveau_handle *root; struct nouveau_object *device; - u32 handle; + char name[16]; u32 debug; struct nouveau_vm *vm; }; @@ -34,7 +34,7 @@ nouveau_client(void *obj) #define nouveau_client_create(n,c,oc,od,d) \ nouveau_client_create_((n), (c), (oc), (od), sizeof(**d), (void **)d) -int nouveau_client_create_(u32 name, u64 device, const char *cfg, +int nouveau_client_create_(const char *name, u64 device, const char *cfg, const char *dbg, int, void **); int nouveau_client_init(struct nouveau_client *); int nouveau_client_fini(struct nouveau_client *, bool suspend); -- cgit v1.1 From acac7bdba61226502a230db9245ca426a67102a9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 12 Sep 2012 15:55:01 +1000 Subject: drm/nouveau/bios: check that fixed tvdac gpio data is valid before using it Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index 718267d..1ae23b3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c @@ -100,13 +100,17 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, /* DCB 2.2, fixed TVDAC GPIO data */ if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len)) && ver >= 0x22) { if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct dcb_gpio_func) { - .func = DCB_GPIO_TVDAC0, - .line = nv_ro08(bios, entry - 4) >> 4, - .log[0] = !!(nv_ro08(bios, entry - 5) & 2), - .log[1] = !(nv_ro08(bios, entry - 5) & 2), - }; - return 0; + u8 conf = nv_ro08(bios, entry - 5); + u8 addr = nv_ro08(bios, entry - 4); + if (conf & 0x01) { + *gpio = (struct dcb_gpio_func) { + .func = DCB_GPIO_TVDAC0, + .line = addr >> 4, + .log[0] = !!(conf & 0x02), + .log[1] = !(conf & 0x02), + }; + return 0; + } } } -- cgit v1.1 From e36199980b51f081671d76de7b7b8f94fe1e0ae3 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Sat, 12 May 2012 15:28:51 +0200 Subject: drm/nouveau/gpio: expose the PWM/TOGGLE parameter found in the gpio vbios table Signed-off-by: Martin Peres Reviewed-by: Ben Skeggs Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h | 7 +++++++ drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | 3 +++ 2 files changed, 10 insertions(+) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index e9789cf..2bf1780 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h @@ -16,6 +16,13 @@ struct dcb_gpio_func { u8 func; u8 line; u8 log[2]; + + /* so far, "param" seems to only have an influence on PWM-related + * GPIOs such as FAN_CONTROL and PANEL_BACKLIGHT_LEVEL. + * if param equals 1, hardware PWM is available + * if param equals 0, the host should toggle the GPIO itself + */ + u8 param; }; u16 dcb_gpio_table(struct nouveau_bios *); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index 1ae23b3..4c9f1e5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c @@ -71,6 +71,7 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, .func = (data & 0x07e0) >> 5, .log[0] = (data & 0x1800) >> 11, .log[1] = (data & 0x6000) >> 13, + .param = !!(data & 0x8000), }; } else if (ver < 0x41) { @@ -80,6 +81,7 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, .func = (data & 0x0000ff00) >> 8, .log[0] = (data & 0x18000000) >> 27, .log[1] = (data & 0x60000000) >> 29, + .param = !!(data & 0x80000000), }; } else { u32 data = nv_ro32(bios, entry + 0); @@ -89,6 +91,7 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, .func = (data & 0x0000ff00) >> 8, .log[0] = (data1 & 0x30) >> 4, .log[1] = (data1 & 0xc0) >> 6, + .param = !!(data & 0x80000000), }; } -- cgit v1.1 From 7d70e9c1c69a5d22588ff5977249ac944d7cdfb0 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 16 Aug 2012 11:00:55 +0200 Subject: drm/nouveau/therm: rework thermal table parsing As an accident, it should also fix temperature reading on nv4x. v2: introduce nvbios_therm_entry as advised by darktama Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/include/subdev/bios/therm.h | 46 ++++++ drivers/gpu/drm/nouveau/core/subdev/bios/therm.c | 177 +++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/therm.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h new file mode 100644 index 0000000..a2c4296 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h @@ -0,0 +1,46 @@ +#ifndef __NVBIOS_THERM_H__ +#define __NVBIOS_THERM_H__ + +struct nouveau_bios; + +struct nvbios_therm_threshold { + u8 temp; + u8 hysteresis; +}; + +struct nvbios_therm_sensor { + /* diode */ + s16 slope_mult; + s16 slope_div; + s16 offset_num; + s16 offset_den; + s8 offset_constant; + + /* thresholds */ + struct nvbios_therm_threshold thrs_fan_boost; + struct nvbios_therm_threshold thrs_down_clock; + struct nvbios_therm_threshold thrs_critical; + struct nvbios_therm_threshold thrs_shutdown; +}; + +struct nvbios_therm_fan { + u16 pwm_freq; + + u8 min_duty; + u8 max_duty; +}; + +enum nvbios_therm_domain { + NVBIOS_THERM_DOMAIN_CORE, + NVBIOS_THERM_DOMAIN_AMBIENT, +}; + +int +nvbios_therm_sensor_parse(struct nouveau_bios *, enum nvbios_therm_domain, + struct nvbios_therm_sensor *); + +int +nvbios_therm_fan_parse(struct nouveau_bios *, struct nvbios_therm_fan *); + + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c new file mode 100644 index 0000000..862a08a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c @@ -0,0 +1,177 @@ +/* + * Copyright 2012 Nouveau Community + * + * 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 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 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: Martin Peres + */ + +#include +#include +#include + +static u16 +therm_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) +{ + struct bit_entry bit_P; + u16 therm = 0; + + if (!bit_entry(bios, 'P', &bit_P)) { + if (bit_P.version == 1) + therm = nv_ro16(bios, bit_P.offset + 12); + else if (bit_P.version == 2) + therm = nv_ro16(bios, bit_P.offset + 16); + else + nv_error(bios, + "unknown offset for thermal in BIT P %d\n", + bit_P.version); + } + + /* exit now if we haven't found the thermal table */ + if (!therm) + return 0x0000; + + *ver = nv_ro08(bios, therm + 0); + *hdr = nv_ro08(bios, therm + 1); + *len = nv_ro08(bios, therm + 2); + *cnt = nv_ro08(bios, therm + 3); + + return therm + nv_ro08(bios, therm + 1); +} + +u16 +nvbios_therm_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 therm = therm_table(bios, ver, &hdr, len, &cnt); + if (therm && idx < cnt) + return therm + idx * *len; + return 0x0000; +} + +int +nvbios_therm_sensor_parse(struct nouveau_bios *bios, + enum nvbios_therm_domain domain, + struct nvbios_therm_sensor *sensor) +{ + s8 thrs_section, sensor_section, offset; + u8 ver, len, i; + u16 entry; + + /* we only support the core domain for now */ + if (domain != NVBIOS_THERM_DOMAIN_CORE) + return -EINVAL; + + /* Read the entries from the table */ + thrs_section = 0; + sensor_section = -1; + i = 0; + while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { + s16 value = nv_ro16(bios, entry + 1); + + switch (nv_ro08(bios, entry + 0)) { + case 0x0: + thrs_section = value; + if (value > 0) + return 0; /* we do not try to support ambient */ + break; + case 0x01: + sensor_section++; + if (sensor_section == 0) { + offset = ((s8) nv_ro08(bios, entry + 2)) / 2; + sensor->offset_constant = offset; + } + break; + + case 0x04: + if (thrs_section == 0) { + sensor->thrs_critical.temp = (value & 0xff0) >> 4; + sensor->thrs_critical.hysteresis = value & 0xf; + } + break; + + case 0x07: + if (thrs_section == 0) { + sensor->thrs_down_clock.temp = (value & 0xff0) >> 4; + sensor->thrs_down_clock.hysteresis = value & 0xf; + } + break; + + case 0x08: + if (thrs_section == 0) { + sensor->thrs_fan_boost.temp = (value & 0xff0) >> 4; + sensor->thrs_fan_boost.hysteresis = value & 0xf; + } + break; + + case 0x10: + if (sensor_section == 0) + sensor->offset_num = value; + break; + + case 0x11: + if (sensor_section == 0) + sensor->offset_den = value; + break; + + case 0x12: + if (sensor_section == 0) + sensor->slope_mult = value; + break; + + case 0x13: + if (sensor_section == 0) + sensor->slope_div = value; + break; + case 0x32: + if (thrs_section == 0) { + sensor->thrs_shutdown.temp = (value & 0xff0) >> 4; + sensor->thrs_shutdown.hysteresis = value & 0xf; + } + break; + } + } + + return 0; +} + +int +nvbios_therm_fan_parse(struct nouveau_bios *bios, + struct nvbios_therm_fan *fan) +{ + u8 ver, len, i; + u16 entry; + + i = 0; + while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { + s16 value = nv_ro16(bios, entry + 1); + + switch (nv_ro08(bios, entry + 0)) { + case 0x22: + fan->min_duty = value & 0xff; + fan->max_duty = (value & 0xff00) >> 8; + break; + case 0x26: + fan->pwm_freq = value; + break; + } + } + + return 0; +} -- cgit v1.1 From 32334cc03a12c51f64613608a8b261738406e1e2 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Sat, 18 Aug 2012 16:33:53 +0200 Subject: drm/nouveau/therm: use the EXTDEV table to detect i2c monitoring devices This commit also adds a static list of all known devices and their possible i2c addresses. v2: use the common table parsing technique as suggested by darktama Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/include/subdev/bios/extdev.h | 30 +++++++ drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c | 100 +++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/extdev.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/extdev.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/extdev.h new file mode 100644 index 0000000..949fee3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/extdev.h @@ -0,0 +1,30 @@ +#ifndef __NVBIOS_EXTDEV_H__ +#define __NVBIOS_EXTDEV_H__ + +struct nouveau_bios; + +enum nvbios_extdev_type { + NVBIOS_EXTDEV_LM89 = 0x02, + NVBIOS_EXTDEV_VT1103M = 0x40, + NVBIOS_EXTDEV_PX3540 = 0x41, + NVBIOS_EXTDEV_VT1105M = 0x42, /* or close enough... */ + NVBIOS_EXTDEV_ADT7473 = 0x70, /* can also be a LM64 */ + NVBIOS_EXTDEV_HDCP_EEPROM = 0x90, + NVBIOS_EXTDEV_NONE = 0xff, +}; + +struct nvbios_extdev_func { + u8 type; + u8 addr; + u8 bus; +}; + +int +nvbios_extdev_parse(struct nouveau_bios *, int, struct nvbios_extdev_func *); + +int +nvbios_extdev_find(struct nouveau_bios *, enum nvbios_extdev_type, + struct nvbios_extdev_func *); + + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c b/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c new file mode 100644 index 0000000..5afb568 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c @@ -0,0 +1,100 @@ +/* + * Copyright 2012 Nouveau Community + * + * 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 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 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: Martin Peres + */ + +#include +#include +#include + +static u16 +extdev_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) +{ + u8 dcb_ver, dcb_hdr, dcb_cnt, dcb_len; + u16 dcb, extdev = 0; + + dcb = dcb_table(bios, &dcb_ver, &dcb_hdr, &dcb_cnt, &dcb_len); + if (!dcb || (dcb_ver != 0x30 && dcb_ver != 0x40)) + return 0x0000; + + extdev = nv_ro16(bios, dcb + 18); + if (!extdev) + return 0x0000; + + *ver = nv_ro08(bios, extdev + 0); + *hdr = nv_ro08(bios, extdev + 1); + *cnt = nv_ro08(bios, extdev + 2); + *len = nv_ro08(bios, extdev + 3); + + return extdev + *hdr; +} + +u16 +nvbios_extdev_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) +{ + u8 hdr, cnt; + u16 extdev = extdev_table(bios, ver, &hdr, len, &cnt); + if (extdev && idx < cnt) + return extdev + idx * *len; + return 0x0000; +} + +static void +extdev_parse_entry(struct nouveau_bios *bios, u16 offset, + struct nvbios_extdev_func *entry) +{ + entry->type = nv_ro08(bios, offset + 0); + entry->addr = nv_ro08(bios, offset + 1); + entry->bus = (nv_ro08(bios, offset + 2) >> 4) & 1; +} + +int +nvbios_extdev_parse(struct nouveau_bios *bios, int idx, + struct nvbios_extdev_func *func) +{ + u8 ver, len; + u16 entry; + + if (!(entry = nvbios_extdev_entry(bios, idx, &ver, &len))) + return -EINVAL; + + extdev_parse_entry(bios, entry, func); + + return 0; +} + +int +nvbios_extdev_find(struct nouveau_bios *bios, enum nvbios_extdev_type type, + struct nvbios_extdev_func *func) +{ + u8 ver, len, i; + u16 entry; + + i = 0; + while (!(entry = nvbios_extdev_entry(bios, i++, &ver, &len))) { + extdev_parse_entry(bios, entry, func); + if (func->type == type) + return 0; + } + + return -EINVAL; +} -- cgit v1.1 From d46497dce7376e9d3e2e10c59d92e1c3b665b5dd Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Thu, 30 Aug 2012 02:31:59 +0200 Subject: drm/nouveau/bios: parse the pwm divisor from the perf table v2: perf_table now is more in line with the other functions Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/core/include/subdev/bios/perf.h | 14 ++++ drivers/gpu/drm/nouveau/core/subdev/bios/perf.c | 75 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/bios/perf.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h new file mode 100644 index 0000000..0b285e9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h @@ -0,0 +1,14 @@ +#ifndef __NVBIOS_PERF_H__ +#define __NVBIOS_PERF_H__ + +struct nouveau_bios; + +struct nvbios_perf_fan { + u32 pwm_divisor; +}; + +int +nvbios_perf_fan_parse(struct nouveau_bios *, struct nvbios_perf_fan *); + + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c b/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c new file mode 100644 index 0000000..bcbb056 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c @@ -0,0 +1,75 @@ +/* + * Copyright 2012 Nouveau Community + * + * 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 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 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: Martin Peres + */ + +#include +#include +#include + +static u16 +perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ + struct bit_entry bit_P; + u16 perf = 0x0000; + + if (!bit_entry(bios, 'P', &bit_P)) { + if (bit_P.version <= 2) { + perf = nv_ro16(bios, bit_P.offset + 0); + if (perf) { + *ver = nv_ro08(bios, perf + 0); + *hdr = nv_ro08(bios, perf + 1); + } + } else + nv_error(bios, "unknown offset for perf in BIT P %d\n", + bit_P.version); + } + + if (bios->bmp_offset) { + if (nv_ro08(bios, bios->bmp_offset + 6) >= 0x25) { + perf = nv_ro16(bios, bios->bmp_offset + 0x94); + if (perf) { + *hdr = nv_ro08(bios, perf + 0); + *ver = nv_ro08(bios, perf + 1); + } + } + } + + return perf; +} + +int +nvbios_perf_fan_parse(struct nouveau_bios *bios, + struct nvbios_perf_fan *fan) +{ + u8 ver = 0, hdr = 0, cnt = 0, len = 0; + u16 perf = perf_table(bios, &ver, &hdr, &cnt, &len); + if (!perf) + return -ENODEV; + + if (ver >= 0x20 && ver < 0x40 && hdr > 6) + fan->pwm_divisor = nv_ro16(bios, perf + 6); + else + fan->pwm_divisor = 0; + + return 0; +} -- cgit v1.1 From aa1b9b4836a8ab093ec06b0780553566a5430da7 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Sun, 2 Sep 2012 02:55:58 +0200 Subject: drm/nouveau/therm: move thermal-related functions to the therm subdev It looks scary because of the size, but I tried to keep the differences minimal. Further patches will fix the actual "driver" code and add new features. v2: change filenames, split to submodules v3: add a missing include v4: Ben Skeggs - fixed set_defaults() to allow min_duty < 30 (thermal table will override this if it's actually necessary) - fixed set_defaults() to not provide pwm_freq so nv4x (which only has pwm_div) can actually work. the boards using pwm_freq will have a thermal table entry to provide us the value. - removed unused files Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/core/device.h | 1 - .../gpu/drm/nouveau/core/include/subdev/therm.h | 58 +++++++ drivers/gpu/drm/nouveau/core/subdev/device/base.c | 1 - drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | 1 + drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 17 ++ drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | 15 ++ drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 ++ drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | 3 + drivers/gpu/drm/nouveau/core/subdev/therm/base.c | 140 +++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 172 +++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | 116 ++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | 163 +++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | 130 ++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 66 ++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | 81 ++++++++++ 15 files changed, 971 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/therm.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/fan.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/ic.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/priv.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/therm/temp.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index c32f96a..57899fc 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -22,7 +22,6 @@ enum nv_subdev_type { NVDEV_SUBDEV_VM, NVDEV_SUBDEV_BAR, NVDEV_SUBDEV_VOLT, - NVDEV_SUBDEV_FAN0, NVDEV_SUBDEV_THERM, NVDEV_ENGINE_DMAOBJ, NVDEV_ENGINE_FIFO, diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h new file mode 100644 index 0000000..faee569 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h @@ -0,0 +1,58 @@ +#ifndef __NOUVEAU_THERM_H__ +#define __NOUVEAU_THERM_H__ + +#include +#include + +enum nouveau_therm_fan_mode { + FAN_CONTROL_NONE = 0, + FAN_CONTROL_MANUAL = 1, + FAN_CONTROL_NR, +}; + +enum nouveau_therm_attr_type { + NOUVEAU_THERM_ATTR_FAN_MIN_DUTY = 0, + NOUVEAU_THERM_ATTR_FAN_MAX_DUTY = 1, + NOUVEAU_THERM_ATTR_FAN_MODE = 2, + + NOUVEAU_THERM_ATTR_THRS_FAN_BOOST = 10, + NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST = 11, + NOUVEAU_THERM_ATTR_THRS_DOWN_CLK = 12, + NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST = 13, + NOUVEAU_THERM_ATTR_THRS_CRITICAL = 14, + NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST = 15, + NOUVEAU_THERM_ATTR_THRS_SHUTDOWN = 16, + NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST = 17, +}; + +struct nouveau_therm { + struct nouveau_subdev base; + + int (*fan_get)(struct nouveau_therm *); + int (*fan_set)(struct nouveau_therm *, int); + int (*fan_sense)(struct nouveau_therm *); + + int (*temp_get)(struct nouveau_therm *); + + int (*attr_get)(struct nouveau_therm *, enum nouveau_therm_attr_type); + int (*attr_set)(struct nouveau_therm *, + enum nouveau_therm_attr_type, int); +}; + +static inline struct nouveau_therm * +nouveau_therm(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_THERM]; +} + +#define nouveau_therm_create(p,e,o,d) \ + nouveau_subdev_create((p), (e), (o), 0, "THERM", "therm", d) +#define nouveau_therm_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) + +#define _nouveau_therm_dtor _nouveau_subdev_dtor + +extern struct nouveau_oclass nv40_therm_oclass; +extern struct nouveau_oclass nv50_therm_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index cac67dc..7bf6f37 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -71,7 +71,6 @@ static const u64 disable_map[] = { [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE, - [NVDEV_SUBDEV_FAN0] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE, [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE, diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 1c8681f..5fa58b7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index c6005c2..320ccc4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -70,6 +72,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -89,6 +92,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -108,6 +112,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -127,6 +132,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -146,6 +152,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -165,6 +172,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -184,6 +192,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -203,6 +212,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -222,6 +232,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -241,6 +252,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -260,6 +272,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -279,6 +292,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -298,6 +312,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -317,6 +332,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; @@ -336,6 +352,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 252e13c..fec3bcc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -79,6 +81,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -103,6 +106,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -127,6 +131,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -151,6 +156,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -175,6 +181,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -199,6 +206,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -223,6 +231,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -247,6 +256,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -271,6 +281,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -295,6 +306,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -320,6 +332,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -344,6 +357,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -368,6 +382,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 8c14b38..246bd08 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -83,6 +85,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -109,6 +112,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -135,6 +139,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -161,6 +166,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -187,6 +193,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -213,6 +220,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -239,6 +247,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 0d9d86b..4a280b7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; @@ -79,6 +81,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c new file mode 100644 index 0000000..6502dfb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c @@ -0,0 +1,140 @@ +/* + * Copyright 2012 The Nouveau community + * + * 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 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 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: Martin Peres + */ + +#include +#include + +#include + +#include "priv.h" + +int +nouveau_therm_attr_get(struct nouveau_therm *therm, + enum nouveau_therm_attr_type type) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + switch (type) { + case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: + return priv->bios_fan.min_duty; + case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: + return priv->bios_fan.max_duty; + case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: + return priv->bios_sensor.thrs_fan_boost.temp; + case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: + return priv->bios_sensor.thrs_fan_boost.hysteresis; + case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: + return priv->bios_sensor.thrs_down_clock.temp; + case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: + return priv->bios_sensor.thrs_down_clock.hysteresis; + case NOUVEAU_THERM_ATTR_THRS_CRITICAL: + return priv->bios_sensor.thrs_critical.temp; + case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: + return priv->bios_sensor.thrs_critical.hysteresis; + case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: + return priv->bios_sensor.thrs_shutdown.temp; + case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: + return priv->bios_sensor.thrs_shutdown.hysteresis; + } + + return -EINVAL; +} + +int +nouveau_therm_attr_set(struct nouveau_therm *therm, + enum nouveau_therm_attr_type type, int value) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + switch (type) { + case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: + if (value < 0) + value = 0; + if (value > priv->bios_fan.max_duty) + value = priv->bios_fan.max_duty; + priv->bios_fan.min_duty = value; + return 0; + case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: + if (value < 0) + value = 0; + if (value < priv->bios_fan.min_duty) + value = priv->bios_fan.min_duty; + priv->bios_fan.max_duty = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: + priv->bios_sensor.thrs_fan_boost.temp = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: + priv->bios_sensor.thrs_fan_boost.hysteresis = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: + priv->bios_sensor.thrs_down_clock.temp = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: + priv->bios_sensor.thrs_down_clock.hysteresis = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_CRITICAL: + priv->bios_sensor.thrs_critical.temp = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: + priv->bios_sensor.thrs_critical.hysteresis = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: + priv->bios_sensor.thrs_shutdown.temp = value; + return 0; + case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: + priv->bios_sensor.thrs_shutdown.hysteresis = value; + return 0; + } + + return -EINVAL; +} + +int +nouveau_therm_init(struct nouveau_object *object) +{ + struct nouveau_therm *therm = (void *)object; + struct nouveau_therm_priv *priv = (void *)therm; + int ret; + + ret = nouveau_subdev_init(&therm->base); + if (ret) + return ret; + + if (priv->fan.percent >= 0) + therm->fan_set(therm, priv->fan.percent); + + return 0; +} + +int +nouveau_therm_fini(struct nouveau_object *object, bool suspend) +{ + struct nouveau_therm *therm = (void *)object; + struct nouveau_therm_priv *priv = (void *)therm; + + priv->fan.percent = therm->fan_get(therm); + + return nouveau_subdev_fini(&therm->base, suspend); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c new file mode 100644 index 0000000..9ad6e16 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -0,0 +1,172 @@ +/* + * 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: + * + * 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 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 + * Martin Peres + */ + +#include "priv.h" + +#include +#include +#include +#include + +int +nouveau_therm_fan_get(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + struct nouveau_gpio *gpio = nouveau_gpio(therm); + struct dcb_gpio_func func; + int card_type = nv_device(therm)->card_type; + u32 divs, duty; + int ret; + + if (!priv->fan.pwm_get) + return -ENODEV; + + ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); + if (ret == 0) { + ret = priv->fan.pwm_get(therm, func.line, &divs, &duty); + if (ret == 0 && divs) { + divs = max(divs, duty); + if (card_type <= NV_40 || (func.log[0] & 1)) + duty = divs - duty; + return (duty * 100) / divs; + } + + return gpio->get(gpio, 0, func.func, func.line) * 100; + } + + return -ENODEV; +} + +int +nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) +{ + struct nouveau_therm_priv *priv = (void *)therm; + struct nouveau_gpio *gpio = nouveau_gpio(therm); + struct dcb_gpio_func func; + int card_type = nv_device(therm)->card_type; + u32 divs, duty; + int ret; + + if (!priv->fan.pwm_set) + return -ENODEV; + + if (percent < priv->bios_fan.min_duty) + percent = priv->bios_fan.min_duty; + if (percent > priv->bios_fan.max_duty) + percent = priv->bios_fan.max_duty; + + ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); + if (ret == 0) { + divs = priv->bios_perf_fan.pwm_divisor; + if (priv->bios_fan.pwm_freq) { + /*XXX: PNVIO clock more than likely... */ + divs = 135000 /priv->bios_fan.pwm_freq; + if (nv_device(therm)->chipset < 0xa3) + divs /= 4; + } + + duty = ((divs * percent) + 99) / 100; + if (card_type <= NV_40 || (func.log[0] & 1)) + duty = divs - duty; + + ret = priv->fan.pwm_set(therm, func.line, divs, duty); + return ret; + } + + return -ENODEV; +} + +int +nouveau_therm_fan_sense(struct nouveau_therm *therm) +{ + struct nouveau_timer *ptimer = nouveau_timer(therm); + struct nouveau_gpio *gpio = nouveau_gpio(therm); + struct dcb_gpio_func func; + u32 cycles, cur, prev; + u64 start; + + if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) + return -ENODEV; + + /* Monitor the GPIO input 0x3b for 250ms. + * When the fan spins, it changes the value of GPIO FAN_SENSE. + * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. + */ + start = ptimer->read(ptimer); + prev = gpio->get(gpio, 0, func.func, func.line); + cycles = 0; + do { + cur = gpio->get(gpio, 0, func.func, func.line); + if (prev != cur) { + cycles++; + prev = cur; + } + + usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ + } while (ptimer->read(ptimer) - start < 250000000); + + /* interpolate to get rpm */ + return cycles / 4 * 4 * 60; +} + +static void +nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + priv->bios_fan.pwm_freq = 0; + priv->bios_fan.min_duty = 0; + priv->bios_fan.max_duty = 100; +} + + +static void +nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + if (priv->bios_fan.min_duty > 100) + priv->bios_fan.min_duty = 100; + if (priv->bios_fan.max_duty > 100) + priv->bios_fan.max_duty = 100; + + if (priv->bios_fan.min_duty > priv->bios_fan.max_duty) + priv->bios_fan.min_duty = priv->bios_fan.max_duty; +} + +int +nouveau_therm_fan_ctor(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + struct nouveau_bios *bios = nouveau_bios(therm); + + nouveau_therm_fan_set_defaults(therm); + nvbios_perf_fan_parse(bios, &priv->bios_perf_fan); + if (nvbios_therm_fan_parse(bios, &priv->bios_fan)) + nv_error(therm, "parsing the thermal table failed\n"); + nouveau_therm_fan_safety_checks(therm); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c new file mode 100644 index 0000000..e512ff0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -0,0 +1,116 @@ +/* + * Copyright 2012 Nouveau community + * + * 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 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 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: Martin Peres + */ + +#include "priv.h" + +#include +#include + +static bool +probe_monitoring_device(struct nouveau_i2c_port *i2c, + struct i2c_board_info *info) +{ + struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c->i2c); + struct i2c_client *client; + + request_module("%s%s", I2C_MODULE_PREFIX, info->type); + + client = i2c_new_device(&i2c->adapter, info); + if (!client) + return false; + + if (!client->driver || client->driver->detect(client, info)) { + i2c_unregister_device(client); + return false; + } + + nv_info(priv, + "Found an %s at address 0x%x (controlled by lm_sensors)\n", + info->type, info->addr); + priv->ic = client; + + return true; +} + +void +nouveau_therm_ic_ctor(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + struct nouveau_bios *bios = nouveau_bios(therm); + struct nouveau_i2c *i2c = nouveau_i2c(therm); + struct nvbios_extdev_func extdev_entry; + struct i2c_board_info info[] = { + { I2C_BOARD_INFO("w83l785ts", 0x2d) }, + { I2C_BOARD_INFO("w83781d", 0x2d) }, + { I2C_BOARD_INFO("adt7473", 0x2e) }, + { I2C_BOARD_INFO("adt7473", 0x2d) }, + { I2C_BOARD_INFO("adt7473", 0x2c) }, + { I2C_BOARD_INFO("f75375", 0x2e) }, + { I2C_BOARD_INFO("lm99", 0x4c) }, + { I2C_BOARD_INFO("lm90", 0x4c) }, + { I2C_BOARD_INFO("lm90", 0x4d) }, + { I2C_BOARD_INFO("adm1021", 0x18) }, + { I2C_BOARD_INFO("adm1021", 0x19) }, + { I2C_BOARD_INFO("adm1021", 0x1a) }, + { I2C_BOARD_INFO("adm1021", 0x29) }, + { I2C_BOARD_INFO("adm1021", 0x2a) }, + { I2C_BOARD_INFO("adm1021", 0x2b) }, + { I2C_BOARD_INFO("adm1021", 0x4c) }, + { I2C_BOARD_INFO("adm1021", 0x4d) }, + { I2C_BOARD_INFO("adm1021", 0x4e) }, + { I2C_BOARD_INFO("lm63", 0x18) }, + { I2C_BOARD_INFO("lm63", 0x4e) }, + { } + }; + + if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { + struct i2c_board_info board[] = { + { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, + { } + }; + + i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", + board, probe_monitoring_device); + if (priv->ic) + return; + } + + if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) { + struct i2c_board_info board[] = { + { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, + { } + }; + + i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", + board, probe_monitoring_device); + if (priv->ic) + return; + } + + /* The vbios doesn't provide the address of an exisiting monitoring + device. Let's try our static list. + */ + i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, + probe_monitoring_device); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c new file mode 100644 index 0000000..9021b54 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c @@ -0,0 +1,163 @@ +/* + * 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: + * + * 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 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 + * Martin Peres + */ + +#include "priv.h" + +static int +nv40_sensor_setup(struct nouveau_therm *therm) +{ + struct nouveau_device *device = nv_device(therm); + + /* enable ADC readout and disable the ALARM threshold */ + if (device->chipset >= 0x46) { + nv_mask(therm, 0x15b8, 0x80000000, 0); + nv_wr32(therm, 0x15b0, 0x80003fff); + return nv_rd32(therm, 0x15b4) & 0x3fff; + } else { + nv_wr32(therm, 0x15b0, 0xff); + return nv_rd32(therm, 0x15b4) & 0xff; + } +} + +static int +nv40_temp_get(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + struct nouveau_device *device = nv_device(therm); + struct nvbios_therm_sensor *sensor = &priv->bios_sensor; + int core_temp; + + if (device->chipset >= 0x46) { + nv_wr32(therm, 0x15b0, 0x80003fff); + core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; + } else { + nv_wr32(therm, 0x15b0, 0xff); + core_temp = nv_rd32(therm, 0x15b4) & 0xff; + } + + /* Setup the sensor if the temperature is 0 */ + if (core_temp == 0) + core_temp = nv40_sensor_setup(therm); + + if (sensor->slope_div == 0) + sensor->slope_div = 1; + if (sensor->offset_den == 0) + sensor->offset_den = 1; + if (sensor->slope_mult < 1) + sensor->slope_mult = 1; + + core_temp = core_temp * sensor->slope_mult / sensor->slope_div; + core_temp = core_temp + sensor->offset_num / sensor->offset_den; + core_temp = core_temp + sensor->offset_constant - 8; + + return core_temp; +} + +int +nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) +{ + if (line == 2) { + u32 reg = nv_rd32(therm, 0x0010f0); + if (reg & 0x80000000) { + *duty = (reg & 0x7fff0000) >> 16; + *divs = (reg & 0x00007fff); + return 0; + } + } else + if (line == 9) { + u32 reg = nv_rd32(therm, 0x0015f4); + if (reg & 0x80000000) { + *divs = nv_rd32(therm, 0x0015f8); + *duty = (reg & 0x7fffffff); + return 0; + } + } else { + nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); + return -ENODEV; + } + + return -EINVAL; +} + +int +nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) +{ + if (line == 2) { + nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs); + } else + if (line == 9) { + nv_wr32(therm, 0x0015f8, divs); + nv_wr32(therm, 0x0015f4, duty | 0x80000000); + } else { + nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); + return -ENODEV; + } + + return 0; +} + +static int +nv40_therm_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_therm_priv *priv; + struct nouveau_therm *therm; + int ret; + + ret = nouveau_therm_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + therm = (void *) priv; + if (ret) + return ret; + + nouveau_therm_ic_ctor(therm); + nouveau_therm_sensor_ctor(therm); + nouveau_therm_fan_ctor(therm); + + priv->fan.pwm_get = nv40_fan_pwm_get; + priv->fan.pwm_set = nv40_fan_pwm_set; + + therm->temp_get = nv40_temp_get; + therm->fan_get = nouveau_therm_fan_get; + therm->fan_set = nouveau_therm_fan_set; + therm->fan_sense = nouveau_therm_fan_sense; + therm->attr_get = nouveau_therm_attr_get; + therm->attr_set = nouveau_therm_attr_set; + + return 0; +} + +struct nouveau_oclass +nv40_therm_oclass = { + .handle = NV_SUBDEV(THERM, 0x40), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv40_therm_ctor, + .dtor = _nouveau_therm_dtor, + .init = nouveau_therm_init, + .fini = nouveau_therm_fini, + }, +}; \ No newline at end of file diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c new file mode 100644 index 0000000..f7f51f3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -0,0 +1,130 @@ +/* + * 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: + * + * 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 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 + * Martin Peres + */ + +#include "priv.h" + +static int +pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx) +{ + if (*line == 0x04) { + *ctrl = 0x00e100; + *line = 4; + *indx = 0; + } else + if (*line == 0x09) { + *ctrl = 0x00e100; + *line = 9; + *indx = 1; + } else + if (*line == 0x10) { + *ctrl = 0x00e28c; + *line = 0; + *indx = 0; + } else { + nv_error(therm, "unknown pwm ctrl for gpio %d\n", *line); + return -ENODEV; + } + + return 0; +} + +int +nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) +{ + int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); + if (ret) + return ret; + + if (nv_rd32(therm, ctrl) & (1 << line)) { + *divs = nv_rd32(therm, 0x00e114 + (id * 8)); + *duty = nv_rd32(therm, 0x00e118 + (id * 8)); + return 0; + } + + return -EINVAL; +} + +int +nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) +{ + int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); + if (ret) + return ret; + + nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line); + nv_wr32(therm, 0x00e114 + (id * 8), divs); + nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); + return 0; +} + +int +nv50_temp_get(struct nouveau_therm *therm) +{ + return nv_rd32(therm, 0x20400); +} + +static int +nv50_therm_ctor(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_therm_priv *priv; + struct nouveau_therm *therm; + int ret; + + ret = nouveau_therm_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + therm = (void *) priv; + if (ret) + return ret; + + nouveau_therm_ic_ctor(therm); + nouveau_therm_sensor_ctor(therm); + nouveau_therm_fan_ctor(therm); + + priv->fan.pwm_get = nv50_fan_pwm_get; + priv->fan.pwm_set = nv50_fan_pwm_set; + + therm->temp_get = nv50_temp_get; + therm->fan_get = nouveau_therm_fan_get; + therm->fan_set = nouveau_therm_fan_set; + therm->fan_sense = nouveau_therm_fan_sense; + therm->attr_get = nouveau_therm_attr_get; + therm->attr_set = nouveau_therm_attr_set; + + return 0; +} + +struct nouveau_oclass +nv50_therm_oclass = { + .handle = NV_SUBDEV(THERM, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv50_therm_ctor, + .dtor = _nouveau_therm_dtor, + .init = nouveau_therm_init, + .fini = nouveau_therm_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h new file mode 100644 index 0000000..b7207b4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -0,0 +1,66 @@ +/* + * Copyright 2012 The Nouveau community + * + * 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 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 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: Martin Peres + */ + +#include + +#include +#include +#include + +struct nouveau_therm_priv { + struct nouveau_therm base; + + /* bios */ + struct nvbios_therm_sensor bios_sensor; + struct nvbios_therm_fan bios_fan; + struct nvbios_perf_fan bios_perf_fan; + + /* fan priv */ + struct { + int percent; + + int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); + int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); + } fan; + + /* ic */ + struct i2c_client *ic; +}; + +int nouveau_therm_init(struct nouveau_object *object); +int nouveau_therm_fini(struct nouveau_object *object, bool suspend); +int nouveau_therm_attr_get(struct nouveau_therm *therm, + enum nouveau_therm_attr_type type); +int nouveau_therm_attr_set(struct nouveau_therm *therm, + enum nouveau_therm_attr_type type, int value); + +void nouveau_therm_ic_ctor(struct nouveau_therm *therm); + +int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); + +int nouveau_therm_fan_ctor(struct nouveau_therm *therm); +int nouveau_therm_fan_get(struct nouveau_therm *therm); +int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); + +int nouveau_therm_fan_sense(struct nouveau_therm *therm); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c new file mode 100644 index 0000000..2042823 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c @@ -0,0 +1,81 @@ +/* + * Copyright 2012 The Nouveau community + * + * 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 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 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: Martin Peres + */ + +#include "priv.h" + +#include +#include + +#include + +static void +nouveau_therm_temp_set_defaults(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + priv->bios_sensor.slope_mult = 1; + priv->bios_sensor.slope_div = 1; + priv->bios_sensor.offset_num = 0; + priv->bios_sensor.offset_den = 1; + priv->bios_sensor.offset_constant = 0; + + priv->bios_sensor.thrs_fan_boost.temp = 90; + priv->bios_sensor.thrs_fan_boost.hysteresis = 3; + + priv->bios_sensor.thrs_down_clock.temp = 95; + priv->bios_sensor.thrs_down_clock.hysteresis = 3; + + priv->bios_sensor.thrs_critical.temp = 105; + priv->bios_sensor.thrs_critical.hysteresis = 5; + + priv->bios_sensor.thrs_shutdown.temp = 135; + priv->bios_sensor.thrs_shutdown.hysteresis = 5; /*not that it matters */ +} + + +static void +nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + if (!priv->bios_sensor.slope_div) + priv->bios_sensor.slope_div = 1; + if (!priv->bios_sensor.offset_den) + priv->bios_sensor.offset_den = 1; +} + +int +nouveau_therm_sensor_ctor(struct nouveau_therm *therm) +{ + struct nouveau_therm_priv *priv = (void *)therm; + struct nouveau_bios *bios = nouveau_bios(therm); + + nouveau_therm_temp_set_defaults(therm); + if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, + &priv->bios_sensor)) + nv_error(therm, "nvbios_therm_sensor_parse failed\n"); + nouveau_therm_temp_safety_checks(therm); + + return 0; +} -- cgit v1.1 From bf6546b4219d2b188529f3242efda4048f5b1b41 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Sun, 2 Sep 2012 03:20:45 +0200 Subject: drm/nouveau/fan: rewrite the fan tachometer driver to get more precision, faster The previous driver waited for 250ms to accumulate data. This version times a complete fan rotation and extrapolates to RPM. The fan rotational speed should now be read in less than 250ms (worst case) and usually in less 50ms. Signed-off-by: Martin Peres Reviewed-by: Ben Skeggs Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index 9ad6e16..b7339b5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -105,30 +105,37 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) struct nouveau_gpio *gpio = nouveau_gpio(therm); struct dcb_gpio_func func; u32 cycles, cur, prev; - u64 start; + u64 start, end, tach; if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) return -ENODEV; - /* Monitor the GPIO input 0x3b for 250ms. + /* Time a complete rotation and extrapolate to RPM: * When the fan spins, it changes the value of GPIO FAN_SENSE. - * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. + * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation. */ start = ptimer->read(ptimer); prev = gpio->get(gpio, 0, func.func, func.line); cycles = 0; do { + usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ + cur = gpio->get(gpio, 0, func.func, func.line); if (prev != cur) { + if (!start) + start = ptimer->read(ptimer); cycles++; prev = cur; } - - usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ - } while (ptimer->read(ptimer) - start < 250000000); - - /* interpolate to get rpm */ - return cycles / 4 * 4 * 60; + } while (cycles < 5 && ptimer->read(ptimer) - start < 250000000); + end = ptimer->read(ptimer); + + if (cycles == 5) { + tach = (u64)60000000000; + do_div(tach, (end - start)); + return tach; + } else + return 0; } static void -- cgit v1.1 From cfc732bbc59d8905634fef7d7b02bdac84ea9221 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Sun, 2 Sep 2012 04:01:43 +0200 Subject: drm/nouveau/therm: calculate the pwm divisor on nv50+ v2: Martin Peres - fixed unintentional use of floating point Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 13 ++++++++---- drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | 27 ++++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index b7339b5..409b95d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -81,10 +81,10 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) if (ret == 0) { divs = priv->bios_perf_fan.pwm_divisor; if (priv->bios_fan.pwm_freq) { - /*XXX: PNVIO clock more than likely... */ - divs = 135000 /priv->bios_fan.pwm_freq; - if (nv_device(therm)->chipset < 0xa3) - divs /= 4; + divs = 1; + if (priv->fan.pwm_clock) + divs = priv->fan.pwm_clock(therm); + divs /= priv->bios_fan.pwm_freq; } duty = ((divs * percent) + 99) / 100; @@ -163,6 +163,11 @@ nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) priv->bios_fan.min_duty = priv->bios_fan.max_duty; } +int nouveau_fan_pwm_clock_dummy(struct nouveau_therm *therm) +{ + return 1; +} + int nouveau_therm_fan_ctor(struct nouveau_therm *therm) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index f7f51f3..de7dc20 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -80,6 +80,32 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) } int +nv50_fan_pwm_clock(struct nouveau_therm *therm) +{ + int chipset = nv_device(therm)->chipset; + int crystal = nv_device(therm)->crystal; + int pwm_clock; + + /* determine the PWM source clock */ + if (chipset > 0x50 && chipset < 0x94) { + u8 pwm_div = nv_rd32(therm, 0x410c); + if (nv_rd32(therm, 0xc040) & 0x800000) { + /* Use the HOST clock (100 MHz) + * Where does this constant(2.4) comes from? */ + pwm_clock = (100000000 >> pwm_div) / 10 / 24; + } else { + /* Where does this constant(20) comes from? */ + pwm_clock = (crystal * 1000) >> pwm_div; + pwm_clock /= 20; + } + } else { + pwm_clock = (crystal * 1000) / 20; + } + + return pwm_clock; +} + +int nv50_temp_get(struct nouveau_therm *therm) { return nv_rd32(therm, 0x20400); @@ -107,6 +133,7 @@ nv50_therm_ctor(struct nouveau_object *parent, priv->fan.pwm_get = nv50_fan_pwm_get; priv->fan.pwm_set = nv50_fan_pwm_set; + priv->fan.pwm_clock = nv50_fan_pwm_clock; therm->temp_get = nv50_temp_get; therm->fan_get = nouveau_therm_fan_get; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index b7207b4..c53eb53 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -42,6 +42,7 @@ struct nouveau_therm_priv { int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); + int (*pwm_clock)(struct nouveau_therm *); } fan; /* ic */ -- cgit v1.1 From 2f951a5db5b55f65eb02d9a90aa7cecafde9f8b8 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Tue, 4 Sep 2012 13:52:00 +0200 Subject: drm/nouveau/therm: add support for fan-control modes For now, only 2 control modes are available: - NONE: The fan is never touched (default) - MANUAL: The fan is set to the user-defined fan speed (pwm1) This patch introduces a distinction between ptherm internal fan management and external fan management. The latter is bound to respect the fan mode while the first can still select the speed it wants unless the NONE mode is selected. This is important for automatic fan management. Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/therm/base.c | 4 ++ drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 52 +++++++++++++++++++++++- drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | 4 +- drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | 4 +- drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 6 +++ 5 files changed, 65 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index 6502dfb..1674c74 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c @@ -40,6 +40,8 @@ nouveau_therm_attr_get(struct nouveau_therm *therm, return priv->bios_fan.min_duty; case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: return priv->bios_fan.max_duty; + case NOUVEAU_THERM_ATTR_FAN_MODE: + return priv->fan.mode; case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: return priv->bios_sensor.thrs_fan_boost.temp; case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: @@ -82,6 +84,8 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, value = priv->bios_fan.min_duty; priv->bios_fan.max_duty = value; return 0; + case NOUVEAU_THERM_ATTR_FAN_MODE: + return nouveau_therm_fan_set_mode(therm, value); case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: priv->bios_sensor.thrs_fan_boost.temp = value; return 0; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index 409b95d..b292379 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -69,6 +69,9 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) u32 divs, duty; int ret; + if (priv->fan.mode == FAN_CONTROL_NONE) + return -EINVAL; + if (!priv->fan.pwm_set) return -ENODEV; @@ -138,7 +141,52 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) return 0; } -static void +int +nouveau_therm_fan_set_mode(struct nouveau_therm *therm, + enum nouveau_therm_fan_mode mode) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + if (priv->fan.mode == mode) + return 0; + + if (mode < FAN_CONTROL_NONE || mode >= FAN_CONTROL_NR) + return -EINVAL; + + switch (mode) + { + case FAN_CONTROL_NONE: + nv_info(therm, "switch fan to no-control mode\n"); + break; + case FAN_CONTROL_MANUAL: + nv_info(therm, "switch fan to manual mode\n"); + break; + case FAN_CONTROL_NR: + break; + } + + priv->fan.mode = mode; + return 0; +} + +int +nouveau_therm_fan_user_get(struct nouveau_therm *therm) +{ + return nouveau_therm_fan_get(therm); +} + +int +nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + if (priv->fan.mode != FAN_CONTROL_MANUAL) + return -EINVAL; + + return nouveau_therm_fan_set(therm, percent); +} + +void nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; @@ -180,5 +228,7 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm) nv_error(therm, "parsing the thermal table failed\n"); nouveau_therm_fan_safety_checks(therm); + nouveau_therm_fan_set_mode(therm, FAN_CONTROL_NONE); + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c index 9021b54..fcf2cfe 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c @@ -142,8 +142,8 @@ nv40_therm_ctor(struct nouveau_object *parent, priv->fan.pwm_set = nv40_fan_pwm_set; therm->temp_get = nv40_temp_get; - therm->fan_get = nouveau_therm_fan_get; - therm->fan_set = nouveau_therm_fan_set; + therm->fan_get = nouveau_therm_fan_user_get; + therm->fan_set = nouveau_therm_fan_user_set; therm->fan_sense = nouveau_therm_fan_sense; therm->attr_get = nouveau_therm_attr_get; therm->attr_set = nouveau_therm_attr_set; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index de7dc20..f87a7a3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -136,8 +136,8 @@ nv50_therm_ctor(struct nouveau_object *parent, priv->fan.pwm_clock = nv50_fan_pwm_clock; therm->temp_get = nv50_temp_get; - therm->fan_get = nouveau_therm_fan_get; - therm->fan_set = nouveau_therm_fan_set; + therm->fan_get = nouveau_therm_fan_user_get; + therm->fan_set = nouveau_therm_fan_user_set; therm->fan_sense = nouveau_therm_fan_sense; therm->attr_get = nouveau_therm_attr_get; therm->attr_set = nouveau_therm_attr_set; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index c53eb53..1c3cd6a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -38,6 +38,7 @@ struct nouveau_therm_priv { /* fan priv */ struct { + enum nouveau_therm_fan_mode mode; int percent; int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); @@ -63,5 +64,10 @@ int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); int nouveau_therm_fan_ctor(struct nouveau_therm *therm); int nouveau_therm_fan_get(struct nouveau_therm *therm); int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); +int nouveau_therm_fan_user_get(struct nouveau_therm *therm); +int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent); +int nouveau_therm_fan_set_mode(struct nouveau_therm *therm, + enum nouveau_therm_fan_mode mode); + int nouveau_therm_fan_sense(struct nouveau_therm *therm); -- cgit v1.1 From c0abf5c9fa1db7188bd6b8b580614a377dbc7080 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 26 Sep 2012 13:05:01 +1000 Subject: drm/nvc0/ibus: initial implementation of subdev Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/subdev/ibus.h | 1 + drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | 9 ++ drivers/gpu/drm/nouveau/core/subdev/ibus/nvc0.c | 123 +++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ibus/nvc0.c (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h index f014594..88814f1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h @@ -28,6 +28,7 @@ nouveau_ibus(void *obj) #define _nouveau_ibus_init _nouveau_subdev_init #define _nouveau_ibus_fini _nouveau_subdev_fini +extern struct nouveau_oclass nvc0_ibus_oclass; extern struct nouveau_oclass nve0_ibus_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 246bd08..6697f0f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -92,6 +94,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -119,6 +122,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -146,6 +150,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -173,6 +178,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -200,6 +206,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -227,6 +234,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; @@ -254,6 +262,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/nvc0.c new file mode 100644 index 0000000..4e977ff --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ibus/nvc0.c @@ -0,0 +1,123 @@ +/* + * 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: + * + * 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 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 + +struct nvc0_ibus_priv { + struct nouveau_ibus base; +}; + +static void +nvc0_ibus_intr_hub(struct nvc0_ibus_priv *priv, int i) +{ + u32 addr = nv_rd32(priv, 0x122120 + (i * 0x0400)); + u32 data = nv_rd32(priv, 0x122124 + (i * 0x0400)); + u32 stat = nv_rd32(priv, 0x122128 + (i * 0x0400)); + nv_error(priv, "HUB%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); + nv_mask(priv, 0x122128 + (i * 0x0400), 0x00000200, 0x00000000); +} + +static void +nvc0_ibus_intr_rop(struct nvc0_ibus_priv *priv, int i) +{ + u32 addr = nv_rd32(priv, 0x124120 + (i * 0x0400)); + u32 data = nv_rd32(priv, 0x124124 + (i * 0x0400)); + u32 stat = nv_rd32(priv, 0x124128 + (i * 0x0400)); + nv_error(priv, "ROP%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); + nv_mask(priv, 0x124128 + (i * 0x0400), 0x00000200, 0x00000000); +} + +static void +nvc0_ibus_intr_gpc(struct nvc0_ibus_priv *priv, int i) +{ + u32 addr = nv_rd32(priv, 0x128120 + (i * 0x0400)); + u32 data = nv_rd32(priv, 0x128124 + (i * 0x0400)); + u32 stat = nv_rd32(priv, 0x128128 + (i * 0x0400)); + nv_error(priv, "GPC%d: 0x%06x 0x%08x (0x%08x)\n", i, addr, data, stat); + nv_mask(priv, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000); +} + +static void +nvc0_ibus_intr(struct nouveau_subdev *subdev) +{ + struct nvc0_ibus_priv *priv = (void *)subdev; + u32 intr0 = nv_rd32(priv, 0x121c58); + u32 intr1 = nv_rd32(priv, 0x121c5c); + u32 hubnr = nv_rd32(priv, 0x121c70); + u32 ropnr = nv_rd32(priv, 0x121c74); + u32 gpcnr = nv_rd32(priv, 0x121c78); + u32 i; + + for (i = 0; (intr0 & 0x0000ff00) && i < hubnr; i++) { + u32 stat = 0x00000100 << i; + if (intr0 & stat) { + nvc0_ibus_intr_hub(priv, i); + intr0 &= ~stat; + } + } + + for (i = 0; (intr0 & 0xffff0000) && i < ropnr; i++) { + u32 stat = 0x00010000 << i; + if (intr0 & stat) { + nvc0_ibus_intr_rop(priv, i); + intr0 &= ~stat; + } + } + + for (i = 0; intr1 && i < gpcnr; i++) { + u32 stat = 0x00000001 << i; + if (intr1 & stat) { + nvc0_ibus_intr_gpc(priv, i); + intr1 &= ~stat; + } + } +} + +static int +nvc0_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvc0_ibus_priv *priv; + int ret; + + ret = nouveau_ibus_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nvc0_ibus_intr; + return 0; +} + +struct nouveau_oclass +nvc0_ibus_oclass = { + .handle = NV_SUBDEV(IBUS, 0xc0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_ibus_ctor, + .dtor = _nouveau_ibus_dtor, + .init = _nouveau_ibus_init, + .fini = _nouveau_ibus_fini, + }, +}; -- cgit v1.1 From dc73b45ad456b173610a211c588d003f7ea77957 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 26 Sep 2012 14:37:51 +1000 Subject: drm/nouveau: store supported dma mask in vmmgr Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/subdev/vm.h | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | 1 + drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 1 + 6 files changed, 6 insertions(+) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index 66a4473..9d595ef 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -69,6 +69,7 @@ struct nouveau_vmmgr { struct nouveau_subdev base; u64 limit; + u8 dma_bits; u32 pgt_bits; u8 spg_shift; u8 lpg_shift; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c index bfe6766..ad6ad5d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -97,6 +97,7 @@ nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.create = nv04_vm_create; priv->base.limit = NV04_PDMA_SIZE; + priv->base.dma_bits = 32; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index bbeac8d..c5486e4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -98,6 +98,7 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.create = nv04_vm_create; priv->base.limit = NV41_GART_SIZE; + priv->base.dma_bits = 39; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index d099cde..8c9cece 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -179,6 +179,7 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.create = nv04_vm_create; priv->base.limit = NV44_GART_SIZE; + priv->base.dma_bits = 39; priv->base.pgt_bits = 32 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 12; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index d83489c..e067f81 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c @@ -201,6 +201,7 @@ nv50_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.limit = 1ULL << 40; + priv->base.dma_bits = 40; priv->base.pgt_bits = 29 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 16; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index 44721a4..30c61e6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -163,6 +163,7 @@ nvc0_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.limit = 1ULL << 40; + priv->base.dma_bits = 40; priv->base.pgt_bits = 27 - 12; priv->base.spg_shift = 12; priv->base.lpg_shift = 17; -- cgit v1.1 From 8a57d279d6e1bf19d2d2e54f51d4f40c46c7d1a8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 26 Sep 2012 15:01:39 +1000 Subject: drm/nv04/dmaobj: fixup vm target handling in preparation for nv4x pcie We don't need to pull the page address out of the page tables on nv4x chips that have a real GART. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c index 5ad76f7..9f4cc2f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c @@ -44,21 +44,24 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng, struct nouveau_dmaobj *dmaobj, struct nouveau_gpuobj **pgpuobj) { + struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng); struct nouveau_gpuobj *gpuobj; u32 flags0 = nv_mclass(dmaobj); u32 flags2 = 0x00000000; - u32 offset = (dmaobj->start & 0xfffff000); - u32 adjust = (dmaobj->start & 0x00000fff); + u64 offset = dmaobj->start & 0xfffff000; + u64 adjust = dmaobj->start & 0x00000fff; u32 length = dmaobj->limit - dmaobj->start; int ret; if (dmaobj->target == NV_MEM_TARGET_VM) { - gpuobj = nv04_vmmgr(dmaeng)->vm->pgt[0].obj[0]; - if (dmaobj->start == 0) - return nouveau_gpuobj_dup(parent, gpuobj, pgpuobj); + if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) { + struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0]; + if (!dmaobj->start) + return nouveau_gpuobj_dup(parent, pgt, pgpuobj); + offset = nv_ro32(pgt, 8 + (offset >> 10)); + offset &= 0xfffff000; + } - offset = nv_ro32(gpuobj, 8 + (offset >> 10)); - offset &= 0xfffff000; dmaobj->target = NV_MEM_TARGET_PCI; dmaobj->access = NV_MEM_ACCESS_RW; } -- cgit v1.1 From e5f186c4f9812eccbc291da6dfe8b15da546f961 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 27 Sep 2012 08:55:53 +1000 Subject: drm/nv44/vm: fix and enable use of "real" pciegart Something seems to be missing in regards to flushing specific ranges of the TLB. For the moment, flushing the entire thing seems to make it work alright. Should give 39-bit DMA addressing on the relevant chipsets. v2: allocate contig 16KiB for dummy pages, reported by mwk on irc Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 16 ++++---- drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c | 7 ++-- drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h | 2 +- drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c | 45 +++++++++-------------- 4 files changed, 29 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 320ccc4..18de4c5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -218,7 +218,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -238,7 +238,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -258,7 +258,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -278,7 +278,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -298,7 +298,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -338,7 +338,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -358,7 +358,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c index ad6ad5d..6adbbc9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -132,10 +132,9 @@ nv04_vmmgr_dtor(struct nouveau_object *object) nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]); nouveau_vm_ref(NULL, &priv->vm, NULL); } - if (priv->page) { - pci_unmap_page(nv_device(priv)->pdev, priv->null, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - __free_page(priv->page); + if (priv->nullp) { + pci_free_consistent(nv_device(priv)->pdev, 16 * 1024, + priv->nullp, priv->null); } nouveau_vmmgr_destroy(&priv->base); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h index e21369c..ec42d4b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h @@ -6,8 +6,8 @@ struct nv04_vmmgr_priv { struct nouveau_vmmgr base; struct nouveau_vm *vm; - struct page *page; dma_addr_t null; + void *nullp; }; static inline struct nv04_vmmgr_priv * diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index 8c9cece..0ac18d0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -23,6 +23,7 @@ */ #include +#include #include #include @@ -37,16 +38,6 @@ ******************************************************************************/ static void -nv44_vm_flush_priv(struct nv04_vmmgr_priv *priv, u32 base, u32 size) -{ - nv_wr32(priv, 0x100814, (size - 1) << 12); - nv_wr32(priv, 0x100808, base | 0x20); - if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001)) - nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808)); - nv_wr32(priv, 0x100808, 0x00000000); -} - -static void nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null, dma_addr_t *list, u32 pte, u32 cnt) { @@ -57,6 +48,7 @@ nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null, tmp[1] = nv_ro32(pgt, base + 0x4); tmp[2] = nv_ro32(pgt, base + 0x8); tmp[3] = nv_ro32(pgt, base + 0xc); + while (cnt--) { u32 addr = list ? (*list++ >> 12) : (null >> 12); switch (pte++ & 0x3) { @@ -96,8 +88,6 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm; - u32 base = pte << 12; - u32 size = cnt; u32 tmp[4]; int i; @@ -122,15 +112,12 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, if (cnt) nv44_vm_fill(pgt, priv->null, list, pte, cnt); - nv44_vm_flush_priv(priv, base, size); } static void nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) { struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt); - u32 base = pte << 12; - u32 size = cnt; if (pte & 3) { u32 max = 4 - (pte & 3); @@ -150,12 +137,17 @@ nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) if (cnt) nv44_vm_fill(pgt, priv->null, NULL, pte, cnt); - nv44_vm_flush_priv(priv, base, size); } static void nv44_vm_flush(struct nouveau_vm *vm) { + struct nv04_vmmgr_priv *priv = (void *)vm->vmm; + nv_wr32(priv, 0x100814, priv->base.limit - NV44_GART_PAGE); + nv_wr32(priv, 0x100808, 0x00000020); + if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001)) + nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808)); + nv_wr32(priv, 0x100808, 0x00000000); } /******************************************************************************* @@ -171,6 +163,11 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv04_vmmgr_priv *priv; int ret; + if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { + return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, + data, size, pobject); + } + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", "pciegart", &priv); *pobject = nv_object(priv); @@ -187,20 +184,12 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.unmap = nv44_vm_unmap; priv->base.flush = nv44_vm_flush; - priv->page = alloc_page(GFP_DMA32 | GFP_KERNEL); - if (priv->page) { - priv->null = pci_map_page(device->pdev, priv->page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(device->pdev, priv->null)) { - __free_page(priv->page); - priv->page = NULL; - priv->null = 0; - } + priv->nullp = pci_alloc_consistent(device->pdev, 16 * 1024, &priv->null); + if (!priv->nullp) { + nv_error(priv, "unable to allocate dummy pages\n"); + return -ENOMEM; } - if (!priv->page) - nv_warn(priv, "unable to allocate dummy page\n"); - ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096, &priv->vm); if (ret) -- cgit v1.1 From 002d0c735c1bd8bffd3786ad5aadb205a76878fa Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 27 Sep 2012 08:56:24 +1000 Subject: drm/nv41/vm: fix and enable use of "real" pciegart Hopefully fixed the tlb flush timeout issue. Was able to observe this condition occur occasionally, and it appears the binary driver doesn't wait on the old condition either.. Should give 39-bit DMA addressing on the relevant chipsets. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | 12 ++++++------ drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | 9 ++++++++- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index 18de4c5..42deadc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -78,7 +78,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -98,7 +98,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -118,7 +118,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -158,7 +158,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -178,7 +178,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; @@ -198,7 +198,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; - device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index c5486e4..0203e1e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -23,6 +23,7 @@ */ #include +#include #include #include @@ -70,7 +71,7 @@ nv41_vm_flush(struct nouveau_vm *vm) mutex_lock(&nv_subdev(priv)->mutex); nv_wr32(priv, 0x100810, 0x00000022); - if (!nv_wait(priv, 0x100810, 0x00000100, 0x00000100)) { + if (!nv_wait(priv, 0x100810, 0x00000020, 0x00000020)) { nv_warn(priv, "flush timeout, 0x%08x\n", nv_rd32(priv, 0x100810)); } @@ -87,9 +88,15 @@ nv41_vmmgr_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 nv04_vmmgr_priv *priv; int ret; + if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { + return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, + data, size, pobject); + } + ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", "pciegart", &priv); *pobject = nv_object(priv); -- cgit v1.1 From 7234d0230e5a371a0cd1969c46eec802c1d6c4ed Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Oct 2012 10:30:34 +1000 Subject: drm/nouveau/devinit: fixup various issues with subdev ctor/init ordering Details of the problem, and solution, are in comments in the commit proper. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/include/core/device.h | 16 ++++++++- drivers/gpu/drm/nouveau/core/subdev/device/base.c | 38 +++++++++++++--------- 2 files changed, 38 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 57899fc..e58b6f0 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -8,11 +8,23 @@ enum nv_subdev_type { NVDEV_SUBDEV_DEVICE, NVDEV_SUBDEV_VBIOS, + + /* All subdevs from DEVINIT to DEVINIT_LAST will be created before + * *any* of them are initialised. This subdev category is used + * for any subdevs that the VBIOS init table parsing may call out + * to during POST. + */ + NVDEV_SUBDEV_DEVINIT, NVDEV_SUBDEV_GPIO, NVDEV_SUBDEV_I2C, NVDEV_SUBDEV_CLOCK, + NVDEV_SUBDEV_DEVINIT_LAST = NVDEV_SUBDEV_CLOCK, + + /* This grouping of subdevs are initialised right after they've + * been created, and are allowed to assume any subdevs in the + * list above them exist and have been initialised. + */ NVDEV_SUBDEV_MXM, - NVDEV_SUBDEV_DEVINIT, NVDEV_SUBDEV_MC, NVDEV_SUBDEV_TIMER, NVDEV_SUBDEV_FB, @@ -23,6 +35,7 @@ enum nv_subdev_type { NVDEV_SUBDEV_BAR, NVDEV_SUBDEV_VOLT, NVDEV_SUBDEV_THERM, + NVDEV_ENGINE_DMAOBJ, NVDEV_ENGINE_FIFO, NVDEV_ENGINE_SW, @@ -38,6 +51,7 @@ enum nv_subdev_type { NVDEV_ENGINE_UNK1C1, NVDEV_ENGINE_VENC, NVDEV_ENGINE_DISP, + NVDEV_SUBDEV_NR, }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index 7bf6f37..ca9a464 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -96,14 +96,13 @@ nouveau_devobj_ctor(struct nouveau_object *parent, struct nouveau_object **pobject) { struct nouveau_client *client = nv_client(parent); - struct nouveau_object *subdev = NULL; struct nouveau_device *device; struct nouveau_devobj *devobj; struct nv_device_class *args = data; u64 disable, boot0, strap; u64 mmio_base, mmio_size; void __iomem *map; - int ret, i; + int ret, i, c; if (size < sizeof(struct nv_device_class)) return -EINVAL; @@ -234,34 +233,43 @@ nouveau_devobj_ctor(struct nouveau_object *parent, } /* ensure requested subsystems are available for use */ - for (i = 0; i < NVDEV_SUBDEV_NR; i++) { + for (i = 0, c = 0; i < NVDEV_SUBDEV_NR; i++) { if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) continue; if (!device->subdev[i]) { ret = nouveau_object_ctor(nv_object(device), NULL, - oclass, NULL, i, &subdev); + oclass, NULL, i, + &devobj->subdev[i]); if (ret == -ENODEV) continue; if (ret) return ret; - if (nv_iclass(subdev, NV_ENGINE_CLASS)) - nouveau_subdev_reset(subdev); + if (nv_iclass(devobj->subdev[i], NV_ENGINE_CLASS)) + nouveau_subdev_reset(devobj->subdev[i]); } else { - nouveau_object_ref(device->subdev[i], &subdev); + nouveau_object_ref(device->subdev[i], + &devobj->subdev[i]); } - if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { - ret = nouveau_object_inc(subdev); - if (ret) { - nouveau_object_ref(NULL, &subdev); - return ret; + /* note: can't init *any* subdevs until devinit has been run + * due to not knowing exactly what the vbios init tables will + * mess with. devinit also can't be run until all of its + * dependencies have been created. + * + * this code delays init of any subdev until all of devinit's + * dependencies have been created, and then initialises each + * subdev in turn as they're created. + */ + while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) { + struct nouveau_object *subdev = devobj->subdev[c++]; + if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) { + ret = nouveau_object_inc(subdev); + if (ret) + return ret; } } - - nouveau_object_ref(subdev, &devobj->subdev[i]); - nouveau_object_ref(NULL, &subdev); } return 0; -- cgit v1.1 From b9f10852fcb1f09369d931dcbfbaad89ad1da4ad Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 3 Oct 2012 10:52:58 +1000 Subject: drm/nv98/crypt: fix fuc build with latest envyas Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau/core') diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc index 7393813..629da02 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc @@ -238,7 +238,7 @@ ih: cmpu b32 $r4 0x60+#dma_count bra nc #illegal_mthd shl b32 $r5 $r4 2 - add b32 $r5 (#ctx_dma - 0x60 * 4) & 0xffff + add b32 $r5 ((#ctx_dma - 0x60 * 4) & 0xffff) bset $r3 0x1e st b32 D[$r5] $r3 add b32 $r4 0x180 - 0x60 -- cgit v1.1