xref: /OK3568_Linux_fs/kernel/drivers/input/sensors/lsensor/cm3218.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* drivers/input/sensors/lsensor/cm3218.c
2  *
3  * Copyright (C) 2012-2016 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 <linux/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 #define LENSFACTOR 1000
35 
36 /* SMBus ARA Address */
37 #define	CM3218_ADDR_ARA			0x0C
38 
39 /* CM3218 CMD Registers */
40 #define	CM3218_REG_ADDR_CMD		0x00
41 #define	CM3218_CMD_ALS_SD		0x0001
42 #define	CM3218_CMD_ALS_INT_EN		0x0002
43 #define	CM3218_CMD_ALS_INT_DISABLE 0x0000
44 
45 #define	CM3218_CMD_ALS_IT_SHIFT		6
46 #define	CM3218_CMD_ALS_IT_MASK		(3 << CM3218_CMD_ALS_IT_SHIFT)
47 #define	CM3218_CMD_ALS_IT_05T		(0 << CM3218_CMD_ALS_IT_SHIFT)
48 #define	CM3218_CMD_ALS_IT_1T		(1 << CM3218_CMD_ALS_IT_SHIFT)
49 #define	CM3218_CMD_ALS_IT_2T		(2 << CM3218_CMD_ALS_IT_SHIFT)
50 #define	CM3218_CMD_ALS_IT_4T		(3 << CM3218_CMD_ALS_IT_SHIFT)
51 #define	CM3218_DEFAULT_CMD		(CM3218_CMD_ALS_IT_1T)
52 
53 #define	CM3218_ALS_PERS 0x0020
54 
55 #define	CM3218_REG_ADDR_ALS_WH		0x01
56 #define	CM3218_DEFAULT_ALS_WH		0x000C
57 
58 #define	CM3218_REG_ADDR_ALS_WL		0x02
59 #define	CM3218_DEFAULT_ALS_WL		0x000A
60 
61 #define	CM3218_REG_ADDR_ALS		0x04
62 
63 #define	CM3218_REG_ADDR_STATUS		0x06
64 
65 #define	CM3218_REG_ADDR_ID		0x07
66 
67 /* Software parameters */
68 #define	CM3218_MAX_CACHE_REGS		(0x03 + 1)	/* Reg.0x00 to 0x03 */
69 
70 static int als_code = 20;
71 static int change_sensitivity = 50;
72 static int if_sensor_init;
73 
cm3218_read_ara(struct i2c_client * client)74 static int cm3218_read_ara(struct i2c_client *client)
75 {
76 	int status;
77 	unsigned short addr;
78 
79 	addr = client->addr;
80 	client->addr = CM3218_ADDR_ARA;
81 	status = i2c_smbus_read_byte(client);
82 	client->addr = addr;
83 
84 	if (status < 0)
85 		return -ENODEV;
86 
87 	return 0;
88 }
89 
cm3218_write(struct i2c_client * client,u8 reg,u16 value)90 static int cm3218_write(struct i2c_client *client, u8 reg, u16 value)
91 {
92 	u16 regval;
93 	int ret;
94 
95 	dev_dbg(&client->dev,
96 		"Write to device register 0x%02X with 0x%04X\n", reg, value);
97 	regval = cpu_to_le16(value);
98 	ret = i2c_smbus_write_word_data(client, reg, regval);
99 	if (ret)
100 		dev_err(&client->dev, "Write to device fails: 0x%x\n", ret);
101 
102 	return ret;
103 }
104 
cm3218_read(struct i2c_client * client,u8 reg)105 static int cm3218_read(struct i2c_client *client, u8 reg)
106 {
107 	int regval;
108 	int status;
109 
110 	status = i2c_smbus_read_word_data(client, reg);
111 	if (status < 0) {
112 		dev_err(&client->dev,
113 			"Error in reading Reg.0x%02X\n", reg);
114 		return status;
115 	}
116 	regval = le16_to_cpu(status);
117 
118 	dev_dbg(&client->dev,
119 		"Read from device register 0x%02X = 0x%04X\n",
120 		reg, regval);
121 
122 	return regval;
123 }
124 
clear_interrupt(struct i2c_client * client)125 static int clear_interrupt(struct i2c_client *client)
126 {
127 	int status = 0;
128 
129 	status = cm3218_read(client, CM3218_REG_ADDR_STATUS);
130 	if (status < 0) {
131 		dev_err(&client->dev, "CM3218: clean interrupt flag fail\n");
132 		return status;
133 	}
134 
135 	return status;
136 }
137 
enable_interrupt(struct i2c_client * client)138 static int enable_interrupt(struct i2c_client *client)
139 {
140 	int status = 0;
141 
142 	status = cm3218_write(
143 		client,
144 		CM3218_REG_ADDR_CMD,
145 		CM3218_DEFAULT_CMD |
146 		CM3218_CMD_ALS_INT_EN |
147 		CM3218_ALS_PERS);
148 
149 	if (status < 0) {
150 		dev_err(&client->dev, "CM3128 enable interrut fails\n");
151 		return status;
152 	}
153 
154 	return status;
155 }
156 
disable_interrupt(struct i2c_client * client)157 static int disable_interrupt(struct i2c_client *client)
158 {
159 	int status = 0;
160 
161 	status = cm3218_write(
162 		client,
163 		CM3218_REG_ADDR_CMD,
164 		CM3218_DEFAULT_CMD |
165 		CM3218_CMD_ALS_INT_DISABLE);
166 
167 	if (status < 0) {
168 		dev_err(&client->dev, "CM3218: disable interrput fail\n");
169 		return status;
170 	}
171 
172 	return status;
173 }
174 
set_als_int_threshold(struct i2c_client * client)175 static int set_als_int_threshold(struct i2c_client *client)
176 {
177 	int threshold_high, threshold_low;
178 	int status = 0;
179 
180 	/* Set ALS high threshold */
181 	threshold_high = als_code * (100 + change_sensitivity) / 100;
182 	if (threshold_high > 65535)
183 		threshold_high = 65535;
184 	status = cm3218_write(client, CM3218_REG_ADDR_ALS_WH, threshold_high);
185 	if (status < 0) {
186 		dev_err(&client->dev, "Init CM3218 CMD fails, set als wh error\n");
187 		return status;
188 	}
189 
190 	/* Set ALS low threshold */
191 	threshold_low = als_code * (100 - change_sensitivity) / 100;
192 	status = cm3218_write(client, CM3218_REG_ADDR_ALS_WL, threshold_low);
193 	if (status < 0) {
194 		dev_err(&client->dev, "Init CM3218 CMD fails, set als wh error\n");
195 		return status;
196 	}
197 
198 	return status;
199 }
200 
201 /****************operate according to sensor chip:start************/
202 
sensor_active(struct i2c_client * client,int enable,int rate)203 static int sensor_active(struct i2c_client *client, int enable, int rate)
204 {
205 	struct sensor_private_data *sensor =
206 	    (struct sensor_private_data *)i2c_get_clientdata(client);
207 	int result = 0;
208 	int status = 0;
209 
210 	if (if_sensor_init)
211 		return 0;
212 
213 	sensor->client->addr = sensor->ops->ctrl_reg;
214 	sensor->ops->ctrl_data = cm3218_read(client, sensor->client->addr);
215 
216 	/* register setting according to chip datasheet */
217 	if (!enable) {
218 		status = CM3218_CMD_ALS_SD;	/* cm3218 */
219 		sensor->ops->ctrl_data |= status;
220 	} else {
221 		status = ~CM3218_CMD_ALS_SD;	/* cm3218 */
222 		sensor->ops->ctrl_data &= status;
223 	}
224 
225 	DBG("%s:reg=0x%x, reg_ctrl=0x%x, enable=%d\n",
226 			__func__,
227 			sensor->ops->ctrl_reg,
228 			sensor->ops->ctrl_data,
229 			enable);
230 
231 	result = cm3218_write(
232 		client,
233 		sensor->client->addr,
234 		sensor->ops->ctrl_data);
235 
236 	if (result)
237 		dev_err(&client->dev, "%s:fail to active sensor\n", __func__);
238 
239 	return result;
240 }
241 
sensor_init(struct i2c_client * client)242 static int sensor_init(struct i2c_client *client)
243 {
244 	int status, i;
245 	struct sensor_private_data *sensor =
246 	    (struct sensor_private_data *)i2c_get_clientdata(client);
247 
248 	if (if_sensor_init)
249 		return 0;
250 
251 	for (i = 0; i < 5; i++) {
252 		status = cm3218_write(
253 			client, CM3218_REG_ADDR_CMD,
254 			CM3218_CMD_ALS_SD);
255 
256 		if (status >= 0)
257 			break;
258 		cm3218_read_ara(client);
259 	}
260 
261 	status = cm3218_write(client, CM3218_REG_ADDR_CMD, CM3218_DEFAULT_CMD);
262 	if (status < 0) {
263 		dev_err(&client->dev, "Init CM3218 CMD fails\n");
264 		return status;
265 	}
266 
267 	if (sensor->pdata->irq_enable) {
268 		set_als_int_threshold(client);
269 
270 		enable_interrupt(client);
271 	}
272 
273 	if_sensor_init = 1;
274 	msleep(250);
275 
276 	return status;
277 }
278 
light_report_value(struct input_dev * input,int data)279 static int light_report_value(struct input_dev *input, int data)
280 {
281 	unsigned char index = 0;
282 
283 	if (data <= 700) {
284 		index = 0;
285 	} else if (data <= 1400) {
286 		index = 1;
287 	} else if (data <= 2800) {
288 		index = 2;
289 	} else if (data <= 5600) {
290 		index = 3;
291 	} else if (data <= 11200) {
292 		index = 4;
293 	} else if (data <= 22400) {
294 		index = 5;
295 	} else if (data <= 44800) {
296 		index = 6;
297 	} else {
298 		index = 7;
299 	}
300 
301 	input_report_abs(input, ABS_MISC, index);
302 	input_sync(input);
303 
304 	return index;
305 }
306 
cm3218_read_lux(struct i2c_client * client,int * lux)307 static int cm3218_read_lux(struct i2c_client *client, int *lux)
308 {
309 	int lux_data;
310 
311 	lux_data = cm3218_read(client, CM3218_REG_ADDR_ALS);
312 	if (lux_data < 0) {
313 		dev_err(&client->dev, "Error in reading Lux DATA\n");
314 		return lux_data;
315 	}
316 
317 	dev_vdbg(&client->dev, "lux = %u\n", lux_data);
318 
319 	if (lux_data < 0)
320 		return lux_data;
321 
322 	*lux  = lux_data * LENSFACTOR;
323 	*lux /= 1000;
324 	return 0;
325 }
326 
sensor_report_value(struct i2c_client * client)327 static int sensor_report_value(struct i2c_client *client)
328 {
329 	struct sensor_private_data *sensor =
330 	    (struct sensor_private_data *)i2c_get_clientdata(client);
331 	int result = 0;
332 	int index = 0;
333 
334 	/* clean interrupt flag and disable it during reading data */
335 	if (sensor->pdata->irq_enable) {
336 		clear_interrupt(client);
337 		disable_interrupt(client);
338 	}
339 
340 	cm3218_read_lux(client, &result);
341 	als_code = result;
342 	index = light_report_value(sensor->input_dev, 200 * result);
343 
344 	/* enable interrupt after read data */
345 	if (sensor->pdata->irq_enable) {
346 		set_als_int_threshold(client);
347 		enable_interrupt(client);
348 	}
349 
350 	return 0;
351 }
352 
353 static struct sensor_operate light_cm3218_ops = {
354 	.name				= "cm3218",
355 	/* sensor type and it should be correct */
356 	.type				= SENSOR_TYPE_LIGHT,
357 	/* i2c id number */
358 	.id_i2c				= LIGHT_ID_CM3218,
359 	/* read data */
360 	.read_reg			= CM3218_REG_ADDR_ALS,
361 	.read_len			= 2, /* data length */
362 	/* read device id from this register */
363 	.id_reg				= SENSOR_UNKNOW_DATA,
364 	/* device id */
365 	.id_data			= SENSOR_UNKNOW_DATA,
366 	.precision			= 16, /* 8 bits */
367 	/* enable or disable */
368 	.ctrl_reg			= CM3218_REG_ADDR_CMD,
369 	/* intterupt status register */
370 	.int_status_reg			= CM3218_REG_ADDR_STATUS,
371 	/* range */
372 	.range				= {0, 65535},
373 	/* brightness */
374 	.brightness			= {10, 255},
375 	.trig				= SENSOR_UNKNOW_DATA,
376 	.active				= sensor_active,
377 	.init				= sensor_init,
378 	.report				= sensor_report_value,
379 };
380 
381 /****************operate according to sensor chip:end************/
light_cm3218_probe(struct i2c_client * client,const struct i2c_device_id * devid)382 static int light_cm3218_probe(struct i2c_client *client,
383 			      const struct i2c_device_id *devid)
384 {
385 	return sensor_register_device(client, NULL, devid, &light_cm3218_ops);
386 }
387 
light_cm3218_remove(struct i2c_client * client)388 static int light_cm3218_remove(struct i2c_client *client)
389 {
390 	return sensor_unregister_device(client, NULL, &light_cm3218_ops);
391 }
392 
393 static const struct i2c_device_id light_cm3218_id[] = {
394 	{"light_cm3218", LIGHT_ID_CM3218},
395 	{}
396 };
397 
398 static struct i2c_driver light_cm3218_driver = {
399 	.probe = light_cm3218_probe,
400 	.remove = light_cm3218_remove,
401 	.shutdown = sensor_shutdown,
402 	.id_table = light_cm3218_id,
403 	.driver = {
404 		.name = "light_cm3218",
405 	#ifdef CONFIG_PM
406 		.pm = &sensor_pm_ops,
407 	#endif
408 	},
409 };
410 
411 module_i2c_driver(light_cm3218_driver);
412 
413 MODULE_AUTHOR("luowei <lw@rock-chips.com>");
414 MODULE_DESCRIPTION("cm3218 light driver");
415 MODULE_LICENSE("GPL");
416