Initial version of libomxil-e3250-v4l2
[platform/adaptation/ap_samsung/libomxil-e3250-v4l2.git] / openmax / osal / Exynos_OSAL_SharedMemory.c
1 /*
2  *
3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /*
19  * @file        Exynos_OSAL_SharedMemory.c
20  * @brief
21  * @author      SeungBeom Kim (sbcrux.kim@samsung.com)
22  *              Taehwan Kim (t_h.kim@samsung.com)
23  * @version     2.0.0
24  * @history
25  *   2012.02.20 : Create
26  */
27
28 #include <stdbool.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <pthread.h>
34 #ifndef SLP_PLATFORM /* build env */
35 #include <cutils/log.h>
36 #include <cutils/atomic.h>
37 #endif
38 #include <fcntl.h>
39 #include <sys/mman.h>
40
41 #include "Exynos_OSAL_SharedMemory.h"
42 #include "ion.h"
43
44 #define EXYNOS_LOG_OFF
45 #include "Exynos_OSAL_Log.h"
46
47 static int mem_cnt = 0;
48
49 struct EXYNOS_SHAREDMEM_LIST;
50 typedef struct _EXYNOS_SHAREDMEM_LIST
51 {
52     OMX_U32                        IONBuffer;
53     OMX_PTR                        mapAddr;
54     OMX_U32                        allocSize;
55     bool                           owner;
56     struct _EXYNOS_SHAREDMEM_LIST *pNextMemory;
57 } EXYNOS_SHAREDMEM_LIST;
58
59 typedef struct _EXYNOS_SHARED_MEMORY
60 {
61     OMX_HANDLETYPE         hIONHandle;
62     EXYNOS_SHAREDMEM_LIST *pAllocMemory;
63     OMX_HANDLETYPE         hSMMutex;
64 } EXYNOS_SHARED_MEMORY;
65
66
67 OMX_HANDLETYPE Exynos_OSAL_SharedMemory_Open()
68 {
69     EXYNOS_SHARED_MEMORY *pHandle = NULL;
70     ion_client            IONClient = 0;
71
72     pHandle = (EXYNOS_SHARED_MEMORY *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHARED_MEMORY));
73     Exynos_OSAL_Memset(pHandle, 0, sizeof(EXYNOS_SHARED_MEMORY));
74     if (pHandle == NULL)
75         goto EXIT;
76
77     IONClient = (OMX_HANDLETYPE)ion_client_create();
78     if (IONClient <= 0) {
79         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_client_create Error: %d", IONClient);
80         Exynos_OSAL_Free((void *)pHandle);
81         pHandle = NULL;
82         goto EXIT;
83     }
84
85     pHandle->hIONHandle = IONClient;
86
87     Exynos_OSAL_MutexCreate(&pHandle->hSMMutex);
88
89 EXIT:
90     return (OMX_HANDLETYPE)pHandle;
91 }
92
93 void Exynos_OSAL_SharedMemory_Close(OMX_HANDLETYPE handle)
94 {
95     EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
96     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
97     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
98     EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL;
99
100     if (pHandle == NULL)
101         goto EXIT;
102
103     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
104     pCurrentElement = pSMList = pHandle->pAllocMemory;
105
106     while (pCurrentElement != NULL) {
107         pDeleteElement = pCurrentElement;
108         pCurrentElement = pCurrentElement->pNextMemory;
109
110         if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize))
111             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
112
113         pDeleteElement->mapAddr = NULL;
114         pDeleteElement->allocSize = 0;
115
116         if (pDeleteElement->owner)
117             ion_free(pDeleteElement->IONBuffer);
118         pDeleteElement->IONBuffer = 0;
119
120         Exynos_OSAL_Free(pDeleteElement);
121
122         mem_cnt--;
123         Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
124     }
125
126     pHandle->pAllocMemory = pSMList = NULL;
127     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
128
129     Exynos_OSAL_MutexTerminate(pHandle->hSMMutex);
130     pHandle->hSMMutex = NULL;
131
132     ion_client_destroy((ion_client)pHandle->hIONHandle);
133     pHandle->hIONHandle = NULL;
134
135     Exynos_OSAL_Free(pHandle);
136
137 EXIT:
138     return;
139 }
140
141 OMX_PTR Exynos_OSAL_SharedMemory_Alloc(OMX_HANDLETYPE handle, OMX_U32 size, MEMORY_TYPE memoryType)
142 {
143     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
144     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
145     EXYNOS_SHAREDMEM_LIST *pElement        = NULL;
146     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
147     ion_buffer             IONBuffer       = 0;
148     OMX_PTR                pBuffer         = NULL;
149     unsigned int mask;
150     unsigned int flag;
151
152     if (pHandle == NULL)
153         goto EXIT;
154
155     pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST));
156     Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST));
157     pElement->owner = true;
158
159     switch (memoryType) {
160     case SECURE_MEMORY:
161         mask = ION_HEAP_EXYNOS_CONTIG_MASK;
162         flag = ION_EXYNOS_FIMD_VIDEO_MASK;
163         break;
164     case NORMAL_MEMORY:
165         mask = ION_HEAP_EXYNOS_MASK;
166         flag = 0;
167         break;
168     case SYSTEM_MEMORY:
169         mask = ION_HEAP_SYSTEM_MASK;
170         flag = ION_FLAG_CACHED;
171         break;
172     default:
173         pBuffer = NULL;
174         goto EXIT;
175         break;
176     }
177
178     IONBuffer = ion_alloc((ion_client)pHandle->hIONHandle, size, 0, mask, flag);
179
180     if (IONBuffer <= 0) {
181         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_alloc Error: %d", IONBuffer);
182         Exynos_OSAL_Free((OMX_PTR)pElement);
183         goto EXIT;
184     }
185
186     pBuffer = ion_map(IONBuffer, size, 0);
187     if (pBuffer == MAP_FAILED) {
188         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_map Error");
189         ion_free(IONBuffer);
190         Exynos_OSAL_Free((OMX_PTR)pElement);
191         pBuffer = NULL;
192         goto EXIT;
193     }
194
195     pElement->IONBuffer = IONBuffer;
196     pElement->mapAddr = pBuffer;
197     pElement->allocSize = size;
198     pElement->pNextMemory = NULL;
199
200     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
201     pSMList = pHandle->pAllocMemory;
202     if (pSMList == NULL) {
203         pHandle->pAllocMemory = pSMList = pElement;
204     } else {
205         pCurrentElement = pSMList;
206         while (pCurrentElement->pNextMemory != NULL) {
207             pCurrentElement = pCurrentElement->pNextMemory;
208         }
209         pCurrentElement->pNextMemory = pElement;
210     }
211     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
212
213     mem_cnt++;
214 #ifndef SLP_PLATFORM
215     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory alloc count: %d", mem_cnt);
216 #else
217     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory alloc count: %d", mem_cnt);
218 #endif
219
220 EXIT:
221     return pBuffer;
222 }
223
224 void Exynos_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
225 {
226     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
227     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
228     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
229     EXYNOS_SHAREDMEM_LIST *pDeleteElement  = NULL;
230
231     if (pHandle == NULL)
232         goto EXIT;
233
234     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
235     pSMList = pHandle->pAllocMemory;
236     if (pSMList == NULL) {
237         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
238         goto EXIT;
239     }
240
241     pCurrentElement = pSMList;
242     if (pSMList->mapAddr == pBuffer) {
243         pDeleteElement = pSMList;
244         pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
245     } else {
246         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
247                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
248             pCurrentElement = pCurrentElement->pNextMemory;
249
250         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
251             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
252             pDeleteElement = pCurrentElement->pNextMemory;
253             pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
254         } else {
255             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
256             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
257             goto EXIT;
258         }
259     }
260     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
261
262     if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
263         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
264         goto EXIT;
265     }
266     pDeleteElement->mapAddr = NULL;
267     pDeleteElement->allocSize = 0;
268
269     if (pDeleteElement->owner)
270         ion_free(pDeleteElement->IONBuffer);
271     pDeleteElement->IONBuffer = 0;
272
273     Exynos_OSAL_Free(pDeleteElement);
274
275     mem_cnt--;
276 #ifndef SLP_PLATFORM
277     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
278 #else
279     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory free count: %d", mem_cnt);
280 #endif
281
282 EXIT:
283     return;
284 }
285
286 #ifdef USE_DMA_BUF
287 OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned int ionfd)
288 {
289     EXYNOS_SHARED_MEMORY  *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
290     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
291     EXYNOS_SHAREDMEM_LIST *pElement = NULL;
292     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
293     ion_buffer IONBuffer = 0;
294     OMX_PTR pBuffer = NULL;
295
296     if (pHandle == NULL)
297         goto EXIT;
298
299     pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST));
300     Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST));
301
302     IONBuffer = (OMX_PTR)ionfd;
303
304     if (IONBuffer <= 0) {
305         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_alloc Error: %d", IONBuffer);
306         Exynos_OSAL_Free((void*)pElement);
307         goto EXIT;
308     }
309
310     pBuffer = ion_map(IONBuffer, size, 0);
311     if (pBuffer == NULL) {
312         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_map Error");
313         ion_free(IONBuffer);
314         Exynos_OSAL_Free((void*)pElement);
315         goto EXIT;
316     }
317
318     pElement->IONBuffer = IONBuffer;
319     pElement->mapAddr = pBuffer;
320     pElement->allocSize = size;
321     pElement->pNextMemory = NULL;
322
323     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
324     pSMList = pHandle->pAllocMemory;
325     if (pSMList == NULL) {
326         pHandle->pAllocMemory = pSMList = pElement;
327     } else {
328         pCurrentElement = pSMList;
329         while (pCurrentElement->pNextMemory != NULL) {
330             pCurrentElement = pCurrentElement->pNextMemory;
331         }
332         pCurrentElement->pNextMemory = pElement;
333     }
334     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
335
336     mem_cnt++;
337 #ifndef SLP_PLATFORM
338     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory alloc count: %d", mem_cnt);
339 #else
340     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory alloc count: %d", mem_cnt);
341 #endif
342
343 EXIT:
344     return pBuffer;
345 }
346
347 void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned int ionfd)
348 {
349     EXYNOS_SHARED_MEMORY  *pHandle = (EXYNOS_SHARED_MEMORY *)handle;
350     EXYNOS_SHAREDMEM_LIST *pSMList = NULL;
351     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
352     EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL;
353
354     if (pHandle == NULL)
355         goto EXIT;
356
357     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
358     pSMList = pHandle->pAllocMemory;
359     if (pSMList == NULL) {
360         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
361         goto EXIT;
362     }
363
364     pCurrentElement = pSMList;
365     if (pSMList->IONBuffer == ionfd) {
366         pDeleteElement = pSMList;
367         pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
368     } else {
369         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
370                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ionfd))
371             pCurrentElement = pCurrentElement->pNextMemory;
372
373         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
374             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ionfd)) {
375             pDeleteElement = pCurrentElement->pNextMemory;
376             pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
377         } else {
378             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
379             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
380             goto EXIT;
381         }
382     }
383     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
384
385     if (ion_unmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
386         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_unmap fail");
387         goto EXIT;
388     }
389     pDeleteElement->mapAddr = NULL;
390     pDeleteElement->allocSize = 0;
391     pDeleteElement->IONBuffer = 0;
392
393     Exynos_OSAL_Free(pDeleteElement);
394
395     mem_cnt--;
396 #ifndef SLP_PLATFORM
397     Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory free count: %d", mem_cnt);
398 #else
399     Exynos_OSAL_Log(EXYNOS_LOG_VERVOSE, "SharedMemory free count: %d", mem_cnt);
400 #endif
401
402 EXIT:
403     return;
404 }
405 #endif
406
407 int Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
408 {
409     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
410     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
411     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
412     EXYNOS_SHAREDMEM_LIST *pFindElement    = NULL;
413     int ion_addr = 0;
414     if (pHandle == NULL || pBuffer == NULL)
415         goto EXIT;
416
417     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
418     pSMList = pHandle->pAllocMemory;
419     if (pSMList == NULL) {
420         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
421         goto EXIT;
422     }
423
424     pCurrentElement = pSMList;
425     if (pSMList->mapAddr == pBuffer) {
426         pFindElement = pSMList;
427     } else {
428         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
429                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
430             pCurrentElement = pCurrentElement->pNextMemory;
431
432         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
433             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
434             pFindElement = pCurrentElement->pNextMemory;
435         } else {
436             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
437             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
438             goto EXIT;
439         }
440     }
441     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
442
443     ion_addr = pFindElement->IONBuffer;
444
445 EXIT:
446     return ion_addr;
447 }
448
449 OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, int ion_addr)
450 {
451     EXYNOS_SHARED_MEMORY  *pHandle         = (EXYNOS_SHARED_MEMORY *)handle;
452     EXYNOS_SHAREDMEM_LIST *pSMList         = NULL;
453     EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL;
454     EXYNOS_SHAREDMEM_LIST *pFindElement    = NULL;
455     OMX_PTR pBuffer = NULL;
456     if (pHandle == NULL || ion_addr == 0)
457         goto EXIT;
458
459     Exynos_OSAL_MutexLock(pHandle->hSMMutex);
460     pSMList = pHandle->pAllocMemory;
461     if (pSMList == NULL) {
462         Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
463         goto EXIT;
464     }
465
466     pCurrentElement = pSMList;
467     if (pSMList->IONBuffer == ion_addr) {
468         pFindElement = pSMList;
469     } else {
470         while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
471                (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ion_addr))
472             pCurrentElement = pCurrentElement->pNextMemory;
473
474         if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
475             (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ion_addr)) {
476             pFindElement = pCurrentElement->pNextMemory;
477         } else {
478             Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
479             Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find SharedMemory");
480             goto EXIT;
481         }
482     }
483     Exynos_OSAL_MutexUnlock(pHandle->hSMMutex);
484
485     pBuffer = pFindElement->mapAddr;
486
487 EXIT:
488     return pBuffer;
489 }