1 /* drivers/input/sensors/access/kxtik.c
2 *
3 * Copyright (C) 2012-2015 ROCKCHIP.
4 * Author: luowei <lw@rock-chips.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16 #include <linux/interrupt.h>
17 #include <linux/i2c.h>
18 #include <linux/slab.h>
19 #include <linux/irq.h>
20 #include <linux/miscdevice.h>
21 #include <linux/gpio.h>
22 #include <linux/uaccess.h>
23 #include <asm/atomic.h>
24 #include <linux/delay.h>
25 #include <linux/input.h>
26 #include <linux/workqueue.h>
27 #include <linux/freezer.h>
28 #include <linux/of_gpio.h>
29 #ifdef CONFIG_HAS_EARLYSUSPEND
30 #include <linux/earlysuspend.h>
31 #endif
32 #include <linux/sensor-dev.h>
33
34
35 #define ISL29023_REG_ADD_COMMAND1 0x00
36 #define COMMMAND1_OPMODE_SHIFT 5
37 #define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT)
38 #define COMMMAND1_OPMODE_POWER_DOWN (0 << COMMMAND1_OPMODE_SHIFT)
39 #define COMMMAND1_OPMODE_ALS_ONCE (1 << COMMMAND1_OPMODE_SHIFT)
40 #define COMMMAND1_OPMODE_IR_ONCE (2 << COMMMAND1_OPMODE_SHIFT)
41 #define COMMMAND1_OPMODE_ALS_CONTINUE (5 << COMMMAND1_OPMODE_SHIFT)
42 #define COMMMAND1_OPMODE_IR_CONTINUE (6 << COMMMAND1_OPMODE_SHIFT)
43
44
45 #define ISL29023_REG_ADD_COMMANDII 0x01
46 #define COMMANDII_RESOLUTION_SHIFT 2
47 #define COMMANDII_RESOLUTION_65536 (0x0 << COMMANDII_RESOLUTION_SHIFT)
48 #define COMMANDII_RESOLUTION_4096 (0x1 << COMMANDII_RESOLUTION_SHIFT)
49 #define COMMANDII_RESOLUTION_256 (0x2 << COMMANDII_RESOLUTION_SHIFT)
50 #define COMMANDII_RESOLUTION_16 (0x3 << COMMANDII_RESOLUTION_SHIFT)
51 #define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT)
52
53 #define COMMANDII_RANGE_SHIFT 0
54 #define COMMANDII_RANGE_1000 (0x0 << COMMANDII_RANGE_SHIFT)
55 #define COMMANDII_RANGE_4000 (0x1 << COMMANDII_RANGE_SHIFT)
56 #define COMMANDII_RANGE_16000 (0x2 << COMMANDII_RANGE_SHIFT)
57 #define COMMANDII_RANGE_64000 (0x3 << COMMANDII_RANGE_SHIFT)
58 #define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
59
60
61 #define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
62
63 #define COMMANDII_SCHEME_SHIFT 7
64 #define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT)
65
66 #define ISL29023_REG_ADD_DATA_LSB 0x02
67 #define ISL29023_REG_ADD_DATA_MSB 0x03
68 #define ISL29023_MAX_REGS ISL29023_REG_ADD_DATA_MSB
69
70 #define ISL29023_REG_LT_LSB 0x04
71 #define ISL29023_REG_LT_MSB 0x05
72 #define ISL29023_REG_HT_LSB 0x06
73 #define ISL29023_REG_HT_MSB 0x07
74
75
76 /****************operate according to sensor chip:start************/
77
sensor_active(struct i2c_client * client,int enable,int rate)78 static int sensor_active(struct i2c_client *client, int enable, int rate)
79 {
80 struct sensor_private_data *sensor =
81 (struct sensor_private_data *) i2c_get_clientdata(client);
82 int result = 0;
83 //int status = 0;
84
85 sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
86
87 //register setting according to chip datasheet
88 if(enable)
89 {
90 sensor->ops->ctrl_data &= 0x1f;
91 sensor->ops->ctrl_data |= COMMMAND1_OPMODE_ALS_CONTINUE;
92 }
93 else
94 {
95 sensor->ops->ctrl_data &= 0x1f;
96 //sensor->ops->ctrl_data |= COMMMAND1_OPMODE_POWER_DOWN;
97 }
98
99 DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
100 result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
101 if(result)
102 printk("%s:fail to active sensor\n",__func__);
103
104 if(enable)
105 sensor->ops->report(sensor->client);
106
107 return result;
108
109 }
110
111
sensor_init(struct i2c_client * client)112 static int sensor_init(struct i2c_client *client)
113 {
114 struct sensor_private_data *sensor =
115 (struct sensor_private_data *) i2c_get_clientdata(client);
116 int result = 0;
117
118 result = sensor->ops->active(client,0,0);
119 if(result)
120 {
121 printk("%s:line=%d,error\n",__func__,__LINE__);
122 return result;
123 }
124
125 sensor->status_cur = SENSOR_OFF;
126
127 result = sensor_write_reg(client, ISL29023_REG_ADD_COMMANDII, COMMANDII_RANGE_4000 | COMMANDII_RESOLUTION_4096);
128 if(result)
129 {
130 printk("%s:line=%d,error\n",__func__,__LINE__);
131 return result;
132 }
133
134 return result;
135 }
136
137
light_report_value(struct input_dev * input,int data)138 static int light_report_value(struct input_dev *input, int data)
139 {
140 unsigned char index = 0;
141
142 if(data <= 2){
143 index = 0;goto report;
144 }
145 else if(data <= 3){
146 index = 2;goto report;
147 }
148 else if(data <= 5){
149 index = 3;goto report;
150 }
151 else if(data <= 8){
152 index = 4;goto report;
153 }
154 else if(data <= 11){
155 index = 5;goto report;
156 }
157 else if(data <= 14){
158 index = 6;goto report;
159 }
160 else if(data <= 17){
161 index = 7;goto report;
162 }
163 else{
164 index = 7;goto report;
165 }
166
167 report:
168 input_report_abs(input, ABS_MISC, index);
169 input_sync(input);
170
171 return index;
172 }
173
174
sensor_report_value(struct i2c_client * client)175 static int sensor_report_value(struct i2c_client *client)
176 {
177 struct sensor_private_data *sensor =
178 (struct sensor_private_data *) i2c_get_clientdata(client);
179 int result = 0;
180 int value = 0;
181 char buffer[2] = {0};
182 char index = 0;
183
184 if(sensor->ops->read_len < 2) //sensor->ops->read_len = 2
185 {
186 printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
187 return -1;
188 }
189
190 memset(buffer, 0, 2);
191
192 buffer[0] = sensor->ops->read_reg;
193 result = sensor_rx_data(client, buffer, sensor->ops->read_len);
194 if(result)
195 {
196 printk("%s:line=%d,error\n",__func__,__LINE__);
197 return result;
198 }
199
200 value = (buffer[1] << 8) | buffer[0];
201
202
203 index = light_report_value(sensor->input_dev, value);
204
205 DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, value,index);
206
207 if(sensor->pdata->irq_enable)
208 {
209 if(sensor->ops->int_status_reg)
210 {
211 value = sensor_read_reg(client, sensor->ops->int_status_reg);
212 }
213
214 }
215
216
217 return result;
218 }
219
220 static struct sensor_operate light_isl29023_ops = {
221 .name = "ls_isl29023",
222 .type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct
223 .id_i2c = LIGHT_ID_ISL29023, //i2c id number
224 .read_reg = ISL29023_REG_ADD_DATA_LSB, //read data
225 .read_len = 2, //data length
226 .id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
227 .id_data = SENSOR_UNKNOW_DATA, //device id
228 .precision = 16, //8 bits
229 .ctrl_reg = ISL29023_REG_ADD_COMMAND1, //enable or disable
230 .int_status_reg = ISL29023_REG_ADD_COMMAND1, //intterupt status register
231 .range = {100,65535}, //range
232 .brightness ={10,255}, //brightness
233 .trig = IRQF_TRIGGER_LOW | IRQF_ONESHOT,
234 .active = sensor_active,
235 .init = sensor_init,
236 .report = sensor_report_value,
237 };
238
239 /****************operate according to sensor chip:end************/
light_isl29023_probe(struct i2c_client * client,const struct i2c_device_id * devid)240 static int light_isl29023_probe(struct i2c_client *client,
241 const struct i2c_device_id *devid)
242 {
243 return sensor_register_device(client, NULL, devid, &light_isl29023_ops);
244 }
245
light_isl29023_remove(struct i2c_client * client)246 static int light_isl29023_remove(struct i2c_client *client)
247 {
248 return sensor_unregister_device(client, NULL, &light_isl29023_ops);
249 }
250
251 static const struct i2c_device_id light_isl29023_id[] = {
252 {"ls_isl29023", LIGHT_ID_ISL29023},
253 {}
254 };
255
256 static struct i2c_driver light_isl29023_driver = {
257 .probe = light_isl29023_probe,
258 .remove = light_isl29023_remove,
259 .shutdown = sensor_shutdown,
260 .id_table = light_isl29023_id,
261 .driver = {
262 .name = "light_isl29023",
263 #ifdef CONFIG_PM
264 .pm = &sensor_pm_ops,
265 #endif
266 },
267 };
268
269 module_i2c_driver(light_isl29023_driver);
270
271 MODULE_AUTHOR("luowei <lw@rock-chips.com>");
272 MODULE_DESCRIPTION("isl29023 light driver");
273 MODULE_LICENSE("GPL");
274