18b054426SDaniel Baluta /* 28b054426SDaniel Baluta * CM3323 - Capella Color Light Sensor 38b054426SDaniel Baluta * 48b054426SDaniel Baluta * Copyright (c) 2015, Intel Corporation. 58b054426SDaniel Baluta * 68b054426SDaniel Baluta * This file is subject to the terms and conditions of version 2 of 78b054426SDaniel Baluta * the GNU General Public License. See the file COPYING in the main 88b054426SDaniel Baluta * directory of this archive for more details. 98b054426SDaniel Baluta * 108b054426SDaniel Baluta * IIO driver for CM3323 (7-bit I2C slave address 0x10) 118b054426SDaniel Baluta * 128b054426SDaniel Baluta * TODO: calibscale to correct the lens factor 138b054426SDaniel Baluta */ 148b054426SDaniel Baluta #include <linux/module.h> 158b054426SDaniel Baluta #include <linux/init.h> 168b054426SDaniel Baluta #include <linux/i2c.h> 178b054426SDaniel Baluta #include <linux/mutex.h> 188b054426SDaniel Baluta 198b054426SDaniel Baluta #include <linux/iio/iio.h> 208b054426SDaniel Baluta #include <linux/iio/sysfs.h> 218b054426SDaniel Baluta 228b054426SDaniel Baluta #define CM3323_DRV_NAME "cm3323" 238b054426SDaniel Baluta 248b054426SDaniel Baluta #define CM3323_CMD_CONF 0x00 258b054426SDaniel Baluta #define CM3323_CMD_RED_DATA 0x08 268b054426SDaniel Baluta #define CM3323_CMD_GREEN_DATA 0x09 278b054426SDaniel Baluta #define CM3323_CMD_BLUE_DATA 0x0A 288b054426SDaniel Baluta #define CM3323_CMD_CLEAR_DATA 0x0B 298b054426SDaniel Baluta 308b054426SDaniel Baluta #define CM3323_CONF_SD_BIT BIT(0) /* sensor disable */ 318b054426SDaniel Baluta #define CM3323_CONF_AF_BIT BIT(1) /* auto/manual force mode */ 32*054101c1SHartmut Knaack #define CM3323_CONF_IT_MASK GENMASK(6, 4) 338b054426SDaniel Baluta #define CM3323_CONF_IT_SHIFT 4 348b054426SDaniel Baluta 358b054426SDaniel Baluta #define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28" 368b054426SDaniel Baluta 378b054426SDaniel Baluta static const struct { 388b054426SDaniel Baluta int val; 398b054426SDaniel Baluta int val2; 408b054426SDaniel Baluta } cm3323_int_time[] = { 418b054426SDaniel Baluta {0, 40000}, /* 40 ms */ 428b054426SDaniel Baluta {0, 80000}, /* 80 ms */ 438b054426SDaniel Baluta {0, 160000}, /* 160 ms */ 448b054426SDaniel Baluta {0, 320000}, /* 320 ms */ 458b054426SDaniel Baluta {0, 640000}, /* 640 ms */ 468b054426SDaniel Baluta {1, 280000}, /* 1280 ms */ 478b054426SDaniel Baluta }; 488b054426SDaniel Baluta 498b054426SDaniel Baluta struct cm3323_data { 508b054426SDaniel Baluta struct i2c_client *client; 518b054426SDaniel Baluta u16 reg_conf; 528b054426SDaniel Baluta struct mutex mutex; 538b054426SDaniel Baluta }; 548b054426SDaniel Baluta 558b054426SDaniel Baluta #define CM3323_COLOR_CHANNEL(_color, _addr) { \ 568b054426SDaniel Baluta .type = IIO_INTENSITY, \ 578b054426SDaniel Baluta .modified = 1, \ 588b054426SDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 598b054426SDaniel Baluta .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \ 608b054426SDaniel Baluta .channel2 = IIO_MOD_LIGHT_##_color, \ 618b054426SDaniel Baluta .address = _addr, \ 628b054426SDaniel Baluta } 638b054426SDaniel Baluta 648b054426SDaniel Baluta static const struct iio_chan_spec cm3323_channels[] = { 658b054426SDaniel Baluta CM3323_COLOR_CHANNEL(RED, CM3323_CMD_RED_DATA), 668b054426SDaniel Baluta CM3323_COLOR_CHANNEL(GREEN, CM3323_CMD_GREEN_DATA), 678b054426SDaniel Baluta CM3323_COLOR_CHANNEL(BLUE, CM3323_CMD_BLUE_DATA), 688b054426SDaniel Baluta CM3323_COLOR_CHANNEL(CLEAR, CM3323_CMD_CLEAR_DATA), 698b054426SDaniel Baluta }; 708b054426SDaniel Baluta 718b054426SDaniel Baluta static IIO_CONST_ATTR_INT_TIME_AVAIL(CM3323_INT_TIME_AVAILABLE); 728b054426SDaniel Baluta 738b054426SDaniel Baluta static struct attribute *cm3323_attributes[] = { 748b054426SDaniel Baluta &iio_const_attr_integration_time_available.dev_attr.attr, 758b054426SDaniel Baluta NULL 768b054426SDaniel Baluta }; 778b054426SDaniel Baluta 788b054426SDaniel Baluta static const struct attribute_group cm3323_attribute_group = { 798b054426SDaniel Baluta .attrs = cm3323_attributes, 808b054426SDaniel Baluta }; 818b054426SDaniel Baluta 828b054426SDaniel Baluta static int cm3323_init(struct iio_dev *indio_dev) 838b054426SDaniel Baluta { 848b054426SDaniel Baluta int ret; 858b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 868b054426SDaniel Baluta 878b054426SDaniel Baluta ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF); 888b054426SDaniel Baluta if (ret < 0) { 898b054426SDaniel Baluta dev_err(&data->client->dev, "Error reading reg_conf\n"); 908b054426SDaniel Baluta return ret; 918b054426SDaniel Baluta } 928b054426SDaniel Baluta 938b054426SDaniel Baluta /* enable sensor and set auto force mode */ 948b054426SDaniel Baluta ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT); 958b054426SDaniel Baluta 968b054426SDaniel Baluta ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, ret); 978b054426SDaniel Baluta if (ret < 0) { 988b054426SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_conf\n"); 998b054426SDaniel Baluta return ret; 1008b054426SDaniel Baluta } 1018b054426SDaniel Baluta 1028b054426SDaniel Baluta data->reg_conf = ret; 1038b054426SDaniel Baluta 1048b054426SDaniel Baluta return 0; 1058b054426SDaniel Baluta } 1068b054426SDaniel Baluta 1078b054426SDaniel Baluta static void cm3323_disable(struct iio_dev *indio_dev) 1088b054426SDaniel Baluta { 1098b054426SDaniel Baluta int ret; 1108b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 1118b054426SDaniel Baluta 1128b054426SDaniel Baluta ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, 1138b054426SDaniel Baluta CM3323_CONF_SD_BIT); 1148b054426SDaniel Baluta if (ret < 0) 1158b054426SDaniel Baluta dev_err(&data->client->dev, "Error writing reg_conf\n"); 1168b054426SDaniel Baluta } 1178b054426SDaniel Baluta 1188b054426SDaniel Baluta static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) 1198b054426SDaniel Baluta { 1208b054426SDaniel Baluta int i, ret; 1218b054426SDaniel Baluta u16 reg_conf; 1228b054426SDaniel Baluta 1238b054426SDaniel Baluta for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) { 1248b054426SDaniel Baluta if (val == cm3323_int_time[i].val && 1258b054426SDaniel Baluta val2 == cm3323_int_time[i].val2) { 1268b054426SDaniel Baluta reg_conf = data->reg_conf; 1278b054426SDaniel Baluta reg_conf |= i << CM3323_CONF_IT_SHIFT; 1288b054426SDaniel Baluta 1298b054426SDaniel Baluta ret = i2c_smbus_write_word_data(data->client, 1308b054426SDaniel Baluta CM3323_CMD_CONF, 1318b054426SDaniel Baluta reg_conf); 1328b054426SDaniel Baluta if (ret < 0) 1338b054426SDaniel Baluta return ret; 1348b054426SDaniel Baluta 1358b054426SDaniel Baluta data->reg_conf = reg_conf; 1368b054426SDaniel Baluta return 0; 1378b054426SDaniel Baluta } 1388b054426SDaniel Baluta } 1398b054426SDaniel Baluta return -EINVAL; 1408b054426SDaniel Baluta } 1418b054426SDaniel Baluta 1428b054426SDaniel Baluta static int cm3323_get_it_bits(struct cm3323_data *data) 1438b054426SDaniel Baluta { 1448b054426SDaniel Baluta int bits; 1458b054426SDaniel Baluta 1468b054426SDaniel Baluta bits = (data->reg_conf & CM3323_CONF_IT_MASK) >> 1478b054426SDaniel Baluta CM3323_CONF_IT_SHIFT; 1488b054426SDaniel Baluta 1498b054426SDaniel Baluta if (bits >= ARRAY_SIZE(cm3323_int_time)) 1508b054426SDaniel Baluta return -EINVAL; 1518b054426SDaniel Baluta return bits; 1528b054426SDaniel Baluta } 1538b054426SDaniel Baluta 1548b054426SDaniel Baluta static int cm3323_read_raw(struct iio_dev *indio_dev, 1558b054426SDaniel Baluta struct iio_chan_spec const *chan, int *val, 1568b054426SDaniel Baluta int *val2, long mask) 1578b054426SDaniel Baluta { 1580ff8c78dSHartmut Knaack int ret; 1598b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 1608b054426SDaniel Baluta 1618b054426SDaniel Baluta switch (mask) { 1628b054426SDaniel Baluta case IIO_CHAN_INFO_RAW: 1638b054426SDaniel Baluta mutex_lock(&data->mutex); 1648b054426SDaniel Baluta ret = i2c_smbus_read_word_data(data->client, chan->address); 1658b054426SDaniel Baluta if (ret < 0) { 1668b054426SDaniel Baluta mutex_unlock(&data->mutex); 1678b054426SDaniel Baluta return ret; 1688b054426SDaniel Baluta } 1698b054426SDaniel Baluta *val = ret; 1708b054426SDaniel Baluta mutex_unlock(&data->mutex); 1718b054426SDaniel Baluta 1728b054426SDaniel Baluta return IIO_VAL_INT; 1738b054426SDaniel Baluta case IIO_CHAN_INFO_INT_TIME: 1748b054426SDaniel Baluta mutex_lock(&data->mutex); 1750ff8c78dSHartmut Knaack ret = cm3323_get_it_bits(data); 1760ff8c78dSHartmut Knaack if (ret < 0) { 1778b054426SDaniel Baluta mutex_unlock(&data->mutex); 1780ff8c78dSHartmut Knaack return ret; 1798b054426SDaniel Baluta } 1808b054426SDaniel Baluta 1810ff8c78dSHartmut Knaack *val = cm3323_int_time[ret].val; 1820ff8c78dSHartmut Knaack *val2 = cm3323_int_time[ret].val2; 1838b054426SDaniel Baluta mutex_unlock(&data->mutex); 1848b054426SDaniel Baluta 1858b054426SDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 1868b054426SDaniel Baluta default: 1878b054426SDaniel Baluta return -EINVAL; 1888b054426SDaniel Baluta } 1898b054426SDaniel Baluta } 1908b054426SDaniel Baluta 1918b054426SDaniel Baluta static int cm3323_write_raw(struct iio_dev *indio_dev, 1928b054426SDaniel Baluta struct iio_chan_spec const *chan, int val, 1938b054426SDaniel Baluta int val2, long mask) 1948b054426SDaniel Baluta { 1958b054426SDaniel Baluta struct cm3323_data *data = iio_priv(indio_dev); 1968b054426SDaniel Baluta int ret; 1978b054426SDaniel Baluta 1988b054426SDaniel Baluta switch (mask) { 1998b054426SDaniel Baluta case IIO_CHAN_INFO_INT_TIME: 2008b054426SDaniel Baluta mutex_lock(&data->mutex); 2018b054426SDaniel Baluta ret = cm3323_set_it_bits(data, val, val2); 2028b054426SDaniel Baluta mutex_unlock(&data->mutex); 2038b054426SDaniel Baluta 2048b054426SDaniel Baluta return ret; 2058b054426SDaniel Baluta default: 2068b054426SDaniel Baluta return -EINVAL; 2078b054426SDaniel Baluta } 2088b054426SDaniel Baluta } 2098b054426SDaniel Baluta 2108b054426SDaniel Baluta static const struct iio_info cm3323_info = { 2118b054426SDaniel Baluta .driver_module = THIS_MODULE, 2128b054426SDaniel Baluta .read_raw = cm3323_read_raw, 2138b054426SDaniel Baluta .write_raw = cm3323_write_raw, 2148b054426SDaniel Baluta .attrs = &cm3323_attribute_group, 2158b054426SDaniel Baluta }; 2168b054426SDaniel Baluta 2178b054426SDaniel Baluta static int cm3323_probe(struct i2c_client *client, 2188b054426SDaniel Baluta const struct i2c_device_id *id) 2198b054426SDaniel Baluta { 2208b054426SDaniel Baluta struct cm3323_data *data; 2218b054426SDaniel Baluta struct iio_dev *indio_dev; 2228b054426SDaniel Baluta int ret; 2238b054426SDaniel Baluta 2248b054426SDaniel Baluta indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 2258b054426SDaniel Baluta if (!indio_dev) 2268b054426SDaniel Baluta return -ENOMEM; 2278b054426SDaniel Baluta 2288b054426SDaniel Baluta data = iio_priv(indio_dev); 2298b054426SDaniel Baluta i2c_set_clientdata(client, indio_dev); 2308b054426SDaniel Baluta data->client = client; 2318b054426SDaniel Baluta 2328b054426SDaniel Baluta mutex_init(&data->mutex); 2338b054426SDaniel Baluta 2348b054426SDaniel Baluta indio_dev->dev.parent = &client->dev; 2358b054426SDaniel Baluta indio_dev->info = &cm3323_info; 2368b054426SDaniel Baluta indio_dev->name = CM3323_DRV_NAME; 2378b054426SDaniel Baluta indio_dev->channels = cm3323_channels; 2388b054426SDaniel Baluta indio_dev->num_channels = ARRAY_SIZE(cm3323_channels); 2398b054426SDaniel Baluta indio_dev->modes = INDIO_DIRECT_MODE; 2408b054426SDaniel Baluta 2418b054426SDaniel Baluta ret = cm3323_init(indio_dev); 2428b054426SDaniel Baluta if (ret < 0) { 2438b054426SDaniel Baluta dev_err(&client->dev, "cm3323 chip init failed\n"); 2448b054426SDaniel Baluta return ret; 2458b054426SDaniel Baluta } 2468b054426SDaniel Baluta ret = iio_device_register(indio_dev); 2478b054426SDaniel Baluta if (ret < 0) { 2488b054426SDaniel Baluta dev_err(&client->dev, "failed to register iio dev\n"); 2498b054426SDaniel Baluta goto err_init; 2508b054426SDaniel Baluta } 2518b054426SDaniel Baluta return 0; 2528b054426SDaniel Baluta err_init: 2538b054426SDaniel Baluta cm3323_disable(indio_dev); 2548b054426SDaniel Baluta return ret; 2558b054426SDaniel Baluta } 2568b054426SDaniel Baluta 2578b054426SDaniel Baluta static int cm3323_remove(struct i2c_client *client) 2588b054426SDaniel Baluta { 2598b054426SDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(client); 2608b054426SDaniel Baluta 2618b054426SDaniel Baluta iio_device_unregister(indio_dev); 2628b054426SDaniel Baluta cm3323_disable(indio_dev); 2638b054426SDaniel Baluta 2648b054426SDaniel Baluta return 0; 2658b054426SDaniel Baluta } 2668b054426SDaniel Baluta 2678b054426SDaniel Baluta static const struct i2c_device_id cm3323_id[] = { 2688b054426SDaniel Baluta {"cm3323", 0}, 2698b054426SDaniel Baluta {} 2708b054426SDaniel Baluta }; 2718b054426SDaniel Baluta MODULE_DEVICE_TABLE(i2c, cm3323_id); 2728b054426SDaniel Baluta 2738b054426SDaniel Baluta static struct i2c_driver cm3323_driver = { 2748b054426SDaniel Baluta .driver = { 2758b054426SDaniel Baluta .name = CM3323_DRV_NAME, 2768b054426SDaniel Baluta }, 2778b054426SDaniel Baluta .probe = cm3323_probe, 2788b054426SDaniel Baluta .remove = cm3323_remove, 2798b054426SDaniel Baluta .id_table = cm3323_id, 2808b054426SDaniel Baluta }; 2818b054426SDaniel Baluta 2828b054426SDaniel Baluta module_i2c_driver(cm3323_driver); 2838b054426SDaniel Baluta 2848b054426SDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 2858b054426SDaniel Baluta MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver"); 2868b054426SDaniel Baluta MODULE_LICENSE("GPL v2"); 287