summaryrefslogtreecommitdiff
path: root/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c')
-rw-r--r--drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c2719
1 files changed, 2719 insertions, 0 deletions
diff --git a/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c b/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c
new file mode 100644
index 00000000..c7d37a7a
--- /dev/null
+++ b/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c
@@ -0,0 +1,2719 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2013 mCube, Inc. All rights reserved.
+ *
+ * This source is subject to the mCube Software License.
+ * This software is protected by Copyright and the information and source code
+ * contained herein is confidential. The software including the source code
+ * may not be copied and the information contained herein may not be used or
+ * disclosed except with the written permission of mCube Inc.
+ *
+ * All other rights reserved.
+ *
+ * This code and information are provided "as is" without warranty of any
+ * kind, either expressed or implied, including but not limited to the
+ * implied warranties of merchantability and/or fitness for a
+ * particular purpose.
+ *
+ * The following software/firmware and/or related documentation ("mCube Software")
+ * have been modified by mCube Inc. All revisions are subject to any receiver's
+ * applicable license agreements with mCube Inc.
+ *
+ * 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/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+//#include <linux/earlysuspend.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+
+
+#include <mach/hardware.h>
+#include <linux/fs.h>
+
+#include "../sensor.h"
+
+
+//#include <mach/sys_config.h>
+
+//=== CONFIGURATIONS ==========================================================
+//#define _MC3XXX_DEBUG_ON_
+
+//=============================================================================
+#ifdef _MC3XXX_DEBUG_ON_
+ #define mcprintkreg(x...) printk(x)
+ #define mcprintkfunc(x...) printk(x)
+ #define GSE_ERR(x...) printk(x)
+ #define GSE_LOG(x...) printk(x)
+#else
+ #define mcprintkreg(x...)
+ #define mcprintkfunc(x...)
+ #define GSE_ERR(x...)
+ #define GSE_LOG(x...)
+#endif
+
+static int g_virtual_z = 0;
+#define G_2_REVERSE_VIRTUAL_Z 0 //!!!!! 1
+#define SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+#define LOW_RESOLUTION 1
+#define HIGH_RESOLUTION 2
+#define RBM_RESOLUTION 3
+#ifdef SUPPORT_VIRTUAL_Z_SENSOR
+#define Low_Pos_Max 127
+#define Low_Neg_Max -128
+#define High_Pos_Max 8191
+#define High_Neg_Max -8192
+#define VIRTUAL_Z 1
+static int Railed = 0;
+#else
+#define VIRTUAL_Z 0
+#endif
+
+
+static struct class* l_dev_class = NULL;
+
+
+#define SENSOR_NAME "mc3xxx"
+#define SENSOR_DRIVER_VERSION "1.0.0"
+#define SENSOR_DATA_SIZE 3
+
+//static int mc3xxx_pin_hd;
+//static char mc3xxx_on_off_str[32];
+#define G_0 ABS_Y
+#define G_1 ABS_X
+#define G_2 ABS_Z
+#define G_0_REVERSE 1
+#define G_1_REVERSE 1
+#define G_2_REVERSE 1
+
+//static unsigned char s_bResolution = 0x00;
+static unsigned char s_bPCODE = 0x00;
+static unsigned short mc3xxx_i2c_auto_probe_addr[] = { 0x4C, 0x6C, 0x4E, 0x6D, 0x6E, 0x6F };
+
+//=============================================================================
+#define SENSOR_DMARD_IOCTL_BASE 234
+#define IOCTL_SENSOR_SET_DELAY_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 100)
+#define IOCTL_SENSOR_GET_DELAY_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 101)
+#define IOCTL_SENSOR_GET_STATE_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 102)
+#define IOCTL_SENSOR_SET_STATE_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 103)
+#define IOCTL_SENSOR_GET_DATA_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 104)
+
+#define IOCTL_MSENSOR_SET_DELAY_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 200)
+#define IOCTL_MSENSOR_GET_DATA_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 201)
+#define IOCTL_MSENSOR_GET_STATE_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 202)
+#define IOCTL_MSENSOR_SET_STATE_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 203)
+
+#define IOCTL_SENSOR_GET_NAME _IO(SENSOR_DMARD_IOCTL_BASE, 301)
+#define IOCTL_SENSOR_GET_VENDOR _IO(SENSOR_DMARD_IOCTL_BASE, 302)
+#define IOCTL_SENSOR_GET_CONVERT_PARA _IO(SENSOR_DMARD_IOCTL_BASE, 401)
+//#define SENSOR_CALIBRATION _IOWR(SENSOR_DMARD_IOCTL_BASE, 402, int[SENSOR_DATA_SIZE])
+
+//=============================================================================
+#define MC3XXX_CONVERT_PARAMETER (1.5f * (9.80665f) / 256.0f)
+#define MC3XXX_DISPLAY_NAME SENSOR_NAME
+#define MC3XXX_DIPLAY_VENDOR "mCube"
+
+//=============================================================================
+#define MC3XXX_AXIS_X 0
+#define MC3XXX_AXIS_Y 1
+#define MC3XXX_AXIS_Z 2
+#define MC3XXX_AXIS_NUM 3
+#define MC3XXX_DATA_LEN 6
+
+
+/***********************************************
+ *** REGISTER MAP
+ ***********************************************/
+#define MC3XXX_REG_XOUT 0x00
+#define MC3XXX_REG_YOUT 0x01
+#define MC3XXX_REG_ZOUT 0x02
+#define MC3XXX_REG_TILT_STATUS 0x03
+#define MC3XXX_REG_SAMPLE_RATE_STATUS 0x04
+#define MC3XXX_REG_SLEEP_COUNT 0x05
+#define MC3XXX_REG_INTERRUPT_ENABLE 0x06
+#define MC3XXX_REG_MODE_FEATURE 0x07
+#define MC3XXX_REG_SAMPLE_RATE 0x08
+#define MC3XXX_REG_TAP_DETECTION_ENABLE 0x09
+#define MC3XXX_REG_TAP_DWELL_REJECT 0x0A
+#define MC3XXX_REG_DROP_CONTROL 0x0B
+#define MC3XXX_REG_SHAKE_DEBOUNCE 0x0C
+#define MC3XXX_REG_XOUT_EX_L 0x0D
+#define MC3XXX_REG_XOUT_EX_H 0x0E
+#define MC3XXX_REG_YOUT_EX_L 0x0F
+#define MC3XXX_REG_YOUT_EX_H 0x10
+#define MC3XXX_REG_ZOUT_EX_L 0x11
+#define MC3XXX_REG_ZOUT_EX_H 0x12
+#define MC3XXX_REG_RANGE_CONTROL 0x20
+#define MC3XXX_REG_SHAKE_THRESHOLD 0x2B
+#define MC3XXX_REG_UD_Z_TH 0x2C
+#define MC3XXX_REG_UD_X_TH 0x2D
+#define MC3XXX_REG_RL_Z_TH 0x2E
+#define MC3XXX_REG_RL_Y_TH 0x2F
+#define MC3XXX_REG_FB_Z_TH 0x30
+#define MC3XXX_REG_DROP_THRESHOLD 0x31
+#define MC3XXX_REG_TAP_THRESHOLD 0x32
+#define MC3XXX_REG_PRODUCT_CODE 0x3B
+
+/***********************************************
+ *** RETURN CODE
+ ***********************************************/
+#define MC3XXX_RETCODE_SUCCESS (0)
+#define MC3XXX_RETCODE_ERROR_I2C (-1)
+#define MC3XXX_RETCODE_ERROR_NULL_POINTER (-2)
+#define MC3XXX_RETCODE_ERROR_STATUS (-3)
+#define MC3XXX_RETCODE_ERROR_SETUP (-4)
+#define MC3XXX_RETCODE_ERROR_GET_DATA (-5)
+#define MC3XXX_RETCODE_ERROR_IDENTIFICATION (-6)
+
+
+/***********************************************
+ *** CONFIGURATION
+ ***********************************************/
+#define MC3XXX_BUF_SIZE 256
+
+#define MCUBE_1_5G_8BIT 0x01 //MC3XXX_LOW_END
+#define MCUBE_8G_14BIT 0x02 //MC3XXX_HIGH_END
+
+#define DOT_CALI
+
+
+#define SENSOR_DURATION_DEFAULT 20
+
+#define INPUT_FUZZ 0
+#define INPUT_FLAT 0
+
+/***********************************************
+ *** PRODUCT ID
+ ***********************************************/
+#define MC3XXX_PCODE_3210 0x90
+#define MC3XXX_PCODE_3230 0x19
+#define MC3XXX_PCODE_3250 0x88
+#define MC3XXX_PCODE_3410 0xA8
+#define MC3XXX_PCODE_3410N 0xB8
+#define MC3XXX_PCODE_3430 0x29
+#define MC3XXX_PCODE_3430N 0x39
+#define MC3XXX_PCODE_3510B 0x40
+#define MC3XXX_PCODE_3530B 0x30
+#define MC3XXX_PCODE_3510C 0x10
+#define MC3XXX_PCODE_3530C 0x6E
+
+//=============================================================================
+static unsigned char is_new_mc34x0 = 0;
+static unsigned char is_mc3250 = 0;
+static unsigned char is_mc35xx = 0;
+static unsigned char Sensor_Accuracy = 0;
+
+
+//=============================================================================
+#ifdef DOT_CALI
+#define CALIB_PATH "/data/data/com.mcube.acc/files/mcube-calib.txt"
+//MCUBE_BACKUP_FILE
+#define BACKUP_CALIB_PATH "/data/misc/mcube-calib.txt"
+static char backup_buf[64];
+//MCUBE_BACKUP_FILE
+#define DATA_PATH "/sdcard/mcube-register-map.txt"
+
+typedef struct {
+ unsigned short x; /**< X axis */
+ unsigned short y; /**< Y axis */
+ unsigned short z; /**< Z axis */
+} GSENSOR_VECTOR3D;
+
+static GSENSOR_VECTOR3D gsensor_gain = { 0 };
+static struct miscdevice mc3xxx_device;
+
+static struct file * fd_file = NULL;
+
+static mm_segment_t oldfs = { 0 };
+static unsigned char offset_buf[6] = { 0 };
+static signed int offset_data[3] = { 0 };
+s16 G_RAW_DATA[3] = { 0 };
+static signed int gain_data[3] = { 0 };
+static signed int enable_RBM_calibration = 0;
+
+#define GSENSOR 0x95
+#define GSENSOR_IOCTL_INIT _IO(GSENSOR, 0x01)
+#define GSENSOR_IOCTL_READ_CHIPINFO _IOR(GSENSOR, 0x02, int)
+#define GSENSOR_IOCTL_READ_SENSORDATA _IOR(GSENSOR, 0x03, int)
+#define GSENSOR_IOCTL_READ_OFFSET _IOR(GSENSOR, 0x04, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_GAIN _IOR(GSENSOR, 0x05, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_RAW_DATA _IOR(GSENSOR, 0x06, int)
+//#define GSENSOR_IOCTL_SET_CALI _IOW(GSENSOR, 0x06, SENSOR_DATA)
+#define GSENSOR_IOCTL_GET_CALI _IOW(GSENSOR, 0x07, SENSOR_DATA)
+#define GSENSOR_IOCTL_CLR_CALI _IO(GSENSOR, 0x08)
+#define GSENSOR_MCUBE_IOCTL_READ_RBM_DATA _IOR(GSENSOR, 0x09, SENSOR_DATA)
+#define GSENSOR_MCUBE_IOCTL_SET_RBM_MODE _IO(GSENSOR, 0x0a)
+#define GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE _IO(GSENSOR, 0x0b)
+#define GSENSOR_MCUBE_IOCTL_SET_CALI _IOW(GSENSOR, 0x0c, SENSOR_DATA)
+#define GSENSOR_MCUBE_IOCTL_REGISTER_MAP _IO(GSENSOR, 0x0d)
+#define GSENSOR_IOCTL_SET_CALI_MODE _IOW(GSENSOR, 0x0e,int)
+#define GSENSOR_MCUBE_IOCTL_READ_PRODUCT_ID _IOR(GSENSOR, 0x0f, int)
+#define GSENSOR_MCUBE_IOCTL_READ_FILEPATH _IOR(GSENSOR, 0x10, char[256])
+
+
+static int MC3XXX_ReadRegMap(struct i2c_client *client, u8 *pbUserBuf);
+static int mc3xxx_chip_init(struct i2c_client *client);
+static int MC3XXX_ResetCalibration(struct i2c_client *client);
+static int MC3XX0_ValidateSensorIC(unsigned char bPCode);
+
+
+typedef struct{
+ int x;
+ int y;
+ int z;
+}SENSOR_DATA;
+
+static int load_cali_flg = 0;
+static int wake_mc3xxx_flg = 0;
+
+//MCUBE_BACKUP_FILE
+static bool READ_FROM_BACKUP = false;
+//MCUBE_BACKUP_FILE
+
+#endif
+
+#define MC3XXX_WAKE 1
+#define MC3XXX_SNIFF 2
+#define MC3XXX_STANDBY 3
+
+struct dev_data {
+ struct i2c_client *client;
+};
+
+static struct dev_data dev = { 0 };
+
+struct acceleration {
+ int x;
+ int y;
+ int z;
+};
+
+struct mc3xxx_data {
+ struct mutex lock;
+ struct i2c_client *client;
+ struct delayed_work work;
+ struct workqueue_struct *mc3xxx_wq;
+ struct hrtimer timer;
+ struct device *device;
+ struct input_dev *input_dev;
+ int use_count;
+ int enabled;
+ volatile unsigned int duration;
+ int use_irq;
+ int irq;
+ unsigned long irqflags;
+ int gpio;
+ unsigned int map[3];
+ int inv[3];
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ // for control
+ int int_gpio; //0-3
+ int op;
+ int samp;
+ //int xyz_axis[3][3]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ int isdbg;
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ int offset[MC3XXX_AXIS_NUM+1]; /*+1: for 4-byte alignment*/
+ s16 data[MC3XXX_AXIS_NUM+1];
+};
+
+static struct mc3xxx_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 16,
+ /*.xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },*/
+ .sensor_proc = NULL,
+ .isdbg = 1,
+ .sensor_samp = 1, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ //.offset={0,0,0},
+};
+
+
+//=============================================================================
+enum mc3xx0_orientation
+{
+ MC3XX0_TOP_LEFT_DOWN = 0,
+ MC3XX0_TOP_RIGHT_DOWN,
+ MC3XX0_TOP_RIGHT_UP,
+ MC3XX0_TOP_LEFT_UP,
+ MC3XX0_BOTTOM_LEFT_DOWN,
+ MC3XX0_BOTTOM_RIGHT_DOWN,
+ MC3XX0_BOTTOM_RIGHT_UP,
+ MC3XX0_BOTTOM_LEFT_UP
+};
+
+
+struct mc3xx0_hwmsen_convert
+{
+ signed int sign[3];
+ unsigned int map[3];
+};
+
+// Transformation matrix for chip mounting position
+static const struct mc3xx0_hwmsen_convert mc3xx0_cvt[] =
+{
+ {{ 1, 1, 1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 0: top , left-down
+ {{-1, 1, 1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 1: top , right-down
+ {{-1, -1, 1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 2: top , right-up
+ {{ 1, -1, 1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 3: top , left-up
+ {{-1, 1, -1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 4: bottom, left-down
+ {{ 1, 1, -1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 5: bottom, right-down
+ {{ 1, -1, -1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 6: bottom, right-up
+ {{-1, -1, -1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 7: bottom, left-up
+};
+
+//static unsigned char mc3xx0_current_placement = MC3XX0_TOP_RIGHT_UP; // current soldered placement
+static struct mc3xx0_hwmsen_convert *pCvt;
+
+#ifdef SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+int Verify_Z_Railed(int AccData, int resolution)
+{
+ int status = 0;
+ GSE_LOG("%s: AccData = %d",__func__, AccData);
+ if(resolution == 1) // Low resolution
+ {
+ if((AccData >= Low_Pos_Max && AccData >=0)|| (AccData <= Low_Neg_Max && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at Low Resolution",__func__);
+ }
+ }
+ else if (resolution == 2) //High resolution
+ {
+ if((AccData >= High_Pos_Max && AccData >=0) || (AccData <= High_Neg_Max && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at High Resolution",__func__);
+ }
+ }
+ else if (resolution == 3) //High resolution
+ {
+ if((AccData >= Low_Pos_Max*3 && AccData >=0) || (AccData <= Low_Neg_Max*3 && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at High Resolution",__func__);
+ }
+ }
+ else
+ GSE_LOG("%s, Wrong resolution",__func__);
+
+ return status;
+}
+
+int SquareRoot(int x)
+{
+ int lowerbound;
+ int upperbound;
+ int root;
+
+ if(x < 0) return -1;
+ if(x == 0 || x == 1) return x;
+ lowerbound = 1;
+ upperbound = x;
+ root = lowerbound + (upperbound - lowerbound)/2;
+
+ while(root > x/root || root+1 <= x/(root+1))
+ {
+ if(root > x/root)
+ {
+ upperbound = root;
+ }
+ else
+ {
+ lowerbound = root;
+ }
+ root = lowerbound + (upperbound - lowerbound)/2;
+ }
+ GSE_LOG("%s: Sqrt root is %d",__func__, root);
+ return root;
+}
+#endif
+
+
+unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+
+//=============================================================================
+//volatile static short sensor_duration = SENSOR_DURATION_DEFAULT;
+//volatile static short sensor_state_flag = 1;
+
+//=============================================================================
+static ssize_t mc3xxx_map_show(struct device *dev, struct device_attribute *attr,char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mc3xxx_data *data = NULL;
+ int i = 0;
+ data = i2c_get_clientdata(client);
+ for (i = 0; i< 3; i++)
+ {
+ if(data->inv[i] == 1)
+ {
+ switch(data->map[i])
+ {
+ case ABS_X:
+ buf[i] = 'x';
+ break;
+ case ABS_Y:
+ buf[i] = 'y';
+ break;
+ case ABS_Z:
+ buf[i] = 'z';
+ break;
+ default:
+ buf[i] = '_';
+ break;
+ }
+ }
+ else
+ {
+ switch(data->map[i])
+ {
+ case ABS_X:
+ buf[i] = 'X';
+ break;
+ case ABS_Y:
+ buf[i] = 'Y';
+ break;
+ case ABS_Z:
+ buf[i] = 'Z';
+ break;
+ default:
+ buf[i] = '-';
+ break;
+ }
+ }
+ }
+ sprintf(buf+3,"\r\n");
+ return 5;
+}
+
+/*****************************************
+ *** show_regiter_map
+ *****************************************/
+static ssize_t show_regiter_map(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 _bIndex = 0;
+ u8 _baRegMap[64] = { 0 };
+ ssize_t _tLength = 0;
+
+ struct i2c_client *client = to_i2c_client(dev);
+
+ MC3XXX_ReadRegMap(client, _baRegMap);
+
+ for (_bIndex = 0; _bIndex < 64; _bIndex++)
+ _tLength += snprintf((buf + _tLength), (PAGE_SIZE - _tLength), "Reg[0x%02X]: 0x%02X\n", _bIndex, _baRegMap[_bIndex]);
+
+ return (_tLength);
+}
+
+static ssize_t mc3xxx_map_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mc3xxx_data *data = NULL;
+ int i = 0;
+ data = i2c_get_clientdata(client);
+
+ if(count < 3) return -EINVAL;
+
+ for(i = 0; i< 3; i++)
+ {
+ switch(buf[i])
+ {
+ case 'x':
+ data->map[i] = ABS_X;
+ data->inv[i] = 1;
+ break;
+ case 'y':
+ data->map[i] = ABS_Y;
+ data->inv[i] = 1;
+ break;
+ case 'z':
+ data->map[i] = ABS_Z;
+ data->inv[i] = 1;
+ break;
+ case 'X':
+ data->map[i] = ABS_X;
+ data->inv[i] = -1;
+ break;
+ case 'Y':
+ data->map[i] = ABS_Y;
+ data->inv[i] = -1;
+ break;
+ case 'Z':
+ data->map[i] = ABS_Z;
+ data->inv[i] = -1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return count;
+}
+
+//=============================================================================
+static ssize_t mc3xxx_version_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", SENSOR_DRIVER_VERSION);
+}
+
+//=============================================================================
+static ssize_t mc3xxx_chip_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ unsigned char bChipID[4] = { 0 };
+ struct i2c_client *client = to_i2c_client(dev);
+
+ i2c_smbus_read_i2c_block_data(client, 0x3C, 4, bChipID);
+
+ return sprintf(buf, "%02X-%02X-%02X-%02X\n", bChipID[0], bChipID[1], bChipID[2], bChipID[3]);
+}
+/*
+//=============================================================================
+static ssize_t mc3xxx_position_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ printk("%s called\n", __func__);
+ return sprintf(buf, "%d\n", mc3xx0_current_placement);
+}
+
+//=============================================================================
+static ssize_t mc3xxx_position_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long position = 0;
+
+ printk("%s called\n", __func__);
+
+ position = simple_strtoul(buf, NULL,10);
+
+ if (position < 8)
+ mc3xx0_current_placement = position;
+
+ return count;
+}
+*/
+
+static int mc3xxx_enable(struct mc3xxx_data *data, int enable)
+{
+ if(enable)
+ {
+ msleep(10);
+ //mutex_lock(&data->lock);
+ mc3xxx_chip_init(data->client);
+ //mutex_unlock(&data->lock);
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));//hrtimer_start(&data->timer, ktime_set(0, sensor_duration*1000000), HRTIMER_MODE_REL);
+ data->enabled = true;
+ }
+ else
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);//hrtimer_cancel(&data->timer);
+ data->enabled = false;
+ }
+ return 0;
+}
+
+static ssize_t mc3xxx_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = container_of(mc3xxx_device.parent, struct i2c_client, dev);
+
+ struct mc3xxx_data *mc3xxx = i2c_get_clientdata(client);
+
+
+ return sprintf(buf, "%d\n", mc3xxx->enabled);
+}
+
+static ssize_t mc3xxx_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ bool new_enable;
+
+ struct i2c_client *client = container_of(mc3xxx_device.parent, struct i2c_client, dev);
+
+ struct mc3xxx_data *mc3xxx = i2c_get_clientdata(client);
+
+ if (sysfs_streq(buf, "1"))
+ new_enable = true;
+ else if (sysfs_streq(buf, "0"))
+ new_enable = false;
+ else
+ {
+ pr_debug("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ mc3xxx_enable(mc3xxx, new_enable);
+
+ return count;
+}
+
+
+static DRIVER_ATTR(regmap , S_IRUGO, show_regiter_map, NULL );
+static DEVICE_ATTR(map, S_IWUSR | S_IRUGO, mc3xxx_map_show, mc3xxx_map_store);
+static DEVICE_ATTR(version , S_IRUGO , mc3xxx_version_show , NULL );
+static DEVICE_ATTR(chipid , S_IRUGO , mc3xxx_chip_id_show , NULL );
+//static DEVICE_ATTR(position, S_IRUGO | S_IWUSR | S_IWGRP, mc3xxx_position_show, mc3xxx_position_store);
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH, mc3xxx_enable_show, mc3xxx_enable_store);
+static struct attribute* mc3xxx_attrs[] =
+{
+ &driver_attr_regmap,
+ &dev_attr_map.attr,
+ &dev_attr_version.attr,
+ &dev_attr_chipid.attr,
+ //&dev_attr_position.attr,
+ &dev_attr_enable.attr,
+ NULL
+};
+
+static const struct attribute_group mc3xxx_group =
+{
+ .attrs = mc3xxx_attrs,
+};
+
+//=============================================================================
+static int mc3xxx_chip_init(struct i2c_client *client)
+{
+ unsigned char data = 0;
+
+ data = i2c_smbus_read_byte_data(client, MC3XXX_REG_PRODUCT_CODE);
+ s_bPCODE =data;
+ if((data == MC3XXX_PCODE_3230)||(data == MC3XXX_PCODE_3430)
+ ||(data == MC3XXX_PCODE_3430N)||(data == MC3XXX_PCODE_3530B)
+ ||((data|0x0E) == MC3XXX_PCODE_3530C))
+ Sensor_Accuracy = MCUBE_1_5G_8BIT; //8bit
+ else if((data == MC3XXX_PCODE_3210)||(data == MC3XXX_PCODE_3410)
+ ||(data == MC3XXX_PCODE_3250)||(data == MC3XXX_PCODE_3410N)
+ ||(data == MC3XXX_PCODE_3510B)||(data == MC3XXX_PCODE_3510C))
+ Sensor_Accuracy = MCUBE_8G_14BIT; //14bit
+ else
+ Sensor_Accuracy = 0;
+
+ if (data == MC3XXX_PCODE_3250)
+ is_mc3250 = 1;
+
+ if ((data == MC3XXX_PCODE_3430N)||(data == MC3XXX_PCODE_3410N))
+ is_new_mc34x0 = 1;
+
+ if((MC3XXX_PCODE_3510B == data) || (MC3XXX_PCODE_3510C == data)
+ ||(data == MC3XXX_PCODE_3530B)||((data|0x0E) == MC3XXX_PCODE_3530C))
+ is_mc35xx = 1;
+
+
+ if(MCUBE_8G_14BIT == Sensor_Accuracy)
+ {
+ data = 0x43;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SLEEP_COUNT, data);
+
+ data = 0x00;
+ if (is_mc35xx)
+ {
+ data = 0x0A;
+ }
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SAMPLE_RATE, data);
+
+ data = 0x3F;
+ if ((MC3XXX_PCODE_3510B == s_bPCODE) || (MC3XXX_PCODE_3510C == s_bPCODE))
+ data = 0x25;
+ else if ((MC3XXX_PCODE_3530B == s_bPCODE) || (MC3XXX_PCODE_3530C == (s_bPCODE|0x0E)))
+ data = 0x02;
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_RANGE_CONTROL, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_TAP_DETECTION_ENABLE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_INTERRUPT_ENABLE, data);
+
+ #ifdef DOT_CALI
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 1024;
+ #endif
+ }
+ else if(MCUBE_1_5G_8BIT == Sensor_Accuracy)
+ {
+ data = 0x43;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SLEEP_COUNT, data);
+
+ data = 0x00;
+ if (is_mc35xx)
+ {
+ data = 0x0A;
+ }
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SAMPLE_RATE, data);
+
+ data = 0x32;
+ if ((MC3XXX_PCODE_3510B == s_bPCODE) || (MC3XXX_PCODE_3510C == s_bPCODE))
+ data = 0x25;
+ else if ((MC3XXX_PCODE_3530B == s_bPCODE) || (MC3XXX_PCODE_3530C == (s_bPCODE|0x0E)))
+ data = 0x02;
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_RANGE_CONTROL,data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_TAP_DETECTION_ENABLE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_INTERRUPT_ENABLE, data);
+
+ #ifdef DOT_CALI
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 86;
+ if (is_mc35xx)
+ {
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 64;
+ }
+ #endif
+ }
+
+ data = 0x41;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+
+ return 0;
+}
+
+//=============================================================================
+int mc3xxx_set_mode(struct i2c_client *client, unsigned char mode)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ if (mode < 4)
+ {
+ data = (0x40 | mode);
+ comres = i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+ }
+
+ return comres;
+}
+
+
+
+#ifdef DOT_CALI
+//=============================================================================
+struct file *openFile(char *path,int flag,int mode)
+{
+ struct file *fp = NULL;
+
+ fp = filp_open(path, flag, mode);
+
+ if (IS_ERR(fp) || !fp->f_op)
+ {
+ GSE_LOG("Calibration File filp_open return NULL\n");
+ return NULL;
+ }
+
+ return fp;
+}
+
+//=============================================================================
+int readFile(struct file *fp,char *buf,int readlen)
+{
+ if (fp->f_op && fp->f_op->read)
+ return fp->f_op->read(fp,buf,readlen, &fp->f_pos);
+ else
+ return -1;
+}
+
+//=============================================================================
+int writeFile(struct file *fp,char *buf,int writelen)
+{
+ if (fp->f_op && fp->f_op->write)
+ return fp->f_op->write(fp,buf,writelen, &fp->f_pos);
+ else
+ return -1;
+}
+
+//=============================================================================
+int closeFile(struct file *fp)
+{
+ filp_close(fp,NULL);
+
+ return 0;
+}
+
+//=============================================================================
+void initKernelEnv(void)
+{
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ printk(KERN_INFO "initKernelEnv\n");
+}
+
+//=============================================================================
+ int MC3XXX_WriteCalibration(struct i2c_client *client, int dat[MC3XXX_AXIS_NUM])
+{
+ int err = 0;
+ u8 buf[9] = { 0 };
+ s16 tmp = 0, x_gain = 0, y_gain = 0, z_gain = 0;
+ s32 x_off = 0, y_off = 0, z_off = 0;
+ int temp_cali_dat[MC3XXX_AXIS_NUM] = { 0 };
+ //const struct mc3xx0_hwmsen_convert *pCvt = NULL;
+
+ u8 bMsbFilter = 0x3F;
+ s16 wSignBitMask = 0x2000;
+ s16 wSignPaddingBits = 0xC000;
+ s32 dwRangePosLimit = 0x1FFF;
+ s32 dwRangeNegLimit = -0x2000;
+
+ if (is_mc35xx)
+ {
+ bMsbFilter = 0x7F;
+ wSignBitMask = 0x4000;
+ wSignPaddingBits = 0x8000;
+ dwRangePosLimit = 0x3FFF;
+ dwRangeNegLimit = -0x4000;
+ }
+
+ //pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+ temp_cali_dat[pCvt->map[MC3XXX_AXIS_X]] = pCvt->sign[MC3XXX_AXIS_X] * dat[MC3XXX_AXIS_X];
+ temp_cali_dat[pCvt->map[MC3XXX_AXIS_Y]] = pCvt->sign[MC3XXX_AXIS_Y] * dat[MC3XXX_AXIS_Y];
+ temp_cali_dat[pCvt->map[MC3XXX_AXIS_Z]] = pCvt->sign[MC3XXX_AXIS_Z] * dat[MC3XXX_AXIS_Z];
+
+ if ((is_new_mc34x0)||(is_mc35xx))
+ {
+ temp_cali_dat[MC3XXX_AXIS_X] = -temp_cali_dat[MC3XXX_AXIS_X];
+ temp_cali_dat[MC3XXX_AXIS_Y] = -temp_cali_dat[MC3XXX_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = temp_cali_dat[MC3XXX_AXIS_X];
+
+ temp_cali_dat[MC3XXX_AXIS_X] = -temp_cali_dat[MC3XXX_AXIS_Y];
+ temp_cali_dat[MC3XXX_AXIS_Y] = temp;
+ }
+
+ dat[MC3XXX_AXIS_X] = temp_cali_dat[MC3XXX_AXIS_X];
+ dat[MC3XXX_AXIS_Y] = temp_cali_dat[MC3XXX_AXIS_Y];
+ dat[MC3XXX_AXIS_Z] = temp_cali_dat[MC3XXX_AXIS_Z];
+
+ GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
+ dat[MC3XXX_AXIS_X], dat[MC3XXX_AXIS_Y], dat[MC3XXX_AXIS_Z]);
+
+ // read register 0x21~0x29
+ err = i2c_smbus_read_i2c_block_data(client , 0x21 , 3 , &buf[0]);
+ err |= i2c_smbus_read_i2c_block_data(client , 0x24 , 3 , &buf[3]);
+ err |= i2c_smbus_read_i2c_block_data(client , 0x27 , 3 , &buf[6]);
+
+
+ // get x,y,z offset
+ tmp = ((buf[1] & bMsbFilter) << 8) + buf[0];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ x_off = tmp;
+
+ tmp = ((buf[3] & bMsbFilter) << 8) + buf[2];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ y_off = tmp;
+
+ tmp = ((buf[5] & bMsbFilter) << 8) + buf[4];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ z_off = tmp;
+
+ // get x,y,z gain
+ x_gain = ((buf[1] >> 7) << 8) + buf[6];
+ y_gain = ((buf[3] >> 7) << 8) + buf[7];
+ z_gain = ((buf[5] >> 7) << 8) + buf[8];
+
+ // prepare new offset
+ x_off = x_off + 16 * dat[MC3XXX_AXIS_X] * 256 * 128 / 3 / gsensor_gain.x / (40 + x_gain);
+ y_off = y_off + 16 * dat[MC3XXX_AXIS_Y] * 256 * 128 / 3 / gsensor_gain.y / (40 + y_gain);
+ z_off = z_off + 16 * dat[MC3XXX_AXIS_Z] * 256 * 128 / 3 / gsensor_gain.z / (40 + z_gain);
+
+ //add for over range
+ if( x_off > dwRangePosLimit)
+ {
+ x_off = dwRangePosLimit;
+ }
+ else if( x_off < dwRangeNegLimit)
+ {
+ x_off = dwRangeNegLimit;
+ }
+
+ if( y_off > dwRangePosLimit)
+ {
+ y_off = dwRangePosLimit;
+ }
+ else if( y_off < dwRangeNegLimit)
+ {
+ y_off = dwRangeNegLimit;
+ }
+
+ if( z_off > dwRangePosLimit)
+ {
+ z_off = dwRangePosLimit;
+ }
+ else if( z_off < dwRangeNegLimit)
+ {
+ z_off = dwRangeNegLimit;
+ }
+
+ //storege the cerrunt offset data with DOT format
+ offset_data[0] = x_off;
+ offset_data[1] = y_off;
+ offset_data[2] = z_off;
+
+ //storege the cerrunt Gain data with GOT format
+ gain_data[0] = 256*8*128/3/(40+x_gain);
+ gain_data[1] = 256*8*128/3/(40+y_gain);
+ gain_data[2] = 256*8*128/3/(40+z_gain);
+ printk("%d %d ======================\n\n ",gain_data[0],x_gain);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+ buf[0] = x_off & 0xff;
+ buf[1] = ((x_off >> 8) & bMsbFilter) | (x_gain & 0x0100 ? 0x80 : 0);
+ buf[2] = y_off & 0xff;
+ buf[3] = ((y_off >> 8) & bMsbFilter) | (y_gain & 0x0100 ? 0x80 : 0);
+ buf[4] = z_off & 0xff;
+ buf[5] = ((z_off >> 8) & bMsbFilter) | (z_gain & 0x0100 ? 0x80 : 0);
+
+ i2c_smbus_write_i2c_block_data(client, 0x21, 2, &buf[0]);
+ i2c_smbus_write_i2c_block_data(client, 0x21+2, 2, &buf[2]);
+ i2c_smbus_write_i2c_block_data(client, 0x21+4, 2, &buf[4]);
+
+ buf[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07,buf[0]);
+
+ msleep(50);
+
+ return err;
+
+}
+
+int mcube_read_cali_file(struct i2c_client *client)
+{
+ int cali_data[3] = { 0 };
+ int err =0;
+ //char buf[64];
+ printk("%s %d\n",__func__,__LINE__);
+ //MCUBE_BACKUP_FILE
+ READ_FROM_BACKUP = false;
+ //MCUBE_BACKUP_FILE
+ initKernelEnv();
+ fd_file = openFile(CALIB_PATH,O_RDONLY,0);
+ //MCUBE_BACKUP_FILE
+ if (fd_file == NULL)
+ {
+ fd_file = openFile(BACKUP_CALIB_PATH, O_RDONLY, 0);
+ if(fd_file != NULL)
+ {
+ READ_FROM_BACKUP = true;
+ }
+ }
+ //MCUBE_BACKUP_FILE
+ if (fd_file == NULL)
+ {
+ GSE_LOG("fail to open\n");
+ cali_data[0] = 0;
+ cali_data[1] = 0;
+ cali_data[2] = 0;
+
+ return -1;
+ }
+ else
+ {
+ printk("%s %d\n",__func__,__LINE__);
+ memset(backup_buf,0,64);
+ if ((err = readFile(fd_file,backup_buf,128))>0)
+ GSE_LOG("buf:%s\n",backup_buf);
+ else
+ GSE_LOG("read file error %d\n",err);
+ printk("%s %d\n",__func__,__LINE__);
+
+ set_fs(oldfs);
+ closeFile(fd_file);
+
+ sscanf(backup_buf, "%d %d %d",&cali_data[MC3XXX_AXIS_X], &cali_data[MC3XXX_AXIS_Y], &cali_data[MC3XXX_AXIS_Z]);
+ GSE_LOG("cali_data: %d %d %d\n", cali_data[MC3XXX_AXIS_X], cali_data[MC3XXX_AXIS_Y], cali_data[MC3XXX_AXIS_Z]);
+
+ MC3XXX_WriteCalibration(client, cali_data);
+ }
+ return 0;
+}
+
+//=============================================================================
+static int mcube_write_log_data(struct i2c_client *client, u8 data[0x3f])
+{
+ #define _WRT_LOG_DATA_BUFFER_SIZE (66 * 50)
+
+ s16 rbm_data[3]={0}, raw_data[3]={0};
+ int err =0;
+ char *_pszBuffer = NULL;
+ int n=0,i=0;
+
+ initKernelEnv();
+ fd_file = openFile(DATA_PATH ,O_RDWR | O_CREAT,0);
+ if (fd_file == NULL)
+ {
+ GSE_LOG("mcube_write_log_data fail to open\n");
+ }
+ else
+ {
+ rbm_data[MC3XXX_AXIS_X] = (s16)((data[0x0d]) | (data[0x0e] << 8));
+ rbm_data[MC3XXX_AXIS_Y] = (s16)((data[0x0f]) | (data[0x10] << 8));
+ rbm_data[MC3XXX_AXIS_Z] = (s16)((data[0x11]) | (data[0x12] << 8));
+
+ raw_data[MC3XXX_AXIS_X] = (rbm_data[MC3XXX_AXIS_X] + offset_data[0]/2)*gsensor_gain.x/gain_data[0];
+ raw_data[MC3XXX_AXIS_Y] = (rbm_data[MC3XXX_AXIS_Y] + offset_data[1]/2)*gsensor_gain.y/gain_data[1];
+ raw_data[MC3XXX_AXIS_Z] = (rbm_data[MC3XXX_AXIS_Z] + offset_data[2]/2)*gsensor_gain.z/gain_data[2];
+
+ _pszBuffer = kzalloc(_WRT_LOG_DATA_BUFFER_SIZE, GFP_KERNEL);
+ if (NULL == _pszBuffer)
+ {
+ GSE_ERR("fail to allocate memory for buffer\n");
+ closeFile(fd_file);
+ return -1;
+ }
+ memset(_pszBuffer, 0, _WRT_LOG_DATA_BUFFER_SIZE);
+
+ n += sprintf(_pszBuffer+n, "G-sensor RAW X = %d Y = %d Z = %d\n", raw_data[0] ,raw_data[1] ,raw_data[2]);
+ n += sprintf(_pszBuffer+n, "G-sensor RBM X = %d Y = %d Z = %d\n", rbm_data[0] ,rbm_data[1] ,rbm_data[2]);
+ for(i=0; i<64; i++)
+ {
+ n += sprintf(_pszBuffer+n, "mCube register map Register[%x] = 0x%x\n",i,data[i]);
+ }
+ msleep(50);
+ if ((err = writeFile(fd_file,_pszBuffer,n))>0)
+ GSE_LOG("buf:%s\n",_pszBuffer);
+ else
+ GSE_LOG("write file error %d\n",err);
+
+ kfree(_pszBuffer);
+
+ set_fs(oldfs);
+ closeFile(fd_file);
+ }
+ return 0;
+}
+
+//=============================================================================
+void MC3XXX_rbm(struct i2c_client *client, int enable)
+{
+ char buf1[3] = { 0 };
+ if(enable == 1 )
+ {
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ buf1[0] = 0x6D;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x3B, buf1[0]);
+
+ buf1[0] = 0x02;
+ i2c_smbus_write_byte_data(client, 0x14, buf1[0]);
+
+ buf1[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ enable_RBM_calibration = 1;
+
+ GSE_LOG("set rbm!!\n");
+
+ msleep(10);
+ }
+ else if(enable == 0 )
+ {
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ buf1[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x14, buf1[0]);
+ GSE_LOG("set rbm!! %x @@@@\n",s_bPCODE);
+
+ buf1[0] = s_bPCODE;
+ i2c_smbus_write_byte_data(client, 0x3B, buf1[0]);
+
+ buf1[0] = 0x6D;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ enable_RBM_calibration = 0;
+
+ GSE_LOG("clear rbm!!\n");
+
+ msleep(10);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+ int MC3XXX_ReadData_RBM(struct i2c_client *client,int data[MC3XXX_AXIS_NUM])
+{
+ u8 addr = 0x0d;
+ u8 rbm_buf[MC3XXX_DATA_LEN] = {0};
+ int err = 0;
+
+ //err = p_mc3xxx->MC3XXX_BUS_READ_FUNC(p_mc3xxx->dev_addr, addr, &rbm_buf[0],6);
+ err = i2c_smbus_read_i2c_block_data(client , addr , 6 , rbm_buf);
+ //err = mc3xxx_read_block(client, addr, rbm_buf, 0x06);
+
+ data[MC3XXX_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
+ data[MC3XXX_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
+ data[MC3XXX_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
+
+ GSE_LOG("rbm_buf<<<<<[%02x %02x %02x %02x %02x %02x]\n",rbm_buf[0], rbm_buf[2], rbm_buf[2], rbm_buf[3], rbm_buf[4], rbm_buf[5]);
+ GSE_LOG("RBM<<<<<[%04x %04x %04x]\n", data[MC3XXX_AXIS_X], data[MC3XXX_AXIS_Y], data[MC3XXX_AXIS_Z]);
+ GSE_LOG("RBM<<<<<[%04d %04d %04d]\n", data[MC3XXX_AXIS_X], data[MC3XXX_AXIS_Y], data[MC3XXX_AXIS_Z]);
+ return err;
+}
+
+
+ int MC3XXX_ReadRBMData(struct i2c_client *client, char *buf)
+{
+ int res = 0;
+ int data[3];
+
+ if (!buf)
+ {
+ return EINVAL;
+ }
+
+ mc3xxx_set_mode(client,MC3XXX_WAKE);
+
+ res = MC3XXX_ReadData_RBM(client,data);
+
+ if(res)
+ {
+ GSE_ERR("%s I2C error: ret value=%d",__func__, res);
+ return EIO;
+ }
+ else
+ {
+ sprintf(buf, "%04x %04x %04x", data[MC3XXX_AXIS_X],
+ data[MC3XXX_AXIS_Y], data[MC3XXX_AXIS_Z]);
+
+ }
+
+ return 0;
+}
+ int MC3XXX_ReadOffset(struct i2c_client *client,s16 ofs[MC3XXX_AXIS_NUM])
+{
+ int err = 0;
+ u8 off_data[6] = { 0 };
+
+ if(Sensor_Accuracy == MCUBE_8G_14BIT)
+ {
+ err = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT_EX_L, MC3XXX_DATA_LEN, off_data);
+
+ ofs[MC3XXX_AXIS_X] = ((s16)(off_data[0]))|((s16)(off_data[1])<<8);
+ ofs[MC3XXX_AXIS_Y] = ((s16)(off_data[2]))|((s16)(off_data[3])<<8);
+ ofs[MC3XXX_AXIS_Z] = ((s16)(off_data[4]))|((s16)(off_data[5])<<8);
+ }
+ else if(Sensor_Accuracy == MCUBE_1_5G_8BIT)
+ {
+ err = i2c_smbus_read_i2c_block_data(client, 0, 3, off_data);
+
+ ofs[MC3XXX_AXIS_X] = (s8)off_data[0];
+ ofs[MC3XXX_AXIS_Y] = (s8)off_data[1];
+ ofs[MC3XXX_AXIS_Z] = (s8)off_data[2];
+ }
+
+ GSE_LOG("MC3XXX_ReadOffset %d %d %d\n", ofs[MC3XXX_AXIS_X], ofs[MC3XXX_AXIS_Y], ofs[MC3XXX_AXIS_Z]);
+
+ return err;
+}
+/*----------------------------------------------------------------------------*/
+ static int MC3XXX_ResetCalibration(struct i2c_client *client)
+{
+ u8 buf[6] = { 0 };
+ s16 tmp = 0;
+ int err = 0;
+
+ u8 bMsbFilter = 0x3F;
+ s16 wSignBitMask = 0x2000;
+ s16 wSignPaddingBits = 0xC000;
+
+ buf[0] = 0x43;
+ err = i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+ if(err)
+ {
+ GSE_ERR("error 0x07: %d\n", err);
+ }
+
+ err = i2c_smbus_write_i2c_block_data(client, 0x21, 6, offset_buf);
+ if(err)
+ {
+ GSE_ERR("error: %d\n", err);
+ }
+
+ buf[0] = 0x41;
+ err = i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+ if(err)
+ {
+ GSE_ERR("error: %d\n", err);
+ }
+
+ msleep(20);
+
+
+ if (is_mc35xx)
+ {
+ bMsbFilter = 0x7F;
+ wSignBitMask = 0x4000;
+ wSignPaddingBits = 0x8000;
+ }
+
+ tmp = ((offset_buf[1] & bMsbFilter) << 8) + offset_buf[0];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ offset_data[0] = tmp;
+
+ tmp = ((offset_buf[3] & bMsbFilter) << 8) + offset_buf[2];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ offset_data[1] = tmp;
+
+ tmp = ((offset_buf[5] & bMsbFilter) << 8) + offset_buf[4];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ offset_data[2] = tmp;
+
+ return 0;
+}
+
+//=============================================================================
+ int MC3XXX_ReadCalibration(struct i2c_client *client,int dat[MC3XXX_AXIS_NUM])
+{
+ signed short MC_offset[MC3XXX_AXIS_NUM + 1] = { 0 }; // +1: for 4-byte alignment
+ int err = 0;
+
+ memset(MC_offset, 0, sizeof(MC_offset));
+
+ err = MC3XXX_ReadOffset(client, MC_offset);
+
+ if (err)
+ {
+ GSE_ERR("read offset fail, %d\n", err);
+ return err;
+ }
+
+ dat[MC3XXX_AXIS_X] = MC_offset[MC3XXX_AXIS_X];
+ dat[MC3XXX_AXIS_Y] = MC_offset[MC3XXX_AXIS_Y];
+ dat[MC3XXX_AXIS_Z] = MC_offset[MC3XXX_AXIS_Z];
+
+ return 0;
+}
+
+//=============================================================================
+int MC3XXX_ReadData(struct i2c_client *client, s16 buffer[MC3XXX_AXIS_NUM])
+{
+ unsigned char buf[6] = { 0 };
+ signed char buf1[6] = { 0 };
+ char rbm_buf[6] = { 0 };
+ int ret = 0;
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR
+ int tempX=0;
+ int tempY=0;
+ int tempZ=0;
+ #endif
+
+ if (enable_RBM_calibration == 0)
+ {
+ //err = hwmsen_read_block(client, addr, buf, 0x06);
+ }
+ else if (enable_RBM_calibration == 1)
+ {
+ memset(rbm_buf, 0, 6);
+ i2c_smbus_read_i2c_block_data(client, 0x0d , 2, &rbm_buf[0]);
+ i2c_smbus_read_i2c_block_data(client, 0x0d+2, 2, &rbm_buf[2]);
+ i2c_smbus_read_i2c_block_data(client, 0x0d+4, 2, &rbm_buf[4]);
+ }
+
+ if (enable_RBM_calibration == 0)
+ {
+ if(Sensor_Accuracy == MCUBE_8G_14BIT)
+ {
+ ret = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT_EX_L, 6, buf);
+
+ buffer[0] = (signed short)((buf[0])|(buf[1]<<8));
+ buffer[1] = (signed short)((buf[2])|(buf[3]<<8));
+ buffer[2] = (signed short)((buf[4])|(buf[5]<<8));
+ }
+ else if(Sensor_Accuracy == MCUBE_1_5G_8BIT)
+ {
+ ret = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT, 3, buf1);
+
+ buffer[0] = (signed short)buf1[0];
+ buffer[1] = (signed short)buf1[1];
+ buffer[2] = (signed short)buf1[2];
+ }
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+ if (g_virtual_z)
+ {
+ //printk("%s 1\n", __FUNCTION__);
+
+ tempX = buffer[MC3XXX_AXIS_X];
+ tempY = buffer[MC3XXX_AXIS_Y];
+ tempZ = buffer[MC3XXX_AXIS_Z];
+ //printk(" %d:Verify_Z_Railed() %d\n", (int)buffer[MC32X0_AXIS_Z], Verify_Z_Railed((int)buffer[MC32X0_AXIS_Z], LOW_RESOLUTION));
+ if(1 == Verify_Z_Railed((int)buffer[MC3XXX_AXIS_Z], LOW_RESOLUTION)) // z-railed
+ {
+ Railed = 1;
+
+ GSE_LOG("%s: Z railed", __func__);
+ //printk("%s: Z railed \n", __func__);
+ if (G_2_REVERSE_VIRTUAL_Z == 1)
+ buffer[MC3XXX_AXIS_Z] = (s8) ( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ else
+ buffer[MC3XXX_AXIS_Z] = (s8) -( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ }
+ else
+ {
+ Railed = 0;
+ }
+ }
+ #endif
+ mcprintkreg("MC3XXX_ReadData: %d %d %d\n", buffer[0], buffer[1], buffer[2]);
+ }
+ else if (enable_RBM_calibration == 1)
+ {
+ buffer[MC3XXX_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
+ buffer[MC3XXX_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
+ buffer[MC3XXX_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
+
+ GSE_LOG("%s RBM<<<<<[%08d %08d %08d]\n", __func__, buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+
+ if(gain_data[0] == 0)
+ {
+ buffer[MC3XXX_AXIS_X] = 0;
+ buffer[MC3XXX_AXIS_Y] = 0;
+ buffer[MC3XXX_AXIS_Z] = 0;
+
+ return 0;
+ }
+
+ buffer[MC3XXX_AXIS_X] = (buffer[MC3XXX_AXIS_X] + offset_data[0]/2)*gsensor_gain.x/gain_data[0];
+ buffer[MC3XXX_AXIS_Y] = (buffer[MC3XXX_AXIS_Y] + offset_data[1]/2)*gsensor_gain.y/gain_data[1];
+ buffer[MC3XXX_AXIS_Z] = (buffer[MC3XXX_AXIS_Z] + offset_data[2]/2)*gsensor_gain.z/gain_data[2];
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR // add 2013-10-23
+ if (g_virtual_z)
+ {
+ tempX = buffer[MC3XXX_AXIS_X];
+ tempY = buffer[MC3XXX_AXIS_Y];
+ tempZ = buffer[MC3XXX_AXIS_Z];
+ //printk("%s 2\n", __FUNCTION__);
+ GSE_LOG("Original RBM<<<<<[%08d %08d %08d]\n", buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+ printk("Verify_Z_Railed() %d\n", Verify_Z_Railed((int)buffer[MC3XXX_AXIS_Z], RBM_RESOLUTION));
+ if(1 == Verify_Z_Railed(buffer[MC3XXX_AXIS_Z], RBM_RESOLUTION)) // z-railed
+ {
+ GSE_LOG("%s: Z Railed in RBM mode",__FUNCTION__);
+ //printk("%s: Z Railed in RBM mode\n",__FUNCTION__);
+ if (G_2_REVERSE_VIRTUAL_Z == 1)
+ buffer[MC3XXX_AXIS_Z] = (s16) ( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ else
+ buffer[MC3XXX_AXIS_Z] = (s16) -( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ }
+ GSE_LOG("RBM<<<<<[%08d %08d %08d]\n", buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+ }
+ #endif
+
+ GSE_LOG("%s offset_data <<<<<[%d %d %d]\n", __func__, offset_data[0], offset_data[1], offset_data[2]);
+ GSE_LOG("%s gsensor_gain <<<<<[%d %d %d]\n", __func__, gsensor_gain.x, gsensor_gain.y, gsensor_gain.z);
+ GSE_LOG("%s gain_data <<<<<[%d %d %d]\n", __func__, gain_data[0], gain_data[1], gain_data[2]);
+ GSE_LOG("%s RBM->RAW <<<<<[%d %d %d]\n", __func__, buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+ }
+
+ return 0;
+}
+
+//=============================================================================
+int MC3XXX_ReadRawData(struct i2c_client *client, char * buf)
+{
+ int res = 0;
+ s16 raw_buf[3] = { 0 };
+
+ if (!buf || !client)
+ {
+ return -EINVAL;
+ }
+
+ mc3xxx_set_mode(client, MC3XXX_WAKE);
+ res = MC3XXX_ReadData(client,&raw_buf[0]);
+ if(res)
+ {
+ printk("%s %d\n",__FUNCTION__, __LINE__);
+ GSE_ERR("I2C error: ret value=%d", res);
+ return -EIO;
+ }
+ else
+ {
+ //const struct mc3xx0_hwmsen_convert *pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+ GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
+ raw_buf[MC3XXX_AXIS_X], raw_buf[MC3XXX_AXIS_Y], raw_buf[MC3XXX_AXIS_Z]);
+
+ if ((is_new_mc34x0)||(is_mc35xx))
+ {
+ raw_buf[MC3XXX_AXIS_X] = -raw_buf[MC3XXX_AXIS_X];
+ raw_buf[MC3XXX_AXIS_Y] = -raw_buf[MC3XXX_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = raw_buf[MC3XXX_AXIS_X];
+
+ raw_buf[MC3XXX_AXIS_X] = raw_buf[MC3XXX_AXIS_Y];
+ raw_buf[MC3XXX_AXIS_Y] = -temp;
+ }
+
+ G_RAW_DATA[MC3XXX_AXIS_X] = pCvt->sign[MC3XXX_AXIS_X] * raw_buf[pCvt->map[MC3XXX_AXIS_X]];
+ G_RAW_DATA[MC3XXX_AXIS_Y] = pCvt->sign[MC3XXX_AXIS_Y] * raw_buf[pCvt->map[MC3XXX_AXIS_Y]];
+ G_RAW_DATA[MC3XXX_AXIS_Z] = pCvt->sign[MC3XXX_AXIS_Z] * raw_buf[pCvt->map[MC3XXX_AXIS_Z]];
+
+ G_RAW_DATA[MC3XXX_AXIS_Z] += gsensor_gain.z*(pCvt->sign[MC3XXX_AXIS_Z])*(1);//G_RAW_DATA[MC3XXX_AXIS_Z]+gsensor_gain.z;
+
+ sprintf(buf, "%04x %04x %04x", G_RAW_DATA[MC3XXX_AXIS_X],
+ G_RAW_DATA[MC3XXX_AXIS_Y], G_RAW_DATA[MC3XXX_AXIS_Z]);
+
+ GSE_LOG("G_RAW_DATA: (%+3d %+3d %+3d)\n",
+ G_RAW_DATA[MC3XXX_AXIS_X], G_RAW_DATA[MC3XXX_AXIS_Y], G_RAW_DATA[MC3XXX_AXIS_Z]);
+ }
+
+ return 0;
+}
+
+//=============================================================================
+static int MC3XXX_ReadRegMap(struct i2c_client *client, u8 *pbUserBuf)
+{
+ u8 data[128] = {0};
+ //u8 addr = 0x00;
+ int err = 0;
+ int i = 0;
+
+ if(NULL == client)
+ {
+ err = -EINVAL;
+ return err;
+ }
+
+
+ for(i = 0; i < 64; i++)
+ {
+ data[i] = i2c_smbus_read_byte_data(client, i);
+ printk(KERN_INFO "mcube register map Register[%x] = 0x%x\n", i ,data[i]);
+ }
+
+ msleep(50);
+
+ mcube_write_log_data(client, data);
+
+ msleep(50);
+
+ if (NULL != pbUserBuf)
+ {
+ printk(KERN_INFO "copy to user buffer\n");
+ memcpy(pbUserBuf, data, 64);
+ }
+
+ return err;
+}
+
+//=============================================================================
+void MC3XXX_Reset(struct i2c_client *client)
+{
+ //s16 tmp = 0, x_gain = 0, y_gain = 0, z_gain = 0;
+ u8 buf[3] = { 0 };
+ int err = 0;
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+ i2c_smbus_read_i2c_block_data(client, 0x04, 1, buf);
+
+ if (0x00 == (buf[0] & 0x40))
+ {
+ buf[0] = 0x6d;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+ }
+
+ msleep(5);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+ buf[0] = 0x80;
+ i2c_smbus_write_byte_data(client, 0x1c, buf[0]);
+
+ buf[0] = 0x80;
+ i2c_smbus_write_byte_data(client, 0x17, buf[0]);
+
+ msleep(5);
+
+ buf[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x1c, buf[0]);
+
+ buf[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x17, buf[0]);
+
+ msleep(5);
+
+ memset(offset_buf, 0, sizeof(offset_buf));
+
+ err = i2c_smbus_read_i2c_block_data(client, 0x21, 6, offset_buf);
+
+ i2c_smbus_read_i2c_block_data(client, 0x04, 1, buf);
+
+ if (0x00 == (buf[0] & 0x40))
+ {
+ buf[0] = 0x6d;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+ }
+
+ buf[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+}
+#endif
+
+int mc3xxx_read_accel_xyz(struct i2c_client *client, s16 * acc)
+{
+ int comres = 0;
+ s16 raw_data[MC3XXX_AXIS_NUM] = { 0 };
+ //const struct mc3xx0_hwmsen_convert *pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+#ifdef DOT_CALI
+ s16 raw_buf[6] = { 0 };
+
+ comres = MC3XXX_ReadData(client, &raw_buf[0]);
+
+ raw_data[MC3XXX_AXIS_X] = raw_buf[0];
+ raw_data[MC3XXX_AXIS_Y] = raw_buf[1];
+ raw_data[MC3XXX_AXIS_Z] = raw_buf[2];
+#else
+ unsigned char raw_buf[6] = { 0 };
+ signed char raw_buf1[3] = { 0 };
+
+ if(Sensor_Accuracy == MCUBE_8G_14BIT)
+ {
+ comres = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT_EX_L, 6, raw_buf);
+
+ raw_data[MC3XXX_AXIS_X] = (signed short)((raw_buf[0])|(raw_buf[1]<<8));
+ raw_data[MC3XXX_AXIS_Y] = (signed short)((raw_buf[2])|(raw_buf[3]<<8));
+ raw_data[MC3XXX_AXIS_Z] = (signed short)((raw_buf[4])|(raw_buf[5]<<8));
+ }
+ else if(Sensor_Accuracy == MCUBE_1_5G_8BIT)
+ {
+ comres = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT, 3, raw_buf1);
+
+ raw_data[MC3XXX_AXIS_X] = (signed short)raw_buf1[0];
+ raw_data[MC3XXX_AXIS_Y] = (signed short)raw_buf1[1];
+ raw_data[MC3XXX_AXIS_Z] = (signed short)raw_buf1[2];
+ }
+#endif
+
+ if((is_new_mc34x0)||(is_mc35xx))
+ {
+ raw_data[MC3XXX_AXIS_X] = -raw_data[MC3XXX_AXIS_X];
+ raw_data[MC3XXX_AXIS_Y] = -raw_data[MC3XXX_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = raw_data[MC3XXX_AXIS_X];
+
+ raw_data[MC3XXX_AXIS_X] = raw_data[MC3XXX_AXIS_Y];
+ raw_data[MC3XXX_AXIS_Y] = -temp;
+ }
+ //printk("%s:%d %d %d\n",__FUNCTION__,raw_data[0],raw_data[1],raw_data[2]);
+ acc[MC3XXX_AXIS_X] = pCvt->sign[MC3XXX_AXIS_X] * raw_data[pCvt->map[MC3XXX_AXIS_X]];
+ acc[MC3XXX_AXIS_Y] = pCvt->sign[MC3XXX_AXIS_Y] * raw_data[pCvt->map[MC3XXX_AXIS_Y]];
+ acc[MC3XXX_AXIS_Z] = pCvt->sign[MC3XXX_AXIS_Z] * raw_data[pCvt->map[MC3XXX_AXIS_Z]];
+
+ return comres;
+}
+
+//=============================================================================
+static void mc3xxx_work_func(struct work_struct *work)
+{
+ struct mc3xxx_data *data = &l_sensorconfig;//container_of(work, struct mc3xxx_data, work);
+ //int ret = 0;
+ s16 raw[3] = { 0 };
+
+#ifdef DOT_CALI
+ if( load_cali_flg > 0)
+ {
+ /* ret = mcube_read_cali_file(data->client);
+
+ if(ret == 0)
+ load_cali_flg = ret;
+ else
+ load_cali_flg--;
+
+ GSE_LOG("load_cali %d\n",ret); */
+ MC3XXX_WriteCalibration(data->client,l_sensorconfig.offset);
+ load_cali_flg = 0;
+ }
+#endif
+#if 1
+//gsensor not use when resume
+ if(wake_mc3xxx_flg==1){
+ wake_mc3xxx_flg=0;
+
+
+ mc3xxx_chip_init(data->client);
+ MC3XXX_ResetCalibration(data->client);
+
+ MC3XXX_WriteCalibration(data->client,l_sensorconfig.offset);
+ /*ret =mcube_read_cali_file(data->client);
+ if(ret !=0)
+ printk("*load_cali %d\n",ret); */
+ }
+#endif
+
+ mc3xxx_read_accel_xyz(data->client, &raw[0]);
+ //printk("%s:%d %d %d\n",__FUNCTION__,raw[0],raw[1],raw[2]);
+ input_report_abs(data->input_dev, ABS_X, raw[0]);
+ input_report_abs(data->input_dev, ABS_Y, raw[1]);
+ input_report_abs(data->input_dev, ABS_Z, raw[2]);
+ input_sync(data->input_dev);
+
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+}
+/*
+//=============================================================================
+static enum hrtimer_restart mc3xxx_timer_func(struct hrtimer *timer)
+{
+ struct mc3xxx_data *data = container_of(timer, struct mc3xxx_data, timer);
+
+ queue_work(data->mc3xxx_wq, &data->work);
+
+ hrtimer_start(&data->timer, ktime_set(0, sensor_duration*1000000), HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+*/
+//MCUBE_BACKUP_FILE
+static void mcube_copy_file(const char *dstFilePath)
+{
+ int err =0;
+ initKernelEnv();
+
+ fd_file = openFile(dstFilePath,O_RDWR,0);
+ if (fd_file == NULL)
+ {
+ GSE_LOG("open %s fail\n",dstFilePath);
+ return;
+ }
+
+ if ((err = writeFile(fd_file,backup_buf,64))>0)
+ GSE_LOG("buf:%s\n",backup_buf);
+ else
+ GSE_LOG("write file error %d\n",err);
+
+ set_fs(oldfs); ;
+ closeFile(fd_file);
+
+}
+//MCUBE_BACKUP_FILE
+
+extern int wmt_setsyspara(char *varname, char *varval);
+static void update_var(void)
+{
+ char varbuf[64];
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ sprintf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ (pCvt->map[MC3XXX_AXIS_X]),
+ (pCvt->sign[MC3XXX_AXIS_X]),
+ (pCvt->map[MC3XXX_AXIS_Y]),
+ (pCvt->sign[MC3XXX_AXIS_Y]),
+ (pCvt->map[MC3XXX_AXIS_Z]),
+ (pCvt->sign[MC3XXX_AXIS_Z]),
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+
+ wmt_setsyspara("wmt.io.mc3230sensor",varbuf);
+}
+
+static long wmt_mc3xxx_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ short enable = 0;
+ short delay = 0;
+ unsigned int temp;
+
+ switch (cmd){
+
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, (short*)arg, sizeof(short)))
+ {
+ errlog("Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor. l_sensorconfig.sensor_samp=%d\n", enable, l_sensorconfig.sensor_samp);
+
+ if (enable != l_sensorconfig.sensor_enable)
+ {
+
+ l_sensorconfig.sensor_enable = enable;
+
+ }
+ } else {
+ errlog("Wrong enable argument!!!\n");
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_APP_SET_DELAY://IOCTL_SENSOR_SET_DELAY_ACCEL:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay,(short*)arg, sizeof(short)))
+ {
+ errlog("Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ dbg("Get delay=%d \n", delay);
+
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ if (delay > 0)
+ {
+ l_sensorconfig.sensor_samp = 1000/delay;
+ } else {
+ errlog("error delay argument(delay=%d)!!!\n",delay);
+ return -EFAULT;
+ }
+
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ temp = MC3230_DRVID;
+ if (copy_to_user((unsigned int*)arg, &temp, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("mc32x0_driver_id:%d\n",temp);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+ if(Sensor_Accuracy &MCUBE_1_5G_8BIT){
+ if(is_mc35xx) //mc3236:8 bit ,+/-2g
+ temp = (8<<8) | 4;
+ else
+ temp = (8<<8) | 3; //mc3230:8 bit ,+/-1.5g
+
+ }
+ if (copy_to_user((unsigned int *)arg, &temp, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",temp);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+
+static long mc3xxx_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ //int intBuf[SENSOR_DATA_SIZE] = { 0 };
+ int ret = 0;
+ float convert_para = 0.0f;
+
+ int prod = -1;
+
+
+#ifdef DOT_CALI
+ void __user *data1 = NULL;
+ char strbuf[256] = { 0 };
+ //int cali[3] = { 0 };
+ SENSOR_DATA sensor_data = { 0 };
+ struct i2c_client *client = container_of(mc3xxx_device.parent, struct i2c_client, dev);
+#endif
+
+ struct mc3xxx_data *data = NULL;
+
+ data = i2c_get_clientdata(client);
+
+ switch (cmd) {
+
+
+/* case IOCTL_SENSOR_SET_DELAY_ACCEL:
+ if(copy_from_user((void *)&sensor_duration, (void __user *) arg, sizeof(short))!=0){
+ printk("copy from error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_GET_DELAY_ACCEL:
+ if(copy_to_user((void __user *) arg, (const void *)&sensor_duration, sizeof(short))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_GET_STATE_ACCEL:
+ if(copy_to_user((void __user *) arg, (const void *)&sensor_state_flag, sizeof(short))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_SET_STATE_ACCEL:
+ if(copy_from_user((void *)&sensor_state_flag, (void __user *) arg, sizeof(short))!=0){
+ printk("copy from error in %s.\n",__func__);
+ }
+
+ break;*/
+ case IOCTL_SENSOR_GET_NAME:
+ if(copy_to_user((void __user *) arg,(const void *)MC3XXX_DISPLAY_NAME, sizeof(MC3XXX_DISPLAY_NAME))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+ case IOCTL_SENSOR_GET_VENDOR:
+ if(copy_to_user((void __user *) arg,(const void *)MC3XXX_DIPLAY_VENDOR, sizeof(MC3XXX_DIPLAY_VENDOR))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+ case IOCTL_SENSOR_GET_CONVERT_PARA:
+ convert_para = MC3XXX_CONVERT_PARAMETER;
+ if(copy_to_user((void __user *) arg,(const void *)&convert_para,sizeof(float))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+#ifdef DOT_CALI
+ case GSENSOR_IOCTL_READ_SENSORDATA:
+ case GSENSOR_IOCTL_READ_RAW_DATA:
+ //case GSENSOR_MCUBE_IOCTL_READ_RBM_DATA:
+ GSE_LOG("fwq GSENSOR_IOCTL_READ_RAW_DATA\n");
+
+ //mutex_lock(&data->lock);
+ MC3XXX_ReadRawData(client, strbuf);
+ //mutex_unlock(&data->lock);
+
+ if (copy_to_user((void __user *) arg, &strbuf, strlen(strbuf)+1))
+ {
+ printk("failed to copy sense data to user space.");
+ return -EFAULT;
+ }
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_SET_CALI:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_CALI!!\n");
+ data1 = (void __user *)arg;
+
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+ if(copy_from_user(&sensor_data, data1, sizeof(sensor_data)))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ else
+ {
+ l_sensorconfig.offset[MC3XXX_AXIS_X] = sensor_data.x;
+ l_sensorconfig.offset[MC3XXX_AXIS_Y] = sensor_data.y;
+ l_sensorconfig.offset[MC3XXX_AXIS_Z] = sensor_data.z;
+ update_var();
+ GSE_LOG("GSENSOR_MCUBE_IOCTL_SET_CALI %d %d %d %d %d %d!!\n", l_sensorconfig.offset[MC3XXX_AXIS_X], l_sensorconfig.offset[MC3XXX_AXIS_Y],l_sensorconfig.offset[MC3XXX_AXIS_Z] ,sensor_data.x, sensor_data.y ,sensor_data.z);
+
+ //mutex_lock(&data->lock);
+ ret = MC3XXX_WriteCalibration(client, l_sensorconfig.offset);
+ //mutex_unlock(&data->lock);
+ }
+ break;
+
+ case GSENSOR_IOCTL_CLR_CALI:
+ GSE_LOG("fwq GSENSOR_IOCTL_CLR_CALI!!\n");
+ //mutex_lock(&data->lock);
+ l_sensorconfig.offset[0] = 0;
+ l_sensorconfig.offset[1] = 0;
+ l_sensorconfig.offset[2] = 0;
+
+ update_var();
+ ret = MC3XXX_ResetCalibration(client);
+ //mutex_unlock(&data->lock);
+ break;
+
+ case GSENSOR_IOCTL_GET_CALI:
+ GSE_LOG("fwq mc3xxx GSENSOR_IOCTL_GET_CALI\n");
+
+ data1 = (unsigned char*)arg;
+
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ if((ret = MC3XXX_ReadCalibration(client,l_sensorconfig.offset)))
+ {
+ GSE_LOG("fwq mc3xxx MC3XXX_ReadCalibration error!!!!\n");
+ break;
+ }
+
+ sensor_data.x = l_sensorconfig.offset[MC3XXX_AXIS_X];
+ sensor_data.y = l_sensorconfig.offset[MC3XXX_AXIS_Y];
+ sensor_data.z = l_sensorconfig.offset[MC3XXX_AXIS_Z];
+
+ if(copy_to_user(data1, &sensor_data, sizeof(sensor_data)))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+
+ case GSENSOR_IOCTL_SET_CALI_MODE:
+ GSE_LOG("fwq mc3xxx GSENSOR_IOCTL_SET_CALI_MODE\n");
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_READ_RBM_DATA:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_READ_RBM_DATA\n");
+ data1 = (void __user *) arg;
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+ MC3XXX_ReadRBMData(client,(char *)&strbuf);
+ if(copy_to_user(data1, &strbuf, strlen(strbuf)+1))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+ case GSENSOR_MCUBE_IOCTL_SET_RBM_MODE:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_RBM_MODE\n");
+ //MCUBE_BACKUP_FILE
+ if(READ_FROM_BACKUP==true)
+ {
+
+ //mcube_copy_file(CALIB_PATH);
+
+ READ_FROM_BACKUP = false;
+ }
+ //MCUBE_BACKUP_FILE
+ //mutex_lock(&data->lock);
+ MC3XXX_rbm(client, 1);
+ //mutex_unlock(&data->lock);
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE\n");
+ //mutex_lock(&data->lock);
+ MC3XXX_rbm(client, 0);
+ //mutex_unlock(&data->lock);
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_REGISTER_MAP:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_REGISTER_MAP\n");
+ MC3XXX_ReadRegMap(client, NULL);
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_READ_PRODUCT_ID:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_READ_PRODUCT_ID\n");
+ data1 = (void __user *) arg;
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (MC3XXX_RETCODE_SUCCESS != (prod = MC3XX0_ValidateSensorIC(s_bPCODE)))
+ GSE_LOG("Not mCube accelerometers!\n");
+
+ if(copy_to_user(data1, &prod, sizeof(prod)))
+ {
+ GSE_LOG("%s: read pcode fail to copy!\n", __func__);
+ return -EFAULT;
+ }
+ break;
+#endif
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int mc3xxx_open(struct inode *inode, struct file *filp)
+{
+ return nonseekable_open(inode, filp);
+}
+
+static int mc3xxx_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int wmt_mc3xxx_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int wmt_mc3xxx_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+//=============================================================================
+static struct file_operations sensor_fops =
+{
+ .owner = THIS_MODULE,
+ .open = mc3xxx_open,
+ .release = mc3xxx_release,
+ .unlocked_ioctl = mc3xxx_ioctl,
+};
+
+static struct file_operations wmt_sensor_fops =
+{
+ .owner = THIS_MODULE,
+ .open = wmt_mc3xxx_open,
+ .release = wmt_mc3xxx_release,
+ .unlocked_ioctl = wmt_mc3xxx_ioctl,
+};
+
+
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ //int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ //unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&l_sensorconfig.lock);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ // should do sth
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ klog("Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ dbg("The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&l_sensorconfig.lock);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+//#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mc3xxx_early_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /*struct mc3xxx_data *data = NULL;
+
+ data = container_of(handler, struct mc3xxx_data, early_suspend);
+
+ hrtimer_cancel(&data->timer);*/
+
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ mc3xxx_set_mode(l_sensorconfig.client,MC3XXX_STANDBY);
+}
+
+//=============================================================================
+static void mc3xxx_early_resume(struct platform_device *pdev)
+{
+ struct mc3xxx_data *data = &l_sensorconfig;
+
+ wake_mc3xxx_flg =1;
+ //data = container_of(handler, struct mc3xxx_data, early_suspend);
+
+ mc3xxx_set_mode(data->client,MC3XXX_WAKE);
+
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+ //hrtimer_start(&data->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+}
+//#endif
+
+//=============================================================================
+static struct miscdevice mc3xxx_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = SENSOR_NAME,
+ .fops = &sensor_fops,
+};
+
+static struct miscdevice mc3xxx_wmt_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &wmt_sensor_fops,
+};
+
+
+
+/*****************************************
+ *** MC3XX0_ValidateSensorIC
+ *****************************************/
+static int MC3XX0_ValidateSensorIC(unsigned char bPCode)
+{
+ unsigned char _baOurSensorList[] = { MC3XXX_PCODE_3210 , MC3XXX_PCODE_3230 ,
+ MC3XXX_PCODE_3250 ,
+ MC3XXX_PCODE_3410 , MC3XXX_PCODE_3430 ,
+ MC3XXX_PCODE_3410N, MC3XXX_PCODE_3430N,
+ MC3XXX_PCODE_3510B, MC3XXX_PCODE_3530B,
+ MC3XXX_PCODE_3510C, MC3XXX_PCODE_3530C
+ };
+
+ int _nSensorCount = (sizeof(_baOurSensorList) / sizeof(_baOurSensorList[0]));
+ int _nCheckIndex = 0;
+
+ GSE_LOG("[%s] code to be verified: 0x%X, _nSensorCount: %d\n", __FUNCTION__, bPCode, _nSensorCount);
+
+ for (_nCheckIndex = 0; _nCheckIndex < _nSensorCount; _nCheckIndex++)
+ {
+ if (_baOurSensorList[_nCheckIndex] == bPCode)
+ return (MC3XXX_RETCODE_SUCCESS);
+ }
+
+ if (MC3XXX_PCODE_3530C == (bPCode | 0x0E))
+ return (MC3XXX_RETCODE_SUCCESS);
+
+ return (MC3XXX_RETCODE_ERROR_IDENTIFICATION);
+}
+
+/*****************************************
+ *** _mc3xxx_i2c_auto_probe
+ *****************************************/
+static int _mc3xxx_i2c_auto_probe(struct i2c_client *client)
+{
+ unsigned char _baDataBuf[2] = {0};
+ int _nProbeAddrCount = (sizeof(mc3xxx_i2c_auto_probe_addr) / sizeof(mc3xxx_i2c_auto_probe_addr[0]));
+ int _nCount = 0;
+ int _nCheckCount = 0;
+
+ //GSE_FUN();
+
+ s_bPCODE = 0x00;
+
+ for (_nCount = 0; _nCount < _nProbeAddrCount; _nCount++)
+ {
+ _nCheckCount = 0;
+ client->addr = mc3xxx_i2c_auto_probe_addr[_nCount];
+
+ //GSE_LOG("[%s] probing addr: 0x%X\n", __FUNCTION__, client->addr);
+
+_I2C_AUTO_PROBE_RECHECK_:
+ _baDataBuf[0] = MC3XXX_REG_PRODUCT_CODE;
+ if (0 > i2c_master_send(client, &(_baDataBuf[0]), 1))
+ {
+ //GSE_ERR("ERR: addr: 0x%X fail to communicate-2!\n", client->addr);
+ continue;
+ }
+
+ if (0 > i2c_master_recv(client, &(_baDataBuf[0]), 1))
+ {
+ //GSE_ERR("ERR: addr: 0x%X fail to communicate-3!\n", client->addr);
+ continue;
+ }
+
+ _nCheckCount++;
+
+ //GSE_LOG("[%s][%d] addr: 0x%X ok to read REG(0x3B): 0x%X\n", __FUNCTION__, _nCheckCount, client->addr, _baDataBuf[0]);
+
+ if (0x00 == _baDataBuf[0])
+ {
+ if (1 == _nCheckCount)
+ {
+ MC3XXX_Reset(client);
+ goto _I2C_AUTO_PROBE_RECHECK_;
+ }
+ }
+
+ if (MC3XXX_RETCODE_SUCCESS == MC3XX0_ValidateSensorIC(_baDataBuf[0]))
+ {
+ //GSE_LOG("[%s] addr: 0x%X confirmed ok to use.\n", __FUNCTION__, client->addr);
+
+ s_bPCODE = _baDataBuf[0];
+
+ return (MC3XXX_RETCODE_SUCCESS);
+ }
+ }
+
+ return (MC3XXX_RETCODE_ERROR_I2C);
+}
+
+
+//=============================================================================
+//static int mc3xxx_probe(struct i2c_client *client,
+// const struct i2c_device_id *id)
+static int mc3xxx_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ //int product_code = 0;
+ struct mc3xxx_data *data = &l_sensorconfig;
+ struct i2c_client *client = l_sensorconfig.client;
+
+ #ifdef DOT_CALI
+ load_cali_flg = 30;
+ #endif
+/*
+ if (MC3XXX_RETCODE_SUCCESS != _mc3xxx_i2c_auto_probe(client))
+ {
+ GSE_ERR("ERR: fail to probe mCube sensor!\n");
+ goto err_check_functionality_failed;
+ }
+
+ data = kzalloc(sizeof(struct mc3xxx_data), GFP_KERNEL);
+ if(data == NULL)
+ {
+ ret = -ENOMEM;
+ goto err_alloc_data_failed;
+ }
+*/
+ data->sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (data->sensor_proc != NULL)
+ {
+ data->sensor_proc->write_proc = sensor_writeproc;
+ data->sensor_proc->read_proc = sensor_readproc;
+ }
+
+ data->mc3xxx_wq = create_singlethread_workqueue("mc3xxx_wq");
+ if (!data->mc3xxx_wq )
+ {
+ ret = -ENOMEM;
+ goto err_create_workqueue_failed;
+ }
+ INIT_DELAYED_WORK(&data->work, mc3xxx_work_func);
+ mutex_init(&data->lock);
+
+ //sensor_duration = SENSOR_DURATION_DEFAULT;
+ //sensor_state_flag = 1;
+
+
+ data->client = client;
+ dev.client=client;
+
+ i2c_set_clientdata(client, data);
+
+ data->input_dev = input_allocate_device();
+ if (!data->input_dev) {
+ ret = -ENOMEM;
+ goto exit_input_dev_alloc_failed;
+ }
+
+ #ifdef DOT_CALI
+ MC3XXX_Reset(client);
+ #endif
+
+ ret = mc3xxx_chip_init(client);
+ if (ret < 0) {
+ goto err_chip_init_failed;
+ }
+
+ set_bit(EV_ABS, data->input_dev->evbit);
+ data->map[0] = G_0;
+ data->map[1] = G_1;
+ data->map[2] = G_2;
+ data->inv[0] = G_0_REVERSE;
+ data->inv[1] = G_1_REVERSE;
+ data->inv[2] = G_2_REVERSE;
+
+ input_set_abs_params(data->input_dev, ABS_X, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(data->input_dev, ABS_Y, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(data->input_dev, ABS_Z, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+
+ data->input_dev->name = "g-sensor";
+
+ ret = input_register_device(data->input_dev);
+ if (ret) {
+ goto exit_input_register_device_failed;
+ }
+
+ mc3xxx_device.parent = &client->dev;
+
+ ret = misc_register(&mc3xxx_device);
+ if (ret) {
+ goto exit_misc_device_register_failed;
+ }
+
+ ret = misc_register(&mc3xxx_wmt_device);
+ if (ret) {
+ goto exit_misc_device_register_failed;
+ }
+
+ ret = sysfs_create_group(&data->input_dev->dev.kobj, &mc3xxx_group);
+/*
+ if (!data->use_irq){
+ hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ data->timer.function = mc3xxx_timer_func;
+ //hrtimer_start(&data->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+*/
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.suspend = mc3xxx_early_suspend;
+ data->early_suspend.resume = mc3xxx_early_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+ data->enabled = 1;
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+ //strcpy(mc3xxx_on_off_str,"gsensor_int2");
+ //gpio_set_one_pin_io_status(mc3xxx_pin_hd,0,mc3xxx_on_off_str);
+
+ printk("mc3xxx probe ok \n");
+
+ return 0;
+exit_misc_device_register_failed:
+exit_input_register_device_failed:
+ input_free_device(data->input_dev);
+err_chip_init_failed:
+exit_input_dev_alloc_failed:
+ destroy_workqueue(data->mc3xxx_wq);
+err_create_workqueue_failed:
+ kfree(data);
+//err_alloc_data_failed:
+//err_check_functionality_failed:
+ printk("mc3xxx probe failed \n");
+ return ret;
+
+}
+
+//static int mc3xxx_remove(struct i2c_client *client)
+static int mc3xxx_remove(struct platform_device *pdev)
+{
+ /*struct mc3xxx_data *data = i2c_get_clientdata(client);
+
+ hrtimer_cancel(&data->timer);
+ input_unregister_device(data->input_dev);
+// gpio_release(mc3xxx_pin_hd, 2);
+ misc_deregister(&mc3xxx_device);
+ sysfs_remove_group(&data->input_dev->dev.kobj, &mc3xxx_group);
+ kfree(data);
+ return 0;*/
+
+ if (NULL != l_sensorconfig.mc3xxx_wq)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.mc3xxx_wq);
+ destroy_workqueue(l_sensorconfig.mc3xxx_wq);
+ l_sensorconfig.mc3xxx_wq = NULL;
+ }
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ misc_deregister(&mc3xxx_device);
+ misc_deregister(&mc3xxx_wmt_device);
+ sysfs_remove_group(&l_sensorconfig.input_dev->dev.kobj, &mc3xxx_group);
+ input_unregister_device(l_sensorconfig.input_dev);
+ return 0;
+}
+
+//=============================================================================
+/*
+static void mc3xxx_shutdown(struct i2c_client *client)
+{
+ struct mc3xxx_data *data = i2c_get_clientdata(client);
+
+ if(data->enabled)
+ mc3xxx_enable(data, 0);
+}
+*/
+
+//=============================================================================
+
+static const struct i2c_device_id mc3xxx_id[] =
+{
+ { SENSOR_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, mc3xxx_id);
+/*
+static struct i2c_driver mc3xxx_driver =
+{
+ .class = I2C_CLASS_HWMON,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ },
+ .id_table = mc3xxx_id,
+ .probe = mc3xxx_probe,
+ .remove = mc3xxx_remove,
+ //.shutdown = mc3xxx_shutdown,
+};
+*/
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+ //int tmpoff[3] = {0};
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ pCvt = (struct mc3xx0_hwmsen_convert *)kzalloc(sizeof(struct mc3xx0_hwmsen_convert), GFP_KERNEL);
+
+ if (wmt_getsyspara("wmt.io.mc3230.virtualz", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ //return -1;
+ } else {
+ sscanf(varbuf, "%d", &g_virtual_z);
+
+ }
+ printk("%s g_virtual_z %d\n", __FUNCTION__, g_virtual_z);
+ memset(varbuf, 0, sizeof(varbuf));
+ if (wmt_getsyspara("wmt.io.mc3230sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1; //open it for no env just,not insmod such module 2014-6-30
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(pCvt->map[MC3XXX_AXIS_X]),
+ &(pCvt->sign[MC3XXX_AXIS_X]),
+ &(pCvt->map[MC3XXX_AXIS_Y]),
+ &(pCvt->sign[MC3XXX_AXIS_Y]),
+ &(pCvt->map[MC3XXX_AXIS_Z]),
+ &(pCvt->sign[MC3XXX_AXIS_Z]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2])
+ );
+ if (n != 12) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ pCvt->map[MC3XXX_AXIS_X],
+ pCvt->sign[MC3XXX_AXIS_X],
+ pCvt->map[MC3XXX_AXIS_Y],
+ pCvt->sign[MC3XXX_AXIS_Y],
+ pCvt->map[MC3XXX_AXIS_Z],
+ pCvt->sign[MC3XXX_AXIS_Z],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static void mc3xxx_platform_release(struct device *device)
+{
+ return;
+}
+
+
+static struct platform_device mc3xxx_pdevice = {
+ .name = SENSOR_NAME,
+ .id = 0,
+ .dev = {
+ .release = mc3xxx_platform_release,
+ },
+};
+
+static struct platform_driver mc3xxx_pdriver = {
+ .probe = mc3xxx_probe,
+ .remove = mc3xxx_remove,
+ .suspend = mc3xxx_early_suspend,
+ .resume = mc3xxx_early_resume,
+ //.shutdown = mc3xxx_shutdown,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+
+static int __init mc3xxx_init(void)
+{
+ int ret = -1;
+ struct i2c_client *this_client;
+ printk("mc3xxx: init\n");
+
+ //ret = i2c_add_driver(&mc3xxx_driver);
+
+ // parse g-sensor u-boot arg
+ ret = get_axisset();
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+
+ if (!(this_client = sensor_i2c_register_device(0, mc3xxx_i2c_auto_probe_addr[0], SENSOR_NAME)))
+ {
+ printk(KERN_ERR"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+ if (MC3XXX_RETCODE_SUCCESS != _mc3xxx_i2c_auto_probe(this_client))
+ {
+ GSE_ERR("ERR: fail to auto_probe mCube sensor!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+
+ l_sensorconfig.client = this_client;
+
+ l_dev_class = class_create(THIS_MODULE, SENSOR_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&mc3xxx_pdevice)))
+ {
+ klog("Can't register mc3xxx platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&mc3xxx_pdriver)) != 0)
+ {
+ errlog("Can't register mc3xxx platform driver!!!\n");
+ return ret;
+ }
+
+
+ return ret;
+}
+
+static void __exit mc3xxx_exit(void)
+{
+ //i2c_del_driver(&mc3xxx_driver);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&l_sensorconfig.earlysuspend);
+#endif
+ platform_driver_unregister(&mc3xxx_pdriver);
+ platform_device_unregister(&mc3xxx_pdevice);
+ sensor_i2c_unregister_device(l_sensorconfig.client);
+ class_destroy(l_dev_class);
+}
+
+//=============================================================================
+module_init(mc3xxx_init);
+module_exit(mc3xxx_exit);
+
+MODULE_DESCRIPTION("mc3xxx accelerometer driver");
+MODULE_AUTHOR("mCube-inc");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SENSOR_DRIVER_VERSION);
+