nvc0: move firmware loading functions to nouveau
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_video.c
1 /*
2 * Copyright 2011-2013 Maarten Lankhorst
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 AUTHORS OR COPYRIGHT HOLDERS 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
23 #include "nvc0_video.h"
24
25 #include "util/u_sampler.h"
26 #include "util/u_format.h"
27
28 int
29 nvc0_screen_get_video_param(struct pipe_screen *pscreen,
30 enum pipe_video_profile profile,
31 enum pipe_video_cap param)
32 {
33 switch (param) {
34 case PIPE_VIDEO_CAP_SUPPORTED:
35 return profile >= PIPE_VIDEO_PROFILE_MPEG1;
36 case PIPE_VIDEO_CAP_NPOT_TEXTURES:
37 return 1;
38 case PIPE_VIDEO_CAP_MAX_WIDTH:
39 case PIPE_VIDEO_CAP_MAX_HEIGHT:
40 return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096;
41 case PIPE_VIDEO_CAP_PREFERED_FORMAT:
42 return PIPE_FORMAT_NV12;
43 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
44 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
45 return true;
46 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
47 return false;
48 case PIPE_VIDEO_CAP_MAX_LEVEL:
49 switch (profile) {
50 case PIPE_VIDEO_PROFILE_MPEG1:
51 return 0;
52 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
53 case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
54 return 3;
55 case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
56 return 3;
57 case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
58 return 5;
59 case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
60 return 1;
61 case PIPE_VIDEO_PROFILE_VC1_MAIN:
62 return 2;
63 case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
64 return 4;
65 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
66 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
67 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
68 return 41;
69 default:
70 debug_printf("unknown video profile: %d\n", profile);
71 return 0;
72 }
73 default:
74 debug_printf("unknown video param: %d\n", param);
75 return 0;
76 }
77 }
78
79 static void
80 nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
81 struct pipe_video_buffer *video_target,
82 struct pipe_picture_desc *picture,
83 unsigned num_buffers,
84 const void *const *data,
85 const unsigned *num_bytes)
86 {
87 struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
88 struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
89 uint32_t comm_seq = ++dec->fence_seq;
90 union pipe_desc desc;
91
92 unsigned vp_caps, is_ref, ret;
93 struct nouveau_vp3_video_buffer *refs[16] = {};
94
95 desc.base = picture;
96
97 assert(target->base.buffer_format == PIPE_FORMAT_NV12);
98
99 ret = nvc0_decoder_bsp(dec, desc, target, comm_seq,
100 num_buffers, data, num_bytes,
101 &vp_caps, &is_ref, refs);
102
103 /* did we decode bitstream correctly? */
104 assert(ret == 2);
105
106 nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
107 nvc0_decoder_ppp(dec, desc, target, comm_seq);
108 }
109
110 struct pipe_video_decoder *
111 nvc0_create_decoder(struct pipe_context *context,
112 enum pipe_video_profile profile,
113 enum pipe_video_entrypoint entrypoint,
114 enum pipe_video_chroma_format chroma_format,
115 unsigned width, unsigned height, unsigned max_references,
116 bool chunked_decode)
117 {
118 struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
119 struct nouveau_vp3_decoder *dec;
120 struct nouveau_pushbuf **push;
121 union nouveau_bo_config cfg;
122 bool kepler = screen->device->chipset >= 0xe0;
123
124 cfg.nvc0.tile_mode = 0x10;
125 cfg.nvc0.memtype = 0xfe;
126
127 int ret, i;
128 uint32_t codec = 1, ppp_codec = 3;
129 uint32_t timeout;
130 u32 tmp_size = 0;
131
132 if (getenv("XVMC_VL"))
133 return vl_create_decoder(context, profile, entrypoint,
134 chroma_format, width, height,
135 max_references, chunked_decode);
136
137 if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
138 debug_printf("%x\n", entrypoint);
139 return NULL;
140 }
141
142 dec = CALLOC_STRUCT(nouveau_vp3_decoder);
143 if (!dec)
144 return NULL;
145 dec->client = screen->client;
146 nouveau_vp3_decoder_init_common(&dec->base);
147
148 if (!kepler) {
149 dec->bsp_idx = 5;
150 dec->vp_idx = 6;
151 dec->ppp_idx = 7;
152 } else {
153 dec->bsp_idx = 2;
154 dec->vp_idx = 2;
155 dec->ppp_idx = 2;
156 }
157
158 for (i = 0; i < 3; ++i)
159 if (i && !kepler) {
160 dec->channel[i] = dec->channel[0];
161 dec->pushbuf[i] = dec->pushbuf[0];
162 } else {
163 void *data;
164 u32 size;
165 struct nvc0_fifo nvc0_args = {};
166 struct nve0_fifo nve0_args = {};
167
168 if (!kepler) {
169 size = sizeof(nvc0_args);
170 data = &nvc0_args;
171 } else {
172 unsigned engine[] = {
173 NVE0_FIFO_ENGINE_BSP,
174 NVE0_FIFO_ENGINE_VP,
175 NVE0_FIFO_ENGINE_PPP
176 };
177
178 nve0_args.engine = engine[i];
179 size = sizeof(nve0_args);
180 data = &nve0_args;
181 }
182
183 ret = nouveau_object_new(&screen->device->object, 0,
184 NOUVEAU_FIFO_CHANNEL_CLASS,
185 data, size, &dec->channel[i]);
186
187 if (!ret)
188 ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
189 32 * 1024, true, &dec->pushbuf[i]);
190 if (ret)
191 break;
192 }
193 push = dec->pushbuf;
194
195 if (!kepler) {
196 if (!ret)
197 ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
198 if (!ret)
199 ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
200 if (!ret)
201 ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
202 } else {
203 if (!ret)
204 ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
205 if (!ret)
206 ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
207 if (!ret)
208 ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
209 }
210 if (ret)
211 goto fail;
212
213 BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
214 PUSH_DATA (push[0], dec->bsp->handle);
215
216 BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
217 PUSH_DATA (push[1], dec->vp->handle);
218
219 BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
220 PUSH_DATA (push[2], dec->ppp->handle);
221
222 dec->base.context = context;
223 dec->base.profile = profile;
224 dec->base.entrypoint = entrypoint;
225 dec->base.chroma_format = chroma_format;
226 dec->base.width = width;
227 dec->base.height = height;
228 dec->base.max_references = max_references;
229 dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
230
231 for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
232 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
233 0, 1 << 20, &cfg, &dec->bsp_bo[i]);
234 if (!ret)
235 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
236 0x100, 4 << 20, &cfg, &dec->inter_bo[0]);
237 if (!ret) {
238 if (!kepler)
239 nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);
240 else
241 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
242 0x100, dec->inter_bo[0]->size, &cfg,
243 &dec->inter_bo[1]);
244 }
245 if (ret)
246 goto fail;
247
248 switch (u_reduce_video_profile(profile)) {
249 case PIPE_VIDEO_CODEC_MPEG12: {
250 codec = 1;
251 assert(max_references <= 2);
252 break;
253 }
254 case PIPE_VIDEO_CODEC_MPEG4: {
255 codec = 4;
256 tmp_size = mb(height)*16 * mb(width)*16;
257 assert(max_references <= 2);
258 break;
259 }
260 case PIPE_VIDEO_CODEC_VC1: {
261 ppp_codec = codec = 2;
262 tmp_size = mb(height)*16 * mb(width)*16;
263 assert(max_references <= 2);
264 break;
265 }
266 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
267 codec = 3;
268 dec->tmp_stride = 16 * mb_half(width) * nouveau_vp3_video_align(height) * 3 / 2;
269 tmp_size = dec->tmp_stride * (max_references + 1);
270 assert(max_references <= 16);
271 break;
272 }
273 default:
274 fprintf(stderr, "invalid codec\n");
275 goto fail;
276 }
277
278 if (screen->device->chipset < 0xd0) {
279 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
280 0x4000, &cfg, &dec->fw_bo);
281 if (ret)
282 goto fail;
283
284 ret = nouveau_vp3_load_firmware(dec, profile, screen->device->chipset);
285 if (ret)
286 goto fw_fail;
287 }
288
289 if (codec != 3) {
290 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
291 0x400, &cfg, &dec->bitplane_bo);
292 if (ret)
293 goto fail;
294 }
295
296 dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nouveau_vp3_video_align(height)/2);
297 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
298 dec->ref_stride * (max_references+2) + tmp_size,
299 &cfg, &dec->ref_bo);
300 if (ret)
301 goto fail;
302
303 timeout = 0;
304
305 BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
306 PUSH_DATA (push[0], codec);
307 PUSH_DATA (push[0], timeout);
308
309 BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
310 PUSH_DATA (push[1], codec);
311 PUSH_DATA (push[1], timeout);
312
313 BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
314 PUSH_DATA (push[2], ppp_codec);
315 PUSH_DATA (push[2], timeout);
316
317 ++dec->fence_seq;
318
319 #if NOUVEAU_VP3_DEBUG_FENCE
320 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
321 0, 0x1000, NULL, &dec->fence_bo);
322 if (ret)
323 goto fail;
324
325 nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
326 dec->fence_map = dec->fence_bo->map;
327 dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
328 dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
329
330 /* So lets test if the fence is working? */
331 nouveau_pushbuf_space(push[0], 6, 1, 0);
332 PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
333 BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
334 PUSH_DATAh(push[0], dec->fence_bo->offset);
335 PUSH_DATA (push[0], dec->fence_bo->offset);
336 PUSH_DATA (push[0], dec->fence_seq);
337
338 BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
339 PUSH_DATA (push[0], 0);
340 PUSH_KICK (push[0]);
341
342 nouveau_pushbuf_space(push[1], 6, 1, 0);
343 PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
344 BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
345 PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
346 PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
347 PUSH_DATA (push[1], dec->fence_seq);
348
349 BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
350 PUSH_DATA (push[1], 0);
351 PUSH_KICK (push[1]);
352
353 nouveau_pushbuf_space(push[2], 6, 1, 0);
354 PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
355 BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
356 PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
357 PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
358 PUSH_DATA (push[2], dec->fence_seq);
359
360 BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
361 PUSH_DATA (push[2], 0);
362 PUSH_KICK (push[2]);
363
364 usleep(100);
365 while (dec->fence_seq > dec->fence_map[0] ||
366 dec->fence_seq > dec->fence_map[4] ||
367 dec->fence_seq > dec->fence_map[8]) {
368 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
369 usleep(100);
370 }
371 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
372 #endif
373
374 return &dec->base;
375
376 fw_fail:
377 debug_printf("Cannot create decoder without firmware..\n");
378 dec->base.destroy(&dec->base);
379 return NULL;
380
381 fail:
382 debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
383 dec->base.destroy(&dec->base);
384 return NULL;
385 }
386
387 struct pipe_video_buffer *
388 nvc0_video_buffer_create(struct pipe_context *pipe,
389 const struct pipe_video_buffer *templat)
390 {
391 return nouveau_vp3_video_buffer_create(
392 pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
393 }