1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/init.h>
5 #include <linux/interrupt.h>
6 #include <linux/sched.h>
8 #include <linux/sysctl.h>
9 #include <linux/proc_fs.h>
10 #include <linux/platform_device.h>
11 #include <linux/miscdevice.h>
12 #include <linux/slab.h>
14 #include <asm/uaccess.h>
15 #include <linux/timer.h>
16 #include <linux/input.h>
17 #include <linux/adc.h>
18 #include <linux/delay.h>
19 #include <linux/string.h>
21 #ifdef CONFIG_HAS_EARLYSUSPEND
22 #include <linux/earlysuspend.h>
25 #include <mach/rk29_lightsensor.h>
26 #ifdef CONFIG_HAS_EARLYSUSPEND
27 static struct early_suspend cm3202_early_suspend;
31 struct rk29_lsr_platform_data *lightsensor;
32 static void lsr_report_value(struct input_dev *input_dev, int value)
34 input_report_abs(input_dev, ABS_MISC/*ABS_X*/, value);
35 input_sync(input_dev);
39 static inline void timer_callback(unsigned long data)
43 adc_async_read(lightsensor->client);
44 mutex_lock(&lightsensor->lsr_mutex);
45 rate = lightsensor->rate;
46 mutex_unlock(&lightsensor->lsr_mutex);
47 if(lightsensor->client->result != lightsensor->oldresult)
49 lsr_report_value(lightsensor->input_dev, lightsensor->client->result);
50 lightsensor->oldresult = lightsensor->client->result;
52 ret = mod_timer( &lightsensor->timer, jiffies + msecs_to_jiffies(RATE(rate)));
54 printk("Error in mod_timer\n");
56 static inline void set_lsr_value(bool state)
59 lightsensor->lsr_state = 1;
61 lightsensor->lsr_state = 0;
62 gpio_direction_output(LSR_GPIO, lightsensor->lsr_state);
63 gpio_set_value(LSR_GPIO, lightsensor->lsr_state);
66 static inline unsigned int get_lsr_value(void)
68 if(0 == lightsensor->lsr_state)
74 static inline unsigned int get_adc_value(void)
77 return lightsensor->client->result;
80 static inline unsigned int set_lsr_rate(unsigned int value)
82 mutex_lock(&lightsensor->lsr_mutex);
87 lightsensor->rate = value;
88 mutex_unlock(&lightsensor->lsr_mutex);
91 static inline unsigned int set_lsr_timer(unsigned int value)
95 if(1 != lightsensor->timer_on)
97 add_timer(&lightsensor->timer);
98 lightsensor->timer_on = 1;
104 if(0 != lightsensor->timer_on)
106 del_timer(&lightsensor->timer);
107 lightsensor->timer_on = 0;
116 static ssize_t lsr_store_value(struct device *dev,
117 struct device_attribute *attr,
118 const char *buf, size_t count)
123 if (strict_strtoul(buf, 10, &val) < 0)
128 set_lsr_value(false);
132 static ssize_t lsr_show_value(struct device *dev,
133 struct device_attribute *attr, char *buf)
135 return sprintf(buf, "lsr value:%d\nadc value:%d\n", get_lsr_value(),get_adc_value());
138 static DEVICE_ATTR(value, S_IWUSR|S_IRUGO, lsr_show_value, lsr_store_value );
140 static struct attribute *lsr_attributes[] = {
141 &dev_attr_value.attr,
145 static const struct attribute_group lsr_attr_group = {
146 .attrs = lsr_attributes,
148 static int rk29_lsr_io_init(struct platform_device *dev)
151 struct platform_device *pdev = dev;
152 struct rk29_lsr_platform_data *pdata = pdev->dev.platform_data;
154 err = gpio_request(pdata->gpio, pdata->desc ?: "rk29-lsr");
156 gpio_free(pdata->gpio);
157 printk("-------request RK29_PIN6_PB1 fail--------\n");
161 gpio_direction_output(pdata->gpio, pdata->active_low);
162 gpio_set_value(pdata->gpio, pdata->active_low);
163 set_lsr_value(STARTUP_LEV_LOW);
164 err = sysfs_create_group(&pdev->dev.kobj, &lsr_attr_group);
167 static int rk29_lsr_io_deinit(struct platform_device *dev)
169 struct platform_device *pdev = dev;
170 struct rk29_lsr_platform_data *pdata = pdev->dev.platform_data;
172 gpio_direction_output(pdata->gpio, pdata->active_low);
173 gpio_set_value(pdata->gpio, pdata->active_low);
175 gpio_free(pdata->gpio);
176 sysfs_remove_group(&pdev->dev.kobj, &lsr_attr_group);
179 static void callback(struct adc_client *client, void *callback_param, int result)
181 client->result = result;
183 static int rk29_lsr_adc_init(struct platform_device *dev)
185 struct rk29_lsr_platform_data *pdata = dev->dev.platform_data;
186 pdata->client = adc_register(pdata->adc_chn, callback, "lsr_adc");
189 mutex_init(&pdata->lsr_mutex);
192 static void rk29_lsr_adc_deinit(struct platform_device *dev)
194 struct rk29_lsr_platform_data *pdata = dev->dev.platform_data;
195 adc_unregister(pdata->client);
196 mutex_destroy(&pdata->lsr_mutex);
199 static void rk29_lsr_timer_init(struct platform_device *dev)
202 struct rk29_lsr_platform_data *pdata = dev->dev.platform_data;
203 setup_timer(&pdata->timer, timer_callback, 0);
204 lightsensor->timer_on = 1;
205 ret = mod_timer( &pdata->timer, jiffies + msecs_to_jiffies(pdata->delay_time) );
207 printk("Error in mod_timer\n");
210 static void rk29_lsr_timer_deinit(struct platform_device *dev)
212 struct rk29_lsr_platform_data *pdata = dev->dev.platform_data;
213 del_timer(&pdata->timer);
214 lightsensor->timer_on = 0;
217 static void rk29_lsr_input_init(struct platform_device *dev)
220 struct rk29_lsr_platform_data *pdata = dev->dev.platform_data;
221 pdata->input_dev = input_allocate_device();
222 if (!pdata->input_dev) {
223 printk(KERN_ERR"rk29_lsr_input_init: Failed to allocate input device\n");
224 goto init_input_register_device_failed;
226 pdata->input_dev->name = "lsensor";
227 pdata->input_dev->dev.parent = &dev->dev;
228 pdata->input_dev->evbit[0] = BIT(EV_ABS);
229 input_set_abs_params(pdata->input_dev,ABS_MISC/*ABS_X*/,0,9/*0x3ff*/,0,0);
230 ret = input_register_device(pdata->input_dev);
232 init_input_register_device_failed:
233 input_free_device(pdata->input_dev);
236 static void rk29_lsr_input_deinit(struct platform_device *dev)
238 struct rk29_lsr_platform_data *pdata = dev->dev.platform_data;
239 input_unregister_device(pdata->input_dev);
240 input_free_device(pdata->input_dev);
242 static int lsr_suspend(struct platform_device *pdev, pm_message_t state)
245 set_lsr_value(LSR_OFF);
249 static int lsr_resume(struct platform_device *pdev)
252 set_lsr_value(LSR_ON);
255 static int __devinit lsr_probe(struct platform_device *pdev)
257 lightsensor = kzalloc(sizeof(struct rk29_lsr_platform_data), GFP_KERNEL);
260 dev_err(&pdev->dev, "no memory for state\n");
261 goto err_kzalloc_lightsensor;
263 lightsensor->gpio = LSR_GPIO;
264 lightsensor->desc = "rk29-lsr";
265 lightsensor->adc_chn = 2;
266 lightsensor->delay_time = 1000;
267 lightsensor->rate = 100;
268 lightsensor->oldresult = 0;
269 lightsensor->active_low = STARTUP_LEV_LOW;
270 pdev->dev.platform_data = lightsensor;
271 rk29_lsr_io_init(pdev);
272 rk29_lsr_adc_init(pdev);
273 rk29_lsr_timer_init(pdev);
274 rk29_lsr_input_init(pdev);
275 #ifdef CONFIG_HAS_EARLYSUSPEND
276 cm3202_early_suspend.suspend = lsr_suspend;
277 cm3202_early_suspend.resume = lsr_resume;
278 register_early_suspend(&cm3202_early_suspend);
283 err_kzalloc_lightsensor:
289 static int __devexit lsr_remove(struct platform_device *pdev)
291 rk29_lsr_io_deinit(pdev);
292 rk29_lsr_adc_deinit(pdev);
293 rk29_lsr_timer_deinit(pdev);
294 rk29_lsr_input_deinit(pdev);
299 static struct platform_driver lsr_device_driver = {
301 .remove = __devexit_p(lsr_remove),
302 // .suspend = lsr_suspend,
303 // .resume = lsr_resume,
306 .owner = THIS_MODULE,
310 static int lsr_adc_open(struct inode * inode, struct file * file)
312 set_lsr_value(LSR_ON);
316 static int lsr_adc_ioctl(struct tty_struct * tty,struct file * file,unsigned int cmd, unsigned long arg)
321 case LSR_IOCTL_ENABLE:
324 case LSR_IOCTL_SETRATE:
327 case LSR_IOCTL_DEVNAME:
328 ret = copy_to_user((void __user *)arg,lightsensor->input_dev->name,strlen(lightsensor->input_dev->name)+1);
330 case LSR_IOCTL_SWICTH:
339 static ssize_t lsr_adc_read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
342 ret = copy_to_user(userbuf,&lightsensor->client->result,bytes);
346 static struct file_operations lsr_adc_fops = {
347 .owner = THIS_MODULE,
348 .open = lsr_adc_open,
349 .read = lsr_adc_read,
350 .ioctl = lsr_adc_ioctl,
353 static struct miscdevice misc_lsr_adc_device = {
354 .minor = MISC_DYNAMIC_MINOR,
356 .fops = &lsr_adc_fops,
359 static int __init lsr_init(void)
361 platform_driver_register(&lsr_device_driver);
362 misc_register(&misc_lsr_adc_device);
366 static void __exit lsr_exit(void)
368 platform_driver_unregister(&lsr_device_driver);
369 misc_deregister(&misc_lsr_adc_device);
372 module_init(lsr_init);
373 module_exit(lsr_exit);
375 MODULE_LICENSE("GPL");
376 MODULE_AUTHOR("Seven Huang <sevenxuemin@sina.com>");
377 MODULE_DESCRIPTION("Light sensor for Backlight");
378 MODULE_ALIAS("platform:gpio-lightsensor");