rk fb: extend output mutex lock in win config
[firefly-linux-kernel-4.4.55.git] / drivers / input / gsensor / lis3dh.c
1
2  /****************************************************************************************
3  * File:                        driver/input/gsensor/lis3dh.c
4  * Copyright:           Copyright (C) 2012-2013 RK Corporation.
5  * Author:              LiBing <libing@rock-chips.com>
6  * Date:                        2012.03.06
7  * Description: This driver use for rk29 chip extern gsensor. Use i2c IF ,the chip is 
8  *                              STMicroelectronics lis3dh.
9  *****************************************************************************************/
10 #include <linux/interrupt.h>
11 #include <linux/i2c.h>
12 #include <linux/slab.h>
13 #include <linux/irq.h>
14 #include <linux/miscdevice.h>
15 #include <linux/gpio.h>
16 #include <asm/uaccess.h>
17 #include <asm/atomic.h>
18 #include <linux/delay.h>
19 #include <linux/input.h>
20 #include <linux/workqueue.h>
21 #include <linux/freezer.h>
22 #include <mach/gpio.h>
23 #include <mach/board.h> 
24 #ifdef CONFIG_HAS_EARLYSUSPEND
25 #include <linux/earlysuspend.h>
26 #endif
27
28 #include "lis3dh.h"
29
30 #if 0
31 #define stprintk(x...) printk(x)
32 #else
33 #define stprintk(x...)
34 #endif
35
36 #if 0
37 #define stprintkd(x...) printk(x)
38 #else
39 #define stprintkd(x...)
40 #endif
41
42 #if 0
43 #define stprintkf(x...) printk(x)
44 #else
45 #define stprintkf(x...)
46 #endif
47
48
49 static struct i2c_client *this_client;
50 static struct miscdevice lis3dh_device;
51 static struct kobject *android_gsensor_kobj;
52 static const char* vendor = "STMicroelectronics";
53 static int suspend_flag;
54 static int  lis3dh_probe(struct i2c_client *client, const struct i2c_device_id *id);
55 static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq);
56
57 /* AKM HW info */
58 static ssize_t gsensor_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
59 {
60         ssize_t liRet = 0;
61
62         sprintf(buf, "%s.\n", vendor);
63         liRet = strlen(buf) + 1;
64
65         return liRet;
66 }
67
68 static DEVICE_ATTR(vendor, 0444, gsensor_vendor_show, NULL);
69
70 static int gsensor_sysfs_init(void)
71 {
72         int liRet ;
73
74         android_gsensor_kobj = kobject_create_and_add("android_gsensor", NULL);
75         if (android_gsensor_kobj == NULL)
76         {
77                 stprintk(KERN_ERR "LIS3DH gsensor_sysfs_init:subsystem_register failed\n");
78                 liRet = -ENOMEM;
79                 goto kobject_create_failed;
80         }
81         else
82         {
83                 //nothing
84         }
85
86         liRet = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr); // "vendor"
87         if (liRet) {
88                 stprintk(KERN_ERR "LIS3DH gsensor_sysfs_init:sysfs_create_group failed\n");
89                 goto sysfs_create_failed;
90         }
91         else
92         {
93                 //nothing
94         }
95
96         return 0 ;
97         
98 sysfs_create_failed:
99         kobject_del(android_gsensor_kobj);
100         
101 kobject_create_failed:
102         return liRet ;
103         
104 }
105
106 static int lis3dh_rx_data(struct i2c_client *client, char *rxData, int length)
107 {
108         int liRet = 0;
109         char lcReg = rxData[0];
110         liRet = i2c_master_reg8_recv(client, lcReg, rxData, length, LIS3DH_SPEED);
111         
112         return (liRet > 0)? 0 : liRet;
113 }
114
115 static int lis3dh_tx_data(struct i2c_client *client, char *txData, int length)
116 {
117         int liRet       = 0;
118         char lcReg      = txData[0];
119         liRet = i2c_master_reg8_send(client, lcReg, &txData[1], length-1, LIS3DH_SPEED);
120         
121         return (liRet > 0)? 0 : liRet;
122 }
123
124 static char lis3dh_read_reg(struct i2c_client *client, int addr)
125 {
126         char liTmp;
127         int     liRet = 0;
128
129         liTmp = addr;
130         liRet = lis3dh_rx_data(client, &liTmp, 1);
131         return liTmp;
132 }
133
134 static int lis3dh_write_reg(struct i2c_client *client,int addr,int value)
135 {
136         char buffer[3];
137         int liRet = 0;
138         buffer[0] = addr;
139         buffer[1] = value;
140         
141         liRet = lis3dh_tx_data(client, &buffer[0], 2);
142         return liRet;
143 }
144
145 static int lis3dh_init_device(struct lis3dh_data *lis3dh)
146 {
147         int liRet =-1;
148
149         memset(lis3dh->resume_state, 0, ARRAY_SIZE(lis3dh->resume_state));
150         lis3dh->resume_state[RES_CTRL_REG1]             = LIS3DH_ACC_ENABLE_ALL_AXES;
151         lis3dh->resume_state[RES_CTRL_REG2]             = 0x00;
152         lis3dh->resume_state[RES_CTRL_REG3]             = 0x40; 
153         lis3dh->resume_state[RES_CTRL_REG4]             = 0x08;
154         lis3dh->resume_state[RES_CTRL_REG5]             = 0x08;
155         lis3dh->resume_state[RES_CTRL_REG6]             = 0x40; 
156         lis3dh->resume_state[RES_TEMP_CFG_REG]  = 0x00;
157         lis3dh->resume_state[RES_FIFO_CTRL_REG] = 0x00;
158         lis3dh->resume_state[RES_INT_CFG1]              = 0xFF;
159         lis3dh->resume_state[RES_INT_THS1]              = 0x7F; 
160         lis3dh->resume_state[RES_INT_DUR1]              = 0x7F; //0x00->ox7f
161         lis3dh->resume_state[RES_TT_CFG]                = 0x00;
162         lis3dh->resume_state[RES_TT_THS]                = 0x00;
163         lis3dh->resume_state[RES_TT_LIM]                = 0x00;
164         lis3dh->resume_state[RES_TT_TLAT]               = 0x00;
165         lis3dh->resume_state[RES_TT_TW]                 = 0x00;
166         
167         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG1, lis3dh->resume_state[RES_CTRL_REG1]);
168         if (liRet < 0)
169         {
170                 printk("RES_CTRL_REG1 err\n");
171                 return 0;
172         }
173         else
174         {
175                 //nothing
176         }
177
178         liRet =lis3dh_write_reg(lis3dh->client, TEMP_CFG_REG, lis3dh->resume_state[RES_TEMP_CFG_REG]);
179         if (liRet < 0)
180         {
181                 printk("TEMP_CFG_REG err\n");
182                 return 0;
183         }
184         else
185         {
186                 //nothing
187         }
188
189         liRet =lis3dh_write_reg(lis3dh->client, FIFO_CTRL_REG, lis3dh->resume_state[RES_FIFO_CTRL_REG]);
190         if(liRet < 0)
191         {
192                 printk("FIFO_CTRL_REG err\n");
193                 return 0;
194         }
195         else
196         {
197                 //nothing
198         }
199         
200         liRet =lis3dh_write_reg(lis3dh->client, TT_THS, lis3dh->resume_state[RES_TT_THS]);
201         liRet =lis3dh_write_reg(lis3dh->client, TT_LIM, lis3dh->resume_state[RES_TT_LIM]);
202         liRet =lis3dh_write_reg(lis3dh->client, TT_TLAT, lis3dh->resume_state[RES_TT_TLAT]);
203         liRet =lis3dh_write_reg(lis3dh->client, TT_TW, lis3dh->resume_state[RES_TT_TW]);
204         if(liRet < 0)
205         {
206                 printk("I2C_AUTO_INCREMENT err\n");
207                 return 0;
208         }
209         else
210         {
211                 //nothing
212         }
213
214         liRet =lis3dh_write_reg(lis3dh->client, TT_CFG, lis3dh->resume_state[RES_TT_CFG]);
215         if(liRet < 0)
216         {
217                 printk("TT_CFG err\n");
218                 return 0;
219         }
220         else
221         {
222                 //nothing
223         }
224         
225         liRet =lis3dh_write_reg(lis3dh->client, INT_THS1, lis3dh->resume_state[RES_INT_THS1]);
226         liRet =lis3dh_write_reg(lis3dh->client, INT_DUR1, lis3dh->resume_state[RES_INT_DUR1]);
227         if(liRet < 0)
228         {
229                 printk("I2C_AUTO_INCREMENT err\n");
230                 return 0;
231         }
232         else
233         {
234                 //nothing
235         }
236
237         liRet =lis3dh_write_reg(lis3dh->client, INT_CFG1, lis3dh->resume_state[RES_INT_CFG1]);
238         if(liRet < 0)
239         {
240                 printk("INT_CFG1 err\n");
241                 return 0;
242         }
243         else
244         {
245                 //nothing
246         }
247         
248         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG2, lis3dh->resume_state[RES_CTRL_REG2]);
249         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG3, lis3dh->resume_state[RES_CTRL_REG3]);
250         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG4, lis3dh->resume_state[RES_CTRL_REG4]);
251         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG5, lis3dh->resume_state[RES_CTRL_REG5]);
252         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG6, lis3dh->resume_state[RES_CTRL_REG6]);
253         if(liRet < 0)
254         {
255                 printk("I2C_AUTO_INCREMENT err\n");
256                 return 0;
257         }
258         else
259         {
260                 //nothing
261         }
262
263         return liRet;
264 }
265
266 static char lis3dh_get_devid(struct lis3dh_data *lis3dh)
267 {
268         char lcDeviceID;
269
270         lcDeviceID      = lis3dh_read_reg(lis3dh->client,WHO_AM_I);
271         if(lcDeviceID < 0)
272         {
273                 printk("devid err\n");
274                 return 0;
275         }
276         else
277         {
278                 printk("lis3dh devid:%x\n",lcDeviceID);
279         }
280         
281         return lcDeviceID;
282 }
283
284 static int lis3dh_active(struct i2c_client *client,int enable)
285 {
286         int liTmp = 0;
287         int liRet = 0;
288
289         liTmp =lis3dh_read_reg(client, CTRL_REG1);
290         if(enable)
291         {
292                 liTmp |= LIS3DH_ACC_ENABLE_ALL_AXES;
293         }
294         else
295         {
296                 liTmp = 0x08;
297         }
298         
299         liRet =lis3dh_write_reg(client, CTRL_REG1, liTmp);
300         
301         return liRet;
302 }
303
304 static int lis3dh_start_dev(struct i2c_client *client, char rate)
305 {
306         int liRet       = 0;
307         int liRate      = 0;
308         char lcTmp      = 0x0;
309         struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
310         
311         if((int)rate == 5)
312         {
313                 liRate = 3;
314         }
315         else if((int)rate == 6)
316         {
317                 liRate = 2;
318         }
319         else
320         {
321                 liRate = 4;
322         }
323
324         lcTmp = liRate<<4 | LIS3DH_ACC_ENABLE_ALL_AXES;
325
326         liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG1, lcTmp);
327         if (liRet < 0)
328         {
329                 printk(KERN_ERR "lis3dh_start_dev err\n");
330         }
331         else
332         {
333                 stprintkf("lis3dh_start_dev\n");
334         }
335         lis3dh_active(client,1);
336         enable_irq(client->irq);
337         return liRet;
338 }
339
340 static int lis3dh_start(struct i2c_client *client, char rate)
341
342     struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
343     
344         stprintkf("%s::enter\n",__FUNCTION__); 
345     if (lis3dh->status == LIS3DH_OPEN)
346         {
347         return 0;      
348     }
349         else
350         {
351                 //nothing
352         }
353     lis3dh->status = LIS3DH_OPEN;
354         
355     return lis3dh_start_dev(client, rate);
356 }
357
358 static int lis3dh_close_dev(struct i2c_client *client)
359 {
360         disable_irq_nosync(client->irq);
361         return lis3dh_active(client,0);
362 }
363
364 static int lis3dh_close(struct i2c_client *client)
365 {
366     struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
367           stprintkf("%s::enter\n",__FUNCTION__); 
368     lis3dh->status = LIS3DH_CLOSE;  
369     return lis3dh_close_dev(client);
370 }
371
372 static int lis3dh_reset_rate(struct i2c_client *client, char rate)
373 {
374         int liRet = 0;
375         
376     liRet = lis3dh_close_dev(client);
377     liRet = lis3dh_start_dev(client, rate);
378   
379         return liRet ;
380 }
381
382 static void lis3dh_report_value(struct i2c_client *client, struct lis3dh_axis *axis)
383 {
384         struct lis3dh_data *lis3dh = i2c_get_clientdata(client);
385
386         /* Report acceleration sensor information */
387     input_report_abs(lis3dh->input_dev, ABS_X, axis->x);
388     input_report_abs(lis3dh->input_dev, ABS_Y, axis->y);
389     input_report_abs(lis3dh->input_dev, ABS_Z, axis->z);
390     input_sync(lis3dh->input_dev);
391     stprintkd("Gsensor x==%d  y==%d z==%d\n",axis->x,axis->y,axis->z);
392 }
393
394 static inline s64 lis3dh_convert_to_int(const char High_Value, const char Low_Value)
395 {
396         s64 liResult;
397         
398         liResult = ((long) High_Value << 8) | Low_Value;
399         
400     if (liResult < LIS3DH_BOUNDARY)
401         {
402        liResult = liResult * LIS3DH_GRAVITY_STEP;
403     } 
404         else
405         {
406        liResult = ~(((~liResult & 0x7fff) + 1)* LIS3DH_GRAVITY_STEP) + 1;
407     }
408
409     return liResult;
410 }
411
412 /**get the gsensor data. */
413 static int lis3dh_get_data(struct i2c_client *client)
414 {
415         int liResult;
416         int x,y,z;
417         char acc_data[6];
418
419         struct lis3dh_axis axis;
420     struct lis3dh_data* lis3dh = i2c_get_clientdata(client);
421     struct gsensor_platform_data *pdata = pdata = client->dev.platform_data;
422         
423         /* x,y,z hardware data */
424         do {
425                 
426         memset(acc_data, 0, 6);
427         acc_data[0] = (I2C_AUTO_INCREMENT | AXISDATA_REG);
428                 
429                 liResult = lis3dh_rx_data(client, &acc_data[0], 6);
430                 if (liResult < 0)
431                 {
432             return liResult;
433         }
434                 else
435                 {
436                         //nothing
437                 }
438     } while (0);
439         
440         stprintkd("0x%02x 0x%02x 0x%02x \n",acc_data[1],acc_data[3],acc_data[5]);
441         
442         z = -lis3dh_convert_to_int(acc_data[1],acc_data[0]);
443         x = -lis3dh_convert_to_int(acc_data[3],acc_data[2]);
444         y = lis3dh_convert_to_int(acc_data[5],acc_data[4]);
445
446         axis.x = x;
447         axis.y = z;
448         axis.z = y;
449
450         if (pdata->swap_xyz)
451         {
452                 axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
453                 axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
454                 axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
455         }
456         else 
457         {
458                 axis.x = x;
459                 axis.y = y;
460                 axis.z = z;
461         }
462
463         if(pdata->swap_xy)
464         {
465                 axis.x = -axis.x;
466                 swap(axis.x,axis.y);            
467         }
468         
469         stprintkd( "%s: GetData axis = %d  %d  %d-------\n",__func__, axis.x, axis.y, axis.z); 
470
471     lis3dh_report_value(client, &axis);
472
473     /* Caching data mutually exclusive.*/
474     mutex_lock(&(lis3dh->sense_data_mutex) );
475     lis3dh->sense_data = axis;
476     mutex_unlock(&(lis3dh->sense_data_mutex) );
477
478         /* set data_ready */
479     atomic_set(&(lis3dh->data_ready), 1);
480         /* wakeup the data_ready,the first of wait queue */
481         wake_up(&(lis3dh->data_ready_wq) );
482
483         return 0;
484 }
485
486 static int lis3dh_get_cached_data(struct i2c_client* client, struct lis3dh_axis* sense_data)
487 {
488     struct lis3dh_data* lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
489
490     wait_event_interruptible_timeout(lis3dh->data_ready_wq, 
491                                      atomic_read(&(lis3dh->data_ready) ),msecs_to_jiffies(1000) );
492         
493     if ( 0 == atomic_read(&(lis3dh->data_ready) ) ) 
494         {
495         printk("waiting 'data_ready_wq' timed out.");
496         return -1;
497     }
498         else
499         {
500                 //nothing
501         }
502         
503     mutex_lock(&(lis3dh->sense_data_mutex));
504     *sense_data = lis3dh->sense_data;
505     mutex_unlock(&(lis3dh->sense_data_mutex));
506         
507     return 0;
508 }
509
510 static int lis3dh_open(struct inode *inode, struct file *file)
511 {
512         return 0;//nonseekable_open(inode, file);
513 }
514
515 static int lis3dh_release(struct inode *inode, struct file *file)
516 {
517         return 0;
518 }
519
520 static long lis3dh_ioctl(struct file *file, unsigned int cmd,unsigned long arg)
521 {
522         int liRet = -1;
523         char rate;
524         void __user *argp = (void __user *)arg;
525         
526     struct lis3dh_axis sense_data = {0};
527         struct i2c_client *client = container_of(lis3dh_device.parent, struct i2c_client, dev);
528     struct lis3dh_data* lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);  
529
530         switch (cmd)
531         {
532                 case ST_IOCTL_APP_SET_RATE:
533                         
534                         if (copy_from_user(&rate, argp, sizeof(rate)))
535                         {
536                                 return -EFAULT;
537                         }
538                         else
539                         {
540                                 //nothing
541                         }
542                         
543                         break;
544                         
545                 default:
546                         break;
547         }
548
549         switch (cmd)
550         {
551                 case ST_IOCTL_START:
552                         
553                 mutex_lock(&(lis3dh->operation_mutex) );
554                 stprintkd("to perform 'ST_IOCTL_START', former 'start_count' is %d.", lis3dh->start_count);
555                 (lis3dh->start_count)++;
556                         
557                 if ( 1 == lis3dh->start_count )
558                         {
559                 atomic_set(&(lis3dh->data_ready), 0);
560                 if ( (liRet = lis3dh_start(client, LIS3DH_RATE_12P5) ) < 0 ) 
561                                 {
562                         mutex_unlock(&(lis3dh->operation_mutex) );
563                         return liRet;
564                 }
565                                 else
566                                 {
567                                         //nothing
568                                 }
569                 }
570                         else
571                         {
572                                 //nothing
573                         }
574                 mutex_unlock(&(lis3dh->operation_mutex) );
575                 stprintkd("finish 'ST_IOCTL_START', ret = %d.", liRet);
576                 return 0;
577
578                 case ST_IOCTL_CLOSE:
579                         
580                 mutex_lock(&(lis3dh->operation_mutex) );
581                 stprintkd("to perform 'ST_IOCTL_CLOSE', former 'start_count' is %d, PID : %d", lis3dh->start_count, get_current()->pid);
582                 if ( 0 == (--(lis3dh->start_count) ) )
583                         {
584                 atomic_set(&(lis3dh->data_ready), 0);
585                 if ( (liRet = lis3dh_close(client) ) < 0 ) 
586                                 {
587                         mutex_unlock(&(lis3dh->operation_mutex) );
588                         return liRet;
589                 }
590                                 else
591                                 {
592                                         //nothing
593                                 }
594                 }
595                 mutex_unlock(&(lis3dh->operation_mutex) );
596                 return 0;
597
598                 case ST_IOCTL_APP_SET_RATE:
599                         
600                         liRet = lis3dh_reset_rate(client, rate);
601                         if (liRet< 0)
602                         {
603                                 return liRet;
604                         }
605                         else
606                         {
607                                 //nothing
608                         }
609                         
610                         break;
611                         
612                 case ST_IOCTL_GETDATA:
613                         if ( (liRet = lis3dh_get_cached_data(client, &sense_data) ) < 0 )
614                         {
615                 printk("failed to get cached sense data, ret = %d.", liRet);
616                                 return liRet;
617                         }
618                         else
619                         {
620                                 //nothing
621                         }
622                         break;
623                         
624                 default:
625                         return -ENOTTY;
626         }
627
628         switch (cmd)
629         {
630                 case ST_IOCTL_GETDATA:
631                 if ( copy_to_user(argp, &sense_data, sizeof(sense_data) ) )
632                         {
633                 printk("failed to copy sense data to user space.");
634                                 return -EFAULT;
635                 }
636                         else
637                         {
638                                 //npthing
639                         }
640                         break;
641                         
642                 default:
643                         break;
644         }
645         return 0;
646 }
647
648 static void lis3dh_work_func(struct work_struct *work)
649 {
650         struct lis3dh_data *lis3dh = container_of(work, struct lis3dh_data, work);
651         struct i2c_client *client = lis3dh->client;
652         
653         if (lis3dh_get_data(client) < 0) 
654         {
655                 stprintkd(KERN_ERR "LIS3DH lis3dh_work_func: Get data failed\n");
656         }
657         else
658         {
659                 //nothing
660         }
661                 
662         enable_irq(client->irq);                
663 }
664
665 static void  lis3dh_delaywork_func(struct work_struct *work)
666 {
667         struct delayed_work *delaywork = container_of(work, struct delayed_work, work);
668         struct lis3dh_data *lis3dh = container_of(delaywork, struct lis3dh_data, delaywork);
669         struct i2c_client *client = lis3dh->client;
670
671         if (lis3dh_get_data(client) < 0) 
672         {
673                 printk(KERN_ERR " lis3dh_work_func: Get data failed\n");
674         }
675         else
676         {
677                 //nothing
678         }
679         
680         stprintkd("%s :int src:0x%02x\n",__FUNCTION__,lis3dh_read_reg(lis3dh->client,INT_SRC1));
681         if(0==suspend_flag){
682            enable_irq(client->irq);             
683         }
684 }
685
686 static irqreturn_t lis3dh_interrupt(int irq, void *dev_id)
687 {
688         struct lis3dh_data *lis3dh = (struct lis3dh_data *)dev_id;
689         
690         disable_irq_nosync(irq);
691         schedule_delayed_work(&lis3dh->delaywork, msecs_to_jiffies(30));
692         stprintkf("%s :enter\n",__FUNCTION__);  
693         return IRQ_HANDLED;
694 }
695
696 static struct file_operations lis3dh_fops = {
697         .owner                  = THIS_MODULE,
698         .open                   = lis3dh_open,
699         .release                = lis3dh_release,
700         .unlocked_ioctl = lis3dh_ioctl,
701 };
702
703 static struct miscdevice lis3dh_device = {
704         .minor  = MISC_DYNAMIC_MINOR,
705         .name   = "mma8452_daemon",//"mma8452_daemon",
706         .fops   = &lis3dh_fops,
707 };
708
709 static int lis3dh_remove(struct i2c_client *client)
710 {
711         struct lis3dh_data *lis3dh = i2c_get_clientdata(client);
712         
713     misc_deregister(&lis3dh_device);
714     input_unregister_device(lis3dh->input_dev);
715     input_free_device(lis3dh->input_dev);
716     free_irq(client->irq, lis3dh);
717     kfree(lis3dh); 
718 #ifdef CONFIG_HAS_EARLYSUSPEND
719     unregister_early_suspend(&lis3dh_early_suspend);
720 #endif      
721     this_client = NULL;
722         return 0;
723 }
724
725 #ifdef CONFIG_HAS_EARLYSUSPEND
726 static void lis3dh_suspend(struct early_suspend *h)
727 {
728         struct i2c_client *client = container_of(lis3dh_device.parent, struct i2c_client, dev);
729         struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
730         suspend_flag=1;
731   cancel_delayed_work_sync(&(lis3dh->delaywork));       
732         lis3dh_close(client);
733 }
734
735 static void lis3dh_resume(struct early_suspend *h)
736 {
737         struct i2c_client *client = container_of(lis3dh_device.parent, struct i2c_client, dev);
738   struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
739         suspend_flag=0;
740         lis3dh_start_dev(client,lis3dh->curr_tate);
741         enable_irq(client->irq);
742 }
743 #else
744 static int lis3dh_suspend(struct i2c_client *client, pm_message_t mesg)
745 {
746         int liRet;
747         stprintkd("Gsensor lis3dh enter 2 level  suspend lis3dh->status %d\n",lis3dh->status);
748         struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
749
750         return liRet;
751 }
752 static int lis3dh_resume(struct i2c_client *client)
753 {
754         int liRet;
755         struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client);
756         stprintkd("Gsensor lis3dh 2 level resume!! lis3dh->status %d\n",lis3dh->status);
757         return liRet;
758 }
759 #endif
760
761 static const struct i2c_device_id lis3dh_id[] = {
762         {"lis3dh", 0},
763         { }
764 };
765
766 static struct i2c_driver lis3dh_driver = {
767         .driver = {
768                 .name = "lis3dh",
769         },
770         .id_table       = lis3dh_id,
771         .probe          = lis3dh_probe,           
772         .remove         = __devexit_p(lis3dh_remove),
773 #ifndef CONFIG_HAS_EARLYSUSPEND 
774         .suspend        = &lis3dh_suspend,
775         .resume         = &lis3dh_resume,
776 #endif  
777 };
778
779 static int lis3dh_init_client(struct i2c_client *client)
780 {
781         int liRet       = 0;
782         int irq         = 0;
783         struct lis3dh_data *lis3dh;
784         
785         lis3dh = i2c_get_clientdata(client);
786         
787         liRet = gpio_request(client->irq, "lis3dh_int");
788         if (liRet) {
789                 stprintk( "failed to request lis3dh_trig GPIO%d\n",gpio_to_irq(client->irq));
790                 return liRet;
791         }
792         else
793         {
794                 //nothing
795         }
796
797         gpio_direction_output(client->irq, 1);
798     liRet = gpio_direction_input(client->irq);
799     if (liRet)
800         {
801         stprintk("failed to set lis3dh_trig GPIO gpio input\n");
802                 gpio_free(client->irq);
803                 return liRet;
804     }
805         else
806         {
807                 //nothing
808         }
809         
810         irq = gpio_to_irq(client->irq);
811         liRet = request_irq(irq, lis3dh_interrupt, IRQF_TRIGGER_LOW, client->dev.driver->name, lis3dh);
812         if (liRet )
813         {
814                 gpio_free(client->irq);
815                 stprintk(KERN_ERR "lis3dh_init_client: request irq failed,ret is %d\n",liRet);
816         return liRet;
817         }
818         else
819         {
820                 stprintk("request irq is %d,ret is  0x%x\n",irq,liRet);
821         }
822         
823         client->irq = irq;
824         disable_irq(client->irq);
825         init_waitqueue_head(&data_ready_wq);
826         
827         return 0;
828
829
830 static int  lis3dh_probe(struct i2c_client *client, const struct i2c_device_id *id)
831 {
832         struct lis3dh_data *lis3dh;
833         struct lis3dh_platform_data *pdata = pdata = client->dev.platform_data;
834         int liRet = -1;
835         char devid;
836
837         stprintkf("%s enter\n",__FUNCTION__);
838
839         lis3dh = kzalloc(sizeof(struct lis3dh_data), GFP_KERNEL);
840         if (!lis3dh)
841         {
842                 stprintk("[lis3dh]:alloc data failed.\n");
843                 liRet = -ENOMEM;
844                 goto exit_alloc_data_failed;
845         }
846         else
847         {
848                 //nothig
849         }
850
851         INIT_WORK(&lis3dh->work, lis3dh_work_func);
852         INIT_DELAYED_WORK(&lis3dh->delaywork, lis3dh_delaywork_func);
853
854     memset(&(lis3dh->sense_data), 0, sizeof(struct lis3dh_axis) );
855     mutex_init(&(lis3dh->sense_data_mutex) );
856     
857         atomic_set(&(lis3dh->data_ready), 0);
858     init_waitqueue_head(&(lis3dh->data_ready_wq) );
859
860     lis3dh->start_count = 0;
861     mutex_init(&(lis3dh->operation_mutex) );
862     
863         lis3dh->status = LIS3DH_CLOSE;
864         lis3dh->client = client;
865         
866         i2c_set_clientdata(client, lis3dh);
867
868         this_client = client;
869
870         devid = lis3dh_get_devid(lis3dh);
871         if (devid != WHOAMI_LIS3DH_ACC)
872         {
873                 pr_info("lis3dh: invalid devid\n");
874                 goto exit_invalid_devid;
875         }
876         else
877         {
878                 //nothing
879         }
880
881         liRet = lis3dh_init_device(lis3dh);
882         if (devid < 0)
883         {
884                 pr_info("lis3dh: init err\n");
885                 goto exit_invalid_devid;
886         }
887         else
888         {
889                 //nothing
890         }
891  
892         liRet = lis3dh_init_client(client);
893         if (liRet < 0)
894         {
895                 stprintk(KERN_ERR "lis3dh_probe: lis3dh_init_client failed\n");
896                 goto exit_request_irq_failed;
897         }
898         else
899         {
900                 //nothing
901         }
902
903         lis3dh->input_dev = input_allocate_device();
904         if (!lis3dh->input_dev)
905         {
906                 liRet = -ENOMEM;
907                 stprintk(KERN_ERR "lis3dh_probe: Failed to allocate input device\n");
908                 goto exit_input_allocate_device_failed;
909         }
910         else
911         {
912                 //nothing
913         }
914
915         set_bit(EV_ABS, lis3dh->input_dev->evbit);
916
917         /* x-axis acceleration */
918         input_set_abs_params(lis3dh->input_dev, ABS_X, -LIS3DH_RANGE, LIS3DH_RANGE, 0, 0); //2g full scale range
919         /* y-axis acceleration */
920         input_set_abs_params(lis3dh->input_dev, ABS_Y, -LIS3DH_RANGE, LIS3DH_RANGE, 0, 0); //2g full scale range
921         /* z-axis acceleration */
922         input_set_abs_params(lis3dh->input_dev, ABS_Z, -LIS3DH_RANGE, LIS3DH_RANGE, 0, 0); //2g full scale range
923
924         lis3dh->input_dev->name = "gsensor";
925         lis3dh->input_dev->dev.parent = &client->dev;
926
927         liRet = input_register_device(lis3dh->input_dev);
928         if (liRet < 0)
929         {
930                 stprintk(KERN_ERR "lis3dh_probe: Unable to register input device: %s\n",lis3dh->input_dev->name);
931                 goto exit_input_register_device_failed;
932         }
933         else
934         {
935                 //nothing
936         }
937
938     lis3dh_device.parent = &client->dev;
939         liRet = misc_register(&lis3dh_device);
940         if (liRet < 0) 
941         {
942                 stprintk(KERN_ERR"lis3dh_probe: mmad_device register failed\n");
943                 goto exit_misc_device_failed;
944         }
945         else
946         {
947                 //nothing
948         }
949
950         liRet = gsensor_sysfs_init();
951         if (liRet < 0)
952         {
953                 stprintk(KERN_ERR "lis3dh_probe: gsensor sysfs init failed\n");
954                 goto exit_gsensor_sysfs_init_failed;
955         }
956         else
957         {
958                 //nothing
959         }
960         
961 #ifdef CONFIG_HAS_EARLYSUSPEND
962     lis3dh_early_suspend.suspend        = lis3dh_suspend;
963     lis3dh_early_suspend.resume         = lis3dh_resume;
964     lis3dh_early_suspend.level          = 0x2;
965     register_early_suspend(&lis3dh_early_suspend);
966 #endif
967   suspend_flag=0;
968         printk(KERN_INFO "lis3dh probe ok\n");
969
970         return 0;
971
972 exit_gsensor_sysfs_init_failed:
973     misc_deregister(&lis3dh_device);
974 exit_misc_device_failed:
975     input_unregister_device(lis3dh->input_dev);
976 exit_input_register_device_failed:
977         input_free_device(lis3dh->input_dev);
978 exit_input_allocate_device_failed:
979         free_irq(client->irq, lis3dh);
980 exit_request_irq_failed:
981         cancel_delayed_work_sync(&lis3dh->delaywork);
982         cancel_work_sync(&lis3dh->work);
983 exit_invalid_devid:
984         kfree(lis3dh);  
985 exit_alloc_data_failed:
986         stprintk("%s error\n",__FUNCTION__);
987         return -1;
988 }
989
990 static int __init lis3dh_i2c_init(void)
991 {
992         return i2c_add_driver(&lis3dh_driver);
993 }
994
995 static void __exit lis3dh_i2c_exit(void)
996 {
997         i2c_del_driver(&lis3dh_driver);
998 }
999
1000 module_init(lis3dh_i2c_init);
1001 module_exit(lis3dh_i2c_exit);
1002
1003 MODULE_DESCRIPTION ("STMicroelectronics gsensor driver");
1004 MODULE_AUTHOR("LB<libing@rock-chips.com>");
1005 MODULE_LICENSE("GPL");