2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
25 #include <core/client.h>
26 #include <core/engctx.h>
27 #include <core/ramht.h>
28 #include <core/class.h>
29 #include <core/math.h>
31 #include <subdev/timer.h>
32 #include <subdev/bar.h>
34 #include <engine/dmaobj.h>
35 #include <engine/fifo.h>
39 /*******************************************************************************
40 * FIFO channel objects
41 ******************************************************************************/
44 nv50_fifo_playlist_update(struct nv50_fifo_priv
*priv
)
46 struct nouveau_bar
*bar
= nouveau_bar(priv
);
47 struct nouveau_gpuobj
*cur
;
50 cur
= priv
->playlist
[priv
->cur_playlist
];
51 priv
->cur_playlist
= !priv
->cur_playlist
;
53 for (i
= priv
->base
.min
, p
= 0; i
< priv
->base
.max
; i
++) {
54 if (nv_rd32(priv
, 0x002600 + (i
* 4)) & 0x80000000)
55 nv_wo32(cur
, p
++ * 4, i
);
60 nv_wr32(priv
, 0x0032f4, cur
->addr
>> 12);
61 nv_wr32(priv
, 0x0032ec, p
);
62 nv_wr32(priv
, 0x002500, 0x00000101);
66 nv50_fifo_context_attach(struct nouveau_object
*parent
,
67 struct nouveau_object
*object
)
69 struct nouveau_bar
*bar
= nouveau_bar(parent
);
70 struct nv50_fifo_base
*base
= (void *)parent
->parent
;
71 struct nouveau_gpuobj
*ectx
= (void *)object
;
72 u64 limit
= ectx
->addr
+ ectx
->size
- 1;
73 u64 start
= ectx
->addr
;
76 switch (nv_engidx(object
->engine
)) {
77 case NVDEV_ENGINE_SW
: return 0;
78 case NVDEV_ENGINE_GR
: addr
= 0x0000; break;
79 case NVDEV_ENGINE_MPEG
: addr
= 0x0060; break;
84 nv_wo32(base
->eng
, addr
+ 0x00, 0x00190000);
85 nv_wo32(base
->eng
, addr
+ 0x04, lower_32_bits(limit
));
86 nv_wo32(base
->eng
, addr
+ 0x08, lower_32_bits(start
));
87 nv_wo32(base
->eng
, addr
+ 0x0c, upper_32_bits(limit
) << 24 |
88 upper_32_bits(start
));
89 nv_wo32(base
->eng
, addr
+ 0x10, 0x00000000);
90 nv_wo32(base
->eng
, addr
+ 0x14, 0x00000000);
96 nv50_fifo_context_detach(struct nouveau_object
*parent
, bool suspend
,
97 struct nouveau_object
*object
)
99 struct nouveau_bar
*bar
= nouveau_bar(parent
);
100 struct nv50_fifo_priv
*priv
= (void *)parent
->engine
;
101 struct nv50_fifo_base
*base
= (void *)parent
->parent
;
102 struct nv50_fifo_chan
*chan
= (void *)parent
;
106 switch (nv_engidx(object
->engine
)) {
107 case NVDEV_ENGINE_SW
: return 0;
108 case NVDEV_ENGINE_GR
: addr
= 0x0000; break;
109 case NVDEV_ENGINE_MPEG
: addr
= 0x0060; break;
114 nv_wo32(base
->eng
, addr
+ 0x00, 0x00000000);
115 nv_wo32(base
->eng
, addr
+ 0x04, 0x00000000);
116 nv_wo32(base
->eng
, addr
+ 0x08, 0x00000000);
117 nv_wo32(base
->eng
, addr
+ 0x0c, 0x00000000);
118 nv_wo32(base
->eng
, addr
+ 0x10, 0x00000000);
119 nv_wo32(base
->eng
, addr
+ 0x14, 0x00000000);
122 /* HW bug workaround:
124 * PFIFO will hang forever if the connected engines don't report
125 * that they've processed the context switch request.
127 * In order for the kickoff to work, we need to ensure all the
128 * connected engines are in a state where they can answer.
130 * Newer chipsets don't seem to suffer from this issue, and well,
131 * there's also a "ignore these engines" bitmask reg we can use
132 * if we hit the issue there..
134 me
= nv_mask(priv
, 0x00b860, 0x00000001, 0x00000001);
136 /* do the kickoff... */
137 nv_wr32(priv
, 0x0032fc, nv_gpuobj(base
)->addr
>> 12);
138 if (!nv_wait_ne(priv
, 0x0032fc, 0xffffffff, 0xffffffff)) {
139 nv_error(priv
, "channel %d unload timeout\n", chan
->base
.chid
);
144 nv_wr32(priv
, 0x00b860, me
);
149 nv50_fifo_object_attach(struct nouveau_object
*parent
,
150 struct nouveau_object
*object
, u32 handle
)
152 struct nv50_fifo_chan
*chan
= (void *)parent
;
155 if (nv_iclass(object
, NV_GPUOBJ_CLASS
))
156 context
= nv_gpuobj(object
)->node
->offset
>> 4;
158 context
= 0x00000004; /* just non-zero */
160 switch (nv_engidx(object
->engine
)) {
161 case NVDEV_ENGINE_DMAOBJ
:
162 case NVDEV_ENGINE_SW
: context
|= 0x00000000; break;
163 case NVDEV_ENGINE_GR
: context
|= 0x00100000; break;
164 case NVDEV_ENGINE_MPEG
: context
|= 0x00200000; break;
169 return nouveau_ramht_insert(chan
->ramht
, 0, handle
, context
);
173 nv50_fifo_object_detach(struct nouveau_object
*parent
, int cookie
)
175 struct nv50_fifo_chan
*chan
= (void *)parent
;
176 nouveau_ramht_remove(chan
->ramht
, cookie
);
180 nv50_fifo_chan_ctor(struct nouveau_object
*parent
,
181 struct nouveau_object
*engine
,
182 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
183 struct nouveau_object
**pobject
)
185 struct nv_channel_ind_class
*args
= data
;
186 struct nouveau_bar
*bar
= nouveau_bar(parent
);
187 struct nv50_fifo_base
*base
= (void *)parent
;
188 struct nv50_fifo_chan
*chan
;
189 u64 ioffset
, ilength
;
192 if (size
< sizeof(*args
))
195 ret
= nouveau_fifo_channel_create(parent
, engine
, oclass
, 0, 0xc00000,
196 0x2000, args
->pushbuf
,
197 (1 << NVDEV_ENGINE_DMAOBJ
) |
198 (1 << NVDEV_ENGINE_SW
) |
199 (1 << NVDEV_ENGINE_GR
) |
200 (1 << NVDEV_ENGINE_MPEG
), &chan
);
201 *pobject
= nv_object(chan
);
205 nv_parent(chan
)->context_attach
= nv50_fifo_context_attach
;
206 nv_parent(chan
)->context_detach
= nv50_fifo_context_detach
;
207 nv_parent(chan
)->object_attach
= nv50_fifo_object_attach
;
208 nv_parent(chan
)->object_detach
= nv50_fifo_object_detach
;
210 ret
= nouveau_ramht_new(parent
, parent
, 0x8000, 16, &chan
->ramht
);
214 ioffset
= args
->ioffset
;
215 ilength
= log2i(args
->ilength
/ 8);
217 nv_wo32(base
->ramfc
, 0x3c, 0x403f6078);
218 nv_wo32(base
->ramfc
, 0x44, 0x01003fff);
219 nv_wo32(base
->ramfc
, 0x48, chan
->base
.pushgpu
->node
->offset
>> 4);
220 nv_wo32(base
->ramfc
, 0x50, lower_32_bits(ioffset
));
221 nv_wo32(base
->ramfc
, 0x54, upper_32_bits(ioffset
) | (ilength
<< 16));
222 nv_wo32(base
->ramfc
, 0x60, 0x7fffffff);
223 nv_wo32(base
->ramfc
, 0x78, 0x00000000);
224 nv_wo32(base
->ramfc
, 0x7c, 0x30000001);
225 nv_wo32(base
->ramfc
, 0x80, ((chan
->ramht
->bits
- 9) << 27) |
226 (4 << 24) /* SEARCH_FULL */ |
227 (chan
->ramht
->base
.node
->offset
>> 4));
233 nv50_fifo_chan_dtor(struct nouveau_object
*object
)
235 struct nv50_fifo_chan
*chan
= (void *)object
;
236 nouveau_ramht_ref(NULL
, &chan
->ramht
);
237 nouveau_fifo_channel_destroy(&chan
->base
);
241 nv50_fifo_chan_init(struct nouveau_object
*object
)
243 struct nv50_fifo_priv
*priv
= (void *)object
->engine
;
244 struct nv50_fifo_base
*base
= (void *)object
->parent
;
245 struct nv50_fifo_chan
*chan
= (void *)object
;
246 struct nouveau_gpuobj
*ramfc
= base
->ramfc
;
247 u32 chid
= chan
->base
.chid
;
250 ret
= nouveau_fifo_channel_init(&chan
->base
);
254 nv_wr32(priv
, 0x002600 + (chid
* 4), 0x80000000 | ramfc
->addr
>> 12);
255 nv50_fifo_playlist_update(priv
);
260 nv50_fifo_chan_fini(struct nouveau_object
*object
, bool suspend
)
262 struct nv50_fifo_priv
*priv
= (void *)object
->engine
;
263 struct nv50_fifo_chan
*chan
= (void *)object
;
264 u32 chid
= chan
->base
.chid
;
266 /* remove channel from playlist, fifo will unload context */
267 nv_mask(priv
, 0x002600 + (chid
* 4), 0x80000000, 0x00000000);
268 nv50_fifo_playlist_update(priv
);
269 nv_wr32(priv
, 0x002600 + (chid
* 4), 0x00000000);
271 return nouveau_fifo_channel_fini(&chan
->base
, suspend
);
274 static struct nouveau_ofuncs
276 .ctor
= nv50_fifo_chan_ctor
,
277 .dtor
= nv50_fifo_chan_dtor
,
278 .init
= nv50_fifo_chan_init
,
279 .fini
= nv50_fifo_chan_fini
,
280 .rd32
= _nouveau_fifo_channel_rd32
,
281 .wr32
= _nouveau_fifo_channel_wr32
,
284 static struct nouveau_oclass
285 nv50_fifo_sclass
[] = {
286 { 0x506f, &nv50_fifo_ofuncs
},
290 /*******************************************************************************
291 * FIFO context - basically just the instmem reserved for the channel
292 ******************************************************************************/
295 nv50_fifo_context_ctor(struct nouveau_object
*parent
,
296 struct nouveau_object
*engine
,
297 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
298 struct nouveau_object
**pobject
)
300 struct nv50_fifo_base
*base
;
303 ret
= nouveau_fifo_context_create(parent
, engine
, oclass
, NULL
, 0x10000,
304 0x1000, NVOBJ_FLAG_HEAP
, &base
);
305 *pobject
= nv_object(base
);
309 ret
= nouveau_gpuobj_new(parent
, nv_object(base
), 0x0200, 0x1000,
310 NVOBJ_FLAG_ZERO_ALLOC
, &base
->ramfc
);
314 ret
= nouveau_gpuobj_new(parent
, nv_object(base
), 0x1200, 0,
315 NVOBJ_FLAG_ZERO_ALLOC
, &base
->eng
);
319 ret
= nouveau_gpuobj_new(parent
, nv_object(base
), 0x4000, 0, 0,
324 ret
= nouveau_vm_ref(nouveau_client(parent
)->vm
, &base
->vm
, base
->pgd
);
332 nv50_fifo_context_dtor(struct nouveau_object
*object
)
334 struct nv50_fifo_base
*base
= (void *)object
;
335 nouveau_vm_ref(NULL
, &base
->vm
, base
->pgd
);
336 nouveau_gpuobj_ref(NULL
, &base
->pgd
);
337 nouveau_gpuobj_ref(NULL
, &base
->eng
);
338 nouveau_gpuobj_ref(NULL
, &base
->ramfc
);
339 nouveau_gpuobj_ref(NULL
, &base
->cache
);
340 nouveau_fifo_context_destroy(&base
->base
);
343 static struct nouveau_oclass
345 .handle
= NV_ENGCTX(FIFO
, 0x50),
346 .ofuncs
= &(struct nouveau_ofuncs
) {
347 .ctor
= nv50_fifo_context_ctor
,
348 .dtor
= nv50_fifo_context_dtor
,
349 .init
= _nouveau_fifo_context_init
,
350 .fini
= _nouveau_fifo_context_fini
,
351 .rd32
= _nouveau_fifo_context_rd32
,
352 .wr32
= _nouveau_fifo_context_wr32
,
356 /*******************************************************************************
358 ******************************************************************************/
361 nv50_fifo_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
362 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
363 struct nouveau_object
**pobject
)
365 struct nv50_fifo_priv
*priv
;
368 ret
= nouveau_fifo_create(parent
, engine
, oclass
, 1, 127, &priv
);
369 *pobject
= nv_object(priv
);
373 ret
= nouveau_gpuobj_new(parent
, NULL
, 128 * 4, 0x1000, 0,
378 ret
= nouveau_gpuobj_new(parent
, NULL
, 128 * 4, 0x1000, 0,
383 nv_subdev(priv
)->unit
= 0x00000100;
384 nv_subdev(priv
)->intr
= nv04_fifo_intr
;
385 nv_engine(priv
)->cclass
= &nv50_fifo_cclass
;
386 nv_engine(priv
)->sclass
= nv50_fifo_sclass
;
391 nv50_fifo_dtor(struct nouveau_object
*object
)
393 struct nv50_fifo_priv
*priv
= (void *)object
;
395 nouveau_gpuobj_ref(NULL
, &priv
->playlist
[1]);
396 nouveau_gpuobj_ref(NULL
, &priv
->playlist
[0]);
398 nouveau_fifo_destroy(&priv
->base
);
402 nv50_fifo_init(struct nouveau_object
*object
)
404 struct nv50_fifo_priv
*priv
= (void *)object
;
407 ret
= nouveau_fifo_init(&priv
->base
);
411 nv_mask(priv
, 0x000200, 0x00000100, 0x00000000);
412 nv_mask(priv
, 0x000200, 0x00000100, 0x00000100);
413 nv_wr32(priv
, 0x00250c, 0x6f3cfc34);
414 nv_wr32(priv
, 0x002044, 0x01003fff);
416 nv_wr32(priv
, 0x002100, 0xffffffff);
417 nv_wr32(priv
, 0x002140, 0xffffffff);
419 for (i
= 0; i
< 128; i
++)
420 nv_wr32(priv
, 0x002600 + (i
* 4), 0x00000000);
421 nv50_fifo_playlist_update(priv
);
423 nv_wr32(priv
, 0x003200, 0x00000001);
424 nv_wr32(priv
, 0x003250, 0x00000001);
425 nv_wr32(priv
, 0x002500, 0x00000001);
429 struct nouveau_oclass
431 .handle
= NV_ENGINE(FIFO
, 0x50),
432 .ofuncs
= &(struct nouveau_ofuncs
) {
433 .ctor
= nv50_fifo_ctor
,
434 .dtor
= nv50_fifo_dtor
,
435 .init
= nv50_fifo_init
,
436 .fini
= _nouveau_fifo_fini
,