2 * Copyright (C) 2010 Samsung Electronics
3 * Hwansoon sung <hs2704.sung@samsung.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/workqueue.h>
15 #include <linux/mutex.h>
16 #include <linux/err.h>
17 #include <linux/i2c.h>
18 #include <linux/delay.h>
19 #include <linux/gpio.h>
20 #include <linux/completion.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/slab.h>
28 #define BH1721_MAX_LUX_TABLE 10
30 const unsigned char POWERDOWN = 0x00;
31 const unsigned char POWERON = 0x01;
32 const unsigned char AUTO_RESOLUTION_1 = 0x10;
33 const unsigned char AUTO_RESOLUTION_2 = 0x20;
34 const unsigned char H_RESOLUTION_1 = 0x12;
35 const unsigned char H_RESOLUTION_2 = 0x22;
36 const unsigned char L_RESOLUTION_1 = 0x13;
37 const unsigned char L_RESOLUTION_2 = 0x23;
38 const unsigned char L_RESOLUTION_3 = 0x16;
39 const unsigned char L_RESOLUTION_4 = 0x26;
46 static int lux_table[BH1721_MAX_LUX_TABLE] = {
47 1, 165, 288, 497, 869, 1532, 2692, 4692, 8280, 100000,
50 static int bh1721_write_command(struct i2c_client *client, const char *command)
52 return i2c_master_send(client, command, NUM_OF_BYTES_WRITE);
55 static int bh1721_read_value(struct i2c_client *client, char *buf)
57 return i2c_master_recv(client, buf, NUM_OF_BYTES_READ);
60 /* initial state is power down mode after vcc supply
61 * power on command is possible to omit
62 * there are 3mode: HIGH_RES, LOW_RES, AUTO_RES
63 * IN AUTO_RES, if current illuminance is more than 4000 Lx,
64 * data is output at LOW_RES mode and vice versa
67 #define BH1721_INPUT(set_mode, name) \
68 static ssize_t bh1721_store_##name(struct device *dev, \
69 struct device_attribute *attr, const char *buf, \
72 struct iio_dev *indio_dev = dev_get_drvdata(dev); \
73 struct bh1721_chip *bc = indio_dev->dev_data; \
76 bc->mode = set_mode; \
79 static DEVICE_ATTR(name, S_IWUGO, NULL, bh1721_store_##name); \
81 #define BH1721_OUTPUT_MODE(name) \
82 static ssize_t bh1721_show_##name(struct device *dev, \
83 struct device_attribute *attr, char *buf) \
85 struct iio_dev *indio_dev = dev_get_drvdata(dev); \
86 struct bh1721_chip *bc = indio_dev->dev_data; \
87 return sprintf(buf, "%d\n", bc->mode); \
89 static DEVICE_ATTR(name, S_IRUGO, bh1721_show_##name, NULL); \
91 #define BH1721_OUTPUT(name, set_value_type) \
92 static ssize_t bh1721_show_##name(struct device *dev, \
93 struct device_attribute *attr, char *buf) \
95 struct iio_dev *indio_dev = dev_get_drvdata(dev); \
96 struct bh1721_chip *bc = indio_dev->dev_data; \
97 unsigned int result; \
98 int gpio = bc->pdata->gpio; \
100 if (bc->power_control) \
101 bc->power_control(ON); \
103 bc->reset(gpio, ON); \
105 printk(KERN_INFO "bh1721 reset func doesn't exist.\n"); \
106 bh1721_write_command(bc->client, &AUTO_RESOLUTION_1); \
108 switch (bc->mode) { \
110 bh1721_write_command(bc->client, &AUTO_RESOLUTION_1); \
111 msleep(MAX_AUTO_RES_MEASURE_TIME); \
114 bh1721_write_command(bc->client, &H_RESOLUTION_2); \
115 msleep(MAX_HIGH_RES_MEASURE_TIME); \
118 bh1721_write_command(bc->client, &L_RESOLUTION_2); \
119 msleep(MAX_LOW_RES_MEASURE_TIME); \
124 bh1721_read_value(bc->client, bc->illuminance_data); \
125 bh1721_write_command(bc->client, &POWERDOWN); \
127 bc->reset(gpio, OFF); \
129 printk(KERN_INFO "bh1721 reset func doesn't exist.\n"); \
130 if (bc->power_control) \
131 bc->power_control(OFF); \
132 if (set_value_type == INPUT) \
133 result = bc->illuminance_data[0] << NUM_OF_BYTE | \
134 bc->illuminance_data[1]*10/12; \
136 result = bc->illuminance_data[0] << NUM_OF_BYTE | \
137 bc->illuminance_data[1]*10/12; \
138 for (i = 0; i < BH1721_MAX_LUX_TABLE; i++) { \
139 if (lux_table[i] > result) {\
146 return sprintf(buf, "%d\n", result); \
148 static DEVICE_ATTR(name, S_IRUGO, bh1721_show_##name, NULL); \
150 static ssize_t bh1721_show_name(struct device *dev,
151 struct device_attribute *attr,
154 struct iio_dev *indio_dev = dev_get_drvdata(dev);
155 struct bh1721_chip *chip = indio_dev->dev_data;
156 return sprintf(buf, "%s\n", chip->client->name);
159 static DEVICE_ATTR(name, S_IRUGO, bh1721_show_name, NULL);
161 BH1721_INPUT(HIGH_RES, high_res_mode);
162 BH1721_INPUT(LOW_RES, low_res_mode);
163 BH1721_INPUT(AUTO_RES, auto_res_mode);
165 BH1721_OUTPUT(illuminance0_input, INPUT);
166 BH1721_OUTPUT(level, LEVEL);
167 BH1721_OUTPUT_MODE(current_mode);
169 static struct attribute *bh1721_attributes[] = {
170 &dev_attr_high_res_mode.attr,
171 &dev_attr_low_res_mode.attr,
172 &dev_attr_auto_res_mode.attr,
173 &dev_attr_current_mode.attr,
174 &dev_attr_illuminance0_input.attr,
175 &dev_attr_level.attr,
180 static const struct attribute_group bh1721_group = {
181 .attrs = bh1721_attributes,
184 static int bh1721_probe(struct i2c_client *client,
185 const struct i2c_device_id *id)
187 struct bh1721_chip *bc;
190 bc = kzalloc(sizeof(struct bh1721_chip), GFP_KERNEL);
194 bc->indio_dev = iio_allocate_device();
195 if (!bc->indio_dev) {
197 goto error_allocate_iio_device;
201 i2c_set_clientdata(client, bc);
203 bc->indio_dev->attrs = &bh1721_group;
204 bc->indio_dev->dev.parent = &client->dev;
205 bc->indio_dev->dev_data = bc;
206 bc->indio_dev->driver_module = THIS_MODULE;
207 bc->indio_dev->modes = INDIO_DIRECT_MODE;
209 bc->mode = HIGH_RES; /* default mode */
211 ret = iio_device_register(bc->indio_dev);
213 goto error_register_iio;
215 bc->pdata = client->dev.platform_data;
217 if (bc->pdata->reset)
218 bc->reset = bc->pdata->reset;
220 printk(KERN_INFO "bh1721 reset func doesn't exist.\n");
222 if (bc->pdata->power_control)
223 bc->power_control = bc->pdata->power_control;
225 printk(KERN_INFO "bh1721 power_controlt func doesn't exist.\n");
229 error_allocate_iio_device:
232 iio_free_device(bc->indio_dev);
236 static int __devexit bh1721_remove(struct i2c_client *client)
238 struct bh1721_chip *bc = i2c_get_clientdata(client);
240 iio_device_unregister(bc->indio_dev);
241 iio_free_device(bc->indio_dev);
248 static int bh1721_suspend(struct device *dev)
250 struct i2c_client *client = to_i2c_client(dev);
251 struct bh1721_chip *bc = i2c_get_clientdata(client);
252 int gpio = bc->pdata->gpio;
255 bc->reset(gpio, OFF);
260 static int bh1721_resume(struct device *dev)
262 struct i2c_client *client = to_i2c_client(dev);
263 struct bh1721_chip *bc = i2c_get_clientdata(client);
264 int gpio = bc->pdata->gpio;
272 static const struct dev_pm_ops bh1721_dev_pm_ops = {
273 .suspend = bh1721_suspend,
274 .resume = bh1721_resume,
277 #define BH1721_DEV_PM_OPS (&bh1721_dev_pm_ops)
279 #define BH1721_DEV_PM_OPS NULL
282 static const struct i2c_device_id bh1721_id[] = {
287 MODULE_DEVICE_TABLE(i2c, bh1721_id);
289 static struct i2c_driver bh1721_i2c_driver = {
292 .pm = BH1721_DEV_PM_OPS,
294 .probe = bh1721_probe,
295 .remove = __devexit_p(bh1721_remove),
296 .id_table = bh1721_id,
299 static int __init bh1721_init(void)
301 return i2c_add_driver(&bh1721_i2c_driver);
304 module_init(bh1721_init);
306 static void __exit bh1721_exit(void)
308 i2c_del_driver(&bh1721_i2c_driver);
311 module_exit(bh1721_exit);
313 MODULE_AUTHOR("Hwan soon sung <hs2704.sung@samsung.com>");
314 MODULE_DESCRIPTION("bh1721 light sensor driver");
315 MODULE_LICENSE("GPL");