0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/bitfield.h>
0016 #include <linux/i2c.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019
0020 #include <linux/iio/iio.h>
0021 #include <linux/iio/sysfs.h>
0022
0023 #define AL3320A_DRV_NAME "al3320a"
0024
0025 #define AL3320A_REG_CONFIG 0x00
0026 #define AL3320A_REG_STATUS 0x01
0027 #define AL3320A_REG_INT 0x02
0028 #define AL3320A_REG_WAIT 0x06
0029 #define AL3320A_REG_CONFIG_RANGE 0x07
0030 #define AL3320A_REG_PERSIST 0x08
0031 #define AL3320A_REG_MEAN_TIME 0x09
0032 #define AL3320A_REG_ADUMMY 0x0A
0033 #define AL3320A_REG_DATA_LOW 0x22
0034
0035 #define AL3320A_REG_LOW_THRESH_LOW 0x30
0036 #define AL3320A_REG_LOW_THRESH_HIGH 0x31
0037 #define AL3320A_REG_HIGH_THRESH_LOW 0x32
0038 #define AL3320A_REG_HIGH_THRESH_HIGH 0x33
0039
0040 #define AL3320A_CONFIG_DISABLE 0x00
0041 #define AL3320A_CONFIG_ENABLE 0x01
0042
0043 #define AL3320A_GAIN_MASK GENMASK(2, 1)
0044
0045
0046 #define AL3320A_DEFAULT_MEAN_TIME 4
0047 #define AL3320A_DEFAULT_WAIT_TIME 0
0048
0049 #define AL3320A_SCALE_AVAILABLE "0.512 0.128 0.032 0.01"
0050
0051 enum al3320a_range {
0052 AL3320A_RANGE_1,
0053 AL3320A_RANGE_2,
0054 AL3320A_RANGE_3,
0055 AL3320A_RANGE_4
0056 };
0057
0058 static const int al3320a_scales[][2] = {
0059 {0, 512000}, {0, 128000}, {0, 32000}, {0, 10000}
0060 };
0061
0062 struct al3320a_data {
0063 struct i2c_client *client;
0064 };
0065
0066 static const struct iio_chan_spec al3320a_channels[] = {
0067 {
0068 .type = IIO_LIGHT,
0069 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0070 BIT(IIO_CHAN_INFO_SCALE),
0071 }
0072 };
0073
0074 static IIO_CONST_ATTR(in_illuminance_scale_available, AL3320A_SCALE_AVAILABLE);
0075
0076 static struct attribute *al3320a_attributes[] = {
0077 &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
0078 NULL,
0079 };
0080
0081 static const struct attribute_group al3320a_attribute_group = {
0082 .attrs = al3320a_attributes,
0083 };
0084
0085 static int al3320a_set_pwr(struct i2c_client *client, bool pwr)
0086 {
0087 u8 val = pwr ? AL3320A_CONFIG_ENABLE : AL3320A_CONFIG_DISABLE;
0088 return i2c_smbus_write_byte_data(client, AL3320A_REG_CONFIG, val);
0089 }
0090
0091 static void al3320a_set_pwr_off(void *_data)
0092 {
0093 struct al3320a_data *data = _data;
0094
0095 al3320a_set_pwr(data->client, false);
0096 }
0097
0098 static int al3320a_init(struct al3320a_data *data)
0099 {
0100 int ret;
0101
0102 ret = al3320a_set_pwr(data->client, true);
0103
0104 if (ret < 0)
0105 return ret;
0106
0107 ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_CONFIG_RANGE,
0108 FIELD_PREP(AL3320A_GAIN_MASK,
0109 AL3320A_RANGE_3));
0110 if (ret < 0)
0111 return ret;
0112
0113 ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_MEAN_TIME,
0114 AL3320A_DEFAULT_MEAN_TIME);
0115 if (ret < 0)
0116 return ret;
0117
0118 ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_WAIT,
0119 AL3320A_DEFAULT_WAIT_TIME);
0120 if (ret < 0)
0121 return ret;
0122
0123 return 0;
0124 }
0125
0126 static int al3320a_read_raw(struct iio_dev *indio_dev,
0127 struct iio_chan_spec const *chan, int *val,
0128 int *val2, long mask)
0129 {
0130 struct al3320a_data *data = iio_priv(indio_dev);
0131 int ret;
0132
0133 switch (mask) {
0134 case IIO_CHAN_INFO_RAW:
0135
0136
0137
0138
0139
0140 ret = i2c_smbus_read_word_data(data->client,
0141 AL3320A_REG_DATA_LOW);
0142 if (ret < 0)
0143 return ret;
0144 *val = ret;
0145 return IIO_VAL_INT;
0146 case IIO_CHAN_INFO_SCALE:
0147 ret = i2c_smbus_read_byte_data(data->client,
0148 AL3320A_REG_CONFIG_RANGE);
0149 if (ret < 0)
0150 return ret;
0151
0152 ret = FIELD_GET(AL3320A_GAIN_MASK, ret);
0153 *val = al3320a_scales[ret][0];
0154 *val2 = al3320a_scales[ret][1];
0155
0156 return IIO_VAL_INT_PLUS_MICRO;
0157 }
0158 return -EINVAL;
0159 }
0160
0161 static int al3320a_write_raw(struct iio_dev *indio_dev,
0162 struct iio_chan_spec const *chan, int val,
0163 int val2, long mask)
0164 {
0165 struct al3320a_data *data = iio_priv(indio_dev);
0166 int i;
0167
0168 switch (mask) {
0169 case IIO_CHAN_INFO_SCALE:
0170 for (i = 0; i < ARRAY_SIZE(al3320a_scales); i++) {
0171 if (val != al3320a_scales[i][0] ||
0172 val2 != al3320a_scales[i][1])
0173 continue;
0174
0175 return i2c_smbus_write_byte_data(data->client,
0176 AL3320A_REG_CONFIG_RANGE,
0177 FIELD_PREP(AL3320A_GAIN_MASK, i));
0178 }
0179 break;
0180 }
0181 return -EINVAL;
0182 }
0183
0184 static const struct iio_info al3320a_info = {
0185 .read_raw = al3320a_read_raw,
0186 .write_raw = al3320a_write_raw,
0187 .attrs = &al3320a_attribute_group,
0188 };
0189
0190 static int al3320a_probe(struct i2c_client *client,
0191 const struct i2c_device_id *id)
0192 {
0193 struct al3320a_data *data;
0194 struct iio_dev *indio_dev;
0195 int ret;
0196
0197 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0198 if (!indio_dev)
0199 return -ENOMEM;
0200
0201 data = iio_priv(indio_dev);
0202 i2c_set_clientdata(client, indio_dev);
0203 data->client = client;
0204
0205 indio_dev->info = &al3320a_info;
0206 indio_dev->name = AL3320A_DRV_NAME;
0207 indio_dev->channels = al3320a_channels;
0208 indio_dev->num_channels = ARRAY_SIZE(al3320a_channels);
0209 indio_dev->modes = INDIO_DIRECT_MODE;
0210
0211 ret = al3320a_init(data);
0212 if (ret < 0) {
0213 dev_err(&client->dev, "al3320a chip init failed\n");
0214 return ret;
0215 }
0216
0217 ret = devm_add_action_or_reset(&client->dev,
0218 al3320a_set_pwr_off,
0219 data);
0220 if (ret < 0)
0221 return ret;
0222
0223 return devm_iio_device_register(&client->dev, indio_dev);
0224 }
0225
0226 static int al3320a_suspend(struct device *dev)
0227 {
0228 return al3320a_set_pwr(to_i2c_client(dev), false);
0229 }
0230
0231 static int al3320a_resume(struct device *dev)
0232 {
0233 return al3320a_set_pwr(to_i2c_client(dev), true);
0234 }
0235
0236 static DEFINE_SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend,
0237 al3320a_resume);
0238
0239 static const struct i2c_device_id al3320a_id[] = {
0240 {"al3320a", 0},
0241 {}
0242 };
0243 MODULE_DEVICE_TABLE(i2c, al3320a_id);
0244
0245 static const struct of_device_id al3320a_of_match[] = {
0246 { .compatible = "dynaimage,al3320a", },
0247 {},
0248 };
0249 MODULE_DEVICE_TABLE(of, al3320a_of_match);
0250
0251 static struct i2c_driver al3320a_driver = {
0252 .driver = {
0253 .name = AL3320A_DRV_NAME,
0254 .of_match_table = al3320a_of_match,
0255 .pm = pm_sleep_ptr(&al3320a_pm_ops),
0256 },
0257 .probe = al3320a_probe,
0258 .id_table = al3320a_id,
0259 };
0260
0261 module_i2c_driver(al3320a_driver);
0262
0263 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
0264 MODULE_DESCRIPTION("AL3320A Ambient Light Sensor driver");
0265 MODULE_LICENSE("GPL v2");