Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 2a259a3d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -910,7 +910,6 @@ extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
extern int  nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
				   int cout, uint32_t start, uint32_t end,
				   uint32_t *offset);
extern int  nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *);

/* nouveau_channel.c */
extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *);
+0 −18
Original line number Diff line number Diff line
@@ -161,21 +161,3 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
	*b_offset = mem->start;
	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 −18
Original line number Diff line number Diff line
@@ -4,36 +4,21 @@
struct nouveau_software_priv {
	struct nouveau_exec_engine base;
	struct list_head vblank;
	spinlock_t peephole_lock;
};

struct nouveau_software_chan {
	struct list_head flip;
	struct {
		struct list_head list;
		struct nouveau_bo *bo;
		u32 channel;
		u32 ctxdma;
		u32 offset;
		u32 value;
		u32 head;
	} 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
nouveau_software_context_new(struct nouveau_software_chan *pch)
{
@@ -44,6 +29,7 @@ static inline void
nouveau_software_create(struct nouveau_software_priv *psw)
{
	INIT_LIST_HEAD(&psw->vblank);
	spin_lock_init(&psw->peephole_lock);
}

static inline u16
+24 −1
Original line number Diff line number Diff line
@@ -646,7 +646,30 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb,
static void
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);
}

+4 −15
Original line number Diff line number Diff line
@@ -36,9 +36,6 @@ struct nv50_software_priv {

struct nv50_software_chan {
	struct nouveau_software_chan base;
	struct {
		struct nouveau_gpuobj *object;
	} vblank;
};

static int
@@ -51,11 +48,7 @@ mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
	if (!gpuobj)
		return -ENOENT;

	if (nouveau_notifier_offset(gpuobj, NULL))
		return -EINVAL;

	pch->vblank.object = gpuobj;
	pch->base.vblank.offset = ~0;
	pch->base.vblank.ctxdma = gpuobj->cinst >> 4;
	return 0;
}

@@ -63,11 +56,7 @@ static int
mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
{
	struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];

	if (nouveau_notifier_offset(pch->vblank.object, &data))
		return -ERANGE;

	pch->base.vblank.offset = data >> 2;
	pch->base.vblank.offset = data;
	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 drm_device *dev = chan->dev;

	if (!pch->vblank.object || pch->base.vblank.offset == ~0 || data > 1)
	if (data > 1)
		return -EINVAL;

	drm_vblank_get(dev, data);
@@ -116,7 +105,7 @@ nv50_software_context_new(struct nouveau_channel *chan, int engine)
		return -ENOMEM;

	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;

	/* dma objects for display sync channel semaphore blocks */