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