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.
26 #include <core/client.h>
27 #include <core/ramht.h>
28 #include <subdev/mmu.h>
29 #include <subdev/timer.h>
31 #include <nvif/cl826e.h>
34 g84_fifo_chan_ntfy(struct nvkm_fifo_chan
*chan
, u32 type
,
35 struct nvkm_event
**pevent
)
38 case NV826E_V0_NTFY_NON_STALL_INTERRUPT
:
39 *pevent
= &chan
->fifo
->uevent
;
48 g84_fifo_chan_engine(struct nvkm_engine
*engine
)
50 switch (engine
->subdev
.index
) {
51 case NVKM_ENGINE_GR
: return 0;
52 case NVKM_ENGINE_MPEG
:
53 case NVKM_ENGINE_MSPPP
: return 1;
54 case NVKM_ENGINE_CE0
: return 2;
56 case NVKM_ENGINE_MSPDEC
: return 3;
57 case NVKM_ENGINE_CIPHER
:
58 case NVKM_ENGINE_SEC
: return 4;
59 case NVKM_ENGINE_BSP
:
60 case NVKM_ENGINE_MSVLD
: return 5;
68 g84_fifo_chan_engine_addr(struct nvkm_engine
*engine
)
70 switch (engine
->subdev
.index
) {
71 case NVKM_ENGINE_DMAOBJ
:
72 case NVKM_ENGINE_SW
: return -1;
73 case NVKM_ENGINE_GR
: return 0x0020;
75 case NVKM_ENGINE_MSPDEC
: return 0x0040;
76 case NVKM_ENGINE_MPEG
:
77 case NVKM_ENGINE_MSPPP
: return 0x0060;
78 case NVKM_ENGINE_BSP
:
79 case NVKM_ENGINE_MSVLD
: return 0x0080;
80 case NVKM_ENGINE_CIPHER
:
81 case NVKM_ENGINE_SEC
: return 0x00a0;
82 case NVKM_ENGINE_CE0
: return 0x00c0;
90 g84_fifo_chan_engine_fini(struct nvkm_fifo_chan
*base
,
91 struct nvkm_engine
*engine
, bool suspend
)
93 struct nv50_fifo_chan
*chan
= nv50_fifo_chan(base
);
94 struct nv50_fifo
*fifo
= chan
->fifo
;
95 struct nvkm_subdev
*subdev
= &fifo
->base
.engine
.subdev
;
96 struct nvkm_device
*device
= subdev
->device
;
101 offset
= g84_fifo_chan_engine_addr(engine
);
105 engn
= g84_fifo_chan_engine(engine
);
106 save
= nvkm_mask(device
, 0x002520, 0x0000003f, 1 << engn
);
107 nvkm_wr32(device
, 0x0032fc, chan
->base
.inst
->addr
>> 12);
108 done
= nvkm_msec(device
, 2000,
109 if (nvkm_rd32(device
, 0x0032fc) != 0xffffffff)
112 nvkm_wr32(device
, 0x002520, save
);
114 nvkm_error(subdev
, "channel %d [%s] unload timeout\n",
115 chan
->base
.chid
, chan
->base
.object
.client
->name
);
120 nvkm_kmap(chan
->eng
);
121 nvkm_wo32(chan
->eng
, offset
+ 0x00, 0x00000000);
122 nvkm_wo32(chan
->eng
, offset
+ 0x04, 0x00000000);
123 nvkm_wo32(chan
->eng
, offset
+ 0x08, 0x00000000);
124 nvkm_wo32(chan
->eng
, offset
+ 0x0c, 0x00000000);
125 nvkm_wo32(chan
->eng
, offset
+ 0x10, 0x00000000);
126 nvkm_wo32(chan
->eng
, offset
+ 0x14, 0x00000000);
127 nvkm_done(chan
->eng
);
133 g84_fifo_chan_engine_init(struct nvkm_fifo_chan
*base
,
134 struct nvkm_engine
*engine
)
136 struct nv50_fifo_chan
*chan
= nv50_fifo_chan(base
);
137 struct nvkm_gpuobj
*engn
= chan
->engn
[engine
->subdev
.index
];
141 offset
= g84_fifo_chan_engine_addr(engine
);
144 limit
= engn
->addr
+ engn
->size
- 1;
147 nvkm_kmap(chan
->eng
);
148 nvkm_wo32(chan
->eng
, offset
+ 0x00, 0x00190000);
149 nvkm_wo32(chan
->eng
, offset
+ 0x04, lower_32_bits(limit
));
150 nvkm_wo32(chan
->eng
, offset
+ 0x08, lower_32_bits(start
));
151 nvkm_wo32(chan
->eng
, offset
+ 0x0c, upper_32_bits(limit
) << 24 |
152 upper_32_bits(start
));
153 nvkm_wo32(chan
->eng
, offset
+ 0x10, 0x00000000);
154 nvkm_wo32(chan
->eng
, offset
+ 0x14, 0x00000000);
155 nvkm_done(chan
->eng
);
160 g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan
*base
,
161 struct nvkm_engine
*engine
,
162 struct nvkm_object
*object
)
164 struct nv50_fifo_chan
*chan
= nv50_fifo_chan(base
);
165 int engn
= engine
->subdev
.index
;
167 if (g84_fifo_chan_engine_addr(engine
) < 0)
170 return nvkm_object_bind(object
, NULL
, 0, &chan
->engn
[engn
]);
174 g84_fifo_chan_object_ctor(struct nvkm_fifo_chan
*base
,
175 struct nvkm_object
*object
)
177 struct nv50_fifo_chan
*chan
= nv50_fifo_chan(base
);
178 u32 handle
= object
->handle
;
181 switch (object
->engine
->subdev
.index
) {
182 case NVKM_ENGINE_DMAOBJ
:
183 case NVKM_ENGINE_SW
: context
= 0x00000000; break;
184 case NVKM_ENGINE_GR
: context
= 0x00100000; break;
185 case NVKM_ENGINE_MPEG
:
186 case NVKM_ENGINE_MSPPP
: context
= 0x00200000; break;
187 case NVKM_ENGINE_ME
:
188 case NVKM_ENGINE_CE0
: context
= 0x00300000; break;
189 case NVKM_ENGINE_VP
:
190 case NVKM_ENGINE_MSPDEC
: context
= 0x00400000; break;
191 case NVKM_ENGINE_CIPHER
:
192 case NVKM_ENGINE_SEC
:
193 case NVKM_ENGINE_VIC
: context
= 0x00500000; break;
194 case NVKM_ENGINE_BSP
:
195 case NVKM_ENGINE_MSVLD
: context
= 0x00600000; break;
201 return nvkm_ramht_insert(chan
->ramht
, object
, 0, 4, handle
, context
);
205 g84_fifo_chan_init(struct nvkm_fifo_chan
*base
)
207 struct nv50_fifo_chan
*chan
= nv50_fifo_chan(base
);
208 struct nv50_fifo
*fifo
= chan
->fifo
;
209 struct nvkm_device
*device
= fifo
->base
.engine
.subdev
.device
;
210 u64 addr
= chan
->ramfc
->addr
>> 8;
211 u32 chid
= chan
->base
.chid
;
213 nvkm_wr32(device
, 0x002600 + (chid
* 4), 0x80000000 | addr
);
214 nv50_fifo_runlist_update(fifo
);
217 static const struct nvkm_fifo_chan_func
218 g84_fifo_chan_func
= {
219 .dtor
= nv50_fifo_chan_dtor
,
220 .init
= g84_fifo_chan_init
,
221 .fini
= nv50_fifo_chan_fini
,
222 .ntfy
= g84_fifo_chan_ntfy
,
223 .engine_ctor
= g84_fifo_chan_engine_ctor
,
224 .engine_dtor
= nv50_fifo_chan_engine_dtor
,
225 .engine_init
= g84_fifo_chan_engine_init
,
226 .engine_fini
= g84_fifo_chan_engine_fini
,
227 .object_ctor
= g84_fifo_chan_object_ctor
,
228 .object_dtor
= nv50_fifo_chan_object_dtor
,
232 g84_fifo_chan_ctor(struct nv50_fifo
*fifo
, u64 vmm
, u64 push
,
233 const struct nvkm_oclass
*oclass
,
234 struct nv50_fifo_chan
*chan
)
236 struct nvkm_device
*device
= fifo
->base
.engine
.subdev
.device
;
242 ret
= nvkm_fifo_chan_ctor(&g84_fifo_chan_func
, &fifo
->base
,
243 0x10000, 0x1000, false, vmm
, push
,
244 (1ULL << NVKM_ENGINE_BSP
) |
245 (1ULL << NVKM_ENGINE_CE0
) |
246 (1ULL << NVKM_ENGINE_CIPHER
) |
247 (1ULL << NVKM_ENGINE_DMAOBJ
) |
248 (1ULL << NVKM_ENGINE_GR
) |
249 (1ULL << NVKM_ENGINE_ME
) |
250 (1ULL << NVKM_ENGINE_MPEG
) |
251 (1ULL << NVKM_ENGINE_MSPDEC
) |
252 (1ULL << NVKM_ENGINE_MSPPP
) |
253 (1ULL << NVKM_ENGINE_MSVLD
) |
254 (1ULL << NVKM_ENGINE_SEC
) |
255 (1ULL << NVKM_ENGINE_SW
) |
256 (1ULL << NVKM_ENGINE_VIC
) |
257 (1ULL << NVKM_ENGINE_VP
),
258 0, 0xc00000, 0x2000, oclass
, &chan
->base
);
263 ret
= nvkm_gpuobj_new(device
, 0x0200, 0, true, chan
->base
.inst
,
268 ret
= nvkm_gpuobj_new(device
, 0x4000, 0, false, chan
->base
.inst
,
273 ret
= nvkm_gpuobj_new(device
, 0x1000, 0x400, true, chan
->base
.inst
,
278 ret
= nvkm_gpuobj_new(device
, 0x100, 0x100, true, chan
->base
.inst
,
283 return nvkm_ramht_new(device
, 0x8000, 16, chan
->base
.inst
, &chan
->ramht
);