~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/misc/bh1780gli.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * bh1780gli.c
 
3
 * ROHM Ambient Light Sensor Driver
 
4
 *
 
5
 * Copyright (C) 2010 Texas Instruments
 
6
 * Author: Hemanth V <hemanthv@ti.com>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify it
 
9
 * under the terms of the GNU General Public License version 2 as published by
 
10
 * the Free Software Foundation.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
15
 * more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along with
 
18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
#include <linux/i2c.h>
 
21
#include <linux/slab.h>
 
22
#include <linux/mutex.h>
 
23
#include <linux/platform_device.h>
 
24
#include <linux/delay.h>
 
25
#include <linux/module.h>
 
26
 
 
27
#define BH1780_REG_CONTROL      0x80
 
28
#define BH1780_REG_PARTID       0x8A
 
29
#define BH1780_REG_MANFID       0x8B
 
30
#define BH1780_REG_DLOW 0x8C
 
31
#define BH1780_REG_DHIGH        0x8D
 
32
 
 
33
#define BH1780_REVMASK          (0xf)
 
34
#define BH1780_POWMASK          (0x3)
 
35
#define BH1780_POFF             (0x0)
 
36
#define BH1780_PON              (0x3)
 
37
 
 
38
/* power on settling time in ms */
 
39
#define BH1780_PON_DELAY        2
 
40
 
 
41
struct bh1780_data {
 
42
        struct i2c_client *client;
 
43
        int power_state;
 
44
        /* lock for sysfs operations */
 
45
        struct mutex lock;
 
46
};
 
47
 
 
48
static int bh1780_write(struct bh1780_data *ddata, u8 reg, u8 val, char *msg)
 
49
{
 
50
        int ret = i2c_smbus_write_byte_data(ddata->client, reg, val);
 
51
        if (ret < 0)
 
52
                dev_err(&ddata->client->dev,
 
53
                        "i2c_smbus_write_byte_data failed error %d Register (%s)\n",
 
54
                        ret, msg);
 
55
        return ret;
 
56
}
 
57
 
 
58
static int bh1780_read(struct bh1780_data *ddata, u8 reg, char *msg)
 
59
{
 
60
        int ret = i2c_smbus_read_byte_data(ddata->client, reg);
 
61
        if (ret < 0)
 
62
                dev_err(&ddata->client->dev,
 
63
                        "i2c_smbus_read_byte_data failed error %d Register (%s)\n",
 
64
                        ret, msg);
 
65
        return ret;
 
66
}
 
67
 
 
68
static ssize_t bh1780_show_lux(struct device *dev,
 
69
                                struct device_attribute *attr, char *buf)
 
70
{
 
71
        struct platform_device *pdev = to_platform_device(dev);
 
72
        struct bh1780_data *ddata = platform_get_drvdata(pdev);
 
73
        int lsb, msb;
 
74
 
 
75
        lsb = bh1780_read(ddata, BH1780_REG_DLOW, "DLOW");
 
76
        if (lsb < 0)
 
77
                return lsb;
 
78
 
 
79
        msb = bh1780_read(ddata, BH1780_REG_DHIGH, "DHIGH");
 
80
        if (msb < 0)
 
81
                return msb;
 
82
 
 
83
        return sprintf(buf, "%d\n", (msb << 8) | lsb);
 
84
}
 
85
 
 
86
static ssize_t bh1780_show_power_state(struct device *dev,
 
87
                                        struct device_attribute *attr,
 
88
                                        char *buf)
 
89
{
 
90
        struct platform_device *pdev = to_platform_device(dev);
 
91
        struct bh1780_data *ddata = platform_get_drvdata(pdev);
 
92
        int state;
 
93
 
 
94
        state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL");
 
95
        if (state < 0)
 
96
                return state;
 
97
 
 
98
        return sprintf(buf, "%d\n", state & BH1780_POWMASK);
 
99
}
 
100
 
 
101
static ssize_t bh1780_store_power_state(struct device *dev,
 
102
                                        struct device_attribute *attr,
 
103
                                        const char *buf, size_t count)
 
104
{
 
105
        struct platform_device *pdev = to_platform_device(dev);
 
106
        struct bh1780_data *ddata = platform_get_drvdata(pdev);
 
107
        unsigned long val;
 
108
        int error;
 
109
 
 
110
        error = strict_strtoul(buf, 0, &val);
 
111
        if (error)
 
112
                return error;
 
113
 
 
114
        if (val < BH1780_POFF || val > BH1780_PON)
 
115
                return -EINVAL;
 
116
 
 
117
        mutex_lock(&ddata->lock);
 
118
 
 
119
        error = bh1780_write(ddata, BH1780_REG_CONTROL, val, "CONTROL");
 
120
        if (error < 0) {
 
121
                mutex_unlock(&ddata->lock);
 
122
                return error;
 
123
        }
 
124
 
 
125
        msleep(BH1780_PON_DELAY);
 
126
        ddata->power_state = val;
 
127
        mutex_unlock(&ddata->lock);
 
128
 
 
129
        return count;
 
130
}
 
131
 
 
132
static DEVICE_ATTR(lux, S_IRUGO, bh1780_show_lux, NULL);
 
133
 
 
134
static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
 
135
                bh1780_show_power_state, bh1780_store_power_state);
 
136
 
 
137
static struct attribute *bh1780_attributes[] = {
 
138
        &dev_attr_power_state.attr,
 
139
        &dev_attr_lux.attr,
 
140
        NULL
 
141
};
 
142
 
 
143
static const struct attribute_group bh1780_attr_group = {
 
144
        .attrs = bh1780_attributes,
 
145
};
 
146
 
 
147
static int __devinit bh1780_probe(struct i2c_client *client,
 
148
                                                const struct i2c_device_id *id)
 
149
{
 
150
        int ret;
 
151
        struct bh1780_data *ddata = NULL;
 
152
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 
153
 
 
154
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
 
155
                ret = -EIO;
 
156
                goto err_op_failed;
 
157
        }
 
158
 
 
159
        ddata = kzalloc(sizeof(struct bh1780_data), GFP_KERNEL);
 
160
        if (ddata == NULL) {
 
161
                ret = -ENOMEM;
 
162
                goto err_op_failed;
 
163
        }
 
164
 
 
165
        ddata->client = client;
 
166
        i2c_set_clientdata(client, ddata);
 
167
 
 
168
        ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID");
 
169
        if (ret < 0)
 
170
                goto err_op_failed;
 
171
 
 
172
        dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n",
 
173
                        (ret & BH1780_REVMASK));
 
174
 
 
175
        mutex_init(&ddata->lock);
 
176
 
 
177
        ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group);
 
178
        if (ret)
 
179
                goto err_op_failed;
 
180
 
 
181
        return 0;
 
182
 
 
183
err_op_failed:
 
184
        kfree(ddata);
 
185
        return ret;
 
186
}
 
187
 
 
188
static int __devexit bh1780_remove(struct i2c_client *client)
 
189
{
 
190
        struct bh1780_data *ddata;
 
191
 
 
192
        ddata = i2c_get_clientdata(client);
 
193
        sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
 
194
        kfree(ddata);
 
195
 
 
196
        return 0;
 
197
}
 
198
 
 
199
#ifdef CONFIG_PM
 
200
static int bh1780_suspend(struct device *dev)
 
201
{
 
202
        struct bh1780_data *ddata;
 
203
        int state, ret;
 
204
        struct i2c_client *client = to_i2c_client(dev);
 
205
 
 
206
        ddata = i2c_get_clientdata(client);
 
207
        state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL");
 
208
        if (state < 0)
 
209
                return state;
 
210
 
 
211
        ddata->power_state = state & BH1780_POWMASK;
 
212
 
 
213
        ret = bh1780_write(ddata, BH1780_REG_CONTROL, BH1780_POFF,
 
214
                                "CONTROL");
 
215
 
 
216
        if (ret < 0)
 
217
                return ret;
 
218
 
 
219
        return 0;
 
220
}
 
221
 
 
222
static int bh1780_resume(struct device *dev)
 
223
{
 
224
        struct bh1780_data *ddata;
 
225
        int state, ret;
 
226
        struct i2c_client *client = to_i2c_client(dev);
 
227
 
 
228
        ddata = i2c_get_clientdata(client);
 
229
        state = ddata->power_state;
 
230
        ret = bh1780_write(ddata, BH1780_REG_CONTROL, state,
 
231
                                "CONTROL");
 
232
 
 
233
        if (ret < 0)
 
234
                return ret;
 
235
 
 
236
        return 0;
 
237
}
 
238
static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume);
 
239
#define BH1780_PMOPS (&bh1780_pm)
 
240
#else
 
241
#define BH1780_PMOPS NULL
 
242
#endif /* CONFIG_PM */
 
243
 
 
244
static const struct i2c_device_id bh1780_id[] = {
 
245
        { "bh1780", 0 },
 
246
        { },
 
247
};
 
248
 
 
249
static struct i2c_driver bh1780_driver = {
 
250
        .probe          = bh1780_probe,
 
251
        .remove         = bh1780_remove,
 
252
        .id_table       = bh1780_id,
 
253
        .driver = {
 
254
                .name = "bh1780",
 
255
                .pm     = BH1780_PMOPS,
 
256
},
 
257
};
 
258
 
 
259
static int __init bh1780_init(void)
 
260
{
 
261
        return i2c_add_driver(&bh1780_driver);
 
262
}
 
263
 
 
264
static void __exit bh1780_exit(void)
 
265
{
 
266
        i2c_del_driver(&bh1780_driver);
 
267
}
 
268
 
 
269
module_init(bh1780_init)
 
270
module_exit(bh1780_exit)
 
271
 
 
272
MODULE_DESCRIPTION("BH1780GLI Ambient Light Sensor Driver");
 
273
MODULE_LICENSE("GPL");
 
274
MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");