diff options
Diffstat (limited to 'drivers/iio/light/adjd_s311.c')
| -rw-r--r-- | drivers/iio/light/adjd_s311.c | 144 |
1 files changed, 50 insertions, 94 deletions
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 164b62b91a4..09ad5f1ce53 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -14,7 +14,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/slab.h> @@ -37,22 +36,14 @@ #define ADJD_S311_CAP_GREEN 0x07 #define ADJD_S311_CAP_BLUE 0x08 #define ADJD_S311_CAP_CLEAR 0x09 -#define ADJD_S311_INT_RED_LO 0x0a -#define ADJD_S311_INT_RED_HI 0x0b -#define ADJD_S311_INT_GREEN_LO 0x0c -#define ADJD_S311_INT_GREEN_HI 0x0d -#define ADJD_S311_INT_BLUE_LO 0x0e -#define ADJD_S311_INT_BLUE_HI 0x0f -#define ADJD_S311_INT_CLEAR_LO 0x10 -#define ADJD_S311_INT_CLEAR_HI 0x11 -#define ADJD_S311_DATA_RED_LO 0x40 -#define ADJD_S311_DATA_RED_HI 0x41 -#define ADJD_S311_DATA_GREEN_LO 0x42 -#define ADJD_S311_DATA_GREEN_HI 0x43 -#define ADJD_S311_DATA_BLUE_LO 0x44 -#define ADJD_S311_DATA_BLUE_HI 0x45 -#define ADJD_S311_DATA_CLEAR_LO 0x46 -#define ADJD_S311_DATA_CLEAR_HI 0x47 +#define ADJD_S311_INT_RED 0x0a +#define ADJD_S311_INT_GREEN 0x0c +#define ADJD_S311_INT_BLUE 0x0e +#define ADJD_S311_INT_CLEAR 0x10 +#define ADJD_S311_DATA_RED 0x40 +#define ADJD_S311_DATA_GREEN 0x42 +#define ADJD_S311_DATA_BLUE 0x44 +#define ADJD_S311_DATA_CLEAR 0x46 #define ADJD_S311_OFFSET_RED 0x48 #define ADJD_S311_OFFSET_GREEN 0x49 #define ADJD_S311_OFFSET_BLUE 0x4a @@ -73,8 +64,8 @@ enum adjd_s311_channel_idx { IDX_RED, IDX_GREEN, IDX_BLUE, IDX_CLEAR }; -#define ADJD_S311_DATA_REG(chan) (ADJD_S311_DATA_RED_LO + (chan) * 2) -#define ADJD_S311_INT_REG(chan) (ADJD_S311_INT_RED_LO + (chan) * 2) +#define ADJD_S311_DATA_REG(chan) (ADJD_S311_DATA_RED + (chan) * 2) +#define ADJD_S311_INT_REG(chan) (ADJD_S311_INT_RED + (chan) * 2) #define ADJD_S311_CAP_REG(chan) (ADJD_S311_CAP_RED + (chan)) static int adjd_s311_req_data(struct iio_dev *indio_dev) @@ -122,51 +113,12 @@ static int adjd_s311_read_data(struct iio_dev *indio_dev, u8 reg, int *val) return 0; } -static ssize_t adjd_s311_read_int_time(struct iio_dev *indio_dev, - uintptr_t private, const struct iio_chan_spec *chan, char *buf) -{ - struct adjd_s311_data *data = iio_priv(indio_dev); - s32 ret; - - ret = i2c_smbus_read_word_data(data->client, - ADJD_S311_INT_REG(chan->address)); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", ret & ADJD_S311_INT_MASK); -} - -static ssize_t adjd_s311_write_int_time(struct iio_dev *indio_dev, - uintptr_t private, const struct iio_chan_spec *chan, const char *buf, - size_t len) -{ - struct adjd_s311_data *data = iio_priv(indio_dev); - unsigned long int_time; - int ret; - - ret = kstrtoul(buf, 10, &int_time); - if (ret) - return ret; - - if (int_time > ADJD_S311_INT_MASK) - return -EINVAL; - - ret = i2c_smbus_write_word_data(data->client, - ADJD_S311_INT_REG(chan->address), int_time); - if (ret < 0) - return ret; - - return len; -} - static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adjd_s311_data *data = iio_priv(indio_dev); - struct iio_buffer *buffer = indio_dev->buffer; s64 time_ns = iio_get_time_ns(); - int len = 0; int i, j = 0; int ret = adjd_s311_req_data(indio_dev); @@ -181,13 +133,9 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) goto done; data->buffer[j++] = ret & ADJD_S311_DATA_MASK; - len += 2; } - if (indio_dev->scan_timestamp) - *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64))) - = time_ns; - iio_push_to_buffer(buffer, (u8 *)data->buffer); + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, time_ns); done: iio_trigger_notify_done(indio_dev->trig); @@ -195,25 +143,21 @@ done: return IRQ_HANDLED; } -static const struct iio_chan_spec_ext_info adjd_s311_ext_info[] = { - { - .name = "integration_time", - .read = adjd_s311_read_int_time, - .write = adjd_s311_write_int_time, - }, - { } -}; - #define ADJD_S311_CHANNEL(_color, _scan_idx) { \ .type = IIO_INTENSITY, \ .modified = 1, \ .address = (IDX_##_color), \ - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ - IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ .channel2 = (IIO_MOD_LIGHT_##_color), \ .scan_index = (_scan_idx), \ - .scan_type = IIO_ST('u', 10, 16, 0), \ - .ext_info = adjd_s311_ext_info, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 10, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ } static const struct iio_chan_spec adjd_s311_channels[] = { @@ -233,7 +177,8 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = adjd_s311_read_data(indio_dev, chan->address, val); + ret = adjd_s311_read_data(indio_dev, + ADJD_S311_DATA_REG(chan->address), val); if (ret < 0) return ret; return IIO_VAL_INT; @@ -244,6 +189,18 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev, return ret; *val = ret & ADJD_S311_CAP_MASK; return IIO_VAL_INT; + case IIO_CHAN_INFO_INT_TIME: + ret = i2c_smbus_read_word_data(data->client, + ADJD_S311_INT_REG(chan->address)); + if (ret < 0) + return ret; + *val = 0; + /* + * not documented, based on measurement: + * 4095 LSBs correspond to roughly 4 ms + */ + *val2 = ret & ADJD_S311_INT_MASK; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } @@ -253,16 +210,20 @@ static int adjd_s311_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adjd_s311_data *data = iio_priv(indio_dev); - int ret; switch (mask) { case IIO_CHAN_INFO_HARDWAREGAIN: if (val < 0 || val > ADJD_S311_CAP_MASK) return -EINVAL; - ret = i2c_smbus_write_byte_data(data->client, + return i2c_smbus_write_byte_data(data->client, ADJD_S311_CAP_REG(chan->address), val); - return ret; + case IIO_CHAN_INFO_INT_TIME: + if (val != 0 || val2 < 0 || val2 > ADJD_S311_INT_MASK) + return -EINVAL; + + return i2c_smbus_write_word_data(data->client, + ADJD_S311_INT_REG(chan->address), val2); } return -EINVAL; } @@ -287,18 +248,17 @@ static const struct iio_info adjd_s311_info = { .driver_module = THIS_MODULE, }; -static int __devinit adjd_s311_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adjd_s311_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct adjd_s311_data *data; struct iio_dev *indio_dev; int err; - indio_dev = iio_device_alloc(sizeof(*data)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto exit; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; @@ -313,7 +273,7 @@ static int __devinit adjd_s311_probe(struct i2c_client *client, err = iio_triggered_buffer_setup(indio_dev, NULL, adjd_s311_trigger_handler, NULL); if (err < 0) - goto exit_free_device; + return err; err = iio_device_register(indio_dev); if (err) @@ -325,13 +285,10 @@ static int __devinit adjd_s311_probe(struct i2c_client *client, exit_unreg_buffer: iio_triggered_buffer_cleanup(indio_dev); -exit_free_device: - iio_device_free(indio_dev); -exit: return err; } -static int __devexit adjd_s311_remove(struct i2c_client *client) +static int adjd_s311_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct adjd_s311_data *data = iio_priv(indio_dev); @@ -339,7 +296,6 @@ static int __devexit adjd_s311_remove(struct i2c_client *client) iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); kfree(data->buffer); - iio_device_free(indio_dev); return 0; } @@ -355,7 +311,7 @@ static struct i2c_driver adjd_s311_driver = { .name = ADJD_S311_DRV_NAME, }, .probe = adjd_s311_probe, - .remove = __devexit_p(adjd_s311_remove), + .remove = adjd_s311_remove, .id_table = adjd_s311_id, }; module_i2c_driver(adjd_s311_driver); |
