1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/device.h>
8 #include <linux/delay.h>
10 #include <linux/sched.h>
12 #include <linux/sysctl.h>
13 #include <linux/miscdevice.h>
14 #include <linux/slab.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>
30 #define DBG(X...) printk(KERN_NOTICE X)
35 #define CM3217_I2C_RATE (200*1000)
36 #define CM3217_ADDR_COM1 0x10
37 #define CM3217_ADDR_COM2 0x11
38 #define CM3217_ADDR_DATA_MSB 0x10
39 #define CM3217_ADDR_DATA_LSB 0x11
41 #define CM3217_COM1_VALUE 0xA7 // (GAIN1:GAIN0)=10, (IT_T1:IT_TO)=01,WMD=1,SD=1,
42 #define CM3217_COM2_VALUE 0xA0 //100ms
47 #define LIGHTSENSOR_IOCTL_MAGIC 'l'
48 #define LIGHTSENSOR_IOCTL_GET_ENABLED _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *)
49 #define LIGHTSENSOR_IOCTL_ENABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *)
50 #define LIGHTSENSOR_IOCTL_DISABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 3, int *)
53 struct i2c_client *client;
54 struct timer_list timer;
55 struct work_struct timer_work;
56 struct input_dev *input;
61 #ifdef CONFIG_HAS_EARLYSUSPEND
62 static struct early_suspend cm3217_early_suspend;
64 static struct cm3217_data *glight;
66 static int cm3217_command_set(struct i2c_client *client, char *buf, int num)
69 ret = i2c_master_normal_send(client, buf, num, CM3217_I2C_RATE);
71 return (ret == num) ? 0 : ret;
74 static int cm3217_command_get(struct i2c_client *client, char *buf, int num)
77 ret = i2c_master_normal_recv(client, buf, num, CM3217_I2C_RATE);
79 return (ret == num) ? 0 : ret;
83 static int cm3217_start(struct cm3217_data *data)
85 struct cm3217_data *cm3217 = data;
90 //if(cm3217->power_pin != INVALID_GPIO)
91 //gpio_direction_output(cm3217->power_pin,0);//level = 0 Sensor ON
93 buf = CM3217_COM1_VALUE & 0xfe ; //SD=0
94 cm3217->client->addr = CM3217_ADDR_COM1;
95 cm3217_command_set(cm3217->client, &buf, 1);
97 cm3217->status = SENSOR_ON;
98 cm3217->timer.expires = jiffies + 1*HZ;
99 add_timer(&cm3217->timer);
100 DBG("cm3217 light sensor start\n");
104 static int cm3217_stop(struct cm3217_data *data)
106 struct cm3217_data *cm3217 = data;
108 if(cm3217->status == 0)
111 //if(cm3217->power_pin != INVALID_GPIO)
112 //gpio_direction_output(cm3217->power_pin,1);//level = 1 Sensor OFF
114 buf = CM3217_COM1_VALUE | 0x01 ; //SD=1
115 cm3217->client->addr = CM3217_ADDR_COM1;
116 cm3217_command_set(cm3217->client, &buf, 1);
118 cm3217->status = SENSOR_OFF;
119 del_timer(&cm3217->timer);
120 DBG("cm3217 light sensor stop\n");
124 #ifdef CONFIG_HAS_EARLYSUSPEND
125 static void cm3217_suspend(struct early_suspend *h)
127 struct cm3217_data *cm3217 = glight;
128 int status = cm3217->status;
130 cm3217->status = status;
131 DBG("Light Sensor cm3217 enter suspend cm3217->status %d\n",cm3217->status);
134 static void cm3217_resume(struct early_suspend *h)
136 struct cm3217_data *cm3217 = glight;
137 if(cm3217->status == SENSOR_ON)
138 cm3217_start(cm3217);
139 DBG("Light Sensor cm3217 enter resume cm3217->status %d\n",cm3217->status);
142 static int cm3217_open(struct inode *indoe, struct file *file)
147 static int cm3217_release(struct inode *inode, struct file *file)
153 static long cm3217_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
155 unsigned int *argp = (unsigned int *)arg;
156 struct cm3217_data *cm3217 = glight;
158 case LIGHTSENSOR_IOCTL_GET_ENABLED:
159 *argp = cm3217->status;
161 case LIGHTSENSOR_IOCTL_ENABLE:
163 cm3217_start(cm3217);
172 static void cm3217_value_report(struct input_dev *input, int data)
174 unsigned char index = 0;
176 index = 0;goto report;
178 else if(data <= 160){
179 index = 1;goto report;
181 else if(data <= 225){
182 index = 2;goto report;
184 else if(data <= 320){
185 index = 3;goto report;
187 else if(data <= 640){
188 index = 4;goto report;
190 else if(data <= 1280){
191 index = 5;goto report;
193 else if(data <= 2600){
194 index = 6;goto report;
197 index = 7;goto report;
201 DBG("cm3217 report data=%d,index = %d\n",data,index);
202 input_report_abs(input, ABS_MISC, index);
207 static void adc_timer(unsigned long data)
209 struct cm3217_data *cm3217=(struct cm3217_data *)data;
210 schedule_work(&cm3217->timer_work);
213 static void adc_timer_work(struct work_struct *work)
216 struct cm3217_data *cm3217 = container_of(work, struct cm3217_data,timer_work);
217 char msb = 0, lsb = 0;
219 cm3217->client->addr = CM3217_ADDR_DATA_LSB;
220 cm3217_command_get(cm3217->client, &lsb, 1);
221 cm3217->client->addr = CM3217_ADDR_DATA_MSB;
222 cm3217_command_get(cm3217->client, &msb, 1);
223 result = ((msb << 8) | lsb) & 0xffff;
224 cm3217_value_report(cm3217->input, result);
225 DBG("%s:result=%d\n",__func__,result);
228 cm3217->timer.expires = jiffies + 1*HZ;
229 add_timer(&cm3217->timer);
233 static struct file_operations cm3217_fops = {
234 .owner = THIS_MODULE,
236 .release = cm3217_release,
237 .unlocked_ioctl = cm3217_ioctl,
240 static struct miscdevice cm3217_device = {
241 .minor = MISC_DYNAMIC_MINOR,
242 .name = "lightsensor",
243 .fops = &cm3217_fops,
246 static int cm3217_probe(struct i2c_client *client, const struct i2c_device_id *id)
248 struct cm3217_data *cm3217;
249 struct cm3217_platform_data *pdata = pdata = client->dev.platform_data;
250 char com1 = CM3217_COM1_VALUE, com2 = CM3217_COM2_VALUE;
253 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
255 dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
257 goto alloc_memory_fail;
260 cm3217 = kmalloc(sizeof(struct cm3217_data), GFP_KERNEL);
262 printk("cm3217 alloc memory err !!!\n");
264 goto alloc_memory_fail;
267 if(pdata->init_platform_hw)
268 pdata->init_platform_hw();
270 cm3217->client = client;
271 i2c_set_clientdata(client, cm3217);
272 cm3217->power_pin = pdata->power_pin;
273 cm3217->irq_pin = pdata->irq_pin;
274 cm3217->status = SENSOR_OFF;
278 client->addr = CM3217_ADDR_COM1;
279 cm3217_command_set(client, &com1, 1);
280 client->addr = CM3217_ADDR_COM2;
281 cm3217_command_set(client, &com2, 1);
283 cm3217->input = input_allocate_device();
284 if (!cm3217->input) {
286 printk(KERN_ERR"cm3217: Failed to allocate input device\n");
287 goto exit_input_allocate_device_failed;
289 set_bit(EV_ABS, cm3217->input->evbit);
290 /* light sensor data */
291 input_set_abs_params(cm3217->input, ABS_MISC, 0, 10, 0, 0);
292 cm3217->input->name = "lightsensor-level";
294 err = input_register_device(cm3217->input);
296 printk(KERN_ERR"cm3217: Unable to register input device: %s\n",cm3217->input->name);
297 goto exit_input_register_device_failed;
300 if(cm3217->power_pin != INVALID_GPIO)
302 gpio_request(cm3217->power_pin, "cm3217_power_pin");
303 gpio_pull_updown(cm3217->power_pin,PullDisable);
306 INIT_WORK(&cm3217->timer_work, adc_timer_work);
307 setup_timer(&cm3217->timer, adc_timer, (unsigned long)cm3217);
308 err = misc_register(&cm3217_device);
310 printk(KERN_ERR"cm3217_probe: lightsensor_device register failed\n");
311 goto exit_misc_register_fail;
313 printk("lightsensor cm3217 driver created !\n");
314 //cm3217_start(cm3217);
315 #ifdef CONFIG_HAS_EARLYSUSPEND
316 cm3217_early_suspend.suspend = cm3217_suspend;
317 cm3217_early_suspend.resume = cm3217_resume;
318 cm3217_early_suspend.level = 0x2;
319 register_early_suspend(&cm3217_early_suspend);
322 exit_misc_register_fail:
323 //gpio_free(pdata->power_pin);
324 input_unregister_device(cm3217->input);
325 exit_input_register_device_failed:
326 input_free_device(cm3217->input);
327 exit_input_allocate_device_failed:
330 printk("%s error\n",__FUNCTION__);
334 static int cm3217_remove(struct i2c_client *client)
336 struct cm3217_data *cm3217 = i2c_get_clientdata(client);
338 input_free_device(cm3217->input);
339 input_unregister_device(cm3217->input);
340 misc_deregister(&cm3217_device);
344 static const struct i2c_device_id cm3217_id[] = {
345 { "lightsensor", 0 },
348 static void cm3217_shutdown(struct i2c_client *client)
350 #ifdef CONFIG_HAS_EARLYSUSPEND
351 unregister_early_suspend(&cm3217_early_suspend);
355 static struct i2c_driver cm3217_driver = {
356 .probe = cm3217_probe,
357 .remove = __devexit_p(cm3217_remove),
358 .shutdown = cm3217_shutdown,
359 .id_table = cm3217_id,
361 .owner = THIS_MODULE,
362 .name = "lightsensor",
367 static int __init cm3217_init(void)
369 return i2c_add_driver(&cm3217_driver);
372 static void __exit cm3217_exit(void)
374 i2c_del_driver(&cm3217_driver);
377 module_init(cm3217_init);
378 module_exit(cm3217_exit);