diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvc0_software.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_software.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_software.c b/drivers/gpu/drm/nouveau/nvc0_software.c index a1b43f580995..93e8c164fec6 100644 --- a/drivers/gpu/drm/nouveau/nvc0_software.c +++ b/drivers/gpu/drm/nouveau/nvc0_software.c @@ -23,22 +23,37 @@ */ #include "drmP.h" + #include "nouveau_drv.h" #include "nouveau_ramht.h" #include "nouveau_software.h" +#include "nv50_display.h" + struct nvc0_software_priv { struct nouveau_software_priv base; }; struct nvc0_software_chan { struct nouveau_software_chan base; + struct nouveau_vma dispc_vma[4]; }; +u64 +nvc0_software_crtc(struct nouveau_channel *chan, int crtc) +{ + struct nvc0_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; + return pch->dispc_vma[crtc].offset; +} + static int nvc0_software_context_new(struct nouveau_channel *chan, int engine) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW); struct nvc0_software_chan *pch; + int ret = 0, i; pch = kzalloc(sizeof(*pch), GFP_KERNEL); if (!pch) @@ -46,13 +61,45 @@ nvc0_software_context_new(struct nouveau_channel *chan, int engine) nouveau_software_context_new(&pch->base); chan->engctx[engine] = pch; - return 0; + + /* 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, &pch->dispc_vma[i]); + } + + if (ret) + psw->base.base.context_del(chan, engine); + return ret; } static void nvc0_software_context_del(struct nouveau_channel *chan, int engine) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_software_chan *pch = chan->engctx[engine]; + 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, &pch->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, &pch->dispc_vma[i]); + } + } + chan->engctx[engine] = NULL; kfree(pch); } |