From 3550ca2f59ae1e5f1d5f33fdfa0b56aa06f9930e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 20 Oct 2012 16:16:08 +0100 Subject: Add support for /dev/vmeta miscdevice The kernel folk don't like the uio ioctl idea, so we can't use uio for this driver. Instead, switch it to be a self-contained miscdevice. This adds support to this library for the miscdevice interface. --- uio_vmeta.h | 56 +++++++++++++++++++--------- vmeta_lib.c | 119 ++++++++++++++++++++++++++++++++++++++++-------------------- vmeta_lib.h | 8 +++- 3 files changed, 126 insertions(+), 57 deletions(-) diff --git a/uio_vmeta.h b/uio_vmeta.h index d1cef5f..6f262a7 100644 --- a/uio_vmeta.h +++ b/uio_vmeta.h @@ -10,39 +10,60 @@ #define __UIO_VMETA_H typedef unsigned int vmeta_instance_status; -typedef struct _id_instance -{ - vmeta_instance_status status; - int height; - int width; - int frame_rate; - pid_t pid; - unsigned int pt;//pthread_t -}id_instance; + +struct _id_instance { + vmeta_instance_status status; + int height; + int width; + int frame_rate; + pid_t pid; + unsigned int pt; /* pthread_t */ +}; #define MAX_VMETA_INSTANCE 32 -typedef enum _VMETA_LOCK_FLAG{ +enum _VMETA_LOCK_FLAG { VMETA_LOCK_OFF = 0, VMETA_LOCK_ON, VMETA_LOCK_FORCE_INIT -}VMETA_LOCK_FLAG; +}; /* This struct should be aligned with user space API */ -typedef struct _kernel_share -{ +struct _kernel_share { int ref_count; - VMETA_LOCK_FLAG lock_flag; + enum _VMETA_LOCK_FLAG lock_flag; int active_user_id; - id_instance user_id_list[MAX_VMETA_INSTANCE]; -}kernel_share; + struct _id_instance user_id_list[MAX_VMETA_INSTANCE]; +}; + +#ifndef __KERNEL__ +/* + * Needed for userspace + */ +typedef enum _VMETA_LOCK_FLAG VMETA_LOCK_FLAG; +typedef struct _id_instance id_instance; +typedef struct _kernel_share kernel_share; +#endif struct vmeta_lock { unsigned long timeout; unsigned int user_id; }; -#define IOP_MAGIC 'v' +struct vmeta_info { + uint32_t revision; + struct { + uint32_t phys; + uint32_t size; + } map[3]; +}; + +#define VMETA_STATUS_BIT_USED 0 +#define VMETA_STATUS_BIT_REGISTED 1 +#define VMETA_STATUS_USED BIT(0) +#define VMETA_STATUS_REGISTERED BIT(1) + +#define IOP_MAGIC ('v') #define VMETA_CMD_POWER_ON _IO(IOP_MAGIC, 0) #define VMETA_CMD_POWER_OFF _IO(IOP_MAGIC, 1) @@ -65,5 +86,6 @@ struct vmeta_lock { #define VMETA_CMD_UNLOCK_USER_ID _IO(IOP_MAGIC, 18) #define VMETA_CMD_FORCE_INI _IO(IOP_MAGIC, 19) #define VMETA_CMD_GET_USER_NUM _IOR(IOP_MAGIC, 20, unsigned) +#define VMETA_CMD_GET_INFO _IOR(IOP_MAGIC, 21, struct vmeta_info) #endif /* __UIO_VMETA_H */ diff --git a/vmeta_lib.c b/vmeta_lib.c index d8e7bcf..38b0139 100644 --- a/vmeta_lib.c +++ b/vmeta_lib.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -257,14 +258,14 @@ UNSG32 vdec_os_api_flush_cache(UNSG32 vaddr, UNSG32 size, enum dma_data_directio void vdec_os_api_irq_enable(void) { int irq_on = 1; - write(vdec_iface->uiofd, &irq_on, sizeof(int)); + write(vdec_iface->fd, &irq_on, sizeof(int)); } // disable vmeta interrupt void vdec_os_api_irq_disable(void) { int irq_on = 0; - write(vdec_iface->uiofd, &irq_on, sizeof(int)); + write(vdec_iface->fd, &irq_on, sizeof(int)); } SIGN32 vdec_os_api_set_sync_timeout_isr(UNSG32 timeout) @@ -278,7 +279,7 @@ SIGN32 vdec_os_api_sync_event() struct pollfd ufds; int result = 0; - ufds.fd = vdec_iface->uiofd; + ufds.fd = vdec_iface->fd; ufds.events = POLLIN; vdec_os_api_irq_enable(); @@ -347,12 +348,17 @@ static UNSG32 get_file_unsg32(const char *fmt, ...) static int uio_get_map(unsigned uio_num, unsigned map, unsigned size, void **rptr, unsigned *rsize, UNSG32 *rphys) { + vdec_os_driver_cb_t *vdec = vdec_iface; UNSG32 phys; UNSG32 map_size; void *addr; - map_size = get_file_unsg32("/sys/class/uio/uio%u/maps/map%u/size", - uio_num, map); + if (vdec->uio) { + map_size = get_file_unsg32("/sys/class/uio/uio%u/maps/map%u/size", + uio_num, map); + } else { + map_size = vdec->map[map].size; + } if (map_size == (UNSG32)-VDEC_OS_DRIVER_OPEN_FAIL) return -VDEC_OS_DRIVER_OPEN_FAIL; @@ -370,8 +376,12 @@ static int uio_get_map(unsigned uio_num, unsigned map, unsigned size, void **rpt *rsize = map_size; if (rphys) { - phys = get_file_unsg32("/sys/class/uio/uio%u/maps/map%u/addr", - uio_num, map); + if (vdec->uio) { + phys = get_file_unsg32("/sys/class/uio/uio%u/maps/map%u/addr", + uio_num, map); + } else { + phys = vdec->map[map].phys; + } if (phys == (UNSG32)-VDEC_OS_DRIVER_OPEN_FAIL) return -VDEC_OS_DRIVER_OPEN_FAIL; if (phys == 0) @@ -385,7 +395,7 @@ static int uio_get_map(unsigned uio_num, unsigned map, unsigned size, void **rpt size = map_size; addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, - vdec_iface->uiofd, map * getpagesize()); + vdec->fd, map * getpagesize()); if (addr == MAP_FAILED) { dbg_printf(VDEC_DEBUG_MEM, "Error: %s: mmap of map %u failed: %d\n", __FUNCTION__, map, errno); @@ -439,20 +449,51 @@ SIGN32 vdec_os_driver_init(void) // 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; + // Try to open the (new) vmeta device + vdec_iface->fd = open("/dev/vmeta", O_RDWR); + if (vdec_iface->fd == -1) { + if (errno == ENOENT || errno == ENODEV) { + // Try the older uio vmeta driver + vdec_iface->fd = open(UIO_DEV, O_RDWR); + if(vdec_iface->fd < 0) { + ret = -VDEC_OS_DRIVER_OPEN_FAIL; + goto err_open_fail; + } + vdec_iface->uio = 1; + + dbg_printf(VDEC_DEBUG_ALL, "%s: using UIO fd=%d\n", + __FUNCTION__, vdec_iface->fd); + + vdec_iface->kern_ver = get_version(UIO_IO_VERSION); + } + } else { + struct vmeta_info info; + int i; +info.revision = 1; + ret = ioctl(vdec_iface->fd, VMETA_CMD_GET_INFO, &info); + if (ret == -1) { + dbg_printf(VDEC_DEBUG_ALL, "%s: unable to get info: %s\n", + __FUNCTION__, strerror(errno)); + close(vdec_iface->fd); + ret = -VDEC_OS_DRIVER_VER_FAIL; + goto err_open_fail; + } + + vdec_iface->kern_ver = info.revision; + + for (i = 0; i < 3; i++) { + vdec_iface->map[i].phys = info.map[i].phys; + vdec_iface->map[i].size = info.map[i].size; + } } - dbg_printf(VDEC_DEBUG_ALL, "vdec os driver open: %s uiofd=%d\n", UIO_DEV,vdec_iface->uiofd); - vdec_iface->kern_ver = get_version(UIO_IO_VERSION); + dbg_printf(VDEC_DEBUG_VER, "vdec os driver kern=%d user=%s\n", vdec_iface->kern_ver,VMETA_USER_VER); + if(vdec_iface->kern_ver < VMETA_KERN_MIN_VER) { + close(vdec_iface->fd); 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 phy addr and size of vPro's register ret = uio_get_map(0, UIO_IO_MEM_INDEX, 0, &addr, &size, &phys); @@ -472,7 +513,7 @@ SIGN32 vdec_os_driver_init(void) err_mmap_fail: if(vdec_iface->io_mem_virt_addr > 0) munmap(vdec_iface->io_mem_virt_addr, vdec_iface->io_mem_size); - close(vdec_iface->uiofd); + close(vdec_iface->fd); err_open_fail: free(vdec_iface); vdec_iface = NULL; @@ -531,8 +572,8 @@ SIGN32 vdec_os_driver_clean(void) } // close fd - if(vdec_iface->uiofd > 0) { - close(vdec_iface->uiofd); + if(vdec_iface->fd > 0) { + close(vdec_iface->fd); dbg_printf(VDEC_DEBUG_ALL, "uio close\n"); } @@ -687,7 +728,7 @@ SIGN32 vdec_os_api_force_ini(void) if (p_cb && p_cb->kern_ver >= 100) { int ret; - ret = ioctl(p_cb->uiofd, VMETA_CMD_FORCE_INI); + ret = ioctl(p_cb->fd, VMETA_CMD_FORCE_INI); return ret < 0 ? -1 : 0; } @@ -703,7 +744,7 @@ SIGN32 vdec_os_api_force_ini(void) p_ks->active_user_id = MAX_VMETA_INSTANCE; vmeta_private_unlock(); - ioctl(vdec_iface->uiofd,VMETA_CMD_UNLOCK); + ioctl(vdec_iface->fd,VMETA_CMD_UNLOCK); return 0; } @@ -717,7 +758,7 @@ SIGN32 vdec_os_api_get_user_id(void) if (p_cb->kern_ver >= 100) { unsigned id; - ret = ioctl(p_cb->uiofd, VMETA_CMD_GET_USER_ID, &id); + ret = ioctl(p_cb->fd, VMETA_CMD_GET_USER_ID, &id); return ret == 0 && id < MAX_VMETA_INSTANCE ? id : -VDEC_OS_DRIVER_USER_ID_FAIL; @@ -747,7 +788,7 @@ SIGN32 vdec_os_api_free_user_id(SIGN32 user_id) if (p_cb->kern_ver >= 100) { int ret; - ret = ioctl(p_cb->uiofd, VMETA_CMD_FREE_USER_ID, user_id); + ret = ioctl(p_cb->fd, VMETA_CMD_FREE_USER_ID, user_id); return ret == 0 ? VDEC_OS_DRIVER_OK : VDEC_OS_DRIVER_USER_ID_FAIL; } @@ -878,7 +919,7 @@ SIGN32 vdec_os_api_register_user_id(SIGN32 user_id) if (p_cb->kern_ver >= 100) { int ret; - ret = ioctl(p_cb->uiofd, VMETA_CMD_REGISTER_USER_ID, user_id); + ret = ioctl(p_cb->fd, VMETA_CMD_REGISTER_USER_ID, user_id); if (ret < 0) { dbg_printf(VDEC_DEBUG_ALL, "%s: error %d\n", @@ -930,7 +971,7 @@ SIGN32 vdec_os_api_unregister_user_id(SIGN32 user_id) if (p_cb->kern_ver >= 100) { int ret; - ret = ioctl(p_cb->uiofd, VMETA_CMD_UNREGISTER_USER_ID, user_id); + ret = ioctl(p_cb->fd, VMETA_CMD_UNREGISTER_USER_ID, user_id); if (ret < 0) { dbg_printf(VDEC_DEBUG_ALL, "%s: error: %d\n", __FUNCTION__, errno); @@ -965,13 +1006,13 @@ SIGN32 vdec_os_api_unregister_user_id(SIGN32 user_id) static SIGN32 vmeta_private_lock() { - ioctl(vdec_iface->uiofd,VMETA_CMD_PRIV_LOCK,(unsigned long)0xffffffff); + ioctl(vdec_iface->fd,VMETA_CMD_PRIV_LOCK,(unsigned long)0xffffffff); return 0; } static SIGN32 vmeta_private_unlock() { - ioctl(vdec_iface->uiofd,VMETA_CMD_PRIV_UNLOCK); + ioctl(vdec_iface->fd,VMETA_CMD_PRIV_UNLOCK); return 0; } @@ -989,7 +1030,7 @@ SIGN32 vdec_os_api_get_user_count(void) unsigned num; int ret; - ret = ioctl(p_cb->uiofd, VMETA_CMD_GET_USER_NUM, &num); + ret = ioctl(p_cb->fd, VMETA_CMD_GET_USER_NUM, &num); return ret < 0 ? -1 : num; } @@ -1023,7 +1064,7 @@ SIGN32 vdec_os_api_lock(SIGN32 user_id, long to_ms) lock.user_id = user_id; lock.timeout = to_ms; - ret = ioctl(p_cb->uiofd, VMETA_CMD_LOCK_USER_ID, &lock); + ret = ioctl(p_cb->fd, VMETA_CMD_LOCK_USER_ID, &lock); if (ret < 0) { switch (errno) { @@ -1048,7 +1089,7 @@ SIGN32 vdec_os_api_lock(SIGN32 user_id, long to_ms) return LOCK_RET_ME;//just return since they are the same caller } - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_LOCK,(unsigned long)to_ms); + ret = ioctl(vdec_iface->fd,VMETA_CMD_LOCK,(unsigned long)to_ms); if(ret!=0) { dbg_printf(VDEC_DEBUG_LOCK, "lock timeout\n"); return LOCK_RET_ERROR_TIMEOUT; @@ -1079,7 +1120,7 @@ SIGN32 vdec_os_api_unlock(SIGN32 user_id) } if (p_cb->kern_ver >= 100) { - ret = ioctl(p_cb->uiofd, VMETA_CMD_UNLOCK_USER_ID, user_id); + ret = ioctl(p_cb->fd, VMETA_CMD_UNLOCK_USER_ID, user_id); if (ret < 0) { dbg_printf(VDEC_DEBUG_LOCK, "%s: error %d\n", @@ -1103,7 +1144,7 @@ SIGN32 vdec_os_api_unlock(SIGN32 user_id) } vmeta_private_unlock(); - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_UNLOCK); + ret = ioctl(vdec_iface->fd,VMETA_CMD_UNLOCK); dbg_printf(VDEC_DEBUG_LOCK, "ID: %d after unlock\n", user_id); if(ret != 0) { dbg_printf(VDEC_DEBUG_LOCK,"vdec_os_api_unlock ioctl error\n"); @@ -1120,7 +1161,7 @@ SIGN32 vdec_os_api_power_on(void) if(vdec_iface == NULL) { return -1; } - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_POWER_ON); + ret = ioctl(vdec_iface->fd,VMETA_CMD_POWER_ON); return ret; } @@ -1132,7 +1173,7 @@ SIGN32 vdec_os_api_power_off(void) if(vdec_iface == NULL) { return -1; } - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_POWER_OFF); + ret = ioctl(vdec_iface->fd,VMETA_CMD_POWER_OFF); return ret; } @@ -1144,7 +1185,7 @@ SIGN32 vdec_os_api_clock_on(void) if(vdec_iface == NULL) { return -1; } - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_CLK_ON); + ret = ioctl(vdec_iface->fd,VMETA_CMD_CLK_ON); return ret; } @@ -1156,7 +1197,7 @@ SIGN32 vdec_os_api_clock_off(void) if(vdec_iface == NULL) { return -1; } - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_CLK_OFF); + ret = ioctl(vdec_iface->fd,VMETA_CMD_CLK_OFF); return ret; } @@ -1168,7 +1209,7 @@ SIGN32 vdec_os_api_clock_switch(VMETA_CLOCK_OP vco) if(vdec_iface == NULL) { return -1; } - ret = ioctl(vdec_iface->uiofd,VMETA_CMD_CLK_SWITCH,(unsigned long)vco); + ret = ioctl(vdec_iface->fd,VMETA_CMD_CLK_SWITCH,(unsigned long)vco); return ret; } @@ -1196,7 +1237,7 @@ SIGN32 vdec_os_api_suspend_check(void) { if(vdec_iface == NULL) return 0; - ioctl(vdec_iface->uiofd, VMETA_CMD_SUSPEND_CHECK, &suspend_check); + ioctl(vdec_iface->fd, VMETA_CMD_SUSPEND_CHECK, &suspend_check); return suspend_check; } @@ -1206,7 +1247,7 @@ SIGN32 vdec_os_api_suspend_ready(void) { if(vdec_iface == NULL) return 0; - ioctl(vdec_iface->uiofd, VMETA_CMD_SUSPEND_READY); + ioctl(vdec_iface->fd, VMETA_CMD_SUSPEND_READY); return 0; } diff --git a/vmeta_lib.h b/vmeta_lib.h index 058d9c9..6226542 100644 --- a/vmeta_lib.h +++ b/vmeta_lib.h @@ -173,7 +173,13 @@ typedef sem_t lock_t; //--------------------------------------------------------------------------- typedef struct vdec_os_driver_cb_s { - int uiofd; // the uio file descriptor + int fd; // kernel file descriptor + int uio; // using uio driver + struct { + UNSG32 phys; + UNSG32 size; + } map[3]; + UNSG32 io_mem_phy_addr; // the physical addr of io register base void *io_mem_virt_addr; // the reg base addr that maped from kernel UNSG32 io_mem_size; // the size of io mem area -- cgit