mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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 <marcin.slusarz@gmail.com> - fix find/replace bug in license header v3: Ben Skeggs <bskeggs@redhat.com> - 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 <marcin.slusarz@gmail.com> - add sparse annotations to nv04_fifo_pause/nv04_fifo_start - use ioread32_native/iowrite32_native for fifo control registers v5: Ben Skeggs <bskeggs@redhat.com> - 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 <bskeggs@redhat.com>
This commit is contained in:
@@ -4,9 +4,11 @@
|
||||
|
||||
ccflags-y := -Iinclude/drm -DCONFIG_NOUVEAU_DEBUG=7 -DCONFIG_NOUVEAU_DEBUG_DEFAULT=3
|
||||
ccflags-y += -I$(src)/core/include
|
||||
ccflags-y += -I$(src)/core
|
||||
ccflags-y += -I$(src)
|
||||
|
||||
nouveau-y := core/core/client.o
|
||||
nouveau-y += core/core/engctx.o
|
||||
nouveau-y += core/core/engine.o
|
||||
nouveau-y += core/core/enum.o
|
||||
nouveau-y += core/core/gpuobj.o
|
||||
@@ -90,12 +92,20 @@ nouveau-y += core/subdev/vm/nv44.o
|
||||
nouveau-y += core/subdev/vm/nv50.o
|
||||
nouveau-y += core/subdev/vm/nvc0.o
|
||||
|
||||
nouveau-y += core/engine/dmaobj/base.o
|
||||
nouveau-y += core/engine/dmaobj/nv04.o
|
||||
nouveau-y += core/engine/dmaobj/nv50.o
|
||||
nouveau-y += core/engine/dmaobj/nvc0.o
|
||||
nouveau-y += core/engine/bsp/nv84.o
|
||||
nouveau-y += core/engine/copy/nva3.o
|
||||
nouveau-y += core/engine/copy/nvc0.o
|
||||
nouveau-y += core/engine/crypt/nv84.o
|
||||
nouveau-y += core/engine/crypt/nv98.o
|
||||
nouveau-y += core/engine/disp/nv04.o
|
||||
nouveau-y += core/engine/disp/nv50.o
|
||||
nouveau-y += core/engine/disp/nvd0.o
|
||||
nouveau-y += core/engine/disp/vga.o
|
||||
nouveau-y += core/engine/fifo/base.o
|
||||
nouveau-y += core/engine/fifo/nv04.o
|
||||
nouveau-y += core/engine/fifo/nv10.o
|
||||
nouveau-y += core/engine/fifo/nv17.o
|
||||
@@ -111,41 +121,82 @@ nouveau-y += core/engine/graph/ctxnve0.o
|
||||
nouveau-y += core/engine/graph/nv04.o
|
||||
nouveau-y += core/engine/graph/nv10.o
|
||||
nouveau-y += core/engine/graph/nv20.o
|
||||
nouveau-y += core/engine/graph/nv25.o
|
||||
nouveau-y += core/engine/graph/nv2a.o
|
||||
nouveau-y += core/engine/graph/nv30.o
|
||||
nouveau-y += core/engine/graph/nv34.o
|
||||
nouveau-y += core/engine/graph/nv35.o
|
||||
nouveau-y += core/engine/graph/nv40.o
|
||||
nouveau-y += core/engine/graph/nv50.o
|
||||
nouveau-y += core/engine/graph/nvc0.o
|
||||
nouveau-y += core/engine/graph/nve0.o
|
||||
nouveau-y += core/engine/mpeg/nv31.o
|
||||
nouveau-y += core/engine/mpeg/nv40.o
|
||||
nouveau-y += core/engine/mpeg/nv50.o
|
||||
nouveau-y += core/engine/mpeg/nv84.o
|
||||
nouveau-y += core/engine/ppp/nv98.o
|
||||
nouveau-y += core/engine/software/nv04.o
|
||||
nouveau-y += core/engine/software/nv10.o
|
||||
nouveau-y += core/engine/software/nv50.o
|
||||
nouveau-y += core/engine/software/nvc0.o
|
||||
nouveau-y += core/engine/vp/nv84.o
|
||||
|
||||
nouveau-y += nouveau_drm.o nouveau_compat.o \
|
||||
nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
|
||||
nouveau_gpuobj.o nouveau_irq.o nouveau_notifier.o \
|
||||
nouveau_sgdma.o nouveau_dma.o nouveau_util.o \
|
||||
nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
|
||||
nouveau_hw.o nouveau_calc.o \
|
||||
nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
|
||||
nouveau_hdmi.o nouveau_dp.o \
|
||||
nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
|
||||
nouveau_mxm.o nouveau_agp.o \
|
||||
nouveau_abi16.o \
|
||||
nouveau_bios.o \
|
||||
nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o \
|
||||
nv04_software.o nv50_software.o nvc0_software.o \
|
||||
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
|
||||
nv04_crtc.o nv04_display.o nv04_cursor.o \
|
||||
nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
|
||||
nv50_cursor.o nv50_display.o \
|
||||
nvd0_display.o \
|
||||
nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \
|
||||
nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
|
||||
nouveau_prime.o
|
||||
# drm/compat - will go away
|
||||
nouveau-y += nouveau_compat.o nouveau_revcompat.o
|
||||
|
||||
nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
|
||||
# drm/core
|
||||
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
|
||||
nouveau-y += nouveau_agp.o
|
||||
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
|
||||
|
||||
nouveau-y += nouveau_abi16.o
|
||||
nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o
|
||||
|
||||
# drm/kms/common
|
||||
nouveau-y += nouveau_fbcon.o
|
||||
|
||||
# drm/kms/nv04:nv50
|
||||
nouveau-y += nv04_fbcon.o
|
||||
|
||||
# drm/kms/nv50:nvd9
|
||||
nouveau-y += nv50_fbcon.o nvc0_fbcon.o
|
||||
|
||||
# drm/kms/nvd9-
|
||||
|
||||
##
|
||||
## unported bits below
|
||||
##
|
||||
|
||||
# drm/core
|
||||
nouveau-y += nouveau_drv.o nouveau_state.o nouveau_irq.o
|
||||
nouveau-y += nouveau_prime.o
|
||||
|
||||
# drm/kms/bios
|
||||
nouveau-y += nouveau_mxm.o nouveau_bios.o
|
||||
|
||||
# drm/kms/common
|
||||
nouveau-y += nouveau_display.o nouveau_connector.o
|
||||
nouveau-y += nouveau_hdmi.o nouveau_dp.o
|
||||
|
||||
# drm/kms/nv04:nv50
|
||||
nouveau-y += nouveau_hw.o nouveau_calc.o
|
||||
nouveau-y += nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o
|
||||
nouveau-y += nv04_crtc.o nv04_display.o nv04_cursor.o
|
||||
|
||||
# drm/kms/nv50-
|
||||
nouveau-y += nv50_display.o nvd0_display.o
|
||||
nouveau-y += nv50_crtc.o nv50_dac.o nv50_sor.o nv50_cursor.o
|
||||
nouveau-y += nv50_evo.o
|
||||
|
||||
# drm/pm
|
||||
nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o
|
||||
nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o
|
||||
nouveau-y += nouveau_mem.o
|
||||
|
||||
# optional stuff
|
||||
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
|
||||
nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
|
||||
nouveau-$(CONFIG_ACPI) += nouveau_acpi.o
|
||||
|
||||
|
||||
obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
|
||||
|
||||
@@ -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 <core/object.h>
|
||||
#include <core/ramht.h>
|
||||
#include <core/math.h>
|
||||
|
||||
#include <subdev/bar.h>
|
||||
|
||||
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;
|
||||
struct nouveau_bar *bar = nouveau_bar(ramht);
|
||||
u32 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);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
nouveau_ramht_remove(struct nouveau_ramht *ramht, int cookie)
|
||||
{
|
||||
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;
|
||||
struct nouveau_bar *bar = nouveau_bar(ramht);
|
||||
nv_wo32(ramht, cookie + 0, 0x00000000);
|
||||
nv_wo32(ramht, cookie + 4, 0x00000000);
|
||||
if (bar)
|
||||
bar->flush(bar);
|
||||
}
|
||||
|
||||
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 nouveau_object *parent, struct nouveau_object *pargpu,
|
||||
u32 size, u32 align, struct nouveau_ramht **pramht)
|
||||
{
|
||||
struct nouveau_ramht *ramht;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_gpuobj_create(parent, parent->engine ?
|
||||
parent->engine : parent, /* <nv50 ramht */
|
||||
&nouveau_ramht_oclass, 0, pargpu, size,
|
||||
align, NVOBJ_FLAG_ZERO_ALLOC, &ramht);
|
||||
*pramht = ramht;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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 <core/ramht.h>
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
|
||||
/*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 <engine/bsp.h>
|
||||
|
||||
struct nv84_bsp_engine {
|
||||
struct nouveau_exec_engine base;
|
||||
struct nv84_bsp_priv {
|
||||
struct nouveau_bsp base;
|
||||
};
|
||||
|
||||
static int
|
||||
nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend)
|
||||
{
|
||||
if (!(nv_rd32(dev, 0x000200) & 0x00008000))
|
||||
return 0;
|
||||
struct nv84_bsp_chan {
|
||||
struct nouveau_bsp_chan base;
|
||||
};
|
||||
|
||||
nv_mask(dev, 0x000200, 0x00008000, 0x00000000);
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************************
|
||||
* BSP object classes
|
||||
******************************************************************************/
|
||||
|
||||
static struct nouveau_oclass
|
||||
nv84_bsp_sclass[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* BSP context
|
||||
******************************************************************************/
|
||||
|
||||
static int
|
||||
nv84_bsp_init(struct drm_device *dev, int engine)
|
||||
nv84_bsp_context_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, 0x00008000, 0x00000000);
|
||||
nv_mask(dev, 0x000200, 0x00008000, 0x00008000);
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nv84_bsp_destroy(struct drm_device *dev, int engine)
|
||||
nv84_bsp_context_dtor(struct nouveau_object *object)
|
||||
{
|
||||
struct nv84_bsp_engine *pbsp = nv_engine(dev, engine);
|
||||
|
||||
NVOBJ_ENGINE_DEL(dev, BSP);
|
||||
|
||||
kfree(pbsp);
|
||||
struct nv84_bsp_chan *priv = (void *)object;
|
||||
nouveau_bsp_context_destroy(&priv->base);
|
||||
}
|
||||
|
||||
int
|
||||
nv84_bsp_create(struct drm_device *dev)
|
||||
static int
|
||||
nv84_bsp_context_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nv84_bsp_engine *pbsp;
|
||||
struct nv84_bsp_chan *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL);
|
||||
if (!pbsp)
|
||||
return -ENOMEM;
|
||||
ret = nouveau_bsp_context_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_intr(struct nouveau_subdev *subdev)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
nv84_bsp_dtor(struct nouveau_object *object)
|
||||
{
|
||||
struct nv84_bsp_priv *priv = (void *)object;
|
||||
nouveau_bsp_destroy(&priv->base);
|
||||
}
|
||||
|
||||
static int
|
||||
nv84_bsp_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nv84_bsp_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_bsp_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 <linux/firmware.h>
|
||||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_util.h"
|
||||
#include <core/ramht.h>
|
||||
#include <core/os.h>
|
||||
#include <core/enum.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/vm.h>
|
||||
|
||||
#include <engine/copy.h>
|
||||
|
||||
#include "fuc/nva3.fuc.h"
|
||||
|
||||
struct nva3_copy_engine {
|
||||
struct nouveau_exec_engine base;
|
||||
struct nva3_copy_priv {
|
||||
struct nouveau_copy base;
|
||||
};
|
||||
|
||||
struct nva3_copy_chan {
|
||||
struct nouveau_copy_chan base;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Copy object classes
|
||||
******************************************************************************/
|
||||
|
||||
static struct nouveau_oclass
|
||||
nva3_copy_sclass[] = {
|
||||
{ 0x85b5, &nouveau_object_ofuncs },
|
||||
{}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* PCOPY context
|
||||
******************************************************************************/
|
||||
|
||||
static int
|
||||
nva3_copy_context_new(struct nouveau_channel *chan, 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)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_gpuobj *ramin = chan->ramin;
|
||||
struct nouveau_gpuobj *ctx = NULL;
|
||||
struct nva3_copy_chan *priv;
|
||||
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_copy_context_create(parent, engine, oclass, NULL, 256, 0,
|
||||
NVOBJ_FLAG_ZERO_ALLOC, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
|
||||
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];
|
||||
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,
|
||||
|
||||
/* 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);
|
||||
|
||||
nvvm_engref(chan->vm, engine, -1);
|
||||
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;
|
||||
}
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
|
||||
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);
|
||||
nv50_vm_flush_engine(&engine->base, 0x0d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
nva3_copy_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nva3_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, 0xffffffff);
|
||||
|
||||
/* 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]);
|
||||
}
|
||||
|
||||
/* 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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 <linux/firmware.h>
|
||||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_util.h"
|
||||
#include <core/ramht.h>
|
||||
#include <core/os.h>
|
||||
#include <core/enum.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
|
||||
#include <engine/copy.h>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Copy object classes
|
||||
******************************************************************************/
|
||||
|
||||
static struct nouveau_oclass
|
||||
nvc0_copy0_sclass[] = {
|
||||
{ 0x90b5, &nouveau_object_ofuncs },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct nouveau_oclass
|
||||
nvc0_copy1_sclass[] = {
|
||||
{ 0x90b8, &nouveau_object_ofuncs },
|
||||
{},
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* PCOPY context
|
||||
******************************************************************************/
|
||||
|
||||
static int
|
||||
nvc0_copy_context_new(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;
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_gpuobj *ramin = chan->ramin;
|
||||
struct nvc0_copy_chan *priv;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256,
|
||||
256, NVOBJ_FLAG_ZERO_ALLOC, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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));
|
||||
nvimem_flush(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_copy_object_new(struct nouveau_channel *chan, int engine,
|
||||
u32 handle, u16 class)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
||||
static void
|
||||
nvc0_copy_context_del(struct nouveau_channel *chan, int engine)
|
||||
{
|
||||
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;
|
||||
static struct nouveau_oclass
|
||||
nvc0_copy0_cclass = {
|
||||
.handle = NV_ENGCTX(COPY0, 0xc0),
|
||||
.ofuncs = &nvc0_copy_context_ofuncs,
|
||||
};
|
||||
|
||||
inst = (chan->ramin->addr >> 12);
|
||||
inst |= 0x40000000;
|
||||
static struct nouveau_oclass
|
||||
nvc0_copy1_cclass = {
|
||||
.handle = NV_ENGCTX(COPY1, 0xc0),
|
||||
.ofuncs = &nvc0_copy_context_ofuncs,
|
||||
};
|
||||
|
||||
/* 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]);
|
||||
|
||||
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;
|
||||
}
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
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);
|
||||
}
|
||||
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 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_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_subdev(priv)->intr = nvc0_copy_intr;
|
||||
nv_engine(priv)->cclass = &nvc0_copy1_cclass;
|
||||
nv_engine(priv)->sclass = nvc0_copy1_sclass;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_copy_init(struct nouveau_object *object)
|
||||
{
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 <core/ramht.h>
|
||||
#include <core/os.h>
|
||||
#include <core/enum.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/gpuobj.h>
|
||||
|
||||
struct nv84_crypt_engine {
|
||||
struct nouveau_exec_engine base;
|
||||
#include <subdev/fb.h>
|
||||
|
||||
#include <engine/crypt.h>
|
||||
|
||||
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;
|
||||
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,
|
||||
};
|
||||
|
||||
inst = (chan->ramin->addr >> 12);
|
||||
inst |= 0x80000000;
|
||||
static struct nouveau_oclass
|
||||
nv84_crypt_sclass[] = {
|
||||
{ 0x74c1, &nv84_crypt_ofuncs },
|
||||
{}
|
||||
};
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/*******************************************************************************
|
||||
* 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,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nouveau_bitfield nv84_crypt_intr[] = {
|
||||
/*******************************************************************************
|
||||
* PCRYPT engine/subdev functions
|
||||
******************************************************************************/
|
||||
|
||||
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);
|
||||
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 (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);
|
||||
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)
|
||||
static int
|
||||
nv84_crypt_init(struct nouveau_object *object)
|
||||
{
|
||||
struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine);
|
||||
struct nv84_crypt_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
NVOBJ_ENGINE_DEL(dev, CRYPT);
|
||||
ret = nouveau_crypt_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 <core/os.h>
|
||||
#include <core/enum.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_util.h"
|
||||
#include <core/ramht.h>
|
||||
#include <subdev/timer.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
#include <engine/crypt.h>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Crypt object classes
|
||||
******************************************************************************/
|
||||
|
||||
static struct nouveau_oclass
|
||||
nv98_crypt_sclass[] = {
|
||||
{ 0x88b4, &nouveau_object_ofuncs },
|
||||
{},
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* PCRYPT context
|
||||
******************************************************************************/
|
||||
|
||||
static int
|
||||
nv98_crypt_context_new(struct nouveau_channel *chan, int engine)
|
||||
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 drm_device *dev = chan->dev;
|
||||
struct nv98_crypt_priv *priv = nv_engine(dev, engine);
|
||||
struct nv98_crypt_chan *cctx;
|
||||
struct nv98_crypt_chan *priv;
|
||||
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);
|
||||
ret = nouveau_crypt_context_create(parent, engine, oclass, NULL, 256,
|
||||
256, NVOBJ_FLAG_ZERO_ALLOC, &priv);
|
||||
*pobject = nv_object(priv);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
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);
|
||||
|
||||
nouveau_gpuobj_ref(NULL, &cctx->mem);
|
||||
|
||||
nvvm_engref(chan->vm, engine, -1);
|
||||
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;
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
nv50_vm_flush_engine(&engine->base, 0x0a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* wait for exit interrupt to signal */
|
||||
nv_wait(priv, 0x087008, 0x00000010, 0x00000010);
|
||||
nv_wr32(priv, 0x087004, 0x00000010);
|
||||
|
||||
/* 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]);
|
||||
|
||||
nv_wr32(priv, 0x087ff8, 0x00000000);
|
||||
for (i = 0; i < ARRAY_SIZE(nv98_pcrypt_data); i++)
|
||||
nv_wr32(priv, 0x087ff4, nv98_pcrypt_data[i]);
|
||||
|
||||
/* 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,
|
||||
},
|
||||
};
|
||||
|
||||
90
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
Normal file
90
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
Normal file
@@ -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 <engine/disp.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
125
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
Normal file
125
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
Normal file
@@ -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 <engine/software.h>
|
||||
#include <engine/disp.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
118
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
Normal file
118
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
Normal file
@@ -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 <subdev/bar.h>
|
||||
|
||||
#include <engine/software.h>
|
||||
#include <engine/disp.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
87
drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
Normal file
87
drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
Normal file
@@ -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 <core/object.h>
|
||||
#include <core/class.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <engine/dmaobj.h>
|
||||
|
||||
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;
|
||||
}
|
||||
176
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
Normal file
176
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
Normal file
@@ -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 <core/gpuobj.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <subdev/vm/nv04.h>
|
||||
|
||||
#include <engine/dmaobj.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
168
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
Normal file
168
drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
Normal file
@@ -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 <core/gpuobj.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <engine/dmaobj.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
99
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
Normal file
99
drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
Normal file
@@ -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 <core/gpuobj.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
#include <engine/dmaobj.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
165
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
Normal file
165
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
Normal file
@@ -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 <core/object.h>
|
||||
#include <core/handle.h>
|
||||
|
||||
#include <engine/dmaobj.h>
|
||||
#include <engine/fifo.h>
|
||||
|
||||
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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
178
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h
Normal file
178
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.h
Normal file
@@ -0,0 +1,178 @@
|
||||
#ifndef __NV04_FIFO_H__
|
||||
#define __NV04_FIFO_H__
|
||||
|
||||
#include <engine/fifo.h>
|
||||
|
||||
#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
|
||||
@@ -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 <engine/fifo.h>
|
||||
#include "nouveau_util.h"
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/ramht.h>
|
||||
|
||||
static struct ramfc_desc {
|
||||
unsigned bits:6;
|
||||
unsigned ctxs:5;
|
||||
unsigned ctxp:8;
|
||||
unsigned regs:5;
|
||||
unsigned regp;
|
||||
} nv10_ramfc[] = {
|
||||
#include <subdev/instmem.h>
|
||||
#include <subdev/instmem/nv04.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
#include <engine/fifo.h>
|
||||
|
||||
#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;
|
||||
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 + 0x0c, chan->pushbuf->addr >> 4);
|
||||
nv_wo32(priv->ramfc, fctx->ramfc + 0x14,
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
nouveau_irq_register(dev, 8, nv04_fifo_isr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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
|
||||
******************************************************************************/
|
||||
|
||||
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 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)
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 <engine/fifo.h>
|
||||
#include "nouveau_util.h"
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/ramht.h>
|
||||
|
||||
static struct ramfc_desc {
|
||||
unsigned bits:6;
|
||||
unsigned ctxs:5;
|
||||
unsigned ctxp:8;
|
||||
unsigned regs:5;
|
||||
unsigned regp;
|
||||
} nv17_ramfc[] = {
|
||||
#include <subdev/instmem.h>
|
||||
#include <subdev/instmem/nv04.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
#include <engine/fifo.h>
|
||||
|
||||
#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;
|
||||
if (size < sizeof(*args))
|
||||
return -EINVAL;
|
||||
|
||||
fctx->ramfc = chan->id * 64;
|
||||
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;
|
||||
|
||||
/* 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 * 64;
|
||||
|
||||
/* 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,
|
||||
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:
|
||||
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_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 = &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;
|
||||
}
|
||||
|
||||
static int
|
||||
nv17_fifo_init(struct drm_device *dev, int engine)
|
||||
nv17_fifo_init(struct nouveau_object *object)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nv17_fifo_priv *priv = nv_engine(dev, engine);
|
||||
int i;
|
||||
struct nv04_fifo_priv *priv = (void *)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, NV04_PFIFO_DELAY_0, 0x000000ff);
|
||||
nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff);
|
||||
nv_wr32(priv, NV04_PFIFO_DELAY_0, 0x000000ff);
|
||||
nv_wr32(priv, 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->addr >> 8));
|
||||
nv_wr32(dev, NV03_PFIFO_RAMRO, priv->ramro->addr >> 8);
|
||||
nv_wr32(dev, NV03_PFIFO_RAMFC, 0x00010000 |
|
||||
priv->ramfc->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);
|
||||
nv_wr32(priv, NV03_PFIFO_RAMFC, priv->ramfc->addr >> 8 | 0x00010000);
|
||||
|
||||
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
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 <engine/fifo.h>
|
||||
#include "nouveau_util.h"
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/ramht.h>
|
||||
|
||||
static struct ramfc_desc {
|
||||
unsigned bits:6;
|
||||
unsigned ctxs:5;
|
||||
unsigned ctxp:8;
|
||||
unsigned regs:5;
|
||||
unsigned regp;
|
||||
} nv40_ramfc[] = {
|
||||
#include <subdev/instmem.h>
|
||||
#include <subdev/instmem/nv04.h>
|
||||
#include <subdev/fb.h>
|
||||
|
||||
#include <engine/fifo.h>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
struct nv40_fifo_chan {
|
||||
struct nouveau_fifo_chan base;
|
||||
u32 ramfc;
|
||||
};
|
||||
/*******************************************************************************
|
||||
* FIFO channel objects
|
||||
******************************************************************************/
|
||||
|
||||
static int
|
||||
nv40_fifo_context_new(struct nouveau_channel *chan, int engine)
|
||||
nv40_fifo_object_attach(struct nouveau_object *parent,
|
||||
struct nouveau_object *object, u32 handle)
|
||||
{
|
||||
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;
|
||||
struct nv04_fifo_priv *priv = (void *)parent->engine;
|
||||
struct nv04_fifo_chan *chan = (void *)parent;
|
||||
u32 context, chid = chan->base.chid;
|
||||
int ret;
|
||||
|
||||
fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
if (!fctx)
|
||||
return -ENOMEM;
|
||||
if (nv_iclass(object, NV_GPUOBJ_CLASS))
|
||||
context = nv_gpuobj(object)->addr >> 4;
|
||||
else
|
||||
context = 0x00000004; /* just non-zero */
|
||||
|
||||
fctx->ramfc = chan->id * 128;
|
||||
|
||||
/* 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(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;
|
||||
}
|
||||
|
||||
/* 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 |
|
||||
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_attach(struct nouveau_object *parent,
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
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,
|
||||
};
|
||||
|
||||
/*XXX: remove this later, need fifo engine context commit hook */
|
||||
nouveau_gpuobj_ref(priv->ramfc, &chan->ramfc);
|
||||
static struct nouveau_oclass
|
||||
nv40_fifo_sclass[] = {
|
||||
{ 0x006e, &nv40_fifo_ofuncs },
|
||||
{}
|
||||
};
|
||||
|
||||
error:
|
||||
/*******************************************************************************
|
||||
* FIFO context - basically just the instmem reserved for the channel
|
||||
******************************************************************************/
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* 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,
|
||||
},
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user