diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 16:46:44 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 16:46:44 -0800 |
commit | fffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (patch) | |
tree | 71bc5e597124dbaf7550f1e089d675718b3ed5c0 /drivers/gpu/drm/nouveau/nv84_fence.c | |
parent | 69086a78bdc973ec0b722be790b146e84ba8a8c4 (diff) | |
parent | be88298b0a3f771a4802f20c5e66af74bfd1dff1 (diff) | |
download | linux-fffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb.tar.bz2 |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge from Dave Airlie:
"Highlights:
- TI LCD controller KMS driver
- TI OMAP KMS driver merged from staging
- drop gma500 stub driver
- the fbcon locking fixes
- the vgacon dirty like zebra fix.
- open firmware videomode and hdmi common code helpers
- major locking rework for kms object handling - pageflip/cursor
won't block on polling anymore!
- fbcon helper and prime helper cleanups
- i915: all over the map, haswell power well enhancements, valleyview
macro horrors cleaned up, killing lots of legacy GTT code,
- radeon: CS ioctl unification, deprecated UMS support, gpu reset
rework, VM fixes
- nouveau: reworked thermal code, external dp/tmds encoder support
(anx9805), fences sleep instead of polling,
- exynos: all over the driver fixes."
Lovely conflict in radeon/evergreen_cs.c between commit de0babd60d8d
("drm/radeon: enforce use of radeon_get_ib_value when reading user cmd")
and the new changes that modified that evergreen_dma_cs_parse()
function.
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (508 commits)
drm/tilcdc: only build on arm
drm/i915: Revert hdmi HDP pin checks
drm/tegra: Add list of framebuffers to debugfs
drm/tegra: Fix color expansion
drm/tegra: Split DC_CMD_STATE_CONTROL register write
drm/tegra: Implement page-flipping support
drm/tegra: Implement VBLANK support
drm/tegra: Implement .mode_set_base()
drm/tegra: Add plane support
drm/tegra: Remove bogus tegra_framebuffer structure
drm: Add consistency check for page-flipping
drm/radeon: Use generic HDMI infoframe helpers
drm/tegra: Use generic HDMI infoframe helpers
drm: Add EDID helper documentation
drm: Add HDMI infoframe helpers
video: Add generic HDMI infoframe helpers
drm: Add some missing forward declarations
drm: Move mode tables to drm_edid.c
drm: Remove duplicate drm_mode_cea_vic()
gma500: Fix n, m1 and m2 clock limits for sdvo and lvds
...
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv84_fence.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_fence.c | 214 |
1 files changed, 154 insertions, 60 deletions
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index c686650584b6..9fd475c89820 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -23,6 +23,7 @@ */ #include <core/object.h> +#include <core/client.h> #include <core/class.h> #include <engine/fifo.h> @@ -33,79 +34,115 @@ #include "nv50_display.h" -struct nv84_fence_chan { - struct nouveau_fence_chan base; -}; - -struct nv84_fence_priv { - struct nouveau_fence_priv base; - struct nouveau_gpuobj *mem; -}; +u64 +nv84_fence_crtc(struct nouveau_channel *chan, int crtc) +{ + struct nv84_fence_chan *fctx = chan->fence; + return fctx->dispc_vma[crtc].offset; +} static int -nv84_fence_emit(struct nouveau_fence *fence) +nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) { - struct nouveau_channel *chan = fence->channel; - struct nouveau_fifo_chan *fifo = (void *)chan->object; - int ret = RING_SPACE(chan, 7); + int ret = RING_SPACE(chan, 8); if (ret == 0) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); - OUT_RING (chan, NvSema); - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(fifo->chid * 16)); - OUT_RING (chan, lower_32_bits(fifo->chid * 16)); - OUT_RING (chan, fence->sequence); + OUT_RING (chan, chan->vram); + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); + OUT_RING (chan, upper_32_bits(virtual)); + OUT_RING (chan, lower_32_bits(virtual)); + OUT_RING (chan, sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); + OUT_RING (chan, 0x00000000); FIRE_RING (chan); } return ret; } - static int -nv84_fence_sync(struct nouveau_fence *fence, - struct nouveau_channel *prev, struct nouveau_channel *chan) +nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) { - struct nouveau_fifo_chan *fifo = (void *)prev->object; int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); - OUT_RING (chan, NvSema); + OUT_RING (chan, chan->vram); BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(fifo->chid * 16)); - OUT_RING (chan, lower_32_bits(fifo->chid * 16)); - OUT_RING (chan, fence->sequence); + OUT_RING (chan, upper_32_bits(virtual)); + OUT_RING (chan, lower_32_bits(virtual)); + OUT_RING (chan, sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL); FIRE_RING (chan); } return ret; } +static int +nv84_fence_emit(struct nouveau_fence *fence) +{ + struct nouveau_channel *chan = fence->channel; + struct nv84_fence_chan *fctx = chan->fence; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + u64 addr = fifo->chid * 16; + + if (fence->sysmem) + addr += fctx->vma_gart.offset; + else + addr += fctx->vma.offset; + + return fctx->base.emit32(chan, addr, fence->sequence); +} + +static int +nv84_fence_sync(struct nouveau_fence *fence, + struct nouveau_channel *prev, struct nouveau_channel *chan) +{ + struct nv84_fence_chan *fctx = chan->fence; + struct nouveau_fifo_chan *fifo = (void *)prev->object; + u64 addr = fifo->chid * 16; + + if (fence->sysmem) + addr += fctx->vma_gart.offset; + else + addr += fctx->vma.offset; + + return fctx->base.sync32(chan, addr, fence->sequence); +} + static u32 nv84_fence_read(struct nouveau_channel *chan) { struct nouveau_fifo_chan *fifo = (void *)chan->object; struct nv84_fence_priv *priv = chan->drm->fence; - return nv_ro32(priv->mem, fifo->chid * 16); + return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); } static void nv84_fence_context_del(struct nouveau_channel *chan) { + struct drm_device *dev = chan->drm->dev; + struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx = chan->fence; + int i; + + for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); + nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); + } + + nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); + nouveau_bo_vma_del(priv->bo, &fctx->vma); nouveau_fence_context_del(&fctx->base); chan->fence = NULL; kfree(fctx); } -static int +int nv84_fence_context_new(struct nouveau_channel *chan) { - struct drm_device *dev = chan->drm->dev; struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nouveau_client *client = nouveau_client(fifo); struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx; - struct nouveau_object *object; int ret, i; fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); @@ -113,44 +150,74 @@ nv84_fence_context_new(struct nouveau_channel *chan) return -ENOMEM; nouveau_fence_context_new(&fctx->base); + fctx->base.emit = nv84_fence_emit; + fctx->base.sync = nv84_fence_sync; + fctx->base.read = nv84_fence_read; + fctx->base.emit32 = nv84_fence_emit32; + fctx->base.sync32 = nv84_fence_sync32; - ret = nouveau_object_new(nv_object(chan->cli), chan->handle, - NvSema, 0x0002, - &(struct nv_dma_class) { - .flags = NV_DMA_TARGET_VRAM | - NV_DMA_ACCESS_RDWR, - .start = priv->mem->addr, - .limit = priv->mem->addr + - priv->mem->size - 1, - }, sizeof(struct nv_dma_class), - &object); - - /* dma objects for display sync channel semaphore blocks */ - for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); + ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); + if (ret == 0) { + ret = nouveau_bo_vma_add(priv->bo_gart, client->vm, + &fctx->vma_gart); + } - ret = nouveau_object_new(nv_object(chan->cli), chan->handle, - NvEvoSema0 + i, 0x003d, - &(struct nv_dma_class) { - .flags = NV_DMA_TARGET_VRAM | - NV_DMA_ACCESS_RDWR, - .start = bo->bo.offset, - .limit = bo->bo.offset + 0xfff, - }, sizeof(struct nv_dma_class), - &object); + /* map display semaphore buffers into channel's vm */ + for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i); + ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); } + nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); + if (ret) nv84_fence_context_del(chan); - nv_wo32(priv->mem, fifo->chid * 16, 0x00000000); return ret; } +static bool +nv84_fence_suspend(struct nouveau_drm *drm) +{ + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nv84_fence_priv *priv = drm->fence; + int i; + + priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); + if (priv->suspend) { + for (i = 0; i <= pfifo->max; i++) + priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); + } + + return priv->suspend != NULL; +} + +static void +nv84_fence_resume(struct nouveau_drm *drm) +{ + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nv84_fence_priv *priv = drm->fence; + int i; + + if (priv->suspend) { + for (i = 0; i <= pfifo->max; i++) + nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); + vfree(priv->suspend); + priv->suspend = NULL; + } +} + static void nv84_fence_destroy(struct nouveau_drm *drm) { struct nv84_fence_priv *priv = drm->fence; - nouveau_gpuobj_ref(NULL, &priv->mem); + nouveau_bo_unmap(priv->bo_gart); + if (priv->bo_gart) + nouveau_bo_unpin(priv->bo_gart); + nouveau_bo_ref(NULL, &priv->bo_gart); + nouveau_bo_unmap(priv->bo); + if (priv->bo) + nouveau_bo_unpin(priv->bo); + nouveau_bo_ref(NULL, &priv->bo); drm->fence = NULL; kfree(priv); } @@ -160,7 +227,6 @@ nv84_fence_create(struct nouveau_drm *drm) { struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nv84_fence_priv *priv; - u32 chan = pfifo->max + 1; int ret; priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -168,14 +234,42 @@ nv84_fence_create(struct nouveau_drm *drm) return -ENOMEM; priv->base.dtor = nv84_fence_destroy; + priv->base.suspend = nv84_fence_suspend; + priv->base.resume = nv84_fence_resume; priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; - priv->base.emit = nv84_fence_emit; - priv->base.sync = nv84_fence_sync; - priv->base.read = nv84_fence_read; - ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, - &priv->mem); + init_waitqueue_head(&priv->base.waiting); + priv->base.uevent = true; + + ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, + TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); + if (ret == 0) { + ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); + if (ret == 0) { + ret = nouveau_bo_map(priv->bo); + if (ret) + nouveau_bo_unpin(priv->bo); + } + if (ret) + nouveau_bo_ref(NULL, &priv->bo); + } + + if (ret == 0) + ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, + TTM_PL_FLAG_TT, 0, 0, NULL, + &priv->bo_gart); + if (ret == 0) { + ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); + if (ret == 0) { + ret = nouveau_bo_map(priv->bo_gart); + if (ret) + nouveau_bo_unpin(priv->bo_gart); + } + if (ret) + nouveau_bo_ref(NULL, &priv->bo_gart); + } + if (ret) nv84_fence_destroy(drm); return ret; |