1 /*
2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3  * Copyright (c) Imagination Technologies Limited, UK
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Waldo Bastian <waldo.bastian@intel.com>
27  *
28  */
29 
30 
31 #include "psb_cmdbuf.h"
32 
33 #include <unistd.h>
34 #include <stdio.h>
35 
36 #include "hwdefs/mem_io.h"
37 #include "hwdefs/msvdx_offsets.h"
38 #include "hwdefs/dma_api.h"
39 #include "hwdefs/reg_io2.h"
40 #include "hwdefs/msvdx_vec_reg_io2.h"
41 #include "hwdefs/msvdx_vdmc_reg_io2.h"
42 #include "hwdefs/msvdx_mtx_reg_io2.h"
43 #include "hwdefs/msvdx_dmac_linked_list.h"
44 #include "hwdefs/msvdx_rendec_mtx_slice_cntrl_reg_io2.h"
45 #include "hwdefs/dxva_cmdseq_msg.h"
46 #include "hwdefs/dxva_fw_ctrl.h"
47 #include "hwdefs/fwrk_msg_mem_io.h"
48 #include "hwdefs/dxva_msg.h"
49 #include "hwdefs/msvdx_cmds_io2.h"
50 #include <stdlib.h>
51 #include <errno.h>
52 #include <string.h>
53 #include <sys/time.h>
54 
55 #include "psb_def.h"
56 #include "psb_drv_debug.h"
57 #ifndef BAYTRAIL
58 #include "psb_ws_driver.h"
59 #endif
60 #include <wsbm/wsbm_pool.h>
61 #include <wsbm/wsbm_manager.h>
62 #include <wsbm/wsbm_util.h>
63 #include <wsbm/wsbm_fencemgr.h>
64 
65 /*
66  * Buffer layout:
67  *         cmd_base <= cmd_idx < CMD_END() == lldma_base
68  *         lldma_base <= lldma_idx < LLDMA_END() == (cmd_base + size)
69  *
70  * Reloc buffer layout:
71  *         MTX_msg < reloc_base == MTX_msg + MTXMSG_SIZE
72  *         reloc_base <= reloc_idx < RELOC_END() == (MTX_msg + reloc_size)
73  */
74 #define MTXMSG_END(cmdbuf)    (cmdbuf->reloc_base)
75 #define RELOC_END(cmdbuf)     (cmdbuf->MTX_msg + cmdbuf->reloc_size)
76 
77 #define CMD_END(cmdbuf)       (cmdbuf->lldma_base)
78 #define LLDMA_END(cmdbuf)     (cmdbuf->cmd_base + cmdbuf->size)
79 
80 #define MTXMSG_SIZE           (0x1000)
81 #define RELOC_SIZE            (0x3000)
82 
83 #define CMD_SIZE              (0x3000)
84 #define LLDMA_SIZE            (0x2000)
85 
86 #define MTXMSG_MARGIN         (0x0040)
87 #define RELOC_MARGIN          (0x0800)
88 
89 #define CMD_MARGIN            (0x0400)
90 #define LLDMA_MARGIN          (0x0400)
91 #define PSB_SLICE_EXTRACT_UPDATE (0x2)
92 
93 /*
94  * Create command buffer
95  */
psb_cmdbuf_create(object_context_p obj_context,psb_driver_data_p driver_data,psb_cmdbuf_p cmdbuf)96 VAStatus psb_cmdbuf_create(object_context_p obj_context, psb_driver_data_p driver_data,
97                            psb_cmdbuf_p cmdbuf
98                           )
99 {
100     VAStatus vaStatus = VA_STATUS_SUCCESS;
101     unsigned int size = CMD_SIZE + LLDMA_SIZE;
102     unsigned int reloc_size = MTXMSG_SIZE + RELOC_SIZE;
103     unsigned int regio_size = (obj_context->picture_width >> 4) * (obj_context->picture_height >> 4) * 172;
104 
105     cmdbuf->size = 0;
106     cmdbuf->reloc_size = 0;
107     cmdbuf->regio_size = 0;
108     cmdbuf->MTX_msg = NULL;
109     cmdbuf->cmd_base = NULL;
110     cmdbuf->regio_base = NULL;
111     cmdbuf->cmd_idx = NULL;
112     cmdbuf->regio_idx = NULL;
113     cmdbuf->cmd_bitstream_size = NULL;
114     cmdbuf->lldma_base = NULL;
115     cmdbuf->lldma_idx = NULL;
116     cmdbuf->reloc_base = NULL;
117     cmdbuf->reloc_idx = NULL;
118     cmdbuf->reg_start = NULL;
119     cmdbuf->rendec_block_start = NULL;
120     cmdbuf->rendec_chunk_start = NULL;
121     cmdbuf->skip_block_start = NULL;
122     cmdbuf->last_next_segment_cmd = NULL;
123     cmdbuf->buffer_refs_count = 0;
124     cmdbuf->buffer_refs_allocated = 10;
125     cmdbuf->buffer_refs = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
126     if (NULL == cmdbuf->buffer_refs) {
127         cmdbuf->buffer_refs_allocated = 0;
128         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
129     }
130     if (VA_STATUS_SUCCESS == vaStatus) {
131         vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, &cmdbuf->buf);
132         cmdbuf->size = size;
133     }
134     if (VA_STATUS_SUCCESS == vaStatus) {
135         vaStatus = psb_buffer_create(driver_data, reloc_size, psb_bt_cpu_only, &cmdbuf->reloc_buf);
136         cmdbuf->reloc_size = reloc_size;
137     }
138     if (VA_STATUS_SUCCESS == vaStatus) {
139         vaStatus = psb_buffer_create(driver_data, regio_size, psb_bt_cpu_only, &cmdbuf->regio_buf);
140         cmdbuf->regio_size = regio_size;
141     }
142 
143     if (VA_STATUS_SUCCESS != vaStatus) {
144         psb_cmdbuf_destroy(cmdbuf);
145     }
146     return vaStatus;
147 }
148 
149 /*
150  * Destroy buffer
151  */
psb_cmdbuf_destroy(psb_cmdbuf_p cmdbuf)152 void psb_cmdbuf_destroy(psb_cmdbuf_p cmdbuf)
153 {
154     if (cmdbuf->size) {
155         psb_buffer_destroy(&cmdbuf->buf);
156         cmdbuf->size = 0;
157     }
158     if (cmdbuf->reloc_size) {
159         psb_buffer_destroy(&cmdbuf->reloc_buf);
160         cmdbuf->reloc_size = 0;
161     }
162     if (cmdbuf->regio_size) {
163         psb_buffer_destroy(&cmdbuf->regio_buf);
164         cmdbuf->regio_size = 0;
165     }
166     if (cmdbuf->buffer_refs_allocated) {
167         free(cmdbuf->buffer_refs);
168         cmdbuf->buffer_refs = NULL;
169         cmdbuf->buffer_refs_allocated = 0;
170     }
171 }
172 
173 /*
174  * Reset buffer & map
175  *
176  * Returns 0 on success
177  */
psb_cmdbuf_reset(psb_cmdbuf_p cmdbuf)178 int psb_cmdbuf_reset(psb_cmdbuf_p cmdbuf)
179 {
180     int ret;
181 
182     cmdbuf->MTX_msg = NULL;
183     cmdbuf->cmd_base = NULL;
184     cmdbuf->cmd_idx = NULL;
185     cmdbuf->cmd_bitstream_size = NULL;
186     cmdbuf->lldma_base = NULL;
187     cmdbuf->lldma_idx = NULL;
188     cmdbuf->reloc_base = NULL;
189     cmdbuf->reloc_idx = NULL;
190     cmdbuf->last_next_segment_cmd = NULL;
191 
192     cmdbuf->buffer_refs_count = 0;
193     cmdbuf->cmd_count = 0;
194     cmdbuf->deblock_count = 0;
195     cmdbuf->oold_count = 0;
196     cmdbuf->host_be_opp_count = 0;
197     cmdbuf->frame_info_count = 0;
198 #ifdef SLICE_HEADER_PARSING
199     cmdbuf->parse_count = 0;
200 #endif
201     ret = psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base);
202     if (ret) {
203         return ret;
204     }
205     ret = psb_buffer_map(&cmdbuf->reloc_buf, &cmdbuf->MTX_msg);
206     if (ret) {
207         psb_buffer_unmap(&cmdbuf->buf);
208         return ret;
209     }
210 
211     cmdbuf->cmd_start = cmdbuf->cmd_base;
212     cmdbuf->cmd_idx = (uint32_t *) cmdbuf->cmd_base;
213     cmdbuf->cmd_bitstream_size = NULL;
214     cmdbuf->lldma_base = cmdbuf->cmd_base + CMD_SIZE;
215     cmdbuf->lldma_idx = cmdbuf->lldma_base;
216 
217     cmdbuf->reloc_base = cmdbuf->MTX_msg + MTXMSG_SIZE;
218     cmdbuf->reloc_idx = (struct drm_psb_reloc *) cmdbuf->reloc_base;
219 
220     /* Add ourselves to the buffer list */
221     psb_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->reloc_buf); /* reloc buf == 0 */
222     psb_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->buf); /* cmd buf == 1 */
223     return ret;
224 }
225 
226 /*
227  * Unmap buffer
228  *
229  * Returns 0 on success
230  */
psb_cmdbuf_unmap(psb_cmdbuf_p cmdbuf)231 int psb_cmdbuf_unmap(psb_cmdbuf_p cmdbuf)
232 {
233     cmdbuf->MTX_msg = NULL;
234     cmdbuf->cmd_base = NULL;
235     cmdbuf->cmd_start = NULL;
236     cmdbuf->cmd_idx = NULL;
237     cmdbuf->cmd_bitstream_size = NULL;
238     cmdbuf->lldma_base = NULL;
239     cmdbuf->lldma_idx = NULL;
240     cmdbuf->reloc_base = NULL;
241     cmdbuf->reloc_idx = NULL;
242     cmdbuf->cmd_count = 0;
243     psb_buffer_unmap(&cmdbuf->buf);
244     psb_buffer_unmap(&cmdbuf->reloc_buf);
245     return 0;
246 }
247 
248 
249 /*
250  * Reference an addtional buffer "buf" in the command stream
251  * Returns a reference index that can be used to refer to "buf" in
252  * relocation records, -1 on error
253  */
psb_cmdbuf_buffer_ref(psb_cmdbuf_p cmdbuf,psb_buffer_p buf)254 int psb_cmdbuf_buffer_ref(psb_cmdbuf_p cmdbuf, psb_buffer_p buf)
255 {
256     int item_loc = 0;
257 
258     // buf->next = NULL; /* buf->next only used for buffer list validation */
259     while ((item_loc < cmdbuf->buffer_refs_count)
260            && (wsbmKBufHandle(wsbmKBuf(cmdbuf->buffer_refs[item_loc]->drm_buf))
261                != wsbmKBufHandle(wsbmKBuf(buf->drm_buf)))) {
262         item_loc++;
263     }
264     if (item_loc == cmdbuf->buffer_refs_count) {
265         /* Add new entry */
266         if (item_loc >= cmdbuf->buffer_refs_allocated) {
267             /* Allocate more entries */
268             int new_size = cmdbuf->buffer_refs_allocated + 10;
269             psb_buffer_p *new_array;
270             new_array = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * new_size);
271             if (NULL == new_array) {
272                 return -1; /* Allocation failure */
273             }
274             memcpy(new_array, cmdbuf->buffer_refs, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
275             free(cmdbuf->buffer_refs);
276             cmdbuf->buffer_refs_allocated = new_size;
277             cmdbuf->buffer_refs = new_array;
278         }
279         cmdbuf->buffer_refs[item_loc] = buf;
280         cmdbuf->buffer_refs_count++;
281         buf->status = psb_bs_queued;
282 
283         buf->next = NULL;
284         buf->unfence_flag = 0;
285     }
286 
287     /* only for RAR buffers */
288     if ((cmdbuf->buffer_refs[item_loc] != buf)
289         && (buf->rar_handle != 0)) {
290         psb_buffer_p tmp = cmdbuf->buffer_refs[item_loc];
291         drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: found same drm buffer with different psb buffer, link them\n",
292                                  tmp, buf);
293         while ((tmp->next != NULL)) {
294             tmp = tmp->next;
295             if (tmp == buf) /* found same buffer */
296                 break;
297         }
298 
299         if (tmp != buf) {
300             tmp->next = buf; /* link it */
301             buf->status = psb_bs_queued;
302             buf->next = NULL;
303         } else {
304             drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: buffer aleady in the list, skip\n",
305                                      tmp, buf);
306         }
307     }
308 
309     return item_loc;
310 }
311 
312 /* Creates a relocation record for a DWORD in the mapped "cmdbuf" at address
313  * "addr_in_cmdbuf"
314  * The relocation is based on the device virtual address of "ref_buffer"
315  * "buf_offset" is be added to the device virtual address, and the sum is then
316  * right shifted with "align_shift".
317  * "mask" determines which bits of the target DWORD will be updated with the so
318  * constructed address. The remaining bits will be filled with bits from "background".
319  */
psb_cmdbuf_add_relocation(psb_cmdbuf_p cmdbuf,uint32_t * addr_in_cmdbuf,psb_buffer_p ref_buffer,uint32_t buf_offset,uint32_t mask,uint32_t background,uint32_t align_shift,uint32_t dst_buffer)320 void psb_cmdbuf_add_relocation(psb_cmdbuf_p cmdbuf,
321                                uint32_t *addr_in_cmdbuf,
322                                psb_buffer_p ref_buffer,
323                                uint32_t buf_offset,
324                                uint32_t mask,
325                                uint32_t background,
326                                uint32_t align_shift,
327                                uint32_t dst_buffer) /* 0 = reloc buf, 1 = cmdbuf, 2 = for host reloc */
328 {
329     struct drm_psb_reloc *reloc = cmdbuf->reloc_idx;
330     uint64_t presumed_offset = wsbmBOOffsetHint(ref_buffer->drm_buf);
331 
332     /* Check that address is within buffer range */
333     if (dst_buffer) {
334         ASSERT(((unsigned char *)(addr_in_cmdbuf)) >= cmdbuf->cmd_base);
335         ASSERT(((unsigned char *)(addr_in_cmdbuf)) < LLDMA_END(cmdbuf));
336         reloc->where = addr_in_cmdbuf - (uint32_t *) cmdbuf->cmd_base; /* Location in DWORDs */
337     } else {
338         ASSERT(((unsigned char *)(addr_in_cmdbuf)) >= cmdbuf->MTX_msg);
339         ASSERT(((unsigned char *)(addr_in_cmdbuf)) < MTXMSG_END(cmdbuf));
340         reloc->where = addr_in_cmdbuf - (uint32_t *) cmdbuf->MTX_msg; /* Location in DWORDs */
341     }
342 
343     reloc->buffer = psb_cmdbuf_buffer_ref(cmdbuf, ref_buffer);
344     ASSERT(reloc->buffer != -1);
345 
346     reloc->reloc_op = PSB_RELOC_OP_OFFSET;
347 
348     psb__trace_message("[RE] Reloc at offset %08x (%08x), offset = %08x background = %08x buffer = %d (%08x)\n",
349         reloc->where, reloc->where << 2, buf_offset, background, reloc->buffer, presumed_offset);
350 
351     if (presumed_offset) {
352         uint32_t new_val =  presumed_offset + buf_offset;
353         new_val = ((new_val >> align_shift) << (align_shift << PSB_RELOC_ALSHIFT_SHIFT));
354         new_val = (background & ~mask) | (new_val & mask);
355         *addr_in_cmdbuf = new_val;
356     } else {
357         *addr_in_cmdbuf = PSB_RELOC_MAGIC;
358     }
359 
360     reloc->mask = mask;
361     reloc->shift = align_shift << PSB_RELOC_ALSHIFT_SHIFT;
362     reloc->pre_add =  buf_offset;
363     reloc->background = background;
364     reloc->dst_buffer = dst_buffer;
365     cmdbuf->reloc_idx++;
366 
367     ASSERT(((unsigned char *)(cmdbuf->reloc_idx)) < RELOC_END(cmdbuf));
368 }
369 
370 /*
371  * Advances "obj_context" to the next cmdbuf
372  *
373  * Returns 0 on success
374  */
psb_context_get_next_cmdbuf(object_context_p obj_context)375 int psb_context_get_next_cmdbuf(object_context_p obj_context)
376 {
377     psb_cmdbuf_p cmdbuf;
378     int ret;
379 
380     if (obj_context->cmdbuf) {
381         return 0;
382     }
383 
384     obj_context->cmdbuf_current++;
385     if (obj_context->cmdbuf_current >= PSB_MAX_CMDBUFS) {
386         obj_context->cmdbuf_current = 0;
387     }
388     cmdbuf = obj_context->cmdbuf_list[obj_context->cmdbuf_current];
389     ret = psb_cmdbuf_reset(cmdbuf);
390     if (!ret) {
391         /* Success */
392         obj_context->cmdbuf = cmdbuf;
393     }
394     return ret;
395 }
396 
397 
398 static unsigned
psbTimeDiff(struct timeval * now,struct timeval * then)399 psbTimeDiff(struct timeval *now, struct timeval *then)
400 {
401     long long val;
402 
403     val = now->tv_sec - then->tv_sec;
404     val *= 1000000LL;
405     val += now->tv_usec;
406     val -= then->tv_usec;
407     if (val < 1LL)
408         val = 1LL;
409 
410     return (unsigned) val;
411 }
412 
413 /*
414  * This is the user-space do-it-all interface to the drm cmdbuf ioctl.
415  * It allows different buffers as command- and reloc buffer. A list of
416  * cliprects to apply and whether to copy the clipRect content to all
417  * scanout buffers (damage = 1).
418  */
419 /*
420  * Don't add debug statements in this function, it gets called with the
421  * DRM lock held and output to an X terminal can cause X to deadlock
422  */
423 static int
psbDRMCmdBuf(int fd,int ioctl_offset,psb_buffer_p * buffer_list,int buffer_count,unsigned cmdBufHandle,unsigned cmdBufOffset,unsigned cmdBufSize,unsigned relocBufHandle,unsigned relocBufOffset,unsigned numRelocs,int __maybe_unused damage,unsigned engine,unsigned fence_flags,struct psb_ttm_fence_rep * fence_arg)424 psbDRMCmdBuf(int fd, int ioctl_offset, psb_buffer_p *buffer_list, int buffer_count, unsigned cmdBufHandle,
425              unsigned cmdBufOffset, unsigned cmdBufSize,
426              unsigned relocBufHandle, unsigned relocBufOffset,
427              unsigned numRelocs, int __maybe_unused damage,
428              unsigned engine, unsigned fence_flags, struct psb_ttm_fence_rep *fence_arg)
429 {
430     drm_psb_cmdbuf_arg_t ca;
431     struct psb_validate_arg *arg_list;
432     int i;
433     int ret;
434     struct timeval then, now;
435     Bool have_then = FALSE;
436     uint64_t mask = PSB_GPU_ACCESS_MASK;
437 
438     arg_list = (struct psb_validate_arg *) calloc(1, sizeof(struct psb_validate_arg) * buffer_count);
439     if (arg_list == NULL) {
440         drv_debug_msg(VIDEO_DEBUG_ERROR, "Malloc failed \n");
441         return -ENOMEM;
442     }
443 
444     for (i = 0; i < buffer_count; i++) {
445         struct psb_validate_arg *arg = &(arg_list[i]);
446         struct psb_validate_req *req = &arg->d.req;
447 
448         req->next = (unsigned long) & (arg_list[i+1]);
449 
450         req->buffer_handle = wsbmKBufHandle(wsbmKBuf(buffer_list[i]->drm_buf));
451         //req->group = 0;
452         req->set_flags = (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) & mask;
453         req->clear_flags = (~(PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)) & mask;
454 
455         req->presumed_gpu_offset = (uint64_t)wsbmBOOffsetHint(buffer_list[i]->drm_buf);
456         req->presumed_flags = PSB_USE_PRESUMED;
457         req->pad64 = (uint32_t)buffer_list[i]->pl_flags;
458 #ifndef BAYTRAIL
459         req->unfence_flag = buffer_list[i]->unfence_flag;
460 #endif
461     }
462     arg_list[buffer_count-1].d.req.next = 0;
463 
464     ca.buffer_list = (uint64_t)((unsigned long)arg_list);
465     ca.fence_arg = (uint64_t)((unsigned long)fence_arg);
466 
467     ca.cmdbuf_handle = cmdBufHandle;
468     ca.cmdbuf_offset = cmdBufOffset;
469     ca.cmdbuf_size = cmdBufSize;
470 
471     ca.reloc_handle = relocBufHandle;
472     ca.reloc_offset = relocBufOffset;
473     ca.num_relocs = numRelocs;
474 
475     ca.fence_flags = fence_flags;
476     ca.engine = engine;
477 
478 #if 0
479     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: buffer_list   = %08x\n", ca.buffer_list);
480     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: clip_rects    = %08x\n", ca.clip_rects);
481     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: cmdbuf_handle = %08x\n", ca.cmdbuf_handle);
482     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: cmdbuf_offset = %08x\n", ca.cmdbuf_offset);
483     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: cmdbuf_size   = %08x\n", ca.cmdbuf_size);
484     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: reloc_handle  = %08x\n", ca.reloc_handle);
485     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: reloc_offset  = %08x\n", ca.reloc_offset);
486     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: num_relocs    = %08x\n", ca.num_relocs);
487     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: engine        = %08x\n", ca.engine);
488     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: fence_flags   = %08x\n", ca.fence_flags);
489 #endif
490 
491     /*
492      * X server Signals will clobber the kernel time out mechanism.
493      * we need a user-space timeout as well.
494      */
495     do {
496         ret = drmCommandWrite(fd, ioctl_offset, &ca, sizeof(ca));
497         if (ret == EAGAIN) {
498             if (!have_then) {
499                 if (gettimeofday(&then, NULL)) {
500                     drv_debug_msg(VIDEO_DEBUG_ERROR, "Gettimeofday error.\n");
501                     break;
502                 }
503 
504                 have_then = TRUE;
505             }
506             if (gettimeofday(&now, NULL)) {
507                 drv_debug_msg(VIDEO_DEBUG_ERROR, "Gettimeofday error.\n");
508                 break;
509             }
510 
511         }
512     } while ((ret == EAGAIN) && (psbTimeDiff(&now, &then) < PSB_TIMEOUT_USEC));
513 
514     if (ret) {
515         drv_debug_msg(VIDEO_DEBUG_GENERAL, "command write return is %d\n", ret);
516         goto out;
517     }
518 
519     for (i = 0; i < buffer_count; i++) {
520         struct psb_validate_arg *arg = &(arg_list[i]);
521         struct psb_validate_rep *rep = &arg->d.rep;
522 
523 #ifndef BAYTRAIL
524         if (arg->d.req.unfence_flag)
525             continue;
526 #endif
527 
528         if (!arg->handled) {
529             ret = -EFAULT;
530             goto out;
531         }
532         if (arg->ret != 0) {
533             ret = arg->ret;
534             goto out;
535         }
536         wsbmUpdateKBuf(wsbmKBuf(buffer_list[i]->drm_buf),
537                        rep->gpu_offset, rep->placement, rep->fence_type_mask);
538     }
539 
540 out:
541     free(arg_list);
542     for (i = 0; i < buffer_count; i++) {
543         /*
544          * Buffer no longer queued in userspace
545          */
546         psb_buffer_p tmp = buffer_list[i];
547 
548         /*
549          * RAR slice buffer/surface buffer are share one BO, and then only one in
550          * buffer_list, but they are linked in psb_cmdbuf_buffer_ref
551 
552          */
553         if (buffer_list[i]->rar_handle == 0)
554             tmp->next = NULL; /* don't loop for non RAR buffer, "next" may be not initialized  */
555 
556         do {
557             psb_buffer_p p = tmp;
558 
559             tmp = tmp->next;
560             switch (p->status) {
561             case psb_bs_queued:
562                 p->status = psb_bs_ready;
563                 break;
564 
565             case psb_bs_abandoned:
566                 psb_buffer_destroy(p);
567                 free(p);
568                 break;
569 
570             default:
571                 /* Not supposed to happen */
572                 ASSERT(0);
573             }
574         } while (tmp);
575     }
576 
577     return ret;
578 }
579 
580 #if 0
581 int psb_fence_destroy(struct _WsbmFenceObject *pFence)
582 {
583     wsbmFenceUnreference(&pFence);
584 
585     return 0;
586 }
587 
588 struct _WsbmFenceObject *
589 psb_fence_wait(psb_driver_data_p driver_data,
590                struct psb_ttm_fence_rep *fence_rep, int *status)
591 
592 {
593     struct _WsbmFenceObject *fence = NULL;
594     int ret = -1;
595 
596     /* copy fence information */
597     if (fence_rep->error != 0) {
598         drv_debug_msg(VIDEO_DEBUG_ERROR, "drm failed to create a fence"
599                            " and has idled the HW\n");
600         DEBUG_FAILURE_RET;
601         return NULL;
602     }
603 
604     fence = wsbmFenceCreate(driver_data->fence_mgr, fence_rep->fence_class,
605                             fence_rep->fence_type,
606                             (unsigned char *)fence_rep->handle,
607                             0);
608     if (fence)
609         *status = wsbmFenceFinish(fence, fence_rep->fence_type, 0);
610 
611     return fence;
612 }
613 #endif
614 
615 /*
616  * Closes the last segment
617  */
psb_cmdbuf_close_segment(psb_cmdbuf_p __maybe_unused cmdbuf)618 static void psb_cmdbuf_close_segment(psb_cmdbuf_p __maybe_unused cmdbuf)
619 {
620 #if 0
621     uint32_t bytes_used = ((unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start) % MTX_SEG_SIZE;
622     unsigned char *segment_start = (unsigned char *) cmdbuf->cmd_idx - bytes_used;
623     uint32_t lldma_record_offset = psb_cmdbuf_lldma_create(cmdbuf,
624                                    &(cmdbuf->buf), (segment_start - cmdbuf->cmd_base) /* offset */,
625                                    bytes_used,
626                                    0 /* destination offset */,
627                                    LLDMA_TYPE_RENDER_BUFF_MC);
628     uint32_t cmd = CMD_NEXT_SEG;
629     RELOC_SHIFT4(*cmdbuf->last_next_segment_cmd, lldma_record_offset, cmd, &(cmdbuf->buf));
630     *(cmdbuf->last_next_segment_cmd + 1) = bytes_used;
631 #endif
632 }
633 
634 /* Issue deblock cmd, HW will do deblock instead of host */
psb_context_submit_hw_deblock(object_context_p obj_context,psb_buffer_p buf_a,psb_buffer_p buf_b,psb_buffer_p colocate_buffer,uint32_t picture_widht_mb,uint32_t frame_height_mb,uint32_t rotation_flags,uint32_t field_type,uint32_t ext_stride_a,uint32_t chroma_offset_a,uint32_t chroma_offset_b,uint32_t is_oold)635 int psb_context_submit_hw_deblock(object_context_p obj_context,
636                                   psb_buffer_p buf_a,
637                                   psb_buffer_p buf_b,
638                                   psb_buffer_p colocate_buffer,
639                                   uint32_t picture_widht_mb,
640                                   uint32_t frame_height_mb,
641                                   uint32_t rotation_flags,
642                                   uint32_t field_type,
643                                   uint32_t ext_stride_a,
644                                   uint32_t chroma_offset_a,
645                                   uint32_t chroma_offset_b,
646                                   uint32_t is_oold)
647 {
648     psb_cmdbuf_p cmdbuf = obj_context->cmdbuf;
649     psb_driver_data_p driver_data = obj_context->driver_data;
650     uint32_t msg_size = FW_DEVA_DEBLOCK_SIZE;
651     unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */
652     FW_VA_DEBLOCK_MSG *deblock_msg;
653 
654     uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + item_size * cmdbuf->cmd_count);
655 
656     memset(msg, 0, sizeof(FW_VA_DEBLOCK_MSG));
657     deblock_msg = (FW_VA_DEBLOCK_MSG *)msg;
658 
659     deblock_msg->header.bits.msg_size = FW_DEVA_DEBLOCK_SIZE;
660     if (is_oold)
661         deblock_msg->header.bits.msg_type = VA_MSGID_OOLD_MFLD;
662     else
663         deblock_msg->header.bits.msg_type = VA_MSGID_DEBLOCK_MFLD;
664     deblock_msg->flags.bits.flags = FW_VA_RENDER_HOST_INT | FW_VA_RENDER_IS_LAST_SLICE | FW_DEVA_DEBLOCK_ENABLE;
665     deblock_msg->flags.bits.slice_type = field_type;
666     deblock_msg->operating_mode = obj_context->operating_mode;
667     deblock_msg->mmu_context.bits.context = (uint8_t)(obj_context->msvdx_context);
668     deblock_msg->pic_size.bits.frame_height_mb = (uint16_t)frame_height_mb;
669     deblock_msg->pic_size.bits.pic_width_mb = (uint16_t)picture_widht_mb;
670     deblock_msg->ext_stride_a = ext_stride_a;
671     deblock_msg->rotation_flags = rotation_flags;
672 
673     RELOC_MSG(deblock_msg->address_a0, buf_a->buffer_ofs, buf_a);
674     RELOC_MSG(deblock_msg->address_a1, buf_a->buffer_ofs + chroma_offset_a, buf_a);
675     if (buf_b) {
676         RELOC_MSG(deblock_msg->address_b0, buf_b->buffer_ofs, buf_b);
677         RELOC_MSG(deblock_msg->address_b1, buf_b->buffer_ofs + chroma_offset_b, buf_b);
678     }
679 
680     RELOC_MSG(deblock_msg->mb_param_address, colocate_buffer->buffer_ofs, colocate_buffer);
681     cmdbuf->deblock_count++;
682     return 0;
683 }
684 
685 #ifdef PSBVIDEO_MSVDX_EC
psb_context_submit_host_be_opp(object_context_p obj_context,psb_buffer_p buf_a,psb_buffer_p buf_b,psb_buffer_p __maybe_unused buf_c,uint32_t picture_widht_mb,uint32_t frame_height_mb,uint32_t rotation_flags,uint32_t field_type,uint32_t ext_stride_a,uint32_t chroma_offset_a,uint32_t chroma_offset_b)686 int psb_context_submit_host_be_opp(object_context_p obj_context,
687                                   psb_buffer_p buf_a,
688                                   psb_buffer_p buf_b,
689                                   psb_buffer_p __maybe_unused buf_c,
690                                   uint32_t picture_widht_mb,
691                                   uint32_t frame_height_mb,
692                                   uint32_t rotation_flags,
693                                   uint32_t field_type,
694                                   uint32_t ext_stride_a,
695                                   uint32_t chroma_offset_a,
696                                   uint32_t chroma_offset_b)
697 {
698     psb_cmdbuf_p cmdbuf = obj_context->cmdbuf;
699     psb_driver_data_p driver_data = obj_context->driver_data;
700     uint32_t msg_size = sizeof(FW_VA_DEBLOCK_MSG);
701     unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */
702     FW_VA_DEBLOCK_MSG *deblock_msg;
703 
704     uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + item_size * cmdbuf->cmd_count + cmdbuf->deblock_count * msg_size);
705 
706     memset(msg, 0, sizeof(FW_VA_DEBLOCK_MSG));
707     deblock_msg = (FW_VA_DEBLOCK_MSG *)msg;
708 
709     deblock_msg->header.bits.msg_size = FW_DEVA_DEBLOCK_SIZE;
710     deblock_msg->header.bits.msg_type = VA_MSGID_HOST_BE_OPP_MFLD;
711     deblock_msg->flags.bits.flags = FW_VA_RENDER_HOST_INT | FW_ERROR_DETECTION_AND_RECOVERY;
712     deblock_msg->flags.bits.slice_type = field_type;
713     deblock_msg->operating_mode = obj_context->operating_mode;
714     deblock_msg->mmu_context.bits.context = (uint8_t)(obj_context->msvdx_context);
715     deblock_msg->pic_size.bits.frame_height_mb = (uint16_t)frame_height_mb;
716     deblock_msg->pic_size.bits.pic_width_mb = (uint16_t)picture_widht_mb;
717     deblock_msg->ext_stride_a = ext_stride_a;
718     deblock_msg->rotation_flags = rotation_flags;
719 
720     RELOC_MSG(deblock_msg->address_a0, buf_a->buffer_ofs, buf_a);
721     RELOC_MSG(deblock_msg->address_a1, buf_a->buffer_ofs + chroma_offset_a, buf_a);
722     RELOC_MSG(deblock_msg->address_b0, buf_b->buffer_ofs, buf_b);
723     RELOC_MSG(deblock_msg->address_b1, buf_b->buffer_ofs + chroma_offset_b, buf_b);
724 
725     deblock_msg->mb_param_address = wsbmKBufHandle(wsbmKBuf(buf_a->drm_buf));
726     cmdbuf->deblock_count++;
727     return 0;
728 }
729 #endif
730 /*
731  * Submits the current cmdbuf
732  *
733  * Returns 0 on success
734  */
psb_context_submit_cmdbuf(object_context_p obj_context)735 int psb_context_submit_cmdbuf(object_context_p obj_context)
736 {
737     psb_cmdbuf_p cmdbuf = obj_context->cmdbuf;
738     psb_driver_data_p driver_data = obj_context->driver_data;
739     unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */
740     int ret;
741 
742 
743     uint32_t cmdbuffer_size = (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start; // In bytes
744 
745     if (cmdbuf->last_next_segment_cmd) {
746         cmdbuffer_size = cmdbuf->first_segment_size;
747         psb_cmdbuf_close_segment(cmdbuf);
748     }
749 
750     uint32_t msg_size = item_size;
751     uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + cmdbuf->cmd_count * msg_size + cmdbuf->frame_info_count * FW_VA_FRAME_INFO_SIZE);
752 
753     if (psb_video_trace_fp && (psb_video_trace_level & CMDMSG_TRACE)) {
754         debug_cmd_start[cmdbuf->cmd_count] = cmdbuf->cmd_start - cmdbuf->cmd_base;
755         debug_cmd_size[cmdbuf->cmd_count] = (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start;
756         debug_cmd_count = cmdbuf->cmd_count + 1;
757     }
758 
759 /*
760     static int c = 0;
761     static char pFileName[30];
762 
763 
764     sprintf(pFileName , "cmdbuf%i.txt", c++);
765     FILE* pF = fopen(pFileName, "w");
766 
767     fwrite(cmdbuf->cmd_start, 1, cmdbuffer_size, pF);
768     fclose(pF);
769 */
770     ret = psb_cmdbuf_dump((unsigned int *)cmdbuf->cmd_start, cmdbuffer_size);
771     if(ret)
772         drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_cmdbuf: dump cmdbuf fail\n");
773 
774     cmdbuf->cmd_count++;
775     memset(msg, 0, msg_size);
776 
777     *cmdbuf->cmd_idx = 0; // Add a trailing 0 just in case.
778     ASSERT(cmdbuffer_size < CMD_SIZE);
779     ASSERT((unsigned char *) cmdbuf->cmd_idx < CMD_END(cmdbuf));
780 
781     MEMIO_WRITE_FIELD(msg, FWRK_GENMSG_SIZE,                  msg_size);
782     MEMIO_WRITE_FIELD(msg, FWRK_GENMSG_ID,                    VA_MSGID_RENDER);
783 
784         MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_CONTEXT, (obj_context->msvdx_context)); /* context is 8 bits */
785 
786     /* Point to CMDBUFFER */
787     RELOC_MSG(*(msg + (FW_DEVA_DECODE_LLDMA_ADDRESS_OFFSET / sizeof(uint32_t))),
788               (cmdbuf->cmd_start - cmdbuf->cmd_base), &(cmdbuf->buf));
789     MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_BUFFER_SIZE,          cmdbuffer_size / 4); // In dwords
790     MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_OPERATING_MODE,       obj_context->operating_mode);
791     MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_FLAGS,                obj_context->flags);
792 
793     if (psb_video_trace_fp && (psb_video_trace_level & LLDMA_TRACE)) {
794         debug_lldma_count = (cmdbuf->lldma_idx - cmdbuf->lldma_base) / sizeof(DMA_sLinkedList);
795         debug_lldma_start = cmdbuf->lldma_base - cmdbuf->cmd_base;
796         /* Indicate last LLDMA record (for debugging) */
797         ((uint32_t *)cmdbuf->lldma_idx)[1] = 0;
798     }
799 
800     cmdbuf->cmd_start = (unsigned char *)cmdbuf->cmd_idx;
801 
802     if (psb_video_trace_fp) {
803         return psb_context_flush_cmdbuf(obj_context);
804     } else {
805         if ((cmdbuf->cmd_count >= MAX_CMD_COUNT) ||
806             (MTXMSG_END(cmdbuf) - (unsigned char *) msg < MTXMSG_MARGIN) ||
807             (CMD_END(cmdbuf) - (unsigned char *) cmdbuf->cmd_idx < CMD_MARGIN) ||
808             (LLDMA_END(cmdbuf) - cmdbuf->lldma_idx < LLDMA_MARGIN) ||
809             (RELOC_END(cmdbuf) - (unsigned char *) cmdbuf->reloc_idx < RELOC_MARGIN)) {
810             return psb_context_flush_cmdbuf(obj_context);
811         }
812     }
813     return 0;
814 }
815 
816 /*
817  * Flushes all cmdbufs
818  */
psb_context_flush_cmdbuf(object_context_p obj_context)819 int psb_context_flush_cmdbuf(object_context_p obj_context)
820 {
821     psb_cmdbuf_p cmdbuf = obj_context->cmdbuf;
822     psb_driver_data_p driver_data = obj_context->driver_data;
823     unsigned int fence_flags;
824     /* unsigned int fence_handle = 0; */
825     struct psb_ttm_fence_rep fence_rep;
826     unsigned int reloc_offset;
827     unsigned int num_relocs;
828     int ret;
829     unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */
830 
831 #ifdef SLICE_HEADER_PARSING
832     if ((NULL == cmdbuf) ||
833         (0 == (cmdbuf->cmd_count + cmdbuf->deblock_count + cmdbuf->host_be_opp_count +
834             cmdbuf->frame_info_count + cmdbuf->parse_count))) {
835         return 0; // Nothing to do
836     }
837 #else
838     if ((NULL == cmdbuf) ||
839         (0 == (cmdbuf->cmd_count + cmdbuf->deblock_count + cmdbuf->host_be_opp_count + cmdbuf->frame_info_count))) {
840         return 0; // Nothing to do
841     }
842 #endif
843 
844     uint32_t msg_size = 0;
845     uint32_t *msg = (uint32_t *)cmdbuf->MTX_msg;
846     int32_t i;
847     uint32_t index;
848 
849     /* LOCK */
850     ret = LOCK_HARDWARE(driver_data);
851     if (ret) {
852         UNLOCK_HARDWARE(driver_data);
853         DEBUG_FAILURE_RET;
854         return ret;
855     }
856 
857     for (i = 1; i <= cmdbuf->frame_info_count; i++) {
858         msg_size += FW_VA_FRAME_INFO_SIZE;
859         msg += FW_VA_FRAME_INFO_SIZE / sizeof(uint32_t);
860     }
861 
862     for (i = 1; i <= cmdbuf->cmd_count; i++) {
863         uint32_t flags;
864 
865         flags = MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_FLAGS);
866 
867         /* Update flags */
868         int bBatchEnd = (i == (cmdbuf->cmd_count + cmdbuf->deblock_count + cmdbuf->oold_count
869                                + cmdbuf->host_be_opp_count));
870         flags |=
871             (bBatchEnd ? FW_VA_RENDER_HOST_INT : FW_VA_RENDER_NO_RESPONCE_MSG);
872 
873 #ifdef PSBVIDEO_MSVDX_EC
874         if (driver_data->ec_enabled)
875             flags |= FW_ERROR_DETECTION_AND_RECOVERY;
876 #endif
877 
878         MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_FLAGS, flags);
879 
880         psb__trace_message("MSG BUFFER_SIZE       = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_BUFFER_SIZE));
881         psb__trace_message("MSG OPERATING_MODE    = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_OPERATING_MODE));
882         psb__trace_message("MSG FLAGS             = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_FLAGS));
883 
884         drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSG BUFFER_SIZE       = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_BUFFER_SIZE));
885         drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSG OPERATING_MODE    = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_OPERATING_MODE));
886         drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSG FLAGS             = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_FLAGS));
887 
888 #if 0  /* todo */
889         /* Update SAREA */
890         driver_data->psb_sarea->msvdx_context = obj_context->msvdx_context;
891 #endif
892         msg += item_size / sizeof(uint32_t);
893         msg_size += item_size;
894     }
895 
896     /* Assume deblock message is following render messages and no more render message behand deblock message */
897     for (i = 1; i <= cmdbuf->deblock_count; i++) {
898             msg_size += sizeof(FW_VA_DEBLOCK_MSG);
899     }
900 
901     for (i = 1; i <= cmdbuf->oold_count; i++) {
902         msg_size += sizeof(FW_VA_DEBLOCK_MSG);
903     }
904 
905     for (i = 1; i <= cmdbuf->host_be_opp_count; i++) {
906         msg_size += FW_VA_HOST_BE_OPP_SIZE;
907     }
908 #ifdef SLICE_HEADER_PARSING
909     for (i = 1; i <= cmdbuf->parse_count; i++) {
910         msg_size += sizeof(struct fw_slice_header_extract_msg);
911     }
912 #endif
913     /* Now calculate the total number of relocations */
914     reloc_offset = cmdbuf->reloc_base - cmdbuf->MTX_msg;
915     num_relocs = (((unsigned char *) cmdbuf->reloc_idx) - cmdbuf->reloc_base) / sizeof(struct drm_psb_reloc);
916 
917     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf MTXMSG size = %08x [%08x]\n", msg_size, MTXMSG_SIZE);
918     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf CMD size = %08x - %d[%08x]\n", (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_base, cmdbuf->cmd_count, CMD_SIZE);
919     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf LLDMA size = %08x [%08x]\n", cmdbuf->lldma_idx - cmdbuf->lldma_base, LLDMA_SIZE);
920     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf RELOC size = %08x [%08x]\n", num_relocs * sizeof(struct drm_psb_reloc), RELOC_SIZE);
921 
922     psb_cmdbuf_unmap(cmdbuf);
923 
924     psb__trace_message(NULL); /* Flush trace */
925 
926     ASSERT(NULL == cmdbuf->MTX_msg);
927     ASSERT(NULL == cmdbuf->reloc_base);
928 
929     if (psb_video_trace_fp)
930         fence_flags = 0;
931     else
932         fence_flags = DRM_PSB_FENCE_NO_USER;
933 
934 #ifdef SLICE_HEADER_PARSING
935     if (obj_context->msvdx_frame_end)
936         fence_flags |= PSB_SLICE_EXTRACT_UPDATE;
937 #endif
938     /* cmdbuf will be validated as part of the buffer list */
939     /* Submit */
940     wsbmWriteLockKernelBO();
941     ret = psbDRMCmdBuf(driver_data->drm_fd, driver_data->execIoctlOffset, cmdbuf->buffer_refs,
942                        cmdbuf->buffer_refs_count,
943                        wsbmKBufHandle(wsbmKBuf(cmdbuf->reloc_buf.drm_buf)),
944                        0, msg_size,
945                        wsbmKBufHandle(wsbmKBuf(cmdbuf->reloc_buf.drm_buf)),
946                        reloc_offset, num_relocs,
947                        0, PSB_ENGINE_DECODE, fence_flags, &fence_rep);
948     wsbmWriteUnlockKernelBO();
949     UNLOCK_HARDWARE(driver_data);
950 
951     if (ret) {
952         obj_context->cmdbuf = NULL;
953         obj_context->slice_count++;
954 
955         DEBUG_FAILURE_RET;
956         return ret;
957     }
958 
959     if (psb_video_trace_fp) {
960 #if 0
961         static int error_count = 0;
962         int status = 0;
963         struct _WsbmFenceObject *fence = NULL;
964         fence = psb_fence_wait(driver_data, &fence_rep, &status);
965         drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_fence_wait returns: %d (fence=0x%08x)\n", status, fence);
966 #endif
967 
968         psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base);
969         int ret;
970         ret = psb_buffer_map(&cmdbuf->reloc_buf, &cmdbuf->MTX_msg);
971         if(ret) {
972             psb_buffer_unmap(&cmdbuf->buf);
973             return ret;
974         }
975 
976         if (psb_video_trace_level & LLDMA_TRACE) {
977             psb__trace_message("lldma_count = %d, vitual=0x%08x\n",
978                                debug_lldma_count,  wsbmBOOffsetHint(cmdbuf->buf.drm_buf) + CMD_SIZE);
979             for (index = 0; index < debug_lldma_count; index++) {
980                 DMA_sLinkedList* pasDmaList = (DMA_sLinkedList*)(cmdbuf->cmd_base + debug_lldma_start);
981                 pasDmaList += index;
982 
983                 psb__trace_message("\nLLDMA record at offset %08x\n", ((unsigned char*)pasDmaList) - cmdbuf->cmd_base);
984                 DW(0, BSWAP,    31, 31)
985                 DW(0, DIR,    30, 30)
986                 DW(0, PW,    29, 28)
987                 DW(1, List_FIN, 31, 31)
988                 DW(1, List_INT, 30, 30)
989                 DW(1, PI,    18, 17)
990                 DW(1, INCR,    16, 16)
991                 DW(1, LEN,    15, 0)
992                 DWH(2, ADDR,    22, 0)
993                 DW(3, ACC_DEL,    31, 29)
994                 DW(3, BURST,    28, 26)
995                 DWH(3, EXT_SA,    3, 0)
996                 DW(4, 2D_MODE,    16, 16)
997                 DW(4, REP_COUNT, 10, 0)
998                 DWH(5, LINE_ADD_OFF, 25, 16)
999                 DW(5, ROW_LENGTH, 9, 0)
1000                 DWH(6, SA, 31, 0)
1001                 DWH(7, LISTPTR, 27, 0)
1002             }
1003         }
1004 
1005         if (psb_video_trace_level & AUXBUF_TRACE) {
1006             psb__trace_message("debug_dump_count = %d\n", debug_dump_count);
1007             for (index = 0; index < debug_dump_count; index++) {
1008                 unsigned char *buf_addr;
1009                 psb__trace_message("Buffer %d = '%s' offset = %08x size = %08x\n", index, debug_dump_name[index], debug_dump_offset[index], debug_dump_size[index]);
1010                 if (debug_dump_buf[index]->rar_handle
1011                     || (psb_buffer_map(debug_dump_buf[index], &buf_addr) != 0)) {
1012                     psb__trace_message("Unmappable buffer,e.g. RAR buffer\n");
1013                     continue;
1014                 }
1015 
1016                 g_hexdump_offset = 0;
1017                 psb__hexdump(buf_addr + debug_dump_offset[index], debug_dump_size[index]);
1018                 psb_buffer_unmap(debug_dump_buf[index]);
1019             }
1020             debug_dump_count = 0;
1021         }
1022 
1023         if (psb_video_trace_level & CMDMSG_TRACE) {
1024             psb__trace_message("cmd_count = %d, virtual=0x%08x\n",
1025                                debug_cmd_count, wsbmBOOffsetHint(cmdbuf->buf.drm_buf));
1026             for (index = 0; index < debug_cmd_count; index++) {
1027                 uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + index * item_size);
1028                 uint32_t j;
1029                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "start = %08x size = %08x\n", debug_cmd_start[index], debug_cmd_size[index]);
1030                 debug_dump_cmdbuf((uint32_t *)(cmdbuf->cmd_base + debug_cmd_start[index]), debug_cmd_size[index]);
1031 
1032                 for (j = 0; j < item_size / 4; j++) {
1033                     psb__trace_message("MTX msg[%d] = 0x%08x", j, *(msg + j));
1034                     switch (j) {
1035                     case 0:
1036                         psb__trace_message("[BufferSize|ID|MSG_SIZE]\n");
1037                         break;
1038                     case 1:
1039                         psb__trace_message("[MMUPTD]\n");
1040                         break;
1041                     case 2:
1042                         psb__trace_message("[LLDMA_address]\n");
1043                         break;
1044                     case 3:
1045                         psb__trace_message("[Context]\n");
1046                         break;
1047                     case 4:
1048                         psb__trace_message("[Fence_Value]\n");
1049                         break;
1050                     case 5:
1051                         psb__trace_message("[Operating_Mode]\n");
1052                         break;
1053                     case 6:
1054                         psb__trace_message("[LastMB|FirstMB]\n");
1055                         break;
1056                     case 7:
1057                         psb__trace_message("[Flags]\n");
1058                         break;
1059                     default:
1060                         psb__trace_message("[overflow]\n");
1061                         break;
1062                     }
1063                 }
1064             }
1065             debug_cmd_count = 0;
1066         }
1067         psb_buffer_unmap(&cmdbuf->buf);
1068         psb_buffer_unmap(&cmdbuf->reloc_buf);
1069 
1070         cmdbuf->cmd_base = NULL;
1071 #if 0
1072         if (status) {
1073             drv_debug_msg(VIDEO_DEBUG_ERROR, "RENDERING ERROR FRAME=%03d SLICE=%02d status=%d\n", obj_context->frame_count, obj_context->slice_count, status);
1074             error_count++;
1075             ASSERT(status != 2);
1076             ASSERT(error_count < 40); /* Exit on 40 errors */
1077         }
1078         if (fence)
1079             psb_fence_destroy(fence);
1080 #endif
1081     }
1082 
1083     obj_context->cmdbuf = NULL;
1084     obj_context->slice_count++;
1085 
1086     return 0;
1087 }
1088 
1089 
1090 typedef enum {
1091     MMU_GROUP0 = 0,
1092     MMU_GROUP1 = 1,
1093 } MMU_GROUP;
1094 
1095 typedef enum    {
1096     HOST_TO_MSVDX = 0,
1097     MSXDX_TO_HOST = 1,
1098 } DMA_DIRECTION;
1099 
1100 typedef struct {
1101     IMG_UINT32 ui32DevDestAddr ;        /* destination address */
1102     DMA_ePW     ePeripheralWidth;
1103     DMA_ePeriphIncrSize ePeriphIncrSize;
1104     DMA_ePeriphIncr     ePeriphIncr;
1105     IMG_BOOL            bSynchronous;
1106     MMU_GROUP           eMMUGroup;
1107     DMA_DIRECTION       eDMADir;
1108     DMA_eBurst          eDMA_eBurst;
1109 } DMA_DETAIL_LOOKUP;
1110 
1111 
1112 static const DMA_DETAIL_LOOKUP DmaDetailLookUp[] = {
1113     /* LLDMA_TYPE_VLC_TABLE */ {
1114         REG_MSVDX_VEC_VLC_OFFSET  ,
1115         DMA_PWIDTH_16_BIT,      /* 16 bit wide data*/
1116         DMA_PERIPH_INCR_4,      /* Incrament the dest by 32 bits */
1117         DMA_PERIPH_INCR_ON,
1118         IMG_TRUE,
1119         MMU_GROUP0,
1120         HOST_TO_MSVDX,
1121         DMA_BURST_2
1122     },
1123     /* LLDMA_TYPE_BITSTREAM */ {
1124         (REG_MSVDX_VEC_OFFSET + MSVDX_VEC_CR_VEC_SHIFTREG_STREAMIN_OFFSET),
1125         DMA_PWIDTH_8_BIT,
1126         DMA_PERIPH_INCR_1,
1127         DMA_PERIPH_INCR_OFF,
1128         IMG_FALSE,
1129         MMU_GROUP0,
1130         HOST_TO_MSVDX,
1131         DMA_BURST_4
1132     },
1133     /*LLDMA_TYPE_RESIDUAL*/             {
1134         (REG_MSVDX_VDMC_OFFSET + MSVDX_VDMC_CR_VDMC_RESIDUAL_DIRECT_INSERT_DATA_OFFSET),
1135         DMA_PWIDTH_32_BIT,
1136         DMA_PERIPH_INCR_1,
1137         DMA_PERIPH_INCR_OFF,
1138         IMG_FALSE,
1139         MMU_GROUP1,
1140         HOST_TO_MSVDX,
1141         DMA_BURST_4
1142     },
1143 
1144     /*LLDMA_TYPE_RENDER_BUFF_MC*/{
1145         (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET),
1146         DMA_PWIDTH_32_BIT,
1147         DMA_PERIPH_INCR_1,
1148         DMA_PERIPH_INCR_OFF,
1149         IMG_TRUE,
1150         MMU_GROUP1,
1151         HOST_TO_MSVDX,
1152         DMA_BURST_1             /* Into MTX */
1153     },
1154     /*LLDMA_TYPE_RENDER_BUFF_VLD*/{
1155         (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET),
1156         DMA_PWIDTH_32_BIT,
1157         DMA_PERIPH_INCR_1,
1158         DMA_PERIPH_INCR_OFF,
1159         IMG_TRUE,
1160         MMU_GROUP0,
1161         HOST_TO_MSVDX,
1162         DMA_BURST_1             /* Into MTX */
1163     },
1164     /*LLDMA_TYPE_MPEG4_FESTATE_SAVE*/{
1165         (REG_MSVDX_VEC_RAM_OFFSET + 0xB90),
1166         DMA_PWIDTH_32_BIT,
1167         DMA_PERIPH_INCR_4,
1168         DMA_PERIPH_INCR_ON,
1169         IMG_TRUE,
1170         MMU_GROUP0,
1171         MSXDX_TO_HOST,
1172         DMA_BURST_2              /* From VLR */
1173     },
1174     /*LLDMA_TYPE_MPEG4_FESTATE_RESTORE*/{
1175         (REG_MSVDX_VEC_RAM_OFFSET + 0xB90),
1176         DMA_PWIDTH_32_BIT,
1177         DMA_PERIPH_INCR_4,
1178         DMA_PERIPH_INCR_ON,
1179         IMG_TRUE,
1180         MMU_GROUP0,
1181         HOST_TO_MSVDX,
1182         DMA_BURST_2             /* Into VLR */
1183     },
1184     /*LLDMA_TYPE_H264_PRELOAD_SAVE*/{
1185         (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET),
1186         DMA_PWIDTH_32_BIT,
1187         DMA_PERIPH_INCR_1,
1188         DMA_PERIPH_INCR_OFF,
1189         IMG_TRUE,       /* na */
1190         MMU_GROUP1,
1191         MSXDX_TO_HOST,
1192         DMA_BURST_1             /* From MTX */
1193     },
1194     /*LLDMA_TYPE_H264_PRELOAD_RESTORE*/{
1195         (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET),
1196         DMA_PWIDTH_32_BIT,
1197         DMA_PERIPH_INCR_1,
1198         DMA_PERIPH_INCR_OFF,
1199         IMG_TRUE,       /* na */
1200         MMU_GROUP1,
1201         HOST_TO_MSVDX,
1202         DMA_BURST_1             /* Into MTX */
1203     },
1204     /*LLDMA_TYPE_VC1_PRELOAD_SAVE*/{
1205         (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET),
1206         DMA_PWIDTH_32_BIT,
1207         DMA_PERIPH_INCR_1,
1208         DMA_PERIPH_INCR_OFF,
1209         IMG_TRUE,       /* na */
1210         MMU_GROUP0,
1211         MSXDX_TO_HOST,
1212         DMA_BURST_1             //2     /* From MTX */
1213     },
1214     /*LLDMA_TYPE_VC1_PRELOAD_RESTORE*/{
1215         (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET),
1216         DMA_PWIDTH_32_BIT,
1217         DMA_PERIPH_INCR_1,
1218         DMA_PERIPH_INCR_OFF,
1219         IMG_TRUE,       /* na */
1220         MMU_GROUP0,
1221         HOST_TO_MSVDX,
1222         DMA_BURST_1             /* Into MTX */
1223     },
1224     /*LLDMA_TYPE_MEM_SET */{
1225         (REG_MSVDX_VEC_RAM_OFFSET + 0xCC0),
1226         DMA_PWIDTH_32_BIT,
1227         DMA_PERIPH_INCR_4,
1228         DMA_PERIPH_INCR_OFF,
1229         IMG_TRUE,       /* na */
1230         MMU_GROUP0,
1231         MSXDX_TO_HOST,
1232         DMA_BURST_4                     /* From VLR */
1233     },
1234 
1235 };
1236 
1237 #define MAX_DMA_LEN     ( 0xffff )
1238 
psb_cmdbuf_alloc_space(psb_cmdbuf_p cmdbuf,uint32_t byte_size)1239 void *psb_cmdbuf_alloc_space(psb_cmdbuf_p cmdbuf, uint32_t byte_size)
1240 {
1241     void *pos = (void *)cmdbuf->cmd_idx;
1242     ASSERT(!(byte_size % 4));
1243 
1244     cmdbuf->cmd_idx += (byte_size / 4);
1245 
1246     return pos;
1247 }
1248 
psb_cmdbuf_dma_write_cmdbuf(psb_cmdbuf_p cmdbuf,psb_buffer_p bitstream_buf,uint32_t buffer_offset,uint32_t size,uint32_t dest_offset,DMA_TYPE type)1249 void psb_cmdbuf_dma_write_cmdbuf(psb_cmdbuf_p cmdbuf,
1250                                    psb_buffer_p bitstream_buf,
1251                                    uint32_t buffer_offset,
1252                                    uint32_t size,
1253                                    uint32_t dest_offset,
1254                                    DMA_TYPE type)
1255 {
1256     ASSERT(size < 0xFFFF);
1257     ASSERT(buffer_offset < 0xFFFF);
1258 
1259     DMA_CMD_WITH_OFFSET* dma_cmd;
1260 
1261     if(dest_offset==0)
1262     {
1263             dma_cmd = (DMA_CMD_WITH_OFFSET*)psb_cmdbuf_alloc_space(cmdbuf, sizeof(DMA_CMD));
1264             dma_cmd->ui32Cmd = 0;
1265     }
1266     else
1267     {
1268             dma_cmd = (DMA_CMD_WITH_OFFSET*)psb_cmdbuf_alloc_space(cmdbuf, sizeof(DMA_CMD_WITH_OFFSET));
1269             dma_cmd->ui32Cmd = CMD_DMA_OFFSET_FLAG; // Set flag indicating that offset is deffined
1270             dma_cmd->ui32ByteOffset = dest_offset;
1271     }
1272 
1273     dma_cmd->ui32Cmd |= CMD_DMA;
1274     dma_cmd->ui32Cmd |= (IMG_UINT32)type;
1275     dma_cmd->ui32Cmd |= size;
1276     /* dma_cmd->ui32DevVirtAdd  = ui32DevVirtAddress; */
1277     RELOC(dma_cmd->ui32DevVirtAdd, buffer_offset, bitstream_buf);
1278 }
1279 
1280 /*
1281  * Write a CMD_SR_SETUP referencing a bitstream buffer to the command buffer
1282  */
psb_cmdbuf_dma_write_bitstream(psb_cmdbuf_p cmdbuf,psb_buffer_p bitstream_buf,uint32_t buffer_offset,uint32_t size_in_bytes,uint32_t offset_in_bits,uint32_t flags)1283 void psb_cmdbuf_dma_write_bitstream(psb_cmdbuf_p cmdbuf,
1284                                       psb_buffer_p bitstream_buf,
1285                                       uint32_t buffer_offset,
1286                                       uint32_t size_in_bytes,
1287                                       uint32_t offset_in_bits,
1288                                       uint32_t flags)
1289 {
1290     /*
1291      * We use byte alignment instead of 32bit alignment.
1292      * The third frame of sa10164.vc1 results in the following bitstream
1293      * patttern:
1294      * [0000] 00 00 03 01 76 dc 04 8d
1295      * with offset_in_bits = 0x1e
1296      * This causes an ENTDEC failure because 00 00 03 is a start code
1297      * By byte aligning the datastream the start code will be eliminated.
1298      */
1299 //don't need to change the offset_in_bits, size_in_bytes and buffer_offset
1300 #if 0
1301 #define ALIGNMENT        sizeof(uint8_t)
1302     uint32_t bs_offset_in_dwords    = ((offset_in_bits / 8) / ALIGNMENT);
1303     size_in_bytes                   -= bs_offset_in_dwords * ALIGNMENT;
1304     offset_in_bits                  -= bs_offset_in_dwords * 8 * ALIGNMENT;
1305     buffer_offset                   += bs_offset_in_dwords * ALIGNMENT;
1306 #endif
1307 
1308     *cmdbuf->cmd_idx++ = CMD_SR_SETUP | flags;
1309     *cmdbuf->cmd_idx++ = offset_in_bits;
1310     cmdbuf->cmd_bitstream_size = cmdbuf->cmd_idx;
1311     *cmdbuf->cmd_idx++ = size_in_bytes;
1312     *cmdbuf->cmd_idx++ = (CMD_BITSTREAM_DMA | size_in_bytes);
1313     RELOC(*cmdbuf->cmd_idx++, buffer_offset, bitstream_buf);
1314 }
1315 
1316 #ifdef SLICE_HEADER_PARSING
1317 /*
1318  * Write a CMD_SR_SETUP referencing a bitstream buffer to the command buffer
1319  */
psb_cmdbuf_dma_write_key(psb_cmdbuf_p cmdbuf,uint32_t flags,uint32_t key)1320 void psb_cmdbuf_dma_write_key(psb_cmdbuf_p cmdbuf,
1321                                       uint32_t flags,
1322                                       uint32_t key)
1323 {
1324     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pass key, flags is 0x%x, key is 0x%x.\n", flags, key);
1325     *cmdbuf->cmd_idx++ = CMD_SR_SETUP | flags;
1326     *cmdbuf->cmd_idx++ = key;
1327 }
1328 #endif
1329 
1330 /*
1331  * Chain a LLDMA bitstream command to the previous one
1332  */
psb_cmdbuf_dma_write_bitstream_chained(psb_cmdbuf_p cmdbuf,psb_buffer_p bitstream_buf,uint32_t size_in_bytes)1333 void psb_cmdbuf_dma_write_bitstream_chained(psb_cmdbuf_p cmdbuf,
1334         psb_buffer_p bitstream_buf,
1335         uint32_t size_in_bytes)
1336 {
1337     *cmdbuf->cmd_idx++ = (CMD_BITSTREAM_DMA | size_in_bytes);
1338     RELOC(*cmdbuf->cmd_idx++, bitstream_buf->buffer_ofs, bitstream_buf);
1339 
1340     *(cmdbuf->cmd_bitstream_size) += size_in_bytes;
1341 }
1342 
psb_cmdbuf_reg_start_block(psb_cmdbuf_p cmdbuf,uint32_t flags)1343 void psb_cmdbuf_reg_start_block(psb_cmdbuf_p cmdbuf, uint32_t flags)
1344 {
1345     ASSERT(NULL == cmdbuf->reg_start); /* Can't have both */
1346 
1347     cmdbuf->reg_wt_p = cmdbuf->cmd_idx;
1348     cmdbuf->reg_next = 0;
1349     cmdbuf->reg_flags = (flags << 4); /* flags are diff between DE2 & DE3 */
1350     cmdbuf->reg_start = NULL;
1351 }
1352 
psb_cmdbuf_reg_set(psb_cmdbuf_p cmdbuf,uint32_t reg,uint32_t val)1353 void psb_cmdbuf_reg_set(psb_cmdbuf_p cmdbuf, uint32_t reg, uint32_t val)
1354 {
1355     if(cmdbuf->reg_start && (reg == cmdbuf->reg_next))
1356     {
1357         /* Incrament header size */
1358         *cmdbuf->reg_start += (0x1 << 16);
1359     }
1360     else
1361     {
1362         cmdbuf->reg_start = cmdbuf->reg_wt_p++;
1363         *cmdbuf->reg_start = CMD_REGVALPAIR_WRITE | cmdbuf->reg_flags | 0x10000 | (reg & 0xfffff); /* We want host reg addr */
1364     }
1365     *cmdbuf->reg_wt_p++ = val;
1366     cmdbuf->reg_next = reg + 4;
1367 }
1368 
psb_cmdbuf_reg_set_address(psb_cmdbuf_p cmdbuf,uint32_t reg,psb_buffer_p buffer,uint32_t buffer_offset)1369 void psb_cmdbuf_reg_set_address(psb_cmdbuf_p cmdbuf,
1370                                          uint32_t reg,
1371                                          psb_buffer_p buffer,
1372                                          uint32_t buffer_offset)
1373 {
1374     if(cmdbuf->reg_start && (reg == cmdbuf->reg_next))
1375     {
1376         /* Incrament header size */
1377         *cmdbuf->reg_start += (0x1 << 16);
1378     }
1379     else
1380     {
1381         cmdbuf->reg_start = cmdbuf->reg_wt_p++;
1382         *cmdbuf->reg_start = CMD_REGVALPAIR_WRITE | cmdbuf->reg_flags | 0x10000 | (reg & 0xfffff); /* We want host reg addr */
1383     }
1384 
1385     RELOC(*cmdbuf->reg_wt_p++, buffer_offset, buffer);
1386     cmdbuf->reg_next = reg + 4;
1387 }
1388 
psb_cmdbuf_reg_end_block(psb_cmdbuf_p cmdbuf)1389 void psb_cmdbuf_reg_end_block(psb_cmdbuf_p cmdbuf)
1390 {
1391     cmdbuf->cmd_idx = cmdbuf->reg_wt_p;
1392     cmdbuf->reg_start = NULL;
1393 }
1394 
1395 typedef enum {
1396     MTX_CTRL_HEADER = 0,
1397     RENDEC_SL_HDR,
1398     RENDEC_SL_NULL,
1399     RENDEC_CK_HDR,
1400 } RENDEC_CHUNK_OFFSETS;
1401 
1402 /*
1403  * Start a new rendec block of another format
1404  */
psb_cmdbuf_rendec_start(psb_cmdbuf_p cmdbuf,uint32_t dest_address)1405 void psb_cmdbuf_rendec_start(psb_cmdbuf_p cmdbuf, uint32_t dest_address)
1406 {
1407     ASSERT(((dest_address >> 2)& ~0xfff) == 0);
1408     cmdbuf->rendec_chunk_start = cmdbuf->cmd_idx++;
1409     *cmdbuf->rendec_chunk_start = CMD_RENDEC_BLOCK | dest_address;
1410 }
1411 
psb_cmdbuf_rendec_write_block(psb_cmdbuf_p cmdbuf,unsigned char * block,uint32_t size)1412 void psb_cmdbuf_rendec_write_block(psb_cmdbuf_p cmdbuf,
1413                                    unsigned char *block,
1414                                    uint32_t size)
1415 {
1416     ASSERT((size & 0x3) == 0);
1417     unsigned int i;
1418     for (i = 0; i < size; i += 4) {
1419         uint32_t val = block[i] | (block[i+1] << 8) | (block[i+2] << 16) | (block[i+3] << 24);
1420         psb_cmdbuf_rendec_write(cmdbuf, val);
1421     }
1422 }
1423 
psb_cmdbuf_rendec_write_address(psb_cmdbuf_p cmdbuf,psb_buffer_p buffer,uint32_t buffer_offset)1424 void psb_cmdbuf_rendec_write_address(psb_cmdbuf_p cmdbuf,
1425                                      psb_buffer_p buffer,
1426                                      uint32_t buffer_offset)
1427 {
1428     RELOC(*cmdbuf->cmd_idx++, buffer_offset, buffer);
1429 }
1430 
1431 /*
1432  * Finish a RENDEC block
1433  */
psb_cmdbuf_rendec_end(psb_cmdbuf_p cmdbuf)1434 void psb_cmdbuf_rendec_end(psb_cmdbuf_p cmdbuf)
1435 {
1436     ASSERT(NULL != cmdbuf->rendec_chunk_start); /* Must have an open RENDEC chunk */
1437     uint32_t dword_count = cmdbuf->cmd_idx - cmdbuf->rendec_chunk_start;
1438 
1439     ASSERT((dword_count - 1) <= 0xff);
1440 
1441     *cmdbuf->rendec_chunk_start += ((dword_count - 1) << 16);
1442     cmdbuf->rendec_chunk_start = NULL;
1443 }
1444 
1445 /*
1446  * Create a conditional SKIP block
1447  */
psb_cmdbuf_skip_start_block(psb_cmdbuf_p cmdbuf,uint32_t skip_condition)1448 void psb_cmdbuf_skip_start_block(psb_cmdbuf_p cmdbuf, uint32_t skip_condition)
1449 {
1450     ASSERT(NULL == cmdbuf->rendec_block_start); /* Can't be inside a rendec block */
1451     ASSERT(NULL == cmdbuf->reg_start); /* Can't be inside a reg block */
1452     ASSERT(NULL == cmdbuf->skip_block_start); /* Can't be inside another skip block (limitation of current sw design)*/
1453 
1454     cmdbuf->skip_condition = skip_condition;
1455     cmdbuf->skip_block_start = cmdbuf->cmd_idx++;
1456 }
1457 
1458 /*
1459  * Terminate a conditional SKIP block
1460  */
psb_cmdbuf_skip_end_block(psb_cmdbuf_p cmdbuf)1461 void psb_cmdbuf_skip_end_block(psb_cmdbuf_p cmdbuf)
1462 {
1463     ASSERT(NULL == cmdbuf->rendec_block_start); /* Rendec block must be closed */
1464     ASSERT(NULL == cmdbuf->reg_start); /* Reg block must be closed */
1465     ASSERT(NULL != cmdbuf->skip_block_start); /* Skip block must still be open */
1466 
1467     uint32_t block_size = cmdbuf->cmd_idx - (cmdbuf->skip_block_start + 1);
1468 
1469     *cmdbuf->skip_block_start = CMD_CONDITIONAL_SKIP | (cmdbuf->skip_condition << 20) | block_size;
1470     cmdbuf->skip_block_start = NULL;
1471 }
1472