cm3323.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * CM3323 - Capella Color Light Sensor
  4. *
  5. * Copyright (c) 2015, Intel Corporation.
  6. *
  7. * IIO driver for CM3323 (7-bit I2C slave address 0x10)
  8. *
  9. * TODO: calibscale to correct the lens factor
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/i2c.h>
  14. #include <linux/mutex.h>
  15. #include <linux/iio/iio.h>
  16. #include <linux/iio/sysfs.h>
  17. #define CM3323_DRV_NAME "cm3323"
  18. #define CM3323_CMD_CONF 0x00
  19. #define CM3323_CMD_RED_DATA 0x08
  20. #define CM3323_CMD_GREEN_DATA 0x09
  21. #define CM3323_CMD_BLUE_DATA 0x0A
  22. #define CM3323_CMD_CLEAR_DATA 0x0B
  23. #define CM3323_CONF_SD_BIT BIT(0) /* sensor disable */
  24. #define CM3323_CONF_AF_BIT BIT(1) /* auto/manual force mode */
  25. #define CM3323_CONF_IT_MASK GENMASK(6, 4)
  26. #define CM3323_CONF_IT_SHIFT 4
  27. #define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28"
  28. static const struct {
  29. int val;
  30. int val2;
  31. } cm3323_int_time[] = {
  32. {0, 40000}, /* 40 ms */
  33. {0, 80000}, /* 80 ms */
  34. {0, 160000}, /* 160 ms */
  35. {0, 320000}, /* 320 ms */
  36. {0, 640000}, /* 640 ms */
  37. {1, 280000}, /* 1280 ms */
  38. };
  39. struct cm3323_data {
  40. struct i2c_client *client;
  41. u16 reg_conf;
  42. struct mutex mutex;
  43. };
  44. #define CM3323_COLOR_CHANNEL(_color, _addr) { \
  45. .type = IIO_INTENSITY, \
  46. .modified = 1, \
  47. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  48. .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \
  49. .channel2 = IIO_MOD_LIGHT_##_color, \
  50. .address = _addr, \
  51. }
  52. static const struct iio_chan_spec cm3323_channels[] = {
  53. CM3323_COLOR_CHANNEL(RED, CM3323_CMD_RED_DATA),
  54. CM3323_COLOR_CHANNEL(GREEN, CM3323_CMD_GREEN_DATA),
  55. CM3323_COLOR_CHANNEL(BLUE, CM3323_CMD_BLUE_DATA),
  56. CM3323_COLOR_CHANNEL(CLEAR, CM3323_CMD_CLEAR_DATA),
  57. };
  58. static IIO_CONST_ATTR_INT_TIME_AVAIL(CM3323_INT_TIME_AVAILABLE);
  59. static struct attribute *cm3323_attributes[] = {
  60. &iio_const_attr_integration_time_available.dev_attr.attr,
  61. NULL
  62. };
  63. static const struct attribute_group cm3323_attribute_group = {
  64. .attrs = cm3323_attributes,
  65. };
  66. static int cm3323_init(struct iio_dev *indio_dev)
  67. {
  68. int ret;
  69. struct cm3323_data *data = iio_priv(indio_dev);
  70. ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF);
  71. if (ret < 0) {
  72. dev_err(&data->client->dev, "Error reading reg_conf\n");
  73. return ret;
  74. }
  75. /* enable sensor and set auto force mode */
  76. ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT);
  77. ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, ret);
  78. if (ret < 0) {
  79. dev_err(&data->client->dev, "Error writing reg_conf\n");
  80. return ret;
  81. }
  82. data->reg_conf = ret;
  83. return 0;
  84. }
  85. static void cm3323_disable(void *data)
  86. {
  87. int ret;
  88. struct iio_dev *indio_dev = data;
  89. struct cm3323_data *cm_data = iio_priv(indio_dev);
  90. ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF,
  91. CM3323_CONF_SD_BIT);
  92. if (ret < 0)
  93. dev_err(&cm_data->client->dev, "Error writing reg_conf\n");
  94. }
  95. static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2)
  96. {
  97. int i, ret;
  98. u16 reg_conf;
  99. for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) {
  100. if (val == cm3323_int_time[i].val &&
  101. val2 == cm3323_int_time[i].val2) {
  102. reg_conf = data->reg_conf & ~CM3323_CONF_IT_MASK;
  103. reg_conf |= i << CM3323_CONF_IT_SHIFT;
  104. ret = i2c_smbus_write_word_data(data->client,
  105. CM3323_CMD_CONF,
  106. reg_conf);
  107. if (ret < 0)
  108. return ret;
  109. data->reg_conf = reg_conf;
  110. return 0;
  111. }
  112. }
  113. return -EINVAL;
  114. }
  115. static int cm3323_get_it_bits(struct cm3323_data *data)
  116. {
  117. int bits;
  118. bits = (data->reg_conf & CM3323_CONF_IT_MASK) >>
  119. CM3323_CONF_IT_SHIFT;
  120. if (bits >= ARRAY_SIZE(cm3323_int_time))
  121. return -EINVAL;
  122. return bits;
  123. }
  124. static int cm3323_read_raw(struct iio_dev *indio_dev,
  125. struct iio_chan_spec const *chan, int *val,
  126. int *val2, long mask)
  127. {
  128. int ret;
  129. struct cm3323_data *data = iio_priv(indio_dev);
  130. switch (mask) {
  131. case IIO_CHAN_INFO_RAW:
  132. mutex_lock(&data->mutex);
  133. ret = i2c_smbus_read_word_data(data->client, chan->address);
  134. if (ret < 0) {
  135. mutex_unlock(&data->mutex);
  136. return ret;
  137. }
  138. *val = ret;
  139. mutex_unlock(&data->mutex);
  140. return IIO_VAL_INT;
  141. case IIO_CHAN_INFO_INT_TIME:
  142. mutex_lock(&data->mutex);
  143. ret = cm3323_get_it_bits(data);
  144. if (ret < 0) {
  145. mutex_unlock(&data->mutex);
  146. return ret;
  147. }
  148. *val = cm3323_int_time[ret].val;
  149. *val2 = cm3323_int_time[ret].val2;
  150. mutex_unlock(&data->mutex);
  151. return IIO_VAL_INT_PLUS_MICRO;
  152. default:
  153. return -EINVAL;
  154. }
  155. }
  156. static int cm3323_write_raw(struct iio_dev *indio_dev,
  157. struct iio_chan_spec const *chan, int val,
  158. int val2, long mask)
  159. {
  160. struct cm3323_data *data = iio_priv(indio_dev);
  161. int ret;
  162. switch (mask) {
  163. case IIO_CHAN_INFO_INT_TIME:
  164. mutex_lock(&data->mutex);
  165. ret = cm3323_set_it_bits(data, val, val2);
  166. mutex_unlock(&data->mutex);
  167. return ret;
  168. default:
  169. return -EINVAL;
  170. }
  171. }
  172. static const struct iio_info cm3323_info = {
  173. .read_raw = cm3323_read_raw,
  174. .write_raw = cm3323_write_raw,
  175. .attrs = &cm3323_attribute_group,
  176. };
  177. static int cm3323_probe(struct i2c_client *client,
  178. const struct i2c_device_id *id)
  179. {
  180. struct cm3323_data *data;
  181. struct iio_dev *indio_dev;
  182. int ret;
  183. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  184. if (!indio_dev)
  185. return -ENOMEM;
  186. data = iio_priv(indio_dev);
  187. i2c_set_clientdata(client, indio_dev);
  188. data->client = client;
  189. mutex_init(&data->mutex);
  190. indio_dev->info = &cm3323_info;
  191. indio_dev->name = CM3323_DRV_NAME;
  192. indio_dev->channels = cm3323_channels;
  193. indio_dev->num_channels = ARRAY_SIZE(cm3323_channels);
  194. indio_dev->modes = INDIO_DIRECT_MODE;
  195. ret = cm3323_init(indio_dev);
  196. if (ret < 0) {
  197. dev_err(&client->dev, "cm3323 chip init failed\n");
  198. return ret;
  199. }
  200. ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev);
  201. if (ret < 0)
  202. return ret;
  203. return devm_iio_device_register(&client->dev, indio_dev);
  204. }
  205. static const struct i2c_device_id cm3323_id[] = {
  206. {"cm3323", 0},
  207. {}
  208. };
  209. MODULE_DEVICE_TABLE(i2c, cm3323_id);
  210. static const struct of_device_id cm3323_of_match[] = {
  211. { .compatible = "capella,cm3323", },
  212. { /* sentinel */ }
  213. };
  214. MODULE_DEVICE_TABLE(of, cm3323_of_match);
  215. static struct i2c_driver cm3323_driver = {
  216. .driver = {
  217. .name = CM3323_DRV_NAME,
  218. .of_match_table = cm3323_of_match,
  219. },
  220. .probe = cm3323_probe,
  221. .id_table = cm3323_id,
  222. };
  223. module_i2c_driver(cm3323_driver);
  224. MODULE_AUTHOR("Daniel Baluta <[email protected]>");
  225. MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver");
  226. MODULE_LICENSE("GPL v2");