/* drivers/input/sensors/access/kxtik.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/#include<linux/interrupt.h>#include<linux/i2c.h>#include<linux/slab.h>#include<linux/irq.h>#include<linux/miscdevice.h>#include<linux/gpio.h>#include<linux/uaccess.h>#include<asm/atomic.h>#include<linux/delay.h>#include<linux/input.h>#include<linux/workqueue.h>#include<linux/freezer.h>#include<linux/of_gpio.h>#ifdefCONFIG_HAS_EARLYSUSPEND#include<linux/earlysuspend.h>#endif#include<linux/sensor-dev.h>#defineCM3217_ADDR_COM10x10#defineCM3217_ADDR_COM20x11#defineCM3217_ADDR_DATA_MSB0x10#defineCM3217_ADDR_DATA_LSB0x11#defineCM3217_COM1_VALUE0xA7// (GAIN1:GAIN0)=10, (IT_T1:IT_TO)=01,WMD=1,SD=1,#defineCM3217_COM2_VALUE0xA0//100ms#defineCM3217_CLOSE0x01/****************operate according to sensor chip:start************/staticintsensor_active(structi2c_client*client,int enable,int rate){structsensor_private_data*sensor =(structsensor_private_data*)i2c_get_clientdata(client);int result =0;int status =0;
sensor->client->addr = sensor->ops->ctrl_reg;
sensor->ops->ctrl_data =sensor_read_reg_normal(client);//register setting according to chip datasheetif(!enable){
status = CM3217_CLOSE;//cm3217
sensor->ops->ctrl_data |= status;}else{
status =~CM3217_CLOSE;//cm3217
sensor->ops->ctrl_data &= status;}DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
result =sensor_write_reg_normal(client, sensor->ops->ctrl_data);if(result)printk("%s:fail to active sensor\n",__func__);return result;}staticintsensor_init(structi2c_client*client){structsensor_private_data*sensor =(structsensor_private_data*)i2c_get_clientdata(client);int result =0;
result = sensor->ops->active(client,0,0);if(result){printk("%s:line=%d,error\n",__func__,__LINE__);return result;}
sensor->status_cur = SENSOR_OFF;
sensor->client->addr = sensor->ops->ctrl_reg;
sensor->ops->ctrl_data = CM3217_COM1_VALUE;
result =sensor_write_reg_normal(client, sensor->ops->ctrl_data);if(result){printk("%s:line=%d,error\n",__func__,__LINE__);return result;}
sensor->client->addr = CM3217_ADDR_COM2;
result =sensor_write_reg_normal(client, CM3217_COM2_VALUE);if(result){printk("%s:line=%d,error\n",__func__,__LINE__);return result;}return result;}staticintlight_report_value(structinput_dev*input,int data){unsignedchar index =0;if(data <=10){
index =0;goto report;}elseif(data <=160){
index =1;goto report;}elseif(data <=225){
index =2;goto report;}elseif(data <=320){
index =3;goto report;}elseif(data <=640){
index =4;goto report;}elseif(data <=1280){
index =5;goto report;}elseif(data <=2600){
index =6;goto report;}else{
index =7;goto report;}
report:input_report_abs(input, ABS_MISC, index);input_sync(input);return index;}staticintsensor_report_value(structi2c_client*client){structsensor_private_data*sensor =(structsensor_private_data*)i2c_get_clientdata(client);int result =0;char msb =0, lsb =0;int index =0;
sensor->client->addr = CM3217_ADDR_DATA_LSB;sensor_rx_data_normal(sensor->client,&lsb,1);
sensor->client->addr = CM3217_ADDR_DATA_MSB;sensor_rx_data_normal(sensor->client,&msb,1);
result =((msb <<8)| lsb)&0xffff;
index =light_report_value(sensor->input_dev, result);DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, result,index);if((sensor->pdata->irq_enable)&&(sensor->ops->int_status_reg >=0))//read sensor intterupt status register{
result=sensor_read_reg(client, sensor->ops->int_status_reg);if(result){printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,result);}}return result;}structsensor_operate light_cm3217_ops ={.name ="cm3217",.type = SENSOR_TYPE_LIGHT,//sensor type and it should be correct.id_i2c = LIGHT_ID_CM3217,//i2c id number.read_reg = CM3217_ADDR_DATA_LSB,//read data.read_len =2,//data length.id_reg = SENSOR_UNKNOW_DATA,//read device id from this register.id_data = SENSOR_UNKNOW_DATA,//device id.precision =8,//8 bits.ctrl_reg = CM3217_ADDR_COM1,//enable or disable.int_status_reg = SENSOR_UNKNOW_DATA,//intterupt status register.range ={100,65535},//range.brightness ={10,255},// brightness.trig = SENSOR_UNKNOW_DATA,.active = sensor_active,.init = sensor_init,.report = sensor_report_value,};/****************operate according to sensor chip:end************/staticintlight_cm3217_probe(structi2c_client*client,conststructi2c_device_id*devid){returnsensor_register_device(client,NULL, devid,&light_cm3217_ops);}staticintlight_cm3217_remove(structi2c_client*client){returnsensor_unregister_device(client,NULL,&light_cm3217_ops);}staticconststructi2c_device_id light_cm3217_id[]={{"light_cm3217", LIGHT_ID_CM3217},{}};staticstructi2c_driver light_cm3217_driver ={.probe = light_cm3217_probe,.remove = light_cm3217_remove,.shutdown = sensor_shutdown,.id_table = light_cm3217_id,.driver ={.name ="light_cm3217",#ifdefCONFIG_PM.pm =&sensor_pm_ops,#endif},};module_i2c_driver(light_cm3217_driver);MODULE_AUTHOR("XXX ");MODULE_DESCRIPTION("cm3217 light driver");MODULE_LICENSE("GPL");