drm/nouveau: port all engines to new engine module format
[deliverable/linux.git] / drivers / gpu / drm / nouveau / core / engine / mpeg / nv31.c
CommitLineData
a02ccc7f 1/*
ebb945a9 2 * Copyright 2012 Red Hat Inc.
a02ccc7f
BS
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
ebb945a9
BS
25#include <core/os.h>
26#include <core/class.h>
27#include <core/engctx.h>
28#include <core/handle.h>
29#include <core/engine/graph/nv40.h>
a02ccc7f 30
ebb945a9
BS
31#include <subdev/fb.h>
32#include <subdev/timer.h>
33#include <subdev/instmem.h>
52d07331 34
ebb945a9 35#include <engine/mpeg.h>
a02ccc7f 36
ebb945a9
BS
37struct nv31_mpeg_priv {
38 struct nouveau_mpeg base;
39 atomic_t refcount;
40};
a02ccc7f 41
ebb945a9
BS
42struct nv31_mpeg_chan {
43 struct nouveau_object base;
44};
a02ccc7f 45
ebb945a9
BS
46/*******************************************************************************
47 * MPEG object classes
48 ******************************************************************************/
a02ccc7f
BS
49
50static int
ebb945a9
BS
51nv31_mpeg_object_ctor(struct nouveau_object *parent,
52 struct nouveau_object *engine,
53 struct nouveau_oclass *oclass, void *data, u32 size,
54 struct nouveau_object **pobject)
a02ccc7f 55{
ebb945a9 56 struct nouveau_gpuobj *obj;
a02ccc7f
BS
57 int ret;
58
ebb945a9
BS
59 ret = nouveau_gpuobj_create(parent, engine, oclass, 0, parent,
60 20, 16, 0, &obj);
61 *pobject = nv_object(obj);
a02ccc7f
BS
62 if (ret)
63 return ret;
a02ccc7f 64
ebb945a9
BS
65 nv_wo32(obj, 0x00, nv_mclass(obj));
66 nv_wo32(obj, 0x04, 0x00000000);
67 nv_wo32(obj, 0x08, 0x00000000);
68 nv_wo32(obj, 0x0c, 0x00000000);
a02ccc7f
BS
69 return 0;
70}
71
72static int
ebb945a9 73nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)
a02ccc7f 74{
ebb945a9
BS
75 struct nouveau_instmem *imem = nouveau_instmem(object);
76 struct nv31_mpeg_priv *priv = (void *)object->engine;
77 u32 inst = *(u32 *)arg << 4;
78 u32 dma0 = nv_ro32(imem, inst + 0);
79 u32 dma1 = nv_ro32(imem, inst + 4);
80 u32 dma2 = nv_ro32(imem, inst + 8);
a02ccc7f
BS
81 u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
82 u32 size = dma1 + 1;
83
84 /* only allow linear DMA objects */
85 if (!(dma0 & 0x00002000))
86 return -EINVAL;
87
88 if (mthd == 0x0190) {
89 /* DMA_CMD */
ebb945a9
BS
90 nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000));
91 nv_wr32(priv, 0x00b334, base);
92 nv_wr32(priv, 0x00b324, size);
a02ccc7f
BS
93 } else
94 if (mthd == 0x01a0) {
95 /* DMA_DATA */
ebb945a9
BS
96 nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
97 nv_wr32(priv, 0x00b360, base);
98 nv_wr32(priv, 0x00b364, size);
a02ccc7f
BS
99 } else {
100 /* DMA_IMAGE, VRAM only */
101 if (dma0 & 0x000c0000)
102 return -EINVAL;
103
ebb945a9
BS
104 nv_wr32(priv, 0x00b370, base);
105 nv_wr32(priv, 0x00b374, size);
a02ccc7f
BS
106 }
107
108 return 0;
109}
110
ebb945a9
BS
111struct nouveau_ofuncs
112nv31_mpeg_ofuncs = {
113 .ctor = nv31_mpeg_object_ctor,
114 .dtor = _nouveau_gpuobj_dtor,
115 .init = _nouveau_gpuobj_init,
116 .fini = _nouveau_gpuobj_fini,
117 .rd32 = _nouveau_gpuobj_rd32,
118 .wr32 = _nouveau_gpuobj_wr32,
119};
120
121struct nouveau_omthds
122nv31_mpeg_omthds[] = {
123 { 0x0190, nv31_mpeg_mthd_dma },
124 { 0x01a0, nv31_mpeg_mthd_dma },
125 { 0x01b0, nv31_mpeg_mthd_dma },
126 {}
127};
128
129struct nouveau_oclass
130nv31_mpeg_sclass[] = {
131 { 0x3174, &nv31_mpeg_ofuncs, nv31_mpeg_omthds },
132 {}
133};
134
135/*******************************************************************************
136 * PMPEG context
137 ******************************************************************************/
138
a02ccc7f 139static int
ebb945a9
BS
140nv31_mpeg_context_ctor(struct nouveau_object *parent,
141 struct nouveau_object *engine,
142 struct nouveau_oclass *oclass, void *data, u32 size,
143 struct nouveau_object **pobject)
a02ccc7f 144{
ebb945a9
BS
145 struct nv31_mpeg_priv *priv = (void *)engine;
146 struct nv31_mpeg_chan *chan;
147 int ret;
148
149 if (!atomic_add_unless(&priv->refcount, 1, 1))
150 return -EBUSY;
151
152 ret = nouveau_object_create(parent, engine, oclass, 0, &chan);
153 *pobject = nv_object(chan);
154 if (ret)
155 return ret;
156
157 return 0;
a02ccc7f
BS
158}
159
160static void
ebb945a9 161nv31_mpeg_context_dtor(struct nouveau_object *object)
a02ccc7f 162{
ebb945a9
BS
163 struct nv31_mpeg_priv *priv = (void *)object->engine;
164 struct nv31_mpeg_chan *chan = (void *)object;
165 atomic_dec(&priv->refcount);
166 nouveau_object_destroy(&chan->base);
a02ccc7f
BS
167}
168
ebb945a9
BS
169static struct nouveau_oclass
170nv31_mpeg_cclass = {
171 .handle = NV_ENGCTX(MPEG, 0x31),
172 .ofuncs = &(struct nouveau_ofuncs) {
173 .ctor = nv31_mpeg_context_ctor,
174 .dtor = nv31_mpeg_context_dtor,
175 .init = nouveau_object_init,
176 .fini = nouveau_object_fini,
177 },
178};
179
180/*******************************************************************************
181 * PMPEG engine/subdev functions
182 ******************************************************************************/
183
184void
185nv31_mpeg_tile_prog(struct nouveau_engine *engine, int i)
a02ccc7f 186{
ebb945a9
BS
187 struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i];
188 struct nv31_mpeg_priv *priv = (void *)engine;
189
190 nv_wr32(priv, 0x00b008 + (i * 0x10), tile->pitch);
191 nv_wr32(priv, 0x00b004 + (i * 0x10), tile->limit);
192 nv_wr32(priv, 0x00b000 + (i * 0x10), tile->addr);
193}
194
195void
196nv31_mpeg_intr(struct nouveau_subdev *subdev)
197{
198 struct nv31_mpeg_priv *priv = (void *)subdev;
199 struct nouveau_engine *engine = nv_engine(subdev);
200 struct nouveau_handle *handle = NULL;
201 u32 inst = (nv_rd32(priv, 0x00b318) & 0x000fffff) << 4;
202 u32 stat = nv_rd32(priv, 0x00b100);
203 u32 type = nv_rd32(priv, 0x00b230);
204 u32 mthd = nv_rd32(priv, 0x00b234);
205 u32 data = nv_rd32(priv, 0x00b238);
a02ccc7f
BS
206 u32 show = stat;
207
208 if (stat & 0x01000000) {
209 /* happens on initial binding of the object */
ebb945a9
BS
210 if (handle && type == 0x00000020 && mthd == 0x0000) {
211 nv_mask(priv, 0x00b308, 0x00000000, 0x00000000);
a02ccc7f
BS
212 show &= ~0x01000000;
213 }
214
ebb945a9
BS
215 if (handle && type == 0x00000010) {
216 handle = nouveau_engctx_lookup_class(engine, inst, 0x3174);
217
218 if (handle && !nv_call(handle->object, mthd, data)) {
219 nouveau_engctx_handle_put(handle);
a02ccc7f 220 show &= ~0x01000000;
ebb945a9 221 }
a02ccc7f
BS
222 }
223 }
224
ebb945a9
BS
225 nv_wr32(priv, 0x00b100, stat);
226 nv_wr32(priv, 0x00b230, 0x00000001);
a02ccc7f 227
ebb945a9
BS
228 if (show) {
229 nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
230 inst, stat, type, mthd, data);
a02ccc7f
BS
231 }
232}
233
ebb945a9
BS
234static int
235nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
236 struct nouveau_oclass *oclass, void *data, u32 size,
237 struct nouveau_object **pobject)
a02ccc7f 238{
ebb945a9
BS
239 struct nv31_mpeg_priv *priv;
240 int ret;
a02ccc7f 241
ebb945a9
BS
242 ret = nouveau_mpeg_create(parent, engine, oclass, &priv);
243 *pobject = nv_object(priv);
244 if (ret)
245 return ret;
246
247 nv_subdev(priv)->unit = 0x00000002;
248 nv_subdev(priv)->intr = nv31_mpeg_intr;
249 nv_engine(priv)->cclass = &nv31_mpeg_cclass;
250 nv_engine(priv)->sclass = nv31_mpeg_sclass;
251 nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog;
252 return 0;
a02ccc7f
BS
253}
254
ebb945a9
BS
255int
256nv31_mpeg_init(struct nouveau_object *object)
a02ccc7f 257{
ebb945a9
BS
258 struct nouveau_engine *engine = nv_engine(object->engine);
259 struct nv31_mpeg_priv *priv = (void *)engine;
260 struct nouveau_fb *pfb = nouveau_fb(object);
261 int ret, i;
a02ccc7f 262
ebb945a9
BS
263 ret = nouveau_mpeg_init(&priv->base);
264 if (ret)
265 return ret;
a02ccc7f 266
ebb945a9
BS
267 /* VPE init */
268 nv_wr32(priv, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
269 nv_wr32(priv, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
a02ccc7f 270
ebb945a9
BS
271 for (i = 0; i < pfb->tile.regions; i++)
272 engine->tile_prog(engine, i);
273
274 /* PMPEG init */
275 nv_wr32(priv, 0x00b32c, 0x00000000);
276 nv_wr32(priv, 0x00b314, 0x00000100);
277 nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031);
278 nv_wr32(priv, 0x00b300, 0x02001ec1);
279 nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
280
281 nv_wr32(priv, 0x00b100, 0xffffffff);
282 nv_wr32(priv, 0x00b140, 0xffffffff);
283
284 if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) {
285 nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200));
286 return -EBUSY;
52d07331 287 }
a02ccc7f 288
ebb945a9 289 return 0;
a02ccc7f 290}
ebb945a9
BS
291
292struct nouveau_oclass
293nv31_mpeg_oclass = {
294 .handle = NV_ENGINE(MPEG, 0x31),
295 .ofuncs = &(struct nouveau_ofuncs) {
296 .ctor = nv31_mpeg_ctor,
297 .dtor = _nouveau_mpeg_dtor,
298 .init = nv31_mpeg_init,
299 .fini = _nouveau_mpeg_fini,
300 },
301};
This page took 0.176291 seconds and 5 git commands to generate.