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