2 * apds9802als.c - apds9802 ALS Driver
4 * Copyright (C) 2009 Intel Corp
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/i2c.h>
28 #include <linux/err.h>
29 #include <linux/delay.h>
30 #include <linux/mutex.h>
31 #include <linux/sysfs.h>
32 #include <linux/hwmon-sysfs.h>
34 #define ALS_MIN_RANGE_VAL 1
35 #define ALS_MAX_RANGE_VAL 2
36 #define POWER_STA_ENABLE 1
37 #define POWER_STA_DISABLE 0
38 #define APDS9802ALS_I2C_ADDR 0x29
40 #define DRIVER_NAME "apds9802als"
43 struct device *hwmon_dev;
48 static ssize_t als_sensing_range_show(struct device *dev,
49 struct device_attribute *attr, char *buf)
51 struct i2c_client *client = to_i2c_client(dev);
54 val = i2c_smbus_read_byte_data(client, 0x81);
58 return sprintf(buf, "4095\n");
60 return sprintf(buf, "65535\n");
63 static ssize_t als_lux0_input_data_show(struct device *dev,
64 struct device_attribute *attr, char *buf)
66 struct i2c_client *client = to_i2c_client(dev);
67 struct als_data *data = i2c_get_clientdata(client);
71 /* Protect against parallel reads */
72 mutex_lock(&data->mutex);
73 temp = i2c_smbus_read_byte_data(client, 0x8C);/*LSB data*/
78 ret_val = i2c_smbus_read_byte_data(client, 0x8D);/*MSB data*/
81 mutex_unlock(&data->mutex);
82 ret_val = (ret_val << 8) | temp;
83 return sprintf(buf, "%d\n", ret_val);
85 mutex_unlock(&data->mutex);
89 static ssize_t als_sensing_range_store(struct device *dev,
90 struct device_attribute *attr, const char *buf, size_t count)
92 struct i2c_client *client = to_i2c_client(dev);
93 struct als_data *data = i2c_get_clientdata(client);
97 if (strict_strtoul(buf, 10, &val))
102 else if (val < 65536)
107 /* Make sure nobody else reads/modifies/writes 0x81 while we
110 mutex_lock(&data->mutex);
112 ret_val = i2c_smbus_read_byte_data(client, 0x81);
116 /* Reset the bits before setting them */
117 ret_val = ret_val & 0xFA;
119 if (val == 1) /* Setting the continous measurement up to 4k LUX */
120 ret_val = (ret_val | 0x05);
121 else /* Setting the continous measurement up to 64k LUX*/
122 ret_val = (ret_val | 0x04);
124 ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val);
127 mutex_unlock(&data->mutex);
131 mutex_unlock(&data->mutex);
135 static ssize_t als_power_status_show(struct device *dev,
136 struct device_attribute *attr, char *buf)
138 struct i2c_client *client = to_i2c_client(dev);
140 ret_val = i2c_smbus_read_byte_data(client, 0x80);
143 ret_val = ret_val & 0x01;
144 return sprintf(buf, "%d\n", ret_val);
147 static int als_set_power_state(struct i2c_client *client, bool on_off)
150 struct als_data *data = i2c_get_clientdata(client);
152 mutex_lock(&data->mutex);
153 ret_val = i2c_smbus_read_byte_data(client, 0x80);
157 ret_val = ret_val | 0x01;
159 ret_val = ret_val & 0xFE;
160 ret_val = i2c_smbus_write_byte_data(client, 0x80, ret_val);
162 mutex_unlock(&data->mutex);
166 static ssize_t als_power_status_store(struct device *dev,
167 struct device_attribute *attr, const char *buf, size_t count)
169 struct i2c_client *client = to_i2c_client(dev);
170 struct als_data *data = i2c_get_clientdata(client);
174 if (strict_strtoul(buf, 10, &val))
176 if (val == POWER_STA_ENABLE) {
177 ret_val = als_set_power_state(client, true);
178 data->needresume = true;
179 } else if (val == POWER_STA_DISABLE) {
180 ret_val = als_set_power_state(client, false);
181 data->needresume = false;
189 static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
190 als_sensing_range_show, als_sensing_range_store);
191 static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL);
192 static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
193 als_power_status_show, als_power_status_store);
195 static struct attribute *mid_att_als[] = {
196 &dev_attr_lux0_sensor_range.attr,
197 &dev_attr_lux0_input.attr,
198 &dev_attr_power_state.attr,
202 static struct attribute_group m_als_gr = {
203 .name = "apds9802als",
207 static int als_set_default_config(struct i2c_client *client)
210 /* Write the command and then switch on */
211 ret_val = i2c_smbus_write_byte_data(client, 0x80, 0x01);
213 dev_err(&client->dev, "failed default switch on write\n");
216 /* Continous from 1Lux to 64k Lux */
217 ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x04);
219 dev_err(&client->dev, "failed default LUX on write\n");
223 static int apds9802als_probe(struct i2c_client *client,
224 const struct i2c_device_id *id)
227 struct als_data *data;
229 data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
231 dev_err(&client->dev, "Memory allocation failed\n");
234 i2c_set_clientdata(client, data);
235 res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
237 dev_err(&client->dev, "device create file failed\n");
240 dev_info(&client->dev,
241 "%s apds9802als: ALS chip found\n", client->name);
242 als_set_default_config(client);
243 data->needresume = true;
244 mutex_init(&data->mutex);
247 i2c_set_clientdata(client, NULL);
252 static int apds9802als_remove(struct i2c_client *client)
254 struct als_data *data = i2c_get_clientdata(client);
255 sysfs_remove_group(&client->dev.kobj, &m_als_gr);
260 static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg)
262 als_set_power_state(client, false);
266 static int apds9802als_resume(struct i2c_client *client)
268 struct als_data *data = i2c_get_clientdata(client);
270 if (data->needresume == true)
271 als_set_power_state(client, true);
275 static struct i2c_device_id apds9802als_id[] = {
280 MODULE_DEVICE_TABLE(i2c, apds9802als_id);
282 static struct i2c_driver apds9802als_driver = {
285 .owner = THIS_MODULE,
287 .probe = apds9802als_probe,
288 .remove = apds9802als_remove,
289 .suspend = apds9802als_suspend,
290 .resume = apds9802als_resume,
291 .id_table = apds9802als_id,
294 static int __init sensor_apds9802als_init(void)
296 return i2c_add_driver(&apds9802als_driver);
299 static void __exit sensor_apds9802als_exit(void)
301 i2c_del_driver(&apds9802als_driver);
303 module_init(sensor_apds9802als_init);
304 module_exit(sensor_apds9802als_exit);
306 MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com");
307 MODULE_DESCRIPTION("Avago apds9802als ALS Driver");
308 MODULE_LICENSE("GPL v2");