1 /* drivers/i2c/chips/mma7660.c - mma7660 compass driver
3 * Copyright (C) 2007-2008 HTC Corporation.
4 * Author: Hou-Kun Chen <houkun.chen@gmail.com>
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/interrupt.h>
18 #include <linux/i2c.h>
19 #include <linux/slab.h>
20 #include <linux/irq.h>
21 #include <linux/miscdevice.h>
22 #include <linux/gpio.h>
23 #include <asm/uaccess.h>
24 #include <linux/delay.h>
25 #include <linux/input.h>
26 #include <linux/workqueue.h>
27 #include <linux/freezer.h>
28 #include <linux/mma7660.h>
29 #include <mach/gpio.h>
30 #include <mach/board.h>
31 #ifdef CONFIG_ANDROID_POWER
32 #include <linux/android_power.h>
36 //#include <asm/arch/rk28_debug.h>
38 #define rk28printk(x...) printk(x)
40 static int mma7660_probe(struct i2c_client *client, const struct i2c_device_id *id);
43 #define MMA7660_GPIO_INT RK2818_PIN_PE3
45 /* Addresses to scan -- protected by sense_data_mutex */
46 static char sense_data[RBUFF_SIZE + 1];
47 static struct i2c_client *this_client;
49 static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq);
50 static atomic_t data_ready;
51 #ifdef CONFIG_ANDROID_POWER
52 static android_early_suspend_t mma7660_early_suspend;
54 static int revision = -1;
56 static ssize_t gsensor_vendor_show(struct device *dev,
57 struct device_attribute *attr, char *buf)
61 sprintf(buf, "%#x\n", revision);
62 ret = strlen(buf) + 1;
67 static DEVICE_ATTR(vendor, 0444, gsensor_vendor_show, NULL);
69 static struct kobject *android_gsensor_kobj;
71 static int gsensor_sysfs_init(void)
75 android_gsensor_kobj = kobject_create_and_add("android_gsensor", NULL);
76 if (android_gsensor_kobj == NULL) {
78 "MMA7660 gsensor_sysfs_init:"\
79 "subsystem_register failed\n");
84 ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr);
87 "MMA7660 gsensor_sysfs_init:"\
88 "sysfs_create_group failed\n");
94 kobject_del(android_gsensor_kobj);
99 static int mma7660_rx_data(char *rxData, int length)
102 struct i2c_msg msgs[] = {
104 .addr = this_client->addr,
111 if (i2c_transfer(this_client->adapter, msgs, 1) < 0) {
112 rk28printk(KERN_ERR "MMA7660 mma7660_rx_data: transfer error\n");
118 struct i2c_adapter *adap = this_client->adapter;
119 struct i2c_msg msgs[2];
121 msgs[0].addr = this_client->addr;
122 msgs[0].buf = (char *)rxData;
123 msgs[0].flags = this_client->flags;
125 msgs[0].scl_rate = 200*1000;
127 msgs[1].addr = this_client->addr;
128 msgs[1].buf = (char *)rxData;
129 msgs[1].flags = this_client->flags | I2C_M_RD;
131 msgs[1].scl_rate = 200*1000;
133 ret = i2c_transfer(adap, msgs, 2);
139 static int mma7660_tx_data(char *txData, int length)
142 struct i2c_msg msg[] = {
144 .addr = this_client->addr,
150 if (i2c_transfer(this_client->adapter, msg, 1) < 0) {
151 rk28printk(KERN_ERR "MMA7660 mma7660_tx_data: transfer error\n");
157 struct i2c_adapter *adap = this_client->adapter;
160 msg.addr = this_client->addr;
163 msg.flags = this_client->flags;
164 msg.scl_rate = 200*1000;
166 ret = i2c_transfer(adap, &msg, 1);
172 static int mma7660_set_rate(char rate)
181 for (i = 0; i < 7; i++) {
182 if (rate & (0x1 << i))
186 buffer[0] = MMA7660_REG_SR;
187 buffer[1] = 0xf8 | (0x07 & (~i));
189 ret = mma7660_tx_data(&(buffer[0]), 2);
194 static int mma7660_start_dev(char rate)
196 char buffer[MMA7660_REG_LEN];
199 buffer[0] = MMA7660_REG_INTSU;
200 buffer[1] = 0x10; //0x10; modify by zhao
201 ret = mma7660_tx_data(&buffer[0], 2);
203 ret = mma7660_set_rate(rate);
205 buffer[0] = MMA7660_REG_MODE;
207 ret = mma7660_tx_data(&buffer[0], 2);
209 rk28printk("\n----------------------------mma7660_start------------------------\n");
214 static int mma7660_start(char rate)
216 struct mma7660_data *mma = (struct mma7660_data *)i2c_get_clientdata(this_client);
218 if (mma->status == MMA7660_OPEN) {
221 mma->status = MMA7660_OPEN;
222 return mma7660_start_dev(rate);
225 static int mma7660_close_dev(void)
229 buffer[0] = MMA7660_REG_MODE;
232 return mma7660_tx_data(buffer, 2);
235 static int mma7660_close(void)
237 struct mma7660_data *mma = (struct mma7660_data *)i2c_get_clientdata(this_client);
239 mma->status = MMA7660_CLOSE;
241 return mma7660_close_dev();
244 static int mma7660_reset_rate(char rate)
248 ret = mma7660_close_dev();
249 ret = mma7660_start_dev(rate);
254 static inline int mma7660_convert_to_int(char value)
258 if (value < MMA7660_BOUNDARY) {
259 result = value * MMA7660_GRAVITY_STEP;
261 result = ~(((~value & 0x3f) + 1)* MMA7660_GRAVITY_STEP) + 1;
267 static void mma7660_report_value(short *rbuf)
269 struct mma7660_data *data = i2c_get_clientdata(this_client);
270 struct mma7660_axis *axis = (struct mma7660_axis *)rbuf;
272 /* Report acceleration sensor information */
273 input_report_abs(data->input_dev, ABS_X, axis->x);
274 input_report_abs(data->input_dev, ABS_Y, axis->y);
275 input_report_abs(data->input_dev, ABS_Z, axis->z);
276 input_sync(data->input_dev);
277 rk28printk("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
280 static int mma7660_get_data(void)
284 struct mma7660_axis axis;
286 memset(buffer, 0, 3);
287 buffer[0] = MMA7660_REG_X_OUT;
288 ret = mma7660_rx_data(&buffer[0], 3);
289 //while(mma7660_rx_data(&buffer[0], 3));
292 rk28printk( "%s: -------------------------------------------gsensor device register = [0]:%d [1]:%d [2]:%d [3]:0x%x [4]:0x%x [5]:0x%x [6]:0x%x [7]:0x%x-----------------------------------------------\n",
293 __func__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
299 axis.x = mma7660_convert_to_int(buffer[MMA7660_REG_X_OUT]);
300 axis.y = -mma7660_convert_to_int(buffer[MMA7660_REG_Y_OUT]);
301 axis.z = -mma7660_convert_to_int(buffer[MMA7660_REG_Z_OUT]);
303 rk28printk( "%s: -------------------------------------------mma7660_GetData axis = %d %d %d-----------------------------------------------\n",
304 __func__, axis.x, axis.y, axis.z);
306 memcpy(sense_data, &axis, sizeof(axis));
307 mma7660_report_value(sense_data);
308 //atomic_set(&data_ready, 0);
309 //wake_up(&data_ready_wq);
314 static int mma7660_trans_buff(char *rbuf, int size)
316 //wait_event_interruptible_timeout(data_ready_wq,
317 // atomic_read(&data_ready), 1000);
318 wait_event_interruptible(data_ready_wq,
319 atomic_read(&data_ready));
321 atomic_set(&data_ready, 0);
322 memcpy(rbuf, &sense_data[0], size);
327 static int mma7660_open(struct inode *inode, struct file *file)
329 rk28printk("----------------------------mma7660_open------------------------\n");
330 return 0;//nonseekable_open(inode, file);
333 static int mma7660_release(struct inode *inode, struct file *file)
338 static int mma7660_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
342 void __user *argp = (void __user *)arg;
343 char msg[RBUFF_SIZE + 1];
347 rk28printk("----------------------------mma7660_ioctl------------------------cmd: %d\n", cmd);
350 case ECS_IOCTL_APP_SET_RATE:
351 if (copy_from_user(&rate, argp, sizeof(rate)))
359 case ECS_IOCTL_START:
360 ret = mma7660_start(MMA7660_RATE_32);
364 case ECS_IOCTL_CLOSE:
365 ret = mma7660_close();
369 case ECS_IOCTL_APP_SET_RATE:
370 ret = mma7660_reset_rate(rate);
374 case ECS_IOCTL_GETDATA:
375 ret = mma7660_trans_buff(msg, RBUFF_SIZE);
384 case ECS_IOCTL_GETDATA:
385 if (copy_to_user(argp, &msg, sizeof(msg)))
395 static void mma7660_work_func(struct work_struct *work)
397 if (mma7660_get_data() < 0)
398 rk28printk(KERN_ERR "MMA7660 mma_work_func: Get data failed\n");
400 //GPIOClrearInmarkIntr(MMA7660_GPIO_INT);
402 rk28printk("---------------------------------------mma7660_work_func----------------------------------\n");
405 static void mma7660_delaywork_func(struct work_struct *work)
408 if (mma7660_get_data() < 0)
409 rk28printk(KERN_ERR "MMA7660 mma_work_func: Get data failed\n");
411 //GPIOClrearInmarkIntr(MMA7660_GPIO_INT);
413 rk28printk("---------------------------------------mma7660_delaywork_func------------------------------\n");
417 static irqreturn_t mma7660_interrupt(int irq, void *dev_id)
419 struct mma7660_data *data = dev_id;
421 ///GPIOInmarkIntr(MMA7660_GPIO_INT);
422 //schedule_work(&data->work);
423 schedule_delayed_work(&data->delaywork,msecs_to_jiffies(30));
424 rk28printk("--------------------------------------mma7660_interrupt---------------------------------------\n");
429 static struct file_operations mma7660_fops = {
430 .owner = THIS_MODULE,
431 .open = mma7660_open,
432 .release = mma7660_release,
433 .ioctl = mma7660_ioctl,
436 static struct miscdevice mma7660_device = {
437 .minor = MISC_DYNAMIC_MINOR,
438 .name = "mma7660_daemon",
439 .fops = &mma7660_fops,
442 static int mma7660_remove(struct i2c_client *client)
444 struct mma7660_data *mma = i2c_get_clientdata(client);
446 misc_deregister(&mma7660_device);
447 input_unregister_device(mma->input_dev);
448 input_free_device(mma->input_dev);
449 free_irq(client->irq, mma);
451 #ifdef CONFIG_ANDROID_POWER
452 android_unregister_early_suspend(&mma7660_early_suspend);
458 #ifdef CONFIG_ANDROID_POWER
459 static int mma7660_suspend(android_early_suspend_t *h)
461 rk28printk("Gsensor mma7760 enter suspend\n");
462 return mma7660_close_dev();
465 static int mma7660_resume(android_early_suspend_t *h)
467 struct mma7660_data *mma = (struct mma7660_data *)i2c_get_clientdata(this_client);
468 rk28printk("Gsensor mma7760 resume!!\n");
469 return mma7660_start_dev(mma->curr_tate);
472 static int suspend(struct i2c_client *client, pm_message_t mesg)
474 rk28printk("Gsensor mma7760 enter 2 level suspend\n");
475 return mma7660_close_dev();
477 static int resume(struct i2c_client *client)
479 struct mma7660_data *mma = (struct mma7660_data *)i2c_get_clientdata(this_client);
480 rk28printk("Gsensor mma7760 2 level resume!!\n");
481 return mma7660_start_dev(mma->curr_tate);
485 #define mma7660_suspend NULL
486 #define mma7660_resume NULL
489 static const struct i2c_device_id mma7660_id[] = {
494 static struct i2c_driver mma7660_driver = {
496 .name = "gs_mma7660",
498 .id_table = mma7660_id,
499 .probe = mma7660_probe,
500 .remove = __devexit_p(mma7660_remove),
501 //.suspend = &suspend,
506 static int mma7660_init_client(struct i2c_client *client)
508 struct mma7660_data *data;
510 data = i2c_get_clientdata(client);
511 struct rk2818_gs_platform_data *pdata = client->dev.platform_data;
513 printk("gpio_to_irq(%d) is %d\n",pdata->gsensor_irq_pin, gpio_to_irq(pdata->gsensor_irq_pin));
514 if ( !gpio_is_valid(pdata->gsensor_irq_pin)) {
515 printk("+++++++++++gpio_is_invalid\n");
518 ret = gpio_request(pdata->gsensor_irq_pin, "mma7660_int");
520 gpio_free(pdata->gsensor_irq_pin);
521 printk( "failed to request mma7990_trig GPIO%d\n",gpio_to_irq(pdata->gsensor_irq_pin));
525 client->irq = gpio_to_irq(pdata->gsensor_irq_pin);
527 ret = request_irq(client->irq, mma7660_interrupt, IRQF_TRIGGER_RISING, client->dev.driver->name, data);
528 rk28printk("request irq is %d,ret is 0x%x\n",client->irq,ret);
530 rk28printk(KERN_ERR "mma7660_init_client: request irq failed,ret is %d\n",ret);
533 init_waitqueue_head(&data_ready_wq);
538 static int mma7660_probe(struct i2c_client *client, const struct i2c_device_id *id)
540 struct mma7660_data *mma;
543 mma = kzalloc(sizeof(struct mma7660_data), GFP_KERNEL);
545 rk28printk("[mma7660]:alloc data failed.\n");
547 goto exit_alloc_data_failed;
550 INIT_WORK(&mma->work, mma7660_work_func);
551 INIT_DELAYED_WORK(&mma->delaywork, mma7660_delaywork_func);
553 mma->client = client;
554 i2c_set_clientdata(client, mma);
556 this_client = client;
558 err = mma7660_init_client(client);
561 "mma7660_probe: mma7660_init_client failed\n");
562 goto exit_request_gpio_irq_failed;
565 mma->input_dev = input_allocate_device();
566 if (!mma->input_dev) {
569 "mma7660_probe: Failed to allocate input device\n");
570 goto exit_input_allocate_device_failed;
573 set_bit(EV_ABS, mma->input_dev->evbit);
575 /* x-axis acceleration */
576 input_set_abs_params(mma->input_dev, ABS_X, -1500, 1500, 0, 0);
577 /* y-axis acceleration */
578 input_set_abs_params(mma->input_dev, ABS_Y, -1500, 1500, 0, 0);
579 /* z-axis acceleration */
580 input_set_abs_params(mma->input_dev, ABS_Z, -1500, 1500, 0, 0);
582 mma->input_dev->name = "compass";
584 err = input_register_device(mma->input_dev);
587 "mma7660_probe: Unable to register input device: %s\n",
588 mma->input_dev->name);
589 goto exit_input_register_device_failed;
592 err = misc_register(&mma7660_device);
595 "mma7660_probe: mmad_device register failed\n");
596 goto exit_misc_device_register_mma7660_device_failed;
599 err = gsensor_sysfs_init();
602 "mma7660_probe: gsensor sysfs init failed\n");
603 goto exit_gsensor_sysfs_init_failed;
606 #ifdef CONFIG_ANDROID_POWER
607 mma7660_early_suspend.suspend = mma7660_suspend;
608 mma7660_early_suspend.resume = mma7660_resume;
609 mma7660_early_suspend.level = 0x2;
610 android_register_early_suspend(&mma7660_early_suspend);
615 exit_gsensor_sysfs_init_failed:
616 misc_deregister(&mma7660_device);
617 exit_misc_device_register_mma7660_device_failed:
618 input_unregister_device(mma->input_dev);
619 exit_input_register_device_failed:
620 input_free_device(mma->input_dev);
621 exit_input_allocate_device_failed:
622 free_irq(client->irq, mma);
623 exit_request_gpio_irq_failed:
625 exit_alloc_data_failed:
631 static int __init mma7660_i2c_init(void)
633 return i2c_add_driver(&mma7660_driver);
636 static void __exit mma7660_i2c_exit(void)
638 i2c_del_driver(&mma7660_driver);
641 module_init(mma7660_i2c_init);
642 module_exit(mma7660_i2c_exit);