summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvc0_fence.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-07-22 05:55:54 +0400
committerBen Skeggs <bskeggs@redhat.com>2012-10-03 07:12:55 +0400
commitf589be88caf32501a734e531180d5df5d6089ef3 (patch)
treec6653b5d6aa47aade8abc79c0bb73462f82eef01 /drivers/gpu/drm/nouveau/nvc0_fence.c
parentbc9e7b9a61e9e92ddb58920cb2cb5c2e2825ca8a (diff)
downloadlinux-f589be88caf32501a734e531180d5df5d6089ef3.tar.xz
drm/nouveau/pageflip: kick flip handling out of engsw and into fence
This is all very much a policy thing, and hence will not belong in SW after the rework. engsw now only handles receiving the event to say "can flip now" and makes a callback to perform the actual work. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvc0_fence.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fence.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c
index d53ae32caea3..779c5ff4ed70 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fence.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fence.c
@@ -28,6 +28,7 @@
#include <engine/fifo.h>
#include <core/ramht.h>
#include "nouveau_fence.h"
+#include "nv50_display.h"
struct nvc0_fence_priv {
struct nouveau_fence_priv base;
@@ -38,8 +39,16 @@ struct nvc0_fence_priv {
struct nvc0_fence_chan {
struct nouveau_fence_chan base;
struct nouveau_vma vma;
+ struct nouveau_vma dispc_vma[4];
};
+u64
+nvc0_fence_crtc(struct nouveau_channel *chan, int crtc)
+{
+ struct nvc0_fence_chan *fctx = chan->fence;
+ return fctx->dispc_vma[crtc].offset;
+}
+
static int
nvc0_fence_emit(struct nouveau_fence *fence)
{
@@ -94,9 +103,25 @@ nvc0_fence_read(struct nouveau_channel *chan)
static void
nvc0_fence_context_del(struct nouveau_channel *chan)
{
- struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvc0_fence_priv *priv = dev_priv->fence.func;
struct nvc0_fence_chan *fctx = chan->fence;
+ int i;
+
+ if (dev_priv->card_type >= NV_D0) {
+ for (i = 0; i < dev->mode_config.num_crtc; i++) {
+ struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i);
+ nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
+ }
+ } else
+ if (dev_priv->card_type >= NV_50) {
+ struct nv50_display *disp = nv50_display(dev);
+ for (i = 0; i < dev->mode_config.num_crtc; i++) {
+ struct nv50_display_crtc *dispc = &disp->crtc[i];
+ nouveau_bo_vma_del(dispc->sem.bo, &fctx->dispc_vma[i]);
+ }
+ }
nouveau_bo_vma_del(priv->bo, &fctx->vma);
nouveau_fence_context_del(&fctx->base);
@@ -107,10 +132,11 @@ nvc0_fence_context_del(struct nouveau_channel *chan)
static int
nvc0_fence_context_new(struct nouveau_channel *chan)
{
- struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvc0_fence_priv *priv = dev_priv->fence.func;
struct nvc0_fence_chan *fctx;
- int ret;
+ int ret, i;
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
if (!fctx)
@@ -122,6 +148,17 @@ nvc0_fence_context_new(struct nouveau_channel *chan)
if (ret)
nvc0_fence_context_del(chan);
+ /* map display semaphore buffers into channel's vm */
+ for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
+ struct nouveau_bo *bo;
+ if (dev_priv->card_type >= NV_D0)
+ bo = nvd0_display_crtc_sema(dev, i);
+ else
+ bo = nv50_display(dev)->crtc[i].sem.bo;
+
+ ret = nouveau_bo_vma_add(bo, chan->vm, &fctx->dispc_vma[i]);
+ }
+
nouveau_bo_wr32(priv->bo, chan->id * 16/4, 0x00000000);
return ret;
}