upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / staging / iio / light / tmd27711.c
1 /*
2  *  tmd27711.c - Texas Advanced Optoelectronic Solutions Inc.
3  *               Proximity/Ambient light sensor
4  *
5  *  Copyright (C) 2010 Samsung Electronics
6  *  Donggeun Kim <dg77.kim@samsung.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/interrupt.h>
16 #include <linux/platform_device.h>
17 #include <linux/workqueue.h>
18 #include <linux/mutex.h>
19 #include <linux/err.h>
20 #include <linux/i2c.h>
21 #include <linux/delay.h>
22 #include <linux/slab.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/tmd27711.h>
25 #include "../iio.h"
26 #include "light.h"
27
28 #define TMD27711_MAX_LUX                65535
29 #define TMD27711_MAX_LUX_TABLE          10
30
31 static int als_saturation;
32 static int als_int_time;
33 static int als_time_scale;
34 static int als_gain_scale;
35 static int als_gain_trim = 100;
36
37 /* lux equation table */
38 struct tmd27711_lux_ratio_table {
39         u16 ratio;
40         u16 ch0;
41         u16 ch1;
42 };
43
44 static struct tmd27711_lux_ratio_table lux_ratio_table[5] = {
45         { 9830,         8320,   15360   },
46         { 12452,        10554,  22797   },
47         { 14746,        6234,   11430   },
48         { 17695,        3968,   6400    },
49         { 0,            0,      0       }
50 };
51
52 static int lux_table[TMD27711_MAX_LUX_TABLE] = {
53         1, 165, 288, 497, 869, 1532, 2692, 4692, 8280, 100000,
54 };
55
56 struct tmd27711_chip {
57         struct i2c_client               *client;
58         struct iio_dev                  *indio_dev;
59         struct work_struct              work_thresh;
60         s64                             last_timestamp;
61         struct mutex                    lock;
62
63         struct tmd27711_platform_data   *pdata;
64 };
65
66 static int tmd27711_set_8bit_value(struct tmd27711_chip *chip, u8 val,
67                         u8 *cached_value, u8 shift, u8 mask, u8 reg)
68 {
69         int ret = 0;
70         u8 value, temp;
71
72         mutex_lock(&chip->lock);
73         temp = (val << shift) & mask;
74         if (temp == *cached_value)
75                 goto out;
76
77         ret = value = i2c_smbus_read_byte_data(chip->client,
78                         TMD27711_DEFAULT_COMMAND | reg);
79         if (ret < 0)
80                 goto out;
81
82         value &= ~mask;
83         value |= temp;
84         *cached_value = temp;
85
86         ret = i2c_smbus_write_byte_data(chip->client,
87                         TMD27711_DEFAULT_COMMAND | reg, value);
88 out:
89         mutex_unlock(&chip->lock);
90         return ret;
91 }
92
93 static int tmd27711_get_8bit_value(u8 *cached_value, u8 shift)
94 {
95         return *cached_value >> shift;
96 }
97
98 static int tmd27711_set_16bit_value(struct tmd27711_chip *chip, u16 val,
99                         u16 *cached_value, u8 reg)
100 {
101         int ret = 0;
102         u8 values[2];
103
104         mutex_lock(&chip->lock);
105         if (val == *cached_value)
106                 goto out;
107
108         values[0] = val & TMD27711_8BIT_MASK;
109         values[1] = (val >> BITS_PER_BYTE) & TMD27711_8BIT_MASK;
110
111         *cached_value = val;
112         ret = i2c_smbus_write_i2c_block_data(chip->client,
113                 TMD27711_AUTO_INCREMENT_COMMAND | reg,
114                 2, values);
115         if (ret < 0)
116                 goto out;
117 out:
118         mutex_unlock(&chip->lock);
119         return ret;
120 }
121
122 static int tmd27711_get_16bit_value(u16 *cached_value)
123 {
124         return *cached_value;
125 }
126
127 static int tmd27711_get_raw_value(struct tmd27711_chip *chip, int reg)
128 {
129         u8 values[2];
130         u16 raw_value;
131         int ret;
132
133         mutex_lock(&chip->lock);
134         ret = i2c_smbus_read_i2c_block_data(chip->client,
135                 TMD27711_AUTO_INCREMENT_COMMAND | reg,
136                 2, values);
137         if (ret < 0) {
138                 mutex_unlock(&chip->lock);
139                 return ret;
140         }
141
142         raw_value = (values[1] << BITS_PER_BYTE) | values[0];
143         mutex_unlock(&chip->lock);
144
145         return raw_value;
146 }
147
148 /*
149  * Conversions between lux and ADC values.
150  */
151 static int tmd27711_get_illuminance0_input(struct tmd27711_chip *chip)
152 {
153         static int lux = 0;
154         unsigned int ch0, ch1, ratio, i;
155
156         ch0 = tmd27711_get_raw_value(chip, TMD27711_CH0DATAL);
157         if (ch0 < 0)
158                 return ch0;
159
160         ch1 = tmd27711_get_raw_value(chip, TMD27711_CH1DATAL);
161         if (ch1 < 0)
162                 return ch1;
163
164         if ((ch0 >= als_saturation) || (ch1 >= als_saturation)) {
165                 lux = TMD27711_MAX_LUX;
166                 return lux;
167         }
168
169         if (ch0 == 0) {
170                 lux = 0;
171                 return lux;
172         }
173
174         /* calculate ratio */
175         ratio = (ch1 << 15) / ch0;
176
177         /* convert to unscaled lux */
178         for (i = 0; i < 5; i++) {
179                 if (lux_ratio_table[i].ratio == 0) {
180                         lux = 0;
181                         break;
182                 }
183                 if (lux_ratio_table[i].ratio >= ratio) {
184                         lux = ch0 * lux_ratio_table[i].ch0 -
185                               ch1 * lux_ratio_table[i].ch1;
186                         break;
187                 }
188         }
189
190         if (lux < 0) {
191                 lux = 0;
192                 return lux;
193         }
194
195         /* adjust for active time scale */
196         lux = (lux + (als_time_scale >> 1)) / als_time_scale;
197         /* adjust for active gain scale */
198         lux = (lux + (als_gain_scale >> 1)) / als_gain_scale;
199
200         lux >>= 13;  /* tables have factor of 8192 builtin for accuracy */
201
202         lux *= als_gain_trim;
203         lux /= 100;
204
205         if (lux > TMD27711_MAX_LUX) /* check for overflow */
206                 lux = TMD27711_MAX_LUX;
207
208         return lux;
209 }
210
211 static int tmd27711_thresh_handler_th(struct iio_dev *dev_info,
212                                int index, s64 timestamp, int no_test)
213 {
214         struct tmd27711_chip *chip = dev_info->dev_data;
215
216         chip->last_timestamp = timestamp;
217         schedule_work(&chip->work_thresh);
218
219         return 0;
220 }
221
222 static void tmd27711_thresh_handler_bh(struct work_struct *work_s)
223 {
224         struct tmd27711_chip *chip =
225                 container_of(work_s, struct tmd27711_chip, work_thresh);
226         int value, enable_reg, ps_raw;
227
228         u8 ps_threshold[4];
229
230         value = i2c_smbus_read_byte_data(chip->client,
231                         TMD27711_DEFAULT_COMMAND | TMD27711_STATUS);
232
233         enable_reg = i2c_smbus_read_byte_data(chip->client,
234                                 TMD27711_DEFAULT_COMMAND | TMD27711_ENABLE);
235
236         if (value & TMD27711_PINT) {
237                 ps_raw = tmd27711_get_raw_value(chip, TMD27711_PDATAL);
238
239                 if (ps_raw > chip->pdata->ps_interrupt_h_thres) {
240                         ps_threshold[0] =
241                             chip->pdata->ps_interrupt_l_thres &
242                                                         TMD27711_8BIT_MASK;
243                         ps_threshold[1] =
244                             chip->pdata->ps_interrupt_l_thres >> BITS_PER_BYTE;
245                         ps_threshold[2] = 0xff;
246                         ps_threshold[3] = 0xff;
247
248                         iio_push_event(chip->indio_dev, 0,
249                                IIO_EVENT_CODE_PROXIMITY_THRESH_HIGH,
250                                chip->last_timestamp);
251                 } else {
252                         ps_threshold[0] = 0;
253                         ps_threshold[1] = 0;
254                         ps_threshold[2] =
255                             chip->pdata->ps_interrupt_h_thres &
256                                                         TMD27711_8BIT_MASK;
257                         ps_threshold[3] =
258                             chip->pdata->ps_interrupt_h_thres >> BITS_PER_BYTE;
259
260                         iio_push_event(chip->indio_dev, 0,
261                                IIO_EVENT_CODE_PROXIMITY_THRESH_LOW,
262                                chip->last_timestamp);
263                 }
264
265                 i2c_smbus_write_i2c_block_data(chip->client,
266                         TMD27711_AUTO_INCREMENT_COMMAND | TMD27711_PILTL,
267                         4, ps_threshold);
268         }
269
270         if ((value & TMD27711_AINT) && (enable_reg & TMD27711_AIEN)) {
271                 iio_push_event(chip->indio_dev, 0,
272                                IIO_EVENT_CODE_LIGHT_THRESH,
273                                chip->last_timestamp);
274         }
275
276         enable_irq(chip->client->irq);
277
278         /* Acknowledge proximity and ambient light sensor interrupt */
279         i2c_smbus_write_byte_data(chip->client,
280                 TMD27711_PS_ALS_INT_CLEAR_COMMAND, 0);
281 }
282
283 static ssize_t tmd27711_show_illuminance0_input(struct device *dev,
284                 struct device_attribute *attr, char *buf)
285 {
286         struct iio_dev *indio_dev = dev_get_drvdata(dev);
287         struct tmd27711_chip *chip = indio_dev->dev_data;
288         int value = tmd27711_get_illuminance0_input(chip);
289         return sprintf(buf, "%d\n", value);
290 }
291 static DEVICE_ATTR(illuminance0_input, S_IRUGO,
292                 tmd27711_show_illuminance0_input, NULL);
293
294 static int tmd27711_get_level(struct tmd27711_chip *chip)
295 {
296         int lux = tmd27711_get_illuminance0_input(chip);
297         int level = 0, i;
298
299         for (i = 0; i < TMD27711_MAX_LUX_TABLE; i++) {
300                 if (lux_table[i] > lux) {
301                         level = i;
302                         break;
303                 }
304         }
305
306         return level;
307 }
308
309 static ssize_t tmd27711_show_level(struct device *dev,
310                 struct device_attribute *attr, char *buf)
311 {
312         struct iio_dev *indio_dev = dev_get_drvdata(dev);
313         struct tmd27711_chip *chip = indio_dev->dev_data;
314         int value = tmd27711_get_level(chip);
315         return sprintf(buf, "%d\n", value);
316 }
317 static DEVICE_ATTR(level, S_IRUGO,
318                 tmd27711_show_level, NULL);
319
320 #define TMD27711_OUTPUT(name, reg)                                      \
321 static ssize_t tmd27711_show_##name(struct device *dev,                 \
322                 struct device_attribute *attr, char *buf)               \
323 {                                                                       \
324         struct iio_dev *indio_dev = dev_get_drvdata(dev);               \
325         struct tmd27711_chip *chip = indio_dev->dev_data;               \
326         int value = tmd27711_get_raw_value(chip, reg);                  \
327         return sprintf(buf, "%d\n", value);                             \
328 }                                                                       \
329 static DEVICE_ATTR(name, S_IRUGO, tmd27711_show_##name, NULL);
330
331 #define TMD27711_INPUT(set_func_type, name, field_name,                 \
332                        shift, mask, reg)                                \
333 static ssize_t tmd27711_store_##name(struct device *dev,                \
334         struct device_attribute *attr, const char *buf, size_t count)   \
335 {                                                                       \
336         struct iio_dev *indio_dev = dev_get_drvdata(dev);               \
337         struct tmd27711_chip *chip = indio_dev->dev_data;               \
338         int ret;                                                        \
339         unsigned long val;                                              \
340                                                                         \
341         if (!count)                                                     \
342                 return -EINVAL;                                         \
343                                                                         \
344         ret = strict_strtoul(buf, 10, &val);                            \
345         if (ret)                                                        \
346                 return -EINVAL;                                         \
347                                                                         \
348         if (set_func_type == TMD27711_8BIT_SET_FUNC)                    \
349                 ret = tmd27711_set_8bit_value(chip, val,                \
350                         (u8 *) &chip->pdata->field_name, shift,         \
351                         mask, reg);                                     \
352         else                                                            \
353                 ret = tmd27711_set_16bit_value(chip, val,               \
354                         (u16 *) &chip->pdata->field_name, reg);         \
355                                                                         \
356         if (ret < 0)                                                    \
357                 return ret;                                             \
358                                                                         \
359         return count;                                                   \
360 }                                                                       \
361                                                                         \
362 static ssize_t tmd27711_show_##name(struct device *dev,                 \
363                 struct device_attribute *attr, char *buf)               \
364 {                                                                       \
365         struct iio_dev *indio_dev = dev_get_drvdata(dev);               \
366         struct tmd27711_chip *chip = indio_dev->dev_data;               \
367         int value;                                                      \
368                                                                         \
369         if (set_func_type == TMD27711_8BIT_SET_FUNC)                    \
370                 value = tmd27711_get_8bit_value(                        \
371                           (u8 *) &chip->pdata->field_name, shift);      \
372         else                                                            \
373                 value = tmd27711_get_16bit_value(                       \
374                           (u16 *) &chip->pdata->field_name);            \
375         return sprintf(buf, "%d\n", value);                             \
376 }                                                                       \
377 static DEVICE_ATTR(name, S_IRUGO | S_IWUSR,                             \
378                 tmd27711_show_##name, tmd27711_store_##name);
379
380 TMD27711_OUTPUT(proximity_raw, TMD27711_PDATAL);
381 TMD27711_OUTPUT(intensity_both_raw, TMD27711_CH0DATAL);
382 TMD27711_OUTPUT(intensity_ir_raw, TMD27711_CH1DATAL);
383 TMD27711_INPUT(TMD27711_8BIT_SET_FUNC, power_on, power_on,
384                TMD27711_PON_SHIFT, TMD27711_PON, TMD27711_ENABLE);
385 TMD27711_INPUT(TMD27711_8BIT_SET_FUNC, wait_en, wait_enable,
386                TMD27711_WEN_SHIFT, TMD27711_WEN, TMD27711_ENABLE);
387 TMD27711_INPUT(TMD27711_8BIT_SET_FUNC, light_en, als_enable,
388                TMD27711_AEN_SHIFT, TMD27711_AEN, TMD27711_ENABLE);
389
390 static ssize_t tmd27711_store_proximity_en(struct device *dev,
391         struct device_attribute *attr, const char *buf, size_t count)
392 {
393         struct iio_dev *indio_dev = dev_get_drvdata(dev);
394         struct tmd27711_chip *chip = indio_dev->dev_data;
395         int ret;
396         unsigned long val;
397
398         if (!count)
399                 return -EINVAL;
400
401         ret = strict_strtoul(buf, 10, &val);
402         if (ret)
403                 return -EINVAL;
404
405         ret = tmd27711_set_8bit_value(chip, val,
406                 (u8 *) &chip->pdata->ps_enable, TMD27711_PEN_SHIFT,
407                 TMD27711_PEN, TMD27711_ENABLE);
408
409         if (ret < 0)
410                 return ret;
411
412         if (chip->pdata->ps_enable)
413                 iio_push_event(chip->indio_dev, 0,
414                                IIO_EVENT_CODE_PROXIMITY_THRESH_ENABLE,
415                                chip->last_timestamp);
416         else
417                 iio_push_event(chip->indio_dev, 0,
418                                IIO_EVENT_CODE_PROXIMITY_THRESH_DISABLE,
419                                chip->last_timestamp);
420
421         return count;
422 }
423
424 static ssize_t tmd27711_show_proximity_en(struct device *dev,
425                 struct device_attribute *attr, char *buf)
426 {
427         struct iio_dev *indio_dev = dev_get_drvdata(dev);
428         struct tmd27711_chip *chip = indio_dev->dev_data;
429         int value;
430
431         value = tmd27711_get_8bit_value(
432                   (u8 *) &chip->pdata->ps_enable, TMD27711_PEN_SHIFT);
433         return sprintf(buf, "%d\n", value);
434 }
435 static DEVICE_ATTR(proximity_en, S_IRUGO | S_IWUSR,
436                 tmd27711_show_proximity_en, tmd27711_store_proximity_en);
437
438 static ssize_t tmd27711_show_name(struct device *dev,
439                                 struct device_attribute *attr,
440                                 char *buf)
441 {
442         struct iio_dev *indio_dev = dev_get_drvdata(dev);
443         struct tmd27711_chip *chip = indio_dev->dev_data;
444         return sprintf(buf, "%s\n", chip->client->name);
445 }
446
447 static DEVICE_ATTR(name, S_IRUGO, tmd27711_show_name, NULL);
448
449 static struct attribute *tmd27711_attributes[] = {
450         &dev_attr_proximity_raw.attr,
451         &dev_attr_intensity_both_raw.attr,
452         &dev_attr_intensity_ir_raw.attr,
453         &dev_attr_illuminance0_input.attr,
454         &dev_attr_level.attr,
455         &dev_attr_power_on.attr,
456         /* wait_en can control the wait state.
457            When wait state is enabled, waiting time is inserted
458            between the proximity sensing state and the light sensing state. */
459         &dev_attr_wait_en.attr,
460         /* proximity_en can enable or disable the proximity sensor. */
461         &dev_attr_proximity_en.attr,
462         /* light_en can enable or disable the ambient light sensor. */
463         &dev_attr_light_en.attr,
464         &dev_attr_name.attr,
465         NULL
466 };
467
468 static const struct attribute_group tmd27711_group = {
469         .attrs = tmd27711_attributes,
470 };
471
472 static ssize_t tmd27711_read_interrupt_config(struct device *dev,
473                                         struct device_attribute *attr,
474                                         char *buf)
475 {
476         struct iio_event_attr *this_attr = to_iio_event_attr(attr);
477         struct iio_dev *indio_dev = dev_get_drvdata(dev);
478         struct tmd27711_chip *chip = indio_dev->dev_data;
479         u8 val;
480         int ret;
481
482         ret = val = i2c_smbus_read_byte_data(chip->client,
483                 TMD27711_DEFAULT_COMMAND | TMD27711_ENABLE);
484         if (ret < 0)
485                 return ret;
486
487         return sprintf(buf, "%d\n", !!(val & this_attr->mask));
488 }
489
490 static ssize_t tmd27711_write_interrupt_config(struct device *dev,
491                                         struct device_attribute *attr,
492                                         const char *buf,
493                                         size_t len)
494 {
495         struct iio_event_attr *this_attr = to_iio_event_attr(attr);
496         struct iio_dev *indio_dev = dev_get_drvdata(dev);
497         struct tmd27711_chip *chip = indio_dev->dev_data;
498         int ret, currentlyset, changed = 0;
499         u8 valold;
500         bool val;
501
502         val = !(buf[0] == '0');
503
504         mutex_lock(&indio_dev->mlock);
505
506         ret = valold = i2c_smbus_read_byte_data(chip->client,
507                                 TMD27711_DEFAULT_COMMAND | TMD27711_ENABLE);
508         if (ret < 0)
509                 goto error_mutex_unlock;
510
511         currentlyset = !!(valold & this_attr->mask);
512         if (val == false && currentlyset) {
513                 valold &= ~this_attr->mask;
514                 changed = 1;
515         } else if (val == true && !currentlyset) {
516                 changed = 1;
517                 valold |= this_attr->mask;
518         }
519
520         if (changed)
521                 ret = i2c_smbus_write_byte_data(chip->client,
522                         TMD27711_DEFAULT_COMMAND | TMD27711_ENABLE, valold);
523
524 error_mutex_unlock:
525         mutex_unlock(&indio_dev->mlock);
526
527         return (ret < 0) ? ret : len;
528 }
529
530 IIO_EVENT_SH(threshold, &tmd27711_thresh_handler_th);
531
532 IIO_EVENT_ATTR_SH(proximity_thresh_en,
533                   iio_event_threshold,
534                   tmd27711_read_interrupt_config,
535                   tmd27711_write_interrupt_config,
536                   TMD27711_PIEN);
537 TMD27711_INPUT(TMD27711_16BIT_SET_FUNC, proximity_thresh_rising_value,
538                ps_interrupt_h_thres, 0, 0, TMD27711_PIHTL);
539 TMD27711_INPUT(TMD27711_16BIT_SET_FUNC, proximity_thresh_falling_value,
540                ps_interrupt_l_thres, 0, 0, TMD27711_PILTL);
541 TMD27711_INPUT(TMD27711_8BIT_SET_FUNC, proximity_thresh_period,
542                ps_interrupt_persistence, TMD27711_PPERS_SHIFT,
543                TMD27711_PPERS_MASK, TMD27711_PERS);
544
545 IIO_EVENT_ATTR_SH(intensity_both_thresh_en,
546                   iio_event_threshold,
547                   tmd27711_read_interrupt_config,
548                   tmd27711_write_interrupt_config,
549                   TMD27711_AIEN);
550 TMD27711_INPUT(TMD27711_16BIT_SET_FUNC, intensity_both_thresh_rising_value,
551                als_interrupt_h_thres, 0, 0, TMD27711_AIHTL);
552 TMD27711_INPUT(TMD27711_16BIT_SET_FUNC, intensity_both_thresh_falling_value,
553                als_interrupt_l_thres, 0, 0, TMD27711_AILTL);
554 TMD27711_INPUT(TMD27711_8BIT_SET_FUNC, intensity_both_thresh_period,
555                als_interrupt_persistence, TMD27711_APERS_SHIFT,
556                TMD27711_APERS_MASK, TMD27711_PERS);
557
558 static struct attribute *tmd27711_event_attributes[] = {
559         &iio_event_attr_proximity_thresh_en.dev_attr.attr,
560         &dev_attr_proximity_thresh_rising_value.attr,
561         &dev_attr_proximity_thresh_falling_value.attr,
562         &dev_attr_proximity_thresh_period.attr,
563         &iio_event_attr_intensity_both_thresh_en.dev_attr.attr,
564         &dev_attr_intensity_both_thresh_rising_value.attr,
565         &dev_attr_intensity_both_thresh_falling_value.attr,
566         &dev_attr_intensity_both_thresh_period.attr,
567         NULL
568 };
569
570 static struct attribute_group tmd27711_event_attribute_group = {
571         .attrs = tmd27711_event_attributes,
572 };
573
574 static int tmd27711_initialize_chip(struct tmd27711_chip *chip)
575 {
576         u8 value, temp_low, temp_high;
577         int ret;
578
579         /* Disable and powerdown */
580         ret = i2c_smbus_write_byte_data(chip->client,
581                 TMD27711_DEFAULT_COMMAND | TMD27711_ENABLE, 0);
582         if (ret < 0)
583                 return ret;
584
585         /* ALS timing register */
586         value = chip->pdata->als_time;
587         ret = i2c_smbus_write_byte_data(chip->client,
588                 TMD27711_DEFAULT_COMMAND | TMD27711_ATIME, value);
589         if (ret < 0)
590                 return ret;
591
592         /* PS timing register */
593         value = chip->pdata->ps_time;
594         ret = i2c_smbus_write_byte_data(chip->client,
595                 TMD27711_DEFAULT_COMMAND | TMD27711_PTIME, value);
596         if (ret < 0)
597                 return ret;
598
599         /* Wait time register */
600         value = chip->pdata->wait_time;
601         ret = i2c_smbus_write_byte_data(chip->client,
602                 TMD27711_DEFAULT_COMMAND | TMD27711_WTIME, value);
603         if (ret < 0)
604                 return ret;
605
606         /* Proximity pulse count register */
607         value = chip->pdata->ps_pulse_count;
608         ret = i2c_smbus_write_byte_data(chip->client,
609                 TMD27711_DEFAULT_COMMAND | TMD27711_PPCOUNT, value);
610         if (ret < 0)
611                 return ret;
612
613         /* ALS interrupt threshold register */
614         temp_high = (chip->pdata->als_interrupt_l_thres >> BITS_PER_BYTE);
615         temp_low = chip->pdata->als_interrupt_l_thres & TMD27711_8BIT_MASK;
616         ret = i2c_smbus_write_byte_data(chip->client,
617                 TMD27711_DEFAULT_COMMAND | TMD27711_AILTL, temp_low);
618         if (ret < 0)
619                 return ret;
620         ret = i2c_smbus_write_byte_data(chip->client,
621                 TMD27711_DEFAULT_COMMAND | TMD27711_AILTH, temp_high);
622         if (ret < 0)
623                 return ret;
624
625         temp_high = (chip->pdata->als_interrupt_h_thres >> BITS_PER_BYTE);
626         temp_low = chip->pdata->als_interrupt_h_thres & TMD27711_8BIT_MASK;
627         ret = i2c_smbus_write_byte_data(chip->client,
628                 TMD27711_DEFAULT_COMMAND | TMD27711_AIHTL, temp_low);
629         if (ret < 0)
630                 return ret;
631         ret = i2c_smbus_write_byte_data(chip->client,
632                 TMD27711_DEFAULT_COMMAND | TMD27711_AIHTH, temp_high);
633         if (ret < 0)
634                 return ret;
635
636         /* PS interrupt threshold register */
637         temp_high = (chip->pdata->ps_interrupt_l_thres >> BITS_PER_BYTE);
638         temp_low = chip->pdata->ps_interrupt_l_thres & TMD27711_8BIT_MASK;
639         ret = i2c_smbus_write_byte_data(chip->client,
640                 TMD27711_DEFAULT_COMMAND | TMD27711_PILTL, temp_low);
641         if (ret < 0)
642                 return ret;
643         ret = i2c_smbus_write_byte_data(chip->client,
644                 TMD27711_DEFAULT_COMMAND | TMD27711_PILTH, temp_high);
645         if (ret < 0)
646                 return ret;
647
648         temp_high = (chip->pdata->ps_interrupt_h_thres >> BITS_PER_BYTE);
649         temp_low = chip->pdata->ps_interrupt_h_thres & TMD27711_8BIT_MASK;
650         ret = i2c_smbus_write_byte_data(chip->client,
651                 TMD27711_DEFAULT_COMMAND | TMD27711_PIHTL, temp_low);
652         if (ret < 0)
653                 return ret;
654         ret = i2c_smbus_write_byte_data(chip->client,
655                 TMD27711_DEFAULT_COMMAND | TMD27711_PIHTH, temp_high);
656         if (ret < 0)
657                 return ret;
658
659         /* Persistence register */
660         value = chip->pdata->ps_interrupt_persistence |
661                 chip->pdata->als_interrupt_persistence;
662         ret = i2c_smbus_write_byte_data(chip->client,
663                 TMD27711_DEFAULT_COMMAND | TMD27711_PERS, value);
664         if (ret < 0)
665                 return ret;
666
667         /* Configuration register */
668         value = chip->pdata->wait_long;
669         ret = i2c_smbus_write_byte_data(chip->client,
670                 TMD27711_DEFAULT_COMMAND | TMD27711_CONFIG, value);
671         if (ret < 0)
672                 return ret;
673
674         /* Control register */
675         value = chip->pdata->ps_drive_strength | chip->pdata->ps_diode |
676                 chip->pdata->als_gain;
677         ret = i2c_smbus_write_byte_data(chip->client,
678                 TMD27711_DEFAULT_COMMAND | TMD27711_CONTROL, value);
679         if (ret < 0)
680                 return ret;
681
682         /* Enable register */
683         value = chip->pdata->ps_interrupt_enable |
684                 chip->pdata->als_interrupt_enable |
685                 chip->pdata->wait_enable | chip->pdata->ps_enable |
686                 chip->pdata->als_enable | chip->pdata->power_on;
687         ret = i2c_smbus_write_byte_data(chip->client,
688                 TMD27711_DEFAULT_COMMAND | TMD27711_ENABLE, value);
689         if (ret < 0)
690                 return ret;
691
692         als_saturation = (256 - chip->pdata->als_time) * 922;
693         als_int_time = 27 * (256 - chip->pdata->als_time) / 10;
694         als_time_scale = als_int_time / 50;
695         als_gain_scale = chip->pdata->als_gain & 0x3;
696
697         return 0;
698 }
699
700 static int __devinit tmd27711_probe(struct i2c_client *client,
701                           const struct i2c_device_id *id)
702 {
703         struct tmd27711_chip *chip;
704         int ret = -1;
705
706         chip = kzalloc(sizeof(struct tmd27711_chip), GFP_KERNEL);
707         if (!chip)
708                 return -ENOMEM;
709
710         chip->pdata = client->dev.platform_data;
711         if (!(chip->pdata))
712                 goto error_no_pdata;
713
714         chip->client = client;
715         i2c_set_clientdata(client, chip);
716         mutex_init(&chip->lock);
717         INIT_WORK(&chip->work_thresh, tmd27711_thresh_handler_bh);
718
719         if (chip->pdata->control_power_source) {
720                 chip->pdata->control_power_source(1);
721                 msleep(TMD27711_POWERUP_WAIT_TIME);
722         }
723
724         /* Detect device id */
725         ret = i2c_smbus_read_byte_data(client,
726                         TMD27711_DEFAULT_COMMAND | TMD27711_ID);
727         if ((ret != TMD27711_DEV_ID) && (ret != TMD27713_DEV_ID)) {
728                 dev_err(&client->dev, "failed to detect device id\n");
729                 goto error_detect_id;
730         }
731
732         chip->indio_dev = iio_allocate_device();
733         if (!chip->indio_dev)
734                 goto error_allocate_iio;
735
736         chip->indio_dev->attrs = &tmd27711_group;
737         chip->indio_dev->dev.parent = &client->dev;
738         chip->indio_dev->dev_data = (void *)(chip);
739         chip->indio_dev->num_interrupt_lines = 1;
740         chip->indio_dev->event_attrs = &tmd27711_event_attribute_group;
741         chip->indio_dev->driver_module = THIS_MODULE;
742         chip->indio_dev->modes = INDIO_DIRECT_MODE;
743
744         ret = iio_device_register(chip->indio_dev);
745         if (ret)
746                 goto error_register_iio;
747
748         if (client->irq > 0) {
749                 ret = iio_register_interrupt_line(client->irq,
750                                                   chip->indio_dev,
751                                                   0,
752                                                   IRQF_TRIGGER_FALLING,
753                                                   "TMD27711");
754                 if (ret)
755                         goto error_register_interrupt;
756
757                 iio_add_event_to_list(&iio_event_threshold,
758                                     &chip->indio_dev->interrupts[0]->ev_list);
759
760         }
761
762         ret = tmd27711_initialize_chip(chip);
763         if (ret)
764                 goto error_initialize;
765
766         pm_runtime_set_active(&client->dev);
767
768         dev_info(&client->dev, "%s registered\n", id->name);
769
770         return 0;
771
772 error_initialize:
773 error_register_interrupt:
774         iio_device_unregister(chip->indio_dev);
775 error_register_iio:
776         iio_free_device(chip->indio_dev);
777 error_allocate_iio:
778 error_detect_id:
779         if (chip->pdata->control_power_source)
780                 chip->pdata->control_power_source(0);
781 error_no_pdata:
782         kfree(chip);
783         return ret;
784 }
785
786 static int __devexit tmd27711_remove(struct i2c_client *client)
787 {
788         struct tmd27711_chip *chip = i2c_get_clientdata(client);
789
790         if (chip->client->irq > 0)
791                 iio_unregister_interrupt_line(chip->indio_dev, 0);
792
793         iio_device_unregister(chip->indio_dev);
794         iio_free_device(chip->indio_dev);
795         kfree(chip);
796
797         return 0;
798 }
799
800 #ifdef CONFIG_PM
801 static int tmd27711_suspend(struct device *dev)
802 {
803         struct i2c_client *client = to_i2c_client(dev);
804         struct tmd27711_chip *chip = i2c_get_clientdata(client);
805
806         disable_irq_nosync(client->irq);
807
808         if (chip->pdata->control_power_source)
809                 chip->pdata->control_power_source(0);
810
811         return 0;
812 }
813
814 static int tmd27711_resume(struct device *dev)
815 {
816         struct i2c_client *client = to_i2c_client(dev);
817         struct tmd27711_chip *chip = i2c_get_clientdata(client);
818
819         if (chip->pdata->control_power_source) {
820                 chip->pdata->control_power_source(1);
821                 msleep(TMD27711_POWERUP_WAIT_TIME);
822         }
823
824         tmd27711_initialize_chip(chip);
825
826         enable_irq(client->irq);
827
828         return 0;
829 }
830
831 static struct dev_pm_ops tmd27711_dev_pm_ops = {
832         .suspend        = tmd27711_suspend,
833         .resume         = tmd27711_resume,
834 };
835
836 #define TMD27711_DEV_PM_OPS     (&tmd27711_dev_pm_ops)
837 #else
838 #define TMD27711_DEV_PM_OPS     NULL
839 #endif
840
841 static const struct i2c_device_id tmd27711_id[] = {
842         { "TMD27711", 0 },
843         { "TMD27713", 1 },
844         { }
845 };
846 MODULE_DEVICE_TABLE(i2c, tmd27711_id);
847
848 static struct i2c_driver tmd27711_i2c_driver = {
849         .driver = {
850                 .name   = "TMD27711",
851                 .pm     = TMD27711_DEV_PM_OPS,
852         },
853         .probe          = tmd27711_probe,
854         .remove         = __exit_p(tmd27711_remove),
855         .id_table       = tmd27711_id,
856 };
857
858 static int __init tmd27711_init(void)
859 {
860         return i2c_add_driver(&tmd27711_i2c_driver);
861 }
862 module_init(tmd27711_init);
863
864 static void __exit tmd27711_exit(void)
865 {
866         i2c_del_driver(&tmd27711_i2c_driver);
867 }
868 module_exit(tmd27711_exit);
869
870 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
871 MODULE_DESCRIPTION("TMD27711 Proximity/Ambient Light Sensor driver");
872 MODULE_LICENSE("GPL");