Merge remote-tracking branch 'linux-2.6.32.y/master' into develop
[firefly-linux-kernel-4.4.55.git] / drivers / input / lightsensor / cm3202.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/device.h>
5 #include <linux/err.h>
6 #include <linux/io.h>
7 #include <linux/adc.h>
8 #include <linux/delay.h>
9 #include <linux/fs.h>
10 #include <linux/sched.h>
11 #include <linux/pm.h>
12 #include <linux/sysctl.h>
13 #include <linux/miscdevice.h>
14 #include <linux/slab.h>
15 #include <asm/gpio.h>
16 #include <asm/uaccess.h>
17 #include <linux/timer.h>
18 #include <linux/input.h>
19 #include <linux/ioctl.h>
20 //#include <mach/rk29_sdk_io.h>
21 #include <mach/board.h> 
22 #include <linux/platform_device.h>
23 #ifdef CONFIG_HAS_EARLYSUSPEND
24 #include <linux/earlysuspend.h>
25 #endif
26
27 #define DEBUG   0
28
29 #if DEBUG
30 #define DBG(X...)       printk(KERN_NOTICE X)
31 #else
32 #define DBG(X...)
33 #endif
34
35 //#define CM3202_SD_IOPIN               LIGHT_INT_IOPIN//light sensor int Pin  <level=Low "ON"> <level=Hight "OFF">
36 //#define DATA_ADC_CHN  2       //SARADC_AIN[3]
37 #define SENSOR_ON       1
38 #define SENSOR_OFF      0
39 #define LIGHTSENSOR_IOCTL_MAGIC 'l'
40 #define LIGHTSENSOR_IOCTL_GET_ENABLED    _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *) 
41 #define LIGHTSENSOR_IOCTL_ENABLE         _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *) 
42 #define LIGHTSENSOR_IOCTL_DISABLE        _IOW(LIGHTSENSOR_IOCTL_MAGIC, 3, int *)
43
44 struct cm3202_data {
45         struct adc_client       *client;
46         struct timer_list       timer;
47         struct work_struct      timer_work;
48         struct input_dev        *input;
49         int CM3202_SD;
50         int statue;
51 };
52 #ifdef CONFIG_HAS_EARLYSUSPEND
53 static struct early_suspend cm3202_early_suspend;
54 #endif
55 static struct cm3202_data *light;
56
57 static int cm3202_start(struct cm3202_data *data)
58 {
59         struct cm3202_data *cm3202 = data;
60         if(cm3202->statue)
61                 return 0;
62         gpio_direction_output(cm3202->CM3202_SD,0);//level = 0 Sensor ON
63         cm3202->statue = SENSOR_ON;
64         cm3202->timer.expires  = jiffies + 1*HZ;
65         add_timer(&cm3202->timer);
66         printk("========== cm3202 light sensor start ==========\n");
67         return 0;
68 }
69
70 static int cm3202_stop(struct cm3202_data *data)
71 {
72         struct cm3202_data *cm3202 = data;
73         if(cm3202->statue == 0)
74                 return 0;
75         gpio_direction_output(cm3202->CM3202_SD,1);//level = 1 Sensor OFF
76         cm3202->statue = SENSOR_OFF;
77         del_timer(&cm3202->timer);
78         printk("========== cm3202 light sensor stop ==========\n");
79         return 0;
80 }
81
82 #ifdef CONFIG_HAS_EARLYSUSPEND
83 static void cm3202_suspend(struct early_suspend *h)
84 {
85         struct cm3202_data *cm3202 = light;
86         cm3202_stop(cm3202);
87         printk("Light Sensor cm3202 enter suspend cm3202->status %d\n",cm3202->statue);
88 }
89
90 static void cm3202_resume(struct early_suspend *h)
91 {
92         struct cm3202_data *cm3202 = light;
93         cm3202_start(cm3202);
94         printk("Light Sensor cm3202 enter resume cm3202->status %d\n",cm3202->statue);
95 }
96 #endif
97 static int cm3202_open(struct inode *indoe, struct file *file)
98 {
99         return 0;
100 }
101
102 static int cm3202_release(struct inode *inode, struct file *file)
103 {
104         return 0;
105 }
106
107 static int cm3202_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
108 {
109         unsigned long *argp = (unsigned char *)arg;
110         switch(cmd){
111                 case LIGHTSENSOR_IOCTL_GET_ENABLED:
112                         *argp = light->statue;
113                         break;
114                 case LIGHTSENSOR_IOCTL_ENABLE:
115                         if(*argp)
116                                 cm3202_start(light);
117                         else
118                                 cm3202_stop(light);
119                         break;
120                 default:break;
121         }
122         return 0;
123 }
124
125 static void cm3202_value_report(struct input_dev *input, int data)
126 {
127         unsigned char index = 0;
128         if(data <= 10){
129                 index = 0;goto report;
130         }
131         else if(data <= 160){
132                 index = 1;goto report;
133         }
134         else if(data <= 225){
135                 index = 2;goto report;
136         }
137         else if(data <= 320){
138                 index = 3;goto report;
139         }
140         else if(data <= 640){
141                 index = 4;goto report;
142         }
143         else if(data <= 1280){
144                 index = 5;goto report;
145         }
146         else if(data <= 2600){
147                 index = 6;goto report;
148         }
149         else{
150                 index = 7;goto report;
151         }
152 report:
153         DBG("cm3202 report index = %d\n",index);
154         input_report_abs(input, ABS_MISC, index);
155         input_sync(input);
156         return;
157 }
158 static void callback(struct adc_client *client, void *param, int result)
159 {
160         DBG("[chn%d] cm3202 report value: %d\n", client->chn, result);
161         return;
162 }
163 static void adc_timer(unsigned long data)
164 {
165         struct cm3202_data *cm3202=(struct cm3202_data *)data;
166         schedule_work(&cm3202->timer_work);
167 }
168 static void adc_timer_work(struct work_struct *work)
169 {
170         int sync_read = 0;
171         struct cm3202_data *cm3202 = container_of(work, struct cm3202_data,timer_work);
172         adc_async_read(cm3202->client);
173         sync_read = adc_sync_read(cm3202->client);
174         cm3202_value_report(cm3202->input, sync_read);
175         if(cm3202->statue){
176                 cm3202->timer.expires  = jiffies + 3*HZ;
177                 add_timer(&cm3202->timer);
178         }
179 }
180
181 static struct file_operations cm3202_fops = {
182         .owner = THIS_MODULE,
183         .ioctl = cm3202_ioctl,
184         .open = cm3202_open,
185         .release = cm3202_release,
186 };
187
188 static struct miscdevice cm3202_device = {
189         .minor = MISC_DYNAMIC_MINOR,
190         .name = "lightsensor",
191         .fops = &cm3202_fops,
192 };
193
194 static int cm3202_probe(struct platform_device *pdev)
195 {
196         struct cm3202_data *cm3202;
197         struct cm3202_platform_data *pdata = pdata = pdev->dev.platform_data;
198         int err;
199         DBG("============= cm3202 probe enter ==============\n");
200         cm3202 = kmalloc(sizeof(struct cm3202_data), GFP_KERNEL);
201         if(!cm3202){
202                 printk("cm3202 alloc memory err !!!\n");
203                 err = -ENOMEM;
204                 goto alloc_memory_fail;
205         }       
206                 if(pdata->init_platform_hw)
207                 pdata->init_platform_hw();
208
209         cm3202->CM3202_SD = pdata->CM3202_SD_IOPIN;
210         DBG("===============================cm3202==========================\ncm3202_ADC_CHN = %d",pdata->DATA_ADC_CHN);
211         light = cm3202;
212         cm3202->client = adc_register(pdata->DATA_ADC_CHN, callback, NULL);
213         cm3202->statue = SENSOR_OFF;
214         cm3202->input = input_allocate_device();
215         if (!cm3202->input) {
216                 err = -ENOMEM;
217                 printk(KERN_ERR"cm3202: Failed to allocate input device\n");
218                 goto exit_input_allocate_device_failed;
219         }
220         set_bit(EV_ABS, cm3202->input->evbit);
221         /* light sensor data */
222         input_set_abs_params(cm3202->input, ABS_MISC, 0, 0x3ff, 0, 0);
223         cm3202->input->name = "lightsensor";
224
225         err = input_register_device(cm3202->input);
226         if (err < 0) {
227                 printk(KERN_ERR"cm3202: Unable to register input device: %s\n",cm3202->input->name);                                            
228                 goto exit_input_register_device_failed;
229         }
230         /*
231         ret = gpio_request(CM3202_SD_IOPIN, "cm3202_sd");
232         if (ret) {
233                 printk( "failed to request cm3202 SD GPIO%d\n",CM3202_SD_IOPIN);
234                 goto exit_gpio_request_fail;
235         }
236         DBG("cm3202 request INT inpin ok !!!");
237         gpio_pull_updown(CM3202_SD_IOPIN,GPIOPullDown); */
238         INIT_WORK(&cm3202->timer_work, adc_timer_work);
239         setup_timer(&cm3202->timer, adc_timer, (unsigned long)cm3202);
240         err = misc_register(&cm3202_device);
241         if (err < 0) {
242                 printk(KERN_ERR"cm3202_probe: lightsensor_device register failed\n");
243                 goto exit_misc_register_fail;
244         }
245         printk("lightsensor cm3202 driver created !\n");
246         //cm3202_start(light);
247 #ifdef CONFIG_HAS_EARLYSUSPEND
248         cm3202_early_suspend.suspend = cm3202_suspend;
249         cm3202_early_suspend.resume = cm3202_resume;
250         cm3202_early_suspend.level = 0x2;
251         register_early_suspend(&cm3202_early_suspend);
252 #endif
253         return 0;
254 exit_misc_register_fail:
255         gpio_free(pdata->CM3202_SD_IOPIN);
256         input_unregister_device(cm3202->input);
257 exit_input_register_device_failed:
258         input_free_device(cm3202->input);
259 exit_input_allocate_device_failed:
260         kfree(cm3202);
261 alloc_memory_fail:
262         printk("%s error\n",__FUNCTION__);
263         return err;
264 }
265
266 static int cm3202_remove(struct platform_device *pdev)
267 {
268         struct cm3202_data *cm3202 = light;
269         kfree(cm3202);
270         input_free_device(cm3202->input);
271         input_unregister_device(cm3202->input);
272         misc_deregister(&cm3202_device);
273         return 0;
274 }
275
276 static struct platform_driver cm3202_driver = {
277         .probe = cm3202_probe,
278         .remove = cm3202_remove,
279         .driver = {
280                 .owner = THIS_MODULE,
281                 .name = "lightsensor",
282         }
283 };
284
285 static int __init cm3202_init(void)
286 {
287         return platform_driver_register(&cm3202_driver);
288 }
289
290 static void __exit cm3202_exit(void)
291 {
292         platform_driver_unregister(&cm3202_driver);
293 }
294
295 module_init(cm3202_init);
296 module_exit(cm3202_exit);