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
;
59 u16 buffer
[8]; /* 4x 16-bit + 8 bytes timestamp */
62 #define TCS3414_CHANNEL(_color, _si, _addr) { \
63 .type = IIO_INTENSITY, \
65 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
66 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
67 BIT(IIO_CHAN_INFO_INT_TIME), \
68 .channel2 = IIO_MOD_LIGHT_##_color, \
75 .endianness = IIO_CPU, \
79 /* scale factors: 1/gain */
80 static const int tcs3414_scales
[][2] = {
81 {1, 0}, {0, 250000}, {0, 62500}, {0, 15625}
84 /* integration time in ms */
85 static const int tcs3414_times
[] = { 12, 100, 400 };
87 static const struct iio_chan_spec tcs3414_channels
[] = {
88 TCS3414_CHANNEL(GREEN
, 0, TCS3414_DATA_GREEN
),
89 TCS3414_CHANNEL(RED
, 1, TCS3414_DATA_RED
),
90 TCS3414_CHANNEL(BLUE
, 2, TCS3414_DATA_BLUE
),
91 TCS3414_CHANNEL(CLEAR
, 3, TCS3414_DATA_CLEAR
),
92 IIO_CHAN_SOFT_TIMESTAMP(4),
95 static int tcs3414_req_data(struct tcs3414_data
*data
)
100 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
101 data
->control
| TCS3414_CONTROL_ADC_EN
);
106 ret
= i2c_smbus_read_byte_data(data
->client
, TCS3414_CONTROL
);
109 if (ret
& TCS3414_CONTROL_ADC_VALID
)
114 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
120 dev_err(&data
->client
->dev
, "data not ready\n");
127 static int tcs3414_read_raw(struct iio_dev
*indio_dev
,
128 struct iio_chan_spec
const *chan
,
129 int *val
, int *val2
, long mask
)
131 struct tcs3414_data
*data
= iio_priv(indio_dev
);
135 case IIO_CHAN_INFO_RAW
:
136 ret
= iio_device_claim_direct_mode(indio_dev
);
139 ret
= tcs3414_req_data(data
);
141 iio_device_release_direct_mode(indio_dev
);
144 ret
= i2c_smbus_read_word_data(data
->client
, chan
->address
);
145 iio_device_release_direct_mode(indio_dev
);
150 case IIO_CHAN_INFO_SCALE
:
151 i
= (data
->gain
& TCS3414_GAIN_MASK
) >> TCS3414_GAIN_SHIFT
;
152 *val
= tcs3414_scales
[i
][0];
153 *val2
= tcs3414_scales
[i
][1];
154 return IIO_VAL_INT_PLUS_MICRO
;
155 case IIO_CHAN_INFO_INT_TIME
:
157 *val2
= tcs3414_times
[data
->timing
& TCS3414_INTEG_MASK
] * 1000;
158 return IIO_VAL_INT_PLUS_MICRO
;
163 static int tcs3414_write_raw(struct iio_dev
*indio_dev
,
164 struct iio_chan_spec
const *chan
,
165 int val
, int val2
, long mask
)
167 struct tcs3414_data
*data
= iio_priv(indio_dev
);
171 case IIO_CHAN_INFO_SCALE
:
172 for (i
= 0; i
< ARRAY_SIZE(tcs3414_scales
); i
++) {
173 if (val
== tcs3414_scales
[i
][0] &&
174 val2
== tcs3414_scales
[i
][1]) {
175 data
->gain
&= ~TCS3414_GAIN_MASK
;
176 data
->gain
|= i
<< TCS3414_GAIN_SHIFT
;
177 return i2c_smbus_write_byte_data(
178 data
->client
, TCS3414_GAIN
,
183 case IIO_CHAN_INFO_INT_TIME
:
186 for (i
= 0; i
< ARRAY_SIZE(tcs3414_times
); i
++) {
187 if (val2
== tcs3414_times
[i
] * 1000) {
188 data
->timing
&= ~TCS3414_INTEG_MASK
;
190 return i2c_smbus_write_byte_data(
191 data
->client
, TCS3414_TIMING
,
201 static irqreturn_t
tcs3414_trigger_handler(int irq
, void *p
)
203 struct iio_poll_func
*pf
= p
;
204 struct iio_dev
*indio_dev
= pf
->indio_dev
;
205 struct tcs3414_data
*data
= iio_priv(indio_dev
);
208 for_each_set_bit(i
, indio_dev
->active_scan_mask
,
209 indio_dev
->masklength
) {
210 int ret
= i2c_smbus_read_word_data(data
->client
,
211 TCS3414_DATA_GREEN
+ 2*i
);
215 data
->buffer
[j
++] = ret
;
218 iio_push_to_buffers_with_timestamp(indio_dev
, data
->buffer
,
219 iio_get_time_ns(indio_dev
));
222 iio_trigger_notify_done(indio_dev
->trig
);
227 static IIO_CONST_ATTR(scale_available
, "1 0.25 0.0625 0.015625");
228 static IIO_CONST_ATTR_INT_TIME_AVAIL("0.012 0.1 0.4");
230 static struct attribute
*tcs3414_attributes
[] = {
231 &iio_const_attr_scale_available
.dev_attr
.attr
,
232 &iio_const_attr_integration_time_available
.dev_attr
.attr
,
236 static const struct attribute_group tcs3414_attribute_group
= {
237 .attrs
= tcs3414_attributes
,
240 static const struct iio_info tcs3414_info
= {
241 .read_raw
= tcs3414_read_raw
,
242 .write_raw
= tcs3414_write_raw
,
243 .attrs
= &tcs3414_attribute_group
,
244 .driver_module
= THIS_MODULE
,
247 static int tcs3414_buffer_preenable(struct iio_dev
*indio_dev
)
249 struct tcs3414_data
*data
= iio_priv(indio_dev
);
251 data
->control
|= TCS3414_CONTROL_ADC_EN
;
252 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
256 static int tcs3414_buffer_predisable(struct iio_dev
*indio_dev
)
258 struct tcs3414_data
*data
= iio_priv(indio_dev
);
261 ret
= iio_triggered_buffer_predisable(indio_dev
);
265 data
->control
&= ~TCS3414_CONTROL_ADC_EN
;
266 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
270 static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops
= {
271 .preenable
= tcs3414_buffer_preenable
,
272 .postenable
= &iio_triggered_buffer_postenable
,
273 .predisable
= tcs3414_buffer_predisable
,
276 static int tcs3414_probe(struct i2c_client
*client
,
277 const struct i2c_device_id
*id
)
279 struct tcs3414_data
*data
;
280 struct iio_dev
*indio_dev
;
283 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
284 if (indio_dev
== NULL
)
287 data
= iio_priv(indio_dev
);
288 i2c_set_clientdata(client
, indio_dev
);
289 data
->client
= client
;
291 indio_dev
->dev
.parent
= &client
->dev
;
292 indio_dev
->info
= &tcs3414_info
;
293 indio_dev
->name
= TCS3414_DRV_NAME
;
294 indio_dev
->channels
= tcs3414_channels
;
295 indio_dev
->num_channels
= ARRAY_SIZE(tcs3414_channels
);
296 indio_dev
->modes
= INDIO_DIRECT_MODE
;
298 ret
= i2c_smbus_read_byte_data(data
->client
, TCS3414_ID
);
302 switch (ret
& 0xf0) {
304 dev_info(&client
->dev
, "TCS3404 found\n");
307 dev_info(&client
->dev
, "TCS3413/14/15/16 found\n");
313 data
->control
= TCS3414_CONTROL_POWER
;
314 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
319 data
->timing
= TCS3414_INTEG_12MS
; /* free running */
320 ret
= i2c_smbus_write_byte_data(data
->client
, TCS3414_TIMING
,
325 ret
= i2c_smbus_read_byte_data(data
->client
, TCS3414_GAIN
);
330 ret
= iio_triggered_buffer_setup(indio_dev
, NULL
,
331 tcs3414_trigger_handler
, &tcs3414_buffer_setup_ops
);
335 ret
= iio_device_register(indio_dev
);
342 iio_triggered_buffer_cleanup(indio_dev
);
346 static int tcs3414_powerdown(struct tcs3414_data
*data
)
348 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
349 data
->control
& ~(TCS3414_CONTROL_POWER
|
350 TCS3414_CONTROL_ADC_EN
));
353 static int tcs3414_remove(struct i2c_client
*client
)
355 struct iio_dev
*indio_dev
= i2c_get_clientdata(client
);
357 iio_device_unregister(indio_dev
);
358 iio_triggered_buffer_cleanup(indio_dev
);
359 tcs3414_powerdown(iio_priv(indio_dev
));
364 #ifdef CONFIG_PM_SLEEP
365 static int tcs3414_suspend(struct device
*dev
)
367 struct tcs3414_data
*data
= iio_priv(i2c_get_clientdata(
368 to_i2c_client(dev
)));
369 return tcs3414_powerdown(data
);
372 static int tcs3414_resume(struct device
*dev
)
374 struct tcs3414_data
*data
= iio_priv(i2c_get_clientdata(
375 to_i2c_client(dev
)));
376 return i2c_smbus_write_byte_data(data
->client
, TCS3414_CONTROL
,
381 static SIMPLE_DEV_PM_OPS(tcs3414_pm_ops
, tcs3414_suspend
, tcs3414_resume
);
383 static const struct i2c_device_id tcs3414_id
[] = {
387 MODULE_DEVICE_TABLE(i2c
, tcs3414_id
);
389 static struct i2c_driver tcs3414_driver
= {
391 .name
= TCS3414_DRV_NAME
,
392 .pm
= &tcs3414_pm_ops
,
394 .probe
= tcs3414_probe
,
395 .remove
= tcs3414_remove
,
396 .id_table
= tcs3414_id
,
398 module_i2c_driver(tcs3414_driver
);
400 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
401 MODULE_DESCRIPTION("TCS3414 digital color sensors driver");
402 MODULE_LICENSE("GPL");