diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-06-23 16:44:05 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 16:03:44 +1000 |
commit | 52d073318a4c32865e6439f7f6c247092a6f6af3 (patch) | |
tree | 9b7df0397728b970025d12bba04304391d3edd37 /drivers/gpu/drm/nouveau/nv31_mpeg.c | |
parent | 323dcac552b39884cdeff26a38d5dd80854795a1 (diff) |
drm/nv31/mpeg: support for a single class3174 user
Uncertain if/how the hw does multiple PMPEG channels, supporting one is
better than none however.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv31_mpeg.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv31_mpeg.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/gpu/drm/nouveau/nv31_mpeg.c b/drivers/gpu/drm/nouveau/nv31_mpeg.c index 72e86660258..6f06a0713f0 100644 --- a/drivers/gpu/drm/nouveau/nv31_mpeg.c +++ b/drivers/gpu/drm/nouveau/nv31_mpeg.c @@ -28,8 +28,30 @@ struct nv31_mpeg_engine { struct nouveau_exec_engine base; + atomic_t refcount; }; + +static int +nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) +{ + struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); + + if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) + return -EBUSY; + + chan->engctx[engine] = (void *)0xdeadcafe; + return 0; +} + +static void +nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) +{ + struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); + atomic_dec(&pmpeg->refcount); + chan->engctx[engine] = NULL; +} + static int nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) { @@ -121,7 +143,7 @@ nv31_mpeg_init(struct drm_device *dev, int engine) /* PMPEG init */ nv_wr32(dev, 0x00b32c, 0x00000000); nv_wr32(dev, 0x00b314, 0x00000100); - nv_wr32(dev, 0x00b220, 0x00000044); + nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); nv_wr32(dev, 0x00b300, 0x02001ec1); nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); @@ -191,6 +213,10 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) unsigned long flags; int i; + /* hardcode drm channel id on nv3x, so swmthd lookup works */ + if (dev_priv->card_type < NV_40) + return 0; + spin_lock_irqsave(&dev_priv->channels.lock, flags); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { if (!dev_priv->channels.ptr[i]) @@ -275,17 +301,24 @@ nv31_mpeg_destroy(struct drm_device *dev, int engine) int nv31_mpeg_create(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv31_mpeg_engine *pmpeg; pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); if (!pmpeg) return -ENOMEM; + atomic_set(&pmpeg->refcount, 0); pmpeg->base.destroy = nv31_mpeg_destroy; pmpeg->base.init = nv31_mpeg_init; pmpeg->base.fini = nv31_mpeg_fini; - pmpeg->base.context_new = nv40_mpeg_context_new; - pmpeg->base.context_del = nv40_mpeg_context_del; + if (dev_priv->card_type < NV_40) { + pmpeg->base.context_new = nv31_mpeg_context_new; + pmpeg->base.context_del = nv31_mpeg_context_del; + } else { + pmpeg->base.context_new = nv40_mpeg_context_new; + pmpeg->base.context_del = nv40_mpeg_context_del; + } pmpeg->base.object_new = nv31_mpeg_object_new; /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between |