1000 lines
28 KiB
C
Executable File
1000 lines
28 KiB
C
Executable File
/*
|
|
*
|
|
* Copyright 2013 Rockchip Electronics Co. LTD
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*
|
|
* @file Rockchip_OSAL_SharedMemory.c
|
|
* @brief
|
|
* @author csy(csy@rock-chips.com)
|
|
* @version 1.0.0
|
|
* @history
|
|
* 2013.11.26 : Create
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <cutils/log.h>
|
|
#include <cutils/atomic.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include "vpu.h"
|
|
|
|
#include "drm_mode.h"
|
|
#include "drm.h"
|
|
|
|
#include "Rockchip_OSAL_SharedMemory.h"
|
|
#include "Rockchip_OSAL_Mutex.h"
|
|
|
|
#include "rockchip_ion.h"
|
|
#include <linux/ion.h>
|
|
#include <dlfcn.h>
|
|
#include <cutils/native_handle.h>
|
|
|
|
|
|
|
|
#define ROCKCHIP_LOG_OFF
|
|
#include "Rockchip_OSAL_Log.h"
|
|
|
|
#ifndef ION_SECURE_HEAP_ID
|
|
#define ION_SECURE_HEAP_ID ION_CMA_HEAP_ID
|
|
#endif
|
|
|
|
static int mem_cnt = 0;
|
|
static int mem_type = MEMORY_TYPE_ION;
|
|
|
|
struct ROCKCHIP_SHAREDMEM_LIST;
|
|
typedef struct _ROCKCHIP_SHAREDMEM_LIST {
|
|
RK_U32 ion_hdl;
|
|
OMX_PTR mapAddr;
|
|
OMX_U32 allocSize;
|
|
OMX_BOOL owner;
|
|
struct _ROCKCHIP_SHAREDMEM_LIST *pNextMemory;
|
|
} ROCKCHIP_SHAREDMEM_LIST;
|
|
|
|
typedef struct _ROCKCHIP_SHARED_MEMORY {
|
|
int fd;
|
|
ROCKCHIP_SHAREDMEM_LIST *pAllocMemory;
|
|
OMX_HANDLETYPE hSMMutex;
|
|
} ROCKCHIP_SHARED_MEMORY;
|
|
|
|
#define ION_FUNCTION (0x00000001)
|
|
#define ION_DEVICE (0x00000002)
|
|
#define ION_CLINET (0x00000004)
|
|
#define ION_IOCTL (0x00000008)
|
|
|
|
static int ion_ioctl(int fd, int req, void *arg)
|
|
{
|
|
int ret = ioctl(fd, req, arg);
|
|
if (ret < 0) {
|
|
omx_err("ion_ioctl %x failed with code %d: %s\n", req,
|
|
ret, strerror(errno));
|
|
return -errno;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
|
|
unsigned int flags, ion_user_handle_t *handle)
|
|
{
|
|
int ret;
|
|
struct ion_allocation_data data = {
|
|
.len = len,
|
|
.align = align,
|
|
.heap_id_mask = heap_mask,
|
|
.flags = flags,
|
|
};
|
|
|
|
if (handle == NULL)
|
|
return -EINVAL;
|
|
|
|
ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
|
|
if (ret < 0)
|
|
return ret;
|
|
*handle = data.handle;
|
|
return ret;
|
|
}
|
|
|
|
static int ion_free(int fd, ion_user_handle_t handle)
|
|
{
|
|
struct ion_handle_data data = {
|
|
.handle = handle,
|
|
};
|
|
return ion_ioctl(fd, ION_IOC_FREE, &data);
|
|
}
|
|
|
|
static int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
|
|
int flags, off_t offset, unsigned char **ptr, int *map_fd)
|
|
{
|
|
int ret;
|
|
struct ion_fd_data data = {
|
|
.handle = handle,
|
|
};
|
|
|
|
if (map_fd == NULL)
|
|
return -EINVAL;
|
|
if (ptr == NULL)
|
|
return -EINVAL;
|
|
|
|
ret = ion_ioctl(fd, ION_IOC_MAP, &data);
|
|
if (ret < 0)
|
|
return ret;
|
|
*map_fd = data.fd;
|
|
if (*map_fd < 0) {
|
|
omx_err("map ioctl returned negative fd\n");
|
|
return -EINVAL;
|
|
}
|
|
*ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
|
|
if (*ptr == MAP_FAILED) {
|
|
omx_err("mmap failed: %s\n", strerror(errno));
|
|
return -errno;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ion_import(int fd, int share_fd, ion_user_handle_t *handle)
|
|
{
|
|
int ret;
|
|
struct ion_fd_data data = {
|
|
.fd = share_fd,
|
|
};
|
|
|
|
if (handle == NULL)
|
|
return -EINVAL;
|
|
|
|
ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
|
|
if (ret < 0)
|
|
return ret;
|
|
*handle = data.handle;
|
|
return ret;
|
|
}
|
|
|
|
int ion_get_phys(int fd, ion_user_handle_t handle, unsigned long *phys)
|
|
{
|
|
struct ion_phys_data phys_data;
|
|
struct ion_custom_data data;
|
|
|
|
phys_data.handle = handle;
|
|
phys_data.phys = 0;
|
|
|
|
data.cmd = ION_IOC_GET_PHYS;
|
|
data.arg = (unsigned long)&phys_data;
|
|
|
|
int ret = ion_ioctl(fd, ION_IOC_CUSTOM, &data);
|
|
omx_err("ion_get_phys:phys_data.phys = %p", phys_data.phys);
|
|
omx_err("ion_get_phys:phys_data.size = %ld", phys_data.size);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
*phys = phys_data.phys;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int drm_ioctl(int fd, int req, void *arg)
|
|
{
|
|
int ret;
|
|
|
|
do {
|
|
ret = ioctl(fd, req, arg);
|
|
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
typedef void *(*func_mmap64)(void* addr, size_t length, int prot, int flags,
|
|
int fd, off_t offset);
|
|
static func_mmap64 mpp_rt_mmap64 = NULL;
|
|
|
|
|
|
func_mmap64 mpp_rt_get_mmap64()
|
|
{
|
|
static RK_U32 once = 1;
|
|
|
|
if (once) {
|
|
void *libc_hdl = dlopen("libc", RTLD_LAZY);
|
|
if (libc_hdl) {
|
|
mpp_rt_mmap64 = (func_mmap64)dlsym(libc_hdl, "mmap64");
|
|
dlclose(libc_hdl);
|
|
}
|
|
|
|
once = 0;
|
|
}
|
|
|
|
|
|
return mpp_rt_mmap64;
|
|
}
|
|
|
|
|
|
static void* drm_mmap(int fd, size_t len, int prot, int flags, loff_t offset)
|
|
{
|
|
static unsigned long pagesize_mask = 0;
|
|
func_mmap64 fp_mmap64 = mpp_rt_get_mmap64();
|
|
|
|
if (fd < 0)
|
|
return NULL;
|
|
|
|
if (!pagesize_mask)
|
|
pagesize_mask = sysconf(_SC_PAGESIZE) - 1;
|
|
|
|
len = (len + pagesize_mask) & ~pagesize_mask;
|
|
|
|
if (offset & 4095) {
|
|
return NULL;
|
|
}
|
|
|
|
return mmap64(NULL, len, prot, flags, fd, offset);
|
|
}
|
|
|
|
|
|
static int drm_handle_to_fd(int fd, RK_U32 handle, int *map_fd, RK_U32 flags)
|
|
{
|
|
int ret;
|
|
struct drm_prime_handle dph;
|
|
memset(&dph, 0, sizeof(struct drm_prime_handle));
|
|
dph.handle = handle;
|
|
dph.fd = -1;
|
|
dph.flags = flags;
|
|
|
|
if (map_fd == NULL)
|
|
return -EINVAL;
|
|
|
|
ret = drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
|
|
*map_fd = dph.fd;
|
|
if (*map_fd < 0) {
|
|
omx_err("map ioctl returned negative fd\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
static int drm_fd_to_handle(int fd, int map_fd, RK_U32 *handle, RK_U32 flags)
|
|
{
|
|
int ret;
|
|
struct drm_prime_handle dph;
|
|
|
|
dph.fd = map_fd;
|
|
dph.flags = flags;
|
|
|
|
ret = drm_ioctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &dph);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
|
|
*handle = dph.handle;
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int drm_map(int fd, RK_U32 handle, size_t length, int prot,
|
|
int flags, unsigned char **ptr, int *map_fd)
|
|
{
|
|
int ret;
|
|
struct drm_mode_map_dumb dmmd;
|
|
memset(&dmmd, 0, sizeof(dmmd));
|
|
dmmd.handle = handle;
|
|
|
|
if (map_fd == NULL)
|
|
return -EINVAL;
|
|
if (ptr == NULL)
|
|
return -EINVAL;
|
|
|
|
ret = drm_handle_to_fd(fd, handle, map_fd, 0);
|
|
omx_err("drm_map fd %d", *map_fd);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
ret = drm_ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
|
|
if (ret < 0) {
|
|
omx_err("drm_map FAIL");
|
|
close(*map_fd);
|
|
return ret;
|
|
}
|
|
|
|
omx_trace("dev fd %d length %d", fd, length);
|
|
|
|
*ptr = drm_mmap(fd, length, prot, flags, dmmd.offset);
|
|
if (*ptr == MAP_FAILED) {
|
|
close(*map_fd);
|
|
*map_fd = -1;
|
|
omx_err("mmap failed: %s\n", strerror(errno));
|
|
return -errno;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int drm_alloc(int fd, size_t len, size_t align, RK_U32 *handle, int flag)
|
|
{
|
|
int ret;
|
|
struct drm_mode_create_dumb dmcb;
|
|
|
|
memset(&dmcb, 0, sizeof(struct drm_mode_create_dumb));
|
|
dmcb.bpp = 8;
|
|
dmcb.width = (len + align - 1) & (~(align - 1));
|
|
dmcb.height = 1;
|
|
dmcb.size = dmcb.width * dmcb.bpp;
|
|
dmcb.flags = flag;
|
|
|
|
if (handle == NULL)
|
|
return -1;
|
|
|
|
ret = drm_ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcb);
|
|
if (ret < 0) {
|
|
omx_err("drm_alloc fail: ret = %d", ret);
|
|
return ret;
|
|
}
|
|
*handle = dmcb.handle;
|
|
|
|
omx_trace("drm_alloc success: handle %d size %d", *handle, dmcb.size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int drm_free(int fd, RK_U32 handle)
|
|
{
|
|
struct drm_mode_destroy_dumb data = {
|
|
.handle = handle,
|
|
};
|
|
return drm_ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &data);
|
|
}
|
|
OMX_U32 Rockchip_OSAL_SharedMemory_HandleToAddress(OMX_HANDLETYPE handle, OMX_HANDLETYPE handle_ptr)
|
|
{
|
|
int map_fd = -1;
|
|
native_handle_t* pnative_handle_t = NULL;
|
|
RK_S32 err = 0;
|
|
RK_S32 mClient = 0;
|
|
RK_U32 mHandle = 0;
|
|
struct drm_rockchip_gem_phys phys_arg;
|
|
|
|
(void)handle;
|
|
|
|
pnative_handle_t = (native_handle_t*)handle_ptr;
|
|
map_fd = pnative_handle_t->data[0];
|
|
//omx_err("Rockchip_OSAL_SharedMemory_HandleToAddress map_fd = %d", map_fd);
|
|
|
|
mClient = open("/dev/dri/card0", O_RDWR);
|
|
if (mClient < 0) {
|
|
omx_err("Rockchip_OSAL_SharedMemory_HandleToAddress open drm fail");
|
|
return 0;
|
|
}
|
|
drm_fd_to_handle(mClient, (int32_t)map_fd, &mHandle, 0);
|
|
phys_arg.handle = mHandle;
|
|
err = drm_ioctl(mClient, DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS, &phys_arg);
|
|
if (err)
|
|
omx_err("failed to get phy address: %s\n", strerror(errno));
|
|
|
|
// omx_err("Rockchip_OSAL_SharedMemory_HandleToAddress phys_arg.phy_addr = %0x",phys_arg.phy_addr);
|
|
close(mClient);
|
|
mClient = -1;
|
|
return (OMX_U32)phys_arg.phy_addr;
|
|
}
|
|
|
|
|
|
|
|
OMX_U32 Rockchip_OSAL_SharedMemory_HandleToSecureAddress(OMX_HANDLETYPE handle, OMX_HANDLETYPE handle_ptr, RK_S32 size)
|
|
{
|
|
int map_fd = -1;
|
|
native_handle_t* pnative_handle_t = NULL;
|
|
RK_S32 err = 0;
|
|
RK_S32 mClient = 0;
|
|
RK_U32 mHandle = 0;
|
|
RK_U8* pBuffer = NULL;
|
|
int ret;
|
|
struct drm_mode_map_dumb dmmd;
|
|
memset(&dmmd, 0, sizeof(dmmd));
|
|
(void)handle;
|
|
|
|
pnative_handle_t = (native_handle_t*)handle_ptr;
|
|
map_fd = pnative_handle_t->data[0];
|
|
//omx_err("Rockchip_OSAL_SharedMemory_HandleToSecureAddress map_fd = %d", map_fd);
|
|
|
|
mClient = open("/dev/dri/card0", O_RDWR);
|
|
if (mClient < 0) {
|
|
omx_err("Rockchip_OSAL_SharedMemory_HandleToAddress open drm fail");
|
|
return 0;
|
|
}
|
|
drm_fd_to_handle(mClient, (int32_t)map_fd, &mHandle, 0);
|
|
//omx_err("Rockchip_OSAL_SharedMemory_HandleToSecureAddress mHandle = %d", mHandle);
|
|
dmmd.handle = mHandle;
|
|
|
|
|
|
ret = drm_ioctl(mClient, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);
|
|
if (ret < 0) {
|
|
close(mClient);
|
|
mClient = -1;
|
|
omx_err("drm_ioctl DRM_IOCTL_MODE_MAP_DUMB failed: %s\n", strerror(errno));
|
|
return ret;
|
|
}
|
|
|
|
pBuffer = (uint8_t*)drm_mmap(mClient, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmmd.offset);
|
|
if (pBuffer == MAP_FAILED) {
|
|
close(mClient);
|
|
mClient = -1;
|
|
omx_err("mmap failed:fd = %d,length = %d, %s\n", mClient, size, strerror(errno));
|
|
return -errno;
|
|
}
|
|
|
|
|
|
close(mClient);
|
|
mClient = -1;
|
|
//omx_err("Rockchip_OSAL_SharedMemory_HandleToSecureAddress pBuffer = %p", pBuffer);
|
|
return (OMX_U32)pBuffer;
|
|
}
|
|
|
|
void Rockchip_OSAL_SharedMemory_SecureUnmap(OMX_HANDLETYPE handle, OMX_HANDLETYPE handle_ptr, RK_S32 size)
|
|
{
|
|
(void)handle;
|
|
if (munmap(handle_ptr, size)) {
|
|
omx_err("ion_unmap fail");
|
|
}
|
|
}
|
|
|
|
OMX_HANDLETYPE Rockchip_OSAL_SharedMemory_Open()
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = NULL;
|
|
int IONClient = 0;
|
|
|
|
pHandle = (ROCKCHIP_SHARED_MEMORY *)malloc(sizeof(ROCKCHIP_SHARED_MEMORY));
|
|
Rockchip_OSAL_Memset(pHandle, 0, sizeof(ROCKCHIP_SHARED_MEMORY));
|
|
if (pHandle == NULL)
|
|
goto EXIT;
|
|
if (!access("/dev/dri/card0", F_OK)) {
|
|
IONClient = open("/dev/dri/card0", O_RDWR);
|
|
mem_type = MEMORY_TYPE_DRM;
|
|
} else {
|
|
IONClient = open("/dev/ion", O_RDWR);
|
|
mem_type = MEMORY_TYPE_ION;
|
|
}
|
|
|
|
if (IONClient <= 0) {
|
|
omx_err("ion_client_create Error: %d", IONClient);
|
|
Rockchip_OSAL_Free((void *)pHandle);
|
|
pHandle = NULL;
|
|
goto EXIT;
|
|
}
|
|
|
|
pHandle->fd = IONClient;
|
|
|
|
Rockchip_OSAL_MutexCreate(&pHandle->hSMMutex);
|
|
|
|
EXIT:
|
|
return (OMX_HANDLETYPE)pHandle;
|
|
}
|
|
|
|
void Rockchip_OSAL_SharedMemory_Close(OMX_HANDLETYPE handle, OMX_BOOL b_secure)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pDeleteElement = NULL;
|
|
|
|
if (pHandle == NULL)
|
|
goto EXIT;
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pCurrentElement = pSMList = pHandle->pAllocMemory;
|
|
|
|
while (pCurrentElement != NULL) {
|
|
pDeleteElement = pCurrentElement;
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
if (b_secure) {
|
|
#ifdef AVS80
|
|
native_handle_t* pnative_handle_t = NULL;
|
|
int map_fd = 0;
|
|
void *pTrueAddree = NULL;
|
|
pnative_handle_t = (native_handle_t*)pDeleteElement->mapAddr;
|
|
map_fd = pnative_handle_t->data[0];
|
|
pTrueAddree = (void *)Rockchip_OSAL_SharedMemory_HandleToSecureAddress(handle, pDeleteElement->mapAddr, pDeleteElement->allocSize);
|
|
pDeleteElement->mapAddr = pTrueAddree;
|
|
close(map_fd);
|
|
map_fd = -1;
|
|
#endif
|
|
}
|
|
if (munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
|
|
omx_err("ion_unmap fail");
|
|
}
|
|
pDeleteElement->mapAddr = NULL;
|
|
pDeleteElement->allocSize = 0;
|
|
|
|
if (pDeleteElement->owner) {
|
|
if (mem_type == MEMORY_TYPE_ION) {
|
|
ion_free(pHandle->fd, pDeleteElement->ion_hdl);
|
|
} else {
|
|
drm_free(pHandle->fd, pDeleteElement->ion_hdl);
|
|
}
|
|
}
|
|
pDeleteElement->ion_hdl = -1;
|
|
|
|
Rockchip_OSAL_Free(pDeleteElement);
|
|
|
|
mem_cnt--;
|
|
omx_trace("SharedMemory free count: %d", mem_cnt);
|
|
}
|
|
|
|
pHandle->pAllocMemory = pSMList = NULL;
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
|
|
Rockchip_OSAL_MutexTerminate(pHandle->hSMMutex);
|
|
pHandle->hSMMutex = NULL;
|
|
|
|
close(pHandle->fd);
|
|
|
|
pHandle->fd = -1;
|
|
|
|
Rockchip_OSAL_Free(pHandle);
|
|
|
|
EXIT:
|
|
return;
|
|
}
|
|
static int ion_custom_op(int ion_client, int op, void *op_data)
|
|
{
|
|
struct ion_custom_data data;
|
|
int err;
|
|
data.cmd = op;
|
|
data.arg = (unsigned long)op_data;
|
|
err = ioctl(ion_client, ION_IOC_CUSTOM, &data);
|
|
if (err < 0) {
|
|
omx_err("ION_IOC_CUSTOM (%d) failed with error - %s", op, strerror(errno));
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
OMX_PTR Rockchip_OSAL_SharedMemory_Alloc(OMX_HANDLETYPE handle, OMX_U32 size, MEMORY_TYPE memoryType)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
OMX_U32 ion_hdl = 0;
|
|
OMX_PTR pBuffer = NULL;
|
|
unsigned long phys = 0;
|
|
unsigned int mask;
|
|
unsigned int flag;
|
|
int err = 0;
|
|
int map_fd = -1;
|
|
|
|
|
|
if (pHandle == NULL)
|
|
goto EXIT;
|
|
|
|
pElement = (ROCKCHIP_SHAREDMEM_LIST *)malloc(sizeof(ROCKCHIP_SHAREDMEM_LIST));
|
|
Rockchip_OSAL_Memset(pElement, 0, sizeof(ROCKCHIP_SHAREDMEM_LIST));
|
|
pElement->owner = OMX_TRUE;
|
|
int secure_flag = 0;
|
|
|
|
switch (memoryType) {
|
|
case SECURE_MEMORY:
|
|
mask = ION_HEAP(ION_SECURE_HEAP_ID);
|
|
flag = 0;
|
|
omx_info("pHandle->fd = %d,size = %d, mem_type = %d", pHandle->fd, size, mem_type);
|
|
if (mem_type == MEMORY_TYPE_DRM) {
|
|
err = drm_alloc(pHandle->fd, size, 4096, (RK_U32 *)&ion_hdl, 0);
|
|
} else {
|
|
err = ion_alloc(pHandle->fd, size, 4096, mask, 0, (ion_user_handle_t *)&ion_hdl);
|
|
}
|
|
if (err) {
|
|
omx_err("ion_alloc failed with err (%d)", err);
|
|
goto EXIT;
|
|
}
|
|
if (err) {
|
|
omx_err("failed to get phy address: %s\n", strerror(errno));
|
|
goto EXIT;
|
|
}
|
|
|
|
secure_flag = 1;
|
|
pElement->allocSize = size;
|
|
pElement->ion_hdl = ion_hdl;
|
|
pElement->pNextMemory = NULL;
|
|
|
|
#ifdef AVS80
|
|
native_handle_t* pnative_handle_t = NULL;
|
|
pnative_handle_t = native_handle_create(1, 0);
|
|
err = drm_handle_to_fd(pHandle->fd, ion_hdl, &map_fd, 0);
|
|
if (err < 0) {
|
|
omx_err("failed to trans handle to fd: %s\n", strerror(errno));
|
|
goto EXIT;
|
|
}
|
|
omx_trace("pnative_handle_t = %p, map_fd = %d, handle = %d", pnative_handle_t, map_fd, ion_hdl);
|
|
pnative_handle_t->data[0] = map_fd;
|
|
pBuffer = (void *)pnative_handle_t;
|
|
if (mem_type == MEMORY_TYPE_DRM) {
|
|
pElement->mapAddr = (OMX_PTR)((__u64)pnative_handle_t);
|
|
} else {
|
|
pElement->mapAddr = (OMX_PTR)((__u64)pnative_handle_t);
|
|
}
|
|
#endif
|
|
break;
|
|
case SYSTEM_MEMORY:
|
|
mask = ION_HEAP(ION_VMALLOC_HEAP_ID);;
|
|
flag = 0;
|
|
break;
|
|
default:
|
|
pBuffer = NULL;
|
|
goto EXIT;
|
|
break;
|
|
}
|
|
|
|
if (!secure_flag) {
|
|
err = ion_alloc((int)pHandle->fd, size, 4096, mask, flag, (ion_user_handle_t *)&ion_hdl);
|
|
|
|
if (err < 0) {
|
|
omx_err("ion_alloc Error: %d", ion_hdl);
|
|
Rockchip_OSAL_Free((OMX_PTR)pElement);
|
|
goto EXIT;
|
|
}
|
|
|
|
err = ion_map((int)pHandle->fd, ion_hdl, size, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, (off_t)0, (unsigned char**)&pBuffer, &map_fd);
|
|
|
|
if (err) {
|
|
omx_err("ion_map Error");
|
|
ion_free(pHandle->fd, ion_hdl);
|
|
Rockchip_OSAL_Free((OMX_PTR)pElement);
|
|
pBuffer = NULL;
|
|
goto EXIT;
|
|
}
|
|
|
|
pElement->ion_hdl = ion_hdl;
|
|
pElement->mapAddr = pBuffer;
|
|
pElement->allocSize = size;
|
|
pElement->pNextMemory = NULL;
|
|
}
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pSMList = pHandle->pAllocMemory;
|
|
if (pSMList == NULL) {
|
|
pHandle->pAllocMemory = pSMList = pElement;
|
|
} else {
|
|
pCurrentElement = pSMList;
|
|
while (pCurrentElement->pNextMemory != NULL) {
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
}
|
|
pCurrentElement->pNextMemory = pElement;
|
|
}
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
|
|
mem_cnt++;
|
|
omx_trace("SharedMemory alloc count: %d", mem_cnt);
|
|
|
|
EXIT:
|
|
return pBuffer;
|
|
}
|
|
|
|
void Rockchip_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pDeleteElement = NULL;
|
|
|
|
if (pHandle == NULL)
|
|
goto EXIT;
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pSMList = pHandle->pAllocMemory;
|
|
if (pSMList == NULL) {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
goto EXIT;
|
|
}
|
|
|
|
pCurrentElement = pSMList;
|
|
if (pSMList->mapAddr == pBuffer) {
|
|
pDeleteElement = pSMList;
|
|
pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
|
|
} else {
|
|
while ((pCurrentElement != NULL) && (((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
|
|
if ((((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
|
|
pDeleteElement = pCurrentElement->pNextMemory;
|
|
pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
|
|
} else {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
omx_err("Can not find SharedMemory");
|
|
goto EXIT;
|
|
}
|
|
}
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
if (munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
|
|
omx_err("ion_unmap fail");
|
|
goto EXIT;
|
|
}
|
|
pDeleteElement->mapAddr = NULL;
|
|
pDeleteElement->allocSize = 0;
|
|
|
|
if (pDeleteElement->owner) {
|
|
if (mem_cnt == MEMORY_TYPE_ION) {
|
|
ion_free(pHandle->fd, (ion_user_handle_t)pDeleteElement->ion_hdl);
|
|
} else {
|
|
drm_free(pHandle->fd, pDeleteElement->ion_hdl);
|
|
}
|
|
}
|
|
pDeleteElement->ion_hdl = -1;
|
|
|
|
Rockchip_OSAL_Free(pDeleteElement);
|
|
|
|
mem_cnt--;
|
|
omx_trace("SharedMemory free count: %d", mem_cnt);
|
|
|
|
EXIT:
|
|
return;
|
|
}
|
|
|
|
OMX_PTR Rockchip_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, int ion_hdl)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
OMX_PTR pBuffer = NULL;
|
|
int err = 0;
|
|
int map_fd = -1;
|
|
|
|
if (pHandle == NULL)
|
|
goto EXIT;
|
|
|
|
pElement = Rockchip_OSAL_Malloc(sizeof(ROCKCHIP_SHAREDMEM_LIST));
|
|
Rockchip_OSAL_Memset(pElement, 0, sizeof(ROCKCHIP_SHAREDMEM_LIST));
|
|
|
|
if (ion_hdl == -1) {
|
|
omx_err("ion_alloc Error: %d", ion_hdl);
|
|
Rockchip_OSAL_Free((void*)pElement);
|
|
goto EXIT;
|
|
}
|
|
if (mem_type == MEMORY_TYPE_ION) {
|
|
err = ion_map(pHandle->fd, (ion_user_handle_t)ion_hdl, size, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, (off_t)0, (unsigned char**)&pBuffer, &map_fd);
|
|
if (pBuffer == NULL) {
|
|
omx_err("ion_map Error");
|
|
ion_free(pHandle->fd, (ion_user_handle_t)ion_hdl);
|
|
Rockchip_OSAL_Free((void*)pElement);
|
|
goto EXIT;
|
|
}
|
|
|
|
} else {
|
|
err = drm_map(pHandle->fd, ion_hdl, size, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, (unsigned char**)&pBuffer, &map_fd);
|
|
if (pBuffer == NULL) {
|
|
omx_err("ion_map Error");
|
|
drm_free(pHandle->fd, ion_hdl);
|
|
Rockchip_OSAL_Free((void*)pElement);
|
|
goto EXIT;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
pElement->ion_hdl = ion_hdl;
|
|
pElement->mapAddr = pBuffer;
|
|
pElement->allocSize = size;
|
|
pElement->pNextMemory = NULL;
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pSMList = pHandle->pAllocMemory;
|
|
if (pSMList == NULL) {
|
|
pHandle->pAllocMemory = pSMList = pElement;
|
|
} else {
|
|
pCurrentElement = pSMList;
|
|
while (pCurrentElement->pNextMemory != NULL) {
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
}
|
|
pCurrentElement->pNextMemory = pElement;
|
|
}
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
|
|
mem_cnt++;
|
|
omx_trace("SharedMemory alloc count: %d", mem_cnt);
|
|
|
|
EXIT:
|
|
return pBuffer;
|
|
}
|
|
|
|
void Rockchip_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, int ionfd)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pDeleteElement = NULL;
|
|
|
|
if (pHandle == NULL)
|
|
goto EXIT;
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pSMList = pHandle->pAllocMemory;
|
|
if (pSMList == NULL) {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
goto EXIT;
|
|
}
|
|
|
|
pCurrentElement = pSMList;
|
|
if (pSMList->ion_hdl == (RK_U32)ionfd) {
|
|
pDeleteElement = pSMList;
|
|
pHandle->pAllocMemory = pSMList = pSMList->pNextMemory;
|
|
} else {
|
|
while ((pCurrentElement != NULL) && (((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->ion_hdl != (RK_U32)ionfd))
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
|
|
if ((((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->ion_hdl == (RK_U32)ionfd)) {
|
|
pDeleteElement = pCurrentElement->pNextMemory;
|
|
pCurrentElement->pNextMemory = pDeleteElement->pNextMemory;
|
|
} else {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
omx_err("Can not find SharedMemory");
|
|
goto EXIT;
|
|
}
|
|
}
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
|
|
if (munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) {
|
|
omx_err("ion_unmap fail");
|
|
goto EXIT;
|
|
}
|
|
pDeleteElement->mapAddr = NULL;
|
|
pDeleteElement->allocSize = 0;
|
|
pDeleteElement->ion_hdl = -1;
|
|
|
|
Rockchip_OSAL_Free(pDeleteElement);
|
|
|
|
mem_cnt--;
|
|
omx_trace("SharedMemory free count: %d", mem_cnt);
|
|
|
|
EXIT:
|
|
return;
|
|
}
|
|
|
|
int Rockchip_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pFindElement = NULL;
|
|
if (pHandle == NULL || pBuffer == NULL)
|
|
goto EXIT;
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pSMList = pHandle->pAllocMemory;
|
|
if (pSMList == NULL) {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
goto EXIT;
|
|
}
|
|
|
|
pCurrentElement = pSMList;
|
|
if (pSMList->mapAddr == pBuffer) {
|
|
pFindElement = pSMList;
|
|
} else {
|
|
while ((pCurrentElement != NULL) && (((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer))
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
|
|
if ((((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) {
|
|
pFindElement = pCurrentElement->pNextMemory;
|
|
} else {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
omx_warn("Can not find SharedMemory");
|
|
goto EXIT;
|
|
}
|
|
}
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
|
|
EXIT:
|
|
return pFindElement->ion_hdl;
|
|
}
|
|
|
|
OMX_PTR Rockchip_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, int ion_fd)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
ROCKCHIP_SHAREDMEM_LIST *pSMList = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pCurrentElement = NULL;
|
|
ROCKCHIP_SHAREDMEM_LIST *pFindElement = NULL;
|
|
OMX_PTR pBuffer = NULL;
|
|
if (pHandle == NULL || ion_fd == -1)
|
|
goto EXIT;
|
|
|
|
Rockchip_OSAL_MutexLock(pHandle->hSMMutex);
|
|
pSMList = pHandle->pAllocMemory;
|
|
if (pSMList == NULL) {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
goto EXIT;
|
|
}
|
|
|
|
pCurrentElement = pSMList;
|
|
if (pSMList->ion_hdl == (RK_U32)ion_fd) {
|
|
pFindElement = pSMList;
|
|
} else {
|
|
while ((pCurrentElement != NULL) && (((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->ion_hdl != (RK_U32)ion_fd))
|
|
pCurrentElement = pCurrentElement->pNextMemory;
|
|
|
|
if ((((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) &&
|
|
(((ROCKCHIP_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->ion_hdl == (RK_U32)ion_fd)) {
|
|
pFindElement = pCurrentElement->pNextMemory;
|
|
} else {
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
omx_warn("Can not find SharedMemory");
|
|
goto EXIT;
|
|
}
|
|
}
|
|
Rockchip_OSAL_MutexUnlock(pHandle->hSMMutex);
|
|
|
|
pBuffer = pFindElement->mapAddr;
|
|
|
|
EXIT:
|
|
return pBuffer;
|
|
}
|
|
static OMX_S32 check_used_heaps_type()
|
|
{
|
|
// TODO, use property_get
|
|
if (!VPUClientGetIOMMUStatus()) {
|
|
return ION_HEAP(ION_CMA_HEAP_ID);
|
|
} else {
|
|
omx_trace("USE ION_SYSTEM_HEAP");
|
|
return ION_HEAP(ION_VMALLOC_HEAP_ID);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
OMX_S32 Rockchip_OSAL_SharedMemory_getPhyAddress(OMX_HANDLETYPE handle, int share_fd, OMX_U32 *phyaddress)
|
|
{
|
|
ROCKCHIP_SHARED_MEMORY *pHandle = (ROCKCHIP_SHARED_MEMORY *)handle;
|
|
int err = 0;
|
|
ion_user_handle_t ion_handle = 0;
|
|
struct ion_phys_data phys_data;
|
|
if (check_used_heaps_type() == ION_HEAP(ION_CMA_HEAP_ID)) {
|
|
err = ion_import(pHandle->fd, share_fd, &ion_handle);
|
|
if (err) {
|
|
omx_err("ion import failed, share fd %d\n", share_fd);
|
|
return err;
|
|
}
|
|
phys_data.handle = ion_handle;
|
|
err = ion_custom_op(pHandle->fd, ION_IOC_GET_PHYS, &phys_data);
|
|
*phyaddress = phys_data.phys;
|
|
ion_free(pHandle->fd, ion_handle);
|
|
} else {
|
|
*phyaddress = share_fd;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|