2 * tcs3414.c - Support for TAOS TCS3414 digital color sensor
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
6 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details.
10 * Digital color sensor with 16-bit channels for red, green, blue, clear);
11 * 7-bit I2C slave address 0x39 (TCS3414) or 0x29, 0x49, 0x59 (TCS3413,
12 * TCS3415, TCS3416, resp.)
14 * TODO: sync, interrupt support, thresholds, prescaler
17 #include <linux/module.h>
18 #include <linux/i2c.h>
19 #include <linux/delay.h>
22 #include <linux/iio/iio.h>
23 #include <linux/iio/sysfs.h>
24 #include <linux/iio/trigger_consumer.h>
25 #include <linux/iio/buffer.h>
26 #include <linux/iio/triggered_buffer.h>
28 #define TCS3414_DRV_NAME "tcs3414"
30 #define TCS3414_COMMAND BIT(7)
31 #define TCS3414_COMMAND_WORD (TCS3414_COMMAND | BIT(5))
33 #define TCS3414_CONTROL (TCS3414_COMMAND | 0x00)
34 #define TCS3414_TIMING (TCS3414_COMMAND | 0x01)
35 #define TCS3414_ID (TCS3414_COMMAND | 0x04)
36 #define TCS3414_GAIN (TCS3414_COMMAND | 0x07)
37 #define TCS3414_DATA_GREEN (TCS3414_COMMAND_WORD | 0x10)
38 #define TCS3414_DATA_RED (TCS3414_COMMAND_WORD | 0x12)
39 #define TCS3414_DATA_BLUE (TCS3414_COMMAND_WORD | 0x14)
40 #define TCS3414_DATA_CLEAR (TCS3414_COMMAND_WORD | 0x16)
42 #define TCS3414_CONTROL_ADC_VALID BIT(4)
43 #define TCS3414_CONTROL_ADC_EN BIT(1)
44 #define TCS3414_CONTROL_POWER BIT(0)
46 #define TCS3414_INTEG_MASK GENMASK(1, 0)
47 #define TCS3414_INTEG_12MS 0x0
48 #define TCS3414_INTEG_100MS 0x1
49 #define TCS3414_INTEG_400MS 0x2
51 #define TCS3414_GAIN_MASK GENMASK(5, 4)
52 #define TCS3414_GAIN_SHIFT 4
55 struct i2c_client
*client
;
60 u16 buffer
[8]; /* 4x 16-bit + 8 bytes timestamp */
63 #define TCS3414_CHANNEL(_color, _si, _addr) { \
64 .type = IIO_INTENSITY, \
66 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
67 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
68 BIT(IIO_CHAN_INFO_INT_TIME), \
69 .channel2 = IIO_MOD_LIGHT_##_color, \
76 .endianness = IIO_CPU, \
80 /* scale factors: 1/gain */
81 static const int tcs3414_scales
[][2] = {
82 {1, 0}, {0, 250000}, {0, 62500}, {0, 15625}
85 /* integration time in ms */
86 static const int tcs3414_times
[] = { 12, 100, 400 };
88 static const struct iio_chan_spec tcs3414_channels
[] = {
89 TCS3414_CHANNEL(GREEN
, 0, TCS3414_DATA_GREEN
),
90 TCS3414_CHANNEL(RED
, 1, TCS3414_DATA_RED
),
91 TCS3414_CHANNEL(BLUE
, 2, TCS3414_DATA_BLUE
),
92 TCS3414_CHANNEL(CLEAR
, 3, TCS3414_DATA_CLEAR
),
93 IIO_CHAN_SOFT_TIMESTAMP(4),
96 static int tcs3414_req_data(struct tcs3414_data
*data
)
101 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
102 data
->control
| TCS3414_CONTROL_ADC_EN
);
107 ret
= i2c_smbus_read_byte_data(data
->client
, TCS3414_CONTROL
);
110 if (ret
& TCS3414_CONTROL_ADC_VALID
)
115 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
121 dev_err(&data
->client
->dev
, "data not ready\n");
128 static int tcs3414_read_raw(struct iio_dev
*indio_dev
,
129 struct iio_chan_spec
const *chan
,
130 int *val
, int *val2
, long mask
)
132 struct tcs3414_data
*data
= iio_priv(indio_dev
);
136 case IIO_CHAN_INFO_RAW
:
137 if (iio_buffer_enabled(indio_dev
))
139 mutex_lock(&data
->lock
);
140 ret
= tcs3414_req_data(data
);
142 mutex_unlock(&data
->lock
);
145 ret
= i2c_smbus_read_word_data(data
->client
, chan
->address
);
146 mutex_unlock(&data
->lock
);
151 case IIO_CHAN_INFO_SCALE
:
152 i
= (data
->gain
& TCS3414_GAIN_MASK
) >> TCS3414_GAIN_SHIFT
;
153 *val
= tcs3414_scales
[i
][0];
154 *val2
= tcs3414_scales
[i
][1];
155 return IIO_VAL_INT_PLUS_MICRO
;
156 case IIO_CHAN_INFO_INT_TIME
:
158 *val2
= tcs3414_times
[data
->timing
& TCS3414_INTEG_MASK
] * 1000;
159 return IIO_VAL_INT_PLUS_MICRO
;
164 static int tcs3414_write_raw(struct iio_dev
*indio_dev
,
165 struct iio_chan_spec
const *chan
,
166 int val
, int val2
, long mask
)
168 struct tcs3414_data
*data
= iio_priv(indio_dev
);
172 case IIO_CHAN_INFO_SCALE
:
173 for (i
= 0; i
< ARRAY_SIZE(tcs3414_scales
); i
++) {
174 if (val
== tcs3414_scales
[i
][0] &&
175 val2
== tcs3414_scales
[i
][1]) {
176 data
->gain
&= ~TCS3414_GAIN_MASK
;
177 data
->gain
|= i
<< TCS3414_GAIN_SHIFT
;
178 return i2c_smbus_write_byte_data(
179 data
->client
, TCS3414_GAIN
,
184 case IIO_CHAN_INFO_INT_TIME
:
187 for (i
= 0; i
< ARRAY_SIZE(tcs3414_times
); i
++) {
188 if (val
== tcs3414_times
[i
] * 1000) {
189 data
->timing
&= ~TCS3414_INTEG_MASK
;
191 return i2c_smbus_write_byte_data(
192 data
->client
, TCS3414_TIMING
,
202 static irqreturn_t
tcs3414_trigger_handler(int irq
, void *p
)
204 struct iio_poll_func
*pf
= p
;
205 struct iio_dev
*indio_dev
= pf
->indio_dev
;
206 struct tcs3414_data
*data
= iio_priv(indio_dev
);
209 for_each_set_bit(i
, indio_dev
->active_scan_mask
,
210 indio_dev
->masklength
) {
211 int ret
= i2c_smbus_read_word_data(data
->client
,
212 TCS3414_DATA_GREEN
+ 2*i
);
216 data
->buffer
[j
++] = ret
;
219 iio_push_to_buffers_with_timestamp(indio_dev
, data
->buffer
,
223 iio_trigger_notify_done(indio_dev
->trig
);
228 static IIO_CONST_ATTR(scale_available
, "1 0.25 0.0625 0.015625");
229 static IIO_CONST_ATTR_INT_TIME_AVAIL("0.012 0.1 0.4");
231 static struct attribute
*tcs3414_attributes
[] = {
232 &iio_const_attr_scale_available
.dev_attr
.attr
,
233 &iio_const_attr_integration_time_available
.dev_attr
.attr
,
237 static const struct attribute_group tcs3414_attribute_group
= {
238 .attrs
= tcs3414_attributes
,
241 static const struct iio_info tcs3414_info
= {
242 .read_raw
= tcs3414_read_raw
,
243 .write_raw
= tcs3414_write_raw
,
244 .attrs
= &tcs3414_attribute_group
,
245 .driver_module
= THIS_MODULE
,
248 static int tcs3414_buffer_preenable(struct iio_dev
*indio_dev
)
250 struct tcs3414_data
*data
= iio_priv(indio_dev
);
252 data
->control
|= TCS3414_CONTROL_ADC_EN
;
253 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
257 static int tcs3414_buffer_predisable(struct iio_dev
*indio_dev
)
259 struct tcs3414_data
*data
= iio_priv(indio_dev
);
262 ret
= iio_triggered_buffer_predisable(indio_dev
);
266 data
->control
&= ~TCS3414_CONTROL_ADC_EN
;
267 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
271 static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops
= {
272 .preenable
= tcs3414_buffer_preenable
,
273 .postenable
= &iio_triggered_buffer_postenable
,
274 .predisable
= tcs3414_buffer_predisable
,
277 static int tcs3414_probe(struct i2c_client
*client
,
278 const struct i2c_device_id
*id
)
280 struct tcs3414_data
*data
;
281 struct iio_dev
*indio_dev
;
284 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
285 if (indio_dev
== NULL
)
288 data
= iio_priv(indio_dev
);
289 i2c_set_clientdata(client
, indio_dev
);
290 data
->client
= client
;
291 mutex_init(&data
->lock
);
293 indio_dev
->dev
.parent
= &client
->dev
;
294 indio_dev
->info
= &tcs3414_info
;
295 indio_dev
->name
= TCS3414_DRV_NAME
;
296 indio_dev
->channels
= tcs3414_channels
;
297 indio_dev
->num_channels
= ARRAY_SIZE(tcs3414_channels
);
298 indio_dev
->modes
= INDIO_DIRECT_MODE
;
300 ret
= i2c_smbus_read_byte_data(data
->client
, TCS3414_ID
);
304 switch (ret
& 0xf0) {
306 dev_info(&client
->dev
, "TCS3404 found\n");
309 dev_info(&client
->dev
, "TCS3413/14/15/16 found\n");
315 data
->control
= TCS3414_CONTROL_POWER
;
316 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
321 data
->timing
= TCS3414_INTEG_12MS
; /* free running */
322 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_TIMING
,
327 ret
= i2c_smbus_read_byte_data(data
->client
, TCS3414_GAIN
);
332 ret
= iio_triggered_buffer_setup(indio_dev
, NULL
,
333 tcs3414_trigger_handler
, &tcs3414_buffer_setup_ops
);
337 ret
= iio_device_register(indio_dev
);
344 iio_triggered_buffer_cleanup(indio_dev
);
348 static int tcs3414_powerdown(struct tcs3414_data
*data
)
350 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
351 data
->control
& ~(TCS3414_CONTROL_POWER
|
352 TCS3414_CONTROL_ADC_EN
));
355 static int tcs3414_remove(struct i2c_client
*client
)
357 struct iio_dev
*indio_dev
= i2c_get_clientdata(client
);
359 iio_device_unregister(indio_dev
);
360 iio_triggered_buffer_cleanup(indio_dev
);
361 tcs3414_powerdown(iio_priv(indio_dev
));
366 #ifdef CONFIG_PM_SLEEP
367 static int tcs3414_suspend(struct device
*dev
)
369 struct tcs3414_data
*data
= iio_priv(i2c_get_clientdata(
370 to_i2c_client(dev
)));
371 return tcs3414_powerdown(data
);
374 static int tcs3414_resume(struct device
*dev
)
376 struct tcs3414_data
*data
= iio_priv(i2c_get_clientdata(
377 to_i2c_client(dev
)));
378 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
383 static SIMPLE_DEV_PM_OPS(tcs3414_pm_ops
, tcs3414_suspend
, tcs3414_resume
);
385 static const struct i2c_device_id tcs3414_id
[] = {
389 MODULE_DEVICE_TABLE(i2c
, tcs3414_id
);
391 static struct i2c_driver tcs3414_driver
= {
393 .name
= TCS3414_DRV_NAME
,
394 .pm
= &tcs3414_pm_ops
,
395 .owner
= THIS_MODULE
,
397 .probe
= tcs3414_probe
,
398 .remove
= tcs3414_remove
,
399 .id_table
= tcs3414_id
,
401 module_i2c_driver(tcs3414_driver
);
403 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
404 MODULE_DESCRIPTION("TCS3414 digital color sensors driver");
405 MODULE_LICENSE("GPL");