/*
|
* 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 <string.h>
|
|
#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;
|
}
|