driver: input: sensor: add sc7660 sc7a20 da223

Change-Id: I4206f328ed2245fdfe1f7d2955603b0bb5a5e0e3
Signed-off-by: Wu Liangqing <wlq@rock-chips.com>
This commit is contained in:
Wu Liangqing
2020-06-17 17:39:49 +08:00
committed by Tao Huang
parent 549e092cc4
commit e634183e78
10 changed files with 6587 additions and 0 deletions

View File

@@ -71,6 +71,18 @@ config GS_MC3230
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
config GS_SC7660
bool "gsensor sc7660"
help
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
config GS_SC7A20
bool "gsensor sc7a20"
help
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
config GS_SC7A30
bool "gsensor sc7a30"
help
@@ -122,4 +134,10 @@ config BMA2XX_ACC
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
config GS_DA223
bool "gsensor da223"
help
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
endif

View File

@@ -10,8 +10,12 @@ obj-$(CONFIG_GS_DMT10) += dmard10.o
obj-$(CONFIG_GS_LSM303D) += lsm303d.o
obj-$(CONFIG_GS_MC3230) += mc3230.o
obj-$(CONFIG_MPU6880_ACC) += mpu6880_acc.o
obj-$(CONFIG_GS_SC7660) += sc7660.o
obj-$(CONFIG_GS_SC7A20) += sc7a20.o
obj-$(CONFIG_GS_SC7A30) += sc7a30.o
obj-$(CONFIG_MPU6500_ACC) += mpu6500_acc.o
obj-$(CONFIG_LSM330_ACC) += lsm330_acc.o
obj-$(CONFIG_BMA2XX_ACC) += bma2xx.o
obj-$(CONFIG_STK8BAXX_ACC) += stk8baxx.o
obj-$(CONFIG_GS_DA223) += da223.o
da223-objs := da223_cust.o da223_core.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,303 @@
/* Core header for MiraMEMS 3-Axis Accelerometer's driver.
*
* mir3da_core.h - Linux kernel modules for MiraMEMS 3-Axis Accelerometer
*
* Copyright (C) 2011-2013 MiraMEMS Sensing Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MIR3DA_CORE_H__
#define __MIR3DA_CORE_H__
#define CUST_VER "" /* for Custom debug version */
#define CORE_VER "4.2.0_2018-08-10-14:56:30_"CUST_VER
#define MIR3DA_SUPPORT_CHIP_LIST MIR_NSA_NTO
#define MIR3DA_BUFSIZE 256
#define MIR3DA_STK_TEMP_SOLUTION 0
#define MIR3DA_OFFSET_TEMP_SOLUTION 0
#if MIR3DA_OFFSET_TEMP_SOLUTION
#define MIR3DA_AUTO_CALIBRATE 0
#else
#define MIR3DA_AUTO_CALIBRATE 0
#endif /* !MIR3DA_OFFSET_TEMP_SOLUTION */
#if MIR3DA_AUTO_CALIBRATE
#define MIR3DA_SUPPORT_FAST_AUTO_CALI 0
#else
#define MIR3DA_SUPPORT_FAST_AUTO_CALI 0
#endif
#define MIR3DA_SENS_TEMP_SOLUTION 1
#define FILTER_AVERAGE_ENHANCE 0
#define FILTER_AVERAGE_EX 0
#define MIR3DA_SUPPORT_MULTI_LAYOUT 0
#define YZ_CROSS_TALK_ENABLE 1
#define MIR3DA_OFFSET_LEN 9
typedef void* MIR_HANDLE;
typedef void* PLAT_HANDLE;
struct serial_manage_if_s {
int (*read)(PLAT_HANDLE handle, unsigned char addr, unsigned char *data);
int (*write)(PLAT_HANDLE handle, unsigned char addr, unsigned char data);
int (*read_block)(PLAT_HANDLE handle, unsigned char base_addr, unsigned char count, unsigned char *data);
};
struct general_op_s {
struct serial_manage_if_s smi;
int (*data_save)(unsigned char *data);
int (*data_get)(unsigned char *data);
int (*data_check)(void);
int (*get_address)(PLAT_HANDLE handle);
int (*support_fast_auto_cali)(void);
int (*myprintf)(const char *fmt, ...);
int (*mysprintf)(char *buf, const char *fmt, ...);
void (*msdelay)(int ms);
};
#define MIR_GENERAL_OPS_DECLARE(OPS_HDL, SMI_RD, SMI_RDBL, SMI_WR, DAT_SAVE, DAT_GET,DAT_CHECK, GET_ADDRESS,SUPPORT_FAST_AUTO_CALI,MDELAY, MYPRINTF, MYSPRINTF) \
\
struct general_op_s OPS_HDL = { { SMI_RD, SMI_WR, SMI_RDBL }, DAT_SAVE, DAT_GET,DAT_CHECK,GET_ADDRESS, SUPPORT_FAST_AUTO_CALI,MYPRINTF, MYSPRINTF, MDELAY }
enum interrupt_src {
INTERRUPT_ACTIVITY = 1,
INTERRUPT_CLICK,
};
typedef enum _int_op_type {
INTERRUPT_OP_INIT,
INTERRUPT_OP_ENABLE,
INTERRUPT_OP_CONFIG,
INTERRUPT_OP_DISABLE,
} mir_int_op_type;
enum interrupt_pin {
INTERRUPT_PIN1,
INTERRUPT_PIN2,
};
enum pin_output_mode {
OUTPUT_MOD_PULL_PUSH,
OUTPUT_MOD_OD,
};
struct int_act_cfg_s {
unsigned char threshold;
unsigned char duration;
};
struct int_clk_cfg_s {
unsigned char threshold;
unsigned char click_time; /* click time */
unsigned char quiet_time; /* quiet time after click */
unsigned char window; /* for second click time window */
};
typedef union _int_src_configuration {
struct int_act_cfg_s act;
struct int_clk_cfg_s clk;
} mir_int_src_cfg_t;
typedef struct _int_configuration {
enum interrupt_pin pin;
enum interrupt_src int_src;
mir_int_src_cfg_t int_cfg;
} mir_int_cfg_t;
typedef struct _int_init_data {
enum pin_output_mode pin_mod;
unsigned char level; /* 1: high active, 0: low active */
unsigned char latch; /* >0: latch time, 0: no latch */
} mir_int_init_t ;
typedef union _int_op_data {
enum interrupt_src int_src;
mir_int_init_t init;
mir_int_cfg_t cfg;
} mir_int_op_data;
typedef struct _int_operations {
mir_int_op_type type;
mir_int_op_data data;
} mir_int_ops_t;
/* Register define for NSA asic */
#define NSA_REG_SPI_I2C 0x00
#define NSA_REG_WHO_AM_I 0x01
#define NSA_REG_ACC_X_LSB 0x02
#define NSA_REG_ACC_X_MSB 0x03
#define NSA_REG_ACC_Y_LSB 0x04
#define NSA_REG_ACC_Y_MSB 0x05
#define NSA_REG_ACC_Z_LSB 0x06
#define NSA_REG_ACC_Z_MSB 0x07
#define NSA_REG_MOTION_FLAG 0x09
#define NSA_REG_STEPS_MSB 0x0D
#define NSA_REG_STEPS_LSB 0x0E
#define NSA_REG_G_RANGE 0x0F
#define NSA_REG_ODR_AXIS_DISABLE 0x10
#define NSA_REG_POWERMODE_BW 0x11
#define NSA_REG_SWAP_POLARITY 0x12
#define NSA_REG_FIFO_CTRL 0x14
#define NAS_REG_INT_SET0 0x15
#define NSA_REG_INTERRUPT_SETTINGS1 0x16
#define NSA_REG_INTERRUPT_SETTINGS2 0x17
#define NSA_REG_INTERRUPT_MAPPING1 0x19
#define NSA_REG_INTERRUPT_MAPPING2 0x1a
#define NSA_REG_INTERRUPT_MAPPING3 0x1b
#define NSA_REG_INT_PIN_CONFIG 0x20
#define NSA_REG_INT_LATCH 0x21
#define NSA_REG_ACTIVE_DURATION 0x27
#define NSA_REG_ACTIVE_THRESHOLD 0x28
#define NSA_REG_TAP_DURATION 0x2A
#define NSA_REG_TAP_THRESHOLD 0x2B
#define NSA_REG_STEP_CONFIG1 0x2F
#define NSA_REG_STEP_CONFIG2 0x30
#define NSA_REG_STEP_CONFIG3 0x31
#define NSA_REG_STEP_CONFIG4 0x32
#define NSA_REG_STEP_FILTER 0x33
#define NSA_REG_SM_THRESHOLD 0x34
#define NSA_REG_CUSTOM_OFFSET_X 0x38
#define NSA_REG_CUSTOM_OFFSET_Y 0x39
#define NSA_REG_CUSTOM_OFFSET_Z 0x3a
#define NSA_REG_ENGINEERING_MODE 0x7f
#define NSA_REG_SENSITIVITY_TRIM_X 0x80
#define NSA_REG_SENSITIVITY_TRIM_Y 0x81
#define NSA_REG_SENSITIVITY_TRIM_Z 0x82
#define NSA_REG_COARSE_OFFSET_TRIM_X 0x83
#define NSA_REG_COARSE_OFFSET_TRIM_Y 0x84
#define NSA_REG_COARSE_OFFSET_TRIM_Z 0x85
#define NSA_REG_FINE_OFFSET_TRIM_X 0x86
#define NSA_REG_FINE_OFFSET_TRIM_Y 0x87
#define NSA_REG_FINE_OFFSET_TRIM_Z 0x88
#define NSA_REG_SENS_COMP 0x8c
#define NSA_REG_MEMS_OPTION 0x8f
#define NSA_REG_CHIP_INFO 0xc0
#define NSA_REG_CHIP_INFO_SECOND 0xc1
#define NSA_REG_MEMS_OPTION_SECOND 0xc7
#define NSA_REG_SENS_COARSE_TRIM 0xd1
#define NAS_REG_OSC_TRIM 0x8e
#define MIR3DA_ODR_50HZ 0
#define MIR3DA_ODR_100HZ 1
#define MIR3DA_ODR_200HZ 2
#define MI_TAG "[MIR3DA] "
enum{
DEBUG_ERR=1,
DEBUG_ASSERT=1<<1,
DEBUG_MSG=1<<2,
DEBUG_FUNC=1<<3,
DEBUG_DATA=1<<4,
};
extern int mir3da_Log_level;
/* register operation */
int mir3da_register_read(MIR_HANDLE handle, short reg, unsigned char *data);
int mir3da_register_write(MIR_HANDLE handle, short reg, unsigned char data);
int mir3da_register_read_continuously(MIR_HANDLE handle, short base_reg, unsigned char count, unsigned char *data);
int mir3da_register_mask_write(MIR_HANDLE handle, short addr, unsigned char mask, unsigned char data);
int mir3da_install_general_ops(struct general_op_s *ops);
/* chip init */
MIR_HANDLE mir3da_core_init(PLAT_HANDLE handle);
/* data polling */
int mir3da_read_data(MIR_HANDLE handle, short *x, short *y, short *z);
/* filter configure */
#if FILTER_AVERAGE_ENHANCE
struct mir3da_filter_param_s{
int filter_param_l;
int filter_param_h;
int filter_threhold;
};
int mir3da_get_filter_param(struct mir3da_filter_param_s* param);
int mir3da_set_filter_param(struct mir3da_filter_param_s* param);
#endif
#if MIR3DA_STK_TEMP_SOLUTION
#endif
enum {
GSENSOR_MOD_NSA_NTO=0,
};
/* CALI */
int mir3da_calibrate(MIR_HANDLE handle, int z_dir);
/* calibration */
#if MIR3DA_OFFSET_TEMP_SOLUTION
enum file_check_statu {
FILE_NO_EXIST ,
FILE_CHECKING ,
FILE_EXIST,
};
#endif
/* Interrupt operations */
int mir3da_interrupt_ops(MIR_HANDLE handle, mir_int_ops_t *ops);
int mir3da_read_offset(MIR_HANDLE handle, unsigned char* offst);
int mir3da_write_offset(MIR_HANDLE handle, unsigned char* offset);
int mir3da_set_enable(MIR_HANDLE handle, char bEnable);
int mir3da_get_enable(MIR_HANDLE handle, char *bEnable);
int mir3da_get_reg_data(MIR_HANDLE handle, char *buf);
int mir3da_set_odr(MIR_HANDLE handle, int delay);
int mir3da_direction_remap(short *x,short *y, short *z, int direction);
int mir3da_chip_resume(MIR_HANDLE handle);
int mir3da_get_primary_offset(MIR_HANDLE handle,int *x,int *y,int *z);
int mir3da_read_step(MIR_HANDLE handle, unsigned short *count);
int mir3da_step_count_init(MIR_HANDLE handle);
int mir3da_irq_init(MIR_HANDLE handle);
int mir3da_step_count_init(MIR_HANDLE handle);
int mir3da_get_step_enable(MIR_HANDLE handle, char *enable);
int mir3da_set_step_enable(MIR_HANDLE handle, char enable);
int mir3da_get_sm_enable(MIR_HANDLE handle, char *enable);
int mir3da_set_sm_enable(MIR_HANDLE handle, char enable);
int mir3da_get_tilt_enable(MIR_HANDLE handle, char *enable);
int mir3da_set_tilt_enable(MIR_HANDLE handle, char enable);
#endif /* __MIR3DA_CORE_H__ */

View File

@@ -0,0 +1,890 @@
/* For RockChip android platform.
*
* mir3da.c - Linux kernel modules for 3-Axis Accelerometer
*
* Copyright (C) 2011-2013 MiraMEMS Sensing Technology Co., Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/freezer.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>
#include <linux/syscalls.h>
#include <linux/fs.h>
#include "da223_core.h"
#include "da223_cust.h"
/******************************************************************************/
#define GSENSOR_MIN 2
#define MIR3DA_PRECISION 11
#define MIR3DA_RANGE 1000000
#define DA311_BOUNDARY (0x1 << (MIR3DA_PRECISION - 1))
#define DA311_GRAVITY_STEP (MIR3DA_RANGE/DA311_BOUNDARY)
/******************************************************************************/
#define MIR3DA_DRV_NAME "mir3da"
#define MIR3DA_INPUT_DEV_NAME MIR3DA_DRV_NAME
/******************************************************************************/
static MIR_HANDLE mir_handle;
static int is_init =0;
/******************************************************************************/
#define MI_DATA(format, ...) if(DEBUG_DATA&mir3da_Log_level){printk(KERN_ERR MI_TAG format "\n", ## __VA_ARGS__);}
#define MI_MSG(format, ...) if(DEBUG_MSG&mir3da_Log_level){printk(KERN_ERR MI_TAG format "\n", ## __VA_ARGS__);}
#define MI_ERR(format, ...) if(DEBUG_ERR&mir3da_Log_level){printk(KERN_ERR MI_TAG format "\n", ## __VA_ARGS__);}
#define MI_FUN if(DEBUG_FUNC&mir3da_Log_level){printk(KERN_ERR MI_TAG "%s is called, line: %d\n", __FUNCTION__,__LINE__);}
#define MI_ASSERT(expr) \
if (!(expr)) {\
printk(KERN_ERR "Assertion failed! %s,%d,%s,%s\n",\
__FILE__, __LINE__, __func__, #expr);\
}
/******************************************************************************/
#if MIR3DA_OFFSET_TEMP_SOLUTION
static char OffsetFileName[] = "/data/misc/miraGSensorOffset.txt";
static char OffsetFolerName[] = "/data/misc/";
#define OFFSET_STRING_LEN 26
struct work_info
{
char tst1[20];
char tst2[20];
char buffer[OFFSET_STRING_LEN];
struct workqueue_struct *wq;
struct delayed_work read_work;
struct delayed_work write_work;
struct completion completion;
int len;
int rst;
};
static struct work_info m_work_info = {{0}};
/******************************************************************************/
static void sensor_write_work( struct work_struct *work )
{
struct work_info* pWorkInfo;
struct file *filep;
mm_segment_t orgfs;
int ret;
orgfs = get_fs();
set_fs(KERNEL_DS);
pWorkInfo = container_of((struct delayed_work*)work, struct work_info, write_work);
if (pWorkInfo == NULL){
MI_ERR("get pWorkInfo failed!");
return;
}
filep = filp_open(OffsetFileName, O_RDWR|O_CREAT, 0600);
if (IS_ERR(filep)){
MI_ERR("write, sys_open %s error!!.\n", OffsetFileName);
ret = -1;
}
else
{
filep->f_op->write(filep, pWorkInfo->buffer, pWorkInfo->len, &filep->f_pos);
filp_close(filep, NULL);
ret = 0;
set_fs(orgfs);
pWorkInfo->rst = ret;
complete( &pWorkInfo->completion );
}
/******************************************************************************/
static void sensor_read_work( struct work_struct *work )
{
mm_segment_t orgfs;
struct file *filep;
int ret;
struct work_info* pWorkInfo;
orgfs = get_fs();
set_fs(KERNEL_DS);
pWorkInfo = container_of((struct delayed_work*)work, struct work_info, read_work);
if (pWorkInfo == NULL){
MI_ERR("get pWorkInfo failed!");
return;
}
filep = filp_open(OffsetFileName, O_RDONLY, 0600);
if (IS_ERR(filep)){
MI_ERR("read, sys_open %s error!!.\n",OffsetFileName);
set_fs(orgfs);
ret = -1;
}
else{
filep->f_op->read(filep, pWorkInfo->buffer, sizeof(pWorkInfo->buffer), &filep->f_pos);
filp_close(filep, NULL);
set_fs(orgfs);
ret = 0;
}
pWorkInfo->rst = ret;
complete( &(pWorkInfo->completion) );
}
/******************************************************************************/
static int sensor_sync_read(u8* offset)
{
int err;
int off[MIR3DA_OFFSET_LEN] = {0};
struct work_info* pWorkInfo = &m_work_info;
init_completion( &pWorkInfo->completion );
queue_delayed_work( pWorkInfo->wq, &pWorkInfo->read_work, msecs_to_jiffies(0) );
err = wait_for_completion_timeout( &pWorkInfo->completion, msecs_to_jiffies( 2000 ) );
if ( err == 0 ){
MI_ERR("wait_for_completion_timeout TIMEOUT");
return -1;
}
if (pWorkInfo->rst != 0){
MI_ERR("work_info.rst not equal 0");
return pWorkInfo->rst;
}
sscanf(m_work_info.buffer, "%x,%x,%x,%x,%x,%x,%x,%x,%x", &off[0], &off[1], &off[2], &off[3], &off[4], &off[5],&off[6], &off[7], &off[8]);
offset[0] = (u8)off[0];
offset[1] = (u8)off[1];
offset[2] = (u8)off[2];
offset[3] = (u8)off[3];
offset[4] = (u8)off[4];
offset[5] = (u8)off[5];
offset[6] = (u8)off[6];
offset[7] = (u8)off[7];
offset[8] = (u8)off[8];
return 0;
}
/******************************************************************************/
static int sensor_sync_write(u8* off)
{
int err = 0;
struct work_info* pWorkInfo = &m_work_info;
init_completion( &pWorkInfo->completion );
sprintf(m_work_info.buffer, "%x,%x,%x,%x,%x,%x,%x,%x,%x\n", off[0],off[1],off[2],off[3],off[4],off[5],off[6],off[7],off[8]);
pWorkInfo->len = sizeof(m_work_info.buffer);
queue_delayed_work( pWorkInfo->wq, &pWorkInfo->write_work, msecs_to_jiffies(0) );
err = wait_for_completion_timeout( &pWorkInfo->completion, msecs_to_jiffies( 2000 ) );
if ( err == 0 ){
MI_ERR("wait_for_completion_timeout TIMEOUT");
return -1;
}
if (pWorkInfo->rst != 0){
MI_ERR("work_info.rst not equal 0");
return pWorkInfo->rst;
}
return 0;
}
/******************************************************************************/
static int check_califolder_exist(void)
{
mm_segment_t orgfs;
struct file *filep;
orgfs = get_fs();
set_fs(KERNEL_DS);
filep = filp_open(OffsetFolerName, O_RDONLY, 0600);
if (IS_ERR(filep)) {
MI_ERR("%s read, sys_open %s error!!.\n",__func__,OffsetFolerName);
set_fs(orgfs);
return 0;
}
filp_close(filep, NULL);
set_fs(orgfs);
return 1;
}
/******************************************************************************/
static int support_fast_auto_cali(void)
{
#if MIR3DA_SUPPORT_FAST_AUTO_CALI
return 1;
#else
return 0;
#endif
}
#endif
/******************************************************************************/
static int get_address(PLAT_HANDLE handle)
{
if(NULL == handle){
MI_ERR("chip init failed !\n");
return -1;
}
return ((struct i2c_client *)handle)->addr;
}
/******************************************************************************/
static int i2c_smbus_read(PLAT_HANDLE handle, u8 addr, u8 *data)
{
int res = 0;
struct i2c_client *client = (struct i2c_client*)handle;
*data = i2c_smbus_read_byte_data(client, addr);
return res;
}
/******************************************************************************/
static int i2c_smbus_read_block(PLAT_HANDLE handle, u8 addr, u8 count, u8 *data)
{
int res = 0;
struct i2c_client *client = (struct i2c_client*)handle;
res = i2c_smbus_read_i2c_block_data(client, addr, count, data);
return res;
}
/******************************************************************************/
static int i2c_smbus_write(PLAT_HANDLE handle, u8 addr, u8 data)
{
int res = 0;
struct i2c_client *client = (struct i2c_client*)handle;
res = i2c_smbus_write_byte_data(client, addr, data);
return res;
}
/******************************************************************************/
static void msdelay(int ms)
{
mdelay(ms);
}
/******************************************************************************/
#if MIR3DA_OFFSET_TEMP_SOLUTION
static MIR_GENERAL_OPS_DECLARE(ops_handle, i2c_smbus_read, i2c_smbus_read_block, i2c_smbus_write, sensor_sync_write, sensor_sync_read, check_califolder_exist,get_address,support_fast_auto_cali,msdelay, printk, sprintf);
#else
static MIR_GENERAL_OPS_DECLARE(ops_handle, i2c_smbus_read, i2c_smbus_read_block, i2c_smbus_write, NULL, NULL, NULL,get_address,NULL,msdelay, printk, sprintf);
#endif
/******************************************************************************/
static ssize_t enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
char bEnable;
MI_FUN;
ret = mir3da_get_enable(mir_handle, &bEnable);
if (ret < 0){
ret = -EINVAL;
}
else{
ret = sprintf(buf, "%d\n", bEnable);
}
return ret;
}
/******************************************************************************/
static ssize_t enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
bool bEnable;
unsigned long enable;
if (buf == NULL){
return -1;
}
enable = simple_strtoul(buf, NULL, 10);
bEnable = (enable > 0) ? true : false;
MI_MSG("%s:enable=%d\n",__func__,bEnable);
ret = mir3da_set_enable (mir_handle, bEnable);
if (ret < 0){
ret = -EINVAL;
}
else{
ret = count;
}
return ret;
}
/******************************************************************************/
static ssize_t axis_data_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int result;
short x,y,z;
int count = 0;
result = mir3da_read_data(mir_handle, &x, &y, &z);
if (result == 0)
count += sprintf(buf+count, "x= %d;y=%d;z=%d\n", x,y,z);
else
count += sprintf(buf+count, "reading failed!");
return count;
}
/******************************************************************************/
static ssize_t reg_data_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int addr, data;
int result;
sscanf(buf, "0x%x, 0x%x\n", &addr, &data);
result = mir3da_register_write(mir_handle, addr, data);
MI_ASSERT(result==0);
return count;
}
/******************************************************************************/
static ssize_t reg_data_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
MIR_HANDLE handle = mir_handle;
return mir3da_get_reg_data(handle, buf);
}
/******************************************************************************/
#if MIR3DA_OFFSET_TEMP_SOLUTION
static ssize_t offset_show(struct device *dev, struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
if(bLoad==FILE_EXIST)
count += sprintf(buf,"%s",m_work_info.buffer);
else
count += sprintf(buf,"%s","Calibration file not exist!\n");
return count;
}
#endif
/******************************************************************************/
#if FILTER_AVERAGE_ENHANCE
static ssize_t average_enhance_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret = 0;
struct mir3da_filter_param_s param = {0};
ret = mir3da_get_filter_param(&param);
ret |= sprintf(buf, "%d %d %d\n", param.filter_param_l, param.filter_param_h, param.filter_threhold);
return ret;
}
/******************************************************************************/
static ssize_t average_enhance_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
int ret = 0;
struct mir3da_filter_param_s param = {0};
sscanf(buf, "%d %d %d\n", &param.filter_param_l, &param.filter_param_h, &param.filter_threhold);
ret = mir3da_set_filter_param(&param);
return count;
}
#endif
/******************************************************************************/
#if MIR3DA_OFFSET_TEMP_SOLUTION
static int bCaliResult = -1;
static ssize_t calibrate_miraGSensor_show(struct device *dev,struct device_attribute *attr,char *buf)
{
int ret;
ret = sprintf(buf, "%d\n", bCaliResult);
return ret;
}
/******************************************************************************/
static ssize_t calibrate_miraGSensor_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
s8 z_dir = 0;
MIR_HANDLE handle = mir_handle;
z_dir = simple_strtol(buf, NULL, 10);
bCaliResult = mir3da_calibrate(handle,z_dir);
return count;
}
#endif
/******************************************************************************/
static ssize_t log_level_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
ret = sprintf(buf, "%d\n", mir3da_Log_level);
return ret;
}
/******************************************************************************/
static ssize_t log_level_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
mir3da_Log_level = simple_strtoul(buf, NULL, 10);
return count;
}
/******************************************************************************/
static ssize_t primary_offset_show(struct device *dev,
struct device_attribute *attr, char *buf){
MIR_HANDLE handle = mir_handle;
int x=0,y=0,z=0;
mir3da_get_primary_offset(handle,&x,&y,&z);
return sprintf(buf, "x=%d ,y=%d ,z=%d\n",x,y,z);
}
/******************************************************************************/
static ssize_t version_show(struct device *dev,
struct device_attribute *attr, char *buf){
return sprintf(buf, "%s_%s\n", DRI_VER, CORE_VER);
}
/******************************************************************************/
static ssize_t vendor_show(struct device *dev,
struct device_attribute *attr, char *buf){
return sprintf(buf, "%s\n", "MiraMEMS");
}
/******************************************************************************/
static DEVICE_ATTR_RW(enable);
static DEVICE_ATTR_RO(axis_data);
static DEVICE_ATTR_RW(reg_data);
static DEVICE_ATTR_RW(log_level);
#if MIR3DA_OFFSET_TEMP_SOLUTION
static DEVICE_ATTR_RO(offset);
static DEVICE_ATTR_RW(calibrate_miraGSensor);
#endif
#if FILTER_AVERAGE_ENHANCE
static DEVICE_ATTR_RW(average_enhance);
#endif
static DEVICE_ATTR_RO(primary_offset);
static DEVICE_ATTR_RO(version);
static DEVICE_ATTR_RO(vendor);
/******************************************************************************/
static struct attribute *mir3da_attributes[] = {
&dev_attr_enable.attr,
&dev_attr_axis_data.attr,
&dev_attr_reg_data.attr,
&dev_attr_log_level.attr,
#if MIR3DA_OFFSET_TEMP_SOLUTION
&dev_attr_offset.attr,
&dev_attr_calibrate_miraGSensor.attr,
#endif
#if FILTER_AVERAGE_ENHANCE
&dev_attr_average_enhance.attr,
#endif
&dev_attr_primary_offset.attr,
&dev_attr_version.attr,
&dev_attr_vendor.attr,
NULL
};
static const struct attribute_group mir3da_attr_group = {
.attrs = mir3da_attributes,
};
/******************************************************************************/
static int sensor_init(struct i2c_client *client)
{
int ret = 0;
static int withSysAttr = 1;
unsigned char chip_id=0;
unsigned char i=0;
struct sensor_private_data *sensor =(struct sensor_private_data *) i2c_get_clientdata(client);
MI_FUN;
if(is_init)
return 0;
sensor->status_cur = SENSOR_OFF;
if(mir3da_install_general_ops(&ops_handle)){
MI_ERR("Install ops failed !\n");
return -1;
}
#if MIR3DA_OFFSET_TEMP_SOLUTION
m_work_info.wq = create_singlethread_workqueue( "oo" );
if(NULL==m_work_info.wq) {
MI_ERR("Failed to create workqueue !");
return -1;
}
INIT_DELAYED_WORK( &m_work_info.read_work, sensor_read_work );
INIT_DELAYED_WORK( &m_work_info.write_work, sensor_write_work );
#endif
i2c_smbus_read((PLAT_HANDLE) client, NSA_REG_WHO_AM_I, &chip_id);
if(chip_id != 0x13){
for(i=0;i<5;i++){
mdelay(5);
i2c_smbus_read((PLAT_HANDLE) client, NSA_REG_WHO_AM_I, &chip_id);
if(chip_id == 0x13)
break;
}
if(i == 5)
client->addr = 0x27;
}
mir_handle = mir3da_core_init(client);
if(NULL == mir_handle){
MI_ERR("chip init failed !\n");
return -1;
}
if(withSysAttr)
{
struct input_dev* pInputDev;
pInputDev = input_allocate_device();
if (!pInputDev) {
MI_ERR("Failed to allocate input device %s\n", sensor->input_dev->name);
return -ENOMEM;
}
pInputDev->name = MIR3DA_INPUT_DEV_NAME;
set_bit(EV_ABS, pInputDev->evbit);
/* x-axis acceleration */
input_set_abs_params(pInputDev, ABS_X, sensor->ops->range[0], sensor->ops->range[1], 0, 0);
/* y-axis acceleration */
input_set_abs_params(pInputDev, ABS_Y, sensor->ops->range[0], sensor->ops->range[1], 0, 0);
/* z-axis acceleration */
input_set_abs_params(pInputDev, ABS_Z, sensor->ops->range[0], sensor->ops->range[1], 0, 0);
ret = input_register_device(pInputDev);
if (ret) {
MI_ERR("Unable to register input device %s\n", pInputDev->name);
return -ENOMEM;
}
MI_MSG("Sys Attribute Register here %s is called for MIR3DA.\n", __func__);
ret = sysfs_create_group(&pInputDev->dev.kobj, &mir3da_attr_group);
if (ret) {
MI_ERR("mir3da_attr_group create Error err=%d..", ret);
ret = -EINVAL;
}
withSysAttr = 0;
}
is_init =1;
return ret;
}
/******************************************************************************/
static int sensor_active(struct i2c_client *client, int enable, int rate)
{
int result = 0;
MI_MSG("%s. enable=%d.\n", __func__,enable);
if(!is_init)
return -1;
mdelay(10);
if(enable){
/* result = mir3da_chip_resume(client);
if(result) {
MI_ERR("sensor_active chip resume fail!!\n");
return result;
}
*/
result = mir3da_set_enable(client, true);
if(result){
MI_ERR("sensor_active enable fail!!\n");
return result;
}
}
else{
result = mir3da_set_enable(client, false);
if(result){
MI_ERR("sensor_active disable fail!!\n");
return result;
}
}
mdelay(10);
return result;
}
/******************************************************************************/
static int sensor_report_value(struct i2c_client *client)
{
struct sensor_private_data *sensor = (struct sensor_private_data *) i2c_get_clientdata(client);
struct sensor_platform_data *pdata = sensor->pdata;
struct sensor_axis axis;
int ret = 0;
short x=0,y=0,z=0;
int tmp_x=0,tmp_y=0,tmp_z=0;
static struct sensor_axis last_axis;
static int flag;
if(!is_init)
return -1;
ret = mir3da_read_data (client,&x, &y, &z);
if (ret){
MI_ERR("read data failed!");
return ret;
}
//MI_DATA(" x = %d, y = %d, z = %d\n", x, y, z);
tmp_x = x*DA311_GRAVITY_STEP;
tmp_y = y*DA311_GRAVITY_STEP;
tmp_z = z*DA311_GRAVITY_STEP;
//MI_DATA(" tmp_x = %d, tmp_y = %d, tmp_z = %d\n", tmp_x, tmp_y, tmp_z);
axis.x = (pdata->orientation[0])*tmp_x + (pdata->orientation[1])*tmp_y + (pdata->orientation[2])*tmp_z;
axis.y = (pdata->orientation[3])*tmp_x + (pdata->orientation[4])*tmp_y + (pdata->orientation[5])*tmp_z;
#if MIR3DA_STK_TEMP_SOLUTION
axis.z = (pdata->orientation[6])*tmp_x + (pdata->orientation[7])*tmp_y + (bzstk?1:(pdata->orientation[8]))*tmp_z;
#else
axis.z = (pdata->orientation[6])*tmp_x + (pdata->orientation[7])*tmp_y + (pdata->orientation[8])*tmp_z;
#endif
//MI_DATA( "map: axis = %d %d %d \n", axis.x, axis.y, axis.z);
#if 0
if (axis.x == last_axis.x && axis.y == last_axis.y && axis.z == last_axis.z)
axis.x += 1;
#else
if ((sensor->axis.x == axis.x) && (sensor->axis.y == axis.y) && (sensor->axis.z == axis.z)) {
if (flag) {
flag = 0;
axis.x += 1;
axis.y += 1;
axis.z += 1;
} else {
flag = 1;
axis.x -= 1;
axis.y -= 1;
axis.z -= 1;
}
}
#endif
// if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))
{
/* RK3326 platform board */
#if defined (CONFIG_BOARD_RK3326_AK47)
input_report_abs(sensor->input_dev, ABS_X, -(axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined (CONFIG_BOARD_RK3326_TH700)
input_report_abs(sensor->input_dev, ABS_X, -(axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH863B_10)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH863B_7)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH863B_V31_7)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH863B_8)
input_report_abs(sensor->input_dev, ABS_X, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH7926_7)
input_report_abs(sensor->input_dev, ABS_X, -(axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH7926_9)
input_report_abs(sensor->input_dev, ABS_X, -(axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_MT1011)
input_report_abs(sensor->input_dev, ABS_X, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_M1011QR)
input_report_abs(sensor->input_dev, ABS_X, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH1021DN)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3326_TH1021DN_V20)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
/* RK3126C platform board */
#elif defined(CONFIG_BOARD_RK3126C_AK47)
input_report_abs(sensor->input_dev, ABS_X, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3126C_TH1021DN)
input_report_abs(sensor->input_dev, ABS_X, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, -(axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3126C_TH863_7)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3126C_TH863_8)
input_report_abs(sensor->input_dev, ABS_X, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#elif defined(CONFIG_BOARD_RK3126C_TH98V)
input_report_abs(sensor->input_dev, ABS_X, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.x/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
/* RK3368 platform board */
#elif defined(CONFIG_BOARD_RK3368_TH863C_10)
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#else
input_report_abs(sensor->input_dev, ABS_X, -(axis.x/64));
input_report_abs(sensor->input_dev, ABS_Y, (axis.y/64));
input_report_abs(sensor->input_dev, ABS_Z, -(axis.z/64));
#endif
input_sync(sensor->input_dev);
last_axis = axis;
mutex_lock(&(sensor->data_mutex) );
sensor->axis = axis;
mutex_unlock(&(sensor->data_mutex) );
}
return ret;
}
/******************************************************************************/
static int sensor_suspend(struct i2c_client *client)
{
int result = 0;
MI_FUN;
mdelay(10);
result = mir3da_set_enable(client, false);
if(result){
MI_ERR("sensor_suspend disable fail!!\n");
return result;
}
mdelay(10);
return result;
}
/******************************************************************************/
static int sensor_resume(struct i2c_client *client)
{
int result = 0;
MI_FUN;
mdelay(10);
/*
result = mir3da_chip_resume(client);
if(result) {
MI_ERR("sensor_resume chip resume fail!!\n");
return result;
}
*/
result = mir3da_set_enable(client, true);
if(result){
MI_ERR("sensor_resume enable fail!!\n");
return result;
}
mdelay(10);
return result;
}
/******************************************************************************/
struct sensor_operate gsensor_ops = {
.name = MIR3DA_DRV_NAME,
.type = SENSOR_TYPE_ACCEL,
.id_i2c = ACCEL_ID_MIR3DA,
.read_reg =-1,
.read_len = 0,
.id_reg = -1,
.id_data = 0,
.precision = MIR3DA_PRECISION,
.ctrl_reg = -1,
.int_status_reg = 0x00,
.range = {-MIR3DA_RANGE,MIR3DA_RANGE},
.trig = IRQF_TRIGGER_LOW|IRQF_ONESHOT,
.active = sensor_active,
.init = sensor_init,
.report = sensor_report_value,
.suspend =sensor_suspend,
.resume =sensor_resume,
};
/******************************************************************************/
static struct sensor_operate *gsensor_get_ops(void)
{
return &gsensor_ops;
}
/******************************************************************************/
static int __init mir3da_init(void)
{
struct sensor_operate *ops = gsensor_get_ops();
int result = 0;
int type = ops->type;
MI_FUN;
result = sensor_register_slave(type, NULL, NULL, gsensor_get_ops);
return result;
}
/******************************************************************************/
static void __exit mir3da_exit(void)
{
struct sensor_operate *ops = gsensor_get_ops();
int type = ops->type;
MI_FUN;
sensor_unregister_slave(type, NULL, NULL, gsensor_get_ops);
}
/******************************************************************************/
module_init(mir3da_init);
module_exit(mir3da_exit);

View File

@@ -0,0 +1,44 @@
/* For RockChip android platform.
*
* mir3da.h - Linux kernel modules for 3-Axis Accelerometer
*
* Copyright (C) 2011-2013 MiraMEMS Sensing Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MIR3DA_STANDARD_H__
#define __MIR3DA_STANDARD_H__
#include <linux/ioctl.h>
#include <linux/kernel.h>
#include "da223_core.h"
#define DRI_VER "1.0"
#define MIR3DA_I2C_ADDR 0x26//0x26<-> SD0=GND;0x27<-> SD0=High
#define MIR3DA_ACC_IOCTL_BASE 88
#define IOCTL_INDEX_BASE 0x00
#define MIR3DA_ACC_IOCTL_SET_DELAY _IOW(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE, int)
#define MIR3DA_ACC_IOCTL_GET_DELAY _IOR(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+1, int)
#define MIR3DA_ACC_IOCTL_SET_ENABLE _IOW(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+2, int)
#define MIR3DA_ACC_IOCTL_GET_ENABLE _IOR(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+3, int)
#define MIR3DA_ACC_IOCTL_SET_G_RANGE _IOW(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+4, int)
#define MIR3DA_ACC_IOCTL_GET_G_RANGE _IOR(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+5, int)
#define MIR3DA_ACC_IOCTL_GET_COOR_XYZ _IOW(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+22, int)
#define MIR3DA_ACC_IOCTL_CALIBRATION _IOW(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+23, int)
#define MIR3DA_ACC_IOCTL_UPDATE_OFFSET _IOW(MIR3DA_ACC_IOCTL_BASE, IOCTL_INDEX_BASE+24, int)
#endif /* !__MIR3DA_STANDARD_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2016,6 +2016,8 @@ static const struct i2c_device_id sensor_id[] = {
{"gs_mxc6655xa", ACCEL_ID_MXC6655XA},
{"gs_dmard10", ACCEL_ID_DMARD10},
{"gs_lsm303d", ACCEL_ID_LSM303D},
{"gs_sc7660", ACCEL_ID_SC7660},
{"gs_sc7a20", ACCEL_ID_SC7A20},
{"gs_sc7a30",ACCEL_ID_SC7A30},
{"gs_mc3230", ACCEL_ID_MC3230},
{"mpu6880_acc", ACCEL_ID_MPU6880},
@@ -2023,6 +2025,7 @@ static const struct i2c_device_id sensor_id[] = {
{"lsm330_acc", ACCEL_ID_LSM330},
{"bma2xx_acc", ACCEL_ID_BMA2XX},
{"gs_stk8baxx", ACCEL_ID_STK8BAXX},
{"gs_da223", ACCEL_ID_MIR3DA},
/*compass*/
{"compass", COMPASS_ID_ALL},
{"ak8975", COMPASS_ID_AK8975},

View File

@@ -51,6 +51,8 @@ enum sensor_id {
ACCEL_ID_MMA8450,
ACCEL_ID_MMA845X,
ACCEL_ID_MMA7660,
ACCEL_ID_SC7660,
ACCEL_ID_SC7A20,
ACCEL_ID_SC7A30,
ACCEL_ID_MPU6050,
ACCEL_ID_MXC6225,
@@ -63,6 +65,7 @@ enum sensor_id {
ACCEL_ID_LSM330,
ACCEL_ID_BMA2XX,
ACCEL_ID_STK8BAXX,
ACCEL_ID_MIR3DA,
COMPASS_ID_ALL,
COMPASS_ID_AK8975,
COMPASS_ID_AK8963,