sdk-hwV1.3/lichee/linux-4.9/drivers/input/sensor/sc7660.c

2108 lines
62 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* drivers/hwmon/sc7660.c
*
*allwinner platform
*
* 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/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/fs.h>
#include <linux/input-polldev.h>
#include <linux/device.h>
#include "../init-input.h"
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
//#include <mach/system.h>
//#include <mach/hardware.h>
//#undef CONFIG_HAS_EARLYSUSPEND
#undef CONFIG_PM
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_PM)
#include <linux/pm.h>
#endif
/*
* Defines
*/
#define assert(expr)\
if (!(expr)) {\
printk("Assertion failed! %s,%d,%s,%s\n",\
__FILE__, __LINE__, __func__, #expr);\
}
#define sc7660_DRV_NAME "sc7660"
#define SENSOR_NAME sc7660_DRV_NAME
#define POLL_INTERVAL_MAX 1000
#define POLL_INTERVAL 50
#define INPUT_FUZZ 2
#define INPUT_FLAT 2
#define TIANJU_FILTER
#define sc7660_REG_CTRL 0x20
#define sc7660_REG_DATA 0x00
/* sc7660 control bit */
#define sc7660_CTRL_PWRON 0x47 /* power on */
#define sc7660_CTRL_PWRDN 0x00 /* power donw */
#define MODE_CHANGE_DELAY_MS 100
#define CALIBRATION_NUM 40
#define AXIS_X_Y_RANGE_LIMIT 200
#define AXIS_X_Y_AVG_LIMIT 400
#define AXIS_Z_RANGE 200
#define AXIS_Z_DFT_G 1000
#define GOTO_CALI 100
#define FAILTO_CALI 101
#define SC7660_ENABLE 1
#define SC7660_XOUT_L 0x28
#define SC7660_XOUT_H 0x29
#define SC7660_YOUT_L 0x2A
#define SC7660_YOUT_H 0x2B
#define SC7660_ZOUT_L 0x2C
#define SC7660_ZOUT_H 0x2D
#define SC7660_MODE 0x20
#define SC7660_MODE1 0x21
#define SC7660_MODE2 0x22
#define SC7660_MODE3 0x23
#define SC7660_BOOT 0x24
#define SC7660_STATUS 0x27
#define GSENSOR_REG_CALI
/*
#ifdef GSENSOR_REG_CALI
static int reg[29] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, \
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, \
0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A};
static int reg_data[29] = {0};
#endif
*/
static struct device *hwmon_dev = NULL;
static struct i2c_client *sc7660_i2c_client = NULL;
static struct input_polled_dev *sc7660_idev = NULL;
struct sc7660_data_s {
struct i2c_client *client;
struct input_polled_dev *pollDev;
struct mutex interval_mutex;
struct delayed_work dwork;//allen
int time_of_cali;
atomic_t enable;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
#if defined(CONFIG_PM) || defined(CONFIG_HAS_EARLYSUSPEND)
volatile int suspend_indator;
#endif
struct hrtimer hr_timer;
struct work_struct wq_hrtimer;
ktime_t ktime;
} sc7660_data;
/* Addresses to scan */
static const unsigned short normal_i2c[] = {0x1D,I2C_CLIENT_END};
static __u32 twi_id = 0;
static struct sensor_config_info gsensor_info = {
.input_type = GSENSOR_TYPE,
};
enum {
DEBUG_INIT = 1U << 0,
DEBUG_CONTROL_INFO = 1U << 1,
DEBUG_DATA_INFO = 1U << 2,
DEBUG_SUSPEND = 1U << 3,
};
static u32 debug_mask = 0x0;
#define dprintk(level_mask, fmt, arg...) if (unlikely(debug_mask & level_mask)) \
printk(KERN_DEBUG fmt , ## arg)
module_param_named(debug_mask, debug_mask, int, S_IRUGO);
#ifdef CONFIG_HAS_EARLYSUSPEND
static void sc7660_early_suspend(struct early_suspend *h);
static void sc7660_late_resume(struct early_suspend *h);
#endif
static struct workqueue_struct *sc7660_workqueue = NULL;
struct SC7660_acc{
int x;
int y;
int z;
} ;
struct Cali_Data {
//mis p and n
unsigned char xpmis; //x axis positive mismatch to write
unsigned char xnmis; //x axis negtive mismatch to write
unsigned char ypmis;
unsigned char ynmis;
unsigned char zpmis;
unsigned char znmis;
//off p and n
unsigned char xpoff; //x axis positive offset to write
unsigned char xnoff; //x axis negtive offset to write
unsigned char ypoff;
unsigned char ynoff;
unsigned char zpoff;
unsigned char znoff;
//mid mis and off
unsigned char xmmis; //x axis middle mismatch to write
unsigned char ymmis; //y axis middle mismatch to write
unsigned char zmmis; //z axis middle mismatch to write
unsigned char xmoff; //x axis middle offset to write
unsigned char ymoff; //y axis middle offset to write
unsigned char zmoff; //z axis middle offset to write
//output p and n
signed int xpoutput; //x axis output of positive mismatch
signed int xnoutput; //x axis output of negtive mismatch
signed int ypoutput;
signed int ynoutput;
signed int zpoutput;
signed int znoutput;
//output
signed int xfoutput; //x axis the best or the temporary output
signed int yfoutput; //y axis the best or the temporary output
signed int zfoutput; //z axis the best or the temporary output
//final and temp flag
unsigned char xfinalf; //x axis final flag:if 1,calibration finished
unsigned char yfinalf; //y axis final flag:if 1,calibration finished
unsigned char zfinalf; //z axis final flag:if 1,calibration finished
unsigned char xtempf; //x axis temp flag:if 1,the step calibration finished
unsigned char ytempf; //y axis temp flag:if 1,the step calibration finished
unsigned char ztempf; //z axis temp flag:if 1,the step calibration finished
unsigned char xaddmis; //x axis mismtach register address
unsigned char yaddmis; //y axis mismtach register address
unsigned char zaddmis; //z axis mismtach register address
unsigned char xaddoff; //x axis offset register address
unsigned char yaddoff; //y axis offset register address
unsigned char zaddoff; //z axis offset register address
unsigned char (*MisDataSpaceConvert)(unsigned char continuous); //mismatch space convert function pointer
unsigned char (*OffDataSpaceConvert)(unsigned char continuous); //offset space convert function pointer
};
static int sc7660_acc_get_data( int *xyz);
static void sc7660_reset(void);
static char Read_Reg(unsigned char reg)
{
char ret;
ret = i2c_smbus_read_byte_data(sc7660_i2c_client, reg);
return ret;
}
/*
static signed char Read_Output(char reg)
{
char ret = 0;
char acc_buf[6];
int index = 0;
while(1)
{
msleep(15);
ret = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_STATUS);
if( (ret & 0x08) != 0 )
{
break;
}
index++;
if(index > 40)
break;
}
acc_buf[0] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_L);
acc_buf[1] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_H);
acc_buf[2] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_L);
acc_buf[3] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_H);
acc_buf[4] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_L);
acc_buf[5] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_H);
if(reg == 0x29)
{
return acc_buf[1];
}
else if(reg == 0x2b)
{
return acc_buf[3];
}
else if(reg == 0x2d)
{
return acc_buf[5];
}
else
return 0;
}
*/
static void Read_Output_3axis(unsigned char *acc_buf)
{
char buffer[3] = {0};
int index = 0;
//int ret = 0;
while(1){
msleep(20);
*buffer = SC7660_STATUS;
//ret = sensor_rx_data(sc7660_client, buffer,1);
buffer[0] = Read_Reg(0x27);
if( (buffer[0] & 0x08) != 0 ){break;}
index++;
if(index > 40)break;
}
//6 register data be read out
acc_buf[0] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_L);
acc_buf[1] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_H);
acc_buf[2] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_L);
acc_buf[3] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_H);
acc_buf[4] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_L);
acc_buf[5] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_H);
}
static void Write_Input(char addr, char thedata)
{
int result;
//result = sensor_write_reg(sc7660_i2c_client, addr, thedata);
result = i2c_smbus_write_byte_data(sc7660_i2c_client, addr, thedata);
}
static void tilt_3axis_mtp(signed int x,signed int y,signed int z){
char buffer[6] = {0};
unsigned char buffer0[6] = {0};
unsigned char buffer1[6] = {0};
signed char mtpread[3]={0};
signed int xoutp,youtp,zoutp;
signed int xoutpt,youtpt,zoutpt;
signed char xtilt,ytilt,ztilt;
xoutp=youtp=zoutp=0;
xoutpt=youtpt=zoutpt=0;
xtilt=ytilt=ztilt=0;
Read_Output_3axis(buffer0);
Read_Output_3axis(buffer1);
xoutpt = ((signed int)((buffer1[1]<<8)|buffer1[0]))>>4;
youtpt = ((signed int)((buffer1[3]<<8)|buffer1[2]))>>4;
zoutpt = ((signed int)((buffer1[5]<<8)|buffer1[4]))>>4;
xoutp = xoutpt-x*16;
youtp = youtpt-y*16;
zoutp = zoutpt-z*16;
buffer[0] = Read_Reg(0x10);
mtpread[0]=(signed char)buffer[0];
buffer[0] = Read_Reg(0x11);
mtpread[1]=(signed char)buffer[0];
buffer[0] = Read_Reg(0x12);
mtpread[2]=(signed char)buffer[0];
//calculate the new tilt mtp value
xtilt=(signed char)(xoutp/8)+ mtpread[0];
ytilt=(signed char)(youtp/8)+ mtpread[1];
ztilt=(signed char)(zoutp/8)+ mtpread[2];
//write the new into mtp
Write_Input(0x10,xtilt);
Write_Input(0x11,ytilt);
Write_Input(0x12,ztilt);
}
//input:two data
//0 for not near zero
//1 for first data
//2 for second data
/*
static char IsNearZero(unsigned int Pos, unsigned int Neg, unsigned char error)
{
if(abs(Pos) < error)
return 1;
if(abs(Neg) < error)
return 2;
return 0;
}
*/
/*
static unsigned char forword_MisDataSpaceConvert(unsigned char continuous)
{
if(continuous >= 128)
return continuous - 128;
else
return 255 - continuous;
}
*/
static unsigned char reverse_MisDataSpaceConvert(unsigned char continuous)
{
if(continuous >= 128)
return continuous;
else
return 127 - continuous;
}
static unsigned char reverse_OffDataSpaceConvert(unsigned char continuous)
{
return 127 - continuous;
}
static unsigned char forword_OffDataSpaceConvert(unsigned char continuous)
{
return continuous;
}
//set finalflag xfinalf-yfinalf-zfinalf upto the relative output
static void check_output_set_finalflag(struct Cali_Data *pcalidata,unsigned char err){
if(abs(pcalidata->xfoutput) < err){
//printk("line:%d Xcali finish!Final=%d\n",__LINE__,pcalidata->xfoutput);
pcalidata->xfinalf=1;
}
if(abs(pcalidata->yfoutput) < err){
//printk("line:%d Xcali finish!Final=%d\n",__LINE__,pcalidata->yfoutput);
pcalidata->yfinalf=1;
}
if(abs(pcalidata->zfoutput) < err){
//printk("line:%d Xcali finish!Final=%d\n",__LINE__,pcalidata->zfoutput);
pcalidata->zfinalf=1;
}
}
static void check_finalflag_set_tempflag(struct Cali_Data *pcalidata){
if(pcalidata->xfinalf){pcalidata->xtempf=1;}
if(pcalidata->yfinalf){pcalidata->ytempf=1;}
if(pcalidata->zfinalf){pcalidata->ztempf=1;}
}
static unsigned char check_flag_is_return(struct Cali_Data *pcalidata){
if((pcalidata->xfinalf) && (pcalidata->yfinalf) && (pcalidata->zfinalf))
{
return 1;
}
else return 0;
}
static void updata_midmis_address(struct Cali_Data *pcalidata){
if(pcalidata->xtempf==0){
pcalidata->xmmis=(unsigned char)(((unsigned int)(pcalidata->xpmis) + (unsigned int)(pcalidata->xnmis))/2);
pcalidata->MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(pcalidata->xaddmis, (*(pcalidata->MisDataSpaceConvert))(pcalidata->xmmis));
}
if(pcalidata->ytempf==0){
pcalidata->ymmis=(unsigned char)(((unsigned int)(pcalidata->ypmis) + (unsigned int)(pcalidata->ynmis))/2);
//pcalidata->MisDataSpaceConvert = forword_MisDataSpaceConvert;
pcalidata->MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(pcalidata->yaddmis, (*(pcalidata->MisDataSpaceConvert))(pcalidata->ymmis));
}
if(pcalidata->ztempf==0){
pcalidata->zmmis=(unsigned char)(((unsigned int)(pcalidata->zpmis) + (unsigned int)(pcalidata->znmis))/2);
pcalidata->MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(pcalidata->zaddmis, (*(pcalidata->MisDataSpaceConvert))(pcalidata->zmmis));
}
}
static void updata_midoff_address(struct Cali_Data *pcalidata){
if(pcalidata->xtempf==0){
pcalidata->xmoff=(unsigned char)(((unsigned int)(pcalidata->xpoff) + (unsigned int)(pcalidata->xnoff))/2);
pcalidata->OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(pcalidata->xaddoff, (*(pcalidata->OffDataSpaceConvert))(pcalidata->xmoff));
}
if(pcalidata->ytempf==0){
pcalidata->ymoff=(unsigned char)(((unsigned int)(pcalidata->ypoff) + (unsigned int)(pcalidata->ynoff))/2);
//pcalidata->OffDataSpaceConvert = forword_OffDataSpaceConvert;
pcalidata->OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(pcalidata->yaddoff, (*(pcalidata->OffDataSpaceConvert))(pcalidata->ymoff));
}
if(pcalidata->ztempf==0){
pcalidata->zmoff=(unsigned char)(((unsigned int)(pcalidata->zpoff) + (unsigned int)(pcalidata->znoff))/2);
pcalidata->OffDataSpaceConvert = forword_OffDataSpaceConvert;
Write_Input(pcalidata->zaddoff, (*(pcalidata->OffDataSpaceConvert))(pcalidata->zmoff));
}
}
static void updata_mmis_pnfoutput_set_tempflag( struct Cali_Data *pcalidata,
unsigned char *buf,
signed int xrel,
signed int yrel,
signed int zrel){
//output 2 struct data
pcalidata->xfoutput=(signed int)((signed char)buf[1])-xrel;
pcalidata->yfoutput=(signed int)((signed char)buf[3])-yrel;
pcalidata->zfoutput=(signed int)((signed char)buf[5])-zrel;
if(abs(pcalidata->xfoutput)<25)pcalidata->xtempf=1;
if(abs(pcalidata->yfoutput)<25)pcalidata->ytempf=1;
if(abs(pcalidata->zfoutput)<25)pcalidata->ztempf=1;
if(pcalidata->xtempf==0)
{
if(pcalidata->xfoutput>0){
pcalidata->xpoutput = pcalidata->xfoutput;
pcalidata->xpmis = pcalidata->xmmis;
}
else{
pcalidata->xnoutput = pcalidata->xfoutput;
pcalidata->xnmis = pcalidata->xmmis;
}
}
if(pcalidata->ytempf==0)
{
if(pcalidata->yfoutput>0){
pcalidata->ypoutput = pcalidata->yfoutput;
pcalidata->ypmis = pcalidata->ymmis;
}
else{
pcalidata->ynoutput = pcalidata->yfoutput;
pcalidata->ynmis = pcalidata->ymmis;
}
}
if(pcalidata->ztempf==0)
{
if(pcalidata->zfoutput>0){
pcalidata->zpoutput = pcalidata->zfoutput;
pcalidata->zpmis = pcalidata->zmmis;
}
else{
pcalidata->znoutput = pcalidata->zfoutput;
pcalidata->znmis = pcalidata->zmmis;
}
}
}
static void updata_moff_pnfoutput_set_tempflag( struct Cali_Data *pcalidata,
unsigned char *buf,
signed int xrel,
signed int yrel,
signed int zrel){
pcalidata->xfoutput=(signed int)((signed char)buf[1])-xrel;
pcalidata->yfoutput=(signed int)((signed char)buf[3])-yrel;
pcalidata->zfoutput=(signed int)((signed char)buf[5])-zrel;
if(abs(pcalidata->xfoutput)<3)pcalidata->xtempf=1;
if(abs(pcalidata->yfoutput)<3)pcalidata->ytempf=1;
if(abs(pcalidata->zfoutput)<3)pcalidata->ztempf=1;
if(pcalidata->xtempf==0)
{
if(pcalidata->xfoutput>0){
pcalidata->xpoutput = pcalidata->xfoutput;
pcalidata->xpoff = pcalidata->xmoff;
}
else{
pcalidata->xnoutput = pcalidata->xfoutput;
pcalidata->xnoff = pcalidata->xmoff;
}
}
if(pcalidata->ytempf==0)
{
if(pcalidata->yfoutput>0){
pcalidata->ypoutput = pcalidata->yfoutput;
pcalidata->ypoff = pcalidata->ymoff;
}
else{
pcalidata->ynoutput = pcalidata->yfoutput;
pcalidata->ynoff = pcalidata->ymoff;
}
}
if(pcalidata->ztempf==0)
{
if(pcalidata->zfoutput>0){
pcalidata->zpoutput = pcalidata->zfoutput;
pcalidata->zpoff = pcalidata->zmoff;
}
else{
pcalidata->znoutput = pcalidata->zfoutput;
pcalidata->znoff = pcalidata->zmoff;
}
}
}
int auto_calibration_instant(signed int x, signed int y, signed int z){
unsigned char count=0,cyclecount=0;
unsigned char acc_buf[6];
struct Cali_Data calidata={0};
calidata.xaddmis = 0x41;//0x40; x and y mismatch addr swap
calidata.yaddmis = 0x40;//0x41;
calidata.zaddmis = 0x42;
calidata.xaddoff = 0x47;
calidata.yaddoff = 0x48;
calidata.zaddoff = 0x49;
#ifdef PRINT
printf("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(UINT)calidata.xfinalf,(UINT)calidata.xtempf,
(UINT)calidata.yfinalf,(UINT)calidata.ytempf,
(UINT)calidata.zfinalf,(UINT)calidata.ztempf
);
#endif
Read_Output_3axis(acc_buf);
calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
check_output_set_finalflag(&calidata,2);
if(check_flag_is_return(&calidata)){
printk("step1:=file=%s,line=%dcalibration ok \n",__FILE__,__LINE__);
return 1;
}
#ifdef PRINT
printf("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(UINT)calidata.xfinalf,(UINT)calidata.xtempf,
(UINT)calidata.yfinalf,(UINT)calidata.ytempf,
(UINT)calidata.zfinalf,(UINT)calidata.ztempf
);
#endif
if(calidata.xfinalf==0){
Write_Input(calidata.xaddoff, 0x3f);//cali mis under off=0x3f
Write_Input(0x10, 0); //tilt clear
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.xaddmis, (*(calidata.MisDataSpaceConvert))(255)); // x mis to max
}
if(calidata.yfinalf==0){
Write_Input(calidata.yaddoff, 0x3f);//cali mis under off=0x3f
Write_Input(0x11, 0); //tilt clear
//calidata.MisDataSpaceConvert = forword_MisDataSpaceConvert;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.yaddmis, (*(calidata.MisDataSpaceConvert))(255)); // y mis to max
}
if(calidata.zfinalf==0){
Write_Input(calidata.zaddoff, 0x3f);//cali mis under off=0x3f
Write_Input(0x12, 0); //tilt clear
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.zaddmis, (*(calidata.MisDataSpaceConvert))(255)); // z mis to max
}
Read_Output_3axis(acc_buf);
calidata.xpoutput=calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.ypoutput=calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.zpoutput=calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
if((calidata.xpoutput<-25)||(calidata.ypoutput<-25)||(calidata.zpoutput<-25)){
printk("step2:=file=%s,line=%d calibration failed\n",__FILE__,__LINE__);
printk("calidata.xpoutput = 0x%4x calidata.ypoutput = 0x%4x calidata.zpoutput = 0x%4x\n",calidata.xpoutput,calidata.ypoutput,calidata.zpoutput);
return 0;
}
if(calidata.xfinalf==0){
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.xaddmis, (*(calidata.MisDataSpaceConvert))(0));
}
if(calidata.yfinalf==0){
//calidata.MisDataSpaceConvert = forword_MisDataSpaceConvert;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.yaddmis, (*(calidata.MisDataSpaceConvert))(0));
}
if(calidata.zfinalf==0){
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.zaddmis, (*(calidata.MisDataSpaceConvert))(0));
}
Read_Output_3axis(acc_buf);
calidata.xnoutput=calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.ynoutput=calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.znoutput=calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
if((calidata.xnoutput>25)||(calidata.ynoutput>25)||(calidata.znoutput>25)){
printk("step2:=file=%s,line=%d calibration failed\n",__FILE__,__LINE__);
printk("calidata.xnoutput = 0x%4x calidata.ynoutput = 0x%4x calidata.znoutput = 0x%4x\n",calidata.xnoutput,calidata.ynoutput,calidata.znoutput);
return 0;
}
if(abs(calidata.xpoutput)<=abs(calidata.xnoutput)){
calidata.xfoutput=calidata.xpoutput;
calidata.xmmis=255;
}
else{
calidata.xfoutput=calidata.xnoutput;
calidata.xmmis=0;
}
if(abs(calidata.ypoutput)<=abs(calidata.ynoutput)){
calidata.yfoutput=calidata.ypoutput;
calidata.ymmis=255;
}
else{
calidata.yfoutput=calidata.ynoutput;
calidata.ymmis=0;
}
if(abs(calidata.zpoutput)<=abs(calidata.znoutput)){
calidata.zfoutput=calidata.zpoutput;
calidata.zmmis=255;
}
else{
calidata.zfoutput=calidata.znoutput;
calidata.zmmis=0;
}
if(calidata.xfinalf==0){
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.xaddmis, (*(calidata.MisDataSpaceConvert))(calidata.xmmis));
}
if(calidata.yfinalf==0){
//calidata.MisDataSpaceConvert = forword_MisDataSpaceConvert;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.yaddmis, (*(calidata.MisDataSpaceConvert))(calidata.ymmis));
}
if(calidata.zfinalf==0){
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.zaddmis, (*(calidata.MisDataSpaceConvert))(calidata.zmmis));
}
check_output_set_finalflag(&calidata,2);
//if the smaller output <25,the step3 mis is finished
if(abs(calidata.xfoutput)<25) calidata.xtempf=1;
if(abs(calidata.yfoutput)<25) calidata.ytempf=1;
if(abs(calidata.zfoutput)<25) calidata.ztempf=1;
calidata.xpmis=calidata.ypmis=calidata.zpmis=255;
calidata.xnmis=calidata.ynmis=calidata.znmis=0;
check_finalflag_set_tempflag(&calidata);
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
cyclecount=0;
while(1){
if(++cyclecount>20)break;//if some errs happened,the cyclecount exceeded
if((calidata.xtempf)&&(calidata.ytempf)&&(calidata.ztempf))break;
updata_midmis_address(&calidata);
Read_Output_3axis(acc_buf);
calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
#ifdef PRINT
printk("xp%4d=%4d,xm%4d=%4d,xn%4d=%4d, yp%4d=%4d,ym%4d=%4d,yn%4d=%4d, zp%4d=%4d,zm%4d=%4d,zn%4d=%4d\n\r",
calidata.xpoutput,(unsigned int)calidata.xpmis,
calidata.xfoutput,(unsigned int)calidata.xmmis,
calidata.xnoutput,(unsigned int)calidata.xnmis,
calidata.ypoutput,(unsigned int)calidata.ypmis,
calidata.yfoutput,(unsigned int)calidata.ymmis,
calidata.ynoutput,(unsigned int)calidata.ynmis,
calidata.zpoutput,(unsigned int)calidata.zpmis,
calidata.zfoutput,(unsigned int)calidata.zmmis,
calidata.znoutput,(unsigned int)calidata.znmis
);
#endif
updata_mmis_pnfoutput_set_tempflag(&calidata,acc_buf,x,y,z);
check_output_set_finalflag(&calidata,2);
if(check_flag_is_return(&calidata))return 1;
}
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
calidata.xtempf=calidata.ytempf=calidata.ztempf=1;
if((calidata.xmmis>0)&&(calidata.xmmis<255))calidata.xtempf=0;
if((calidata.ymmis>0)&&(calidata.ymmis<255))calidata.ytempf=0;
if((calidata.zmmis>0)&&(calidata.zmmis<255))calidata.ztempf=0;
calidata.xpmis=calidata.xnmis=calidata.xmmis;
calidata.ypmis=calidata.ynmis=calidata.ymmis;
calidata.zpmis=calidata.znmis=calidata.zmmis;
for(count = 0; count < 3; count++)
{
if(calidata.xtempf==0){
calidata.xpmis = calidata.xmmis + count - 1;
if((calidata.xpmis>calidata.xmmis)&&(calidata.xpmis==128))calidata.xpmis = calidata.xmmis + count-1 + 1;
if((calidata.xpmis<calidata.xmmis)&&(calidata.xpmis==127))calidata.xpmis = calidata.xmmis + count-1 - 1;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.xaddmis, (*(calidata.MisDataSpaceConvert))(calidata.xpmis));
}
if(calidata.ytempf==0){
calidata.ypmis = calidata.ymmis + count - 1;
if((calidata.ypmis>calidata.ymmis)&&(calidata.ypmis==128))calidata.ypmis = calidata.ymmis + count-1 + 1;
if((calidata.ypmis<calidata.ymmis)&&(calidata.ypmis==127))calidata.ypmis = calidata.ymmis + count-1 - 1;
//calidata.MisDataSpaceConvert = forword_MisDataSpaceConvert;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.yaddmis, (*(calidata.MisDataSpaceConvert))(calidata.ypmis));
}
if(calidata.ztempf==0){
calidata.zpmis = calidata.zmmis + count - 1;
if((calidata.zpmis>calidata.zmmis)&&(calidata.zpmis==128))calidata.zpmis = calidata.zmmis + count-1 + 1;
if((calidata.zpmis<calidata.zmmis)&&(calidata.zpmis==127))calidata.zpmis = calidata.zmmis + count-1 - 1;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.zaddmis, (*(calidata.MisDataSpaceConvert))(calidata.zpmis));
}
Read_Output_3axis(acc_buf);
if(abs((signed int)((signed char)acc_buf[1])-x)<abs(calidata.xfoutput)){
calidata.xnmis=calidata.xpmis;
calidata.xfoutput= (signed int)((signed char)acc_buf[1])-x;
}
if(abs((signed int)((signed char)acc_buf[3])-y)<abs(calidata.yfoutput)){
calidata.ynmis=calidata.ypmis;
calidata.yfoutput= (signed int)((signed char)acc_buf[3])-y;
}
if(abs((signed int)((signed char)acc_buf[5])-z)<abs(calidata.zfoutput)){
calidata.znmis=calidata.zpmis;
calidata.zfoutput= (signed int)((signed char)acc_buf[5])-z;
}
if(calidata.xtempf==0){
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.xaddmis, (*(calidata.MisDataSpaceConvert))(calidata.xnmis));
}
if(calidata.ytempf==0){
//calidata.MisDataSpaceConvert = forword_MisDataSpaceConvert;
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.yaddmis, (*(calidata.MisDataSpaceConvert))(calidata.ynmis));
}
if(calidata.ztempf==0){
calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
Write_Input(calidata.zaddmis, (*(calidata.MisDataSpaceConvert))(calidata.znmis));
}
#ifdef PRINT
printk("L%4d:xf=%4d,xmis=%4d,yf=%4d,ymis=%4d,zf=%4d,zmis=%4d\n\r",__LINE__,
(signed int)((signed char)acc_buf[1])-x,(unsigned int)calidata.xpmis,
(signed int)((signed char)acc_buf[3])-y,(unsigned int)calidata.ypmis,
(signed int)((signed char)acc_buf[5])-z,(unsigned int)calidata.zpmis
);
#endif
}
calidata.xpoff=calidata.ypoff=calidata.zpoff=0x7f;
calidata.xnoff=calidata.ynoff=calidata.znoff=0;
calidata.xtempf=calidata.ytempf=calidata.ztempf=0;
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
check_finalflag_set_tempflag(&calidata);
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
if(calidata.xtempf==0){
calidata.OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(calidata.xaddoff, (*(calidata.OffDataSpaceConvert))(calidata.xpoff)); // x off to max
}
if(calidata.ytempf==0){
//calidata.OffDataSpaceConvert = forword_OffDataSpaceConvert;
calidata.OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(calidata.yaddoff, (*(calidata.OffDataSpaceConvert))(calidata.xpoff)); // y off to max
}
if(calidata.ztempf==0){
calidata.OffDataSpaceConvert = forword_OffDataSpaceConvert;
Write_Input(calidata.zaddoff, (*(calidata.OffDataSpaceConvert))(calidata.xpoff)); // z off to max
}
Read_Output_3axis(acc_buf);
calidata.xpoutput=calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.ypoutput=calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.zpoutput=calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
check_output_set_finalflag(&calidata,2);
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
if(calidata.xtempf==0){
calidata.OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(calidata.xaddoff, (*(calidata.OffDataSpaceConvert))(calidata.xnoff)); // x off to min
}
if(calidata.ytempf==0){
//calidata.OffDataSpaceConvert = forword_OffDataSpaceConvert;
calidata.OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(calidata.yaddoff, (*(calidata.OffDataSpaceConvert))(calidata.ynoff)); // y off to min
}
if(calidata.ztempf==0){
calidata.OffDataSpaceConvert = forword_OffDataSpaceConvert;
Write_Input(calidata.zaddoff, (*(calidata.OffDataSpaceConvert))(calidata.znoff)); // z off to min
}
Read_Output_3axis(acc_buf);
calidata.xnoutput=calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.ynoutput=calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.znoutput=calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
check_output_set_finalflag(&calidata,2);
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
if(abs(calidata.xpoutput)<=abs(calidata.xnoutput)){
calidata.xfoutput=calidata.xpoutput;
calidata.xmoff=calidata.xpoff;
}
else{
calidata.xfoutput=calidata.xnoutput;
calidata.xmoff=calidata.xnoff;
}
if(abs(calidata.ypoutput)<=abs(calidata.ynoutput)){
calidata.yfoutput=calidata.ypoutput;
calidata.ymoff=calidata.ypoff;
}
else{
calidata.yfoutput=calidata.ynoutput;
calidata.ymoff=calidata.ynoff;
}
if(abs(calidata.zpoutput)<=abs(calidata.znoutput)){
calidata.zfoutput=calidata.zpoutput;
calidata.zmoff=calidata.zpoff;
}
else{
calidata.zfoutput=calidata.znoutput;
calidata.zmoff=calidata.znoff;
}
if(calidata.xtempf==0){
calidata.OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(calidata.xaddoff, (*(calidata.OffDataSpaceConvert))(calidata.xmoff));
}
if(calidata.ytempf==0){
//calidata.OffDataSpaceConvert = forword_OffDataSpaceConvert;
calidata.OffDataSpaceConvert = reverse_OffDataSpaceConvert;
Write_Input(calidata.yaddoff, (*(calidata.OffDataSpaceConvert))(calidata.ymoff));
}
if(calidata.ztempf==0){
calidata.OffDataSpaceConvert = forword_OffDataSpaceConvert;
Write_Input(calidata.zaddoff, (*(calidata.OffDataSpaceConvert))(calidata.zmoff));
}
if((calidata.xpoutput>0 && calidata.xnoutput>0)||(calidata.xpoutput<0 && calidata.xnoutput<0)){
calidata.xfinalf=1;
}
if((calidata.ypoutput>0 && calidata.ynoutput>0)||(calidata.ypoutput<0 && calidata.ynoutput<0)){
calidata.yfinalf=1;
}
if((calidata.zpoutput>0 && calidata.znoutput>0)||(calidata.zpoutput<0 && calidata.znoutput<0)){
calidata.zfinalf=1;
}
check_finalflag_set_tempflag(&calidata);
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
cyclecount=0;
while(1){
if(++cyclecount>20)break;
if((calidata.xtempf)&&(calidata.ytempf)&&(calidata.ztempf))break;
updata_midoff_address(&calidata);
Read_Output_3axis(acc_buf);
calidata.xfoutput=(signed int)((signed char)acc_buf[1])-x;
calidata.yfoutput=(signed int)((signed char)acc_buf[3])-y;
calidata.zfoutput=(signed int)((signed char)acc_buf[5])-z;
#ifdef PRINT
printk("xp%4d=%4d,xm%4d=%4d,xn%4d=%4d, yp%4d=%4d,ym%4d=%4d,yn%4d=%4d, zp%4d=%4d,zm%4d=%4d,zn%4d=%4d\n\r",
calidata.xpoutput,(unsigned int)calidata.xpoff,
calidata.xfoutput,(unsigned int)calidata.xmoff,
calidata.xnoutput,(unsigned int)calidata.xnoff,
calidata.ypoutput,(unsigned int)calidata.ypoff,
calidata.yfoutput,(unsigned int)calidata.ymoff,
calidata.ynoutput,(unsigned int)calidata.ynoff,
calidata.zpoutput,(unsigned int)calidata.zpoff,
calidata.zfoutput,(unsigned int)calidata.zmoff,
calidata.znoutput,(unsigned int)calidata.znoff
);
#endif
updata_moff_pnfoutput_set_tempflag(&calidata,acc_buf,x,y,z);
check_output_set_finalflag(&calidata,2);
if(check_flag_is_return(&calidata))return 1;
}
#ifdef PRINT
printk("L%4d:xff=%4d,xtf=%4d,yff=%4d,ytf=%4d,zff=%4d,ztf=%4d\n\r",__LINE__,
(unsigned int)calidata.xfinalf,(unsigned int)calidata.xtempf,
(unsigned int)calidata.yfinalf,(unsigned int)calidata.ytempf,
(unsigned int)calidata.zfinalf,(unsigned int)calidata.ztempf
);
#endif
return 1;
}
int auto_calibration_instant_mtp(signed int x, signed int y, signed int z){
unsigned char readbuf[3]={0};
unsigned char buffer[6] = {0};
char reg_13;
signed int xoutp,youtp,zoutp;
unsigned char xfinalf,yfinalf,zfinalf;
xoutp=youtp=zoutp=0;
xfinalf=yfinalf=zfinalf=0;
reg_13= 0;
Write_Input(0x1e, 0x05);
if(auto_calibration_instant(x,y,z)==0)return 0;
//msleep(20);
tilt_3axis_mtp(x,y,z);
Read_Output_3axis(buffer);
xoutp=(signed int)((signed char)buffer[1])-x;
youtp=(signed int)((signed char)buffer[3])-y;
zoutp=(signed int)((signed char)buffer[5])-z;
if(abs(xoutp) < 2){xfinalf=1;}
if(abs(youtp) < 2){yfinalf=1;}
if(abs(zoutp) < 2){zfinalf=1;}
//*tbuffer = 0x10;
//sensor_rx_data(sc7660_client, tbuffer,1);
readbuf[0]= Read_Reg(0x10);
//*tbuffer = 0x40;
//sensor_rx_data(sc7660_client, tbuffer,1);
readbuf[1]= Read_Reg(0x40);
//*tbuffer = 0x47;
//sensor_rx_data(sc7660_client, tbuffer,1);
readbuf[2]= Read_Reg(0x47);
printk("L%4d:xtilt=%4d,xmis=%4d,xoff=%4d\n\r",__LINE__,
(unsigned int)readbuf[0],
(unsigned int)readbuf[1],
(unsigned int)readbuf[2]
);
//*tbuffer = 0x11;
//sensor_rx_data(sc7660_client, tbuffer,1);
readbuf[0]= Read_Reg(0x11);
//*tbuffer = 0x41;
//sensor_rx_data(sc7660_client, tbuffer,1);
readbuf[1]= Read_Reg(0x41);
//*tbuffer = 0x48;
//sensor_rx_data(sc7660_client, tbuffer,1);
readbuf[2]= Read_Reg(0x48);
printk("L%4d:ytilt=%4d,ymis=%4d,yoff=%4d\n\r",__LINE__,
(unsigned int)readbuf[0],
(unsigned int)readbuf[1],
(unsigned int)readbuf[2]
);
readbuf[0]= Read_Reg(0x12);
readbuf[1]= Read_Reg(0x42);
readbuf[2]= Read_Reg(0x49);
printk("L%4d:ztilt=%4d,zmis=%4d,zoff=%4d\n\r",__LINE__,
(unsigned int)readbuf[0],
(unsigned int)readbuf[1],
(unsigned int)readbuf[2]
);
if(xfinalf && yfinalf && zfinalf)
{
Write_Input(0x13,0x01);//allen MTP
reg_13 = Read_Reg(0x13);
printk("line %d reg_13 = %x\n",__LINE__,reg_13);
Write_Input(0x1e, 0x15);
mdelay(300);
reg_13 = Read_Reg(0x13);
printk("line %d reg_13 = %x\n",__LINE__,reg_13);
Write_Input(0x1e, 05);
printk(KERN_INFO "run calibration finished\n");
return 1;
}
else
return 0;
}
static ssize_t SC7660_3_axis_Calibration(struct device *dev, struct device_attribute *attr ,const char *buf, size_t count)
{
int adj_ok;
Write_Input(0x22, 0x77);
Write_Input(0x1e, 0x05); //supply the rivilege for MTP
mdelay(100);
adj_ok = auto_calibration_instant_mtp(0,0,-64);
if(adj_ok )
{
Write_Input(0x1e, 0x15); //save the modifyed register value
mdelay(200);
Write_Input(0x1e, 0);
printk(KERN_INFO "run calibration success\n");
}
else
{
printk(KERN_INFO "run calibration failed\n");
}
Write_Input(0x22, 0x47);
mdelay(5);
return 1;
}
/**
* gsensor_detect - Device detection callback for automatic device creation
* return value:
* = 0; success;
* < 0; err
*/
static int sc7660_gsensor_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
//__s32 ret = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
if(twi_id == adapter->nr){
printk("%s: addr= %x\n",__func__,client->addr);
/*
ret = gsensor_i2c_test(client);
if(!ret){
pr_info("%s:I2C connection might be something wrong or maybe the other gsensor equipment! \n",__func__);
return -ENODEV;
}else
*/
{
dprintk(DEBUG_INIT, "%s: I2C connection sucess!\n", __func__);
strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE);
return 0;
}
}else{
dprintk(DEBUG_INIT, "%s: I2C connection error!\n", __func__);
return -ENODEV;
}
}
static ssize_t sc7660_delay_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = sc7660_i2c_client;
struct sc7660_data_s *sc7660 = NULL;
sc7660 = i2c_get_clientdata(client);
return sprintf(buf, "%d\n", sc7660->pollDev->poll_interval);
}
static ssize_t sc7660_delay_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long data;
//int error;
struct i2c_client *client = sc7660_i2c_client;
struct sc7660_data_s *sc7660 = NULL;
sc7660 = i2c_get_clientdata(client);
dprintk(DEBUG_INIT, "delay store %d\n", __LINE__);
data = simple_strtoul(buf, NULL, 10);
//error = strict_strtoul(buf, 10, &data);
//if (error)
// return error;
if (data > POLL_INTERVAL_MAX)
data = POLL_INTERVAL_MAX;
mutex_lock(&sc7660->interval_mutex);
sc7660->pollDev->poll_interval = data;
mutex_unlock(&sc7660->interval_mutex);
if (atomic_read(&sc7660_data.enable)) {
sc7660_data.ktime = ktime_set(0, sc7660->pollDev->poll_interval * NSEC_PER_MSEC);
hrtimer_start(&sc7660_data.hr_timer, sc7660_data.ktime, HRTIMER_MODE_REL);
}
return count;
}
static ssize_t sc7660_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = sc7660_i2c_client;
struct sc7660_data_s *sc7660 = NULL;
sc7660 = i2c_get_clientdata(client);
return sprintf(buf, "%d\n",atomic_read(&sc7660_data.enable));
}
static ssize_t sc7660_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long data;
int error;
struct i2c_client *client = sc7660_i2c_client;
struct sc7660_data_s *sc7660 = NULL;
sc7660 = i2c_get_clientdata(client);
printk(KERN_INFO "%s: buf=%s\n", __func__, buf);
data = simple_strtoul(buf, NULL, 10);
//error = strict_strtoul(buf, 10, &data);
//if(error) {
// pr_err("%s strict_strtoul error\n", __FUNCTION__);
// goto exit;
//}
if(data) {
printk(KERN_INFO "%s: sc7660_CTRL_PWRON\n", __func__);
error = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL,sc7660_CTRL_PWRON);
atomic_set(&sc7660_data.enable, 1);
assert(error==0);
//
printk(KERN_INFO "%s: sc7660 delay %d\n", __func__, sc7660->pollDev->poll_interval);
sc7660_data.ktime = ktime_set(0, sc7660->pollDev->poll_interval * NSEC_PER_MSEC);
hrtimer_start(&sc7660_data.hr_timer, ktime_set(0, 0), HRTIMER_MODE_REL);
//sc7660_idev->input->open(sc7660_idev->input);
} else {
printk(KERN_INFO "%s: sc7660_CTRL_PWRDN\n", __func__);
//sc7660_idev->input->close(sc7660_idev->input);
hrtimer_cancel(&sc7660_data.hr_timer);
atomic_set(&sc7660_data.enable, 0);
error = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL,sc7660_CTRL_PWRDN);
assert(error==0);
}
return count;
//exit:
// return error;
}
#if 0
static ssize_t SC7660_reg13_reset(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int result = 0;
result = i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e,0x05);
mdelay(100);
result = i2c_smbus_write_byte_data(sc7660_i2c_client, 0x13, 0x00);
result = i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e, 0x15);
mdelay(300);
if(result)
printk("%s:fail to write sensor_register\n",__func__);
return count;
}
#endif
static ssize_t SC7660_register_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned int address, value;
int result = 0;
sscanf(buf, "0x%x=0x%x", &address, &value);
result = i2c_smbus_write_byte_data(sc7660_i2c_client, address,value);
if(result)
printk("%s:fail to write sensor_register\n",__func__);
return count;
}
static ssize_t SC7660_register_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
size_t count = 0;
//u8 reg[0x5b];
char i;
int buffer[3] = {0};
i = 0x0f;
*buffer = i;
buffer[0] = i2c_smbus_read_byte_data(sc7660_i2c_client,i );
count += sprintf(buf, "0x%x: 0x%x\n", i, buffer[0]);
for(i=0x10;i<0x5a;i++)
{
*buffer = i;
buffer[0]=i2c_smbus_read_byte_data(sc7660_i2c_client, i);
count += sprintf(&buf[count],"0x%x: 0x%x\n", i, buffer[0]);
}
return count;
}
#if 0
static DEVICE_ATTR(enable, S_IRUGO,
sc7660_enable_show, sc7660_enable_store);
static DEVICE_ATTR(delay, S_IRUGO,
sc7660_delay_show, sc7660_delay_store);
static DEVICE_ATTR(reg, S_IRUGO,
SC7660_register_show, SC7660_register_store);
static DEVICE_ATTR(reg13_reset, S_IRUGO,
SC7660_reg13_reset, NULL);
static DEVICE_ATTR(calibration_run, S_IRUGO,//S_IWUSR|S_IWGRP, //calibration_run
NULL, SC7660_3_axis_Calibration);
#endif
static DEVICE_ATTR(enable, 0644,
sc7660_enable_show, sc7660_enable_store);
static DEVICE_ATTR(delay, 0644,
sc7660_delay_show, sc7660_delay_store);
static DEVICE_ATTR(reg, 0644,
SC7660_register_show, SC7660_register_store);
//static DEVICE_ATTR(reg13_reset, 0644,
// SC7660_reg13_reset, NULL);
static DEVICE_ATTR(calibration_run, 0644,//S_IWUSR|S_IWGRP, //calibration_run
NULL, SC7660_3_axis_Calibration);
static struct attribute *sc7660_attributes[] = {
// &dev_attr_reg13_reset.attr,
&dev_attr_reg.attr,
&dev_attr_enable.attr,
&dev_attr_delay.attr,
&dev_attr_calibration_run.attr,
NULL
};
static struct attribute_group sc7660_attribute_group = {
.attrs = sc7660_attributes
};
#if 0
static int report_abs(void)
{
s8 xyz[6] = {0, 0, 0};
s16 x = 0, y = 0, z = 0;
s8 ret = 0;
s16 conut = 0;
while(1)
{
ret = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_STATUS);
if ((ret& 0x08) != 0 ){
break;
}
msleep(1);
conut++;
if(conut > 40)
break;
}
xyz[0] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_L);
xyz[1] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_H);
xyz[2] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_L);
xyz[3] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_H);
xyz[4] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_L);
xyz[5] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_H);
//x = ((xyz[1]) << 8) | xyz[0];
//y = ((xyz[3]) << 8) | xyz[2];
//z = ((xyz[5]) << 8) | xyz[4];
x = xyz[1];
y = xyz[3];
z = xyz[5];
input_report_abs(sc7660_idev->input, ABS_X, x);
input_report_abs(sc7660_idev->input, ABS_Y, y);
input_report_abs(sc7660_idev->input, ABS_Z, z);
input_sync(sc7660_idev->input);
return 1;
}
#endif
static void sc7660_dev_poll(struct input_polled_dev *dev)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
if(0 == sc7660_data.suspend_indator){
//report_abs();
}
#else
{
//report_abs();
}
#endif
}
/*
* I2C init/probing/exit functions
*/
////////////////////////////////djq////////////////////////////////////
static int sc7660_acc_get_data( int *xyz)
{
u8 acc_data[6];
/* x,y,z hardware data */
int hw_d[3] = { 0 };
signed short temp_data[3];
int count = 0;
u8 buf[3];
buf[0] = SC7660_STATUS;
while(1)
{
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_STATUS);
if ((buf[0] & 0x08) != 0 ){
break;
}
msleep(1);
count++;
if(count > 40)
break;
}
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client,SC7660_XOUT_L);
acc_data[0] = buf[0];
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client,SC7660_XOUT_H);
acc_data[1] = buf[0];
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client,SC7660_YOUT_L);
acc_data[2] = buf[0];
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client,SC7660_YOUT_H);
acc_data[3] = buf[0];
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client,SC7660_ZOUT_L);
acc_data[4] = buf[0];
buf[0]=i2c_smbus_read_byte_data(sc7660_i2c_client,SC7660_ZOUT_H);
acc_data[5] = buf[0];
/* 12-bit */
temp_data[0] = (signed short)( (acc_data[1] << 8 | acc_data[0]) >> 4 );
temp_data[1] = (signed short)( (acc_data[3] << 8 | acc_data[2]) >> 4 );
temp_data[2] = (signed short)( (acc_data[5] << 8 | acc_data[4]) >> 4 );
hw_d[0] = (temp_data[0] & 0x0800) ? (temp_data[0] | 0xFFFFF800) : (temp_data[0]);
hw_d[1] = (temp_data[1] & 0x0800) ? (temp_data[1] | 0xFFFFF800) : (temp_data[1]);
hw_d[2] = (temp_data[2] & 0x0800) ? (temp_data[2] | 0xFFFFF800) : (temp_data[2]);
xyz[0] = (hw_d[0] ) * 1000;
xyz[1] = (hw_d[1] ) * 1000;
xyz[2] = (hw_d[2] ) * 1000;
return 0;
}
static int sc7660_acc_hw_init(void)
{
char ret;
ret = i2c_smbus_write_byte_data(sc7660_i2c_client, SC7660_MODE, 0x77);
if(ret < 0)
{
return -1;
}
return 0;
}
static int sc7660_acc_cali(struct i2c_client *client)
{
struct sc7660_data_s *data = (struct sc7660_data_s *) i2c_get_clientdata(client);
queue_delayed_work(sc7660_workqueue,
&data->dwork,
msecs_to_jiffies(1000));
printk("cali !!!\n");
sc7660_acc_hw_init();
return 0;
}
static void sc7660_work_handler(struct work_struct *work)
{
int xyz[3] = {0, 0, 0};
int ret =0;
int adj_ok;
int auto_count = 0;
int max_x=0, max_y=0, max_z=0, min_x=0, min_y=0, min_z=0;
int sum_x = 0, sum_y = 0, sum_z = 0;
struct sc7660_data_s *data =
container_of(work, struct sc7660_data_s, dwork.work);
while (1) {
ret = sc7660_acc_get_data(xyz);
if(ret == -1)
{
printk("Line %d:error!\n",__LINE__);
continue;
}
xyz[0] /= 1024;
xyz[1] /= 1024;
xyz[2] /= 1024;
if (auto_count == 0) {
max_x = min_x = xyz[0];
max_y = min_y = xyz[1];
max_z = min_z = xyz[2];
}
max_x = max_x > xyz[0] ? max_x : xyz[0];
max_y = max_y > xyz[1] ? max_y : xyz[1];
max_z = max_z > xyz[2] ? max_z : xyz[2];
min_x = min_x > xyz[0] ? xyz[0] : min_x;
min_y = min_y > xyz[1] ? xyz[1] : min_y;
min_z = min_z > xyz[2] ? xyz[2] : min_z;
sum_x = sum_x + xyz[0];
sum_y = sum_y + xyz[1];
sum_z = sum_z + xyz[2];
printk("x : %d y : %d z : %d sum_z = %d,auto_count = %d\n",xyz[0], xyz[1], xyz[2],sum_z, auto_count);
if (auto_count > CALIBRATION_NUM-1) {
printk("x-x : %d\n", max_x - min_x);
printk("y-y : %d\n", max_y - min_y);
printk("z-z : %d\n", max_z - min_z);
if (max_x - min_x < AXIS_X_Y_RANGE_LIMIT
&& max_y - min_y < AXIS_X_Y_RANGE_LIMIT
&& max_z - min_z < AXIS_X_Y_RANGE_LIMIT ) {
printk("sum-x-before : %d\n", sum_x);
printk("sum-y-before : %d\n", sum_y);
printk("sum-z-before : %d\n", sum_z);
//ok
sum_x /= CALIBRATION_NUM;
sum_y /= CALIBRATION_NUM;
sum_z /= CALIBRATION_NUM;
printk("sum-x : %d\n", sum_x);
printk("sum-y : %d\n", sum_y);
printk("sum-z : %d\n", sum_z);
//if (sum_x < AXIS_X_Y_AVG_LIMIT && sum_y < AXIS_X_Y_AVG_LIMIT) {
if(1){
if (sum_z > AXIS_Z_RANGE) {
//auto_SC7660_3_axis_Calibration( 0, 0, 64);
adj_ok = auto_calibration_instant_mtp(0,0,64);
auto_count = GOTO_CALI;
}
else if ( sum_z < -AXIS_Z_RANGE) {
//auto_SC7660_3_axis_Calibration( 0, 0, -64);
adj_ok = auto_calibration_instant_mtp(0,0,-64);
auto_count = GOTO_CALI;
}
else {
printk("Line %d:error!\n",__LINE__);
auto_count = FAILTO_CALI;
}
}
else if( sum_x < AXIS_X_Y_AVG_LIMIT || sum_y < AXIS_X_Y_AVG_LIMIT) {
if ( sum_z > AXIS_Z_DFT_G - AXIS_Z_RANGE && sum_z < AXIS_Z_DFT_G + AXIS_Z_RANGE) {
//auto_SC7660_3_axis_Calibration( 0, 0, 64);
auto_count = GOTO_CALI;
}
else if ( sum_z < -(AXIS_Z_DFT_G - AXIS_Z_RANGE) && sum_z > -(AXIS_Z_DFT_G + AXIS_Z_RANGE)) {
//auto_SC7660_3_axis_Calibration( 0, 0, -64);
auto_count = GOTO_CALI;
}
else {
auto_count = FAILTO_CALI;
printk("Line %d:error!\n",__LINE__);
}
}
else {
auto_count = FAILTO_CALI;
printk("Line %d:error!\n",__LINE__);
}
if(adj_ok==1)
{
printk("Calibration succeed\n");
Write_Input( 0x1e, 0x05);
}
else
{
printk("Calibration failed\n");
}
}
else {
auto_count = FAILTO_CALI;
printk("Line %d:error!\n",__LINE__);
}
}
if(auto_count == GOTO_CALI){
break;
}
if (auto_count == FAILTO_CALI) {
sum_x = sum_y = sum_z = max_x = max_y = max_z = min_x = min_y = min_z = 0;
auto_count = -1;
data->time_of_cali++;
if (data->time_of_cali > 1) {
printk("calibration failed !!\n");
break;
}
}
auto_count++;
msleep(20);
}
}
static enum hrtimer_restart my_hrtimer_callback(struct hrtimer *timer)
{
schedule_work(&sc7660_data.wq_hrtimer);
hrtimer_forward_now(&sc7660_data.hr_timer, sc7660_data.ktime);
return HRTIMER_RESTART;
}
static void wq_func_hrtimer(struct work_struct *work)
{
s8 xyz[6] = {0, 0, 0};
s16 x = 0, y = 0, z = 0;
xyz[0] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_L);
xyz[1] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_XOUT_H);
xyz[2] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_L);
xyz[3] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_YOUT_H);
xyz[4] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_L);
xyz[5] = i2c_smbus_read_byte_data(sc7660_i2c_client, SC7660_ZOUT_H);
x = xyz[1];
y = xyz[3];
z = xyz[5];
if (x == 0 && y == 0 && z == 0) {
pr_err("sc7660 gsensor x y z all 0!!!\n");
sc7660_reset();
return;
}
input_report_abs(sc7660_idev->input, ABS_X, x);
input_report_abs(sc7660_idev->input, ABS_Y, y);
input_report_abs(sc7660_idev->input, ABS_Z, z);
input_sync(sc7660_idev->input);
}
static int sc7660_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
char reg_cali;
int result;
struct i2c_adapter *adapter;
struct sc7660_data_s* data = &sc7660_data;
printk( "sc7660 probe\n");
sc7660_i2c_client = client;
adapter = to_i2c_adapter(client->dev.parent);
result = i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA);
assert(result);
hwmon_dev = hwmon_device_register(&client->dev);
assert(!(IS_ERR(hwmon_dev)));
/*input poll device register */
sc7660_idev = input_allocate_polled_device();
if (!sc7660_idev) {
dev_err(&client->dev, "alloc poll device failed!\n");
result = -ENOMEM;
return result;
}
sc7660_idev->poll = sc7660_dev_poll;
sc7660_idev->poll_interval = POLL_INTERVAL;
sc7660_idev->poll_interval_max = POLL_INTERVAL_MAX;
sc7660_idev->input->name = sc7660_DRV_NAME;
sc7660_idev->input->id.bustype = BUS_I2C;
sc7660_idev->input->evbit[0] = BIT_MASK(EV_ABS);
mutex_init(&data->interval_mutex);
input_set_capability(sc7660_idev->input, EV_ABS, ABS_MISC);
input_set_abs_params(sc7660_idev->input, ABS_X, -512, 512, INPUT_FUZZ, INPUT_FLAT);
input_set_abs_params(sc7660_idev->input, ABS_Y, -512, 512, INPUT_FUZZ, INPUT_FLAT);
input_set_abs_params(sc7660_idev->input, ABS_Z, -512, 512, INPUT_FUZZ, INPUT_FLAT);
result = input_register_polled_device(sc7660_idev);
if (result) {
dev_err(&client->dev, "register poll device failed!\n");
return result;
}
result = sysfs_create_group(&sc7660_idev->input->dev.kobj, &sc7660_attribute_group);
if(result) {
dev_err(&client->dev, "create sys failed\n");
}
data->client = client;
data->pollDev = sc7660_idev;
i2c_set_clientdata(client, data);
#ifdef CONFIG_HAS_EARLYSUSPEND
sc7660_data.early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
sc7660_data.early_suspend.suspend = sc7660_early_suspend;
sc7660_data.early_suspend.resume = sc7660_late_resume;
register_early_suspend(&sc7660_data.early_suspend);
sc7660_data.suspend_indator = 0;
#endif
//result = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL, sc7660_CTRL_PWRON);
//assert(result==0);
reg_cali = i2c_smbus_read_byte_data(sc7660_i2c_client, 0x13);
printk("line %d reg_cali = 0x%x \n",__LINE__,reg_cali);
if (0) {
//if ((reg_cali & 0x1) == 0) {
if (sc7660_workqueue == NULL) {
sc7660_workqueue = create_workqueue("sc7660_acc");
if (sc7660_workqueue == NULL) {
printk("line %d workque fail!!!!!!!!!!!!!!\n",__LINE__);
}
}
INIT_DELAYED_WORK(&(data->dwork), sc7660_work_handler);
sc7660_acc_cali(client);
}
else {
}
hrtimer_init(&sc7660_data.hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
sc7660_data.hr_timer.function = my_hrtimer_callback;
INIT_WORK(&sc7660_data.wq_hrtimer, wq_func_hrtimer);
return result;
}
static int sc7660_remove(struct i2c_client *client)
{
int result;
result = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL, sc7660_CTRL_PWRDN);
assert(result==0);
hwmon_device_unregister(hwmon_dev);
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&sc7660_data.early_suspend);
#endif
sysfs_remove_group(&sc7660_idev->input->dev.kobj, &sc7660_attribute_group);
input_unregister_polled_device(sc7660_idev);
input_free_polled_device(sc7660_idev);
i2c_set_clientdata(sc7660_i2c_client, NULL);
return result;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void sc7660_early_suspend(struct early_suspend *h)
{
int result;
printk( "sc7660 early suspend\n");
sc7660_data.suspend_indator = 1;
result = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL, sc7660_CTRL_PWRDN);
assert(result==0);
#ifdef GSENSOR_REG_CALI
{
int i = 0;
for(i = 0; i < sizeof(reg)/sizeof(reg[0]); i++) {
reg_data[i] = i2c_smbus_read_byte_data(sc7660_i2c_client, reg[i]);
}
}
#endif
return;
}
static void sc7660_late_resume(struct early_suspend *h)
{
int result;
int val_reg;
int MTPSETTING,B57H,B1BH,i;
printk("sc7660 late resume\n");
sc7660_data.suspend_indator = 0;
val_reg = i2c_smbus_read_byte_data(sc7660_i2c_client,0x0f);
if(val_reg != 0x11)
{
for(i=0;i<3;i++)
{
MTPSETTING = 0x07;
B57H = 0x00;
B1BH = 0x08;
sc7660_i2c_client->addr=0x18;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x19;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x1a;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x1b;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x1c;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x1d;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x1e;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
sc7660_i2c_client->addr=0x1f;
i2c_smbus_write_byte_data(sc7660_i2c_client,0x59,MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1b,B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x57,B57H);
}
sc7660_i2c_client->addr=0x1d;
msleep(100);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x24,0x80);
i2c_smbus_write_byte_data(sc7660_i2c_client,0x1e,0x05);
val_reg = i2c_smbus_read_byte_data(sc7660_i2c_client,0x0f);
if(val_reg != 0x11)
printk("momkey sc7660 resume fail! regchip_id=0x%x\n", val_reg);
}
result = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL, sc7660_CTRL_PWRON);
assert(result==0);
#ifdef GSENSOR_REG_CALI
{
int i = 0;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1E, 0x05);
for(i = 0; i < sizeof(reg)/sizeof(reg[0]); i++) {
if(reg_data[i] != i2c_smbus_read_byte_data(sc7660_i2c_client, reg[i])){
i2c_smbus_write_byte_data(sc7660_i2c_client, reg[i], reg_data[i]);
}
}
}
#endif
return;
}
#else
#ifdef CONFIG_PM
static int sc7660_resume(struct i2c_client *client)
{
return 0;
}
static int sc7660_suspend(struct i2c_client *client, pm_message_t mesg)
{
return 0;
}
#endif
#endif /* CONFIG_HAS_EARLYSUSPEND */
static void sc7660_reset(void)
{
int result;
int val_reg;
int MTPSETTING, B57H, B1BH, i;
printk("sc7660 reset power down\n");
result = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL, sc7660_CTRL_PWRDN);
assert(result == 0);
msleep(50);
printk("sc7660 reset power on\n");
val_reg = i2c_smbus_read_byte_data(sc7660_i2c_client, 0x0f);
if (val_reg != 0x11) {
for (i = 0; i < 3; i++) {
MTPSETTING = 0x07;
B57H = 0x00;
B1BH = 0x08;
sc7660_i2c_client->addr = 0x18;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x19;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x1a;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x1b;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x1c;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x1d;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x1e;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
sc7660_i2c_client->addr = 0x1f;
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x59, MTPSETTING);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1b, B1BH);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x57, B57H);
}
sc7660_i2c_client->addr = 0x1d;
msleep(100);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x24, 0x80);
i2c_smbus_write_byte_data(sc7660_i2c_client, 0x1e, 0x05);
val_reg = i2c_smbus_read_byte_data(sc7660_i2c_client, 0x0f);
if (val_reg != 0x11)
printk("momkey sc7660 resume fail! regchip_id=0x%x\n", val_reg);
}
result = i2c_smbus_write_byte_data(sc7660_i2c_client, sc7660_REG_CTRL, sc7660_CTRL_PWRON);
assert(result == 0);
}
static const struct i2c_device_id sc7660_id[] = {
{ sc7660_DRV_NAME, 1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, sc7660_id);
static struct i2c_driver sc7660_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = sc7660_DRV_NAME,
.owner = THIS_MODULE,
},
.probe = sc7660_probe,
.remove = sc7660_remove,
#ifdef CONFIG_HAS_EARLYSUSPEND
#else
#ifdef CONFIG_PM
.suspend = sc7660_suspend,
.resume = sc7660_resume,
#endif
#endif
.id_table = sc7660_id,
.detect = sc7660_gsensor_detect,
.address_list = normal_i2c,
};
static int __init sc7660_init(void)
{
int ret = -1;
printk("function=%s=========LINE=%d. \n", __func__,__LINE__);
if(input_sensor_startup(&(gsensor_info.input_type))){
printk("%s: err.\n", __func__);
return -1;
} else
ret = input_sensor_init(&(gsensor_info.input_type));
if (0 != ret){
printk("%s:gsensor.init_platform_resource err. \n", __func__);
}
twi_id = gsensor_info.twi_id;
input_set_power_enable(&(gsensor_info.input_type),1);
ret = i2c_add_driver(&sc7660_driver);
if (ret < 0) {
printk( "add sc7660 i2c driver failed\n");
return -ENODEV;
}
return ret;
}
static void __exit sc7660_exit(void)
{
printk("remove sc7660 i2c driver.\n");
i2c_del_driver(&sc7660_driver);
input_sensor_free(&(gsensor_info.input_type));
}
MODULE_AUTHOR("djq");
MODULE_DESCRIPTION("sc7660 Sensor driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.1");
module_init(sc7660_init);
module_exit(sc7660_exit);