mirror of https://gitee.com/openkylin/linux.git
drm/nv50: extend vblank semaphore to generic dmaobj + offset pair
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
2a259a3d84
commit
0ade74b6c6
|
@ -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,
|
||||||
*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 @@
|
||||||
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
|
||||||
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,
|
||||||
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 {
|
||||||
|
|
||||||
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)
|
||||||
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
|
||||||
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)
|
||||||
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)
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue