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