summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-01-30 23:23:34 (GMT)
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 06:00:46 (GMT)
commit1d7c71a3e2f77336df536855b0efd2dc5bdeb41b (patch)
tree8343ee580c5de2abcab27bc1bf51a7f44563e4d2 /drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
parent21a5ace0bfb737d65e6d345ccf3d63fdee141f98 (diff)
downloadlinux-fsl-qoriq-1d7c71a3e2f77336df536855b0efd2dc5bdeb41b.tar.xz
drm/nouveau/disp: port vblank handling to event interface
This removes the nastiness with the interactions between display and software engines when handling vblank semaphore release interrupts. Now, all the semantics are handled in one place (sw) \o/. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/software/nvc0.c')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nvc0.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
index 282a1cd..a523eaa 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
@@ -25,6 +25,9 @@
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
+#include <core/event.h>
+
+#include <subdev/bar.h>
#include <engine/software.h>
#include <engine/disp.h>
@@ -72,18 +75,12 @@ nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
{
struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
struct nouveau_disp *disp = nouveau_disp(object);
- unsigned long flags;
u32 crtc = *(u32 *)args;
if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3)
return -EINVAL;
- disp->vblank.get(disp->vblank.data, crtc);
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_add(&chan->base.vblank.head, &disp->vblank.list);
- chan->base.vblank.crtc = crtc;
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
+ nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event);
return 0;
}
@@ -118,6 +115,23 @@ nvc0_software_sclass[] = {
******************************************************************************/
static int
+nvc0_software_vblsem_release(struct nouveau_eventh *event, int head)
+{
+ struct nouveau_software_chan *chan =
+ container_of(event, struct nouveau_software_chan, vblank.event);
+ struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine;
+ struct nouveau_bar *bar = nouveau_bar(priv);
+
+ 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);
+
+ return NVKM_EVENT_DROP;
+}
+
+static int
nvc0_software_context_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -132,6 +146,7 @@ nvc0_software_context_ctor(struct nouveau_object *parent,
return ret;
chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
+ chan->base.vblank.event.func = nvc0_software_vblsem_release;
return 0;
}