]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ivimm/ipumm.git/blob - src/ti/framework/dce/dce.c
62bea8cf70b08fc7fff52a1e3cc11bcc3ff63d44
[ivimm/ipumm.git] / src / ti / framework / dce / dce.c
1 /*
2  * Copyright (c) 2011, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <ti/grcm/RcmServer.h>
38 #include <ti/grcm/RcmTypes.h>
39 #include <ti/ipc/mm/MmServiceMgr.h>
40 #include <ti/ipc/mm/MmRpc.h>
41 #include <ti/ipc/MultiProc.h>
42 #include <ti/ipc/rpmsg/RPMessage.h>
43 #include <ti/ipc/rpmsg/NameMap.h>
44 #include <ti/pm/IpcPower.h>
45 #include <ti/sdo/ce/global/CESettings.h>
46 #include <ti/sdo/ce/Engine.h>
47 #include <ti/sdo/fc/global/FCSettings.h>
48 #include <ti/sdo/fc/utils/fcutils.h>
49 #include <ti/sysbios/BIOS.h>
50 #include <ti/sysbios/hal/Cache.h>
51 #include <ti/sysbios/knl/Task.h>
52 #include <ti/sysbios/knl/Semaphore.h>
53 #include <ti/sysbios/posix/pthread.h>
54 #include <xdc/cfg/global.h>
55 #include <xdc/runtime/System.h>
56 #include <xdc/runtime/Diags.h>
57 #include <xdc/runtime/Memory.h>
58 #include <xdc/runtime/IHeap.h>
59 #include <xdc/runtime/knl/Thread.h>
60 #include <xdc/std.h>
61 #include <ti/sysbios/utils/Load.h>
63 #include "dce_priv.h"
64 #include "dce_rpc.h"
65 #include "ti/utils/profile.h"
67 static uint32_t    suspend_initialised = 0;
68 uint32_t           dce_debug = DCE_DEBUG_LEVEL;
70 #define SERVER_NAME "rpmsg-dce"
71 #define CALLBACK_SERVER_NAME "dce-callback"
73 #define MEMORYSTATS_DEBUG
74 /* Each client is based on a unique id from MmServiceMgr which is the connect identity */
75 /*   created by IPC per MmRpc_create instances                                         */
76 #define NUM_CLIENTS 10
77 /* Each client can have NUM_INSTANCE of ENGINE, DECODE_CODEC, and ENCODE_CODEC handle */
78 /* Commonly one ENGINE is associated with one DECODE_CODEC or one ENCODE_CODEC handle */
79 #define NUM_INSTANCE 5
81 #define MmRpc_NUM_PARAMETERS(size) \
82     (size / sizeof(MmType_Param))
84 /* dce_inv, dce_clean needs to be modified to expect buffers */
85 /* without headers (relevant for GLP)                        */
86 static void dce_inv(void *ptr)
87 {
88     if( ptr ) {
89         Cache_inv(ptr, P2H(ptr)->size, Cache_Type_ALL, TRUE);
90     }
91 }
93 static void dce_clean(void *ptr)
94 {
95     if( ptr ) {
96         Cache_wbInv(ptr, P2H(ptr)->size, Cache_Type_ALL, TRUE);
97     }
98 }
100 typedef void * (*CreateFxn)(Engine_Handle, String, void *);
101 typedef Int32 (*ControlFxn)(void *, int, void *, void *);
102 typedef Int32 (*ProcessFxn)(void *, void *, void *, void *, void *);
103 typedef Int32 (*RelocFxn)(void *, uint8_t *ptr, uint32_t len);
104 typedef void (*DeleteFxn)(void *);
106 /* DCE Server static function declarations */
107 static Int32 engine_open(UInt32 size, UInt32 *data);
108 static Int32 engine_close(UInt32 size, UInt32 *data);
110 /* Encoder Server static function declarations */
111 static VIDENC2_Handle videnc2_create(Engine_Handle engine, String name, VIDENC2_Params *params);
112 static XDAS_Int32 videnc2_control(VIDENC2_Handle codec, VIDENC2_Cmd id, VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status);
113 static int videnc2_reloc(VIDDEC3_Handle handle, uint8_t *ptr, uint32_t len);
115 /* Decoder Server static function declarations */
116 static VIDDEC3_Handle viddec3_create(Engine_Handle engine, String name, VIDDEC3_Params *params);
117 static XDAS_Int32 viddec3_control(VIDDEC3_Handle codec,VIDDEC3_Cmd id,VIDDEC3_DynamicParams * dynParams,VIDDEC3_Status * status);
118 static XDAS_Int32 viddec3_process(VIDDEC3_Handle codec, XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs);
120 static Int32 get_rproc_info(UInt32 size, UInt32 *data);
122 static int viddec3_reloc(VIDDEC3_Handle handle, uint8_t *ptr, uint32_t len);
124 static Semaphore_Handle sync_process_sem;
126 typedef struct {
127     XDM_DataSyncHandle dataSyncHandle;
128     XDM_DataSyncDesc *dataSyncDesc;
129     pthread_mutex_t callback_mutex;
130     pthread_cond_t synch_callback;
131     Uint32 row_mode;
132     Uint32 getdata_ready;
133     Uint32 codec_request;
134     Uint32 putdata_ready;
135     Uint32 mpu_crash_indication;
136     Uint32 putdata_toclient;
137     Uint32 putData_endprocess;
138 } Callback_data;
140 typedef struct {
141     Uint32 mm_serv_id;  /* value of zero means unused */
142     Int refs;           /* reference count on number of engine */
143     Engine_Handle engines[NUM_INSTANCE];
144     VIDDEC3_Handle decode_codec[NUM_INSTANCE];
145     VIDENC2_Handle encode_codec[NUM_INSTANCE];
146     Uint32 codec_id;
147     Callback_data decode_callback[NUM_INSTANCE];
148     Callback_data encode_callback[NUM_INSTANCE];
149 } Client;
150 static Client clients[NUM_CLIENTS] = {0};
152 static inline Client * get_client(Uint32 mm_serv_id)
154     int i;
155     for (i = 0; i < DIM(clients); i++) {
156         if (clients[i].mm_serv_id == mm_serv_id) {
157             return &clients[i];
158         }
159     }
160     return NULL;
163 static inline Client * get_client_instance(Uint32 codec)
165     int i, j;
167     for (i = 0; i < DIM(clients); i++) {
168         for (j = 0; j < DIM(clients[i].decode_codec); j++) {
169             if (clients[i].decode_codec[j] == (VIDDEC3_Handle) codec) {
170                 DEBUG("Found VIDDEC3 clients[%d] = 0x%x, &clients[%d] = 0x%x", i, clients[i], i, &clients[i]);
171                 return &clients[i];
172             }
173             if (clients[i].encode_codec[j] == (VIDENC2_Handle) codec) {
174                 DEBUG("Found VIDENC2 clients[%d] = 0x%x, &clients[%d] = 0x%x", i, clients[i], i, &clients[i]);
175                 return &clients[i];
176             }
177         }
178     }
179     return NULL;
182 static struct {
183     CreateFxn  create;
184     ControlFxn control;
185     ProcessFxn process;
186     DeleteFxn  delete;
187     RelocFxn   reloc;   /* handle buffer relocation table */
188 } codec_fxns[] =
190     [OMAP_DCE_VIDENC2] =
191     {
192         (CreateFxn)videnc2_create,   (ControlFxn)videnc2_control,
193         (ProcessFxn)VIDENC2_process, (DeleteFxn)VIDENC2_delete,
194         (RelocFxn)videnc2_reloc,
195     },
196     [OMAP_DCE_VIDDEC3] =
197     {
198         (CreateFxn)viddec3_create,   (ControlFxn)viddec3_control,
199         (ProcessFxn)viddec3_process, (DeleteFxn)VIDDEC3_delete,
200         (RelocFxn)viddec3_reloc,
201     },
202 };
205 /* Static version string buffer.
206  * Note: codec version can be large. For example, h264vdec needs more than
207  * 58 characters, or the query will fail. */
208 #define VERSION_SIZE 128
209 static char    version_buffer[VERSION_SIZE];
211 /* the following callbacks are needed for suspend/resume
212  * on the linux side.
213  * - FC_suspend() waits for all algorithms to get deactivated and
214  * and takes care of the resources acquired.
215  * - FC_resume() does nothing for now, but we add it just in case
216  * it gets populated in the future versions of framework components.
217  *
218  * Forced off mode during video decode/encode is not supported. */
219 static void dce_suspend()
221     INFO("Preparing for suspend...");
222     FC_suspend();
225 static void dce_resume()
227     INFO("Restoring after suspend...");
228     FC_resume();
231 static void get_videnc2_version(VIDENC2_Handle h, char *buffer, unsigned size)
233     VIDENC2_DynamicParams    params =
234     {
235         .size = sizeof(VIDENC2_DynamicParams),
236     };
238     VIDENC2_Status    status =
239     {
240         .size = sizeof(VIDENC2_Status),
241         .data =
242         {
243             .buf = (XDAS_Int8 *)buffer,
244             .bufSize = (XDAS_Int32)size,
245         },
246     };
248     XDAS_Int32    s;
250     memset(buffer, 0, size);
251     s = VIDENC2_control(h, XDM_GETVERSION, &params, &status);
253     if( s != VIDENC2_EOK ) {
254         ERROR("Unknown version Error = %d:: buffer = %p size = %d", s, buffer, size);
255     }
258 // VIDENC2_create wrapper, to display version string in the trace.
259 static VIDENC2_Handle videnc2_create(Engine_Handle engine, String name, VIDENC2_Params *params)
261     VIDENC2_Handle    h;
263     h = VIDENC2_create(engine, name, params);
265     if( h ) {
266         get_videnc2_version(h, version_buffer, VERSION_SIZE);
267         INFO("Created videnc2 %s: version %s", name, version_buffer);
268     }
270     return (h);
273 static XDAS_Int32 getBufferFxnStub(XDM_DataSyncHandle handle, XDM_DataSyncDesc *desc)
275     return (0);
278 static XDAS_Int32 videnc2_control(VIDENC2_Handle codec, VIDENC2_Cmd id,
279                                   VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status)
281     Client* c;
283     c = get_client_instance((Uint32) codec);
284     if (c) {
285         int i;
286         for (i = 0; i < DIM(c->encode_codec); i++) {
287             if (c->encode_codec[i] == codec) {
288                 if (c->encode_callback[i].row_mode) {
289                     if (id == XDM_SETPARAMS) {
290                         c->encode_callback[i].dataSyncHandle = codec;
291                         c->encode_callback[i].mpu_crash_indication = FALSE;
292                         dynParams->getDataFxn = (XDM_DataSyncGetFxn) H264E_GetDataFxn;
293                         dynParams->getDataHandle = codec;
294                     }
295                 }
296             }
297         }
298     }
300     dynParams->getBufferFxn = getBufferFxnStub;
301     return (VIDENC2_control(codec, id, dynParams, status));
304 static void get_viddec3_version(VIDDEC3_Handle h, char *buffer, unsigned size)
306     VIDDEC3_DynamicParams    params =
307     {
308         .size = sizeof(VIDDEC3_DynamicParams),
309     };
311     VIDDEC3_Status    status =
312     {
313         .size = sizeof(VIDDEC3_Status),
314         .data =
315         {
316             .buf = (XDAS_Int8 *)buffer,
317             .bufSize = (XDAS_Int32)size,
318         },
319     };
321     XDAS_Int32    s;
323     memset(buffer, 0, size);
324     s = VIDDEC3_control(h, XDM_GETVERSION, &params, &status);
326     if( s != VIDDEC3_EOK ) {
327         ERROR("Unknown version Error = %d:: buffer = %p size = %d", s, buffer, size);
328     }
331 // VIDDEC3_create wrapper, to display version string in the trace.
332 static VIDDEC3_Handle viddec3_create(Engine_Handle engine, String name, VIDDEC3_Params *params)
334     VIDDEC3_Handle    h;
336     DEBUG(">> engine=%08x, name=%s, params=%p", engine, name, params);
337     DEBUG(">> max_height %d max_width %d frame_rate %d", params->maxHeight, params->maxWidth, params->maxFrameRate);
339     h = VIDDEC3_create(engine, name, params);
341     if( h ) {
342         get_viddec3_version(h, version_buffer, VERSION_SIZE);
343         INFO("Created viddec3 %s: version %s", name, version_buffer);
344     }
346     return (h);
349 static XDAS_Int32 viddec3_control(VIDDEC3_Handle codec,VIDDEC3_Cmd id,VIDDEC3_DynamicParams * dynParams,VIDDEC3_Status * status)
351     Client* c;
353     c = get_client_instance((Uint32) codec);
354     if (c) {
355         int i;
356         for (i = 0; i < DIM(c->decode_codec); i++) {
357             if (c->decode_codec[i] == codec) {
358                 if (c->decode_callback[i].row_mode) {
359                     DEBUG("Check codec 0x%x control id %d", codec, id);
360                     if (id == XDM_SETPARAMS) {
361                         c->decode_callback[i].dataSyncHandle = codec;
362                         c->decode_callback[i].mpu_crash_indication = FALSE;
363                         dynParams->putDataFxn = (XDM_DataSyncPutFxn) H264D_PutDataFxn;
364                         dynParams->putDataHandle = codec;
365                     }
366                 }
367             }
368         }
369     }
371     //dynParams->putBufferFxn = putBufferFxnStub;
372     return (VIDDEC3_control(codec, id, dynParams, status));
375 static XDAS_Int32 viddec3_process(VIDDEC3_Handle codec, XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs)
377     Client* c;
378     XDAS_Int32 ret;
380     c = get_client_instance((Uint32) codec);
381     if (c) {
382         int i;
383         for (i = 0; i < DIM(c->decode_codec); i++) {
384             if (c->decode_codec[i] == codec) {
385                 if (c->decode_callback[i].row_mode) {
386                     DEBUG("Codec 0x%x", codec);
387                     c->decode_callback[i].codec_request = 0;
388                     c->decode_callback[i].putdata_toclient = 0;
389                     c->decode_callback[i].putData_endprocess = 0;
390                     ret = VIDDEC3_process(codec, inBufs, outBufs, inArgs, outArgs);
392                     // Set flag and signal for put_DataFxn to return.
393                     c->decode_callback[i].putData_endprocess = 1;
394                     pthread_cond_signal(&(c->decode_callback[i].synch_callback));
395                     return (ret);
396                 }
397             }
398         }
399     }
400     return (VIDDEC3_process(codec, inBufs, outBufs, inArgs, outArgs));
403 static int videnc2_reloc(VIDENC2_Handle handle, uint8_t *ptr, uint32_t len)
405     return (-1); // Not implemented
408 /* Only valid if XDM_MOVEBUFS added in XDC tools */
409 static int viddec3_reloc(VIDDEC3_Handle handle, uint8_t *ptr, uint32_t len)
411     return (-1); // Not implemented
412 #if 0
413     static VIDDEC3_DynamicParams    params =
414     {
415         .size = sizeof(VIDDEC3_DynamicParams),
416     };
417     VIDDEC3_Status    status =
418     {
419         .size = sizeof(VIDDEC3_Status),
420         .data =
421         {
422             .buf = (XDAS_Int8 *)ptr,
423             .bufSize = (XDAS_Int32)len,
424         },
425     };
426     INFO("status.size=%d", status.size);
427     return (VIDDEC3_control(handle, XDM_MOVEBUFS, &params, &status));
428 #endif
431 /*
432  * RPC message handlers
433  */
434 static int connect(void *msg)
436     dce_connect   *req = msg;
438     DEBUG(">> chipset_id=0x%x, debug=%d", req->chipset_id, req->debug);
440     if( dce_debug >= MAX_DEBUG_LEVEL ) {
441         DEBUG("Enable FC, CE and IPC traces");
443         FCSettings_init();
444         Diags_setMask(FCSETTINGS_MODNAME "+12345678LEXAIZFS");
445         CESettings_init();
446         Diags_setMask(CESETTINGS_MODNAME "+12345678LEXAIZFS");
448         /*
449             * Enable use of runtime Diags_setMask per module:
450             *
451             * Codes: E = ENTRY, X = EXIT, L = LIFECYCLE, F = INFO, S = STATUS
452             */
453         Diags_setMask("ti.ipc.rpmsg.RPMessage=EXLFS");
454         Diags_setMask("ti.ipc.rpmsg.VirtQueue=EXLFS");
455     }
457     ivahd_init(req->chipset_id);
459     if( !suspend_initialised ) {
461         /* registering sysbios-rpmsg callbacks for suspend/resume */
462         IpcPower_registerCallback(IpcPower_Event_SUSPEND, (IpcPower_CallbackFuncPtr)dce_suspend, 0);
463         IpcPower_registerCallback(IpcPower_Event_RESUME, (IpcPower_CallbackFuncPtr)dce_resume, 0);
464         suspend_initialised++;
465     }
467     DEBUG("<<");
469     return (0);
472 static Int32 dce_register_engine(Uint32 mm_serv_id, Engine_Handle engine)
474     Int32  ret = 0;
475     Uint32 clientIndex = 0;
476     Client *c;
478     c = get_client(mm_serv_id);
479     if( c ) {
480         int i;
481         DEBUG("found mem client: %p refs=%d", c, c->refs);
482         c->refs++;
483         for (i = 0; i < DIM(c->engines); i++) {
484             if (c->engines[i] == NULL) {
485                 c->engines[i] = engine;
486                 clientIndex = i;
487                 DEBUG("registered engine: mm_serv_id=%x engine=%p", mm_serv_id, engine);
488                 break;
489             }
490         }
492         //If clientIndex is equal to 0 and it is not the register engine, then we know that no more
493         //empty spot since clientIndex not getting set in the for loop.
494         if( (clientIndex == 0) && (c->engines[clientIndex]) != engine ){
495             ERROR("No more empty space for engine");
496             ret = -1;
497             goto out;
498         }
499     }else {
500         c = get_client(0);
501         if (!c) {
502             ERROR("too many clients");
503             ret = -1;
504             goto out;
505         }
506         DEBUG("new client: %p refs=%d", c, c->refs);
508         c->mm_serv_id = mm_serv_id;
509         c->refs = 1;
510         c->engines[0] = engine;
511     }
512 out:
513     if ((ret != 0) && (c)){
514         c->mm_serv_id = NULL;
515         c->refs--;
516         c->engines[0] = NULL;
517     }
518     return ret;
521 static void dce_unregister_engine(Uint32 mm_serv_id, Engine_Handle engine)
523     Client *c;
525     c = get_client(mm_serv_id);
526     if( c ) {
527         int i;
528         DEBUG("found mem client: %p refs=%d", c, c->refs);
530         for( i = 0; i < DIM(c->engines); i++ ) {
531             if( c->engines[i] == engine ) {
532                 c->engines[i] = NULL;
533                 DEBUG("unregistered engine: mm_serv_id=0x%x engine=%p", mm_serv_id, engine);
534                 break;
535             }
536         }
538         //If i is equal to the size of Array, then it means it has search the whole array.
539         if( i == DIM(c->engines) ) {
540             ERROR("Unknown engine received on dce_unregister_engine");
541             return;
542         }
544         DEBUG("dce_unregister_engine: %p refs=%d", c, c->refs);
545         c->refs--;
547         if( !c->refs ) {
548             c->mm_serv_id = NULL;
549         }
550     }
553 static Int32 dce_register_codec(Uint32 type, Uint32 mm_serv_id, Uint32 codec)
555     Client *c;
556     Int32 ret = 0;
557     Uint32 clientIndex = 0;
559     c = get_client(mm_serv_id);
560     if( c ) {
561         int i;
562         DEBUG("found mem client: %p refs=%d", c, c->refs);
564         if( type == OMAP_DCE_VIDDEC3 ) {
565             for( i = 0; i < DIM(c->decode_codec); i++ ) {
566                 if( c->decode_codec[i] == NULL ) {
567                     c->decode_codec[i] = (VIDDEC3_Handle) codec;
568                     c->codec_id = type;
569                     clientIndex = i;
570                     DEBUG("registering codec: decode_codec[%d] codec=%p", i, codec);
571                     break;
572                 }
573             }
575             //If clientIndex is equal to 0 and it's not the register codec, then we know that no more
576             //empty spot since clientIndex not getting set in the for loop.
577             if( (clientIndex == 0) && (c->decode_codec[clientIndex]) != (VIDDEC3_Handle) codec ) {
578                 ERROR("No more empty space for codecs");
579                 ret = -1;
580                 goto out;
581             }
582         }
583         else if( type == OMAP_DCE_VIDENC2 ) {
584             for( i = 0; i < DIM(c->encode_codec); i++ ) {
585                 if( c->encode_codec[i] == NULL ) {
586                     c->encode_codec[i] = (VIDENC2_Handle) codec;
587                     c->codec_id = type;
588                     clientIndex = i;
589                     DEBUG("registering codec: encode_codec[%d] codec=%p", i, codec);
590                     break;
591                 }
592             }
594             //If clientIndex is equal to 0 and it's not the register codec, then we know that no more
595             //empty spot since clientIndex not getting set in the for loop.
596             if( (clientIndex == 0) && (c->encode_codec[clientIndex]) != (VIDENC2_Handle) codec ) {
597                 ERROR("No more empty space for codecs");
598                 ret = -1;
599                 goto out;
600             }
601         }
602     }
604 out:
605     return ret;
608 static void dce_unregister_codec(Uint32 type, Uint32 mm_serv_id, Uint32 codec)
610     Client *c;
612     c = get_client(mm_serv_id);
613     if (c) {
614         int i;
615         DEBUG("found mem client: %p refs=%d", c, c->refs);
617         if( type == OMAP_DCE_VIDDEC3 ) {
618             for( i = 0; i < DIM(c->decode_codec); i++ ) {
619                 if( c->decode_codec[i] == (VIDDEC3_Handle) codec ) {
620                     c->decode_codec[i] = NULL;
621                     DEBUG("unregistered decode_codec[%d] type Decoder codec=%p", i, codec);
622                     break;
623                 }
624             }
625         }
626         else if( type == OMAP_DCE_VIDENC2 ) {
627             for( i = 0; i < DIM(c->encode_codec); i++ ) {
628                 if( c->encode_codec[i] == (VIDENC2_Handle) codec ) {
629                     c->encode_codec[i] = NULL;
630                     DEBUG("unregistered encode_codec[%d] type Encoder codec=%p", i, codec);
631                     break;
632                 }
633             }
634         }
635     }
638 /*
639  * Engine_open:
640  */
641 static Int32 engine_open(UInt32 size, UInt32 *data)
643     MmType_Param      *payload = (MmType_Param *)data;
644     dce_engine_open   *engine_open_msg = (dce_engine_open *)payload[0].data;
645     Uint32             mm_serv_id = 0;
646     Engine_Handle      eng_handle = NULL;
647     Uint32             num_params = MmRpc_NUM_PARAMETERS(size);
648     Int32              ret = 0;
650     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
652     DEBUG(">> engine_open");
654     if( num_params != 1 ) {
655         ERROR("Invalid number of params sent");
656         return (-1);
657     }
659     dce_inv(engine_open_msg);
661     eng_handle = Engine_open(engine_open_msg->name, engine_open_msg->engine_attrs, &engine_open_msg->error_code);
663     if( eng_handle ) {
664         mm_serv_id = MmServiceMgr_getId();
665         DEBUG("engine_open mm_serv_id 0x%x eng_handle %08x", mm_serv_id, eng_handle);
667         ret = dce_register_engine(mm_serv_id, eng_handle);
668         if( ret < 0 ) {
669             Engine_close(eng_handle);
670             eng_handle = NULL;
671         }
672     }
674     DEBUG("<< engine=%08x, ec=%d", eng_handle, engine_open_msg->error_code);
676     dce_clean(engine_open_msg);
677     Semaphore_post(sync_process_sem);
679     return ((Int32)eng_handle);
682 /*
683  * Engine_close:
684  */
685 static Int32 engine_close(UInt32 size, UInt32 *data)
687     MmType_Param    *payload = (MmType_Param *)data;
688     Engine_Handle    eng_handle = (Engine_Handle)payload[0].data;
689     Uint32           mm_serv_id = 0;
690     Uint32           num_params = MmRpc_NUM_PARAMETERS(size);
692     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
694     DEBUG(">> engine_close %08x", eng_handle);
696     if( num_params != 1 ) {
697         ERROR("invalid number of params sent");
698         return (-1);
699     }
701     mm_serv_id = MmServiceMgr_getId();
702     DEBUG("engine_close mm_serv_id 0x%x", mm_serv_id);
704     dce_unregister_engine(mm_serv_id, eng_handle);
706     Engine_close(eng_handle);
707     DEBUG("<<");
709     Semaphore_post(sync_process_sem);
711     return (0);
715 #define INFO_TYPE_CPU_LOAD 0
716 #define INFO_TYPE_TOTAL_HEAP_SIZE 1
717 #define INFO_TYPE_AVAILABLE_HEAP_SIZE 2
719 static Int32 get_rproc_info(UInt32 size, UInt32 *data)
721     MmType_Param    *payload = (MmType_Param *)data;
722     Uint32           info_type = (Uint32)payload[0].data;
723     Memory_Stats     stats;
724     Uint32           output = 0;
726     switch(info_type)
727     {
728         case INFO_TYPE_CPU_LOAD:
729             output = Load_getCPULoad();
730             break;
732         case INFO_TYPE_TOTAL_HEAP_SIZE:
733             Memory_getStats(NULL, &stats);
734             output = stats.totalSize;
735             break;
737         case INFO_TYPE_AVAILABLE_HEAP_SIZE:
738             Memory_getStats(NULL, &stats);
739             output = stats.totalFreeSize;
740             break;
742         default:
743             System_printf("\n ERROR: Invalid INFO TYPE chosen \n");
744             break;
745     }
747     return output;
752 /*
753   * codec_create
754   */
755 static Int32 codec_create(UInt32 size, UInt32 *data)
757     MmType_Param    *payload = (MmType_Param *)data;
758     Uint32           codec_id      = (Uint32)payload[0].data;
759     Engine_Handle    engine = (Engine_Handle)payload[1].data;
760     char            *codec_name    = (char *)payload[2].data;
761     void            *static_params = (void *)payload[3].data;
762     Uint32           mm_serv_id = 0;
763     Uint32           num_params = MmRpc_NUM_PARAMETERS(size);
764     void            *codec_handle;
765     Int32            ret = 0;
766     Client*          c;
768 #ifdef MEMORYSTATS_DEBUG
769     Memory_Stats    stats;
770 #endif
772     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
774     DEBUG(">> codec_create on engine %08x", engine);
776     if( num_params != 4 ) {
777         ERROR("invalid number of params sent");
778         return (-1);
779     }
781     dce_inv(codec_name);
782     dce_inv(static_params);
784     /* The next source code statement shouldn't get executed in real world as the client should send */
785     /* the correct width and height for the video resolution to be decoded.                          */
786     /* It is coded to test the Error Recovery when IPUMM on IPU2 is crashing                         */
787     /* by simulating the condition where A15 will send maxHeight as zero                             */
788     if( (((VIDDEC3_Params*)static_params)->maxHeight == 0) && (codec_id == OMAP_DCE_VIDDEC3) ) {
789         DEBUG("IPC RECOVERY will be performed due to maxHeight is zero which will cause exception!!!!");
790         num_params = num_params / ((VIDDEC3_Params*)static_params)->maxHeight;
791         System_printf("Crashing the IPU2 after divided by zero num_params %d", num_params);
792     }
794     ivahd_acquire();
796     codec_handle = (void *)codec_fxns[codec_id].create(engine, codec_name, static_params);
797     ivahd_release();
799     if( codec_handle ) {
800         mm_serv_id = MmServiceMgr_getId();
802         ret = dce_register_codec(codec_id, mm_serv_id, (Uint32) codec_handle);
803         if( ret < 0 ) {
804             codec_fxns[codec_id].delete((void *)codec_handle);
805             codec_handle = NULL;
806         } else {
807             if( codec_id == OMAP_DCE_VIDDEC3 ) {
808                 DEBUG("codec_create for VIDDEC3 codec_handle 0x%x mm_serv_id 0x%x", codec_handle, mm_serv_id);
809                 if( ((VIDDEC3_Params*)static_params)->outputDataMode == IVIDEO_NUMROWS ) {
810                     c = get_client_instance((Uint32) codec_handle);
811                     int i;
812                     for( i = 0; i < DIM(c->decode_codec); i++ ) {
813                         if( c->decode_codec[i] == codec_handle ) {
814                             c->decode_callback[i].row_mode = 1;
815                             pthread_mutex_init(&(c->decode_callback[i].callback_mutex), NULL);
816                             pthread_cond_init(&(c->decode_callback[i].synch_callback), NULL);
817                             DEBUG("codec_create client 0x%x c->decode_callback[%d].callback_mutex 0x%x c->decode_callback[%d].row_mode %d",
818                                 c, i, c->decode_callback[i].callback_mutex, i, c->decode_callback[i].row_mode);
819                         }
820                     }
821                 }
822             } else if( codec_id == OMAP_DCE_VIDENC2 ) {
823                 DEBUG("codec_create for VIDENC2 codec_handle 0x%x mm_serv_id 0x%x", codec_handle, mm_serv_id);
824                 if( ((VIDENC2_Params*)static_params)->inputDataMode == IVIDEO_NUMROWS ) {
825                     c = get_client_instance((Uint32) codec_handle);
826                     int i;
827                     for( i = 0; i < DIM(c->encode_codec); i++ ) {
828                         if( c->encode_codec[i] == codec_handle ) {
829                             c->encode_callback[i].row_mode = 1;
830                             pthread_mutex_init(&(c->encode_callback[i].callback_mutex), NULL);
831                             pthread_cond_init(&(c->encode_callback[i].synch_callback), NULL);
832                             DEBUG("codec_create client 0x%x c->encode_callback[%d].callback_mutex 0x%x c->encode_callback[%d].row_mode %d",
833                                 c, i, c->encode_callback[i].callback_mutex, i, c->encode_callback[i].row_mode);
834                         }
835                     }
836                 }
837             }
838         }
839     }
840     DEBUG("<< codec_handle=%08x on engine %08x", codec_handle, engine);
842     dce_clean(static_params);
843     dce_clean(codec_name);
845     Semaphore_post(sync_process_sem);
847 #ifdef MEMORYSTATS_DEBUG
848     Memory_getStats(NULL, &stats);
849     INFO("Total: %d\tFree: %d\tLargest: %d", stats.totalSize,
850          stats.totalFreeSize, stats.largestFreeSize);
851 #endif
852 #ifdef PSI_KPI
853         kpi_comp_init(codec_handle);
854 #endif /*PSI_KPI*/
855     return ((Int32)codec_handle);
858 /*
859   * codec_control
860   */
861 static int codec_control(UInt32 size, UInt32 *data)
863     MmType_Param   *payload = (MmType_Param *)data;
864     Uint32          codec_id            = (Uint32)payload[0].data;
865     void           *codec_handle = (Engine_Handle)payload[1].data;
866     uint32_t        cmd_id              = (Uint32)payload[2].data;
867     void           *dyn_params          = (void *)payload[3].data;
868     void           *status              = (void *)payload[4].data;
869     Uint32          num_params = MmRpc_NUM_PARAMETERS(size);
870     Int32           ret = 0;
872     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
874     DEBUG(">> codec_control on codec_handle %08x", codec_handle);
876     if( num_params != 5 ) {
877         ERROR("invalid number of params sent");
878         return (-1);
879     }
881     dce_inv(dyn_params);
882     dce_inv(status);
884     /* Only for cmd_id == XDM_FLUSH/XDM_MOVEBUF ? */
885     ivahd_acquire();
887     ret = (uint32_t) codec_fxns[codec_id].control(codec_handle, cmd_id, dyn_params, status);
888     ivahd_release();
890     DEBUG("<< codec_control on codec_handle %08x result=%d", codec_handle, ret);
892     dce_clean(dyn_params);
893     dce_clean(status);
895     Semaphore_post(sync_process_sem);
897     return (ret);
900 /*
901   * codec get version
902   */
903 static int codec_get_version(UInt32 size, UInt32 *data)
905     MmType_Param   *payload = (MmType_Param *)data;
906     Uint32          codec_id            = (Uint32)payload[0].data;
907     void           *codec_handle = (Engine_Handle)payload[1].data;
908     void           *dyn_params          = (void *)payload[2].data;
909     void           *status              = (void *)payload[3].data;
910     Uint32          num_params = MmRpc_NUM_PARAMETERS(size);
911     void           *version_buf = NULL;
912     Int32           ret = 0;
914     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
916     DEBUG(">> codec_get_version on codec_handle %08x", codec_handle);
918     if( num_params != 4 ) {
919         ERROR("invalid number of params sent");
920         return (-1);
921     }
923     dce_inv(dyn_params);
924     dce_inv(status);
926     if( codec_id == OMAP_DCE_VIDDEC3 ) {
927         version_buf = (void *)(H2P((MemHeader *)((IVIDDEC3_Status *)status)->data.buf));
928     } else if( codec_id == OMAP_DCE_VIDENC2 ) {
929         version_buf = (void *)(H2P((MemHeader *)((IVIDENC2_Status *)status)->data.buf));
930     }
932     dce_inv(version_buf);
934     ivahd_acquire();
935     ret = (uint32_t) codec_fxns[codec_id].control(codec_handle, XDM_GETVERSION, dyn_params, status);
936     ivahd_release();
938     DEBUG("<< codec_get_version on codec_handle %08x result=%d", codec_handle, ret);
940     dce_clean(dyn_params);
941     dce_clean(status);
942     dce_clean(version_buf);
944     Semaphore_post(sync_process_sem);\
946     return (ret);
949 /* Notes about serialization of process command:
950  *
951  * Since codec_process code on kernel side is doing buffer mapping/unmapping,
952  * and keeping track of codec's locked buffers, it is necessary for it to
953  * look into the contents of some of the parameter structs, and in some cases
954  * re-write them.  For this reason inArgs/outBufs/inBufs are serialized within
955  * the rpmsg rather than just passed by pointer.
957 XDAS_Int32 VIDDEC3_process(VIDDEC3_Handle handle, XDM2_BufDesc *inBufs,
958     XDM2_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs);
960   REQ:
961     struct dce_rpc_hdr hdr   -> 4
962     codec_id                 -> 4
963     codec                    -> 4
964     reloc length             -> 1   (length/4)
965     inArgs length            -> 1   (length/4)
966     outBufs length           -> 1   (length/4)
967     inBufs length            -> 1   (length/4)
968     VIDDEC3_OutArgs *outArgs -> 4   (pass by pointer)
969     reloc table              -> 12 * nreloc (typically <= 16)
970     VIDDEC3_InArgs   inArgs  -> 12  (need inputID from userspace)
971     XDM2_BufDesc     outBufs -> 44  (4 + 2 * 20)
972     XDM2_BufDesc     inBufs  -> 24  (4 + 1 * 20)
973     -------------------------------
974                                99
976   RSP
977     struct dce_rpc_hdr hdr   -> 4
978     result                   -> 4
979     inBufs length            -> 1   (length/4)
980     XDAS_Int32 freeBufID[]   -> 4*n (n typically 0 or 2, but could be up to 20)
981     -------------------------------
982                                9-89
983     Note: freeBufID[] duplicates what is returned in outArgs, but avoids
984     needing to create kernel mappings of these objects which are to big
985     to copy inline.  Also it avoids differences between VIDDEC3/VIDDENC2.
988 XDAS_Int32 VIDENC2_process(VIDENC2_Handle handle, IVIDEO2_BufDesc *inBufs,
989     XDM2_BufDesc *outBufs, IVIDENC2_InArgs *inArgs, IVIDENC2_OutArgs *outArgs);
991   REQ:
992     struct dce_rpc_hdr hdr   -> 4
993     codec_id                 -> 4
994     codec                    -> 4
995     reloc length             -> 1   (length/4)
996     inArgs length            -> 1   (length/4)
997     outBufs length           -> 1   (length/4)
998     inBufs length            -> 1   (length/4)
999     VIDENC2_OutArgs *outArgs -> 4   (pass by pointer)
1000     reloc table              -> ???
1001     VIDENC2_InArgs   inArgs  -> 12  (need inputID from userspace)
1002     XDM2_BufDesc     outBufs -> 24  (4 + 1 * 20)
1003     IVIDEO2_BufDesc  inBufs  -> 252
1004     -------------------------------
1005                               307
1007   RSP
1008     struct dce_rpc_hdr hdr   -> 4
1009     result                   -> 4
1010     inBufs length            -> 1   (length/4)
1011     XDAS_Int32 freeBufID[]   -> 4*n (n typically 0 or 2, but could be up to 20)
1012     -------------------------------
1013                                9-89
1014  */
1016 static int codec_process(UInt32 size, UInt32 *data)
1018     MmType_Param   *payload = (MmType_Param *)data;
1019     Uint32          num_params = MmRpc_NUM_PARAMETERS(size);
1020     Uint32          codec_id = (Uint32) payload[0].data;
1021     Uint32          codec    = (Uint32) payload[1].data;
1022     void           *inBufs   = (void *) payload[2].data;
1023     void           *outBufs  = (void *) payload[3].data;
1024     void           *inArgs   = (void *) payload[4].data;
1025     void           *outArgs  = (void *) payload[5].data;
1026     Int32           ret = 0;
1028     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
1030     DEBUG(">> codec_process codec=%p", codec);
1032     if( num_params != 6 ) {
1033         ERROR("invalid number of params sent");
1034         return (-1);
1035     }
1037     dce_inv(inBufs);
1038     dce_inv(outBufs);
1039     dce_inv(inArgs);
1040     dce_inv(outArgs);
1042     DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p codec_id=%d LOCK sync_process_sem 0x%x",
1043         codec, inBufs, outBufs, inArgs, outArgs, codec_id, sync_process_sem);
1045 #ifdef PSI_KPI
1046         kpi_before_codec();
1047 #endif /*PSI_KPI*/
1048     ivahd_acquire();
1049     // do a reloc()
1050     ret = codec_fxns[codec_id].process((void *)codec, inBufs, outBufs, inArgs, outArgs);
1052     ivahd_release();
1054 #ifdef PSI_KPI
1055         kpi_after_codec();
1056 #endif /*PSI_KPI*/
1057     DEBUG("<< codec=%p ret=%d extendedError=%08x", codec, ret, ((VIDDEC3_OutArgs *)outArgs)->extendedError);
1059     dce_clean(inBufs);
1060     dce_clean(outBufs);
1061     dce_clean(inArgs);
1062     dce_clean(outArgs);
1064     Semaphore_post(sync_process_sem);
1066     return ((Int32)ret);
1069 /*
1070   * codec delete
1071   */
1073 static int codec_delete(UInt32 size, UInt32 *data)
1075     MmType_Param   *payload = (MmType_Param *)data;
1076     Uint32          num_params = MmRpc_NUM_PARAMETERS(size);
1077     Uint32          codec_id = (Uint32) payload[0].data;
1078     Uint32          codec    = (Uint32) payload[1].data;
1079     Uint32          mm_serv_id = 0;
1080     Client*          c;
1082 #ifdef MEMORYSTATS_DEBUG
1083     Memory_Stats    stats;
1084 #endif
1086     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
1088     DEBUG(">> codec_delete on codec 0x%x", codec);
1090     if( num_params != 2 ) {
1091         ERROR("invalid number of params sent");
1092         return (-1);
1093     }
1095     if ( codec_id == OMAP_DCE_VIDDEC3 ) {
1096         DEBUG("codec_delete for VIDDEC3 codec_handle 0x%x", codec);
1097         c = get_client_instance((Uint32) codec);
1098         int i;
1099         for (i = 0; i < DIM(c->decode_codec); i++ ) {
1100             if (c->decode_codec[i] == (VIDDEC3_Handle) codec) {
1101                 if (c->decode_callback[i].row_mode) {
1102                     c->decode_callback[i].row_mode = 0;
1103                     pthread_mutex_destroy(&(c->decode_callback[i].callback_mutex));
1104                     pthread_cond_destroy(&(c->decode_callback[i].synch_callback));
1105                 }
1106                 DEBUG("codec_delete client 0x%x c->decode_callback[%d].callback_mutex 0x%x", c, i, c->decode_callback[i].callback_mutex);
1107             }
1108         }
1109     } else if ( codec_id == OMAP_DCE_VIDENC2 ) {
1110         DEBUG("codec_delete for VIDENC2 codec_handle 0x%x", codec);
1111         c = get_client_instance((Uint32) codec);
1112         int i;
1113         for (i = 0; i < DIM(c->encode_codec); i++ ) {
1114             if (c->encode_codec[i] == (VIDENC2_Handle) codec) {
1115                 if (c->encode_callback[i].row_mode) {
1116                     c->encode_callback[i].row_mode = 0;
1117                     pthread_mutex_destroy(&(c->encode_callback[i].callback_mutex));
1118                     pthread_cond_destroy(&(c->encode_callback[i].synch_callback));
1119                 }
1120                 DEBUG("codec_delete client 0x%x c->encode_callback[%d].callback_mutex 0x%x", c, i, c->encode_callback[i].callback_mutex);
1121             }
1122         }
1123     }
1125     codec_fxns[codec_id].delete((void *)codec);
1127     mm_serv_id = MmServiceMgr_getId();
1128     DEBUG("codec_delete mm_serv_id 0x%x", mm_serv_id);
1129     dce_unregister_codec(codec_id, mm_serv_id, codec);
1131 #ifdef MEMORYSTATS_DEBUG
1132     Memory_getStats(NULL, &stats);
1133     INFO("Total: %d\tFree: %d\tLargest: %d", stats.totalSize,
1134          stats.totalFreeSize, stats.largestFreeSize);
1135 #endif
1137     DEBUG("<< codec_delete");
1139     Semaphore_post(sync_process_sem);
1141 #ifdef PSI_KPI
1142         kpi_comp_deinit((void*)codec);
1143 #endif /*PSI_KPI*/
1144     return (0);
1147 /*
1148  * get_DataFxn : Sync/transfer the input data information from MPU side to DCE Server.
1149  * DCE Server will pass the information through the IVA-HD callback function:
1150  * H264E_GetDataFxn.
1151  */
1152 static int get_DataFxn(UInt32 size, UInt32 *data)
1154     MmType_Param   *payload = (MmType_Param *)data;
1155     Uint32          num_params = MmRpc_NUM_PARAMETERS(size);
1156     XDM_DataSyncHandle          dataSyncHandle = (XDM_DataSyncHandle) payload[0].data;
1157     XDM_DataSyncDesc            *dataSyncDesc    = (void *) payload[1].data;
1158     Client* c;
1160     DEBUG(">> get_DataFxn dataSyncHandle 0x%x", dataSyncHandle);
1162     if( num_params != 2 ) {
1163         ERROR("invalid number of params sent");
1164         return (-1);
1165     }
1167     dce_inv(dataSyncDesc);
1169     c = get_client_instance((Uint32) dataSyncHandle);
1170     if (c) {
1171         int i;
1172         for (i = 0; i < DIM(c->encode_codec); i++) {
1173             if (c->encode_codec[i] == dataSyncHandle) {
1174                 pthread_mutex_lock(&(c->encode_callback[i].callback_mutex));
1175                 c->encode_callback[i].dataSyncHandle = dataSyncHandle;
1176                 c->encode_callback[i].dataSyncDesc = dataSyncDesc;
1178                 if (c->encode_callback[i].codec_request) {
1179                     DEBUG("Case#1 get_DataFxn is received while codec has requested first. Signal the H264E_GetDataFxn to continue.");
1180                     pthread_cond_signal(&(c->encode_callback[i].synch_callback));
1181                 } else {
1182                     // We received get_DataFxn from libdce/client, need to hold it until the data
1183                     // is consumed by codec through H264E_GetDataFxn before continuing. Otherwise
1184                     // we will receive another one since MPU side thinks that the data has been
1185                     // consumed by the codec.
1186                     c->encode_callback[i].getdata_ready = 1;
1187                     DEBUG("Case#2 get_DataFxn is received but codec has not request H264E_GetDataFxn. Wait conditionally.");
1188                     pthread_cond_wait(&(c->encode_callback[i].synch_callback), &(c->encode_callback[i].callback_mutex));
1189                     DEBUG("Case#2 get_DataFxn finally gets H264E_GetDataFxn, and the data has been consumed, continue.");
1190                     c->encode_callback[i].getdata_ready = 0;
1191                 }
1192                 pthread_mutex_unlock(&(c->encode_callback[i].callback_mutex));
1193             }
1194         }
1195     }
1197     dce_clean(dataSyncDesc);
1198     return (0);
1201 /*
1202  * put_DataFxn : Sync/transfer the output data information from DCE Server to MPU side.
1203  * DCE Server will pass the information from the IVA-HD callback function:
1204  * H264D_PutDataFxn to MPU side.
1205  */
1206 static int put_DataFxn(UInt32 size, UInt32 *data)
1208     MmType_Param   *payload = (MmType_Param *)data;
1209     Uint32          num_params = MmRpc_NUM_PARAMETERS(size);
1210     XDM_DataSyncHandle          dataSyncHandle = (XDM_DataSyncHandle) payload[0].data;
1211     XDM_DataSyncDesc            *dataSyncDesc    = (void *) payload[1].data;
1212     Client* c;
1214     DEBUG(">> put_DataFxn dataSyncHandle 0x%x dataSyncDesc 0x%x", dataSyncHandle, dataSyncDesc);
1216     if( num_params != 2 ) {
1217         ERROR("invalid number of params sent");
1218         return (-1);
1219     }
1221     dce_inv(dataSyncDesc);
1223     c = get_client_instance((Uint32) dataSyncHandle);
1224     if (c) {
1225         int i;
1226         for (i = 0; i < DIM(c->decode_codec); i++) {
1227             if (c->decode_codec[i] == dataSyncHandle) {
1228                 pthread_mutex_lock(&(c->decode_callback[i].callback_mutex));
1229                 // Found the corresponding entry, check if IVA-HD has already called the callback (codec_request == 1).
1231                 if ((c->decode_callback[i].codec_request) && ((c->decode_callback[i].putdata_toclient) == 0)) {
1232                     DEBUG("Case#1 put_DataFxn is received while codec has requested first. c->decode_callback[%d].callback_mutex 0x%x",
1233                         i, c->decode_callback[i].callback_mutex);
1234                     DEBUG("Case#1 c->decode_callback[i].dataSyncDesc 0x%x dataSyncDesc 0x%x", c->decode_callback[i].dataSyncDesc, dataSyncDesc);
1235                     // Copy the local structure as H264D_PutDataFxn has already stored codec partial decoded data.
1236                     dataSyncDesc->size = (c->decode_callback[i].dataSyncDesc)->size;
1237                     dataSyncDesc->scatteredBlocksFlag = (c->decode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
1238                     dataSyncDesc->baseAddr = (c->decode_callback[i].dataSyncDesc)->baseAddr;
1239                     dataSyncDesc->numBlocks = (c->decode_callback[i].dataSyncDesc)->numBlocks;
1240                     dataSyncDesc->varBlockSizesFlag = (c->decode_callback[i].dataSyncDesc)->varBlockSizesFlag;
1241                     dataSyncDesc->blockSizes = (c->decode_callback[i].dataSyncDesc)->blockSizes;
1243                     (c->decode_callback[i].putdata_toclient)++;
1244                     pthread_mutex_unlock(&(c->decode_callback[i].callback_mutex));
1246                     dce_clean(dataSyncDesc);
1247                     return (0);
1248                 } else if ((c->decode_callback[i].codec_request) && (c->decode_callback[i].putdata_toclient)) {
1249                     // Check if put_data_toclient are set; Otherwise send the data to MPU.
1250                     DEBUG("MPU has received the earlier put_DataFxn from codec on 0x%x", c->decode_codec[i]);
1251                     (c->decode_callback[i].putdata_toclient)--;
1252                     DEBUG("Signal thread H264D_PutDataFxn to continue");
1253                     pthread_cond_signal(&(c->decode_callback[i].synch_callback));
1254                     // After signaling H264D_PutDataFxn, it needs to wait for the new data to be returned by codec.
1255                 }
1257                 // We received put_DataFxn from client, need to wait for data from codec through H264D_PutDataFxn before continuing
1258                 c->decode_callback[i].putdata_ready = 1;
1259                 DEBUG("Case#2 put_DataFxn is received. Wait for H264D_PutDataFxn to come; set putdata_ready = 1 c->decode_callback[%d].callback_mutex 0x%x", i, c->decode_callback[i].callback_mutex);
1260                 DEBUG("Case#2 c->decode_callback[i].dataSyncDesc 0x%x dataSyncDesc 0x%x", c->decode_callback[i].dataSyncDesc, dataSyncDesc);
1261                 pthread_cond_wait(&(c->decode_callback[i].synch_callback), &(c->decode_callback[i].callback_mutex));
1263                 DEBUG("put_DataFxn FINALLY gets H264D_PutDataFxn, and the data has been provided, continue.");
1264                 // Signal is received; check if it is from VIDDEC3_process or from H264D_PutDataFxn
1265                 if (c->decode_callback[i].putData_endprocess ) {
1266                     dataSyncDesc->numBlocks = 0;  // To be returned to MPU side which will be ignored.
1267                 } else {
1268                     // Copy the local structure as H264D_PutDataFxn has already stored codec partial decoded data to be sent to MPU side.
1269                     dataSyncDesc->size = (c->decode_callback[i].dataSyncDesc)->size;
1270                     dataSyncDesc->scatteredBlocksFlag = (c->decode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
1271                     dataSyncDesc->baseAddr = (c->decode_callback[i].dataSyncDesc)->baseAddr;
1272                     dataSyncDesc->numBlocks = (c->decode_callback[i].dataSyncDesc)->numBlocks;
1273                     dataSyncDesc->varBlockSizesFlag = (c->decode_callback[i].dataSyncDesc)->varBlockSizesFlag;
1274                     dataSyncDesc->blockSizes = (c->decode_callback[i].dataSyncDesc)->blockSizes;
1275                 }
1276                 c->decode_callback[i].putdata_ready = 0;
1277                 // After resetting putdata_ready to 0, this function will return to MPU
1278                 DEBUG("From client dataSyncDesc->size %d ", dataSyncDesc->size);
1279                 DEBUG("From client dataSyncDesc->scatteredBlocksFlag %d ", dataSyncDesc->scatteredBlocksFlag);
1280                 DEBUG("From client dataSyncDesc->baseAddr %d ", dataSyncDesc->baseAddr);
1281                 DEBUG("From client dataSyncDesc->numBlocks %d ", dataSyncDesc->numBlocks);
1282                 DEBUG("From client dataSyncDesc->varBlockSizesFlag %d ", dataSyncDesc->varBlockSizesFlag);
1283                 DEBUG("From client dataSyncDesc->blockSizes %d ", dataSyncDesc->blockSizes);
1285                 (c->decode_callback[i].putdata_toclient)++;
1286                 pthread_mutex_unlock(&(c->decode_callback[i].callback_mutex));
1287             }
1288         }
1289     }
1291     dce_clean(dataSyncDesc);
1292     return (0);
1295 static int get_BufferFxn(UInt32 size, UInt32 *data)
1297     return (0);
1301 /* the server create parameters, must be in persistent memory */
1302 static RcmServer_Params    rpc_Params;
1304 /* DCE Server skel function array */
1305 static RcmServer_FxnDesc    DCEServerFxnAry[] =
1307     { "engine_open",     (RcmServer_MsgFxn) engine_open },
1308     { "engine_close",    (RcmServer_MsgFxn) engine_close },
1309     { "codec_create",    (RcmServer_MsgFxn) codec_create },
1310     { "codec_control",    (RcmServer_MsgFxn) codec_control },
1311     { "codec_get_version",    (RcmServer_MsgFxn) codec_get_version },
1312     { "codec_process",   (RcmServer_MsgFxn) codec_process },
1313     { "codec_delete",    (RcmServer_MsgFxn) codec_delete },
1314     { "get_rproc_info", (RcmServer_MsgFxn) get_rproc_info }
1316 };
1318 /* DCE Server skel function table */
1319 #define DCEServerFxnAryLen (sizeof(DCEServerFxnAry) / sizeof(DCEServerFxnAry[0]))
1321 static const RcmServer_FxnDescAry    DCEServer_fxnTab =
1323     DCEServerFxnAryLen,
1324     DCEServerFxnAry
1325 };
1327 static MmType_FxnSig    DCEServer_sigAry[] =
1329     { "engine_open", 2,
1330       {
1331           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1332           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1333       } },
1334     { "engine_close", 2,
1335       {
1336           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1337           { MmType_Dir_In, MmType_Param_U32, 1 }
1338       } },
1339     { "codec_create", 5,
1340       {
1341           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1342           { MmType_Dir_In, MmType_Param_U32, 1 },
1343           { MmType_Dir_In, MmType_Param_U32, 1 },
1344           { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 },
1345           { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 }
1346       } },
1347     { "codec_control", 6,
1348       {
1349           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1350           { MmType_Dir_In, MmType_Param_U32, 1 },
1351           { MmType_Dir_In, MmType_Param_U32, 1 },
1352           { MmType_Dir_In, MmType_Param_U32, 1 },
1353           { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 },
1354           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1355       } },
1356     { "codec_get_version", 5,
1357       {
1358           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1359           { MmType_Dir_In, MmType_Param_U32, 1 },
1360           { MmType_Dir_In, MmType_Param_U32, 1 },
1361           { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 },
1362           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1363       } },
1364     { "codec_process", 7,
1365       {
1366           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1367           { MmType_Dir_In, MmType_Param_U32, 1 },
1368           { MmType_Dir_In, MmType_Param_U32, 1 },
1369           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },
1370           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },
1371           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },
1372           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1373       } },
1374     { "codec_delete", 3,
1375       {
1376           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1377           { MmType_Dir_In, MmType_Param_U32, 1 },
1378           { MmType_Dir_In, MmType_Param_U32, 1 }
1379       } },
1380     { "get_rproc_info", 2,
1381       {
1382          { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1383           { MmType_Dir_In, MmType_Param_U32, 1 }
1384       } }
1386 };
1388 static MmType_FxnSigTab    dce_fxnSigTab =
1390     MmType_NumElem(DCEServer_sigAry), DCEServer_sigAry
1391 };
1393 /* DCE Callback Server skel function array */
1394 static RcmServer_FxnDesc    DCECallbackServerFxnAry[] =
1396     { "get_DataFxn",     (RcmServer_MsgFxn) get_DataFxn },
1397     { "put_DataFxn",     (RcmServer_MsgFxn) put_DataFxn },
1398     { "get_BufferFxn",   (RcmServer_MsgFxn) get_BufferFxn }
1399 };
1401 #define DCECallbackServerFxnAryLen (sizeof(DCECallbackServerFxnAry) / sizeof(DCECallbackServerFxnAry[0]))
1403 static const RcmServer_FxnDescAry    DCECallbackServer_fxnTab =
1405     DCECallbackServerFxnAryLen,
1406     DCECallbackServerFxnAry
1407 };
1409 static MmType_FxnSig    DCECallbackServer_sigAry[] =
1411     { "get_DataFxn", 3,
1412       {
1413           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1414           { MmType_Dir_In, MmType_Param_U32, 1 },
1415           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1416       } },
1417     { "put_DataFxn", 3,
1418       {
1419           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1420           { MmType_Dir_In, MmType_Param_U32, 1 },
1421           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1422       } },
1423     { "get_BufferFxn", 3,
1424       {
1425           { MmType_Dir_Out, MmType_Param_S32, 1 }, // return
1426           { MmType_Dir_In, MmType_Param_U32, 1 },
1427           { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }
1428       } }
1429 };
1431 static MmType_FxnSigTab    dce_callback_fxnSigTab =
1433     MmType_NumElem(DCECallbackServer_sigAry), DCECallbackServer_sigAry
1434 };
1436 Void dce_SrvDelNotification(Void)
1438     Client *c;
1439     int i;
1440     uint32_t mm_serv_id = 0;
1442     Semaphore_pend(sync_process_sem, BIOS_WAIT_FOREVER);
1444     DEBUG("dce_SrvDelNotification: cleanup existing codec and engine\n");
1446     mm_serv_id = MmServiceMgr_getId();
1447     DEBUG("cleanup: mm_serv_id=0x%x", mm_serv_id);
1449     c = get_client(mm_serv_id);
1450     if( c ) {
1451         DEBUG("cleanup: mm_serv_id=0x%x c=%p c->refs=%d", mm_serv_id, c, c->refs);
1453         /* For low latency instance, need to trigger the flag to callback function so that it will return full numblock*/
1454         for( i = 0; i < DIM(c->decode_codec); i++ ) {
1455             if (c->decode_callback[i].row_mode) {
1456                 DEBUG("Setting c->decode_callback[%d].mpu_crash_indication = TRUE c->decode_codec[%d].callback_mutex 0x%x", i, i, c->decode_callback[i].callback_mutex);
1457                 c->decode_callback[i].mpu_crash_indication = TRUE;
1458                 pthread_cond_signal(&(c->decode_callback[i].synch_callback));
1459             }
1460         }
1462         for( i = 0; i < DIM(c->encode_codec); i++ ) {
1463             if (c->encode_callback[i].row_mode) {
1464                 DEBUG("Setting c->encode_callback[%d].mpu_crash_indication = TRUE c->encode_codec[%d].callback_mutex 0x%x", i, i, c->encode_callback[i].callback_mutex);
1465                 c->encode_callback[i].mpu_crash_indication = TRUE;
1466                 pthread_cond_signal(&(c->encode_callback[i].synch_callback));
1467             }
1468         }
1470         /* Make sure IVAHD and SL2 are idle before proceeding */
1471         ivahd_idle_check();
1473         /* delete all codecs first */
1474         for( i = 0; i < DIM(c->decode_codec); i++ ) {
1475             DEBUG("dce_SrvDelNotification: test c->decode_codec[%d] 0x%x", i, c->decode_codec[i]);
1476             if( c->decode_codec[i] ) {
1477                 DEBUG("dce_SrvDelNotification: delete decoder codec handle 0x%x c->decode_callback[i] 0x%x c->decode_callback[i].row_mode %d\n",
1478                     c->decode_codec[i], c->decode_callback[i], c->decode_callback[i].row_mode);
1479                 if (c->decode_callback[i].row_mode) {
1480                     pthread_mutex_destroy(&(c->decode_callback[i].callback_mutex));
1481                     pthread_cond_destroy(&(c->decode_callback[i].synch_callback));
1482                     c->decode_callback[i].row_mode = 0;
1483                     c->decode_callback[i].mpu_crash_indication = FALSE;
1484                 }
1485                 codec_fxns[OMAP_DCE_VIDDEC3].delete((void *)c->decode_codec[i]);
1486                 c->decode_codec[i] = NULL;
1487             }
1488         }
1490         for( i = 0; i < DIM(c->encode_codec); i++ ) {
1491             DEBUG("dce_SrvDelNotification: test c->encode_codec[%d] 0x%x", i, c->encode_codec[i]);
1492             if( c->encode_codec[i] ) {
1493                 DEBUG("dce_SrvDelNotification: delete encoder codec handle 0x%x c->encode_callback[i] 0x%x \n",
1494                     c->encode_codec[i], c->encode_callback[i]);
1495                 if (c->encode_callback[i].row_mode) {
1496                     pthread_mutex_destroy(&(c->encode_callback[i].callback_mutex));
1497                     pthread_cond_destroy(&(c->encode_callback[i].synch_callback));
1498                     c->encode_callback[i].row_mode = 0;
1499                     c->encode_callback[i].mpu_crash_indication = FALSE;
1500                 }
1501                 codec_fxns[OMAP_DCE_VIDENC2].delete((void *)c->encode_codec[i]);
1502                 c->encode_codec[i] = NULL;
1503             }
1504         }
1506         /* and lastly close all engines */
1507         for( i = 0; i < DIM(c->engines); i++ ) {
1508             if( c->engines[i] ) {
1509                 DEBUG("dce_SrvDelNotification: delete Engine handle 0x%x\n", c->engines[i]);
1510                 Engine_close(c->engines[i]);
1511                 c->engines[i] = NULL;
1512                 DEBUG("dce_SrvDelNotification engine_close: %p refs=%d", c, c->refs);
1513                 c->refs--;
1514             }
1515         }
1517         if( !c->refs ) {
1518             c->mm_serv_id = NULL;
1519         }
1520     }
1521     DEBUG("dce_SrvDelNotification: COMPLETE exit function \n");
1523     Semaphore_post(sync_process_sem);
1526 Void dceCallback_SrvDelNotification(Void)
1528     System_printf("dceCallback_SrvDelNotification - call dce_SrvDelNotification to clean up\n");
1531 /*
1532  * dce_main : main function for dce-server thread.
1533  * Registering to MmServiceMgr.
1534  */
1535 static void dce_main(uint32_t arg0, uint32_t arg1)
1537     int            err = 0;
1538     dce_connect    dce_connect_msg;
1540     /* Read the register for ID_CODE to figure out the correct configuration: */
1541     /* CONTROL_STD_FUSE_ID_CODE[31:0] ID_CODE STD_FUSE_IDCODE */
1542     /* physical address: 0x4A00 2204 Address offset: 0x204                       */
1543 #ifdef OMAP5430_ES10
1544     dce_connect_msg.chipset_id = 0x5430;
1545 #elif OMAP5432_ES20
1546     dce_connect_msg.chipset_id = 0x5432;
1547 #elif VAYU_ES10
1548     dce_connect_msg.chipset_id = 0x5436;
1549 #endif
1550     dce_connect_msg.debug = dce_debug;
1551     connect(&dce_connect_msg);
1553     err = MmServiceMgr_init();  // MmServiceMgr_init() will always return MmServiceMgr_S_SUCCESS.
1555     // setup the RCM Server create params
1556     RcmServer_Params_init(&rpc_Params);
1557     rpc_Params.priority = Thread_Priority_ABOVE_NORMAL;
1558     rpc_Params.stackSize = 0x1000;
1559     rpc_Params.fxns.length = DCEServer_fxnTab.length;
1560     rpc_Params.fxns.elem = DCEServer_fxnTab.elem;
1562     DEBUG("REGISTER %s\n", SERVER_NAME);
1564     // Get the Service Manager handle
1565     err = MmServiceMgr_register(SERVER_NAME, &rpc_Params, &dce_fxnSigTab, dce_SrvDelNotification);
1566     if( err < 0 ) {
1567         DEBUG("failed to start " SERVER_NAME " \n");
1568     } else {
1569         DEBUG(SERVER_NAME " running through MmServiceMgr");
1570     }
1572     MmServiceMgr_exit();
1574     DEBUG("deleted " SERVER_NAME);
1576     return;
1579 /*
1580  * dce_callback_main : main function for dce-callback-server thread.
1581  * Registering to MmServiceMgr.
1582  */
1584 static void dce_callback_main(uint32_t arg0, uint32_t arg1)
1586     int            err = 0;
1588     err = MmServiceMgr_init();  // MmServiceMgr_init() will always return MmServiceMgr_S_SUCCESS.
1590     // setup the RCM Server create params
1591     RcmServer_Params_init(&rpc_Params);
1592     rpc_Params.priority = Thread_Priority_ABOVE_NORMAL;
1593     rpc_Params.stackSize = 0x1000;
1594     rpc_Params.fxns.length = DCECallbackServer_fxnTab.length;
1595     rpc_Params.fxns.elem = DCECallbackServer_fxnTab.elem;
1597     DEBUG("REGISTER %s\n", CALLBACK_SERVER_NAME);
1599     // Get the Service Manager handle
1600     err = MmServiceMgr_register(CALLBACK_SERVER_NAME, &rpc_Params, &dce_callback_fxnSigTab, dceCallback_SrvDelNotification);
1601     if( err < 0 ) {
1602         DEBUG("failed to start " CALLBACK_SERVER_NAME " \n");
1603     } else {
1604         DEBUG(CALLBACK_SERVER_NAME " running through MmServiceMgr");
1605     }
1607     MmServiceMgr_exit();
1609     DEBUG("deleted " CALLBACK_SERVER_NAME);
1611     return;
1615 /*
1616   * dce init : Startup Function
1617   */
1618 Bool dce_init(void)
1620     Task_Params    params;
1621     Task_Params    callback_params;
1622     Semaphore_Params semParams;
1624     INFO("Creating DCE server and DCE callback server thread...");
1626     /* Create DCE task. */
1627     Task_Params_init(&params);
1628     params.instance->name = "dce-server";
1629     params.priority = Thread_Priority_ABOVE_NORMAL;
1630     Task_create(dce_main, &params, NULL);
1632     /* Create DCE callback task. */
1633     Task_Params_init(&callback_params);
1634     callback_params.instance->name = "dce-callback-server";
1635     callback_params.priority = Thread_Priority_ABOVE_NORMAL;
1636     Task_create(dce_callback_main, &callback_params, NULL);
1638     Semaphore_Params_init(&semParams);
1639     semParams.mode = Semaphore_Mode_BINARY;
1640     sync_process_sem = Semaphore_create(1, &semParams, NULL);
1642     return (TRUE);
1645 /*
1646   * dce deinit
1647   */
1649 void dce_deinit(void)
1651     DEBUG("dce_deinit");
1653     Semaphore_delete(&sync_process_sem);
1656 /*
1657  * H264E_GetDataFxn
1658  * This is callback function provided for IVA-HD codec to callback for more input data.
1659  * This function syncs with get_DataFxn which handles the required data from the MPU side.
1660  * It will continue if DCE Server has received get_DataFxn from MPU side otherwise it will
1661  * wait until DCE server receive get_DataFxn.
1662  */
1663 XDM_DataSyncGetFxn H264E_GetDataFxn(XDM_DataSyncHandle dataSyncHandle,
1664     XDM_DataSyncDesc *dataSyncDesc)
1666     Client* c;
1668     dce_inv(dataSyncDesc);
1670     DEBUG("********************H264E_GetDataFxn START*************************** dataSyncHandle 0x%x",
1671         dataSyncHandle);
1672     c = get_client_instance((Uint32) dataSyncHandle);
1673     if (c) {
1674         int i;
1675         for (i = 0; i < DIM(c->encode_codec); i++) {
1676             if (c->encode_codec[i] == dataSyncHandle) {
1677                 pthread_mutex_lock(&(c->encode_callback[i].callback_mutex));
1678                 DEBUG("H264E_GetDataFxn dataSyncHandle 0x%x c->encode_callback[%d].callback_mutex 0x%x", dataSyncHandle, i, c->encode_callback[i].callback_mutex);
1679                 // Check if H264E_GetDataFxn from codec and get_DataFxn from MPU side. Which comes first.
1680                 // Check if MPU has crashed c->encode_callback[i].mpu_crash_indication, if it is then send the highest numBlock to codec so that VIDENC2_process will be returned and IVA back to IDLE.
1681                 if (c->encode_callback[i].mpu_crash_indication) {
1682                     // Since MPU has crashed, need to send the numBlocks to codec so that VIDENC2_process can be returned and IVA back to IDLE.
1683                     // Send the numBlocks as expected max value or add functionality to count up to proper numBlocks to be returned to codec.
1684                     // Current implementation will send arbitrary value 100 numBlocks (height resolution 1600) which will let codec return the process call and move IVA into IDLE state.
1685                     DEBUG("MPU has crashed, send arbitrary numBlocks 100 so that VIDENC2_process will be returned");
1686                     dataSyncDesc->size = sizeof(XDM_DataSyncDesc);
1687                     dataSyncDesc->scatteredBlocksFlag = 0;
1688                     dataSyncDesc->baseAddr = 0;
1689                     dataSyncDesc->numBlocks = 100;
1690                     dataSyncDesc->varBlockSizesFlag = 0;
1691                     dataSyncDesc->blockSizes = 0;
1692                 } else {
1693                     if (c->encode_callback[i].getdata_ready) {
1694                         // Already have data to be passed to codec
1695                         DEBUG("H264E_GetDataFxn Case#2 c->encode_callback[%d].dataSyncHandle 0x%x c->encode_callback[%d].dataSyncDesc 0x%x",
1696                             i, c->encode_callback[i].dataSyncHandle, i, c->encode_callback[i].dataSyncDesc);
1697                         if (dataSyncHandle == c->encode_callback[i].dataSyncHandle) {
1698                             dataSyncDesc->size = (c->encode_callback[i].dataSyncDesc)->size;
1699                             dataSyncDesc->scatteredBlocksFlag = (c->encode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
1700                             dataSyncDesc->baseAddr = (c->encode_callback[i].dataSyncDesc)->baseAddr;
1701                             dataSyncDesc->numBlocks = (c->encode_callback[i].dataSyncDesc)->numBlocks;
1702                             dataSyncDesc->varBlockSizesFlag = (c->encode_callback[i].dataSyncDesc)->varBlockSizesFlag;
1703                             dataSyncDesc->blockSizes = (c->encode_callback[i].dataSyncDesc)->blockSizes;
1704                         }
1706                         // Order get_DataFxn to continue request to MPU client side for more data as it is currently pending.
1707                         pthread_cond_signal(&(c->encode_callback[i].synch_callback));
1708                     } else {
1709                         c->encode_callback[i].codec_request = 1;
1711                         DEBUG("H264E_GetDataFxn wait Case#1");
1712                         // Wait until get_DataFxn is received from MPU client side. Need the information to be passed to codec as currently not available.
1713                         pthread_cond_wait(&(c->encode_callback[i].synch_callback), &(c->encode_callback[i].callback_mutex));
1715                         // Once get_DataFxn is received from MPU side continue by providing it to IVA-HD codec.
1716                         DEBUG("H264E_GetDataFxn Case#1 c->encode_callback[%d].dataSyncHandle 0x%x c->encode_callback[%d].dataSyncDesc 0x%x",
1717                             i, c->encode_callback[i].dataSyncHandle, i, c->encode_callback[i].dataSyncDesc);
1718                         if (dataSyncHandle == c->encode_callback[i].dataSyncHandle) {
1719                             dataSyncDesc->size = (c->encode_callback[i].dataSyncDesc)->size;
1720                             dataSyncDesc->scatteredBlocksFlag = (c->encode_callback[i].dataSyncDesc)->scatteredBlocksFlag;
1721                             dataSyncDesc->baseAddr = (c->encode_callback[i].dataSyncDesc)->baseAddr;
1722                             dataSyncDesc->numBlocks = (c->encode_callback[i].dataSyncDesc)->numBlocks;
1723                             dataSyncDesc->varBlockSizesFlag = (c->encode_callback[i].dataSyncDesc)->varBlockSizesFlag;
1724                             dataSyncDesc->blockSizes = (c->encode_callback[i].dataSyncDesc)->blockSizes;
1725                         }
1726                         c->encode_callback[i].codec_request = 0;
1727                     }
1728                 }
1729                 pthread_mutex_unlock(&(c->encode_callback[i].callback_mutex));
1730             }
1731         }
1732     }
1734     DEBUG("********************H264E_GetDataFxn END*************************** dataSyncHandle 0x%x", dataSyncHandle);
1735     dce_clean(dataSyncDesc);
1736     return (0);
1739 /*
1740  * H264D_PutDataFxn
1741  * This is callback function provided for IVA-HD codec to callback for notifying client on partial decoded output.
1742  * This function syncs with put_DataFxn which handles passing the data from codec to the MPU side.
1743  * Once this callback is received from IVA-HD codec, it will save the codec partial decoded data into local structure
1744  * for put_DataFxn to pick up.
1745  * If DCE server has already receive put_DataFxn (putdata_ready == 1), then it notifies through semaphore_post to continue.
1746  * If DCE server is waiting for put_DataFxn, then it will set codec_request = 1, and wait through semaphore_pend.
1747  */
1748 XDM_DataSyncPutFxn H264D_PutDataFxn(XDM_DataSyncHandle dataSyncHandle,
1749     XDM_DataSyncDesc *dataSyncDesc)
1751     Client* c;
1753     dce_inv(dataSyncDesc);
1754     DEBUG("********************H264D_PutDataFxn START*************************** dataSyncHandle 0x%x dataSyncDesc->numBlocks %d",
1755         dataSyncHandle, dataSyncDesc->numBlocks);
1757     c = get_client_instance((Uint32) dataSyncHandle);
1758     if (c) {
1759         int i;
1760         for (i = 0; i < DIM(c->decode_codec); i++) {
1761             if (c->decode_codec[i] == dataSyncHandle) {
1762                 pthread_mutex_lock(&(c->decode_callback[i].callback_mutex));
1763                 DEBUG("H264D_PutDataFxn dataSyncHandle 0x%x c->decode_codec[%d].callback_mutex 0x%x", dataSyncHandle, i, c->decode_callback[i].callback_mutex);
1764                 c->decode_callback[i].codec_request = 1;
1765                 // Save the data from IVA-HD codec into local structure for put_DataFxn to pick up.
1766                 if (dataSyncHandle == c->decode_callback[i].dataSyncHandle) {
1767                     (c->decode_callback[i].dataSyncDesc)->size = dataSyncDesc->size;
1768                     (c->decode_callback[i].dataSyncDesc)->scatteredBlocksFlag = dataSyncDesc->scatteredBlocksFlag;
1769                     (c->decode_callback[i].dataSyncDesc)->baseAddr = dataSyncDesc->baseAddr;
1770                     (c->decode_callback[i].dataSyncDesc)->numBlocks = dataSyncDesc->numBlocks;
1771                     (c->decode_callback[i].dataSyncDesc)->varBlockSizesFlag = dataSyncDesc->varBlockSizesFlag;
1772                     (c->decode_callback[i].dataSyncDesc)->blockSizes = dataSyncDesc->blockSizes;
1773                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->size %d ", i, (c->decode_callback[i].dataSyncDesc)->size);
1774                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->scatteredBlocksFlag %d ", i, (c->decode_callback[i].dataSyncDesc)->scatteredBlocksFlag);
1775                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->baseAddr %d ", i, (c->decode_callback[i].dataSyncDesc)->baseAddr);
1776                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->numBlocks %d ", i, (c->decode_callback[i].dataSyncDesc)->numBlocks);
1777                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->varBlockSizesFlag %d ", i, (c->decode_callback[i].dataSyncDesc)->varBlockSizesFlag);
1778                     DEBUG("From Codec (c->decode_callback[%d].dataSyncDesc)->blockSizes %d ", i, (c->decode_callback[i].dataSyncDesc)->blockSizes);
1779                 }
1781                 // If MPU has crashed, there is no way MPU will respond after this. Let codec thinking that MPU has received the numblock. Don't wait, just returned.
1782                 if (!(c->decode_callback[i].mpu_crash_indication)) {
1783                     // MPU is alive. Wait until the put_DataFxn is received from MPU side. Codec has callback with partial decoded data but put_DataFxn is not received yet.
1784                     // Check if put_DataFxn from MPU side has come before H264D_PutDataFxn.
1785                     if (c->decode_callback[i].putdata_ready) {
1786                         // Already receive request from client for partial decoded output information from codec.
1787                         // Order put_DataFxn to continue sending codec partial decoded data in the local structure to MPU side.
1788                         DEBUG("H264D_PutDataFxn Case#2 c->decode_callback[%d].dataSyncHandle 0x%x c->decode_callback[%d].dataSyncDesc 0x%x",
1789                             i, c->decode_callback[i].dataSyncHandle, i, c->decode_callback[i].dataSyncDesc);
1791                         // After storing the data from codec, send thread signal conditional for put_DataFxn to continue passing the codec data to MPU.
1792                         pthread_cond_signal(&(c->decode_callback[i].synch_callback));
1794                         DEBUG("H264D_PutDataFxn Case#2 wait on pthread_cond_wait");
1795                         // After signal put_DataFxn, needs to wait for put_DataFxn return from A15 before returning to codec.
1796                         pthread_cond_wait(&(c->decode_callback[i].synch_callback), &(c->decode_callback[i].callback_mutex));
1797                     } else {
1798                         DEBUG("H264D_PutDataFxn Case#1 wait on pthread_cond_wait c->decode_codec[%d].callback_mutex 0x%x", i, c->decode_callback[i].callback_mutex);
1799                         pthread_cond_wait(&(c->decode_callback[i].synch_callback), &(c->decode_callback[i].callback_mutex));
1800                     }
1801                 }
1802                 c->decode_callback[i].codec_request = 0;
1803                 pthread_mutex_unlock(&(c->decode_callback[i].callback_mutex));
1804             }
1805         }
1806     }
1808     DEBUG("********************H264D_PutDataFxn END*************************** dataSyncHandle 0x%x", dataSyncHandle);
1809     dce_clean(dataSyncDesc);
1810     return (0);