Merge branch '3.2-without-smb2' of git://git.samba.org/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nv31_mpeg.c
1 /*
2  * Copyright 2011 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24
25 #include "drmP.h"
26 #include "nouveau_drv.h"
27 #include "nouveau_ramht.h"
28
29 struct nv31_mpeg_engine {
30         struct nouveau_exec_engine base;
31         atomic_t refcount;
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
55 static int
56 nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
57 {
58         struct drm_device *dev = chan->dev;
59         struct drm_nouveau_private *dev_priv = dev->dev_private;
60         struct nouveau_gpuobj *ctx = NULL;
61         unsigned long flags;
62         int ret;
63
64         NV_DEBUG(dev, "ch%d\n", chan->id);
65
66         ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
67                                  NVOBJ_FLAG_ZERO_FREE, &ctx);
68         if (ret)
69                 return ret;
70
71         nv_wo32(ctx, 0x78, 0x02001ec1);
72
73         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
74         nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
75         if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
76                 nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
77         nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
78         nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
79         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
80
81         chan->engctx[engine] = ctx;
82         return 0;
83 }
84
85 static void
86 nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
87 {
88         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
89         struct nouveau_gpuobj *ctx = chan->engctx[engine];
90         struct drm_device *dev = chan->dev;
91         unsigned long flags;
92         u32 inst = 0x80000000 | (ctx->pinst >> 4);
93
94         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
95         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
96         if (nv_rd32(dev, 0x00b318) == inst)
97                 nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
98         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
99         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
100
101         nouveau_gpuobj_ref(NULL, &ctx);
102         chan->engctx[engine] = NULL;
103 }
104
105 static int
106 nv31_mpeg_object_new(struct nouveau_channel *chan, int engine,
107                       u32 handle, u16 class)
108 {
109         struct drm_device *dev = chan->dev;
110         struct nouveau_gpuobj *obj = NULL;
111         int ret;
112
113         ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
114                                  NVOBJ_FLAG_ZERO_FREE, &obj);
115         if (ret)
116                 return ret;
117         obj->engine = 2;
118         obj->class  = class;
119
120         nv_wo32(obj, 0x00, class);
121
122         ret = nouveau_ramht_insert(chan, handle, obj);
123         nouveau_gpuobj_ref(NULL, &obj);
124         return ret;
125 }
126
127 static int
128 nv31_mpeg_init(struct drm_device *dev, int engine)
129 {
130         struct drm_nouveau_private *dev_priv = dev->dev_private;
131         struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
132         int i;
133
134         /* VPE init */
135         nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
136         nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
137         nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
138         nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
139
140         for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
141                 pmpeg->base.set_tile_region(dev, i);
142
143         /* PMPEG init */
144         nv_wr32(dev, 0x00b32c, 0x00000000);
145         nv_wr32(dev, 0x00b314, 0x00000100);
146         nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031);
147         nv_wr32(dev, 0x00b300, 0x02001ec1);
148         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
149
150         nv_wr32(dev, 0x00b100, 0xffffffff);
151         nv_wr32(dev, 0x00b140, 0xffffffff);
152
153         if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
154                 NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
155                 return -EBUSY;
156         }
157
158         return 0;
159 }
160
161 static int
162 nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
163 {
164         /*XXX: context save? */
165         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
166         nv_wr32(dev, 0x00b140, 0x00000000);
167         return 0;
168 }
169
170 static int
171 nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
172 {
173         struct drm_device *dev = chan->dev;
174         u32 inst = data << 4;
175         u32 dma0 = nv_ri32(dev, inst + 0);
176         u32 dma1 = nv_ri32(dev, inst + 4);
177         u32 dma2 = nv_ri32(dev, inst + 8);
178         u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
179         u32 size = dma1 + 1;
180
181         /* only allow linear DMA objects */
182         if (!(dma0 & 0x00002000))
183                 return -EINVAL;
184
185         if (mthd == 0x0190) {
186                 /* DMA_CMD */
187                 nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
188                 nv_wr32(dev, 0x00b334, base);
189                 nv_wr32(dev, 0x00b324, size);
190         } else
191         if (mthd == 0x01a0) {
192                 /* DMA_DATA */
193                 nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
194                 nv_wr32(dev, 0x00b360, base);
195                 nv_wr32(dev, 0x00b364, size);
196         } else {
197                 /* DMA_IMAGE, VRAM only */
198                 if (dma0 & 0x000c0000)
199                         return -EINVAL;
200
201                 nv_wr32(dev, 0x00b370, base);
202                 nv_wr32(dev, 0x00b374, size);
203         }
204
205         return 0;
206 }
207
208 static int
209 nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst)
210 {
211         struct drm_nouveau_private *dev_priv = dev->dev_private;
212         struct nouveau_gpuobj *ctx;
213         unsigned long flags;
214         int i;
215
216         /* hardcode drm channel id on nv3x, so swmthd lookup works */
217         if (dev_priv->card_type < NV_40)
218                 return 0;
219
220         spin_lock_irqsave(&dev_priv->channels.lock, flags);
221         for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
222                 if (!dev_priv->channels.ptr[i])
223                         continue;
224
225                 ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
226                 if (ctx && ctx->pinst == inst)
227                         break;
228         }
229         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
230         return i;
231 }
232
233 static void
234 nv31_vpe_set_tile_region(struct drm_device *dev, int i)
235 {
236         struct drm_nouveau_private *dev_priv = dev->dev_private;
237         struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
238
239         nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
240         nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
241         nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
242 }
243
244 static void
245 nv31_mpeg_isr(struct drm_device *dev)
246 {
247         u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
248         u32 chid = nv31_mpeg_isr_chid(dev, inst);
249         u32 stat = nv_rd32(dev, 0x00b100);
250         u32 type = nv_rd32(dev, 0x00b230);
251         u32 mthd = nv_rd32(dev, 0x00b234);
252         u32 data = nv_rd32(dev, 0x00b238);
253         u32 show = stat;
254
255         if (stat & 0x01000000) {
256                 /* happens on initial binding of the object */
257                 if (type == 0x00000020 && mthd == 0x0000) {
258                         nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
259                         show &= ~0x01000000;
260                 }
261
262                 if (type == 0x00000010) {
263                         if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
264                                 show &= ~0x01000000;
265                 }
266         }
267
268         nv_wr32(dev, 0x00b100, stat);
269         nv_wr32(dev, 0x00b230, 0x00000001);
270
271         if (show && nouveau_ratelimit()) {
272                 NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
273                         chid, inst, stat, type, mthd, data);
274         }
275 }
276
277 static void
278 nv31_vpe_isr(struct drm_device *dev)
279 {
280         if (nv_rd32(dev, 0x00b100))
281                 nv31_mpeg_isr(dev);
282
283         if (nv_rd32(dev, 0x00b800)) {
284                 u32 stat = nv_rd32(dev, 0x00b800);
285                 NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
286                 nv_wr32(dev, 0xb800, stat);
287         }
288 }
289
290 static void
291 nv31_mpeg_destroy(struct drm_device *dev, int engine)
292 {
293         struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
294
295         nouveau_irq_unregister(dev, 0);
296
297         NVOBJ_ENGINE_DEL(dev, MPEG);
298         kfree(pmpeg);
299 }
300
301 int
302 nv31_mpeg_create(struct drm_device *dev)
303 {
304         struct drm_nouveau_private *dev_priv = dev->dev_private;
305         struct nv31_mpeg_engine *pmpeg;
306
307         pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
308         if (!pmpeg)
309                 return -ENOMEM;
310         atomic_set(&pmpeg->refcount, 0);
311
312         pmpeg->base.destroy = nv31_mpeg_destroy;
313         pmpeg->base.init = nv31_mpeg_init;
314         pmpeg->base.fini = nv31_mpeg_fini;
315         if (dev_priv->card_type < NV_40) {
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         }
322         pmpeg->base.object_new = nv31_mpeg_object_new;
323
324         /* ISR vector, PMC_ENABLE bit,  and TILE regs are shared between
325          * all VPE engines, for this driver's purposes the PMPEG engine
326          * will be treated as the "master" and handle the global VPE
327          * bits too
328          */
329         pmpeg->base.set_tile_region = nv31_vpe_set_tile_region;
330         nouveau_irq_register(dev, 0, nv31_vpe_isr);
331
332         NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
333         NVOBJ_CLASS(dev, 0x3174, MPEG);
334         NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma);
335         NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma);
336         NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma);
337
338 #if 0
339         NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
340         NVOBJ_CLASS(dev, 0x4075, ME);
341 #endif
342         return 0;
343
344 }