From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- drivers/input/sensor/mma7660_gsensor/Makefile | 34 + drivers/input/sensor/mma7660_gsensor/mma7660.c | 1052 ++++++++++++++++++++++++ drivers/input/sensor/mma7660_gsensor/mma7660.h | 106 +++ 3 files changed, 1192 insertions(+) create mode 100755 drivers/input/sensor/mma7660_gsensor/Makefile create mode 100755 drivers/input/sensor/mma7660_gsensor/mma7660.c create mode 100755 drivers/input/sensor/mma7660_gsensor/mma7660.h (limited to 'drivers/input/sensor/mma7660_gsensor') diff --git a/drivers/input/sensor/mma7660_gsensor/Makefile b/drivers/input/sensor/mma7660_gsensor/Makefile new file mode 100755 index 00000000..99ecc6a1 --- /dev/null +++ b/drivers/input/sensor/mma7660_gsensor/Makefile @@ -0,0 +1,34 @@ +KERNELDIR=../../../../ +#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8 +CROSS = arm_1103_le- +CC= $(CROSS)gcc +LD= $(CROSS)ld +STRIP = $(CROSS)strip + +DEBUG = n + +# Add your debugging flag (or not) to EXTRA_CFLAGS +ifeq ($(DEBUG),y) +# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines +DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines + +else + DEBFLAGS = -O2 -Wall +endif + +EXTRA_CFLAGS += $(DEBFLAGS) + + +MY_MODULE_NAME=s_wmt_gsensor_mma7660 + +obj-m := $(MY_MODULE_NAME).o +$(MY_MODULE_NAME)-objs := mma7660.o + +default: + $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules + $(STRIP) --strip-debug $(MY_MODULE_NAME).ko + rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions + +clean: + rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers + diff --git a/drivers/input/sensor/mma7660_gsensor/mma7660.c b/drivers/input/sensor/mma7660_gsensor/mma7660.c new file mode 100755 index 00000000..f0a0b1ee --- /dev/null +++ b/drivers/input/sensor/mma7660_gsensor/mma7660.c @@ -0,0 +1,1052 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mma7660.h" + + +//#define DEBUG 1 + +#undef dbg + +//#if 0 + #define dbg(fmt, args...) if (l_sensorconfig.isdbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args) + //#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args) + +#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args) + + //#define dbg(format, arg...) printk(KERN_ALERT format, ## arg) + + +//#else +// #define dbg(format, arg...) +//#endif + +/////////////////////Macro constant +#define SENSOR_POLL_WAIT_TIME 1837 +#define MAX_FAILURE_COUNT 10 +#define MMA7660_ADDR 0x4C +#define LAND_PORT_MASK 0x1C +#define LAND_LEFT 0x1 +#define LAND_RIGHT 0x2 +#define PORT_INVERT 0x5 +#define PORT_NORMAL 0x6 + +#define LANDSCAPE_LOCATION 0 +#define PORTRAIT_LOCATION 1 + +#define SENSOR_UI_MODE 0 +#define SENSOR_GRAVITYGAME_MODE 1 + +#define UI_SAMPLE_RATE 0xFC + +#define GSENSOR_PROC_NAME "gsensor_config" +#define GSENSOR_MAJOR 161 +#define GSENSOR_NAME "mma7660" +#define GSENSOR_DRIVER_NAME "mma7660_drv" + + +#define sin30_1000 500 +#define cos30_1000 866 + +#define DISABLE 0 +#define ENABLE 1 + +////////////////////////the rate of g-sensor///////////////////////////////////////////// +#define SENSOR_DELAY_FASTEST 0 +#define SENSOR_DELAY_GAME 20 +#define SENSOR_DELAY_UI 60 +#define SENSOR_DELAY_NORMAL 200 + +#define FASTEST_MMA_AMSR 0 // 120 samples/sec +#define GAME_MMA_AMSR 1 // 1, (64, samples/sec) +#define UI_MMA_AMSR 3 // 2, 3,4, (16, 8,32 samples/sec) +#define NORMAL_MMA_AMSR 5 // 5, 6, 7 (4, 2, 1 samples/sec) + +///////////////////////////////////////////////////////////////////////// +static int xyz_g_table[64] = { +0,47,94,141,188,234,281,328, +375,422,469,516,563,609,656,703, +750,797,844,891,938,984,1031,1078, +1125,1172,1219,1266,1313,1359,1406,1453, +-1500,-1453,-1406,-1359,-1313,-1266,-1219,-1172, +-1125,-1078,-1031,-984,-938,-891,-844,-797, +-750,-703,-656,-609,-563,-516,-469,-422, +-375,-328,-281,-234,-188,-141,-94,-47 +}; + +static struct platform_device *this_pdev; + +static struct class* l_dev_class = NULL; +static struct device *l_clsdevice = NULL; + + + +struct mma7660_config +{ + int op; + int int_gpio; //0-3 + int xyz_axis[3][2]; // (axis,direction) + int rxyz_axis[3][2]; + int irq; + struct proc_dir_entry* sensor_proc; + int sensorlevel; + int shake_enable; // 1--enable shake, 0--disable shake + int manual_rotation; // 0--landance, 90--vertical + struct input_dev *input_dev; + //struct work_struct work; + struct delayed_work work; // for polling + struct workqueue_struct *queue; + int isdbg; // 0-- no debug log, 1--show debug log + int sensor_samp; // 1,2,4,8,16,32,64,120 + int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor + int test_pass; + spinlock_t spinlock; + int pollcnt; // the counts of polling + int offset[3]; +}; + +static struct mma7660_config l_sensorconfig = { + .op = 0, + .int_gpio = 3, + .xyz_axis = { + {ABS_X, -1}, + {ABS_Y, 1}, + {ABS_Z, -1}, + }, + .irq = 6, + .int_gpio = 3, + .sensor_proc = NULL, + .sensorlevel = SENSOR_GRAVITYGAME_MODE, + .shake_enable = 0, // default enable shake + .isdbg = 0, + .sensor_samp = 10, // 4sample/second + .sensor_enable = 1, // enable sensor + .test_pass = 0, // for test program + .pollcnt = 0, // Don't report the x,y,z when the driver is loaded until 2~3 seconds + .offset = {0,0,0}, +}; + + +static struct timer_list l_polltimer; // for shaking +static int is_sensor_good = 0; // 1-- work well, 0 -- exception +struct work_struct poll_work; +static struct mutex sense_data_mutex; +static int revision = -1; +static int l_resumed = 0; // 1: suspend --> resume;2: suspend but not resumed; other values have no meaning + +//////////////////Macro function////////////////////////////////////////////////////// + +#define SET_MMA_SAMPLE(buf,samp) { \ + buf[0] = 0; \ + sensor_i2c_write(MMA7660_ADDR,7,buf,1); \ + buf[0] = samp; \ + sensor_i2c_write(MMA7660_ADDR,8,buf,1); \ + buf[0] = 0x01; \ + sensor_i2c_write(MMA7660_ADDR,7,buf,1); \ +} + +////////////////////////Function define///////////////////////////////////////////////////////// + +static unsigned int mma_sample2AMSR(unsigned int samp); + +////////////////////////Function implement///////////////////////////////////////////////// +// rate: 1,2,4,8,16,32,64,120 +static unsigned int sample_rate_2_memsec(unsigned int rate) +{ + return (1000/rate); +} + + + +static ssize_t gsensor_vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + sprintf(buf, "MMA7660_%#x\n", revision); + ret = strlen(buf) + 1; + + return ret; +} + +static DEVICE_ATTR(vendor, 0444, gsensor_vendor_show, NULL); + +static struct kobject *android_gsensor_kobj; +static int gsensor_sysfs_init(void) +{ + int ret ; + + android_gsensor_kobj = kobject_create_and_add("android_gsensor", NULL); + if (android_gsensor_kobj == NULL) { + printk(KERN_ERR + "mma7660 gsensor_sysfs_init:"\ + "subsystem_register failed\n"); + ret = -ENOMEM; + goto err; + } + + ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr); + if (ret) { + printk(KERN_ERR + "mma7660 gsensor_sysfs_init:"\ + "sysfs_create_group failed\n"); + goto err4; + } + + return 0 ; +err4: + kobject_del(android_gsensor_kobj); +err: + return ret ; +} + +static int gsensor_sysfs_exit(void) +{ + sysfs_remove_file(android_gsensor_kobj, &dev_attr_vendor.attr); + kobject_del(android_gsensor_kobj); + return 0; +} + +//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num, int bus_id); +extern int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size); +extern int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size); + +int sensor_i2c_write(unsigned int addr,unsigned int index,char *pdata,int len) +{ + /*struct i2c_msg msg[1]; + unsigned char buf[len+1]; + + //addr = (addr >> 1); + buf[0] = index; + memcpy(&buf[1],pdata,len); + msg[0].addr = addr; + msg[0].flags = 0 ; + msg[0].flags &= ~(I2C_M_RD); + msg[0].len = len+1; + msg[0].buf = buf; +//tmp sensor_i2c_do_xfer(msg,1); + if (wmt_i2c_xfer_continue_if_4(msg,1,0) <= 0) + { + klog("write error!\n"); + return -1; + }*/ + int ret; + ret = i2c_api_do_send(0, addr, index, pdata, len); + if (ret <= 0) { + klog("i2c_api_do_send error!\n"); + return -1; + } + +#ifdef DEBUG +{ + int i; + + printk("sensor_i2c_write(addr 0x%x,index 0x%x,len %d\n",addr,index,len); + for(i=0;i> 1); + memset(buf,0x55,len+1); + buf[0] = index; + buf[1] = 0x0; + + msg[0].addr = addr; + msg[0].flags = 0 ; + msg[0].flags &= ~(I2C_M_RD); + msg[0].len = 1; + msg[0].buf = buf; + + msg[1].addr = addr; + msg[1].flags = 0 ; + msg[1].flags |= (I2C_M_RD); + msg[1].len = len; + msg[1].buf = buf; + + //tmp sensor_i2c_do_xfer(msg, 2); + ret = wmt_i2c_xfer_continue_if_4(msg, 2,0); + if (ret < 0) + { + klog("read error!\n"); + return ret; + } + + memcpy(pdata,buf,len);*/ + int ret; + ret = i2c_api_do_recv(0, addr, index, pdata, len); + if (ret <= 0) { + klog("i2c_api_do_recv error!\n"); + return -1; + } +#ifdef DEBUG +{ + int i; + + printk("sensor_i2c_read(addr 0x%x,index 0x%x,len %d\n",addr,index,len); + for(i=0;i= 120) + { + return 0; + } + while (samp) + { + samp = samp >> 1; + i++; + } + amsr = 8 - i; + return amsr; +} + +static int mma_enable_disable(int enable) +{ + char buf[1]; + + // disable all interrupt of g-sensor + memset(buf, 0, sizeof(buf)); + if ((enable < 0) || (enable > 1)) + { + return -1; + } + buf[0] = 0; + sensor_i2c_write(MMA7660_ADDR,7,buf,1); + if (enable != 0) + { + buf[0] = (1 == l_sensorconfig.shake_enable) ? 0xF0:0x10; + } else { + buf[0] = 0; + } + sensor_i2c_write(MMA7660_ADDR,6,buf,1); + buf[0] = 0xf9; + sensor_i2c_write(MMA7660_ADDR,7,buf,1); + return 0; +} + +// To contol the g-sensor for UI +static int mmad_open(struct inode *inode, struct file *file) +{ + dbg("Open the g-sensor node...\n"); + return 0; +} + +static int mmad_release(struct inode *inode, struct file *file) +{ + dbg("Close the g-sensor node...\n"); + return 0; +} + +static /*int*/ long +mmad_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + char rwbuf[5]; + short delay, enable; //amsr = -1; + unsigned int uval = 0; + int i = 0; + unsigned char rxData[3] = {0}; + int intBuf[3] = {0}; + dbg("g-sensor ioctr...\n"); + memset(rwbuf, 0, sizeof(rwbuf)); + switch (cmd) { + case ECS_IOCTL_APP_SET_DELAY: + // set the rate of g-sensor + if (copy_from_user(&delay, argp, sizeof(short))) + { + printk(KERN_ALERT "Can't get set delay!!!\n"); + return -EFAULT; + } + klog("Get delay=%d\n", delay); + //klog("before change sensor sample:%d...\n", l_sensorconfig.sensor_samp); + if ((delay >=0) && (delay < 20)) + { + delay = 20; + } else if (delay > 200) + { + delay = 200; + } + l_sensorconfig.sensor_samp = 1000/delay; + + break; + case ECS_IOCTL_APP_SET_AFLAG: + // enable/disable sensor + if (copy_from_user(&enable, argp, sizeof(short))) + { + printk(KERN_ERR "Can't get enable flag!!!\n"); + return -EFAULT; + } + klog("enable=%d\n",enable); + if ((enable >=0) && (enable <=1)) + { + dbg("driver: disable/enable(%d) gsensor.\n", enable); + + l_sensorconfig.sensor_enable = enable; + + } else { + printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__); + return -EINVAL; + } + break; + case WMT_IOCTL_SENSOR_GET_DRVID: + uval = MMA7660_DRVID; + if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int))) + { + return -EFAULT; + } + dbg("mma7660_driver_id:%d\n",uval); + break; + case ECS_IOCTL_APP_READ_XYZ: + sensor_i2c_read(MMA7660_ADDR,0,rxData,3); + + for (i=0; i < 3; i++) + { + if (rxData[i]&0x40) break; + } + //if (l_sensorconfig.pollcnt >= 20) + if (3 == i) + { + intBuf[0] = xyz_g_table[rxData[l_sensorconfig.xyz_axis[0][0]]]*l_sensorconfig.xyz_axis[0][1]; + intBuf[1] = xyz_g_table[rxData[l_sensorconfig.xyz_axis[1][0]]]*l_sensorconfig.xyz_axis[1][1]; + intBuf[2] = xyz_g_table[rxData[l_sensorconfig.xyz_axis[2][0]]]*l_sensorconfig.xyz_axis[2][1]; + + if (copy_to_user((unsigned int*)arg, intBuf, sizeof(intBuf))) + { + return -EFAULT; + } + } + break; + } + + + + return 0; +} + + +static void mma_work_func(struct work_struct *work) +{ + struct mma7660_config *data; + unsigned char rxData[3]; + //unsigned char tiltval = 0; + int i = 0; + int x,y,z; + + dbg("enter...\n"); + data = dev_get_drvdata(&this_pdev->dev); + if (!l_sensorconfig.sensor_enable) + { + queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp))); + return; + } + mutex_lock(&sense_data_mutex); + is_sensor_good = 1; // for watchdog + l_sensorconfig.test_pass = 1; // for testing + + /*sensor_i2c_read(MMA7660_ADDR,3,rxData,1); + tiltval = rxData[0]; + if (tiltval & 0x80) { + if (1 == l_sensorconfig.shake_enable) { + printk(KERN_NOTICE "shake!!!\n"); + input_report_key(data->input_dev, KEY_NEXTSONG, 1); + input_report_key(data->input_dev, KEY_NEXTSONG, 0); + input_sync(data->input_dev); + + } + } else*/ { + sensor_i2c_read(MMA7660_ADDR,0,rxData,3); + /* dbg(KERN_DEBUG "Angle: x=%d, y=%d, z=%d\n", + xy_degree_table[rxData[0]], + xy_degree_table[rxData[1]], + z_degree_table[rxData[2]]); + dbg(KERN_DEBUG "G value: x=%d, y=%d, z=%d\n", + xyz_g_table[rxData[0]], + xyz_g_table[rxData[1]], + xyz_g_table[rxData[2]]); + */ + for (i=0; i < 3; i++) + { + if (rxData[i]&0x40) break; + } + //if (l_sensorconfig.pollcnt >= 20) + if (3 == i) + { + x = xyz_g_table[rxData[l_sensorconfig.xyz_axis[0][0]]]*l_sensorconfig.xyz_axis[0][1]; + y = xyz_g_table[rxData[l_sensorconfig.xyz_axis[1][0]]]*l_sensorconfig.xyz_axis[1][1]; + z = xyz_g_table[rxData[l_sensorconfig.xyz_axis[2][0]]]*l_sensorconfig.xyz_axis[2][1]; + input_report_abs(data->input_dev, ABS_X, x); + input_report_abs(data->input_dev, ABS_Y, y); + input_report_abs(data->input_dev, ABS_Z, z); + input_sync(data->input_dev); + dbg("gx=%x,gy=%x,gz=%x\n",x,y,z); + } + } + //gsensor_int_ctrl(ENABLE); + mutex_unlock(&sense_data_mutex); + queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp))); +} + +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(&sense_data_mutex); + // disable int + //gsensor_int_ctrl(DISABLE); + memset(tembuf, 0, sizeof(tembuf)); + // get sensor level and set sensor level + if (sscanf(buffer, "level=%d\n", &l_sensorconfig.sensorlevel)) + { + } else if (sscanf(buffer, "shakenable=%d\n", &l_sensorconfig.shake_enable)) + { + /* + regval[0] = 0; + sensor_i2c_write(MMA7660_ADDR,7,regval,1); // standard mode + sensor_i2c_read(MMA7660_ADDR,6,regval,1); + switch (l_sensorconfig.shake_enable) + { + case 0: // disable shake + regval[0] &= 0x1F; + sensor_i2c_write(MMA7660_ADDR,6, regval,1); + dbg("Shake disable!!\n"); + break; + case 1: // enable shake + regval[0] |= 0xE0; + sensor_i2c_write(MMA7660_ADDR,6, regval,1); + dbg("Shake enable!!\n"); + break; + }; + sensor_i2c_write(MMA7660_ADDR,7,&oldval,1); + */ + } /*else if (sscanf(buffer, "rotation=%d\n", &l_sensorconfig.manual_rotation)) + { + switch (l_sensorconfig.manual_rotation) + { + case 90: + // portrait + input_report_abs(mma7660data->input_dev, ABS_X, cos30_1000); + input_report_abs(mma7660data->input_dev, ABS_Y, 0); + input_report_abs(mma7660data->input_dev, ABS_Z, sin30_1000); + input_sync(mma7660data->input_dev); + break; + case 0: + // landscape + input_report_abs(mma7660data->input_dev, ABS_X, 0); + input_report_abs(mma7660data->input_dev, ABS_Y, cos30_1000); + input_report_abs(mma7660data->input_dev, ABS_Z, sin30_1000); + input_sync(mma7660data->input_dev); + break; + }; + }*/ else if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg)) + { + // only set the dbg flag + } else if (sscanf(buffer, "init=%d\n", &inputval)) + { + mma7660_chip_init(); + dbg("Has reinit sensor !!!\n"); + } else if (sscanf(buffer, "samp=%d\n", &sample)) + { + if (sample > 0) + { + if (sample != l_sensorconfig.sensor_samp) + { + amsr = mma_sample2AMSR(sample); + SET_MMA_SAMPLE(tembuf, amsr); + klog("sample:%d ,amsr:%d \n", sample, amsr); + l_sensorconfig.sensor_samp = sample; + } + printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr); + } else { + printk(KERN_ALERT "Wrong sample argumnet of sensor.\n"); + } + } else if (sscanf(buffer, "enable=%d\n", &enable)) + { + if ((enable < 0) || (enable > 1)) + { + printk(KERN_ERR "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(&sense_data_mutex); + 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; +} + + + +static int mma7660_init_client(struct platform_device *pdev) +{ + struct mma7660_config *data; +// int ret; + + data = dev_get_drvdata(&pdev->dev); + mutex_init(&sense_data_mutex); + /*Only for polling, not interrupt*/ + l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/); + if (l_sensorconfig.sensor_proc != NULL) + { + l_sensorconfig.sensor_proc->write_proc = sensor_writeproc; + l_sensorconfig.sensor_proc->read_proc = sensor_readproc; + } + + + return 0; + +//err: +// return ret; +} + +static struct file_operations mmad_fops = { + .owner = THIS_MODULE, + .open = mmad_open, + .release = mmad_release, + .unlocked_ioctl = mmad_ioctl, +}; + + +static struct miscdevice mmad_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "sensor_ctrl", + .fops = &mmad_fops, +}; + +static int mma7660_probe( + struct platform_device *pdev) +{ + int err; + + this_pdev = pdev; + l_sensorconfig.queue = create_singlethread_workqueue("sensor-intterupt-handle"); + INIT_DELAYED_WORK(&l_sensorconfig.work, mma_work_func); + + l_sensorconfig.input_dev = input_allocate_device(); + if (!l_sensorconfig.input_dev) { + err = -ENOMEM; + printk(KERN_ERR + "mma7660_probe: Failed to allocate input device\n"); + goto exit_input_dev_alloc_failed; + } + l_sensorconfig.input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY); + set_bit(KEY_NEXTSONG, l_sensorconfig.input_dev->keybit); + + /* x-axis acceleration */ + input_set_abs_params(l_sensorconfig.input_dev, ABS_X, -65532, 65532, 0, 0); + /* y-axis acceleration */ + input_set_abs_params(l_sensorconfig.input_dev, ABS_Y, -65532, 65532, 0, 0); + /* z-axis acceleration */ + input_set_abs_params(l_sensorconfig.input_dev, ABS_Z, -65532, 65532, 0, 0); + + l_sensorconfig.input_dev->name = "g-sensor"; + + err = input_register_device(l_sensorconfig.input_dev); + + if (err) { + printk(KERN_ERR + "mma7660_probe: Unable to register input device: %s\n", + l_sensorconfig.input_dev->name); + goto exit_input_register_device_failed; + } + + err = misc_register(&mmad_device); + if (err) { + printk(KERN_ERR + "mma7660_probe: mmad_device register failed\n"); + goto exit_misc_device_register_failed; + } + + dev_set_drvdata(&pdev->dev, &l_sensorconfig); + mma7660_chip_init(); + mma7660_init_client(pdev); + gsensor_sysfs_init(); + + // satrt the polling work + l_sensorconfig.sensor_samp = 10; + queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp))); + return 0; + +exit_misc_device_register_failed: +exit_input_register_device_failed: + input_free_device(l_sensorconfig.input_dev); +//exit_alloc_data_failed: +exit_input_dev_alloc_failed: +//exit_check_functionality_failed: + return err; +} + +static int mma7660_remove(struct platform_device *pdev) +{ + if (NULL != l_sensorconfig.queue) + { + cancel_delayed_work_sync(&l_sensorconfig.work); + flush_workqueue(l_sensorconfig.queue); + destroy_workqueue(l_sensorconfig.queue); + l_sensorconfig.queue = NULL; + } + gsensor_sysfs_exit(); + misc_deregister(&mmad_device); + input_unregister_device(l_sensorconfig.input_dev); + if (l_sensorconfig.sensor_proc != NULL) + { + remove_proc_entry(GSENSOR_PROC_NAME, NULL); + l_sensorconfig.sensor_proc = NULL; + } + //free_irq(l_sensorconfig.irq, &l_sensorconfig); + return 0; +} + +static int mma7660_suspend(struct platform_device *pdev, pm_message_t state) +{ + //gsensor_int_ctrl(DISABLE); + cancel_delayed_work_sync(&l_sensorconfig.work); + del_timer(&l_polltimer); + dbg("...ok\n"); + //l_resumed = 2; + + return 0; +} + +static int mma7660_resume(struct platform_device *pdev) +{ + + //mma7660_chip_init(); + //gsensor_int_ctrl(ENABLE); + //mma_enable_disable(1); + l_resumed = 1; + mod_timer(&l_polltimer, jiffies + msecs_to_jiffies(SENSOR_POLL_WAIT_TIME)); + dbg("...ok\n"); + + return 0; +} + +static void mma7660_platform_release(struct device *device) +{ + return; +} + +static void mma7660_shutdown(struct platform_device *pdev) +{ + + flush_delayed_work_sync(&l_sensorconfig.work); + cancel_delayed_work_sync(&l_sensorconfig.work); + +} + +static struct platform_device mma7660_device = { + .name = "mma7660", + .id = 0, + .dev = { + .release = mma7660_platform_release, + }, +}; + +static struct platform_driver mma7660_driver = { + .probe = mma7660_probe, + .remove = mma7660_remove, + .suspend = mma7660_suspend, + .resume = mma7660_resume, + .shutdown = mma7660_shutdown, + .driver = { + .name = "mma7660", + }, +}; + +/* + * Brief: + * Get the configure of sensor from u-boot. + * Input: + * no use. + * Output: + * no use. + * Return: + * 0--success, -1--error. + * History: + * Created by HangYan on 2010-4-19 + * Author: + * Hang Yan in ShenZhen. + */ +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); +static int get_axisset(void* param) +{ + char varbuf[64]; + int n; + int varlen; + + memset(varbuf, 0, sizeof(varbuf)); + varlen = sizeof(varbuf); + if (wmt_getsyspara("wmt.io.mma7660gsensor", varbuf, &varlen)) { + printk(KERN_DEBUG "Can't get gsensor config in u-boot!!!!\n"); + return -1; + } else { + n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &l_sensorconfig.op, + &(l_sensorconfig.xyz_axis[0][0]), + &(l_sensorconfig.xyz_axis[0][1]), + &(l_sensorconfig.xyz_axis[1][0]), + &(l_sensorconfig.xyz_axis[1][1]), + &(l_sensorconfig.xyz_axis[2][0]), + &(l_sensorconfig.xyz_axis[2][1]), + &(l_sensorconfig.offset[0]), + &(l_sensorconfig.offset[1]), + &(l_sensorconfig.offset[2])); + if (n != 10) { + printk(KERN_ERR "gsensor format is error in u-boot!!!\n"); + return -1; + } + + dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n", + l_sensorconfig.op, + l_sensorconfig.xyz_axis[0][0], + l_sensorconfig.xyz_axis[0][1], + l_sensorconfig.xyz_axis[1][0], + l_sensorconfig.xyz_axis[1][1], + l_sensorconfig.xyz_axis[2][0], + l_sensorconfig.xyz_axis[2][1], + l_sensorconfig.offset[0], + l_sensorconfig.offset[1], + l_sensorconfig.offset[2] + ); + } + return 0; +} + + +// Add one timer to reinit sensor every 5s +static void sensor_polltimer_timeout(unsigned long timeout) +{ + schedule_work(&poll_work); +} + +static void poll_work_func(struct work_struct *work) +{ + char rxData[1]; + + //mutex_lock(&sense_data_mutex); + if (l_sensorconfig.pollcnt != 20) + { + l_sensorconfig.pollcnt++; + } + dbg("read to work!\n"); + //spin_lock(&l_sensorconfig.spinlock); + mutex_lock(&sense_data_mutex); + if (1 == l_resumed) + { + mma7660_chip_init(); + //gsensor_int_ctrl(ENABLE); + //mma_enable_disable(1); + dbg("reinit for resume...\n"); + l_resumed = 0; + //spin_unlock(&l_sensorconfig.spinlock); + mutex_unlock(&sense_data_mutex); + queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp))); + + return; + } + //spin_unlock(&l_sensorconfig.spinlock); + mutex_unlock(&sense_data_mutex); + if (!is_sensor_good) + { + //mma7660_chip_init(); + // if ic is blocked then wake g-sensor + sensor_i2c_read(MMA7660_ADDR,3,rxData,1); + } else { + is_sensor_good = 0; + } + + //mutex_unlock(&sense_data_mutex); + mod_timer(&l_polltimer, jiffies + msecs_to_jiffies(SENSOR_POLL_WAIT_TIME)); + +} + +static int mma7660_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mma7660_release(struct inode *inode, struct file *file) +{ + return 0; +} + + +static struct file_operations mma7660_fops = { + .owner = THIS_MODULE, + .open = mma7660_open, + .release = mma7660_release, +}; + +static int is_mma7660(void) +{ + char txData[2]; + int i = 0; + + txData[1] = 0; + for (i = 0; i < 3; i++) + { + if(sensor_i2c_write(MMA7660_ADDR,7,txData,1) == 0) + { + return 0; + } + } + return -1; +} + +static int __init mma7660_init(void) +{ + int ret = 0; + + if (is_mma7660()) + { + printk(KERN_ERR "Can't find mma7660!!\n"); + return -1; + } + ret = get_axisset(NULL); // get gsensor config from u-boot + if (ret < 0) + { + printk("<<<<<%s user choose to no sensor chip!\n", __func__); + return ret; + } + /*if ((ret != 0) || !l_sensorconfig.op) + return -EINVAL;*/ + + + printk(KERN_INFO "mma7660fc g-sensor driver init\n"); + + spin_lock_init(&l_sensorconfig.spinlock); + INIT_WORK(&poll_work, poll_work_func); + // Create device node + if (register_chrdev (GSENSOR_MAJOR, GSENSOR_NAME, &mma7660_fops)) { + printk (KERN_ERR "unable to get major %d\n", GSENSOR_MAJOR); + return -EIO; + } + + l_dev_class = class_create(THIS_MODULE, GSENSOR_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; + } + l_clsdevice = device_create(l_dev_class, NULL, MKDEV(GSENSOR_MAJOR, 0), NULL, GSENSOR_NAME); + if (IS_ERR(l_clsdevice)){ + ret = PTR_ERR(l_clsdevice); + printk(KERN_ERR "Failed to create device %s !!!",GSENSOR_NAME); + return ret; + } + + if((ret = platform_device_register(&mma7660_device))) + { + printk(KERN_ERR "%s Can't register mma7660 platform devcie!!!\n", __FUNCTION__); + return ret; + } + if ((ret = platform_driver_register(&mma7660_driver)) != 0) + { + printk(KERN_ERR "%s Can't register mma7660 platform driver!!!\n", __FUNCTION__); + return ret; + } + + setup_timer(&l_polltimer, sensor_polltimer_timeout, 0); + mod_timer(&l_polltimer, jiffies + msecs_to_jiffies(SENSOR_POLL_WAIT_TIME)); + is_sensor_good = 1; + + return 0; +} + +static void __exit mma7660_exit(void) +{ + del_timer(&l_polltimer); + platform_driver_unregister(&mma7660_driver); + platform_device_unregister(&mma7660_device); + device_destroy(l_dev_class, MKDEV(GSENSOR_MAJOR, 0)); + unregister_chrdev(GSENSOR_MAJOR, GSENSOR_NAME); + class_destroy(l_dev_class); + +} + +module_init(mma7660_init); +module_exit(mma7660_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/sensor/mma7660_gsensor/mma7660.h b/drivers/input/sensor/mma7660_gsensor/mma7660.h new file mode 100755 index 00000000..db6c06c0 --- /dev/null +++ b/drivers/input/sensor/mma7660_gsensor/mma7660.h @@ -0,0 +1,106 @@ +/* + * Definitions for akm8976 compass chip. + */ +#ifndef AKM8976_H +#define AKM8976_H + +#include + +/* Compass device dependent definition */ +#define AKECS_MODE_MEASURE 0x00 /* Starts measurement. Please use AKECS_MODE_MEASURE_SNG */ + /* or AKECS_MODE_MEASURE_SEQ instead of this. */ +#define AKECS_MODE_PFFD 0x01 /* Start pedometer and free fall detect. */ +#define AKECS_MODE_E2P_READ 0x02 /* E2P access mode (read). */ +#define AKECS_MODE_POWERDOWN 0x03 /* Power down mode */ + +#define AKECS_MODE_MEASURE_SNG 0x10 /* Starts single measurement */ +#define AKECS_MODE_MEASURE_SEQ 0x11 /* Starts sequential measurement */ + +/* Default register settings */ +#define CSPEC_AINT 0x01 /* Amplification for acceleration sensor */ +#define CSPEC_SNG_NUM 0x01 /* Single measurement mode */ +#define CSPEC_SEQ_NUM 0x02 /* Sequential measurement mode */ +#define CSPEC_SFRQ_32 0x00 /* Measurement frequency: 32Hz */ +#define CSPEC_SFRQ_64 0x01 /* Measurement frequency: 64Hz */ +#define CSPEC_MCS 0x07 /* Clock frequency */ +#define CSPEC_MKS 0x01 /* Clock type: CMOS level */ +#define CSPEC_INTEN 0x01 /* Interruption pin enable: Enable */ + +#define RBUFF_SIZE 31 /* Rx buffer size */ +#define MAX_CALI_SIZE 0x1000U /* calibration buffer size */ + +/* AK8976A register address */ +#define AKECS_REG_ST 0xC0 +#define AKECS_REG_TMPS 0xC1 +#define AKECS_REG_MS1 0xE0 +#define AKECS_REG_MS2 0xE1 +#define AKECS_REG_MS3 0xE2 + +#define AKMIO 0xA1 + +/* IOCTLs for AKM library */ +#define ECS_IOCTL_RESET _IO(AKMIO, 0x04) +#define ECS_IOCTL_INT_STATUS _IO(AKMIO, 0x05) +#define ECS_IOCTL_FFD_STATUS _IO(AKMIO, 0x06) +#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x07, short) +#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x08, char[RBUFF_SIZE+1]) +#define ECS_IOCTL_GET_NUMFRQ _IOR(AKMIO, 0x09, char[2]) +#define ECS_IOCTL_SET_PERST _IO(AKMIO, 0x0A) +#define ECS_IOCTL_SET_G0RST _IO(AKMIO, 0x0B) +#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x0C, short[12]) +#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x0D, int) +#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x0E, int) +#define ECS_IOCTL_GET_CALI_DATA _IOR(AKMIO, 0x0F, char[MAX_CALI_SIZE]) +#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short) + +/* IOCTLs for APPs */ +#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short) +#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short) +#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short) +#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short) +#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short) +#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short) +#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17) +#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY +#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short) /* Set raw magnetic vector flag */ +#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short) /* Get raw magnetic vector flag */ + +/* IOCTLs for pedometer */ +#define ECS_IOCTL_SET_STEP_CNT _IOW(AKMIO, 0x20, short) +#define SENSOR_DATA_SIZE 3 +#define WMTGSENSOR_IOCTL_MAGIC 0x09 +#define ECS_IOCTL_APP_SET_AFLAG _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x02, short) +#define ECS_IOCTL_APP_SET_DELAY _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x03, short) +#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int) +#define ECS_IOCTL_APP_READ_XYZ _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x05, int[SENSOR_DATA_SIZE]) + +#define MMA7660_DRVID 0 + + + +/* Default GPIO setting */ +#define ECS_RST 146 /*MISC4, bit2 */ +#define ECS_CLK_ON 155 /*MISC5, bit3 */ +#define ECS_INTR 161 /*INT2, bit1 */ + +/* MISC */ +#define MMA7660_ADDR 0x4C +#define SENSOR_UI_MODE 0 +#define SENSOR_GRAVITYGAME_MODE 1 +#define UI_SAMPLE_RATE 0xFC +#define GSENSOR_PROC_NAME "gsensor_config" +#define sin30_1000 500 +#define cos30_1000 866 +#define DISABLE 0 +#define ENABLE 1 + +struct mma7660_platform_data { + int reset; + int clk_on; + int intr; +}; + +extern char *get_mma_cal_ram(void); + +#endif + -- cgit