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  *    Zeng Li <zeng.li@intel.com>
27  *    Shengquan Yuan  <shengquan.yuan@intel.com>
28  *    Binglin Chen <binglin.chen@intel.com>
29  *
30  */
31 
32 #include "lnc_cmdbuf.h"
33 
34 #include <unistd.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <wsbm/wsbm_manager.h>
40 
41 #include "psb_def.h"
42 #include "psb_drv_debug.h"
43 #include "lnc_hostcode.h"
44 #include "psb_ws_driver.h"
45 
46 /*
47  * Buffer layout:
48  *         cmd_base <= cmd_idx < CMD_END() == reloc_base
49  *         reloc_base <= reloc_idx < RELOC_END() == (reloc_size)
50  */
51 
52 #define RELOC_END(cmdbuf)     (cmdbuf->cmd_base + cmdbuf->size)
53 
54 #define CMD_END(cmdbuf)       (cmdbuf->reloc_base)
55 
56 #define RELOC_SIZE            (0x3000)
57 
58 #define CMD_SIZE              (0x3000)
59 
60 #define RELOC_MARGIN          (0x0800)
61 
62 #define CMD_MARGIN            (0x0400)
63 
64 
65 #define MAX_CMD_COUNT         12
66 
67 #define MTX_SEG_SIZE          (0x0800)
68 
69 /*
70  * Create command buffer
71  */
lnc_cmdbuf_create(object_context_p obj_context,psb_driver_data_p driver_data,lnc_cmdbuf_p cmdbuf)72 VAStatus lnc_cmdbuf_create(
73     object_context_p obj_context,
74     psb_driver_data_p driver_data,
75     lnc_cmdbuf_p cmdbuf)
76 {
77     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
78     VAStatus vaStatus = VA_STATUS_SUCCESS;
79     unsigned int size = CMD_SIZE + RELOC_SIZE;
80 
81     cmdbuf->size = 0;
82     cmdbuf->cmd_base = NULL;
83     cmdbuf->cmd_idx = NULL;
84     cmdbuf->reloc_base = NULL;
85     cmdbuf->reloc_idx = NULL;
86     cmdbuf->buffer_refs_count = 0;
87     cmdbuf->buffer_refs_allocated = 10;
88     cmdbuf->buffer_refs = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
89     if (NULL == cmdbuf->buffer_refs) {
90         cmdbuf->buffer_refs_allocated = 0;
91         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
92     }
93     if (VA_STATUS_SUCCESS == vaStatus) {
94         vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_only, &cmdbuf->buf);
95         cmdbuf->size = size;
96     }
97 
98     if (VA_STATUS_SUCCESS != vaStatus) {
99         free(cmdbuf->buffer_refs);
100         cmdbuf->buffer_refs = NULL;
101         cmdbuf->buffer_refs_allocated = 0;
102         return vaStatus;
103     }
104 
105     /* create topaz parameter buffer */
106     vaStatus = psb_buffer_create(driver_data, ctx->pic_params_size, psb_bt_cpu_vpu, &cmdbuf->pic_params);
107     if (VA_STATUS_SUCCESS != vaStatus)
108         goto error_out3;
109 
110     /* create header buffer */
111     vaStatus = psb_buffer_create(driver_data, ctx->header_buffer_size, psb_bt_cpu_vpu, &cmdbuf->header_mem);
112     if (VA_STATUS_SUCCESS != vaStatus)
113         goto error_out2;
114 
115     /* create slice parameter buffer */
116     vaStatus = psb_buffer_create(driver_data, ctx->sliceparam_buffer_size, psb_bt_cpu_vpu, &cmdbuf->slice_params);
117     if (VA_STATUS_SUCCESS != vaStatus)
118         goto error_out1;
119 
120     /* all cmdbuf share one MTX_CURRENT_IN_PARAMS since every MB has a MTX_CURRENT_IN_PARAMS structure
121      * and filling this structure for all MB is very time-consuming
122      */
123     cmdbuf->topaz_in_params_I = &ctx->topaz_in_params_I;
124     cmdbuf->topaz_in_params_P = &ctx->topaz_in_params_P;
125     cmdbuf->topaz_above_bellow_params = &ctx->topaz_above_bellow_params;
126 
127     return vaStatus;
128 
129 error_out1:
130     psb_buffer_destroy(&cmdbuf->header_mem);
131 error_out2:
132     psb_buffer_destroy(&cmdbuf->pic_params);
133 error_out3:
134     lnc_cmdbuf_destroy(cmdbuf);
135 
136     return vaStatus;
137 }
138 
139 /*
140  * Destroy buffer
141  */
lnc_cmdbuf_destroy(lnc_cmdbuf_p cmdbuf)142 void lnc_cmdbuf_destroy(lnc_cmdbuf_p cmdbuf)
143 {
144     if (cmdbuf->size) {
145         psb_buffer_destroy(&cmdbuf->buf);
146         cmdbuf->size = 0;
147     }
148     if (cmdbuf->buffer_refs_allocated) {
149         free(cmdbuf->buffer_refs);
150         cmdbuf->buffer_refs = NULL;
151         cmdbuf->buffer_refs_allocated = 0;
152     }
153 
154     psb_buffer_destroy(&cmdbuf->pic_params);
155     psb_buffer_destroy(&cmdbuf->header_mem);
156     psb_buffer_destroy(&cmdbuf->slice_params);
157 
158 }
159 
160 /*
161  * Reset buffer & map
162  *
163  * Returns 0 on success
164  */
lnc_cmdbuf_reset(lnc_cmdbuf_p cmdbuf)165 int lnc_cmdbuf_reset(lnc_cmdbuf_p cmdbuf)
166 {
167     int ret;
168 
169     cmdbuf->cmd_base = NULL;
170     cmdbuf->cmd_idx = NULL;
171     cmdbuf->reloc_base = NULL;
172     cmdbuf->reloc_idx = NULL;
173 
174     cmdbuf->buffer_refs_count = 0;
175     cmdbuf->cmd_count = 0;
176 
177     ret = psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base);
178     if (ret) {
179         return ret;
180     }
181 
182     cmdbuf->cmd_start = cmdbuf->cmd_base;
183     cmdbuf->cmd_idx = (uint32_t *) cmdbuf->cmd_base;
184 
185     cmdbuf->reloc_base = cmdbuf->cmd_base + CMD_SIZE;
186     cmdbuf->reloc_idx = (struct drm_psb_reloc *) cmdbuf->reloc_base;
187 
188     /* Add ourselves to the buffer list */
189     lnc_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->buf); /* cmd buf == 0 */
190     return ret;
191 }
192 
193 /*
194  * Unmap buffer
195  *
196  * Returns 0 on success
197  */
lnc_cmdbuf_unmap(lnc_cmdbuf_p cmdbuf)198 int lnc_cmdbuf_unmap(lnc_cmdbuf_p cmdbuf)
199 {
200     cmdbuf->cmd_base = NULL;
201     cmdbuf->cmd_start = NULL;
202     cmdbuf->cmd_idx = NULL;
203     cmdbuf->reloc_base = NULL;
204     cmdbuf->reloc_idx = NULL;
205     cmdbuf->cmd_count = 0;
206     psb_buffer_unmap(&cmdbuf->buf);
207     return 0;
208 }
209 
210 
211 /*
212  * Reference an addtional buffer "buf" in the command stream
213  * Returns a reference index that can be used to refer to "buf" in
214  * relocation records, -1 on error
215  */
lnc_cmdbuf_buffer_ref(lnc_cmdbuf_p cmdbuf,psb_buffer_p buf)216 int lnc_cmdbuf_buffer_ref(lnc_cmdbuf_p cmdbuf, psb_buffer_p buf)
217 {
218     int item_loc = 0;
219 
220     while ((item_loc < cmdbuf->buffer_refs_count) && (cmdbuf->buffer_refs[item_loc] != buf)) {
221         item_loc++;
222     }
223     if (item_loc == cmdbuf->buffer_refs_count) {
224         /* Add new entry */
225         if (item_loc >= cmdbuf->buffer_refs_allocated) {
226             /* Allocate more entries */
227             int new_size = cmdbuf->buffer_refs_allocated + 10;
228             psb_buffer_p *new_array;
229             new_array = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * new_size);
230             if (NULL == new_array) {
231                 return -1; /* Allocation failure */
232             }
233             memcpy(new_array, cmdbuf->buffer_refs, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
234             free(cmdbuf->buffer_refs);
235             cmdbuf->buffer_refs_allocated = new_size;
236             cmdbuf->buffer_refs = new_array;
237         }
238         cmdbuf->buffer_refs[item_loc] = buf;
239         cmdbuf->buffer_refs_count++;
240         buf->status = psb_bs_queued;
241     }
242     return item_loc;
243 }
244 
245 /* Creates a relocation record for a DWORD in the mapped "cmdbuf" at address
246  * "addr_in_cmdbuf"
247  * The relocation is based on the device virtual address of "ref_buffer"
248  * "buf_offset" is be added to the device virtual address, and the sum is then
249  * right shifted with "align_shift".
250  * "mask" determines which bits of the target DWORD will be updated with the so
251  * constructed address. The remaining bits will be filled with bits from "background".
252  */
lnc_cmdbuf_add_relocation(lnc_cmdbuf_p cmdbuf,uint32_t * addr_in_dst_buffer,psb_buffer_p ref_buffer,uint32_t buf_offset,uint32_t mask,uint32_t background,uint32_t align_shift,uint32_t dst_buffer,uint32_t * start_of_dst_buffer)253 void lnc_cmdbuf_add_relocation(lnc_cmdbuf_p cmdbuf,
254                                uint32_t *addr_in_dst_buffer,/*addr of dst_buffer for the DWORD*/
255                                psb_buffer_p ref_buffer,
256                                uint32_t buf_offset,
257                                uint32_t mask,
258                                uint32_t background,
259                                uint32_t align_shift,
260                                uint32_t dst_buffer,
261                                uint32_t *start_of_dst_buffer) /*Index of the list refered by cmdbuf->buffer_refs */
262 {
263     struct drm_psb_reloc *reloc = cmdbuf->reloc_idx;
264     uint64_t presumed_offset = wsbmBOOffsetHint(ref_buffer->drm_buf);
265 
266     reloc->where = addr_in_dst_buffer - start_of_dst_buffer; /* Offset in DWORDs */
267 
268     reloc->buffer = lnc_cmdbuf_buffer_ref(cmdbuf, ref_buffer);
269     ASSERT(reloc->buffer != -1);
270 
271     reloc->reloc_op = PSB_RELOC_OP_OFFSET;
272 #ifndef VA_EMULATOR
273     if (presumed_offset) {
274         uint32_t new_val =  presumed_offset + buf_offset;
275 
276         new_val = ((new_val >> align_shift) << (align_shift << PSB_RELOC_ALSHIFT_SHIFT));
277         new_val = (background & ~mask) | (new_val & mask);
278         *addr_in_dst_buffer = new_val;
279     } else {
280         *addr_in_dst_buffer = PSB_RELOC_MAGIC;
281     }
282 #else
283     /* indicate subscript of relocation buffer */
284     *addr_in_dst_buffer = reloc - (struct drm_psb_reloc *)cmdbuf->reloc_base;
285 #endif
286     reloc->mask = mask;
287     reloc->shift = align_shift << PSB_RELOC_ALSHIFT_SHIFT;
288     reloc->pre_add = buf_offset;
289     reloc->background = background;
290     reloc->dst_buffer = dst_buffer;
291     cmdbuf->reloc_idx++;
292 
293     ASSERT(((unsigned char *)(cmdbuf->reloc_idx)) < RELOC_END(cmdbuf));
294 }
295 
296 /*
297  * Advances "obj_context" to the next cmdbuf
298  *
299  * Returns 0 on success
300  */
lnc_context_get_next_cmdbuf(object_context_p obj_context)301 int lnc_context_get_next_cmdbuf(object_context_p obj_context)
302 {
303     lnc_cmdbuf_p cmdbuf;
304     int ret;
305 
306     if (obj_context->lnc_cmdbuf) {
307         return 0;
308     }
309 
310     obj_context->cmdbuf_current++;
311     if (obj_context->cmdbuf_current >= LNC_MAX_CMDBUFS_ENCODE) {
312         obj_context->cmdbuf_current = 0;
313     }
314 
315     cmdbuf = obj_context->lnc_cmdbuf_list[obj_context->cmdbuf_current];
316     ret = lnc_cmdbuf_reset(cmdbuf);
317     if (!ret) {
318         /* Success */
319         obj_context->lnc_cmdbuf = cmdbuf;
320     }
321 
322     /* added pic_params/slice_params into ref, so the index is 1/2 */
323     lnc_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->pic_params);
324     lnc_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->slice_params);
325 
326     return ret;
327 }
328 
329 /*
330  * This is the user-space do-it-all interface to the drm cmdbuf ioctl.
331  * It allows different buffers as command- and reloc buffer. A list of
332  * cliprects to apply and whether to copy the clipRect content to all
333  * scanout buffers (damage = 1).
334  */
335 /*
336  * Don't add debug statements in this function, it gets called with the
337  * DRM lock held and output to an X terminal can cause X to deadlock
338  */
339 static int
lncDRMCmdBuf(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 damage,unsigned engine,unsigned fence_flags,struct psb_ttm_fence_rep * fence_rep)340 lncDRMCmdBuf(int fd, int ioctl_offset, psb_buffer_p *buffer_list, int buffer_count, unsigned cmdBufHandle,
341              unsigned cmdBufOffset, unsigned cmdBufSize,
342              unsigned relocBufHandle, unsigned relocBufOffset,
343              unsigned numRelocs, int damage,
344              unsigned engine, unsigned fence_flags, struct psb_ttm_fence_rep *fence_rep)
345 {
346     drm_psb_cmdbuf_arg_t ca;
347     struct psb_validate_arg *arg_list;
348     int i;
349     int ret;
350     uint64_t mask = PSB_GPU_ACCESS_MASK;
351 
352     arg_list = (struct psb_validate_arg *) calloc(1, sizeof(struct psb_validate_arg) * buffer_count);
353     if (arg_list == NULL) {
354         drv_debug_msg(VIDEO_DEBUG_ERROR, "Allocate memory failed\n");
355         return -ENOMEM;
356     }
357 
358     for (i = 0; i < buffer_count; i++) {
359         struct psb_validate_arg *arg = &(arg_list[i]);
360         struct psb_validate_req *req = &arg->d.req;
361 
362         req->next = (unsigned long) & (arg_list[i+1]);
363 
364         req->buffer_handle = wsbmKBufHandle(wsbmKBuf(buffer_list[i]->drm_buf));
365         req->group = 0;
366         req->set_flags = (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) & mask;
367         req->clear_flags = (~(PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)) & mask;
368 #if 1
369         req->presumed_gpu_offset = (uint64_t)wsbmBOOffsetHint(buffer_list[i]->drm_buf);
370         req->presumed_flags = PSB_USE_PRESUMED;
371         if ((req->presumed_gpu_offset >> 28) & 0x1) {
372             drv_debug_msg(VIDEO_DEBUG_ERROR, "buffer is at the address topaz can not access\n");
373             ret = -1;
374             goto out;
375         }
376 #else
377         req->presumed_flags = 0;
378 #endif
379         req->pad64 = (uint32_t)buffer_list[i]->pl_flags;
380     }
381     arg_list[buffer_count-1].d.req.next = 0;
382 
383     ca.buffer_list = (uint64_t)((unsigned long)arg_list);
384     ca.cmdbuf_handle = cmdBufHandle;
385     ca.cmdbuf_offset = cmdBufOffset;
386     ca.cmdbuf_size = cmdBufSize;
387     ca.reloc_handle = relocBufHandle;
388     ca.reloc_offset = relocBufOffset;
389     ca.num_relocs = numRelocs;
390     ca.engine = engine;
391     ca.fence_flags = fence_flags;
392     ca.fence_arg = (uint64_t)((unsigned long)fence_rep);
393 
394     do {
395         ret = drmCommandWrite(fd, ioctl_offset, &ca, sizeof(ca));
396     } while (ret == EAGAIN);
397 
398     if (ret)
399         goto out;
400 
401     for (i = 0; i < buffer_count; i++) {
402         struct psb_validate_arg *arg = &(arg_list[i]);
403         struct psb_validate_rep *rep = &arg->d.rep;
404 
405         if (!arg->handled) {
406             ret = -EFAULT;
407             goto out;
408         }
409         if (arg->ret != 0) {
410             ret = arg->ret;
411             goto out;
412         }
413         wsbmUpdateKBuf(wsbmKBuf(buffer_list[i]->drm_buf),
414                        rep->gpu_offset, rep->placement, rep->fence_type_mask);
415     }
416 out:
417     free(arg_list);
418     for (i = 0; i < buffer_count; i++) {
419         /*
420          * Buffer no longer queued in userspace
421          */
422         switch (buffer_list[i]->status) {
423         case psb_bs_queued:
424             buffer_list[i]->status = psb_bs_ready;
425             break;
426 
427         case psb_bs_abandoned:
428             psb_buffer_destroy(buffer_list[i]);
429             free(buffer_list[i]);
430             break;
431 
432         default:
433             /* Not supposed to happen */
434             ASSERT(0);
435         }
436     }
437 
438     return ret;
439 }
440 
441 #if 0
442 static struct _WsbmFenceObject *
443 lnc_fence_wait(psb_driver_data_p driver_data,
444                struct psb_ttm_fence_rep *fence_rep, int *status)
445 
446 {
447     struct _WsbmFenceObject *fence = NULL;
448     int ret = -1;
449 
450     /* copy fence information */
451     if (fence_rep->error != 0) {
452         drv_debug_msg(VIDEO_DEBUG_ERROR, "drm failed to create a fence"
453                            " and has idled the HW\n");
454         DEBUG_FAILURE_RET;
455         return NULL;
456     }
457 
458     fence = wsbmFenceCreate(driver_data->fence_mgr, fence_rep->fence_class,
459                             fence_rep->fence_type,
460                             (unsigned char *)fence_rep->handle,
461                             0);
462     if (fence)
463         *status = wsbmFenceFinish(fence, fence_rep->fence_type, 0);
464 
465     return fence;
466 }
467 #endif
468 
469 /*
470  * Submits the current cmdbuf
471  *
472  * Returns 0 on success
473  */
lnc_context_submit_cmdbuf(object_context_p obj_context)474 int lnc_context_submit_cmdbuf(object_context_p obj_context)
475 {
476 
477     return 0;
478 }
479 
480 /*
481  * FrameSkip is only meaningful for RC enabled mode
482  * Topaz raises this flag after surface N encoding is finished (vaSyncSurface gets back)
483  * then for the next encode surface N+1 (ctx->src_surface) frameskip flag is cleared in vaBeginPicuture
484  * and is always set in vaEndPicture:lnc_PatchRCMode
485  * vaQuerySurfaceStatus is supposed only to be called after vaEndPicture/vaSyncSurface,
486  * The caller should ensure the surface pertains to an encode context
487  */
lnc_surface_get_frameskip(psb_driver_data_p driver_data,psb_surface_p surface,int * frame_skip)488 int lnc_surface_get_frameskip(psb_driver_data_p driver_data, psb_surface_p surface, int *frame_skip)
489 {
490     struct drm_lnc_video_getparam_arg arg;
491     unsigned long temp;
492     int ret = 0;
493 
494     /* bit31 indicate if frameskip is already settled, it is used to record the frame skip flag for old surfaces
495      * because current FRAMESKIP in hardware can't be applied to the old surfaces
496      * bit31 is cleared when the surface is used as encode render target or reference/reconstrucure target
497      */
498     if (GET_SURFACE_INFO_skipped_flag(surface) & SURFACE_INFO_SKIP_FLAG_SETTLED) {
499         *frame_skip = GET_SURFACE_INFO_skipped_flag(surface) & 1;
500         return 0;
501     }
502 
503     /* not settled, we get it from current HW FRAMESKIP flag */
504     arg.key = LNC_VIDEO_FRAME_SKIP;
505     arg.value = (uint64_t)((unsigned long) & temp);
506     ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
507                               &arg, sizeof(arg));
508     if (ret == 0) {
509         SET_SURFACE_INFO_skipped_flag(surface, temp);
510         *frame_skip = temp;
511         if (temp == 1)
512             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected a skipped frame for encode\n");
513     }
514 
515     return ret;
516 }
517 
518 
519 /*
520  * Flushes all cmdbufs
521  */
lnc_context_flush_cmdbuf(object_context_p obj_context)522 int lnc_context_flush_cmdbuf(object_context_p obj_context)
523 {
524     lnc_cmdbuf_p cmdbuf = obj_context->lnc_cmdbuf;
525     psb_driver_data_p driver_data = obj_context->driver_data;
526     unsigned int fence_flags;
527     struct psb_ttm_fence_rep fence_rep;
528     unsigned int reloc_offset;
529     unsigned int num_relocs;
530     int ret;
531     unsigned int cmdbuffer_size = (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start; /* In bytes */
532 
533     ASSERT(cmdbuffer_size < CMD_SIZE);
534     ASSERT((unsigned char *) cmdbuf->cmd_idx < CMD_END(cmdbuf));
535     /* LOCK */
536     ret = LOCK_HARDWARE(driver_data);
537     if (ret) {
538         UNLOCK_HARDWARE(driver_data);
539         DEBUG_FAILURE_RET;
540         return ret;
541     }
542 
543     /* Now calculate the total number of relocations */
544     reloc_offset = cmdbuf->reloc_base - cmdbuf->cmd_base;
545     num_relocs = (((unsigned char *) cmdbuf->reloc_idx) - cmdbuf->reloc_base) / sizeof(struct drm_psb_reloc);
546 
547     lnc_cmdbuf_unmap(cmdbuf);
548 
549     ASSERT(NULL == cmdbuf->reloc_base);
550 
551     if (psb_video_trace_fp)
552         fence_flags = 0;
553     else
554         fence_flags = DRM_PSB_FENCE_NO_USER;
555 
556 #ifndef LNC_ENGINE_ENCODE
557 #define LNC_ENGINE_ENCODE  5
558 #endif
559 
560     wsbmWriteLockKernelBO();
561     ret = lncDRMCmdBuf(driver_data->drm_fd, driver_data->execIoctlOffset,
562                        cmdbuf->buffer_refs, cmdbuf->buffer_refs_count, wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)),
563                        0, cmdbuffer_size,/*unsigned cmdBufSize*/
564                        wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)), reloc_offset, num_relocs,
565                        0, LNC_ENGINE_ENCODE, fence_flags, &fence_rep);
566     wsbmWriteUnlockKernelBO();
567     UNLOCK_HARDWARE(driver_data);
568 
569     if (ret) {
570         obj_context->lnc_cmdbuf = NULL;
571 
572         DEBUG_FAILURE_RET;
573         return ret;
574     }
575 
576 #if 0
577     int status = -1;
578     struct _WsbmFenceObject *fence = NULL;
579 
580     fence = lnc_fence_wait(driver_data, &fence_rep, &status);
581     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_fence_wait returns: %d (fence=0x%08x)\n", status, fence);
582 
583     if (fence)
584         wsbmFenceUnreference(fence);
585 #endif
586 
587     obj_context->lnc_cmdbuf = NULL;
588 
589     return 0;
590 }
591 
592