diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-07-22 05:55:54 +0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-10-03 07:12:55 +0400 |
commit | f589be88caf32501a734e531180d5df5d6089ef3 (patch) | |
tree | c6653b5d6aa47aade8abc79c0bb73462f82eef01 /drivers/gpu/drm/nouveau/nvc0_fence.c | |
parent | bc9e7b9a61e9e92ddb58920cb2cb5c2e2825ca8a (diff) | |
download | linux-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.c | 43 |
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; } |