mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 23:25:54 +00:00
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>
This commit is contained in:
parent
bc9e7b9a61
commit
f589be88ca
@ -132,7 +132,7 @@ nouveau-y += nouveau_drm.o nouveau_compat.o \
|
||||
nouveau_mxm.o nouveau_agp.o \
|
||||
nouveau_abi16.o \
|
||||
nouveau_bios.o \
|
||||
nv04_fence.o nv10_fence.o nv84_fence.o nvc0_fence.o \
|
||||
nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o \
|
||||
nv04_software.o nv50_software.o nvc0_software.o \
|
||||
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
|
||||
nv04_crtc.o nv04_display.o nv04_cursor.o \
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "nouveau_drv.h"
|
||||
#include <core/mm.h>
|
||||
#include <engine/fifo.h>
|
||||
#include "nouveau_software.h"
|
||||
|
||||
static void nvc0_fifo_isr(struct drm_device *);
|
||||
|
||||
@ -323,8 +324,11 @@ nvc0_fifo_page_flip(struct drm_device *dev, u32 chid)
|
||||
spin_lock_irqsave(&dev_priv->channels.lock, flags);
|
||||
if (likely(chid >= 0 && chid < priv->base.channels)) {
|
||||
chan = dev_priv->channels.ptr[chid];
|
||||
if (likely(chan))
|
||||
ret = nouveau_finish_page_flip(chan, NULL);
|
||||
if (likely(chan)) {
|
||||
struct nouveau_software_chan *swch =
|
||||
chan->engctx[NVOBJ_ENGINE_SW];
|
||||
ret = swch->flip(swch->flip_data);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
|
||||
return ret;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "nouveau_drv.h"
|
||||
#include <core/mm.h>
|
||||
#include <engine/fifo.h>
|
||||
#include "nouveau_software.h"
|
||||
|
||||
#define NVE0_FIFO_ENGINE_NUM 32
|
||||
|
||||
@ -302,8 +303,11 @@ nve0_fifo_page_flip(struct drm_device *dev, u32 chid)
|
||||
spin_lock_irqsave(&dev_priv->channels.lock, flags);
|
||||
if (likely(chid >= 0 && chid < priv->base.channels)) {
|
||||
chan = dev_priv->channels.ptr[chid];
|
||||
if (likely(chan))
|
||||
ret = nouveau_finish_page_flip(chan, NULL);
|
||||
if (likely(chan)) {
|
||||
struct nouveau_software_chan *swch =
|
||||
chan->engctx[NVOBJ_ENGINE_SW];
|
||||
ret = swch->flip(swch->flip_data);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
|
||||
return ret;
|
||||
@ -315,7 +319,7 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
|
||||
u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000));
|
||||
u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000));
|
||||
u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000));
|
||||
u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;
|
||||
u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0xfff;
|
||||
u32 subc = (addr & 0x00070000);
|
||||
u32 mthd = (addr & 0x00003ffc);
|
||||
u32 show = stat;
|
||||
|
@ -435,7 +435,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
|
||||
struct nouveau_page_flip_state *s,
|
||||
struct nouveau_fence **pfence)
|
||||
{
|
||||
struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
|
||||
struct nouveau_fence_chan *fctx = chan->fence;
|
||||
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
|
||||
struct drm_device *dev = chan->dev;
|
||||
unsigned long flags;
|
||||
@ -443,7 +443,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
|
||||
|
||||
/* Queue it to the pending list */
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
list_add_tail(&s->head, &swch->flip);
|
||||
list_add_tail(&s->head, &fctx->flip);
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
|
||||
/* Synchronize with the old framebuffer */
|
||||
@ -553,20 +553,20 @@ int
|
||||
nouveau_finish_page_flip(struct nouveau_channel *chan,
|
||||
struct nouveau_page_flip_state *ps)
|
||||
{
|
||||
struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
|
||||
struct nouveau_fence_chan *fctx = chan->fence;
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_page_flip_state *s;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
|
||||
if (list_empty(&swch->flip)) {
|
||||
if (list_empty(&fctx->flip)) {
|
||||
NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = list_first_entry(&swch->flip, struct nouveau_page_flip_state, head);
|
||||
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
|
||||
if (s->event) {
|
||||
struct drm_pending_vblank_event *e = s->event;
|
||||
struct timeval now;
|
||||
@ -588,6 +588,25 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_flip_complete(void *data)
|
||||
{
|
||||
struct nouveau_channel *chan = data;
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_page_flip_state state;
|
||||
|
||||
if (!nouveau_finish_page_flip(chan, &state)) {
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
nv_set_crtc_base(dev, state.crtc, state.offset +
|
||||
state.y * state.pitch +
|
||||
state.x * state.bpp / 8);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
|
@ -54,6 +54,7 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
|
||||
void
|
||||
nouveau_fence_context_new(struct nouveau_fence_chan *fctx)
|
||||
{
|
||||
INIT_LIST_HEAD(&fctx->flip);
|
||||
INIT_LIST_HEAD(&fctx->pending);
|
||||
spin_lock_init(&fctx->lock);
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ void nouveau_fence_update(struct nouveau_channel *);
|
||||
|
||||
struct nouveau_fence_chan {
|
||||
struct list_head pending;
|
||||
struct list_head flip;
|
||||
|
||||
spinlock_t lock;
|
||||
u32 sequence;
|
||||
};
|
||||
@ -49,8 +51,19 @@ void nouveau_fence_context_del(struct nouveau_fence_chan *);
|
||||
int nv04_fence_create(struct drm_device *dev);
|
||||
int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32);
|
||||
|
||||
int nv10_fence_create(struct drm_device *dev);
|
||||
int nv10_fence_emit(struct nouveau_fence *);
|
||||
int nv17_fence_sync(struct nouveau_fence *, struct nouveau_channel *,
|
||||
struct nouveau_channel *);
|
||||
u32 nv10_fence_read(struct nouveau_channel *);
|
||||
void nv10_fence_context_del(struct nouveau_channel *);
|
||||
void nv10_fence_destroy(struct drm_device *);
|
||||
int nv10_fence_create(struct drm_device *dev);
|
||||
|
||||
int nv50_fence_create(struct drm_device *dev);
|
||||
int nv84_fence_create(struct drm_device *dev);
|
||||
int nvc0_fence_create(struct drm_device *dev);
|
||||
u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc);
|
||||
|
||||
int nouveau_flip_complete(void *chan);
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef __NOUVEAU_SOFTWARE_H__
|
||||
#define __NOUVEAU_SOFTWARE_H__
|
||||
|
||||
#include "nouveau_fence.h"
|
||||
|
||||
struct nouveau_software_priv {
|
||||
struct nouveau_exec_engine base;
|
||||
struct list_head vblank;
|
||||
@ -8,7 +10,9 @@ struct nouveau_software_priv {
|
||||
};
|
||||
|
||||
struct nouveau_software_chan {
|
||||
struct list_head flip;
|
||||
int (*flip)(void *data);
|
||||
void *flip_data;
|
||||
|
||||
struct {
|
||||
struct list_head list;
|
||||
u32 channel;
|
||||
@ -20,10 +24,11 @@ struct nouveau_software_chan {
|
||||
};
|
||||
|
||||
static inline void
|
||||
nouveau_software_context_new(struct nouveau_software_chan *pch)
|
||||
nouveau_software_context_new(struct nouveau_channel *chan,
|
||||
struct nouveau_software_chan *pch)
|
||||
{
|
||||
INIT_LIST_HEAD(&pch->flip);
|
||||
INIT_LIST_HEAD(&pch->vblank.list);
|
||||
pch->flip = nouveau_flip_complete;
|
||||
pch->flip_data = chan;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -51,6 +56,5 @@ nouveau_software_class(struct drm_device *dev)
|
||||
int nv04_software_create(struct drm_device *);
|
||||
int nv50_software_create(struct drm_device *);
|
||||
int nvc0_software_create(struct drm_device *);
|
||||
u64 nvc0_software_crtc(struct nouveau_channel *, int crtc);
|
||||
|
||||
#endif
|
||||
|
@ -394,7 +394,7 @@ nouveau_card_init(struct drm_device *dev)
|
||||
case NV_40:
|
||||
case NV_50:
|
||||
if (dev_priv->chipset < 0x84)
|
||||
nv10_fence_create(dev);
|
||||
nv50_fence_create(dev);
|
||||
else
|
||||
nv84_fence_create(dev);
|
||||
break;
|
||||
|
@ -41,16 +41,8 @@ struct nv04_software_chan {
|
||||
static int
|
||||
mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
|
||||
{
|
||||
|
||||
struct nouveau_page_flip_state state;
|
||||
|
||||
if (!nouveau_finish_page_flip(chan, &state)) {
|
||||
nv_set_crtc_base(chan->dev, state.crtc, state.offset +
|
||||
state.y * state.pitch +
|
||||
state.x * state.bpp / 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
struct nv04_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
|
||||
return pch->base.flip(pch->base.flip_data);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -62,7 +54,7 @@ nv04_software_context_new(struct nouveau_channel *chan, int engine)
|
||||
if (!pch)
|
||||
return -ENOMEM;
|
||||
|
||||
nouveau_software_context_new(&pch->base);
|
||||
nouveau_software_context_new(chan, &pch->base);
|
||||
chan->engctx[engine] = pch;
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ struct nv10_fence_priv {
|
||||
u32 sequence;
|
||||
};
|
||||
|
||||
static int
|
||||
int
|
||||
nv10_fence_emit(struct nouveau_fence *fence)
|
||||
{
|
||||
struct nouveau_channel *chan = fence->channel;
|
||||
@ -60,7 +60,7 @@ nv10_fence_sync(struct nouveau_fence *fence,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
nv17_fence_sync(struct nouveau_fence *fence,
|
||||
struct nouveau_channel *prev, struct nouveau_channel *chan)
|
||||
{
|
||||
@ -100,13 +100,13 @@ nv17_fence_sync(struct nouveau_fence *fence,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32
|
||||
u32
|
||||
nv10_fence_read(struct nouveau_channel *chan)
|
||||
{
|
||||
return nvchan_rd32(chan, 0x0048);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv10_fence_context_del(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nv10_fence_chan *fctx = chan->fence;
|
||||
@ -148,7 +148,7 @@ nv10_fence_context_new(struct nouveau_channel *chan)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv10_fence_destroy(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
@ -32,8 +32,8 @@
|
||||
#include "nouveau_fb.h"
|
||||
#include "nouveau_fbcon.h"
|
||||
#include <core/ramht.h>
|
||||
#include "nouveau_software.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "nouveau_fence.h"
|
||||
|
||||
static void nv50_display_isr(struct drm_device *);
|
||||
static void nv50_display_bh(unsigned long);
|
||||
@ -446,7 +446,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
else
|
||||
OUT_RING (chan, chan->vram_handle);
|
||||
} else {
|
||||
u64 offset = nvc0_software_crtc(chan, nv_crtc->index);
|
||||
u64 offset = nvc0_fence_crtc(chan, nv_crtc->index);
|
||||
offset += dispc->sem.offset;
|
||||
BEGIN_NVC0(chan, 0, 0x0010, 4);
|
||||
OUT_RING (chan, upper_32_bits(offset));
|
||||
|
125
drivers/gpu/drm/nouveau/nv50_fence.c
Normal file
125
drivers/gpu/drm/nouveau/nv50_fence.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs <bskeggs@redhat.com>
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_dma.h"
|
||||
#include <core/ramht.h>
|
||||
#include "nouveau_fence.h"
|
||||
#include "nv50_display.h"
|
||||
|
||||
struct nv50_fence_chan {
|
||||
struct nouveau_fence_chan base;
|
||||
};
|
||||
|
||||
struct nv50_fence_priv {
|
||||
struct nouveau_fence_priv base;
|
||||
struct nouveau_bo *bo;
|
||||
spinlock_t lock;
|
||||
u32 sequence;
|
||||
};
|
||||
|
||||
static int
|
||||
nv50_fence_context_new(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
|
||||
struct nv50_fence_priv *priv = dev_priv->fence.func;
|
||||
struct nv50_fence_chan *fctx;
|
||||
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
|
||||
struct nouveau_gpuobj *obj;
|
||||
int ret = 0, i;
|
||||
|
||||
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
if (!fctx)
|
||||
return -ENOMEM;
|
||||
|
||||
nouveau_fence_context_new(&fctx->base);
|
||||
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY,
|
||||
mem->start * PAGE_SIZE, mem->size,
|
||||
NV_MEM_ACCESS_RW,
|
||||
NV_MEM_TARGET_VRAM, &obj);
|
||||
if (!ret) {
|
||||
ret = nouveau_ramht_insert(chan, NvSema, obj);
|
||||
nouveau_gpuobj_ref(NULL, &obj);
|
||||
}
|
||||
|
||||
/* dma objects for display sync channel semaphore blocks */
|
||||
for (i = 0; i < chan->dev->mode_config.num_crtc; i++) {
|
||||
struct nv50_display *pdisp = nv50_display(chan->dev);
|
||||
struct nv50_display_crtc *dispc = &pdisp->crtc[i];
|
||||
struct nouveau_gpuobj *obj = NULL;
|
||||
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
dispc->sem.bo->bo.offset, 0x1000,
|
||||
NV_MEM_ACCESS_RW,
|
||||
NV_MEM_TARGET_VRAM, &obj);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj);
|
||||
nouveau_gpuobj_ref(NULL, &obj);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
nv10_fence_context_del(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_fence_create(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nv50_fence_priv *priv;
|
||||
int ret = 0;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->base.dtor = nv10_fence_destroy;
|
||||
priv->base.context_new = nv50_fence_context_new;
|
||||
priv->base.context_del = nv10_fence_context_del;
|
||||
priv->base.emit = nv10_fence_emit;
|
||||
priv->base.read = nv10_fence_read;
|
||||
priv->base.sync = nv17_fence_sync;
|
||||
dev_priv->fence.func = &priv->base;
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
|
||||
0, 0x0000, NULL, &priv->bo);
|
||||
if (!ret) {
|
||||
ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
|
||||
if (!ret)
|
||||
ret = nouveau_bo_map(priv->bo);
|
||||
if (ret)
|
||||
nouveau_bo_ref(NULL, &priv->bo);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
|
||||
else
|
||||
nv10_fence_destroy(dev);
|
||||
return ret;
|
||||
}
|
@ -88,45 +88,23 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
|
||||
static int
|
||||
mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
|
||||
{
|
||||
nouveau_finish_page_flip(chan, NULL);
|
||||
return 0;
|
||||
struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
|
||||
return pch->base.flip(pch->base.flip_data);
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_software_context_new(struct nouveau_channel *chan, int engine)
|
||||
{
|
||||
struct nv50_software_priv *psw = nv_engine(chan->dev, NVOBJ_ENGINE_SW);
|
||||
struct nv50_display *pdisp = nv50_display(chan->dev);
|
||||
struct nv50_software_chan *pch;
|
||||
int ret = 0, i;
|
||||
|
||||
pch = kzalloc(sizeof(*pch), GFP_KERNEL);
|
||||
if (!pch)
|
||||
return -ENOMEM;
|
||||
|
||||
nouveau_software_context_new(&pch->base);
|
||||
nouveau_software_context_new(chan, &pch->base);
|
||||
pch->base.vblank.channel = chan->ramin->addr >> 12;
|
||||
chan->engctx[engine] = pch;
|
||||
|
||||
/* dma objects for display sync channel semaphore blocks */
|
||||
for (i = 0; i < chan->dev->mode_config.num_crtc; i++) {
|
||||
struct nv50_display_crtc *dispc = &pdisp->crtc[i];
|
||||
struct nouveau_gpuobj *obj = NULL;
|
||||
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
dispc->sem.bo->bo.offset, 0x1000,
|
||||
NV_MEM_ACCESS_RW,
|
||||
NV_MEM_TARGET_VRAM, &obj);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj);
|
||||
nouveau_gpuobj_ref(NULL, &obj);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
psw->base.base.context_del(chan, engine);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <engine/fifo.h>
|
||||
#include <core/ramht.h>
|
||||
#include "nouveau_fence.h"
|
||||
#include "nv50_display.h"
|
||||
|
||||
struct nv84_fence_chan {
|
||||
struct nouveau_fence_chan base;
|
||||
@ -99,7 +100,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
|
||||
struct nv84_fence_priv *priv = dev_priv->fence.func;
|
||||
struct nv84_fence_chan *fctx;
|
||||
struct nouveau_gpuobj *obj;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
if (!fctx)
|
||||
@ -117,6 +118,23 @@ nv84_fence_context_new(struct nouveau_channel *chan)
|
||||
nv_wo32(priv->mem, chan->id * 16, 0x00000000);
|
||||
}
|
||||
|
||||
/* dma objects for display sync channel semaphore blocks */
|
||||
for (i = 0; i < chan->dev->mode_config.num_crtc; i++) {
|
||||
struct nv50_display *pdisp = nv50_display(chan->dev);
|
||||
struct nv50_display_crtc *dispc = &pdisp->crtc[i];
|
||||
struct nouveau_gpuobj *obj = NULL;
|
||||
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
dispc->sem.bo->bo.offset, 0x1000,
|
||||
NV_MEM_ACCESS_RW,
|
||||
NV_MEM_TARGET_VRAM, &obj);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj);
|
||||
nouveau_gpuobj_ref(NULL, &obj);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
nv84_fence_context_del(chan);
|
||||
return ret;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -36,70 +36,26 @@ struct nvc0_software_priv {
|
||||
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
nouveau_software_context_new(&pch->base);
|
||||
nouveau_software_context_new(chan, &pch->base);
|
||||
chan->engctx[engine] = pch;
|
||||
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "nouveau_crtc.h"
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_fb.h"
|
||||
#include "nouveau_software.h"
|
||||
#include "nouveau_fence.h"
|
||||
#include "nv50_display.h"
|
||||
|
||||
#define EVO_DMA_NR 9
|
||||
@ -300,7 +300,7 @@ nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
return ret;
|
||||
|
||||
|
||||
offset = nvc0_software_crtc(chan, nv_crtc->index);
|
||||
offset = nvc0_fence_crtc(chan, nv_crtc->index);
|
||||
offset += evo->sem.offset;
|
||||
|
||||
BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
|
||||
|
Loading…
Reference in New Issue
Block a user