Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nv40_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 nv40_mpeg_engine {
30         struct nouveau_exec_engine base;
31 };
32
33 static int
34 nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
35 {
36         struct drm_device *dev = chan->dev;
37         struct drm_nouveau_private *dev_priv = dev->dev_private;
38         struct nouveau_gpuobj *ctx = NULL;
39         unsigned long flags;
40         int ret;
41
42         NV_DEBUG(dev, "ch%d\n", chan->id);
43
44         ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
45                                  NVOBJ_FLAG_ZERO_FREE, &ctx);
46         if (ret)
47                 return ret;
48
49         nv_wo32(ctx, 0x78, 0x02001ec1);
50
51         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
52         nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
53         if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
54                 nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
55         nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
56         nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
57         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
58
59         chan->engctx[engine] = ctx;
60         return 0;
61 }
62
63 static void
64 nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
65 {
66         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
67         struct nouveau_gpuobj *ctx = chan->engctx[engine];
68         struct drm_device *dev = chan->dev;
69         unsigned long flags;
70         u32 inst = 0x80000000 | (ctx->pinst >> 4);
71
72         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
73         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
74         if (nv_rd32(dev, 0x00b318) == inst)
75                 nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
76         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
77         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
78
79         nouveau_gpuobj_ref(NULL, &ctx);
80         chan->engctx[engine] = NULL;
81 }
82
83 static int
84 nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
85                       u32 handle, u16 class)
86 {
87         struct drm_device *dev = chan->dev;
88         struct nouveau_gpuobj *obj = NULL;
89         int ret;
90
91         ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
92                                  NVOBJ_FLAG_ZERO_FREE, &obj);
93         if (ret)
94                 return ret;
95         obj->engine = 2;
96         obj->class  = class;
97
98         nv_wo32(obj, 0x00, class);
99
100         ret = nouveau_ramht_insert(chan, handle, obj);
101         nouveau_gpuobj_ref(NULL, &obj);
102         return ret;
103 }
104
105 static int
106 nv40_mpeg_init(struct drm_device *dev, int engine)
107 {
108         struct drm_nouveau_private *dev_priv = dev->dev_private;
109         struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
110         int i;
111
112         /* VPE init */
113         nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
114         nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
115         nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
116         nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
117
118         for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
119                 pmpeg->base.set_tile_region(dev, i);
120
121         /* PMPEG init */
122         nv_wr32(dev, 0x00b32c, 0x00000000);
123         nv_wr32(dev, 0x00b314, 0x00000100);
124         nv_wr32(dev, 0x00b220, 0x00000044);
125         nv_wr32(dev, 0x00b300, 0x02001ec1);
126         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
127
128         nv_wr32(dev, 0x00b100, 0xffffffff);
129         nv_wr32(dev, 0x00b140, 0xffffffff);
130
131         if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
132                 NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
133                 return -EBUSY;
134         }
135
136         return 0;
137 }
138
139 static int
140 nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
141 {
142         /*XXX: context save? */
143         nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
144         nv_wr32(dev, 0x00b140, 0x00000000);
145         return 0;
146 }
147
148 static int
149 nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
150 {
151         struct drm_device *dev = chan->dev;
152         u32 inst = data << 4;
153         u32 dma0 = nv_ri32(dev, inst + 0);
154         u32 dma1 = nv_ri32(dev, inst + 4);
155         u32 dma2 = nv_ri32(dev, inst + 8);
156         u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
157         u32 size = dma1 + 1;
158
159         /* only allow linear DMA objects */
160         if (!(dma0 & 0x00002000))
161                 return -EINVAL;
162
163         if (mthd == 0x0190) {
164                 /* DMA_CMD */
165                 nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
166                 nv_wr32(dev, 0x00b334, base);
167                 nv_wr32(dev, 0x00b324, size);
168         } else
169         if (mthd == 0x01a0) {
170                 /* DMA_DATA */
171                 nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
172                 nv_wr32(dev, 0x00b360, base);
173                 nv_wr32(dev, 0x00b364, size);
174         } else {
175                 /* DMA_IMAGE, VRAM only */
176                 if (dma0 & 0x000c0000)
177                         return -EINVAL;
178
179                 nv_wr32(dev, 0x00b370, base);
180                 nv_wr32(dev, 0x00b374, size);
181         }
182
183         return 0;
184 }
185
186 static int
187 nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
188 {
189         struct drm_nouveau_private *dev_priv = dev->dev_private;
190         struct nouveau_gpuobj *ctx;
191         unsigned long flags;
192         int i;
193
194         spin_lock_irqsave(&dev_priv->channels.lock, flags);
195         for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
196                 if (!dev_priv->channels.ptr[i])
197                         continue;
198
199                 ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
200                 if (ctx && ctx->pinst == inst)
201                         break;
202         }
203         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
204         return i;
205 }
206
207 static void
208 nv40_vpe_set_tile_region(struct drm_device *dev, int i)
209 {
210         struct drm_nouveau_private *dev_priv = dev->dev_private;
211         struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
212
213         nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
214         nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
215         nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
216 }
217
218 static void
219 nv40_mpeg_isr(struct drm_device *dev)
220 {
221         u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
222         u32 chid = nv40_mpeg_isr_chid(dev, inst);
223         u32 stat = nv_rd32(dev, 0x00b100);
224         u32 type = nv_rd32(dev, 0x00b230);
225         u32 mthd = nv_rd32(dev, 0x00b234);
226         u32 data = nv_rd32(dev, 0x00b238);
227         u32 show = stat;
228
229         if (stat & 0x01000000) {
230                 /* happens on initial binding of the object */
231                 if (type == 0x00000020 && mthd == 0x0000) {
232                         nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
233                         show &= ~0x01000000;
234                 }
235
236                 if (type == 0x00000010) {
237                         if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
238                                 show &= ~0x01000000;
239                 }
240         }
241
242         nv_wr32(dev, 0x00b100, stat);
243         nv_wr32(dev, 0x00b230, 0x00000001);
244
245         if (show && nouveau_ratelimit()) {
246                 NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
247                         chid, inst, stat, type, mthd, data);
248         }
249 }
250
251 static void
252 nv40_vpe_isr(struct drm_device *dev)
253 {
254         if (nv_rd32(dev, 0x00b100))
255                 nv40_mpeg_isr(dev);
256
257         if (nv_rd32(dev, 0x00b800)) {
258                 u32 stat = nv_rd32(dev, 0x00b800);
259                 NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
260                 nv_wr32(dev, 0xb800, stat);
261         }
262 }
263
264 static void
265 nv40_mpeg_destroy(struct drm_device *dev, int engine)
266 {
267         struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
268
269         nouveau_irq_unregister(dev, 0);
270
271         NVOBJ_ENGINE_DEL(dev, MPEG);
272         kfree(pmpeg);
273 }
274
275 int
276 nv40_mpeg_create(struct drm_device *dev)
277 {
278         struct nv40_mpeg_engine *pmpeg;
279
280         pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
281         if (!pmpeg)
282                 return -ENOMEM;
283
284         pmpeg->base.destroy = nv40_mpeg_destroy;
285         pmpeg->base.init = nv40_mpeg_init;
286         pmpeg->base.fini = nv40_mpeg_fini;
287         pmpeg->base.context_new = nv40_mpeg_context_new;
288         pmpeg->base.context_del = nv40_mpeg_context_del;
289         pmpeg->base.object_new = nv40_mpeg_object_new;
290
291         /* ISR vector, PMC_ENABLE bit,  and TILE regs are shared between
292          * all VPE engines, for this driver's purposes the PMPEG engine
293          * will be treated as the "master" and handle the global VPE
294          * bits too
295          */
296         pmpeg->base.set_tile_region = nv40_vpe_set_tile_region;
297         nouveau_irq_register(dev, 0, nv40_vpe_isr);
298
299         NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
300         NVOBJ_CLASS(dev, 0x3174, MPEG);
301         NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma);
302         NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma);
303         NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma);
304
305 #if 0
306         NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
307         NVOBJ_CLASS(dev, 0x4075, ME);
308 #endif
309         return 0;
310
311 }