1 /*
2  * Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin
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 "nv50/nv98_video.h"
24 
25 #include "util/u_sampler.h"
26 #include "util/u_format.h"
27 
28 #include <nvif/class.h>
29 
30 static void
nv98_decoder_decode_bitstream(struct pipe_video_codec * decoder,struct pipe_video_buffer * video_target,struct pipe_picture_desc * picture,unsigned num_buffers,const void * const * data,const unsigned * num_bytes)31 nv98_decoder_decode_bitstream(struct pipe_video_codec *decoder,
32                               struct pipe_video_buffer *video_target,
33                               struct pipe_picture_desc *picture,
34                               unsigned num_buffers,
35                               const void *const *data,
36                               const unsigned *num_bytes)
37 {
38    struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
39    struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
40    uint32_t comm_seq = ++dec->fence_seq;
41    union pipe_desc desc;
42 
43    unsigned vp_caps, is_ref, ret;
44    struct nouveau_vp3_video_buffer *refs[16] = {};
45 
46    desc.base = picture;
47 
48    assert(target->base.buffer_format == PIPE_FORMAT_NV12);
49 
50    ret = nv98_decoder_bsp(dec, desc, target, comm_seq,
51                           num_buffers, data, num_bytes,
52                           &vp_caps, &is_ref, refs);
53 
54    /* did we decode bitstream correctly? */
55    assert(ret == 2);
56 
57    nv98_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
58    nv98_decoder_ppp(dec, desc, target, comm_seq);
59 }
60 
61 static const struct nouveau_mclass
62 nv98_decoder_msvld[] = {
63    { G98_MSVLD, -1 },
64    { IGT21A_MSVLD, -1 },
65    { GT212_MSVLD, -1 },
66    {}
67 };
68 
69 static const struct nouveau_mclass
70 nv98_decoder_mspdec[] = {
71    { G98_MSPDEC, -1 },
72    { GT212_MSPDEC, -1 },
73    {}
74 };
75 
76 static const struct nouveau_mclass
77 nv98_decoder_msppp[] = {
78    { G98_MSPPP, -1 },
79    { GT212_MSPPP, -1 },
80    {}
81 };
82 
83 struct pipe_video_codec *
nv98_create_decoder(struct pipe_context * context,const struct pipe_video_codec * templ)84 nv98_create_decoder(struct pipe_context *context,
85                     const struct pipe_video_codec *templ)
86 {
87    struct nouveau_screen *screen = &((struct nv50_context *)context)->screen->base;
88    struct nouveau_vp3_decoder *dec;
89    struct nouveau_pushbuf **push;
90    struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202};
91 
92    int ret, i;
93    uint32_t codec = 1, ppp_codec = 3;
94    uint32_t timeout;
95    u32 tmp_size = 0;
96 
97    if (getenv("XVMC_VL"))
98        return vl_create_decoder(context, templ);
99 
100    if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
101       debug_printf("%x\n", templ->entrypoint);
102       return NULL;
103    }
104 
105    dec = CALLOC_STRUCT(nouveau_vp3_decoder);
106    if (!dec)
107       return NULL;
108    dec->client = screen->client;
109    dec->base = *templ;
110    nouveau_vp3_decoder_init_common(&dec->base);
111 
112    dec->bsp_idx = 5;
113    dec->vp_idx = 6;
114    dec->ppp_idx = 7;
115 
116    ret = nouveau_object_new(&screen->device->object, 0,
117                             NOUVEAU_FIFO_CHANNEL_CLASS,
118                             &nv04_data, sizeof(nv04_data), &dec->channel[0]);
119 
120    if (!ret)
121       ret = nouveau_pushbuf_new(screen->client, dec->channel[0], 4,
122                                 32 * 1024, true, &dec->pushbuf[0]);
123 
124    for (i = 1; i < 3; ++i) {
125       dec->channel[i] = dec->channel[0];
126       dec->pushbuf[i] = dec->pushbuf[0];
127    }
128    push = dec->pushbuf;
129 
130    if (!ret) {
131       ret = nouveau_object_mclass(dec->channel[0], nv98_decoder_msvld);
132       if (ret >= 0) {
133          ret = nouveau_object_new(dec->channel[0], 0xbeef85b1,
134                                   nv98_decoder_msvld[ret].oclass, NULL, 0,
135                                   &dec->bsp);
136       }
137    }
138 
139    if (!ret) {
140       ret = nouveau_object_mclass(dec->channel[1], nv98_decoder_mspdec);
141       if (ret >= 0) {
142          ret = nouveau_object_new(dec->channel[1], 0xbeef85b2,
143                                   nv98_decoder_mspdec[ret].oclass, NULL, 0,
144                                   &dec->vp);
145       }
146    }
147 
148    if (!ret) {
149       ret = nouveau_object_mclass(dec->channel[2], nv98_decoder_msppp);
150       if (ret >= 0) {
151          ret = nouveau_object_new(dec->channel[2], 0xbeef85b3,
152                                   nv98_decoder_msppp[ret].oclass, NULL, 0,
153                                   &dec->ppp);
154       }
155    }
156 
157    if (ret)
158       goto fail;
159 
160    BEGIN_NV04(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
161    PUSH_DATA (push[0], dec->bsp->handle);
162 
163    BEGIN_NV04(push[0], SUBC_BSP(0x180), 5);
164    for (i = 0; i < 5; i++)
165       PUSH_DATA (push[0], nv04_data.vram);
166 
167    BEGIN_NV04(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
168    PUSH_DATA (push[1], dec->vp->handle);
169 
170    BEGIN_NV04(push[1], SUBC_VP(0x180), 6);
171    for (i = 0; i < 6; i++)
172       PUSH_DATA (push[1], nv04_data.vram);
173 
174    BEGIN_NV04(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
175    PUSH_DATA (push[2], dec->ppp->handle);
176 
177    BEGIN_NV04(push[2], SUBC_PPP(0x180), 5);
178    for (i = 0; i < 5; i++)
179       PUSH_DATA (push[2], nv04_data.vram);
180 
181    dec->base.context = context;
182    dec->base.decode_bitstream = nv98_decoder_decode_bitstream;
183 
184    for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
185       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
186                            0, 1 << 20, NULL, &dec->bsp_bo[i]);
187    if (!ret)
188       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
189                            0x100, 4 << 20, NULL, &dec->inter_bo[0]);
190    if (!ret)
191       nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);
192    if (ret)
193       goto fail;
194 
195    switch (u_reduce_video_profile(templ->profile)) {
196    case PIPE_VIDEO_FORMAT_MPEG12: {
197       codec = 1;
198       assert(templ->max_references <= 2);
199       break;
200    }
201    case PIPE_VIDEO_FORMAT_MPEG4: {
202       codec = 4;
203       tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
204       assert(templ->max_references <= 2);
205       break;
206    }
207    case PIPE_VIDEO_FORMAT_VC1: {
208       ppp_codec = codec = 2;
209       tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
210       assert(templ->max_references <= 2);
211       break;
212    }
213    case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
214       codec = 3;
215       dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
216       tmp_size = dec->tmp_stride * (templ->max_references + 1);
217       assert(templ->max_references <= 16);
218       break;
219    }
220    default:
221       fprintf(stderr, "invalid codec\n");
222       goto fail;
223    }
224 
225    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
226                            0x4000, NULL, &dec->fw_bo);
227    if (ret)
228       goto fail;
229 
230    ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
231    if (ret)
232       goto fw_fail;
233 
234    if (codec != 3) {
235       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
236                            0x400, NULL, &dec->bitplane_bo);
237       if (ret)
238          goto fail;
239    }
240 
241    dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
242    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
243                         dec->ref_stride * (templ->max_references+2) + tmp_size,
244                         NULL, &dec->ref_bo);
245    if (ret)
246       goto fail;
247 
248    timeout = 0;
249 
250    BEGIN_NV04(push[0], SUBC_BSP(0x200), 2);
251    PUSH_DATA (push[0], codec);
252    PUSH_DATA (push[0], timeout);
253 
254    BEGIN_NV04(push[1], SUBC_VP(0x200), 2);
255    PUSH_DATA (push[1], codec);
256    PUSH_DATA (push[1], timeout);
257 
258    BEGIN_NV04(push[2], SUBC_PPP(0x200), 2);
259    PUSH_DATA (push[2], ppp_codec);
260    PUSH_DATA (push[2], timeout);
261 
262    ++dec->fence_seq;
263 
264 #if NOUVEAU_VP3_DEBUG_FENCE
265    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
266                         0, 0x1000, NULL, &dec->fence_bo);
267    if (ret)
268       goto fail;
269 
270    nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
271    dec->fence_map = dec->fence_bo->map;
272    dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
273    dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
274 
275    /* So lets test if the fence is working? */
276    nouveau_pushbuf_space(push[0], 16, 1, 0);
277    PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
278    BEGIN_NV04(push[0], SUBC_BSP(0x240), 3);
279    PUSH_DATAh(push[0], dec->fence_bo->offset);
280    PUSH_DATA (push[0], dec->fence_bo->offset);
281    PUSH_DATA (push[0], dec->fence_seq);
282 
283    BEGIN_NV04(push[0], SUBC_BSP(0x304), 1);
284    PUSH_DATA (push[0], 0);
285    PUSH_KICK (push[0]);
286 
287    nouveau_pushbuf_space(push[1], 16, 1, 0);
288    PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
289    BEGIN_NV04(push[1], SUBC_VP(0x240), 3);
290    PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
291    PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
292    PUSH_DATA (push[1], dec->fence_seq);
293 
294    BEGIN_NV04(push[1], SUBC_VP(0x304), 1);
295    PUSH_DATA (push[1], 0);
296    PUSH_KICK (push[1]);
297 
298    nouveau_pushbuf_space(push[2], 16, 1, 0);
299    PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
300    BEGIN_NV04(push[2], SUBC_PPP(0x240), 3);
301    PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
302    PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
303    PUSH_DATA (push[2], dec->fence_seq);
304 
305    BEGIN_NV04(push[2], SUBC_PPP(0x304), 1);
306    PUSH_DATA (push[2], 0);
307    PUSH_KICK (push[2]);
308 
309    usleep(100);
310    while (dec->fence_seq > dec->fence_map[0] ||
311           dec->fence_seq > dec->fence_map[4] ||
312           dec->fence_seq > dec->fence_map[8]) {
313       debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
314       usleep(100);
315    }
316    debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
317 #endif
318 
319    return &dec->base;
320 
321 fw_fail:
322    debug_printf("Cannot create decoder without firmware..\n");
323    dec->base.destroy(&dec->base);
324    return NULL;
325 
326 fail:
327    debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
328    dec->base.destroy(&dec->base);
329    return NULL;
330 }
331 
332 struct pipe_video_buffer *
nv98_video_buffer_create(struct pipe_context * pipe,const struct pipe_video_buffer * templat)333 nv98_video_buffer_create(struct pipe_context *pipe,
334                          const struct pipe_video_buffer *templat)
335 {
336    return nouveau_vp3_video_buffer_create(
337          pipe, templat, NV50_RESOURCE_FLAG_VIDEO);
338 }
339