62bea8cf70b08fc7fff52a1e3cc11bcc3ff63d44
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)
153 {
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;
161 }
163 static inline Client * get_client_instance(Uint32 codec)
164 {
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;
180 }
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[] =
189 {
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()
220 {
221 INFO("Preparing for suspend...");
222 FC_suspend();
223 }
225 static void dce_resume()
226 {
227 INFO("Restoring after suspend...");
228 FC_resume();
229 }
231 static void get_videnc2_version(VIDENC2_Handle h, char *buffer, unsigned size)
232 {
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, ¶ms, &status);
253 if( s != VIDENC2_EOK ) {
254 ERROR("Unknown version Error = %d:: buffer = %p size = %d", s, buffer, size);
255 }
256 }
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)
260 {
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);
271 }
273 static XDAS_Int32 getBufferFxnStub(XDM_DataSyncHandle handle, XDM_DataSyncDesc *desc)
274 {
275 return (0);
276 }
278 static XDAS_Int32 videnc2_control(VIDENC2_Handle codec, VIDENC2_Cmd id,
279 VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status)
280 {
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));
302 }
304 static void get_viddec3_version(VIDDEC3_Handle h, char *buffer, unsigned size)
305 {
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, ¶ms, &status);
326 if( s != VIDDEC3_EOK ) {
327 ERROR("Unknown version Error = %d:: buffer = %p size = %d", s, buffer, size);
328 }
329 }
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)
333 {
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);
347 }
349 static XDAS_Int32 viddec3_control(VIDDEC3_Handle codec,VIDDEC3_Cmd id,VIDDEC3_DynamicParams * dynParams,VIDDEC3_Status * status)
350 {
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));
373 }
375 static XDAS_Int32 viddec3_process(VIDDEC3_Handle codec, XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs)
376 {
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));
401 }
403 static int videnc2_reloc(VIDENC2_Handle handle, uint8_t *ptr, uint32_t len)
404 {
405 return (-1); // Not implemented
406 }
408 /* Only valid if XDM_MOVEBUFS added in XDC tools */
409 static int viddec3_reloc(VIDDEC3_Handle handle, uint8_t *ptr, uint32_t len)
410 {
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, ¶ms, &status));
428 #endif
429 }
431 /*
432 * RPC message handlers
433 */
434 static int connect(void *msg)
435 {
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);
470 }
472 static Int32 dce_register_engine(Uint32 mm_serv_id, Engine_Handle engine)
473 {
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;
519 }
521 static void dce_unregister_engine(Uint32 mm_serv_id, Engine_Handle engine)
522 {
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 }
551 }
553 static Int32 dce_register_codec(Uint32 type, Uint32 mm_serv_id, Uint32 codec)
554 {
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;
606 }
608 static void dce_unregister_codec(Uint32 type, Uint32 mm_serv_id, Uint32 codec)
609 {
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 }
636 }
638 /*
639 * Engine_open:
640 */
641 static Int32 engine_open(UInt32 size, UInt32 *data)
642 {
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);
680 }
682 /*
683 * Engine_close:
684 */
685 static Int32 engine_close(UInt32 size, UInt32 *data)
686 {
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);
712 }
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)
720 {
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;
748 }
752 /*
753 * codec_create
754 */
755 static Int32 codec_create(UInt32 size, UInt32 *data)
756 {
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);
856 }
858 /*
859 * codec_control
860 */
861 static int codec_control(UInt32 size, UInt32 *data)
862 {
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);
898 }
900 /*
901 * codec get version
902 */
903 static int codec_get_version(UInt32 size, UInt32 *data)
904 {
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);
947 }
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)
1017 {
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);
1067 }
1069 /*
1070 * codec delete
1071 */
1073 static int codec_delete(UInt32 size, UInt32 *data)
1074 {
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);
1145 }
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)
1153 {
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);
1199 }
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)
1207 {
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);
1293 }
1295 static int get_BufferFxn(UInt32 size, UInt32 *data)
1296 {
1297 return (0);
1298 }
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[] =
1306 {
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 =
1322 {
1323 DCEServerFxnAryLen,
1324 DCEServerFxnAry
1325 };
1327 static MmType_FxnSig DCEServer_sigAry[] =
1328 {
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 =
1389 {
1390 MmType_NumElem(DCEServer_sigAry), DCEServer_sigAry
1391 };
1393 /* DCE Callback Server skel function array */
1394 static RcmServer_FxnDesc DCECallbackServerFxnAry[] =
1395 {
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 =
1404 {
1405 DCECallbackServerFxnAryLen,
1406 DCECallbackServerFxnAry
1407 };
1409 static MmType_FxnSig DCECallbackServer_sigAry[] =
1410 {
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 =
1432 {
1433 MmType_NumElem(DCECallbackServer_sigAry), DCECallbackServer_sigAry
1434 };
1436 Void dce_SrvDelNotification(Void)
1437 {
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);
1524 }
1526 Void dceCallback_SrvDelNotification(Void)
1527 {
1528 System_printf("dceCallback_SrvDelNotification - call dce_SrvDelNotification to clean up\n");
1529 }
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)
1536 {
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;
1577 }
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)
1585 {
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;
1612 }
1615 /*
1616 * dce init : Startup Function
1617 */
1618 Bool dce_init(void)
1619 {
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(¶ms);
1628 params.instance->name = "dce-server";
1629 params.priority = Thread_Priority_ABOVE_NORMAL;
1630 Task_create(dce_main, ¶ms, 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);
1643 }
1645 /*
1646 * dce deinit
1647 */
1649 void dce_deinit(void)
1650 {
1651 DEBUG("dce_deinit");
1653 Semaphore_delete(&sync_process_sem);
1654 }
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)
1665 {
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);
1737 }
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)
1750 {
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);
1811 }