Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
/* drivers/input/sensors/access/sc7a30.c
 *
 * Copyright (C) 2012-2015 ROCKCHIP.
 * Author: luowei <lw@rock-chips.com>
 *
 * 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 <linux/uaccess.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/freezer.h>
#include <linux/of_gpio.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>
#include <linux/ioctl.h>
#include <linux/wakelock.h>

#define SC7A30_ENABLE			1
#define SC7A30_XOUT_L			0x28
#define SC7A30_XOUT_H			0x29
#define SC7A30_YOUT_L			0x2A
#define SC7A30_YOUT_H			0x2B
#define SC7A30_ZOUT_L			0x2C
#define SC7A30_ZOUT_H			0x2D
#define SC7A30_MODE			0x20
#define SC7A30_MODE1			0x21
#define SC7A30_MODE2			0x22
#define SC7A30_MODE3			0x23
#define SC7A30_BOOT			0x24
#define SC7A30_STATUS			0x27
#define SC7A30_50HZ			0x40
#define SC7A30_100HZ			0x50
#define SC7A30_200HZ			0x60
#define SC7A30_400HZ			0x70
#define SC7A30_RANGE			32768

#define CALIBRATION_NUM		20//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
/* LIS3DH */
#define SC7A30_PRECISION        12
#define SC7A30_BOUNDARY		(0x1 << (SC7A30_PRECISION - 1))
#define SC7A30_GRAVITY_STEP	(SC7A30_RANGE / SC7A30_BOUNDARY)

#define SC7A30_COUNT_AVERAGE	2

#define CFG_GSENSOR_CALIBFILE   "/data/data/com.actions.sensor.calib/files/gsensor_calib.txt"

struct SC7A30_acc {
	int    x;
	int    y;
	int    z;
};

static struct SC7A30_acc offset;
static int calibrated;
static struct i2c_client *sc7a30_client;

struct sensor_axis_average {
		long x_average;
		long y_average;
		long z_average;
		int count;
};

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 struct sensor_axis_average axis_average;

static unsigned char Read_Reg(unsigned char reg)
{
	char buffer[3] = {0};
	*buffer = reg;
	sensor_rx_data(sc7a30_client, buffer, 1);
	return buffer[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 = SC7A30_STATUS;
			//ret = sensor_rx_data(sc7a30_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
	*buffer = SC7A30_XOUT_L;
	ret = sensor_rx_data(sc7a30_client, buffer, 1);
	acc_buf[0] = buffer[0];
	*buffer = SC7A30_XOUT_H;
	ret = sensor_rx_data(sc7a30_client, buffer, 1);
	acc_buf[1] = buffer[0];

	*buffer = SC7A30_YOUT_L;
	ret = sensor_rx_data(sc7a30_client, buffer, 1);
	acc_buf[2] = buffer[0];
	*buffer = SC7A30_YOUT_H;
	ret = sensor_rx_data(sc7a30_client, buffer, 1);
	acc_buf[3] = buffer[0];

	*buffer = SC7A30_ZOUT_L;
	ret = sensor_rx_data(sc7a30_client, buffer,1);
	acc_buf[4] = buffer[0];
	*buffer = SC7A30_ZOUT_H;
	ret = sensor_rx_data(sc7a30_client, buffer, 1);
	acc_buf[5] = buffer[0];
}

static void Write_Input(char addr, char thedata)
{
	int result;
	result = sensor_write_reg(sc7a30_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 = 0x10;
	sensor_rx_data(sc7a30_client, buffer, 1);
	mtpread[0]=(signed char)buffer[0];

	*buffer = 0x11;
	sensor_rx_data(sc7a30_client, buffer, 1);
	mtpread[1]=(signed char)buffer[0];

	*buffer = 0x12;
	sensor_rx_data(sc7a30_client, buffer, 1);
	mtpread[2]=(signed char)buffer[0];

	xtilt=(signed char)(xoutp/8)+ mtpread[0];
	ytilt=(signed char)(youtp/8)+ mtpread[1];
	ztilt=(signed char)(zoutp/8)+ mtpread[2];

	Write_Input(0x10, xtilt);
	Write_Input(0x11, ytilt);
	Write_Input(0x12, ztilt);

}

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;
}

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))
	{
		//printk("line:%d Allcali finish!\n",__LINE__);
		return 1;//xyz cali ok
	} 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;
		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;
		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)
{
	
	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;
		}
	}
}

static 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 = 0x40;
	calidata.yaddmis = 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=%d\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;
		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;
	printk("step 2 xnoutput = %d ynoutput = %d znoutput = %d \n",calidata.xnoutput,calidata.ynoutput,calidata.znoutput);
	if ((calidata.xpoutput<-25) || (calidata.ypoutput<-25) || (calidata.zpoutput<-25)){
		printk("step2:=file=%s,line=%d\n",__FILE__,__LINE__);
		sensor_write_reg(sc7a30_client,0x13,0x01);//allen                                         
		Write_Input(0x1e, 0x15);  //保存校准寄存器的修改
		mdelay(300);
		// Write_Input(0x1e, 0);
		return 0; 
	}

	if (calidata.xfinalf == 0) {
		calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
		Write_Input(calidata.xaddmis, (*(calidata.MisDataSpaceConvert))(0)); // x mis to min
	}
	if (calidata.yfinalf == 0) {
		calidata.MisDataSpaceConvert = forword_MisDataSpaceConvert;
		Write_Input(calidata.yaddmis, (*(calidata.MisDataSpaceConvert))(0)); // y mis to min
	}
	if (calidata.zfinalf == 0) {
		calidata.MisDataSpaceConvert = reverse_MisDataSpaceConvert;
		Write_Input(calidata.zaddmis, (*(calidata.MisDataSpaceConvert))(0)); // z mis 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;
	printk("step 2 xnoutput = %d ynoutput = %d znoutput = %d \n",calidata.xnoutput,calidata.ynoutput,calidata.znoutput);
	if ((calidata.xnoutput>25) || (calidata.ynoutput>25) || (calidata.znoutput>25)) {
		printk("step2:=file=%s,line=%d\n",__FILE__,__LINE__);
		sensor_write_reg(sc7a30_client,0x13,0x01);
		Write_Input(0x1e, 0x15);  
		mdelay(300);

		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;
		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(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((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;
			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;
			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

	}
	//Write_Input(AddMis, (*MisDataSpaceConvert)(FinaloutputMisConfiguration));

	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
	//offset max
	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;
		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
	//offset min
	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;
		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;
		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;
}

static __maybe_unused int auto_calibration_instant_mtp(signed int x, signed int y, signed int z)
{
	unsigned char readbuf[3]={0};
	unsigned char buffer[6] = {0};

	signed int xoutp,youtp,zoutp;
	unsigned char xfinalf,yfinalf,zfinalf;
	int reg_13 = 0;

	xoutp=youtp=zoutp=0;
	xfinalf=yfinalf=zfinalf=0;    
	if (auto_calibration_instant(x,y,z) == 0)
         { 
		printk("auto_calibration_instant ==0 \n");
		sensor_write_reg(sc7a30_client, 0x1e,0x05);
		mdelay(100);
		sensor_write_reg(sc7a30_client, 0x13,0x01);

		sensor_write_reg(sc7a30_client, 0x1e,0x15);
		mdelay(300);
		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(sc7a30_client, tbuffer,1);
	readbuf[0]= Read_Reg(0x10);
	//*tbuffer = 0x40;
	//sensor_rx_data(sc7a30_client, tbuffer,1);
	readbuf[1]= Read_Reg(0x40);
	//*tbuffer = 0x47;
	//sensor_rx_data(sc7a30_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]
			);

	readbuf[0]= Read_Reg(0x11);
	readbuf[1]= Read_Reg(0x41);
	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)
	{
		sensor_write_reg(sc7a30_client,0x13,0x01);
		reg_13 = sensor_read_reg(sc7a30_client,0x13);
		printk("line %d  reg_13 = %x\n",__LINE__,reg_13);
		Write_Input(0x1e, 0x15);
		mdelay(300);
		printk(KERN_INFO "run calibration finished\n");

		return 1;
	} else {
		sensor_write_reg(sc7a30_client,0x13,0x01);//allen MTP
		reg_13 = sensor_read_reg(sc7a30_client,0x13);
		printk("line %d  reg_13 = %x\n",__LINE__,reg_13);
		Write_Input(0x1e, 0x15);
		mdelay(300);                                                                           
 
		return 0;
       }
}

/****************operate according to sensor chip:start************/

static int sensor_active(struct i2c_client *client, int enable, int rate)
{
	struct sensor_private_data *sensor =
	    (struct sensor_private_data *) i2c_get_clientdata(client);
	int result = 0;
	int status = 0;

	sensor->ops->ctrl_data = 0x07;

	if (enable)
	{
		status = SC7A30_ENABLE;	//sc7a30
		sensor->ops->ctrl_data |= SC7A30_400HZ;
	} else
		status = ~SC7A30_ENABLE;	//sc7a30

	printk("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
	result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
	
	if(result)
		printk("%s:fail to active sensor\n",__func__);
	
	return result;
}

static int sensor_init(struct i2c_client *client)
{
	struct sensor_private_data *sensor =
	    (struct sensor_private_data *) i2c_get_clientdata(client);
	int result = 0;

	//mutex_lock(&(sensor->allen_mutex) );//allen

	printk("aaaaa %s:line=%d\n",__func__,__LINE__);
	
	result = sensor->ops->active(client,0,0);
	if (result)
	{
		printk("%s:line=%d,error\n",__func__,__LINE__);
		return result;
	}
	calibrated = 0;
	sc7a30_client = client;
	sensor->status_cur = SENSOR_OFF;
	//sensor->time_of_cali =0;//allen
	offset.x=offset.y=offset.z=0;
	sensor_write_reg(client, SC7A30_BOOT, 0x80);
	mdelay(20);
	result = sensor_write_reg(client, SC7A30_MODE, 0x07);

	sensor_write_reg(client, SC7A30_MODE3, 0x88);      
//	result = sensor_write_reg(client, SC7A30_MODE, 0x77);
        
	//register_test(); 
	if(result)
	{
		printk("aaaaa %s:line=%d,error\n",__func__,__LINE__);
		return result;
	} 

	if(sensor->pdata->irq_enable)	//open interrupt
	{
		result = sensor_write_reg(client, SC7A30_MODE2, 0x10);
		result = sensor_write_reg(client, 0x25, 0x02);

		if(result)
		{
			printk("%s:line=%d,error\n",__func__,__LINE__);
			return result;
		}
	}
	memset(&axis_average, 0, sizeof(struct sensor_axis_average));

	return result;
}

static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte ,s16 off)
{
    s64 result;
	result = (((s16)((high_byte << 8) + low_byte)) >>4);
	result -= off;
	result = result* SC7A30_GRAVITY_STEP;

	return (int)result;
}

static int gsensor_report_value(struct i2c_client *client, struct sensor_axis *axis)
{
	struct sensor_private_data *sensor =
	    (struct sensor_private_data *) i2c_get_clientdata(client);	
	if (sensor->status_cur == SENSOR_ON) {
		/* Report acceleration sensor information */
		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);
		input_sync(sensor->input_dev);
		//printk("Gsensor x==%d  y==%d z==%d\n",axis->x,axis->y,axis->z);
	}
	return 0;
}

#define GSENSOR_MIN  		2
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;
	int ret = 0;
	int x,y,z;
	struct sensor_axis axis;
	char value = 0;
	//SC7A30_load_user_calibration(client);
	//printk("---------------in--------------------\n");
#if 0
	memset(buffer1, 0, 3);
	memset(buffer2, 0, 3);

	*buffer1 = SC7A30_STATUS;
	ret = sensor_rx_data(sc7a30_client, buffer1,1);
	buffer1[0] &= 0x08;
	if(!buffer1[0])
		return ret;

	*buffer1 = SC7A30_XOUT_L;
	ret = sensor_rx_data(sc7a30_client, buffer1,1);  
        *buffer2 = SC7A30_XOUT_H;
	ret = sensor_rx_data(client, buffer2,1);
	if (ret < 0)
		return ret;
	x = sensor_convert_data(sensor->client, buffer2[0], buffer1[0],0);	//buffer[1]:high bit 

	*buffer1 = SC7A30_YOUT_L;
	ret = sensor_rx_data(sc7a30_client, buffer1,1);
	*buffer2 = SC7A30_YOUT_H;
	ret = sensor_rx_data(client, buffer2,1);
	if (ret < 0)
		return ret;
	y = sensor_convert_data(sensor->client, buffer2[0], buffer1[0],0);
	*buffer1 = SC7A30_ZOUT_L;
	ret = sensor_rx_data(sc7a30_client, buffer1,1);
	*buffer2 = SC7A30_ZOUT_H;
	ret = sensor_rx_data(client, buffer2,1);
	if (ret < 0)
		return ret;
	z = sensor_convert_data(sensor->client, buffer2[0], buffer1[0],0);
#else
	char buffer[6] = {0};
	memset(buffer, 0, 6);

	/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
	*buffer = SC7A30_XOUT_L | 0x80;
	ret = sensor_rx_data(sc7a30_client, buffer, 6);
	if (ret < 0) {
		printk("%s, %d, sensor rx data failed\n", __func__, __LINE__);
		return ret;
	}

	//this gsensor need 6 bytes buffer
	x = sensor_convert_data(sensor->client, buffer[1], buffer[0], 0);  //buffer[1]:high bit 
	y = sensor_convert_data(sensor->client, buffer[3], buffer[2], 0);
	z = sensor_convert_data(sensor->client, buffer[5], buffer[4], 0);
#endif

	axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
	axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z; 
	axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;

#if 0
	axis_average.x_average += axis.x;
	axis_average.y_average += axis.y;
	axis_average.z_average += axis.z;
	axis_average.count++;

	if(axis_average.count >= SC7A30_COUNT_AVERAGE)
	{
		axis.x = axis_average.x_average / axis_average.count;
		axis.y = axis_average.y_average / axis_average.count;
		axis.z = axis_average.z_average / axis_average.count;

		printk( "%s: axis = %d  %d  %d \n", __func__, axis.x, axis.y, axis.z);

		memset(&axis_average, 0, sizeof(struct sensor_axis_average));
		
		//Report event only while value is changed to save some power
		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))
		{
			gsensor_report_value(client, &axis);

			/* \BB\A5\B3\E2\B5ػ\BA\B4\E6\CA\FD\BE\DD. */
			mutex_lock(&(sensor->data_mutex) );
			sensor->axis = axis;
			mutex_unlock(&(sensor->data_mutex) );
		}
	}
#else
	gsensor_report_value(client, &axis);

	/* \BB\A5\B3\E2\B5ػ\BA\B4\E6\CA\FD\BE\DD. */
	mutex_lock(&(sensor->data_mutex) );
	sensor->axis = axis;
	mutex_unlock(&(sensor->data_mutex) );
#endif
	if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0))	//read sensor intterupt status register
	{

		value = sensor_read_reg(client, sensor->ops->int_status_reg);
		printk("%s:sensor int status :0x%x\n",__func__,value);
	}
	return ret;
}

static struct sensor_operate gsensor_sc7a30_ops = {
	.name				= "gs_sc7a30",
	.type				= SENSOR_TYPE_ACCEL,			//sensor type and it should be correct
	.id_i2c				= ACCEL_ID_SC7A30,			//i2c id number
	.read_reg			= SC7A30_XOUT_H,			//read data
	.read_len			= 1,					//data length
	.id_reg				= SENSOR_UNKNOW_DATA,			//read device id from this register
	.id_data 			= SENSOR_UNKNOW_DATA,			//device id
	.precision			= SC7A30_PRECISION,			//12 bit
	.ctrl_reg 			= SC7A30_MODE,			        //enable or disable SC7A30_MODE
	.int_status_reg 		= SENSOR_UNKNOW_DATA,			//intterupt status register
	.range				= {-SC7A30_RANGE,SC7A30_RANGE},	//range
	.trig				= IRQF_TRIGGER_HIGH|IRQF_ONESHOT,
	.active				= sensor_active,
	.init				= sensor_init,
	.report 			= sensor_report_value,
};

/****************operate according to sensor chip:end************/
static int gsensor_sc7a30_probe(struct i2c_client *client,
				const struct i2c_device_id *devid)
{
	return sensor_register_device(client, NULL, devid, &gsensor_sc7a30_ops);
}

static int gsensor_sc7a30_remove(struct i2c_client *client)
{
	return sensor_unregister_device(client, NULL, &gsensor_sc7a30_ops);
}

static const struct i2c_device_id gsensor_sc7a30_id[] = {
	{"gs_sc7a30", ACCEL_ID_SC7A30},
	{}
};

static struct i2c_driver gsensor_sc7a30_driver = {
	.probe = gsensor_sc7a30_probe,
	.remove = gsensor_sc7a30_remove,
	.shutdown = sensor_shutdown,
	.id_table = gsensor_sc7a30_id,
	.driver = {
		.name = "gsensor_sc7a30",
	#ifdef CONFIG_PM
		.pm = &sensor_pm_ops,
	#endif
	},
};

module_i2c_driver(gsensor_sc7a30_driver);

MODULE_AUTHOR("luowei <lw@rock-chips.com>");
MODULE_DESCRIPTION("sc7a30 3-Axis accelerometer driver");
MODULE_LICENSE("GPL");