1*8b054426SDaniel Baluta /* 2*8b054426SDaniel Baluta * CM3323 - Capella Color Light Sensor 3*8b054426SDaniel Baluta * 4*8b054426SDaniel Baluta * Copyright (c) 2015, Intel Corporation. 5*8b054426SDaniel Baluta * 6*8b054426SDaniel Baluta * This file is subject to the terms and conditions of version 2 of 7*8b054426SDaniel Baluta * the GNU General Public License. See the file COPYING in the main 8*8b054426SDaniel Baluta * directory of this archive for more details. 9*8b054426SDaniel Baluta * 10*8b054426SDaniel Baluta * IIO driver for CM3323 (7-bit I2C slave address 0x10) 11*8b054426SDaniel Baluta * 12*8b054426SDaniel Baluta * TODO: calibscale to correct the lens factor 13*8b054426SDaniel Baluta */ 14*8b054426SDaniel Baluta #include <linux/module.h> 15*8b054426SDaniel Baluta #include <linux/init.h> 16*8b054426SDaniel Baluta #include <linux/i2c.h> 17*8b054426SDaniel Baluta #include <linux/mutex.h> 18*8b054426SDaniel Baluta 19*8b054426SDaniel Baluta #include <linux/iio/iio.h> 20*8b054426SDaniel Baluta #include <linux/iio/sysfs.h> 21*8b054426SDaniel Baluta 22*8b054426SDaniel Baluta #define CM3323_DRV_NAME "cm3323" 23*8b054426SDaniel Baluta 24*8b054426SDaniel Baluta #define CM3323_CMD_CONF 0x00 25*8b054426SDaniel Baluta #define CM3323_CMD_RED_DATA 0x08 26*8b054426SDaniel Baluta #define CM3323_CMD_GREEN_DATA 0x09 27*8b054426SDaniel Baluta #define CM3323_CMD_BLUE_DATA 0x0A 28*8b054426SDaniel Baluta #define CM3323_CMD_CLEAR_DATA 0x0B 29*8b054426SDaniel Baluta 30*8b054426SDaniel Baluta #define CM3323_CONF_SD_BIT BIT(0) /* sensor disable */ 31*8b054426SDaniel Baluta #define CM3323_CONF_AF_BIT BIT(1) /* auto/manual force mode */ 32*8b054426SDaniel Baluta #define CM3323_CONF_IT_MASK (BIT(4) | BIT(5) | BIT(6)) 33*8b054426SDaniel Baluta #define CM3323_CONF_IT_SHIFT 4 34*8b054426SDaniel Baluta 35*8b054426SDaniel Baluta #define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28" 36*8b054426SDaniel Baluta 37*8b054426SDaniel Baluta static const struct { 38*8b054426SDaniel Baluta int val; 39*8b054426SDaniel Baluta int val2; 40*8b054426SDaniel Baluta } cm3323_int_time[] = { 41*8b054426SDaniel Baluta {0, 40000}, /* 40 ms */ 42*8b054426SDaniel Baluta {0, 80000}, /* 80 ms */ 43*8b054426SDaniel Baluta {0, 160000}, /* 160 ms */ 44*8b054426SDaniel Baluta {0, 320000}, /* 320 ms */ 45*8b054426SDaniel Baluta {0, 640000}, /* 640 ms */ 46*8b054426SDaniel Baluta {1, 280000}, /* 1280 ms */ 47*8b054426SDaniel Baluta }; 48*8b054426SDaniel Baluta 49*8b054426SDaniel Baluta struct cm3323_data { 50*8b054426SDaniel Baluta struct i2c_client *client; 51*8b054426SDaniel Baluta u16 reg_conf; 52*8b054426SDaniel Baluta struct mutex mutex; 53*8b054426SDaniel Baluta }; 54*8b054426SDaniel Baluta 55*8b054426SDaniel Baluta #define CM3323_COLOR_CHANNEL(_color, _addr) { \ 56*8b054426SDaniel Baluta .type = IIO_INTENSITY, \ 57*8b054426SDaniel Baluta .modified = 1, \ 58*8b054426SDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 59*8b054426SDaniel Baluta .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \ 60*8b054426SDaniel Baluta .channel2 = IIO_MOD_LIGHT_##_color, \ 61*8b054426SDaniel Baluta .address = _addr, \ 62*8b054426SDaniel Baluta } 63*8b054426SDaniel Baluta 64*8b054426SDaniel Baluta static const struct iio_chan_spec cm3323_channels[] = { 65*8b054426SDaniel Baluta CM3323_COLOR_CHANNEL(RED, CM3323_CMD_RED_DATA), 66*8b054426SDaniel Baluta CM3323_COLOR_CHANNEL(GREEN, CM3323_CMD_GREEN_DATA), 67*8b054426SDaniel Baluta CM3323_COLOR_CHANNEL(BLUE, CM3323_CMD_BLUE_DATA), 68*8b054426SDaniel Baluta CM3323_COLOR_CHANNEL(CLEAR, CM3323_CMD_CLEAR_DATA), 69*8b054426SDaniel Baluta }; 70*8b054426SDaniel Baluta 71*8b054426SDaniel Baluta static IIO_CONST_ATTR_INT_TIME_AVAIL(CM3323_INT_TIME_AVAILABLE); 72*8b054426SDaniel Baluta 73*8b054426SDaniel Baluta static struct attribute *cm3323_attributes[] = { 74*8b054426SDaniel Baluta &iio_const_attr_integration_time_available.dev_attr.attr, 75*8b054426SDaniel Baluta NULL 76*8b054426SDaniel Baluta }; 77*8b054426SDaniel Baluta 78*8b054426SDaniel Baluta static const struct attribute_group cm3323_attribute_group = { 79*8b054426SDaniel Baluta .attrs = cm3323_attributes, 80*8b054426SDaniel Baluta }; 81*8b054426SDaniel Baluta 82*8b054426SDaniel Baluta static int cm3323_init(struct iio_dev *indio_dev) 83*8b054426SDaniel Baluta { 84*8b054426SDaniel Baluta int ret; 85*8b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 86*8b054426SDaniel Baluta 87*8b054426SDaniel Baluta ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF); 88*8b054426SDaniel Baluta if (ret < 0) { 89*8b054426SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_conf\n"); 90*8b054426SDaniel Baluta return ret; 91*8b054426SDaniel Baluta } 92*8b054426SDaniel Baluta 93*8b054426SDaniel Baluta /* enable sensor and set auto force mode */ 94*8b054426SDaniel Baluta ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT); 95*8b054426SDaniel Baluta 96*8b054426SDaniel Baluta ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, ret); 97*8b054426SDaniel Baluta if (ret < 0) { 98*8b054426SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_conf\n"); 99*8b054426SDaniel Baluta return ret; 100*8b054426SDaniel Baluta } 101*8b054426SDaniel Baluta 102*8b054426SDaniel Baluta data->reg_conf = ret; 103*8b054426SDaniel Baluta 104*8b054426SDaniel Baluta return 0; 105*8b054426SDaniel Baluta } 106*8b054426SDaniel Baluta 107*8b054426SDaniel Baluta static void cm3323_disable(struct iio_dev *indio_dev) 108*8b054426SDaniel Baluta { 109*8b054426SDaniel Baluta int ret; 110*8b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 111*8b054426SDaniel Baluta 112*8b054426SDaniel Baluta ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, 113*8b054426SDaniel Baluta CM3323_CONF_SD_BIT); 114*8b054426SDaniel Baluta if (ret < 0) 115*8b054426SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_conf\n"); 116*8b054426SDaniel Baluta } 117*8b054426SDaniel Baluta 118*8b054426SDaniel Baluta static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) 119*8b054426SDaniel Baluta { 120*8b054426SDaniel Baluta int i, ret; 121*8b054426SDaniel Baluta u16 reg_conf; 122*8b054426SDaniel Baluta 123*8b054426SDaniel Baluta for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) { 124*8b054426SDaniel Baluta if (val == cm3323_int_time[i].val && 125*8b054426SDaniel Baluta val2 == cm3323_int_time[i].val2) { 126*8b054426SDaniel Baluta reg_conf = data->reg_conf; 127*8b054426SDaniel Baluta reg_conf |= i << CM3323_CONF_IT_SHIFT; 128*8b054426SDaniel Baluta 129*8b054426SDaniel Baluta ret = i2c_smbus_write_word_data(data->client, 130*8b054426SDaniel Baluta CM3323_CMD_CONF, 131*8b054426SDaniel Baluta reg_conf); 132*8b054426SDaniel Baluta if (ret < 0) 133*8b054426SDaniel Baluta return ret; 134*8b054426SDaniel Baluta 135*8b054426SDaniel Baluta data->reg_conf = reg_conf; 136*8b054426SDaniel Baluta return 0; 137*8b054426SDaniel Baluta } 138*8b054426SDaniel Baluta } 139*8b054426SDaniel Baluta return -EINVAL; 140*8b054426SDaniel Baluta } 141*8b054426SDaniel Baluta 142*8b054426SDaniel Baluta static int cm3323_get_it_bits(struct cm3323_data *data) 143*8b054426SDaniel Baluta { 144*8b054426SDaniel Baluta int bits; 145*8b054426SDaniel Baluta 146*8b054426SDaniel Baluta bits = (data->reg_conf & CM3323_CONF_IT_MASK) >> 147*8b054426SDaniel Baluta CM3323_CONF_IT_SHIFT; 148*8b054426SDaniel Baluta 149*8b054426SDaniel Baluta if (bits >= ARRAY_SIZE(cm3323_int_time)) 150*8b054426SDaniel Baluta return -EINVAL; 151*8b054426SDaniel Baluta return bits; 152*8b054426SDaniel Baluta } 153*8b054426SDaniel Baluta 154*8b054426SDaniel Baluta static int cm3323_read_raw(struct iio_dev *indio_dev, 155*8b054426SDaniel Baluta struct iio_chan_spec const *chan, int *val, 156*8b054426SDaniel Baluta int *val2, long mask) 157*8b054426SDaniel Baluta { 158*8b054426SDaniel Baluta int i, ret; 159*8b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 160*8b054426SDaniel Baluta 161*8b054426SDaniel Baluta switch (mask) { 162*8b054426SDaniel Baluta case IIO_CHAN_INFO_RAW: 163*8b054426SDaniel Baluta mutex_lock(&data->mutex); 164*8b054426SDaniel Baluta ret = i2c_smbus_read_word_data(data->client, chan->address); 165*8b054426SDaniel Baluta if (ret < 0) { 166*8b054426SDaniel Baluta mutex_unlock(&data->mutex); 167*8b054426SDaniel Baluta return ret; 168*8b054426SDaniel Baluta } 169*8b054426SDaniel Baluta *val = ret; 170*8b054426SDaniel Baluta mutex_unlock(&data->mutex); 171*8b054426SDaniel Baluta 172*8b054426SDaniel Baluta return IIO_VAL_INT; 173*8b054426SDaniel Baluta case IIO_CHAN_INFO_INT_TIME: 174*8b054426SDaniel Baluta mutex_lock(&data->mutex); 175*8b054426SDaniel Baluta i = cm3323_get_it_bits(data); 176*8b054426SDaniel Baluta if (i < 0) { 177*8b054426SDaniel Baluta mutex_unlock(&data->mutex); 178*8b054426SDaniel Baluta return -EINVAL; 179*8b054426SDaniel Baluta } 180*8b054426SDaniel Baluta 181*8b054426SDaniel Baluta *val = cm3323_int_time[i].val; 182*8b054426SDaniel Baluta *val2 = cm3323_int_time[i].val2; 183*8b054426SDaniel Baluta mutex_unlock(&data->mutex); 184*8b054426SDaniel Baluta 185*8b054426SDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 186*8b054426SDaniel Baluta default: 187*8b054426SDaniel Baluta return -EINVAL; 188*8b054426SDaniel Baluta } 189*8b054426SDaniel Baluta } 190*8b054426SDaniel Baluta 191*8b054426SDaniel Baluta static int cm3323_write_raw(struct iio_dev *indio_dev, 192*8b054426SDaniel Baluta struct iio_chan_spec const *chan, int val, 193*8b054426SDaniel Baluta int val2, long mask) 194*8b054426SDaniel Baluta { 195*8b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 196*8b054426SDaniel Baluta int ret; 197*8b054426SDaniel Baluta 198*8b054426SDaniel Baluta switch (mask) { 199*8b054426SDaniel Baluta case IIO_CHAN_INFO_INT_TIME: 200*8b054426SDaniel Baluta mutex_lock(&data->mutex); 201*8b054426SDaniel Baluta ret = cm3323_set_it_bits(data, val, val2); 202*8b054426SDaniel Baluta mutex_unlock(&data->mutex); 203*8b054426SDaniel Baluta 204*8b054426SDaniel Baluta return ret; 205*8b054426SDaniel Baluta default: 206*8b054426SDaniel Baluta return -EINVAL; 207*8b054426SDaniel Baluta } 208*8b054426SDaniel Baluta } 209*8b054426SDaniel Baluta 210*8b054426SDaniel Baluta static const struct iio_info cm3323_info = { 211*8b054426SDaniel Baluta .driver_module = THIS_MODULE, 212*8b054426SDaniel Baluta .read_raw = cm3323_read_raw, 213*8b054426SDaniel Baluta .write_raw = cm3323_write_raw, 214*8b054426SDaniel Baluta .attrs = &cm3323_attribute_group, 215*8b054426SDaniel Baluta }; 216*8b054426SDaniel Baluta 217*8b054426SDaniel Baluta static int cm3323_probe(struct i2c_client *client, 218*8b054426SDaniel Baluta const struct i2c_device_id *id) 219*8b054426SDaniel Baluta { 220*8b054426SDaniel Baluta struct cm3323_data *data; 221*8b054426SDaniel Baluta struct iio_dev *indio_dev; 222*8b054426SDaniel Baluta int ret; 223*8b054426SDaniel Baluta 224*8b054426SDaniel Baluta indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 225*8b054426SDaniel Baluta if (!indio_dev) 226*8b054426SDaniel Baluta return -ENOMEM; 227*8b054426SDaniel Baluta 228*8b054426SDaniel Baluta data = iio_priv(indio_dev); 229*8b054426SDaniel Baluta i2c_set_clientdata(client, indio_dev); 230*8b054426SDaniel Baluta data->client = client; 231*8b054426SDaniel Baluta 232*8b054426SDaniel Baluta mutex_init(&data->mutex); 233*8b054426SDaniel Baluta 234*8b054426SDaniel Baluta indio_dev->dev.parent = &client->dev; 235*8b054426SDaniel Baluta indio_dev->info = &cm3323_info; 236*8b054426SDaniel Baluta indio_dev->name = CM3323_DRV_NAME; 237*8b054426SDaniel Baluta indio_dev->channels = cm3323_channels; 238*8b054426SDaniel Baluta indio_dev->num_channels = ARRAY_SIZE(cm3323_channels); 239*8b054426SDaniel Baluta indio_dev->modes = INDIO_DIRECT_MODE; 240*8b054426SDaniel Baluta 241*8b054426SDaniel Baluta ret = cm3323_init(indio_dev); 242*8b054426SDaniel Baluta if (ret < 0) { 243*8b054426SDaniel Baluta dev_err(&client->dev, "cm3323 chip init failed\n"); 244*8b054426SDaniel Baluta return ret; 245*8b054426SDaniel Baluta } 246*8b054426SDaniel Baluta ret = iio_device_register(indio_dev); 247*8b054426SDaniel Baluta if (ret < 0) { 248*8b054426SDaniel Baluta dev_err(&client->dev, "failed to register iio dev\n"); 249*8b054426SDaniel Baluta goto err_init; 250*8b054426SDaniel Baluta } 251*8b054426SDaniel Baluta return 0; 252*8b054426SDaniel Baluta err_init: 253*8b054426SDaniel Baluta cm3323_disable(indio_dev); 254*8b054426SDaniel Baluta return ret; 255*8b054426SDaniel Baluta } 256*8b054426SDaniel Baluta 257*8b054426SDaniel Baluta static int cm3323_remove(struct i2c_client *client) 258*8b054426SDaniel Baluta { 259*8b054426SDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(client); 260*8b054426SDaniel Baluta 261*8b054426SDaniel Baluta iio_device_unregister(indio_dev); 262*8b054426SDaniel Baluta cm3323_disable(indio_dev); 263*8b054426SDaniel Baluta 264*8b054426SDaniel Baluta return 0; 265*8b054426SDaniel Baluta } 266*8b054426SDaniel Baluta 267*8b054426SDaniel Baluta static const struct i2c_device_id cm3323_id[] = { 268*8b054426SDaniel Baluta {"cm3323", 0}, 269*8b054426SDaniel Baluta {} 270*8b054426SDaniel Baluta }; 271*8b054426SDaniel Baluta MODULE_DEVICE_TABLE(i2c, cm3323_id); 272*8b054426SDaniel Baluta 273*8b054426SDaniel Baluta static struct i2c_driver cm3323_driver = { 274*8b054426SDaniel Baluta .driver = { 275*8b054426SDaniel Baluta .name = CM3323_DRV_NAME, 276*8b054426SDaniel Baluta }, 277*8b054426SDaniel Baluta .probe = cm3323_probe, 278*8b054426SDaniel Baluta .remove = cm3323_remove, 279*8b054426SDaniel Baluta .id_table = cm3323_id, 280*8b054426SDaniel Baluta }; 281*8b054426SDaniel Baluta 282*8b054426SDaniel Baluta module_i2c_driver(cm3323_driver); 283*8b054426SDaniel Baluta 284*8b054426SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 285*8b054426SDaniel Baluta MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver"); 286*8b054426SDaniel Baluta MODULE_LICENSE("GPL v2"); 287