blob: 17127a8e70d5c6cea5b4ed4aae2e01d4492ace5f [file] [log] [blame]
Joseph Hsiao091151d2013-06-17 11:37:05 +08001/* drivers/input/misc/cm36283.c - cm36283 optical sensors driver
2 *
3 * Copyright (C) 2012 Capella Microsystems Inc.
4 * Author: Frank Hsieh <pengyueh@gmail.com>
Oliver Wang8a1b8be2013-08-23 13:42:10 +08005 *
6 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
7 *
Joseph Hsiao091151d2013-06-17 11:37:05 +08008 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/delay.h>
20#include <linux/earlysuspend.h>
21#include <linux/i2c.h>
22#include <linux/input.h>
23#include <linux/interrupt.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/workqueue.h>
27#include <linux/irq.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/gpio.h>
31#include <linux/miscdevice.h>
Joseph Hsiao091151d2013-06-17 11:37:05 +080032#include <linux/slab.h>
Oliver Wanga9be2d22013-08-22 18:08:22 +080033#include <linux/regulator/consumer.h>
Joseph Hsiao091151d2013-06-17 11:37:05 +080034#include <linux/wakelock.h>
35#include <linux/jiffies.h>
Oliver Wanga9be2d22013-08-22 18:08:22 +080036#include <linux/cm36283.h>
Oliver Wang8a1b8be2013-08-23 13:42:10 +080037#include <linux/of_gpio.h>
Oliver Wanga9be2d22013-08-22 18:08:22 +080038
39#include <asm/uaccess.h>
40#include <asm/mach-types.h>
41#include <asm/setup.h>
Joseph Hsiao091151d2013-06-17 11:37:05 +080042
Joseph Hsiao091151d2013-06-17 11:37:05 +080043#define I2C_RETRY_COUNT 10
44
45#define NEAR_DELAY_TIME ((100 * HZ) / 1000)
46
47#define CONTROL_INT_ISR_REPORT 0x00
48#define CONTROL_ALS 0x01
49#define CONTROL_PS 0x02
50
Oliver Wanga9be2d22013-08-22 18:08:22 +080051/* POWER SUPPLY VOLTAGE RANGE */
52#define CM36283_VDD_MIN_UV 2700000
53#define CM36283_VDD_MAX_UV 3300000
54#define CM36283_VI2C_MIN_UV 1750000
55#define CM36283_VI2C_MAX_UV 1950000
56
Oliver Wanged314dd2013-08-23 16:34:37 +080057/* cm36283 polling rate in ms */
58#define CM36283_LS_MIN_POLL_DELAY 1
59#define CM36283_LS_MAX_POLL_DELAY 1000
60#define CM36283_LS_DEFAULT_POLL_DELAY 100
61
62#define CM36283_PS_MIN_POLL_DELAY 1
63#define CM36283_PS_MAX_POLL_DELAY 1000
64#define CM36283_PS_DEFAULT_POLL_DELAY 100
65
Oliver Wanged314dd2013-08-23 16:34:37 +080066static const int als_range[] = {
67 [CM36283_ALS_IT0] = 6554,
68 [CM36283_ALS_IT1] = 3277,
69 [CM36283_ALS_IT2] = 1638,
70 [CM36283_ALS_IT3] = 819,
71};
72
73static const int als_sense[] = {
74 [CM36283_ALS_IT0] = 10,
75 [CM36283_ALS_IT1] = 20,
76 [CM36283_ALS_IT2] = 40,
77 [CM36283_ALS_IT3] = 80,
78};
79
Joseph Hsiao091151d2013-06-17 11:37:05 +080080static void sensor_irq_do_work(struct work_struct *work);
81static DECLARE_WORK(sensor_irq_work, sensor_irq_do_work);
82
83struct cm36283_info {
84 struct class *cm36283_class;
85 struct device *ls_dev;
86 struct device *ps_dev;
87
88 struct input_dev *ls_input_dev;
89 struct input_dev *ps_input_dev;
90
91 struct early_suspend early_suspend;
92 struct i2c_client *i2c_client;
93 struct workqueue_struct *lp_wq;
94
95 int intr_pin;
96 int als_enable;
97 int ps_enable;
98 int ps_irq_flag;
99
100 uint16_t *adc_table;
101 uint16_t cali_table[10];
102 int irq;
103
104 int ls_calibrate;
105
106 int (*power)(int, uint8_t); /* power to the chip */
107
108 uint32_t als_kadc;
109 uint32_t als_gadc;
110 uint16_t golden_adc;
111
112 struct wake_lock ps_wake_lock;
113 int psensor_opened;
114 int lightsensor_opened;
115 uint8_t slave_addr;
116
117 uint8_t ps_close_thd_set;
118 uint8_t ps_away_thd_set;
119 int current_level;
120 uint16_t current_adc;
121
122 uint16_t ps_conf1_val;
123 uint16_t ps_conf3_val;
124
125 uint16_t ls_cmd;
126 uint8_t record_clear_int_fail;
Oliver Wanged314dd2013-08-23 16:34:37 +0800127 bool polling;
128 atomic_t ls_poll_delay;
129 atomic_t ps_poll_delay;
Oliver Wanga9be2d22013-08-22 18:08:22 +0800130 struct regulator *vdd;
131 struct regulator *vio;
Oliver Wanged314dd2013-08-23 16:34:37 +0800132 struct delayed_work ldwork;
133 struct delayed_work pdwork;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800134};
135struct cm36283_info *lp_info;
136int fLevel=-1;
137static struct mutex als_enable_mutex, als_disable_mutex, als_get_adc_mutex;
138static struct mutex ps_enable_mutex, ps_disable_mutex, ps_get_adc_mutex;
139static struct mutex CM36283_control_mutex;
Oliver Wanged314dd2013-08-23 16:34:37 +0800140static struct mutex wq_lock;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800141static int lightsensor_enable(struct cm36283_info *lpi);
142static int lightsensor_disable(struct cm36283_info *lpi);
143static int initial_cm36283(struct cm36283_info *lpi);
144static void psensor_initial_cmd(struct cm36283_info *lpi);
Oliver Wang0afd6a32013-08-26 14:23:51 +0800145static int cm36283_power_set(struct cm36283_info *info, bool on);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800146
147int32_t als_kadc;
148
Oliver Wanged314dd2013-08-23 16:34:37 +0800149static int control_and_report(struct cm36283_info *lpi, uint8_t mode,
150 uint16_t param, int report);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800151
152static int I2C_RxData(uint16_t slaveAddr, uint8_t cmd, uint8_t *rxData, int length)
153{
154 uint8_t loop_i;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800155 struct cm36283_info *lpi = lp_info;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800156 uint8_t subaddr[1];
Joseph Hsiao091151d2013-06-17 11:37:05 +0800157
158 struct i2c_msg msgs[] = {
159 {
160 .addr = slaveAddr,
161 .flags = 0,
162 .len = 1,
163 .buf = subaddr,
164 },
165 {
166 .addr = slaveAddr,
167 .flags = I2C_M_RD,
168 .len = length,
169 .buf = rxData,
170 },
171 };
Oliver Wangd89c81b2013-09-22 19:49:29 +0800172
173 subaddr[0] = cmd;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800174
175 for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
176
177 if (i2c_transfer(lp_info->i2c_client->adapter, msgs, 2) > 0)
178 break;
179
Oliver Wangd89c81b2013-09-22 19:49:29 +0800180 dev_err(&lpi->i2c_client->dev, "%s: I2C error(%d). Retrying.\n",
181 __func__, cmd);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800182 msleep(10);
183 }
184 if (loop_i >= I2C_RETRY_COUNT) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800185 dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
186 __func__, I2C_RETRY_COUNT);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800187 return -EIO;
188 }
189
190 return 0;
191}
192
193static int I2C_TxData(uint16_t slaveAddr, uint8_t *txData, int length)
194{
195 uint8_t loop_i;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800196 struct cm36283_info *lpi = lp_info;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800197
Joseph Hsiao091151d2013-06-17 11:37:05 +0800198 struct i2c_msg msg[] = {
199 {
200 .addr = slaveAddr,
201 .flags = 0,
202 .len = length,
203 .buf = txData,
204 },
205 };
206
207 for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
208 if (i2c_transfer(lp_info->i2c_client->adapter, msg, 1) > 0)
209 break;
210
Oliver Wangd89c81b2013-09-22 19:49:29 +0800211 pr_err("%s: I2C error. Retrying...\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800212 msleep(10);
213 }
214
215 if (loop_i >= I2C_RETRY_COUNT) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800216 dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
217 __func__, I2C_RETRY_COUNT);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800218 return -EIO;
219 }
220
221 return 0;
222}
223
224static int _cm36283_I2C_Read_Word(uint16_t slaveAddr, uint8_t cmd, uint16_t *pdata)
225{
226 uint8_t buffer[2];
227 int ret = 0;
228
229 if (pdata == NULL)
230 return -EFAULT;
231
232 ret = I2C_RxData(slaveAddr, cmd, buffer, 2);
233 if (ret < 0) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800234 pr_err("%s: I2C RxData fail(%d).\n", __func__, cmd);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800235 return ret;
236 }
237
238 *pdata = (buffer[1]<<8)|buffer[0];
Oliver Wangd89c81b2013-09-22 19:49:29 +0800239
Joseph Hsiao091151d2013-06-17 11:37:05 +0800240 return ret;
241}
242
243static int _cm36283_I2C_Write_Word(uint16_t SlaveAddress, uint8_t cmd, uint16_t data)
244{
245 char buffer[3];
246 int ret = 0;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800247
Joseph Hsiao091151d2013-06-17 11:37:05 +0800248 buffer[0] = cmd;
249 buffer[1] = (uint8_t)(data&0xff);
250 buffer[2] = (uint8_t)((data&0xff00)>>8);
251
252 ret = I2C_TxData(SlaveAddress, buffer, 3);
253 if (ret < 0) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800254 pr_err("%s: I2C_TxData failed.\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800255 return -EIO;
256 }
257
258 return ret;
259}
260
261static int get_ls_adc_value(uint16_t *als_step, bool resume)
262{
263 struct cm36283_info *lpi = lp_info;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800264 uint32_t tmp;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800265 int ret = 0;
266
267 if (als_step == NULL)
268 return -EFAULT;
269
270 /* Read ALS data: */
271 ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_DATA, als_step);
272 if (ret < 0) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800273 dev_err(&lpi->i2c_client->dev, "%s: I2C read word failed.\n",
274 __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800275 return -EIO;
276 }
277
Oliver Wangd89c81b2013-09-22 19:49:29 +0800278 if (!lpi->ls_calibrate) {
279 tmp = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
280 if (tmp > 0xFFFF)
Joseph Hsiao091151d2013-06-17 11:37:05 +0800281 *als_step = 0xFFFF;
282 else
Oliver Wangd89c81b2013-09-22 19:49:29 +0800283 *als_step = tmp;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800284 }
285
Oliver Wangd89c81b2013-09-22 19:49:29 +0800286 dev_dbg(&lpi->i2c_client->dev, "raw adc = 0x%x\n", *als_step);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800287
288 return ret;
289}
290
291static int set_lsensor_range(uint16_t low_thd, uint16_t high_thd)
292{
293 int ret = 0;
294 struct cm36283_info *lpi = lp_info;
295
296 _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_THDH, high_thd);
297 _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_THDL, low_thd);
298
299 return ret;
300}
301
302static int get_ps_adc_value(uint16_t *data)
303{
304 int ret = 0;
305 struct cm36283_info *lpi = lp_info;
306
307 if (data == NULL)
308 return -EFAULT;
309
310 ret = _cm36283_I2C_Read_Word(lpi->slave_addr, PS_DATA, data);
311
Oliver Wangd89c81b2013-09-22 19:49:29 +0800312 if (ret < 0)
313 return ret;
314
Joseph Hsiao091151d2013-06-17 11:37:05 +0800315 (*data) &= 0xFF;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800316
317 return ret;
318}
319
320static uint16_t mid_value(uint16_t value[], uint8_t size)
321{
322 int i = 0, j = 0;
323 uint16_t temp = 0;
324
325 if (size < 3)
326 return 0;
327
328 for (i = 0; i < (size - 1); i++)
329 for (j = (i + 1); j < size; j++)
330 if (value[i] > value[j]) {
331 temp = value[i];
332 value[i] = value[j];
333 value[j] = temp;
334 }
335 return value[((size - 1) / 2)];
336}
337
338static int get_stable_ps_adc_value(uint16_t *ps_adc)
339{
340 uint16_t value[3] = {0, 0, 0}, mid_val = 0;
341 int ret = 0;
342 int i = 0;
343 int wait_count = 0;
344 struct cm36283_info *lpi = lp_info;
345
346 for (i = 0; i < 3; i++) {
347 /*wait interrupt GPIO high*/
348 while (gpio_get_value(lpi->intr_pin) == 0) {
349 msleep(10);
350 wait_count++;
351 if (wait_count > 12) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800352 dev_err(&lpi->i2c_client->dev, "%s: interrupt GPIO low\n",
353 __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800354 return -EIO;
355 }
356 }
357
358 ret = get_ps_adc_value(&value[i]);
359 if (ret < 0) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800360 dev_err(&lpi->i2c_client->dev,
361 "%s: error get ps value\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800362 return -EIO;
363 }
364
365 if (wait_count < 60/10) {/*wait gpio less than 60ms*/
366 msleep(60 - (10*wait_count));
367 }
368 wait_count = 0;
369 }
370
Joseph Hsiao091151d2013-06-17 11:37:05 +0800371 mid_val = mid_value(value, 3);
Oliver Wangd89c81b2013-09-22 19:49:29 +0800372 dev_dbg(&lpi->i2c_client->dev, "Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
Joseph Hsiao091151d2013-06-17 11:37:05 +0800373 value[0], value[1], value[2]);
374 *ps_adc = (mid_val & 0xFF);
375
376 return 0;
377}
378
379static void sensor_irq_do_work(struct work_struct *work)
380{
381 struct cm36283_info *lpi = lp_info;
382 uint16_t intFlag;
Oliver Wanged314dd2013-08-23 16:34:37 +0800383 _cm36283_I2C_Read_Word(lpi->slave_addr, INT_FLAG, &intFlag);
384 control_and_report(lpi, CONTROL_INT_ISR_REPORT, intFlag, 1);
385
Joseph Hsiao091151d2013-06-17 11:37:05 +0800386 enable_irq(lpi->irq);
387}
388
Oliver Wanged314dd2013-08-23 16:34:37 +0800389static int get_als_range(void)
390{
391 uint16_t ls_conf;
392 int ret = 0;
393 int index = 0;
394 struct cm36283_info *lpi = lp_info;
395
396 ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_CONF, &ls_conf);
397 if (ret) {
398 dev_err(&lpi->i2c_client->dev, "read ALS_CONF from i2c error. %d\n",
399 ret);
400 return -EIO;
401 }
402
403 index = (ls_conf & 0xC0) >> 0x06;
404 return als_range[index];
405}
406
407static int get_als_sense(void)
408{
409 uint16_t ls_conf;
410 int ret = 0;
411 int index = 0;
412 struct cm36283_info *lpi = lp_info;
413
414 ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_CONF, &ls_conf);
415 if (ret) {
416 dev_err(&lpi->i2c_client->dev, "read ALS_CONF from i2c error. %d\n",
417 ret);
418 return -EIO;
419 }
420
421 index = (ls_conf & 0xC0) >> 0x06;
422 return als_sense[index];
423}
424
425static void psensor_delay_work_handler(struct work_struct *work)
426{
427 struct cm36283_info *lpi = lp_info;
428 uint16_t adc_value = 0;
429 int ret;
430
431 mutex_lock(&wq_lock);
432
433 ret = get_ps_adc_value(&adc_value);
434
435 mutex_unlock(&wq_lock);
436
437 if (ret >= 0) {
438 input_report_abs(lpi->ps_input_dev, ABS_DISTANCE,
439 adc_value > lpi->ps_close_thd_set ? 0 : 1);
440 input_sync(lpi->ps_input_dev);
441 }
442 schedule_delayed_work(&lpi->pdwork,
443 msecs_to_jiffies(atomic_read(&lpi->ps_poll_delay)));
444}
445
446static void lsensor_delay_work_handler(struct work_struct *work)
447{
448 struct cm36283_info *lpi = lp_info;
449 uint16_t adc_value = 0;
450 int sense;
451
452 mutex_lock(&wq_lock);
453
454 get_ls_adc_value(&adc_value, 0);
455 sense = get_als_sense();
456
457 mutex_unlock(&wq_lock);
458
459 if (sense > 0) {
460 lpi->current_adc = adc_value;
461 input_report_abs(lpi->ls_input_dev, ABS_MISC, adc_value/sense);
462 input_sync(lpi->ls_input_dev);
463 }
464 schedule_delayed_work(&lpi->ldwork,
465 msecs_to_jiffies(atomic_read(&lpi->ls_poll_delay)));
466}
467
Joseph Hsiao091151d2013-06-17 11:37:05 +0800468static irqreturn_t cm36283_irq_handler(int irq, void *data)
469{
470 struct cm36283_info *lpi = data;
471
472 disable_irq_nosync(lpi->irq);
473 queue_work(lpi->lp_wq, &sensor_irq_work);
474
475 return IRQ_HANDLED;
476}
477
478static int als_power(int enable)
479{
480 struct cm36283_info *lpi = lp_info;
481
482 if (lpi->power)
483 lpi->power(LS_PWR_ON, 1);
484
485 return 0;
486}
487
488static void ls_initial_cmd(struct cm36283_info *lpi)
489{
490 /*must disable l-sensor interrupt befrore IST create*//*disable ALS func*/
491 lpi->ls_cmd &= CM36283_ALS_INT_MASK;
492 lpi->ls_cmd |= CM36283_ALS_SD;
493 _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
494}
495
496static void psensor_initial_cmd(struct cm36283_info *lpi)
497{
Oliver Wangd89c81b2013-09-22 19:49:29 +0800498 /*must disable p-sensor interrupt befrore IST create*/
499 lpi->ps_conf1_val |= CM36283_PS_SD;
500 lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
501 _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
502 _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
503 _cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD,
504 (lpi->ps_close_thd_set << 8) | lpi->ps_away_thd_set);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800505
Oliver Wangd89c81b2013-09-22 19:49:29 +0800506 dev_dbg(&lpi->i2c_client->dev,
507 "%s:send psensor initial command finished\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800508}
509
510static int psensor_enable(struct cm36283_info *lpi)
511{
512 int ret = -EIO;
Oliver Wanged314dd2013-08-23 16:34:37 +0800513 unsigned int delay;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800514
515 mutex_lock(&ps_enable_mutex);
Oliver Wangd89c81b2013-09-22 19:49:29 +0800516 dev_dbg(&lpi->i2c_client->dev, "psensor enable!\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800517
Oliver Wanged314dd2013-08-23 16:34:37 +0800518 if (lpi->ps_enable) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800519 dev_err(&lpi->i2c_client->dev, "already enabled\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800520 ret = 0;
Oliver Wanged314dd2013-08-23 16:34:37 +0800521 } else {
522 ret = control_and_report(lpi, CONTROL_PS, 1, 0);
523 }
524
Joseph Hsiao091151d2013-06-17 11:37:05 +0800525 mutex_unlock(&ps_enable_mutex);
Oliver Wanged314dd2013-08-23 16:34:37 +0800526
527 delay = atomic_read(&lpi->ps_poll_delay);
528 if (lpi->polling)
529 schedule_delayed_work(&lpi->pdwork, msecs_to_jiffies(delay));
530
Joseph Hsiao091151d2013-06-17 11:37:05 +0800531 return ret;
532}
533
534static int psensor_disable(struct cm36283_info *lpi)
535{
536 int ret = -EIO;
Oliver Wanged314dd2013-08-23 16:34:37 +0800537
538 if (lpi->polling)
539 cancel_delayed_work_sync(&lpi->pdwork);
540
Joseph Hsiao091151d2013-06-17 11:37:05 +0800541 mutex_lock(&ps_disable_mutex);
Oliver Wangd89c81b2013-09-22 19:49:29 +0800542 dev_dbg(&lpi->i2c_client->dev, "psensor disable!\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800543
Oliver Wanged314dd2013-08-23 16:34:37 +0800544 if (lpi->ps_enable == 0) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800545 dev_err(&lpi->i2c_client->dev, "already disabled\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800546 ret = 0;
Oliver Wanged314dd2013-08-23 16:34:37 +0800547 } else {
548 ret = control_and_report(lpi, CONTROL_PS, 0, 0);
549 }
550
Joseph Hsiao091151d2013-06-17 11:37:05 +0800551 mutex_unlock(&ps_disable_mutex);
552 return ret;
553}
554
555static int psensor_open(struct inode *inode, struct file *file)
556{
557 struct cm36283_info *lpi = lp_info;
558
Oliver Wangd89c81b2013-09-22 19:49:29 +0800559 dev_dbg(&lpi->i2c_client->dev, "psensor open!");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800560
561 if (lpi->psensor_opened)
562 return -EBUSY;
563
564 lpi->psensor_opened = 1;
565
566 return 0;
567}
568
569static int psensor_release(struct inode *inode, struct file *file)
570{
571 struct cm36283_info *lpi = lp_info;
572
Oliver Wangd89c81b2013-09-22 19:49:29 +0800573 dev_dbg(&lpi->i2c_client->dev, "psensor release!");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800574
575 lpi->psensor_opened = 0;
576
577 return psensor_disable(lpi);
578 //return 0;
579}
580
581static long psensor_ioctl(struct file *file, unsigned int cmd,
582 unsigned long arg)
583{
584 int val;
585 struct cm36283_info *lpi = lp_info;
586
Oliver Wangd89c81b2013-09-22 19:49:29 +0800587 dev_dbg(&lpi->i2c_client->dev, "%s cmd %d\n", __func__, _IOC_NR(cmd));
Joseph Hsiao091151d2013-06-17 11:37:05 +0800588
589 switch (cmd) {
590 case CAPELLA_CM3602_IOCTL_ENABLE:
591 if (get_user(val, (unsigned long __user *)arg))
592 return -EFAULT;
593 if (val)
594 return psensor_enable(lpi);
595 else
596 return psensor_disable(lpi);
597 break;
598 case CAPELLA_CM3602_IOCTL_GET_ENABLED:
599 return put_user(lpi->ps_enable, (unsigned long __user *)arg);
600 break;
601 default:
Oliver Wangd89c81b2013-09-22 19:49:29 +0800602 dev_err(&lpi->i2c_client->dev, "%s: invalid cmd %d\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +0800603 __func__, _IOC_NR(cmd));
604 return -EINVAL;
605 }
606}
607
608static const struct file_operations psensor_fops = {
609 .owner = THIS_MODULE,
610 .open = psensor_open,
611 .release = psensor_release,
612 .unlocked_ioctl = psensor_ioctl
613};
614
615struct miscdevice psensor_misc = {
616 .minor = MISC_DYNAMIC_MINOR,
617 .name = "proximity",
618 .fops = &psensor_fops
619};
620
621void lightsensor_set_kvalue(struct cm36283_info *lpi)
622{
623 if (!lpi) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800624 pr_err("%s: ls_info is empty\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800625 return;
626 }
627
Oliver Wangd89c81b2013-09-22 19:49:29 +0800628 dev_dbg(&lpi->i2c_client->dev, "%s: ALS calibrated als_kadc=0x%x\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +0800629 __func__, als_kadc);
630
631 if (als_kadc >> 16 == ALS_CALIBRATED)
632 lpi->als_kadc = als_kadc & 0xFFFF;
633 else {
634 lpi->als_kadc = 0;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800635 dev_dbg(&lpi->i2c_client->dev, "%s: no ALS calibrated\n",
636 __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800637 }
638
639 if (lpi->als_kadc && lpi->golden_adc > 0) {
640 lpi->als_kadc = (lpi->als_kadc > 0 && lpi->als_kadc < 0x1000) ?
641 lpi->als_kadc : lpi->golden_adc;
642 lpi->als_gadc = lpi->golden_adc;
643 } else {
644 lpi->als_kadc = 1;
645 lpi->als_gadc = 1;
646 }
Oliver Wangd89c81b2013-09-22 19:49:29 +0800647 dev_dbg(&lpi->i2c_client->dev, "%s: als_kadc=0x%x, als_gadc=0x%x\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +0800648 __func__, lpi->als_kadc, lpi->als_gadc);
649}
650
651
652static int lightsensor_update_table(struct cm36283_info *lpi)
653{
Oliver Wangd89c81b2013-09-22 19:49:29 +0800654 uint32_t tmp_data[10];
Joseph Hsiao091151d2013-06-17 11:37:05 +0800655 int i;
656 for (i = 0; i < 10; i++) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800657 tmp_data[i] = (uint32_t)(*(lpi->adc_table + i))
658 * lpi->als_kadc / lpi->als_gadc;
659
660 if (tmp_data[i] <= 0xFFFF)
661 lpi->cali_table[i] = (uint16_t) tmp_data[i];
662 else
663 lpi->cali_table[i] = 0xFFFF;
664
665 dev_dbg(&lpi->i2c_client->dev, "%s: Calibrated adc_table: data[%d], %x\n",
666 __func__, i, lpi->cali_table[i]);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800667 }
668
669 return 0;
670}
671
672
673static int lightsensor_enable(struct cm36283_info *lpi)
674{
675 int ret = -EIO;
Oliver Wanged314dd2013-08-23 16:34:37 +0800676 unsigned int delay;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800677
678 mutex_lock(&als_enable_mutex);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800679
680 if (lpi->als_enable) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800681 dev_err(&lpi->i2c_client->dev, "%s: already enabled\n",
682 __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800683 ret = 0;
Oliver Wanged314dd2013-08-23 16:34:37 +0800684 } else {
685 ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
686 }
Joseph Hsiao091151d2013-06-17 11:37:05 +0800687
688 mutex_unlock(&als_enable_mutex);
Oliver Wanged314dd2013-08-23 16:34:37 +0800689
690 delay = atomic_read(&lpi->ls_poll_delay);
691 if (lpi->polling)
692 schedule_delayed_work(&lpi->ldwork,
693 msecs_to_jiffies(delay));
694
Joseph Hsiao091151d2013-06-17 11:37:05 +0800695 return ret;
696}
697
698static int lightsensor_disable(struct cm36283_info *lpi)
699{
700 int ret = -EIO;
701 mutex_lock(&als_disable_mutex);
Oliver Wangd89c81b2013-09-22 19:49:29 +0800702 dev_dbg(&lpi->i2c_client->dev, "disable lightsensor\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800703
Oliver Wanged314dd2013-08-23 16:34:37 +0800704 if (lpi->polling)
705 cancel_delayed_work_sync(&lpi->ldwork);
706
Joseph Hsiao091151d2013-06-17 11:37:05 +0800707 if ( lpi->als_enable == 0 ) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800708 dev_err(&lpi->i2c_client->dev, "already disabled\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +0800709 ret = 0;
Oliver Wanged314dd2013-08-23 16:34:37 +0800710 } else {
711 ret = control_and_report(lpi, CONTROL_ALS, 0, 0);
712 }
Joseph Hsiao091151d2013-06-17 11:37:05 +0800713
714 mutex_unlock(&als_disable_mutex);
715 return ret;
716}
717
718static int lightsensor_open(struct inode *inode, struct file *file)
719{
720 struct cm36283_info *lpi = lp_info;
721 int rc = 0;
722
Oliver Wangd89c81b2013-09-22 19:49:29 +0800723 dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800724 if (lpi->lightsensor_opened) {
Oliver Wangd89c81b2013-09-22 19:49:29 +0800725 dev_err(&lpi->i2c_client->dev, "%s: already opened\n",
726 __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800727 rc = -EBUSY;
728 }
729 lpi->lightsensor_opened = 1;
730 return rc;
731}
732
733static int lightsensor_release(struct inode *inode, struct file *file)
734{
735 struct cm36283_info *lpi = lp_info;
736
Oliver Wangd89c81b2013-09-22 19:49:29 +0800737 dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800738 lpi->lightsensor_opened = 0;
739 return 0;
740}
741
742static long lightsensor_ioctl(struct file *file, unsigned int cmd,
743 unsigned long arg)
744{
745 int rc, val;
746 struct cm36283_info *lpi = lp_info;
747
Joseph Hsiao091151d2013-06-17 11:37:05 +0800748 switch (cmd) {
749 case LIGHTSENSOR_IOCTL_ENABLE:
750 if (get_user(val, (unsigned long __user *)arg)) {
751 rc = -EFAULT;
752 break;
753 }
Joseph Hsiao091151d2013-06-17 11:37:05 +0800754 rc = val ? lightsensor_enable(lpi) : lightsensor_disable(lpi);
755 break;
756 case LIGHTSENSOR_IOCTL_GET_ENABLED:
757 val = lpi->als_enable;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800758 rc = put_user(val, (unsigned long __user *)arg);
759 break;
760 default:
761 pr_err("[LS][CM36283 error]%s: invalid cmd %d\n",
762 __func__, _IOC_NR(cmd));
763 rc = -EINVAL;
764 }
765
766 return rc;
767}
768
769static const struct file_operations lightsensor_fops = {
770 .owner = THIS_MODULE,
771 .open = lightsensor_open,
772 .release = lightsensor_release,
773 .unlocked_ioctl = lightsensor_ioctl
774};
775
776static struct miscdevice lightsensor_misc = {
777 .minor = MISC_DYNAMIC_MINOR,
778 .name = "lightsensor",
779 .fops = &lightsensor_fops
780};
781
782
783static ssize_t ps_adc_show(struct device *dev,
784 struct device_attribute *attr, char *buf)
785{
786
787 uint16_t value;
788 int ret;
789 struct cm36283_info *lpi = lp_info;
Oliver Wanged314dd2013-08-23 16:34:37 +0800790 int intr_val = -1;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800791
792 get_ps_adc_value(&value);
Oliver Wanged314dd2013-08-23 16:34:37 +0800793 if (gpio_is_valid(lpi->intr_pin))
794 intr_val = gpio_get_value(lpi->intr_pin);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800795
Oliver Wanged314dd2013-08-23 16:34:37 +0800796 ret = snprintf(buf, PAGE_SIZE, "ADC[0x%04X], ENABLE=%d intr_pin=%d\n",
797 value, lpi->ps_enable, intr_val);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800798
799 return ret;
800}
801
802static ssize_t ps_enable_store(struct device *dev,
803 struct device_attribute *attr,
804 const char *buf, size_t count)
805{
806 int ps_en;
807 struct cm36283_info *lpi = lp_info;
808
809 ps_en = -1;
810 sscanf(buf, "%d", &ps_en);
811
812 if (ps_en != 0 && ps_en != 1
813 && ps_en != 10 && ps_en != 13 && ps_en != 16)
814 return -EINVAL;
815
Oliver Wangd89c81b2013-09-22 19:49:29 +0800816 dev_dbg(&lpi->i2c_client->dev, "%s: ps_en=%d\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +0800817 __func__, ps_en);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800818
Oliver Wangd89c81b2013-09-22 19:49:29 +0800819 if (ps_en)
820 psensor_enable(lpi);
821 else
822 psensor_disable(lpi);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800823
824 return count;
825}
826
827static DEVICE_ATTR(ps_adc, 0664, ps_adc_show, ps_enable_store);
828
Joseph Hsiao091151d2013-06-17 11:37:05 +0800829static ssize_t ps_parameters_show(struct device *dev,
830 struct device_attribute *attr, char *buf)
831{
832 int ret;
833 struct cm36283_info *lpi = lp_info;
834
Oliver Wangd89c81b2013-09-22 19:49:29 +0800835 ret = snprintf(buf, PAGE_SIZE,
836 "PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x\n",
837 lpi->ps_close_thd_set, lpi->ps_away_thd_set);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800838
839 return ret;
840}
841
842static ssize_t ps_parameters_store(struct device *dev,
843 struct device_attribute *attr,
844 const char *buf, size_t count)
845{
846
847 struct cm36283_info *lpi = lp_info;
848 char *token[10];
849 int i;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800850 unsigned long tmp;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800851
Joseph Hsiao091151d2013-06-17 11:37:05 +0800852 for (i = 0; i < 3; i++)
853 token[i] = strsep((char **)&buf, " ");
854
Oliver Wangd89c81b2013-09-22 19:49:29 +0800855 if (kstrtoul(token[0], 16, &tmp))
856 return -EINVAL;
857 lpi->ps_close_thd_set = tmp;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800858
Oliver Wangd89c81b2013-09-22 19:49:29 +0800859 if (kstrtoul(token[1], 16, &tmp))
860 return -EINVAL;
861 lpi->ps_away_thd_set = tmp;
862
863 dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
864 lpi->ps_close_thd_set);
865 dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
866 lpi->ps_away_thd_set);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800867
868 return count;
869}
870
871static DEVICE_ATTR(ps_parameters, 0664,
872 ps_parameters_show, ps_parameters_store);
873
874
875static ssize_t ps_conf_show(struct device *dev,
876 struct device_attribute *attr, char *buf)
877{
878 struct cm36283_info *lpi = lp_info;
879 return sprintf(buf, "PS_CONF1 = 0x%x, PS_CONF3 = 0x%x\n", lpi->ps_conf1_val, lpi->ps_conf3_val);
880}
881static ssize_t ps_conf_store(struct device *dev,
882 struct device_attribute *attr,
883 const char *buf, size_t count)
884{
885 int code1, code2;
886 struct cm36283_info *lpi = lp_info;
887
888 sscanf(buf, "0x%x 0x%x", &code1, &code2);
Oliver Wangd89c81b2013-09-22 19:49:29 +0800889 dev_dbg(&lpi->i2c_client->dev, "PS_CONF1:0x%x PS_CONF3:0x%x\n",
890 code1, code2);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800891
Oliver Wangd89c81b2013-09-22 19:49:29 +0800892 lpi->ps_conf1_val = code1;
893 lpi->ps_conf3_val = code2;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800894
Oliver Wangd89c81b2013-09-22 19:49:29 +0800895 _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
896 _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800897
898 return count;
899}
900static DEVICE_ATTR(ps_conf, 0664, ps_conf_show, ps_conf_store);
901
902static ssize_t ps_thd_show(struct device *dev,
903 struct device_attribute *attr, char *buf)
904{
905 int ret;
906 struct cm36283_info *lpi = lp_info;
907 ret = sprintf(buf, "%s ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n", __func__, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
908 return ret;
909}
910static ssize_t ps_thd_store(struct device *dev,
911 struct device_attribute *attr,
912 const char *buf, size_t count)
913{
914 int code;
915 struct cm36283_info *lpi = lp_info;
916
917 sscanf(buf, "0x%x", &code);
918
Joseph Hsiao091151d2013-06-17 11:37:05 +0800919 lpi->ps_away_thd_set = code &0xFF;
Oliver Wangd89c81b2013-09-22 19:49:29 +0800920 lpi->ps_close_thd_set = (code & 0xFF00)>>8;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800921
Oliver Wangd89c81b2013-09-22 19:49:29 +0800922 dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
923 lpi->ps_away_thd_set);
924 dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
925 lpi->ps_close_thd_set);
Joseph Hsiao091151d2013-06-17 11:37:05 +0800926
927 return count;
928}
929static DEVICE_ATTR(ps_thd, 0664, ps_thd_show, ps_thd_store);
930
931static ssize_t ps_hw_show(struct device *dev,
932 struct device_attribute *attr, char *buf)
933{
934 int ret = 0;
935 struct cm36283_info *lpi = lp_info;
936
937 ret = sprintf(buf, "PS1: reg = 0x%x, PS3: reg = 0x%x, ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n",
938 lpi->ps_conf1_val, lpi->ps_conf3_val, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
939
940 return ret;
941}
942static ssize_t ps_hw_store(struct device *dev,
943 struct device_attribute *attr,
944 const char *buf, size_t count)
945{
946 int code;
Joseph Hsiao091151d2013-06-17 11:37:05 +0800947
948 sscanf(buf, "0x%x", &code);
949
Joseph Hsiao091151d2013-06-17 11:37:05 +0800950 return count;
951}
952static DEVICE_ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store);
953
954static ssize_t ls_adc_show(struct device *dev,
955 struct device_attribute *attr, char *buf)
956{
957 int ret;
958 struct cm36283_info *lpi = lp_info;
959
Joseph Hsiao091151d2013-06-17 11:37:05 +0800960 ret = sprintf(buf, "ADC[0x%04X] => level %d\n",
961 lpi->current_adc, lpi->current_level);
962
963 return ret;
964}
965
966static DEVICE_ATTR(ls_adc, 0664, ls_adc_show, NULL);
967
968static ssize_t ls_enable_show(struct device *dev,
969 struct device_attribute *attr, char *buf)
970{
971
972 int ret = 0;
973 struct cm36283_info *lpi = lp_info;
974
975 ret = sprintf(buf, "Light sensor Auto Enable = %d\n",
976 lpi->als_enable);
977
978 return ret;
979}
980
981static ssize_t ls_enable_store(struct device *dev,
982 struct device_attribute *attr,
983 const char *buf, size_t count)
984{
985 int ret = 0;
986 int ls_auto;
987 struct cm36283_info *lpi = lp_info;
988
989 ls_auto = -1;
990 sscanf(buf, "%d", &ls_auto);
991
992 if (ls_auto != 0 && ls_auto != 1 && ls_auto != 147)
993 return -EINVAL;
994
995 if (ls_auto) {
996 lpi->ls_calibrate = (ls_auto == 147) ? 1 : 0;
997 ret = lightsensor_enable(lpi);
998 } else {
999 lpi->ls_calibrate = 0;
1000 ret = lightsensor_disable(lpi);
1001 }
1002
Oliver Wangd89c81b2013-09-22 19:49:29 +08001003 dev_dbg(&lpi->i2c_client->dev, "als_enable:0x%x\n",
1004 lpi->als_enable);
1005 dev_dbg(&lpi->i2c_client->dev, "ls_calibrate:0x%x\n",
1006 lpi->ls_calibrate);
1007 dev_dbg(&lpi->i2c_client->dev, "ls_auto:0x%x\n", ls_auto);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001008
1009 if (ret < 0)
Oliver Wangd89c81b2013-09-22 19:49:29 +08001010 dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +08001011 __func__);
1012
1013 return count;
1014}
1015
1016static DEVICE_ATTR(ls_auto, 0664,
1017 ls_enable_show, ls_enable_store);
1018
1019static ssize_t ls_kadc_show(struct device *dev,
1020 struct device_attribute *attr, char *buf)
1021{
1022 struct cm36283_info *lpi = lp_info;
1023 int ret;
1024
1025 ret = sprintf(buf, "kadc = 0x%x",
1026 lpi->als_kadc);
1027
1028 return ret;
1029}
1030
1031static ssize_t ls_kadc_store(struct device *dev,
1032 struct device_attribute *attr,
1033 const char *buf, size_t count)
1034{
1035 struct cm36283_info *lpi = lp_info;
1036 int kadc_temp = 0;
1037
1038 sscanf(buf, "%d", &kadc_temp);
1039
1040 mutex_lock(&als_get_adc_mutex);
Oliver Wangd89c81b2013-09-22 19:49:29 +08001041 if (kadc_temp != 0) {
Joseph Hsiao091151d2013-06-17 11:37:05 +08001042 lpi->als_kadc = kadc_temp;
Oliver Wangd89c81b2013-09-22 19:49:29 +08001043 if (lpi->als_gadc != 0) {
1044 if (lightsensor_update_table(lpi) < 0)
1045 dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
1046 __func__);
1047 else
1048 dev_dbg(&lpi->i2c_client->dev, "%s: als_gadc =0x%x wait to be set\n",
1049 __func__, lpi->als_gadc);
1050 }
Joseph Hsiao091151d2013-06-17 11:37:05 +08001051 } else {
Oliver Wangd89c81b2013-09-22 19:49:29 +08001052 dev_err(&lpi->i2c_client->dev, "%s: als_kadc can't be set to zero\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +08001053 __func__);
1054 }
1055
1056 mutex_unlock(&als_get_adc_mutex);
1057 return count;
1058}
1059
1060static DEVICE_ATTR(ls_kadc, 0664, ls_kadc_show, ls_kadc_store);
1061
1062static ssize_t ls_gadc_show(struct device *dev,
1063 struct device_attribute *attr, char *buf)
1064{
1065 struct cm36283_info *lpi = lp_info;
1066 int ret;
1067
1068 ret = sprintf(buf, "gadc = 0x%x\n", lpi->als_gadc);
1069
1070 return ret;
1071}
1072
1073static ssize_t ls_gadc_store(struct device *dev,
1074 struct device_attribute *attr,
1075 const char *buf, size_t count)
1076{
1077 struct cm36283_info *lpi = lp_info;
1078 int gadc_temp = 0;
1079
1080 sscanf(buf, "%d", &gadc_temp);
1081
1082 mutex_lock(&als_get_adc_mutex);
Oliver Wangd89c81b2013-09-22 19:49:29 +08001083 if (gadc_temp != 0) {
Joseph Hsiao091151d2013-06-17 11:37:05 +08001084 lpi->als_gadc = gadc_temp;
Oliver Wangd89c81b2013-09-22 19:49:29 +08001085 if (lpi->als_kadc != 0) {
1086 if (lightsensor_update_table(lpi) < 0)
1087 dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
1088 __func__);
1089 } else {
1090 dev_dbg(&lpi->i2c_client->dev, "als_kadc =0x%x wait to be set\n",
1091 lpi->als_kadc);
1092 }
Joseph Hsiao091151d2013-06-17 11:37:05 +08001093 } else {
Oliver Wangd89c81b2013-09-22 19:49:29 +08001094 dev_err(&lpi->i2c_client->dev, "als_gadc can't be set to zero\n");
Joseph Hsiao091151d2013-06-17 11:37:05 +08001095 }
1096 mutex_unlock(&als_get_adc_mutex);
1097 return count;
1098}
1099
1100static DEVICE_ATTR(ls_gadc, 0664, ls_gadc_show, ls_gadc_store);
1101
1102static ssize_t ls_adc_table_show(struct device *dev,
1103 struct device_attribute *attr, char *buf)
1104{
1105 unsigned length = 0;
1106 int i;
1107
1108 for (i = 0; i < 10; i++) {
1109 length += sprintf(buf + length,
1110 "[CM36283]Get adc_table[%d] = 0x%x ; %d, Get cali_table[%d] = 0x%x ; %d, \n",
1111 i, *(lp_info->adc_table + i),
1112 *(lp_info->adc_table + i),
1113 i, *(lp_info->cali_table + i),
1114 *(lp_info->cali_table + i));
1115 }
1116 return length;
1117}
1118
1119static ssize_t ls_adc_table_store(struct device *dev,
1120 struct device_attribute *attr,
1121 const char *buf, size_t count)
1122{
1123
1124 struct cm36283_info *lpi = lp_info;
1125 char *token[10];
1126 uint16_t tempdata[10];
1127 int i;
1128
Joseph Hsiao091151d2013-06-17 11:37:05 +08001129 for (i = 0; i < 10; i++) {
1130 token[i] = strsep((char **)&buf, " ");
1131 tempdata[i] = simple_strtoul(token[i], NULL, 16);
1132 if (tempdata[i] < 1 || tempdata[i] > 0xffff) {
Oliver Wangd89c81b2013-09-22 19:49:29 +08001133 dev_err(&lpi->i2c_client->dev,
1134 "adc_table[%d] = 0x%x error\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +08001135 i, tempdata[i]);
1136 return count;
1137 }
1138 }
1139 mutex_lock(&als_get_adc_mutex);
Oliver Wangd89c81b2013-09-22 19:49:29 +08001140 for (i = 0; i < 10; i++)
Joseph Hsiao091151d2013-06-17 11:37:05 +08001141 lpi->adc_table[i] = tempdata[i];
Oliver Wangd89c81b2013-09-22 19:49:29 +08001142
Joseph Hsiao091151d2013-06-17 11:37:05 +08001143 if (lightsensor_update_table(lpi) < 0)
Oliver Wangd89c81b2013-09-22 19:49:29 +08001144 dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +08001145 __func__);
1146 mutex_unlock(&als_get_adc_mutex);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001147
1148 return count;
1149}
1150
1151static DEVICE_ATTR(ls_adc_table, 0664,
1152 ls_adc_table_show, ls_adc_table_store);
1153
1154static ssize_t ls_conf_show(struct device *dev,
1155 struct device_attribute *attr, char *buf)
1156{
1157 struct cm36283_info *lpi = lp_info;
1158 return sprintf(buf, "ALS_CONF = %x\n", lpi->ls_cmd);
1159}
1160static ssize_t ls_conf_store(struct device *dev,
1161 struct device_attribute *attr,
1162 const char *buf, size_t count)
1163{
1164 struct cm36283_info *lpi = lp_info;
1165 int value = 0;
1166 sscanf(buf, "0x%x", &value);
1167
1168 lpi->ls_cmd = value;
Oliver Wangd89c81b2013-09-22 19:49:29 +08001169
1170 dev_dbg(&lpi->i2c_client->dev, "ALS_CONF:0x%x\n", lpi->ls_cmd);
1171
Joseph Hsiao091151d2013-06-17 11:37:05 +08001172 _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
1173 return count;
1174}
1175static DEVICE_ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store);
1176
Oliver Wanged314dd2013-08-23 16:34:37 +08001177static ssize_t ls_poll_delay_show(struct device *dev,
1178 struct device_attribute *attr, char *buf)
1179{
1180 struct cm36283_info *lpi = lp_info;
1181 return snprintf(buf, PAGE_SIZE, "%d\n",
1182 atomic_read(&lpi->ls_poll_delay));
1183}
1184
1185static ssize_t ls_poll_delay_store(struct device *dev,
1186 struct device_attribute *attr, const char *buf, size_t count)
1187{
1188 struct cm36283_info *lpi = lp_info;
1189 unsigned long interval_ms;
1190
1191 if (kstrtoul(buf, 10, &interval_ms))
1192 return -EINVAL;
1193
1194 if ((interval_ms < CM36283_LS_MIN_POLL_DELAY) ||
1195 (interval_ms > CM36283_LS_MAX_POLL_DELAY))
1196 return -EINVAL;
1197
1198 atomic_set(&lpi->ls_poll_delay, (unsigned int) interval_ms);
1199 return count;
1200}
1201
1202static DEVICE_ATTR(ls_poll_delay, 0664, ls_poll_delay_show,
1203 ls_poll_delay_store);
1204
1205static ssize_t ps_poll_delay_show(struct device *dev,
1206 struct device_attribute *attr, char *buf)
1207{
1208 struct cm36283_info *lpi = lp_info;
1209 return snprintf(buf, PAGE_SIZE, "%d\n",
1210 atomic_read(&lpi->ps_poll_delay));
1211}
1212
1213static ssize_t ps_poll_delay_store(struct device *dev,
1214 struct device_attribute *attr, const char *buf, size_t count)
1215{
1216 struct cm36283_info *lpi = lp_info;
1217 unsigned long interval_ms;
1218
1219 if (kstrtoul(buf, 10, &interval_ms))
1220 return -EINVAL;
1221
1222 if ((interval_ms < CM36283_PS_MIN_POLL_DELAY) ||
1223 (interval_ms > CM36283_PS_MAX_POLL_DELAY))
1224 return -EINVAL;
1225
1226 atomic_set(&lpi->ps_poll_delay, (unsigned int) interval_ms);
1227 return count;
1228}
1229
1230static DEVICE_ATTR(ps_poll_delay, 0664, ps_poll_delay_show,
1231 ps_poll_delay_store);
1232
Joseph Hsiao091151d2013-06-17 11:37:05 +08001233static ssize_t ls_fLevel_show(struct device *dev,
1234 struct device_attribute *attr, char *buf)
1235{
1236 return sprintf(buf, "fLevel = %d\n", fLevel);
1237}
1238static ssize_t ls_fLevel_store(struct device *dev,
1239 struct device_attribute *attr,
1240 const char *buf, size_t count)
1241{
1242 struct cm36283_info *lpi = lp_info;
1243 int value=0;
1244 sscanf(buf, "%d", &value);
1245 (value>=0)?(value=min(value,10)):(value=max(value,-1));
1246 fLevel=value;
1247 input_report_abs(lpi->ls_input_dev, ABS_MISC, fLevel);
1248 input_sync(lpi->ls_input_dev);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001249
1250 msleep(1000);
1251 fLevel=-1;
1252 return count;
1253}
1254static DEVICE_ATTR(ls_flevel, 0664, ls_fLevel_show, ls_fLevel_store);
1255
1256static int lightsensor_setup(struct cm36283_info *lpi)
1257{
1258 int ret;
Oliver Wanged314dd2013-08-23 16:34:37 +08001259 int range;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001260
1261 lpi->ls_input_dev = input_allocate_device();
1262 if (!lpi->ls_input_dev) {
1263 pr_err(
1264 "[LS][CM36283 error]%s: could not allocate ls input device\n",
1265 __func__);
1266 return -ENOMEM;
1267 }
1268 lpi->ls_input_dev->name = "cm36283-ls";
1269 set_bit(EV_ABS, lpi->ls_input_dev->evbit);
Oliver Wanged314dd2013-08-23 16:34:37 +08001270
1271 range = get_als_range();
1272 input_set_abs_params(lpi->ls_input_dev, ABS_MISC, 0, range, 0, 0);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001273
1274 ret = input_register_device(lpi->ls_input_dev);
1275 if (ret < 0) {
1276 pr_err("[LS][CM36283 error]%s: can not register ls input device\n",
1277 __func__);
1278 goto err_free_ls_input_device;
1279 }
1280
1281 ret = misc_register(&lightsensor_misc);
1282 if (ret < 0) {
1283 pr_err("[LS][CM36283 error]%s: can not register ls misc device\n",
1284 __func__);
1285 goto err_unregister_ls_input_device;
1286 }
1287
1288 return ret;
1289
1290err_unregister_ls_input_device:
1291 input_unregister_device(lpi->ls_input_dev);
1292err_free_ls_input_device:
1293 input_free_device(lpi->ls_input_dev);
1294 return ret;
1295}
1296
1297static int psensor_setup(struct cm36283_info *lpi)
1298{
1299 int ret;
1300
1301 lpi->ps_input_dev = input_allocate_device();
1302 if (!lpi->ps_input_dev) {
1303 pr_err(
1304 "[PS][CM36283 error]%s: could not allocate ps input device\n",
1305 __func__);
1306 return -ENOMEM;
1307 }
1308 lpi->ps_input_dev->name = "cm36283-ps";
1309 set_bit(EV_ABS, lpi->ps_input_dev->evbit);
1310 input_set_abs_params(lpi->ps_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
1311
1312 ret = input_register_device(lpi->ps_input_dev);
1313 if (ret < 0) {
1314 pr_err(
1315 "[PS][CM36283 error]%s: could not register ps input device\n",
1316 __func__);
1317 goto err_free_ps_input_device;
1318 }
1319
1320 ret = misc_register(&psensor_misc);
1321 if (ret < 0) {
1322 pr_err(
1323 "[PS][CM36283 error]%s: could not register ps misc device\n",
1324 __func__);
1325 goto err_unregister_ps_input_device;
1326 }
1327
1328 return ret;
1329
1330err_unregister_ps_input_device:
1331 input_unregister_device(lpi->ps_input_dev);
1332err_free_ps_input_device:
1333 input_free_device(lpi->ps_input_dev);
1334 return ret;
1335}
1336
1337
1338static int initial_cm36283(struct cm36283_info *lpi)
1339{
1340 int val, ret;
1341 uint16_t idReg;
1342
1343 val = gpio_get_value(lpi->intr_pin);
Oliver Wangd89c81b2013-09-22 19:49:29 +08001344 dev_dbg(&lpi->i2c_client->dev, "%s, INTERRUPT GPIO val = %d\n",
1345 __func__, val);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001346
1347 ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ID_REG, &idReg);
Oliver Wanged314dd2013-08-23 16:34:37 +08001348
1349 return ret;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001350}
1351
1352static int cm36283_setup(struct cm36283_info *lpi)
1353{
1354 int ret = 0;
1355
1356 als_power(1);
1357 msleep(5);
1358 ret = gpio_request(lpi->intr_pin, "gpio_cm36283_intr");
1359 if (ret < 0) {
1360 pr_err("[PS][CM36283 error]%s: gpio %d request failed (%d)\n",
1361 __func__, lpi->intr_pin, ret);
1362 return ret;
1363 }
1364
1365 ret = gpio_direction_input(lpi->intr_pin);
1366 if (ret < 0) {
1367 pr_err(
1368 "[PS][CM36283 error]%s: fail to set gpio %d as input (%d)\n",
1369 __func__, lpi->intr_pin, ret);
1370 goto fail_free_intr_pin;
1371 }
1372
1373
1374 ret = initial_cm36283(lpi);
1375 if (ret < 0) {
1376 pr_err(
1377 "[PS_ERR][CM36283 error]%s: fail to initial cm36283 (%d)\n",
1378 __func__, ret);
1379 goto fail_free_intr_pin;
1380 }
1381
1382 /*Default disable P sensor and L sensor*/
Oliver Wanged314dd2013-08-23 16:34:37 +08001383 ls_initial_cmd(lpi);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001384 psensor_initial_cmd(lpi);
1385
Oliver Wanged314dd2013-08-23 16:34:37 +08001386 if (!lpi->polling)
1387 ret = request_any_context_irq(lpi->irq,
1388 cm36283_irq_handler,
1389 IRQF_TRIGGER_LOW,
1390 "cm36283",
1391 lpi);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001392 if (ret < 0) {
1393 pr_err(
1394 "[PS][CM36283 error]%s: req_irq(%d) fail for gpio %d (%d)\n",
1395 __func__, lpi->irq,
1396 lpi->intr_pin, ret);
1397 goto fail_free_intr_pin;
1398 }
1399
1400 return ret;
1401
1402fail_free_intr_pin:
1403 gpio_free(lpi->intr_pin);
1404 return ret;
1405}
1406
1407#ifdef CONFIG_HAS_EARLYSUSPEND
1408static void cm36283_early_suspend(struct early_suspend *h)
1409{
1410 struct cm36283_info *lpi = lp_info;
1411
1412 D("[LS][CM36283] %s\n", __func__);
1413
1414 if (lpi->als_enable)
1415 lightsensor_disable(lpi);
1416
1417}
1418
1419static void cm36283_late_resume(struct early_suspend *h)
1420{
1421 struct cm36283_info *lpi = lp_info;
1422
1423 D("[LS][CM36283] %s\n", __func__);
1424
1425 if (!lpi->als_enable)
1426 lightsensor_enable(lpi);
1427}
1428#endif
1429
Oliver Wang8a1b8be2013-08-23 13:42:10 +08001430static int cm36283_parse_dt(struct device *dev,
1431 struct cm36283_platform_data *pdata)
1432{
1433 struct device_node *np = dev->of_node;
1434 u32 levels[CM36283_LEVELS_SIZE], i;
1435 u32 temp_val;
1436 int rc;
1437
1438 rc = of_get_named_gpio_flags(np, "capella,interrupt-gpio",
1439 0, NULL);
1440 if (rc < 0) {
1441 dev_err(dev, "Unable to read interrupt pin number\n");
1442 return rc;
1443 } else {
1444 pdata->intr = rc;
1445 }
1446
1447 rc = of_property_read_u32_array(np, "capella,levels", levels,
1448 CM36283_LEVELS_SIZE);
1449 if (rc) {
1450 dev_err(dev, "Unable to read levels data\n");
1451 return rc;
1452 } else {
1453 for (i = 0; i < CM36283_LEVELS_SIZE; i++)
1454 pdata->levels[i] = levels[i];
1455 }
1456
1457 rc = of_property_read_u32(np, "capella,ps_close_thd_set", &temp_val);
1458 if (rc) {
1459 dev_err(dev, "Unable to read ps_close_thd_set\n");
1460 return rc;
1461 } else {
1462 pdata->ps_close_thd_set = (u8)temp_val;
1463 }
1464
1465 rc = of_property_read_u32(np, "capella,ps_away_thd_set", &temp_val);
1466 if (rc) {
1467 dev_err(dev, "Unable to read ps_away_thd_set\n");
1468 return rc;
1469 } else {
1470 pdata->ps_away_thd_set = (u8)temp_val;
1471 }
1472
1473 rc = of_property_read_u32(np, "capella,ls_cmd", &temp_val);
1474 if (rc) {
1475 dev_err(dev, "Unable to read ls_cmd\n");
1476 return rc;
1477 } else {
1478 pdata->ls_cmd = (u16)temp_val;
1479 }
1480
1481 rc = of_property_read_u32(np, "capella,ps_conf1_val", &temp_val);
1482 if (rc) {
1483 dev_err(dev, "Unable to read ps_conf1_val\n");
1484 return rc;
1485 } else {
1486 pdata->ps_conf1_val = (u16)temp_val;
1487 }
1488
1489 rc = of_property_read_u32(np, "capella,ps_conf3_val", &temp_val);
1490 if (rc) {
1491 dev_err(dev, "Unable to read ps_conf3_val\n");
1492 return rc;
1493 } else {
1494 pdata->ps_conf3_val = (u16)temp_val;
1495 }
1496
1497 pdata->polling = of_property_read_bool(np, "capella,use-polling");
1498
1499 return 0;
1500}
1501
Joseph Hsiao091151d2013-06-17 11:37:05 +08001502static int cm36283_probe(struct i2c_client *client,
1503 const struct i2c_device_id *id)
1504{
1505 int ret = 0;
1506 struct cm36283_info *lpi;
1507 struct cm36283_platform_data *pdata;
1508
Joseph Hsiao091151d2013-06-17 11:37:05 +08001509 lpi = kzalloc(sizeof(struct cm36283_info), GFP_KERNEL);
1510 if (!lpi)
1511 return -ENOMEM;
1512
Joseph Hsiao091151d2013-06-17 11:37:05 +08001513 lpi->i2c_client = client;
Oliver Wang8a1b8be2013-08-23 13:42:10 +08001514
1515 if (client->dev.of_node) {
1516 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
1517 if (!pdata) {
1518 dev_err(&client->dev, "Failed to allocate memory for pdata\n");
1519 ret = -ENOMEM;
1520 goto err_platform_data_null;
1521 }
1522
1523 ret = cm36283_parse_dt(&client->dev, pdata);
1524 pdata->slave_addr = client->addr;
1525 if (ret) {
1526 dev_err(&client->dev, "Failed to get pdata from device tree\n");
1527 goto err_parse_dt;
1528 }
1529 } else {
1530 pdata = client->dev.platform_data;
1531 if (!pdata) {
1532 dev_err(&client->dev, "%s: Assign platform_data error!!\n",
1533 __func__);
1534 ret = -EBUSY;
1535 goto err_platform_data_null;
1536 }
Joseph Hsiao091151d2013-06-17 11:37:05 +08001537 }
1538
1539 lpi->irq = client->irq;
1540
1541 i2c_set_clientdata(client, lpi);
1542
1543 lpi->intr_pin = pdata->intr;
1544 lpi->adc_table = pdata->levels;
1545 lpi->power = pdata->power;
1546
1547 lpi->slave_addr = pdata->slave_addr;
1548
1549 lpi->ps_away_thd_set = pdata->ps_away_thd_set;
1550 lpi->ps_close_thd_set = pdata->ps_close_thd_set;
1551 lpi->ps_conf1_val = pdata->ps_conf1_val;
1552 lpi->ps_conf3_val = pdata->ps_conf3_val;
Oliver Wanged314dd2013-08-23 16:34:37 +08001553 lpi->polling = pdata->polling;
1554 atomic_set(&lpi->ls_poll_delay,
1555 (unsigned int) CM36283_LS_DEFAULT_POLL_DELAY);
1556 atomic_set(&lpi->ps_poll_delay,
1557 (unsigned int) CM36283_PS_DEFAULT_POLL_DELAY);
1558
Joseph Hsiao091151d2013-06-17 11:37:05 +08001559
1560 lpi->ls_cmd = pdata->ls_cmd;
1561
1562 lpi->record_clear_int_fail=0;
1563
Oliver Wangd89c81b2013-09-22 19:49:29 +08001564 dev_dbg(&lpi->i2c_client->dev, "[PS][CM36283] %s: ls_cmd 0x%x\n",
Joseph Hsiao091151d2013-06-17 11:37:05 +08001565 __func__, lpi->ls_cmd);
1566
1567 if (pdata->ls_cmd == 0) {
1568 lpi->ls_cmd = CM36283_ALS_IT_160ms | CM36283_ALS_GAIN_2;
1569 }
1570
1571 lp_info = lpi;
1572
1573 mutex_init(&CM36283_control_mutex);
1574
1575 mutex_init(&als_enable_mutex);
1576 mutex_init(&als_disable_mutex);
1577 mutex_init(&als_get_adc_mutex);
1578
Joseph Hsiao091151d2013-06-17 11:37:05 +08001579
1580 mutex_init(&ps_enable_mutex);
1581 mutex_init(&ps_disable_mutex);
1582 mutex_init(&ps_get_adc_mutex);
1583
Joseph Hsiao091151d2013-06-17 11:37:05 +08001584
1585 //SET LUX STEP FACTOR HERE
1586 // if adc raw value one step = 5/100 = 1/20 = 0.05 lux
1587 // the following will set the factor 0.05 = 1/20
1588 // and lpi->golden_adc = 1;
1589 // set als_kadc = (ALS_CALIBRATED <<16) | 20;
1590
1591 als_kadc = (ALS_CALIBRATED <<16) | 20;
1592 lpi->golden_adc = 1;
1593
1594 //ls calibrate always set to 1
1595 lpi->ls_calibrate = 1;
1596
1597 lightsensor_set_kvalue(lpi);
1598 ret = lightsensor_update_table(lpi);
1599 if (ret < 0) {
1600 pr_err("[LS][CM36283 error]%s: update ls table fail\n",
1601 __func__);
1602 goto err_lightsensor_update_table;
1603 }
1604
1605 lpi->lp_wq = create_singlethread_workqueue("cm36283_wq");
1606 if (!lpi->lp_wq) {
1607 pr_err("[PS][CM36283 error]%s: can't create workqueue\n", __func__);
1608 ret = -ENOMEM;
1609 goto err_create_singlethread_workqueue;
1610 }
1611 wake_lock_init(&(lpi->ps_wake_lock), WAKE_LOCK_SUSPEND, "proximity");
1612
Oliver Wang0afd6a32013-08-26 14:23:51 +08001613 ret = cm36283_power_set(lpi, true);
1614 if (ret < 0) {
1615 dev_err(&client->dev, "%s:cm36283 power on error!\n", __func__);
1616 goto err_cm36283_power_on;
1617 }
1618
Joseph Hsiao091151d2013-06-17 11:37:05 +08001619 ret = cm36283_setup(lpi);
1620 if (ret < 0) {
1621 pr_err("[PS_ERR][CM36283 error]%s: cm36283_setup error!\n", __func__);
1622 goto err_cm36283_setup;
1623 }
Oliver Wang0afd6a32013-08-26 14:23:51 +08001624
1625 ret = lightsensor_setup(lpi);
1626 if (ret < 0) {
1627 pr_err("[LS][CM36283 error]%s: lightsensor_setup error!!\n",
1628 __func__);
1629 goto err_lightsensor_setup;
1630 }
1631
1632 ret = psensor_setup(lpi);
1633 if (ret < 0) {
1634 pr_err("[PS][CM36283 error]%s: psensor_setup error!!\n",
1635 __func__);
1636 goto err_psensor_setup;
1637 }
1638
Joseph Hsiao091151d2013-06-17 11:37:05 +08001639 lpi->cm36283_class = class_create(THIS_MODULE, "optical_sensors");
1640 if (IS_ERR(lpi->cm36283_class)) {
1641 ret = PTR_ERR(lpi->cm36283_class);
1642 lpi->cm36283_class = NULL;
1643 goto err_create_class;
1644 }
1645
1646 lpi->ls_dev = device_create(lpi->cm36283_class,
1647 NULL, 0, "%s", "lightsensor");
1648 if (unlikely(IS_ERR(lpi->ls_dev))) {
1649 ret = PTR_ERR(lpi->ls_dev);
1650 lpi->ls_dev = NULL;
1651 goto err_create_ls_device;
1652 }
1653
1654 /* register the attributes */
1655 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_adc);
1656 if (ret)
1657 goto err_create_ls_device_file;
1658
1659 /* register the attributes */
1660 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_auto);
1661 if (ret)
1662 goto err_create_ls_device_file;
1663
1664 /* register the attributes */
1665 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_kadc);
1666 if (ret)
1667 goto err_create_ls_device_file;
1668
1669 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_gadc);
1670 if (ret)
1671 goto err_create_ls_device_file;
1672
1673 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_adc_table);
1674 if (ret)
1675 goto err_create_ls_device_file;
1676
1677 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_conf);
1678 if (ret)
1679 goto err_create_ls_device_file;
1680
1681 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_flevel);
1682 if (ret)
1683 goto err_create_ls_device_file;
1684
Oliver Wanged314dd2013-08-23 16:34:37 +08001685 ret = device_create_file(lpi->ls_dev, &dev_attr_ls_poll_delay);
1686 if (ret)
1687 goto err_create_ls_device_file;
1688
Joseph Hsiao091151d2013-06-17 11:37:05 +08001689 lpi->ps_dev = device_create(lpi->cm36283_class,
1690 NULL, 0, "%s", "proximity");
1691 if (unlikely(IS_ERR(lpi->ps_dev))) {
1692 ret = PTR_ERR(lpi->ps_dev);
1693 lpi->ps_dev = NULL;
Oliver Wang0afd6a32013-08-26 14:23:51 +08001694 goto err_create_ps_device;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001695 }
1696
1697 /* register the attributes */
1698 ret = device_create_file(lpi->ps_dev, &dev_attr_ps_adc);
1699 if (ret)
Oliver Wang0afd6a32013-08-26 14:23:51 +08001700 goto err_create_ps_device_file;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001701
1702 ret = device_create_file(lpi->ps_dev,
1703 &dev_attr_ps_parameters);
1704 if (ret)
Oliver Wang0afd6a32013-08-26 14:23:51 +08001705 goto err_create_ps_device_file;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001706
1707 /* register the attributes */
1708 ret = device_create_file(lpi->ps_dev, &dev_attr_ps_conf);
1709 if (ret)
Oliver Wang0afd6a32013-08-26 14:23:51 +08001710 goto err_create_ps_device_file;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001711
1712 /* register the attributes */
1713 ret = device_create_file(lpi->ps_dev, &dev_attr_ps_thd);
1714 if (ret)
Oliver Wang0afd6a32013-08-26 14:23:51 +08001715 goto err_create_ps_device_file;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001716
1717 ret = device_create_file(lpi->ps_dev, &dev_attr_ps_hw);
1718 if (ret)
Oliver Wang0afd6a32013-08-26 14:23:51 +08001719 goto err_create_ps_device_file;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001720
Oliver Wanged314dd2013-08-23 16:34:37 +08001721 ret = device_create_file(lpi->ps_dev, &dev_attr_ps_poll_delay);
1722 if (ret)
Oliver Wang0afd6a32013-08-26 14:23:51 +08001723 goto err_create_ps_device_file;
Oliver Wanged314dd2013-08-23 16:34:37 +08001724
Joseph Hsiao091151d2013-06-17 11:37:05 +08001725#ifdef CONFIG_HAS_EARLYSUSPEND
1726 lpi->early_suspend.level =
1727 EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
1728 lpi->early_suspend.suspend = cm36283_early_suspend;
1729 lpi->early_suspend.resume = cm36283_late_resume;
1730 register_early_suspend(&lpi->early_suspend);
1731#endif
1732
Oliver Wanged314dd2013-08-23 16:34:37 +08001733 mutex_init(&wq_lock);
1734 INIT_DELAYED_WORK(&lpi->ldwork, lsensor_delay_work_handler);
1735 INIT_DELAYED_WORK(&lpi->pdwork, psensor_delay_work_handler);
Oliver Wangd89c81b2013-09-22 19:49:29 +08001736 dev_dbg(&lpi->i2c_client->dev, "%s: Probe success!\n", __func__);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001737
1738 return ret;
1739
Oliver Wang0afd6a32013-08-26 14:23:51 +08001740err_create_ps_device_file:
Joseph Hsiao091151d2013-06-17 11:37:05 +08001741 device_unregister(lpi->ps_dev);
Oliver Wang0afd6a32013-08-26 14:23:51 +08001742err_create_ps_device:
Joseph Hsiao091151d2013-06-17 11:37:05 +08001743err_create_ls_device_file:
1744 device_unregister(lpi->ls_dev);
1745err_create_ls_device:
1746 class_destroy(lpi->cm36283_class);
1747err_create_class:
Oliver Wang0afd6a32013-08-26 14:23:51 +08001748 misc_deregister(&psensor_misc);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001749 input_unregister_device(lpi->ps_input_dev);
1750 input_free_device(lpi->ps_input_dev);
Oliver Wang0afd6a32013-08-26 14:23:51 +08001751err_psensor_setup:
1752 misc_deregister(&lightsensor_misc);
1753 input_unregister_device(lpi->ls_input_dev);
1754 input_free_device(lpi->ls_input_dev);
1755err_lightsensor_setup:
1756err_cm36283_setup:
1757 cm36283_power_set(lpi, false);
1758err_cm36283_power_on:
1759 wake_lock_destroy(&(lpi->ps_wake_lock));
1760 destroy_workqueue(lpi->lp_wq);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001761err_create_singlethread_workqueue:
1762err_lightsensor_update_table:
Joseph Hsiao091151d2013-06-17 11:37:05 +08001763 mutex_destroy(&CM36283_control_mutex);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001764 mutex_destroy(&als_enable_mutex);
1765 mutex_destroy(&als_disable_mutex);
1766 mutex_destroy(&als_get_adc_mutex);
Oliver Wang0afd6a32013-08-26 14:23:51 +08001767 mutex_destroy(&ps_enable_mutex);
1768 mutex_destroy(&ps_disable_mutex);
1769 mutex_destroy(&ps_get_adc_mutex);
Oliver Wang8a1b8be2013-08-23 13:42:10 +08001770err_parse_dt:
1771 if (client->dev.of_node && (pdata != NULL))
1772 devm_kfree(&client->dev, pdata);
Joseph Hsiao091151d2013-06-17 11:37:05 +08001773err_platform_data_null:
1774 kfree(lpi);
Oliver Wang0afd6a32013-08-26 14:23:51 +08001775 dev_err(&client->dev, "%s:error exit! ret = %d\n", __func__, ret);
1776
Joseph Hsiao091151d2013-06-17 11:37:05 +08001777 return ret;
1778}
Oliver Wanged314dd2013-08-23 16:34:37 +08001779
1780static int control_and_report(struct cm36283_info *lpi, uint8_t mode,
1781 uint16_t param, int report)
1782{
1783 int ret = 0;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001784 uint16_t adc_value = 0;
Oliver Wanged314dd2013-08-23 16:34:37 +08001785 uint16_t ps_data = 0;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001786 int level = 0, i, val;
1787
1788 mutex_lock(&CM36283_control_mutex);
1789
1790 if( mode == CONTROL_ALS ){
1791 if(param){
1792 lpi->ls_cmd &= CM36283_ALS_SD_MASK;
1793 } else {
1794 lpi->ls_cmd |= CM36283_ALS_SD;
1795 }
1796 _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
1797 lpi->als_enable=param;
1798 } else if( mode == CONTROL_PS ){
1799 if(param){
1800 lpi->ps_conf1_val &= CM36283_PS_SD_MASK;
1801 lpi->ps_conf1_val |= CM36283_PS_INT_IN_AND_OUT;
1802 } else {
1803 lpi->ps_conf1_val |= CM36283_PS_SD;
1804 lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
1805 }
1806 _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
1807 lpi->ps_enable=param;
1808 }
1809 if((mode == CONTROL_ALS)||(mode == CONTROL_PS)){
1810 if( param==1 ){
1811 msleep(100);
1812 }
1813 }
1814
1815 if(lpi->als_enable){
1816 if( mode == CONTROL_ALS ||
1817 ( mode == CONTROL_INT_ISR_REPORT &&
1818 ((param&INT_FLAG_ALS_IF_L)||(param&INT_FLAG_ALS_IF_H)))){
1819
1820 lpi->ls_cmd &= CM36283_ALS_INT_MASK;
1821 ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
1822
1823 get_ls_adc_value(&adc_value, 0);
1824
1825 if( lpi->ls_calibrate ) {
1826 for (i = 0; i < 10; i++) {
1827 if (adc_value <= (*(lpi->cali_table + i))) {
1828 level = i;
1829 if (*(lpi->cali_table + i))
1830 break;
1831 }
1832 if ( i == 9) {/*avoid i = 10, because 'cali_table' of size is 10 */
1833 level = i;
1834 break;
1835 }
1836 }
1837 } else {
1838 for (i = 0; i < 10; i++) {
1839 if (adc_value <= (*(lpi->adc_table + i))) {
1840 level = i;
1841 if (*(lpi->adc_table + i))
1842 break;
1843 }
1844 if ( i == 9) {/*avoid i = 10, because 'cali_table' of size is 10 */
1845 level = i;
1846 break;
1847 }
1848 }
1849 }
Oliver Wanged314dd2013-08-23 16:34:37 +08001850 if (!lpi->polling) {
1851 ret = set_lsensor_range(((i == 0) ||
1852 (adc_value == 0)) ? 0 :
1853 *(lpi->cali_table + (i - 1)) + 1,
1854 *(lpi->cali_table + i));
1855
1856 lpi->ls_cmd |= CM36283_ALS_INT_EN;
1857 }
1858
1859 ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF,
1860 lpi->ls_cmd);
1861
1862 if (report) {
1863 lpi->current_level = level;
1864 lpi->current_adc = adc_value;
1865 input_report_abs(lpi->ls_input_dev, ABS_MISC, level);
1866 input_sync(lpi->ls_input_dev);
1867 }
Joseph Hsiao091151d2013-06-17 11:37:05 +08001868 }
1869 }
1870
1871#define PS_CLOSE 1
1872#define PS_AWAY (1<<1)
1873#define PS_CLOSE_AND_AWAY PS_CLOSE+PS_AWAY
Oliver Wanged314dd2013-08-23 16:34:37 +08001874 if (report && (lpi->ps_enable)) {
1875 int ps_status = 0;
1876 if (mode == CONTROL_PS)
1877 ps_status = PS_CLOSE_AND_AWAY;
1878 else if (mode == CONTROL_INT_ISR_REPORT) {
1879 if (param & INT_FLAG_PS_IF_CLOSE)
1880 ps_status |= PS_CLOSE;
1881 if (param & INT_FLAG_PS_IF_AWAY)
1882 ps_status |= PS_AWAY;
1883 }
Joseph Hsiao091151d2013-06-17 11:37:05 +08001884
Oliver Wanged314dd2013-08-23 16:34:37 +08001885 if (ps_status != 0) {
1886 switch (ps_status) {
1887 case PS_CLOSE_AND_AWAY:
1888 get_stable_ps_adc_value(&ps_data);
1889 val = (ps_data >= lpi->ps_close_thd_set)
1890 ? 0 : 1;
1891 break;
1892 case PS_AWAY:
1893 val = 1;
1894 break;
1895 case PS_CLOSE:
1896 val = 0;
1897 break;
1898 };
1899 input_report_abs(lpi->ps_input_dev, ABS_DISTANCE, val);
1900 input_sync(lpi->ps_input_dev);
1901 }
1902 }
Joseph Hsiao091151d2013-06-17 11:37:05 +08001903
Oliver Wanged314dd2013-08-23 16:34:37 +08001904 mutex_unlock(&CM36283_control_mutex);
1905 return ret;
Joseph Hsiao091151d2013-06-17 11:37:05 +08001906}
1907
Oliver Wanga9be2d22013-08-22 18:08:22 +08001908static int cm36283_power_set(struct cm36283_info *info, bool on)
1909{
1910 int rc;
1911
1912 if (on) {
1913 info->vdd = regulator_get(&info->i2c_client->dev, "vdd");
1914 if (IS_ERR(info->vdd)) {
1915 rc = PTR_ERR(info->vdd);
1916 dev_err(&info->i2c_client->dev,
1917 "Regulator get failed vdd rc=%d\n", rc);
1918 goto err_vdd_get;
1919 }
1920
1921 if (regulator_count_voltages(info->vdd) > 0) {
1922 rc = regulator_set_voltage(info->vdd,
1923 CM36283_VDD_MIN_UV, CM36283_VDD_MAX_UV);
1924 if (rc) {
1925 dev_err(&info->i2c_client->dev,
1926 "Regulator set failed vdd rc=%d\n", rc);
1927 goto err_vdd_set_vtg;
1928 }
1929 }
1930
1931 info->vio = regulator_get(&info->i2c_client->dev, "vio");
1932 if (IS_ERR(info->vio)) {
1933 rc = PTR_ERR(info->vio);
1934 dev_err(&info->i2c_client->dev,
1935 "Regulator get failed vio rc=%d\n", rc);
1936 goto err_vio_get;
1937 }
1938
1939 if (regulator_count_voltages(info->vio) > 0) {
1940 rc = regulator_set_voltage(info->vio,
1941 CM36283_VI2C_MIN_UV, CM36283_VI2C_MAX_UV);
1942 if (rc) {
1943 dev_err(&info->i2c_client->dev,
1944 "Regulator set failed vio rc=%d\n", rc);
1945 goto err_vio_set_vtg;
1946 }
1947 }
1948
1949 rc = regulator_enable(info->vdd);
1950 if (rc) {
1951 dev_err(&info->i2c_client->dev,
1952 "Regulator vdd enable failed rc=%d\n", rc);
1953 goto err_vdd_ena;
1954 }
1955
1956 rc = regulator_enable(info->vio);
1957 if (rc) {
1958 dev_err(&info->i2c_client->dev,
1959 "Regulator vio enable failed rc=%d\n", rc);
1960 goto err_vio_ena;
1961 }
1962
1963 } else {
1964 rc = regulator_disable(info->vdd);
1965 if (rc) {
1966 dev_err(&info->i2c_client->dev,
1967 "Regulator vdd disable failed rc=%d\n", rc);
1968 return rc;
1969 }
1970 if (regulator_count_voltages(info->vdd) > 0)
1971 regulator_set_voltage(info->vdd, 0, CM36283_VDD_MAX_UV);
1972
1973 regulator_put(info->vdd);
1974
1975 rc = regulator_disable(info->vio);
1976 if (rc) {
1977 dev_err(&info->i2c_client->dev,
1978 "Regulator vio disable failed rc=%d\n", rc);
1979 return rc;
1980 }
1981 if (regulator_count_voltages(info->vio) > 0)
1982 regulator_set_voltage(info->vio, 0,
1983 CM36283_VI2C_MAX_UV);
1984
1985 regulator_put(info->vio);
1986 }
1987
1988 return 0;
1989
1990err_vio_ena:
1991 regulator_disable(info->vdd);
1992err_vdd_ena:
1993 if (regulator_count_voltages(info->vio) > 0)
1994 regulator_set_voltage(info->vio, 0, CM36283_VI2C_MAX_UV);
1995err_vio_set_vtg:
1996 regulator_put(info->vio);
1997err_vio_get:
1998 if (regulator_count_voltages(info->vdd) > 0)
1999 regulator_set_voltage(info->vdd, 0, CM36283_VDD_MAX_UV);
2000err_vdd_set_vtg:
2001 regulator_put(info->vdd);
2002err_vdd_get:
2003 return rc;
2004}
2005
2006#ifdef CONFIG_PM_SLEEP
2007static int cm36283_suspend(struct device *dev)
2008{
2009 struct cm36283_info *lpi = lp_info;
2010
2011 if (lpi->als_enable) {
2012 lightsensor_disable(lpi);
2013 lpi->als_enable = 1;
2014 }
2015 cm36283_power_set(lpi, 0);
2016
2017 return 0;
2018}
2019
2020static int cm36283_resume(struct device *dev)
2021{
2022 struct cm36283_info *lpi = lp_info;
2023
2024 cm36283_power_set(lpi, 1);
2025
2026 if (lpi->als_enable) {
2027 cm36283_setup(lpi);
2028 lightsensor_setup(lpi);
2029 psensor_setup(lpi);
2030 lightsensor_enable(lpi);
2031 }
2032 return 0;
2033}
2034#endif
2035
2036static UNIVERSAL_DEV_PM_OPS(cm36283_pm, cm36283_suspend, cm36283_resume, NULL);
Joseph Hsiao091151d2013-06-17 11:37:05 +08002037
2038static const struct i2c_device_id cm36283_i2c_id[] = {
2039 {CM36283_I2C_NAME, 0},
2040 {}
2041};
2042
Oliver Wang8a1b8be2013-08-23 13:42:10 +08002043static struct of_device_id cm36283_match_table[] = {
2044 { .compatible = "capella,cm36283",},
2045 { },
2046};
2047
Joseph Hsiao091151d2013-06-17 11:37:05 +08002048static struct i2c_driver cm36283_driver = {
2049 .id_table = cm36283_i2c_id,
2050 .probe = cm36283_probe,
2051 .driver = {
2052 .name = CM36283_I2C_NAME,
2053 .owner = THIS_MODULE,
Oliver Wanga9be2d22013-08-22 18:08:22 +08002054 .pm = &cm36283_pm,
Oliver Wang8a1b8be2013-08-23 13:42:10 +08002055 .of_match_table = cm36283_match_table,
Joseph Hsiao091151d2013-06-17 11:37:05 +08002056 },
2057};
2058
2059static int __init cm36283_init(void)
2060{
2061 return i2c_add_driver(&cm36283_driver);
2062}
2063
2064static void __exit cm36283_exit(void)
2065{
2066 i2c_del_driver(&cm36283_driver);
2067}
2068
2069module_init(cm36283_init);
2070module_exit(cm36283_exit);
2071
2072MODULE_LICENSE("GPL");
2073MODULE_DESCRIPTION("CM36283 Driver");
2074MODULE_AUTHOR("Frank Hsieh <pengyueh@gmail.com>");