Commit 0ade74b6 authored by Ben Skeggs's avatar Ben Skeggs

drm/nv50: extend vblank semaphore to generic dmaobj + offset pair

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 2a259a3d
...@@ -910,7 +910,6 @@ extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); ...@@ -910,7 +910,6 @@ extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
int cout, uint32_t start, uint32_t end, int cout, uint32_t start, uint32_t end,
uint32_t *offset); uint32_t *offset);
extern int nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *);
/* nouveau_channel.c */ /* nouveau_channel.c */
extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *);
......
...@@ -161,21 +161,3 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -161,21 +161,3 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
*b_offset = mem->start; *b_offset = mem->start;
return 0; return 0;
} }
int
nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset)
{
if (!nobj || nobj->dtor != nouveau_notifier_gpuobj_dtor)
return -EINVAL;
if (poffset) {
struct drm_mm_node *mem = nobj->priv;
if (*poffset >= mem->size)
return false;
*poffset += mem->start;
}
return 0;
}
...@@ -4,36 +4,21 @@ ...@@ -4,36 +4,21 @@
struct nouveau_software_priv { struct nouveau_software_priv {
struct nouveau_exec_engine base; struct nouveau_exec_engine base;
struct list_head vblank; struct list_head vblank;
spinlock_t peephole_lock;
}; };
struct nouveau_software_chan { struct nouveau_software_chan {
struct list_head flip; struct list_head flip;
struct { struct {
struct list_head list; struct list_head list;
struct nouveau_bo *bo; u32 channel;
u32 ctxdma;
u32 offset; u32 offset;
u32 value; u32 value;
u32 head; u32 head;
} vblank; } vblank;
}; };
static inline void
nouveau_software_vblank(struct drm_device *dev, int crtc)
{
struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW);
struct nouveau_software_chan *pch, *tmp;
list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) {
if (pch->vblank.head != crtc)
continue;
nouveau_bo_wr32(pch->vblank.bo, pch->vblank.offset,
pch->vblank.value);
list_del(&pch->vblank.list);
drm_vblank_put(dev, crtc);
}
}
static inline void static inline void
nouveau_software_context_new(struct nouveau_software_chan *pch) nouveau_software_context_new(struct nouveau_software_chan *pch)
{ {
...@@ -44,6 +29,7 @@ static inline void ...@@ -44,6 +29,7 @@ static inline void
nouveau_software_create(struct nouveau_software_priv *psw) nouveau_software_create(struct nouveau_software_priv *psw)
{ {
INIT_LIST_HEAD(&psw->vblank); INIT_LIST_HEAD(&psw->vblank);
spin_lock_init(&psw->peephole_lock);
} }
static inline u16 static inline u16
......
...@@ -646,7 +646,30 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, ...@@ -646,7 +646,30 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb,
static void static void
nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc)
{ {
nouveau_software_vblank(dev, crtc); struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW);
struct nouveau_software_chan *pch, *tmp;
list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) {
if (pch->vblank.head != crtc)
continue;
spin_lock(&psw->peephole_lock);
nv_wr32(dev, 0x001704, pch->vblank.channel);
nv_wr32(dev, 0x001710, 0x80000000 | pch->vblank.ctxdma);
if (dev_priv->chipset == 0x50) {
nv_wr32(dev, 0x001570, pch->vblank.offset);
nv_wr32(dev, 0x001574, pch->vblank.value);
} else {
nv_wr32(dev, 0x060010, pch->vblank.offset);
nv_wr32(dev, 0x060014, pch->vblank.value);
}
spin_unlock(&psw->peephole_lock);
list_del(&pch->vblank.list);
drm_vblank_put(dev, crtc);
}
drm_handle_vblank(dev, crtc); drm_handle_vblank(dev, crtc);
} }
......
...@@ -36,9 +36,6 @@ struct nv50_software_priv { ...@@ -36,9 +36,6 @@ struct nv50_software_priv {
struct nv50_software_chan { struct nv50_software_chan {
struct nouveau_software_chan base; struct nouveau_software_chan base;
struct {
struct nouveau_gpuobj *object;
} vblank;
}; };
static int static int
...@@ -51,11 +48,7 @@ mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) ...@@ -51,11 +48,7 @@ mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
if (!gpuobj) if (!gpuobj)
return -ENOENT; return -ENOENT;
if (nouveau_notifier_offset(gpuobj, NULL)) pch->base.vblank.ctxdma = gpuobj->cinst >> 4;
return -EINVAL;
pch->vblank.object = gpuobj;
pch->base.vblank.offset = ~0;
return 0; return 0;
} }
...@@ -63,11 +56,7 @@ static int ...@@ -63,11 +56,7 @@ static int
mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
{ {
struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
pch->base.vblank.offset = data;
if (nouveau_notifier_offset(pch->vblank.object, &data))
return -ERANGE;
pch->base.vblank.offset = data >> 2;
return 0; return 0;
} }
...@@ -86,7 +75,7 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) ...@@ -86,7 +75,7 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
if (!pch->vblank.object || pch->base.vblank.offset == ~0 || data > 1) if (data > 1)
return -EINVAL; return -EINVAL;
drm_vblank_get(dev, data); drm_vblank_get(dev, data);
...@@ -116,7 +105,7 @@ nv50_software_context_new(struct nouveau_channel *chan, int engine) ...@@ -116,7 +105,7 @@ nv50_software_context_new(struct nouveau_channel *chan, int engine)
return -ENOMEM; return -ENOMEM;
nouveau_software_context_new(&pch->base); nouveau_software_context_new(&pch->base);
pch->base.vblank.bo = chan->notifier_bo; pch->base.vblank.channel = chan->ramin->vinst >> 12;
chan->engctx[engine] = pch; chan->engctx[engine] = pch;
/* dma objects for display sync channel semaphore blocks */ /* dma objects for display sync channel semaphore blocks */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment