rk3188 ds1006h: add lightsensor us5151
authorcdy <cdy@rock-chips.com>
Sun, 27 Jan 2013 03:30:12 +0000 (11:30 +0800)
committerwuhao <wuhao@wuhao@rock-chips.com>
Sun, 27 Jan 2013 03:30:12 +0000 (11:30 +0800)
arch/arm/configs/rk3188_ds1006h_defconfig
arch/arm/mach-rk3188/board-rk3188-ds1006h.c
drivers/input/lightsensor/Kconfig
drivers/input/lightsensor/Makefile
drivers/input/lightsensor/us5151.c [new file with mode: 0644]

index 2b89d6b5abb5327f7131a1d19f082696076059ad..70110426f0f78408da5c2e180e6e4ca3ffbf1a34 100644 (file)
@@ -242,7 +242,8 @@ CONFIG_COMPASS_AK8975=y
 CONFIG_GS_MMA8452=y
 CONFIG_GS_LIS3DH=y
 CONFIG_GYRO_L3G4200D=y
-CONFIG_LS_CM3217=y
+CONFIG_LIGHT_SENSOR_DEVICE=y
+CONFIG_LS_US5151=y
 CONFIG_SENSOR_DEVICE=y
 CONFIG_GSENSOR_DEVICE=y
 CONFIG_GS_KXTIK=y
index 2efcfa45de04832edfd981b841b8f1680fc1576d..2757b1f96b80a75e8cb97c824263ab5e0cbf4e77 100755 (executable)
@@ -1112,6 +1112,13 @@ static struct i2c_board_info __initdata i2c0_info[] = {
                .platform_data = &mma8452_info,
        },
 #endif
+#if defined (CONFIG_LS_US5151)
+        {    
+                .type           = "us5151",
+                .addr           = 0x10,
+                .flags          = 0, 
+        },   
+#endif
 #if defined (CONFIG_GS_LIS3DH)
        {
                .type           = "gs_lis3dh",
index a95de5a87d476d139945b600fe399c4eaf29977b..4afb3a6c11df639a507ae7e1b40e9c29ee0bfa8f 100644 (file)
@@ -26,5 +26,12 @@ config LS_CM3217
        help     
          To have support for your specific gsesnor you will have to
          select the proper drivers which depend on this option.
+config LS_US5151
+  bool "us5151"
+        depends on LIGHT_SENSOR_DEVICE
+        default n
+        help
+          To have support for your specific gsesnor you will have to
+          select the proper drivers which depend on this option.
          
 endif
index 08554c7dc42cf81c6d47c010ca58bb566e46d0d8..fa05b856b9e5ae912be34140ba569a4d88dd8d63 100644 (file)
@@ -2,4 +2,5 @@
 
 obj-$(CONFIG_CM3202)   += cm3202.o
 obj-$(CONFIG_LS_CM3217)        += cm3217.o
+obj-$(CONFIG_LS_US5151)        += us5151.o
 
diff --git a/drivers/input/lightsensor/us5151.c b/drivers/input/lightsensor/us5151.c
new file mode 100644 (file)
index 0000000..6fd6009
--- /dev/null
@@ -0,0 +1,392 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/adc.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <asm/gpio.h>
+#include <asm/uaccess.h>
+#include <linux/timer.h>
+#include <linux/input.h>
+#include <linux/ioctl.h>
+//#include <mach/rk29_sdk_io.h>
+#include <mach/board.h> 
+#include <linux/platform_device.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#define DEBUG  0
+
+#define  POWER_PIN  NULL//RK29_PIN6_PA0
+
+#if DEBUG
+#define DBG(X...)      printk(KERN_NOTICE X)
+#else
+#define DBG(X...)
+#endif
+
+//#define DATA_ADC_CHN 2       //SARADC_AIN[3]
+#define SENSOR_ON      1
+#define SENSOR_OFF     0
+#define LIGHTSENSOR_IOCTL_MAGIC 'l'
+#define LIGHTSENSOR_IOCTL_GET_ENABLED   _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *) 
+#define LIGHTSENSOR_IOCTL_ENABLE        _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *) 
+#define LIGHTSENSOR_IOCTL_DISABLE        _IOW(LIGHTSENSOR_IOCTL_MAGIC, 3, int *)
+
+struct us5151_data {
+       struct timer_list       timer;
+       struct work_struct      timer_work;
+       struct input_dev        *input;
+       struct i2c_client *client;
+       int statue;
+};
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend us5151_early_suspend;
+#endif
+static struct us5151_data *light;
+
+static int us5151_rx_data(struct i2c_client *client, char *rxData, int length)
+{
+       int ret = 0;
+       char reg = rxData[0];
+       DBG("%s.....%d...\n",__FUNCTION__,__LINE__);
+       ret = i2c_master_reg8_recv(client, reg, rxData, length, 250*1000);
+       return (ret > 0)? 0 : ret;
+}
+
+static int us5151_tx_data(struct i2c_client *client, char *txData, int length)
+{
+       int ret = 0;
+       char reg = txData[0];
+       char i = 0;
+       DBG("%s.....%d...\n",__FUNCTION__,__LINE__);
+
+       ret =i2c_master_normal_send(client,txData,length,250*1000);
+       //ret = i2c_master_reg8_send(client, reg, &txData[1], length-1, 250*1000);
+       return (ret > 0)? 0 : ret;
+}
+
+static char start_flag = 0;
+static int us5151_start(struct us5151_data *data)
+{
+       struct us5151_data *us5151 = data;
+       int ret = 0;
+       char txData[2] = {0x01,0x80}; 
+       
+       DBG("%s.....%d...\n",__FUNCTION__,__LINE__);
+       if(us5151->statue)
+               return 0;
+       ret = us5151_tx_data(us5151->client,txData,sizeof(txData));
+       if (ret == 0)
+       {
+               us5151->statue = SENSOR_ON;
+               us5151->timer.expires  = jiffies + 3*HZ;
+               add_timer(&us5151->timer);
+       }
+       else
+       {
+               us5151->statue = 0;
+               printk("%s......%d ret=%d\n",__FUNCTION__,__LINE__,ret);
+       }
+       printk("========== us5151 light sensor start ==========\n");
+       return 0;
+}
+
+static int us5151_stop(struct us5151_data *data)
+{
+       struct us5151_data *us5151 = data;
+       int ret = 0;
+       char txData[2] = {0x01,0x00}; 
+
+       DBG("%s.....%d...\n",__FUNCTION__,__LINE__);
+       if(us5151->statue == 0)
+               return 0;
+       
+       ret = us5151_tx_data(us5151->client,txData,sizeof(txData));
+       if (ret == 0)
+       {
+               us5151->statue = SENSOR_OFF;
+               del_timer(&us5151->timer);
+       }
+       else
+       {
+               us5151->statue = 0;
+               printk("%s......%d ret=%d\n",__FUNCTION__,__LINE__,ret);
+       }
+       printk("========== us5151 light sensor stop ==========\n");
+       return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void us5151_suspend(struct early_suspend *h)
+{
+       struct us5151_data *us5151 = light;
+       
+       if (start_flag == 1)
+               us5151_stop(us5151);
+       
+       printk("Light Sensor us5151 enter suspend us5151->status %d\n",us5151->statue);
+}
+
+static void us5151_resume(struct early_suspend *h)
+{
+       struct us5151_data *us5151 = light;
+       
+       if (start_flag == 1)
+               us5151_start(us5151);
+       
+       printk("Light Sensor us5151 enter resume us5151->status %d\n",us5151->statue);
+}
+#endif
+static int us5151_open(struct inode *indoe, struct file *file)
+{
+       DBG("%s.....%d\n",__FUNCTION__,__LINE__);
+       return 0;
+}
+
+static int us5151_release(struct inode *inode, struct file *file)
+{
+       DBG("%s.....%d\n",__FUNCTION__,__LINE__);
+       return 0;
+}
+
+static long us5151_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       unsigned long *argp = (unsigned long *)arg;
+
+       DBG("%s.....%d\n",__FUNCTION__,__LINE__);
+       switch(cmd){
+               case LIGHTSENSOR_IOCTL_GET_ENABLED:
+                       *argp = light->statue;
+                       break;
+               case LIGHTSENSOR_IOCTL_ENABLE:
+                       if(*argp)
+                       {
+                               start_flag = 1;
+                               us5151_start(light);
+                       }
+                       else
+                       {
+                               start_flag = 0;
+                               us5151_stop(light);
+                       }
+                       break;
+               default:break;
+       }
+       return 0;
+}
+
+static void us5151_value_report(struct input_dev *input, int data)
+{
+       unsigned char index = 0;
+       if(data <= 30){
+               index = 0;goto report;
+       }
+       else if(data <= 100){
+               index = 1;goto report;
+       }
+       else if(data <= 150){
+               index = 2;goto report;
+       }
+       else if(data <= 220){
+               index = 3;goto report;
+       }
+       else if(data <= 280){
+               index = 4;goto report;
+       }
+       else if(data <= 350){
+               index = 5;goto report;
+       }
+       else if(data <= 420){
+               index = 6;goto report;
+       }
+       else{
+               index = 7;goto report;
+       }
+report:
+       DBG("us5151 report index = %d data=%d\n",index,data);
+       input_report_abs(input, ABS_MISC, index);
+       input_sync(input);
+       return;
+}
+
+static void us5151_read(struct work_struct *work)
+{
+
+       int ret = 0;
+       int adc_value = 35541;
+       char value[2] = {0x02,0x03};
+       char enable[1] = {0x01};
+
+       struct us5151_data *us5151 = container_of(work, struct us5151_data,timer_work);
+
+       ret = us5151_rx_data(us5151->client,value,sizeof(value));
+       ret = us5151_rx_data(us5151->client,enable,sizeof(enable));
+       if (ret == 0)
+       {
+               adc_value = value[1]>>7 | value[0]<<1;
+               DBG("%s......%d ret=%d value[0]=%d value[1]=%d adc_value=%d enable=%d\n",__FUNCTION__,__LINE__,ret,value[0],value[1],adc_value,enable[0]);              
+               us5151_value_report(us5151->input,adc_value);
+       }
+       else
+       {
+               //us5151->statue = 0;
+               printk("%s......%d ret=%d value[0]=%d value[1]=%d adc_value=%d\n",__FUNCTION__,__LINE__,ret,value[0],value[1],adc_value);
+       }
+
+       if(us5151->statue){
+               us5151->timer.expires  = jiffies + 3*HZ;
+               add_timer(&us5151->timer);
+       }
+};
+
+static void us5151_read_value(unsigned long data)
+{
+       struct us5151_data *us5151=(struct us5151_data *)data;
+       schedule_work(&us5151->timer_work);
+};
+static struct file_operations us5151_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = us5151_ioctl,
+       .open = us5151_open,
+       .release = us5151_release,
+};
+
+static struct miscdevice us5151_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "lightsensor",
+       .fops = &us5151_fops,
+};
+
+static ssize_t us5151_start_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+
+       DBG("%s......\n",__FUNCTION__);
+       if (*buf == 'A')
+               us5151_start(light);
+       else
+       {
+               us5151_stop(light);
+               printk("%s.........%s\n",__FUNCTION__,buf);
+       }
+
+       return len;
+};
+static DEVICE_ATTR(start,0666,NULL,us5151_start_store);
+
+static int us5151_probe(struct i2c_client *pdev,const struct i2c_device_id *id)
+{
+       struct us5151_data *us5151;
+       struct us5151_platform_data *pdata = pdata = pdev->dev.platform_data;
+       int err;
+       DBG("============= us5151 probe enter ==============\n");
+       us5151 = kmalloc(sizeof(struct us5151_data), GFP_KERNEL);
+       if(!us5151){
+               printk("us5151 alloc memory err !!!\n");
+               err = -ENOMEM;
+               goto alloc_memory_fail;
+       }
+       light = us5151;
+       us5151->statue = SENSOR_OFF;
+       us5151->client = pdev;
+       us5151->input = input_allocate_device();
+       if (!us5151->input) {
+               err = -ENOMEM;
+               printk(KERN_ERR"us5151: Failed to allocate input device\n");
+               goto exit_input_allocate_device_failed;
+       }
+       set_bit(EV_ABS, us5151->input->evbit);
+       /* light sensor data */
+       input_set_abs_params(us5151->input, ABS_MISC, 0, 0x1ff, 0, 0);
+       us5151->input->name = "lightsensor-level";
+
+       err = input_register_device(us5151->input);
+       if (err < 0) {
+               printk(KERN_ERR"us5151: Unable to register input device: %s\n",us5151->input->name);                                            
+               goto exit_input_register_device_failed;
+       }
+
+       INIT_WORK(&us5151->timer_work,us5151_read);
+       setup_timer(&us5151->timer, us5151_read_value, (unsigned long)us5151);
+       
+       err = misc_register(&us5151_device);
+       if (err < 0) {
+               printk(KERN_ERR"us5151_probe: lightsensor_device register failed\n");
+               goto exit_misc_register_fail;
+       }
+       
+     err = device_create_file(&pdev->dev, &dev_attr_start);
+     if (err)
+     {
+       
+               printk("%s....make a mistake in creating devices  attr file\n\n ",__FUNCTION__);
+     }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       us5151_early_suspend.suspend = us5151_suspend;
+       us5151_early_suspend.resume = us5151_resume;
+       us5151_early_suspend.level = 0x2;
+       register_early_suspend(&us5151_early_suspend);
+#endif
+
+       printk("lightsensor us5151 driver created !\n");
+       //us5151_start(light);
+       return 0;
+exit_misc_register_fail:
+       input_unregister_device(us5151->input);
+exit_input_register_device_failed:
+       input_free_device(us5151->input);
+exit_input_allocate_device_failed:
+       kfree(us5151);
+alloc_memory_fail:
+       printk("%s error\n",__FUNCTION__);
+       return err;
+}
+
+static __devexit int  us5151_remove(struct i2c_client *pdev)
+{
+       struct us5151_data *us5151 = light;
+       kfree(us5151);
+       input_free_device(us5151->input);
+       input_unregister_device(us5151->input);
+       misc_deregister(&us5151_device);
+       return 0;
+}
+
+static const struct i2c_device_id us5151_i2c_id[] = {
+       { "us5151", 0 },
+       { }
+};
+
+static struct i2c_driver us5151_driver = {
+       .probe = us5151_probe,
+       .remove = __devexit_p(us5151_remove),
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "lightsensor",
+       },
+       .id_table = us5151_i2c_id,
+};
+
+static int __init us5151_init(void)
+{
+       return i2c_add_driver(&us5151_driver);
+}
+
+static void __exit us5151_exit(void)
+{
+       i2c_del_driver(&us5151_driver);
+}
+
+module_init(us5151_init);
+module_exit(us5151_exit);