Files
2026-08-24 10:03:24 +08:00

1825 lines
48 KiB
C

/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in below
* which is part of this source code package.
*
* Description:
*/
// Copyright (C) 2019 Amlogic, Inc. All rights reserved.
//
// All information contained herein is Amlogic confidential.
//
// This software is provided to you pursuant to Software License
// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
// used only in accordance with the terms of this agreement.
//
// Redistribution and use in source and binary forms, with or without
// modification is strictly prohibited without prior written permission
// from Amlogic.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define LOG_TAG "vdi"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h> /* SIGIO */
#include <fcntl.h> /* fcntl */
#include <pthread.h>
#include <sys/mman.h> /* mmap */
#include <sys/ioctl.h> /* fopen/fread */
#include <sys/errno.h> /* fopen/fread */
#include <sys/types.h>
#include <sys/time.h>
#include "vdi.h"
#include "vdi_osal.h"
#include "enc_regdefine.h"
#include "vpuapi.h"
#include "debug.h"
#define VPU_DEVICE_NAME "/dev/amvenc_multi"
typedef pthread_mutex_t MUTEX_HANDLE;
#define VDI_SRAM_BASE_ADDR 0x00000000 // if we can know the sram address in SOC directly for vdi layer. it is possible to set in vdi layer without allocation from driver
#define INIT_RETRY 100
#define VDI_SYSTEM_ENDIAN VDI_LITTLE_ENDIAN
#define VDI_128BIT_BUS_SYSTEM_ENDIAN VDI_128BIT_LITTLE_ENDIAN
#define VPU_BIT_REG_SIZE (0x4000*MAX_NUM_VPU_CORE)
#define VDI_VP521C_SRAM_SIZE 0x23000 /* 10bit profile : 8Kx8K -> 143360, 4Kx2K -> 71680
* 8bit profile : 8Kx8K -> 114688, 4Kx2K -> 57344
* NOTE: Decoder > Encoder
*/
#define VDI_NUM_LOCK_HANDLES 4
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
#define VPU_CORE_BASE_OFFSET 0x4000
#endif
enum
{
INIT_VDI_STAT_NULL = 0,
INIT_VDI_STAT_INIT = 1,
INIT_VDI_STAT_OPENING = 2,
INIT_VDI_STAT_ALLOC = 3,
INIT_VDI_STAT_DONE = 4,
};
typedef struct vpu_buffer_t vpudrv_buffer_t;
typedef struct vpudrv_buffer_pool_t
{
vpudrv_buffer_t vdb;
int inuse;
} vpudrv_buffer_pool_t;
typedef struct {
unsigned long core_idx;
unsigned int product_code;
int vpu_fd;
vpu_instance_pool_t *pvip;
#ifdef AML_FIXED_FOR_GLIBC_2_33
int shared_mutex_fd;
void* shared_mutex_map;
#endif
int task_num;
int clock_state;
vpudrv_buffer_t vdb_register;
vpu_buffer_t vpu_common_memory;
vpudrv_buffer_pool_t vpu_buffer_pool[MAX_VPU_BUFFER_POOL];
int vpu_buffer_pool_count;
void* vpu_mutex;
void* vpu_omx_mutex;
void* vpu_disp_mutex;
void* vmem_mutex;
} vdi_info_t;
static vdi_info_t s_vdi_info[MAX_NUM_VPU_CORE];
static int vdi_init_flag[MAX_NUM_VPU_CORE] = {0};
static pthread_mutex_t vid_mutex = PTHREAD_MUTEX_INITIALIZER;
static int swap_endian(u32 core_idx, unsigned char *data, int len, int endian);
static void restore_mutex_in_dead(MUTEX_HANDLE *mutex)
{
int mutex_value;
if (!mutex)
return;
#if 0 // defined(ANDROID)
mutex_value = mutex->value;
#else
memcpy(&mutex_value, mutex, sizeof(mutex_value));
#endif
if (mutex_value == (int)0xdead10cc) // destroy by device driver
{
pthread_mutexattr_t mutexattr;
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mutex, &mutexattr);
}
}
static void vmem_lock(vdi_info_t* vdi)
{
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
#else
const int MUTEX_TIMEOUT = 0x7fffffff;
#endif
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
restore_mutex_in_dead((MUTEX_HANDLE *)vdi->vmem_mutex);
pthread_mutex_lock((MUTEX_HANDLE*)vdi->vmem_mutex);
#else
if (pthread_mutex_lock((MUTEX_HANDLE *)vdi->vmem_mutex) != 0) {
VLOG(ERR, "%s:%d failed to pthread_mutex_locK\n", __FUNCTION__, __LINE__);
}
#endif
return;
}
static void vmem_unlock(vdi_info_t* vdi)
{
pthread_mutex_unlock((MUTEX_HANDLE *)vdi->vmem_mutex);
}
int vdi_probe(u32 core_idx)
{
int ret;
ret = vdi_init(core_idx);
vdi_release(core_idx);
return ret;
}
int vdi_init(u32 core_idx)
{
vdi_info_t *vdi;
int i, retry_cnt = 0;
if (core_idx >= MAX_NUM_VPU_CORE)
return 0;
pthread_mutex_lock(&vid_mutex);
if (vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL) {
vdi_init_flag[core_idx] = INIT_VDI_STAT_INIT;
memset(&s_vdi_info[core_idx], 0x00, sizeof(s_vdi_info));
s_vdi_info[core_idx].vpu_fd = -1;
}
vdi = &s_vdi_info[core_idx];
if (vdi->vpu_fd != -1 && vdi_init_flag[core_idx] == INIT_VDI_STAT_DONE)
{
VLOG(ERR, "[VDI] opend already.\n");
vdi->task_num++;
pthread_mutex_unlock(&vid_mutex);
return 0;
}
vdi_init_flag[core_idx] = INIT_VDI_STAT_OPENING;
retry:
vdi->vpu_fd = open(VPU_DEVICE_NAME, O_RDWR);
if (vdi->vpu_fd < 0) {
if (retry_cnt >= INIT_RETRY) {
VLOG(ERR, "[VDI] Can't open vpu driver. [error=%s]\n", strerror(errno));
vdi_init_flag[core_idx] = INIT_VDI_STAT_DONE;
pthread_mutex_unlock(&vid_mutex);
return -1;
} else {
VLOG(ERR,"[VDI] Init open vpu driver fail retrying \n");
retry_cnt ++;
pthread_mutex_unlock(&vid_mutex);
osal_msleep(100);
pthread_mutex_lock(&vid_mutex);
goto retry;
}
}
memset(vdi->vpu_buffer_pool, 0x00, sizeof(vpudrv_buffer_pool_t)*MAX_VPU_BUFFER_POOL);
vdi_init_flag[core_idx] = INIT_VDI_STAT_ALLOC;
if (!vdi_get_instance_pool(core_idx))
{
VLOG(INFO, "[VDI] fail to create shared info for saving context \n");
goto ERR_VDI_INIT;
}
if (vdi->pvip->instance_pool_inited == FALSE)
{
int* pCodecInst;
pthread_mutexattr_t mutexattr;
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
#else
/* If a process or a thread is terminated abnormally,
* pthread_mutexattr_setrobust_np(attr, PTHREAD_MUTEX_ROBUST_NP) makes
* next onwer call pthread_mutex_lock() without deadlock.
*/
pthread_mutexattr_setrobust_np(&mutexattr, PTHREAD_MUTEX_ROBUST_NP);
#endif
pthread_mutex_init((MUTEX_HANDLE *)vdi->vpu_mutex, &mutexattr);
pthread_mutex_init((MUTEX_HANDLE *)vdi->vpu_disp_mutex, &mutexattr);
pthread_mutex_init((MUTEX_HANDLE *)vdi->vmem_mutex, &mutexattr);
for ( i = 0; i < MAX_NUM_INSTANCE; i++) {
pCodecInst = (int *)vdi->pvip->codecInstPool[i];
pCodecInst[1] = i; // indicate instIndex of CodecInst
pCodecInst[0] = 0; // indicate inUse of CodecInst
}
vdi->pvip->instance_pool_inited = TRUE;
}
if (ioctl(vdi->vpu_fd, VDI_IOCTL_GET_REGISTER_INFO, &vdi->vdb_register) < 0)
{
VLOG(ERR, "[VDI] fail to get host interface register\n");
goto ERR_VDI_INIT;
}
vdi->vdb_register.virt_addr = (unsigned long)mmap(NULL, vdi->vdb_register.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdi->vpu_fd, vdi->vdb_register.phys_addr);
if ((void *)vdi->vdb_register.virt_addr == MAP_FAILED)
{
VLOG(ERR, "[VDI] fail to map vpu registers \n");
goto ERR_VDI_INIT;
}
VLOG(INFO, "[VDI] map vdb_register core_idx=%d, virtaddr=0x%lx, size=%d\n", core_idx, vdi->vdb_register.virt_addr, vdi->vdb_register.size);
vdi_set_clock_gate(core_idx, 1);
vdi->product_code = vdi_read_register(core_idx, VPU_PRODUCT_CODE_REGISTER);
vdi_set_clock_gate(core_idx, 0);
if (vdi_lock(core_idx) < 0)
{
VLOG(ERR, "[VDI] fail to handle lock function\n");
goto ERR_VDI_INIT;
}
if (vdi_allocate_common_memory(core_idx) < 0)
{
VLOG(ERR, "[VDI] fail to get vpu common buffer from driver\n");
goto ERR_VDI_INIT;
}
vdi->core_idx = core_idx;
vdi->task_num++;
vdi_unlock(core_idx);
vdi_init_flag[core_idx] = INIT_VDI_STAT_DONE;
pthread_mutex_unlock(&vid_mutex);
VLOG(INFO, "[VDI] success to init driver \n");
return 0;
ERR_VDI_INIT:
vdi_unlock(core_idx);
vdi_init_flag[core_idx] = INIT_VDI_STAT_DONE;
pthread_mutex_unlock(&vid_mutex);
vdi_release(core_idx);
return -1;
}
int vdi_set_bit_firmware_to_pm(u32 core_idx, const u16 *code)
{
int i;
vpu_bit_firmware_info_t bit_firmware_info;
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return 0;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return 0;
bit_firmware_info.size = sizeof(vpu_bit_firmware_info_t);
bit_firmware_info.core_idx = core_idx;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
bit_firmware_info.reg_base_offset = (core_idx*VPU_CORE_BASE_OFFSET);
#else
bit_firmware_info.reg_base_offset = 0;
#endif
for (i=0; i<512; i++)
bit_firmware_info.bit_code[i] = code[i];
if (write(vdi->vpu_fd, &bit_firmware_info, bit_firmware_info.size) < 0)
{
VLOG(ERR, "[VDI] fail to vdi_set_bit_firmware core=%d\n", bit_firmware_info.core_idx);
return -1;
}
return 0;
}
#if defined(SUPPORT_SW_UART) || defined(SUPPORT_SW_UART_V2)
int vdi_get_task_num(unsigned long core_idx)
{
vdi_info_t *vdi;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
return vdi->task_num;
}
#endif
int vdi_release(u32 core_idx)
{
int i;
vpudrv_buffer_t vdb;
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return 0;
pthread_mutex_lock(&vid_mutex);
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL) {
pthread_mutex_unlock(&vid_mutex);
return 0;
}
if (vdi_lock(core_idx) < 0)
{
VLOG(ERR, "[VDI] fail to handle lock function\n");
pthread_mutex_unlock(&vid_mutex);
return -1;
}
if (vdi->task_num > 1) // means that the opened instance remains
{
vdi->task_num--;
vdi_unlock(core_idx);
pthread_mutex_unlock(&vid_mutex);
return 0;
}
if (vdi->vdb_register.virt_addr)
munmap((void *)vdi->vdb_register.virt_addr, vdi->vdb_register.size);
osal_memset(&vdi->vdb_register, 0x00, sizeof(vpudrv_buffer_t));
vdb.size = 0;
// get common memory information to free virtual address
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_common_memory.phys_addr >= vdi->vpu_buffer_pool[i].vdb.phys_addr &&
vdi->vpu_common_memory.phys_addr < (vdi->vpu_buffer_pool[i].vdb.phys_addr + vdi->vpu_buffer_pool[i].vdb.size))
{
vdi->vpu_buffer_pool[i].inuse = 0;
vdi->vpu_buffer_pool_count--;
vdb = vdi->vpu_buffer_pool[i].vdb;
break;
}
}
vdi_unlock(core_idx);
//pthread_mutex_lock(&vid_mutex);
if (vdb.size > 0)
{
munmap((void *)vdb.virt_addr, vdb.size);
memset(&vdi->vpu_common_memory, 0x00, sizeof(vpu_buffer_t));
}
vdi->task_num--;
if (vdi->pvip)
munmap(vdi->pvip, (sizeof(vpu_instance_pool_t) + sizeof(MUTEX_HANDLE) * VDI_NUM_LOCK_HANDLES));
#ifdef AML_FIXED_FOR_GLIBC_2_33
if (vdi->shared_mutex_map)
munmap(vdi->shared_mutex_map, sizeof(MUTEX_HANDLE) * VDI_NUM_LOCK_HANDLES);
if (vdi->shared_mutex_fd) {
close(vdi->shared_mutex_fd);
vdi->shared_mutex_fd = -1;
}
#endif
if (vdi->vpu_fd != -1 && vdi_init_flag[core_idx] != INIT_VDI_STAT_NULL)
{
close(vdi->vpu_fd);
vdi->vpu_fd = -1;
}
vdi_init_flag[core_idx] = INIT_VDI_STAT_NULL;
memset(vdi, 0x00, sizeof(vdi_info_t));
pthread_mutex_unlock(&vid_mutex);
return 0;
}
int vdi_get_common_memory(u32 core_idx, vpu_buffer_t *vb)
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memcpy(vb, &vdi->vpu_common_memory, sizeof(vpu_buffer_t));
return 0;
}
int vdi_allocate_common_memory(u32 core_idx)
{
vdi_info_t *vdi = &s_vdi_info[core_idx];
vpudrv_buffer_t vdb;
int i;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
vdb.size = SIZE_COMMON*MAX_NUM_VPU_CORE;
if (ioctl(vdi->vpu_fd, VDI_IOCTL_GET_COMMON_MEMORY, &vdb) < 0)
{
VLOG(ERR, "[VDI] fail to vdi_allocate_dma_memory size=%d\n", vdb.size);
return -1;
}
vdb.virt_addr = (unsigned long)mmap(NULL, vdb.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdi->vpu_fd, vdb.phys_addr);
if ((void *)vdb.virt_addr == MAP_FAILED)
{
VLOG(ERR, "[VDI] fail to map common memory phyaddr=0x%lx, size = %d\n", (ulong)vdb.phys_addr, (int)vdb.size);
return -1;
}
VLOG(INFO, "[VDI] vdi_allocate_common_memory, physaddr=0x%lx, virtaddr=0x%lx\n", (ulong)vdb.phys_addr, (ulong)vdb.virt_addr);
// convert os driver buffer type to vpu buffer type
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
vdi->pvip->vpu_common_buffer.size = SIZE_COMMON;
vdi->pvip->vpu_common_buffer.phys_addr = (ulong)(vdb.phys_addr + (core_idx*SIZE_COMMON));
vdi->pvip->vpu_common_buffer.base = (ulong)(vdb.base + (core_idx*SIZE_COMMON));
vdi->pvip->vpu_common_buffer.virt_addr = (ulong)(vdb.virt_addr + (core_idx*SIZE_COMMON));
#else
vdi->pvip->vpu_common_buffer.size = SIZE_COMMON;
vdi->pvip->vpu_common_buffer.phys_addr = (ulong)(vdb.phys_addr);
vdi->pvip->vpu_common_buffer.base = (ulong)(vdb.base);
vdi->pvip->vpu_common_buffer.virt_addr = (ulong)(vdb.virt_addr);
#endif
osal_memcpy(&vdi->vpu_common_memory, &vdi->pvip->vpu_common_buffer, sizeof(vpudrv_buffer_t));
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].inuse == 0)
{
vdi->vpu_buffer_pool[i].vdb = vdb;
vdi->vpu_buffer_pool_count++;
vdi->vpu_buffer_pool[i].inuse = 1;
break;
}
}
VLOG(INFO, "[VDI] vdi_get_common_memory physaddr=0x%lx, size=%d, virtaddr=0x%lx\n", (ulong)vdi->vpu_common_memory.phys_addr, (int)vdi->vpu_common_memory.size, (ulong)vdi->vpu_common_memory.virt_addr);
return 0;
}
vpu_instance_pool_t *vdi_get_instance_pool(u32 core_idx)
{
vdi_info_t *vdi;
vpudrv_buffer_t vdb;
if (core_idx >= MAX_NUM_VPU_CORE)
return NULL;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return NULL;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
if (!vdi->pvip)
{
vdb.size = sizeof(vpu_instance_pool_t) + sizeof(MUTEX_HANDLE)*VDI_NUM_LOCK_HANDLES;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
vdb.size *= MAX_NUM_VPU_CORE;
#endif
if (ioctl(vdi->vpu_fd, VDI_IOCTL_GET_INSTANCE_POOL, &vdb) < 0)
{
VLOG(ERR, "[VDI] fail to allocate get instance pool physical space=%d\n", (int)vdb.size);
return NULL;
}
vdb.virt_addr = (ulong)mmap(NULL, vdb.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdi->vpu_fd, 0);
if (vdb.virt_addr == (ulong)MAP_FAILED)
{
VLOG(ERR, "[VDI] fail to map instance pool phyaddr=0x%x, size = %d\n", (int)vdb.phys_addr, (int)vdb.size);
return NULL;
}
#ifdef AML_FIXED_FOR_GLIBC_2_33
int shared_mutex_fd = open(VPU_SHARED_FILE_NAME, O_CREAT|O_RDWR, 00777);
if (shared_mutex_fd < 0) {
VLOG(ERR,
"[VDI] Can't open %s. [error=%s]\n"
"Maybe this file has been created by others\n",
VPU_SHARED_FILE_NAME, strerror(errno));
munmap((void *)vdb.virt_addr, vdb.size);
return NULL;
}
if (ftruncate(shared_mutex_fd, VPU_SHARED_FILE_SIZE) != 0) {
VLOG(ERR, "[VDI] Can't truncate %s. [error=%s]\n",
VPU_SHARED_FILE_NAME, strerror(errno));
close(shared_mutex_fd);
shared_mutex_fd = -1;
munmap((void *)vdb.virt_addr, vdb.size);
return NULL;
}
void *shared_mutex_map = mmap(NULL, VPU_SHARED_FILE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED, shared_mutex_fd, 0);
if (shared_mutex_map == MAP_FAILED) {
VLOG(ERR, "[VDI] fail to map vpu shared file=0x%lx, size = %d\n",
(unsigned long)shared_mutex_map, VPU_SHARED_FILE_SIZE);
close(shared_mutex_fd);
shared_mutex_fd = -1;
munmap((void *)vdb.virt_addr, vdb.size);
return NULL;
}
vdi->shared_mutex_fd = shared_mutex_fd;
vdi->shared_mutex_map = shared_mutex_map;
#endif
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
vdi->pvip = (vpu_instance_pool_t *)(vdb.virt_addr + (core_idx*(sizeof(vpu_instance_pool_t) + sizeof(MUTEX_HANDLE)*VDI_NUM_LOCK_HANDLES)));
#else
vdi->pvip = (vpu_instance_pool_t *)(vdb.virt_addr);
#endif
#ifdef AML_FIXED_FOR_GLIBC_2_33
vdi->vpu_mutex = vdi->shared_mutex_map;
// Unused Mutex
vdi->vpu_disp_mutex =
(void*)((unsigned long)vdi->shared_mutex_map + sizeof(MUTEX_HANDLE));
vdi->vmem_mutex =
(void*)((unsigned long)vdi->shared_mutex_map + 2 * sizeof(MUTEX_HANDLE));
#else
vdi->vpu_mutex = (void *)((ulong)vdi->pvip + sizeof(vpu_instance_pool_t)); //change the pointer of vpu_mutex to at end pointer of vpu_instance_pool_t to assign at allocated position.
vdi->vpu_disp_mutex = (void *)((ulong)vdi->pvip + sizeof(vpu_instance_pool_t) + sizeof(MUTEX_HANDLE));
vdi->vmem_mutex = (void *)((unsigned long)vdi->pvip + sizeof(vpu_instance_pool_t) + 2*sizeof(MUTEX_HANDLE));
#endif
VLOG(INFO, "[VDI] instance pool physaddr=0x%x, virtaddr=0x%x, base=0x%x, size=%d\n", (int)vdb.phys_addr, (int)vdb.virt_addr, (int)vdb.base, (int)vdb.size);
}
return (vpu_instance_pool_t *)vdi->pvip;
}
int vdi_open_instance(u32 core_idx, u32 inst_idx)
{
vdi_info_t *vdi;
vpudrv_inst_info_t inst_info;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
inst_info.core_idx = core_idx;
inst_info.inst_idx = inst_idx;
if (ioctl(vdi->vpu_fd, VDI_IOCTL_OPEN_INSTANCE, &inst_info) < 0)
{
VLOG(ERR, "[VDI] fail to deliver open instance num inst_idx=%d\n", (int)inst_idx);
return -1;
}
vdi->pvip->vpu_instance_num = inst_info.inst_open_count;
return 0;
}
int vdi_close_instance(u32 core_idx, u32 inst_idx)
{
vdi_info_t *vdi;
vpudrv_inst_info_t inst_info = {0, };
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
inst_info.core_idx = core_idx;
inst_info.inst_idx = inst_idx;
if (ioctl(vdi->vpu_fd, VDI_IOCTL_CLOSE_INSTANCE, &inst_info) < 0)
{
VLOG(ERR, "[VDI] fail to deliver open instance num inst_idx=%d\n", (int)inst_idx);
return -1;
}
vdi->pvip->vpu_instance_num = inst_info.inst_open_count;
return 0;
}
int vdi_sys_sync_inst_param(struct vpudrv_inst_param_t *pvip)
{
vdi_info_t *vdi;
if (pvip->core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[pvip->core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[pvip->core_idx] == INIT_VDI_STAT_NULL)
return -1;
if (ioctl(vdi->vpu_fd, VDI_IOCTL_SYNC_INSTANCE_PARAM, pvip) < 0)
{
VLOG(ERR, "[VDI] fail to deliver sync instance param inst_idx=%d\n", (int)pvip->inst_idx);
return -1;
}
return 0;
}
u32 vdi_get_instance_num(u32 core_idx)
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
return vdi->pvip->vpu_instance_num;
}
int vdi_hw_reset(u32 core_idx) // DEVICE_ADDR_SW_RESET
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
return ioctl(vdi->vpu_fd, VDI_IOCTL_RESET, 0);
}
int vdi_lock(u32 core_idx)
{
vdi_info_t *vdi;
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
#else
const int MUTEX_TIMEOUT = 0x7fffffff;
#endif
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
restore_mutex_in_dead((MUTEX_HANDLE *)vdi->vpu_mutex);
pthread_mutex_lock((MUTEX_HANDLE*)vdi->vpu_mutex);
#else
if (pthread_mutex_lock((MUTEX_HANDLE *)vdi->vpu_mutex) != 0) {
VLOG(ERR, "%s:%d failed to pthread_mutex_locK\n", __FUNCTION__, __LINE__);
return -1;
}
#endif
return 0;
}
void vdi_unlock(u32 core_idx)
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return;
pthread_mutex_unlock((MUTEX_HANDLE *)vdi->vpu_mutex);//lint !e455
}
int vdi_disp_lock(u32 core_idx)
{
vdi_info_t *vdi;
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
#else
const int MUTEX_TIMEOUT = 5000; // ms
#endif
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
#if defined(ANDROID) || !defined(PTHREAD_MUTEX_ROBUST_NP)
restore_mutex_in_dead((MUTEX_HANDLE *)vdi->vpu_disp_mutex);
pthread_mutex_lock((MUTEX_HANDLE*)vdi->vpu_disp_mutex);
#else
if (pthread_mutex_lock((MUTEX_HANDLE *)vdi->vpu_disp_mutex) != 0)
VLOG(ERR, "%s:%d failed to pthread_mutex_lock\n", __FUNCTION__, __LINE__);
return -1;
}
#endif /* ANDROID */
return 0;//lint !e454
}
void vdi_disp_unlock(u32 core_idx)
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return;
pthread_mutex_unlock((MUTEX_HANDLE *)vdi->vpu_disp_mutex);//lint !e455
}
void vdi_write_register(u32 core_idx, unsigned int addr, unsigned int data)
{
vdi_info_t *vdi;
unsigned long *reg_addr;
if (core_idx >= MAX_NUM_VPU_CORE)
return;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
reg_addr = (unsigned long *)(addr + (unsigned long)vdi->vdb_register.virt_addr + (core_idx*VPU_CORE_BASE_OFFSET));
#else
reg_addr = (unsigned long *)(addr + (unsigned long)vdi->vdb_register.virt_addr);
#endif
*(volatile unsigned int *)reg_addr = data;
}
unsigned int vdi_read_register(u32 core_idx, unsigned int addr)
{
vdi_info_t *vdi;
unsigned long *reg_addr;
if (core_idx >= MAX_NUM_VPU_CORE)
return (unsigned int)-1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return (unsigned int)-1;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
reg_addr = (unsigned long *)(addr + (unsigned long)vdi->vdb_register.virt_addr + (core_idx*VPU_CORE_BASE_OFFSET));
#else
reg_addr = (unsigned long *)(addr + (unsigned long)vdi->vdb_register.virt_addr);
#endif
return *(volatile unsigned int *)reg_addr;
}
#define FIO_TIMEOUT 100
unsigned int vdi_fio_read_register(u32 core_idx, unsigned int addr)
{
unsigned int ctrl;
unsigned int count = 0;
unsigned int data = 0xffffffff;
ctrl = (addr&0xffff);
ctrl |= (0<<16); /* read operation */
vdi_write_register(core_idx, VP5_VPU_FIO_CTRL_ADDR, ctrl);
count = FIO_TIMEOUT;
while (count--) {
ctrl = vdi_read_register(core_idx, VP5_VPU_FIO_CTRL_ADDR);
if (ctrl & 0x80000000) {
data = vdi_read_register(core_idx, VP5_VPU_FIO_DATA);
break;
}
}
return data;
}
void vdi_fio_write_register(u32 core_idx, unsigned int addr, unsigned int data)
{
unsigned int ctrl;
unsigned int count = 0;
vdi_write_register(core_idx, VP5_VPU_FIO_DATA, data);
ctrl = (addr&0xffff);
ctrl |= (1<<16); /* write operation */
vdi_write_register(core_idx, VP5_VPU_FIO_CTRL_ADDR, ctrl);
count = FIO_TIMEOUT;
while (count--) {
ctrl = vdi_read_register(core_idx, VP5_VPU_FIO_CTRL_ADDR);
if (ctrl & 0x80000000) {
break;
}
}
}
int vdi_clear_memory(u32 core_idx, PhysicalAddress addr, int len, int endian)
{
vdi_info_t *vdi;
vpudrv_buffer_t vdb;
unsigned long offset;
int i;
Uint8* zero;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
if(endian > VDI_ENDIAN_MAX) return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].inuse == 1)
{
vdb = vdi->vpu_buffer_pool[i].vdb;
if (addr >= vdb.phys_addr && addr < (vdb.phys_addr + vdb.size))
break;
}
}
if (!vdb.size) {
VLOG(ERR, "address 0x%08x is not mapped address!!!\n", (int)addr);
return -1;
}
zero = (Uint8*)osal_malloc(len);
osal_memset((void*)zero, 0x00, len);
offset = addr - (unsigned long)vdb.phys_addr;
osal_memcpy((void *)((unsigned long)vdb.virt_addr+offset), zero, len);
osal_free(zero);
vdb.phys_addr = addr;
vdb.size = len;
vdi_flush_memory(core_idx, &vdb);
return len;
}
int vdi_set_memory(u32 core_idx, PhysicalAddress addr, int len, int endian, Uint32 data)
{
vdi_info_t *vdi;
vpudrv_buffer_t vdb;
unsigned long offset;
int i;
Uint8* zero;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
if (endian > VDI_ENDIAN_MAX) return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].inuse == 1)
{
vdb = vdi->vpu_buffer_pool[i].vdb;
if (addr >= vdb.phys_addr && addr < (vdb.phys_addr + vdb.size))
break;
}
}
if (!vdb.size) {
VLOG(ERR, "address 0x%08x is not mapped address!!!\n", (int)addr);
return -1;
}
zero = (Uint8*)osal_malloc(len);
osal_memset((void*)zero, data, len);
offset = addr - (unsigned long)vdb.phys_addr;
osal_memcpy((void *)((unsigned long)vdb.virt_addr+offset), zero, len);
osal_free(zero);
vdb.phys_addr = addr;
vdb.size = len;
vdi_flush_memory(core_idx, &vdb);
return len;
}
int vdi_write_memory(u32 core_idx, PhysicalAddress addr, unsigned char *data, int len, int endian)
{
vdi_info_t *vdi;
vpudrv_buffer_t vdb;
unsigned long offset;
int i;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
if (!data)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].inuse == 1)
{
vdb = vdi->vpu_buffer_pool[i].vdb;
if (addr >= vdb.phys_addr && addr < (vdb.phys_addr + vdb.size)) {
break;
}
}
}
if (!vdb.size) {
VLOG(ERR, "address 0x%08x is not mapped address!!!\n", (int)addr);
return -1;
}
offset = addr - (unsigned long)vdb.phys_addr;
swap_endian(core_idx, data, len, endian);
osal_memcpy((void *)((unsigned long)vdb.virt_addr+offset), data, len);
vdb.phys_addr = addr;
vdb.size = len;
vdi_flush_memory(core_idx, &vdb);
return len;
}
int vdi_read_memory(u32 core_idx, PhysicalAddress addr, unsigned char *data, int len, int endian)
{
vdi_info_t *vdi;
vpudrv_buffer_t vdb;
ulong offset;
int i;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].inuse == 1)
{
vdb = vdi->vpu_buffer_pool[i].vdb;
if (addr >= vdb.phys_addr && addr < (vdb.phys_addr + vdb.size))
break;
}
}
if (!vdb.size)
return -1;
offset = addr - (ulong)vdb.phys_addr;
vdb.phys_addr = addr;
vdb.size = len;
vdi_invalidate_memory(core_idx, &vdb);
osal_memcpy(data, (const void *)((ulong)vdb.virt_addr+offset), len);
swap_endian(core_idx, data, len, endian);
return len;
}
int vdi_allocate_dma_memory(u32 core_idx, vpu_buffer_t *vb, int memTypes, int instIndex)
{
vdi_info_t *vdi;
int i;
vpudrv_buffer_t vdb;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
vdb.size = vb->size;
vdb.cached = 1;
if (ioctl(vdi->vpu_fd, VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY, &vdb) < 0)
{
VLOG(ERR, "[VDI] fail to vdi_allocate_dma_memory size=%d\n", vb->size);
return -1;
}
vb->phys_addr = (ulong)vdb.phys_addr;
vb->base = (ulong)vdb.base;
//map to virtual address
vdb.virt_addr = (ulong)mmap(NULL, vdb.size, PROT_READ | PROT_WRITE,
MAP_SHARED, vdi->vpu_fd, vdb.phys_addr);
if ((void *)vdb.virt_addr == MAP_FAILED)
{
memset(vb, 0x00, sizeof(vpu_buffer_t));
return -1;
}
vb->virt_addr = vdb.virt_addr;
vmem_lock(vdi);
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].inuse == 0)
{
vdi->vpu_buffer_pool[i].vdb = vdb;
vdi->vpu_buffer_pool_count++;
vdi->vpu_buffer_pool[i].inuse = 1;
break;
}
}
vmem_unlock(vdi);
VLOG(INFO, "[VDI] vdi_allocate_dma_memory, physaddr=%lx, virtaddr=%p~%p, size=%d, memType=%d\n",
(ulong)vb->phys_addr, (void *)vb->virt_addr, (void *)(vb->virt_addr + vb->size), vb->size, memTypes);
return 0;
}
unsigned long vdi_get_dma_memory_free_size(u32 coreIdx)
{
vdi_info_t *vdi;
int size;
vdi = &s_vdi_info[coreIdx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[coreIdx] == INIT_VDI_STAT_NULL)
return (unsigned long)-1;
if (ioctl(vdi->vpu_fd, VDI_IOCTL_GET_FREE_MEM_SIZE, &size) < 0) {
VLOG(ERR, "[VDI] fail VDI_IOCTL_GET_FREE_MEM_SIZE size=%d\n", size);
return 0;
}
return size;
}
int vdi_attach_dma_memory(u32 core_idx, vpu_buffer_t *vb)
{
vdi_info_t *vdi;
int i;
vpudrv_buffer_t vdb;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
vdb.size = vb->size;
vdb.phys_addr = vb->phys_addr;
vdb.base = vb->base;
vdb.virt_addr = vb->virt_addr;
vmem_lock(vdi);
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].vdb.phys_addr == vb->phys_addr)
{
vdi->vpu_buffer_pool[i].vdb = vdb;
vdi->vpu_buffer_pool[i].inuse = 1;
break;
}
else
{
if (vdi->vpu_buffer_pool[i].inuse == 0)
{
vdi->vpu_buffer_pool[i].vdb = vdb;
vdi->vpu_buffer_pool_count++;
vdi->vpu_buffer_pool[i].inuse = 1;
break;
}
}
}
vmem_unlock(vdi);
//VLOG(INFO, "[VDI] vdi_attach_dma_memory, physaddr=0x%lx, virtaddr=0x%lx, size=%d, index=%d\n", vb->phys_addr, vb->virt_addr, vb->size, i);
return 0;
}
int vdi_dettach_dma_memory(u32 core_idx, vpu_buffer_t *vb)
{
vdi_info_t *vdi;
int i;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
#endif
vdi = &s_vdi_info[core_idx];
if (!vb || !vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
if (vb->size == 0)
return -1;
vmem_lock(vdi);
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].vdb.phys_addr == vb->phys_addr)
{
vdi->vpu_buffer_pool[i].inuse = 0;
vdi->vpu_buffer_pool_count--;
break;
}
}
vmem_unlock(vdi);
return 0;
}
void vdi_free_dma_memory(u32 core_idx, vpu_buffer_t *vb, int memTypes, int instIndex)
{
vdi_info_t *vdi;
int i;
vpudrv_buffer_t vdb;
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
core_idx = 0;
#else
if (core_idx >= MAX_NUM_VPU_CORE)
return;
#endif
vdi = &s_vdi_info[core_idx];
if (!vb || !vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return;
if (vb->size == 0)
return ;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
vmem_lock(vdi);
for (i=0; i<MAX_VPU_BUFFER_POOL; i++)
{
if (vdi->vpu_buffer_pool[i].vdb.phys_addr == vb->phys_addr)
{
vdi->vpu_buffer_pool[i].inuse = 0;
vdi->vpu_buffer_pool_count--;
vdb = vdi->vpu_buffer_pool[i].vdb;
break;
}
}
vmem_unlock(vdi);
if (!vdb.size)
{
VLOG(ERR, "[VDI] invalid buffer to free address = 0x%lx vb address 0x%lx size %d\n",
(ulong)vdb.virt_addr, (ulong)vb->phys_addr, vb->size);
return ;
}
ioctl(vdi->vpu_fd, VDI_IOCTL_FREE_PHYSICALMEMORY, &vdb);
if (munmap((void *)vdb.virt_addr, vdb.size) != 0)
{
VLOG(ERR, "[VDI] fail to vdi_free_dma_memory virtial address = 0x%lx\n", (ulong)vdb.virt_addr);
}
osal_memset(vb, 0, sizeof(vpu_buffer_t));
}
int vdi_get_sram_memory(u32 core_idx, vpu_buffer_t *vb)
{
vdi_info_t *vdi = NULL;
vpudrv_buffer_t vdb;
unsigned int sram_size = 0;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vb || !vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
switch (vdi->product_code) {
case VP521C_CODE:
sram_size = VDI_VP521C_SRAM_SIZE; break;
default:
VLOG(ERR, "[VDI] check product_code(%x)\n", vdi->product_code);
break;
}
if (sram_size > 0) // if we can know the sram address directly in vdi layer, we use it first for sdram address
{
vb->phys_addr = VDI_SRAM_BASE_ADDR+(core_idx*sram_size); // HOST can set DRAM base addr to VDI_SRAM_BASE_ADDR.
vb->size = sram_size;
return 0;
}
return 0;
}
int vdi_flush_memory(u32 core_idx, vpu_buffer_t* vb)
{
vdi_info_t* vdi;
int i, ret = -1;
vpu_buffer_t vdb;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vb || !vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
memset(&vdb, 0x00, sizeof(vpu_buffer_t));
for (i = 0; i < MAX_VPU_BUFFER_POOL; i++) {
if ((vdi->vpu_buffer_pool[i].vdb.phys_addr <= vb->phys_addr) &&
(vdi->vpu_buffer_pool[i].vdb.phys_addr + vdi->vpu_buffer_pool[i].vdb.size) >= (vb->phys_addr + vb->size))
{ //validate buffer
vdb = *vb;
break;
}
}
if (vdb.size > 0)
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_FLUSH_BUFFER, (void*)&vdb);
return ret;
}
int vdi_invalidate_memory(u32 core_idx, vpu_buffer_t *vb)
{
vdi_info_t* vdi;
int i, ret = -1;
vpu_buffer_t vdb;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vb || !vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
memset(&vdb, 0x00, sizeof(vpu_buffer_t));
for (i = 0; i < MAX_VPU_BUFFER_POOL; i++) {
if (vdi->vpu_buffer_pool[i].vdb.phys_addr <= vb->phys_addr &&
(vdi->vpu_buffer_pool[i].vdb.phys_addr + vdi->vpu_buffer_pool[i].vdb.size) >= (vb->phys_addr + vb->size))
{ //validate buffer
vdb = *vb;
break;
}
}
if (vdb.size > 0)
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_CACHE_INV_BUFFER, (void*)&vdb);
return ret;
}
int vdi_config_dma(u32 core_idx, vpu_dma_buf_info_t *info)
{
int ret;
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
VLOG(INFO, "[VDI] CONFIG_DMA plane %d fd(%d, %d, %d)\n",
info->num_planes, info->fd[0], info->fd[1], info->fd[2]);
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_CONFIG_DMA, (void*)info);
VLOG(INFO, "[VDI] DMA physic %d phy(%lx, %lx, %lx)\n",
info->num_planes, info->phys_addr[0], info->phys_addr[1], info->phys_addr[2]);
return ret;
}
//hoan add for canvas
int vdi_config_dma_canvas(u32 core_idx, vpu_dma_buf_canvas_info_t *info)
{
int ret;
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_READ_CANVAS, (void*)info);
VLOG(NONE, "[canvas_u] >> vdi_config_dma_canvas DMA physic %d phy(%lx, %lx, %lx)\n",
info->num_planes, info->phys_addr[0], info->phys_addr[1], info->phys_addr[2]);
return ret;
}
//end
int vdi_unmap_dma(u32 core_idx, vpu_dma_buf_info_t *info)
{
int ret;
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_UNMAP_DMA, (void*)info);
return ret;
}
int vdi_set_clock_gate(u32 core_idx, int enable)
{
vdi_info_t *vdi = NULL;
int ret;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
vdi->clock_state = enable;
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_SET_CLOCK_GATE, &enable);
VLOG(INFO, "[VDI] clock enable %d\n", enable);
return ret;
}
int vdi_get_clock_gate(u32 core_idx)
{
vdi_info_t *vdi;
int ret;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
ret = vdi->clock_state;
return ret;
}
static int get_pc_addr(Uint32 product_code)
{
if (PRODUCT_CODE_VP_SERIES(product_code)) {
return VP5_VCPU_CUR_PC;
}
else {
VLOG(ERR, "Unknown product id : %08x\n", product_code);
return -1;
}
}
int vdi_wait_bus_busy(u32 core_idx, int timeout, unsigned int gdi_busy_flag)
{
Uint64 elapse, cur;
Uint32 pc;
vdi_info_t *vdi;
vdi = &s_vdi_info[core_idx];
elapse = osal_gettime();
pc = get_pc_addr(vdi->product_code);
while(1)
{
if (vdi->product_code == VP521C_CODE) {
if (vdi_fio_read_register(core_idx, gdi_busy_flag) == 0x3f) break;
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
if (timeout > 0) {
cur = osal_gettime();
if ((int)(cur - elapse) > timeout) {
print_busy_timeout_status(core_idx, vdi->product_code, pc);
return -1;
}
}
}
return 0;
}
int vdi_wait_vpu_busy(u32 core_idx, int timeout, unsigned int addr_bit_busy_flag)
{
Uint64 elapse, cur;
Uint32 pc;
Uint32 normalReg = TRUE;
vdi_info_t *vdi;
vdi = &s_vdi_info[core_idx];
elapse = osal_gettime();
pc = get_pc_addr(vdi->product_code);
if (PRODUCT_CODE_VP_SERIES(vdi->product_code)) {
if (addr_bit_busy_flag&0x8000) normalReg = FALSE;
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
while(1)
{
if (normalReg == TRUE) {
if (vdi_read_register(core_idx, addr_bit_busy_flag) == 0) break;
}
else {
if (vdi_fio_read_register(core_idx, addr_bit_busy_flag) == 0) break;
}
if (timeout > 0) {
cur = osal_gettime();
if ((int)(cur - elapse) > timeout) {
print_busy_timeout_status(core_idx, vdi->product_code, pc);
return -1;
}
}
}
return 0;
}
int vdi_wait_vcpu_bus_busy(u32 core_idx, int timeout, unsigned int addr_bit_busy_flag)
{
Uint64 elapse, cur;
Uint32 pc;
Uint32 normalReg = TRUE;
vdi_info_t *vdi;
vdi = &s_vdi_info[core_idx];
elapse = osal_gettime();
pc = get_pc_addr(vdi->product_code);
if (PRODUCT_CODE_VP_SERIES(vdi->product_code)) {
if (addr_bit_busy_flag&0x8000) normalReg = FALSE;
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
while(1)
{
if (normalReg == TRUE) {
if (vdi_read_register(core_idx, addr_bit_busy_flag) == 0x40) break;
}
else {
if (vdi_fio_read_register(core_idx, addr_bit_busy_flag) == 0x40) break;
}
if (timeout > 0) {
cur = osal_gettime();
if ((int)(cur - elapse) > timeout) {
print_busy_timeout_status(core_idx, vdi->product_code, pc);
return -1;
}
}
}
return 0;
}
int vdi_wait_interrupt(u32 coreIdx, unsigned int instIdx, int timeout)
{
int intr_reason = 0;
int ret;
vdi_info_t *vdi;
vpudrv_intr_info_t intr_info;
if (coreIdx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[coreIdx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[coreIdx] == INIT_VDI_STAT_NULL)
return -1;
intr_info.timeout = timeout;
intr_info.intr_reason = 0;
intr_info.intr_inst_index = instIdx;
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_WAIT_INTERRUPT, (void*)&intr_info);
if (ret != 0)
return -1;
intr_reason = intr_info.intr_reason;
return intr_reason;
}
//------------------------------------------------------------------------------
// LOG & ENDIAN functions
//------------------------------------------------------------------------------
int vdi_get_system_endian(u32 core_idx)
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
if (PRODUCT_CODE_VP_SERIES(vdi->product_code)) {
return VDI_128BIT_BUS_SYSTEM_ENDIAN;
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
}
int vdi_convert_endian(u32 core_idx, unsigned int endian)
{
vdi_info_t *vdi;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
if (PRODUCT_CODE_VP_SERIES(vdi->product_code)) {
switch (endian) {
case VDI_LITTLE_ENDIAN: endian = 0x00; break;
case VDI_BIG_ENDIAN: endian = 0x0f; break;
case VDI_32BIT_LITTLE_ENDIAN: endian = 0x04; break;
case VDI_32BIT_BIG_ENDIAN: endian = 0x03; break;
}
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
return (endian&0x0f);
}
void byte_swap(unsigned char* data, int len)
{
Uint8 temp;
Int32 i;
if(len & 0x1) len++;
for (i=0; i<len; i+=2) {
if (i + 1 < len) {
temp = data[i];
data[i] = data[i+1];
data[i+1] = temp;
}
}
}
void word_swap(unsigned char* data, int len)
{
Uint16 temp;
Uint16* ptr = (Uint16*)data;
Int32 i, size = (len + (int)sizeof(Uint16) -1)/(int)sizeof(Uint16);
for (i=0; i<size; i+=2) {
temp = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = temp;
}
}
void dword_swap(unsigned char* data, int len)
{
Uint32 temp;
Uint32* ptr = (Uint32*)data;
Int32 i, size = (len + (int)sizeof(Uint32) -1)/(int)sizeof(Uint32);
for (i=0; i<size; i+=2) {
temp = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = temp;
}
}
void lword_swap(unsigned char* data, int len)
{
Uint64 temp;
Uint64* ptr = (Uint64*)data;
Int32 i, size = (len + (int)sizeof(Uint64) -1)/(int)sizeof(Uint64);
for (i=0; i<size; i+=2) {
temp = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = temp;
}
}
int swap_endian(u32 core_idx, unsigned char *data, int len, int endian)
{
vdi_info_t *vdi;
int changes;
int sys_endian;
BOOL byteChange, wordChange, dwordChange, lwordChange;
if (core_idx >= MAX_NUM_VPU_CORE)
return -1;
vdi = &s_vdi_info[core_idx];
if (!vdi || vdi->vpu_fd == -1 ||
vdi_init_flag[core_idx] == INIT_VDI_STAT_NULL)
return -1;
if (PRODUCT_CODE_VP_SERIES(vdi->product_code)) {
sys_endian = VDI_128BIT_BUS_SYSTEM_ENDIAN;
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
endian = vdi_convert_endian(core_idx, endian);
sys_endian = vdi_convert_endian(core_idx, sys_endian);
if (endian == sys_endian)
return 0;
if (PRODUCT_CODE_VP_SERIES(vdi->product_code)) {
}
else {
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
return -1;
}
changes = endian ^ sys_endian;
byteChange = changes&0x01;
wordChange = ((changes&0x02) == 0x02);
dwordChange = ((changes&0x04) == 0x04);
lwordChange = ((changes&0x08) == 0x08);
if (byteChange) byte_swap(data, len);
if (wordChange) word_swap(data, len);
if (dwordChange) dword_swap(data, len);
if (lwordChange) lword_swap(data, len);
return 1;
}