summaryrefslogtreecommitdiff
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
initial commit
Signed-off-by: Lea Li <lea.li@marvell.com>
-rwxr-xr-xvmeta_lib.c452
-rwxr-xr-xvmeta_lib.h144
2 files changed, 596 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;
+}
diff --git a/vmeta_lib.h b/vmeta_lib.h
new file mode 100755
index 0000000..561e855
--- /dev/null
+++ b/vmeta_lib.h
@@ -0,0 +1,144 @@
+#ifndef VDEC_OS_DRIVER_H
+#define VDEC_OS_DRIVER_H
+#include <sys/poll.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define VDEC_DEBUG_ALL 0x1
+#define VDEC_DEBUG_MEM 0x2
+#define VDEC_DEBUG_NONE 0x80
+
+#define UIO_DEV "/dev/uio0"
+#define UIO_IO_MEM_SIZE "/sys/class/uio/uio0/maps/map0/size"
+#define UIO_IO_MEM_ADDR "/sys/class/uio/uio0/maps/map0/addr"
+
+//---------------------------------------------------------------------------
+// Macros
+//---------------------------------------------------------------------------
+#ifndef UNSG32
+#define UNSG32 unsigned int
+#endif
+
+#ifndef SIGN32
+#define SIGN32 int
+#endif
+
+#ifndef UNSG16
+#define UNSG16 unsigned short
+#endif
+
+#ifndef SIGN16
+#define SIGN16 short
+#endif
+
+#ifndef UNSG8
+#define UNSG8 unsigned char
+#endif
+
+enum dma_data_direction {
+ DMA_BIDIRECTIONAL = 0,
+ DMA_TO_DEVICE = 1,
+ DMA_FROM_DEVICE = 2,
+ DMA_NONE = 3,
+};
+
+//---------------------------------------------------------------------------
+// Driver initialization API
+//---------------------------------------------------------------------------
+SIGN32 vdec_os_driver_init(void);
+SIGN32 vdec_os_driver_clean(void);
+
+//---------------------------------------------------------------------------
+// Memory operation API
+//---------------------------------------------------------------------------
+void * vdec_os_api_dma_alloc(UNSG32 size, UNSG32 align, UNSG32 * pPhysical);
+
+void vdec_os_api_dma_free(void *ptr);
+void *vdec_os_api_vmalloc(UNSG32 size, UNSG32 align); // always return VA and can't be translated to PA
+void vdec_os_api_vfree(void *ptr);
+UNSG32 vdec_os_api_get_va(UNSG32 paddr);
+UNSG32 vdec_os_api_get_pa(UNSG32 vaddr);
+
+UNSG32 vdec_os_api_flush_cache(UNSG32 vaddr, UNSG32 size, enum dma_data_direction direction);
+
+//---------------------------------------------------------------------------
+// Mem/IO R/W API
+//---------------------------------------------------------------------------
+UNSG8 vdec_os_api_rd8(UNSG32 addr);
+UNSG16 vdec_os_api_rd16(UNSG32 addr);
+UNSG32 vdec_os_api_rd32(UNSG32 addr);
+void vdec_os_api_wr8(UNSG32 addr, UNSG8 data);
+void vdec_os_api_wr16(UNSG32 addr, UNSG16 data);
+void vdec_os_api_wr32(UNSG32 addr, UNSG32 data);
+UNSG32 vdec_os_api_get_regbase_addr(void); // return VA
+
+//---------------------------------------------------------------------------
+// Interrupt register API
+//---------------------------------------------------------------------------
+SIGN32 vdec_os_api_set_sync_timeout_isr(UNSG32 timeout);
+SIGN32 vdec_os_api_sync_event();
+
+//---------------------------------------------------------------------------
+// Power Management API
+//---------------------------------------------------------------------------
+void vdec_os_api_power_on(void);
+void vdec_os_api_power_off(void);
+SIGN32 vdec_os_api_suspend_check(void);
+void vdec_os_api_suspend_ready(void);
+
+typedef enum _VPRO_CODEC_ERROR_CODE_ {
+ VDEC_OS_DRIVER_OK = 0,
+ VDEC_OS_DRIVER_INIT_FAIL,
+ VDEC_OS_DRIVER_OPEN_FAIL,
+ VDEC_OS_DRIVER_NO_SYS_MEM_FAIL,
+ VDEC_OS_DRIVER_MEM_POOL_INIT_FAIL,
+ VDEC_OS_DRIVER_MMAP_FAIL,
+ VDEC_OS_DRIVER_SYNC_TIMEOUT_FAIL,
+ VDEC_OS_DRIVER_IO_CONTROL_FAIL,
+ VDEC_OS_DRIVER_ALREADY_INIT_FAIL,
+ VDEC_OS_DRIVER_CLEAN_FAIL
+}VPRO_DEC_ERROR_CODE;
+
+/*************************
+ * Vmeta ioctl Define *
+ *************************/
+#define IOP_MAGIC 'v'
+
+#define UIO_VPRO_IRQ_ENABLE _IO(IOP_MAGIC, 2)
+#define UIO_VPRO_IRQ_DISABLE _IO(IOP_MAGIC, 3)
+#define UIO_VPRO_XV_IN_QUEUE _IOW(IOP_MAGIC, 4, struct vpro_xv_frame) // used for vpro decoder to put a video frame in queue
+#define UIO_VPRO_XV_DQUEUE _IOR(IOP_MAGIC, 5, struct vpro_xv_frame) // used for vpro decoder to free a video frame in queue
+#define UIO_VPRO_XV_QUERY_VIDEO _IOR(IOP_MAGIC, 6, struct vpro_xv_frame) // used for vo xv interface to query a video frame that from vpro
+#define UIO_VPRO_XV_FREE_VIDEO _IOW(IOP_MAGIC, 7, struct vpro_xv_frame) // used for vo xv interface to free a video frame
+#define UIO_VPRO_XV_INIT_QUEUE _IO(IOP_MAGIC, 8)
+#define UIO_VMETA_POWER_ON _IO(IOP_MAGIC, 9)
+#define UIO_VMETA_POWER_OFF _IO(IOP_MAGIC, 10)
+#define UIO_VMETA_SUSPEND_CHECK _IOR(IOP_MAGIC, 11, int)
+#define UIO_VMETA_SUSPEND_READY _IO(IOP_MAGIC, 12)
+
+/* display debug message */
+int dbg_printf(UNSG32 dbglevel, const char* format, ...);
+
+//---------------------------------------------------------------------------
+// the control block of vdec os driver
+//---------------------------------------------------------------------------
+typedef struct vdec_os_driver_cb_s
+{
+ int uiofd; // the uio file descriptor
+ UNSG32 io_mem_phy_addr; // the physical addr of io register base
+ SIGN32 io_mem_virt_addr; // the reg base addr that maped from kernel
+ UNSG32 io_mem_size; // the size of io mem area
+ int refcount; // reference count
+} vdec_os_driver_cb_t;
+
+/* vdec driver get cb */
+vdec_os_driver_cb_t *vdec_driver_get_cb(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif