Commit f03a314b authored by Francisco Jerez's avatar Francisco Jerez Committed by Ben Skeggs

drm/nouveau: Allocate a per-channel instance of NV_SW.

It will be useful for various synchronization purposes, mostly stolen
from "[PATCH] drm/nv50: synchronize user channel after buffer object
move on kernel channel" by Maarten Maathuis.
Signed-off-by: default avatarFrancisco Jerez <currojerez@riseup.net>
parent a510604d
...@@ -414,7 +414,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, ...@@ -414,7 +414,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
init->subchan[0].grclass = 0x0039; init->subchan[0].grclass = 0x0039;
else else
init->subchan[0].grclass = 0x5039; init->subchan[0].grclass = 0x5039;
init->nr_subchan = 1; init->subchan[1].handle = NvSw;
init->subchan[1].grclass = NV_SW;
init->nr_subchan = 2;
/* Named memory object area */ /* Named memory object area */
ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
......
...@@ -35,6 +35,7 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -35,6 +35,7 @@ nouveau_dma_init(struct nouveau_channel *chan)
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *m2mf = NULL; struct nouveau_gpuobj *m2mf = NULL;
struct nouveau_gpuobj *nvsw = NULL;
int ret, i; int ret, i;
/* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
...@@ -47,6 +48,15 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -47,6 +48,15 @@ nouveau_dma_init(struct nouveau_channel *chan)
if (ret) if (ret)
return ret; return ret;
/* Create an NV_SW object for various sync purposes */
ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw);
if (ret)
return ret;
ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL);
if (ret)
return ret;
/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy);
if (ret) if (ret)
...@@ -87,6 +97,13 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -87,6 +97,13 @@ nouveau_dma_init(struct nouveau_channel *chan)
BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING(chan, NvNotify0); OUT_RING(chan, NvNotify0);
/* Initialise NV_SW */
ret = RING_SPACE(chan, 2);
if (ret)
return ret;
BEGIN_RING(chan, NvSubSw, 0, 1);
OUT_RING(chan, NvSw);
/* Sit back and pray the channel works.. */ /* Sit back and pray the channel works.. */
FIRE_RING(chan); FIRE_RING(chan);
......
...@@ -46,10 +46,11 @@ ...@@ -46,10 +46,11 @@
/* Hardcoded object assignments to subchannels (subchannel id). */ /* Hardcoded object assignments to subchannels (subchannel id). */
enum { enum {
NvSubM2MF = 0, NvSubM2MF = 0,
NvSub2D = 1, NvSubSw = 1,
NvSubCtxSurf2D = 1, NvSub2D = 2,
NvSubGdiRect = 2, NvSubCtxSurf2D = 2,
NvSubImageBlit = 3 NvSubGdiRect = 3,
NvSubImageBlit = 4
}; };
/* Object handles. */ /* Object handles. */
...@@ -67,6 +68,7 @@ enum { ...@@ -67,6 +68,7 @@ enum {
NvClipRect = 0x8000000b, NvClipRect = 0x8000000b,
NvGdiRect = 0x8000000c, NvGdiRect = 0x8000000c,
NvImageBlit = 0x8000000d, NvImageBlit = 0x8000000d,
NvSw = 0x8000000e,
/* G80+ display objects */ /* G80+ display objects */
NvEvoVRAM = 0x01000000, NvEvoVRAM = 0x01000000,
......
...@@ -788,6 +788,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, ...@@ -788,6 +788,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
uint32_t *o_ret); uint32_t *o_ret);
extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
struct nouveau_gpuobj **); struct nouveau_gpuobj **);
extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class,
struct nouveau_gpuobj **);
extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
struct drm_file *); struct drm_file *);
extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
...@@ -1330,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev) ...@@ -1330,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev)
return false; return false;
} }
#define NV50_NVSW 0x0000506e #define NV_SW 0x0000506e
#define NV50_NVSW_DMA_SEMAPHORE 0x00000060 #define NV_SW_DMA_SEMAPHORE 0x00000060
#define NV50_NVSW_SEMAPHORE_OFFSET 0x00000064 #define NV_SW_SEMAPHORE_OFFSET 0x00000064
#define NV50_NVSW_SEMAPHORE_ACQUIRE 0x00000068 #define NV_SW_SEMAPHORE_ACQUIRE 0x00000068
#define NV50_NVSW_SEMAPHORE_RELEASE 0x0000006c #define NV_SW_SEMAPHORE_RELEASE 0x0000006c
#define NV50_NVSW_DMA_VBLSEM 0x0000018c #define NV_SW_DMA_VBLSEM 0x0000018c
#define NV50_NVSW_VBLSEM_OFFSET 0x00000400 #define NV_SW_VBLSEM_OFFSET 0x00000400
#define NV50_NVSW_VBLSEM_RELEASE_VALUE 0x00000404 #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404
#define NV50_NVSW_VBLSEM_RELEASE 0x00000408 #define NV_SW_VBLSEM_RELEASE 0x00000408
#endif /* __NOUVEAU_DRV_H__ */ #endif /* __NOUVEAU_DRV_H__ */
...@@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, ...@@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
return 0; return 0;
} }
static int int
nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
struct nouveau_gpuobj **gpuobj_ret) struct nouveau_gpuobj **gpuobj_ret)
{ {
......
...@@ -184,6 +184,7 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -184,6 +184,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
struct drm_device *dev = par->dev; struct drm_device *dev = par->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel; struct nouveau_channel *chan = dev_priv->channel;
const int sub = NvSubCtxSurf2D;
int surface_fmt, pattern_fmt, rect_fmt; int surface_fmt, pattern_fmt, rect_fmt;
int ret; int ret;
...@@ -247,25 +248,25 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -247,25 +248,25 @@ nv04_fbcon_accel_init(struct fb_info *info)
return 0; return 0;
} }
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvCtxSurf2D); OUT_RING(chan, NvCtxSurf2D);
BEGIN_RING(chan, 1, 0x0184, 2); BEGIN_RING(chan, sub, 0x0184, 2);
OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB);
OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB);
BEGIN_RING(chan, 1, 0x0300, 4); BEGIN_RING(chan, sub, 0x0300, 4);
OUT_RING(chan, surface_fmt); OUT_RING(chan, surface_fmt);
OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16)); OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvRop); OUT_RING(chan, NvRop);
BEGIN_RING(chan, 1, 0x0300, 1); BEGIN_RING(chan, sub, 0x0300, 1);
OUT_RING(chan, 0x55); OUT_RING(chan, 0x55);
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvImagePatt); OUT_RING(chan, NvImagePatt);
BEGIN_RING(chan, 1, 0x0300, 8); BEGIN_RING(chan, sub, 0x0300, 8);
OUT_RING(chan, pattern_fmt); OUT_RING(chan, pattern_fmt);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
OUT_RING(chan, 2); OUT_RING(chan, 2);
...@@ -279,9 +280,9 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -279,9 +280,9 @@ nv04_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, ~0); OUT_RING(chan, ~0);
OUT_RING(chan, ~0); OUT_RING(chan, ~0);
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvClipRect); OUT_RING(chan, NvClipRect);
BEGIN_RING(chan, 1, 0x0300, 2); BEGIN_RING(chan, sub, 0x0300, 2);
OUT_RING(chan, 0); OUT_RING(chan, 0);
OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual); OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment