Merge branch 'android-tegra-2.6.36' into android-tegra-moto-2.6.36
[firefly-linux-kernel-4.4.55.git] / drivers / leds / leds-lp8550.c
1 /*
2  * Copyright (C) 2010 Motorola, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
16  * 02111-1307, USA
17  */
18
19 #include <linux/delay.h>
20 #include <linux/i2c.h>
21 #include <linux/leds.h>
22 #include <linux/platform_device.h>
23 #include <linux/leds-lp8550.h>
24 #include <linux/slab.h>
25 #include <linux/types.h>
26
27 #define DEBUG
28
29 #define LD_LP8550_ON_OFF_MASK 0xFE
30
31 #define LD_LP8550_ALLOWED_R_BYTES 1
32 #define LD_LP8550_ALLOWED_W_BYTES 2
33 #define LD_LP8550_MAX_RW_RETRIES 5
34 #define LD_LP8550_I2C_RETRY_DELAY 10
35
36 #define LP8550_BRIGHTNESS_CTRL  0x00
37 #define LP8550_DEVICE_CTRL      0x01
38 #define LP8550_FAULT            0x02
39 #define LP8550_CHIP_ID          0x03
40 #define LP8550_DIRECT_CTRL      0x04
41 #define LP8550_TEMP_MSB         0x05
42 #define LP8550_TEMP_LSB         0x06
43
44 /* EEPROM Register address */
45 #define LP8550_EEPROM_CTRL      0x72
46 #define LP8550_EEPROM_A0        0xa0
47 #define LP8550_EEPROM_A1        0xa1
48 #define LP8550_EEPROM_A2        0xa2
49 #define LP8550_EEPROM_A3        0xa3
50 #define LP8550_EEPROM_A4        0xa4
51 #define LP8550_EEPROM_A5        0xa5
52 #define LP8550_EEPROM_A6        0xa6
53 #define LP8550_EEPROM_A7        0xa7
54
55
56 struct lp8550_data {
57         struct led_classdev led_dev;
58         struct i2c_client *client;
59         struct work_struct wq;
60         struct lp8550_platform_data *led_pdata;
61         uint8_t last_requested_brightness;
62         int brightness;
63 };
64
65 #ifdef DEBUG
66 struct lp8550_reg {
67         const char *name;
68         uint8_t reg;
69 } lp8550_regs[] = {
70         { "BRIGHTNESS_CTRL",    LP8550_BRIGHTNESS_CTRL },
71         { "DEV_CTRL",           LP8550_DEVICE_CTRL },
72         { "FAULT",              LP8550_FAULT },
73         { "CHIP_ID",            LP8550_CHIP_ID },
74         { "DIRECT_CTRL",        LP8550_DIRECT_CTRL },
75         { "EEPROM_CTRL",        LP8550_EEPROM_CTRL },
76         { "EEPROM_A0",          LP8550_EEPROM_A0 },
77         { "EEPROM_A1",          LP8550_EEPROM_A1 },
78         { "EEPROM_A2",          LP8550_EEPROM_A2 },
79         { "EEPROM_A3",          LP8550_EEPROM_A3 },
80         { "EEPROM_A4",          LP8550_EEPROM_A4 },
81         { "EEPROM_A5",          LP8550_EEPROM_A5 },
82         { "EEPROM_A6",          LP8550_EEPROM_A6 },
83         { "EEPROM_A7",          LP8550_EEPROM_A7 },
84 };
85 #endif
86
87 static uint32_t lp8550_debug;
88 module_param_named(als_debug, lp8550_debug, uint, 0664);
89 static void lp8550_brightness_write(struct lp8550_data *led_data);
90
91 static int lp8550_read_reg(struct lp8550_data *led_data, uint8_t reg,
92                    uint8_t *value)
93 {
94         int error = 0;
95         int i = 0;
96         uint8_t dest_buffer;
97
98         if (!value) {
99                 pr_err("%s: invalid value pointer\n", __func__);
100                 return -EINVAL;
101         }
102         do {
103                 dest_buffer = reg;
104                 error = i2c_master_send(led_data->client, &dest_buffer, 1);
105                 if (error == 1) {
106                         error = i2c_master_recv(led_data->client,
107                                 &dest_buffer, LD_LP8550_ALLOWED_R_BYTES);
108                 }
109                 if (error != LD_LP8550_ALLOWED_R_BYTES) {
110                         pr_err("%s: read[%i] failed: %d\n", __func__, i, error);
111                         msleep(LD_LP8550_I2C_RETRY_DELAY);
112                 }
113         } while ((error != LD_LP8550_ALLOWED_R_BYTES) &&
114                         ((++i) < LD_LP8550_MAX_RW_RETRIES));
115
116         if (error == LD_LP8550_ALLOWED_R_BYTES) {
117                 error = 0;
118                 *value = dest_buffer;
119         }
120
121         return error;
122 }
123
124 static int lp8550_write_reg(struct lp8550_data *led_data, uint8_t reg,
125                         uint8_t value)
126 {
127         uint8_t buf[LD_LP8550_ALLOWED_W_BYTES] = { reg, value };
128         int bytes;
129         int i = 0;
130
131         do {
132                 bytes = i2c_master_send(led_data->client, buf,
133                                         LD_LP8550_ALLOWED_W_BYTES);
134
135                 if (bytes != LD_LP8550_ALLOWED_W_BYTES) {
136                         pr_err("%s: write %d failed: %d\n", __func__, i, bytes);
137                         msleep(LD_LP8550_I2C_RETRY_DELAY);
138                 }
139         } while ((bytes != (LD_LP8550_ALLOWED_W_BYTES))
140                  && ((++i) < LD_LP8550_MAX_RW_RETRIES));
141
142         if (bytes != LD_LP8550_ALLOWED_W_BYTES) {
143                 pr_err("%s: i2c_master_send error\n", __func__);
144                 return -EINVAL;
145         }
146         return 0;
147 }
148
149 static int ld_lp8550_init_registers(struct lp8550_data *led_data)
150 {
151         unsigned i, n, reg_count, reg_addr;
152         uint8_t value = 0;
153
154         /* Check the EEPROM values and update if neccessary */
155         reg_count = 8;
156         reg_addr = LP8550_EEPROM_A0;
157         for (i = 0, n = 0; i < reg_count; i++) {
158                 lp8550_read_reg(led_data, reg_addr, &value);
159                 if (lp8550_debug)
160                         pr_info("%s:Register 0x%x value 0x%X\n", __func__,
161                                 reg_addr, value);
162                 if (value != led_data->led_pdata->eeprom_table[n].eeprom_data) {
163                         if (lp8550_debug)
164                                 pr_info("%s:Writing 0x%x to 0x%X\n", __func__,
165                                 led_data->led_pdata->eeprom_table[n].eeprom_data,
166                                 reg_addr);
167                         if (lp8550_write_reg(led_data, LP8550_DEVICE_CTRL,
168                                         0x05))
169                                 pr_err("%s:Register initialization failed\n",
170                                         __func__);
171                         if (lp8550_write_reg(led_data, reg_addr,
172                                 led_data->led_pdata->eeprom_table[n].eeprom_data))
173                                 pr_err("%s:Register initialization failed\n",
174                                         __func__);
175                         if (lp8550_write_reg(led_data, LP8550_EEPROM_CTRL,
176                                         0x04))
177                                 pr_err("%s:Register initialization failed\n",
178                                         __func__);
179                         if (lp8550_write_reg(led_data, LP8550_EEPROM_CTRL,
180                                         0x02))
181                                 pr_err("%s:Register initialization failed\n",
182                                         __func__);
183                         msleep(200);
184                         if (lp8550_write_reg(led_data, LP8550_EEPROM_CTRL,
185                                         0x00))
186                                 pr_err("%s:Register initialization failed\n",
187                                         __func__);
188                 }
189                 n++;
190                 reg_addr++;
191         }
192
193         if (lp8550_write_reg(led_data, LP8550_DEVICE_CTRL,
194                 led_data->led_pdata->dev_ctrl_config)) {
195                 pr_err("%s:Register initialization failed\n", __func__);
196                 return -EINVAL;
197         }
198         return 0;
199 }
200
201 static void ld_lp8550_brightness_set(struct led_classdev *led_cdev,
202                                      enum led_brightness brightness)
203 {
204         struct lp8550_data *led_data =
205                 container_of(led_cdev, struct lp8550_data, led_dev);
206
207         if (brightness > 255)
208                 brightness = 255;
209
210         led_data->brightness = brightness;
211         schedule_work(&led_data->wq);
212 }
213 EXPORT_SYMBOL(ld_lp8550_brightness_set);
214
215 static void lp8550_brightness_work(struct work_struct *work)
216 {
217         struct lp8550_data *led_data =
218                 container_of(work, struct lp8550_data, wq);
219
220         lp8550_brightness_write(led_data);
221 }
222
223 static void lp8550_brightness_write(struct lp8550_data *led_data)
224 {
225         int error = 0;
226         int brightness = led_data->brightness;
227
228         if (lp8550_debug)
229                 pr_info("%s: setting brightness to %i\n",
230                         __func__, brightness);
231
232         if (brightness == LED_OFF) {
233                 if (lp8550_write_reg(led_data, LP8550_DEVICE_CTRL,
234                                 (led_data->led_pdata->dev_ctrl_config &
235                                 LD_LP8550_ON_OFF_MASK))) {
236                         pr_err("%s:writing failed while setting brightness:%d\n",
237                                 __func__, error);
238                 }
239         } else {
240                 if (lp8550_write_reg(led_data, LP8550_DEVICE_CTRL,
241                                 led_data->led_pdata->dev_ctrl_config | 0x01)) {
242                         pr_err("%s:writing failed while setting brightness:%d\n",
243                                 __func__, error);
244                 }
245                 if (lp8550_write_reg(led_data, LP8550_BRIGHTNESS_CTRL, brightness)) {
246                                 pr_err("%s:Failed to set brightness:%d\n",
247                                 __func__, error);
248                 }
249                 led_data->last_requested_brightness = brightness;
250         }
251 }
252
253 #ifdef DEBUG
254 static ssize_t ld_lp8550_registers_show(struct device *dev,
255                               struct device_attribute *attr, char *buf)
256 {
257         struct i2c_client *client = container_of(dev->parent, struct i2c_client,
258                                                  dev);
259         struct lp8550_data *led_data = i2c_get_clientdata(client);
260         unsigned i, n, reg_count;
261         uint8_t value = 0;
262
263         reg_count = sizeof(lp8550_regs) / sizeof(lp8550_regs[0]);
264         for (i = 0, n = 0; i < reg_count; i++) {
265                 lp8550_read_reg(led_data, lp8550_regs[i].reg, &value);
266                 n += scnprintf(buf + n, PAGE_SIZE - n,
267                                "%-20s = 0x%02X\n",
268                                lp8550_regs[i].name,
269                                value);
270         }
271
272         return n;
273 }
274
275 static ssize_t ld_lp8550_registers_store(struct device *dev,
276                                struct device_attribute *attr,
277                                const char *buf, size_t count)
278 {
279         struct i2c_client *client = container_of(dev->parent, struct i2c_client,
280                                                  dev);
281         struct lp8550_data *led_data = i2c_get_clientdata(client);
282         unsigned i, reg_count, value;
283         int error;
284         char name[30];
285
286         if (count >= 30) {
287                 pr_err("%s:input too long\n", __func__);
288                 return -1;
289         }
290
291         if (sscanf(buf, "%s %x", name, &value) != 2) {
292                 pr_err("%s:unable to parse input\n", __func__);
293                 return -1;
294         }
295
296         reg_count = sizeof(lp8550_regs) / sizeof(lp8550_regs[0]);
297         for (i = 0; i < reg_count; i++) {
298                 if (!strcmp(name, lp8550_regs[i].name)) {
299                         error = lp8550_write_reg(led_data,
300                                 lp8550_regs[i].reg,
301                                 value);
302                         if (error) {
303                                 pr_err("%s:Failed to write register %s\n",
304                                         __func__, name);
305                                 return -1;
306                         }
307                         return count;
308                 }
309         }
310
311         pr_err("%s:no such register %s\n", __func__, name);
312         return -1;
313 }
314 static DEVICE_ATTR(registers, 0644, ld_lp8550_registers_show,
315                 ld_lp8550_registers_store);
316 #endif
317
318 static int ld_lp8550_probe(struct i2c_client *client,
319                            const struct i2c_device_id *id)
320 {
321         struct lp8550_platform_data *pdata = client->dev.platform_data;
322         struct lp8550_data *led_data;
323         int error = 0;
324
325         if (pdata == NULL) {
326                 pr_err("%s: platform data required\n", __func__);
327                 return -ENODEV;
328         } else if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
329                 pr_err("%s:I2C_FUNC_I2C not supported\n", __func__);
330                 return -ENODEV;
331         }
332
333         led_data = kzalloc(sizeof(struct lp8550_data), GFP_KERNEL);
334         if (led_data == NULL) {
335                 error = -ENOMEM;
336                 goto err_alloc_data_failed;
337         }
338
339         led_data->client = client;
340
341         led_data->led_dev.name = LD_LP8550_LED_DEV;
342         led_data->led_dev.brightness_set = ld_lp8550_brightness_set;
343         led_data->led_pdata = client->dev.platform_data;
344
345         i2c_set_clientdata(client, led_data);
346
347         error = ld_lp8550_init_registers(led_data);
348         if (error < 0) {
349                 pr_err("%s: Register Initialization failed: %d\n",
350                        __func__, error);
351                 error = -ENODEV;
352                 goto err_reg_init_failed;
353         }
354
355         error = lp8550_write_reg(led_data, LP8550_BRIGHTNESS_CTRL,
356                                  pdata->power_up_brightness);
357         if (error) {
358                 pr_err("%s:Setting power up brightness failed %d\n",
359                        __func__, error);
360                 error = -ENODEV;
361                 goto err_reg_init_failed;
362         }
363
364         INIT_WORK(&led_data->wq, lp8550_brightness_work);
365
366         error = led_classdev_register((struct device *) &client->dev,
367                                 &led_data->led_dev);
368         if (error < 0) {
369                 pr_err("%s: Register led class failed: %d\n", __func__, error);
370                 error = -ENODEV;
371                 goto err_class_reg_failed;
372         }
373
374 #ifdef DEBUG
375         error = device_create_file(led_data->led_dev.dev, &dev_attr_registers);
376         if (error < 0) {
377                 pr_err("%s:File device creation failed: %d\n", __func__, error);
378         }
379 #endif
380
381         return 0;
382
383 err_class_reg_failed:
384 err_reg_init_failed:
385         kfree(led_data);
386 err_alloc_data_failed:
387         return error;
388 }
389
390 static int ld_lp8550_remove(struct i2c_client *client)
391 {
392         struct lp8550_data *led_data = i2c_get_clientdata(client);
393
394 #ifdef DEBUG
395         device_remove_file(led_data->led_dev.dev, &dev_attr_registers);
396 #endif
397         led_classdev_unregister(&led_data->led_dev);
398         kfree(led_data);
399         return 0;
400 }
401
402 static const struct i2c_device_id lp8550_id[] = {
403         {LD_LP8550_NAME, 0},
404         {}
405 };
406
407 static struct i2c_driver ld_lp8550_i2c_driver = {
408         .probe = ld_lp8550_probe,
409         .remove = ld_lp8550_remove,
410         .id_table = lp8550_id,
411         .driver = {
412                    .name = LD_LP8550_NAME,
413                    .owner = THIS_MODULE,
414         },
415 };
416
417 static int __init ld_lp8550_init(void)
418 {
419         return i2c_add_driver(&ld_lp8550_i2c_driver);
420 }
421
422 static void __exit ld_lp8550_exit(void)
423 {
424         i2c_del_driver(&ld_lp8550_i2c_driver);
425
426 }
427
428 module_init(ld_lp8550_init);
429 module_exit(ld_lp8550_exit);
430
431 MODULE_DESCRIPTION("Lighting driver for LP8550");
432 MODULE_AUTHOR("Dan Murphy D.Murphy@Motorola.com");
433 MODULE_LICENSE("GPL");