summaryrefslogtreecommitdiff
path: root/vmeta_lib.c
diff options
context:
space:
mode:
authorLea Li <lea.li@marvell.com>2010-04-19 18:16:47 +0800
committerLea Li <lea.li@marvell.com>2010-04-19 18:16:47 +0800
commitd22406f55aa68562b23cc64d3249255f608eccd7 (patch)
tree1e58f82539ce661b81ebaa10dc8cd9eed1a5a44e /vmeta_lib.c
initial commit
Signed-off-by: Lea Li <lea.li@marvell.com>
Diffstat (limited to 'vmeta_lib.c')
-rwxr-xr-xvmeta_lib.c452
1 files changed, 452 insertions, 0 deletions
diff --git a/vmeta_lib.c b/vmeta_lib.c
new file mode 100755
index 0000000..9d83f30
--- /dev/null
+++ b/vmeta_lib.c
@@ -0,0 +1,452 @@
+/*
+ * vmeta_lib.c
+ *
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.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))
+
+// global variable
+vdec_os_driver_cb_t *vdec_iface = NULL;
+UNSG32 globalDbgLevel = VDEC_DEBUG_NONE;
+struct timeval vdec_timer;
+
+//Add for hal mmap
+UNSG8 vdec_os_api_rd8(UNSG32 addr)
+{
+ return *((volatile UNSG8*)addr);
+}
+
+UNSG16 vdec_os_api_rd16(UNSG32 addr)
+{
+ return *((volatile UNSG16*)addr);
+}
+
+UNSG32 vdec_os_api_rd32(UNSG32 addr)
+{
+ return *((volatile UNSG32*)addr);
+}
+
+void vdec_os_api_wr8(UNSG32 addr, UNSG8 data)
+{
+ *((volatile UNSG8*)addr) = data;
+}
+
+void vdec_os_api_wr16(UNSG32 addr, UNSG16 data)
+{
+ *((volatile UNSG16*)addr) = data;
+}
+
+void vdec_os_api_wr32(UNSG32 addr, UNSG32 data)
+{
+ *((volatile UNSG32*)addr) = data;
+}
+
+UNSG32 vdec_os_api_get_regbase_addr(void)
+{
+ vdec_os_driver_cb_t *vdec_iface = vdec_driver_get_cb();
+ return vdec_iface->io_mem_virt_addr;
+}
+//End of hal mmap
+
+//Mem map to bmm_lib
+UNSG32 vdec_os_api_get_pa(UNSG32 vaddr)
+{
+ return ((UNSG32)bmm_get_paddr((void *)vaddr));
+}
+
+UNSG32 vdec_os_api_get_va(UNSG32 paddr)
+{
+ return ((UNSG32)bmm_get_vaddr((void *)paddr));
+}
+
+void vdec_os_api_vfree(void *ptr)
+{
+ unsigned int offset = 0;
+ unsigned int *paddr = NULL;
+
+ paddr = (unsigned int *)(ptr);
+ offset = *(paddr - 1);
+ paddr = (unsigned int *)((unsigned int)paddr - offset);
+ free((void *)paddr);
+}
+
+void *vdec_os_api_vmalloc(UNSG32 size, UNSG32 align)
+{
+ unsigned int *ptr = NULL;
+ unsigned int tmp = 0;
+
+ align = ALIGN(align, sizeof(int));
+ size += align;
+ ptr = malloc(size);
+ 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;
+
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_vmalloc ptr: 0x%x\n", ptr);
+ return ptr;
+}
+
+void vdec_os_api_dma_free(void *ptr)
+{
+ unsigned int offset = 0;
+ unsigned int *paddr = NULL;
+
+ paddr = (unsigned int *)(ptr);
+ offset = *(paddr - 1);
+ paddr = (unsigned int *)((unsigned int)paddr - offset);
+ bmm_free((void *)paddr);
+}
+
+void * vdec_os_api_dma_alloc(UNSG32 size, UNSG32 align, UNSG32 * pPhysical)
+{
+ unsigned int *ptr = NULL;
+ unsigned int tmp = 0;
+
+ if(size <= 0)
+ return NULL;
+
+ dbg_printf(VDEC_DEBUG_MEM, "vdec_os_api_dma_alloc -> size: 0x%x\n", size);
+
+ align = ALIGN(align, sizeof(int));
+ size += align;
+ ptr = bmm_malloc(size, BMM_ATTR_NONBUFFERABLE | BMM_ATTR_NONCACHEABLE);
+ 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;
+}
+
+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;
+ }
+ return 0;
+}
+
+// enable vmeta interrupt
+void vdec_os_api_irq_enable(void)
+{
+ if(vdec_iface == NULL)
+ return;
+
+ ioctl(vdec_iface->uiofd, UIO_VPRO_IRQ_ENABLE);
+}
+
+// disable vmeta interrupt
+void vdec_os_api_irq_disable(void)
+{
+ if(vdec_iface == NULL)
+ return;
+
+ ioctl(vdec_iface->uiofd, UIO_VPRO_IRQ_DISABLE);
+}
+
+SIGN32 vdec_os_api_set_sync_timeout_isr(UNSG32 timeout)
+{
+ vdec_timer.tv_sec = 0;
+ vdec_timer.tv_usec = timeout * 1000;
+
+ return 0;
+}
+
+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)
+ return -VDEC_OS_DRIVER_SYNC_TIMEOUT_FAIL;
+
+ 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;
+
+ // enable interrupt
+ vdec_os_api_irq_enable();
+
+ 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;
+
+ break;
+ }
+
+ return ret;
+}
+//End of mem mmap
+
+UNSG32 get_mem_size(char *msg)
+{
+ int ret;
+ UNSG32 result;
+ FILE *file = fopen(msg, "r");
+
+ if(!file) {
+ dbg_printf(VDEC_DEBUG_ALL, "Error: get_mem_size -> fopen failed\n");
+ return -VDEC_OS_DRIVER_OPEN_FAIL;
+ }
+
+ ret = fscanf(file, "0x%x", &result);
+ if(ret<0) {
+ dbg_printf(VDEC_DEBUG_ALL, "Error: get_mem_size -> fscanf failed\n");
+ result = 0;
+ }
+
+ fclose(file);
+ return result;
+}
+
+UNSG32 get_mem_addr(char *msg)
+{
+ UNSG32 result;
+ int ret;
+ FILE *file = fopen(msg, "r");
+
+ if(!file) {
+ dbg_printf(VDEC_DEBUG_ALL, "Error: get_mem_addr -> fopen failed\n");
+ return -VDEC_OS_DRIVER_OPEN_FAIL;
+ }
+
+ ret = fscanf(file, "0x%x", &result);
+ if(ret<0) {
+ dbg_printf(VDEC_DEBUG_ALL, "Error: get_mem_addr -> fscanf failed\n");
+ result = 0;
+ }
+
+ fclose(file);
+ 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;
+
+ if(vdec_iface != NULL) { // already been initiated
+ vdec_iface->refcount++;
+ return ret;
+ }
+
+ // Prepare the vdec os driver control interface
+ vdec_iface = (vdec_os_driver_cb_t*)malloc(sizeof(vdec_os_driver_cb_t));
+ memset((void*)vdec_iface, 0, sizeof(vdec_os_driver_cb_t));
+ if(vdec_iface == NULL)
+ return -VDEC_OS_DRIVER_INIT_FAIL;
+
+ // initialize reference count
+ vdec_iface->refcount++;
+
+ // Open the vdec uio driver
+ vdec_iface->uiofd = open(UIO_DEV, O_RDWR);
+ if(vdec_iface->uiofd < 0) {
+ ret = -VDEC_OS_DRIVER_OPEN_FAIL;
+ goto err_open_fail;
+ }
+ dbg_printf(VDEC_DEBUG_ALL, "vdec os driver open: %s\n", UIO_DEV);
+
+ // 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) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ goto err_mmap_fail;
+ }
+ dbg_printf(VDEC_DEBUG_MEM, "vdec os driver io mem size: 0x%x\n", vdec_iface->io_mem_size);
+
+ // Get the IO mem phy addr
+ vdec_iface->io_mem_phy_addr = get_mem_addr(UIO_IO_MEM_ADDR);
+ if(vdec_iface->io_mem_phy_addr <= 0) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ goto err_mmap_fail;
+ }
+ dbg_printf(VDEC_DEBUG_MEM, "vdec os driver io mem phy addr: 0x%x\n", vdec_iface->io_mem_phy_addr);
+
+ // mmap the io mem area
+ vdec_iface->io_mem_virt_addr = (SIGN32)mmap(NULL, vdec_iface->io_mem_size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, vdec_iface->uiofd, 0);
+
+ if(vdec_iface->io_mem_virt_addr == -1) {
+ ret = -VDEC_OS_DRIVER_MMAP_FAIL;
+ goto err_mmap_fail;
+ }
+ dbg_printf(VDEC_DEBUG_MEM, "vdec os driver io mem map to: 0x%x\n", vdec_iface->io_mem_virt_addr);
+
+ return ret;
+
+err_mmap_fail:
+ if(vdec_iface->io_mem_virt_addr > 0)
+ munmap((void*)vdec_iface->io_mem_virt_addr, vdec_iface->io_mem_size);
+ close(vdec_iface->uiofd);
+err_open_fail:
+ free((void*)vdec_iface);
+ vdec_iface = NULL;
+
+ return ret;
+}
+
+// clean vdec os driver
+SIGN32 vdec_os_driver_clean(void)
+{
+ if(vdec_iface == NULL)
+ return -VDEC_OS_DRIVER_CLEAN_FAIL;
+
+ // decrease the refcount
+ vdec_iface->refcount--;
+
+ if(vdec_iface->refcount != 0)
+ return 0;
+
+ // unmap memory area
+ if(vdec_iface->io_mem_virt_addr > 0)
+ munmap((void*)vdec_iface->io_mem_virt_addr, vdec_iface->io_mem_size);
+
+ // close fd
+ if(vdec_iface->uiofd > 0)
+ close(vdec_iface->uiofd);
+
+ // free vdec_iface
+ if(vdec_iface != NULL) {
+ free((void*)vdec_iface);
+ vdec_iface = NULL;
+ }
+
+ return 0;
+}
+
+/* display debug message */
+int dbg_printf(UNSG32 dbglevel, const char* format, ...) {
+ char dbgBuf[256] = {'\0'};
+ va_list var;
+
+ if(VDEC_DEBUG_NONE == globalDbgLevel)
+ return 0;
+ else {
+ va_start(var, format);
+ vsprintf(dbgBuf, format, var);
+ va_end(var);
+
+ if(VDEC_DEBUG_ALL & globalDbgLevel)
+ printf(dbgBuf);
+ else if((VDEC_DEBUG_MEM & globalDbgLevel) && (dbglevel == VDEC_DEBUG_MEM))
+ printf(dbgBuf);
+ else
+ return 0;
+ }
+
+ return 0;
+}
+
+/* vdec driver get cb */
+vdec_os_driver_cb_t *vdec_driver_get_cb(void) {
+ return vdec_iface;
+}