1 /*\r
2 * Copyright (c) 2011, Texas Instruments Incorporated\r
3 * All rights reserved.\r
4 *\r
5 * Redistribution and use in source and binary forms, with or without\r
6 * modification, are permitted provided that the following conditions\r
7 * are met:\r
8 *\r
9 * * Redistributions of source code must retain the above copyright\r
10 * notice, this list of conditions and the following disclaimer.\r
11 *\r
12 * * Redistributions in binary form must reproduce the above copyright\r
13 * notice, this list of conditions and the following disclaimer in the\r
14 * documentation and/or other materials provided with the distribution.\r
15 *\r
16 * * Neither the name of Texas Instruments Incorporated nor the names of\r
17 * its contributors may be used to endorse or promote products derived\r
18 * from this software without specific prior written permission.\r
19 *\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31 */\r
32 \r
33 #include <stdlib.h>\r
34 #include <stdint.h>\r
35 #include <string.h>\r
36 #include <stdio.h>\r
37 #include <ti/grcm/RcmServer.h>\r
38 #include <ti/grcm/RcmTypes.h>\r
39 #include <ti/ipc/mm/MmServiceMgr.h>\r
40 #include <ti/ipc/mm/MmRpc.h>\r
41 #include <ti/ipc/MultiProc.h>\r
42 #include <ti/ipc/rpmsg/RPMessage.h>\r
43 #include <ti/ipc/rpmsg/NameMap.h>\r
44 #include <ti/pm/IpcPower.h>\r
45 #include <ti/sdo/ce/global/CESettings.h>\r
46 #include <ti/sdo/ce/CERuntime.h>\r
47 #include <ti/sdo/ce/Engine.h>\r
48 #include <ti/sdo/ce/video2/viddec2.h>\r
49 #include <ti/sdo/ce/universal/universal.h>\r
50 #include <ti/sdo/fc/global/FCSettings.h>\r
51 #include <ti/sdo/fc/utils/fcutils.h>\r
52 #include <ti/sysbios/BIOS.h>\r
53 #include <ti/sysbios/hal/Cache.h>\r
54 #include <ti/sysbios/knl/Task.h>\r
55 #include <ti/xdais/dm/xdm.h>\r
56 #include <xdc/cfg/global.h>\r
57 #include <xdc/runtime/System.h>\r
58 #include <xdc/runtime/Diags.h>\r
59 #include <xdc/runtime/Memory.h>\r
60 #include <xdc/runtime/IHeap.h>\r
61 #include <xdc/runtime/knl/Thread.h>\r
62 #include <xdc/std.h>\r
63 \r
64 #include "dce_priv.h"\r
65 #include "dce_rpc.h"\r
66 \r
67 static uint32_t suspend_initialised = 0;\r
68 uint32_t dce_debug = DCE_DEBUG_LEVEL;\r
69 \r
70 #define SERVER_NAME "rpmsg-dce-dsp"\r
71 #define MEMORYSTATS_DEBUG\r
72 \r
73 #define MmRpc_NUM_PARAMETERS(size) \\r
74 (size / sizeof(MmType_Param))\r
75 \r
76 /* dce_inv, dce_clean needs to be modified to expect buffers */\r
77 /* without headers (relevant for GLP */\r
78 static void dce_inv(void *ptr)\r
79 {\r
80 if( ptr ) {\r
81 Cache_inv(ptr, P2H(ptr)->size, Cache_Type_ALL, TRUE);\r
82 }\r
83 }\r
84 \r
85 static void dce_clean(void *ptr)\r
86 {\r
87 if( ptr ) {\r
88 Cache_wbInv(ptr, P2H(ptr)->size, Cache_Type_ALL, TRUE);\r
89 }\r
90 }\r
91 \r
92 typedef void * (*CreateFxn)(Engine_Handle, String, void *);\r
93 typedef Int32 (*ControlFxn)(void *, int, void *, void *);\r
94 typedef Int32 (*ProcessFxn)(void *, void *, void *, void *, void *);\r
95 typedef Int32 (*RelocFxn)(void *, uint8_t *ptr, uint32_t len);\r
96 typedef void (*DeleteFxn)(void *);\r
97 \r
98 /* DCE Server static function declarations */\r
99 static Int32 engine_open(UInt32 size, UInt32 *data);\r
100 static Int32 engine_close(UInt32 size, UInt32 *data);\r
101 \r
102 /* VIDDEC2 Decoder Server static function declarations */\r
103 static VIDDEC2_Handle viddec2_create(Engine_Handle engine, String name, VIDDEC2_Params *params);\r
104 static int viddec2_reloc(VIDDEC2_Handle handle, uint8_t *ptr, uint32_t len); \r
105 static int viddec2_control(VIDDEC2_Handle handle, VIDDEC2_Cmd id, VIDDEC2_DynamicParams *dynParams, \r
106 VIDDEC2_Status *status );\r
107 static int viddec2_process(VIDDEC2_Handle handle, XDM1_BufDesc *inBufs,\r
108 XDM_BufDesc *outBufs, VIDDEC2_InArgs *inArgs, VIDDEC2_OutArgs *outArgs );\r
109 static int viddec2_delete(VIDDEC2_Handle handle); \r
110 \r
111 static struct {\r
112 CreateFxn create;\r
113 ControlFxn control;\r
114 ProcessFxn process;\r
115 DeleteFxn delete;\r
116 RelocFxn reloc; /* handle buffer relocation table */\r
117 } codec_fxns[] =\r
118 {\r
119 [OMAP_DCE_VIDDEC2] =\r
120 {\r
121 (CreateFxn)viddec2_create, (ControlFxn)viddec2_control,\r
122 (ProcessFxn)viddec2_process, (DeleteFxn)viddec2_delete,\r
123 (RelocFxn)viddec2_reloc,\r
124 },\r
125 };\r
126 \r
127 \r
128 /* Static version string buffer.\r
129 * Note: codec version can be large. For example, h264vdec needs more than\r
130 * 58 characters, or the query will fail. */\r
131 #define VERSION_SIZE 128\r
132 static char version_buffer[VERSION_SIZE];\r
133 \r
134 /* the following callbacks are needed for suspend/resume\r
135 * on the linux side.\r
136 * - FC_suspend() waits for all algorithms to get deactivated and\r
137 * and takes care of the resources acquired.\r
138 * - FC_resume() does nothing for now, but we add it just in case\r
139 * it gets populated in the future versions of framework components.\r
140 *\r
141 * Forced off mode during video decode/encode is not supported. */\r
142 #if 0 \r
143 static void dce_suspend()\r
144 {\r
145 INFO("Preparing for suspend...");\r
146 FC_suspend();\r
147 }\r
148 \r
149 static void dce_resume()\r
150 {\r
151 INFO("Restoring after suspend...");\r
152 FC_resume();\r
153 }\r
154 #endif\r
155 \r
156 static void get_universal_version(UNIVERSAL_Handle h, char *buffer, unsigned size)\r
157 {\r
158 UNIVERSAL_DynamicParams params =\r
159 {\r
160 .size = sizeof(UNIVERSAL_DynamicParams),\r
161 };\r
162 \r
163 UNIVERSAL_Status status =\r
164 {\r
165 .size = sizeof(UNIVERSAL_Status),\r
166 .data =\r
167 {\r
168 .numBufs = 1,\r
169 .descs[0].buf = (XDAS_Int8 *)buffer,\r
170 .descs[0].bufSize = (XDAS_Int32)size,\r
171 },\r
172 };\r
173 \r
174 XDAS_Int32 s;\r
175 \r
176 memset(buffer, 0, size);\r
177 s = UNIVERSAL_control(h, XDM_GETVERSION, ¶ms, &status);\r
178 \r
179 if( s != IUNIVERSAL_EOK ) {\r
180 ERROR("Unknown version Error = %d:: buffer = %p size = %d", s, buffer, size);\r
181 }\r
182 }\r
183 \r
184 // VIDDEC2_create wrapper, to display version string in the trace.\r
185 static VIDDEC2_Handle viddec2_create(Engine_Handle engine, String name, VIDDEC2_Params *params)\r
186 {\r
187 UNIVERSAL_Handle h;\r
188 \r
189 DEBUG(">> engine=%08x, name=%s, params=%p", engine, name, params);\r
190 \r
191 h = UNIVERSAL_create(engine, name, (IUNIVERSAL_Params*)params);\r
192 \r
193 get_universal_version(h, version_buffer, VERSION_SIZE);\r
194 \r
195 INFO("Created codec %s: version %s", name, version_buffer);\r
196 \r
197 return ((VIDDEC2_Handle)h);\r
198 }\r
199 \r
200 /* needs to be updated when XDM_MOVEBUFS added in XDC tools */\r
201 static int viddec2_reloc(VIDDEC2_Handle handle, uint8_t *ptr, uint32_t len)\r
202 {\r
203 return (-1); // TODO\r
204 \r
205 }\r
206 \r
207 static int viddec2_control(VIDDEC2_Handle handle, VIDDEC2_Cmd id, VIDDEC2_DynamicParams *dynParams, \r
208 VIDDEC2_Status *status )\r
209 {\r
210 int ret = 0;\r
211 UNIVERSAL_DynamicParams udynParam;\r
212 UNIVERSAL_Status ustatus;\r
213 \r
214 udynParam.size = sizeof(UNIVERSAL_DynamicParams);\r
215 ustatus.size = sizeof(UNIVERSAL_Status);\r
216 //System_printf("command id is %d\n", id);\r
217 \r
218 if(id == XDM_GETVERSION){\r
219 ustatus.data.numBufs = 1;\r
220 ustatus.data.descs[0].buf = status->data.buf;\r
221 ustatus.data.descs[0].bufSize = status->data.bufSize;\r
222 }\r
223 \r
224 ret = UNIVERSAL_control((UNIVERSAL_Handle)handle, (UNIVERSAL_Cmd)id, \r
225 &udynParam, &ustatus);\r
226 \r
227 /*universal copy supports only XDM_GETVERSION cmd id */\r
228 /*This is to return success to VIDDEC2 application in case of other cmd ids */ \r
229 if(ret == IUNIVERSAL_EFAIL)ret = IUNIVERSAL_EOK;\r
230 \r
231 return ret;\r
232 }\r
233 \r
234 static int viddec2_process(VIDDEC2_Handle handle, XDM1_BufDesc *inBufs,\r
235 XDM_BufDesc *outBufs, VIDDEC2_InArgs *inArgs, VIDDEC2_OutArgs *outArgs )\r
236 { \r
237 int ret = 0;\r
238 XDM1_BufDesc inBuf, outBuf;\r
239 UNIVERSAL_InArgs inArg;\r
240 UNIVERSAL_OutArgs outArg;\r
241 \r
242 inArg.size = sizeof(UNIVERSAL_InArgs);\r
243 outArg.size = sizeof(UNIVERSAL_OutArgs); \r
244 outArg.extendedError = 0;\r
245 //System_printf("Before VIDDEC2 process\n");\r
246 \r
247 //System_printf("outptr = 0x%x, size = %d\n",outBufs->bufs[0],outBufs->bufSizes[0]);\r
248 inBuf.numBufs = 1;\r
249 outBuf.numBufs = 1;\r
250 inBuf.descs[0].buf = inBufs->descs[0].buf;\r
251 inBuf.descs[0].bufSize = inBufs->descs[0].bufSize;\r
252 \r
253 outBuf.descs[0].buf = outBufs->bufs[0];\r
254 outBuf.descs[0].bufSize = outBufs->bufSizes[0];\r
255 \r
256 ret = UNIVERSAL_process((UNIVERSAL_Handle)handle, &inBuf, &outBuf, NULL, \r
257 &inArg, &outArg);\r
258 \r
259 //System_printf("After VIDDEC2 process\n");\r
260 return ret; \r
261 }\r
262 \r
263 static int viddec2_delete(VIDDEC2_Handle handle)\r
264 {\r
265 //System_printf("Deleting VIDDEC2\n"); \r
266 UNIVERSAL_delete((UNIVERSAL_Handle)handle);\r
267 return 0;\r
268 }\r
269 \r
270 \r
271 /*\r
272 * RPC message handlers\r
273 */\r
274 static int connect(void *msg)\r
275 {\r
276 //dce_connect *req = msg;\r
277 //DEBUG(">> chipset_id=0x%x, debug=%d", req->chipset_id, req->debug);\r
278 \r
279 if( dce_debug >= MAX_DEBUG_LEVEL ) {\r
280 DEBUG("Enable FC, CE and IPC traces");\r
281 \r
282 FCSettings_init();\r
283 Diags_setMask(FCSETTINGS_MODNAME "+12345678LEXAIZFS");\r
284 \r
285 CESettings_init();\r
286 Diags_setMask(CESETTINGS_MODNAME "+12345678LEXAIZFS");\r
287 \r
288 /*\r
289 * Enable use of runtime Diags_setMask per module:\r
290 *\r
291 * Codes: E = ENTRY, X = EXIT, L = LIFECYCLE, F = INFO, S = STATUS\r
292 */\r
293 Diags_setMask("ti.ipc.rpmsg.RPMessage=EXLFS");\r
294 Diags_setMask("ti.ipc.rpmsg.VirtQueue=EXLFS");\r
295 }\r
296 \r
297 CERuntime_init();\r
298 \r
299 if( !suspend_initialised ) {\r
300 \r
301 /* registering sysbios-rpmsg callbacks for suspend/resume */\r
302 // IpcPower_registerCallback(IpcPower_Event_SUSPEND, (IpcPower_CallbackFuncPtr)dce_suspend, 0);\r
303 // IpcPower_registerCallback(IpcPower_Event_RESUME, (IpcPower_CallbackFuncPtr)dce_resume, 0);\r
304 suspend_initialised++;\r
305 }\r
306 \r
307 DEBUG("<<");\r
308 \r
309 return (0);\r
310 }\r
311 \r
312 /*\r
313 * Engine_open:\r
314 */\r
315 static Int32 engine_open(UInt32 size, UInt32 *data)\r
316 {\r
317 MmType_Param *payload = (MmType_Param *)data;\r
318 dce_engine_open *engine_open_msg = (dce_engine_open *)payload[0].data;\r
319 Engine_Handle eng_handle = NULL;\r
320 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
321 \r
322 DEBUG(">> engine_open");\r
323 if( num_params != 1 ) {\r
324 ERROR("Invalid number of params sent");\r
325 return (-1);\r
326 }\r
327 \r
328 dce_inv(engine_open_msg);\r
329 \r
330 eng_handle = Engine_open(engine_open_msg->name, engine_open_msg->engine_attrs, &engine_open_msg->error_code);\r
331 DEBUG("<< engine=%08x, ec=%d", eng_handle, engine_open_msg->error_code);\r
332 \r
333 dce_clean(engine_open_msg);\r
334 \r
335 return ((Int32)eng_handle);\r
336 }\r
337 \r
338 /*\r
339 * Engine_close:\r
340 */\r
341 static Int32 engine_close(UInt32 size, UInt32 *data)\r
342 {\r
343 MmType_Param *payload = (MmType_Param *)data;\r
344 Engine_Handle eng_handle = (Engine_Handle)payload[0].data;\r
345 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
346 \r
347 if( num_params != 1 ) {\r
348 ERROR("invalid number of params sent");\r
349 return (-1);\r
350 }\r
351 \r
352 Engine_close(eng_handle);\r
353 DEBUG("<<");\r
354 \r
355 return (0);\r
356 }\r
357 \r
358 /*\r
359 * codec_create\r
360 */\r
361 static Int32 codec_create(UInt32 size, UInt32 *data)\r
362 {\r
363 MmType_Param *payload = (MmType_Param *)data;\r
364 Uint32 codec_id = (Uint32)payload[0].data;\r
365 Engine_Handle engine = (Engine_Handle)payload[1].data;\r
366 char *codec_name = (char *)payload[2].data;\r
367 void *static_params = (void *)payload[3].data;\r
368 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
369 void *codec_handle;\r
370 \r
371 #ifdef MEMORYSTATS_DEBUG\r
372 Memory_Stats stats;\r
373 #endif\r
374 DEBUG(">> codec_create");\r
375 \r
376 if( num_params != 4 ) {\r
377 ERROR("invalid number of params sent");\r
378 return (-1);\r
379 }\r
380 \r
381 if(codec_id != OMAP_DCE_VIDDEC2){\r
382 ERROR("invalid codec id sent");\r
383 return (-1);\r
384 }\r
385 \r
386 dce_inv(static_params);\r
387 \r
388 codec_handle = (void *)codec_fxns[codec_id].create(engine, codec_name, static_params);\r
389 \r
390 DEBUG("<< codec_handle=%08x", codec_handle);\r
391 \r
392 dce_clean(static_params);\r
393 \r
394 #ifdef MEMORYSTATS_DEBUG\r
395 Memory_getStats(NULL, &stats);\r
396 INFO("Total: %d\tFree: %d\tLargest: %d", stats.totalSize,\r
397 stats.totalFreeSize, stats.largestFreeSize);\r
398 #endif\r
399 return ((Int32)codec_handle);\r
400 }\r
401 \r
402 /*\r
403 * codec_control\r
404 */\r
405 static int codec_control(UInt32 size, UInt32 *data)\r
406 {\r
407 MmType_Param *payload = (MmType_Param *)data;\r
408 Uint32 codec_id = (Uint32)payload[0].data;\r
409 void *codec_handle = (Engine_Handle)payload[1].data;\r
410 uint32_t cmd_id = (Uint32)payload[2].data;\r
411 void *dyn_params = (void *)payload[3].data;\r
412 void *status = (void *)payload[4].data;\r
413 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
414 Int32 ret = 0;\r
415 \r
416 \r
417 DEBUG(">> codec_control");\r
418 \r
419 if( num_params != 5 ) {\r
420 ERROR("invalid number of params sent");\r
421 return (-1);\r
422 }\r
423 \r
424 if(codec_id != OMAP_DCE_VIDDEC2){\r
425 ERROR("invalid codec id sent");\r
426 return (-1);\r
427 }\r
428 \r
429 dce_inv(dyn_params);\r
430 dce_inv(status);\r
431 \r
432 ret = (uint32_t) codec_fxns[codec_id].control(codec_handle, cmd_id, dyn_params, status);\r
433 \r
434 DEBUG("<< result=%d", ret);\r
435 \r
436 dce_clean(dyn_params);\r
437 dce_clean(status);\r
438 \r
439 return (ret);\r
440 }\r
441 \r
442 /*\r
443 * codec get version\r
444 */\r
445 static int codec_get_version(UInt32 size, UInt32 *data)\r
446 {\r
447 MmType_Param *payload = (MmType_Param *)data;\r
448 Uint32 codec_id = (Uint32)payload[0].data;\r
449 void *codec_handle = (Engine_Handle)payload[1].data;\r
450 void *dyn_params = (void *)payload[2].data;\r
451 void *status = (void *)payload[3].data;\r
452 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
453 void *version_buf = NULL;\r
454 Int32 ret = 0;\r
455 \r
456 DEBUG(">> codec_get_version");\r
457 \r
458 if( num_params != 4 ) {\r
459 ERROR("invalid number of params sent");\r
460 return (-1);\r
461 }\r
462 \r
463 if(codec_id != OMAP_DCE_VIDDEC2){\r
464 ERROR("invalid codec id sent");\r
465 return (-1);\r
466 }\r
467 \r
468 version_buf = (void *)(H2P((MemHeader *)((IVIDDEC2_Status *)status)->data.buf));\r
469 \r
470 dce_inv(dyn_params);\r
471 dce_inv(status);\r
472 dce_inv(version_buf);\r
473 \r
474 ret = (uint32_t) codec_fxns[codec_id].control(codec_handle, XDM_GETVERSION, dyn_params, status);\r
475 \r
476 DEBUG("<< result=%d", ret);\r
477 \r
478 dce_clean(dyn_params);\r
479 dce_clean(status);\r
480 dce_clean(version_buf);\r
481 \r
482 return (ret);\r
483 }\r
484 \r
485 /* Notes about serialization of process command:\r
486 *\r
487 * Since codec_process code on kernel side is doing buffer mapping/unmapping,\r
488 * and keeping track of codec's locked buffers, it is necessary for it to\r
489 * look into the contents of some of the parameter structs, and in some cases\r
490 * re-write them. For this reason inArgs/outBufs/inBufs are serialized within\r
491 * the rpmsg rather than just passed by pointer.\r
492 \r
493 XDAS_Int32 VIDDEC3_process(VIDDEC3_Handle handle, XDM1_BufDesc *inBufs,\r
494 XDM_BufDesc *outBufs, VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs);\r
495 \r
496 REQ:\r
497 struct dce_rpc_hdr hdr -> 4\r
498 codec_id -> 4\r
499 codec -> 4\r
500 reloc length -> 1 (length/4)\r
501 inArgs length -> 1 (length/4)\r
502 outBufs length -> 1 (length/4)\r
503 inBufs length -> 1 (length/4)\r
504 VIDDEC3_OutArgs *outArgs -> 4 (pass by pointer)\r
505 reloc table -> 12 * nreloc (typically <= 16)\r
506 VIDDEC3_InArgs inArgs -> 12 (need inputID from userspace)\r
507 XDM_BufDesc outBufs -> 44 (4 + 2 * 20)\r
508 XDM1_BufDesc inBufs -> 24 (4 + 1 * 20)\r
509 -------------------------------\r
510 99\r
511 \r
512 RSP\r
513 struct dce_rpc_hdr hdr -> 4\r
514 result -> 4\r
515 inBufs length -> 1 (length/4)\r
516 XDAS_Int32 freeBufID[] -> 4*n (n typically 0 or 2, but could be up to 20)\r
517 -------------------------------\r
518 9-89\r
519 Note: freeBufID[] duplicates what is returned in outArgs, but avoids\r
520 needing to create kernel mappings of these objects which are to big\r
521 to copy inline. Also it avoids differences between VIDDEC3/VIDDENC2.\r
522 \r
523 \r
524 XDAS_Int32 VIDENC2_process(VIDENC2_Handle handle, IVIDEO2_BufDesc *inBufs,\r
525 XDM2_BufDesc *outBufs, IVIDENC2_InArgs *inArgs, IVIDENC2_OutArgs *outArgs);\r
526 \r
527 REQ:\r
528 struct dce_rpc_hdr hdr -> 4\r
529 codec_id -> 4\r
530 codec -> 4\r
531 reloc length -> 1 (length/4)\r
532 inArgs length -> 1 (length/4)\r
533 outBufs length -> 1 (length/4)\r
534 inBufs length -> 1 (length/4)\r
535 VIDENC2_OutArgs *outArgs -> 4 (pass by pointer)\r
536 reloc table -> ???\r
537 VIDENC2_InArgs inArgs -> 12 (need inputID from userspace)\r
538 XDM2_BufDesc outBufs -> 24 (4 + 1 * 20)\r
539 IVIDEO2_BufDesc inBufs -> 252\r
540 -------------------------------\r
541 307\r
542 \r
543 RSP\r
544 struct dce_rpc_hdr hdr -> 4\r
545 result -> 4\r
546 inBufs length -> 1 (length/4)\r
547 XDAS_Int32 freeBufID[] -> 4*n (n typically 0 or 2, but could be up to 20)\r
548 -------------------------------\r
549 9-89\r
550 */\r
551 \r
552 static int codec_process(UInt32 size, UInt32 *data)\r
553 {\r
554 MmType_Param *payload = (MmType_Param *)data;\r
555 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
556 Uint32 codec_id = (Uint32) payload[0].data;\r
557 Uint32 codec = (Uint32) payload[1].data;\r
558 void *inBufs = (void *) payload[2].data;\r
559 void *outBufs = (void *) payload[3].data;\r
560 void *inArgs = (void *) payload[4].data;\r
561 void *outArgs = (void *) payload[5].data;\r
562 void *outBufptr = (void *)payload[6].data;\r
563 Int32 ret = 0;\r
564 void *outBufSize = NULL;\r
565 \r
566 DEBUG(">> codec_process");\r
567 \r
568 if( num_params != 7 ) {\r
569 ERROR("invalid number of params sent");\r
570 return (-1);\r
571 }\r
572 \r
573 if(codec_id != OMAP_DCE_VIDDEC2){\r
574 ERROR("invalid codec id sent");\r
575 return (-1);\r
576 }\r
577 \r
578 outBufSize = (void *)(H2P((MemHeader *)((XDM_BufDesc *)outBufs)->bufSizes));\r
579 \r
580 dce_inv(inBufs);\r
581 dce_inv(outBufs);\r
582 dce_inv(inArgs);\r
583 dce_inv(outArgs);\r
584 dce_inv(outBufptr);\r
585 dce_inv(outBufSize);\r
586 \r
587 DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p codec_id=%d",\r
588 codec, inBufs, outBufs, inArgs, outArgs, codec_id);\r
589 \r
590 ret = codec_fxns[codec_id].process((void *)codec, inBufs, outBufs, inArgs, outArgs);\r
591 \r
592 \r
593 DEBUG("<< ret=%d extendedError=%08x", ret, ((VIDDEC3_OutArgs *)outArgs)->extendedError);\r
594 \r
595 dce_clean(inBufs);\r
596 dce_clean(outBufs);\r
597 dce_clean(inArgs);\r
598 dce_clean(outArgs);\r
599 dce_clean(outBufptr);\r
600 dce_clean(outBufSize);\r
601 \r
602 return ((Int32)ret);\r
603 }\r
604 \r
605 /*\r
606 * codec delete\r
607 */\r
608 \r
609 static int codec_delete(UInt32 size, UInt32 *data)\r
610 {\r
611 MmType_Param *payload = (MmType_Param *)data;\r
612 Uint32 num_params = MmRpc_NUM_PARAMETERS(size);\r
613 Uint32 codec_id = (Uint32) payload[0].data;\r
614 Uint32 codec = (Uint32) payload[1].data;\r
615 \r
616 #ifdef MEMORYSTATS_DEBUG\r
617 Memory_Stats stats;\r
618 #endif\r
619 \r
620 DEBUG(">> codec_delete");\r
621 \r
622 if( num_params != 2 ) {\r
623 ERROR("invalid number of params sent");\r
624 return (-1);\r
625 }\r
626 \r
627 if(codec_id != OMAP_DCE_VIDDEC2){\r
628 ERROR("invalid codec id sent");\r
629 return (-1);\r
630 }\r
631 \r
632 codec_fxns[codec_id].delete((void *)codec);\r
633 \r
634 #ifdef MEMORYSTATS_DEBUG\r
635 Memory_getStats(NULL, &stats);\r
636 INFO("Total: %d\tFree: %d\tLargest: %d", stats.totalSize,\r
637 stats.totalFreeSize, stats.largestFreeSize);\r
638 #endif\r
639 \r
640 DEBUG("<<");\r
641 \r
642 return (0);\r
643 }\r
644 \r
645 /* the server create parameters, must be in persistent memory */\r
646 static RcmServer_Params rpc_Params;\r
647 \r
648 /* DCE Server skel function array */\r
649 static RcmServer_FxnDesc DCEServerFxnAry[] =\r
650 {\r
651 { "engine_open", (RcmServer_MsgFxn) engine_open },\r
652 { "engine_close", (RcmServer_MsgFxn) engine_close },\r
653 { "codec_create", (RcmServer_MsgFxn) codec_create },\r
654 { "codec_control", (RcmServer_MsgFxn) codec_control },\r
655 { "codec_get_version", (RcmServer_MsgFxn) codec_get_version },\r
656 { "codec_process", (RcmServer_MsgFxn) codec_process },\r
657 { "codec_delete", (RcmServer_MsgFxn) codec_delete }\r
658 };\r
659 \r
660 /* DCE Server skel function table */\r
661 #define DCEServerFxnAryLen (sizeof(DCEServerFxnAry) / sizeof(DCEServerFxnAry[0]))\r
662 \r
663 static const RcmServer_FxnDescAry DCEServer_fxnTab =\r
664 {\r
665 DCEServerFxnAryLen,\r
666 DCEServerFxnAry\r
667 };\r
668 \r
669 static MmType_FxnSig DCEServer_sigAry[] =\r
670 {\r
671 { "engine_open", 2,\r
672 {\r
673 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
674 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }\r
675 } },\r
676 { "engine_close", 2,\r
677 {\r
678 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
679 { MmType_Dir_In, MmType_Param_U32, 1 }\r
680 \r
681 } },\r
682 { "codec_create", 5,\r
683 {\r
684 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
685 { MmType_Dir_In, MmType_Param_U32, 1 },\r
686 { MmType_Dir_In, MmType_Param_U32, 1 },\r
687 { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 },\r
688 { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 }\r
689 } },\r
690 { "codec_control", 6,\r
691 {\r
692 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
693 { MmType_Dir_In, MmType_Param_U32, 1 },\r
694 { MmType_Dir_In, MmType_Param_U32, 1 },\r
695 { MmType_Dir_In, MmType_Param_U32, 1 },\r
696 { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 },\r
697 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }\r
698 } },\r
699 { "codec_get_version", 5,\r
700 {\r
701 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
702 { MmType_Dir_In, MmType_Param_U32, 1 },\r
703 { MmType_Dir_In, MmType_Param_U32, 1 },\r
704 { MmType_Dir_In, MmType_PtrType(MmType_Param_VOID), 1 },\r
705 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }\r
706 } },\r
707 \r
708 { "codec_process", 8,\r
709 {\r
710 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
711 { MmType_Dir_In, MmType_Param_U32, 1 },\r
712 { MmType_Dir_In, MmType_Param_U32, 1 },\r
713 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },\r
714 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },\r
715 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },\r
716 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 },\r
717 { MmType_Dir_Bi, MmType_PtrType(MmType_Param_VOID), 1 }\r
718 } },\r
719 \r
720 { "codec_delete", 3,\r
721 {\r
722 { MmType_Dir_Out, MmType_Param_S32, 1 }, // return\r
723 { MmType_Dir_In, MmType_Param_U32, 1 },\r
724 { MmType_Dir_In, MmType_Param_U32, 1 }\r
725 } }\r
726 };\r
727 \r
728 static MmType_FxnSigTab dce_fxnSigTab =\r
729 {\r
730 MmType_NumElem(DCEServer_sigAry), DCEServer_sigAry\r
731 };\r
732 \r
733 Void dce_SrvDelNotification(Void)\r
734 {\r
735 DEBUG("dce_SrvDelNotification: Nothing to cleanup\n");\r
736 }\r
737 \r
738 static void dce_main(uint32_t arg0, uint32_t arg1)\r
739 {\r
740 int err = 0;\r
741 dce_connect dce_connect_msg;\r
742 \r
743 err = MmServiceMgr_init(); // MmServiceMgr_init() will always return MmServiceMgr_S_SUCCESS.\r
744 \r
745 // setup the RCM Server create params\r
746 RcmServer_Params_init(&rpc_Params);\r
747 rpc_Params.priority = Thread_Priority_ABOVE_NORMAL;\r
748 rpc_Params.stackSize = 0x1000;\r
749 rpc_Params.fxns.length = DCEServer_fxnTab.length;\r
750 rpc_Params.fxns.elem = DCEServer_fxnTab.elem;\r
751 \r
752 // Get the Service Manager handle\r
753 err = MmServiceMgr_register(SERVER_NAME, &rpc_Params, &dce_fxnSigTab, dce_SrvDelNotification);\r
754 \r
755 if( err < 0 ) {\r
756 DEBUG("failed to start " SERVER_NAME " \n");\r
757 //err = -1;\r
758 } else {\r
759 DEBUG(SERVER_NAME " running through MmServiceMgr");\r
760 }\r
761 \r
762 // Question to IPC team: where is the call to OmapRpc_deleteChannel(handle). The OmapRpc_createChannel is part of MmServiceMgr_register\r
763 // missing the call to OmapRpc_deleteChannel(handle).\r
764 MmServiceMgr_exit();\r
765 \r
766 DEBUG("deleted " SERVER_NAME);\r
767 \r
768 /* Read the register for ID_CODE to figure out the correct configuration: */\r
769 /* CONTROL_STD_FUSE_ID_CODE[31:0] ID_CODE STD_FUSE_IDCODE */\r
770 /* physical address: 0x4A00 2204 Address offset: 0x204 */\r
771 #ifdef OMAP5430_ES10\r
772 dce_connect_msg.chipset_id = 0x5430;\r
773 #elif OMAP5432_ES20\r
774 dce_connect_msg.chipset_id = 0x5432;\r
775 #elif VAYU_ES10\r
776 dce_connect_msg.chipset_id = 0x5436;\r
777 #endif\r
778 dce_connect_msg.debug = dce_debug;\r
779 connect(&dce_connect_msg);\r
780 \r
781 return;\r
782 }\r
783 \r
784 /*\r
785 * dce init : Startup Function\r
786 */\r
787 Bool dce_init(void)\r
788 {\r
789 Task_Params params;\r
790 \r
791 INFO("Creating DCE server thread...");\r
792 \r
793 \r
794 /* Create DCE task. */\r
795 Task_Params_init(¶ms);\r
796 params.instance->name = "dce-server";\r
797 params.priority = Thread_Priority_ABOVE_NORMAL;\r
798 Task_create(dce_main, ¶ms, NULL);\r
799 \r
800 return (TRUE);\r
801 }\r
802 \r
803 /*\r
804 * dce deinit\r
805 */\r
806 \r
807 void dce_deinit(void)\r
808 {\r
809 DEBUG("dce_deinit");\r
810 }\r
811 \r