You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1808 lines
48 KiB
1808 lines
48 KiB
|
7 months ago
|
//-----------------------------------------------------------------------------
|
||
|
|
// COPYRIGHT (C) 2020 CHIPS&MEDIA INC. ALL RIGHTS RESERVED
|
||
|
|
//
|
||
|
|
// This file is distributed under BSD 3 clause and LGPL2.1 (dual license)
|
||
|
|
// SPDX License Identifier: BSD-3-Clause
|
||
|
|
// SPDX License Identifier: LGPL-2.1-only
|
||
|
|
//
|
||
|
|
// The entire notice above must be reproduced on all authorized copies.
|
||
|
|
//
|
||
|
|
// Description :
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
#if defined(linux) || defined(__linux) || defined(ANDROID)
|
||
|
|
|
||
|
|
#include <ctype.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#ifdef _KERNEL_
|
||
|
|
#include <linux/delay.h>
|
||
|
|
#endif
|
||
|
|
#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 "vpu.h"
|
||
|
|
#include "vdi.h"
|
||
|
|
#include "vdi_osal.h"
|
||
|
|
#include "wave5_regdefine.h"
|
||
|
|
#include "main_helper.h"
|
||
|
|
#include "misc/debug.h"
|
||
|
|
|
||
|
|
#include <pthread.h>
|
||
|
|
|
||
|
|
#define VPU_DEVICE_NAME "/dev/vpu"
|
||
|
|
|
||
|
|
#ifdef USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
#else
|
||
|
|
typedef pthread_mutex_t MUTEX_HANDLE;
|
||
|
|
#endif
|
||
|
|
#ifdef SUPPORT_SW_UART_ON_NONOS
|
||
|
|
extern void SwUartHandler(void *context);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define SUPPORT_INTERRUPT
|
||
|
|
#define VDI_SRAM_BASE_ADDR 0x01000000 // 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 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)
|
||
|
|
|
||
|
|
#ifdef USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
#else
|
||
|
|
#define VDI_NUM_LOCK_HANDLES 4
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
|
||
|
|
#define VPU_CORE_BASE_OFFSET 0x4000
|
||
|
|
#endif
|
||
|
|
|
||
|
|
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;
|
||
|
|
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;
|
||
|
|
|
||
|
|
#ifdef USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
#else
|
||
|
|
void* vpu_mutex;
|
||
|
|
void* vmem_mutex;
|
||
|
|
void* vpu_disp_mutex;
|
||
|
|
#endif // USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
} vdi_info_t;
|
||
|
|
|
||
|
|
static vdi_info_t s_vdi_info[MAX_NUM_VPU_CORE];
|
||
|
|
|
||
|
|
static int swap_endian(unsigned long core_idx, unsigned char *data, int len, int endian);
|
||
|
|
|
||
|
|
int vdi_probe(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
int ret;
|
||
|
|
|
||
|
|
ret = vdi_init(core_idx);
|
||
|
|
vdi_release(core_idx);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_init(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if (vdi->vpu_fd != -1 && vdi->vpu_fd != 0x00)
|
||
|
|
{
|
||
|
|
vdi->task_num++;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
vdi->vpu_fd = open(VPU_DEVICE_NAME, O_RDWR); // if this API supports VPU parallel processing using multi VPU. the driver should be made to open multiple times.
|
||
|
|
if (vdi->vpu_fd < 0) {
|
||
|
|
VLOG(ERR, "[VDI] Can't open vpu driver. [error=%s]. try to run vdi/linux/driver/load.sh script \n", strerror(errno));
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(vdi->vpu_buffer_pool, 0x00, sizeof(vpudrv_buffer_pool_t)*MAX_VPU_BUFFER_POOL);
|
||
|
|
|
||
|
|
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;
|
||
|
|
#ifdef USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
#else
|
||
|
|
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);
|
||
|
|
#endif // USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
#ifdef USE_VMALLOC_FOR_INSTANCE_POOL_MEMORY
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef USE_VMALLOC_FOR_INSTANCE_POOL_MEMORY
|
||
|
|
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);
|
||
|
|
#else
|
||
|
|
vdi->vdb_register.size = VPU_BIT_REG_SIZE;
|
||
|
|
vdi->vdb_register.virt_addr = (unsigned long)mmap(NULL, vdi->vdb_register.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdi->vpu_fd, 0);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
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%x, size=%d\n", core_idx, (int)vdi->vdb_register.virt_addr, vdi->vdb_register.size);
|
||
|
|
|
||
|
|
if (vdi_lock(core_idx) < 0)
|
||
|
|
{
|
||
|
|
VLOG(ERR, "[VDI] fail to handle lock function\n");
|
||
|
|
goto ERR_VDI_INIT;
|
||
|
|
}
|
||
|
|
|
||
|
|
vdi_set_clock_gate(core_idx, 1);
|
||
|
|
|
||
|
|
vdi->product_code = vdi_read_register(core_idx, VPU_PRODUCT_CODE_REGISTER);
|
||
|
|
|
||
|
|
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_set_clock_gate(core_idx, 0);
|
||
|
|
vdi_unlock(core_idx);
|
||
|
|
|
||
|
|
// VLOG(INFO, "[VDI] success to init driver \n");
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
ERR_VDI_INIT:
|
||
|
|
vdi_unlock(core_idx);
|
||
|
|
vdi_release(core_idx);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_set_bit_firmware_to_pm(unsigned long core_idx, const unsigned short *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->vpu_fd == 0x00)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
bit_firmware_info.size = sizeof(vpu_bit_firmware_info_t);
|
||
|
|
bit_firmware_info.core_idx = (unsigned int)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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
return vdi->task_num;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
int vdi_release(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
vpudrv_buffer_t vdb;
|
||
|
|
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->vpu_fd == 0x00)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
if (vdi_lock(core_idx) < 0)
|
||
|
|
{
|
||
|
|
VLOG(ERR, "[VDI] fail to handle lock function\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (vdi->task_num > 1) // means that the opened instance remains
|
||
|
|
{
|
||
|
|
vdi->task_num--;
|
||
|
|
vdi_unlock(core_idx);
|
||
|
|
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);
|
||
|
|
|
||
|
|
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->vpu_fd != -1 && vdi->vpu_fd != 0x00)
|
||
|
|
{
|
||
|
|
close(vdi->vpu_fd);
|
||
|
|
vdi->vpu_fd = -1;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(vdi, 0x00, sizeof(vdi_info_t));
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_get_common_memory(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
osal_memcpy(vb, &vdi->vpu_common_memory, sizeof(vpu_buffer_t));
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_allocate_common_memory(unsigned long 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->vpu_fd==0x00)
|
||
|
|
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%x, size = %d\n", (int)vdb.phys_addr, (int)vdb.size);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// VLOG(INFO, "[VDI] vdi_allocate_common_memory, physaddr=0x%x, virtaddr=0x%x\n", (int)vdb.phys_addr, (int)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 = (PhysicalAddress)((unsigned long)(vdb.phys_addr + (core_idx*SIZE_COMMON)));
|
||
|
|
vdi->pvip->vpu_common_buffer.base = (unsigned long)(vdb.base + (core_idx*SIZE_COMMON));
|
||
|
|
vdi->pvip->vpu_common_buffer.virt_addr = (unsigned long)(vdb.virt_addr + (core_idx*SIZE_COMMON));
|
||
|
|
#else
|
||
|
|
vdi->pvip->vpu_common_buffer.size = SIZE_COMMON;
|
||
|
|
vdi->pvip->vpu_common_buffer.phys_addr = (unsigned long)(vdb.phys_addr);
|
||
|
|
vdi->pvip->vpu_common_buffer.base = (unsigned long)(vdb.base);
|
||
|
|
vdi->pvip->vpu_common_buffer.virt_addr = (unsigned long)(vdb.virt_addr);
|
||
|
|
#endif
|
||
|
|
osal_memcpy(&vdi->vpu_common_memory, &vdi->pvip->vpu_common_buffer, sizeof(vpu_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%x, size=%d, virtaddr=0x%x\n", (int)vdi->vpu_common_memory.phys_addr, (int)vdi->vpu_common_memory.size, (int)vdi->vpu_common_memory.virt_addr);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
vpu_instance_pool_t *vdi_get_instance_pool(unsigned long 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->vpu_fd == 0x00 )
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
|
||
|
|
if (!vdi->pvip)
|
||
|
|
{
|
||
|
|
#ifdef USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
vdb.size = sizeof(vpu_instance_pool_t);
|
||
|
|
#else
|
||
|
|
vdb.size = sizeof(vpu_instance_pool_t) + sizeof(MUTEX_HANDLE)*VDI_NUM_LOCK_HANDLES;
|
||
|
|
#endif // USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
#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;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef USE_VMALLOC_FOR_INSTANCE_POOL_MEMORY
|
||
|
|
vdb.virt_addr = (unsigned long)mmap(NULL, vdb.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdi->vpu_fd, 0);
|
||
|
|
#else
|
||
|
|
vdb.virt_addr = (unsigned long)mmap(NULL, vdb.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdi->vpu_fd, vdb.phys_addr);
|
||
|
|
#endif
|
||
|
|
if ((void *)vdb.virt_addr == 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 USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
#ifdef SUPPORT_MULTI_CORE_IN_ONE_DRIVER
|
||
|
|
vdi->pvip = (vpu_instance_pool_t *)(vdb.virt_addr + (core_idx*(sizeof(vpu_instance_pool_t))));
|
||
|
|
#else
|
||
|
|
vdi->pvip = (vpu_instance_pool_t *)(vdb.virt_addr);
|
||
|
|
#endif
|
||
|
|
#else
|
||
|
|
#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
|
||
|
|
vdi->vpu_mutex = (void *)((unsigned long)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 *)((unsigned long)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 // USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
|
||
|
|
// 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(unsigned long core_idx, unsigned long inst_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
vpudrv_inst_info_t inst_info;
|
||
|
|
memset(&inst_info, 0, sizeof(vpudrv_inst_info_t));
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
inst_info.core_idx = (unsigned int)core_idx;
|
||
|
|
inst_info.inst_idx = (unsigned int)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(unsigned long core_idx, unsigned long inst_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
vpudrv_inst_info_t inst_info;
|
||
|
|
memset(&inst_info, 0, sizeof(vpudrv_inst_info_t));
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
inst_info.core_idx = (unsigned int)core_idx;
|
||
|
|
inst_info.inst_idx = (unsigned int)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_get_instance_num(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
return vdi->pvip->vpu_instance_num;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_hw_reset(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
return ioctl(vdi->vpu_fd, VDI_IOCTL_RESET, 0);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
|
||
|
|
int vdi_lock(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int mutex_type = VPUDRV_MUTEX_VPU;
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
return ioctl(vdi->vpu_fd, VDI_IOCTL_VDI_LOCK, &mutex_type);
|
||
|
|
}
|
||
|
|
|
||
|
|
void vdi_unlock(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int mutex_type = VPUDRV_MUTEX_VPU;
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
|
||
|
|
ioctl(vdi->vpu_fd, VDI_IOCTL_VDI_UNLOCK, &mutex_type);
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_disp_lock(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int mutex_type = VPUDRV_MUTEX_DISP_FALG;
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
return ioctl(vdi->vpu_fd, VDI_IOCTL_VDI_LOCK, &mutex_type);
|
||
|
|
}
|
||
|
|
|
||
|
|
void vdi_disp_unlock(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int mutex_type = VPUDRV_MUTEX_DISP_FALG;
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
ioctl(vdi->vpu_fd, VDI_IOCTL_VDI_UNLOCK, &mutex_type);
|
||
|
|
}
|
||
|
|
static int vmem_lock(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int mutex_type = VPUDRV_MUTEX_VMEM;
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
return ioctl(vdi->vpu_fd, VDI_IOCTL_VDI_LOCK, &mutex_type);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void vmem_unlock(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int mutex_type = VPUDRV_MUTEX_VMEM;
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
ioctl(vdi->vpu_fd, VDI_IOCTL_VDI_UNLOCK, &mutex_type);
|
||
|
|
}
|
||
|
|
|
||
|
|
#else
|
||
|
|
static void restore_mutex_in_dead(MUTEX_HANDLE *mutex)
|
||
|
|
{
|
||
|
|
int mutex_value;
|
||
|
|
|
||
|
|
if (!mutex)
|
||
|
|
return;
|
||
|
|
#if 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 int vmem_lock(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
#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__);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return 0;//lint !e454
|
||
|
|
}
|
||
|
|
|
||
|
|
static void vmem_unlock(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
pthread_mutex_unlock((MUTEX_HANDLE *)vdi->vmem_mutex);//lint !e455
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_lock(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
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;//lint !e454
|
||
|
|
}
|
||
|
|
|
||
|
|
void vdi_unlock(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
pthread_mutex_unlock((MUTEX_HANDLE *)vdi->vpu_mutex);//lint !e455
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_disp_lock(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
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(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
pthread_mutex_unlock((MUTEX_HANDLE *)vdi->vpu_disp_mutex);//lint !e455
|
||
|
|
}
|
||
|
|
#endif // USE_MUTEX_IN_KERNEL_SPACE
|
||
|
|
|
||
|
|
void vdi_write_register(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
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(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
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(unsigned long 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, W5_VPU_FIO_CTRL_ADDR, ctrl);
|
||
|
|
count = FIO_TIMEOUT;
|
||
|
|
while (count--) {
|
||
|
|
ctrl = vdi_read_register(core_idx, W5_VPU_FIO_CTRL_ADDR);
|
||
|
|
if (ctrl & 0x80000000) {
|
||
|
|
data = vdi_read_register(core_idx, W5_VPU_FIO_DATA);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
void vdi_fio_write_register(unsigned long core_idx, unsigned int addr, unsigned int data)
|
||
|
|
{
|
||
|
|
unsigned int ctrl;
|
||
|
|
unsigned int count = 0;
|
||
|
|
|
||
|
|
vdi_write_register(core_idx, W5_VPU_FIO_DATA, data);
|
||
|
|
ctrl = (addr&0xffff);
|
||
|
|
ctrl |= (1<<16); /* write operation */
|
||
|
|
vdi_write_register(core_idx, W5_VPU_FIO_CTRL_ADDR, ctrl);
|
||
|
|
|
||
|
|
count = FIO_TIMEOUT;
|
||
|
|
while (count--) {
|
||
|
|
ctrl = vdi_read_register(core_idx, W5_VPU_FIO_CTRL_ADDR);
|
||
|
|
if (ctrl & 0x80000000) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_clear_memory(unsigned long core_idx, PhysicalAddress addr, int len, int endian __attribute__((unused)))
|
||
|
|
{
|
||
|
|
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
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
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);
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_set_memory(unsigned long core_idx, PhysicalAddress addr, int len, int endian __attribute__((unused)), 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
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
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);
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_write_memory(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if 0 //def CNM_FPGA_PLATFORM
|
||
|
|
// to check some writing of common buffer
|
||
|
|
if (vdb.phys_addr >= vdi->vpu_common_memory.phys_addr &&
|
||
|
|
vdb.phys_addr < (vdi->vpu_common_memory.phys_addr + SIZE_COMMON))
|
||
|
|
{
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code))
|
||
|
|
{
|
||
|
|
if (vdi_read_register(core_idx, W5_VCPU_CUR_PC) != 0)
|
||
|
|
{
|
||
|
|
VLOG(ERR, "not to permit writing common buffer addr=0x%x, size=%d\n", (int)vdb.phys_addr, (int)vdb.size);
|
||
|
|
VLOG(ERR, "this process will be exit\n");
|
||
|
|
exit(-1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
offset = addr - (unsigned long)vdb.phys_addr;
|
||
|
|
swap_endian(core_idx, data, len, endian);
|
||
|
|
|
||
|
|
/*TODO CHECK*/
|
||
|
|
osal_memcpy((void *)((unsigned long)vdb.virt_addr+offset), data, len);
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_read_memory(unsigned long 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
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd==-1 || vdi->vpu_fd == 0x00)
|
||
|
|
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 - (unsigned long)vdb.phys_addr;
|
||
|
|
|
||
|
|
/*TODO CHECK*/
|
||
|
|
osal_memcpy(data, (unsigned char*)vdb.virt_addr+offset, len);
|
||
|
|
|
||
|
|
swap_endian(core_idx, data, len, endian);
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
unsigned char* vdi_read_yuv_memory(unsigned long core_idx, PhysicalAddress addr, int len __attribute__((unused)), int endian __attribute__((unused)))
|
||
|
|
{
|
||
|
|
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
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd==-1 || vdi->vpu_fd == 0x00)
|
||
|
|
exit(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)
|
||
|
|
exit(1);
|
||
|
|
|
||
|
|
offset = addr - (unsigned long)vdb.phys_addr;
|
||
|
|
|
||
|
|
return (unsigned char*)vdb.virt_addr+offset;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_allocate_dma_memory(unsigned long core_idx, vpu_buffer_t *vb, int memTypes __attribute__((unused)), int instIndex __attribute__((unused)))
|
||
|
|
{
|
||
|
|
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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vmem_lock(core_idx);
|
||
|
|
|
||
|
|
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
|
||
|
|
|
||
|
|
vdb.size = vb->size;
|
||
|
|
|
||
|
|
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);
|
||
|
|
vmem_unlock(core_idx);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
vb->phys_addr = (PhysicalAddress)(unsigned long)vdb.phys_addr;
|
||
|
|
vb->base = (unsigned long)vdb.base;
|
||
|
|
|
||
|
|
//map to virtual address
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
memset(vb, 0x00, sizeof(vpu_buffer_t));
|
||
|
|
vmem_unlock(core_idx);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
vb->virt_addr = vdb.virt_addr;
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MAX_VPU_BUFFER_POOL == i) {
|
||
|
|
VLOG(ERR, "[VDI] fail to vdi_allocate_dma_memory, vpu_buffer_pool_count=%d MAX_VPU_BUFFER_POOL=%d\n", vdi->vpu_buffer_pool_count, MAX_VPU_BUFFER_POOL);
|
||
|
|
vmem_unlock(core_idx);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
vmem_unlock(core_idx);
|
||
|
|
|
||
|
|
// VLOG(INFO, "[VDI] vdi_allocate_dma_memory, physaddr=%p, virtaddr=%p~%p, size=%d, memType=%d\n",
|
||
|
|
// vb->phys_addr, vb->virt_addr, vb->virt_addr + vb->size, vb->size, memTypes);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
unsigned long vdi_get_dma_memory_free_size(unsigned long core_idx)
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
unsigned int size;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd==-1 || vdi->vpu_fd == 0x00)
|
||
|
|
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(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
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(core_idx);
|
||
|
|
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(core_idx);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_dettach_dma_memory(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (vb->size == 0)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
vmem_lock(core_idx);
|
||
|
|
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(core_idx);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void vdi_free_dma_memory(unsigned long core_idx, vpu_buffer_t *vb, int memTypes __attribute__((unused)), int instIndex __attribute__((unused)))
|
||
|
|
{
|
||
|
|
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->vpu_fd == 0x00)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (vb->size == 0)
|
||
|
|
return ;
|
||
|
|
|
||
|
|
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
|
||
|
|
|
||
|
|
vmem_lock(core_idx);
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!vdb.size)
|
||
|
|
{
|
||
|
|
VLOG(ERR, "[VDI] invalid buffer to free address = 0x%x\n", (int)vdb.virt_addr);
|
||
|
|
vmem_unlock(core_idx);
|
||
|
|
return ;
|
||
|
|
}
|
||
|
|
if (ioctl(vdi->vpu_fd, VDI_IOCTL_FREE_PHYSICALMEMORY, &vdb) < 0) {
|
||
|
|
VLOG(ERR, "[VDI] fail to VDI_IOCTL_FREE_PHYSICALMEMORY \n");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (munmap((void *)vdb.virt_addr, vdb.size) != 0)
|
||
|
|
{
|
||
|
|
VLOG(ERR, "[VDI] fail to vdi_free_dma_memory virtial address = 0x%x\n", (int)vdb.virt_addr);
|
||
|
|
}
|
||
|
|
osal_memset(vb, 0, sizeof(vpu_buffer_t));
|
||
|
|
vmem_unlock(core_idx);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int vdi_get_sram_memory(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
osal_memset(&vdb, 0x00, sizeof(vpudrv_buffer_t));
|
||
|
|
|
||
|
|
switch (vdi->product_code) {
|
||
|
|
case BODA950_CODE:
|
||
|
|
case CODA960_CODE:
|
||
|
|
case CODA980_CODE:
|
||
|
|
// 4K : 0x34600, FHD : 0x17D00
|
||
|
|
sram_size = 0x34600; break;
|
||
|
|
case WAVE511_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 129024, 4Kx2K -> 64512
|
||
|
|
*/
|
||
|
|
sram_size = 0x1F800; break;
|
||
|
|
case WAVE517_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 272384, 4Kx2K -> 104448
|
||
|
|
*/
|
||
|
|
sram_size = 0x42800; break;
|
||
|
|
case WAVE537_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 272384, 4Kx2K -> 104448
|
||
|
|
*/
|
||
|
|
sram_size = 0x42800; break;
|
||
|
|
case WAVE521_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 126976, 4Kx2K -> 63488
|
||
|
|
*/
|
||
|
|
sram_size = 0x1F000; break;
|
||
|
|
case WAVE521E1_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 126976, 4Kx2K -> 63488
|
||
|
|
*/
|
||
|
|
sram_size = 0x1F000; break;
|
||
|
|
case WAVE521C_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 129024, 4Kx2K -> 64512
|
||
|
|
* NOTE: Decoder > Encoder
|
||
|
|
*/
|
||
|
|
sram_size = 0x1F800; break;
|
||
|
|
case WAVE521C_DUAL_CODE:
|
||
|
|
/* 10bit profile : 8Kx8K -> 129024, 4Kx2K -> 64512
|
||
|
|
* NOTE: Decoder > Encoder
|
||
|
|
*/
|
||
|
|
sram_size = 0x1F800; break;
|
||
|
|
default:
|
||
|
|
VLOG(ERR, "[VDI] check product_code(%x)\n", vdi->product_code);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 10bit profile : 40KB, 8bit profile : 20KB
|
||
|
|
sram_size += 0xA000;
|
||
|
|
|
||
|
|
// 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+(PhysicalAddress)(core_idx*sram_size);
|
||
|
|
vb->size = sram_size;
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_set_clock_gate(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
//CommandQueue does not support clock gate
|
||
|
|
//first value 0
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code) || vdi->product_code == 0) {
|
||
|
|
vdi->clock_state = 1;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
vdi->clock_state = enable;
|
||
|
|
|
||
|
|
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_SET_CLOCK_GATE, &enable);
|
||
|
|
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_get_clock_gate(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
ret = vdi->clock_state;
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int get_pc_addr(Uint32 product_code)
|
||
|
|
{
|
||
|
|
if (PRODUCT_CODE_W_SERIES(product_code)) {
|
||
|
|
return W5_VCPU_CUR_PC;
|
||
|
|
}
|
||
|
|
else if (PRODUCT_CODE_NOT_W_SERIES(product_code)) {
|
||
|
|
return BIT_CUR_PC;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
VLOG(ERR, "Unknown product id : %08x\n", product_code);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_wait_bus_busy(unsigned long core_idx, int timeout, unsigned int gdi_busy_flag)
|
||
|
|
{
|
||
|
|
Uint64 elapse, cur;
|
||
|
|
Uint32 pc;
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
Uint32 gdi_status_check_value = 0x3f;
|
||
|
|
Uint32 read_val = 0x0;
|
||
|
|
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
|
||
|
|
elapse = osal_gettime();
|
||
|
|
pc = get_pc_addr(vdi->product_code);
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code)) {
|
||
|
|
gdi_status_check_value = 0x3f;
|
||
|
|
if (vdi->product_code == WAVE521C_CODE || vdi->product_code == WAVE521_CODE || vdi->product_code == WAVE521E1_CODE) {
|
||
|
|
gdi_status_check_value = 0x00ff1f3f;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
while(1)
|
||
|
|
{
|
||
|
|
#ifdef SUPPORT_SW_UART_ON_NONOS
|
||
|
|
SwUartHandler(NULL);
|
||
|
|
#endif
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code)) {
|
||
|
|
|
||
|
|
// if (vdi_fio_read_register(core_idx, gdi_busy_flag) == gdi_status_check_value) break;
|
||
|
|
|
||
|
|
read_val = vdi_fio_read_register(core_idx, gdi_busy_flag);
|
||
|
|
|
||
|
|
if( read_val == gdi_status_check_value) break;
|
||
|
|
|
||
|
|
}
|
||
|
|
else if (PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
if (vdi_read_register(core_idx, gdi_busy_flag) == 0x77) break;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (timeout > 0) {
|
||
|
|
cur = osal_gettime();
|
||
|
|
if ((Uint64)((cur - elapse) > (Uint64)timeout)) {
|
||
|
|
print_busy_timeout_status((Uint32)core_idx, vdi->product_code, pc);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_wait_vpu_busy(unsigned long core_idx, int timeout, unsigned int addr_bit_busy_flag)
|
||
|
|
{
|
||
|
|
Uint64 elapse, cur;
|
||
|
|
Uint32 pc;
|
||
|
|
vdi_info_t *vdi;
|
||
|
|
vdi = &s_vdi_info[core_idx];
|
||
|
|
Uint32 read_val = 0x0;
|
||
|
|
|
||
|
|
elapse = osal_gettime();
|
||
|
|
pc = get_pc_addr(vdi->product_code);
|
||
|
|
|
||
|
|
while(1)
|
||
|
|
{
|
||
|
|
#ifdef SUPPORT_SW_UART_ON_NONOS
|
||
|
|
SwUartHandler(NULL);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// if (vdi_read_register(core_idx, addr_bit_busy_flag) == 0)
|
||
|
|
// break;
|
||
|
|
|
||
|
|
|
||
|
|
read_val = vdi_read_register(core_idx, addr_bit_busy_flag);
|
||
|
|
|
||
|
|
if( read_val == 0 ) break;
|
||
|
|
|
||
|
|
|
||
|
|
if (timeout > 0) {
|
||
|
|
cur = osal_gettime();
|
||
|
|
if ((Uint64)((cur - elapse) > (Uint64)timeout)) {
|
||
|
|
print_busy_timeout_status((Uint32)core_idx, vdi->product_code, pc);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_wait_vcpu_bus_busy(unsigned long 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)
|
||
|
|
{
|
||
|
|
#ifdef SUPPORT_SW_UART_ON_NONOS
|
||
|
|
SwUartHandler(NULL);
|
||
|
|
#endif
|
||
|
|
if (vdi_fio_read_register(core_idx, gdi_busy_flag) == 0x00)
|
||
|
|
break;
|
||
|
|
if (timeout > 0) {
|
||
|
|
cur = osal_gettime();
|
||
|
|
|
||
|
|
if ((Uint64)((cur - elapse) > (Uint64)timeout)) {
|
||
|
|
print_busy_timeout_status((Uint32)core_idx, vdi->product_code, pc);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef SUPPORT_MULTI_INST_INTR
|
||
|
|
int vdi_wait_interrupt(unsigned long core_idx, unsigned int instIdx, int timeout)
|
||
|
|
#else
|
||
|
|
int vdi_wait_interrupt(unsigned long core_idx, int timeout)
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
vdi_info_t *vdi = &s_vdi_info[core_idx];
|
||
|
|
int intr_reason = 0;
|
||
|
|
#ifdef SUPPORT_INTERRUPT
|
||
|
|
int ret;
|
||
|
|
vpudrv_intr_info_t intr_info;
|
||
|
|
#else
|
||
|
|
Uint64 startTime, endTime;
|
||
|
|
Uint32 int_sts_reg;
|
||
|
|
Uint32 int_clear_reg;
|
||
|
|
Uint32 int_reason_reg;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (core_idx >= MAX_NUM_VPU_CORE)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if(!vdi || vdi->vpu_fd == -1 || vdi->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
#ifdef SUPPORT_INTERRUPT
|
||
|
|
intr_info.timeout = timeout;
|
||
|
|
intr_info.intr_reason = 0;
|
||
|
|
#ifdef SUPPORT_MULTI_INST_INTR
|
||
|
|
intr_info.intr_inst_index = instIdx;
|
||
|
|
#endif
|
||
|
|
ret = ioctl(vdi->vpu_fd, VDI_IOCTL_WAIT_INTERRUPT, (void*)&intr_info);
|
||
|
|
if (ret != 0)
|
||
|
|
return -1;
|
||
|
|
intr_reason = intr_info.intr_reason;
|
||
|
|
|
||
|
|
#else /* SUPPORT_INTERRUPT */
|
||
|
|
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code)) {
|
||
|
|
int_sts_reg = W5_VPU_VPU_INT_STS;
|
||
|
|
int_clear_reg = W5_VPU_VINT_CLEAR;
|
||
|
|
int_reason_reg = W5_VPU_VINT_REASON;
|
||
|
|
}
|
||
|
|
else if (PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
int_sts_reg = BIT_INT_STS;
|
||
|
|
int_clear_reg = BIT_INT_CLEAR;
|
||
|
|
int_reason_reg = BIT_INT_REASON;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
startTime = osal_gettime();
|
||
|
|
while (TRUE)
|
||
|
|
{
|
||
|
|
#ifdef SUPPORT_SW_UART_ON_NONOS
|
||
|
|
SwUartHandler(NULL);
|
||
|
|
#endif
|
||
|
|
if (vdi_read_register(core_idx, int_sts_reg))
|
||
|
|
{
|
||
|
|
if ((intr_reason=vdi_read_register(core_idx, int_reason_reg))) {
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code)) {
|
||
|
|
vdi_write_register(core_idx, W5_VPU_VINT_REASON_CLR, intr_reason);
|
||
|
|
}
|
||
|
|
vdi_write_register(core_idx, int_clear_reg, 1);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
endTime = osal_gettime();
|
||
|
|
if (timeout > 0 && (endTime-startTime) >= timeout) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return intr_reason;
|
||
|
|
}
|
||
|
|
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
// LOG & ENDIAN functions
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
int vdi_get_system_endian(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code)) {
|
||
|
|
return VDI_128BIT_BUS_SYSTEM_ENDIAN;
|
||
|
|
}
|
||
|
|
else if(PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
return VDI_SYSTEM_ENDIAN;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int vdi_convert_endian(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (PRODUCT_CODE_W_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 if(PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
VLOG(ERR, "Unknown product id : %08x\n", vdi->product_code);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (endian&0x0f);
|
||
|
|
}
|
||
|
|
|
||
|
|
static Uint32 convert_endian_coda9_to_wave4(Uint32 endian)
|
||
|
|
{
|
||
|
|
Uint32 converted_endian = endian;
|
||
|
|
switch(endian) {
|
||
|
|
case VDI_LITTLE_ENDIAN: converted_endian = 0; break;
|
||
|
|
case VDI_BIG_ENDIAN: converted_endian = 7; break;
|
||
|
|
case VDI_32BIT_LITTLE_ENDIAN: converted_endian = 4; break;
|
||
|
|
case VDI_32BIT_BIG_ENDIAN: converted_endian = 3; break;
|
||
|
|
}
|
||
|
|
return converted_endian;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int swap_endian(unsigned long 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->vpu_fd == 0x00)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (PRODUCT_CODE_W_SERIES(vdi->product_code)) {
|
||
|
|
sys_endian = VDI_128BIT_BUS_SYSTEM_ENDIAN;
|
||
|
|
}
|
||
|
|
else if(PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
sys_endian = VDI_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_W_SERIES(vdi->product_code)) {
|
||
|
|
}
|
||
|
|
else if (PRODUCT_CODE_NOT_W_SERIES(vdi->product_code)) {
|
||
|
|
endian = convert_endian_coda9_to_wave4(endian);
|
||
|
|
sys_endian = convert_endian_coda9_to_wave4(sys_endian);
|
||
|
|
}
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif //#if defined(linux) || defined(__linux) || defined(ANDROID)
|