diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-06-23 02:44:05 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 02:03:44 -0400 |
commit | 52d073318a4c32865e6439f7f6c247092a6f6af3 (patch) | |
tree | 9b7df0397728b970025d12bba04304391d3edd37 /drivers/gpu | |
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')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv31_mpeg.c | 39 |
2 files changed, 40 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 93a2e83d0246..07691c2eceac 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -633,7 +633,10 @@ nouveau_card_init(struct drm_device *dev) | |||
633 | break; | 633 | break; |
634 | } | 634 | } |
635 | 635 | ||
636 | if (dev_priv->card_type == NV_40) | 636 | if (dev_priv->card_type == NV_40 || |
637 | dev_priv->chipset == 0x31 || | ||
638 | dev_priv->chipset == 0x34 || | ||
639 | dev_priv->chipset == 0x36) | ||
637 | nv31_mpeg_create(dev); | 640 | nv31_mpeg_create(dev); |
638 | else | 641 | else |
639 | if (dev_priv->card_type == NV_50 && | 642 | if (dev_priv->card_type == NV_50 && |
diff --git a/drivers/gpu/drm/nouveau/nv31_mpeg.c b/drivers/gpu/drm/nouveau/nv31_mpeg.c index 72e86660258d..6f06a0713f00 100644 --- a/drivers/gpu/drm/nouveau/nv31_mpeg.c +++ b/drivers/gpu/drm/nouveau/nv31_mpeg.c | |||
@@ -28,8 +28,30 @@ | |||
28 | 28 | ||
29 | struct nv31_mpeg_engine { | 29 | struct nv31_mpeg_engine { |
30 | struct nouveau_exec_engine base; | 30 | struct nouveau_exec_engine base; |
31 | atomic_t refcount; | ||
31 | }; | 32 | }; |
32 | 33 | ||
34 | |||
35 | static int | ||
36 | nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) | ||
37 | { | ||
38 | struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); | ||
39 | |||
40 | if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) | ||
41 | return -EBUSY; | ||
42 | |||
43 | chan->engctx[engine] = (void *)0xdeadcafe; | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static void | ||
48 | nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) | ||
49 | { | ||
50 | struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); | ||
51 | atomic_dec(&pmpeg->refcount); | ||
52 | chan->engctx[engine] = NULL; | ||
53 | } | ||
54 | |||
33 | static int | 55 | static int |
34 | nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) | 56 | nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) |
35 | { | 57 | { |
@@ -121,7 +143,7 @@ nv31_mpeg_init(struct drm_device *dev, int engine) | |||
121 | /* PMPEG init */ | 143 | /* PMPEG init */ |
122 | nv_wr32(dev, 0x00b32c, 0x00000000); | 144 | nv_wr32(dev, 0x00b32c, 0x00000000); |
123 | nv_wr32(dev, 0x00b314, 0x00000100); | 145 | nv_wr32(dev, 0x00b314, 0x00000100); |
124 | nv_wr32(dev, 0x00b220, 0x00000044); | 146 | nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); |
125 | nv_wr32(dev, 0x00b300, 0x02001ec1); | 147 | nv_wr32(dev, 0x00b300, 0x02001ec1); |
126 | nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); | 148 | nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); |
127 | 149 | ||
@@ -191,6 +213,10 @@ nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) | |||
191 | unsigned long flags; | 213 | unsigned long flags; |
192 | int i; | 214 | int i; |
193 | 215 | ||
216 | /* hardcode drm channel id on nv3x, so swmthd lookup works */ | ||
217 | if (dev_priv->card_type < NV_40) | ||
218 | return 0; | ||
219 | |||
194 | spin_lock_irqsave(&dev_priv->channels.lock, flags); | 220 | spin_lock_irqsave(&dev_priv->channels.lock, flags); |
195 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { | 221 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { |
196 | if (!dev_priv->channels.ptr[i]) | 222 | if (!dev_priv->channels.ptr[i]) |
@@ -275,17 +301,24 @@ nv31_mpeg_destroy(struct drm_device *dev, int engine) | |||
275 | int | 301 | int |
276 | nv31_mpeg_create(struct drm_device *dev) | 302 | nv31_mpeg_create(struct drm_device *dev) |
277 | { | 303 | { |
304 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
278 | struct nv31_mpeg_engine *pmpeg; | 305 | struct nv31_mpeg_engine *pmpeg; |
279 | 306 | ||
280 | pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); | 307 | pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); |
281 | if (!pmpeg) | 308 | if (!pmpeg) |
282 | return -ENOMEM; | 309 | return -ENOMEM; |
310 | atomic_set(&pmpeg->refcount, 0); | ||
283 | 311 | ||
284 | pmpeg->base.destroy = nv31_mpeg_destroy; | 312 | pmpeg->base.destroy = nv31_mpeg_destroy; |
285 | pmpeg->base.init = nv31_mpeg_init; | 313 | pmpeg->base.init = nv31_mpeg_init; |
286 | pmpeg->base.fini = nv31_mpeg_fini; | 314 | pmpeg->base.fini = nv31_mpeg_fini; |
287 | pmpeg->base.context_new = nv40_mpeg_context_new; | 315 | if (dev_priv->card_type < NV_40) { |
288 | pmpeg->base.context_del = nv40_mpeg_context_del; | 316 | pmpeg->base.context_new = nv31_mpeg_context_new; |
317 | pmpeg->base.context_del = nv31_mpeg_context_del; | ||
318 | } else { | ||
319 | pmpeg->base.context_new = nv40_mpeg_context_new; | ||
320 | pmpeg->base.context_del = nv40_mpeg_context_del; | ||
321 | } | ||
289 | pmpeg->base.object_new = nv31_mpeg_object_new; | 322 | pmpeg->base.object_new = nv31_mpeg_object_new; |
290 | 323 | ||
291 | /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between | 324 | /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between |