GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
SDK_DIR := $(shell cd $(CURDIR)/../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
.PHONY: all clean
all:
$(AT)test -d $(SDK_STATIC_LIB_DIR) || mkdir -p $(SDK_STATIC_LIB_DIR)
$(AT)test -d $(SDK_SHARE_LIB_DIR) || mkdir -p $(SDK_SHARE_LIB_DIR)
$(AT)cp $(GMP_DIR)/lib/$(CONFIG_XMEDIA_USR_ARM_TOOLCHAINS)/$(OBJ_LOG_MODE)/static/*.a $(SDK_STATIC_LIB_DIR) -rf
$(AT)cp $(GMP_DIR)/lib/$(CONFIG_XMEDIA_USR_ARM_TOOLCHAINS)/$(OBJ_LOG_MODE)/share/*.so $(SDK_SHARE_LIB_DIR) -rf
$(AT)cp -rf $(GMP_DIR)/include $(OUT_DIR)
$(AT)$(MAKE) -C drv/
$(AT)$(MAKE) -C usr/
clean:
$(AT)$(MAKE) -C drv/ clean
$(AT)$(MAKE) -C usr/ clean
+30
View File
@@ -0,0 +1,30 @@
SDK_DIR := $(shell cd $(CURDIR)/../../.. && /bin/pwd)
include $(SDK_DIR)/build/base.mk
objects := osal lsadc misc ext pm
objects += obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
objects += init
endif
obj-$(XMEDIA_DRV_BUILDTYPE) += $(addsuffix /, $(objects))
objects_clean := $(addsuffix _clean, $(objects))
.PHONY: all clean $(objects) $(objects_clean)
all: $(objects)
ifeq ($(XMEDIA_DRV_BUILDTYPE),m)
$(AT)cp -rf $(BUILD_DIR)/load $(SDK_KO_DIR)
endif
clean: $(objects_clean)
$(objects):
$(AT)$(MAKE) -C $@
$(objects_clean):
$(AT)$(MAKE) -C $(patsubst %_clean, %, $@) clean
+24
View File
@@ -0,0 +1,24 @@
SDK_DIR ?= $(shell cd $(CURDIR)/../../../.. && /bin/pwd)
include $(SDK_DIR)/build/base.mk
objects :=
objects += msensor
obj-$(XMEDIA_DRV_BUILDTYPE) += ${addsuffix /,${objects}}
objects_clean := $(addsuffix _clean, $(objects))
.PHONY: all clean prepare $(objects) $(objects_clean)
all: prepare $(objects)
clean: $(objects_clean)
$(objects):
$(AT)$(MAKE) -C $@
$(objects_clean):
$(AT)$(MAKE) -C $(patsubst %_clean, %, $@) clean
prepare:
+26
View File
@@ -0,0 +1,26 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
objects := msensor_spi msensor_mng msensor_chip
objects_clean := $(addsuffix _clean, $(objects))
obj-y += $(addsuffix /, $(objects))
.PHONY: all clean $(objects) $(objects_clean)
all: $(objects)
# $(AT)cp -rf $(BUILD_DIR)/load $(SDK_KO_DIR)
clean: $(objects_clean)
$(objects):
$(AT)$(MAKE) -C $@
$(objects_clean):
$(AT)$(MAKE) -C $(patsubst %_clean, %, $@) clean
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __DRV_MSENSOR_H__
#define __DRV_MSENSOR_H__
#include "xmedia_msensor.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
xmedia_s32 msensor_buf_add_user(xmedia_s32 dev, xmedia_s32 *id);
xmedia_s32 msensor_buf_delete_user(xmedia_s32 dev, const xmedia_s32 *id);
xmedia_s32 msensor_buf_get_data(xmedia_s32 dev, xmedia_msensor_data_info *msensor_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif //__DRV_MSENSOR_H__
@@ -0,0 +1,56 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef MOTIONSENSOR_EXT_H
#define MOTIONSENSOR_EXT_H
#include "common.h"
#include "xmedia_debug.h"
#include "xmedia_msensor.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
typedef struct {
xmedia_s32 (*pfn_get_config_from_chip) (xmedia_s32 dev, xmedia_msensor_param *param);
xmedia_s32 (*pfn_write_data_to_buf) (xmedia_s32 dev);
} msensor_mng_callback;
/* debug print format */
#define MSENSOR_ERR_TRACE(fmt, ...) \
printk(KERN_ERR "" fmt, \
##__VA_ARGS__)
#define msensor_warn_trace(fmt, ...) \
printk(KERN_WARN "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, \
##__VA_ARGS__)
#define msensor_notice_trace(fmt, ...) \
printk(KERN_NOTICE "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, \
##__VA_ARGS__)
#define msensor_info_trace(fmt, ...) \
printk(KERN_INFO "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, \
##__VA_ARGS__)
#define msensor_debug_trace(fmt, ...) \
printk(KERN_DEBUG "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, \
##__VA_ARGS__)
xmedia_s32 msensor_mng_register_call_back(xmedia_s32 dev, const msensor_mng_callback *callback);
xmedia_void msensor_mng_unregister_call_back(xmedia_s32 dev);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,44 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_CHIP_IOCTL_H__
#define __MSENSOR_CHIP_IOCTL_H__
#include "xmedia_msensor.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* end of #ifdef __cplusplus */
#define MSENSOR_TYPE_CHIP 12
typedef enum {
IOC_NR_MSENSOR_CHIP_BIND_FLAG2FD = 0,
IOC_NR_MSENSOR_CHIP_CREATE,
IOC_NR_MSENSOR_CHIP_DESTROY,
IOC_NR_MSENSOR_CHIP_START,
IOC_NR_MSENSOR_CHIP_STOP,
IOC_NR_MSENSOR_CHIP_GET_PARAM,
IOC_NR_MSENSOR_CHIP_MNG_INIT,
IOC_NR_MSENSOR_CHIP_MAX
} ioc_nr_msensor_chip;
#define MSENSOR_CMD_CHIP_BIND_FLAG2FD _IOW(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_BIND_FLAG2FD, xmedia_s32)
#define MSENSOR_CMD_START _IO(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_START)
#define MSENSOR_CMD_STOP _IO(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_STOP)
#define MSENSOR_CMD_CREATE _IOW(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_CREATE, xmedia_msensor_param)
#define MSENSOR_CMD_DESTROY _IO(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_DESTROY)
#define MSENSOR_CMD_GET_PARAM _IOR(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_GET_PARAM, xmedia_msensor_param)
#define MSENSOR_CMD_MNG_INIT _IOW(MSENSOR_TYPE_CHIP, IOC_NR_MSENSOR_CHIP_MNG_INIT, xmedia_msensor_param)
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,46 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
export TRANSFER_TYPE := SPI
MOD_NAME := xm_msensor_chip
SRCS := ./main/msensor.c
SRCS += ./proc/msensor_chip_proc.c
SRCS += ./sensor_dev/icm42670/icm42670.c
SRCS += ./sensor_dev/icm42670/msensor_gpio.c
SRCS += ./transfer_type/spi/spi_dev.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/usr/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/osal/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/proc
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/sensor_dev/icm42670
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/transfer_type/spi
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_spi/spi
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_chip/main
#SDK_KER_CFLAGS += -I$(PWD)/pub
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/ext_inc
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_spi
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_mng/include
SDK_KER_CFLAGS += -DTRANSFER_SPI
SDK_KER_CFLAGS += -DICM42670_PARAM_PROC
SDK_KER_CFLAGS += -DCONFIG_PROC_SHOW_SUPPORT
$(info SDK_KER_CFLAGS=$(SDK_KER_CFLAGS))
$(info SRCS=$(SRCS))
$(info SDK_DIR=$(SDK_DIR))
$(info CURDIR=$(CURDIR))
include $(SDK_DIR)/build/sdk_ko_rules.mk
@@ -0,0 +1,712 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor.h"
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/semaphore.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/hrtimer.h>
#include "osal.h"
#include "mmz.h"
#include "msensor_ext.h"
#include "msensor_chip_ioctl.h"
#include "msensor.h"
#include "msensor_exe.h"
#include "icm42670.h"
#define UMAP_MSENSOR_CHIP_MINOR_BASE 153
#define UMAP_DEVNANME_MSENSOR_CHIP_BASE "msensor_chip"
#if (defined CONFIG_PROC_SHOW_SUPPORT)
#include "msensor_chip_proc.h"
#endif
static osal_dev_t *g_msensor_chip_dev = XMEDIA_NULL;
static xmedia_s32 g_msensor_init[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_FALSE};
static xmedia_bool g_msensor_start[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_FALSE};
xmedia_msensor_param *g_msensor_param [XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_NULL};
static triger_config g_triger_data[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
static osal_atomic_t g_msensor_chip_user_ref[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
#define safe_kfree(memory) \
do { \
if ((memory) != XMEDIA_NULL) { \
osal_kfree(memory); \
memory = XMEDIA_NULL; \
} \
} while (0)
xmedia_msensor_param *msensor_chip_get_param(xmedia_s32 dev)
{
return g_msensor_param[dev];
}
xmedia_bool msensor_chip_get_status(xmedia_s32 dev)
{
return g_msensor_start[dev];
}
#ifdef MNGBUFF_ENABLE
xmedia_s32 msensor_chip_int_callback(xmedia_s32 dev, xmedia_msensor_data *msensor_data)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
if (msensor_data == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d msensor_data is null\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
ret = msensor_mng_write_data_to_buf(dev, msensor_data);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d write data tobuf failed!(ret:0x%x)\n", dev, ret);
return ret;
}
return ret;
}
static xmedia_s32 msensor_chip_init_mng_buf(xmedia_s32 dev, xmedia_msensor_attr msensor_attr,
xmedia_msensor_buf_attr *msensor_buf_attr, xmedia_msensor_config *msensor_config)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
if ((msensor_buf_attr == XMEDIA_NULL) || (msensor_config == XMEDIA_NULL)) {
MSENSOR_ERR_TRACE("dev %d msensor_buf_attr or msensor_config is null!\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
ret = msensor_mng_buf_init(dev, &msensor_attr, msensor_buf_attr, msensor_config);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d init mng buff failed!(ret:0x%x)\n", dev, ret);
return ret;
}
return ret;
}
static xmedia_s32 msensor_chip_exit_mng_buf(xmedia_s32 dev)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
ret = msensor_mng_buf_exit(dev);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d exit mng buff failed!(ret:0x%x)\n", dev, ret);
return ret;
}
return ret;
}
//todo,待确认,释放需要通过ioctl开放get cfg接口
static xmedia_s32 msensor_chip_get_cfg(xmedia_s32 dev, xmedia_msensor_param *msensor_param)
{
if (g_msensor_param[dev] == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d msensor_param is null\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
if (msensor_param == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d input param is null\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
osal_memcpy(msensor_param, g_msensor_param[dev], sizeof(xmedia_msensor_param));
return XMEDIA_SUCCESS;
}
// todo,通过ioctl开放get data接口
xmedia_s32 msensor_chip_get_data(xmedia_s32 dev)
{
xmedia_s32 ret;
ret = chip_get_data_for_one_frm(dev);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d get data failed!\n", dev);
}
return ret;
}
static xmedia_s32 msensor_chip_register_mng_callback(xmedia_s32 dev)
{
xmedia_s32 ret;
msensor_mng_callback callback = { 0 };
callback.pfn_get_config_from_chip = msensor_chip_get_cfg;
callback.pfn_write_data_to_buf = msensor_chip_get_data;
ret = msensor_mng_register_call_back(dev, &callback);
if(ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d register msensor callback failed\n", dev);
return XMEDIA_FAILURE;
}
return ret;
}
static xmedia_void msensor_chip_unregister_mng_callback(xmedia_s32 dev)
{
msensor_mng_unregister_call_back(dev);
return;
}
#endif
static xmedia_s32 msensor_chip_open(xmedia_void *private_data)
{
xmedia_unused(private_data);
MSENSOR_ERR_TRACE("msensor open\n");
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_chip_release(xmedia_void *private_data)
{
xmedia_unused(private_data);
MSENSOR_ERR_TRACE("msensor close\n");
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_chip_freeze(osal_dev_t *dev)
{
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_chip_restore(osal_dev_t *dev)
{
return XMEDIA_SUCCESS;
}
/* msensor chip ioctl functions */
static xmedia_s32 msensor_chip_drv_user_start(xmedia_s32 dev, xmedia_uintptr_t arg)
{
if (g_msensor_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d msensor is not init!\n", dev);
return XMEDIA_FAILURE;
}
if (g_msensor_start[dev] == XMEDIA_TRUE) {
MSENSOR_ERR_TRACE("dev %d msensor is already start!\n", dev);
return XMEDIA_SUCCESS;
}
xmedia_unused(arg);
chip_fifo_data_reset(dev);
osal_msleep(100); // 1.16 fix acc && gyro pts not sync problem
if (g_triger_data[dev].triger_mode == TRIGER_TIMER) {
chip_timer_run(dev);
} else if (g_triger_data[dev].triger_mode == TRIGER_EXTERN_INTERRUPT) {
chip_interrupt_run(dev);
} else {
MSENSOR_ERR_TRACE("not triger_mode %d\n",g_triger_data[dev].triger_mode);
return XMEDIA_FAILURE;
}
g_msensor_start[dev] = XMEDIA_TRUE;
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_chip_drv_user_stop(xmedia_s32 dev, xmedia_uintptr_t arg)
{
if (g_msensor_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d msensor is not init!\n", dev);
return XMEDIA_FAILURE;
}
if (g_msensor_start[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d msensor is already stop!\n", dev);
return XMEDIA_SUCCESS;
}
xmedia_unused(arg);
if (g_triger_data[dev].triger_mode == TRIGER_TIMER) {
chip_timer_stop(dev);
} else if (g_triger_data[dev].triger_mode == TRIGER_EXTERN_INTERRUPT) {
chip_interrupt_stop(dev);
} else {
MSENSOR_ERR_TRACE("not triger_mode %d\n",g_triger_data[dev].triger_mode);
return XMEDIA_FAILURE;
}
g_msensor_start[dev] = XMEDIA_FALSE;
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_chip_drv_user_init(xmedia_s32 dev, xmedia_uintptr_t arg)
{
xmedia_s32 ret;
xmedia_msensor_param *msensor_param;
if (g_msensor_init[dev] == XMEDIA_TRUE) {
MSENSOR_ERR_TRACE("dev %d msensor is already inited!\n", dev);
return XMEDIA_FAILURE;
}
msensor_param = (xmedia_msensor_param *)(arg);
ret = mmz_check_phyaddr(msensor_param->buf_attr.phys_addr, msensor_param->buf_attr.buf_len);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d check mem share failed, buf_attr.phys_addr is 0x%llx\n", dev,
msensor_param->buf_attr.phys_addr);
return XMEDIA_FAILURE;
}
osal_memcpy(g_msensor_param[dev], (xmedia_void *)arg, sizeof(xmedia_msensor_param));
if (((XMEDIA_MSENSOR_DEVICE_GYRO & g_msensor_param[dev]->attr.device_mask) &&
(g_msensor_param[dev]->config.gyro_config.odr == 0)) ||
((XMEDIA_MSENSOR_DEVICE_ACC & g_msensor_param[dev]->attr.device_mask) &&
(g_msensor_param[dev]->config.acc_config.odr == 0))) {
MSENSOR_ERR_TRACE("dev %d msensor param err!\n", dev);
return XMEDIA_FAILURE;
}
g_msensor_param[dev]->config.gyro_config.temperature_max = MOTIONSENSOR_MAX_TEMP;
g_msensor_param[dev]->config.gyro_config.temperature_min = MOTIONSENSOR_MIN_TEMP;
g_msensor_param[dev]->config.acc_config.temperature_max = MOTIONSENSOR_MAX_TEMP;
g_msensor_param[dev]->config.acc_config.temperature_min = MOTIONSENSOR_MIN_TEMP;
/* init senser */
ret = chip_dev_init(dev, g_msensor_param[dev]);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d chip dev init failed! ret=%x\n", dev, ret);
return ret;
}
ret = chip_get_triger_config(dev, &g_triger_data[dev]);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d imu get triger config failed! ret=%x\n", dev, ret);
return ret;
}
#ifdef MNGBUFF_ENABLE
/* buff init, fix in this */
msensor_chip_init_mng_buf(dev, g_msensor_param[dev]->attr, &g_msensor_param[dev]->buf_attr,
&g_msensor_param[dev]->config);
#endif
g_msensor_init[dev] = XMEDIA_TRUE;
return ret;
}
static xmedia_s32 msensor_chip_drv_user_deinit(xmedia_s32 dev, xmedia_uintptr_t arg)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
if (g_msensor_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d msensor has not inited!\n", dev);
return XMEDIA_FAILURE;
}
if (g_msensor_start[dev] == XMEDIA_TRUE) {
MSENSOR_ERR_TRACE("dev %d please stop msensor first!\n", dev);
return XMEDIA_FAILURE;
}
xmedia_unused(arg);
g_msensor_init[dev] = XMEDIA_FALSE;
chip_dev_exit(dev, g_msensor_param[dev]);
#ifdef MNGBUFF_ENABLE
ret = msensor_chip_exit_mng_buf(dev);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d exit mng buf failed! ret=%x\n", dev, ret);
return ret;
}
#endif
return ret;
}
static xmedia_s32 msensor_chip_drv_user_get_param(xmedia_s32 dev, xmedia_uintptr_t arg)
{
xmedia_s32 ret;
ret = mmz_check_phyaddr(g_msensor_param[dev]->buf_attr.phys_addr, g_msensor_param[dev]->buf_attr.buf_len);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d check mem share failed, buf_attr.phys_addr is 0x%llx\n", dev,
g_msensor_param[dev]->buf_attr.phys_addr);
return ret;
}
osal_memcpy((xmedia_msensor_param *)arg, g_msensor_param[dev], sizeof(xmedia_msensor_param));
return XMEDIA_SUCCESS;
}
/* only for debug: send and save yuv */
static xmedia_s32 msensor_chip_drv_user_mng_init(xmedia_s32 dev, xmedia_uintptr_t arg)
{
xmedia_s32 ret;
xmedia_msensor_param *msensor_param = XMEDIA_NULL;
if (g_msensor_init[dev] == XMEDIA_TRUE) {
MSENSOR_ERR_TRACE("dev %d msensor is already inited!\n", dev);
return XMEDIA_FAILURE;
}
msensor_param = (xmedia_msensor_param *)(arg);
ret = mmz_check_phyaddr(msensor_param->buf_attr.phys_addr, msensor_param->buf_attr.buf_len);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d check mem share failed, buf_attr.phys_addr is 0x%llx\n",
dev, msensor_param->buf_attr.phys_addr);
return ret;
}
osal_memcpy(g_msensor_param[dev], (xmedia_void *)arg, sizeof(xmedia_msensor_param));
if (((XMEDIA_MSENSOR_DEVICE_GYRO & g_msensor_param[dev]->attr.device_mask) &&
(g_msensor_param[dev]->config.gyro_config.odr == 0)) ||
((XMEDIA_MSENSOR_DEVICE_ACC & g_msensor_param[dev]->attr.device_mask) &&
(g_msensor_param[dev]->config.acc_config.odr == 0))) {
MSENSOR_ERR_TRACE("dev %d msensor param error\n", dev);
return ret;
}
/* init senser */
ret = chip_dev_mng_init(dev, g_msensor_param[dev]);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d mng init failed! ret=%x\n", dev, ret);
return ret;
}
#ifdef MNGBUFF_ENABLE
/* buff init, fix in this */
msensor_chip_init_mng_buf(dev, g_msensor_param[dev]->attr, &g_msensor_param[dev]->buf_attr,
&g_msensor_param[dev]->config);
#endif
g_msensor_init[dev] = XMEDIA_TRUE;
return ret;
}
static xmedia_s32 msensor_chip_drv_start(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_chip_drv_user_start(dev, (xmedia_uintptr_t)arg);
}
static xmedia_s32 msensor_chip_drv_stop(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_chip_drv_user_stop(dev, (xmedia_uintptr_t)arg);
}
static xmedia_s32 msensor_chip_drv_init(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_chip_drv_user_init(dev, (xmedia_uintptr_t)arg);
}
static xmedia_s32 msensor_chip_drv_deinit(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_chip_drv_user_deinit(dev, (xmedia_uintptr_t)arg);
}
static xmedia_s32 msensor_chip_drv_get_param(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_chip_drv_user_get_param(dev, (xmedia_uintptr_t)arg);
}
/* only for debug: send and save yuv */
static xmedia_s32 msensor_chip_drv_mng_init(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_chip_drv_user_mng_init(dev, (xmedia_uintptr_t)arg);
}
typedef xmedia_s32 (*msensor_ctl_ptr_func)(xmedia_s32 dev, xmedia_ulong arg);
typedef struct {
xmedia_u32 cmd;
msensor_ctl_ptr_func ptr_func;
} msensor_ioctl_func_item;
static msensor_ioctl_func_item g_msensor_chip_cmd_list[] = {
{ MSENSOR_CMD_START, msensor_chip_drv_start },
{ MSENSOR_CMD_STOP, msensor_chip_drv_stop },
{ MSENSOR_CMD_CREATE, msensor_chip_drv_init },
{ MSENSOR_CMD_DESTROY, msensor_chip_drv_deinit },
{ MSENSOR_CMD_GET_PARAM, msensor_chip_drv_get_param },
{ MSENSOR_CMD_MNG_INIT, msensor_chip_drv_mng_init }, /* only for debug: send and save yuv */
};
static xmedia_s32 msensor_chip_do_ioctl(xmedia_s32 dev, xmedia_u32 cmd, xmedia_ulong arg)
{
xmedia_s32 i;
for (i = 0; i < sizeof(g_msensor_chip_cmd_list) / sizeof(g_msensor_chip_cmd_list[0]); i++) {
if (cmd == g_msensor_chip_cmd_list[i].cmd) {
return g_msensor_chip_cmd_list[i].ptr_func(dev, arg);
}
}
MSENSOR_ERR_TRACE("dev %d msensor chip ioctl cmd 0x%x not supported!\n", dev, cmd);
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
xmedia_slong msensor_chip_ioctl(xmedia_u32 cmd, xmedia_ulong arg, xmedia_void *private_data)
{
xmedia_s32 ret;
xmedia_s32 dev;
if (cmd == MSENSOR_CMD_CHIP_BIND_FLAG2FD) {
*(xmedia_u32 *)private_data = *(xmedia_u32 *)arg;
return XMEDIA_SUCCESS;
}
dev = *(xmedia_u32 *)private_data;
osal_atomic_inc_return(&g_msensor_chip_user_ref[dev]);
ret = msensor_chip_do_ioctl(dev, cmd, arg);
osal_atomic_dec_return(&g_msensor_chip_user_ref[dev]);
return ret;
}
static struct osal_fileops g_msensor_chip_fileop = {
.open = msensor_chip_open,
.unlocked_ioctl = msensor_chip_ioctl,
.release = msensor_chip_release,
};
struct osal_pmops g_msensor_chip_drv_ops = {
.pm_freeze = msensor_chip_freeze,
.pm_restore = msensor_chip_restore,
};
static xmedia_s32 msensor_chip_param_init(xmedia_void)
{
xmedia_s32 i ,j;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
g_msensor_param[i] = (xmedia_msensor_param *)osal_kmalloc(sizeof(xmedia_msensor_param), osal_gfp_kernel);
if (g_msensor_param[i] == XMEDIA_NULL) {
osal_printk("kmalloc memory failed\n");
goto failed;
}
(xmedia_void) osal_memset(g_msensor_param[i], 0, sizeof(xmedia_msensor_param));
g_msensor_start[i] = XMEDIA_FALSE;
}
return XMEDIA_SUCCESS;
failed:
for (j = i - 1; j >= 0; j--) {
osal_kfree(g_msensor_param[j]);
}
return -ENOMEM;
}
static xmedia_s32 msensor_chip_param_exit(xmedia_void)
{
xmedia_s32 i;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
if(g_msensor_param[i] == XMEDIA_NULL) {
osal_printk("msensor_param is null, nothing to exit \n");
} else {
osal_kfree(g_msensor_param[i]);
g_msensor_param[i] = XMEDIA_NULL;
}
g_msensor_start[i] = XMEDIA_FALSE;
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_chip_sensor_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_s32 i , j;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
ret = chip_sensor_init(i);
if (ret != XMEDIA_SUCCESS) {
osal_printk("init sensor! failed ret=%x\n", ret);
goto failed;
}
}
return XMEDIA_SUCCESS;
failed:
for (j = i - 1; j >= 0; j--) {
chip_sensor_exit(j);
}
return ret;
}
static xmedia_void msensor_chip_sensor_exit(xmedia_void)
{
xmedia_s32 i;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
chip_sensor_exit(i);
}
return;
}
static xmedia_s32 msensor_chip_register_mng_callback_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_s32 i;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
ret = msensor_chip_register_mng_callback(i);
if (ret != XMEDIA_SUCCESS) {
osal_printk("register mng callback failed! ret=%x\n", ret);
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_void msensor_chip_register_mng_callback_exit(xmedia_void)
{
xmedia_s32 i;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
msensor_chip_unregister_mng_callback(i);
}
return;
}
static xmedia_s32 msensor_chip_atomic_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_s32 i ,j;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
ret = osal_atomic_init(&g_msensor_chip_user_ref[i]);
if (ret != XMEDIA_SUCCESS) {
osal_printk("atomic init failed. \n");
goto failed;
}
osal_atomic_set(&g_msensor_chip_user_ref[i], 0);
}
return XMEDIA_SUCCESS;
failed:
for (j = i - 1; j >= 0; j--) {
osal_atomic_destory(&g_msensor_chip_user_ref[j]);
}
return ret;
}
static xmedia_void msensor_chip_atomic_exit(xmedia_void)
{
xmedia_s32 i;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
osal_atomic_destroy(&g_msensor_chip_user_ref[i]);
}
return;
}
xmedia_s32 msensor_chip_module_init(xmedia_void)
{
xmedia_s32 ret;
ret = msensor_chip_param_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("init param failed! ret=%x\n", ret);
goto FAIL0;
}
ret = msensor_chip_sensor_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("init sensor failed! ret=%x\n", ret);
goto FAIL1;
}
#ifdef MNGBUFF_ENABLE
ret = msensor_chip_register_mng_callback_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("init sensor failed! ret=%x\n", ret);
goto FAIL2;
}
#endif
ret = msensor_chip_atomic_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("init sensor failed! ret=%x\n", ret);
goto FAIL3;
}
g_msensor_chip_dev = osal_createdev(UMAP_DEVNANME_MSENSOR_CHIP_BASE);
if (g_msensor_chip_dev == XMEDIA_NULL) {
osal_printk("msensor: create device failed\n");
goto FAIL4;
}
g_msensor_chip_dev->fops = &g_msensor_chip_fileop;
g_msensor_chip_dev->minor = UMAP_MSENSOR_CHIP_MINOR_BASE;
g_msensor_chip_dev->osal_pmops = &g_msensor_chip_drv_ops;
ret = osal_registerdevice(g_msensor_chip_dev);
if (ret != XMEDIA_SUCCESS) {
osal_printk("register msensor device failed!\n");
goto FAIL5;
}
#if (defined CONFIG_PROC_SHOW_SUPPORT) && (defined ICM42670_PARAM_PROC)
ret = mpu_proc_init();
if (ret != XMEDIA_SUCCESS) {
goto FAIL6;
}
#endif
osal_printk("load xm_msensor_chip.ko OK!\n");
return XMEDIA_SUCCESS;
FAIL6:
osal_deregisterdevice(g_msensor_chip_dev);
FAIL5:
osal_destroydev(g_msensor_chip_dev);
FAIL4:
msensor_chip_atomic_exit();
FAIL3:
msensor_chip_register_mng_callback_exit();
FAIL2:
msensor_chip_sensor_exit();
FAIL1:
msensor_chip_param_exit();
FAIL0:
osal_printk("load xm_msensor_chip.ko failed !\n");
return XMEDIA_FAILURE;
}
xmedia_void msensor_chip_module_exit(xmedia_void)
{
msensor_chip_atomic_exit();
#ifdef MNGBUFF_ENABLE
msensor_chip_register_mng_callback_exit();
#endif
msensor_chip_sensor_exit();
msensor_chip_param_exit();
osal_deregisterdevice(g_msensor_chip_dev);
osal_destroydev(g_msensor_chip_dev);
#if (defined CONFIG_PROC_SHOW_SUPPORT)
mpu_proc_exit();
#endif
osal_printk("unload xm_msensor_chip.ko OK!\n");
}
#ifdef MODULE
module_init(msensor_chip_module_init);
module_exit(msensor_chip_module_exit);
MODULE_AUTHOR("otlicon");
MODULE_DESCRIPTION("motion_sensor driver");
MODULE_LICENSE("GPL");
#else
int __init msensor_chip_driver_init(void)
{
return msensor_chip_module_init();
}
#endif
@@ -0,0 +1,178 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_H__
#define __MSENSOR_H__
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include "xmedia_msensor.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#define MNGBUFF_ENABLE
#define DATA_RATE_RESERVED 0x00
#define DATA_RATE_25HZ 0x06
#define DATA_RATE_50HZ 0x07
#define DATA_RATE_100HZ 0x08
#define DATA_RATE_200HZ 0x09
#define DATA_RATE_400HZ 0x0A
#define DATA_RATE_800HZ 0x0B
#define DATA_RATE_1600HZ 0x0C
#define DATA_RATE_3200HZ 0x0D
#define GYRO_FULL_SCALE_RANGE_250DPS (250 << 10)
#define GYRO_FULL_SCALE_RANGE_500DPS (500 << 10)
#define GYRO_FULL_SCALE_RANGE_1KDPS (1000 << 10)
#define GYRO_FULL_SCALE_RANGE_2KDPS (2000 << 10)
#define GYRO_FULL_SCALE_RANGE_31DPS ((3125 << 10) / 100)
#define GYRO_FULL_SCALE_RANGE_62DPS ((625 << 10) / 10)
#define GYRO_FULL_SCALE_RANGE_125DPS (125 << 10)
#define ACCEL_UI_FULL_SCALE_RANGE_2G 1
#define ACCEL_UI_FULL_SCALE_RANGE_4G 2
#define ACCEL_UI_FULL_SCALE_RANGE_8G 3
#define ACCEL_UI_FULL_SCALE_RANGE_16G 4
#define ACCEL_OIS_FULL_SCALE_RANGE_1G 5
#define ACCEL_OIS_FULL_SCALE_RANGE_2G 6
#define ACCEL_OIS_FULL_SCALE_RANGE_4G 7
#define ACCEL_OIS_FULL_SCALE_RANGE_8G 8
#define MOTIONSENSOR_MAX_TEMP 85
#define MOTIONSENSOR_MIN_TEMP (-40)
typedef enum {
GYRO_OUTPUT_DATA_RATE_32KHZ = 32000,
GYRO_OUTPUT_DATA_RATE_8KHZ = 8000,
GYRO_OUTPUT_DATA_RATE_3200HZ = 3200,
GYRO_OUTPUT_DATA_RATE_1600HZ = 1600,
GYRO_OUTPUT_DATA_RATE_800HZ = 800,
GYRO_OUTPUT_DATA_RATE_400HZ = 400,
GYRO_OUTPUT_DATA_RATE_200HZ = 200,
GYRO_OUTPUT_DATA_RATE_100HZ = 100,
GYRO_OUTPUT_DATA_RATE_50HZ = 50,
GYRO_OUTPUT_DATA_RATE_25HZ = 25,
GYRO_OUTPUT_DATA_RATE_UNDER_1KHZ,
GYRO_OUTPUT_DATA_RATE_BUTT
} msensor_gyro_output_data_rate;
typedef enum {
GYRO_BAND_WIDTH_16HZ,
GYRO_BAND_WIDTH_25HZ,
GYRO_BAND_WIDTH_34HZ,
GYRO_BAND_WIDTH_53HZ,
GYRO_BAND_WIDTH_73HZ,
GYRO_BAND_WIDTH_121HZ,
GYRO_BAND_WIDTH_180HZ,
GYRO_BAND_WIDTH_BUTT
} msensor_gyro_band_width;
typedef enum {
ACCEL_OUTPUT_DATA_RATE_4KHZ = 4000,
ACCEL_OUTPUT_DATA_RATE_1KHZ = 1000,
ACCEL_OUTPUT_DATA_RATE_1600HZ = 1600,
ACCEL_OUTPUT_DATA_RATE_800HZ = 800,
ACCEL_OUTPUT_DATA_RATE_400HZ = 400,
ACCEL_OUTPUT_DATA_RATE_200HZ = 200,
ACCEL_OUTPUT_DATA_RATE_100HZ = 100,
ACCEL_OUTPUT_DATA_RATE_50HZ = 50,
ACCEL_OUTPUT_DATA_RATE_25HZ = 25,
ACCEL_OUTPUT_DATA_RATE_UNDER_1KHZ,
ACCEL_OUTPUT_DATA_RATE_BUTT
} msensor_accel_output_data_rate;
typedef enum {
GYRO_FULL_SCALE_SET_250DPS = 250 << 10, /* 250 dps */
GYRO_FULL_SCALE_SET_500DPS = 500 << 10, /* 500 dps */
GYRO_FULL_SCALE_SET_1KDPS = 1000 << 10, /* 1000 dps */
GYRO_FULL_SCALE_SET_2KDPS = 2000 << 10, /* 2000 dps */
GYRO_FULL_SCALE_SET_31DPS = (3125 << 10) / 100, /* 31.25 dps : 3125 / 100 */
GYRO_FULL_SCALE_SET_62DPS = (625 << 10) / 10, /* 62.5 dps : 625 / 10 */
GYRO_FULL_SCALE_SET_125DPS = 125 << 10, /* 125 dps */
GYRO_FULL_SCALE_SET_BUTT
} msensor_gyro_full_scale_range;
typedef enum {
ACCEL_UI_FULL_SCALE_SET_2G = 2 << 10,
ACCEL_UI_FULL_SCALE_SET_4G = 4 << 10,
ACCEL_UI_FULL_SCALE_SET_8G = 8 << 10,
ACCEL_UI_FULL_SCALE_SET_16G = 16 << 10,
ACCEL_UI_FULL_SCALE_SET_BUTT
} msensor_accel_ui_full_scale_range;
typedef enum {
ACCEL_OIS_FULL_SCALE_SET_1G = 1,
ACCEL_OIS_FULL_SCALE_SET_2G = 2,
ACCEL_OIS_FULL_SCALE_SET_4G = 4,
ACCEL_OIS_FULL_SCALE_SET_8G = 8,
ACCEL_OIS_FULL_SCALE_SET_BUTT
} msensor_accel_ois_full_scale_range;
typedef enum {
ACCEL_BAND_WIDTH_16HZ,
ACCEL_BAND_WIDTH_25HZ,
ACCEL_BAND_WIDTH_34HZ,
ACCEL_BAND_WIDTH_53HZ,
ACCEL_BAND_WIDTH_73HZ,
ACCEL_BAND_WIDTH_121HZ,
ACCEL_BAND_WIDTH_180HZ,
ACCEL_BAND_WIDTH_BUTT
} msensor_accel_band_width;
typedef enum {
TRIGER_TIMER = 0,
TRIGER_EXTERN_INTERRUPT,
TRIGER_BUTT
} msensor_triger_mode;
typedef struct {
xmedia_u32 interval; /* unit :us */
} timer_param;
typedef struct {
xmedia_u32 interrupt_num;
} extern_interrupt_param;
typedef union {
timer_param timer_config;
extern_interrupt_param extern_interrupt_config;
} msensor_triger_info;
typedef struct {
msensor_triger_mode triger_mode;
msensor_triger_info triger_info;
} triger_config;
typedef struct {
xmedia_u32 cmd;
xmedia_s32 (*func)(xmedia_uintptr_t arg);
} msensor_chip_info;
xmedia_msensor_param *msensor_chip_get_param(xmedia_s32 dev);
xmedia_bool msensor_chip_get_status(xmedia_s32 dev);
xmedia_s32 msensor_chip_int_callback(xmedia_s32 dev, xmedia_msensor_data *msensor_data);
#define print_info(fmt, arg...) osal_printk("fun:%s,%d " fmt, __func__, __LINE__, ##arg)
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,113 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor_chip_proc.h"
#include <linux/kernel.h>
#include "osal.h"
#include "msensor.h"
#include "icm42670.h"
#define MSENSOR_CHIP_INFO "msensor_chip"
#define MSENSOR_CHIP_VERSION_INFO "msensor_chip debug 0.0.0.1"
static xmedia_char *msensor_triger_mode2_str(msensor_triger_mode mode)
{
switch (mode) {
case TRIGER_TIMER:
return "TIMER";
case TRIGER_EXTERN_INTERRUPT:
return "GPIO_INTERRUPT";
default:
return "error";
}
return "0";
}
static xmedia_void msensor_print_proc_title(osal_proc_entry_t *s, xmedia_char *title)
{
xmedia_s32 i;
for (i = 0; i < 50; i++) {
osal_seq_printf(s, "-");
}
osal_seq_printf(s, title);
for (i = 0; i < 50; i++) {
osal_seq_printf(s, "-");
}
osal_seq_printf(s, "\n");
}
static xmedia_s32 msensor_chip_proc_show(osal_proc_entry_t *s)
{
xmedia_s32 i;
xmedia_msensor_param *msensor_param = XMEDIA_NULL;
icm42670_dev_info *dev_info = XMEDIA_NULL;
osal_seq_printf(s,
"[msensor] version:[" MSENSOR_CHIP_VERSION_INFO "], build time["__DATE__
", "__TIME__
"]\n");
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
if(msensor_chip_get_status(i) == XMEDIA_FALSE) {
continue;
}
msensor_param = msensor_chip_get_param(i);
dev_info = chip_get_dev_info(i);
msensor_print_proc_title(s, "common parameter");
osal_seq_printf(s, "%24s %24s %24s\n", "dev_no", "trigle_mode", "fifo_en");
osal_seq_printf(s, "%24d %24s %24d\n", i, msensor_triger_mode2_str(dev_info->triger_data.triger_mode), dev_info->fifo_en);
if (msensor_param->attr.device_mask & XMEDIA_MSENSOR_DEVICE_GYRO) {
msensor_print_proc_title(s, "gyro parameter");
osal_seq_printf(s, "%24s\n", "##ICM42670##");
osal_seq_printf(s, "%24s %24s %24s %24s %24s\n", "sample_rate", "full-scale-range", "datawidth",
"max-chip-temperature", "min-chip-temperature");
osal_seq_printf(s, "%24d %24d %24d %24d %24d\n", msensor_param->config.gyro_config.odr,
msensor_param->config.gyro_config.fsr, msensor_param->config.gyro_config.data_width,
msensor_param->config.gyro_config.temperature_max,
msensor_param->config.gyro_config.temperature_min);
}
if (msensor_param->attr.device_mask & XMEDIA_MSENSOR_DEVICE_ACC) {
msensor_print_proc_title(s, "accelerometer parameter");
osal_seq_printf(s, "%24s\n", "##ICM42670##");
osal_seq_printf(s, "%24s %24s %24s %24s %24s\n", "sample_rate", "full-scale-range", "datawidth",
"max-chip-temperature", "min-chip-temperature");
osal_seq_printf(s, "%24d %24d %24d %24d %24d\n", msensor_param->config.acc_config.odr,
msensor_param->config.acc_config.fsr, msensor_param->config.acc_config.data_width,
msensor_param->config.acc_config.temperature_max,
msensor_param->config.acc_config.temperature_min);
}
}
return 0;
}
xmedia_s32 mpu_proc_init(xmedia_void)
{
osal_proc_entry_t *msensor_chip_entry = XMEDIA_NULL;
msensor_chip_entry = osal_create_proc_entry(MSENSOR_CHIP_INFO, XMEDIA_NULL);
if (msensor_chip_entry == XMEDIA_NULL) {
printk("osal_create_proc_entry failed!\n");
return XMEDIA_FAILURE;
}
msensor_chip_entry->read = msensor_chip_proc_show;
msensor_chip_entry->write = XMEDIA_NULL;
return XMEDIA_SUCCESS;
}
void mpu_proc_exit(xmedia_void)
{
osal_remove_proc_entry(MSENSOR_CHIP_INFO, 0);
return;
}
@@ -0,0 +1,28 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_CHIP_PROC_H__
#define __MSENSOR_CHIP_PROC_H__
#include "xmedia_type.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define MAX_LEN 32
xmedia_s32 mpu_proc_init(xmedia_void);
xmedia_void mpu_proc_exit(xmedia_void);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,162 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef ICM42670_H
#define ICM42670_H
#include "msensor.h"
#include "osal.h"
#include "linux/workqueue.h"
#include "linux/hrtimer.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#define ICM42670_DEV_ADDR 0x68
#define I2C_DEV_NUM 0x1
#define ICM42670_VALID_DATA_BIT 16
#define div_0_to_1(a) (((a) == 0) ? 1 : (a))
#define TRUE_REGISTER_VALUE 0x01
#define RESET_OFFSET 0x04
#define CLKSET_VALUE 0x01
// MREGs
#define MREG1 0
#define MREG2 1
#define MREG3 2
#define ICM42670_SELFID 0x67 // ICM42670 device id default value
#define ICM42670_FIFO_MAX_RECORD 140
#define ICM42670_FIFO_R_MAX_SIZE 1152
#define ROOMTEMP_OFFSET (25 * (0x1 << 10))
#define GRADIENT_TEMP (0x1 << 10)
#define TEMP_SENSITIVITY 128
/* icm42670 interrupt pin reg */
#define INT_GPIO_CHIP 4 //7
#define INT_GPIO_OFFSET 6 //2
#define TIME_RECORD_CNT 10
#define DATA_RECORD_CNT (TIME_RECORD_CNT)
typedef struct {
xmedia_msensor_gyro_config gyro_config;
xmedia_u32 band_width;
xmedia_u64 last_pts;
} msensor_gyro_status;
typedef struct {
xmedia_msensor_acc_config acc_config;
xmedia_u32 band_width;
xmedia_u64 last_pts;
} msensor_acc_status;
typedef struct {
xmedia_msensor_sample_data accel_cur_data;
xmedia_msensor_sample_data gyro_cur_data;
xmedia_msensor_sample_data magn_data;
struct i2c_client *client;
struct spi_device *xmedia_spi;
struct task_struct *read_data_task;
struct task_struct *get_data_kthread;
osal_work_struct_t work;
xmedia_u8 power_mode;
xmedia_u8 flag_acc_fifo_enabled;
xmedia_u8 flag_gyro_fifo_enabled;
xmedia_u8 flag_fifo_incomming;
xmedia_u8 *fifo_buf;
xmedia_u32 fifo_length;
xmedia_u8 record_num;
xmedia_u8 enable_kthread;
xmedia_u8 fifo_en;
triger_config triger_data;
struct hrtimer hrtimer;
xmedia_u8 thread_wakeup;
osal_semaphore_t g_sem;
msensor_acc_status acc_status;
msensor_gyro_status gyro_status;
xmedia_s32 temperature;
xmedia_s32 irq_num;
xmedia_s32 workqueue_call_times;
osal_wait_t wait_call_stop_working;
} icm42670_dev_info;
icm42670_dev_info *chip_get_dev_info(xmedia_s32 dev);
xmedia_s32 chip_fifo_data_reset(xmedia_s32 dev);
xmedia_s32 chip_get_triger_config(xmedia_s32 dev, triger_config *triger_data);
xmedia_s32 chip_dev_init(xmedia_s32 dev, xmedia_msensor_param *msensor_param);
xmedia_s32 chip_dev_mng_init(xmedia_s32 dev, xmedia_msensor_param *msensor_param);
xmedia_void chip_dev_exit(xmedia_s32 dev, xmedia_msensor_param *msensor_param);
xmedia_s32 chip_sensor_init(xmedia_s32 dev);
xmedia_void chip_sensor_exit(xmedia_s32 dev);
xmedia_s32 chip_timer_run(xmedia_s32 dev);
xmedia_s32 chip_interrupt_run(xmedia_s32 dev);
xmedia_s32 chip_timer_stop(xmedia_s32 dev);
xmedia_s32 chip_interrupt_stop(xmedia_s32 dev);
xmedia_s32 chip_get_data_for_one_frm(xmedia_s32 dev);
/*
* otp_pwr_down
* 0: to power up OTP for read/write operation.
* 1: to power down OTP to save power.
* This bit is automatically set to 1 when OTP copy operation is complete.
*/
#define OTP_CTRL7_OTP_PWR_DOWN_POS 0x01
#define OTP_CTRL7_OTP_PWR_DOWN_MASK (0x01 << OTP_CTRL7_OTP_PWR_DOWN_POS)
/* ---------------------------------------------------------------------------
* register MREG_FPGA
* ---------------------------------------------------------------------------*/
/* ---------------------------------------------------------------------------
* register ROM
* ---------------------------------------------------------------------------*/
#define ACCEL_DATA_SIZE 6
#define GYRO_DATA_SIZE 6
#define TEMP_DATA_SIZE 2
#define FIFO_HEADER_SIZE 1
#define FIFO_ACCEL_DATA_SIZE ACCEL_DATA_SIZE
#define FIFO_GYRO_DATA_SIZE GYRO_DATA_SIZE
#define FIFO_TEMP_DATA_SIZE 1
#define FIFO_TS_FSYNC_SIZE 2
#define FIFO_TEMP_HIGH_RES_SIZE 1
#define FIFO_ACCEL_GYRO_HIGH_RES_SIZE 3
/*
* Hysteresis high peak threshold (mg) added to the threshold after the initial threshold is met.
* Use type APEX_CONFIG5_HIGHG_PEAK_TH_HYST_t to define highG peak hysteresis
* These types are defined in inv_imu_defs.h.
*/
#define HIGHG_PEAK_HYSTERESIS APEX_CONFIG5_HIGHG_PEAK_TH_HYST_156MG
/* Initial WOM threshold to be applied to IMU in mg */
#define WOM_THRESHOLD_INITIAL_MG 200
/*
* HighG frequencies
* Use type APEX_CONFIG1_DMP_ODR_t to define DMP frequency
* These types are defined in inv_imu_defs.h.
*
* \note The frequency modes to run the HighG are :
* APEX_CONFIG1_DMP_ODR_25Hz (Low Power mode),
* APEX_CONFIG1_DMP_ODR_50Hz (Performance mode)
*/
#define HIGHG_FREQUENCY_MODE APEX_CONFIG1_DMP_ODR_50Hz
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,188 @@
/*
* ________________________________________________________________________________________________________
* Copyright (c) 2017 InvenSense Inc. All rights reserved.
*
* This software, related documentation and any modifications thereto (collectively "Software") is subject
* to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
* and other intellectual property rights laws.
*
* InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
* and any use, reproduction, disclosure or distribution of the Software without an express license agreement
* from InvenSense is strictly prohibited.
*
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
* PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
* INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THE SOFTWARE.
* ________________________________________________________________________________________________________
*/
/** @defgroup Apex APEX
* @brief High-level functions to drive APEX features
* @{
*/
/** @file inv_imu_apex.h */
#ifndef _INV_IMU_APEX_H_
#define _INV_IMU_APEX_H_
#include "inv_imu_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations */
struct inv_imu_device;
/** IMU APEX inputs parameters definition */
typedef struct {
APEX_CONFIG3_PEDO_AMP_TH_t pedo_amp_th;
uint8_t pedo_step_cnt_th;
uint8_t pedo_step_det_th;
APEX_CONFIG4_PEDO_SB_TIMER_TH_t pedo_sb_timer_th;
APEX_CONFIG4_PEDO_HI_ENRGY_TH_t pedo_hi_enrgy_th;
APEX_CONFIG5_TILT_WAIT_TIME_t tilt_wait_time;
APEX_CONFIG2_DMP_POWER_SAVE_TIME_t power_save_time;
APEX_CONFIG0_DMP_POWER_SAVE_t power_save;
APEX_CONFIG9_SENSITIVITY_MODE_t sensitivity_mode;
APEX_CONFIG2_LOW_ENERGY_AMP_TH_t low_energy_amp_th;
APEX_CONFIG9_SMD_SENSITIVITY_t smd_sensitivity;
APEX_CONFIG9_FF_DEBOUNCE_DURATION_t ff_debounce_duration;
APEX_CONFIG12_FF_MAX_DURATION_t ff_max_duration_cm;
APEX_CONFIG12_FF_MIN_DURATION_t ff_min_duration_cm;
APEX_CONFIG10_LOWG_PEAK_TH_t lowg_peak_th;
APEX_CONFIG5_LOWG_PEAK_TH_HYST_t lowg_peak_hyst;
APEX_CONFIG10_LOWG_TIME_TH_SAMPLES_t lowg_samples_th;
APEX_CONFIG11_HIGHG_PEAK_TH_t highg_peak_th;
APEX_CONFIG5_HIGHG_PEAK_TH_HYST_t highg_peak_hyst;
APEX_CONFIG11_HIGHG_TIME_TH_SAMPLES_t highg_samples_th;
} inv_imu_apex_parameters_t;
/** APEX pedometer outputs */
typedef struct inv_imu_apex_step_activity {
/** Number of steps taken */
uint16_t step_cnt;
/** Walk/run cadence in number of samples.
* Format is u6.2. (at 50Hz and 2Hz walk frequency, if the cadency
* is 25 samples, the register will output 100).
*/
uint8_t step_cadence;
/** Detected activity.
* Unknown (0), Walk (1) or Run (2)
*/
uint8_t activity_class;
} inv_imu_apex_step_activity_t;
/** @brief Enable Free Fall.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_enable_ff(struct inv_imu_device *s);
/** @brief Disable Free Fall.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_disable_ff(struct inv_imu_device *s);
/** @brief Enable Significant Motion Detection.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
* @warning SMD requires to have the pedometer enabled to work.
*/
int inv_imu_apex_enable_smd(struct inv_imu_device *s);
/** @brief Disable Significant Motion Detection.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_disable_smd(struct inv_imu_device *s);
/** @brief Fill the APEX parameters structure with all the default parameters for APEX algorithms.
* @param[in] s Pointer to device.
* @param[out] apex_inputs Default input parameters.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_init_parameters_struct(struct inv_imu_device * s,
inv_imu_apex_parameters_t *apex_inputs);
/** @brief Configures DMP parameters for APEX algorithms.
* @param[in] s Pointer to device.
* @param[in] apex_inputs The requested input parameters.
* @return 0 on success, negative value on error.
* @warning APEX inputs can't change on the fly, this should be called before enabling
* any APEX features.
* @warning This API can't be called twice within 10 ms.
*/
int inv_imu_apex_configure_parameters(struct inv_imu_device * s,
const inv_imu_apex_parameters_t *apex_inputs);
/** @brief Returns current DMP parameters for APEX algorithms.
* @param[in] s Pointer to device.
* @param[out] apex_params The current parameter, fetched from registers.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_get_parameters(struct inv_imu_device *s, inv_imu_apex_parameters_t *apex_params);
/** @brief Configure DMP Output Data Rate for APEX algorithms.
* @param[in] s Pointer to device.
* @param[in] frequency The requested frequency.
* @return 0 on success, negative value on error.
* @warning Accel frequency must be higher or equal to DMP frequency.
*/
int inv_imu_apex_set_frequency(struct inv_imu_device *s, const APEX_CONFIG1_DMP_ODR_t frequency);
/** @brief Enable APEX algorithm Pedometer.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_enable_pedometer(struct inv_imu_device *s);
/** @brief Disable APEX algorithm Pedometer.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_disable_pedometer(struct inv_imu_device *s);
/** @brief Enable APEX algorithm Tilt.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_enable_tilt(struct inv_imu_device *s);
/** @brief Disable APEX algorithm Tilt.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_disable_tilt(struct inv_imu_device *s);
/** @brief Retrieve APEX pedometer outputs and format them
* @param[in] s Pointer to device.
* @param[out] apex_activity Apex step and activity data value.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_get_data_activity(struct inv_imu_device * s,
inv_imu_apex_step_activity_t *apex_activity);
/** @brief Retrieve APEX free fall outputs and format them
* @param[in] s Pointer to device.
* @param[out] freefall_duration Free fall duration in number of sample.
* @return 0 on success, negative value on error.
*/
int inv_imu_apex_get_data_free_fall(struct inv_imu_device *s, uint16_t *freefall_duration);
#ifdef __cplusplus
}
#endif
#endif /* _INV_IMU_APEX_H_ */
/** @} */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,444 @@
/*
* ________________________________________________________________________________________________________
* Copyright (c) 2017 InvenSense Inc. All rights reserved.
*
* This software, related documentation and any modifications thereto (collectively "Software") is subject
* to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
* and other intellectual property rights laws.
*
* InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
* and any use, reproduction, disclosure or distribution of the Software without an express license agreement
* from InvenSense is strictly prohibited.
*
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
* PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
* INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THE SOFTWARE.
* ________________________________________________________________________________________________________
*/
/** @defgroup Driver Driver
* @brief High-level functions to drive the device
* @{
*/
/** @file inv_imu_driver.h */
#ifndef _INV_IMU_DRIVER_H_
#define _INV_IMU_DRIVER_H_
#include "inv_imu_defs.h"
#include "inv_imu_transport.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Max FSR values for accel */
#define ACCEL_CONFIG0_FS_SEL_MAX ACCEL_CONFIG0_FS_SEL_16g
/** Max FSR values for gyro */
#define GYRO_CONFIG0_FS_SEL_MAX GYRO_CONFIG0_FS_SEL_2000dps
/** Max user offset value for accel (mg) */
#define ACCEL_OFFUSER_MAX_MG 1000
/** Max user offset value for gyro (dps) */
#define GYRO_OFFUSER_MAX_DPS 64
/** Max buffer size mirrored from FIFO at polling time */
#define FIFO_MIRRORING_SIZE 16 * 258 // packet size * max_count = 4kB
/** Accel start-up time */
#define ACC_STARTUP_TIME_US 10000
/** Gyro start-up time */
#define GYR_STARTUP_TIME_US 70000
/** Sensor identifier for UI control function */
enum inv_imu_sensor {
INV_SENSOR_ACCEL, /**< Accelerometer */
INV_SENSOR_GYRO, /**< Gyroscope */
INV_SENSOR_FSYNC_EVENT, /**< FSYNC */
INV_SENSOR_TEMPERATURE, /**< Chip temperature */
INV_SENSOR_DMP_PEDOMETER_EVENT, /**< Pedometer: step detected */
INV_SENSOR_DMP_PEDOMETER_COUNT, /**< Pedometer: step counter */
INV_SENSOR_DMP_TILT, /**< Tilt */
INV_SENSOR_DMP_FF, /**< FreeFall */
INV_SENSOR_DMP_LOWG, /**< Low G */
INV_SENSOR_DMP_SMD, /**< Significant Motion Detection */
INV_SENSOR_MAX
};
/** Configure Fifo usage */
typedef enum {
INV_IMU_FIFO_DISABLED = 0, /**< Fifo is disabled and data source is sensors registers */
INV_IMU_FIFO_ENABLED = 1, /**< Fifo is used as data source */
} INV_IMU_FIFO_CONFIG_t;
/** Sensor event structure definition */
typedef struct {
xmedia_s32 sensor_mask;
xmedia_u16 timestamp_fsync;
xmedia_s16 accel[3];
xmedia_s16 gyro[3];
xmedia_s16 temperature;
xmedia_s8 accel_high_res[3];
xmedia_s8 gyro_high_res[3];
} inv_imu_sensor_event_t;
/** IMU driver states definition */
struct inv_imu_device {
/** Transport layer.
* @warning Must be the first one of struct inv_imu_device
*/
struct inv_imu_transport transport;
/** callback executed by:
* * inv_imu_get_data_from_fifo (if FIFO is used).
* * inv_imu_get_data_from_registers (if FIFO isn't used).
* May be NULL if above API are not used by application
*/
void (*sensor_event_cb)(xmedia_s32 dev, xmedia_u16 packet_count, xmedia_u16 idx, xmedia_u64 time_inter,
inv_imu_sensor_event_t *event);
xmedia_u8 fifo_data[FIFO_MIRRORING_SIZE]; /**< FIFO mirroring memory area */
xmedia_u8 dmp_is_on; /**< DMP started status */
xmedia_u8 endianness_data; /**< Data endianness configuration */
xmedia_u8 fifo_highres_enabled; /**< Highres mode configuration */
INV_IMU_FIFO_CONFIG_t fifo_is_used; /**< FIFO configuration */
xmedia_u64 gyro_start_time_us; /**< Gyro start time used to discard first samples */
xmedia_u64 accel_start_time_us; /**< Accel start time used to discard first samples */
};
/** Interrupt enum state for INT1, INT2, and IBI */
typedef enum {
INV_IMU_DISABLE = 0,
INV_IMU_ENABLE
} inv_imu_interrupt_value;
/** Interrupt definition */
typedef struct {
inv_imu_interrupt_value INV_UI_FSYNC;
inv_imu_interrupt_value INV_UI_DRDY;
inv_imu_interrupt_value INV_FIFO_THS;
inv_imu_interrupt_value INV_FIFO_FULL;
inv_imu_interrupt_value INV_SMD;
inv_imu_interrupt_value INV_WOM_X;
inv_imu_interrupt_value INV_WOM_Y;
inv_imu_interrupt_value INV_WOM_Z;
inv_imu_interrupt_value INV_FF;
inv_imu_interrupt_value INV_LOWG;
inv_imu_interrupt_value INV_STEP_DET;
inv_imu_interrupt_value INV_STEP_CNT_OVFL;
inv_imu_interrupt_value INV_TILT_DET;
} inv_imu_interrupt_parameter_t;
/** @brief Initializes device.
* @param[in] s Pointer to device.
* @param[in] serif Pointer on serial interface structure.
* @param[in] sensor_event_cb Callback executed when a new sensor event is available. *
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_init(xmedia_s32 dev, struct inv_imu_device *s, struct inv_imu_serif *serif,
void (*sensor_event_cb)(xmedia_s32 dev, xmedia_u16 packet_count, xmedia_u16 idx, xmedia_u64 time_inter,
inv_imu_sensor_event_t *event));
/** @brief Reset device by reloading OTPs.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_device_reset(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief return WHOAMI value.
* @param[in] s Pointer to device.
* @param[out] who_am_i WHOAMI for device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_who_am_i(xmedia_s32 dev, struct inv_imu_device *s, xmedia_u8 *who_am_i);
/** @brief Enable/put accel in low power mode.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_enable_accel_low_power_mode(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Enable/put accel in low noise mode.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_enable_accel_low_noise_mode(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Disable all 3 axes of accel.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_disable_accel(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Enable/put gyro in low noise mode.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_enable_gyro_low_noise_mode(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Disable all 3 axes of gyro.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_disable_gyro(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Enable fsync tagging functionality.
* * Enables fsync.
* * Enables timestamp to registers. Once fsync is enabled fsync counter is pushed to
* fifo instead of timestamp. So timestamp is made available in registers. Note that
* this increase power consumption.
* * Enables fsync related interrupt.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_enable_fsync(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Disable fsync tagging functionality.
* * Disables fsync.
* * Disables timestamp to registers. Once fsync is disabled timestamp is pushed to fifo
* instead of fsync counter. So in order to decrease power consumption, timestamp is no
* more available in registers.
* * Disables fsync related interrupt.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_disable_fsync(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Configure which interrupt source can trigger INT1.
* @param[in] s Pointer to device.
* @param[in] interrupt_to_configure Structure with the corresponding state to manage INT1.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_config_int1(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
/** @brief Retrieve interrupts configuration.
* @param[in] s Pointer to device.
* @param[in] interrupt_to_configure Structure with the corresponding state to manage INT1.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_config_int1(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
/** @brief Configure which interrupt source can trigger INT2.
* @param[in] s Pointer to device.
* @param[in] interrupt_to_configure Structure with the corresponding state to INT2.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_config_int2(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
/** @brief Retrieve interrupts configuration.
* @param[in] s Pointer to device.
* @param[in] interrupt_to_configure Structure with the corresponding state to manage INT2.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_config_int2(xmedia_s32 dev, struct inv_imu_device *s, inv_imu_interrupt_parameter_t *interrupt_to_configure);
/** @brief Read all registers containing data (temperature, accelerometer and gyroscope).
* Then it calls sensor_event_cb function passed at init for each packet.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_data_from_registers(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Read all available packets from the FIFO.
* For each packet function builds a sensor event containing packet data
* and validity information. Then it calls sensor_event_cb funtion passed
* at init for each packet.
* @param[in] s Pointer to device.
* @return Number of valid packets read on success, negative value on error.
*/
xmedia_s32 inv_imu_get_data_from_fifo(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Converts ACCEL_CONFIG0_ODR_t or GYRO_CONFIG0_ODR_t enums to period expressed in us.
* @param[in] odr_bitfield An ACCEL_CONFIG0_ODR_t or GYRO_CONFIG0_ODR_t enum.
* @return The corresponding period expressed in us.
*/
xmedia_u32 inv_imu_convert_odr_bitfield_to_us(xmedia_s32 dev, xmedia_u32 odr_bitfield);
/** @brief Configure accel Output Data Rate.
* @param[in] s Pointer to device.
* @param[in] frequency The requested frequency.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_accel_frequency(xmedia_s32 dev, struct inv_imu_device *s, const ACCEL_CONFIG0_ODR_t frequency);
/** @brief Configure gyro Output Data Rate.
* @param[in] s Pointer to device.
* @param[in] frequency The requested frequency.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_gyro_frequency(xmedia_s32 dev, struct inv_imu_device *s, const GYRO_CONFIG0_ODR_t frequency);
/** @brief Set accel full scale range.
* @param[in] s Pointer to device.
* @param[in] accel_fsr_g Requested full scale range.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_accel_fsr(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG0_FS_SEL_t accel_fsr_g);
/** @brief Access accel full scale range.
* @param[in] s Pointer to device.
* @param[out] accel_fsr_g Current full scale range.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_accel_fsr(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG0_FS_SEL_t *accel_fsr_g);
/** @brief Set gyro full scale range.
* @param[in] s Pointer to device.
* @param[in] gyro_fsr_dps Requested full scale range.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_gyro_fsr(xmedia_s32 dev, struct inv_imu_device *s, GYRO_CONFIG0_FS_SEL_t gyro_fsr_dps);
/** @brief Access gyro full scale range.
* @param[in] s Pointer to device.
* @param[out] gyro_fsr_dps Current full scale range.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_gyro_fsr(xmedia_s32 dev, struct inv_imu_device *s, GYRO_CONFIG0_FS_SEL_t *gyro_fsr_dps);
/** @brief Set accel Low-Power averaging value.
* @param[in] s Pointer to device.
* @param[in] acc_avg Requested averaging value.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_accel_lp_avg(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG1_ACCEL_FILT_AVG_t acc_avg);
/** @brief Set accel Low-Noise bandwidth value.
* @param[in] s Pointer to device.
* @param[in] acc_bw Requested averaging value.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_accel_ln_bw(xmedia_s32 dev, struct inv_imu_device *s, ACCEL_CONFIG1_ACCEL_FILT_BW_t acc_bw);
/** @brief Set gyro Low-Noise bandwidth value.
* @param[in] s Pointer to device.
* @param[in] gyr_bw Requested averaging value.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_gyro_ln_bw(xmedia_s32 dev, struct inv_imu_device *s, GYRO_CONFIG1_GYRO_FILT_BW_t gyr_bw);
/** @brief Set timestamp resolution.
* @param[in] s Pointer to device.
* @param[in] timestamp_resol Requested timestamp resolution.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_timestamp_resolution(xmedia_s32 dev, struct inv_imu_device *s, const TMST_CONFIG1_RESOL_t timestamp_resol);
/** @brief Reset IMU fifo.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_reset_fifo(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Enable 20 bits raw acc and raw gyr data in fifo.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_enable_high_resolution_fifo(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Disable 20 bits raw acc and raw gyr data in fifo.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_disable_high_resolution_fifo(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Configure Fifo.
* @param[in] s Pointer to device.
* @param[in] fifo_config Fifo configuration method.
* Enabled: data are pushed to FIFO and FIFO THS interrupt is set.
* Disabled: data are not pused to FIFO and DRDY interrupt is set.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_configure_fifo(xmedia_s32 dev, struct inv_imu_device *s, INV_IMU_FIFO_CONFIG_t fifo_config);
/** @brief Get timestamp resolution
* @param[in] s Pointer to device.
* @return The timestamp resolution in us or 0 in case of error
*/
xmedia_u32 inv_imu_get_timestamp_resolution_us(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Enable Wake On Motion.
* @param[in] s Pointer to device.
* @param[in] wom_x_th Threshold value for the Wake on Motion Interrupt for X-axis accel.
* @param[in] wom_y_th Threshold value for the Wake on Motion Interrupt for Y-axis accel.
* @param[in] wom_z_th Threshold value for the Wake on Motion Interrupt for Z-axis accel.
* @param[in] wom_int Select which mode between AND/OR is used to generate interrupt.
* @param[in] wom_dur Select the number of overthreshold event to wait
* before generating interrupt.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_configure_wom(xmedia_s32 dev, struct inv_imu_device *s, const xmedia_u8 wom_x_th, const xmedia_u8 wom_y_th,
const xmedia_u8 wom_z_th, WOM_CONFIG_WOM_INT_MODE_t wom_int,
WOM_CONFIG_WOM_INT_DUR_t wom_dur);
/** @brief Enable Wake On Motion.
* WoM requests to have the accelerometer enabled to work.
* As a consequence Fifo water-mark interrupt is disabled to only trigger WoM interrupts.
* To have good performance, it's recommended to set accel ODR to 20ms
* and in Low Power Mode.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_enable_wom(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Disable Wake On Motion.
* Fifo water-mark interrupt is re-enabled when WoM is disabled.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_disable_wom(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Start DMP for APEX algorithms and selftest.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_start_dmp(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Reset DMP for APEX algorithms and selftest.
* @param[in] s Pointer to device.
* @param[in] sram_reset Reset mode for the SRAM.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_reset_dmp(xmedia_s32 dev, struct inv_imu_device *s, const APEX_CONFIG0_DMP_MEM_RESET_t sram_reset);
/** @brief Set the UI endianness and set the inv_device endianness field.
* @param[in] s Pointer to device.
* @param[in] endianness Endianness to be set.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_set_endianness(xmedia_s32 dev, struct inv_imu_device *s, INTF_CONFIG0_DATA_ENDIAN_t endianness);
/** @brief Read the UI endianness and set the inv_device endianness field.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_get_endianness(xmedia_s32 dev, struct inv_imu_device *s);
/** @brief Configure Fifo decimation.
* @param[in] s Pointer to device.
* @param[in] dec_factor Requested decimation factor value from 2 to 256.
* @return 0 on success, negative value on error.
*/
xmedia_s32 inv_imu_configure_fifo_data_rate(xmedia_s32 dev, struct inv_imu_device *s, FDR_CONFIG_FDR_SEL_t dec_factor);
/** @brief Return driver version x.y.z-suffix as a xmedia_char array
* @return driver version a xmedia_char array "x.y.z-suffix"
*/
const xmedia_char *inv_imu_get_version(void);
#ifdef __cplusplus
}
#endif
#endif /* _INV_IMU_DRIVER_H_ */
/** @} */
@@ -0,0 +1,119 @@
/*
* ________________________________________________________________________________________________________
* Copyright (c) 2015-2015 InvenSense Inc. All rights reserved.
*
* This software, related documentation and any modifications thereto (collectively "Software") is subject
* to InvenSense and its licensors' intellectual property rights under U.S. and international copyright
* and other intellectual property rights laws.
*
* InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
* and any use, reproduction, disclosure or distribution of the Software without an express license agreement
* from InvenSense is strictly prohibited.
*
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, THE SOFTWARE IS
* PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* EXCEPT AS OTHERWISE PROVIDED IN A LICENSE AGREEMENT BETWEEN THE PARTIES, IN NO EVENT SHALL
* INVENSENSE BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THE SOFTWARE.
* ________________________________________________________________________________________________________
*/
/** @defgroup Transport Transport
* @brief Abstraction layer to access device's registers
* @{
*/
/** @file inv_imu_transport.h */
#ifndef _INV_IMU_TRANSPORT_H_
#define _INV_IMU_TRANSPORT_H_
#ifdef __cplusplus
extern "C" {
#endif
/* forward declaration */
struct inv_imu_device;
/** Available serial interface type. */
typedef enum {
UI_I2C, /**< Selects I2C interface. */
UI_SPI4, /**< Selects 4-wire SPI interface. */
UI_SPI3 /**< Selects 3-wire SPI interface. */
} SERIAL_IF_TYPE_t;
/** Serial interface definition */
struct inv_imu_serif {
void *context;
int (*read_reg)(xmedia_s32 dev, struct inv_imu_serif *serif, uint8_t reg, uint8_t *buf, uint32_t len);
int (*write_reg)(xmedia_s32 dev, struct inv_imu_serif *serif, uint8_t reg, const uint8_t *buf, uint32_t len);
uint32_t max_read;
uint32_t max_write;
SERIAL_IF_TYPE_t serif_type;
};
/** Transport interface definition. */
struct inv_imu_transport {
/** Serial interface object.
* @warning Must be the first object in this structure.
*/
struct inv_imu_serif serif;
/** Contains mirrored values of some IP registers. */
struct register_cache {
uint8_t pwr_mgmt0_reg;
uint8_t gyro_config0_reg;
uint8_t accel_config0_reg;
uint8_t tmst_config1_reg;
} register_cache;
/** Internal counter for MCLK requests. */
uint8_t need_mclk_cnt;
};
/** @brief Init cache variable.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_init_transport(int32_t dev, struct inv_imu_device *s);
/** @brief Reads data from a register on IMU.
* @param[in] s Pointer to device.
* @param[in] reg Register address to be read.
* @param[in] len Number of byte to be read.
* @param[out] buf Output data from the register.
* @return 0 on success, negative value on error.
*/
int inv_imu_read_reg(int32_t dev, struct inv_imu_device *s, uint32_t reg, uint32_t len, uint8_t *buf);
/** @brief Writes data to a register on IMU.
* @param[in] s Pointer to device.
* @param[in] reg Register address to be written.
* @param[in] len Number of byte to be written.
* @param[in] buf Input data to write.
* @return 0 on success, negative value on error.
*/
int inv_imu_write_reg(int32_t dev, struct inv_imu_device *s, uint32_t reg, uint32_t len, const uint8_t *buf);
/** @brief Enable MCLK.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_switch_on_mclk(int32_t dev, struct inv_imu_device *s);
/** @brief Disable MCLK.
* @param[in] s Pointer to device.
* @return 0 on success, negative value on error.
*/
int inv_imu_switch_off_mclk(int32_t dev, struct inv_imu_device *s);
#ifdef __cplusplus
}
#endif
#endif /* _INV_IMU_TRANSPORT_H_ */
/** @} */
@@ -0,0 +1,40 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor_gpio.h"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "icm42670.h"
xmedia_s32 gpio_init(xmedia_void)
{
xmedia_s32 ret;
ret = gpio_request(gpio_num(INT_GPIO_CHIP, INT_GPIO_OFFSET), "icm42670_irq");
if (ret != XMEDIA_SUCCESS) {
print_info("irq GPIO request failed: %d", ret);
return ret;
}
gpio_direction_input(gpio_num(INT_GPIO_CHIP, INT_GPIO_OFFSET));
return XMEDIA_SUCCESS;
}
xmedia_s32 gpio_deinit(xmedia_void)
{
gpio_free(gpio_num(INT_GPIO_CHIP, INT_GPIO_OFFSET));
return XMEDIA_SUCCESS;
}
@@ -0,0 +1,30 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_GPIO_H__
#define __MSENSOR_GPIO_H__
#include "xmedia_type.h"
#include <linux/gpio.h>
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#define gpio_num(gpio_chip_num, gpio_offset_num) ((gpio_chip_num) * 8 + (gpio_offset_num))
xmedia_s32 gpio_init(xmedia_void);
xmedia_s32 gpio_deinit(xmedia_void);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,88 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
/* include <liteos/i2c.h> */
#include "i2c_dev.h"
#include "linux/i2c.h"
#include "msensor.h"
struct i2c_client g_i2c_client_obj; /* i2c control struct */
#define SLAVE_ADDR 0x34 /* i2c dev addr */
#define SLAVE_REG_ADDR 0x300f /* i2c dev register */
/* client initial */
static xmedia_s32 i2c_client_init(struct i2c_client **xmedia_i2c_client)
{
xmedia_s32 ret;
/* struct i2c_client * i2c_client0 is &g_i2c_client_obj */
/* i2c_client0->addr is SLAVE_ADDR >> 1 */
xmedia_i2c_client->addr = ICM40690_DEV_ADDR;
ret = client_attach(*xmedia_i2c_client, 0);
if (ret != XMEDIA_SUCCESS) {
dprintf("fail to attach client!\n");
return -1;
}
return 0;
}
static xmedia_s32 sample_i2c_write(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, const xmedia_u8 *reg_data,
xmedia_u32 cnt)
{
xmedia_s32 ret;
/* struct i2c_client * i2c_client0 is & g_i2c_client_obj */
xmedia_char buf[4] = { 0 }; /* 4 buf */
/* i2c_client_init */
buf[0] = reg_addr & 0xff;
osal_memcpy(&buf[1], reg_data, cnt);
/* buf[1] is (SLAVE_REG_ADDR >> 8) & 0xff */
/* buf[2] is 0x03 write value to i2c */
/* call I2C standard function drv to write */
ret = i2c_master_send(xmedia_i2c_client, &buf, cnt + 1);
return ret;
}
static xmedia_s32 sample_i2c_read(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, xmedia_u8 *reg_data,
xmedia_u32 cnt)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
/* struct i2c_client *i2c_client0 is & g_i2c_client_obj */
struct i2c_rdwr_data rdwr;
struct i2c_msg msg[2]; /* 2 msg */
xmedia_u8 recvbuf[4]; /* 4 bytes */
(xmedia_void) osal_memset(recvbuf, 0x0, sizeof(recvbuf));
/* i2c_client_init */
msg[0].addr = xmedia_i2c_client->addr;
msg[0].flags = xmedia_i2c_client->flags & I2C_M_TEN;
msg[0].len = 1;
msg[0].buf = reg_addr;
msg[1].addr = xmedia_i2c_client->addr;
msg[1].flags = xmedia_i2c_client->flags & I2C_M_TEN;
msg[1].flags |= I2C_M_RD;
msg[1].len = cnt;
msg[1].buf = reg_data;
/* rdwr.msgs = &msg[0] */
rdwr.nmsgs = 2; /* 2 msg */
recvbuf[0] = SLAVE_REG_ADDR & 0xff;
recvbuf[1] = (SLAVE_REG_ADDR >> 8) & 0xff; /* 8 bits */
i2c_transfer(xmedia_i2c_client->adapter, msg, rdwr.nmsgs);
/* dprintf("val is 0x%x\n",recvbuf[0]) buf[0] save the value read from i2c dev */
return ret;
}
xmedia_u8 msensor_i2c_write(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, const xmedia_u8 *reg_data,
xmedia_u32 cnt)
{
return sample_i2c_write(xmedia_i2c_client, reg_addr, reg_data, cnt);
}
xmedia_u8 msensor_i2c_read(struct i2c_client *xmedia_i2c_client, xmedia_u8 reg_addr, xmedia_u8 *reg_data,
xmedia_u32 cnt)
{
return sample_i2c_read(xmedia_i2c_client, reg_addr, reg_data, cnt);
}
@@ -0,0 +1,34 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __I2C_DEV_H__
#define __I2C_DEV_H__
#include <linux/i2c.h>
#include "xmedia_type.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
xmedia_u8 msensor_i2c_write(struct i2c_client *xmedia_i2c_client,
xmedia_u8 reg_addr, const xmedia_u8 *reg_data,xmedia_u32 cnt);
xmedia_u8 msensor_i2c_read(struct i2c_client *xmedia_i2c_client,
xmedia_u8 reg_addr, xmedia_u8 *reg_data, xmedia_u32 cnt);
xmedia_u32 msensor_i2c_get_frequency(struct i2c_client *xmedia_i2c_client, xmedia_s32 *frequency);
xmedia_u32 msensor_i2c_init(struct i2c_client **xmedia_i2c_client,
struct i2c_board_info xmedia_i2c_board_info, xmedia_s32 adapt_num);
xmedia_void msensor_i2c_exit(struct i2c_client **xmedia_i2c_client);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,195 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "spi_dev.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/spinlock.h>
#include "common.h"
#include "msensor.h"
#define REG_WIDTH 1
static xmedia_u32 g_csn = 0;
static spinlock_t g_lock_rd;
static xmedia_u32 g_bus_num = 1;
module_param(g_bus_num, uint, S_IRUGO);
MODULE_PARM_DESC(g_bus_num, "spi bus number");
module_param(g_csn, uint, S_IRUGO);
MODULE_PARM_DESC(g_csn, "chip select number");
struct spi_master *g_xmedia_master;
static xmedia_s32 ssp_func_write(struct spi_device *xmedia_spi, xmedia_u8 addr, const xmedia_u8 *data, xmedia_u32 cnt)
{
struct spi_master *master = g_xmedia_master;
static struct spi_transfer t;
static struct spi_message msg;
static xmedia_u8 buf[4] = { 0 }; /* 4 byte buf */
xmedia_s16 ret;
xmedia_ulong flags;
if (xmedia_spi == XMEDIA_NULL) {
return -ENODEV;
}
xmedia_unused(cnt);
/* check spi_message is or no finish */
spin_lock_irqsave(&master->queue_lock, flags);
if (msg.state != XMEDIA_NULL) {
MSENSOR_ERR_TRACE("msg.state not null!!\n");
return -EFAULT;
}
spin_unlock_irqrestore(&master->queue_lock, flags);
buf[0] = addr;
buf[0] &= (~0x80);
buf[1] = *data;
t.tx_buf = buf;
t.len = 2; /* length 2 */
spi_message_init(&msg);
spi_message_add_tail(&t, &msg);
msg.state = &msg;
ret = spi_sync(xmedia_spi, &msg);
if (ret != 0) {
MSENSOR_ERR_TRACE(" spi_async() error(%d)!\n", ret);
return -EAGAIN;
}
return ret;
}
static xmedia_s32 ssp_func_read(struct spi_device *xmedia_spi, xmedia_u8 addr, xmedia_u8 *data, xmedia_u32 cnt)
{
struct spi_master *master = g_xmedia_master;
static struct spi_transfer t;
static struct spi_message msg;
static xmedia_u8 buf[4] = { 0 }; /* 4 byte buf */
xmedia_s16 ret;
xmedia_ulong flags;
static xmedia_u8 body[1024] = { 0 }; /* 1024 byte buf */
if (xmedia_spi == XMEDIA_NULL) {
return -ENODEV;
}
/* check spi_message is or no finish */
spin_lock_irqsave(&master->queue_lock, flags);
if (msg.state != XMEDIA_NULL) {
MSENSOR_ERR_TRACE("msg.state not null!!(%x)\n", addr);
spin_unlock_irqrestore(&master->queue_lock, flags);
return -EFAULT;
}
spin_unlock_irqrestore(&master->queue_lock, flags);
buf[0] = addr;
buf[0] |= 0x80;
buf[1] = 0;
t.tx_buf = buf;
t.rx_buf = body;
t.len = cnt + 1;
spi_message_init(&msg);
spi_message_add_tail(&t, &msg);
msg.state = &msg;
ret = spi_sync(xmedia_spi, &msg);
if (ret != 0) {
MSENSOR_ERR_TRACE(" spi_async() error(%d)!\n", ret);
return -EAGAIN;
}
osal_memcpy(data, body + 1, cnt);
return ret;
}
xmedia_s32 msensor_spi_write(struct spi_device *xmedia_spi, xmedia_u8 addr, const xmedia_u8 *data, xmedia_u32 cnt)
{
return ssp_func_write(xmedia_spi, addr, data, cnt);
}
xmedia_s32 msensor_spi_read(struct spi_device *xmedia_spi, xmedia_u8 addr, xmedia_u8 *data, xmedia_u32 cnt)
{
xmedia_s16 ret;
ret = ssp_func_read(xmedia_spi, addr, data, cnt);
return ret;
}
xmedia_s32 msensor_spi_init(struct spi_device **xmedia_spi)
{
xmedia_s32 status = XMEDIA_SUCCESS;
struct device *d = XMEDIA_NULL;
xmedia_char *spi_name = XMEDIA_NULL;
xmedia_s32 spi_name_len;
g_xmedia_master = spi_busnum_to_master(g_bus_num);
if (g_xmedia_master == XMEDIA_NULL) {
status = -ENXIO;
goto err0;
}
spi_name_len = strlen(dev_name(&g_xmedia_master->dev)) + 10; /* extend 10 */
spi_name = osal_kmalloc(spi_name_len, osal_gfp_kernel);
if (spi_name == XMEDIA_NULL) {
status = -ENOMEM;
goto err0;
}
(xmedia_void) osal_memset(spi_name, 0, spi_name_len);
if (osal_sprintf(spi_name, "%s.%u", dev_name(&g_xmedia_master->dev), g_csn) == XMEDIA_FAILURE) {
status = XMEDIA_FAILURE;
goto err1;
}
d = bus_find_device_by_name(&spi_bus_type, XMEDIA_NULL, spi_name);
if (d == XMEDIA_NULL) {
status = -ENXIO;
goto err1;
}
*xmedia_spi = to_spi_device(d);
if (*xmedia_spi == XMEDIA_NULL) {
status = -ENXIO;
goto err2;
}
spin_lock_init(&g_lock_rd);
err2:
put_device(d);
err1:
if (spi_name != XMEDIA_NULL) {
osal_kfree(spi_name);
spi_name = XMEDIA_NULL;
}
err0:
return status;
}
xmedia_s32 msensor_spi_deinit(const struct spi_device *spi_device)
{
xmedia_unused(spi_device);
return XMEDIA_SUCCESS;
}
@@ -0,0 +1,37 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __SPI_DEV_H__
#define __SPI_DEV_H__
#include "xmedia_type.h"
#include "osal.h"
#include "xmedia_debug.h"
#include <linux/spi/spi.h>
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
xmedia_s32 msensor_spi_write(struct spi_device *xmedia_spi, xmedia_u8 addr, const xmedia_u8 *data, xmedia_u32 cnt);
xmedia_s32 msensor_spi_read(struct spi_device *xmedia_spi, xmedia_u8 addr, xmedia_u8 *data, xmedia_u32 cnt);
xmedia_s32 msensor_spi_init(struct spi_device **xmedia_spi);
xmedia_s32 msensor_spi_deinit(const struct spi_device *spi_device);
#ifndef MSENSOR_ERR_TRACE
#define MSENSOR_ERR_TRACE(fmt, ...) \
printk(KERN_ERR "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, \
##__VA_ARGS__)
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,29 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
MOD_NAME := xm_msensor_mng
SRCS = ./src/msensor_exe.c
SRCS += ./src/msensor_buf.c
SRCS += ./src/msensor_mng_proc.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/usr/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/osal/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/msensor_mng/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/ext/msensor/ext_inc
#SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/msensor/msensor_chip/main/
SDK_KER_CFLAGS += -DCONFIG_PROC_SHOW_SUPPORT
include $(SDK_DIR)/build/sdk_ko_rules.mk
@@ -0,0 +1,76 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_BUF_H__
#define __MSENSOR_BUF_H__
#include "msensor_ext.h"
#include "osal.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#define BUF_BLOCK_NUM 6
#define MAX_USER_NUM 10
/*
* min msensor gap between reader pointer and write pointer,
* to prevent new data overlap with reading/processing data
*/
#define WR_GAP 100
typedef struct {
xmedia_void *start_addr; /* start address */
xmedia_void *write_ptr; /* write pointer */
} msensor_buf_info;
typedef enum {
DATA_X,
DATA_Y,
DATA_Z,
DATA_TEMP,
DATA_PTS,
DATA_BUTT
} msensor_buf_data_type;
typedef struct {
xmedia_void *read_ptr[XMEDIA_MSENSOR_DATA_TYPE_MAX][DATA_BUTT];
xmedia_s32 reverd3[4]; /* array 4 */
} msensor_buf_user_context;
typedef struct {
xmedia_u32 user_cnt;
osal_spinlock_t mng_lock;
osal_spinlock_t read_lock[MAX_USER_NUM];
msensor_buf_user_context *user_ctx[MAX_USER_NUM];
osal_mutex_t mng_mutex;
} msensor_buf_user_mng;
msensor_buf_info **msensor_buf_get_info(xmedia_s32 dev);
osal_spinlock_t *msensor_buf_get_lock(xmedia_s32 dev);
xmedia_s32 msensor_buf_lock_init(xmedia_void);
xmedia_void msensor_buf_lock_exit(xmedia_void);
xmedia_s32 msensor_buf_init(xmedia_s32 dev, const xmedia_msensor_buf_attr *buf_attr,
xmedia_u32 gyro_freq, xmedia_u32 accel_freq, xmedia_u32 mag_freq);
xmedia_s32 msensor_buf_exit(xmedia_s32 dev);
xmedia_s32 msensor_buf_write_data(xmedia_s32 dev, xmedia_msensor_data_type data_type,
const xmedia_msensor_sample_data *sample_data);
xmedia_s32 msensor_buf_get_data(xmedia_s32 dev, xmedia_msensor_data_info *msensor_data);
xmedia_s32 msensor_buf_release_data(xmedia_s32 dev, xmedia_msensor_data_info *msensor_data_info);
xmedia_s32 msensor_buf_add_user(xmedia_s32 dev, xmedia_s32 *id);
xmedia_s32 msensor_buf_delete_user(xmedia_s32 dev, const xmedia_s32 *id);
xmedia_bool msensor_buf_get_status(xmedia_s32 dev);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,80 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_EXE_H__
#define __MSENSOR_EXE_H__
#include "xmedia_debug.h"
#include "xmedia_type.h"
#include "xmedia_msensor.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
/* name MAG INTERFACE */
#define C_BMI160_BYTE_COUNT 2
#define BMI160_SLEEP_STATE 0x00
#define BMI160_WAKEUP_INTR 0x00
#define BMI160_SLEEP_TRIGGER 0x04
#define BMI160_WAKEUP_TRIGGER 0x02
#define BMI160_ENABLE_FIFO_WM 0x02
#define BMI160_MAG_INTERFACE_OFF_PRIMARY_ON 0x00
#define BMI160_MAG_INTERFACE_ON_PRIMARY_ON 0x02
#define BMI160_MODE_SWITCHING_DELAY 30
#define msensor_return_if_null_ptr(ptr) \
do { \
if ((ptr) == XMEDIA_NULL) { \
printk("input null ptr\n"); \
return XMEDIA_FAILURE; \
} \
} while (0)
typedef struct {
xmedia_u32 cmd;
xmedia_s32 (*func)(xmedia_uintptr_t arg);
} msensor_mng_info;
/* for msensor_mng proc */
#define MNG_MAX_LEN 10
typedef struct {
xmedia_char gyro_name[MNG_MAX_LEN];
xmedia_char accel_name[MNG_MAX_LEN];
xmedia_char mag_name[MNG_MAX_LEN];
xmedia_u64 buf_addr[XMEDIA_MSENSOR_DATA_TYPE_MAX];
xmedia_u32 buf_size[XMEDIA_MSENSOR_DATA_TYPE_MAX];
xmedia_u32 buf_overflow[XMEDIA_MSENSOR_DATA_TYPE_MAX];
xmedia_u32 buf_data_unmatch[XMEDIA_MSENSOR_DATA_TYPE_MAX];
xmedia_s32 buf_overflow_id[XMEDIA_MSENSOR_DATA_TYPE_MAX];
xmedia_s32 buf_data_unmatch_id[XMEDIA_MSENSOR_DATA_TYPE_MAX];
} msensor_mng_proc_info;
msensor_mng_proc_info *msensor_mng_get_proc_info(xmedia_s32 dev);
xmedia_s32 msensor_mng_proc_info_init(xmedia_s32 dev);
xmedia_s32 msensor_mng_buf_init(xmedia_s32 dev,
const xmedia_msensor_attr *motion_attr,
const xmedia_msensor_buf_attr *msensor_buf_attr,
const xmedia_msensor_config *msensor_config);
xmedia_s32 msensor_mng_buf_exit(xmedia_s32 dev);
xmedia_s32 msensor_mng_write_data_to_buf(xmedia_s32 dev, xmedia_msensor_data *msensor_data);
xmedia_s32 msensor_mng_write_data_2_buf(xmedia_s32 dev);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,42 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_MNG_IOCTL_H__
#define __MSENSOR_MNG_IOCTL_H__
#include "xmedia_msensor.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* end of #ifdef __cplusplus */
#define MSENSOR_TYPE_MNG 10
typedef enum {
IOC_NR_MSENSOR_MNG_FLAG2FD,
IOC_NR_MSENSOR_MNG_GET_DATA,
IOC_NR_MSENSOR_MNG_RELEASE_BUF,
IOC_NR_MSENSOR_MNG_ADD_USER,
IOC_NR_MSENSOR_MNG_DELETE_USER,
IOC_NR_MSENSOR_MNG_SEND_DATA,
IOC_NR_MSENSOR_MNG_BUTT
} ioc_nr_msensor_mng;
#define MSENSOR_CMD_MNG_BIND_FLAG2FD _IOW(MSENSOR_TYPE_MNG, IOC_NR_MSENSOR_MNG_FLAG2FD, xmedia_u32)
#define MSENSOR_CMD_GET_DATA _IOWR(MSENSOR_TYPE_MNG, IOC_NR_MSENSOR_MNG_GET_DATA, xmedia_msensor_data_info)
#define MSENSOR_CMD_RELEASE_BUF _IOWR(MSENSOR_TYPE_MNG, IOC_NR_MSENSOR_MNG_RELEASE_BUF, xmedia_msensor_data_info)
#define MSENSOR_CMD_ADD_USER _IOWR(MSENSOR_TYPE_MNG, IOC_NR_MSENSOR_MNG_ADD_USER, xmedia_s32)
#define MSENSOR_CMD_DELETE_USER _IOWR(MSENSOR_TYPE_MNG, IOC_NR_MSENSOR_MNG_DELETE_USER, xmedia_s32)
#define MSENSOR_CMD_SEND_DATA _IOW(MSENSOR_TYPE_MNG, IOC_NR_MSENSOR_MNG_SEND_DATA, xmedia_msensor_data)
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,26 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_MNG_PROC__
#define __MSENSOR_MNG_PROC__
#include "msensor_ext.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
int msensor_proc_init(xmedia_void);
void msensor_proc_exit(xmedia_void);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
@@ -0,0 +1,832 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor_buf.h"
#include <linux/kernel.h>
#include "msensor_exe.h"
#include "osal.h"
static xmedia_bool g_forward[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_TRUE };
static xmedia_bool g_buf_init[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_FALSE };
msensor_buf_info g_buf_info[XMEDIA_MSENSOR_MAX_DEV_NUM][XMEDIA_MSENSOR_DATA_TYPE_MAX][DATA_BUTT];
static xmedia_s64 g_offset[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
xmedia_bool g_already_released[XMEDIA_MSENSOR_MAX_DEV_NUM][MAX_USER_NUM] = { XMEDIA_FALSE };
msensor_buf_user_mng g_user_mng[XMEDIA_MSENSOR_MAX_DEV_NUM];
static unsigned long g_msensor_buf_len[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
#define DATA_RESERVE_NUM 50
#define xmedia_align(x, a) ((a) * (((x) + (a) - 1) / (a)))
#define x_start_addr(dev, data_type) g_buf_info[dev][data_type][DATA_X].start_addr
#define y_start_addr(dev, data_type) g_buf_info[dev][data_type][DATA_Y].start_addr
#define z_start_addr(dev, data_type) g_buf_info[dev][data_type][DATA_Z].start_addr
#define temp_start_addr(dev, data_type) g_buf_info[dev][data_type][DATA_TEMP].start_addr
#define pts_start_addr(dev, data_type) g_buf_info[dev][data_type][DATA_PTS].start_addr
#define x_write_ptr(dev, data_type) g_buf_info[dev][data_type][DATA_X].write_ptr
#define y_write_ptr(dev, data_type) g_buf_info[dev][data_type][DATA_Y].write_ptr
#define z_write_ptr(dev, data_type) g_buf_info[dev][data_type][DATA_Z].write_ptr
#define temp_write_ptr(dev, data_type) g_buf_info[dev][data_type][DATA_TEMP].write_ptr
#define pts_write_ptr(dev, data_type) g_buf_info[dev][data_type][DATA_PTS].write_ptr
#define x_read_ptr(dev, i, data_type) g_user_mng[dev].user_ctx[i]->read_ptr[data_type][DATA_X]
#define y_read_ptr(dev, i, data_type) g_user_mng[dev].user_ctx[i]->read_ptr[data_type][DATA_Y]
#define z_read_ptr(dev, i, data_type) g_user_mng[dev].user_ctx[i]->read_ptr[data_type][DATA_Z]
#define temp_read_ptr(dev, i, data_type) g_user_mng[dev].user_ctx[i]->read_ptr[data_type][DATA_TEMP]
#define pts_read_ptr(dev, i, data_type) g_user_mng[dev].user_ctx[i]->read_ptr[data_type][DATA_PTS]
msensor_buf_info **msensor_buf_get_info(xmedia_s32 dev)
{
return (msensor_buf_info **)g_buf_info[dev];
}
xmedia_bool msensor_buf_get_status(xmedia_s32 dev)
{
return g_buf_init[dev];
}
osal_spinlock_t *msensor_buf_get_lock(xmedia_s32 dev)
{
return &g_user_mng[dev].mng_lock;
}
static xmedia_s32 msensor_buf_get_user_id(xmedia_s32 dev, xmedia_s32 *id)
{
xmedia_s32 i;
for (i = 0; i < MAX_USER_NUM; i++) {
if (g_user_mng[dev].user_ctx[i] == XMEDIA_NULL) {
*id = i;
return XMEDIA_SUCCESS;
}
}
MSENSOR_ERR_TRACE("dev %d no id for user.\n", dev);
return XMEDIA_FAILURE;
}
static xmedia_s32 msensor_buf_add_user_create_ctx(xmedia_s32 dev, const xmedia_s32 *id)
{
xmedia_s32 i;
xmedia_s32 j;
xmedia_ulong flags;
msensor_buf_user_context *user_ctx = XMEDIA_NULL;
msensor_mng_proc_info *proc_info = XMEDIA_NULL;
proc_info = msensor_mng_get_proc_info(dev);
user_ctx = (msensor_buf_user_context *)osal_vmalloc(sizeof(msensor_buf_user_context));
if (user_ctx == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d osal_vmalloc failed.\n", dev);
return XMEDIA_FAILURE;
}
(xmedia_void) osal_memset(user_ctx, 0, sizeof(msensor_buf_user_context));
osal_spin_lock_irqsave(&g_user_mng[dev].read_lock[*id], &flags);
for (i = 0; i < DATA_BUTT; i++) {
if (i == DATA_PTS) {
for (j = 0; j < XMEDIA_MSENSOR_DATA_TYPE_MAX; j++) {
user_ctx->read_ptr[j][i] = (proc_info->buf_size[j] > DATA_RESERVE_NUM * BUF_BLOCK_NUM)
? (xmedia_u64 *)g_buf_info[dev][j][i].write_ptr
: g_buf_info[dev][j][i].write_ptr;
}
} else {
for (j = 0; j < XMEDIA_MSENSOR_DATA_TYPE_MAX; j++) {
user_ctx->read_ptr[j][i] = (int *)g_buf_info[dev][j][i].write_ptr;
}
}
}
g_forward[dev] = XMEDIA_TRUE;
g_user_mng[dev].user_ctx[*id] = user_ctx;
g_user_mng[dev].user_cnt++;
osal_spin_unlock_irqrestore(&g_user_mng[dev].read_lock[*id], &flags);
return XMEDIA_SUCCESS;
}
xmedia_s32 msensor_buf_add_user(xmedia_s32 dev, xmedia_s32 *id)
{
xmedia_s32 ret;
if (id == NULL) {
MSENSOR_ERR_TRACE("dev %d msensor id is null.\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
if (g_buf_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d buf not init, g_buf_init:%d\n", dev, g_buf_init[dev]);
return XMEDIA_FAILURE;
}
osal_mutex_lock(&g_user_mng[dev].mng_mutex);
/* step 1: get available ID */
if (g_user_mng[dev].user_cnt > MAX_USER_NUM) {
MSENSOR_ERR_TRACE("dev %d msensor id has reached toplimit.\n", dev);
goto err0;
}
/* get user id for use */
ret = msensor_buf_get_user_id(dev, id);
if (ret != XMEDIA_SUCCESS) {
*id = -1;
MSENSOR_ERR_TRACE("dev %d get_user_id failed.\n", dev);
goto err0;
}
if ((*id < 0) || (*id >= MAX_USER_NUM)) {
MSENSOR_ERR_TRACE("dev %d id(%d) out of range[0,%d].\n", dev, *id, MAX_USER_NUM);
goto err0;
}
/* step 2: create context for new ID */
ret = msensor_buf_add_user_create_ctx(dev, id);
if (ret != XMEDIA_SUCCESS) {
goto err0;
}
osal_mutex_unlock(&g_user_mng[dev].mng_mutex);
osal_msleep(200); /* 200ms */
return XMEDIA_SUCCESS;
err0:
osal_mutex_unlock(&g_user_mng[dev].mng_mutex);
return XMEDIA_FAILURE;
}
xmedia_s32 msensor_buf_delete_user(xmedia_s32 dev, const xmedia_s32 *id)
{
msensor_buf_user_context *msenser_buf_user_contex_temp = XMEDIA_NULL;
xmedia_ulong flags;
if (id == NULL) {
MSENSOR_ERR_TRACE("dev %d msensor id is null.\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
if ((*id < 0) || (*id >= MAX_USER_NUM)) {
MSENSOR_ERR_TRACE("dev %d id(%d) out of range[0,%d].\n", dev, *id, MAX_USER_NUM);
return XMEDIA_FAILURE;
}
if (g_buf_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d msensor buffer not inited.\n", dev);
return XMEDIA_FAILURE;
}
if (g_user_mng[dev].user_ctx[*id] == XMEDIA_NULL) {
msensor_debug_trace("dev %d id is null.\n", dev);
return XMEDIA_SUCCESS;
}
osal_mutex_lock(&g_user_mng[dev].mng_mutex);
osal_spin_lock_irqsave(&g_user_mng[dev].mng_lock, &flags);
/* release context */
msenser_buf_user_contex_temp = g_user_mng[dev].user_ctx[*id];
g_user_mng[dev].user_ctx[*id] = XMEDIA_NULL;
g_user_mng[dev].user_cnt--;
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
osal_mutex_unlock(&g_user_mng[dev].mng_mutex);
if (msenser_buf_user_contex_temp != XMEDIA_NULL) {
osal_vfree(msenser_buf_user_contex_temp);
msenser_buf_user_contex_temp = XMEDIA_NULL;
}
return XMEDIA_SUCCESS;
}
static xmedia_void msensor_buf_init_proc(xmedia_s32 dev, const xmedia_u32 *gyro_block_size,
const xmedia_u32 *acc_block_size, const xmedia_u32 *mag_block_size)
{
msensor_mng_proc_info *proc_info = XMEDIA_NULL;
proc_info = msensor_mng_get_proc_info(dev);
proc_info->buf_addr[XMEDIA_MSENSOR_DATA_TYPE_GYRO] =
(xmedia_u64)(xmedia_uintptr_t)g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_X].start_addr;
proc_info->buf_addr[XMEDIA_MSENSOR_DATA_TYPE_ACC] =
(xmedia_u64)(xmedia_uintptr_t)g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_X].start_addr;
proc_info->buf_size[XMEDIA_MSENSOR_DATA_TYPE_GYRO] = *gyro_block_size * BUF_BLOCK_NUM;
proc_info->buf_size[XMEDIA_MSENSOR_DATA_TYPE_ACC] = *acc_block_size * BUF_BLOCK_NUM;
msensor_debug_trace("##### dev %d gyro-au64_buf_addr:%llu acc-au64_buf_addr:%llu\n", dev,
proc_info->buf_addr[XMEDIA_MSENSOR_DATA_TYPE_GYRO],
proc_info->buf_addr[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
return;
}
static xmedia_void msensor_buf_allocation_init(xmedia_s32 dev, xmedia_u32 buflen, xmedia_u32 gyro_odr,
xmedia_u32 accel_odr, xmedia_u32 mag_odr, const xmedia_void *vir_addr)
{
xmedia_s32 i;
xmedia_u32 gyro_block_size;
xmedia_u32 acc_block_size;
xmedia_u32 mag_block_size;
gyro_block_size = buflen * gyro_odr / (gyro_odr + accel_odr + mag_odr) / BUF_BLOCK_NUM / 32 * 32; /* align by 32 */
acc_block_size = buflen * accel_odr / (gyro_odr + accel_odr + mag_odr) / BUF_BLOCK_NUM / 32 * 32; /* align by 32 */
mag_block_size = (buflen / BUF_BLOCK_NUM - gyro_block_size - acc_block_size) / 32 * 32; /* align by 32 */
msensor_debug_trace("dev %d gyro block size %u, acc block size %d, mag block size %u\n", dev, gyro_block_size,
acc_block_size, mag_block_size);
for (i = 0; i < DATA_BUTT; i++) {
g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_GYRO][i].start_addr = (xmedia_u8 *)vir_addr + gyro_block_size * i;
g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_GYRO][i].write_ptr =
g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_GYRO][i].start_addr;
g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_ACC][i].start_addr =
(xmedia_u8 *)vir_addr + gyro_block_size * BUF_BLOCK_NUM + acc_block_size * i;
g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_ACC][i].write_ptr =
g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_ACC][i].start_addr;
}
msensor_debug_trace("**pts-write_pointer:%p\n", g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_PTS].write_ptr);
msensor_buf_init_proc(dev, &gyro_block_size, &acc_block_size, &mag_block_size);
return;
}
xmedia_s32 msensor_buf_init(xmedia_s32 dev, const xmedia_msensor_buf_attr *buf_attr, xmedia_u32 gyro_odr,
xmedia_u32 accel_odr, xmedia_u32 mag_odr)
{
xmedia_void *vir_addr = XMEDIA_NULL;
xmedia_s32 i;
if (g_buf_init[dev] == XMEDIA_TRUE) {
MSENSOR_ERR_TRACE("dev %d buf already inited\n", dev);
return XMEDIA_SUCCESS;
}
if ((buf_attr->phys_addr == 0) || (buf_attr->buf_len == 0)) {
MSENSOR_ERR_TRACE("dev %d buf addr can not be null and buf size must lager than 0\n", dev);
return XMEDIA_FAILURE;
}
if ((gyro_odr == 0) && (accel_odr == 0) && (mag_odr == 0)) {
MSENSOR_ERR_TRACE("dev %d can't all frequency be 0\n", dev);
return XMEDIA_FAILURE;
}
/* modify for 64bit chip */
vir_addr = osal_ioremap_wc((xmedia_u64)buf_attr->phys_addr, xmedia_align(buf_attr->buf_len, 4));
if (vir_addr == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d ioremap err\n", dev);
return XMEDIA_FAILURE;
}
g_msensor_buf_len[dev] = xmedia_align(buf_attr->buf_len, 4);
(xmedia_void) osal_memset(vir_addr, 0, buf_attr->buf_len);
msensor_debug_trace("dev %d phy_addr:%llx vir_addr:%p buflen:%d\n", dev, buf_attr->phys_addr, vir_addr,
buf_attr->buf_len);
g_offset[dev] = buf_attr->phys_addr - (xmedia_u64)(xmedia_uintptr_t)vir_addr;
msensor_buf_allocation_init(dev, buf_attr->buf_len, gyro_odr, accel_odr, mag_odr, vir_addr);
osal_mutex_init(&g_user_mng[dev].mng_mutex);
for (i = 0; i < MAX_USER_NUM; i++) {
g_already_released[dev][i] = XMEDIA_TRUE;
}
g_buf_init[dev] = XMEDIA_TRUE;
return XMEDIA_SUCCESS;
}
xmedia_s32 msensor_buf_exit(xmedia_s32 dev)
{
xmedia_s32 i;
xmedia_s32 ret;
if (g_buf_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d buf already deinited\n", dev);
return XMEDIA_SUCCESS;
}
for (i = 0; i < MAX_USER_NUM; i++) {
ret = msensor_buf_delete_user(dev, &i);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d msensor delete user failed\n", dev);
}
}
osal_iounmap(g_buf_info[dev][XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_X].start_addr);
g_msensor_buf_len[dev] = 0;
(xmedia_void) osal_memset(&g_buf_info[dev], 0, sizeof(g_buf_info[dev]));
g_buf_init[dev] = XMEDIA_FALSE;
return ret;
}
static xmedia_void msensor_buf_write(xmedia_s32 dev, xmedia_msensor_data_type data_type,
const xmedia_msensor_sample_data *sample_data)
{
xmedia_void *next_write_pointer = XMEDIA_NULL;
/* step 2:write data */
*(xmedia_s32 *)x_write_ptr(dev, data_type) = sample_data->x;
*(xmedia_s32 *)y_write_ptr(dev, data_type) = sample_data->y;
*(xmedia_s32 *)z_write_ptr(dev, data_type) = sample_data->z;
*(xmedia_s32 *)temp_write_ptr(dev, data_type) = sample_data->temperature;
*(xmedia_u64 *)pts_write_ptr(dev, data_type) = sample_data->pts;
/* step 3:calculate next write pointer */
next_write_pointer = (xmedia_u8 *)x_write_ptr(dev, data_type) + sizeof(sample_data->x);
if (next_write_pointer >= y_start_addr(dev, data_type)) {
x_write_ptr(dev, data_type) = x_start_addr(dev, data_type);
y_write_ptr(dev, data_type) = y_start_addr(dev, data_type);
z_write_ptr(dev, data_type) = z_start_addr(dev, data_type);
temp_write_ptr(dev, data_type) = temp_start_addr(dev, data_type);
pts_write_ptr(dev, data_type) = pts_start_addr(dev, data_type);
} else {
x_write_ptr(dev, data_type) = (xmedia_u8 *)x_write_ptr(dev, data_type) + sizeof(sample_data->x);
y_write_ptr(dev, data_type) = (xmedia_u8 *)y_write_ptr(dev, data_type) + sizeof(sample_data->y);
z_write_ptr(dev, data_type) = (xmedia_u8 *)z_write_ptr(dev, data_type) + sizeof(sample_data->z);
temp_write_ptr(dev, data_type) = (xmedia_u8 *)temp_write_ptr(dev, data_type) + sizeof(sample_data->temperature);
pts_write_ptr(dev, data_type) = (xmedia_u8 *)pts_write_ptr(dev, data_type) + sizeof(sample_data->pts);
}
return;
}
xmedia_s32 msensor_buf_write_data(xmedia_s32 dev, xmedia_msensor_data_type data_type,
const xmedia_msensor_sample_data *sample_data)
{
xmedia_s32 i;
xmedia_void *tmp_ptr = XMEDIA_NULL;
xmedia_bool condition;
msensor_mng_proc_info *proc_info = XMEDIA_NULL;
xmedia_ulong flags;
proc_info = msensor_mng_get_proc_info(dev);
if (g_buf_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d when write_data(pts:%lld),msensor buf not be inited yet\n", dev, sample_data->pts);
return XMEDIA_FAILURE;
}
/* step 1:judge if any user overflow */
if ((xmedia_u8 *)y_start_addr(dev, data_type) - (xmedia_u8 *)x_write_ptr(dev, data_type) >
(xmedia_s32)(sizeof(sample_data->x) * WR_GAP)) {
tmp_ptr = (xmedia_u8 *)x_write_ptr(dev, data_type) + sizeof(sample_data->x) * WR_GAP;
} else {
tmp_ptr = (xmedia_u8 *)x_start_addr(dev, data_type) + sizeof(sample_data->x) * WR_GAP -
((xmedia_u8 *)y_start_addr(dev, data_type) - (xmedia_u8 *)x_write_ptr(dev, data_type));
}
for (i = 0; i < MAX_USER_NUM; i++) {
if (g_user_mng[dev].user_ctx[i] != XMEDIA_NULL) {
if (((tmp_ptr == y_start_addr(dev, data_type)) &&
(x_read_ptr(dev, i, data_type) == x_start_addr(dev, data_type))) ||
(tmp_ptr == x_read_ptr(dev, i, data_type))) {
proc_info->buf_overflow[data_type]++;
proc_info->buf_overflow_id[data_type] = i;
osal_spin_lock_irqsave(&g_user_mng[dev].read_lock[i], &flags);
condition =
((xmedia_u32 *)x_read_ptr(dev, i, data_type) + 1) >= (xmedia_u32 *)y_start_addr(dev, data_type);
x_read_ptr(dev, i, data_type) =
condition ? x_start_addr(dev, data_type) : (xmedia_u32 *)x_read_ptr(dev, i, data_type) + 1;
y_read_ptr(dev, i, data_type) =
condition ? y_start_addr(dev, data_type) : (xmedia_u32 *)y_read_ptr(dev, i, data_type) + 1;
z_read_ptr(dev, i, data_type) =
condition ? z_start_addr(dev, data_type) : (xmedia_u32 *)z_read_ptr(dev, i, data_type) + 1;
temp_read_ptr(dev, i, data_type) =
condition ? temp_start_addr(dev, data_type) : (xmedia_u32 *)temp_read_ptr(dev, i, data_type) + 1;
pts_read_ptr(dev, i, data_type) =
condition ? pts_start_addr(dev, data_type) : (xmedia_u64 *)pts_read_ptr(dev, i, data_type) + 1;
osal_spin_unlock_irqrestore(&g_user_mng[dev].read_lock[i], &flags);
}
}
}
/* write data */
msensor_buf_write(dev, data_type, sample_data);
return XMEDIA_SUCCESS;
}
static xmedia_void msensor_buf_release(xmedia_s32 dev, xmedia_msensor_data_info *data_info)
{
xmedia_s32 id = data_info->id;
xmedia_msensor_data_type data_type = data_info->data_type;
xmedia_ulong flags;
osal_spin_lock_irqsave(&g_user_mng[dev].read_lock[id], &flags);
if (data_info->data[1].num == 0) {
if (data_info->data[0].num > 0) {
if (((xmedia_u64)(xmedia_uintptr_t)data_info->data[0].x_phys_addr +
data_info->data[0].num * sizeof(xmedia_s32) - g_offset[dev]) >=
((xmedia_u64)(xmedia_uintptr_t)y_start_addr(dev, data_type))) {
x_read_ptr(dev, id, data_type) = x_start_addr(dev, data_type);
y_read_ptr(dev, id, data_type) = y_start_addr(dev, data_type);
z_read_ptr(dev, id, data_type) = z_start_addr(dev, data_type);
temp_read_ptr(dev, id, data_type) = temp_start_addr(dev, data_type);
pts_read_ptr(dev, id, data_type) = pts_start_addr(dev, data_type);
} else {
x_read_ptr(dev, id, data_type) = (xmedia_u8 *)data_info->data[0].x_phys_addr +
data_info->data[0].num * sizeof(xmedia_s32) - g_offset[dev];
y_read_ptr(dev, id, data_type) = (xmedia_u8 *)data_info->data[0].y_phys_addr +
data_info->data[0].num * sizeof(xmedia_s32) - g_offset[dev];
z_read_ptr(dev, id, data_type) = (xmedia_u8 *)data_info->data[0].z_phys_addr +
data_info->data[0].num * sizeof(xmedia_s32) - g_offset[dev];
temp_read_ptr(dev, id, data_type) = (xmedia_u8 *)data_info->data[0].temperature_phys_addr +
data_info->data[0].num * sizeof(xmedia_s32) - g_offset[dev];
pts_read_ptr(dev, id, data_type) = (xmedia_u8 *)data_info->data[0].pts_phys_addr +
data_info->data[0].num * sizeof(xmedia_u64) - g_offset[dev];
}
}
} else {
x_read_ptr(dev, id, data_type) =
(xmedia_u8 *)data_info->data[1].x_phys_addr + data_info->data[1].num * sizeof(xmedia_s32) - g_offset[dev];
y_read_ptr(dev, id, data_type) =
(xmedia_u8 *)data_info->data[1].y_phys_addr + data_info->data[1].num * sizeof(xmedia_s32) - g_offset[dev];
z_read_ptr(dev, id, data_type) =
(xmedia_u8 *)data_info->data[1].z_phys_addr + data_info->data[1].num * sizeof(xmedia_s32) - g_offset[dev];
temp_read_ptr(dev, id, data_type) = (xmedia_u8 *)data_info->data[1].temperature_phys_addr +
data_info->data[1].num * sizeof(xmedia_s32) - g_offset[dev];
pts_read_ptr(dev, id, data_type) =
(xmedia_u8 *)data_info->data[1].pts_phys_addr + data_info->data[1].num * sizeof(xmedia_u64) - g_offset[dev];
}
data_info->data[0].num = 0;
data_info->data[1].num = 0;
g_already_released[dev][id] = XMEDIA_TRUE;
osal_spin_unlock_irqrestore(&g_user_mng[dev].read_lock[id], &flags);
return;
}
xmedia_s32 msensor_buf_release_data(xmedia_s32 dev, xmedia_msensor_data_info *data_info)
{
xmedia_ulong flags;
if (data_info == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d data info is null\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
osal_spin_lock_irqsave(&g_user_mng[dev].mng_lock, &flags);
if ((data_info->id < 0) || (data_info->id >= MAX_USER_NUM)) {
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
MSENSOR_ERR_TRACE("dev %d *id(%d) is out of range[0,%d].\n", dev, data_info->id, MAX_USER_NUM);
return XMEDIA_FAILURE;
}
if (g_buf_init[dev] == XMEDIA_FALSE) {
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
MSENSOR_ERR_TRACE("dev %d when release_data, msensor buf not be inited yet\n", dev);
return XMEDIA_FAILURE;
}
if (g_user_mng[dev].user_ctx[data_info->id] == XMEDIA_NULL) {
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
MSENSOR_ERR_TRACE("dev %d msensor buf release: id is null.\n", dev);
return XMEDIA_FAILURE;
}
if (data_info->data_type >= XMEDIA_MSENSOR_DATA_TYPE_MAX) {
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
MSENSOR_ERR_TRACE("dev %d data_type:%d is out of range.\n", dev, data_info->data_type);
return XMEDIA_FAILURE;
}
if (g_already_released[dev][data_info->id] == XMEDIA_TRUE) {
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
return XMEDIA_SUCCESS;
}
/* release data */
msensor_buf_release(dev, data_info);
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_buf_arrive_back_start_addr(xmedia_s32 dev, const xmedia_msensor_data_info *data_info)
{
xmedia_s32 length[2] = { 0 }; /* 2 : cycle buf */
xmedia_s32 buftotal_len;
xmedia_bool loop_flag = XMEDIA_FALSE;
xmedia_u32 interval;
xmedia_u64 *p_pts_read_ptr = XMEDIA_NULL;
xmedia_msensor_data_type data_type = data_info->data_type;
xmedia_s32 id = data_info->id;
buftotal_len = (xmedia_u32 *)y_start_addr(dev, data_type) - (xmedia_u32 *)x_start_addr(dev, data_type);
p_pts_read_ptr = pts_read_ptr(dev, id, data_type);
while (1) {
if ((*p_pts_read_ptr <= data_info->begin_pts) || (p_pts_read_ptr == pts_write_ptr(dev, data_type))) {
if (p_pts_read_ptr == pts_write_ptr(dev, data_type)) {
MSENSOR_ERR_TRACE("dev %d arrive to write_addr!\n", dev);
}
break;
}
if (p_pts_read_ptr == pts_start_addr(dev, data_type)) {
loop_flag = XMEDIA_TRUE;
p_pts_read_ptr = (xmedia_u64 *)pts_start_addr(dev, data_type) + buftotal_len - 1;
} else {
p_pts_read_ptr--;
}
g_forward[dev] = XMEDIA_FALSE;
/* msensor_debug_trace("#####pts_read_pointer:%p %lld\n", pts_read_ptr, *pts_read_ptr) */
if (loop_flag == XMEDIA_TRUE) {
length[1]++;
} else {
length[0]++;
}
}
if (length[1] > 0) {
interval = (xmedia_u64 *)pts_start_addr(dev, data_type) + buftotal_len - p_pts_read_ptr;
x_read_ptr(dev, id, data_type) = (xmedia_u32 *)y_start_addr(dev, data_type) - interval;
y_read_ptr(dev, id, data_type) = (xmedia_u32 *)z_start_addr(dev, data_type) - interval;
z_read_ptr(dev, id, data_type) = (xmedia_u32 *)temp_start_addr(dev, data_type) - interval;
temp_read_ptr(dev, id, data_type) = (xmedia_u32 *)pts_start_addr(dev, data_type) - interval;
pts_read_ptr(dev, id, data_type) = p_pts_read_ptr;
} else {
interval = (xmedia_u64 *)pts_read_ptr(dev, id, data_type) - p_pts_read_ptr;
x_read_ptr(dev, id, data_type) = (xmedia_u32 *)x_read_ptr(dev, id, data_type) - interval;
y_read_ptr(dev, id, data_type) = (xmedia_u32 *)y_read_ptr(dev, id, data_type) - interval;
z_read_ptr(dev, id, data_type) = (xmedia_u32 *)z_read_ptr(dev, id, data_type) - interval;
temp_read_ptr(dev, id, data_type) = (xmedia_u32 *)temp_read_ptr(dev, id, data_type) - interval;
pts_read_ptr(dev, id, data_type) = p_pts_read_ptr;
}
return XMEDIA_SUCCESS;
}
static xmedia_void msensor_buf_get_data_assign(xmedia_s32 dev, xmedia_msensor_data_info *data_info)
{
xmedia_s32 id = data_info->id;
xmedia_msensor_data_type data_type = data_info->data_type;
xmedia_u32 interval;
msensor_mng_proc_info *proc_info = XMEDIA_NULL;
proc_info = msensor_mng_get_proc_info(dev);
if (data_info->data[0].num > 0) {
data_info->data[0].x_phys_addr = (xmedia_void *)((xmedia_u8 *)x_read_ptr(dev, id, data_type) + g_offset[dev]);
data_info->data[0].y_phys_addr = (xmedia_void *)((xmedia_u8 *)y_read_ptr(dev, id, data_type) + g_offset[dev]);
data_info->data[0].z_phys_addr = (xmedia_void *)((xmedia_u8 *)z_read_ptr(dev, id, data_type) + g_offset[dev]);
data_info->data[0].temperature_phys_addr =
(xmedia_void *)((xmedia_u8 *)temp_read_ptr(dev, id, data_type) + g_offset[dev]);
data_info->data[0].pts_phys_addr =
(xmedia_void *)((xmedia_u8 *)pts_read_ptr(dev, id, data_type) + g_offset[dev]);
}
if (data_info->data[1].num > 0) {
data_info->data[1].x_phys_addr = (xmedia_void *)((xmedia_u8 *)x_start_addr(dev, data_type) + g_offset[dev]);
data_info->data[1].y_phys_addr = (xmedia_void *)((xmedia_u8 *)y_start_addr(dev, data_type) + g_offset[dev]);
data_info->data[1].z_phys_addr = (xmedia_void *)((xmedia_u8 *)z_start_addr(dev, data_type) + g_offset[dev]);
data_info->data[1].temperature_phys_addr =
(xmedia_void *)((xmedia_u8 *)temp_start_addr(dev, data_type) + g_offset[dev]);
data_info->data[1].pts_phys_addr = (xmedia_void *)((xmedia_u8 *)pts_start_addr(dev, data_type) + g_offset[dev]);
}
if ((data_info->data[0].num == 0) && (data_info->data[1].num == 0)) {
g_already_released[dev][id] = XMEDIA_TRUE;
proc_info->buf_data_unmatch[data_type]++;
proc_info->buf_data_unmatch_id[data_type] = id;
interval = (xmedia_u32)(xmedia_uintptr_t)((xmedia_u8 *)pts_read_ptr(dev, id, data_type) -
(xmedia_u8 *)pts_start_addr(dev, data_type)) >>
1;
x_read_ptr(dev, id, data_type) = (xmedia_u8 *)x_start_addr(dev, data_type) + interval;
y_read_ptr(dev, id, data_type) = (xmedia_u8 *)y_start_addr(dev, data_type) + interval;
z_read_ptr(dev, id, data_type) = (xmedia_u8 *)z_start_addr(dev, data_type) + interval;
temp_read_ptr(dev, id, data_type) = (xmedia_u8 *)temp_start_addr(dev, data_type) + interval;
pts_read_ptr(dev, id, data_type) = pts_read_ptr(dev, id, data_type);
} else {
g_already_released[dev][id] = XMEDIA_FALSE;
}
data_info->addr_offset = g_offset[dev];
return;
}
static xmedia_void msensor_buf_get_data_process(xmedia_s32 dev, xmedia_msensor_data_info *data_info)
{
xmedia_bool loop_flag = XMEDIA_FALSE;
xmedia_bool first_found = XMEDIA_FALSE;
xmedia_u32 interval;
xmedia_u64 *pts_read_ptr = XMEDIA_NULL;
xmedia_void *pts_start_ptr = XMEDIA_NULL;
xmedia_s32 id = data_info->id;
xmedia_msensor_data_type data_type = data_info->data_type;
pts_read_ptr = pts_read_ptr(dev, id, data_type);
pts_start_ptr = pts_start_addr(dev, data_type);
while (1) {
if (((pts_read_ptr == pts_write_ptr(dev, data_type)) && (g_forward[dev] == XMEDIA_TRUE)) ||
(*pts_read_ptr > data_info->end_pts)) {
break;
}
if ((*pts_read_ptr >= data_info->begin_pts) && (*pts_read_ptr <= data_info->end_pts)) {
if (loop_flag == XMEDIA_TRUE) {
data_info->data[1].num++;
} else if (first_found == XMEDIA_FALSE) {
data_info->data[0].num++;
interval = (xmedia_u32)(xmedia_uintptr_t)((xmedia_u8 *)pts_read_ptr - (xmedia_u8 *)pts_start_ptr) >> 1;
x_read_ptr(dev, id, data_type) = (xmedia_u8 *)x_start_addr(dev, data_type) + interval;
y_read_ptr(dev, id, data_type) = (xmedia_u8 *)y_start_addr(dev, data_type) + interval;
z_read_ptr(dev, id, data_type) = (xmedia_u8 *)z_start_addr(dev, data_type) + interval;
temp_read_ptr(dev, id, data_type) = (xmedia_u8 *)temp_start_addr(dev, data_type) + interval;
pts_read_ptr(dev, id, data_type) = pts_read_ptr;
first_found = XMEDIA_TRUE;
} else {
data_info->data[0].num++;
}
}
pts_read_ptr++;
g_forward[dev] = XMEDIA_TRUE;
if (pts_read_ptr >= ((xmedia_u64 *)pts_start_ptr +
((xmedia_u8 *)y_start_addr(dev, data_type) - (xmedia_u8 *)x_start_addr(dev, data_type)) /
sizeof(xmedia_s32))) {
pts_read_ptr = pts_start_ptr;
if (first_found == XMEDIA_TRUE) {
loop_flag = XMEDIA_TRUE;
}
}
}
return;
}
static xmedia_s32 msensor_buf_data_check(xmedia_s32 dev, const xmedia_msensor_data_info *msensor_data)
{
if (g_buf_init[dev] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d get data, but msensor buffer hasn't been initialised.\n", dev);
return XMEDIA_FAILURE;
}
if (msensor_data == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d msensor_data(%p) is null!!!\n", dev, msensor_data);
return XMEDIA_FAILURE;
}
if ((msensor_data->id < 0) || (msensor_data->id >= MAX_USER_NUM)) {
MSENSOR_ERR_TRACE("dev %d id(%d) is out of range[0, %d].\n", dev, msensor_data->id, MAX_USER_NUM);
return XMEDIA_FAILURE;
}
if (msensor_data->data_type >= XMEDIA_MSENSOR_DATA_TYPE_MAX) {
MSENSOR_ERR_TRACE("dev %d data_type:%d out of range.\n", dev, msensor_data->data_type);
return XMEDIA_FAILURE;
}
/* Check whether user is created. */
if (g_user_mng[dev].user_ctx[msensor_data->id] == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d msensor_buf_read_data: id:%d is null.\n", dev, msensor_data->id);
return XMEDIA_FAILURE;
}
if (g_already_released[dev][msensor_data->id] == XMEDIA_FALSE) {
MSENSOR_ERR_TRACE("dev %d please release last read\n", dev);
return XMEDIA_FAILURE;
}
if ((msensor_data->end_pts - msensor_data->begin_pts) > 5000000) { /* 5000000us */
MSENSOR_ERR_TRACE("dev %d end pts[%llu] - begin pts[%llu] = %llu, more than 5000000\n", dev,
msensor_data->end_pts, msensor_data->begin_pts,
msensor_data->end_pts - msensor_data->begin_pts);
return XMEDIA_FAILURE;
}
if (msensor_data->end_pts <= msensor_data->begin_pts) {
MSENSOR_ERR_TRACE("dev %d end_pts[%llu] <= begin_pts[%llu]\n", dev, msensor_data->end_pts,
msensor_data->begin_pts);
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 msensor_buf_get_data(xmedia_s32 dev, xmedia_msensor_data_info *msensor_data)
{
xmedia_s32 ret;
xmedia_ulong flags;
xmedia_ulong flags_read;
xmedia_msensor_data_info data_info = { 0 };
ret = msensor_buf_data_check(dev, msensor_data);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
/* remain check user id to be done */
osal_memcpy(&data_info, msensor_data, sizeof(xmedia_msensor_data_info));
if (msensor_data->data_type == XMEDIA_MSENSOR_DATA_TYPE_GYRO) {
msensor_mng_write_data_2_buf(dev);
}
osal_spin_lock_irqsave(&g_user_mng[dev].mng_lock, &flags);
ret = msensor_buf_data_check(dev, msensor_data);
if (ret != XMEDIA_SUCCESS) {
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
return ret;
}
ret = msensor_buf_arrive_back_start_addr(dev, &data_info);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d data_type:%d has no data.\n", dev, msensor_data->data_type);
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
return XMEDIA_FAILURE;
}
data_info.data[0].num = 0;
data_info.data[1].num = 0;
osal_spin_lock_irqsave(&g_user_mng[dev].read_lock[msensor_data->id], &flags_read);
msensor_buf_get_data_process(dev, &data_info);
msensor_buf_get_data_assign(dev, &data_info);
osal_spin_unlock_irqrestore(&g_user_mng[dev].read_lock[msensor_data->id], &flags_read);
osal_memcpy(msensor_data, &data_info, sizeof(xmedia_msensor_data_info));
osal_spin_unlock_irqrestore(&g_user_mng[dev].mng_lock, &flags);
ret = msensor_buf_release_data(dev, &data_info);
return ret;
}
static xmedia_s32 msensor_buf_sync_init(xmedia_s32 dev)
{
xmedia_s32 ret;
xmedia_s32 i;
for (i = 0; i < MAX_USER_NUM; i++) {
ret = osal_spin_lock_init(&g_user_mng[dev].read_lock[i]);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d spin_lock_init failed!!!!\n", dev);
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_void msensor_buf_sync_deinit(xmedia_s32 dev)
{
xmedia_s32 i;
for (i = 0; i < MAX_USER_NUM; i++) {
osal_spin_lock_destroy(&g_user_mng[dev].read_lock[i]);
}
return;
}
xmedia_s32 msensor_buf_lock_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_s32 dev;
for (dev = 0; dev < XMEDIA_MSENSOR_MAX_DEV_NUM; dev++) {
(xmedia_void) osal_memset(&g_user_mng[dev], 0, sizeof(msensor_buf_user_mng));
ret = osal_spin_lock_init(&g_user_mng[dev].mng_lock);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("spin_lock_init failed!!!!\n");
return XMEDIA_FAILURE;
}
ret = msensor_buf_sync_init(dev);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("msensor buf sync init failed!!!!\n");
return XMEDIA_FAILURE;
}
osal_mutex_init(&g_user_mng[dev].mng_mutex);
}
return XMEDIA_SUCCESS;
}
xmedia_void msensor_buf_lock_exit(xmedia_void)
{
xmedia_s32 dev;
for (dev = 0; dev < XMEDIA_MSENSOR_MAX_DEV_NUM; dev++) {
osal_mutex_destroy(&g_user_mng[dev].mng_mutex);
msensor_buf_sync_deinit(dev);
osal_spin_lock_destroy(&g_user_mng[dev].mng_lock);
}
return;
}
@@ -0,0 +1,560 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor_exe.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include "osal.h"
#include "mmz.h"
#include "common.h"
#include "msensor_ext.h"
#include "msensor_buf.h"
#ifdef CONFIG_PROC_SHOW_SUPPORT
#include "msensor_mng_proc.h"
#endif
#include "msensor_mng_ioctl.h"
#define UMAP_MSENSOR_MNG_MINOR_BASE 154
#define UMAP_DEVNANME_MSENSOR_MNG_BASE "msensor_mng"
static osal_dev_t *g_msensor_mng_dev = XMEDIA_NULL;
msensor_mng_proc_info g_mng_proc_info[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
static msensor_mng_callback g_msensor_mng_callback[XMEDIA_MSENSOR_MAX_DEV_NUM] = { XMEDIA_NULL };
static osal_atomic_t g_msensor_mng_user_ref[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 };
#define USER_SEND_DATA 1
#define GYRO_NAME "ICM42670"
msensor_mng_proc_info *msensor_mng_get_proc_info(xmedia_s32 dev)
{
return &g_mng_proc_info[dev];
}
xmedia_s32 msensor_mng_proc_info_init(xmedia_s32 dev)
{
msensor_mng_proc_info *proc_info = XMEDIA_NULL;
proc_info = msensor_mng_get_proc_info(dev);
osal_memcpy(proc_info->gyro_name, "ICM42670", sizeof("ICM42670"));
osal_memcpy(proc_info->accel_name, "ICM42670", sizeof("ICM42670"));
return XMEDIA_SUCCESS;
}
xmedia_s32 msensor_mng_write_data_to_buf(xmedia_s32 dev, xmedia_msensor_data *msensor_data)
{
xmedia_u32 i;
xmedia_s32 ret = XMEDIA_SUCCESS;
osal_spinlock_t *mng_lock = msensor_buf_get_lock(dev);
xmedia_ulong flags;
if (msensor_data == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d msensor data is null\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
if ((msensor_data->gyro_buf.data_num > XMEDIA_MSENSOR_MAX_DATA_NUM) ||
(msensor_data->acc_buf.data_num > XMEDIA_MSENSOR_MAX_DATA_NUM)) {
return XMEDIA_FAILURE;
}
osal_spin_lock_irqsave(mng_lock, &flags);
if ((msensor_data->attr.device_mask & XMEDIA_MSENSOR_DEVICE_GYRO) == XMEDIA_MSENSOR_DEVICE_GYRO) {
for (i = 0; i < msensor_data->gyro_buf.data_num; i++) {
if ((msensor_data->attr.temperature_mask & XMEDIA_MSENSOR_TEMP_GYRO) != XMEDIA_MSENSOR_TEMP_GYRO) {
msensor_data->gyro_buf.gyro_data[i].temperature = 0xffffffff;
}
ret = msensor_buf_write_data(dev, XMEDIA_MSENSOR_DATA_TYPE_GYRO, &(msensor_data->gyro_buf.gyro_data[i]));
}
}
if ((msensor_data->attr.device_mask & XMEDIA_MSENSOR_DEVICE_ACC) == XMEDIA_MSENSOR_DEVICE_ACC) {
for (i = 0; i < msensor_data->acc_buf.data_num; i++) {
if ((msensor_data->attr.temperature_mask & XMEDIA_MSENSOR_TEMP_ACC) != XMEDIA_MSENSOR_TEMP_ACC) {
msensor_data->acc_buf.acc_data[i].temperature = 0xffffffff;
}
ret = msensor_buf_write_data(dev, XMEDIA_MSENSOR_DATA_TYPE_ACC, &(msensor_data->acc_buf.acc_data[i]));
}
}
osal_spin_unlock_irqrestore(mng_lock, &flags);
return ret;
}
static xmedia_s32 msensor_buf_check_phys_addr(xmedia_s32 dev, xmedia_msensor_data_info *data_info)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
xmedia_unused(dev);
if (data_info->data[0].num > 0) {
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[0].x_phys_addr,
sizeof(xmedia_s32) * data_info->data[0].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[0].y_phys_addr,
sizeof(xmedia_s32) * data_info->data[0].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[0].z_phys_addr,
sizeof(xmedia_s32) * data_info->data[0].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[0].temperature_phys_addr,
sizeof(xmedia_s32) * data_info->data[0].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[0].pts_phys_addr,
sizeof(xmedia_u64) * data_info->data[0].num);
}
if (data_info->data[1].num > 0) {
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[1].x_phys_addr,
sizeof(xmedia_s32) * data_info->data[1].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[1].y_phys_addr,
sizeof(xmedia_s32) * data_info->data[1].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[1].z_phys_addr,
sizeof(xmedia_s32) * data_info->data[1].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[1].temperature_phys_addr,
sizeof(xmedia_s32) * data_info->data[1].num);
ret |= mmz_check_phyaddr((xmedia_u64)(xmedia_uintptr_t)data_info->data[1].pts_phys_addr,
sizeof(xmedia_u64) * data_info->data[1].num);
}
return ret;
}
/* msensor mng ioctl functions */
static xmedia_s32 msensor_mng_drv_user_get_data(xmedia_s32 dev, xmedia_ulong arg)
{
xmedia_s32 ret;
ret = msensor_buf_get_data(dev, (xmedia_msensor_data_info *)arg);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d get data failed! ret=%x\n", dev, ret);
return ret;
}
ret = msensor_buf_check_phys_addr(dev, (xmedia_msensor_data_info *)arg);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d check msensor data addr share failed\n", dev);
return ret;
}
return ret;
}
static xmedia_s32 msensor_mng_drv_user_release_buf(xmedia_s32 dev, xmedia_ulong arg)
{
xmedia_s32 ret;
ret = msensor_buf_check_phys_addr(dev, (xmedia_msensor_data_info *)arg);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d check msensor_data_addr share failed\n", dev);
return XMEDIA_FAILURE;
}
ret = msensor_buf_release_data(dev, (xmedia_msensor_data_info *)arg);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d buf release failed! ret=%x\n", dev, ret);
return XMEDIA_FAILURE;
}
return ret;
}
static xmedia_s32 msensor_mng_drv_user_add_user(xmedia_s32 dev, xmedia_ulong arg)
{
xmedia_s32 ret;
ret = msensor_buf_add_user(dev, (xmedia_s32 *)arg);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d msensor buf add_user failed! ret=%x\n", dev, ret);
return ret;
}
return ret;
}
static xmedia_s32 msensor_mng_drv_user_delete_user(xmedia_s32 dev, xmedia_ulong arg)
{
xmedia_s32 ret;
ret = msensor_buf_delete_user(dev, (xmedia_s32 *)arg);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d msensor buf delete user failed! ret=%x\n", dev, ret);
return ret;
}
return ret;
}
static xmedia_s32 msensor_mng_drv_user_send_data(xmedia_s32 dev, xmedia_ulong arg)
{
#ifdef USER_SEND_DATA
xmedia_s32 ret;
xmedia_msensor_data *msensor_data;
msensor_data = (xmedia_msensor_data *)arg;
ret = msensor_mng_write_data_to_buf(dev, msensor_data);
if (ret != XMEDIA_SUCCESS) {
MSENSOR_ERR_TRACE("dev %d write data to buf failed! ret=%x\n", dev, ret);
return ret;
}
return ret;
#else
MSENSOR_ERR_TRACE("dev %d msensor send data not support\n", dev);
return XMEDIA_FAILURE;
#endif
}
xmedia_s32 msensor_mng_drv_get_data(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_mng_drv_user_get_data(dev, arg);
}
xmedia_s32 msensor_mng_drv_release_buf(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_mng_drv_user_release_buf(dev, arg);
}
xmedia_s32 msensor_mng_drv_add_user(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_mng_drv_user_add_user(dev, arg);
}
xmedia_s32 msensor_mng_drv_delete_user(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_mng_drv_user_delete_user(dev, arg);
}
xmedia_s32 msensor_mng_drv_send_data(xmedia_s32 dev, xmedia_ulong arg)
{
return msensor_mng_drv_user_send_data(dev, arg);
}
typedef xmedia_s32 (*msensor_ctl_ptr_func)(xmedia_s32 dev_id, xmedia_ulong arg);
typedef struct {
xmedia_u32 cmd;
msensor_ctl_ptr_func ptr_func;
} msensor_ioctl_func_item;
static msensor_ioctl_func_item g_msensor_mng_cmd_list[] = {
{ MSENSOR_CMD_GET_DATA, msensor_mng_drv_get_data }, { MSENSOR_CMD_RELEASE_BUF, msensor_mng_drv_release_buf },
{ MSENSOR_CMD_ADD_USER, msensor_mng_drv_add_user }, { MSENSOR_CMD_DELETE_USER, msensor_mng_drv_delete_user },
{ MSENSOR_CMD_SEND_DATA, msensor_mng_drv_send_data },
};
static xmedia_s32 msensor_mng_do_ioctl(xmedia_s32 dev, xmedia_u32 cmd, xmedia_ulong arg)
{
xmedia_s32 i;
for (i = 0; i < sizeof(g_msensor_mng_cmd_list) / sizeof(g_msensor_mng_cmd_list[0]); i++) {
if (cmd == g_msensor_mng_cmd_list[i].cmd) {
return g_msensor_mng_cmd_list[i].ptr_func(dev, arg);
}
}
MSENSOR_ERR_TRACE("dev %d msensor chip ioctl cmd 0x%x not supported!\n", dev, cmd);
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
xmedia_slong msensor_mng_ioctl(xmedia_u32 cmd, xmedia_ulong arg, xmedia_void *private_data)
{
xmedia_s32 ret;
xmedia_s32 dev;
if (cmd == MSENSOR_CMD_MNG_BIND_FLAG2FD) {
*(xmedia_u32 *)private_data = *(xmedia_u32 *)arg;
return XMEDIA_SUCCESS;
}
dev = *(xmedia_u32 *)private_data;
osal_atomic_inc_return(&g_msensor_mng_user_ref[dev]);
ret = msensor_mng_do_ioctl(dev, cmd, arg);
osal_atomic_dec_return(&g_msensor_mng_user_ref[dev]);
return ret;
}
static xmedia_s32 msensor_mng_open(xmedia_void *private_data)
{
xmedia_unused(private_data);
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_mng_release(xmedia_void *private_data)
{
xmedia_unused(private_data);
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_mng_freeze(osal_dev_t *dev)
{
return XMEDIA_SUCCESS;
}
static xmedia_s32 msensor_mng_restore(osal_dev_t *dev)
{
return XMEDIA_SUCCESS;
}
// todo,待实现 init 函数
// static xmedia_s32 msensor_mng_fn_init(xmedia_void *args)
// {
// xmedia_unused(args);
// return XMEDIA_SUCCESS;
// }
xmedia_s32 msensor_mng_buf_init(xmedia_s32 dev, const xmedia_msensor_attr *motion_attr,
const xmedia_msensor_buf_attr *msensor_buf_attr,
const xmedia_msensor_config *msensor_config)
{
xmedia_u32 gyro_odr;
xmedia_u32 acc_odr;
xmedia_u32 magn_odr;
xmedia_s32 ret;
if (motion_attr == XMEDIA_NULL || msensor_buf_attr == XMEDIA_NULL || msensor_config == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("input NULL\n");
return XMEDIA_FAILURE;
}
switch (motion_attr->device_mask) {
case XMEDIA_MSENSOR_DEVICE_GYRO | XMEDIA_MSENSOR_DEVICE_ACC: {
/* only for american present */
gyro_odr = msensor_config->gyro_config.odr;
acc_odr = msensor_config->acc_config.odr;
magn_odr = 0;
msensor_debug_trace("dev %d odr:gyro_odr:%d acc_odr:%d magn_odr:%d\n", dev, gyro_odr, acc_odr, magn_odr);
ret = msensor_buf_init(dev, msensor_buf_attr, gyro_odr, acc_odr, magn_odr);
break;
}
case XMEDIA_MSENSOR_DEVICE_GYRO: {
/* only for american present */
gyro_odr = msensor_config->gyro_config.odr;
acc_odr = 0;
magn_odr = 0;
msensor_debug_trace("dev %d gyro_odr:%d acc_odr:%d magn_odr:%d\n", dev, gyro_odr, acc_odr, magn_odr);
ret = msensor_buf_init(dev, msensor_buf_attr, gyro_odr, acc_odr, magn_odr);
break;
}
#if 0
case XMEDIA_MSENSOR_DEVICE_ALL: {
/* only for american present */
gyro_odr = msensor_config->gyro_config.odr;
acc_odr = msensor_config->acc_config.odr;
magn_odr = msensor_config->acc_config.odr;
msensor_debug_trace("dev %d gyro_odr:%d acc_odr:%d magn_odr:%d\n", dev, gyro_odr, acc_odr, magn_odr);
ret = msensor_buf_init(dev, msensor_buf_attr, gyro_odr, acc_odr, magn_odr);
break;
}
#endif
default: {
gyro_odr = 0;
acc_odr = 0;
magn_odr = 0;
MSENSOR_ERR_TRACE("dev %d msensor mng init buf(gyro_odr:%d acc_odr:%d magn_odr:%d) err!\n", dev, gyro_odr,
acc_odr, magn_odr);
ret = XMEDIA_FAILURE;
break;
}
}
return ret;
}
xmedia_s32 msensor_mng_buf_exit(xmedia_s32 dev)
{
return msensor_buf_exit(dev);
}
xmedia_s32 msensor_mng_get_chip_cfg(xmedia_s32 dev, xmedia_msensor_param *msensor_param)
{
if (g_msensor_mng_callback[dev].pfn_get_config_from_chip == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d null point!\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
return g_msensor_mng_callback[dev].pfn_get_config_from_chip(dev, msensor_param);
}
xmedia_s32 msensor_mng_write_data_2_buf(xmedia_s32 dev)
{
if (g_msensor_mng_callback[dev].pfn_write_data_to_buf == XMEDIA_NULL) {
MSENSOR_ERR_TRACE("dev %d nul point!\n", dev);
return XMEDIA_ERRCODE_NULL_PTR;
}
return g_msensor_mng_callback[dev].pfn_write_data_to_buf(dev);
}
xmedia_s32 msensor_mng_register_call_back(xmedia_s32 dev, const msensor_mng_callback *callback)
{
msensor_return_if_null_ptr(callback);
g_msensor_mng_callback[dev].pfn_get_config_from_chip = callback->pfn_get_config_from_chip;
g_msensor_mng_callback[dev].pfn_write_data_to_buf = callback->pfn_write_data_to_buf;
return XMEDIA_SUCCESS;
}
xmedia_void msensor_mng_unregister_call_back(xmedia_s32 dev)
{
g_msensor_mng_callback[dev].pfn_get_config_from_chip = XMEDIA_NULL;
g_msensor_mng_callback[dev].pfn_write_data_to_buf = XMEDIA_NULL;
return;
}
static struct osal_fileops g_msensor_mng_fops = {
.open = msensor_mng_open,
.unlocked_ioctl = msensor_mng_ioctl,
.release = msensor_mng_release,
};
struct osal_pmops g_msensor_mng_drv_ops = {
.pm_freeze = msensor_mng_freeze,
.pm_restore = msensor_mng_restore,
};
static xmedia_s32 msensor_mng_atomic_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_s32 i, j;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
ret = osal_atomic_init(&g_msensor_mng_user_ref[i]);
if (ret != XMEDIA_SUCCESS) {
osal_printk("atomic init failed. \n");
goto failed;
}
osal_atomic_set(&g_msensor_mng_user_ref[i], 0);
}
return XMEDIA_SUCCESS;
failed:
for (j = i - 1; j >= 0; j--) {
osal_atomic_destory(&g_msensor_mng_user_ref[j]);
}
return ret;
}
static xmedia_void msensor_mng_atomic_exit(xmedia_void)
{
xmedia_s32 i;
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
osal_atomic_destroy(&g_msensor_mng_user_ref[i]);
}
return;
}
xmedia_s32 msensor_mng_module_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_s32 i;
#ifdef CONFIG_PROC_SHOW_SUPPORT
ret = msensor_proc_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("msensor proc init failed\n");
goto FAIL0;
}
#endif
g_msensor_mng_dev = osal_createdev(UMAP_DEVNANME_MSENSOR_MNG_BASE);
if (g_msensor_mng_dev == XMEDIA_NULL) {
osal_printk("msensor: create device failed\n");
goto FAIL1;
}
g_msensor_mng_dev->fops = &g_msensor_mng_fops;
g_msensor_mng_dev->minor = UMAP_MSENSOR_MNG_MINOR_BASE;
g_msensor_mng_dev->osal_pmops = &g_msensor_mng_drv_ops;
ret = osal_registerdevice(g_msensor_mng_dev);
if (ret != XMEDIA_SUCCESS) {
osal_printk("register msensor device failed!\n");
goto FAIL2;
}
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
(xmedia_void) osal_memset(&g_mng_proc_info[i], 0, sizeof(g_mng_proc_info[i]));
}
ret = msensor_buf_lock_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("register msensor buf lock init failed!\n");
goto FAIL3;
}
ret = msensor_mng_atomic_init();
if (ret != XMEDIA_SUCCESS) {
osal_printk("register msensor device failed!\n");
goto FAIL4;
}
osal_printk("load xm_msensor_mng.ko OK!\n");
return XMEDIA_SUCCESS;
FAIL4:
msensor_buf_lock_exit();
FAIL3:
osal_deregisterdevice(g_msensor_mng_dev);
FAIL2:
osal_destroydev(g_msensor_mng_dev);
FAIL1:
#ifdef CONFIG_PROC_SHOW_SUPPORT
msensor_proc_exit();
FAIL0:
#endif
return XMEDIA_FAILURE;
}
/* if static, liteos warning */
xmedia_void msensor_mng_module_exit(xmedia_void)
{
xmedia_s32 i;
msensor_mng_atomic_exit();
msensor_buf_lock_exit();
for (i = 0; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
(xmedia_void) osal_memset(&g_mng_proc_info[i], 0, sizeof(g_mng_proc_info[i]));
}
osal_deregisterdevice(g_msensor_mng_dev);
osal_destroydev(g_msensor_mng_dev);
#ifdef CONFIG_PROC_SHOW_SUPPORT
msensor_proc_exit();
#endif
osal_printk("unload msensor_mng.ko OK!\n");
}
#ifdef MODULE
EXPORT_SYMBOL(msensor_mng_buf_init);
EXPORT_SYMBOL(msensor_mng_buf_exit);
EXPORT_SYMBOL(msensor_mng_write_data_to_buf);
EXPORT_SYMBOL(msensor_mng_register_call_back);
EXPORT_SYMBOL(msensor_mng_unregister_call_back);
module_init(msensor_mng_module_init);
module_exit(msensor_mng_module_exit);
MODULE_DESCRIPTION("msensor driver");
MODULE_LICENSE("GPL");
#else
int __init msensor_mng_driver_init(void)
{
return msensor_mng_module_init();
}
#endif
@@ -0,0 +1,158 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor_mng_proc.h"
#include <linux/kernel.h>
#include "osal.h"
#include "msensor_buf.h"
#include "msensor_exe.h"
#define MSENSOR_MNG_INFO "msensor_mng"
#define MSENSOR_MNG_VERSION_INFO "msensor_mng debug V0.0.0.1"
static xmedia_void msensor_print_proc_title(osal_proc_entry_t *s, xmedia_char *title)
{
xmedia_s32 i;
for (i = 0; i < 50; i++) {
osal_seq_printf(s, "-");
}
osal_seq_printf(s, title);
for (i = 0; i < 50; i++) {
osal_seq_printf(s, "-");
}
osal_seq_printf(s, "\n");
}
static xmedia_void msensor_proc_show_gyro(xmedia_s32 dev, osal_proc_entry_t *s, msensor_buf_info (*buf_info)[DATA_BUTT])
{
msensor_mng_proc_info *proc_info = msensor_mng_get_proc_info(dev);
if (proc_info->gyro_name[0] == 0) {
return;
}
msensor_print_proc_title(s, "gyro sensor name");
osal_seq_printf(s, "%20s\n", proc_info->gyro_name);
msensor_print_proc_title(s, "gyro sensor param");
osal_seq_printf(s, "%16s%20s%16s%16s%16s%16s%16s\n", "dev_no", "buf_addr", "buf_size",
"overflow", "data_unmatch", "overflow_id", "data_unmatch_id");
osal_seq_printf(s, "%16d", dev);
osal_seq_printf(s, "%20llx", proc_info->buf_addr[XMEDIA_MSENSOR_DATA_TYPE_GYRO]);
osal_seq_printf(s, "%16u", proc_info->buf_size[XMEDIA_MSENSOR_DATA_TYPE_GYRO]);
osal_seq_printf(s, "%16u", proc_info->buf_overflow[XMEDIA_MSENSOR_DATA_TYPE_GYRO]);
osal_seq_printf(s, "%16u", proc_info->buf_data_unmatch[XMEDIA_MSENSOR_DATA_TYPE_GYRO]);
osal_seq_printf(s, "%16d", proc_info->buf_overflow_id[XMEDIA_MSENSOR_DATA_TYPE_GYRO]);
osal_seq_printf(s, "%16d\n", proc_info->buf_data_unmatch_id[XMEDIA_MSENSOR_DATA_TYPE_GYRO]);
msensor_print_proc_title(s, "gyro sensor addr");
osal_seq_printf(s, "%10s%20s%20s", "", "start_addr", "write_addr");
osal_seq_printf(s, "\n%10s%20px%20px", "x", buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_X].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_X].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px", "y", buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_Y].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_Y].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px", "z", buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_Z].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_Z].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px", "temp", buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_TEMP].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_TEMP].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px\n", "pts", buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_PTS].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_GYRO][DATA_PTS].write_ptr);
return;
}
static xmedia_void msensor_proc_show_acc(xmedia_s32 dev, osal_proc_entry_t *s, msensor_buf_info (*buf_info)[DATA_BUTT])
{
msensor_mng_proc_info *proc_info = msensor_mng_get_proc_info(dev);
if (proc_info->accel_name[0] == 0) {
return;
}
msensor_print_proc_title(s, "acc sensor name");
osal_seq_printf(s, "%21s\n", proc_info->accel_name);
msensor_print_proc_title(s, "acc sensor param");
osal_seq_printf(s, "%16s%20s%16s%16s%16s%16s%16s\n", "dev_no", "buf_addr", "buf_size",
"overflow", "data_unmatch", "overflow_id", "data_unmatch_id");
osal_seq_printf(s, "%16d", dev);
osal_seq_printf(s, "%20llx", proc_info->buf_addr[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
osal_seq_printf(s, "%16u", proc_info->buf_size[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
osal_seq_printf(s, "%16u", proc_info->buf_overflow[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
osal_seq_printf(s, "%16u", proc_info->buf_data_unmatch[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
osal_seq_printf(s, "%16d", proc_info->buf_overflow_id[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
osal_seq_printf(s, "%16d\n", proc_info->buf_data_unmatch_id[XMEDIA_MSENSOR_DATA_TYPE_ACC]);
msensor_print_proc_title(s, "acc sensor addr");
osal_seq_printf(s, "%10s%20s%20s\n", "", "start_addr", "write_addr");
osal_seq_printf(s, "%10s%20px%20px", "x", buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_X].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_X].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px", "y", buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_Y].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_Y].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px", "z", buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_Z].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_Z].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px", "temp", buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_TEMP].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_TEMP].write_ptr);
osal_seq_printf(s, "\n%10s%20px%20px\n", "pts", buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_PTS].start_addr,
buf_info[XMEDIA_MSENSOR_DATA_TYPE_ACC][DATA_PTS].write_ptr);
return;
}
static xmedia_s32 msensor_proc_show(osal_proc_entry_t *s)
{
xmedia_s32 ret;
msensor_buf_info(*buf_info)[DATA_BUTT] = XMEDIA_NULL;
xmedia_s32 i;
osal_seq_printf(s,
"[msensor] version:[" MSENSOR_MNG_VERSION_INFO "], build time["__DATE__
", "__TIME__
"]\n");
for (i = 0 ; i < XMEDIA_MSENSOR_MAX_DEV_NUM; i++) {
if (msensor_buf_get_status(i) == XMEDIA_FALSE) {
continue;
}
ret = msensor_mng_proc_info_init(i);
if (ret != XMEDIA_SUCCESS) {
continue;
}
buf_info = (msensor_buf_info(*)[DATA_BUTT])msensor_buf_get_info(i);
msensor_proc_show_gyro(i, s, buf_info);
msensor_proc_show_acc(i, s, buf_info);
}
return 0;
}
xmedia_s32 msensor_proc_init(xmedia_void)
{
osal_proc_entry_t *msensor_entry = XMEDIA_NULL;
msensor_entry = osal_create_proc_entry(MSENSOR_MNG_INFO, XMEDIA_NULL);
if (msensor_entry == XMEDIA_NULL) {
printk("osal_create_proc_entry failed!\n");
return -1;
}
msensor_entry->read = msensor_proc_show;
msensor_entry->write = XMEDIA_NULL;
return 0;
}
void msensor_proc_exit(xmedia_void)
{
osal_remove_proc_entry(MSENSOR_MNG_INFO, XMEDIA_NULL);
return;
}
@@ -0,0 +1,22 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
MOD_NAME := xm_msensor_spi
SRCS := msensor_spi.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/osal/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/include
$(info SDK_KER_CFLAGS=$(SDK_KER_CFLAGS))
$(info SRCS=$(SRCS))
$(info SDK_DIR=$(SDK_DIR))
include $(SDK_DIR)/build/sdk_ko_rules.mk
@@ -0,0 +1,581 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#include "msensor_spi.h"
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include "osal.h"
#define xmedia_unused(x) ((xmedia_void)(x))
#define SSP_DBG_ERR KERN_ALERT
#define SSP_DBG_INFO KERN_DEBUG
#define ssp_trace(level, fmt, ...) printk(level fmt, ##__VA_ARGS__)
#define SPI_DATAWIDTH_8 0
#define DEV_NAME "ssp"
#define MAX_MSENSOR_DEV_NUM 2
#define SSP_DEV_NUM 3
#define ssp_readw(addr, ret) ((ret) = (*(volatile xmedia_u32 *)(addr)))
#define ssp_writew(addr, value) ((*(volatile xmedia_u32 *)(addr)) = (value))
#define xmedia_reg_read(addr, ret) ((ret) = (*(volatile xmedia_u32 *)(addr)))
#define xmedia_reg_write(addr, value) ((*(volatile xmedia_u32 *)(addr)) = (value))
#define SSP_BASE 0x12070000
#define SSP_SIZE 0x10000 /* 64KB */
#define CRG_BASE 0x12010000
#define CRG_SIZE 0x10000
#define SSP_CRG_OFFSET 0x01bc
//spi 管脚复用基地址,需要根据对应芯片做修改
#define XM7206_GPIO_BASE 0x100c0000 // 管脚复用基地址
#define IO1_SIZE 0x1000
#define CS_SIZE 0x4
#define SPI1_CS_BASE_ADDRS 0x12028000
static xmedia_void __iomem *g_reg_ssp_base_va = XMEDIA_NULL;
static xmedia_void __iomem *g_reg_crg_base_va = XMEDIA_NULL;
static xmedia_void __iomem *g_reg_io1_base_va = XMEDIA_NULL;
static xmedia_void __iomem *g_reg_spi1_cs_base_va = XMEDIA_NULL;
#define io_address_verify(x) ((xmedia_ulong)(xmedia_uintptr_t)g_reg_ssp_base_va + ((x) - (SSP_BASE)))
#define SSP_CRG_ADDRESS ((xmedia_ulong)(xmedia_uintptr_t)g_reg_crg_base_va + SSP_CRG_OFFSET)
#define io1_addr(offset) ((xmedia_ulong)(xmedia_uintptr_t)g_reg_io1_base_va + offset)
#define spi1_cs_addr(offset) ((xmedia_ulong)(xmedia_uintptr_t)g_reg_spi1_cs_base_va + offset)
/* SSP register definition . */
#define ssp_cr0(ssp_no) io_address_verify(SSP_BASE + 0x00 + ((ssp_no) * 0x1000))
#define ssp_cr1(ssp_no) io_address_verify(SSP_BASE + 0x04 + ((ssp_no) * 0x1000))
#define ssp_dr(ssp_no) io_address_verify(SSP_BASE + 0x08 + ((ssp_no) * 0x1000))
#define ssp_sr(ssp_no) io_address_verify(SSP_BASE + 0x0C + ((ssp_no) * 0x1000))
#define ssp_cpsr(ssp_no) io_address_verify(SSP_BASE + 0x10 + ((ssp_no) * 0x1000))
#define ssp_imsc(ssp_no) io_address_verify(SSP_BASE + 0x14 + ((ssp_no) * 0x1000))
#define ssp_ris(ssp_no) io_address_verify(SSP_BASE + 0x18 + ((ssp_no) * 0x1000))
#define ssp_mis(ssp_no) io_address_verify(SSP_BASE + 0x1C + ((ssp_no) * 0x1000))
#define ssp_icr(ssp_no) io_address_verify(SSP_BASE + 0x20 + ((ssp_no) * 0x1000))
#define ssp_dmacr(ssp_no) io_address_verify(SSP_BASE + 0x24 + ((ssp_no) * 0x1000))
#define ssp_csr(ssp_no) io_address_verify(SSP_BASE + 0x30 + ((ssp_no) * 0x1000))
static xmedia_u32 g_dev_ssp_no[MAX_MSENSOR_DEV_NUM] = {2,};
static spinlock_t g_ssp_lock[SSP_DEV_NUM];
#define ssp_spin_lock_init(ssp_no) spin_lock_init(&g_ssp_lock[ssp_no])
#define ssp_spin_lock(ssp_no, flags) spin_lock_irqsave(&g_ssp_lock[ssp_no], flags)
#define ssp_spin_unlock(ssp_no, flags) spin_unlock_irqrestore(&g_ssp_lock[ssp_no], flags)
static spinlock_t g_ssp_crg_lock;
#define ssp_crg_spin_lock_init() spin_lock_init(&g_ssp_crg_lock)
#define ssp_crg_spin_lock(flags) spin_lock_irqsave(&g_ssp_crg_lock, flags)
#define ssp_crg_spin_unlock(flags) spin_unlock_irqrestore(&g_ssp_crg_lock, flags)
static xmedia_void xmedia_ssp_clock_enable(xmedia_u32 ssp_no)
{
xmedia_u32 ret = 0;
xmedia_ulong flags;
ssp_crg_spin_lock(flags);
xmedia_reg_read(SSP_CRG_ADDRESS, ret);
ret |= 0x1 << (12 + ssp_no); /* ssp clock enable bit: 4 */
xmedia_reg_write(SSP_CRG_ADDRESS, ret);
ssp_crg_spin_unlock(flags);
return;
}
static xmedia_void xmedia_ssp_clock_disable(xmedia_u32 ssp_no)
{
xmedia_u32 ret = 0;
xmedia_ulong flags;
ssp_crg_spin_lock(flags);
xmedia_reg_read(SSP_CRG_ADDRESS, ret);
ret = ret & (~(0x1 << (12 + ssp_no))); /* ssp clock enable bit: 4 */
xmedia_reg_write(SSP_CRG_ADDRESS, ret);
ssp_crg_spin_unlock(flags);
return;
}
static xmedia_void xmedia_ssp_clock_reset(xmedia_u32 ssp_no)
{
#ifdef MSENSOR_SPI_DEBUG
xmedia_u32 ret = 0;
xmedia_ulong flags;
ssp_crg_spin_lock(flags);
xmedia_reg_read(SSP_CRG_ADDRESS, ret);
ret |= 0x1 << (16 + ssp_no); /* ssp clock reset bit: 0 */
xmedia_reg_write(SSP_CRG_ADDRESS, ret);
ssp_crg_spin_unlock(flags);
#endif
}
static xmedia_void xmedia_ssp_clock_unreset(xmedia_u32 ssp_no)
{
#ifdef MSENSOR_SPI_DEBUG
xmedia_u32 ret = 0;
xmedia_ulong flags;
ssp_crg_spin_lock(flags);
xmedia_reg_read(SSP_CRG_ADDRESS, ret);
ret = ret & (~(0x1 << (16 + ssp_no))); /* ssp clock reset bit: 0 */
xmedia_reg_write(SSP_CRG_ADDRESS, ret);
ssp_crg_spin_unlock(flags);
#endif
}
/*
* set SSP frame form routine.
*
* @param framemode: frame form
* 00: Motorola SPI frame form.
* when set the mode,need set SSPCLKOUT phase and SSPCLKOUT voltage level.
* 01: TI synchronous serial frame form
* 10: National Microwire frame form
* 11: reserved
* @param sphvalue: SSPCLKOUT phase (0/1)
* @param sp0: SSPCLKOUT voltage level (0/1)
* @param datavalue: data bit
* 0000: reserved 0001: reserved 0010: reserved 0011: 4bit data
* 0100: 5bit data 0101: 6bit data 0110:7bit data 0111: 8bit data
* 1000: 9bit data 1001: 10bit data 1010:11bit data 1011: 12bit data
* 1100: 13bit data 1101: 14bit data 1110:15bit data 1111: 16bit data
*
* @return value: 0--success; -1--error.
*/
static xmedia_s32 xmedia_ssp_set_frameform(xmedia_u32 ssp_no, xmedia_u8 framemode,
xmedia_u8 spo, xmedia_u8 sph, xmedia_u8 datawidth)
{
xmedia_u32 ret = 0;
ssp_readw(ssp_cr0(ssp_no), ret);
if (framemode > 3) { /* frame form 3 */
ssp_trace(SSP_DBG_ERR, "set framemode failed.\n");
return -1;
}
ret = (ret & 0xFFCF) | (framemode << 4); /* 4 bits */
if ((ret & 0x30) == 0) {
if (spo > 1) {
ssp_trace(SSP_DBG_ERR, "set spo failed.\n");
return -1;
}
if (sph > 1) {
ssp_trace(SSP_DBG_ERR, "set sph failed.\n");
return -1;
}
ret = (ret & 0xFF3F) | (sph << 7) | (spo << 6); /* sph 7 bits, spo 6 bits */
}
if ((datawidth > 16) || (datawidth < 4)) { /* datawidth between 4 bits and 16 bits */
ssp_trace(SSP_DBG_ERR, "set datawidth parameter err.\n");
return -1;
}
ret = (ret & 0xFFF0) | (datawidth - 1);
ssp_writew(ssp_cr0(ssp_no), ret);
return 0;
}
/*
* set SSP serial clock rate routine.
*
* @param scr: scr value.(0-255,usually it is 0)
* @param cpsdvsr: clock prescale divisor.(2-254 even)
*
* @return value: 0--success; -1--error.
*/
static xmedia_s32 xmedia_ssp_set_serialclock(xmedia_u32 ssp_no, xmedia_u8 scr, xmedia_u8 cpsdvsr)
{
xmedia_u32 ret = 0;
ssp_readw(ssp_cr0(ssp_no), ret);
ret = (ret & 0xFF) | (scr << 8); /* 8 bits */
ssp_writew(ssp_cr0(ssp_no), ret);
if ((cpsdvsr & 0x1)) {
ssp_trace(SSP_DBG_ERR, "set cpsdvsr failed.\n");
return -1;
}
ssp_writew(ssp_cpsr(ssp_no), cpsdvsr);
return 0;
}
static xmedia_s32 xmedia_ssp_big_end_set(xmedia_u32 ssp_no)
{
xmedia_u32 ret = 0;
ssp_readw(ssp_cr1(ssp_no), ret);
ret = (ret & 0xFF) & 0xEF;
ssp_writew(ssp_cr1(ssp_no), ret);
return 0;
}
static xmedia_s32 xmedia_ssp_alt_mode_set(xmedia_u32 ssp_no, xmedia_s32 enable)
{
xmedia_u32 ret = 0;
ssp_readw(ssp_cr1(ssp_no), ret);
if (enable == 0) {
ret = ret & (~0x40);
} else {
ret = (ret & 0xFF) | 0x40;
}
ssp_writew(ssp_cr1(ssp_no), ret);
return 0;
}
static xmedia_u32 xmedia_ssp_is_fifo_busy(xmedia_u32 ssp_no)
{
xmedia_u32 ret = 0;
ssp_readw(ssp_sr(ssp_no), ret);
return (ret & 0x10);
}
static xmedia_u32 xmedia_ssp_is_fifo_empty(xmedia_u32 ssp_no, xmedia_s32 send)
{
xmedia_u32 ret = 0;
ssp_readw(ssp_sr(ssp_no), ret);
if (send != 0) {
if ((ret & 0x1) == 0x1) { /* send fifo */
return 0;
} else {
return 1;
}
} else {
if ((ret & 0x4) == 0x4) { /* receive fifo */
return 0;
} else {
return 1;
}
}
}
/* fsspclkout is fsspclk / (cpsdvsr * (1 + scr)) */
static xmedia_s32 xmedia_ssp_init_cfg(xmedia_u32 ssp_no)
{
const xmedia_u8 framemode = 0;
const xmedia_u8 spo = 1;
const xmedia_u8 sph = 1;
#if SPI_DATAWIDTH_8
const xmedia_u8 datawidth = 8;
#else
const xmedia_u8 datawidth = 16;
#endif
const xmedia_u8 scr = 29; /* scr 4 */
const xmedia_u8 cpsdvsr = 2; /* cpsdvsr 2 */
xmedia_ssp_set_frameform(ssp_no, framemode, spo, sph, datawidth);
xmedia_ssp_set_serialclock(ssp_no, scr, cpsdvsr);
xmedia_ssp_big_end_set(ssp_no);
/* altasens mode, which CS won't be pull high between 16bit data transfer */
xmedia_ssp_alt_mode_set(ssp_no, 0);
return 0;
}
static xmedia_void spi_enable(xmedia_u32 ssp_no)
{
xmedia_u32 ret = 0;
xmedia_ssp_clock_enable(ssp_no);
xmedia_ssp_clock_unreset(ssp_no);
/* little endian */
xmedia_reg_read(ssp_cr1(ssp_no), ret);
ret = (ret & 0xff) | 0x2;
xmedia_reg_write(ssp_cr1(ssp_no), ret); /* 0x2 */
xmedia_ssp_init_cfg(ssp_no);
return;
}
static xmedia_void spi_disable(xmedia_u32 ssp_no)
{
xmedia_u32 ret = 0;
xmedia_reg_read(ssp_cr1(ssp_no), ret);
ret = (ret & 0xff) & (~0x2);
xmedia_reg_write(ssp_cr1(ssp_no), ret); /* 0x0 */
xmedia_ssp_clock_reset(ssp_no);
xmedia_ssp_clock_disable(ssp_no);
return;
}
xmedia_u16 xmedia_msensor_ssp_read_alt(xmedia_s32 dev, xmedia_u8 reg_addr,
xmedia_u8 *reg_data, xmedia_u32 cnt, xmedia_bool fifo_mode)
{
xmedia_u32 ret = 0;
xmedia_ulong flags;
xmedia_s32 ssp_no = 0;
#if SPI_DATAWIDTH_8
xmedia_u8 buf[2] = { 0 }; /* 2 buf */
#else
xmedia_u16 buf_16;
#endif
xmedia_u32 i;
ssp_no = g_dev_ssp_no[dev];
ssp_spin_lock(ssp_no, flags);
spi_enable(ssp_no);
for (i = 0; i < cnt; i++) {
#if SPI_DATAWIDTH_8
if (fifo_mode != XMEDIA_FALSE) {
buf[0] = reg_addr | 0x80;
buf[1] = 0x0;
} else {
buf[0] = (reg_addr + i) | 0x80;
buf[1] = 0x0;
}
ssp_writew(ssp_dr(ssp_no), buf[0]);
ssp_writew(ssp_dr(ssp_no), buf[1]);
#else
if (fifo_mode != XMEDIA_FALSE) {
buf_16 = (reg_addr | 0x80) << 8; /* 8 bit */
} else {
buf_16 = ((reg_addr + i) | 0x80) << 8; /* 8 bit */
}
ssp_writew(ssp_dr(ssp_no), buf_16);
#endif
while (xmedia_ssp_is_fifo_busy(ssp_no) != 0) {
}
while (xmedia_ssp_is_fifo_empty(ssp_no, 1) != 0) {
}
while (xmedia_ssp_is_fifo_empty(ssp_no, 0) != 0) {
}
while (xmedia_ssp_is_fifo_empty(ssp_no, 0) == 0) {
ssp_readw(ssp_dr(ssp_no), ret);
}
reg_data[i] = ret & 0xff;
}
spi_disable(ssp_no);
ssp_spin_unlock(ssp_no, flags);
return 0;
}
xmedia_s32 xmedia_msensor_ssp_write_alt(xmedia_s32 dev, xmedia_u8 reg_addr, const xmedia_u8 *data)
{
xmedia_u32 ret;
xmedia_s32 ssp_no = 0;
xmedia_ulong flags;
#if SPI_DATAWIDTH_8
xmedia_u8 buf[2] = { 0 }; /* 2 buf */
#else
xmedia_u16 buf_16;
#endif
ssp_no = g_dev_ssp_no[dev];
ssp_spin_lock(ssp_no, flags);
spi_enable(ssp_no);
#if SPI_DATAWIDTH_8
buf[0] = reg_addr & (~0x80);
buf[1] = *data;
ssp_writew(ssp_dr(ssp_no), buf[0]);
ssp_writew(ssp_dr(ssp_no), buf[1]);
#else
buf_16 = (reg_addr & (~0x80)) << 8; /* 8 bit */
buf_16 = buf_16 | *data;
ssp_writew(ssp_dr(ssp_no), buf_16);
#endif
while (xmedia_ssp_is_fifo_busy(ssp_no) != 0) {
}
while (xmedia_ssp_is_fifo_empty(ssp_no, 1) != 0) {
}
while (xmedia_ssp_is_fifo_empty(ssp_no, 0) != 0) {
}
while (xmedia_ssp_is_fifo_empty(ssp_no, 0) == 0) {
ssp_readw(ssp_dr(ssp_no), ret);
}
xmedia_unused(ret);
spi_disable(ssp_no);
ssp_spin_unlock(ssp_no, flags);
return 0;
}
// 根据实际使用gpio 正确复用spi 功能管脚
static xmedia_void spi_pin_muxing(xmedia_void)
{
// xm7206 默认使用一路spi spi2
xmedia_reg_write(io1_addr(0x28), 0x1204); /* SPI2_SCLK gpio4_7 打开上拉 */
xmedia_reg_write(io1_addr(0x2c), 0x1004); /* SPI2_SDO gpio5_0 */
xmedia_reg_write(io1_addr(0x30), 0x1004); /* SPI2_CSN gpio5_1 */
xmedia_reg_write(io1_addr(0x34), 0x1004); /* SPI2_SDI gpio5_2 */
ssp_trace(SSP_DBG_INFO, "use spi12\n");
}
static struct file_operations g_ssp_fops = {
.owner = THIS_MODULE,
};
static struct miscdevice g_ssp_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEV_NAME,
.fops = &g_ssp_fops,
};
xmedia_s32 xmedia_msensor_spi_base_addr(xmedia_u32 *base_addr)
{
*base_addr = XM7206_GPIO_BASE;
return XMEDIA_SUCCESS;
}
/*
* initializes SSP interface routine.
* @return value:0--success.
*/
static xmedia_s32 __init xmedia_msensor_ssp_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_u32 ssp_no;
xmedia_u32 spi_base_addr = 0x12345678;
g_reg_ssp_base_va = ioremap((unsigned long)SSP_BASE, (unsigned long)(SSP_SIZE * SSP_DEV_NUM));
if (g_reg_ssp_base_va == XMEDIA_NULL) {
ssp_trace(SSP_DBG_ERR, "ioremap ssp base failed!\n");
return -ENOMEM;
}
g_reg_crg_base_va = ioremap((unsigned long)CRG_BASE, (unsigned long)(CRG_SIZE));
if (g_reg_crg_base_va == XMEDIA_NULL) {
ssp_trace(SSP_DBG_ERR, "ioremap ssp crg failed!\n");
ret = -ENOMEM;
goto err0;
}
ret = xmedia_msensor_spi_base_addr(&spi_base_addr);
if (ret != XMEDIA_SUCCESS) {
goto err1;
}
g_reg_io1_base_va = ioremap((unsigned long)spi_base_addr, (unsigned long)(IO1_SIZE));
if (g_reg_io1_base_va == XMEDIA_NULL) {
ssp_trace(SSP_DBG_ERR, "ioremap ssp io failed!\n");
ret = -ENOMEM;
goto err1;
}
g_reg_spi1_cs_base_va = ioremap((unsigned long)SPI1_CS_BASE_ADDRS, (unsigned long)(CS_SIZE));
if (g_reg_spi1_cs_base_va == XMEDIA_NULL) {
ssp_trace(SSP_DBG_ERR, "ioremap ssp gpio failed!\n");
ret = -ENOMEM;
goto err2;
}
spi_pin_muxing();
ret = misc_register(&g_ssp_dev);
if (ret != XMEDIA_SUCCESS) {
ssp_trace(SSP_DBG_ERR, "register ssp_0 device failed!");
ret = XMEDIA_FAILURE;
goto err3;
}
for (ssp_no = 0; ssp_no < SSP_DEV_NUM; ssp_no++) {
ssp_spin_lock_init(ssp_no);
}
ssp_crg_spin_lock_init();
ssp_trace(SSP_DBG_INFO, "kernel: ssp initial ok!\n");
printk(KERN_INFO "load xm_msensor_spi.ko OK!\n");
return 0;
err3:
iounmap((xmedia_void *)g_reg_spi1_cs_base_va);
g_reg_spi1_cs_base_va = XMEDIA_NULL;
err2:
iounmap((xmedia_void *)g_reg_io1_base_va);
g_reg_io1_base_va = XMEDIA_NULL;
err1:
iounmap((xmedia_void *)g_reg_crg_base_va);
g_reg_crg_base_va = XMEDIA_NULL;
err0:
iounmap((xmedia_void *)g_reg_ssp_base_va);
g_reg_ssp_base_va = XMEDIA_NULL;
return ret;
}
static xmedia_void __exit xmedia_msensor_ssp_exit(xmedia_void)
{
misc_deregister(&g_ssp_dev);
iounmap((xmedia_void *)g_reg_spi1_cs_base_va);
g_reg_spi1_cs_base_va = XMEDIA_NULL;
iounmap((xmedia_void *)g_reg_io1_base_va);
g_reg_io1_base_va = XMEDIA_NULL;
iounmap((xmedia_void *)g_reg_crg_base_va);
g_reg_crg_base_va = XMEDIA_NULL;
iounmap((xmedia_void *)g_reg_ssp_base_va);
g_reg_ssp_base_va = XMEDIA_NULL;
printk(KERN_INFO "unload xm_msensor_spi.ko OK!\n");
}
#ifdef MODULE
EXPORT_SYMBOL(xmedia_msensor_ssp_read_alt);
EXPORT_SYMBOL(xmedia_msensor_ssp_write_alt);
module_init(xmedia_msensor_ssp_init);
module_exit(xmedia_msensor_ssp_exit);
MODULE_DESCRIPTION("ssp driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("otlicon");
#else
int __init msensor_spi_driver_init(void)
{
return xmedia_msensor_ssp_init();
}
#endif
@@ -0,0 +1,40 @@
/*
* Copyright (c); XMEDIA. All rights reserved.
*/
#ifndef __MSENSOR_SPI_H__
#define __MSENSOR_SPI_H__
#include "xmedia_type.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#define SSP_READ_ALT 0x1
#define SSP_WRITE_ALT 0X3
typedef struct {
xmedia_u32 spi_no;
xmedia_u8 dev_addr;
xmedia_u32 dev_byte_num;
xmedia_u32 reg_addr;
xmedia_u32 addr_byte_num;
xmedia_u32 data;
xmedia_u32 data_byte_num;
} spi_data;
xmedia_s32 xmedia_msensor_ssp_write_alt(xmedia_s32 dev, xmedia_u8 reg_addr, const xmedia_u8 *data);
xmedia_u16 xmedia_msensor_ssp_read_alt(xmedia_s32 dev, xmedia_u8 reg_addr,
xmedia_u8 *reg_data, xmedia_u32 cnt, xmedia_bool fifo_mode);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* end of #ifdef __cplusplus */
#endif
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef DRV_DEV_DEFINES_H
#define DRV_DEV_DEFINES_H
#include "xmedia_type.h"
#include "common.h"
#define UMAP_DEV_NUM 64
#define UMAP_NAME_MAXLEN 32
#define UMAP_VI_MINOR_BASE 0
#define UMAP_VO_MINOR_BASE 1
#define UMAP_VENC_MINOR_BASE 2
#define UMAP_VDEC_MINOR_BASE 3
#define UMAP_JPEGD_MINOR_BASE 4
#define UMAP_AI_MINOR_BASE 5
#define UMAP_AO_MINOR_BASE 6
#define UMAP_GRP_MINOR_BASE 7
#define UMAP_SYS_MINOR_BASE 8
#define UMAP_VB_MINOR_BASE 9
#define UMAP_VPSS_MINOR_BASE 10
#define UMAP_AIO_MINOR_BASE 11
#define UMAP_LOG_MINOR_BASE 12
#define UMAP_AENC_MINOR_BASE 13
#define UMAP_ADEC_MINOR_BASE 14
#define UMAP_MST_LOG_MINOR_BASE 15
#define UMAP_RGN_MINOR_BASE 16
#define UMAP_IVE_MINOR_BASE 17
#define UMAP_HDMI_MINOR_BASE 18
#define UMAP_VGS_MINOR_BASE 19
#define UMAP_ISP_MINOR_BASE 20
#define UMAP_RC_MINOR_BASE 21
#define UMAP_H264E_MINOR_BASE 22
#define UMAP_H265E_MINOR_BASE 23
#define UMAP_JPEGE_MINOR_BASE 24
#define UMAP_CHNL_MINOR_BASE 25
#define UMAP_MPEG4E_MINOR_BASE 26
#define UMAP_GDC_MINOR_BASE 27
#define UMAP_PCIV_MINOR_BASE 28
#define UMAP_PCIVFMW_MINOR_BASE 29
#define UMAP_FD_MINOR_BASE 30
#define UMAP_ACODEC_MINOR_BASE 31
#define UMAP_VPU_MINOR_BASE 32
#define UMAP_AVS_MINOR_BASE 33
#define UMAP_DIS_MINOR_BASE 34
#define UMAP_SVP_MINOR_BASE 35
#define UMAP_PRORES_MINOR_BASE 36
#define UMAP_SVP_NNIE_MINOR_BASE 37
#define UMAP_SVP_DSP_MINOR_BASE 38
#define UMAP_DPU_RECT_MINOR_BASE 39
#define UMAP_DPU_MATCH_MINOR_BASE 40
#define UMAP_PM_MINOR_BASE 41
#define UMAP_GYRODIS_MINOR_BASE 42
#define UMAP_PDM_MINOR_BASE 43
#define UMAP_TDE_MINOR_BASE 44
#define UMAP_FB_MINOR_BASE 45
#define UMAP_MCF_MINOR_BASE 46
#define UMAP_ACOMM_MINOR_BASE 47
#define UMAP_NPU_MINOR_BASE 48
#define UMAP_DDR_OST_QOS_MINOR_BASE 49
#define UMAP_CIPHER_MINOR_BASE 50
#define UMAP_OTP_MINOR_BASE 51
#define UMAP_MISC_MINOR_BASE 52
#define UMAP_GET_CHN(f) (*((xmedia_u32*)(f)))
#define UMAP_SET_CHN(f, chn) (*((xmedia_u32*)(f)) = (chn))
#define UMAP_NAME "umap"
#define UMAP_NAME_VIDEO UMAP_NAME "/video/"
#define UMAP_NAME_AUDIO UMAP_NAME "/audio/"
#define UMAP_DEVNAME_SYSCTL MPP_MOD_SYS
#define UMAP_DEVNAME_LOG_BASE MPP_MOD_LOG
#define UMAP_DEVNAME_MST_LOG_BASE MPP_MOD_MST_LOG
#define UMAP_DEVNAME_VI_BASE MPP_MOD_VI
#define UMAP_DEVNAME_VO_BASE MPP_MOD_VO
#define UMAP_DEVNAME_FB_BASE MPP_MOD_FB
#define UMAP_DEVNAME_AVS_BASE MPP_MOD_AVS
#define UMAP_DEVNAME_VENC_BASE MPP_MOD_VENC
#define UMAP_DEVNAME_VDEC_BASE MPP_MOD_VDEC
#define UMAP_DEVNAME_JPEGD_BASE MPP_MOD_JPEGD
#define UMAP_DEVNAME_DSU_BASE MPP_MOD_DSU
#define UMAP_DEVNAME_VB_BASE MPP_MOD_VB
#define UMAP_DEVNAME_VPSS_BASE MPP_MOD_VPSS
#define UMAP_DEVNAME_GRP_BASE MPP_MOD_GRP
#define UMAP_DEVNAME_RGN_BASE MPP_MOD_RGN
#define UMAP_DEVNAME_IVE_BASE MPP_MOD_IVE
#define UMAP_DEVNAME_FD_BASE MPP_MOD_FD
#define UMAP_DEVNAME_SVP_BASE MPP_MOD_SVP
#define UMAP_DEVNAME_SVP_NNIE_BASE MPP_MOD_SVP_NNIE
#define UMAP_DEVNAME_SVP_DSP_BASE MPP_MOD_SVP_DSP
#define UMAP_DEVNAME_DPU_RECT_BASE MPP_MOD_DPU_RECT
#define UMAP_DEVNAME_DPU_MATCH_BASE MPP_MOD_DPU_MATCH
#define UMAP_DEVNAME_ACODEC_BASE MPP_MOD_ACODEC
#define UMAP_DEVNAME_AIO_BASE MPP_MOD_AIO
#define UMAP_DEVNAME_AI_BASE MPP_MOD_AI
#define UMAP_DEVNAME_AO_BASE MPP_MOD_AO
#define UMAP_DEVNAME_AENC_BASE MPP_MOD_AENC
#define UMAP_DEVNAME_ADEC_BASE MPP_MOD_ADEC
#define UMAP_DEVNAME_ACOMM_BASE MPP_MOD_ACOMM
#define UMAP_DEVNAME_HDMI_BASE MPP_MOD_HDMI
#define UMAP_DEVNAME_VGS_BASE MPP_MOD_VGS
#define UMAP_DEVNAME_TDE_BASE MPP_MOD_TDE
#define UMAP_DEVNAME_GDC_BASE MPP_MOD_GDC
#define UMAP_DEVNAME_H264E_BASE MPP_MOD_H264E
#define UMAP_DEVNAME_H265E_BASE MPP_MOD_H265E
#define UMAP_DEVNAME_JPEGE_BASE MPP_MOD_JPEGE
#define UMAP_DEVNAME_MPEG4E_BASE MPP_MOD_MPEG4E
#define UMAP_DEVNAME_CHNL_BASE MPP_MOD_CHNL
#define UMAP_DEVNAME_RC_BASE MPP_MOD_RC
#define UMAP_DEVNAME_MPEG4E_BASE MPP_MOD_MPEG4E
#define UMAP_DEVNAME_PRORES_BASE MPP_MOD_PRORES
#define UMAP_DEVNAME_PCIV_BASE MPP_MOD_PCIV
#define UMAP_DEVNAME_PCIVFMW_BASE MPP_MOD_PCIVFMW
#define UMAP_DEVNAME_VPU_BASE MPP_MOD_VPU
#define UMAP_DEVNAME_DIS_BASE MPP_MOD_DIS
#define UMAP_DEVNAME_PM_BASE MPP_MOD_PM
#define UMAP_DEVNAME_GYRODIS_BASE MPP_MOD_GYRODIS
#define UMAP_DEVNAME_MCF_BASE MPP_MOD_MCF
#define UMAP_DEVNAME_NPU_BASE MPP_MOD_NPU
#define UMAP_DEVNAME_DDR_OST_QOS_BASE MPP_MOD_DDR_OST_QOS
#define UMAP_DEVNAME_CIPHER_BASE MPP_MOD_CIPHER
#define UMAP_DEVNAME_OTP_BASE MPP_MOD_OTP
#define UMAP_DEVNAME_MISC_BASE MPP_MOD_MISC
#endif /* DRV_DEV_DEFINES_H */
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __DRV_EXPORT_H__
#define __DRV_EXPORT_H__
#include "xmedia_region.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
//rgn
xmedia_s32 export_rgn_init(xmedia_void);
xmedia_void export_rgn_exit(xmedia_void);
xmedia_s32 export_rgn_create(xmedia_u32 handle, const xmedia_rgn_attr *rgn_attr);
xmedia_s32 export_rgn_destroy(xmedia_u32 handle);
xmedia_s32 export_rgn_get_attr(xmedia_u32 handle, xmedia_rgn_attr *rgn_attr);
xmedia_s32 export_rgn_set_attr(xmedia_u32 handle, const xmedia_rgn_attr *rgn_attr);
xmedia_s32 export_rgn_attach_to_chn(xmedia_u32 handle, const xmedia_chn_info *chn, const xmedia_rgn_chn_attr *chn_attr);
xmedia_s32 export_rgn_detach_from_chn(xmedia_u32 handle, const xmedia_chn_info *chn);
xmedia_s32 export_rgn_get_display_attr(xmedia_u32 handle, const xmedia_chn_info *chn, xmedia_rgn_chn_attr *chn_attr);
xmedia_s32 export_rgn_set_display_attr(xmedia_u32 handle, const xmedia_chn_info *chn, const xmedia_rgn_chn_attr *chn_attr);
xmedia_s32 export_rgn_get_canvas_info(xmedia_u32 handle, xmedia_rgn_canvas_info *canvas_info);
xmedia_s32 export_rgn_update_canvas (xmedia_u32 handle);
xmedia_s32 export_rgn_batch_begin(xmedia_u32 *grp, xmedia_u32 handle_num, const xmedia_u32 handle[]);
xmedia_s32 export_rgn_batch_end(xmedia_u32 grp);
//isp
xmedia_s32 export_isp_suspend_sensor(xmedia_u32 pipe);
xmedia_s32 export_isp_resume_sensor(xmedia_u32 pipe);
//vi
xmedia_void export_vi_register_misc_aov_callback(xmedia_s32 (*misc_aov_callback)(xmedia_s32 pipe));
xmedia_bool export_vi_check_busy(xmedia_void);
//vpss
xmedia_bool export_vpss_check_busy(xmedia_void);
//venc
xmedia_bool export_venc_check_busy(xmedia_void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __DRV_EXPORT_H__ */
+26
View File
@@ -0,0 +1,26 @@
#ifndef __DRV_ISP_EXPORT_H__
#define __DRV_ISP_EXPORT_H__
#include "xmedia_type.h"
#include "xmedia_isp.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
xmedia_s32 (*pfn_i2c_write)(xmedia_s8 i2c_dev, xmedia_u32 slave_addr, xmedia_u32 reg_addr,
xmedia_u32 reg_addr_byte_num, xmedia_u32 data, xmedia_u32 data_byte_num);
xmedia_s32 (*pfn_i2c_read)(xmedia_s8 i2c_dev, xmedia_u32 slave_addr, xmedia_u32 reg_addr,
xmedia_u32 reg_addr_byte_num, xmedia_u32 *data, xmedia_u32 data_byte_num);
} isp_i2c_callback;
xmedia_s32 drv_isp_set_mclk(xmedia_u32 clk_chn, xmedia_bool enable, xmedia_sensor_clock_freq clk);
xmedia_s32 drv_isp_register_i2c(isp_i2c_callback *i2c_callback);
#ifdef __cplusplus
}
#endif
#endif // __DRV_ISP_EXPORT_H__
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef DRV_LOG_H
#define DRV_LOG_H
#include "xmedia_type.h"
#ifdef __cplusplus
extern "C" {
#endif
xmedia_s32 drv_log_mod_init(xmedia_u32 buf_len);
xmedia_void drv_log_mod_exit(xmedia_void);
xmedia_s32 drv_log_write(xmedia_s32 level, xmedia_u32 mod_id, const xmedia_char *fmt, ...) __attribute__((format(printf,3,4)));
xmedia_s32 drv_log_check_level(xmedia_s32 level, xmedia_u32 mod_id);
xmedia_char *drv_get_module_name(xmedia_u32 mod_id);
#ifdef __cplusplus
}
#endif
#endif
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef DRV_TYPE_IOCTL_H
#define DRV_TYPE_IOCTL_H
#define IOC_TYPE_VI 'I'
#define IOC_TYPE_VOU 'O'
#define IOC_TYPE_VENC 'E'
#define IOC_TYPE_VDEC 'D'
#define IOC_TYPE_AENC 'A'
#define IOC_TYPE_ADEC 'H'
#define IOC_TYPE_AI 'Z'
#define IOC_TYPE_AO 'X'
#define IOC_TYPE_AIO 'S'
#define IOC_TYPE_SYS 'Y'
#define IOC_TYPE_VB 'B'
#define IOC_TYPE_LOG 'L'
#define IOC_TYPE_DDR_OST_QOS 'K'
#define IOC_TYPE_VPSS 'P'
#define IOC_TYPE_RGN 'R'
#define IOC_TYPE_IVE 'F'
#define IOC_TYPE_VGS 'J'
#define IOC_TYPE_GDC 'N'
#define IOC_TYPE_ISP 'M'
#define IOC_TYPE_TDE 'T'
#define IOC_TYPE_MCF 'C'
#define IOC_TYPE_ACOMM 'S'
#define IOC_TYPE_IR 'U'
#define IOC_TYPE_LSADC 'G'
#define IOC_TYPE_OTP 'Q'
#define IOC_TYPE_MISC 'V'
#endif /* DRV_TYPE_IOCTL_H */
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __MMZ_H__
#define __MMZ_H__
#include <linux/types.h>
unsigned long long mmz_alloc(const char *mmz_name, const char *buf_name, unsigned long size);
void mmz_free(unsigned long long phy_addr);
void *mmz_map(unsigned long long phy_addr, unsigned long size, bool cached);
void mmz_unmap(void *vir_addr);
int mmz_check_phyaddr(unsigned long long phy_addr, unsigned long len);
int mmz_flush_cache(unsigned long phy_addr, void *kvirt, unsigned long length);
#endif
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _VERSION_H_
#define _VERSION_H_
#include <linux/types.h>
#include "xmedia_type.h"
#include "osal.h"
#ifdef __cplusplus
extern "C" {
#endif
#if (defined SDK_VERSION_RELEASE)
#define VERSION_FORMAT(buff,module,module_version,ext_info) \
osal_sprintf(buff,"Version:[%s %s], [%s %s %s], %s, Build Time[%s %s]",\
VERSION_MAJOR, VERSION_MINOR, \
module,module_version,ext_info,"Release",__DATE__,__TIME__)
#elif (defined SDK_VERSION_DEBUG)
#define VERSION_FORMAT(buff,module,module_version,ext_info) \
osal_sprintf(buff,"Version:[%s %s], [%s %s %s], %s, Build Time[%s %s]",\
VERSION_MAJOR, VERSION_MINOR, \
module,module_version,ext_info,"Debug",__DATE__,__TIME__)
#else
#warning "version type is invalid !!!"
#define VERSION_FORMAT(buff,module,module_version,ext_info) \
osal_sprintf(buff,"Version:[%s %s], [%s %s %s], %s, Build Time[%s %s]",\
VERSION_MAJOR, VERSION_MINOR, \
module,module_version,ext_info,"Invalid",__DATE__,__TIME__)
#endif
#ifdef __cplusplus
}
#endif
#endif
+19
View File
@@ -0,0 +1,19 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
MOD_NAME := xm_drv_init
SRCS := xmedia_drv_init.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include \
-I$(GMP_DIR)/drv/include \
-I$(GMP_DIR)/drv/osal/include
include $(SDK_DIR)/build/sdk_ko_rules.mk
+90
View File
@@ -0,0 +1,90 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/version.h>
#include <linux/of_platform.h>
#include "common.h"
#include "osal.h"
#ifndef MODULE
extern int __init osal_driver_init(void);
extern int __init common_driver_init(void);
extern int __init pmoc_driver_init(void);
extern int __init tde_driver_init(void);
extern int __init vgs_driver_init(void);
extern int __init rgn_driver_init(void);
extern int __init isp_driver_init(void);
extern int __init vpss_driver_init(void);
extern int __init vi_driver_init(void);
extern int __init chnl_driver_init(void);
extern int __init vedu_driver_init(void);
extern int __init rc_driver_init(void);
extern int __init jpege_driver_init(void);
extern int __init h264e_driver_init(void);
extern int __init h265e_driver_init(void);
extern int __init venc_driver_init(void);
extern int __init vo_driver_init(void);
extern int __init gfbg_driver_init(void);
extern int __init cipher_driver_init(void);
extern int __init acomm_driver_init(void);
extern int __init aiao_driver_init(void);
extern int __init ao_driver_init(void);
extern int __init ai_driver_init(void);
extern int __init aenc_driver_init(void);
extern int __init adec_driver_init(void);
extern int __init npu_driver_init(void);
extern int __init ir_driver_init(void);
extern int __init adc_driver_init(void);
extern int __init ive_driver_init(void);
extern int __init misc_driver_init(void);
static int __init xmedia_driver_init(void)
{
osal_driver_init();
common_driver_init();
pmoc_driver_init();
vgs_driver_init();
tde_driver_init();
rgn_driver_init();
isp_driver_init();
vpss_driver_init();
npu_driver_init();
ive_driver_init();
vi_driver_init();
//misc_driver_init();
chnl_driver_init();
vedu_driver_init();
rc_driver_init();
jpege_driver_init();
h264e_driver_init();
h265e_driver_init();
venc_driver_init();
vo_driver_init();
gfbg_driver_init();
cipher_driver_init();
acomm_driver_init();
aiao_driver_init();
ao_driver_init();
ai_driver_init();
aenc_driver_init();
adec_driver_init();
/*IR_IN confilicts with SDIO_CARD_DETECT pin function,
SDIO_CARD_DETECT function is retained by default.*/
//ir_driver_init();
//adc_driver_init();
return 0;
}
late_initcall(xmedia_driver_init);
MODULE_LICENSE("GPL");
#endif
+22
View File
@@ -0,0 +1,22 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
include $(SDK_DIR)/build/version.mk
ISP_DIR := $(GMP_DIR)/drv/isp
MOD_NAME := xm_isp_adp
SRCS :=
SRCS += adp_isp.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/include
include $(SDK_DIR)/build/sdk_ko_rules.mk
+65
View File
@@ -0,0 +1,65 @@
#include <linux/export.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "xmedia_type.h"
#include "xmedia_errcode.h"
#include "drv_isp_export.h"
#include "adp_isp.h"
typedef struct {
xmedia_u32 sensor_num;
xmedia_u32 clk_chn;
} adp_isp_cfg;
static adp_isp_cfg g_cfg[] = {
{ 0, 0 },
};
xmedia_s32 adp_isp_set_mclk(xmedia_u32 sensor_num, xmedia_bool enable, xmedia_sensor_clock_freq clk)
{
xmedia_s32 i;
xmedia_s32 num = sizeof(g_cfg) / sizeof(adp_isp_cfg);
for (i = 0; i < num; i++) {
if (g_cfg[i].sensor_num == sensor_num) {
return drv_isp_set_mclk(g_cfg[i].clk_chn, enable, clk);
}
}
return XMEDIA_ERRCODE_INVALID_PARAM;
}
EXPORT_SYMBOL(adp_isp_set_mclk);
xmedia_s32 adp_isp_set_i2c(xmedia_u32 sensor_num, xmedia_sensor_bus_type bus_type, adp_isp_i2c_callback *i2c_callback)
{
isp_i2c_callback i2c_cb = { 0 };
if (i2c_callback == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
i2c_cb.pfn_i2c_write = i2c_callback->pfn_i2c_write;
return drv_isp_register_i2c(&i2c_cb);
}
EXPORT_SYMBOL(adp_isp_set_i2c);
static int __init adp_isp_init(void)
{
return 0;
}
module_init(adp_isp_init);
static void __exit adp_isp_exit(void)
{
return;
}
module_exit(adp_isp_exit);
MODULE_LICENSE("GPL");
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __ADP_ISP_H__
#define __ADP_ISP_H__
#include "xmedia_type.h"
#include "xmedia_isp.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef struct {
xmedia_s32 (*pfn_i2c_write)(xmedia_s8 i2c_dev, xmedia_u32 slave_addr, xmedia_u32 reg_addr,
xmedia_u32 reg_addr_byte_num, xmedia_u32 data, xmedia_u32 data_byte_num);
} adp_isp_i2c_callback;
xmedia_s32 adp_isp_set_mclk(xmedia_u32 sensor_num, xmedia_bool enable, xmedia_sensor_clock_freq clk);
xmedia_s32 adp_isp_set_i2c(xmedia_u32 sensor_num, xmedia_sensor_bus_type bus_type, adp_isp_i2c_callback *i2c_callback);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // __ADP_ISP_H__
+25
View File
@@ -0,0 +1,25 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
MOD_NAME := xm_lsadc
SRCS := adc.c
SRCS += adc_init.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include \
-I$(GMP_DIR)/drv/osal/include \
-I$(GMP_DIR)/drv/include
SDK_KER_CFLAGS += -DUSER_BIT_32 -DKERNEL_BIT_32 -Wno-date-time -D_GNU_SOURCE
include $(SDK_DIR)/build/sdk_ko_rules.mk
+447
View File
@@ -0,0 +1,447 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/types.h>
#include "adc.h"
#ifndef NULL
#define NULL ((xmedia_void *)0)
#endif
#define lsadc_print(fmt, ...) osal_printk("Func:%s, Line:%d, "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
//#define USE_LSADC_CHANNEL_0
//#define ENABLE_ADC_IRQ
#define LSADC_IRQ_ID 37
#define LSADC_BASE_ADDR 0x120a0000
#define LSADC_ADDR_OFFSET(x) (LSADC_BASE_ADDR+(x))
#define LSADC_CRG_ADDR 0x120101BC
#define LSADC_CONFIG 0x00
#define LSADC_GLITCH 0x04
#define LSADC_TIMESCAN 0x08
#define LSADC_PD_TD 0x0C
#define LSADC_INTEN 0x10
#define LSADC_INTSTATUS 0x14
#define LSADC_INTCLR 0x18
#define LSADC_START 0x1C
#define LSADC_STOP 0x20
#define LSADC_ACTBIT 0x24
#define LSADC_CHNDATA 0x2C
#define LSADC_ENABLE 0x3C
#define LSADC_MAX_CHN_NUM 3
#define LSADC_NUM_BITS 10
#define LSADC_ALL_CHN_INT_MASK 0xF
#define LSADC_ACTIVE_BIT (0xfff)
#define LSADC_ACTIVE_BIT_MASK (0xFFF)
#define LSADC_DATA_DELTA (0xc)
#define LSADC_DATA_DELTA_MASK (0xF)
#define LSADC_GLITCH_SAMPLE (0x30)
#define LSADC_TIME_SCAN (0x200)
#define LSADC_GLITCH_TIME_US ((LSADC_GLITCH_SAMPLE + 1) * LSADC_TIME_SCAN * 25 / 100)
volatile xmedia_void* lsadc_reg = NULL;
xmedia_s32 lsadc_irq = LSADC_IRQ_ID;
#ifdef ENABLE_ADC_IRQ
#define INVALID_CDC_VALUE (0)
typedef struct {
xmedia_u32 adc_value;
} lsadc_cdc_info;
lsadc_cdc_info g_cdc_info[LSADC_MAX_CHN_NUM];
static osal_spinlock_t g_lsadc_spin_lock;
#endif
#define LSADC_SPIN_LOCK_FLAG xmedia_ulong
#define LSADC_VIR_ADDR(x) ((uintptr_t)(lsadc_reg) + ((x)-LSADC_BASE_ADDR))
#define lsadc_writel(v, x) osal_writel(v, LSADC_VIR_ADDR(LSADC_ADDR_OFFSET(x)))
#define lsadc_readl(x) osal_readl(LSADC_VIR_ADDR(LSADC_ADDR_OFFSET(x)))
static inline xmedia_void lsadc_reg_write(xmedia_ulong value, xmedia_ulong mask,
xmedia_ulong addr)
{
xmedia_ulong t;
t = lsadc_readl(addr);
t &= ~mask;
t |= value & mask;
lsadc_writel(t, addr);
}
static xmedia_void write_reg32(xmedia_u32 value, xmedia_u32 mask, const xmedia_void* addr)
{
xmedia_u32 t;
t = osal_readl((xmedia_void*)addr);
t &= ~mask;
t |= value & mask;
osal_writel(t, (xmedia_void*)addr);
}
static xmedia_void lsadc_enable_clock(xmedia_void)
{
xmedia_void *lsadc_crg_addr;
lsadc_crg_addr = osal_ioremap(LSADC_CRG_ADDR, (xmedia_ulong)0x4);
write_reg32(0x0 << 2, 0x1 << 2, lsadc_crg_addr); // (bit2)ls_adc_srst_req = 0
osal_udelay(200);
write_reg32(0x1 << 3, 0x1 << 3, lsadc_crg_addr); // (bit3)ls_adc_cken = 1
osal_udelay(100);
osal_iounmap((xmedia_void*)lsadc_crg_addr);
}
static xmedia_void lsadc_disable_clock(xmedia_void)
{
xmedia_void *lsadc_crg_addr;
lsadc_crg_addr = osal_ioremap(LSADC_CRG_ADDR, (xmedia_ulong)0x4);
write_reg32(0x0 << 3, 0x1 << 3, lsadc_crg_addr); // (bit3)ls_adc_cken = 0
osal_udelay(100);
write_reg32(0x1 << 2, 0x1 << 2, lsadc_crg_addr); // (bit2)ls_adc_srst_req = 1
osal_udelay(100);
osal_iounmap((xmedia_void*)lsadc_crg_addr);
}
static xmedia_s32 lsadc_open(xmedia_void* private_data)
{
lsadc_enable_clock();
lsadc_reg_write(1 << 15, 1 << 15, LSADC_CONFIG); // exit reset state
lsadc_reg_write(1 << 9, 1 << 9 , LSADC_ENABLE); // enable lsadc
return 0;
}
static xmedia_s32 lsadc_release(xmedia_void* private_data)
{
lsadc_reg_write(0 << 15, 1 << 15, LSADC_CONFIG); // enter reset state
lsadc_reg_write(0 << 9, 1 << 9 , LSADC_ENABLE); // disable lsadc
lsadc_disable_clock();
return 0;
}
/* 0: single scanning mode
* 1: continuous scanning mode
* The filter glitch is already eanble, only the continuous mode has a filter glitch, and the single mode is invalid.
*/
static xmedia_s32 lsadc_model_select(xmedia_s32 value)
{
xmedia_u32 val;
val = (xmedia_u32)value;
if ((val != 0) && (val != 1)) {
lsadc_print("error value:%x\n", val);
return -1;
}
lsadc_reg_write(val << 13, 1 << 13, LSADC_CONFIG);
if (val == 1) {
lsadc_reg_write(LSADC_ACTIVE_BIT, LSADC_ACTIVE_BIT_MASK, LSADC_ACTBIT); // [11:0]
lsadc_reg_write(LSADC_DATA_DELTA << 20, LSADC_DATA_DELTA_MASK << 20, LSADC_CONFIG); // [23:20]
lsadc_writel(LSADC_GLITCH_SAMPLE, LSADC_GLITCH); //glitch_sample, must > 0
lsadc_writel(LSADC_TIME_SCAN, LSADC_TIMESCAN); //time_scan, must > 20
/* set filter glitch function, 0:enable, 1:bypass, attention to LSADC_CTRL10(0x120a0028),
* lsadc will filter the lsadc_zero value in this reg;defaule value is 0
*/
lsadc_reg_write(0 << 17, 1 << 17, LSADC_CONFIG);
} else {
lsadc_reg_write(1 << 17, 1 << 17, LSADC_CONFIG); //set glitch bypass
}
return 0;
}
static xmedia_s32 lsadc_chn_valid(xmedia_s32 chn, xmedia_s32 enable)
{
xmedia_ulong value;
value = enable ? 1 : 0;
switch (chn)
{
#ifdef USE_LSADC_CHANNEL_0
case 0:
lsadc_reg_write(value << 8, 1 << 8, LSADC_CONFIG);
break;
#endif
case 1:
lsadc_reg_write(value << 9, 1 << 9, LSADC_CONFIG);
break;
case 2:
lsadc_reg_write(value << 10, 1 << 10, LSADC_CONFIG);
break;
default:
lsadc_print("error chn:%d\n", chn);
return -1;
}
return 0;
}
static xmedia_s32 lsadc_start(xmedia_void)
{
#ifdef ENABLE_ADC_IRQ
LSADC_SPIN_LOCK_FLAG flag;
#endif
xmedia_s32 model_sel = 0;
xmedia_s32 deglitch_bypass = 0;
xmedia_s32 config = lsadc_readl(LSADC_CONFIG);
xmedia_s32 chn_num = 0;
xmedia_s32 sleep_time_ms = 0;
if ( (config & (1 << 13)) != 0 ) {
model_sel = 1;
}
if ( (config & (1 << 17)) != 0 ) {
deglitch_bypass = 1;
}
if (1 == model_sel) {
xmedia_s32 lsadc_active_bit = lsadc_readl(LSADC_ACTBIT) & 0xFFF;
lsadc_print("config=%#x lsadc_active_bit=%#x\n", config, lsadc_active_bit);
#ifdef USE_LSADC_CHANNEL_0
if ( (config & (1 << 8)) != 0 ) {
chn_num++;
}
#endif
if ( (config & (1 << 9)) != 0 ) {
chn_num++;
}
if ( (config & (1 << 10)) != 0 ) {
chn_num++;
}
if (0 == deglitch_bypass) {
xmedia_s32 sleep_time_us = LSADC_GLITCH_TIME_US * chn_num;
sleep_time_ms = sleep_time_us / 1000;
if (0 != (sleep_time_us % 1000))
sleep_time_ms += 1;
} else {
sleep_time_ms = 1;
lsadc_print("bypass in continuous scan mode! sleep_time_ms=%d\n", sleep_time_ms);
}
} else {
sleep_time_ms = 1;
}
#ifdef ENABLE_ADC_IRQ
osal_memset(g_cdc_info, 0, sizeof(g_cdc_info));
osal_spin_lock_irqsave(&g_lsadc_spin_lock, &flag);
lsadc_reg_write(1, 1, LSADC_INTEN); //inten enable
lsadc_reg_write(LSADC_ALL_CHN_INT_MASK, LSADC_ALL_CHN_INT_MASK, LSADC_INTCLR); //clr all intflag
osal_spin_unlock_irqrestore(&g_lsadc_spin_lock, &flag);
#endif
lsadc_reg_write(1, 1, LSADC_START); //start
osal_msleep(sleep_time_ms); // wait for scan & calculate equ_vaule.
return 0;
}
static xmedia_s32 lsadc_stop(xmedia_void)
{
#ifdef ENABLE_ADC_IRQ
LSADC_SPIN_LOCK_FLAG flag;
#endif
lsadc_reg_write(1, 1, LSADC_STOP); //stop
#ifdef ENABLE_ADC_IRQ
osal_spin_lock_irqsave(&g_lsadc_spin_lock, &flag);
osal_memset(g_cdc_info, 0, sizeof(g_cdc_info));
lsadc_reg_write(0, 1, LSADC_INTEN); //inten disable
osal_spin_unlock_irqrestore(&g_lsadc_spin_lock, &flag);
#endif
return 0;
}
static xmedia_s32 lsadc_get_chn_value(xmedia_s32 chn)
{
xmedia_u32 unchn;
#ifdef USE_LSADC_CHANNEL_0
if (chn < 0 || chn >= LSADC_MAX_CHN_NUM) {
#else
if (chn <= 0 || chn >= LSADC_MAX_CHN_NUM) {
#endif
lsadc_print("error chn:%d\n", chn);
return -1;
}
unchn = (xmedia_u32)chn;
#ifdef ENABLE_ADC_IRQ
return g_cdc_info[unchn].adc_value;
#else
return lsadc_readl(LSADC_CHNDATA + (unchn << 2));
#endif
}
#ifdef ENABLE_ADC_IRQ
static xmedia_s32 lsadc_irq_proc(xmedia_s32 irq, xmedia_void* devId)
{
xmedia_u32 intstate;
xmedia_s32 chn_value;
xmedia_u32 chn;
LSADC_SPIN_LOCK_FLAG flag;
xmedia_u32 int_flag;
osal_spin_lock_irqsave(&g_lsadc_spin_lock, &flag);
intstate = lsadc_readl(LSADC_INTSTATUS);
for (chn = 0; chn < LSADC_MAX_CHN_NUM; chn++) {
int_flag = 1 << chn;
if (intstate & (int_flag)) {
chn_value = lsadc_readl(LSADC_CHNDATA + (chn << 2));
g_cdc_info[chn].adc_value = chn_value;
lsadc_reg_write(int_flag, int_flag, LSADC_INTCLR);//clr intflag
}
}
osal_spin_unlock_irqrestore(&g_lsadc_spin_lock, &flag);
return OSAL_IRQ_HANDLED;
}
#endif
static xmedia_slong lsadc_ioctl (xmedia_u32 cmd, xmedia_ulong arg, xmedia_void* private_data)
{
xmedia_s32 ret = -1;
xmedia_s32 param = 0;
switch (cmd) {
case LSADC_IOC_MODEL_SEL:
{
param = *(xmedia_s32*)(uintptr_t)arg;
ret = lsadc_model_select(param);
break;
}
case LSADC_IOC_CHN_ENABLE:
{
param = *(xmedia_s32*)(uintptr_t)arg;
ret = lsadc_chn_valid(param, 1);
break;
}
case LSADC_IOC_CHN_DISABLE:
{
param = *(xmedia_s32*)(uintptr_t)arg;
ret = lsadc_chn_valid(param, 0);
break;
}
case LSADC_IOC_START:
{
ret = lsadc_start();
break;
}
case LSADC_IOC_STOP:
{
ret = lsadc_stop();
break;
}
case LSADC_IOC_GET_CHNVAL:
{
param = *(xmedia_s32*)(uintptr_t)arg;
ret = lsadc_get_chn_value(param);
break;
}
default:
lsadc_print("error cmd:%08x\n", cmd);
ret = -1;
}
return ret;
}
static struct osal_fileops g_lsadc_fops =
{
.open = lsadc_open,
.release = lsadc_release,
.unlocked_ioctl = lsadc_ioctl,
};
static osal_dev_t* g_lsadc_dev;
xmedia_s32 lsadc_init(xmedia_void)
{
xmedia_s32 ret = 0;
if (!lsadc_reg) {
lsadc_reg = (volatile xmedia_void*)osal_ioremap(LSADC_BASE_ADDR, 0x100);
if (!lsadc_reg) {
lsadc_print("lsadc ioremap error.\n");
return -1;
}
}
#ifdef ENABLE_ADC_IRQ
lsadc_print("lsadc_irq=%d.\n", lsadc_irq);
if (lsadc_irq <= 0) {
lsadc_irq = LSADC_IRQ_ID;
lsadc_print("lsadc_irq=LSADC_IRQ_ID(%d).\n", lsadc_irq);
}
osal_spin_lock_init(&g_lsadc_spin_lock);
ret = osal_request_irq(lsadc_irq, lsadc_irq_proc, XMEDIA_NULL, "lsadc", &g_lsadc_fops);
if (ret != 0) {
lsadc_print("lsadc request irq error.\n");
osal_iounmap((xmedia_void*)lsadc_reg);
return -1;
}
#endif
g_lsadc_dev = osal_createdev("lsadc");
g_lsadc_dev->minor = 255;
g_lsadc_dev->fops = &g_lsadc_fops;
ret = osal_registerdevice(g_lsadc_dev);
if (ret != 0) {
osal_destroydev(g_lsadc_dev);
lsadc_print("lsadc register device error.\n");
osal_free_irq(lsadc_irq, &g_lsadc_fops);
osal_iounmap((xmedia_void*)lsadc_reg);
}
osal_printk("load xm_adc.ko OK!\n");
return ret;
}
xmedia_void lsadc_exit(xmedia_void)
{
#ifdef ENABLE_ADC_IRQ
osal_free_irq(lsadc_irq, &g_lsadc_fops);
osal_spin_lock_destory(&g_lsadc_spin_lock);
#endif
osal_deregisterdevice(g_lsadc_dev);
osal_destroydev(g_lsadc_dev);
lsadc_disable_clock();
osal_printk("unload xm_adc.ko OK!\n");
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __ADC_H__
#define __ADC_H__
#include "drv_type_ioctl.h"
#include "xmedia_type.h"
typedef enum IOC_NR_LSADC_E
{
IOC_NR_LSADC_MODEL_SEL = 0,
IOC_NR_LSADC_CHN_ENABLE,
IOC_NR_LSADC_CHN_DISABLE,
IOC_NR_LSADC_START,
IOC_NR_LSADC_STOP,
IOC_NR_LSADC_GET_CHNVAL,
IOC_NR_LSADC_BUTT
}IOC_NR_LSADC_E;
#define LSADC_IOC_MODEL_SEL _IOWR(IOC_TYPE_LSADC, IOC_NR_LSADC_MODEL_SEL, xmedia_s32)
#define LSADC_IOC_CHN_ENABLE _IOW(IOC_TYPE_LSADC, IOC_NR_LSADC_CHN_ENABLE, xmedia_s32)
#define LSADC_IOC_CHN_DISABLE _IOW(IOC_TYPE_LSADC, IOC_NR_LSADC_CHN_DISABLE, xmedia_s32)
#define LSADC_IOC_START _IO(IOC_TYPE_LSADC, IOC_NR_LSADC_START)
#define LSADC_IOC_STOP _IO(IOC_TYPE_LSADC, IOC_NR_LSADC_STOP)
#define LSADC_IOC_GET_CHNVAL _IOWR(IOC_TYPE_LSADC, IOC_NR_LSADC_GET_CHNVAL, xmedia_s32)
#endif /* __ADC_H__ */
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/version.h>
#include <linux/of_platform.h>
#include "osal.h"
extern unsigned int lsadc_irq;
extern volatile void *lsadc_reg;
extern int lsadc_init(void);
extern void lsadc_exit(void);
static int adc_probe(struct platform_device *pdev)
{
struct resource *mem;
lsadc_irq = platform_get_irq(pdev, 0);
if (lsadc_irq <= 0)
{
dev_err(&pdev->dev, "cannot find lsadc IRQ%d. \n", lsadc_irq);
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
lsadc_reg = (volatile void *)devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR((void* )lsadc_reg))
{
dev_err(&pdev->dev, "lsadc reg map failed. \n");
}
return lsadc_init();
}
static int adc_remove(struct platform_device *pdev)
{
lsadc_exit();
return 0;
}
static const struct of_device_id adc_match[] = {
{ .compatible = "lotus,lsadc" },
{},
};
static struct platform_driver lsadc_driver = {
.probe = adc_probe,
.remove = adc_remove,
.driver = { .name = "xmedia_lsadc",
.of_match_table = adc_match,
},
};
#ifdef MODULE
osal_module_platform_driver(lsadc_driver);
MODULE_LICENSE("GPL");
#else
int __init adc_driver_init(void)
{
return osal_platform_driver_register(&lsadc_driver);
}
#endif
+32
View File
@@ -0,0 +1,32 @@
ifeq ($(CFG_XMEDIA_EXPORT_FLAG),)
SDK_DIR := $(shell cd $(CURDIR)/../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
TARGET := adc_test
LIBS :=
INCLUDES := -I$(GMP_DIR)/include \
-I$(GMP_DIR)/drv/osal/include \
-I$(GMP_DIR)/drv/include \
-I$(GMP_DIR)/drv/lsadc
CFLAGS := $(SDK_USR_CFLAGS) $(LIBS) $(INCLUDES)
SRCS := $(wildcard ./*.c)
OBJS := $(patsubst %.c, %.o, $(SRCS))
.PHONY: all clean
all: $(OBJS)
$(AT)$(CC) -o $(TARGET) $^ $(CFLAGS)
%.o : %.c
$(AT)$(CC) -c -o $@ $< $(CFLAGS)
clean:
$(AT)rm -rf $(OBJS) $(TARGET)
+214
View File
@@ -0,0 +1,214 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "adc.h"
#define DEV_FILE "/dev/lsadc"
#define LSADC_GLITCH_SAMPLE_MS (7)
typedef enum {
LSADC_SCAN_MODE_SINGLE_STEP,
LSADC_SCAN_MODE_CONTINUOUS,
LSADC_SCAN_MODE_BUTT
} lsadc_scan_mode;
static xmedia_s32 lsadc_check_glitch
(xmedia_s32 value_arr[13], xmedia_s32 start_pos, xmedia_s32 end_pos, xmedia_s32 *lsadc_equ_vaule)
{
xmedia_s32 j;
xmedia_s32 last_sum = 0;
xmedia_s32 start_value;
const xmedia_s32 LSADC_DATA_DELTA = 0xc;
xmedia_s32 arr_len = 13;
xmedia_s32 len = end_pos - start_pos + 1;
if (start_pos < 0 || start_pos >= arr_len || len <= 0 || end_pos >= arr_len || NULL == lsadc_equ_vaule) {
fprintf(stderr, "fail to check! start_pos:%d end_pos:%d\n", start_pos, end_pos);
return 0;
}
start_value = value_arr[start_pos];
for(j = start_pos; j <= end_pos; j++) {
last_sum += value_arr[j];
}
*lsadc_equ_vaule = last_sum / len;
if (*lsadc_equ_vaule - start_value > LSADC_DATA_DELTA
|| start_value - *lsadc_equ_vaule > LSADC_DATA_DELTA) {
return 1;
}
return 0;
}
xmedia_s32 sample_lsadc_single_step_scan_mode(lsadc_scan_mode mode, xmedia_s32 chn)
{
xmedia_s32 i, value;
xmedia_s32 fd = open(DEV_FILE, O_RDWR);
if (fd < 0) {
fprintf(stderr, "fail to open file:%s\n", DEV_FILE);
return -1;
}
if(ioctl(fd, LSADC_IOC_MODEL_SEL, &mode) < 0) {
fprintf(stderr, "adc model select error.\n");
goto exit;
}
if(ioctl(fd, LSADC_IOC_CHN_ENABLE, &chn) < 0) {
fprintf(stderr, "enable chn %d error.\n", chn);
goto exit;
}
printf("[%s] LSADC_GLITCH_SAMPLE_MS=%d\n", __FUNCTION__, LSADC_GLITCH_SAMPLE_MS);
for(i=0; i < 20; i++)
{
xmedia_s32 j, k;
const xmedia_s32 gnum = LSADC_GLITCH_SAMPLE_MS;
xmedia_s32 last_value[gnum + 6];
xmedia_s32 lsadc_equ_vaule;
xmedia_s32 len = sizeof(last_value) / sizeof(last_value[0]);
for(j = 0; j < len; j++) {
if(ioctl(fd, LSADC_IOC_START) < 0) {
fprintf(stderr, "start lsadc error.\n");
goto exit;
}
value = ioctl(fd, LSADC_IOC_GET_CHNVAL, &chn);
last_value[j] = value;
if (0 == j)
printf("[%d][%d] get value:%d,chn[%d]\n", i, j, value, chn);
if (j >= (gnum - 1)) {
k = j - (gnum - 1);
if (lsadc_check_glitch(last_value, k, j, &lsadc_equ_vaule)) {
printf("[%d][%d] is glitch, value:%d equ_vaule:%d chn[%d]\n", i, k, last_value[k], lsadc_equ_vaule, chn);
}
}
if(ioctl(fd, LSADC_IOC_STOP) <0) {
fprintf(stderr, "stop lsadc error.\n");
}
}
usleep(1000*1000);
}
exit:
if(ioctl(fd, LSADC_IOC_STOP) < 0) {
fprintf(stderr, "stop lsadc error.\n");
}
if(ioctl(fd, LSADC_IOC_CHN_DISABLE, &chn) < 0) {
fprintf(stderr, "disable chn %d error.\n", chn);
}
close(fd);
return 0;
}
xmedia_s32 sample_lsadc_continuous_scan_mode(lsadc_scan_mode mode, xmedia_s32 chn)
{
xmedia_s32 i, value;
xmedia_s32 fd = open(DEV_FILE, O_RDWR);
if (fd < 0) {
fprintf(stderr, "fail to open file:%s\n", DEV_FILE);
return -1;
}
if(ioctl(fd, LSADC_IOC_MODEL_SEL, &mode) < 0) {
fprintf(stderr, "adc model select error.\n");
goto exit;
}
if(ioctl(fd, LSADC_IOC_CHN_ENABLE, &chn) < 0) {
fprintf(stderr, "enable chn %d error.\n", chn);
goto exit;
}
if(ioctl(fd, LSADC_IOC_START) < 0) {
fprintf(stderr, "start lsadc error.\n");
goto exit;
}
for(i = 0; i < 20; i++) {
xmedia_s32 j, k;
const xmedia_s32 gnum = LSADC_GLITCH_SAMPLE_MS;
xmedia_s32 last_value[gnum + 6];
xmedia_s32 lsadc_equ_vaule;
xmedia_s32 len = sizeof(last_value) / sizeof(last_value[0]);
for(j = 0; j < len; j++) {
value = ioctl(fd, LSADC_IOC_GET_CHNVAL, &chn);
last_value[j] = value;
if (0 == j)
printf("[%d][%d] get value:%d,chn[%d]\n", i, j, value, chn);
if (j >= (gnum - 1)) {
k = j - (gnum - 1);
if (lsadc_check_glitch(last_value, k, j, &lsadc_equ_vaule)) {
printf("[%d][%d] is glitch, value:%d equ_vaule:%d chn[%d]\n", i, k, last_value[k], lsadc_equ_vaule, chn);
}
}
usleep(1*1000);
}
usleep(1000*1000);
}
exit:
if(ioctl(fd, LSADC_IOC_STOP) < 0) {
fprintf(stderr, "stop lsadc error.\n");
}
if(ioctl(fd, LSADC_IOC_CHN_DISABLE, &chn) < 0) {
fprintf(stderr, "disable chn %d error.\n", chn);
}
close(fd);
return 0;
}
#ifdef __LITEOS__
xmedia_s32 app_main(xmedia_s32 argc, char *argv[])
#else
xmedia_s32 main(xmedia_s32 argc, char* argv[])
#endif
{
lsadc_scan_mode mode = LSADC_SCAN_MODE_BUTT;
xmedia_s32 chn = 0;
printf("select scan mode:\n");
printf(" - [0] is single step scan mode\n");
printf(" - [1] is Continuous scan mode\n");
mode = getchar() - '0';
getchar();
printf("select ADC CHN:\n");
printf(" - [0] is CHN[0]\n");
printf(" - [1] is CHN[1]\n");
printf(" - [2] is CHN[2]\n");
chn = getchar() - '0';
switch (mode) {
case LSADC_SCAN_MODE_SINGLE_STEP:
sample_lsadc_single_step_scan_mode(mode, chn);
break;
case LSADC_SCAN_MODE_CONTINUOUS:
sample_lsadc_continuous_scan_mode(mode, chn);
break;
default:
printf("error scan mode\n");
break;
}
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
include $(SDK_DIR)/build/version.mk
MOD_NAME := xm_misc
SRCS := ./src/drv_misc.c
SRCS += ./src/drv_osd_draw_time.c
SRCS += ./src/drv_sensor.c
SDK_KER_CFLAGS += -I$(GMP_DIR)/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/osal/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/common/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/common/task
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/drv/misc/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/usr/include
SDK_KER_CFLAGS += -I$(GMP_DIR)/usr/common/include
$(info SDK_KER_CFLAGS=$(SDK_KER_CFLAGS))
$(info SRCS=$(SRCS))
$(info SDK_DIR=$(SDK_DIR))
include $(SDK_DIR)/build/sdk_ko_rules.mk
+99
View File
@@ -0,0 +1,99 @@
#ifndef __DRV_MISC_H__
#define __DRV_MISC_H__
#include "xmedia_debug.h"
#include "xmedia_type.h"
#include "drv_type_ioctl.h"
//#define SUPPORT_OSD_TIME 1
//#define SUPPORT_SENSOR_PWDN_MODE 1
//#define APP_STANDBY_SENSOR 1
#ifdef SUPPORT_OSD_TIME
#include "xmedia_region.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
CMD_MISC_AOV_INIT = 0,
CMD_MISC_AOV_SET_SENSOR_MODE,
#ifdef SUPPORT_OSD_TIME
CMD_MISC_OSD_TIME_CREATE,
CMD_MISC_OSD_TIME_UPDATE,
CMD_MISC_OSD_TIME_UPDATE_TIMEZONE,
CMD_MISC_OSD_TIME_DESTROY,
#endif
#ifdef SUPPORT_SENSOR_PWDN_MODE
CMD_MISC_SENSOR_PWDN_STANDBY,
CMD_MISC_SENSOR_PWDN_RESUME,
#endif
CMD_MISC_END = 0xFFFF,
} misc_ioctl_cmd;
// ioctl cmd 对应的函数指针
typedef xmedia_s32 (*misc_ctl_ptr_func)(xmedia_ulong arg);
typedef struct misc_ioctl_func_item {
xmedia_u32 cmd;
misc_ctl_ptr_func ptr_func;
} misc_ioctl_func_item;
#ifdef SUPPORT_OSD_TIME
typedef struct __misc_osd_time_attach_info_ {
xmedia_chn_info mpp_chn;
xmedia_rgn_chn_attr chn_attr;
}misc_osd_time_attach_info_t;
typedef struct _misc_osd_time_ {
xmedia_s32 rgn_hdl;
xmedia_rgn_attr rgn_attr;
xmedia_u16 rgn_attach_num;
misc_osd_time_attach_info_t attach_obj[4];
xmedia_u16 font_size_scale;
xmedia_u16 text_color;
xmedia_u16 bg_color;
} misc_osd_time_attr_t;
#endif
typedef struct misc_aov_isp_info{
xmedia_s32 isp_pipe_num;
xmedia_u32 isp_pipe[VI_MAX_DEV_NUM];
#ifdef SUPPORT_SENSOR_PWDN_MODE
xmedia_bool support_sensor_pwdn_standby[VI_MAX_DEV_NUM];
#endif
} misc_aov_isp_info;
typedef struct misc_aov_state{
xmedia_bool en_aov_mode;
xmedia_s32 frame_num;
} misc_aov_state;
#define XMEDIA_MISC_AOV_INIT _IOWR(IOC_TYPE_MISC, CMD_MISC_AOV_INIT, misc_aov_isp_info)
#define XMEDIA_MISC_AOV_SET_SENSOR_MODE _IOWR(IOC_TYPE_MISC, CMD_MISC_AOV_SET_SENSOR_MODE, misc_aov_state)
#ifdef SUPPORT_OSD_TIME
#define XMEDIA_MISC_OSD_TIME_CREATE_CTRL _IOW(IOC_TYPE_MISC, CMD_MISC_OSD_TIME_CREATE, misc_osd_time_attr_t)
#define XMEDIA_MISC_OSD_TIME_UPDATE_CTRL _IOW(IOC_TYPE_MISC, CMD_MISC_OSD_TIME_UPDATE, misc_osd_time_attr_t)
#define XMEDIA_MISC_OSD_TIME_UPDATE_TIMEZONE_CTRL _IOW(IOC_TYPE_MISC, CMD_MISC_OSD_TIME_UPDATE_TIMEZONE, xmedia_s32)
#define XMEDIA_MISC_OSD_TIME_DESTROY_CTRL _IOW(IOC_TYPE_MISC, CMD_MISC_OSD_TIME_DESTROY, misc_osd_time_attr_t)
#endif
#ifdef SUPPORT_SENSOR_PWDN_MODE
#define XMEDIA_MISC_SENSOR_PWDN_STANDBY _IOWR(IOC_TYPE_MISC, CMD_MISC_SENSOR_PWDN_STANDBY, xmedia_s32)
#define XMEDIA_MISC_SENSOR_PWDN_RESUME _IOWR(IOC_TYPE_MISC, CMD_MISC_SENSOR_PWDN_RESUME, xmedia_s32)
#endif
#define MISC_TRACE(level, fmt, ...) \
do { \
MODULE_TRACE(level, MOD_ID_MISC, "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0)
#ifdef __cplusplus
}
#endif
#endif /* __DRV_MISC_H__ */
@@ -0,0 +1,80 @@
#ifndef DRV_OSD_DRAW_TIME_H
#define DRV_OSD_DRAW_TIME_H
#ifdef __KERNEL__
#include <linux/types.h>
#endif
#include "xmedia_type.h"
#include "drv_misc.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef SUPPORT_OSD_TIME
// ARGB1555颜色定义 (1位alpha + 5位RGB)
typedef unsigned short argb1555_t;
// 颜色宏定义
#define ARGB1555(a, r, g, b) (((a) ? 0x8000 : 0) | (((r) & 0xF8) << 7) | (((g) & 0xF8) << 2) | (((b) & 0xF8) >> 3))
#define ARGB1555_BLACK ARGB1555(1, 0, 0, 0)
#define ARGB1555_WHITE ARGB1555(1, 255, 255, 255)
#define ARGB1555_RED ARGB1555(1, 255, 0, 0)
#define ARGB1555_GREEN ARGB1555(1, 0, 255, 0)
#define ARGB1555_BLUE ARGB1555(1, 0, 0, 255)
#define ARGB1555_YELLOW ARGB1555(1, 255, 255, 0)
#define ARGB1555_CYAN ARGB1555(1, 0, 255, 255)
#define ARGB1555_MAGENTA ARGB1555(1, 255, 0, 255)
#define ARGB1555_GRAY ARGB1555(1, 128, 128, 128)
#define ARGB1555_DARKBLUE ARGB1555(1, 0, 0, 128)
#define ARGB1555_ORANGE ARGB1555(1, 255, 165, 0)
// 时间字符串长度是8 "HH:MM:SS"
#define TIME_STRING_LEN 8
// 日期字符串长度是10 "YYYY-MM-DD"
#define DATE_STRING_LEN 10
// 总文本宽度:时间(8字符) + 空格(1字符) + 日期(10字符) + 结束符=20字符
#define TOTAL_OSD_STRING_LEN 20
// 显示上下文结构体
typedef struct {
unsigned char *buffer; // 显示buffer地址
int width; // 屏幕宽度
int height; // 屏幕高度
int stride;
int font_size; // 字体大小
argb1555_t text_color; // 文字颜色
argb1555_t bg_color; // 背景颜色
// 缓存上一次显示的内容,用于增量更新
char last_draw_str[TOTAL_OSD_STRING_LEN];
int display_initialized; // 是否已经初始化显示
} osd_draw_context_t;
// 函数声明
void osd_draw_context_init(osd_draw_context_t *ctx, int width, int height, int stride, int font_size_scale);
void osd_set_colors(osd_draw_context_t *ctx, argb1555_t text_color, argb1555_t bg_color);
void osd_clear_screen(osd_draw_context_t *ctx);
//void draw_pixel(osd_draw_context_t *ctx, int x, int y, argb1555_t color);
//void draw_char(osd_draw_context_t *ctx, int x, int y, char c, argb1555_t color);
void osd_draw_str(osd_draw_context_t *ctx, int x, int y, const char *draw_str, int draw_str_size, argb1555_t color);
void osd_draw_str_ex(osd_draw_context_t *ctx, const char *draw_str, int draw_str_size, unsigned char *buffer);
void osd_get_min_size(osd_draw_context_t *ctx, int *width, int *height);
xmedia_s32 misc_ctl_osd_time_create(xmedia_ulong arg);
xmedia_s32 misc_ctl_osd_time_destroy(xmedia_ulong arg);
xmedia_s32 misc_ctl_osd_time_update(xmedia_ulong arg);
xmedia_s32 misc_ctl_osd_time_update_timezone(xmedia_ulong arg);
xmedia_s32 osd_time_update_all(xmedia_void);
#endif //SUPPORT_OSD_TIME
#ifdef __cplusplus
}
#endif
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef __DRV_SENSOR_H__
#define __DRV_SENSOR_H__
#include "xmedia_debug.h"
#include "xmedia_type.h"
#include "drv_type_ioctl.h"
#include <linux/gpio.h>
#include <linux/pwm.h>
#include "common.h"
#include "osal.h"
#include "xmedia_errcode.h"
#include "drv_dev_defines.h"
#include "drv_misc.h"
#include "drv_export.h"
#ifdef __cplusplus
extern "C" {
#endif
xmedia_s32 misc_sensor_init(xmedia_void);
xmedia_s32 misc_sensor_exit(xmedia_void);
xmedia_s32 misc_sensor_resume(xmedia_void);
xmedia_s32 misc_media_suspend(xmedia_void);
xmedia_s32 misc_ctl_aov_init(xmedia_ulong arg);
xmedia_s32 misc_ctl_aov_set_sensor_mode(xmedia_ulong arg);
#ifdef SUPPORT_SENSOR_PWDN_MODE
xmedia_s32 misc_ctl_sensor_pwdn_standby(xmedia_ulong arg);
xmedia_s32 misc_ctl_sensor_pwdn_resume(xmedia_ulong arg);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __DRV_SENSOR_H__ */
+150
View File
@@ -0,0 +1,150 @@
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/pwm.h>
#include "common.h"
#include "osal.h"
#include "xmedia_errcode.h"
#include "drv_dev_defines.h"
#include "drv_misc.h"
#ifdef SUPPORT_OSD_TIME
#include "drv_osd_draw_time.h"
#endif
#include "drv_export.h"
#include "drv_sensor.h"
static osal_dev_t *g_misc_dev = XMEDIA_NULL;
xmedia_s32 drv_misc_open(xmedia_void *private_data)
{
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_misc_close(xmedia_void *private_data)
{
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_misc_suspend(osal_dev_t *pdev)
{
misc_media_suspend();
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_misc_resume(osal_dev_t *pdev)
{
#ifdef SUPPORT_OSD_TIME
osd_time_update_all();
#endif
misc_sensor_resume();
return 0;
}
misc_ioctl_func_item g_misc_ctl_func_item[] = {
{XMEDIA_MISC_AOV_INIT, misc_ctl_aov_init},
{XMEDIA_MISC_AOV_SET_SENSOR_MODE, misc_ctl_aov_set_sensor_mode},
#ifdef SUPPORT_OSD_TIME
{XMEDIA_MISC_OSD_TIME_CREATE_CTRL, misc_ctl_osd_time_create},
{XMEDIA_MISC_OSD_TIME_UPDATE_CTRL, misc_ctl_osd_time_update},
{XMEDIA_MISC_OSD_TIME_UPDATE_TIMEZONE_CTRL, misc_ctl_osd_time_update_timezone},
{XMEDIA_MISC_OSD_TIME_DESTROY_CTRL, misc_ctl_osd_time_destroy},
#endif
#ifdef SUPPORT_SENSOR_PWDN_MODE
{XMEDIA_MISC_SENSOR_PWDN_STANDBY, misc_ctl_sensor_pwdn_standby},
{XMEDIA_MISC_SENSOR_PWDN_RESUME, misc_ctl_sensor_pwdn_resume},
#endif
};
static xmedia_slong drv_misc_ioctl(xmedia_u32 cmd, xmedia_ulong arg, xmedia_void *private_data)
{
xmedia_u32 i;
for (i = 0; i < sizeof(g_misc_ctl_func_item)/sizeof(misc_ioctl_func_item); i++) {
if (cmd == g_misc_ctl_func_item[i].cmd && g_misc_ctl_func_item[i].ptr_func != XMEDIA_NULL) {
return g_misc_ctl_func_item[i].ptr_func(arg);
}
}
MISC_TRACE(MODULE_DBG_ERR, "invalid cmd(0x%x)!\n", cmd);
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
#ifdef CONFIG_COMPAT
xmedia_slong drv_misc_compat_ioctl(xmedia_u32 cmd, xmedia_ulong arg, xmedia_void *private_data)
{
return drv_misc_ioctl(cmd, arg, private_data);
}
#endif
static struct osal_fileops g_misc_fops = {
.open = drv_misc_open,
.unlocked_ioctl = drv_misc_ioctl,
.release = drv_misc_close,
#ifdef CONFIG_COMPAT
.compat_ioctl = drv_misc_compat_ioctl,
#endif
};
struct osal_pmops g_misc_drv_ops = {
.pm_suspend = drv_misc_suspend,
.pm_resume= drv_misc_resume,
};
xmedia_s32 drv_misc_modinit(xmedia_void)
{
g_misc_dev = osal_createdev(UMAP_DEVNAME_MISC_BASE);
if (g_misc_dev == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR,"pm create dev err!\n");
goto out0;
}
g_misc_dev->fops = &g_misc_fops;
g_misc_dev->minor = UMAP_MISC_MINOR_BASE;
g_misc_dev->osal_pmops = &g_misc_drv_ops;
if (osal_registerdevice(g_misc_dev) < 0) {
MISC_TRACE(MODULE_DBG_ERR,"regist pm device err!\n");
goto out1;
}
misc_sensor_init();
osal_printk("load xm_misc.ko OK!\n");
return XMEDIA_SUCCESS;
out1:
osal_destroydev(g_misc_dev);
g_misc_dev = XMEDIA_NULL;
out0:
osal_printk("load xm_misc.ko err!\n");
return XMEDIA_FAILURE;
}
xmedia_void drv_misc_modexit(xmedia_void)
{
osal_deregisterdevice(g_misc_dev);
osal_destroydev(g_misc_dev);
g_misc_dev = XMEDIA_NULL;
misc_sensor_exit();
MISC_TRACE(MODULE_DBG_ERR,"unload xm_misc.ko OK!\n");
return;
}
#ifdef MODULE
module_init(drv_misc_modinit);
module_exit(drv_misc_modexit);
MODULE_LICENSE("GPL");
#else
int __init misc_driver_init(void)
{
return drv_misc_modinit();
}
#endif
+564
View File
@@ -0,0 +1,564 @@
#include "drv_misc.h"
#ifdef SUPPORT_OSD_TIME
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/timekeeping.h>
#include <linux/rtc.h>
#include <linux/time64.h>
#include "xmedia_errcode.h"
#include "drv_dev_defines.h"
#include "drv_osd_draw_time.h"
#include "drv_export.h"
typedef struct __osd_time_ext {
misc_osd_time_attr_t osd_time_attr;
osd_draw_context_t osd_draw_ctx;
struct __osd_time_ext *next;
}osd_time_ext_t;
osd_time_ext_t *g_osd_time_ext_hdl = XMEDIA_NULL;
xmedia_s32 g_tz_minuteswest = 0;
#define FONT_ORIGINAL_WIDTH 8
#define FONT_ORIGINAL_HEIGHT 8
// 8x8数字字体点阵 (0-9和冒号)
static const uint8_t font_8x8[13][8] = {
{0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C}, // 0
{0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C}, // 1
{0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E}, // 2
{0x3C, 0x66, 0x06, 0x1C, 0x06, 0x06, 0x66, 0x3C}, // 3
{0x0C, 0x1C, 0x2C, 0x4C, 0x7E, 0x0C, 0x0C, 0x0C}, // 4
{0x7E, 0x60, 0x7C, 0x06, 0x06, 0x06, 0x66, 0x3C}, // 5
{0x3C, 0x66, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x3C}, // 6
{0x7E, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0x18}, // 7
{0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x66, 0x3C}, // 8
{0x3C, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C}, // 9
{0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00}, // :
{0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00}, // -
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 空格
};
// 初始化显示上下文
void osd_draw_context_init(osd_draw_context_t *ctx, int width, int height, int stride, int font_size_scale) {
ctx->width = width;
ctx->height = height;
ctx->stride = stride;
ctx->font_size = (font_size_scale < 1) ? 1 : font_size_scale; // 最小字体大小为1
ctx->text_color = ARGB1555_YELLOW;
ctx->bg_color = ARGB1555_BLACK;
// 初始化缓存
memset(ctx->last_draw_str, 0, sizeof(ctx->last_draw_str));
ctx->display_initialized = 0;
}
// 设置颜色
void osd_set_colors(osd_draw_context_t *ctx, argb1555_t text_color, argb1555_t bg_color) {
ctx->text_color = text_color;
ctx->bg_color = bg_color;
}
// 清空屏幕
void osd_clear_screen(osd_draw_context_t *ctx) {
int i = 0, j = 0;
argb1555_t *p = NULL;
if (!ctx->buffer) {
MISC_TRACE(MODULE_DBG_ERR,"Error: Buffer is NULL\n");
return;
}
for (i = 0; i < ctx->height; i++) {
for (j = 0; j < ctx->width; j++) {
p = (argb1555_t*)(ctx->buffer + i * ctx->stride + j * sizeof(argb1555_t));
*p = ctx->bg_color;
}
}
}
// 绘制像素
void draw_pixel(osd_draw_context_t *ctx, int x, int y, argb1555_t color) {
argb1555_t *p = NULL;
if (!ctx->buffer)
return;
if (x >= 0 && x < ctx->width && y >= 0 && y < ctx->height) {
p = (argb1555_t*)(ctx->buffer + y * ctx->stride + x * sizeof(argb1555_t));
*p = color;
}
}
// 绘制缩放后的像素块 (用于字体放大)
void draw_scaled_pixel(osd_draw_context_t *ctx, int x, int y, int scale, argb1555_t color) {
int dx = 0, dy = 0;
for (dy = 0; dy < scale; dy++) {
for (dx = 0; dx < scale; dx++) {
draw_pixel(ctx, x + dx, y + dy, color);
}
}
}
// 绘制字符
void draw_char(osd_draw_context_t *ctx, int x, int y, char c, argb1555_t color) {
int char_index, scale, row, col;
uint8_t row_data;
if (c >= '0' && c <= '9') {
char_index = c - '0';
} else if (c == ':') {
char_index = 10;
} else if (c == '-') {
char_index = 11; // 减号
} else {
char_index = 12; // 空格或其他字符
}
scale = ctx->font_size;
for (row = 0; row < FONT_ORIGINAL_WIDTH; row++) {
row_data = font_8x8[char_index][row];
for (col = 0; col < FONT_ORIGINAL_HEIGHT; col++) {
if (row_data & (1 << (7 - col))) {
// 绘制放大的像素
draw_scaled_pixel(ctx,
x + col * scale,
y + row * scale,
scale, color);
}
}
}
}
// 绘制字符串
void osd_draw_str(osd_draw_context_t *ctx, int x, int y, const char *draw_str, int draw_str_size, argb1555_t color) {
int i;
int pos_x = x;
int char_width = FONT_ORIGINAL_WIDTH * ctx->font_size + ctx->font_size; // 字符宽度 + 间距
for (i = 0; draw_str[i] != '\0'; i++) {
draw_char(ctx, pos_x, y, draw_str[i], color);
pos_x += char_width;
}
}
// 绘制单个字符(增量更新用)
void draw_single_char(osd_draw_context_t *ctx, int x, int y, char c, argb1555_t color) {
int char_width, char_height;
int px, py;
// 先清除该字符区域
char_width = FONT_ORIGINAL_WIDTH * ctx->font_size;
char_height = FONT_ORIGINAL_HEIGHT * ctx->font_size;
for (py = y; py < y + char_height; py++) {
for (px = x; px < x + char_width; px++) {
draw_pixel(ctx, px, py, ctx->bg_color);
}
}
// 绘制新字符
draw_char(ctx, x, y, c, color);
}
// 获取字符宽度
int get_char_width(osd_draw_context_t *ctx) {
return FONT_ORIGINAL_WIDTH * ctx->font_size + ctx->font_size;
}
// 获取字符高度
int get_char_height(osd_draw_context_t *ctx) {
return FONT_ORIGINAL_HEIGHT * ctx->font_size;
}
// 获取时钟显示所需的尺寸
void get_osd_time_size(osd_draw_context_t *ctx, int *width, int *height) {
// 格式: "HH:MM:SS YYYY-MM-DD" 总共19个字符
*width = (TOTAL_OSD_STRING_LEN - 1) * get_char_width(ctx);
*height = get_char_height(ctx);
}
// 增量更新日期(只更新变化的字符)
void update_str_incremental(osd_draw_context_t *ctx, int date_x, int date_y, const char *draw_str, int draw_str_size) {
int char_width, i, char_x;
if (!ctx->display_initialized) {
// 第一次显示,绘制全部字符
osd_draw_str(ctx, date_x, date_y, draw_str, draw_str_size, ctx->text_color);
strcpy(ctx->last_draw_str, draw_str);
return;
}
char_width = get_char_width(ctx);
// 比较每个字符,只更新变化的字符
for (i = 0; i < sizeof(ctx->last_draw_str); i++) { // 日期字符串长度是10 "YYYY-MM-DD"
if (draw_str[i] != ctx->last_draw_str[i]) {
char_x = date_x + i * char_width;
draw_single_char(ctx, char_x, date_y, draw_str[i], ctx->text_color);
}
}
strcpy(ctx->last_draw_str, draw_str);
}
// 绘制时钟
void osd_draw_str_ex(osd_draw_context_t *ctx, const char *draw_str, int draw_str_size, uint8_t *buffer) {
int char_width, char_height;
int total_width, total_height;
int start_x, start_y;
int i;
if (!buffer) {
MISC_TRACE(MODULE_DBG_ERR,"Error: Buffer is NULL\n");
return;
}
ctx->buffer = buffer;
// 计算显示位置(时间和日期在同一行)
char_width = get_char_width(ctx);
char_height = get_char_height(ctx);
// 总文本宽度:时间(8字符) + 空格(1字符) + 日期(10字符) = 19字符
total_width = (TOTAL_OSD_STRING_LEN - 1) * char_width;
total_height = char_height;
start_x = (ctx->width - total_width) / 2;
start_y = (ctx->height - total_height) / 2;
// 确保位置有效
if (start_x < 0) start_x = 0;
if (start_y < 0) start_y = 0;
// 第一次显示时清屏并绘制边框
if (!ctx->display_initialized) {
osd_clear_screen(ctx);
// 绘制装饰边框
for (i = 0; i < ctx->width; i++) {
draw_pixel(ctx, i, 0, ARGB1555_GRAY);
draw_pixel(ctx, i, ctx->height - 1, ARGB1555_GRAY);
}
for (i = 0; i < ctx->height; i++) {
draw_pixel(ctx, 0, i, ARGB1555_GRAY);
draw_pixel(ctx, ctx->width - 1, i, ARGB1555_GRAY);
}
// 绘制分隔符(时间和日期之间的空格)
//int separator_x = start_x + DATE_STRING_LEN * char_width;
//draw_char(ctx, separator_x, start_y, ' ', ctx->bg_color);
ctx->display_initialized = 1;
}
// 更新时间(增量更新)
update_str_incremental(ctx, start_x, start_y, draw_str, draw_str_size);
}
// 应用时区偏移
xmedia_void apply_timezone_offset(struct timespec64 *ts, xmedia_s32 tz_minuteswest)
{
// 将时区偏移转换为秒(西区为正值,需要减去)
xmedia_slong tz_seconds = tz_minuteswest * 60;
// 调整时间
ts->tv_sec -= tz_seconds;
// 处理纳秒溢出
if (ts->tv_nsec < 0) {
ts->tv_sec--;
ts->tv_nsec += NSEC_PER_SEC;
}
if (ts->tv_nsec >= NSEC_PER_SEC) {
ts->tv_sec++;
ts->tv_nsec -= NSEC_PER_SEC;
}
}
xmedia_s32 get_local_time_string(xmedia_char *time_buf, size_t time_buf_size)
{
struct timespec64 ts_utc, ts_local;
struct tm tm_local;
// 获取UTC时间
ktime_get_real_ts64(&ts_utc);
// 计算本地时间
ts_local = ts_utc;
apply_timezone_offset(&ts_local, g_tz_minuteswest);
time64_to_tm(ts_local.tv_sec, 0, &tm_local);
snprintf(time_buf, time_buf_size,
"%04ld-%02d-%02d %02d:%02d:%02d",
tm_local.tm_year + 1900, tm_local.tm_mon + 1, tm_local.tm_mday,
tm_local.tm_hour, tm_local.tm_min, tm_local.tm_sec);
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_ctl_osd_time_create(xmedia_ulong arg)
{
xmedia_s32 s32Ret = XMEDIA_SUCCESS, s32Ret2 = XMEDIA_SUCCESS;
xmedia_s32 i = 0;
xmedia_rgn_canvas_info canvas_info;
char time_buf[TOTAL_OSD_STRING_LEN];
osd_time_ext_t *osd_time_ext_hdl = XMEDIA_NULL, *p = XMEDIA_NULL;
osd_time_ext_hdl = osal_vmalloc(sizeof(osd_time_ext_t));
if (osd_time_ext_hdl == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
}
memset(osd_time_ext_hdl, 0, sizeof(osd_time_ext_t));
memcpy(&osd_time_ext_hdl->osd_time_attr, (xmedia_void *)arg, sizeof(misc_osd_time_attr_t));
if(g_osd_time_ext_hdl == XMEDIA_NULL) {
s32Ret = export_rgn_init();
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_region_init failed! ret:0x%x\n", s32Ret);
goto EXIT1;
}
}
s32Ret = export_rgn_create(osd_time_ext_hdl->osd_time_attr.rgn_hdl, &osd_time_ext_hdl->osd_time_attr.rgn_attr);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_region_create failed! ret:0x%x\n", s32Ret);
goto EXIT1;
}
for(i = 0; i < osd_time_ext_hdl->osd_time_attr.rgn_attach_num; i++) {
s32Ret = export_rgn_attach_to_chn(osd_time_ext_hdl->osd_time_attr.rgn_hdl, &osd_time_ext_hdl->osd_time_attr.attach_obj[i].mpp_chn,
&osd_time_ext_hdl->osd_time_attr.attach_obj[i].chn_attr);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_attach_to_chn failed with %#x!\n", s32Ret);
goto EXIT2;
}
}
s32Ret = export_rgn_get_canvas_info(osd_time_ext_hdl->osd_time_attr.rgn_hdl, &canvas_info);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_get_canvas_info failed with %#x!\n", s32Ret);
goto EXIT3;
}
osd_draw_context_init(&osd_time_ext_hdl->osd_draw_ctx, canvas_info.size.width, canvas_info.size.height, canvas_info.stride, osd_time_ext_hdl->osd_time_attr.font_size_scale);
osd_set_colors(&osd_time_ext_hdl->osd_draw_ctx, (argb1555_t)osd_time_ext_hdl->osd_time_attr.text_color, (argb1555_t)osd_time_ext_hdl->osd_time_attr.bg_color);
get_local_time_string(time_buf, sizeof(time_buf));
osd_draw_str_ex(&osd_time_ext_hdl->osd_draw_ctx, time_buf, sizeof(time_buf), canvas_info.virt_addr);
s32Ret = export_rgn_update_canvas(osd_time_ext_hdl->osd_time_attr.rgn_hdl);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_update_canvas failed with %#x!\n", s32Ret);
goto EXIT3;
}
if(g_osd_time_ext_hdl == XMEDIA_NULL)
g_osd_time_ext_hdl = osd_time_ext_hdl;
else {
p = g_osd_time_ext_hdl;
while(p->next != XMEDIA_NULL) {
p = p->next;
}
p->next = osd_time_ext_hdl;
}
return XMEDIA_SUCCESS;
EXIT3:
for(i = 0; i < osd_time_ext_hdl->osd_time_attr.rgn_attach_num; i++) {
s32Ret2 = export_rgn_detach_from_chn(osd_time_ext_hdl->osd_time_attr.rgn_hdl, &osd_time_ext_hdl->osd_time_attr.attach_obj[i].mpp_chn);
if(s32Ret2 != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_detach_from_chn failed!\n");
}
}
EXIT2:
s32Ret2 = export_rgn_destroy(osd_time_ext_hdl->osd_time_attr.rgn_hdl);
if (s32Ret2 != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_destroy failed with %#x!\n", s32Ret2);
}
EXIT1:
osal_vfree(osd_time_ext_hdl);
osd_time_ext_hdl = XMEDIA_NULL;
return s32Ret;
}
xmedia_s32 misc_ctl_osd_time_update_timezone(xmedia_ulong arg)
{
xmedia_s32 tz_minuteswest = *(xmedia_s32*)arg;
/* Verify we're within the +-15 hrs range */
if (tz_minuteswest > 15*60 || tz_minuteswest < -15*60) {
MISC_TRACE(MODULE_DBG_ERR, "invaild tz_minuteswest:%d,i it should be within the +-15 hrs range!\n", tz_minuteswest);
return XMEDIA_FAILURE;
}
g_tz_minuteswest = tz_minuteswest;
MISC_TRACE(MODULE_DBG_DEBUG, "set tz_minuteswest:%d!\n", g_tz_minuteswest);
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_ctl_osd_time_destroy(xmedia_ulong arg)
{
xmedia_s32 i = 0;
xmedia_s32 s32Ret = XMEDIA_SUCCESS;
misc_osd_time_attr_t *osd_time_attr = XMEDIA_NULL;
osd_time_ext_t *p = XMEDIA_NULL, *tmp = XMEDIA_NULL;
xmedia_s32 have_found = 0;
osd_time_attr = (misc_osd_time_attr_t*)arg;
if(osd_time_attr == XMEDIA_NULL)
{
MISC_TRACE(MODULE_DBG_ERR, "input parameter is NULL!\n");
return XMEDIA_FAILURE;
}
if(g_osd_time_ext_hdl == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR, "osd time destory failed! because not create this object!!!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
else if(g_osd_time_ext_hdl->osd_time_attr.rgn_hdl == osd_time_attr->rgn_hdl) {
p = g_osd_time_ext_hdl;
g_osd_time_ext_hdl = g_osd_time_ext_hdl->next;
}
else if(g_osd_time_ext_hdl->next == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR, "osd time destory failed! because not create this object!!!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
else {
p = g_osd_time_ext_hdl;
while(p->next != XMEDIA_NULL) {
if(p->next->osd_time_attr.rgn_hdl == osd_time_attr->rgn_hdl) {
have_found = 1;
tmp = p->next;
p->next = p->next->next;
p = tmp;
break;
}
p = p->next;
}
if(!have_found) {
MISC_TRACE(MODULE_DBG_ERR, "osd time destory failed! because not create this object!!!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
}
for(i = 0; i < osd_time_attr->rgn_attach_num; i++) {
s32Ret = export_rgn_detach_from_chn(osd_time_attr->rgn_hdl, &osd_time_attr->attach_obj[i].mpp_chn);
if(s32Ret !=XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_detach_from_chn failed!\n");
}
}
s32Ret = export_rgn_destroy(osd_time_attr->rgn_hdl);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_destroy failed with %#x!\n", s32Ret);
}
if(p)
osal_vfree(p);
if(g_osd_time_ext_hdl == XMEDIA_NULL) {
export_rgn_exit();
}
return s32Ret;
}
xmedia_s32 osd_time_update(misc_osd_time_attr_t *osd_time_attr, osd_draw_context_t *osd_draw_ctx)
{
xmedia_s32 s32Ret = XMEDIA_SUCCESS;
xmedia_rgn_canvas_info canvas_info;
char time_buf[TOTAL_OSD_STRING_LEN];
if(osd_time_attr == XMEDIA_NULL || osd_draw_ctx == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR, "osd time object not create!\n");
return XMEDIA_ERRCODE_NOT_INIT;
}
s32Ret = export_rgn_get_canvas_info(osd_time_attr->rgn_hdl, &canvas_info);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_get_canvas_info failed with %#x!\n", s32Ret);
return s32Ret;
}
get_local_time_string(time_buf, sizeof(time_buf));
//MISC_TRACE(MODULE_DBG_ERR, "osd time:%s!\n", time_buf);
osd_draw_str_ex(osd_draw_ctx, time_buf, sizeof(time_buf), canvas_info.virt_addr);
s32Ret = export_rgn_update_canvas(osd_time_attr->rgn_hdl);
if (s32Ret != XMEDIA_SUCCESS) {
MISC_TRACE(MODULE_DBG_ERR, "export_rgn_update_canvas failed with %#x!\n", s32Ret);
return s32Ret;
}
return s32Ret;
}
xmedia_s32 osd_time_update_all()
{
xmedia_s32 s32Ret = XMEDIA_SUCCESS;
osd_time_ext_t *p = g_osd_time_ext_hdl;
while(p != XMEDIA_NULL) {
s32Ret |= osd_time_update(&p->osd_time_attr, &p->osd_draw_ctx);
p = p->next;
}
return s32Ret;
}
xmedia_s32 misc_ctl_osd_time_update(xmedia_ulong arg)
{
osd_time_ext_t *p = XMEDIA_NULL;
xmedia_s32 have_found = 0;
misc_osd_time_attr_t *osd_time_attr = (misc_osd_time_attr_t *)arg;
if(osd_time_attr == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR, "input parameter is NULL!\n");
return XMEDIA_ERRCODE_NULL_PTR;
}
if(g_osd_time_ext_hdl == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR, "osd time update failed! because not create this object!!!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
else if(g_osd_time_ext_hdl->osd_time_attr.rgn_hdl == osd_time_attr->rgn_hdl) {
p = g_osd_time_ext_hdl;
}
else if(g_osd_time_ext_hdl->next == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR, "osd time update failed! because not create this object!!!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
else {
p = g_osd_time_ext_hdl;
while(p->next != XMEDIA_NULL) {
if(p->next->osd_time_attr.rgn_hdl == osd_time_attr->rgn_hdl) {
have_found = 1;
break;
}
p = p->next;
}
if(!have_found) {
MISC_TRACE(MODULE_DBG_ERR, "osd time update failed! because not create this object!!!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
}
return osd_time_update(osd_time_attr, &p->osd_draw_ctx);
}
#endif
+362
View File
@@ -0,0 +1,362 @@
#include "drv_export.h"
#include "drv_sensor.h"
#ifdef SUPPORT_SENSOR_PWDN_MODE
#define SENSOR0_PWDN_GPIO_NUM 58 //gpio7-2
#define SENSOR1_PWDN_GPIO_NUM 60 //gpio7-4
#define SENSOR0_PWDN_REG_OFFSET 0x74
#define SENSOR1_PWDN_REG_OFFSET 0x7C
#define GPIO_PINMUX_VALUE 0x1100
static void *pwdn_reg_base = XMEDIA_NULL;
#endif
static misc_aov_isp_info g_isp_info = { 0 };
static misc_aov_state g_aov_state = { 0 };
static xmedia_bool g_misc_do_suspend = XMEDIA_FALSE;
#ifdef SUPPORT_SENSOR_PWDN_MODE
static xmedia_s32 drv_pwdn_sensor_init(xmedia_void)
{
pwdn_reg_base = (void *)osal_ioremap(0x100C0000, (xmedia_u32)0x80);
if (pwdn_reg_base == XMEDIA_NULL) {
MISC_TRACE(MODULE_DBG_ERR,"misc ioremap fail \n");
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_void drv_pwdn_sensor_exit(xmedia_void)
{
osal_iounmap(pwdn_reg_base);
pwdn_reg_base = XMEDIA_NULL;
}
static xmedia_s32 drv_pwdn_sensor_resume(xmedia_s32 isp_pipe)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
xmedia_s32 gpio_num;
if(isp_pipe == 0 && g_isp_info.support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE) {
gpio_num = SENSOR0_PWDN_GPIO_NUM;
//set pinmux
osal_writel(GPIO_PINMUX_VALUE, pwdn_reg_base + SENSOR0_PWDN_REG_OFFSET);
}
else if(isp_pipe == 1 && g_isp_info.support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE) {
gpio_num = SENSOR1_PWDN_GPIO_NUM;
//set pinmux
osal_writel(GPIO_PINMUX_VALUE, pwdn_reg_base + SENSOR1_PWDN_REG_OFFSET);
}
else {
MISC_TRACE(MODULE_DBG_ERR,"isp pipe(%d) is illegal!\n", isp_pipe);
return XMEDIA_FAILURE;
}
s32Ret = gpio_request(gpio_num, NULL);
if (s32Ret) {
return XMEDIA_FAILURE;
}
s32Ret = gpio_direction_output(gpio_num, 1);
if (s32Ret) {
return XMEDIA_FAILURE;
}
gpio_set_value(gpio_num, 1);
gpio_free(gpio_num);
return XMEDIA_SUCCESS;
}
static xmedia_s32 drv_pwdn_sensor_stanby(xmedia_s32 isp_pipe)
{
xmedia_s32 gpio_num;
xmedia_s32 s32Ret = XMEDIA_FAILURE;
if(isp_pipe == 0 && g_isp_info.support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE)
gpio_num = SENSOR0_PWDN_GPIO_NUM;
else if(isp_pipe == 1 && g_isp_info.support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE)
gpio_num = SENSOR1_PWDN_GPIO_NUM;
else {
MISC_TRACE(MODULE_DBG_ERR,"isp pipe(%d) is illegal!\n", isp_pipe);
return XMEDIA_FAILURE;
}
s32Ret = gpio_request(gpio_num, NULL);
if (s32Ret) {
return XMEDIA_FAILURE;
}
s32Ret = gpio_direction_output(gpio_num, 1);
if (s32Ret) {
return XMEDIA_FAILURE;
}
gpio_set_value(gpio_num, 0);
gpio_free(gpio_num);
return XMEDIA_SUCCESS;
}
#endif
static xmedia_s32 drv_i2c_sensor_resume(xmedia_s32 pipe)
{
return export_isp_resume_sensor(pipe);
}
static xmedia_s32 drv_i2c_sensor_suspend(xmedia_s32 pipe)
{
return export_isp_suspend_sensor(pipe);
}
static xmedia_void misc_set_sensor_sync_status(xmedia_bool misc_suspend)
{
g_misc_do_suspend = misc_suspend;
}
static xmedia_bool misc_get_sensor_sync_status(xmedia_void)
{
return g_misc_do_suspend;
}
static xmedia_s32 misc_set_sensor_mode(xmedia_ulong arg)
{
misc_aov_state *aov_state = (misc_aov_state *)arg;
if (aov_state == XMEDIA_NULL) {
return XMEDIA_FAILURE;
}
g_aov_state.en_aov_mode = aov_state->en_aov_mode;
g_aov_state.frame_num = aov_state->frame_num;
misc_set_sensor_sync_status(XMEDIA_FALSE);
return XMEDIA_SUCCESS;
}
static xmedia_s32 misc_get_sensor_mode(misc_aov_state *aov_state)
{
if (aov_state == XMEDIA_NULL) {
return XMEDIA_FAILURE;
}
if (g_aov_state.en_aov_mode == XMEDIA_FALSE || g_aov_state.frame_num == 0) {
return XMEDIA_FAILURE;
}
aov_state->en_aov_mode = g_aov_state.en_aov_mode;
aov_state->frame_num = g_aov_state.frame_num;
return XMEDIA_SUCCESS;
}
static xmedia_s32 misc_sensor_standby(xmedia_s32 pipe)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
xmedia_s32 i = 0;
static xmedia_s32 cur_frame_num[VI_MAX_DEV_NUM] = {0};
misc_aov_state aov_state = {0};
s32Ret = misc_get_sensor_mode(&aov_state);
if (s32Ret != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
if (g_isp_info.isp_pipe_num == 0) {
return XMEDIA_FAILURE;
}
for (i = 0; i < g_isp_info.isp_pipe_num; i++) {
if (pipe == g_isp_info.isp_pipe[i]) {
if (cur_frame_num[i] < (g_aov_state.frame_num - 1)) {
cur_frame_num[i] ++;
} else {
drv_i2c_sensor_suspend(pipe);
cur_frame_num[i] = 0;
}
}
}
#ifdef SUPPORT_SENSOR_PWDN_MODE
if(g_isp_info.support_sensor_pwdn_standby[pipe] == XMEDIA_TRUE) {
drv_pwdn_sensor_stanby(pipe);
}
#endif
misc_set_sensor_sync_status(XMEDIA_TRUE);
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_sensor_init(xmedia_void)
{
#ifdef SUPPORT_SENSOR_PWDN_MODE
return drv_pwdn_sensor_init();
#else
return XMEDIA_SUCCESS;
#endif
}
xmedia_s32 misc_sensor_exit(xmedia_void)
{
#ifdef SUPPORT_SENSOR_PWDN_MODE
drv_pwdn_sensor_exit();
#endif
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_sensor_resume(xmedia_void)
{
xmedia_s32 i = 0;
#ifdef SUPPORT_SENSOR_PWDN_MODE
xmedia_s32 isp_pipe;
#endif
for (i = 0; i < g_isp_info.isp_pipe_num; i++) {
#ifdef SUPPORT_SENSOR_PWDN_MODE
isp_pipe = g_isp_info.isp_pipe[i];
if(g_isp_info.support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE) {
drv_pwdn_sensor_resume(isp_pipe);
}
#endif
drv_i2c_sensor_resume(g_isp_info.isp_pipe[i]);
}
misc_set_sensor_sync_status(XMEDIA_FALSE);
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_media_suspend(xmedia_void)
{
xmedia_s32 media_timeout = 50;//ms
xmedia_s32 try_count = 0;
MISC_TRACE(MODULE_DBG_DEBUG,"misc start!\n");
#ifndef APP_STANDBY_SENSOR
while(1) {
if (misc_get_sensor_sync_status() == XMEDIA_TRUE)
{
break;
}
if (try_count >= (media_timeout / 2))
{
break;
}
try_count++;
osal_udelay(2000);
}
try_count = 0;
#endif
MISC_TRACE(MODULE_DBG_DEBUG,"misc sensor!\n");
while(1) {
if (export_vi_check_busy() == XMEDIA_FALSE) {
break;
}
if (try_count >= (media_timeout / 2))
{
break;
}
try_count++;
osal_udelay(2000);
}
try_count = 0;
while(1) {
if (export_vpss_check_busy() == XMEDIA_FALSE) {
break;
}
if (try_count >= (media_timeout / 2))
{
break;
}
try_count++;
osal_udelay(2000);
}
try_count = 0;
MISC_TRACE(MODULE_DBG_DEBUG,"misc vpss!\n");
while(1) {
if (export_venc_check_busy() == XMEDIA_FALSE) {
break;
}
if (try_count >= (media_timeout / 2))
{
break;
}
try_count++;
osal_udelay(2000);
}
try_count = 0;
MISC_TRACE(MODULE_DBG_DEBUG,"misc venc!\n");
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_ctl_aov_init(xmedia_ulong arg)
{
#ifdef SUPPORT_SENSOR_PWDN_MODE
xmedia_s32 i = 0, isp_pipe;
#endif
misc_aov_isp_info *isp_info = (misc_aov_isp_info *)arg;
if (isp_info == XMEDIA_NULL) {
return XMEDIA_FAILURE;
}
if (isp_info->isp_pipe_num == 0) {
return XMEDIA_FAILURE;
}
memcpy(&g_isp_info, isp_info, sizeof(misc_aov_isp_info));
export_vi_register_misc_aov_callback(misc_sensor_standby);
#ifdef SUPPORT_SENSOR_PWDN_MODE
for (i = 0; i < g_isp_info.isp_pipe_num; i++) {
isp_pipe = g_isp_info.isp_pipe[i];
if(g_isp_info.support_sensor_pwdn_standby[isp_pipe] == XMEDIA_TRUE) {
drv_pwdn_sensor_resume(isp_pipe);
}
}
#endif
return XMEDIA_SUCCESS;
}
xmedia_s32 misc_ctl_aov_set_sensor_mode(xmedia_ulong arg)
{
return misc_set_sensor_mode(arg);
}
#ifdef SUPPORT_SENSOR_PWDN_MODE
xmedia_s32 misc_ctl_sensor_pwdn_standby(xmedia_ulong arg)
{
xmedia_s32 isp_pipe = *(xmedia_s32*)arg;
return drv_pwdn_sensor_stanby(isp_pipe);
}
xmedia_s32 misc_ctl_sensor_pwdn_resume(xmedia_ulong arg)
{
xmedia_s32 isp_pipe = *(xmedia_s32*)arg;
return drv_pwdn_sensor_resume(isp_pipe);
}
#endif
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
@@ -0,0 +1,108 @@
ifeq ($(CFG_SDK_EXPORT_FLAG),)
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../../.. && /bin/pwd)
endif
endif
include $(SDK_DIR)/build/base.mk
CC := $(KERNEL_TOOLCHAIN)-gcc
AR := $(KERNEL_TOOLCHAIN)-ar
NM := $(KERNEL_TOOLCHAIN)-nm
STRIP := $(KERNEL_TOOLCHAIN)-strip
KERNEL_ROOT := $(KERNEL_BUILDDIR)
EXTRA_CFLAGS += $(SDK_KER_CFLAGS)
ARCH_NAME = xm
#$(ARCH_NAME)_osal-objs = osal.o
$(ARCH_NAME)_common-objs = common.o
#$(ARCH_NAME)_pm-objs = pm.o
$(ARCH_NAME)_tde-objs = tde.o
$(ARCH_NAME)_vgs-objs = vgs.o
$(ARCH_NAME)_region-objs = region.o
$(ARCH_NAME)_isp-objs = isp.o
$(ARCH_NAME)_vpss-objs = vpss.o
$(ARCH_NAME)_vi-objs = vi.o
$(ARCH_NAME)_chnl-objs = chnl.o
$(ARCH_NAME)_vedu-objs = vedu.o
$(ARCH_NAME)_rc-objs = rc.o
$(ARCH_NAME)_jpege-objs = jpege.o
$(ARCH_NAME)_h264e-objs = h264e.o
$(ARCH_NAME)_h265e-objs = h265e.o
$(ARCH_NAME)_venc-objs = venc.o
$(ARCH_NAME)_vo-objs = vo.o
$(ARCH_NAME)_fb-objs = fb.o
$(ARCH_NAME)_cipher_drv-objs = cipher_drv.o
$(ARCH_NAME)_acomm-objs = acomm.o
$(ARCH_NAME)_aio-objs = aio.o
$(ARCH_NAME)_ao-objs = ao.o
$(ARCH_NAME)_ai-objs = ai.o
$(ARCH_NAME)_aenc-objs = aenc.o
$(ARCH_NAME)_adec-objs = adec.o
$(ARCH_NAME)_npu-objs = npu.o
$(ARCH_NAME)_ive-objs = ive.o
#$(ARCH_NAME)_ir-objs = ir.o
#$(ARCH_NAME)lsadc-objs = lsadc.o
#
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# $(ARCH_NAME)_drv_init-objs = drv_init.o
#endif
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_osal.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_common.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_pm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_tde.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vgs.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_region.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_isp.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vpss.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vi.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_chnl.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vedu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_rc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_jpege.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h264e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_h265e.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_venc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_vo.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_fb.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_cipher_drv.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_acomm.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aio.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ao.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ai.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_aenc.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_adec.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_npu.o
obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ive.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_ir.o
#obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_lsadc.o
#ifeq ($(XMEDIA_DRV_BUILDTYPE),y)
# obj-$(XMEDIA_DRV_BUILDTYPE) += $(ARCH_NAME)_drv_init.o
#endif
OBJ_DIR:= $(GMP_DIR)/drv/obj_$(OBJ_KERNEL_VERSION)/$(KERNEL_TOOLCHAIN)/$(OBJ_BUILD_TYPE)/$(OBJ_LOG_MODE)
all:
$(AT)make -C $(KERNEL_ROOT) ARCH=arm CROSS_COMPILE=$(KERNEL_TOOLCHAIN)- M=$(OBJ_DIR) modules
$(AT)rm -rf *.mod *.mod.c *.mod.o *.order *.symvers .*.cmd .tmp_versions $(ARCH_NAME)*.o
ifneq ($(XMEDIA_DRV_BUILDTYPE),y)
$(AT)test -d $(SDK_KO_DIR) || mkdir -p $(SDK_KO_DIR)
$(AT)cp -rf $(OBJ_DIR)/*.ko $(SDK_KO_DIR)/
$(AT)rm -f $(OBJ_DIR)/*.ko
$(AT)$(STRIP) --strip-unneeded $(SDK_KO_DIR)/*.ko
endif
clean:
$(AT)rm -rf *.mod *.mod.c *.mod.o *.mod.d *.order *.symvers *.ko .*.cmd .tmp_versions $(ARCH_NAME)*.o ./data/
$(AT)rm -rf $(SDK_KO_DIR)
+18
View File
@@ -0,0 +1,18 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
obj-$(XMEDIA_DRV_BUILDTYPE) += linux/kernel/
.PHONY: all clean
all:
$(AT)$(MAKE) -C linux/kernel
clean:
$(AT)$(MAKE) -C linux/kernel clean
+608
View File
@@ -0,0 +1,608 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __OSAL__
#define __OSAL__
#define OSAL_VERSION "1.0"
#include "osal_list.h"
#include "osal_devfreq.h"
#define osal_gfp_kernel 0
#define osal_gfp_atomic 1
extern void *osal_vmalloc(unsigned long size);
extern void osal_vfree(const void *addr);
extern void *osal_kmalloc(unsigned long size, unsigned int osal_gfp_flag);
extern void osal_kfree(const void *addr);
// atomic api
typedef struct {
void *atomic;
} osal_atomic_t;
#define OSAL_ATOMIC_INIT(i) { (i) }
extern int osal_atomic_init(osal_atomic_t *atomic);
extern void osal_atomic_destory(osal_atomic_t *atomic);
extern void osal_atomic_destroy(osal_atomic_t *atomic);
extern int osal_atomic_read(osal_atomic_t *v);
extern void osal_atomic_set(osal_atomic_t *v, int i);
extern int osal_atomic_inc_return(osal_atomic_t *v);
extern int osal_atomic_dec_return(osal_atomic_t *v);
// semaphore api
#define EINTR 4
typedef struct osal_semaphore {
void *sem;
} osal_semaphore_t;
extern int osal_sema_init(osal_semaphore_t *sem, int val);
extern int osal_down(osal_semaphore_t *sem);
extern int osal_down_interruptible(osal_semaphore_t *sem);
extern int osal_down_trylock(osal_semaphore_t *sem);
extern void osal_up(osal_semaphore_t *sem);
// notice:must be called when kmod exit, other wise will lead to memory leak;
extern void osal_sema_destory(osal_semaphore_t *sem);
extern void osal_sema_destroy(osal_semaphore_t *sem);
// mutex api
typedef struct osal_mutex {
void *mutex;
} osal_mutex_t;
extern int osal_mutex_init(osal_mutex_t *mutex);
extern int osal_mutex_lock(osal_mutex_t *mutex);
extern int osal_mutex_lock_interruptible(osal_mutex_t *mutex);
extern int osal_mutex_trylock(osal_mutex_t *mutex);
extern void osal_mutex_unlock(osal_mutex_t *mutex);
// notice:must be called when kmod exit, other wise will lead to memory leak;
extern void osal_mutex_destroy(osal_mutex_t *mutex);
// spin lock api
typedef struct osal_spinlock {
void *lock;
} osal_spinlock_t;
extern int osal_spin_lock_init(osal_spinlock_t *lock);
extern void osal_spin_lock(osal_spinlock_t *lock);
extern int osal_spin_trylock(osal_spinlock_t *lock);
extern void osal_spin_unlock(osal_spinlock_t *lock);
extern void osal_spin_lock_irqsave(osal_spinlock_t *lock, unsigned long *flags);
extern void osal_spin_unlock_irqrestore(osal_spinlock_t *lock, unsigned long *flags);
// notice:must be called when kmod exit, other wise will lead to memory leak;
extern void osal_spin_lock_destory(osal_spinlock_t *lock);
extern void osal_spin_lock_destroy(osal_spinlock_t *lock);
// wait api
typedef int (*osal_wait_cond_func_t)(const void *param);
typedef struct osal_wait {
void *wait;
} osal_wait_t;
#define ERESTARTSYS 512
extern unsigned long osal_msecs_to_jiffies(const unsigned int m);
extern int osal_wait_init(osal_wait_t *wait);
extern int osal_wait_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param);
extern int osal_wait_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param);
extern int osal_wait_timeout_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param,
unsigned long ms);
extern int osal_wait_timeout_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param,
unsigned long ms);
#define osal_wait_event_interruptible(wait, func, param) \
({ \
int __ret = 0; \
\
for (;;) { \
if (func(param)) { \
__ret = 0; \
break; \
} \
__ret = osal_wait_timeout_interruptible(wait, (func), param, 100); \
if (__ret < 0) \
break; \
} \
__ret; \
})
#define osal_wait_event_uninterruptible(wait, func, param) \
({ \
int __ret = 0; \
\
for (;;) { \
if (func(param)) { \
__ret = 0; \
break; \
} \
__ret = osal_wait_uninterruptible(wait, (func), param); \
if (__ret < 0) \
break; \
} \
__ret; \
})
#define osal_wait_event_timeout_interruptible(wait, func, param, timeout) \
({ \
int __ret = timeout; \
\
if ((func(param)) && !timeout) { \
__ret = 1; \
} \
\
for (;;) { \
if (func(param)) { \
__ret = osal_msecs_to_jiffies(__ret); \
break; \
} \
__ret = osal_wait_timeout_interruptible(wait, (func), param, __ret); \
if (!__ret || __ret == -ERESTARTSYS) \
break; \
} \
__ret; \
})
#define osal_wait_event_timeout_uninterruptible(wait, func, param, timeout) \
({ \
int __ret = timeout; \
\
if ((func(param)) && !timeout) { \
__ret = 1; \
} \
\
for (;;) { \
if (func(param)) { \
__ret = osal_msecs_to_jiffies(__ret); \
break; \
} \
__ret = osal_wait_timeout_uninterruptible(wait, (func), param, __ret); \
if (!__ret || __ret == -ERESTARTSYS) \
break; \
} \
__ret; \
})
extern void osal_wakeup(osal_wait_t *wait); // same as wake_up_all
extern void osal_wait_destory(osal_wait_t *wait);
extern void osal_wait_destroy(osal_wait_t *wait);
// workqueue api
typedef struct osal_work_struct {
void *work;
void (*func)(struct osal_work_struct *work);
} osal_work_struct_t;
typedef void (*osal_work_func_t)(struct osal_work_struct *work);
extern int osal_init_work(struct osal_work_struct *work, osal_work_func_t func);
#define OSAL_INIT_WORK(_work, _func) \
do { \
osal_init_work((_work), (_func)); \
} while (0)
extern int osal_schedule_work(struct osal_work_struct *work);
extern void osal_destroy_work(struct osal_work_struct *work);
// shedule
extern void osal_yield(void);
// interrupt api
enum osal_irqreturn {
OSAL_IRQ_NONE = (0 << 0),
OSAL_IRQ_HANDLED = (1 << 0),
OSAL_IRQ_WAKE_THREAD = (1 << 1),
};
typedef int (*osal_irq_handler_t)(int, void *);
extern int osal_request_irq(unsigned int irq, osal_irq_handler_t handler, osal_irq_handler_t thread_fn,
const char *name, void *dev);
extern void osal_free_irq(unsigned int irq, void *dev);
extern int osal_in_interrupt(void);
#define OSAL_DIS_IRQ_CNT 2
typedef void (*osal_gic_handle_t)(unsigned int, unsigned int, void *);
extern int osal_register_gic_handle(unsigned int index, unsigned int irq, osal_gic_handle_t handle, const char *name,
void *dev);
extern int osal_unregister_gic_handle(unsigned int index, unsigned int irq, void *dev);
// task api
typedef struct osal_task {
void *task_struct;
} osal_task_t;
typedef int (*threadfn_t)(void *data);
extern osal_task_t *osal_kthread_create(threadfn_t thread, void *data, const char *name);
extern void osal_kthread_destory(osal_task_t *task, unsigned int stop_flag);
extern void osal_kthread_destroy(osal_task_t *task, unsigned int stop_flag);
int osal_kthread_should_stop(void);
// string api
extern char *osal_strcpy(char *s1, const char *s2);
extern char *osal_strncpy(char *s1, const char *s2, int size);
extern int osal_strlcpy(char *s1, const char *s2, int size);
extern char *osal_strcat(char *s1, const char *s2);
extern char *osal_strncat(char *s1, const char *s2, int size);
extern int osal_strlcat(char *s1, const char *s2, int size);
extern int osal_strcmp(const char *s1, const char *s2);
extern int osal_strncmp(const char *s1, const char *s2, int size);
extern int osal_strnicmp(const char *s1, const char *s2, int size);
extern int osal_strcasecmp(const char *s1, const char *s2);
extern int osal_strncasecmp(const char *s1, const char *s2, int n);
extern char *osal_strchr(const char *s, int n);
extern char *osal_strnchr(const char *s, int count, int c);
extern char *osal_strrchr(const char *s, int c);
extern char *osal_strstr(const char *s1, const char *s2);
extern char *osal_strnstr(const char *s1, const char *s2, int n);
extern int osal_strlen(const char *s);
extern int osal_strnlen(const char *s, int size);
extern char *osal_strpbrk(const char *s1, const char *s2);
extern char *osal_strsep(char **s, const char *ct);
extern int osal_strspn(const char *s, const char *accept);
extern int osal_strcspn(const char *s, const char *reject);
extern void *osal_memset(void *str, int c, int count);
extern void *osal_memcpy(void *s1, const void *s2, int count);
extern void *osal_memmove(void *s1, const void *s2, int count);
extern void *osal_memscan(void *addr, int c, int size);
extern int osal_memcmp(const void *cs, const void *ct, int count);
extern void *osal_memchr(const void *s, int c, int n);
extern void *osal_memchr_inv(const void *s, int c, int n);
extern unsigned long long osal_strtoull(const char *cp, char **endp, unsigned int base);
extern unsigned long osal_strtoul(const char *cp, char **endp, unsigned int base);
extern long osal_strtol(const char *cp, char **endp, unsigned int base);
extern long long osal_strtoll(const char *cp, char **endp, unsigned int base);
extern int osal_snprintf(char *buf, int size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
extern int osal_scnprintf(char *buf, int size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
extern int osal_sprintf(char *buf, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
extern int osal_sscanf(const char *buf, const char *fmt, ...);
// addr translate
extern void *osal_ioremap(unsigned long phys_addr, unsigned long size);
extern void *osal_ioremap_nocache(unsigned long phys_addr, unsigned long size);
extern void *osal_ioremap_cached(unsigned long phys_addr, unsigned long size);
extern void *osal_ioremap_wc(unsigned long phys_addr, unsigned long size);
extern void osal_iounmap(void *addr);
#define osal_readl(x) (*((volatile int *)(x)))
#define osal_writel(v, x) (*((volatile int *)(x)) = (v))
extern unsigned long osal_copy_from_user(void *to, const void *from, unsigned long n);
extern unsigned long osal_copy_to_user(void *to, const void *from, unsigned long n);
#define OSAL_VERIFY_READ 0
#define OSAL_VERIFY_WRITE 1
extern int osal_access_ok(int type, const void *addr, unsigned long size);
// cache api
extern void osal_flush_cache_all(void);
extern void osal_cpuc_flush_dcache_area(void *addr, int size);
extern void osal_flush_dcache_area(void *kvirt, unsigned long phys_addr, unsigned long length);
extern int osal_flush_dcache_all(void);
// math
extern int osal_isdigit(int c);
extern void osal_kernel_neon_end(void);
extern void osal_kernel_neon_begin(void);
extern unsigned long long osal_div_u64(unsigned long long dividend, unsigned int divisor);
extern long long osal_div_s64(long long dividend, int divisor);
extern unsigned long long osal_div64_u64(unsigned long long dividend, unsigned long long divisor);
extern long long osal_div64_s64(long long dividend, long long divisor);
extern unsigned long long osal_div_u64_rem(unsigned long long dividend, unsigned int divisor);
extern long long osal_div_s64_rem(long long dividend, int divisor);
extern unsigned long long osal_div64_u64_rem(unsigned long long dividend, unsigned long long divisor);
extern unsigned int osal_random(void);
#define osal_max(x, y) ({ \
__typeof__(x) _max1 = (x); \
__typeof__(y) _max2 = (y); \
(void) (&_max1 == &_max2); \
_max1 > _max2 ? _max1 : _max2; })
#define osal_min(x, y) ({ \
__typeof__(x) _min1 = (x); \
__typeof__(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
#define osal_abs(x) ({ \
long ret; \
if (sizeof(x) == sizeof(long)) { \
long __x = (x); \
ret = (__x < 0) ? -__x : __x; \
} else { \
int __x = (x); \
ret = (__x < 0) ? -__x : __x; \
} \
ret; \
})
// barrier
extern void osal_mb(void);
extern void osal_rmb(void);
extern void osal_wmb(void);
extern void osal_smp_mb(void);
extern void osal_smp_rmb(void);
extern void osal_smp_wmb(void);
extern void osal_isb(void);
extern void osal_dsb(void);
extern void osal_dmb(void);
// debug
extern int osal_printk(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
extern void osal_panic(const char *fmt, const char *fun, int line, const char *);
#define OSAL_BUG() \
do { \
} while (1)
#define OSAL_ASSERT(expr) \
do { \
if (!(expr)) { \
osal_printk("\nASSERT failed at:\n" \
" >Condition: %s\n", \
#expr); \
OSAL_BUG(); \
} \
} while (0)
#define OSAL_BUG_ON(expr) \
do { \
if (expr) { \
osal_printk("BUG: failure at %d/%s()!\n", __LINE__, __func__); \
OSAL_BUG(); \
} \
} while (0)
// proc
typedef struct osal_proc_dir_entry {
char name[50];
void *proc_dir_entry;
int (*open)(struct osal_proc_dir_entry *entry);
int (*read)(struct osal_proc_dir_entry *entry);
int (*write)(struct osal_proc_dir_entry *entry, const char *buf, int count, long long *);
void *private;
void *seqfile;
struct osal_list_head node;
} osal_proc_entry_t;
extern osal_proc_entry_t *osal_create_proc_entry(const char *name, osal_proc_entry_t *parent);
extern osal_proc_entry_t *osal_proc_mkdir(const char *name, osal_proc_entry_t *parent);
extern void osal_remove_proc_entry(const char *name, osal_proc_entry_t *parent);
extern void osal_seq_printf(osal_proc_entry_t *entry, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
// device api
#ifndef _IOC_TYPECHECK
#ifdef __KERNEL__
#include "osal_ioctl.h"
#endif
#endif
typedef struct osal_dev {
char name[48];
void *dev;
int minor;
struct osal_fileops *fops;
struct osal_pmops *osal_pmops;
struct osal_devfreq_dev_profile *osal_profile;
} osal_dev_t;
typedef struct osal_devfreq_dev_profile {
unsigned long initial_freq;
unsigned int polling_ms;
int (*target)(osal_dev_t *dev, unsigned long *freq, unsigned int flags);
int (*get_dev_status)(osal_dev_t *dev, struct osal_devfreq_dev_status *stat);
int (*get_cur_freq)(osal_dev_t *dev, unsigned long *freq);
void (*exit)(osal_dev_t *dev);
unsigned long *freq_table;
unsigned int max_state;
} osal_devfreq_dev_profile_t;
typedef struct osal_vm {
void *vm;
} osal_vm_t;
#define OSAL_POLLIN 0x0001
#define OSAL_POLLPRI 0x0002
#define OSAL_POLLOUT 0x0004
#define OSAL_POLLERR 0x0008
#define OSAL_POLLHUP 0x0010
#define OSAL_POLLNVAL 0x0020
#define OSAL_POLLRDNORM 0x0040
#define OSAL_POLLRDBAND 0x0080
#define OSAL_POLLWRNORM 0x0100
typedef struct osal_poll {
void *poll_table;
void *data;
} osal_poll_t;
typedef struct osal_fileops {
int (*open)(void *private_data);
int (*read)(char *buf, int size, long *offset, void *private_data);
int (*write)(const char *buf, int size, long *offset, void *private_data);
long (*llseek)(long offset, int whence, void *private_data);
int (*release)(void *private_data);
long (*unlocked_ioctl)(unsigned int cmd, unsigned long arg, void *private_data);
unsigned int (*poll)(osal_poll_t *osal_poll, void *private_data);
int (*mmap)(osal_vm_t *vm, unsigned long start, unsigned long end, unsigned long vm_pgoff, void *private_data);
#ifdef CONFIG_COMPAT
long (*compat_ioctl)(unsigned int cmd, unsigned long arg, void *private_data);
#endif
} osal_fileops_t;
typedef struct osal_pmops {
int (*pm_prepare)(osal_dev_t *dev);
void (*pm_complete)(osal_dev_t *dev);
int (*pm_suspend)(osal_dev_t *dev);
int (*pm_resume)(osal_dev_t *dev);
int (*pm_freeze)(osal_dev_t *dev);
int (*pm_thaw)(osal_dev_t *dev);
int (*pm_poweroff)(osal_dev_t *dev);
int (*pm_restore)(osal_dev_t *dev);
int (*pm_suspend_late)(osal_dev_t *dev);
int (*pm_resume_early)(osal_dev_t *dev);
int (*pm_freeze_late)(osal_dev_t *dev);
int (*pm_thaw_early)(osal_dev_t *dev);
int (*pm_poweroff_late)(osal_dev_t *dev);
int (*pm_restore_early)(osal_dev_t *dev);
int (*pm_suspend_noirq)(osal_dev_t *dev);
int (*pm_resume_noirq)(osal_dev_t *dev);
int (*pm_freeze_noirq)(osal_dev_t *dev);
int (*pm_thaw_noirq)(osal_dev_t *dev);
int (*pm_poweroff_noirq)(osal_dev_t *dev);
int (*pm_restore_noirq)(osal_dev_t *dev);
} osal_pmops_t;
#define OSAL_SEEK_SET 0
#define OSAL_SEEK_CUR 1
#define OSAL_SEEK_END 2
// #define PAGE_SHIFT 12
extern osal_dev_t *osal_createdev(const char *name);
extern int osal_destroydev(osal_dev_t *pdev);
extern int osal_registerdevice(osal_dev_t *pdev);
extern void osal_deregisterdevice(osal_dev_t *pdev);
extern void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait);
extern void osal_pgprot_noncached(osal_vm_t *vm);
extern void osal_pgprot_cached(osal_vm_t *vm);
extern void osal_pgprot_writecombine(osal_vm_t *vm);
extern void osal_pgprot_stronglyordered(osal_vm_t *vm);
extern int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size);
extern int osal_io_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size);
extern int osal_devfreq_register(osal_dev_t *osal_dev, struct osal_devfreq_dev_profile *osal_profile,
const char *governor, void *data);
extern void osal_devfreq_unregister(osal_dev_t *osal_dev);
// timer
typedef struct osal_timer {
void *timer;
void (*function)(unsigned long);
unsigned long data;
} osal_timer_t;
typedef struct osal_timeval {
long tv_sec;
long tv_usec;
} osal_timeval_t;
typedef struct osal_rtc_time {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
} osal_rtc_time_t;
/* Return values for the timer callback function */
typedef enum OSAL_HRTIMER_RESTART_E {
OSAL_HRTIMER_NORESTART, /* < The timer will not be restarted. */
OSAL_HRTIMER_RESTART /* < The timer must be restarted. */
} OSAL_HRTIMER_RESTART_E;
/* hrtimer struct */
typedef struct osal_hrtimer {
void *timer;
OSAL_HRTIMER_RESTART_E (*function)(void *timer);
unsigned long interval; /* Unit ms */
} osal_hrtimer_t;
extern int osal_hrtimer_create(osal_hrtimer_t *phrtimer);
extern int osal_hrtimer_start(osal_hrtimer_t *phrtimer);
extern int osal_hrtimer_destroy(osal_hrtimer_t *phrtimer);
extern int osal_timer_init(osal_timer_t *timer);
extern int osal_set_timer(osal_timer_t *timer, unsigned long interval); /* ms */
extern unsigned long osal_timer_get_private_data(void *data);
extern int osal_del_timer(osal_timer_t *timer);
extern int osal_timer_destory(osal_timer_t *timer);
extern int osal_timer_destroy(osal_timer_t *timer);
extern unsigned long osal_msleep(unsigned int msecs);
extern void osal_udelay(unsigned int usecs);
extern void osal_mdelay(unsigned int msecs);
extern unsigned int osal_get_tickcount(void);
extern unsigned long long osal_sched_clock(void);
extern void osal_gettimeofday(osal_timeval_t *tv);
/* unit is ns */
extern unsigned long long osal_get_boottime(void);
extern void osal_rtc_time_to_tm(unsigned long time, osal_rtc_time_t *tm);
extern void osal_rtc_tm_to_time(osal_rtc_time_t *tm, unsigned long *time);
extern int osal_rtc_valid_tm(struct osal_rtc_time *tm);
extern void osal_getjiffies(unsigned long long *pjiffies);
#define OSAL_O_ACCMODE 00000003
#define OSAL_O_RDONLY 00000000
#define OSAL_O_WRONLY 00000001
#define OSAL_O_RDWR 00000002
#define OSAL_O_CREAT 00000100
extern void *osal_klib_fopen(const char *filename, int flags, int mode);
extern void osal_klib_fclose(void *filp);
extern int osal_klib_fwrite(const char *buf, int len, void *filp);
extern int osal_klib_fread(char *buf, unsigned int len, void *filp);
// reboot
struct osal_notifier_block {
int (*notifier_call)(struct osal_notifier_block *nb, unsigned long action, void *data);
void *notifier_block;
};
typedef int (*osal_notifier_fn_t)(struct osal_notifier_block *nb, unsigned long action, void *data);
extern int osal_register_reboot_notifier(struct osal_notifier_block *nb);
extern int osal_unregister_reboot_notifier(struct osal_notifier_block *nb);
#include <stdarg.h>
#ifndef _OSAL_VA_LIST
#define _OSAL_VA_LIST
#define osal_va_list va_list
#define osal_va_arg(ap, T) va_arg(ap, T)
#define osal_va_end(ap) va_end(ap)
#define osal_va_start(ap, A) va_start(ap, A)
#endif /* va_arg */
#define NULL_STRING "NULL"
extern void osal_vprintk(const char *fmt, osal_va_list args);
extern int osal_vsnprintf(char *str, int size, const char *fmt, osal_va_list args);
#ifdef CONFIG_SNAPSHOT_BOOT
#ifndef OSAL_UMH_WAIT_PROC
#define OSAL_UMH_WAIT_PROC 2 /* wait for the process to complete */
#endif
extern int osal_call_usermodehelper_force(char *path, char **argv, char **envp, int wait);
#endif
int osal_platform_driver_register(void *drv);
void osal_platform_driver_unregister(void *drv);
void *osal_platform_get_resource_byname(void *dev, unsigned int type, const char *name);
void *osal_platform_get_resource(void *dev, unsigned int type, unsigned int num);
int osal_platform_get_irq(void *dev, unsigned int num);
int osal_platform_get_irq_byname(void *dev, const char *name);
#define osal_module_driver(osal_driver, osal_register, osal_unregister, ...) \
static int __init osal_driver##_init(void) \
{ \
return osal_register(&(osal_driver)); \
} \
module_init(osal_driver##_init); \
static void __exit osal_driver##_exit(void) \
{ \
osal_unregister(&(osal_driver)); \
} \
module_exit(osal_driver##_exit);
#define osal_module_platform_driver(platform_driver) \
osal_module_driver(platform_driver, osal_platform_driver_register, \
osal_platform_driver_unregister)
#endif
@@ -0,0 +1,22 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __OSAL_DEVFREQ__H
#define __OSAL_DEVFREQ__H
typedef struct osal_devfreq_dev_status {
/* both since the last measure */
unsigned long total_time;
unsigned long busy_time;
unsigned long current_frequency;
void *private_data;
} osal_devfreq_dev_status_t;
typedef struct osal_devfreq_para {
unsigned long initial_freq;
unsigned int polling_ms;
unsigned long *freq_table;
unsigned int max_state;
} osal_devfreq_para_t;
#endif /* __OSAL_DEVFREQ__H */
+109
View File
@@ -0,0 +1,109 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _DRV_IOCTL_H
#define _DRV_IOCTL_H
/* ioctl command encoding: 32 bits total, command in lower 16 bits,
* size of the parameter structure in the lower 14 bits of the
* upper 16 bits.
* Encoding the size of the parameter structure in the ioctl request
* is useful for catching programs compiled with old versions
* and to avoid overwriting user space outside the user buffer area.
* The highest 2 bits are reserved for indicating the ``access mode''.
* NOTE: This limits the max parameter size to 16kB -1 !
*/
/*
* The following is for compatibility across the various Linux
* platforms. The generic ioctl numbering scheme doesn't really enforce
* a type field. De facto, however, the top 8 bits of the lower 16
* bits are indeed used as a type field, so we might just as well make
* this explicit here. Please be sure to use the decoding macros
* below from now on.
*/
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
/*
* Let any architecture override either of the following before
* including this file.
*/
#ifndef _IOC_SIZEBITS
#define _IOC_SIZEBITS 14
#endif
#ifndef _IOC_DIRBITS
#define _IOC_DIRBITS 2
#endif
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
#define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
/*
* Direction bits, which any architecture can choose to override
* before including this file.
*/
#ifndef _IOC_NONE
#define _IOC_NONE 0U
#endif
#ifndef _IOC_WRITE
#define _IOC_WRITE 1U
#endif
#ifndef _IOC_READ
#define _IOC_READ 2U
#endif
#define _IOC(dir, type, nr, size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
// #define _IOC_TYPECHECK(t) (sizeof(t))
#ifdef __CHECKER__
#define _IOC_TYPECHECK(t) (sizeof(t))
#else
/* provoke compile error for invalid uses of size argument */
extern unsigned int __invalid_size_argument_for_IOC;
#define _IOC_TYPECHECK(t) \
((sizeof(t) == sizeof(t[1]) && \
sizeof(t) < (1 << _IOC_SIZEBITS)) \
? sizeof(t) \
: __invalid_size_argument_for_IOC)
#endif
/* used to create numbers */
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
#endif /* _DRV_IOCTL_H */
+745
View File
@@ -0,0 +1,745 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _OSAL_LIST_H
#define _OSAL_LIST_H
#define OSAL_NULL (0)
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct osal_list_head {
struct osal_list_head *next, *prev;
};
#define OSAL_LIST_HEAD_INIT(name) \
{ \
&(name), &(name) \
}
#define OSAL_LIST_HEAD(name) \
struct osal_list_head name = OSAL_LIST_HEAD_INIT(name)
static inline void OSAL_INIT_LIST_HEAD(struct osal_list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void osal___list_add(struct osal_list_head *new,
struct osal_list_head *prev,
struct osal_list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void osal_list_add(struct osal_list_head *new, struct osal_list_head *head)
{
osal___list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void osal_list_add_tail(struct osal_list_head *new, struct osal_list_head *head)
{
osal___list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void osal___list_del(struct osal_list_head *prev, struct osal_list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void osal___list_del_entry(struct osal_list_head *entry)
{
osal___list_del(entry->prev, entry->next);
}
#define OSAL_LIST_POISON1 ((void *)0x00100100)
#define OSAL_LIST_POISON2 ((void *)0x00200200)
static inline void osal_list_del(struct osal_list_head *entry)
{
osal___list_del(entry->prev, entry->next);
entry->next = OSAL_LIST_POISON1;
entry->prev = OSAL_LIST_POISON2;
}
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void osal_list_replace(struct osal_list_head *old,
struct osal_list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void osal_list_replace_init(struct osal_list_head *old,
struct osal_list_head *new)
{
osal_list_replace(old, new);
OSAL_INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void osal_list_del_init(struct osal_list_head *entry)
{
osal___list_del_entry(entry);
OSAL_INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void osal_list_move(struct osal_list_head *list, struct osal_list_head *head)
{
osal___list_del_entry(list);
osal_list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void osal_list_move_tail(struct osal_list_head *list,
struct osal_list_head *head)
{
osal___list_del_entry(list);
osal_list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int osal_list_is_last(const struct osal_list_head *list,
const struct osal_list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int osal_list_empty(const struct osal_list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int osal_list_empty_careful(const struct osal_list_head *head)
{
struct osal_list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void osal_list_rotate_left(struct osal_list_head *head)
{
struct osal_list_head *first;
if (!osal_list_empty(head)) {
first = head->next;
osal_list_move_tail(first, head);
}
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int osal_list_is_singular(const struct osal_list_head *head)
{
return !osal_list_empty(head) && (head->next == head->prev);
}
static inline void osal___list_cut_position(struct osal_list_head *list,
struct osal_list_head *head, struct osal_list_head *entry)
{
struct osal_list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void osal_list_cut_position(struct osal_list_head *list,
struct osal_list_head *head, struct osal_list_head *entry)
{
if (osal_list_empty(head)) {
return;
}
if (osal_list_is_singular(head) &&
((head->next != entry) && (head != entry))) {
return;
}
if (entry == head) {
OSAL_INIT_LIST_HEAD(list);
} else {
osal___list_cut_position(list, head, entry);
}
}
static inline void osal___list_splice(const struct osal_list_head *list,
struct osal_list_head *prev,
struct osal_list_head *next)
{
struct osal_list_head *first = list->next;
struct osal_list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void osal_list_splice(const struct osal_list_head *list,
struct osal_list_head *head)
{
if (!osal_list_empty(list)) {
osal___list_splice(list, head, head->next);
}
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void osal_list_splice_tail(struct osal_list_head *list,
struct osal_list_head *head)
{
if (!osal_list_empty(list)) {
osal___list_splice(list, head->prev, head);
}
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void osal_list_splice_init(struct osal_list_head *list,
struct osal_list_head *head)
{
if (!osal_list_empty(list)) {
osal___list_splice(list, head, head->next);
OSAL_INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void osal_list_splice_tail_init(struct osal_list_head *list,
struct osal_list_head *head)
{
if (!osal_list_empty(list)) {
osal___list_splice(list, head->prev, head);
OSAL_INIT_LIST_HEAD(list);
}
}
#undef osal_offsetof
#ifdef __compiler_offsetof
#define osal_offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
#else
#define osal_offsetof(TYPE, MEMBER) ((int)(unsigned long)&((TYPE *)0)->MEMBER)
#endif
#define osal_container_of(ptr, type, member) ({ \
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - osal_offsetof(type,member) ); })
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define osal_list_entry(ptr, type, member) \
osal_container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define osal_list_first_entry(ptr, type, member) \
osal_list_entry((ptr)->next, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define osal_list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant doesn't differ from list_for_each() any more.
* We don't do prefetching in either case.
*/
#define osal___list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define osal_list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define osal_list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define osal_list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define osal_list_for_each_entry(pos, head, member) \
for (pos = osal_list_entry((head)->next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = osal_list_entry(pos->member.next, __typeof__(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define osal_list_for_each_entry_reverse(pos, head, member) \
for (pos = osal_list_entry((head)->prev, __typeof__(*pos), member); \
&pos->member != (head); \
pos = osal_list_entry(pos->member.prev, __typeof__(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define osal_list_prepare_entry(pos, head, member) \
((pos) ?: osal_list_entry(head, __typeof__(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define osal_list_for_each_entry_continue(pos, head, member) \
for (pos = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = osal_list_entry(pos->member.next, __typeof__(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define osal_list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = osal_list_entry(pos->member.prev, __typeof__(*pos), member); \
&pos->member != (head); \
pos = osal_list_entry(pos->member.prev, __typeof__(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define osal_list_for_each_entry_from(pos, head, member) \
for (; &pos->member != (head); \
pos = osal_list_entry(pos->member.next, __typeof__(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define osal_list_for_each_entry_safe(pos, n, head, member) \
for (pos = osal_list_entry((head)->next, __typeof__(*pos), member), \
n = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = n, n = osal_list_entry(n->member.next, __typeof__(*n), member))
/**
* list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define osal_list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = osal_list_entry(pos->member.next, __typeof__(*pos), member), \
n = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = n, n = osal_list_entry(n->member.next, __typeof__(*n), member))
/**
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define osal_list_for_each_entry_safe_from(pos, n, head, member) \
for (n = osal_list_entry(pos->member.next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = n, n = osal_list_entry(n->member.next, __typeof__(*n), member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define osal_list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = osal_list_entry((head)->prev, __typeof__(*pos), member), \
n = osal_list_entry(pos->member.prev, __typeof__(*pos), member); \
&pos->member != (head); \
pos = n, n = osal_list_entry(n->member.prev, __typeof__(*n), member))
/**
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
* @pos: the loop cursor used in the list_for_each_entry_safe loop
* @n: temporary storage used in list_for_each_entry_safe
* @member: the name of the list_struct within the struct.
*
* list_safe_reset_next is not safe to use in general if the list may be
* modified concurrently (eg. the lock is dropped in the loop body). An
* exception to this is if the cursor element (pos) is pinned in the list,
* and list_safe_reset_next is called after re-taking the lock and before
* completing the current iteration of the loop body.
*/
#define osal_list_safe_reset_next(pos, n, member) \
n = osal_list_entry(pos->member.next, __typeof__(*pos), member)
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct osal_hlist_node {
struct osal_hlist_node *next, **pprev;
};
struct osal_hlist_head {
struct osal_hlist_node *first;
};
#define OSAL_HLIST_HEAD_INIT \
{ \
.first = OSAL_NULL \
}
#define OSAL_HLIST_HEAD(name) struct osal_hlist_head name = { .first = OSAL_NULL }
#define INIT_OSAL_HLIST_HEAD(ptr) ((ptr)->first = OSAL_NULL)
static inline void INIT_OSAL_HLIST_NODE(struct osal_hlist_node *h)
{
h->next = OSAL_NULL;
h->pprev = OSAL_NULL;
}
static inline int osal_hlist_unhashed(const struct osal_hlist_node *h)
{
return !h->pprev;
}
static inline int osal_hlist_empty(const struct osal_hlist_head *h)
{
return !h->first;
}
static inline void osal___hlist_del(struct osal_hlist_node *n)
{
struct osal_hlist_node *next = n->next;
struct osal_hlist_node **pprev = n->pprev;
*pprev = next;
if (next) {
next->pprev = pprev;
}
}
static inline void osal_hlist_del(struct osal_hlist_node *n)
{
osal___hlist_del(n);
n->next = OSAL_LIST_POISON1;
n->pprev = OSAL_LIST_POISON2;
}
static inline void osal_hlist_del_init(struct osal_hlist_node *n)
{
if (!osal_hlist_unhashed(n)) {
osal___hlist_del(n);
INIT_OSAL_HLIST_NODE(n);
}
}
static inline void osal_hlist_add_head(struct osal_hlist_node *n, struct osal_hlist_head *h)
{
struct osal_hlist_node *first = h->first;
n->next = first;
if (first) {
first->pprev = &n->next;
}
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void osal_hlist_add_before(struct osal_hlist_node *n,
struct osal_hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void osal_hlist_add_after(struct osal_hlist_node *n,
struct osal_hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if (next->next) {
next->next->pprev = &next->next;
}
}
/* after that we'll appear to be on some hlist and hlist_del will work */
static inline void osal_hlist_add_fake(struct osal_hlist_node *n)
{
n->pprev = &n->next;
}
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void osal_hlist_move_list(struct osal_hlist_head *old,
struct osal_hlist_head *new)
{
new->first = old->first;
if (new->first) {
new->first->pprev = &new->first;
}
old->first = OSAL_NULL;
}
#define osal_hlist_entry(ptr, type, member) osal_container_of(ptr, type, member)
#define osal_hlist_for_each(pos, head) \
for (pos = (head)->first; pos; pos = pos->next)
#define osal_hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define osal_hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && \
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define osal_hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && \
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define osal_hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && \
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define osal_hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = osal_hlist_entry(pos, __typeof__(*tpos), member); 1; }); \
pos = n)
#endif
+241
View File
@@ -0,0 +1,241 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _OSAL_MMZ_H
#define _OSAL_MMZ_H
#include "osal.h"
#define CACHE_LINE_SIZE (0x40)
#define MMZ_MMZ_NAME_LEN 32
#define MMZ_MMB_NAME_LEN 16
struct mmz_media_memory_zone {
char name[MMZ_MMZ_NAME_LEN];
unsigned long gfp;
unsigned long phys_start;
unsigned long nbytes;
struct osal_list_head list;
union {
struct device *cma_dev;
unsigned char *bitmap;
};
struct osal_list_head mmb_list;
unsigned int alloc_type;
unsigned long block_align;
void (*destructor)(const void *);
};
typedef struct mmz_media_memory_zone mmz_mmz_t;
#define MMZ_MMZ_FMT_S "PHYS(0x%08lX, 0x%08lX), GFP=%lu, nBYTES=%luKB, NAME=\"%s\""
#define mmz_mmz_fmt_arg(p) (p)->phys_start, (p)->phys_start + (p)->nbytes - 1, (p)->gfp, (p)->nbytes / SZ_1K, (p)->name
#define MMZ_MMB_NAME_LEN 16
struct mmz_media_memory_block {
#ifndef MMZ_V2_SUPPORT
unsigned int id;
#endif
char name[MMZ_MMB_NAME_LEN];
struct mmz_media_memory_zone *zone;
struct osal_list_head list;
unsigned long phys_addr;
void *kvirt;
unsigned long length;
unsigned long flags;
unsigned int order;
int phy_ref;
int map_ref;
};
typedef struct mmz_media_memory_block mmz_mmb_t;
#define mmz_mmb_kvirt(p) ({mmz_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->kvirt; })
#define mmz_mmb_phys(p) ({mmz_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->phys_addr; })
#define mmz_mmb_length(p) ({mmz_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->length; })
#define mmz_mmb_name(p) ({mmz_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->name; })
#define mmz_mmb_zone(p) ({mmz_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->zone; })
#define MMZ_MMB_MAP2KERN (1 << 0)
#define MMZ_MMB_MAP2KERN_CACHED (1 << 1)
#define MMZ_MMB_RELEASED (1 << 2)
#define MMZ_MMB_FMT_S "phys(0x%08lX, 0x%08lX), kvirt=0x%08lX, flags=0x%08lX, length=%luKB, name=\"%s\""
#define mmz_mmb_fmt_arg(p) (p)->phys_addr, mmz_grain_align((p)->phys_addr + (p)->length) - 1, (unsigned long)(uintptr_t)((p)->kvirt), (p)->flags, (p)->length / SZ_1K, (p)->name
#define DEFAULT_ALLOC 0
#define SLAB_ALLOC 1
#define EQ_BLOCK_ALLOC 2
#define LOW_TO_HIGH 0
#define HIGH_TO_LOW 1
#define MMZ_DBG_LEVEL 0x0
#define mmz_trace(level, s, params...) \
do { \
if (level & MMZ_DBG_LEVEL) \
printk(KERN_INFO "[%s, %d]: " s "\n", __FUNCTION__, __LINE__, params); \
} while (0)
#define mmz_trace_func() mmz_trace(0x02, "%s", __FUNCTION__)
#define MMZ_GRAIN PAGE_SIZE
#define mmz_bitmap_size(p) (mmz_align2(mmz_length2grain((p)->nbytes), 8) / 8)
#define mmz_get_bit(p, n) (((p)->bitmap[(n) / 8] >> ((n)&0x7)) & 0x1)
#define mmz_set_bit(p, n) (p)->bitmap[(n) / 8] |= 1 << ((n)&0x7)
#define mmz_clr_bit(p, n) (p)->bitmap[(n) / 8] &= ~(1 << ((n)&0x7))
#define mmz_pos2phy_addr(p, n) ((p)->phys_start + (n)*MMZ_GRAIN)
#define mmz_phy_addr2pos(p, a) (((a) - (p)->phys_start) / MMZ_GRAIN)
#define mmz_align2low(x, g) (((x) / (g)) * (g))
#define mmz_align2(x, g) ((((x) + (g)-1) / (g)) * (g))
#define mmz_grain_align(x) mmz_align2(x, MMZ_GRAIN)
#define mmz_length2grain(len) (mmz_grain_align(len) / MMZ_GRAIN)
#define begin_list_for_each_mmz(p, gfp, mmz_name) \
list_for_each_entry(p, &mmz_list, list) \
{ \
if (gfp == 0 ? 0 : (p)->gfp != (gfp)) \
continue; \
if ((mmz_name == NULL) || (*mmz_name == '\0')) { \
if (strcmp("anonymous", p->name)) \
continue; \
} else { \
if (strcmp(mmz_name, p->name)) \
continue; \
} \
mmz_trace(1, MMZ_MMZ_FMT_S, mmz_mmz_fmt_arg(p));
#define end_list_for_each_mmz() }
#if defined(KERNEL_BIT_64) && defined(USER_BIT_32)
#define __phys_addr_type__ unsigned long long
#define __phys_len_type__ unsigned long long
#define __phys_addr_align__ __attribute__((aligned(8)))
#else
#define __phys_addr_type__ unsigned long
#define __phys_len_type__ unsigned long
#define __phys_addr_align__ __attribute__((aligned(sizeof(long))))
#endif
struct mmb_info {
__phys_addr_type__ phys_addr; /* phys-memory address */
__phys_addr_type__ __phys_addr_align__ align; /* if you need your phys-memory have special align size */
__phys_len_type__ __phys_addr_align__ size; /* length of memory you need, in bytes */
unsigned int __phys_addr_align__ order;
void *__phys_addr_align__ mapped; /* userspace mapped ptr */
union {
struct
{
unsigned long prot : 8; /* PROT_READ or PROT_WRITE */
unsigned long flags : 12; /* MAP_SHARED or MAP_PRIVATE */
#ifdef __KERNEL__
unsigned long reserved : 7;/* reserved, do not use */
unsigned long kernel_mmb :1;
unsigned long delayed_free : 1;
unsigned long map_cached : 1;
#endif
};
unsigned long w32_stuf;
} __phys_addr_align__;
char mmb_name[MMZ_MMB_NAME_LEN];
char mmz_name[MMZ_MMZ_NAME_LEN];
unsigned long __phys_addr_align__ gfp; /* reserved, do set to 0 */
#ifdef __KERNEL__
int map_ref;
int mmb_ref;
struct osal_list_head list;
mmz_mmb_t *mmb;
#endif
} __attribute__((aligned(8)));
struct dirty_area {
__phys_addr_type__ dirty_phys_start; /* dirty physical address */
void *__phys_addr_align__ dirty_virt_start; /* dirty virtual address,
must be coherent with dirty_phys_addr */
__phys_len_type__ __phys_addr_align__ dirty_size;
} __phys_addr_align__;
#define IOC_MMB_ALLOC _IOWR('m', 10, struct mmb_info)
#define IOC_MMB_ATTR _IOR('m', 11, struct mmb_info)
#define IOC_MMB_FREE _IOW('m', 12, struct mmb_info)
#define IOC_MMB_USER_REMAP _IOWR('m', 20, struct mmb_info)
#define IOC_MMB_USER_REMAP_CACHED _IOWR('m', 21, struct mmb_info)
#define IOC_MMB_USER_UNMAP _IOWR('m', 22, struct mmb_info)
#define IOC_MMB_VIRT_GET_PHYS _IOWR('m', 23, struct mmb_info)
#define IOC_MMB_ADD_REF _IO('r', 30) /* ioctl(file, cmd, arg), arg is mmb_addr */
#define IOC_MMB_DEC_REF _IO('r', 31) /* ioctl(file, cmd, arg), arg is mmb_addr */
#define IOC_MMB_FLUSH_DCACHE _IO('c', 40)
#define IOC_MMB_FLUSH_DCACHE_DIRTY _IOW('d', 50, struct dirty_area)
#define IOC_MMB_TEST_CACHE _IOW('t', 11, struct mmb_info)
#define MMZ_SETUP_CMDLINE_LEN 256
/*
* APIs
*/
extern mmz_mmz_t *mmz_mmz_create(const char *name, unsigned long gfp, unsigned long phys_start,
unsigned long nbytes);
extern int mmz_mmz_destroy(mmz_mmz_t *zone);
extern int mmz_mmz_register(mmz_mmz_t *zone);
extern int mmz_mmz_unregister(mmz_mmz_t *zone);
extern mmz_mmz_t *mmz_mmz_find(unsigned long gfp, const char *mmz_name);
extern mmz_mmb_t *mmz_mmb_alloc(const char *name, unsigned long size, unsigned long align,
unsigned long gfp, const char *mmz_name);
extern int mmz_mmb_free(mmz_mmb_t *mmb);
extern mmz_mmb_t *mmz_mmb_getby_phys(unsigned long addr);
extern mmz_mmb_t *mmz_mmb_getby_phys_2(unsigned long addr, unsigned long *Outoffset); // used in cipher
extern mmz_mmb_t *mmz_mmb_getby_kvirt(void *virt);
extern unsigned long usr_virt_to_phys(unsigned long virt);
extern int mmz_is_phys_in_mmz(unsigned long addr_start, unsigned long addr_len);
extern int mmz_vma_check(unsigned long vm_start, unsigned long vm_end);
extern int mmz_mmb_flush_dcache_byaddr_safe(void *kvirt, unsigned long phys_addr, unsigned long length);
extern unsigned long mmz_mmz_get_phys(const char *zone_name);
#define mmz_mmb_freeby_phys(phys_addr) mmz_mmb_free(mmz_mmb_getby_phys(phys_addr))
extern void *mmz_mmb_map2kern(mmz_mmb_t *mmb);
extern void *mmz_mmb_map2kern_cached(mmz_mmb_t *mmb);
extern int mmz_mmb_flush_dcache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length);
extern int mmz_mmb_invalid_cache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length);
extern int mmz_mmb_unmap(mmz_mmb_t *mmb);
extern int mmz_mmb_get(mmz_mmb_t *mmb);
extern int mmz_mmb_put(mmz_mmb_t *mmb);
extern void *mmz_mmf_map2kern_nocache(unsigned long phys, int len);
extern void *mmz_mmf_map2kern_cache(unsigned long phys, int len);
extern void mmz_mmf_unmap(void *virt);
/* for mmz userdev */
int mmz_userdev_init(void);
void mmz_userdev_exit(void);
int mmz_flush_dcache_all(void);
#endif
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __OSAL_USER__
#define __OSAL_USER__
#ifndef PROT_READ
#define PROT_READ
#endif
#ifndef PROT_WRITE
#define PROT_WRITE
#endif
#ifndef MAP_SHARED
#define MAP_SHARED
#endif
#ifndef MAP_FAILED
#define MAP_FAILED (NULL)
#endif
#endif
+59
View File
@@ -0,0 +1,59 @@
ifneq ($(srctree),)
KERNEL_DIR := $(srctree)
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
else
SDK_DIR := $(shell cd $(CURDIR)/../../../../../.. && /bin/pwd)
endif
include $(SDK_DIR)/build/base.mk
include $(SDK_DIR)/build/version.mk
OSAL_ROOT := $(GMP_DIR)/drv/osal
MOD_NAME := xm_osal
SRCS := osal_fileops.c \
osal_vmalloc.c \
osal_addr.c \
osal_init.c \
osal_atomic.c \
osal_barrier.c \
osal_cache.c \
osal_debug.c \
osal_device.c \
osal_interrupt.c \
osal_math.c \
osal_mutex.c \
osal_proc.c \
osal_schedule.c \
osal_semaphore.c \
osal_spinlock.c \
osal_string.c \
osal_task.c \
osal_timer.c \
osal_wait.c \
osal_workqueue.c \
osal_notifier.c \
osal_platform.c
SRCS += ./media/base.c \
./media/media.c \
./mmz/media-mem.c \
./mmz/mmz-userdev.c \
./mmz/drv_mmz.c \
./mmz/allocator.c
ifeq ($(CONFIG_CMA),y)
SRCS += ./mmz/cma_allocator.c
endif
SDK_KER_CFLAGS += -D$(CHIPSET) -DRELEASE -DUSER_BIT_32 -DKERNEL_BIT_32 -Wno-date-time -D_GNU_SOURCE
SDK_KER_CFLAGS += -I$(OSAL_ROOT)/include \
-I$(OSAL_ROOT)/linux/kernel \
-I$(OSAL_ROOT)/linux/kernel/media \
-I$(OSAL_ROOT)/linux/kernel/mmz \
-I$(GMP_DIR)/drv/include \
-I$(GMP_DIR)/include
include $(SDK_DIR)/build/sdk_ko_rules.mk
+362
View File
@@ -0,0 +1,362 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include "base.h"
/*****************************************************************************/
/**** media bus ****/
/*****************************************************************************/
static void media_bus_release(struct device *dev)
{
return;
}
struct device media_bus = {
// change media_bus name from "media" to "gmp", because bus "media" is used in kenrel
.init_name = "gmp",
.release = media_bus_release
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
/* sysfs modalias store/show */
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
char *buf)
{
struct media_device *pdev = to_media_device(dev);
int len = snprintf(buf, PAGE_SIZE, "media:%s\n", pdev->devfs_name);
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}
static struct device_attribute media_dev_attrs[] = {
__ATTR_RO(modalias),
__ATTR_NULL,
};
#endif
/* bus match & uevent */
static int media_match(struct device *dev, struct device_driver *drv)
{
struct media_device *pdev = to_media_device(dev);
return (strncmp(pdev->devfs_name, drv->name, sizeof(pdev->devfs_name)) == 0);
}
static int media_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct media_device *pdev = to_media_device(dev);
add_uevent_var(env, "MODALIAS=media:%s", pdev->devfs_name);
return 0;
}
/*****************************************************************************/
// pm methods
static int media_pm_prepare(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_prepare == NULL)) {
return 0;
}
return pdrv->ops->pm_prepare(pdev);
}
static void media_pm_complete(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_complete == NULL)) {
return;
}
pdrv->ops->pm_complete(pdev);
}
static int media_pm_suspend(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_suspend == NULL)) {
return 0;
}
return pdrv->ops->pm_suspend(pdev);
}
static int media_pm_resume(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_resume == NULL)) {
return 0;
}
return pdrv->ops->pm_resume(pdev);
}
static int media_pm_freeze(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_freeze == NULL)) {
return 0;
}
return pdrv->ops->pm_freeze(pdev);
}
static int media_pm_thaw(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_thaw == NULL)) {
return 0;
}
return pdrv->ops->pm_thaw(pdev);
}
static int media_pm_poweroff(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_poweroff == NULL)) {
return 0;
}
return pdrv->ops->pm_poweroff(pdev);
}
static int media_pm_restore(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_restore == NULL)) {
return 0;
}
return pdrv->ops->pm_restore(pdev);
}
static int media_pm_suspend_noirq(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_suspend_noirq == NULL)) {
return 0;
}
return pdrv->ops->pm_suspend_noirq(pdev);
}
static int media_pm_resume_noirq(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_resume_noirq == NULL)) {
return 0;
}
return pdrv->ops->pm_resume_noirq(pdev);
}
static int media_pm_freeze_noirq(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_freeze_noirq == NULL)) {
return 0;
}
return pdrv->ops->pm_freeze_noirq(pdev);
}
static int media_pm_thaw_noirq(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_thaw_noirq == NULL)) {
return 0;
}
return pdrv->ops->pm_thaw_noirq(pdev);
}
static int media_pm_poweroff_noirq(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_poweroff_noirq == NULL)) {
return 0;
}
return pdrv->ops->pm_poweroff_noirq(pdev);
}
static int media_pm_restore_noirq(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->pm_restore_noirq == NULL)) {
return 0;
}
return pdrv->ops->pm_restore_noirq(pdev);
}
static struct dev_pm_ops media_bus_pm_ops = {
.prepare = media_pm_prepare,
.complete = media_pm_complete,
// with irq
.suspend = media_pm_suspend,
.resume = media_pm_resume,
.freeze = media_pm_freeze,
.thaw = media_pm_thaw,
.poweroff = media_pm_poweroff,
.restore = media_pm_restore,
// with noirq
.suspend_noirq = media_pm_suspend_noirq,
.resume_noirq = media_pm_resume_noirq,
.freeze_noirq = media_pm_freeze_noirq,
.thaw_noirq = media_pm_thaw_noirq,
.poweroff_noirq = media_pm_poweroff_noirq,
.restore_noirq = media_pm_restore_noirq,
};
struct bus_type media_bus_type = {
// change media_bus name from "media" to "gmp", because bus "media" is used in kenrel
.name = "gmp",
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
.dev_attrs = media_dev_attrs,
#endif
.match = media_match,
.uevent = media_uevent,
.pm = &media_bus_pm_ops,
};
int media_bus_init(void)
{
int ret;
ret = device_register(&media_bus);
if (ret) {
return ret;
}
ret = bus_register(&media_bus_type);
if (ret) {
goto error;
}
return 0;
error:
device_unregister(&media_bus);
return ret;
}
void media_bus_exit(void)
{
bus_unregister(&media_bus_type);
device_unregister(&media_bus);
}
static void media_device_release(struct device *dev)
{
return;
}
int _media_device_register(struct media_device *pdev)
{
dev_set_name(&pdev->device, "%s", pdev->devfs_name);
pdev->device.devt = MKDEV(MEDIA_DEVICE_MAJOR, pdev->minor);
pdev->device.release = media_device_release;
pdev->device.bus = &media_bus_type;
return device_register(&pdev->device);
}
void _media_device_unregister(struct media_device *pdev)
{
device_unregister(&pdev->device);
}
struct media_driver *media_driver_register(const char *name,
struct module *owner, struct media_ops *ops)
{
int ret;
struct media_driver *pdrv = NULL;
#ifdef MODULE
if ((name == NULL) || (owner == NULL)) {
#else
if (name == NULL){
#endif
return ERR_PTR(-EINVAL);
}
pdrv = kzalloc(sizeof(struct media_driver) + strnlen(name, MEDIA_MAX_DEV_NAME_LEN), GFP_KERNEL);
if (pdrv == NULL) {
return ERR_PTR(-ENOMEM);
}
/* init driver object */
strncpy(pdrv->name, name, strnlen(name, MEDIA_MAX_DEV_NAME_LEN));
pdrv->ops = ops;
pdrv->driver.name = pdrv->name;
pdrv->driver.owner = owner;
pdrv->driver.bus = &media_bus_type;
ret = driver_register(&pdrv->driver);
if (ret) {
kfree(pdrv);
return ERR_PTR(ret);
}
return pdrv;
}
void media_driver_unregister(struct media_driver *pdrv)
{
if (pdrv != NULL) {
driver_unregister(&pdrv->driver);
kfree(pdrv);
}
}
// end!
/*****************************************************************************/
@@ -0,0 +1,31 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _MEDIA_BASE_H_
#define _MEDIA_BASE_H_
#include "media.h"
int media_bus_init(void);
void media_bus_exit(void);
#if 0
struct device *_media_device_register(struct class *class,
dev_t devt, const char *name);
void _media_device_unregister(struct class *class, dev_t devt);
#else
int _media_device_register(struct media_device *pdev);
void _media_device_unregister(struct media_device *pdev);
#endif
struct media_driver *media_driver_register(const char *name,
struct module *owner, struct media_ops *ops);
void media_driver_unregister(struct media_driver *pdrv);
#endif
@@ -0,0 +1,343 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/devfreq.h>
#include "base.h"
#include "osal_devfreq.h"
static OSAL_LIST_HEAD(media_list);
static DEFINE_MUTEX(media_sem);
/*
* Assigned numbers, used for dynamic minors
*/
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char media_minors[DYNAMIC_MINORS / 8];
int media_devfreq_target(struct device *dev, unsigned long *freq, unsigned int flags)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_target == NULL)) {
return 0;
}
return pdrv->ops->devfreq_target(pdev, freq, flags);
}
int media_devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *stat)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
osal_devfreq_dev_status_t pstat;
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_get_dev_status == NULL)) {
return 0;
}
pstat.total_time = stat->total_time;
pstat.busy_time = stat->busy_time;
pstat.current_frequency = stat->current_frequency;
pstat.private_data = stat->private_data;
return pdrv->ops->devfreq_get_dev_status(pdev, &pstat);
}
int media_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_get_cur_freq == NULL)) {
return 0;
}
return pdrv->ops->devfreq_get_cur_freq(pdev, freq);
}
void media_devfreq_exit(struct device *dev)
{
struct media_device *pdev = to_media_device(dev);
struct media_driver *pdrv = to_media_driver(dev->driver);
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_exit == NULL)) {
return;
}
return pdrv->ops->devfreq_exit(pdev);
}
int media_devfreq_register(struct media_device *media, osal_devfreq_para_t *devfreq_para)
{
struct device *dev = (struct device *)&media->device;
struct devfreq_dev_profile *profile = &(media->profile);
profile->initial_freq = devfreq_para->initial_freq;
profile->polling_ms = devfreq_para->polling_ms;
profile->target = media_devfreq_target;
profile->get_dev_status = media_devfreq_get_dev_status;
profile->get_cur_freq = media_devfreq_get_cur_freq;
profile->exit = media_devfreq_exit;
profile->freq_table = devfreq_para->freq_table;
profile->max_state = devfreq_para->max_state;
media->devfreq = devm_devfreq_add_device(dev, profile, "userspace", NULL);
if (IS_ERR(media->devfreq)) {
printk("failed to add devfreq device\n");
return -1;
}
return 0;
}
void media_devfreq_unregister(struct media_device *media)
{
struct device *dev = (struct device *)&media->device;
devm_devfreq_remove_device(dev, media->devfreq);
return;
}
static int media_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
struct media_device *c = NULL;
int err = -ENODEV;
const struct file_operations *old_fops, *new_fops = NULL;
mutex_lock(&media_sem);
osal_list_for_each_entry(c, &media_list, list) {
if (c->minor == minor) {
new_fops = fops_get(c->fops);
break;
}
}
if (new_fops == NULL) {
mutex_unlock(&media_sem);
request_module("char-major-%d-%d", MEDIA_DEVICE_MAJOR, minor);
mutex_lock(&media_sem);
osal_list_for_each_entry(c, &media_list, list) {
if (c->minor == minor) {
new_fops = fops_get(c->fops);
break;
}
}
if (new_fops == NULL) {
goto fail;
}
}
err = 0;
old_fops = file->f_op;
file->f_op = new_fops;
if (file->f_op->open) {
file->private_data = c;
err = file->f_op->open(inode, file);
if (err) {
fops_put(file->f_op);
file->private_data = NULL;
file->f_op = fops_get(old_fops);
}
}
fops_put(old_fops);
fail:
mutex_unlock(&media_sem);
return err;
}
static struct file_operations media_fops = {
.owner = THIS_MODULE,
.open = media_open,
};
/**
* media_register - register a media device
* @media: device structure
*
* Register a media device with the kernel. If the minor
* number is set to %MEDIA_DYNAMIC_MINOR a minor number is assigned
* and placed in the minor field of the structure. For other cases
* the minor number requested is used.
*
* The structure passed is linked into the kernel and may not be
* destroyed until it has been unregistered.
*
* A zero is returned on success and a negative errno code for
* failure.
*/
int media_register(struct media_device *media)
{
struct media_device *ptmp = NULL;
struct media_driver *pdrv = NULL;
int err = 0;
mutex_lock(&media_sem);
/* check if registered */
osal_list_for_each_entry(ptmp, &media_list, list) {
if (ptmp->minor == media->minor) {
mutex_unlock(&media_sem);
return -EBUSY;
}
}
/* check minor */
if (media->minor == MEDIA_DYNAMIC_MINOR) {
int i = DYNAMIC_MINORS;
while (--i >= 0)
if ((media_minors[(unsigned int)i >> 3] & (1 << ((unsigned int)i & 7))) == 0) {
break;
}
if (i < 0) {
mutex_unlock(&media_sem);
return -EBUSY;
}
media->minor = i;
}
if (media->minor < DYNAMIC_MINORS) {
media_minors[media->minor >> 3] |= 1 << (media->minor & 7);
}
/* device register */
err = _media_device_register(media);
if (err < 0) {
media_minors[media->minor >> 3] &= ~(1 << (media->minor & 7));
goto out;
}
/* driver register */
pdrv = media_driver_register(media->devfs_name, media->owner, media->drvops);
if (IS_ERR(pdrv)) {
_media_device_unregister(media);
media_minors[media->minor >> 3] &= ~(1 << (media->minor & 7));
err = PTR_ERR(pdrv);
goto out;
}
media->driver = pdrv;
/*
* Add it to the front, so that later devices can "override"
* earlier defaults
*/
osal_list_add(&media->list, &media_list);
out:
mutex_unlock(&media_sem);
return err;
}
EXPORT_SYMBOL(media_register);
/**
* media_unregister - unregister a media device
* @media: device to unregister
*
* Unregister a media device that was previously
* successfully registered with media_register(). Success
* is indicated by a zero return, a negative errno code
* indicates an error.
*/
int media_unregister(struct media_device *media)
{
struct media_device *ptmp = NULL, *_ptmp = NULL;
if (osal_list_empty(&media->list)) {
return -EINVAL;
}
mutex_lock(&media_sem);
osal_list_for_each_entry_safe(ptmp, _ptmp, &media_list, list) {
/* if found, unregister device & driver */
if (ptmp->minor == media->minor) {
osal_list_del(&media->list);
media_driver_unregister(media->driver);
media->driver = NULL;
_media_device_unregister(media);
media_minors[media->minor >> 3] &= ~(1 << (media->minor & 7));
break;
}
}
mutex_unlock(&media_sem);
return 0;
}
EXPORT_SYMBOL(media_unregister);
int media_init(void)
{
int ret;
// 1
ret = media_bus_init();
if (ret) {
goto err0;
}
// 2
ret = -EIO;
if (register_chrdev(MEDIA_DEVICE_MAJOR, "media", &media_fops)) {
goto err1;
}
printk("Module media: init ok\n");
return 0;
// 3
err1:
media_bus_exit();
err0:
return ret;
}
void media_exit(void)
{
// 0
if (!osal_list_empty(&media_list)) {
printk("!!! Module media: sub module in list\n");
return;
}
unregister_chrdev(MEDIA_DEVICE_MAJOR, "media");
media_bus_exit();
printk("!!! Module media: exit ok\n");
}
@@ -0,0 +1,100 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _LINUX_MEDIA_DEVICE_H_
#define _LINUX_MEDIA_DEVICE_H_
#include <linux/module.h>
#include <linux/major.h>
#include <linux/device.h>
#include <linux/devfreq.h>
#include "osal_list.h"
#include "osal_devfreq.h"
#define MEDIA_DEVICE_MAJOR 218
#define MEDIA_DYNAMIC_MINOR 255
struct media_device;
struct media_ops {
// pm methos
int (*pm_prepare)(struct media_device *);
void (*pm_complete)(struct media_device *);
int (*pm_suspend)(struct media_device *);
int (*pm_resume)(struct media_device *);
int (*pm_freeze)(struct media_device *);
int (*pm_thaw)(struct media_device *);
int (*pm_poweroff)(struct media_device *);
int (*pm_restore)(struct media_device *);
int (*pm_suspend_late)(struct media_device *);
int (*pm_resume_early)(struct media_device *);
int (*pm_freeze_late)(struct media_device *);
int (*pm_thaw_early)(struct media_device *);
int (*pm_poweroff_late)(struct media_device *);
int (*pm_restore_early)(struct media_device *);
int (*pm_suspend_noirq)(struct media_device *);
int (*pm_resume_noirq)(struct media_device *);
int (*pm_freeze_noirq)(struct media_device *);
int (*pm_thaw_noirq)(struct media_device *);
int (*pm_poweroff_noirq)(struct media_device *);
int (*pm_restore_noirq)(struct media_device *);
/* devfreq */
int (*devfreq_target)(struct media_device *, unsigned long *, unsigned int);
int (*devfreq_get_dev_status)(struct media_device *, struct osal_devfreq_dev_status *);
int (*devfreq_get_cur_freq)(struct media_device *, unsigned long *);
void (*devfreq_exit)(struct media_device *);
};
#define MEDIA_MAX_DEV_NAME_LEN 32
struct media_driver {
struct device_driver driver;
struct media_ops *ops;
char name[1];
};
#define to_media_driver(drv) \
container_of((drv), struct media_driver, driver)
struct media_device {
struct osal_list_head list;
char devfs_name[MEDIA_MAX_DEV_NAME_LEN];
unsigned int minor;
struct device device;
struct module *owner;
const struct file_operations *fops;
struct media_ops *drvops;
/* for internal use */
struct media_driver *driver;
struct devfreq *devfreq;
struct devfreq_dev_profile profile;
};
#define to_media_device(dev) \
container_of((dev), struct media_device, device)
int media_devfreq_register(struct media_device *media, osal_devfreq_para_t *devfreq_para);
void media_devfreq_unregister(struct media_device *media);
int media_register(struct media_device *pdev);
int media_unregister(struct media_device *pdev);
#define MODULE_ALIAS_MEDIA(minor) \
MODULE_ALIAS("media-char-major-" __stringify(MEDIA_DEVICE_MAJOR) "-" __stringify(minor))
#endif /* _LINUX_MEDIA_DEVICE_H_ */
@@ -0,0 +1,419 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/list.h>
#include <asm/cacheflush.h>
#include <linux/version.h>
#include "allocator.h"
#ifndef fallthrough
#define fallthrough
#endif
extern struct osal_list_head mmz_list;
long long max_malloc_size = 0x40000000UL;
static unsigned long _strtoul_ex(const char *s, char **ep, unsigned int base)
{
char *__end_p = NULL;
unsigned long __value;
__value = simple_strtoul(s, &__end_p, base);
switch (*__end_p) {
case 'm':
fallthrough;
case 'M':
__value <<= 10;
fallthrough;
case 'k':
fallthrough;
case 'K':
__value <<= 10;
if (ep != NULL) {
(*ep) = __end_p + 1;
}
fallthrough;
default:
break;
}
return __value;
}
static unsigned long find_fixed_region(unsigned long *region_len,
mmz_mmz_t *mmz,
unsigned long size,
unsigned long align)
{
unsigned long start;
unsigned long fixed_start = 0;
unsigned long fixed_len = -1;
unsigned long len = 0;
unsigned long blank_len = 0;
mmz_mmb_t *p = NULL;
mmz_trace_func();
align = mmz_grain_align(align);
if (align == 0) {
align = MMZ_GRAIN;
}
start = mmz_align2(mmz->phys_start, align);
len = mmz_grain_align(size);
list_for_each_entry(p, &mmz->mmb_list, list) {
mmz_mmb_t *next = NULL;
mmz_trace(4, "p->phys_addr=0x%08lX p->length = %luKB \t",
p->phys_addr, p->length / SZ_1K);
next = list_entry(p->list.next, typeof(*p), list);
mmz_trace(4, ",next = 0x%08lX\n\n", next->phys_addr);
/*
* if p is the first entry or not.
*/
if (list_first_entry(&mmz->mmb_list, typeof(*p), list) == p) {
blank_len = p->phys_addr - start;
if ((blank_len < fixed_len) && (blank_len >= len)) {
fixed_len = blank_len;
fixed_start = start;
mmz_trace(4, "%d: fixed_region: start=0x%08lX, len=%luKB\n",
__LINE__, fixed_start, fixed_len / SZ_1K);
}
}
start = mmz_align2((p->phys_addr + p->length), align);
/*
* if aglin is larger than mmz->nbytes, it would trigger the BUG_ON
*/
// BUG_ON((start < mmz->phys_start) || (start > (mmz->phys_start + mmz->nbytes)));
/*
* if we have to alloc after the last node.
*/
if (osal_list_is_last(&p->list, &mmz->mmb_list)) {
blank_len = mmz->phys_start + mmz->nbytes - start;
if ((blank_len < fixed_len) && (blank_len >= len)) {
fixed_len = blank_len;
fixed_start = start;
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
fixed_start, fixed_len / SZ_1K);
break;
} else {
if (fixed_len != -1) {
goto out;
}
fixed_start = 0;
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
fixed_start, fixed_len / SZ_1K);
goto out;
}
}
/* blank is too small */
if ((start + len) > next->phys_addr) {
mmz_trace(4, "start=0x%08lX ,len=%lu,next=0x%08lX\n",
start, len, next->phys_addr);
continue;
}
blank_len = next->phys_addr - start;
if ((blank_len < fixed_len) && (blank_len >= len)) {
fixed_len = blank_len;
fixed_start = start;
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
fixed_start, fixed_len / SZ_1K);
}
}
if ((mmz_grain_align(start + len) <= (mmz->phys_start + mmz->nbytes)) &&
(start >= mmz->phys_start) &&
(start < (mmz->phys_start + mmz->nbytes))) {
fixed_len = len;
fixed_start = start;
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
fixed_start, fixed_len / SZ_1K);
} else {
fixed_start = 0;
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
fixed_start, len / SZ_1K);
}
out:
*region_len = len;
return fixed_start;
}
static int do_mmb_alloc(mmz_mmb_t *mmb)
{
mmz_mmb_t *p = NULL;
mmz_trace_func();
/* add mmb sorted */
osal_list_for_each_entry(p, &mmb->zone->mmb_list, list) {
if (mmb->phys_addr < p->phys_addr) {
break;
}
if (mmb->phys_addr == p->phys_addr) {
printk(KERN_ERR "ERROR: media-mem allocator bad in %s! (%s, %d)",
mmb->zone->name, __FUNCTION__, __LINE__);
}
}
osal_list_add(&mmb->list, p->list.prev);
mmz_trace(1, MMZ_MMB_FMT_S, mmz_mmb_fmt_arg(mmb));
return 0;
}
static mmz_mmb_t *__mmb_alloc(const char *name,
unsigned long size,
unsigned long align,
unsigned long gfp,
const char *mmz_name,
mmz_mmz_t *_user_mmz)
{
mmz_mmz_t *mmz = NULL;
mmz_mmb_t *mmb = NULL;
unsigned long start;
unsigned long region_len;
unsigned long fixed_start = 0;
unsigned long fixed_len = ~1;
mmz_mmz_t *fixed_mmz = NULL;
mmz_trace_func();
if ((size == 0) || (size > max_malloc_size)) {
return NULL;
}
if (align == 0) {
align = MMZ_GRAIN;
}
size = mmz_grain_align(size);
mmz_trace(1, "size=%luKB, align=%lu", size / SZ_1K, align);
begin_list_for_each_mmz(mmz, gfp, mmz_name)
if ((_user_mmz != NULL) && (_user_mmz != mmz)) {
continue;
}
start = find_fixed_region(&region_len, mmz, size, align);
if ((fixed_len > region_len) && (start != 0)) {
fixed_len = region_len;
fixed_start = start;
fixed_mmz = mmz;
}
end_list_for_each_mmz()
if (fixed_mmz == NULL) {
return NULL;
}
mmb = kmalloc(sizeof(mmz_mmb_t), GFP_KERNEL);
if (mmb == NULL) {
return NULL;
}
memset(mmb, 0, sizeof(mmz_mmb_t));
mmb->zone = fixed_mmz;
mmb->phys_addr = fixed_start;
mmb->length = size;
if (name != NULL) {
strlcpy(mmb->name, name, MMZ_MMB_NAME_LEN);
} else {
strncpy(mmb->name, "<null>", MMZ_MMB_NAME_LEN);
}
if (do_mmb_alloc(mmb)) {
kfree(mmb);
mmb = NULL;
}
return mmb;
}
static void *__mmb_map2kern(mmz_mmb_t *mmb, int cached)
{
/*
* already mapped? no need to remap again,
* just return mmb's kernel virtual address.
*/
if (mmb->flags & MMZ_MMB_MAP2KERN) {
if ((!!cached * MMZ_MMB_MAP2KERN_CACHED) != (mmb->flags & MMZ_MMB_MAP2KERN_CACHED)) {
printk(KERN_ERR "mmb<%s> has been kernel-mapped as %s, \
can not be re-mapped as %s.",
mmb->name,
(mmb->flags & MMZ_MMB_MAP2KERN_CACHED) ? "cached" : "non-cached",
(cached) ? "cached" : "non-cached");
return NULL;
}
mmb->map_ref++;
return mmb->kvirt;
}
if (cached) {
mmb->flags |= MMZ_MMB_MAP2KERN_CACHED;
mmb->kvirt = ioremap_cache(mmb->phys_addr, mmb->length);
} else {
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
/* ioremap_wc has better performance */
mmb->kvirt = ioremap_wc(mmb->phys_addr, mmb->length);
}
if (mmb->kvirt) {
mmb->flags |= MMZ_MMB_MAP2KERN;
mmb->map_ref++;
} else {
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
}
return mmb->kvirt;
}
static void __mmb_free(mmz_mmb_t *mmb)
{
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
#ifdef CONFIG_64BIT
__flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
#else
__cpuc_flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
outer_flush_range(mmb->phys_addr, mmb->phys_addr + mmb->length);
#endif
}
osal_list_del(&mmb->list);
kfree(mmb);
}
static int __mmb_unmap(mmz_mmb_t *mmb)
{
int ref;
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
#ifdef CONFIG_64BIT
__flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
#else
__cpuc_flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
outer_flush_range(mmb->phys_addr, mmb->phys_addr + mmb->length);
#endif
}
if (mmb->flags & MMZ_MMB_MAP2KERN) {
ref = --mmb->map_ref;
if (mmb->map_ref != 0) {
return ref;
}
iounmap(mmb->kvirt);
}
mmb->kvirt = NULL;
mmb->flags &= ~MMZ_MMB_MAP2KERN;
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
if ((mmb->flags & MMZ_MMB_RELEASED) && (mmb->phy_ref == 0)) {
__mmb_free(mmb);
}
return 0;
}
static void *__mmf_map(phys_addr_t phys, int len, int cache)
{
void *virt = NULL;
if (cache) {
virt = ioremap_cache(phys, len);
} else {
virt = ioremap_wc(phys, len);
}
return virt;
}
static void __mmf_unmap(void *virt)
{
if (virt != NULL) {
iounmap(virt);
}
}
static int __allocator_init(char *s)
{
mmz_mmz_t *zone = NULL;
char *line = NULL;
unsigned long phys_end = 0;
while ((line = strsep(&s, ":")) != NULL) {
int i;
char *argv[6];
for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;)
if (++i == ARRAY_SIZE(argv)) {
break;
}
if (i == 4) {
zone = mmz_mmz_create("null", 0, 0, 0);
if (zone == NULL) {
continue;
}
strlcpy(zone->name, argv[0], MMZ_MMZ_NAME_LEN);
zone->gfp = _strtoul_ex(argv[1], NULL, 0);
zone->phys_start = _strtoul_ex(argv[2], NULL, 0);
zone->nbytes = _strtoul_ex(argv[3], NULL, 0);
if (zone->nbytes > max_malloc_size) {
max_malloc_size = zone->nbytes;
}
} else {
printk(KERN_ERR "error parameters\n");
return -EINVAL;
}
// mmz_info_phys_start = zone->phys_start + zone->nbytes - 0x2000;
if (mmz_mmz_register(zone)) {
printk(KERN_WARNING "Add MMZ failed: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(zone));
mmz_mmz_destroy(zone);
return -1;
}
// if phys_end is 0xFFFFFFFF (32bit)
phys_end = (zone->phys_start + zone->nbytes);
if ((phys_end == 0) && (zone->nbytes >= PAGE_SIZE)) {
// reserve last PAGE_SIZE memory
zone->nbytes = zone->nbytes - PAGE_SIZE;
}
// if phys_end exceed 0xFFFFFFFF (32bit), wraping error
if ((zone->phys_start > phys_end) && (phys_end != 0)) {
printk(KERN_ERR "MMZ: parameter is not correct! Address exceeds 0xFFFFFFFF\n");
mmz_mmz_unregister(zone);
mmz_mmz_destroy(zone);
return -1;
}
zone = NULL;
}
return 0;
}
int allocator_setopt(struct mmz_allocator *allocator)
{
allocator->init = __allocator_init;
allocator->mmb_alloc = __mmb_alloc;
allocator->mmb_map2kern = __mmb_map2kern;
allocator->mmb_unmap = __mmb_unmap;
allocator->mmb_free = __mmb_free;
allocator->mmf_map = __mmf_map;
allocator->mmf_unmap = __mmf_unmap;
return 0;
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __ALLOCATOR_H__
#define __ALLOCATOR_H__
#include <linux/device.h>
#include "osal_mmz.h"
#define NAME_LEN_MAX 64
struct mmz_allocator {
int (*init)(char *args);
mmz_mmb_t *(*mmb_alloc)(const char *name,
unsigned long size,
unsigned long align,
unsigned long gfp,
const char *mmz_name,
mmz_mmz_t *_user_mmz);
void *(*mmb_map2kern)(mmz_mmb_t *mmb, int cached);
int (*mmb_unmap)(mmz_mmb_t *mmb);
void (*mmb_free)(mmz_mmb_t *mmb);
void *(*mmf_map)(phys_addr_t phys, int len, int cache);
void (*mmf_unmap)(void *virt);
};
int cma_allocator_setopt(struct mmz_allocator *allocator);
int allocator_setopt(struct mmz_allocator *allocator);
#endif
@@ -0,0 +1,459 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/list.h>
#include <asm/cacheflush.h>
#include <asm/memory.h>
#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <asm/memory.h>
#include <asm/tlbflush.h>
#include <asm/pgtable.h>
#include <linux/vmalloc.h>
#include "allocator.h"
#include "mmz_arm.h"
#define __use_vmalloc_space 1
struct cma_zone {
struct device pdev;
char name[NAME_LEN_MAX];
unsigned long gfp;
unsigned long phys_start;
unsigned long nbytes;
unsigned int alloc_type;
unsigned long block_align;
};
extern struct osal_list_head mmz_list;
long long max_malloc_size = 0x40000000UL;
static int do_mmb_alloc(mmz_mmb_t *mmb)
{
mmz_mmb_t *p = NULL;
mmz_trace_func();
/* add mmb into zone, sorted */
osal_list_for_each_entry(p, &mmb->zone->mmb_list, list) {
if (mmb->phys_addr < p->phys_addr) {
break;
}
if (mmb->phys_addr == p->phys_addr) {
pr_err("ERROR:cma allocator bad in %s(%s, %d)",
mmb->zone->name, __func__, __LINE__);
return -EFAULT;
}
}
osal_list_add(&mmb->list, p->list.prev);
mmz_trace(1, MMZ_MMB_FMT_S, mmz_mmb_fmt_arg(mmb));
return 0;
}
static mmz_mmb_t *__mmb_alloc(const char *name,
unsigned long size,
unsigned long align,
unsigned long gfp,
const char *mmz_name,
mmz_mmz_t *_user_mmz)
{
mmz_mmz_t *mmz = NULL;
mmz_mmb_t *mmb = NULL;
unsigned long order = get_order(size);
size_t count = size >> PAGE_SHIFT;
struct page *page = NULL;
mmz_trace_func();
/*
* No zero length memory request, no supper
* large memory (4GB and above) request.
*/
if ((size == 0) || (size > max_malloc_size)) {
return NULL;
}
if (align == 0) {
align = MMZ_GRAIN;
}
size = mmz_grain_align(size);
order = get_order(size);
count = size >> PAGE_SHIFT;
mmz_trace(1, "anonymous=%s,size=%luKB,align=%lu", mmz_name, size / SZ_1K, align);
begin_list_for_each_mmz(mmz, gfp, mmz_name)
if ((_user_mmz != NULL) && (_user_mmz != mmz)) {
continue;
}
page = dma_alloc_from_contiguous(mmz->cma_dev, count, order);
if (page == NULL) {
return NULL;
}
/* Get it */
break;
end_list_for_each_mmz()
if (page == NULL) {
return NULL;
}
/* clear the allocated buffer, if needed! */
dma_buffer_clear(page, size);
mmb = kmalloc(sizeof(mmz_mmb_t), GFP_KERNEL);
if (mmb == NULL) {
pr_err("<%s,%d> mmb struct alloc failed\n", __func__, __LINE__);
goto cma_free;
}
memset(mmb, 0, sizeof(mmz_mmb_t));
mmb->zone = mmz;
mmb->phys_addr = page_to_phys(page);
mmb->length = size;
if (name != NULL) {
strlcpy(mmb->name, name, MMZ_MMB_NAME_LEN);
} else {
strncpy(mmb->name, "<null>", MMZ_MMB_NAME_LEN - 1);
}
if (do_mmb_alloc(mmb)) {
goto mmb_free;
}
return mmb;
mmb_free:
kfree(mmb);
cma_free:
dma_release_from_contiguous(mmz->cma_dev, page, count);
return NULL;
}
static void __mmb_free(mmz_mmb_t *mmb)
{
size_t count = mmb->length >> PAGE_SHIFT;
struct page *page = phys_to_page(mmb->phys_addr);
mmz_mmz_t *mmz = mmb->zone;
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
mmb_dcache_flush(mmb);
}
dma_release_from_contiguous(mmz->cma_dev, page, count);
osal_list_del(&mmb->list);
kfree(mmb);
}
static void *__mmb_map2kern(mmz_mmb_t *mmb, int cached)
{
pgprot_t prot;
struct page *page = phys_to_page(mmb->phys_addr);
mmz_trace(1, "mmb[phys_addr=%lx,kvirt=%pK,length=%lx]",
mmb->phys_addr, mmb->kvirt, mmb->length);
if (mmb->flags & MMZ_MMB_MAP2KERN) {
if ((!!cached * MMZ_MMB_MAP2KERN_CACHED) != (mmb->flags & MMZ_MMB_MAP2KERN_CACHED)) {
pr_err("mmb<%s> has been kernel-mapped %s, \
can not be re-mapped as %s.",
mmb->name,
(mmb->flags & MMZ_MMB_MAP2KERN_CACHED) ? "cached" : "non-cached",
(cached) ? "cached" : "non-cached");
return NULL;
}
mmz_trace(1, "map[%lx --> %pK]", mmb->phys_addr, mmb->kvirt);
mmb->map_ref++;
return mmb->kvirt;
}
prot = arch_kern_pgprot(cached);
#if __use_vmalloc_space
/*
* Map into vmalloc space
*/
{
int i;
struct page **pages = NULL;
unsigned int pagesnr = mmb->length / PAGE_SIZE;
struct page *tmp = page;
int array_size = sizeof(struct page *) * pagesnr;
/*
* Noted: mmb->length would be very large in some cases(for example:
* more than one Giga Bytes). and array_size would be very large as
* well. So, don't use kmalloc here.
*/
pages = vmalloc(array_size);
if (pages == NULL) {
pr_err("ptr array(0x%x) vmalloc failed.\n", array_size);
return NULL;
}
for (i = 0; i < pagesnr; i++) {
*(pages + i) = tmp;
tmp++;
}
mmb->kvirt = vmap(pages, pagesnr, VM_MAP, prot);
vfree(pages);
}
#else
/*
* Map into linear space
*/
{
dma_pages_remap(page, mmb->length, prot);
mmb->kvirt = __va(mmb->phys_addr);
}
#endif
if (mmb->kvirt == NULL) {
/*
* you should never get here.
*/
printk(KERN_ERR "mmb[0x%lx, 0x%lx] map to kernel failed\n",
mmb->phys_addr, mmb->length);
return NULL;
}
if (cached) {
mmb->flags |= MMZ_MMB_MAP2KERN_CACHED;
} else {
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
}
mmb->flags |= MMZ_MMB_MAP2KERN;
mmb->map_ref++;
mmz_trace(1, "map[%lx --> %pK]", mmb->phys_addr, mmb->kvirt);
return mmb->kvirt;
}
static int __mmb_unmap(mmz_mmb_t *mmb)
{
int ref;
mmz_trace(1, "mmb[phys_addr=%lx,kvirt=%pK,length=%lx]",
mmb->phys_addr, mmb->kvirt, mmb->length);
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
mmb_dcache_flush(mmb);
}
if (mmb->flags & MMZ_MMB_MAP2KERN) {
ref = --mmb->map_ref;
if (mmb->map_ref != 0) {
return ref;
}
}
#if __use_vmalloc_space
/*
* unmap from vmalloc space.
*/
{
vunmap(mmb->kvirt);
}
#endif
mmb->kvirt = NULL;
mmb->flags &= ~MMZ_MMB_MAP2KERN;
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
if ((mmb->flags & MMZ_MMB_RELEASED) && (mmb->phy_ref == 0)) {
__mmb_free(mmb);
}
return 0;
}
/*
* Map any valid phys address passed by users, to virtual address.
* The input phys may not be 4Kbytes aligned.
* FIXME
*/
static void *__mmf_map(phys_addr_t phys, int len, int cache)
{
struct page **pages = NULL;
unsigned int pagesnr = len / PAGE_SIZE;
int i;
void *virt = NULL;
pgprot_t prot;
struct page *page = phys_to_page(phys);
struct page *tmp = page;
int array_size;
mmz_trace(1, "phys=%lx, len=0x%x, cache=%d", (unsigned long)phys, len, cache);
/*
* if the given phys is not page aligned, we need to
* map one more page for the leftover.
*/
if (((phys & 0xfff) + len) > PAGE_SIZE) {
pagesnr += 1;
}
array_size = sizeof(struct page *) * pagesnr;
prot = arch_kern_pgprot(cache);
#if __use_vmalloc_space
/*
* Map into vmalloc space.
*/
{
/*
* Noted: length of region may be very large in some cases(for example:
* more than one Giga Bytes). and array_size would be very large as
* well. So, don't use kmalloc here.
*/
pages = vmalloc(array_size);
if (pages == NULL) {
printk(KERN_ERR "ptr vmalloc %d failed.\n", array_size);
return NULL;
}
for (i = 0; i < pagesnr; i++) {
*(pages + i) = tmp;
tmp++;
}
virt = vmap(pages, pagesnr, VM_MAP, prot);
vfree(pages);
if (virt == NULL) {
return NULL;
}
virt += (phys & 0xfff);
}
#else
/*
* Map into linear space
*/
{
dma_pages_remap(page, len, prot);
virt = __va(phys);
}
#endif
mmz_trace(1, "map[%lx --> %pK]", (unsigned long)phys, virt);
return virt;
}
static void __mmf_unmap(void *virt)
{
unsigned long vaddr = (unsigned long)(uintptr_t)virt;
mmz_trace(1, "virt=%pK", virt);
/*
* virtual address to be vunmaped should be page aligned
*/
vaddr &= 0xfffff000;
if ((vaddr >= VMALLOC_START) && (vaddr < VMALLOC_END)) {
vunmap ((void *)(uintptr_t)vaddr);
}
}
static int __allocator_init(char *s)
{
#ifdef CONFIG_CMA
mmz_mmz_t *zone = NULL;
char *line = NULL;
struct cma_zone *cma_zone = NULL;
while ((line = strsep(&s, ":")) != NULL) {
int i;
char *argv[6];
extern struct cma_zone *get_cma_zone(const char *name);
/*
* FIXME: We got 4 args in "line", formated as
* "argv[0],argv[1],argv[2],argv[3],argv[4]".
* eg: "<mmz_name>,<gfp>,<phys_start>,<size>,<alloc_type>"
* For more convenient, "hard code" are used such as "arg[0]", i.e.
*/
for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;)
if (++i == ARRAY_SIZE(argv)) {
break;
}
cma_zone = get_cma_zone(argv[0]);
if (cma_zone == NULL) {
printk(KERN_ERR "can't get cma zone info:%s\n", argv[0]);
continue;
}
if (i == 4) {
zone = mmz_mmz_create("null", 0, 0, 0);
if (zone == NULL) {
continue;
}
strlcpy(zone->name, argv[0], MMZ_MMZ_NAME_LEN);
printk("cmz zone gfp 0x%lx, phys 0x%lx, nbytes 0x%lx\n",
cma_zone->gfp,
cma_zone->phys_start,
cma_zone->nbytes);
zone->gfp = cma_zone->gfp;
zone->phys_start = cma_zone->phys_start;
zone->nbytes = cma_zone->nbytes;
zone->cma_dev = &cma_zone->pdev;
if (zone->nbytes > max_malloc_size) {
max_malloc_size = zone->nbytes;
}
} else {
printk(KERN_ERR "Input parameter num incorrect!\n");
continue;
}
if (mmz_mmz_register(zone)) {
printk(KERN_WARNING "Add MMZ failed: " MMZ_MMZ_FMT_S "\n",
mmz_mmz_fmt_arg(zone));
mmz_mmz_destroy(zone);
}
zone = NULL;
}
#endif
return 0;
}
int cma_allocator_setopt(struct mmz_allocator *allocator)
{
allocator->init = __allocator_init;
allocator->mmb_alloc = __mmb_alloc;
allocator->mmb_map2kern = __mmb_map2kern;
allocator->mmb_unmap = __mmb_unmap;
allocator->mmb_free = __mmb_free;
allocator->mmf_map = __mmf_map;
allocator->mmf_unmap = __mmf_unmap;
return 0;
}
@@ -0,0 +1,104 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include "osal.h"
#include "osal_mmz.h"
#define MMZ_NAME "anonymous"
unsigned long long mmz_alloc(const char *mmz_name, const char *buf_name, unsigned long size)
{
mmz_mmb_t *pmmb = NULL;
pmmb = mmz_mmb_alloc(buf_name, size, 0, 0, mmz_name);
if (pmmb == NULL) {
osal_printk("Mmz malloc failed!\n");
return 0UL;
}
return mmz_mmb_phys(pmmb);
}
EXPORT_SYMBOL(mmz_alloc);
void mmz_free(unsigned long long phy_addr)
{
mmz_mmb_freeby_phys(phy_addr);
}
EXPORT_SYMBOL(mmz_free);
void *mmz_map(unsigned long long phy_addr, unsigned long size, bool cached)
{
mmz_mmb_t *pmmb = NULL;
void *vir_addr = NULL;
unsigned long offset;
pmmb = mmz_mmb_getby_phys_2(phy_addr, &offset);
if ( pmmb == NULL ) {
osal_printk("mmz remap cache get mmz_mmb failed\n");
return NULL;
}
if (size == 0 || size + offset > pmmb->length) {
osal_printk("mmz remap size(0x%lx) is zero or bigger than mmb size(0x%lx)", size, pmmb->length);
return NULL;
}
if ( cached == 1 ) {
vir_addr = mmz_mmb_map2kern_cached(pmmb);
} else {
vir_addr = mmz_mmb_map2kern(pmmb);
}
if (vir_addr == NULL) {
osal_printk("mmz remap failed!\n");
return NULL;
}
return vir_addr + offset;
}
EXPORT_SYMBOL(mmz_map);
void mmz_unmap(void *vir_addr)
{
if (vir_addr != NULL) {
mmz_mmb_t *pmmb = mmz_mmb_getby_kvirt(vir_addr);
if (pmmb != NULL) {
mmz_mmb_unmap(pmmb);
}
}
}
EXPORT_SYMBOL(mmz_unmap);
int mmz_check_phyaddr(unsigned long long phy_addr, unsigned long len)
{
/* if address in mmz of current system */
if (mmz_is_phys_in_mmz(phy_addr, len))
return -1;
return 0;
}
EXPORT_SYMBOL(mmz_check_phyaddr);
int mmz_flush_cache(unsigned long phy_addr, void *kvirt, unsigned long length)
{
mmz_mmb_t *pmmb = NULL;
unsigned long offset;
/*err address flush maybe panic so judge input parameter*/
pmmb = mmz_mmb_getby_phys_2(phy_addr, &offset);
if ( pmmb == NULL ) {
osal_printk("mmz flush cache get mmz_mmb failed\n");
return -1;
}
if ( mmz_mmb_flush_dcache_byaddr(kvirt, phy_addr, length) != 0 )
return -1;
return 0;
}
EXPORT_SYMBOL(mmz_flush_cache);
+956
View File
@@ -0,0 +1,956 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <generated/autoconf.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <asm/cacheflush.h>
#ifndef CONFIG_64BIT
#include <linux/highmem.h>
#include <asm/pgtable.h>
#endif
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/dma-mapping.h>
#include "osal.h"
#include "allocator.h"
#include "version.h"
#include <linux/lotus/kapi.h>
OSAL_LIST_HEAD(mmz_list);
static DEFINE_SEMAPHORE(mmz_lock);
#define MMZ_SETUP_CMDLINE_LEN 256
#define MMZ_ALLOCATOR_NAME_LEN 32
#define MMZ_DEFAULT_ALLOCATOR "xmedia"
#ifndef MODULE
static char setup_zones[MMZ_SETUP_CMDLINE_LEN] = {'\0'};
static int __init parse_kern_mmz(char *line)
{
strlcpy(setup_zones, line, sizeof(setup_zones));
return 1;
}
__setup("mmz=", parse_kern_mmz);
static char setup_allocator[MMZ_ALLOCATOR_NAME_LEN] = MMZ_DEFAULT_ALLOCATOR;
static int __init parse_kern_allocator(char *line)
{
strlcpy(setup_allocator, line, sizeof(setup_allocator));
return 1;
}
__setup("mmz_allocator=", parse_kern_allocator);
#else
static char setup_zones[MMZ_SETUP_CMDLINE_LEN]={'\0'};
static char setup_allocator[MMZ_ALLOCATOR_NAME_LEN] = MMZ_DEFAULT_ALLOCATOR; //default setting
module_param_string(mmz, setup_zones, MMZ_SETUP_CMDLINE_LEN, 0600);
module_param_string(mmz_allocator, setup_allocator, MMZ_ALLOCATOR_NAME_LEN, 0600);
MODULE_PARM_DESC(mmz,"mmz_allocator=allocator mmz=name,0,start,size,type,eqsize:[others] map_mmz=start,size:[others]");
#endif
static struct mmz_allocator the_allocator;
mmz_mmz_t *mmz_mmz_create(const char *name,
unsigned long gfp,
unsigned long phys_start,
unsigned long nbytes)
{
mmz_mmz_t *p = NULL;
mmz_trace_func();
if(name == NULL) {
printk(KERN_ERR "%s: 'name' should not be NULL!", __FUNCTION__);
return NULL;
}
p = kmalloc(sizeof(mmz_mmz_t) + 1, GFP_KERNEL);
if (p == NULL) {
printk(KERN_ERR "%s: System OOM!\n", __func__);
return NULL;
}
memset(p, 0, sizeof(mmz_mmz_t)+1);
strlcpy(p->name, name, MMZ_MMZ_NAME_LEN);
p->gfp = gfp;
p->phys_start = phys_start;
p->nbytes = nbytes;
OSAL_INIT_LIST_HEAD(&p->list);
OSAL_INIT_LIST_HEAD(&p->mmb_list);
p->destructor = kfree;
return p;
}
EXPORT_SYMBOL(mmz_mmz_create);
int mmz_mmz_destroy(mmz_mmz_t *zone)
{
if(zone == NULL) {
return -1;
}
if(zone->destructor) {
zone->destructor(zone);
}
return 0;
}
EXPORT_SYMBOL(mmz_mmz_destroy);
static int _check_mmz(mmz_mmz_t *zone)
{
mmz_mmz_t *p = NULL;
unsigned long new_start=zone->phys_start;
unsigned long new_end=zone->phys_start+zone->nbytes;
if (zone->nbytes == 0) {
return -1;
}
if (!((new_start >= __pa((uintptr_t)high_memory)) ||
((new_start < PHYS_OFFSET) && (new_end <= PHYS_OFFSET)))) {
printk(KERN_ERR "ERROR: Conflict MMZ:\n");
printk(KERN_ERR MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(zone));
printk(KERN_ERR "MMZ conflict to kernel memory (0x%08lX, 0x%08lX)\n",
(long unsigned int)PHYS_OFFSET,
(long unsigned int)(__pa((uintptr_t)high_memory) - 1));
return -1;
}
osal_list_for_each_entry(p, &mmz_list, list) {
unsigned long start, end;
start = p->phys_start;
end = p->phys_start + p->nbytes;
if(new_start >= end) {
continue;
} else if (new_start < start && new_end <= start) {
continue;
} else {
;
}
printk(KERN_ERR "ERROR: Conflict MMZ:\n");
printk(KERN_ERR "MMZ new: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(zone));
printk(KERN_ERR "MMZ exist: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(p));
printk(KERN_ERR "Add new MMZ failed!\n");
return -1;
}
return 0;
}
int mmz_mmz_register(mmz_mmz_t *zone)
{
int ret = 0;
mmz_trace(1, MMZ_MMZ_FMT_S, mmz_mmz_fmt_arg(zone));
if(zone == NULL) {
return -1;
}
down(&mmz_lock);
if (0 == strcmp(setup_allocator, "xmedia")) {
ret = _check_mmz(zone);
if (ret) {
up(&mmz_lock);
return ret;
}
}
OSAL_INIT_LIST_HEAD(&zone->mmb_list);
osal_list_add(&zone->list, &mmz_list);
up(&mmz_lock);
return 0;
}
int mmz_mmz_unregister(mmz_mmz_t *zone)
{
int losts = 0;
mmz_mmb_t *p = NULL;
if(zone == NULL)
return -1;
mmz_trace_func();
down(&mmz_lock);
osal_list_for_each_entry(p, &zone->mmb_list, list) {
printk(KERN_WARNING "MB Lost: " MMZ_MMB_FMT_S "\n",
mmz_mmb_fmt_arg(p));
losts++;
}
if (losts) {
printk(KERN_ERR "%d mmbs not free, mmz<%s> can not be unregistered!\n",
losts, zone->name);
up(&mmz_lock);
return -1;
}
osal_list_del(&zone->list);
up(&mmz_lock);
return 0;
}
mmz_mmb_t *mmz_mmb_alloc(const char *name,
unsigned long size,
unsigned long align,
unsigned long gfp,
const char *mmz_name)
{
mmz_mmb_t *mmb = NULL;
down(&mmz_lock);
mmb = the_allocator.mmb_alloc(name, size, align, gfp, mmz_name, NULL);
up(&mmz_lock);
return mmb;
}
EXPORT_SYMBOL(mmz_mmb_alloc);
void *mmz_mmb_map2kern(mmz_mmb_t *mmb)
{
void *p = NULL;
if(mmb == NULL)
return NULL;
down(&mmz_lock);
p = the_allocator.mmb_map2kern(mmb, 0);
up(&mmz_lock);
return p;
}
EXPORT_SYMBOL(mmz_mmb_map2kern);
/* mmf: media-memory fragment */
void *mmz_mmf_map2kern_nocache(unsigned long phys, int len)
{
void *virt = the_allocator.mmf_map(phys, len, 0);
if (virt != NULL)
return virt;
return NULL;
}
EXPORT_SYMBOL(mmz_mmf_map2kern_nocache);
void *mmz_mmf_map2kern_cache(unsigned long phys, int len)
{
void *virt = the_allocator.mmf_map(phys, len, 1);
if (virt != NULL)
return virt;
return NULL;
}
EXPORT_SYMBOL(mmz_mmf_map2kern_cache);
void mmz_mmf_unmap(void *virt)
{
the_allocator.mmf_unmap(virt);
}
EXPORT_SYMBOL(mmz_mmf_unmap);
void *mmz_mmb_map2kern_cached(mmz_mmb_t *mmb)
{
void *p = NULL;
if(mmb == NULL)
return NULL;
down(&mmz_lock);
p = the_allocator.mmb_map2kern(mmb, 1);
up(&mmz_lock);
return p;
}
EXPORT_SYMBOL(mmz_mmb_map2kern_cached);
int mmz_mmb_flush_dcache_byaddr(void *kvirt,
unsigned long phys_addr,
unsigned long length)
{
if (kvirt == NULL)
return -EINVAL;
/*
* Use flush range to instead flush_cache_all,
* because flush_cache_all only flush local cpu.
* And on_each_cpu macro cannot used to flush
* all cpus with irq disabled.
*/
#ifdef CONFIG_64BIT
__flush_dcache_area(kvirt, length);
#else
/*
* dmac_map_area is invalid in kernel,
* arm9 is not supported yet
*/
__cpuc_flush_dcache_area(kvirt, length);
#endif
#if defined(CONFIG_CACHE_L2V200) || defined(CONFIG_CACHE_L2X0)
/* flush l2 cache, use paddr */
/*
* if length > L2 cache size, then this interface
* will call <outer_flush_all>
*/
outer_flush_range(phys_addr, phys_addr + length);
#endif
return 0;
}
EXPORT_SYMBOL(mmz_mmb_flush_dcache_byaddr);
int mmz_mmb_invalid_cache_byaddr(void *kvirt,
unsigned long phys_addr,
unsigned long length)
{
if (kvirt == NULL)
return -EINVAL;
#ifdef CONFIG_64BIT
__flush_dcache_area(kvirt, length);
#else
/*
* dmac_map_area is invalid in kernel,
* arm9 is not supported yet
*/
__cpuc_flush_dcache_area(kvirt, length);
#endif
return 0;
}
EXPORT_SYMBOL(mmz_mmb_invalid_cache_byaddr);
int mmz_mmb_unmap(mmz_mmb_t *mmb)
{
int ref;
if(mmb == NULL)
return -1;
down(&mmz_lock);
ref = the_allocator.mmb_unmap(mmb);
up(&mmz_lock);
return ref;
}
EXPORT_SYMBOL(mmz_mmb_unmap);
int mmz_mmb_get(mmz_mmb_t *mmb)
{
int ref;
if(mmb == NULL)
return -1;
down(&mmz_lock);
if(mmb->flags & MMZ_MMB_RELEASED)
printk(KERN_WARNING "mmz_mmb_get: amazing, mmb<%s> is released!\n", mmb->name);
ref = ++mmb->phy_ref;
up(&mmz_lock);
return ref;
}
int mmz_mmb_put(mmz_mmb_t *mmb)
{
int ref;
if(mmb == NULL)
return -1;
down(&mmz_lock);
if(mmb->flags & MMZ_MMB_RELEASED)
printk(KERN_WARNING "mmz_mmb_put: amazing, mmb<%s> is released!\n", mmb->name);
ref = --mmb->phy_ref;
if ((mmb->flags & MMZ_MMB_RELEASED) && (mmb->phy_ref ==0) && (mmb->map_ref ==0)) {
the_allocator.mmb_free(mmb);
}
up(&mmz_lock);
return ref;
}
int mmz_mmb_free(mmz_mmb_t *mmb)
{
mmz_trace_func();
if(mmb == NULL)
return -1;
mmz_trace(1,MMZ_MMB_FMT_S,mmz_mmb_fmt_arg(mmb));
down(&mmz_lock);
if(mmb->flags & MMZ_MMB_RELEASED) {
printk(KERN_WARNING "mmz_mmb_free: amazing, mmb<%s> has been released,\
but is still in use!\n", mmb->name);
up(&mmz_lock);
return 0;
}
if (mmb->phy_ref > 0) {
printk(KERN_WARNING "mmz_mmb_free: free mmb<%s> delayed \
for which ref-count is %d!\n",
mmb->name, mmb->map_ref);
mmb->flags |= MMZ_MMB_RELEASED;
up(&mmz_lock);
return 0;
}
if (mmb->flags & MMZ_MMB_MAP2KERN) {
printk(KERN_WARNING "mmz_mmb_free: free mmb<%s> delayed for which \
is kernel-mapped to 0x%pK with map_ref %d!\n",
mmb->name, mmb->kvirt, mmb->map_ref);
mmb->flags |= MMZ_MMB_RELEASED;
up(&mmz_lock);
return 0;
}
the_allocator.mmb_free(mmb);
up(&mmz_lock);
return 0;
}
EXPORT_SYMBOL(mmz_mmb_free);
#define MACH_MMB(p, val, member) do {\
mmz_mmz_t *__mach_mmb_zone__ = NULL; \
(p) = NULL;\
list_for_each_entry(__mach_mmb_zone__, &mmz_list, list) { \
mmz_mmb_t *__mach_mmb__ = NULL;\
list_for_each_entry(__mach_mmb__, &__mach_mmb_zone__->mmb_list, list) { \
if (__mach_mmb__->member == (val)) { \
(p) = __mach_mmb__; \
break;\
} \
} \
if (p != NULL)break;\
} \
}while(0)
mmz_mmb_t *mmz_mmb_getby_phys(unsigned long addr)
{
mmz_mmb_t *p = NULL;
down(&mmz_lock);
MACH_MMB(p, addr, phys_addr);
up(&mmz_lock);
return p;
}
EXPORT_SYMBOL(mmz_mmb_getby_phys);
unsigned long usr_virt_to_phys(unsigned long virt)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
pgd_t* pgd = NULL;
pud_t* pud = NULL;
#endif
pmd_t* pmd = NULL;
pte_t* pte = NULL;
unsigned int cacheable = 0;
unsigned long page_addr = 0;
unsigned long page_offset = 0;
unsigned long phys_addr = 0;
if (virt & 0x3) {
printk("invalid virt addr 0x%08lx[not 4 bytes align]\n", virt);
return 0;
}
if (virt >= PAGE_OFFSET) {
printk("invalid user space virt addr 0x%08lx\n", virt);
return 0;
}
// in kernel 5.10 just use pmd_off is ok
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
pgd = pgd_offset(current->mm, virt);
if (pgd_none(*pgd)) {
printk("printk: not mapped in pgd!\n");
return 0;
}
pud = pud_offset(pgd, virt);
if (pud_none(*pud)) {
printk("printk: not mapped in pud!\n");
return 0;
}
pmd = pmd_offset(pud, virt);
#else
pmd = pmd_off(current->mm, virt);
#endif
if (pmd_none(*pmd)) {
printk("printk: not mapped in pmd!\n");
return 0;
}
pte = pte_offset_map(pmd, virt);
if (pte_none(*pte)) {
printk("printk: not mapped in pte!\n");
pte_unmap(pte);
return 0;
}
page_addr = (pte_val(*pte) & PHYS_MASK) & PAGE_MASK;
page_offset = virt & ~PAGE_MASK;
phys_addr = page_addr | page_offset;
#ifdef CONFIG_64BIT
if (pte_val(*pte) & (1 << 4))
#else
if (pte_val(*pte) & (1 << 3))
#endif
{ cacheable = 1; }
/*
* phys_addr: the lowest bit indicates its cache attribute
* 1: cacheable
* 0: uncacheable
*/
phys_addr |= cacheable;
pte_unmap(pte);
return phys_addr;
}
EXPORT_SYMBOL(usr_virt_to_phys);
#define MACH_MMB_2(p, val, member, Outoffset) do {\
mmz_mmz_t *__mach_mmb_zone__ = NULL; \
(p) = NULL;\
list_for_each_entry(__mach_mmb_zone__, &mmz_list, list) { \
mmz_mmb_t *__mach_mmb__ = NULL;\
list_for_each_entry(__mach_mmb__, &__mach_mmb_zone__->mmb_list, list) { \
if ((__mach_mmb__->member <= (val)) && ((__mach_mmb__->length + __mach_mmb__->member) > (val))) { \
(p) = __mach_mmb__; \
Outoffset = val - __mach_mmb__->member;\
break;\
}\
} \
if (p != NULL)break;\
} \
}while(0)
mmz_mmb_t *mmz_mmb_getby_kvirt(void *virt)
{
mmz_mmb_t *p = NULL;
unsigned long Outoffset;
if (virt == NULL)
return NULL;
down(&mmz_lock);
MACH_MMB_2(p, virt, kvirt, Outoffset);
up(&mmz_lock);
mmz_trace(1, "Outoffset %lu \n", Outoffset);
return p;
}
EXPORT_SYMBOL(mmz_mmb_getby_kvirt);
mmz_mmb_t *mmz_mmb_getby_phys_2(unsigned long addr, unsigned long *Outoffset)
{
mmz_mmb_t *p = NULL;
down(&mmz_lock);
MACH_MMB_2(p, addr, phys_addr, *Outoffset);
up(&mmz_lock);
return p;
}
EXPORT_SYMBOL(mmz_mmb_getby_phys_2);
mmz_mmz_t *mmz_mmz_find(unsigned long gfp, const char *mmz_name)
{
mmz_mmz_t *p = NULL;
down(&mmz_lock);
begin_list_for_each_mmz(p, gfp, mmz_name)
up(&mmz_lock);
return p;
end_list_for_each_mmz()
up(&mmz_lock);
return NULL;
}
EXPORT_SYMBOL(mmz_mmz_find);
unsigned long mmz_mmz_get_phys(const char *zone_name)
{
mmz_mmz_t *zone = NULL;
zone = mmz_mmz_find(0, zone_name);
if (zone != NULL)
return zone->phys_start;
return 0;
}
EXPORT_SYMBOL(mmz_mmz_get_phys);
int mmz_map_mmz_unregister(mmz_mmz_t *zone)
{
int losts = 0;
mmz_mmb_t *p = NULL;
if (zone == NULL)
return -1;
mmz_trace_func();
down(&mmz_lock);
osal_list_for_each_entry(p, &zone->mmb_list, list) {
printk(KERN_WARNING "MB Lost: " MMZ_MMB_FMT_S "\n",
mmz_mmb_fmt_arg(p));
losts++;
}
if (losts) {
printk(KERN_ERR "%d mmbs not free, mmz<%s> can not be unregistered!\n",
losts, zone->name);
up(&mmz_lock);
return -1;
}
osal_list_del(&zone->list);
up(&mmz_lock);
return 0;
}
int mmz_vma_check(unsigned long vm_start, unsigned long vm_end)
{
struct vm_area_struct *pvma1;
struct vm_area_struct *pvma2;
pvma1 = find_vma(current->mm, vm_start);
if (pvma1 == NULL) {
printk(KERN_ERR "ERROR: pvma1 is null\n");
return -1;
}
pvma2 = find_vma(current->mm, vm_end-1);
if (pvma2 == NULL) {
printk(KERN_ERR "ERROR: pvma2 is null\n");
return -1;
}
if (pvma1 != pvma2) {
printk(KERN_ERR "ERROR: pvma1:[0x%lx,0x%lx) and pvma2:[0x%lx,0x%lx) are not equal\n",
pvma1->vm_start, pvma1->vm_end, pvma2->vm_start, pvma2->vm_end);
return -1;
}
if (!(pvma1->vm_flags & VM_WRITE)) {
printk(KERN_ERR "ERROR vma flag:0x%lx\n", pvma1->vm_flags);
return -1;
}
if (pvma1->vm_start > vm_start) {
printk("cannot find corresponding vma, vm[%lx, %lx], user range[%lx,%lx]\n", pvma1->vm_start, pvma1->vm_end, vm_start, vm_end);
return -1;
}
return 0;
}
EXPORT_SYMBOL(mmz_vma_check);
int mmz_is_phys_in_mmz(unsigned long addr_start, unsigned long addr_len)
{
mmz_mmz_t *p = NULL;
unsigned long addr_end = addr_start + addr_len;
unsigned long temp_start, temp_end;
osal_list_for_each_entry(p, &mmz_list, list) {
temp_start = p->phys_start;
temp_end = p->phys_start + p->nbytes;
if ((addr_start >= temp_start) && (addr_end <= temp_end)) {
return 0;
}
}
return -1;
}
EXPORT_SYMBOL(mmz_is_phys_in_mmz);
int mmz_mmb_flush_dcache_byaddr_safe(void *kvirt,
unsigned long phys_addr,
unsigned long length)
{
int ret = 0;
struct mm_struct *mm = current->mm;
if (kvirt == NULL)
return -EINVAL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
down_read(&mm->mmap_sem);
#else
down_read(&mm->mmap_lock);
#endif
if (mmz_vma_check((unsigned long)(uintptr_t)kvirt, (unsigned long)(uintptr_t)kvirt+length)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
up_read(&mm->mmap_sem);
#else
up_read(&mm->mmap_lock);
#endif
return -EPERM;
}
ret = mmz_mmb_flush_dcache_byaddr(kvirt, phys_addr, length);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
up_read(&mm->mmap_sem);
#else
up_read(&mm->mmap_lock);
#endif
return ret;
}
EXPORT_SYMBOL(mmz_mmb_flush_dcache_byaddr_safe);
#define MEDIA_MEM_NAME "media-mem"
#ifdef CONFIG_PROC_FS
static void mmz_proc_version(struct osal_proc_dir_entry *sfile)
{
unsigned char mmz_version[128] = {0};
VERSION_FORMAT(mmz_version, "MMZ", "V1.0", "");
osal_seq_printf(sfile, "\n%s\n\n", mmz_version);
return;
}
int mmz_seq_show(struct osal_proc_dir_entry *sfile)
{
mmz_mmz_t *p = NULL;
int len = 0;
unsigned int zone_number = 0;
unsigned int block_number = 0;
unsigned int used_size = 0;
unsigned int free_size = 0;
unsigned int mmz_total_size = 0;
mmz_trace_func();
mmz_proc_version(sfile);
down(&mmz_lock);
list_for_each_entry(p, &mmz_list, list) {
mmz_mmb_t *mmb = NULL;
osal_seq_printf(sfile, "+---ZONE: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(p));
mmz_total_size += p->nbytes / 1024;
++zone_number;
list_for_each_entry(mmb, &p->mmb_list, list) {
osal_seq_printf(sfile, " |-MMB: " MMZ_MMB_FMT_S "\n", mmz_mmb_fmt_arg(mmb));
used_size += mmb->length / 1024;
++block_number;
}
}
if (mmz_total_size != 0) {
free_size = mmz_total_size - used_size;
osal_seq_printf(sfile, "\n---MMZ_USE_INFO:\n total size=%dKB(%dMB),"
"used=%dKB(%dMB + %dKB),free=%dKB(%dMB + %dKB),"
"zone_number=%d,block_number=%d\n",
mmz_total_size, mmz_total_size / 1024,
used_size, used_size / 1024, used_size % 1024,
free_size, free_size / 1024, free_size % 1024,
zone_number, block_number);
}
up(&mmz_lock);
return len;
}
static int __init media_mem_proc_init(void)
{
osal_proc_entry_t *proc = NULL;
proc = osal_create_proc_entry(MEDIA_MEM_NAME, NULL);
if (proc == NULL) {
printk(KERN_ERR "Create mmz proc fail!\n");
return -1;
}
proc->read = mmz_seq_show;
return 0;
}
static void __exit media_mem_proc_exit(void)
{
osal_remove_proc_entry(MEDIA_MEM_NAME, NULL);
}
#else
static int __init media_mem_proc_init(void) { return 0; }
static void __exit media_mem_proc_exit(void) { }
#endif /* CONFIG_PROC_FS */
static void mmz_exit_check(void)
{
mmz_mmz_t* pmmz = NULL;
struct osal_list_head* p = NULL, *n = NULL;
mmz_trace_func();
list_for_each_safe(p, n, &mmz_list) {
pmmz = list_entry(p,mmz_mmz_t,list);
printk(KERN_WARNING "MMZ force removed: " MMZ_MMZ_FMT_S "\n",
mmz_mmz_fmt_arg(pmmz));
mmz_mmz_unregister(pmmz);
mmz_mmz_destroy(pmmz);
}
}
int __init media_mem_init(void)
{
int ret = 0;
printk(KERN_INFO "Media Memory Zone Manager\n");
if (setup_zones[0] == '\0') {
char *boot_mmz_para_start = NULL;
char *boot_mmz_para_end = NULL;
int mmz_para_len = 0;
/* get parameter from bootargs*/
boot_mmz_para_start = lotus_get_cmd_line();
if (boot_mmz_para_start != NULL)
boot_mmz_para_start = strstr(boot_mmz_para_start, "mmz_allocator=");
printk("mmz allocator from bootargs:%s\n", boot_mmz_para_start == NULL ? "none" : boot_mmz_para_start);
if (boot_mmz_para_start != NULL) {
boot_mmz_para_start += strlen("mmz_allocator=");
/*find mmz parameter end*/
boot_mmz_para_end = strchr(boot_mmz_para_start, ' ');
/*if this is the last bootargs, bootargs end is mmz parameter end*/
if (boot_mmz_para_end == NULL) {
mmz_para_len = strlen(boot_mmz_para_start);
} else {
mmz_para_len = boot_mmz_para_end - boot_mmz_para_start;
}
mmz_para_len = ((mmz_para_len > MMZ_ALLOCATOR_NAME_LEN) ? MMZ_ALLOCATOR_NAME_LEN : mmz_para_len);
memcpy(setup_allocator, boot_mmz_para_start, mmz_para_len);
boot_mmz_para_start = lotus_get_cmd_line();
/*no need judge here*/
boot_mmz_para_start = strstr(boot_mmz_para_start, "mmz=") + strlen("mmz=");
printk("mmz zone setting from bootargs:%s\n", boot_mmz_para_start);
if (boot_mmz_para_start != NULL) {
/*find mmz parameter end*/
boot_mmz_para_end = strchr(boot_mmz_para_start, ' ');
/*if this is the last bootargs, bootargs end is mmz parameter end*/
if (boot_mmz_para_end == NULL) {
mmz_para_len = strlen(boot_mmz_para_start);
} else {
mmz_para_len = boot_mmz_para_end - boot_mmz_para_start;
}
mmz_para_len = ((mmz_para_len > MMZ_SETUP_CMDLINE_LEN) ? MMZ_SETUP_CMDLINE_LEN : mmz_para_len);
memcpy(setup_zones, boot_mmz_para_start, mmz_para_len);
printk("mmz cfg from bootargs allocator:%s zones:%s\n", setup_allocator, setup_zones);
}
}
}
if (strcmp(setup_allocator, "cma") == 0) {
#ifdef CONFIG_CMA
ret = cma_allocator_setopt(&the_allocator);
#else
pr_err("cma is not enabled in kernel, please check!\n");
return -EINVAL;
#endif
} else if (strcmp(setup_allocator, "xmedia") == 0) {
ret = allocator_setopt(&the_allocator);
} else {
printk("The module param \"setup_allocator\" should be \"cma\" or \"xmedia\", which is \"%s\"\n",
setup_allocator);
mmz_exit_check();
return -EINVAL;
}
ret = the_allocator.init(setup_zones);
if (ret != 0) {
mmz_exit_check();
return ret;
}
media_mem_proc_init();
mmz_userdev_init();
return 0;
}
void __exit media_mem_exit(void)
{
mmz_userdev_exit();
mmz_exit_check();
media_mem_proc_exit();
}
/*
module_init(media_mem_init);
module_exit(media_mem_exit);
MODULE_LICENSE("GPL");
*/
/*
#ifndef MODULE
subsys_initcall(media_mem_init);
#endif
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,62 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __MMZ_ARCH_OPS_HEADER__
#define __MMZ_ARCH_OPS_HEADER__
#if defined(CONFIG_ARM64)
/* this function is used to change memory's property. */
static void dma_pages_remap(struct page *page, size_t size, pgprot_t prot) {}
static void dma_buffer_clear(struct page *page, size_t size)
{
memset(page_address(page), 0, size);
__flush_dcache_area(page_address(page), size);
}
static void mmb_dcache_flush(mmz_mmb_t *mmb)
{
__flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
}
static pgprot_t arch_kern_pgprot(int cache)
{
if (cache) {
return PAGE_KERNEL;
}
return __pgprot(PROT_NORMAL_NC);
}
#elif defined(CONFIG_ARM)
#include <asm/highmem.h>
#include <asm/pgtable.h>
extern void __dma_clear_buffer(struct page *page, size_t size);
static void dma_buffer_clear(struct page *page, size_t size)
{
__dma_clear_buffer(page, size);
}
static void mmb_dcache_flush(mmz_mmb_t *mmb)
{
__cpuc_flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
outer_flush_range(mmb->phys_addr, mmb->phys_addr + mmb->length);
}
static pgprot_t arch_kern_pgprot(int cache)
{
if (cache) {
return pgprot_kernel;
}
return pgprot_noncached(pgprot_kernel);
}
#else
#error no proper arch selected(CONFIG_ARM64/CONFIG_ARM)!
#endif
#endif
@@ -0,0 +1,82 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#include <linux/uaccess.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
#ifndef CONFIG_64BIT
#include <mach/io.h>
#endif
#endif
void *osal_ioremap(unsigned long phys_addr, unsigned long size)
{
return ioremap(phys_addr, size);
}
EXPORT_SYMBOL(osal_ioremap);
void *osal_ioremap_nocache(unsigned long phys_addr, unsigned long size)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
return ioremap_nocache(phys_addr, size);
#else
return ioremap(phys_addr, size);
#endif
}
EXPORT_SYMBOL(osal_ioremap_nocache);
void *osal_ioremap_cached(unsigned long phys_addr, unsigned long size)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
return ioremap_cached(phys_addr, size);
#else
return ioremap_cache(phys_addr, size);
#endif
}
void *osal_ioremap_wc(unsigned long phys_addr, unsigned long size)
{
return ioremap_wc(phys_addr, size);
}
EXPORT_SYMBOL(osal_ioremap_wc);
EXPORT_SYMBOL(osal_ioremap_cached);
void osal_iounmap(void *addr)
{
iounmap(addr);
}
EXPORT_SYMBOL(osal_iounmap);
unsigned long osal_copy_from_user(void *to, const void *from, unsigned long n)
{
return copy_from_user(to, from, n);
}
EXPORT_SYMBOL(osal_copy_from_user);
unsigned long osal_copy_to_user(void *to, const void *from, unsigned long n)
{
return copy_to_user(to, from, n);
}
EXPORT_SYMBOL(osal_copy_to_user);
int osal_access_ok(int type, const void *addr, unsigned long size)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
return access_ok(type, addr, size);
#else
return access_ok(addr, size);
#endif
}
EXPORT_SYMBOL(osal_access_ok);
@@ -0,0 +1,93 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/atomic.h>
#include <linux/printk.h>
#include <linux/slab.h>
int osal_atomic_init(osal_atomic_t *atomic)
{
atomic_t *p = NULL;
if (atomic == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
p = (atomic_t *)kmalloc(sizeof(atomic_t), GFP_KERNEL);
if (p == NULL) {
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
return -1;
}
memset(p, 0, sizeof(atomic_t));
atomic->atomic = p;
return 0;
}
EXPORT_SYMBOL(osal_atomic_init);
void osal_atomic_destory(osal_atomic_t *atomic)
{
if((atomic != NULL ) && (atomic->atomic != NULL)) {
kfree(atomic->atomic);
atomic->atomic = NULL;
} else {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
}
}
EXPORT_SYMBOL(osal_atomic_destory);
void osal_atomic_destroy(osal_atomic_t *atomic)
{
if((atomic != NULL ) && (atomic->atomic != NULL)) {
kfree(atomic->atomic);
atomic->atomic = NULL;
} else {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
}
}
EXPORT_SYMBOL(osal_atomic_destroy);
int osal_atomic_read(osal_atomic_t *atomic)
{
atomic_t *p = NULL;
if (atomic == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
p = (atomic_t *)(atomic->atomic);
return atomic_read(p);
}
EXPORT_SYMBOL(osal_atomic_read);
void osal_atomic_set(osal_atomic_t *atomic, int i)
{
atomic_t *p = NULL;
p = (atomic_t *)(atomic->atomic);
atomic_set(p, i);
}
EXPORT_SYMBOL(osal_atomic_set);
int osal_atomic_inc_return(osal_atomic_t *atomic)
{
atomic_t *p = NULL;
if (atomic == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
p = (atomic_t *)(atomic->atomic);
return atomic_inc_return(p);
}
EXPORT_SYMBOL(osal_atomic_inc_return);
int osal_atomic_dec_return(osal_atomic_t *atomic)
{
atomic_t *p = NULL;
if (atomic == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
p = (atomic_t *)(atomic->atomic);
return atomic_dec_return(p);
}
EXPORT_SYMBOL(osal_atomic_dec_return);
@@ -0,0 +1,61 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/barrier.h>
void osal_mb(void)
{
mb();
}
EXPORT_SYMBOL(osal_mb);
void osal_rmb(void)
{
rmb();
}
EXPORT_SYMBOL(osal_rmb);
void osal_wmb(void)
{
wmb();
}
EXPORT_SYMBOL(osal_wmb);
void osal_smp_mb(void)
{
smp_mb();
}
EXPORT_SYMBOL(osal_smp_mb);
void osal_smp_rmb(void)
{
smp_rmb();
}
EXPORT_SYMBOL(osal_smp_rmb);
void osal_smp_wmb(void)
{
smp_wmb();
}
EXPORT_SYMBOL(osal_smp_wmb);
void osal_isb(void)
{
isb();
}
EXPORT_SYMBOL(osal_isb);
void osal_dsb(void)
{
#ifdef CONFIG_64BIT
dsb(sy);
#else
dsb();
#endif
}
EXPORT_SYMBOL(osal_dsb);
void osal_dmb(void)
{
#ifdef CONFIG_64BIT
dmb(sy);
#else
dmb();
#endif
}
EXPORT_SYMBOL(osal_dmb);
@@ -0,0 +1,55 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <asm/cacheflush.h>
#include <linux/dma-direction.h>
#include "osal_mmz.h"
void osal_flush_cache_all(void)
{
flush_cache_all();
}
EXPORT_SYMBOL(osal_flush_cache_all);
void osal_cpuc_flush_dcache_area(void *addr, int size)
{
#ifdef CONFIG_64BIT
__flush_dcache_area(addr, size);
#else
__cpuc_flush_dcache_area(addr, size);
#endif
}
EXPORT_SYMBOL(osal_cpuc_flush_dcache_area);
void osal_flush_dcache_area(void *kvirt, unsigned long phys_addr, unsigned long length)
{
mmz_mmb_flush_dcache_byaddr(kvirt, phys_addr, length);
}
EXPORT_SYMBOL(osal_flush_dcache_area);
int osal_flush_dcache_all(void)
{
#ifdef CONFIG_64BIT
flush_cache_all();
#else
#ifdef CONFIG_SMP
on_each_cpu((smp_call_func_t)__cpuc_flush_kern_all, NULL, 1);
#else
__cpuc_flush_kern_all();
#endif
outer_flush_all();
#endif
return 0;
}
EXPORT_SYMBOL(osal_flush_dcache_all);
@@ -0,0 +1,26 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
int osal_printk(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = vprintk(fmt, args);
va_end(args);
return r;
}
EXPORT_SYMBOL(osal_printk);
void osal_panic(const char *fmt, const char *fun, int line, const char *cond)
{
panic(fmt, fun, line, cond);
}
EXPORT_SYMBOL(osal_panic);
@@ -0,0 +1,952 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm_types.h>
#include <linux/mm.h>
#include <linux/kmod.h>
#include <linux/devfreq.h>
#include "media.h"
#include "osal.h"
#include "osal_devfreq.h"
#define DRVAL_DEBUG 0
#define GET_FILE(file) \
do { \
if (__get_file(file) < 0) \
return -1; \
} while (0)
#define PUT_FILE(file) \
do { \
if (__put_file(file) < 0) \
return -1; \
} while (0)
typedef struct osal_coat_dev {
struct osal_dev osal_dev;
struct media_device media_dev;
} osal_coat_dev_t;
struct osal_private_data {
struct osal_dev *dev;
void *data;
struct osal_poll table;
int f_ref_cnt;
};
spinlock_t f_lock;
void osal_device_init(void)
{
spin_lock_init(&f_lock);
}
static int __get_file(struct file *file)
{
struct osal_private_data *pdata = NULL;
spin_lock(&f_lock);
pdata = file->private_data;
if (pdata == NULL) {
spin_unlock(&f_lock);
return -1;
}
pdata->f_ref_cnt++;
spin_unlock(&f_lock);
return 0;
}
static int __put_file(struct file *file)
{
struct osal_private_data *pdata = NULL;
spin_lock(&f_lock);
pdata = file->private_data;
if (pdata == NULL) {
spin_unlock(&f_lock);
return -1;
}
pdata->f_ref_cnt--;
spin_unlock(&f_lock);
return 0;
}
static int osal_open(struct inode *inode, struct file *file)
{
struct media_device *media = NULL;
osal_coat_dev_t *coat_dev = NULL;
struct osal_private_data *pdata = NULL;
if (!capable(CAP_SYS_RAWIO) || !capable(CAP_SYS_ADMIN)) {
return -EPERM;
}
// media = getmedia(inode);
media = (struct media_device *)file->private_data;
if (media == NULL) {
osal_printk("%s - get media device error!\n", __FUNCTION__);
return -1;
}
coat_dev = osal_container_of(media, struct osal_coat_dev, media_dev);
pdata = (struct osal_private_data *)kmalloc(sizeof(struct osal_private_data), GFP_KERNEL);
if (pdata == NULL) {
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
return -1;
}
if (DRVAL_DEBUG) {
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
}
memset(pdata, 0, sizeof(struct osal_private_data));
file->private_data = pdata;
pdata->dev = &(coat_dev->osal_dev);
if (coat_dev->osal_dev.fops->open != NULL) {
return coat_dev->osal_dev.fops->open((void *)&(pdata->data));
}
return 0;
}
static ssize_t osal_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
struct osal_private_data *pdata = file->private_data;
int ret = 0;
GET_FILE(file);
if (pdata->dev->fops->read != NULL) {
ret = pdata->dev->fops->read(buf, (int)size, (long *)offset, (void *)&(pdata->data));
}
PUT_FILE(file);
return ret;
}
static ssize_t osal_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
struct osal_private_data *pdata = file->private_data;
int ret = 0;
GET_FILE(file);
if (pdata->dev->fops->write != NULL) {
ret = pdata->dev->fops->write(buf, (int)size, (long *)offset, (void *)&(pdata->data));
}
PUT_FILE(file);
return ret;
}
static loff_t osal_llseek(struct file *file, loff_t offset, int whence)
{
struct osal_private_data *pdata = file->private_data;
int ret = 0;
GET_FILE(file);
if (DRVAL_DEBUG) {
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
}
if (whence == SEEK_SET) {
if (pdata->dev->fops->llseek != NULL) {
ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_SET, (void *)&(pdata->data));
}
} else if (whence == SEEK_CUR) {
if (pdata->dev->fops->llseek != NULL) {
ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_CUR, (void *)&(pdata->data));
}
} else if (whence == SEEK_END) {
if (pdata->dev->fops->llseek != NULL) {
ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_END, (void *)&(pdata->data));
}
}
PUT_FILE(file);
return (loff_t)ret;
}
static int osal_release(struct inode *inode, struct file *file)
{
int ret = 0;
struct osal_private_data *pdata = file->private_data;
GET_FILE(file);
if (DRVAL_DEBUG) {
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
}
if (pdata->dev->fops->release != NULL) {
ret = pdata->dev->fops->release((void *)&(pdata->data));
}
if (ret != 0) {
PUT_FILE(file);
osal_printk("%s - release failed!\n", __FUNCTION__);
return ret;
}
PUT_FILE(file);
spin_lock(&f_lock);
if (pdata->f_ref_cnt != 0) {
osal_printk("%s - release failed!\n", __FUNCTION__);
spin_unlock(&f_lock);
return -1;
}
kfree(file->private_data);
file->private_data = NULL;
spin_unlock(&f_lock);
return 0;
}
static long __osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = -1;
struct osal_private_data *pdata = file->private_data;
char *kbuf = NULL;
if (DRVAL_DEBUG) {
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
}
if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
return -1;
}
if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
osal_printk("%s - Input param err,it is null!\n", __FUNCTION__);
return -1;
}
if (_IOC_DIR(cmd) == _IOC_NONE) {
if (pdata->dev->fops->unlocked_ioctl == NULL) {
return -1;
} else {
ret = pdata->dev->fops->unlocked_ioctl(cmd, arg, (void *)&(pdata->data));
}
} else if (_IOC_DIR(cmd) == _IOC_WRITE) {
kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
if (kbuf == NULL) {
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
return -1;
}
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
if (pdata->dev->fops->unlocked_ioctl == NULL) {
vfree(kbuf);
return -1;
} else {
ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
}
} else if (_IOC_DIR(cmd) == _IOC_READ) {
kbuf = vmalloc(_IOC_SIZE(cmd));
if (kbuf == NULL) {
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
return -1;
}
if (pdata->dev->fops->unlocked_ioctl == NULL) {
vfree(kbuf);
return -1;
} else {
ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
if (ret == 0) {
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
}
}
} else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
kbuf = vmalloc(_IOC_SIZE(cmd));
if (kbuf == NULL) {
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
return -1;
}
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
if (pdata->dev->fops->unlocked_ioctl == NULL) {
vfree(kbuf);
return -1;
} else {
ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
if (ret == 0) {
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
}
}
}
if (kbuf != NULL) {
vfree(kbuf);
}
return ret;
}
static long osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = 0;
GET_FILE(file);
ret = __osal_unlocked_ioctl(file, cmd, arg);
PUT_FILE(file);
return ret;
}
#ifdef CONFIG_COMPAT
static long __osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = -1;
struct osal_private_data *pdata = file->private_data;
char *kbuf = NULL;
if (DRVAL_DEBUG) {
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
}
if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
return -1;
}
if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
osal_printk("%s - Input param err,it is null!\n", __FUNCTION__);
return -1;
}
if (_IOC_DIR(cmd) == _IOC_NONE) {
if (pdata->dev->fops->compat_ioctl == NULL) {
return -1;
} else {
ret = pdata->dev->fops->compat_ioctl(cmd, arg, (void *)&(pdata->data));
}
} else if (_IOC_DIR(cmd) == _IOC_WRITE) {
kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
if (kbuf == NULL) {
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
return -1;
}
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
if (pdata->dev->fops->compat_ioctl == NULL) {
vfree(kbuf);
return -1;
} else {
ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
}
} else if (_IOC_DIR(cmd) == _IOC_READ) {
kbuf = vmalloc(_IOC_SIZE(cmd));
if (kbuf == NULL) {
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
return -1;
}
if (pdata->dev->fops->compat_ioctl == NULL) {
vfree(kbuf);
return -1;
} else {
ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
if (ret == 0) {
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
}
}
} else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
kbuf = vmalloc(_IOC_SIZE(cmd));
if (kbuf == NULL) {
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
return -1;
}
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
if (pdata->dev->fops->compat_ioctl == NULL) {
vfree(kbuf);
return -1;
} else {
ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
if (ret == 0) {
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
vfree(kbuf);
return -1;
}
}
}
}
if (kbuf != NULL) {
vfree(kbuf);
}
return ret;
}
static long osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = 0;
GET_FILE(file);
ret = __osal_compat_ioctl(file, cmd, arg);
PUT_FILE(file);
return ret;
}
#endif
static unsigned int osal_poll(struct file *file, struct poll_table_struct *table)
{
struct osal_private_data *pdata = file->private_data;
struct osal_poll t;
unsigned int ret = 0;
GET_FILE(file);
if (DRVAL_DEBUG) {
osal_printk("%s - table=%pK, file=%pK!\n", __FUNCTION__, table, file);
}
t.poll_table = table;
t.data = file;
if (pdata->dev->fops->poll != NULL) {
ret = pdata->dev->fops->poll(&t, (void *)&(pdata->data));
}
PUT_FILE(file);
return ret;
}
static int __osal_valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
/* check physical addr greater than the max addr supported by the system */
if ((pfn + (size >> PAGE_SHIFT)) > (1 + ((~0UL) >> PAGE_SHIFT))) {
osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__);
return 0;
}
/* CMA need to alloc ram region, so annotate the code as follows */
#if 0
/* check physical addr is ram region */
if (pfn_valid(pfn) || pfn_valid(pfn + (size >> PAGE_SHIFT))) {
osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__);
return 0;
}
#endif
/* It's necessary for the variable "size" to align 4k(page_size). */
#define PAGE_SIZE_MASK 0xfffffffffffff000ULL
if ((unsigned long)size & (~PAGE_SIZE_MASK)) {
osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__);
return 0;
}
#undef PAGE_SIZE_MASK
return 1;
}
static int osal_mmap(struct file *file, struct vm_area_struct *vm)
{
struct osal_vm osal_vm;
struct osal_private_data *pdata = file->private_data;
osal_vm.vm = vm;
if (!__osal_valid_mmap_phys_addr_range(vm->vm_pgoff, vm->vm_end - vm->vm_start)) {
osal_printk("\n%s - invalid argument size=%ld!!!\n", __FUNCTION__, vm->vm_end - vm->vm_start);
return -EINVAL;
}
if (DRVAL_DEBUG) {
osal_printk("%s - start=%lx, end=%lx!, off=%lx\n", __FUNCTION__, vm->vm_start, vm->vm_end, vm->vm_pgoff);
}
if (pdata->dev->fops->mmap != NULL) {
return pdata->dev->fops->mmap(&osal_vm, vm->vm_start, vm->vm_end, vm->vm_pgoff, (void *)&(pdata->data));
}
return 0;
}
static struct file_operations s_osal_fops = {
.owner = THIS_MODULE,
.open = osal_open,
.read = osal_read,
.write = osal_write,
.llseek = osal_llseek,
.unlocked_ioctl = osal_unlocked_ioctl,
.release = osal_release,
.poll = osal_poll,
.mmap = osal_mmap,
#ifdef CONFIG_COMPAT
.compat_ioctl = osal_compat_ioctl,
#endif
};
static int osal_pm_prepare(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_prepare) {
return coat_dev->osal_dev.osal_pmops->pm_prepare(&(coat_dev->osal_dev));
}
return 0;
}
static void osal_pm_complete(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_complete) {
coat_dev->osal_dev.osal_pmops->pm_complete(&(coat_dev->osal_dev));
}
}
static int osal_pm_suspend(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend) {
return coat_dev->osal_dev.osal_pmops->pm_suspend(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_resume(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume) {
return coat_dev->osal_dev.osal_pmops->pm_resume(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_freeze(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze) {
return coat_dev->osal_dev.osal_pmops->pm_freeze(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_thaw(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw) {
return coat_dev->osal_dev.osal_pmops->pm_thaw(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_poweroff(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff) {
return coat_dev->osal_dev.osal_pmops->pm_poweroff(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_restore(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore) {
return coat_dev->osal_dev.osal_pmops->pm_restore(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_suspend_late(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_late) {
return coat_dev->osal_dev.osal_pmops->pm_suspend_late(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_resume_early(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_early) {
return coat_dev->osal_dev.osal_pmops->pm_resume_early(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_freeze_late(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_late) {
return coat_dev->osal_dev.osal_pmops->pm_freeze_late(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_thaw_early(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_early) {
return coat_dev->osal_dev.osal_pmops->pm_thaw_early(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_poweroff_late(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_late) {
return coat_dev->osal_dev.osal_pmops->pm_poweroff_late(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_restore_early(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_early) {
return coat_dev->osal_dev.osal_pmops->pm_restore_early(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_suspend_noirq(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_noirq) {
return coat_dev->osal_dev.osal_pmops->pm_suspend_noirq(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_resume_noirq(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_noirq) {
return coat_dev->osal_dev.osal_pmops->pm_resume_noirq(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_freeze_noirq(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_noirq) {
return coat_dev->osal_dev.osal_pmops->pm_freeze_noirq(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_thaw_noirq(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_noirq) {
return coat_dev->osal_dev.osal_pmops->pm_thaw_noirq(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_poweroff_noirq(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq) {
return coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_pm_restore_noirq(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_noirq) {
return coat_dev->osal_dev.osal_pmops->pm_restore_noirq(&(coat_dev->osal_dev));
}
return 0;
}
static int osal_devfreq_target(struct media_device *media, unsigned long *freq, unsigned int flags)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_profile->target) {
return coat_dev->osal_dev.osal_profile->target(&(coat_dev->osal_dev), freq, flags);
}
return 0;
}
static int osal_devfreq_get_dev_status(struct media_device *media, struct osal_devfreq_dev_status *stat)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_profile->get_dev_status) {
return coat_dev->osal_dev.osal_profile->get_dev_status(&(coat_dev->osal_dev), stat);
}
return 0;
}
static int osal_devfreq_get_cur_freq(struct media_device *media, unsigned long *freq)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_profile->get_cur_freq) {
return coat_dev->osal_dev.osal_profile->get_cur_freq(&(coat_dev->osal_dev), freq);
}
return 0;
}
static void osal_devfreq_exit(struct media_device *media)
{
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
if (coat_dev->osal_dev.osal_profile->exit) {
return coat_dev->osal_dev.osal_profile->exit(&(coat_dev->osal_dev));
}
}
int osal_devfreq_register(osal_dev_t *osal_dev, struct osal_devfreq_dev_profile *osal_profile,
const char *governor, void *data)
{
struct media_device *media = NULL;
osal_devfreq_para_t devfreq_para = { 0 };
if ((osal_dev == NULL) || (osal_profile == NULL)) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev);
if ((governor != NULL) && (osal_strcmp(governor, "userspace") == 0)) {
osal_printk("Not supported governor\r\n");
return -1;
}
osal_dev->osal_profile = osal_profile;
devfreq_para.initial_freq = osal_dev->osal_profile->initial_freq;
devfreq_para.polling_ms = osal_dev->osal_profile->polling_ms;
devfreq_para.freq_table = osal_dev->osal_profile->freq_table;
devfreq_para.max_state = osal_dev->osal_profile->max_state;
return media_devfreq_register(media, &devfreq_para);
}
EXPORT_SYMBOL(osal_devfreq_register);
void osal_devfreq_unregister(osal_dev_t *osal_dev)
{
struct media_device *media = NULL;
if ((osal_dev == NULL) || (osal_dev->osal_profile == NULL)) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return;
}
media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev);
media_devfreq_unregister(media);
}
EXPORT_SYMBOL(osal_devfreq_unregister);
static struct media_ops s_osal_pmops = {
.pm_prepare = osal_pm_prepare,
.pm_complete = osal_pm_complete,
.pm_suspend = osal_pm_suspend,
.pm_resume = osal_pm_resume,
.pm_freeze = osal_pm_freeze,
.pm_thaw = osal_pm_thaw,
.pm_poweroff = osal_pm_poweroff,
.pm_restore = osal_pm_restore,
.pm_suspend_late = osal_pm_suspend_late,
.pm_resume_early = osal_pm_resume_early,
.pm_freeze_late = osal_pm_freeze_late,
.pm_thaw_early = osal_pm_thaw_early,
.pm_poweroff_late = osal_pm_poweroff_late,
.pm_restore_early = osal_pm_restore_early,
.pm_suspend_noirq = osal_pm_suspend_noirq,
.pm_resume_noirq = osal_pm_resume_noirq,
.pm_freeze_noirq = osal_pm_freeze_noirq,
.pm_thaw_noirq = osal_pm_thaw_noirq,
.pm_poweroff_noirq = osal_pm_poweroff_noirq,
.pm_restore_noirq = osal_pm_restore_noirq,
.devfreq_target = osal_devfreq_target,
.devfreq_get_dev_status = osal_devfreq_get_dev_status,
.devfreq_get_cur_freq = osal_devfreq_get_cur_freq,
.devfreq_exit = osal_devfreq_exit,
};
osal_dev_t *osal_createdev(const char *name)
{
osal_coat_dev_t *pdev = NULL;
if (name == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return NULL;
}
pdev = (osal_coat_dev_t *)kmalloc(sizeof(osal_coat_dev_t), GFP_KERNEL);
if (pdev == NULL) {
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
return NULL;
}
memset(pdev, 0, sizeof(osal_coat_dev_t));
osal_strncpy(pdev->osal_dev.name, name, sizeof(pdev->osal_dev.name) - 1);
pdev->osal_dev.dev = pdev;
return &(pdev->osal_dev);
}
EXPORT_SYMBOL(osal_createdev);
int osal_destroydev(osal_dev_t *osal_dev)
{
osal_coat_dev_t *pdev = NULL;
if (osal_dev == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
pdev = osal_dev->dev;
if (pdev == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
kfree(pdev);
return 0;
}
EXPORT_SYMBOL(osal_destroydev);
int osal_registerdevice(osal_dev_t *osal_dev)
{
struct media_device *media = NULL;
if ((osal_dev == NULL) || (osal_dev->fops == NULL)) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return -1;
}
media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev);
if (osal_dev->minor != 0) {
media->minor = osal_dev->minor;
} else {
media->minor = MEDIA_DYNAMIC_MINOR;
}
media->owner = THIS_MODULE;
media->fops = &s_osal_fops;
media->drvops = &s_osal_pmops;
osal_strncpy(media->devfs_name, osal_dev->name, sizeof(media->devfs_name) - 1);
return media_register(media);
}
EXPORT_SYMBOL(osal_registerdevice);
void osal_deregisterdevice(osal_dev_t *pdev)
{
if (pdev == NULL) {
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
return;
}
media_unregister((struct media_device *)&(((osal_coat_dev_t *)(pdev->dev))->media_dev));
}
EXPORT_SYMBOL(osal_deregisterdevice);
void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait)
{
if (DRVAL_DEBUG) {
osal_printk("%s - call poll_wait +!, table=%pK, file=%pK\n", __FUNCTION__, table->poll_table, table->data);
}
poll_wait ((struct file *)table->data, (wait_queue_head_t *)(wait->wait), table->poll_table);
if (DRVAL_DEBUG) {
osal_printk("%s - call poll_wait -!\n", __FUNCTION__);
}
}
EXPORT_SYMBOL(osal_poll_wait);
#if 0
void osal_pgprot_noncached(osal_vm_t *vm) {
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
v->vm_page_prot = pgprot_noncached(v->vm_page_prot);
}
#else
void osal_pgprot_noncached(osal_vm_t *vm)
{
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
}
#endif
EXPORT_SYMBOL(osal_pgprot_noncached);
void osal_pgprot_cached(osal_vm_t *vm)
{
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
#ifdef CONFIG_64BIT
v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot)
| PTE_VALID | PTE_DIRTY | PTE_AF);
#else
v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) | L_PTE_PRESENT
| L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_DEV_CACHED);
#endif
}
EXPORT_SYMBOL(osal_pgprot_cached);
void osal_pgprot_writecombine(osal_vm_t *vm)
{
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
}
EXPORT_SYMBOL(osal_pgprot_writecombine);
void osal_pgprot_stronglyordered(osal_vm_t *vm)
{
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
#ifdef CONFIG_64BIT
v->vm_page_prot = pgprot_device(v->vm_page_prot);
#else
v->vm_page_prot = pgprot_stronglyordered(v->vm_page_prot);
#endif
}
EXPORT_SYMBOL(osal_pgprot_stronglyordered);
int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size)
{
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
if (size == 0) {
return -EPERM;
}
return remap_pfn_range(v, addr, pfn, size, v->vm_page_prot);
}
EXPORT_SYMBOL(osal_remap_pfn_range);
int osal_io_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size)
{
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
v->vm_flags |= VM_IO;
if (size == 0) {
return -EPERM;
}
return io_remap_pfn_range(v, addr, pfn, size, v->vm_page_prot);
}
EXPORT_SYMBOL(osal_io_remap_pfn_range);
#ifdef CONFIG_SNAPSHOT_BOOT
int osal_call_usermodehelper_force(char *path, char **argv, char **envp, int wait)
{
return call_usermodehelper_force(path, argv, envp, wait);
}
EXPORT_SYMBOL(osal_call_usermodehelper_force);
#endif
@@ -0,0 +1,80 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "osal.h"
#include <linux/version.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
struct file *klib_fopen(const char *filename, int flags, int mode)
{
struct file *filp = filp_open(filename, flags, mode);
return (IS_ERR(filp)) ? NULL : filp;
}
void klib_fclose(struct file *filp)
{
if (filp != NULL) {
filp_close(filp, NULL);
}
return;
}
int klib_fwrite(const char *buf, int len, struct file *filp)
{
int writelen;
if (filp == NULL) {
return -ENOENT;
}
writelen = __kernel_write(filp, buf, len, &filp->f_pos);
return writelen;
}
int klib_fread(char *buf, unsigned int len, struct file *filp)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
mm_segment_t old_fs;
int readlen;
#endif
if (filp == NULL) {
return -ENOENT;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
old_fs = get_fs();
set_fs(get_ds());
/* The cast to a user pointer is valid due to the set_fs() */
readlen = vfs_read(filp, (void __user *)buf, len, &filp->f_pos);
set_fs(old_fs);
return readlen;
#else
return kernel_read(filp, (void __user*)buf, len, &filp->f_pos);
#endif
}
void *osal_klib_fopen(const char *filename, int flags, int mode)
{
return (void *)klib_fopen(filename, flags, mode);
}
EXPORT_SYMBOL(osal_klib_fopen);
void osal_klib_fclose(void *filp)
{
klib_fclose((struct file *)filp);
}
EXPORT_SYMBOL(osal_klib_fclose);
int osal_klib_fwrite(const char *buf, int len, void *filp)
{
return klib_fwrite(buf, len, (struct file *)filp);
}
EXPORT_SYMBOL(osal_klib_fwrite);
int osal_klib_fread(char *buf, unsigned int len, void *filp)
{
return klib_fread(buf, len, (struct file *)filp);
}
EXPORT_SYMBOL(osal_klib_fread);
@@ -0,0 +1,51 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include "osal.h"
extern void osal_proc_init(void);
extern void osal_proc_exit(void);
extern int media_init(void);
extern void media_exit(void);
extern int media_mem_init(void);
extern void media_mem_exit(void);
extern void osal_device_init(void);
static int __init osal_init(void)
{
osal_device_init();
osal_proc_init();
media_init();
media_mem_init();
osal_printk("osal %s init success!\n", OSAL_VERSION);
return 0;
}
static void __exit osal_exit(void)
{
media_exit();
media_mem_exit();
osal_proc_exit();
osal_printk("osal v1.0 exit!\n");
}
#ifdef MODULE
module_init(osal_init);
module_exit(osal_exit);
MODULE_LICENSE("GPL");
#else
int __init osal_driver_init(void)
{
return osal_init();
}
#endif

Some files were not shown because too many files have changed in this diff Show More