temp revert rk change
[firefly-linux-kernel-4.4.55.git] / drivers / leds / led-lm3559.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/slab.h>
24 #include <linux/types.h>
25 #include <linux/err.h>
26
27 #include <linux/led-lm3559.h>
28
29 /* #define DEBUG */
30
31 #define LM3559_ALLOWED_R_BYTES   1
32 #define LM3559_ALLOWED_W_BYTES   2
33 #define LM3559_MAX_RW_RETRIES    5
34 #define LM3559_I2C_RETRY_DELAY  10
35 #define LM3559_TORCH_STEP       64
36 #define LM3559_STROBE_STEP      16
37 #define LM3559_PRIVACY_STEP     32
38 #define LM3559_RGB_STEP         32
39
40 #define LM3559_ENABLE_REG       0x10
41 #define LM3559_PRIVACY_REG      0x11
42 #define LM3559_MSG_IND_REG      0x12
43 #define LM3559_MSG_BLINK_REG    0x13
44 #define LM3559_PWM_REG          0x14
45 #define LM3559_GPIO_REG         0x20
46 #define LM3559_VLED_MON_REG     0x30
47 #define LM3559_ADC_DELAY_REG    0x31
48 #define LM3559_VIN_MONITOR      0x80
49 #define LM3559_LAST_FLASH       0x81
50 #define LM3559_TORCH_BRIGHTNESS 0xA0
51 #define LM3559_FLASH_BRIGHTNESS 0xB0
52 #define LM3559_FLASH_DURATION   0xC0
53 #define LM3559_FLAG_REG         0xD0
54 #define LM3559_CONFIG_REG_1     0xE0
55 #define LM3559_CONFIG_REG_2     0xF0
56
57
58 #define LED_FAULT               0x04
59 #define THERMAL_SHUTDOWN        0x02
60 #define TX1_INTERRUPT_FAULT     0x08
61 #define THERMAL_MONITOR_FAULT   0x20
62 #define VOLTAGE_MONITOR_FAULT   0x80
63
64 struct lm3559_data {
65         struct i2c_client *client;
66         struct lm3559_platform_data *pdata;
67         struct led_classdev flash_dev;
68         struct led_classdev torch_dev;
69 };
70
71 #ifdef DEBUG
72 struct lm3559_reg {
73         const char *name;
74         uint8_t reg;
75 } lm3559_regs[] = {
76         { "ENABLE",             LM3559_ENABLE_REG},
77         { "PRIVACY",            LM3559_PRIVACY_REG},
78         { "MSG_IND",            LM3559_MSG_IND_REG},
79         { "MSG_BLINK",          LM3559_MSG_BLINK_REG},
80         { "PRIVACY_PWM",        LM3559_PWM_REG},
81         { "GPIO",               LM3559_GPIO_REG},
82         { "VLED_MON",           LM3559_VLED_MON_REG},
83         { "ADC_DELAY",          LM3559_ADC_DELAY_REG},
84         { "VIN_MONITOR",        LM3559_VIN_MONITOR},
85         { "LAST_FLASH",         LM3559_LAST_FLASH},
86         { "TORCH_BRIGHTNESS",   LM3559_TORCH_BRIGHTNESS},
87         { "FLASH_BRIGHTNESS",   LM3559_FLASH_BRIGHTNESS},
88         { "FLASH_DURATION",     LM3559_FLASH_DURATION},
89         { "FLAG",               LM3559_FLAG_REG},
90         { "CONFIG_REG_1",       LM3559_CONFIG_REG_1},
91         { "CONFIG_REG_2",       LM3559_CONFIG_REG_2},
92 };
93 #endif
94
95 static uint32_t lm3559_debug;
96 module_param_named(flash_debug, lm3559_debug, uint, 0664);
97
98 static int lm3559_read_reg(struct lm3559_data *torch_data,
99                                 uint8_t reg, uint8_t* val)
100 {
101         int err = -1;
102         int i = 0;
103         uint8_t dest_buffer;
104
105         if (!val) {
106                 pr_err("%s: invalid value pointer\n", __func__);
107                 return -EINVAL;
108         }
109         /* If I2C client doesn't exist */
110         if (torch_data->client == NULL) {
111                 pr_err("%s: null i2c client\n", __func__);
112                 return -EUNATCH;
113         }
114
115         do {
116                 dest_buffer = reg;
117                 err = i2c_master_send(torch_data->client, &dest_buffer,
118                         LM3559_ALLOWED_R_BYTES);
119                 if (err == LM3559_ALLOWED_R_BYTES)
120                         err = i2c_master_recv(torch_data->client, val,
121                                 LM3559_ALLOWED_R_BYTES);
122                 if (err != LM3559_ALLOWED_R_BYTES)
123                         msleep_interruptible(LM3559_I2C_RETRY_DELAY);
124         } while ((err != LM3559_ALLOWED_R_BYTES) &&
125                 ((++i) < LM3559_MAX_RW_RETRIES));
126
127         if (err != LM3559_ALLOWED_R_BYTES)
128                 return -EINVAL;
129
130         return 0;
131 }
132
133 static int lm3559_write_reg(struct lm3559_data *torch_data,
134                                 uint8_t reg, uint8_t val)
135 {
136         int bytes;
137         int i = 0;
138         uint8_t buf[LM3559_ALLOWED_W_BYTES] = { reg, val };
139
140         /* If I2C client doesn't exist */
141         if (torch_data->client == NULL) {
142                 pr_err("%s: null i2c client\n", __func__);
143                 return -EUNATCH;
144         }
145
146         do {
147                 bytes = i2c_master_send(torch_data->client, buf,
148                         LM3559_ALLOWED_W_BYTES);
149
150                 if (bytes != LM3559_ALLOWED_W_BYTES)
151                         msleep_interruptible(LM3559_I2C_RETRY_DELAY);
152         } while ((bytes != LM3559_ALLOWED_W_BYTES) &&
153                 ((++i) < LM3559_MAX_RW_RETRIES));
154
155         if (bytes != LM3559_ALLOWED_W_BYTES) {
156                 pr_err("%s: i2c_master_send error\n", __func__);
157                 return -EINVAL;
158         }
159
160         return 0;
161 }
162
163 #ifdef DEBUG
164 static ssize_t ld_lm3559_registers_show(struct device *dev,
165                               struct device_attribute *attr, char *buf)
166 {
167         struct i2c_client *client = container_of(dev->parent, struct i2c_client,
168                                                  dev);
169         struct lm3559_data *flash_data = i2c_get_clientdata(client);
170         unsigned i, n, reg_count;
171         uint8_t value = 0;
172
173         reg_count = sizeof(lm3559_regs) / sizeof(lm3559_regs[0]);
174         for (i = 0, n = 0; i < reg_count; i++) {
175                 lm3559_read_reg(flash_data, lm3559_regs[i].reg, &value);
176                 n += scnprintf(buf + n, PAGE_SIZE - n,
177                                "%-20s = 0x%02X\n",
178                                lm3559_regs[i].name,
179                                value);
180         }
181
182         return n;
183 }
184
185 static ssize_t ld_lm3559_registers_store(struct device *dev,
186                                struct device_attribute *attr,
187                                const char *buf, size_t count)
188 {
189         struct i2c_client *client = container_of(dev->parent,
190                 struct i2c_client, dev);
191         struct lm3559_data *flash_data = i2c_get_clientdata(client);
192         unsigned i, reg_count, value;
193         int error;
194         char name[30];
195
196         if (count >= 30) {
197                 pr_err("%s:input too long\n", __func__);
198                 return -1;
199         }
200
201         if (sscanf(buf, "%s %x", name, &value) != 2) {
202                 pr_err("%s:unable to parse input\n", __func__);
203                 return -1;
204         }
205
206         reg_count = sizeof(lm3559_regs) / sizeof(lm3559_regs[0]);
207         for (i = 0; i < reg_count; i++) {
208                 if (!strcmp(name, lm3559_regs[i].name)) {
209                         error = lm3559_write_reg(flash_data,
210                                 lm3559_regs[i].reg,
211                                 value);
212                         if (error) {
213                                 pr_err("%s:Failed to write register %s\n",
214                                         __func__, name);
215                                 return -1;
216                         }
217                         return count;
218                 }
219         }
220
221         pr_err("%s:no such register %s\n", __func__, name);
222         return -1;
223 }
224 static DEVICE_ATTR(registers, 0644, ld_lm3559_registers_show,
225                 ld_lm3559_registers_store);
226 #endif
227
228 int lm3559_init_registers(struct lm3559_data *torch_data)
229 {
230         if (lm3559_write_reg(torch_data, LM3559_TORCH_BRIGHTNESS, 0) ||
231                 lm3559_write_reg(torch_data, LM3559_ADC_DELAY_REG, 0) ||
232                 lm3559_write_reg(torch_data, LM3559_FLASH_BRIGHTNESS, 0) ||
233                 lm3559_write_reg(torch_data, LM3559_FLASH_DURATION,
234                              torch_data->pdata->flash_duration_def) ||
235                 lm3559_write_reg(torch_data, LM3559_CONFIG_REG_1, 0x6C) ||
236                 lm3559_write_reg(torch_data, LM3559_CONFIG_REG_2, 0) ||
237                 lm3559_write_reg(torch_data, LM3559_VIN_MONITOR,
238                         torch_data->pdata->vin_monitor_def) ||
239                 lm3559_write_reg(torch_data, LM3559_GPIO_REG, 0) ||
240                 lm3559_write_reg(torch_data, LM3559_FLAG_REG, 0) ||
241                 lm3559_write_reg(torch_data, LM3559_PRIVACY_REG, 0x10) ||
242                 lm3559_write_reg(torch_data, LM3559_MSG_IND_REG, 0) ||
243                 lm3559_write_reg(torch_data, LM3559_MSG_BLINK_REG, 0) ||
244                 lm3559_write_reg(torch_data, LM3559_PWM_REG, 0) ||
245                 lm3559_write_reg(torch_data, LM3559_ENABLE_REG, 0)) {
246                 pr_err("%s:Register initialization failed\n", __func__);
247                 return -EIO;
248         }
249         return 0;
250 }
251
252 static int lm3559_check_led_error(struct lm3559_data *torch_data) {
253         int err = 0;
254
255         if (torch_data->pdata->flags & LM3559_FLAG_ERROR_CHECK) {
256
257                 uint8_t err_flags;
258                 err = lm3559_read_reg(torch_data, LM3559_FLAG_REG, &err_flags);
259                 if (err) {
260                         pr_err("%s: Reading the status failed for %i\n",
261                                 __func__, err);
262                         return -EIO;
263                 }
264
265                 if (err_flags & (VOLTAGE_MONITOR_FAULT |
266                                 THERMAL_MONITOR_FAULT |
267                                 LED_FAULT |
268                                 THERMAL_SHUTDOWN)) {
269                         pr_err("%s: Error indicated by the chip 0x%X\n",
270                                 __func__, err_flags);
271                         err = -EIO;
272                 }
273         }
274
275         return err;
276 }
277
278 static int lm3559_flash_prepare(struct lm3559_data *torch_data)
279 {
280         int err = lm3559_check_led_error(torch_data);
281         if (err)
282                 return err;
283
284         if (torch_data->flash_dev.brightness) {
285                 uint8_t strobe_brightness;
286                 uint val = torch_data->flash_dev.brightness - 1;
287                 strobe_brightness = val | (val << 4);
288
289                 err = lm3559_write_reg(torch_data, LM3559_FLASH_BRIGHTNESS,
290                         strobe_brightness);
291                 if (err) {
292                         pr_err("%s: Writing to 0x%X failed %i\n",
293                                 __func__, LM3559_FLASH_BRIGHTNESS, err);
294                         return -EIO;
295                 }
296
297                 err = lm3559_write_reg(torch_data, LM3559_FLASH_DURATION,
298                         torch_data->pdata->flash_duration_def);
299                 if (err) {
300                         pr_err("%s: Writing to 0x%X failed %i\n",
301                                 __func__, LM3559_FLASH_DURATION, err);
302                         return -EIO;
303                 }
304
305                 err = lm3559_write_reg(torch_data, LM3559_VIN_MONITOR,
306                                 torch_data->pdata->vin_monitor_def);
307                 if (err) {
308                         pr_err("%s: Writing to 0x%X failed %i\n",
309                                 __func__, LM3559_VIN_MONITOR, err);
310                         return -EIO;
311                 }
312
313                 /* setup flash for trigger by strobe pin:
314                    enable LED1 and LED2, but do not enable current */
315                 err = lm3559_write_reg(torch_data, LM3559_ENABLE_REG, 0x18);
316
317         } else {
318                 /* disable LED1 and LED2 and current */
319                 err = lm3559_write_reg(torch_data, LM3559_ENABLE_REG, 0);
320         }
321
322         if (err)
323                 pr_err("%s: Writing to 0x%X failed %i\n",
324                         __func__, LM3559_ENABLE_REG, err);
325
326         return err;
327 }
328
329 static int lm3559_torch_enable(struct lm3559_data *torch_data)
330 {
331         int err = lm3559_check_led_error(torch_data);
332         if (err)
333                 return err;
334
335         if (torch_data->torch_dev.brightness) {
336                 uint8_t torch_brightness;
337                 uint val = (torch_data->torch_dev.brightness - 1) & 0x3F;
338                 torch_brightness = val | (val << 3);
339
340                 err = lm3559_write_reg(torch_data, LM3559_TORCH_BRIGHTNESS,
341                         torch_brightness);
342                 if (err) {
343                         pr_err("%s: Writing to 0x%X failed %i\n",
344                                 __func__, LM3559_TORCH_BRIGHTNESS, err);
345                         return -EIO;
346                 }
347
348                 err = lm3559_write_reg(torch_data, LM3559_VIN_MONITOR,
349                                         torch_data->pdata->vin_monitor_def);
350                 if (err) {
351                         pr_err("%s: Writing to 0x%X failed %i\n",
352                                 __func__, LM3559_VIN_MONITOR, err);
353                         return -EIO;
354                 }
355
356                 /* enable LED1 and LED2, enable current */
357                 err = lm3559_write_reg(torch_data, LM3559_ENABLE_REG, 0x1A);
358
359         } else {
360                 /* disable LED1 and LED2 and current */
361                 err = lm3559_write_reg(torch_data, LM3559_ENABLE_REG, 0);
362         }
363
364         return err;
365 }
366
367 static void lm3559_flash_brightness_set(struct led_classdev *led_cdev,
368                                         enum led_brightness value)
369 {
370         struct lm3559_data *torch_data =
371             container_of(led_cdev, struct lm3559_data, flash_dev);
372         lm3559_flash_prepare(torch_data);
373 }
374
375 static void lm3559_torch_brightness_set(struct led_classdev *led_cdev,
376                                         enum led_brightness value)
377 {
378         struct lm3559_data *torch_data =
379             container_of(led_cdev, struct lm3559_data, torch_dev);
380         lm3559_torch_enable(torch_data);
381 }
382
383 static int lm3559_remove(struct i2c_client *client)
384 {
385         struct lm3559_data *torch_data = i2c_get_clientdata(client);
386
387         if (torch_data) {
388
389                 if (!IS_ERR_OR_NULL(torch_data->torch_dev.dev)) {
390 #ifdef DEBUG
391                         device_remove_file(torch_data->torch_dev.dev,
392                                 &dev_attr_registers);
393 #endif
394                         led_classdev_unregister(&torch_data->torch_dev);
395                 }
396
397                 if (!IS_ERR_OR_NULL(torch_data->flash_dev.dev)) {
398 #ifdef DEBUG
399                         device_remove_file(torch_data->flash_dev.dev,
400                                 &dev_attr_registers);
401 #endif
402                         led_classdev_unregister(&torch_data->flash_dev);
403                 }
404
405                 kfree(torch_data);
406         }
407         return 0;
408 }
409
410 static int lm3559_probe(struct i2c_client *client,
411                         const struct i2c_device_id *id)
412 {
413         struct lm3559_platform_data *pdata = client->dev.platform_data;
414         struct lm3559_data *torch_data;
415         int err = -1;
416
417         if (pdata == NULL) {
418                 dev_err(&client->dev, "platform data is NULL. exiting.\n");
419                 return -ENODEV;
420         }
421
422         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
423                 dev_err(&client->dev, "client not i2c capable\n");
424                 return -ENODEV;
425         }
426
427         torch_data = kzalloc(sizeof(struct lm3559_data), GFP_KERNEL);
428         if (torch_data == NULL) {
429                 dev_err(&client->dev, "kzalloc failed\n");
430                 return -ENOMEM;
431         }
432
433         torch_data->client = client;
434         torch_data->pdata = pdata;
435
436         i2c_set_clientdata(client, torch_data);
437
438         err = lm3559_init_registers(torch_data);
439         if (err < 0)
440                 goto error;
441
442         torch_data->flash_dev.name = "flash";
443         torch_data->flash_dev.brightness_set = lm3559_flash_brightness_set;
444         torch_data->flash_dev.brightness = LED_OFF;
445         torch_data->flash_dev.max_brightness = LED_FULL;
446         err = led_classdev_register((struct device *)
447                 &client->dev, &torch_data->flash_dev);
448         if (err < 0) {
449                 pr_err("%s: Register flash led class failed: %d\n",
450                         __func__, err);
451                 goto error;
452         }
453
454 #ifdef DEBUG
455         err = device_create_file(torch_data->flash_dev.dev,
456                 &dev_attr_registers);
457         if (err < 0)
458                 pr_err("%s:File device creation failed: %d\n", __func__, err);
459 #endif
460
461         torch_data->torch_dev.name = "torch";
462         torch_data->torch_dev.brightness_set = lm3559_torch_brightness_set;
463         torch_data->torch_dev.brightness = LED_OFF;
464         torch_data->torch_dev.max_brightness = LED_FULL;
465         err = led_classdev_register((struct device *)
466                 &client->dev, &torch_data->torch_dev);
467         if (err < 0) {
468                 pr_err("%s: Register torch led class failed: %d\n",
469                         __func__, err);
470                 goto error;
471         }
472
473 #ifdef DEBUG
474         err = device_create_file(torch_data->torch_dev.dev,
475                 &dev_attr_registers);
476         if (err < 0)
477                 pr_err("%s:File device creation failed: %d\n", __func__, err);
478 #endif
479
480         return 0;
481 error:
482         lm3559_remove(client);
483         return err;
484 }
485
486 static const struct i2c_device_id lm3559_id[] = {
487         {LM3559_NAME, 0},
488         {}
489 };
490
491 static struct i2c_driver lm3559_i2c_driver = {
492         .probe = lm3559_probe,
493         .remove = lm3559_remove,
494         .id_table = lm3559_id,
495         .driver = {
496                 .name = LM3559_NAME,
497                 .owner = THIS_MODULE,
498         },
499 };
500
501 static int __init lm3559_init(void)
502 {
503         return i2c_add_driver(&lm3559_i2c_driver);
504 }
505
506 static void lm3559_exit(void)
507 {
508         i2c_del_driver(&lm3559_i2c_driver);
509 }
510
511 module_init(lm3559_init);
512 module_exit(lm3559_exit);
513
514 /****************************************************************************/
515
516 MODULE_DESCRIPTION("Lighting driver for LM3559");
517 MODULE_AUTHOR("MOTOROLA");
518 MODULE_LICENSE("GPL");