summaryrefslogtreecommitdiff
path: root/vmeta_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'vmeta_lib.c')
-rwxr-xr-xvmeta_lib.c856
1 files changed, 713 insertions, 143 deletions
diff --git a/vmeta_lib.c b/vmeta_lib.c
index 15b3820..023a128 100755
--- a/vmeta_lib.c
+++ b/vmeta_lib.c
@@ -29,19 +29,58 @@
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <pthread.h>
#include "vmeta_lib.h"
#include "bmm_lib.h"
#include "sys/poll.h"
-
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+// these APIs are used for vmeta driver only, not for export purpose.
+#define VMETA_PRIVATE_LOCK_HANDLE "vmeta_private_lock"
+
+static SIGN32 vmeta_private_lock();
+static SIGN32 vmeta_private_unlock();
+static SIGN32 vdec_os_api_get_ks(kernel_share **pp_ks);//get kernel shared resources
+
// global variable
vdec_os_driver_cb_t *vdec_iface = NULL;
UNSG32 globalDbgLevel = VDEC_DEBUG_NONE;
-struct timeval vdec_timer;
+UNSG32 syncTimeout = 500;
+
+static inline int get_bit(int nr, unsigned int *addr)
+{
+ unsigned int mask = 1 << nr;
+
+ return ((*addr) & mask) != 0;
+}
+
+static inline int set_bit(int nr, unsigned int *addr)
+{
+ unsigned int mask = 1 << nr;
+ unsigned int old;
+
+ old = *addr;
+ *addr = old | mask;
+
+ return (old & mask) != 0;
+}
+
+static inline int clear_bit(int nr, unsigned int *addr)
+{
+ unsigned int mask = 1 << nr;
+ unsigned int old;
+
+ old = *addr;
+ *addr = old & ~mask;
+
+ return (old & mask) != 0;
+}
+
//Add for hal mmap
UNSG8 vdec_os_api_rd8(UNSG32 addr)
@@ -167,80 +206,91 @@ void * vdec_os_api_dma_alloc(UNSG32 size, UNSG32 align, UNSG32 * pPhysical)
return ptr;
}
-void * vdec_os_api_dma_alloc_writecombine(UNSG32 size, UNSG32 align, UNSG32 * pPhysical)
+void * vdec_os_api_dma_alloc_cached(UNSG32 size, UNSG32 align, UNSG32 * pPhysical)
{
- unsigned int *ptr = NULL;
- unsigned int tmp = 0;
+ unsigned int *ptr = NULL;
+ unsigned int tmp = 0;
- if(size <= 0)
- return NULL;
+ if(size <= 0)
+ return NULL;
- dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc -> size: 0x%x\n", size);
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc_cached -> size: 0x%x\n", size);
align = ALIGN(align, sizeof(int));
- size += align;
- ptr = bmm_malloc(size, BMM_ATTR_WRITECOMBINE);
- if (!ptr) {
- printf("\tno enough memory\n");
- return NULL;
- }
-
- tmp = (unsigned int)((unsigned int)(ptr) & (align - 1));
- tmp = (unsigned int)(align - tmp);
- ptr = (unsigned int *)((unsigned int)ptr + tmp);
- *(ptr - 1) = tmp;
-
- *pPhysical = (unsigned long)bmm_get_paddr(ptr);
-
- dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc ptr: 0x%x\n", ptr);
- //memset(ptr, 0, size);
-
- return ptr;
+ size += align;
+ ptr = bmm_malloc(size, BMM_ATTR_DEFAULT);
+ if (!ptr) {
+ printf("\tno enough memory\n");
+ return NULL;
+ }
+
+ tmp = (unsigned int)((unsigned int)(ptr) & (align - 1));
+ tmp = (unsigned int)(align - tmp);
+ ptr = (unsigned int *)((unsigned int)ptr + tmp);
+ *(ptr - 1) = tmp;
+
+ *pPhysical = (unsigned long)bmm_get_paddr(ptr);
+
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc_cached ptr: 0x%x\n", ptr);
+ //memset(ptr, 0, size);
+ return ptr;
}
-void * vdec_os_api_dma_alloc_cached(UNSG32 size, UNSG32 align, UNSG32 * pPhysical)
+void * vdec_os_api_dma_alloc_writecombine(UNSG32 size, UNSG32 align, UNSG32 * pPhysical)
{
- unsigned int *ptr = NULL;
- unsigned int tmp = 0;
+ unsigned int *ptr = NULL;
+ unsigned int tmp = 0;
- if(size <= 0)
- return NULL;
+ if(size <= 0)
+ return NULL;
- dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc -> size: 0x%x\n", size);
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc_cached -> size: 0x%x\n", size);
align = ALIGN(align, sizeof(int));
- size += align;
- ptr = bmm_malloc(size, BMM_ATTR_DEFAULT);
- if (!ptr) {
- printf("\tno enough memory\n");
- return NULL;
- }
-
- tmp = (unsigned int)((unsigned int)(ptr) & (align - 1));
- tmp = (unsigned int)(align - tmp);
- ptr = (unsigned int *)((unsigned int)ptr + tmp);
- *(ptr - 1) = tmp;
-
- *pPhysical = (unsigned long)bmm_get_paddr(ptr);
-
- dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc ptr: 0x%x\n", ptr);
- //memset(ptr, 0, size);
-
- return ptr;
+ size += align;
+ ptr = bmm_malloc(size, BMM_ATTR_WRITECOMBINE);
+ if (!ptr) {
+ printf("\tno enough memory\n");
+ return NULL;
+ }
+ tmp = (unsigned int)((unsigned int)(ptr) & (align - 1));
+ tmp = (unsigned int)(align - tmp);
+ ptr = (unsigned int *)((unsigned int)ptr + tmp);
+ *(ptr - 1) = tmp;
+
+ *pPhysical = (unsigned long)bmm_get_paddr(ptr);
+
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc_writecombine ptr: 0x%x\n", ptr);
+ //memset(ptr, 0, size);
+ return ptr;
}
UNSG32 vdec_os_api_flush_cache(UNSG32 vaddr, UNSG32 size, enum dma_data_direction direction)
{
- switch (direction) {
- case DMA_FROM_DEVICE:
- bmm_flush_cache_range((void *)vaddr, size, BMM_DMA_FROM_DEVICE);
- break;
- case DMA_TO_DEVICE:
- bmm_flush_cache_range((void *)vaddr, size, BMM_DMA_TO_DEVICE);
- break;
- case DMA_BIDIRECTIONAL:
- bmm_flush_cache_range((void *)vaddr, size, BMM_DMA_BIDIRECTIONAL);
- break;
+ if (0 < size) {
+ switch (direction) {
+ case DMA_FROM_DEVICE:
+ bmm_flush_cache_range((void *)vaddr, size, BMM_DMA_FROM_DEVICE);
+ break;
+ case DMA_TO_DEVICE:
+ bmm_flush_cache_range((void *)vaddr, size, BMM_DMA_TO_DEVICE);
+ break;
+ case DMA_BIDIRECTIONAL:
+ bmm_flush_cache_range((void *)vaddr, size, BMM_DMA_BIDIRECTIONAL);
+ break;
+ }
+ } else {
+ switch (direction) {
+ case DMA_FROM_DEVICE:
+ bmm_flush_cache((void *)vaddr, BMM_DMA_FROM_DEVICE);
+ break;
+ case DMA_TO_DEVICE:
+ bmm_flush_cache((void *)vaddr, BMM_DMA_TO_DEVICE);
+ break;
+ case DMA_BIDIRECTIONAL:
+ bmm_flush_cache((void *)vaddr, BMM_DMA_BIDIRECTIONAL);
+ break;
+ }
}
return 0;
}
@@ -248,69 +298,62 @@ UNSG32 vdec_os_api_flush_cache(UNSG32 vaddr, UNSG32 size, enum dma_data_directio
// enable vmeta interrupt
void vdec_os_api_irq_enable(void)
{
- if(vdec_iface == NULL)
- return;
-
- ioctl(vdec_iface->uiofd, UIO_VPRO_IRQ_ENABLE);
+ int irq_on = 1;
+ write(vdec_iface->uiofd, &irq_on, sizeof(int));
}
// disable vmeta interrupt
void vdec_os_api_irq_disable(void)
{
- if(vdec_iface == NULL)
- return;
-
- ioctl(vdec_iface->uiofd, UIO_VPRO_IRQ_DISABLE);
+ int irq_on = 0;
+ write(vdec_iface->uiofd, &irq_on, sizeof(int));
}
SIGN32 vdec_os_api_set_sync_timeout_isr(UNSG32 timeout)
{
- vdec_timer.tv_sec = 0;
- vdec_timer.tv_usec = timeout * 1000;
-
- return 0;
+ syncTimeout = timeout;
+ return syncTimeout;
}
SIGN32 vdec_os_api_sync_event()
{
- SIGN32 ret = VDEC_OS_DRIVER_OK;
- fd_set rd_fds, tmp_fds;
- struct timeval timeout;
-
- if(vdec_iface == NULL)
+ struct pollfd ufds;
+ int result = 0;
+
+ ufds.fd = vdec_iface->uiofd;
+ ufds.events = POLLIN;
+
+ vdec_os_api_irq_enable();
+ result = poll(&ufds, 1, syncTimeout);
+ if(result > 0)
+ return VDEC_OS_DRIVER_OK;
+ else
return -VDEC_OS_DRIVER_SYNC_TIMEOUT_FAIL;
+}
+//End of mem mmap
+#define VMETA_VERSION_PREFIX "build-"
- FD_ZERO(&rd_fds);
- FD_SET(vdec_iface->uiofd, &rd_fds);
-
- timeout.tv_sec = vdec_timer.tv_sec;
- timeout.tv_usec = vdec_timer.tv_usec;
-
- while(1) {
- int ret = 0;
-
- tmp_fds = rd_fds;
+int get_version(char *msg)
+{
+ int ret;
+ int version;
- // enable interrupt
- vdec_os_api_irq_enable();
+ FILE *file = fopen(msg, "r");
- ret = select(vdec_iface->uiofd + 1, &tmp_fds, NULL, NULL, &timeout);
- if(FD_ISSET(vdec_iface->uiofd, &tmp_fds)) {
- int irq_num;
- read(vdec_iface->uiofd, &irq_num, sizeof(int));
- // Or handle userspace ISR here
- break;
- }
-
- // timeout
- ret = -VDEC_OS_DRIVER_SYNC_TIMEOUT_FAIL;
+ if(!file) {
+ dbg_printf(VDEC_DEBUG_ALL, "Error: get_mem_size -> fopen failed\n");
+ return -1;
+ }
- break;
+ ret = fscanf(file, VMETA_VERSION_PREFIX"%d", &version);
+ if(ret<0) {
+ dbg_printf(VDEC_DEBUG_ALL, "Error: get_version -> fscanf failed\n");
+ version = -1;
}
-
- return ret;
+
+ fclose(file);
+ return version;
}
-//End of mem mmap
UNSG32 get_mem_size(char *msg)
{
@@ -354,48 +397,13 @@ UNSG32 get_mem_addr(char *msg)
return result;
}
-// VMeta power on
-void vdec_os_api_power_on(void) {
- if(vdec_iface == NULL)
- return;
-
- ioctl(vdec_iface->uiofd, UIO_VMETA_POWER_ON);
- }
-
-// VMeta power off
-void vdec_os_api_power_off(void) {
- if(vdec_iface == NULL)
- return;
-
- ioctl(vdec_iface->uiofd, UIO_VMETA_POWER_OFF);
-}
-
-// check VMeta is ready to suspend
-SIGN32 vdec_os_api_suspend_check(void) {
- SIGN32 suspend_check;
-
- if(vdec_iface == NULL)
- return 0;
-
- ioctl(vdec_iface->uiofd, UIO_VMETA_SUSPEND_CHECK, &suspend_check);
-
- return suspend_check;
-}
-
-// VMeta is ready to suspend
-void vdec_os_api_suspend_ready(void) {
- if(vdec_iface == NULL)
- return;
-
- ioctl(vdec_iface->uiofd, UIO_VMETA_SUSPEND_READY);
-}
-
// init vdec os driver
SIGN32 vdec_os_driver_init(void)
{
int ret = 0;
+ int rv;
- if(vdec_iface != NULL) { // already been initiated
+ if(vdec_iface != NULL) { // already been initiated in this process
vdec_iface->refcount++;
return ret;
}
@@ -417,6 +425,13 @@ SIGN32 vdec_os_driver_init(void)
}
dbg_printf(VDEC_DEBUG_ALL, "vdec os driver open: %s\n", UIO_DEV);
+ vdec_iface->kern_ver = get_version(UIO_IO_VERSION);
+ if(vdec_iface->kern_ver < VMETA_KERN_MIN_VER) {
+ ret = -VDEC_OS_DRIVER_VER_FAIL;
+ goto err_open_fail;
+ }
+ dbg_printf(VDEC_DEBUG_VER, "vdec os driver kern=%d user=%s\n", vdec_iface->kern_ver,VMETA_USER_VER);
+
// Get the IO mem size of vPro's register
vdec_iface->io_mem_size = get_mem_size(UIO_IO_MEM_SIZE);
if(vdec_iface->io_mem_size <= 0) {
@@ -465,23 +480,31 @@ SIGN32 vdec_os_driver_clean(void)
// decrease the refcount
vdec_iface->refcount--;
- if(vdec_iface->refcount != 0)
+ if(vdec_iface->refcount != 0) {
+ dbg_printf(VDEC_DEBUG_ALL, "refcount = %d\n", vdec_iface->refcount);
return 0;
+ }
// unmap memory area
- if(vdec_iface->io_mem_virt_addr > 0)
+ if(vdec_iface->io_mem_virt_addr > 0) {
munmap((void*)vdec_iface->io_mem_virt_addr, vdec_iface->io_mem_size);
+ dbg_printf(VDEC_DEBUG_MEM, "munmap with io_mem_virt_addr = 0x%x\n", vdec_iface->io_mem_virt_addr);
+ }
// close fd
- if(vdec_iface->uiofd > 0)
+ if(vdec_iface->uiofd > 0) {
close(vdec_iface->uiofd);
+ dbg_printf(VDEC_DEBUG_ALL, "uio close\n");
+ }
// free vdec_iface
if(vdec_iface != NULL) {
free((void*)vdec_iface);
+ dbg_printf(VDEC_DEBUG_ALL, "free vdec_iface\n");
vdec_iface = NULL;
}
+ dbg_printf(VDEC_DEBUG_ALL, "vmeta clean done\n");
return 0;
}
@@ -501,6 +524,10 @@ int dbg_printf(UNSG32 dbglevel, const char* format, ...) {
printf(dbgBuf);
else if((VDEC_DEBUG_MEM & globalDbgLevel) && (dbglevel == VDEC_DEBUG_MEM))
printf(dbgBuf);
+ else if((VDEC_DEBUG_LOCK & globalDbgLevel) && (dbglevel == VDEC_DEBUG_LOCK))
+ printf(dbgBuf);
+ else if((VDEC_DEBUG_VER & globalDbgLevel) && (dbglevel == VDEC_DEBUG_VER))
+ printf(dbgBuf);
else
return 0;
}
@@ -512,3 +539,546 @@ int dbg_printf(UNSG32 dbglevel, const char* format, ...) {
vdec_os_driver_cb_t *vdec_driver_get_cb(void) {
return vdec_iface;
}
+
+SIGN32 vdec_os_api_get_hw_obj_addr(UNSG32* vaddr,UNSG32 size)
+{
+ UNSG32 io_mem_size;
+ UNSG32 io_mem_addr;
+ UNSG32 io_mem_virt_addr;
+ UNSG32 ret = VDEC_OS_DRIVER_OK;
+
+ if(vdec_iface->vdec_obj_va != 0)
+ {
+ dbg_printf(VDEC_DEBUG_MEM, "Already get vdec obj\n");
+ }
+
+ io_mem_size = get_mem_size(UIO_IO_VMETA_OBJ_SIZE);
+ if(io_mem_size <= 0 || io_mem_size < size) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_hw_obj_addr error: get_mem_size io_mem_size=%d, requested size=%d!!!\n", \
+ io_mem_size, size);
+ goto get_vdec_obj_fail;
+ }
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_hw_obj_addr: get_mem_size io_mem_size=%d, requested size=%d\n", \
+ io_mem_size,size);
+
+ io_mem_virt_addr = (SIGN32)mmap(NULL, size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, vdec_iface->uiofd, UIO_IO_VMETA_OBJ_INDEX*getpagesize());
+ if(io_mem_virt_addr == -1) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_hw_obj_addr: mmap hw obj error\n");
+ goto get_vdec_obj_fail;
+ }
+
+ dbg_printf(VDEC_DEBUG_MEM, "UIO_IO_VMETA_OBJ_ADDR virtual 0x%x\n", io_mem_virt_addr);
+
+ *vaddr = io_mem_virt_addr;
+ vdec_iface->vdec_obj_va = (UNSG32)io_mem_virt_addr;
+
+get_vdec_obj_fail:
+ return ret;
+}
+
+SIGN32 vdec_os_api_get_hw_context_addr(UNSG32* paddr, UNSG32* vaddr, UNSG32 size, SIGN32 flag)
+{
+ UNSG32 io_mem_size;
+ UNSG32 io_mem_addr;
+ UNSG32 io_mem_virt_addr;
+
+ UNSG32 ret = VDEC_OS_DRIVER_OK;
+
+ if(vdec_iface->hw_context_pa != 0)
+ {
+ dbg_printf(VDEC_DEBUG_MEM, "Already get hw context\n");
+ }
+ io_mem_size = get_mem_size(UIO_IO_HW_CONTEXT_SIZE);
+ if(io_mem_size <= 0 || io_mem_size < size) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_hw_context_addr error: get_mem_size io_mem_size=%d, requested size=%d!!!\n", \
+ io_mem_size,size);
+ goto get_hw_context_fail;
+ }
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_hw_context_addr: get_mem_size io_mem_size=%d, requested size=%d\n", \
+ io_mem_size,size);
+
+ io_mem_addr = get_mem_addr(UIO_IO_HW_CONTEXT_ADDR);
+ if(io_mem_addr <= 0) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_hw_context_addr: get_mem_addr error\n");
+ goto get_hw_context_fail;
+ }
+
+ *((UNSG32*) paddr) = io_mem_addr;
+ vdec_iface->hw_context_pa = io_mem_addr;
+
+ dbg_printf(VDEC_DEBUG_MEM, "UIO_IO_HW_CONTEXT_ADDR: 0x%08x\n", *((UNSG32*) paddr));
+
+
+get_hw_context_fail:
+ return ret;
+}
+
+SIGN32 vdec_os_api_get_ks(kernel_share** pp_ks)
+{
+ UNSG32 io_mem_size;
+ UNSG32 io_mem_addr;
+ UNSG32 io_mem_virt_addr;
+
+ UNSG32 ret = VDEC_OS_DRIVER_OK;
+
+ if(vdec_iface->kernel_share_va != 0)
+ {
+ dbg_printf(VDEC_DEBUG_MEM, "Already get kernel share\n");
+ return 0;
+ }
+
+ io_mem_size = get_mem_size(UIO_IO_KERNEL_SHARE_SIZE);
+ if(io_mem_size <= 0 ) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_ks: get_mem_size error\n");
+ goto get_vos_fail;
+ }
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_ks: get_mem_size io_mem_size=%d\n",io_mem_size);
+
+ io_mem_virt_addr = (UNSG32)mmap(NULL, io_mem_size, \
+ PROT_READ|PROT_WRITE, MAP_SHARED, vdec_iface->uiofd, \
+ UIO_IO_KERNEL_SHARE_INDEX*getpagesize());
+ if(io_mem_virt_addr == -1) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_get_ks: mmap ks error\n");
+ goto get_vos_fail;
+ }
+
+ dbg_printf(VDEC_DEBUG_MEM, "kernel share virtual address: 0x%x\n", io_mem_virt_addr);
+
+ *pp_ks = (kernel_share *)io_mem_virt_addr;
+ vdec_iface->kernel_share_va = io_mem_virt_addr;
+
+get_vos_fail:
+ return ret;
+}
+
+int find_user_id(id_instance *list)//return unoccupied id
+{
+ int i;
+ for(i=0; i<MAX_VMETA_INSTANCE; i++) {
+ if(get_bit(VMETA_STATUS_BIT_USED, &(list[i].status)) == 0) {
+ set_bit(VMETA_STATUS_BIT_USED, &(list[i].status));
+ return i;
+ }
+ }
+ return -VDEC_OS_DRIVER_USER_ID_FAIL;
+}
+
+SIGN32 vdec_os_api_force_ini(void)
+{
+ kernel_share *p_ks;
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+ int rv;
+
+ if(p_cb->kernel_share_va==0)
+ {
+ vdec_os_api_get_ks(&p_ks);
+ }
+ else
+ {
+ p_ks = (kernel_share *)p_cb->kernel_share_va;
+ }
+
+ vmeta_private_lock();
+ memset(p_ks, 0, sizeof(kernel_share));
+ p_ks->active_user_id = MAX_VMETA_INSTANCE;
+ vmeta_private_unlock();
+
+ ioctl(vdec_iface->uiofd,VMETA_CMD_UNLOCK);
+
+ return 0;
+}
+
+SIGN32 vdec_os_api_get_user_id(void)
+{
+ kernel_share *p_ks;
+ SIGN32 ret = -1;
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+
+ if(p_cb->kernel_share_va==0)
+ {
+ vdec_os_api_get_ks(&p_ks);
+ }
+ else
+ {
+ p_ks = (kernel_share *)p_cb->kernel_share_va;
+ }
+
+ vmeta_private_lock();
+ ret = find_user_id(p_ks->user_id_list);
+ if( ret < 0) {
+ dbg_printf(VDEC_DEBUG_ALL, "vdec_os_api_get_user_id: find_user_id error\n");
+ }
+ vmeta_private_unlock();
+
+ return ret;
+
+}
+
+SIGN32 vdec_os_api_free_user_id(SIGN32 user_id)
+{
+ kernel_share *p_ks;
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+
+ if(p_cb->kernel_share_va==0)
+ {
+ printf("vdec_os_api_free_user_id error: not init yet\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+
+ if(user_id >= MAX_VMETA_INSTANCE || user_id < 0) {
+ printf("vdec_os_api_free_user_id error: exceeds max user_id\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+ p_ks = (kernel_share *)p_cb->kernel_share_va;
+
+ vmeta_private_lock();
+
+ clear_bit(VMETA_STATUS_BIT_REGISTED,&(p_ks->user_id_list[user_id].status));
+ clear_bit(VMETA_STATUS_BIT_USED,&(p_ks->user_id_list[user_id].status));
+
+ vmeta_private_unlock();
+
+ return VDEC_OS_DRIVER_OK;
+ }
+
+int vmeta_thread_monitor(struct monitor_data * p_md)
+{
+ kernel_share *p_ks;
+ unsigned int *ret;
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+ pthread_attr_t pat;
+ int detach_attr;
+
+ if(p_cb->kernel_share_va==0 || p_md == NULL)
+ {
+ printf("vdec_os_api_free_user_id error: not init yet\n");
+ return -1;
+ }
+ p_ks = (kernel_share *)p_cb->kernel_share_va;
+
+ if(pthread_getattr_np(p_md->pt,&pat) != 0)
+ {
+ dbg_printf(VDEC_DEBUG_LOCK,"get thread attr failed \n");
+ goto tag_monitor_fail;
+ }
+
+ if( pthread_attr_getdetachstate(&pat,&detach_attr) != 0)
+ {
+ dbg_printf(VDEC_DEBUG_LOCK,"get detach attr failed \n");
+ goto tag_monitor_fail;
+ }
+
+ if( detach_attr == PTHREAD_CREATE_DETACHED)
+ {
+ dbg_printf(VDEC_DEBUG_LOCK,"The thread is a detached thread, cannot join \nexit monitor! \n");
+ goto tag_monitor_fail;
+ }
+
+ dbg_printf(VDEC_DEBUG_LOCK,"wait for pt=0x%x \n",p_md->pt);
+ pthread_join(p_md->pt,NULL);
+ dbg_printf(VDEC_DEBUG_LOCK,"pt=0x%x is killed user_id(%d)\n",p_md->pt,p_md->user_id);
+
+ if( (p_ks->lock_flag==VMETA_LOCK_ON) && (p_md->user_id==p_ks->active_user_id))
+ {
+ vdec_os_api_unlock(p_md->user_id);
+
+ vmeta_private_lock();
+ p_ks->lock_flag = VMETA_LOCK_FORCE_INIT;
+ p_ks->ref_count--;
+ memset(&(p_ks->user_id_list[p_ks->active_user_id]),0x0,sizeof(id_instance));
+ vmeta_private_unlock();
+ }
+
+ free(p_md);//This is malloced in register function
+ pthread_attr_destroy(&pat);
+ return 0;
+
+tag_monitor_fail:
+ free(p_md);
+ pthread_attr_destroy(&pat);
+ return -1;
+
+}
+
+ SIGN32 vdec_os_api_register_user_id(SIGN32 user_id)
+ {
+ kernel_share *p_ks;
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+ pthread_t tmp;
+ struct monitor_data *p_md;
+
+ if(user_id>=MAX_VMETA_INSTANCE || user_id<0) {
+ printf("vdec_os_api_register_user_id error: exceeds max user_id\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+
+ if(p_cb->kernel_share_va==0)
+ {
+ vdec_os_api_get_ks(&p_ks);
+ }
+ else
+ {
+ p_ks = (kernel_share *)p_cb->kernel_share_va;
+ }
+
+ if(set_bit(VMETA_STATUS_BIT_REGISTED, &(p_ks->user_id_list[user_id].status)) == 1) {
+ printf("vdec_os_api_register_user_id error: user id has already been registered\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+
+ p_md = (struct monitor_data*) malloc(sizeof(struct monitor_data));//This is freed monitor function
+ if(p_md == NULL) {
+ printf("vdec_os_api_register_user_id error: OOM\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+ p_ks->ref_count++;
+ p_ks->user_id_list[user_id].pid = getpid();
+ p_md->pt = pthread_self();
+ p_ks->user_id_list[user_id].pt = (unsigned int) p_md->pt;
+ p_md->user_id = user_id;
+
+ pthread_create(&tmp,NULL,vmeta_thread_monitor,p_md);
+ dbg_printf(VDEC_DEBUG_LOCK,"pid=0x%x,pt=0x%x are monitored user_id(%d)\n",p_ks->user_id_list[user_id].pid,p_ks->user_id_list[user_id].pt,user_id);
+
+ return VDEC_OS_DRIVER_OK;
+
+ }
+
+ SIGN32 vdec_os_api_unregister_user_id(SIGN32 user_id)
+ {
+ kernel_share *p_ks;
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+
+ if(user_id>=MAX_VMETA_INSTANCE || user_id<0) {
+ printf("vdec_os_api_unregister_user_id error: exceeds max user_id\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+
+ if(p_cb->kernel_share_va==0)
+ {
+ printf("vdec_os_api_unregister_user_id error: not init yet\n");
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+ else
+ {
+ p_ks = (kernel_share *)p_cb->kernel_share_va;
+ }
+
+ if(clear_bit(VMETA_STATUS_BIT_REGISTED,&(p_ks->user_id_list[user_id].status)) == 0) {
+ printf("vdec_os_api_unregister_user_id error: user id[%d] has not been registered\n",user_id);
+ return VDEC_OS_DRIVER_USER_ID_FAIL;
+ }
+
+ p_ks->ref_count--;
+
+ return VDEC_OS_DRIVER_OK;
+ }
+
+
+ SIGN32 vmeta_private_lock()
+ {
+ ioctl(vdec_iface->uiofd,VMETA_CMD_PRIV_LOCK,(unsigned long)0xffffffff);
+ return 0;
+ }
+
+ SIGN32 vmeta_private_unlock()
+ {
+ ioctl(vdec_iface->uiofd,VMETA_CMD_PRIV_UNLOCK);
+ return 0;
+ }
+
+ SIGN32 vdec_os_api_get_user_count(void)
+ {
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+ kernel_share *p_ks;
+
+ if(p_cb == NULL) {
+ printf("vdec_os_api_get_user_count error: point is NULL\n");
+ return -1;
+ }
+ p_ks = (kernel_share*)p_cb->kernel_share_va;
+
+ dbg_printf(VDEC_DEBUG_ALL, "get_user_count=%d \n",p_ks->ref_count);
+
+ return p_ks->ref_count;
+ }
+
+ SIGN32 vdec_os_api_lock(SIGN32 user_id, long to_ms)
+ {
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+ kernel_share* p_ks;
+ struct timespec ts;
+ SIGN32 ret;
+ SIGN32 sem_val;
+
+ if(p_cb == NULL) {
+ printf("vdec_os_api_lock error: point is NULL\n");
+ return LOCK_RET_ERROR_UNKNOWN;
+ }
+ p_ks = (kernel_share*)p_cb->kernel_share_va;
+
+ if(p_ks->active_user_id == user_id) {
+ dbg_printf(VDEC_DEBUG_LOCK,"lock same user\n");
+ return LOCK_RET_ME;//just return since they are the same caller
+ }
+
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_LOCK,(unsigned long)to_ms);
+ if(ret!=0) {
+ dbg_printf(VDEC_DEBUG_LOCK, "lock timeout \n");
+ return LOCK_RET_ERROR_TIMEOUT;
+ }
+
+ vmeta_private_lock();
+ p_ks->active_user_id = user_id;
+ if(p_ks->lock_flag == VMETA_LOCK_FORCE_INIT){
+ p_ks->lock_flag = VMETA_LOCK_ON;
+ vmeta_private_unlock();
+ return LOCK_RET_FORCE_INIT;
+ }
+ p_ks->lock_flag = VMETA_LOCK_ON;
+ vmeta_private_unlock();
+
+ return LOCK_RET_OHTERS_NORM;
+ }
+
+ SIGN32 vdec_os_api_unlock(SIGN32 user_id)
+ {
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+ kernel_share* p_ks;
+ int ret;
+
+ if(p_cb == NULL) {
+ printf("vdec_os_api_unlock error: point is NULL\n");
+ return LOCK_RET_ERROR_UNKNOWN;
+ }
+
+ p_ks = (kernel_share*)p_cb->kernel_share_va;
+ vmeta_private_lock();
+ if(p_ks->active_user_id == user_id) {
+ p_ks->active_user_id = MAX_VMETA_INSTANCE;
+ p_ks->lock_flag = VMETA_LOCK_OFF;
+ }
+ else
+ {
+ printf("vdec_os_api_unlock error: unlock other user id %d; active_user_id is %d\n", user_id, p_ks->active_user_id);
+ vmeta_private_unlock();
+ return LOCK_RET_ERROR_UNKNOWN;
+ }
+ vmeta_private_unlock();
+
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_UNLOCK);
+ dbg_printf(VDEC_DEBUG_LOCK, "ID: %d after unlock\n", user_id);
+ if(ret != 0) {
+ printf("vdec_os_api_unlock ioctl error\n");
+ return LOCK_RET_ERROR_UNKNOWN;
+ }
+
+ return LOCK_RET_OHTERS_NORM;
+ }
+
+SIGN32 vdec_os_api_power_on(void)
+{
+ SIGN32 ret = 0;
+
+ if(vdec_iface == NULL) {
+ return -1;
+ }
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_POWER_ON);
+
+ return ret;
+}
+
+SIGN32 vdec_os_api_power_off(void)
+{
+ SIGN32 ret = 0;
+
+ if(vdec_iface == NULL) {
+ return -1;
+ }
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_POWER_OFF);
+
+ return ret;
+}
+
+SIGN32 vdec_os_api_clock_on(void)
+{
+ SIGN32 ret = 0;
+
+ if(vdec_iface == NULL) {
+ return -1;
+ }
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_CLK_ON);
+
+ return ret;
+}
+
+SIGN32 vdec_os_api_clock_off(void)
+{
+ SIGN32 ret = 0;
+
+ if(vdec_iface == NULL) {
+ return -1;
+ }
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_CLK_OFF);
+
+ return ret;
+}
+
+SIGN32 vdec_os_api_clock_switch(VMETA_CLOCK_OP vco)
+{
+ SIGN32 ret = 0;
+
+ if(vdec_iface == NULL) {
+ return -1;
+ }
+ ret = ioctl(vdec_iface->uiofd,VMETA_CMD_CLK_SWITCH,(unsigned long)vco);
+
+ return ret;
+}
+
+SIGN32 vdec_os_driver_version(SIGN8 *ver_str)
+{
+ vdec_os_driver_cb_t *p_cb = vdec_driver_get_cb();
+
+ if(p_cb==NULL || ver_str==NULL) {
+ printf("vdec_os_driver_version error: point is NULL\n");
+ return -VDEC_OS_DRIVER_VER_FAIL;
+ }
+
+ //ver_str = (UNSG8 *)VMETA_USER_VER;
+ strcpy(ver_str,VMETA_USER_VER);
+ dbg_printf(VDEC_DEBUG_VER, "vmeta user lib ver=%s\n", ver_str);
+
+ return VDEC_OS_DRIVER_OK;
+}
+
+// check VMeta is ready to suspend
+SIGN32 vdec_os_api_suspend_check(void) {
+ SIGN32 suspend_check;
+
+ if(vdec_iface == NULL)
+ return 0;
+
+ ioctl(vdec_iface->uiofd, VMETA_CMD_SUSPEND_CHECK, &suspend_check);
+
+ return suspend_check;
+}
+
+// VMeta is ready to suspend
+SIGN32 vdec_os_api_suspend_ready(void) {
+ if(vdec_iface == NULL)
+ return;
+
+ ioctl(vdec_iface->uiofd, VMETA_CMD_SUSPEND_READY);
+
+ return 0;
+}
+
+