/* 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 #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_HAS_EARLYSUSPEND #include #endif #include #include #include #include "da223_core.h" #include "da223_cust.h" /******************************************************************************/ #define GSENSOR_MIN 2 #define MIR3DA_PRECISION 11 #define MIR3DA_RANGE 16384 #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(¶m); 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", ¶m.filter_param_l, ¶m.filter_param_h, ¶m.filter_threhold); ret = mir3da_set_filter_param(¶m); 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)); input_report_abs(sensor->input_dev, ABS_Y, (axis.y)); input_report_abs(sensor->input_dev, ABS_Z, -(axis.z)); #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; } /******************************************************************************/ static 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 int gsensor_mir3da_probe(struct i2c_client *client, const struct i2c_device_id *devid) { MI_FUN; return sensor_register_device(client, NULL, devid, &gsensor_ops); } /******************************************************************************/ static int gsensor_mir3da_remove(struct i2c_client *client) { MI_FUN; return sensor_unregister_device(client, NULL, &gsensor_ops); } /******************************************************************************/ static const struct i2c_device_id gsensor_mir3da_id[] = { {"gs_da223", ACCEL_ID_MIR3DA}, {} }; static struct i2c_driver gsensor_mir3da_driver = { .probe = gsensor_mir3da_probe, .remove = gsensor_mir3da_remove, .shutdown = sensor_shutdown, .id_table = gsensor_mir3da_id, .driver = { .name = "gsensor_mir3da", #ifdef CONFIG_PM .pm = &sensor_pm_ops, #endif }, }; module_i2c_driver(gsensor_mir3da_driver); MODULE_DESCRIPTION("mir3da 3-Axis accelerometer driver"); MODULE_LICENSE("GPL");