/* * Copyright 2015 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. */ #include #include "mpp_mem.h" #include "mpp_env.h" #include "mpp_debug.h" #include "mpp_buffer.h" #include "vpu.h" #include "vpu_mem_legacy.h" #define VPU_MEM_DBG_FUNCTION (0x00000001) static RK_U32 vpu_mem_debug = 0; #define vpu_mem_dbg(flag, fmt, ...) _mpp_dbg(vpu_mem_debug, flag, fmt, ## __VA_ARGS__) #define vpu_mem_dbg_f(flag, fmt, ...) _mpp_dbg_f(vpu_mem_debug, flag, fmt, ## __VA_ARGS__) #define vpu_mem_dbg_func(fmt, ...) vpu_mem_dbg_f(VPU_MEM_DBG_FUNCTION, fmt, ## __VA_ARGS__) static RK_S32 commit_memory_handle(vpu_display_mem_pool *p, RK_S32 mem_hdl, RK_S32 size) { MppBufferInfo info; vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; vpu_mem_dbg_func("in pool %p hnl %p size %d\n", p, mem_hdl, size); memset(&info, 0, sizeof(MppBufferInfo)); info.type = MPP_BUFFER_TYPE_ION; info.fd = mem_hdl; info.size = size & 0x07ffffff; info.index = (size & 0xf8000000) >> 27; p_mempool->size = size; p_mempool->buff_size = size; mpp_buffer_commit(p_mempool->group, &info); vpu_mem_dbg_func("out pool %p fd %d\n", p, info.fd); return info.fd; } static void* get_free_memory_vpumem(vpu_display_mem_pool *p) { MPP_RET ret = MPP_OK; MppBuffer buffer = NULL; VPUMemLinear_t *dmabuf = mpp_calloc(VPUMemLinear_t, 1); vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; if (dmabuf == NULL) { return NULL; } vpu_mem_dbg_func("in pool %p\n", p); ret = mpp_buffer_get(p_mempool->group, &buffer, p_mempool->size); if (MPP_OK != ret) { mpp_free(dmabuf); return NULL; } dmabuf->phy_addr = (RK_U32)mpp_buffer_get_fd(buffer); dmabuf->vir_addr = (RK_U32*)mpp_buffer_get_ptr(buffer); dmabuf->size = p_mempool->size; dmabuf->offset = (RK_U32*)buffer; vpu_mem_dbg_func("out pool %p ret %p fd %d size %d buffer %p\n", p, dmabuf, dmabuf->phy_addr, dmabuf->size, buffer); return dmabuf; } static RK_S32 inc_used_memory_handle_ref(vpu_display_mem_pool *p, void * hdl) { VPUMemLinear_t *dmabuf = (VPUMemLinear_t *)hdl; MppBuffer buffer = (MppBuffer)dmabuf->offset; vpu_mem_dbg_func("pool %p hnd %p buffer %p\n", p, hdl, buffer); if (buffer != NULL) { mpp_buffer_inc_ref(buffer); } (void)p; return MPP_OK; } static RK_S32 put_used_memory_handle(vpu_display_mem_pool *p, void *hdl) { VPUMemLinear_t *dmabuf = (VPUMemLinear_t *)hdl; MppBuffer buf = (MppBuffer)dmabuf->offset; vpu_mem_dbg_func("pool %p hnd %p buffer %p\n", p, hdl, buf); if (buf != NULL) { mpp_buffer_put(buf); memset(dmabuf, 0, sizeof(VPUMemLinear_t)); } (void)p; return MPP_OK; } static RK_S32 get_free_memory_num(vpu_display_mem_pool *p) { vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; RK_S32 ret = (p_mempool->group) ? (mpp_buffer_group_unused(p_mempool->group)) : (0); vpu_mem_dbg_func("pool %p ret %d\n", p, ret); return ret; } static RK_S32 reset_vpu_mem_pool(vpu_display_mem_pool *p) { vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; mpp_buffer_group_clear(p_mempool->group); return 0; } vpu_display_mem_pool* open_vpu_memory_pool() { vpu_display_mem_pool_impl *p_mempool = mpp_calloc(vpu_display_mem_pool_impl, 1); mpp_env_get_u32("vpu_mem_debug", &vpu_mem_debug, 0); vpu_mem_dbg_func("in pool %p\n", p_mempool); if (NULL == p_mempool) { return NULL; } mpp_buffer_group_get_external(&p_mempool->group, MPP_BUFFER_TYPE_ION); if (NULL == p_mempool->group) { return NULL; } p_mempool->commit_hdl = commit_memory_handle; p_mempool->get_free = get_free_memory_vpumem; p_mempool->put_used = put_used_memory_handle; p_mempool->inc_used = inc_used_memory_handle_ref; p_mempool->reset = reset_vpu_mem_pool; p_mempool->get_unused_num = get_free_memory_num; p_mempool->version = 1; p_mempool->buff_size = -1; vpu_mem_dbg_func("out pool %p group %p\n", p_mempool, p_mempool->group); return (vpu_display_mem_pool*)p_mempool; } void close_vpu_memory_pool(vpu_display_mem_pool *p) { vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; vpu_mem_dbg_func("pool %p group %p\n", p_mempool, p_mempool->group); mpp_buffer_group_put(p_mempool->group); mpp_free(p_mempool); return; } int create_vpu_memory_pool_allocator(vpu_display_mem_pool **ipool, int num, int size) { vpu_display_mem_pool_impl *p_mempool = mpp_calloc(vpu_display_mem_pool_impl, 1); mpp_env_get_u32("vpu_mem_debug", &vpu_mem_debug, 0); vpu_mem_dbg_func("in pool %p num %d size %d\n", p_mempool, num, size); if (NULL == p_mempool) return -1; mpp_buffer_group_get_internal(&p_mempool->group, MPP_BUFFER_TYPE_ION); mpp_buffer_group_limit_config(p_mempool->group, 0, num + 4); p_mempool->commit_hdl = commit_memory_handle; p_mempool->get_free = get_free_memory_vpumem; p_mempool->put_used = put_used_memory_handle; p_mempool->inc_used = inc_used_memory_handle_ref; p_mempool->reset = reset_vpu_mem_pool; p_mempool->get_unused_num = get_free_memory_num; p_mempool->version = 0; p_mempool->buff_size = size; p_mempool->size = size; *ipool = (vpu_display_mem_pool*)p_mempool; vpu_mem_dbg_func("out pool %p group %p\n", p_mempool, p_mempool->group); return 0; } void release_vpu_memory_pool_allocator(vpu_display_mem_pool *ipool) { vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)ipool; if (p_mempool == NULL) return; vpu_mem_dbg_func("pool %p group %p\n", p_mempool, p_mempool->group); if (p_mempool->group) { mpp_buffer_group_put(p_mempool->group); p_mempool->group = NULL; } vpu_mem_dbg_func("free %p\n", p_mempool); mpp_free(p_mempool); return; } RK_S32 VPUMemJudgeIommu() { int ret = 0; if (VPUClientGetIOMMUStatus() > 0) { //mpp_err("media.used.iommu"); ret = 1; } return ret; } RK_S32 VPUMallocLinear(VPUMemLinear_t *p, RK_U32 size) { int ret = 0; MppBuffer buffer = NULL; ret = mpp_buffer_get(NULL, &buffer, size); if (ret != MPP_OK) { return -1; } p->phy_addr = (RK_U32)mpp_buffer_get_fd(buffer); p->vir_addr = (RK_U32*)mpp_buffer_get_ptr(buffer); p->size = size; p->offset = (RK_U32*)buffer; return 0; } RK_S32 VPUMallocLinearFromRender(VPUMemLinear_t *p, RK_U32 size, void *ctx) { VPUMemLinear_t *dma_buf = NULL; vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)ctx; if (ctx == NULL) { return VPUMallocLinear(p, size); } dma_buf = (VPUMemLinear_t *) p_mempool->get_free((vpu_display_mem_pool *)ctx); memset(p, 0, sizeof(VPUMemLinear_t)); if (dma_buf != NULL) { if (dma_buf->size < size) { mpp_free(dma_buf); return -1; } memcpy(p, dma_buf, sizeof(VPUMemLinear_t)); mpp_free(dma_buf); return 0; } return -1; } RK_S32 VPUFreeLinear(VPUMemLinear_t *p) { if (p->offset != NULL) { put_used_memory_handle(NULL, p); } return 0; } RK_S32 VPUMemDuplicate(VPUMemLinear_t *dst, VPUMemLinear_t *src) { MppBuffer buffer = (MppBuffer)src->offset; if (buffer != NULL) { mpp_buffer_inc_ref(buffer); } memcpy(dst, src, sizeof(VPUMemLinear_t)); return 0; } RK_S32 VPUMemLink(VPUMemLinear_t *p) { (void)p; return 0; } RK_S32 VPUMemFlush(VPUMemLinear_t *p) { (void)p; return 0; } RK_S32 VPUMemClean(VPUMemLinear_t *p) { (void)p; return 0; } RK_S32 VPUMemInvalidate(VPUMemLinear_t *p) { (void)p; return 0; } RK_S32 VPUMemGetFD(VPUMemLinear_t *p) { RK_S32 fd = 0; MppBuffer buffer = (MppBuffer)p->offset; fd = mpp_buffer_get_fd(buffer); return fd; }