diff options
Diffstat (limited to 'vmeta_lib.c')
-rwxr-xr-x | vmeta_lib.c | 856 |
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; +} + + |