1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011-2013 Maarten Lankhorst
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include "nvc0/nvc0_video.h"
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "util/u_sampler.h"
26bf215546Sopenharmony_ci#include "util/format/u_format.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_cistatic void
29bf215546Sopenharmony_cinvc0_decoder_begin_frame(struct pipe_video_codec *decoder,
30bf215546Sopenharmony_ci                         struct pipe_video_buffer *target,
31bf215546Sopenharmony_ci                         struct pipe_picture_desc *picture)
32bf215546Sopenharmony_ci{
33bf215546Sopenharmony_ci   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
34bf215546Sopenharmony_ci   uint32_t comm_seq = ++dec->fence_seq;
35bf215546Sopenharmony_ci   ASSERTED unsigned ret = 0; /* used in debug checks */
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci   assert(dec);
38bf215546Sopenharmony_ci   assert(target);
39bf215546Sopenharmony_ci   assert(target->buffer_format == PIPE_FORMAT_NV12);
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci   ret = nvc0_decoder_bsp_begin(dec, comm_seq);
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   assert(ret == 2);
44bf215546Sopenharmony_ci}
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistatic void
47bf215546Sopenharmony_cinvc0_decoder_decode_bitstream(struct pipe_video_codec *decoder,
48bf215546Sopenharmony_ci                              struct pipe_video_buffer *video_target,
49bf215546Sopenharmony_ci                              struct pipe_picture_desc *picture,
50bf215546Sopenharmony_ci                              unsigned num_buffers,
51bf215546Sopenharmony_ci                              const void *const *data,
52bf215546Sopenharmony_ci                              const unsigned *num_bytes)
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
55bf215546Sopenharmony_ci   uint32_t comm_seq = dec->fence_seq;
56bf215546Sopenharmony_ci   ASSERTED unsigned ret = 0; /* used in debug checks */
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   assert(decoder);
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   ret = nvc0_decoder_bsp_next(dec, comm_seq, num_buffers, data, num_bytes);
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   assert(ret == 2);
63bf215546Sopenharmony_ci}
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistatic void
66bf215546Sopenharmony_cinvc0_decoder_end_frame(struct pipe_video_codec *decoder,
67bf215546Sopenharmony_ci                       struct pipe_video_buffer *video_target,
68bf215546Sopenharmony_ci                       struct pipe_picture_desc *picture)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
71bf215546Sopenharmony_ci   struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
72bf215546Sopenharmony_ci   uint32_t comm_seq = dec->fence_seq;
73bf215546Sopenharmony_ci   union pipe_desc desc;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   unsigned vp_caps, is_ref;
76bf215546Sopenharmony_ci   ASSERTED unsigned ret; /* used in debug checks */
77bf215546Sopenharmony_ci   struct nouveau_vp3_video_buffer *refs[16] = {};
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   desc.base = picture;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   ret = nvc0_decoder_bsp_end(dec, desc, target, comm_seq, &vp_caps, &is_ref, refs);
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   /* did we decode bitstream correctly? */
84bf215546Sopenharmony_ci   assert(ret == 2);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
87bf215546Sopenharmony_ci   nvc0_decoder_ppp(dec, desc, target, comm_seq);
88bf215546Sopenharmony_ci}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_cistruct pipe_video_codec *
91bf215546Sopenharmony_cinvc0_create_decoder(struct pipe_context *context,
92bf215546Sopenharmony_ci                    const struct pipe_video_codec *templ)
93bf215546Sopenharmony_ci{
94bf215546Sopenharmony_ci   struct nvc0_context *nvc0 = nvc0_context(context);
95bf215546Sopenharmony_ci   struct nouveau_screen *screen = &nvc0->screen->base;
96bf215546Sopenharmony_ci   struct nouveau_vp3_decoder *dec;
97bf215546Sopenharmony_ci   struct nouveau_pushbuf **push;
98bf215546Sopenharmony_ci   union nouveau_bo_config cfg;
99bf215546Sopenharmony_ci   bool kepler = screen->device->chipset >= 0xe0;
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   cfg.nvc0.tile_mode = 0x10;
102bf215546Sopenharmony_ci   cfg.nvc0.memtype = 0xfe;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   int ret, i;
105bf215546Sopenharmony_ci   uint32_t codec = 1, ppp_codec = 3;
106bf215546Sopenharmony_ci   uint32_t timeout;
107bf215546Sopenharmony_ci   u32 tmp_size = 0;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   if (getenv("XVMC_VL"))
110bf215546Sopenharmony_ci       return vl_create_decoder(context, templ);
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
113bf215546Sopenharmony_ci      debug_printf("%x\n", templ->entrypoint);
114bf215546Sopenharmony_ci      return NULL;
115bf215546Sopenharmony_ci   }
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   dec = CALLOC_STRUCT(nouveau_vp3_decoder);
118bf215546Sopenharmony_ci   if (!dec)
119bf215546Sopenharmony_ci      return NULL;
120bf215546Sopenharmony_ci   dec->client = nvc0->base.client;
121bf215546Sopenharmony_ci   dec->base = *templ;
122bf215546Sopenharmony_ci   nouveau_vp3_decoder_init_common(&dec->base);
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   if (!kepler) {
125bf215546Sopenharmony_ci      dec->bsp_idx = 5;
126bf215546Sopenharmony_ci      dec->vp_idx = 6;
127bf215546Sopenharmony_ci      dec->ppp_idx = 7;
128bf215546Sopenharmony_ci   } else {
129bf215546Sopenharmony_ci      dec->bsp_idx = 2;
130bf215546Sopenharmony_ci      dec->vp_idx = 2;
131bf215546Sopenharmony_ci      dec->ppp_idx = 2;
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   for (i = 0; i < 3; ++i)
135bf215546Sopenharmony_ci      if (i && !kepler) {
136bf215546Sopenharmony_ci         dec->channel[i] = dec->channel[0];
137bf215546Sopenharmony_ci         dec->pushbuf[i] = dec->pushbuf[0];
138bf215546Sopenharmony_ci      } else {
139bf215546Sopenharmony_ci         void *data;
140bf215546Sopenharmony_ci         u32 size;
141bf215546Sopenharmony_ci         struct nvc0_fifo nvc0_args = {};
142bf215546Sopenharmony_ci         struct nve0_fifo nve0_args = {};
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci         if (!kepler) {
145bf215546Sopenharmony_ci            size = sizeof(nvc0_args);
146bf215546Sopenharmony_ci            data = &nvc0_args;
147bf215546Sopenharmony_ci         } else {
148bf215546Sopenharmony_ci            unsigned engine[] = {
149bf215546Sopenharmony_ci               NVE0_FIFO_ENGINE_BSP,
150bf215546Sopenharmony_ci               NVE0_FIFO_ENGINE_VP,
151bf215546Sopenharmony_ci               NVE0_FIFO_ENGINE_PPP
152bf215546Sopenharmony_ci            };
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci            nve0_args.engine = engine[i];
155bf215546Sopenharmony_ci            size = sizeof(nve0_args);
156bf215546Sopenharmony_ci            data = &nve0_args;
157bf215546Sopenharmony_ci         }
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci         ret = nouveau_object_new(&screen->device->object, 0,
160bf215546Sopenharmony_ci                                  NOUVEAU_FIFO_CHANNEL_CLASS,
161bf215546Sopenharmony_ci                                  data, size, &dec->channel[i]);
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci         if (!ret)
164bf215546Sopenharmony_ci            ret = nouveau_pushbuf_new(nvc0->base.client, dec->channel[i], 4,
165bf215546Sopenharmony_ci                                   32 * 1024, true, &dec->pushbuf[i]);
166bf215546Sopenharmony_ci         if (ret)
167bf215546Sopenharmony_ci            break;
168bf215546Sopenharmony_ci      }
169bf215546Sopenharmony_ci   push = dec->pushbuf;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   if (!kepler) {
172bf215546Sopenharmony_ci      if (!ret)
173bf215546Sopenharmony_ci         ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
174bf215546Sopenharmony_ci      if (!ret)
175bf215546Sopenharmony_ci         ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
176bf215546Sopenharmony_ci      if (!ret)
177bf215546Sopenharmony_ci         ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
178bf215546Sopenharmony_ci   } else {
179bf215546Sopenharmony_ci      if (!ret)
180bf215546Sopenharmony_ci         ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
181bf215546Sopenharmony_ci      if (!ret)
182bf215546Sopenharmony_ci         ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
183bf215546Sopenharmony_ci      if (!ret)
184bf215546Sopenharmony_ci         ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
185bf215546Sopenharmony_ci   }
186bf215546Sopenharmony_ci   if (ret)
187bf215546Sopenharmony_ci      goto fail;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
190bf215546Sopenharmony_ci   PUSH_DATA (push[0], dec->bsp->handle);
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
193bf215546Sopenharmony_ci   PUSH_DATA (push[1], dec->vp->handle);
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
196bf215546Sopenharmony_ci   PUSH_DATA (push[2], dec->ppp->handle);
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   dec->base.context = context;
199bf215546Sopenharmony_ci   dec->base.begin_frame = nvc0_decoder_begin_frame;
200bf215546Sopenharmony_ci   dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
201bf215546Sopenharmony_ci   dec->base.end_frame = nvc0_decoder_end_frame;
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci   for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
204bf215546Sopenharmony_ci      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
205bf215546Sopenharmony_ci                           0, 1 << 20, &cfg, &dec->bsp_bo[i]);
206bf215546Sopenharmony_ci   if (!ret) {
207bf215546Sopenharmony_ci      /* total fudge factor... just has to be bigger for higher bitrates? */
208bf215546Sopenharmony_ci      unsigned inter_size = align(templ->width * templ->height * 2, 4 << 20);
209bf215546Sopenharmony_ci      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
210bf215546Sopenharmony_ci                           0x100, inter_size, &cfg, &dec->inter_bo[0]);
211bf215546Sopenharmony_ci   }
212bf215546Sopenharmony_ci   if (!ret) {
213bf215546Sopenharmony_ci      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
214bf215546Sopenharmony_ci                           0x100, dec->inter_bo[0]->size, &cfg,
215bf215546Sopenharmony_ci                           &dec->inter_bo[1]);
216bf215546Sopenharmony_ci   }
217bf215546Sopenharmony_ci   if (ret)
218bf215546Sopenharmony_ci      goto fail;
219bf215546Sopenharmony_ci   switch (u_reduce_video_profile(templ->profile)) {
220bf215546Sopenharmony_ci   case PIPE_VIDEO_FORMAT_MPEG12: {
221bf215546Sopenharmony_ci      codec = 1;
222bf215546Sopenharmony_ci      assert(templ->max_references <= 2);
223bf215546Sopenharmony_ci      break;
224bf215546Sopenharmony_ci   }
225bf215546Sopenharmony_ci   case PIPE_VIDEO_FORMAT_MPEG4: {
226bf215546Sopenharmony_ci      codec = 4;
227bf215546Sopenharmony_ci      tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
228bf215546Sopenharmony_ci      assert(templ->max_references <= 2);
229bf215546Sopenharmony_ci      break;
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci   case PIPE_VIDEO_FORMAT_VC1: {
232bf215546Sopenharmony_ci      ppp_codec = codec = 2;
233bf215546Sopenharmony_ci      tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
234bf215546Sopenharmony_ci      assert(templ->max_references <= 2);
235bf215546Sopenharmony_ci      break;
236bf215546Sopenharmony_ci   }
237bf215546Sopenharmony_ci   case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
238bf215546Sopenharmony_ci      codec = 3;
239bf215546Sopenharmony_ci      dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
240bf215546Sopenharmony_ci      tmp_size = dec->tmp_stride * (templ->max_references + 1);
241bf215546Sopenharmony_ci      assert(templ->max_references <= 16);
242bf215546Sopenharmony_ci      break;
243bf215546Sopenharmony_ci   }
244bf215546Sopenharmony_ci   default:
245bf215546Sopenharmony_ci      fprintf(stderr, "invalid codec\n");
246bf215546Sopenharmony_ci      goto fail;
247bf215546Sopenharmony_ci   }
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   if (screen->device->chipset < 0xd0) {
250bf215546Sopenharmony_ci      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
251bf215546Sopenharmony_ci                           0x4000, &cfg, &dec->fw_bo);
252bf215546Sopenharmony_ci      if (ret)
253bf215546Sopenharmony_ci         goto fail;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci      ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
256bf215546Sopenharmony_ci      if (ret)
257bf215546Sopenharmony_ci         goto fw_fail;
258bf215546Sopenharmony_ci   }
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   if (codec != 3) {
261bf215546Sopenharmony_ci      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
262bf215546Sopenharmony_ci                           0x400, &cfg, &dec->bitplane_bo);
263bf215546Sopenharmony_ci      if (ret)
264bf215546Sopenharmony_ci         goto fail;
265bf215546Sopenharmony_ci   }
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
268bf215546Sopenharmony_ci   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
269bf215546Sopenharmony_ci                        dec->ref_stride * (templ->max_references+2) + tmp_size,
270bf215546Sopenharmony_ci                        &cfg, &dec->ref_bo);
271bf215546Sopenharmony_ci   if (ret)
272bf215546Sopenharmony_ci      goto fail;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   timeout = 0;
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
277bf215546Sopenharmony_ci   PUSH_DATA (push[0], codec);
278bf215546Sopenharmony_ci   PUSH_DATA (push[0], timeout);
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
281bf215546Sopenharmony_ci   PUSH_DATA (push[1], codec);
282bf215546Sopenharmony_ci   PUSH_DATA (push[1], timeout);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
285bf215546Sopenharmony_ci   PUSH_DATA (push[2], ppp_codec);
286bf215546Sopenharmony_ci   PUSH_DATA (push[2], timeout);
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   ++dec->fence_seq;
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci#if NOUVEAU_VP3_DEBUG_FENCE
291bf215546Sopenharmony_ci   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
292bf215546Sopenharmony_ci                        0, 0x1000, NULL, &dec->fence_bo);
293bf215546Sopenharmony_ci   if (ret)
294bf215546Sopenharmony_ci      goto fail;
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
297bf215546Sopenharmony_ci   dec->fence_map = dec->fence_bo->map;
298bf215546Sopenharmony_ci   dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
299bf215546Sopenharmony_ci   dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   /* So lets test if the fence is working? */
302bf215546Sopenharmony_ci   nouveau_pushbuf_space(push[0], 16, 1, 0);
303bf215546Sopenharmony_ci   PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
304bf215546Sopenharmony_ci   BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
305bf215546Sopenharmony_ci   PUSH_DATAh(push[0], dec->fence_bo->offset);
306bf215546Sopenharmony_ci   PUSH_DATA (push[0], dec->fence_bo->offset);
307bf215546Sopenharmony_ci   PUSH_DATA (push[0], dec->fence_seq);
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
310bf215546Sopenharmony_ci   PUSH_DATA (push[0], 0);
311bf215546Sopenharmony_ci   PUSH_KICK (push[0]);
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   nouveau_pushbuf_space(push[1], 16, 1, 0);
314bf215546Sopenharmony_ci   PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
315bf215546Sopenharmony_ci   BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
316bf215546Sopenharmony_ci   PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
317bf215546Sopenharmony_ci   PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
318bf215546Sopenharmony_ci   PUSH_DATA (push[1], dec->fence_seq);
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
321bf215546Sopenharmony_ci   PUSH_DATA (push[1], 0);
322bf215546Sopenharmony_ci   PUSH_KICK (push[1]);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   nouveau_pushbuf_space(push[2], 16, 1, 0);
325bf215546Sopenharmony_ci   PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
326bf215546Sopenharmony_ci   BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
327bf215546Sopenharmony_ci   PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
328bf215546Sopenharmony_ci   PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
329bf215546Sopenharmony_ci   PUSH_DATA (push[2], dec->fence_seq);
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
332bf215546Sopenharmony_ci   PUSH_DATA (push[2], 0);
333bf215546Sopenharmony_ci   PUSH_KICK (push[2]);
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci   usleep(100);
336bf215546Sopenharmony_ci   while (dec->fence_seq > dec->fence_map[0] ||
337bf215546Sopenharmony_ci          dec->fence_seq > dec->fence_map[4] ||
338bf215546Sopenharmony_ci          dec->fence_seq > dec->fence_map[8]) {
339bf215546Sopenharmony_ci      debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
340bf215546Sopenharmony_ci      usleep(100);
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci   debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
343bf215546Sopenharmony_ci#endif
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   return &dec->base;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_cifw_fail:
348bf215546Sopenharmony_ci   debug_printf("Cannot create decoder without firmware..\n");
349bf215546Sopenharmony_ci   dec->base.destroy(&dec->base);
350bf215546Sopenharmony_ci   return NULL;
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_cifail:
353bf215546Sopenharmony_ci   debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
354bf215546Sopenharmony_ci   dec->base.destroy(&dec->base);
355bf215546Sopenharmony_ci   return NULL;
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_cistruct pipe_video_buffer *
359bf215546Sopenharmony_cinvc0_video_buffer_create(struct pipe_context *pipe,
360bf215546Sopenharmony_ci                         const struct pipe_video_buffer *templat)
361bf215546Sopenharmony_ci{
362bf215546Sopenharmony_ci   return nouveau_vp3_video_buffer_create(
363bf215546Sopenharmony_ci         pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
364bf215546Sopenharmony_ci}
365