Linux-libre 3.6.4-gnu1
[librecmc/linux-libre.git] / drivers / leds / leds-lm3556.c
1 /*
2  * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
3  * Copyright (C) 2012 Texas Instruments
4  *
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.
8  *
9  * Please refer Documentation/leds/leds-lm3556.txt file.
10  */
11 #include <linux/module.h>
12 #include <linux/delay.h>
13 #include <linux/i2c.h>
14 #include <linux/leds.h>
15 #include <linux/slab.h>
16 #include <linux/platform_device.h>
17 #include <linux/fs.h>
18 #include <linux/regmap.h>
19 #include <linux/platform_data/leds-lm3556.h>
20
21 #define REG_FILT_TIME                   (0x0)
22 #define REG_IVFM_MODE                   (0x1)
23 #define REG_NTC                         (0x2)
24 #define REG_INDIC_TIME                  (0x3)
25 #define REG_INDIC_BLINK                 (0x4)
26 #define REG_INDIC_PERIOD                (0x5)
27 #define REG_TORCH_TIME                  (0x6)
28 #define REG_CONF                        (0x7)
29 #define REG_FLASH                       (0x8)
30 #define REG_I_CTRL                      (0x9)
31 #define REG_ENABLE                      (0xA)
32 #define REG_FLAG                        (0xB)
33 #define REG_MAX                         (0xB)
34
35 #define IVFM_FILTER_TIME_SHIFT          (3)
36 #define UVLO_EN_SHIFT                   (7)
37 #define HYSTERSIS_SHIFT                 (5)
38 #define IVM_D_TH_SHIFT                  (2)
39 #define IVFM_ADJ_MODE_SHIFT             (0)
40 #define NTC_EVENT_LVL_SHIFT             (5)
41 #define NTC_TRIP_TH_SHIFT               (2)
42 #define NTC_BIAS_I_LVL_SHIFT            (0)
43 #define INDIC_RAMP_UP_TIME_SHIFT        (3)
44 #define INDIC_RAMP_DN_TIME_SHIFT        (0)
45 #define INDIC_N_BLANK_SHIFT             (4)
46 #define INDIC_PULSE_TIME_SHIFT          (0)
47 #define INDIC_N_PERIOD_SHIFT            (0)
48 #define TORCH_RAMP_UP_TIME_SHIFT        (3)
49 #define TORCH_RAMP_DN_TIME_SHIFT        (0)
50 #define STROBE_USUAGE_SHIFT             (7)
51 #define STROBE_PIN_POLARITY_SHIFT       (6)
52 #define TORCH_PIN_POLARITY_SHIFT        (5)
53 #define TX_PIN_POLARITY_SHIFT           (4)
54 #define TX_EVENT_LVL_SHIFT              (3)
55 #define IVFM_EN_SHIFT                   (2)
56 #define NTC_MODE_SHIFT                  (1)
57 #define INDIC_MODE_SHIFT                (0)
58 #define INDUCTOR_I_LIMIT_SHIFT          (6)
59 #define FLASH_RAMP_TIME_SHIFT           (3)
60 #define FLASH_TOUT_TIME_SHIFT           (0)
61 #define TORCH_I_SHIFT                   (4)
62 #define FLASH_I_SHIFT                   (0)
63 #define NTC_EN_SHIFT                    (7)
64 #define TX_PIN_EN_SHIFT                 (6)
65 #define STROBE_PIN_EN_SHIFT             (5)
66 #define TORCH_PIN_EN_SHIFT              (4)
67 #define PRECHG_MODE_EN_SHIFT            (3)
68 #define PASS_MODE_ONLY_EN_SHIFT         (2)
69 #define MODE_BITS_SHIFT                 (0)
70
71 #define IVFM_FILTER_TIME_MASK           (0x3)
72 #define UVLO_EN_MASK                    (0x1)
73 #define HYSTERSIS_MASK                  (0x3)
74 #define IVM_D_TH_MASK                   (0x7)
75 #define IVFM_ADJ_MODE_MASK              (0x3)
76 #define NTC_EVENT_LVL_MASK              (0x1)
77 #define NTC_TRIP_TH_MASK                (0x7)
78 #define NTC_BIAS_I_LVL_MASK             (0x3)
79 #define INDIC_RAMP_UP_TIME_MASK         (0x7)
80 #define INDIC_RAMP_DN_TIME_MASK         (0x7)
81 #define INDIC_N_BLANK_MASK              (0x7)
82 #define INDIC_PULSE_TIME_MASK           (0x7)
83 #define INDIC_N_PERIOD_MASK             (0x7)
84 #define TORCH_RAMP_UP_TIME_MASK         (0x7)
85 #define TORCH_RAMP_DN_TIME_MASK         (0x7)
86 #define STROBE_USUAGE_MASK              (0x1)
87 #define STROBE_PIN_POLARITY_MASK        (0x1)
88 #define TORCH_PIN_POLARITY_MASK         (0x1)
89 #define TX_PIN_POLARITY_MASK            (0x1)
90 #define TX_EVENT_LVL_MASK               (0x1)
91 #define IVFM_EN_MASK                    (0x1)
92 #define NTC_MODE_MASK                   (0x1)
93 #define INDIC_MODE_MASK                 (0x1)
94 #define INDUCTOR_I_LIMIT_MASK           (0x3)
95 #define FLASH_RAMP_TIME_MASK            (0x7)
96 #define FLASH_TOUT_TIME_MASK            (0x7)
97 #define TORCH_I_MASK                    (0x7)
98 #define FLASH_I_MASK                    (0xF)
99 #define NTC_EN_MASK                     (0x1)
100 #define TX_PIN_EN_MASK                  (0x1)
101 #define STROBE_PIN_EN_MASK              (0x1)
102 #define TORCH_PIN_EN_MASK               (0x1)
103 #define PRECHG_MODE_EN_MASK             (0x1)
104 #define PASS_MODE_ONLY_EN_MASK          (0x1)
105 #define MODE_BITS_MASK                  (0x13)
106 #define EX_PIN_CONTROL_MASK             (0xF1)
107 #define EX_PIN_ENABLE_MASK              (0x70)
108
109 enum lm3556_indic_pulse_time {
110         PULSE_TIME_0_MS = 0,
111         PULSE_TIME_32_MS,
112         PULSE_TIME_64_MS,
113         PULSE_TIME_92_MS,
114         PULSE_TIME_128_MS,
115         PULSE_TIME_160_MS,
116         PULSE_TIME_196_MS,
117         PULSE_TIME_224_MS,
118         PULSE_TIME_256_MS,
119         PULSE_TIME_288_MS,
120         PULSE_TIME_320_MS,
121         PULSE_TIME_352_MS,
122         PULSE_TIME_384_MS,
123         PULSE_TIME_416_MS,
124         PULSE_TIME_448_MS,
125         PULSE_TIME_480_MS,
126 };
127
128 enum lm3556_indic_n_blank {
129         INDIC_N_BLANK_0 = 0,
130         INDIC_N_BLANK_1,
131         INDIC_N_BLANK_2,
132         INDIC_N_BLANK_3,
133         INDIC_N_BLANK_4,
134         INDIC_N_BLANK_5,
135         INDIC_N_BLANK_6,
136         INDIC_N_BLANK_7,
137         INDIC_N_BLANK_8,
138         INDIC_N_BLANK_9,
139         INDIC_N_BLANK_10,
140         INDIC_N_BLANK_11,
141         INDIC_N_BLANK_12,
142         INDIC_N_BLANK_13,
143         INDIC_N_BLANK_14,
144         INDIC_N_BLANK_15,
145 };
146
147 enum lm3556_indic_period {
148         INDIC_PERIOD_0 = 0,
149         INDIC_PERIOD_1,
150         INDIC_PERIOD_2,
151         INDIC_PERIOD_3,
152         INDIC_PERIOD_4,
153         INDIC_PERIOD_5,
154         INDIC_PERIOD_6,
155         INDIC_PERIOD_7,
156 };
157
158 enum lm3556_mode {
159         MODES_STASNDBY = 0,
160         MODES_INDIC,
161         MODES_TORCH,
162         MODES_FLASH
163 };
164
165 #define INDIC_PATTERN_SIZE 4
166
167 struct indicator {
168         u8 blinking;
169         u8 period_cnt;
170 };
171
172 struct lm3556_chip_data {
173         struct device *dev;
174
175         struct led_classdev cdev_flash;
176         struct led_classdev cdev_torch;
177         struct led_classdev cdev_indicator;
178
179         struct lm3556_platform_data *pdata;
180         struct regmap *regmap;
181         struct mutex lock;
182
183         unsigned int last_flag;
184 };
185
186 /* indicator pattern */
187 static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
188         [0] = {(INDIC_N_BLANK_1 << INDIC_N_BLANK_SHIFT)
189                | PULSE_TIME_32_MS, INDIC_PERIOD_1},
190         [1] = {(INDIC_N_BLANK_15 << INDIC_N_BLANK_SHIFT)
191                | PULSE_TIME_32_MS, INDIC_PERIOD_2},
192         [2] = {(INDIC_N_BLANK_10 << INDIC_N_BLANK_SHIFT)
193                | PULSE_TIME_32_MS, INDIC_PERIOD_4},
194         [3] = {(INDIC_N_BLANK_5 << INDIC_N_BLANK_SHIFT)
195                | PULSE_TIME_32_MS, INDIC_PERIOD_7},
196 };
197
198 /* chip initialize */
199 static int __devinit lm3556_chip_init(struct lm3556_chip_data *chip)
200 {
201         unsigned int reg_val;
202         int ret;
203         struct lm3556_platform_data *pdata = chip->pdata;
204
205         /* set config register */
206         ret = regmap_read(chip->regmap, REG_CONF, &reg_val);
207         if (ret < 0) {
208                 dev_err(chip->dev, "Failed to read REG_CONF Register\n");
209                 goto out;
210         }
211
212         reg_val &= (~EX_PIN_CONTROL_MASK);
213         reg_val |= ((pdata->torch_pin_polarity & 0x01)
214                     << TORCH_PIN_POLARITY_SHIFT);
215         reg_val |= ((pdata->strobe_usuage & 0x01) << STROBE_USUAGE_SHIFT);
216         reg_val |= ((pdata->strobe_pin_polarity & 0x01)
217                     << STROBE_PIN_POLARITY_SHIFT);
218         reg_val |= ((pdata->tx_pin_polarity & 0x01) << TX_PIN_POLARITY_SHIFT);
219         reg_val |= ((pdata->indicator_mode & 0x01) << INDIC_MODE_SHIFT);
220
221         ret = regmap_write(chip->regmap, REG_CONF, reg_val);
222         if (ret < 0) {
223                 dev_err(chip->dev, "Failed to write REG_CONF Regisgter\n");
224                 goto out;
225         }
226
227         /* set enable register */
228         ret = regmap_read(chip->regmap, REG_ENABLE, &reg_val);
229         if (ret < 0) {
230                 dev_err(chip->dev, "Failed to read REG_ENABLE Register\n");
231                 goto out;
232         }
233
234         reg_val &= (~EX_PIN_ENABLE_MASK);
235         reg_val |= ((pdata->torch_pin_en & 0x01) << TORCH_PIN_EN_SHIFT);
236         reg_val |= ((pdata->strobe_pin_en & 0x01) << STROBE_PIN_EN_SHIFT);
237         reg_val |= ((pdata->tx_pin_en & 0x01) << TX_PIN_EN_SHIFT);
238
239         ret = regmap_write(chip->regmap, REG_ENABLE, reg_val);
240         if (ret < 0) {
241                 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
242                 goto out;
243         }
244
245 out:
246         return ret;
247 }
248
249 /* chip control */
250 static int lm3556_control(struct lm3556_chip_data *chip,
251                           u8 brightness, enum lm3556_mode opmode)
252 {
253         int ret;
254         struct lm3556_platform_data *pdata = chip->pdata;
255
256         ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
257         if (ret < 0) {
258                 dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
259                 goto out;
260         }
261
262         if (chip->last_flag)
263                 dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
264
265         /* brightness 0 means off-state */
266         if (!brightness)
267                 opmode = MODES_STASNDBY;
268
269         switch (opmode) {
270         case MODES_TORCH:
271                 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
272                                          TORCH_I_MASK << TORCH_I_SHIFT,
273                                          (brightness - 1) << TORCH_I_SHIFT);
274
275                 if (pdata->torch_pin_en)
276                         opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
277                 break;
278
279         case MODES_FLASH:
280                 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
281                                          FLASH_I_MASK << FLASH_I_SHIFT,
282                                          (brightness - 1) << FLASH_I_SHIFT);
283                 break;
284
285         case MODES_INDIC:
286                 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
287                                          TORCH_I_MASK << TORCH_I_SHIFT,
288                                          (brightness - 1) << TORCH_I_SHIFT);
289                 break;
290
291         case MODES_STASNDBY:
292                 if (pdata->torch_pin_en)
293                         opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
294                 break;
295
296         default:
297                 return ret;
298         }
299         if (ret < 0) {
300                 dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
301                 goto out;
302         }
303         ret = regmap_update_bits(chip->regmap, REG_ENABLE,
304                                  MODE_BITS_MASK << MODE_BITS_SHIFT,
305                                  opmode << MODE_BITS_SHIFT);
306
307 out:
308         return ret;
309 }
310
311 /* torch */
312 static void lm3556_torch_brightness_set(struct led_classdev *cdev,
313                                         enum led_brightness brightness)
314 {
315         struct lm3556_chip_data *chip =
316             container_of(cdev, struct lm3556_chip_data, cdev_torch);
317
318         mutex_lock(&chip->lock);
319         lm3556_control(chip, brightness, MODES_TORCH);
320         mutex_unlock(&chip->lock);
321 }
322
323 /* flash */
324 static void lm3556_strobe_brightness_set(struct led_classdev *cdev,
325                                          enum led_brightness brightness)
326 {
327         struct lm3556_chip_data *chip =
328             container_of(cdev, struct lm3556_chip_data, cdev_flash);
329
330         mutex_lock(&chip->lock);
331         lm3556_control(chip, brightness, MODES_FLASH);
332         mutex_unlock(&chip->lock);
333 }
334
335 /* indicator */
336 static void lm3556_indicator_brightness_set(struct led_classdev *cdev,
337                                             enum led_brightness brightness)
338 {
339         struct lm3556_chip_data *chip =
340             container_of(cdev, struct lm3556_chip_data, cdev_indicator);
341
342         mutex_lock(&chip->lock);
343         lm3556_control(chip, brightness, MODES_INDIC);
344         mutex_unlock(&chip->lock);
345 }
346
347 /* indicator pattern */
348 static ssize_t lm3556_indicator_pattern_store(struct device *dev,
349                                               struct device_attribute *devAttr,
350                                               const char *buf, size_t size)
351 {
352         ssize_t ret;
353         struct led_classdev *led_cdev = dev_get_drvdata(dev);
354         struct lm3556_chip_data *chip =
355             container_of(led_cdev, struct lm3556_chip_data, cdev_indicator);
356         unsigned int state;
357
358         ret = kstrtouint(buf, 10, &state);
359         if (ret)
360                 goto out;
361         if (state > INDIC_PATTERN_SIZE - 1)
362                 state = INDIC_PATTERN_SIZE - 1;
363
364         ret = regmap_write(chip->regmap, REG_INDIC_BLINK,
365                            indicator_pattern[state].blinking);
366         if (ret < 0) {
367                 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
368                 goto out;
369         }
370
371         ret = regmap_write(chip->regmap, REG_INDIC_PERIOD,
372                            indicator_pattern[state].period_cnt);
373         if (ret < 0) {
374                 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
375                 goto out;
376         }
377
378         return size;
379 out:
380         dev_err(chip->dev, "Indicator pattern doesn't saved\n");
381         return size;
382 }
383
384 static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
385
386 static const struct regmap_config lm3556_regmap = {
387         .reg_bits = 8,
388         .val_bits = 8,
389         .max_register = REG_MAX,
390 };
391
392 /* module initialize */
393 static int __devinit lm3556_probe(struct i2c_client *client,
394                                   const struct i2c_device_id *id)
395 {
396         struct lm3556_platform_data *pdata = client->dev.platform_data;
397         struct lm3556_chip_data *chip;
398
399         int err;
400
401         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
402                 dev_err(&client->dev, "i2c functionality check fail.\n");
403                 return -EOPNOTSUPP;
404         }
405
406         if (pdata == NULL) {
407                 dev_err(&client->dev, "Needs Platform Data.\n");
408                 return -ENODATA;
409         }
410
411         chip =
412             devm_kzalloc(&client->dev, sizeof(struct lm3556_chip_data),
413                          GFP_KERNEL);
414         if (!chip)
415                 return -ENOMEM;
416
417         chip->dev = &client->dev;
418         chip->pdata = pdata;
419
420         chip->regmap = devm_regmap_init_i2c(client, &lm3556_regmap);
421         if (IS_ERR(chip->regmap)) {
422                 err = PTR_ERR(chip->regmap);
423                 dev_err(&client->dev, "Failed to allocate register map: %d\n",
424                         err);
425                 return err;
426         }
427
428         mutex_init(&chip->lock);
429         i2c_set_clientdata(client, chip);
430
431         err = lm3556_chip_init(chip);
432         if (err < 0)
433                 goto err_out;
434
435         /* flash */
436         chip->cdev_flash.name = "flash";
437         chip->cdev_flash.max_brightness = 16;
438         chip->cdev_flash.brightness_set = lm3556_strobe_brightness_set;
439         err = led_classdev_register((struct device *)
440                                     &client->dev, &chip->cdev_flash);
441         if (err < 0)
442                 goto err_out;
443         /* torch */
444         chip->cdev_torch.name = "torch";
445         chip->cdev_torch.max_brightness = 8;
446         chip->cdev_torch.brightness_set = lm3556_torch_brightness_set;
447         err = led_classdev_register((struct device *)
448                                     &client->dev, &chip->cdev_torch);
449         if (err < 0)
450                 goto err_create_torch_file;
451         /* indicator */
452         chip->cdev_indicator.name = "indicator";
453         chip->cdev_indicator.max_brightness = 8;
454         chip->cdev_indicator.brightness_set = lm3556_indicator_brightness_set;
455         err = led_classdev_register((struct device *)
456                                     &client->dev, &chip->cdev_indicator);
457         if (err < 0)
458                 goto err_create_indicator_file;
459
460         err = device_create_file(chip->cdev_indicator.dev, &dev_attr_pattern);
461         if (err < 0)
462                 goto err_create_pattern_file;
463
464         dev_info(&client->dev, "LM3556 is initialized\n");
465         return 0;
466
467 err_create_pattern_file:
468         led_classdev_unregister(&chip->cdev_indicator);
469 err_create_indicator_file:
470         led_classdev_unregister(&chip->cdev_torch);
471 err_create_torch_file:
472         led_classdev_unregister(&chip->cdev_flash);
473 err_out:
474         return err;
475 }
476
477 static int __devexit lm3556_remove(struct i2c_client *client)
478 {
479         struct lm3556_chip_data *chip = i2c_get_clientdata(client);
480
481         device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
482         led_classdev_unregister(&chip->cdev_indicator);
483         led_classdev_unregister(&chip->cdev_torch);
484         led_classdev_unregister(&chip->cdev_flash);
485         regmap_write(chip->regmap, REG_ENABLE, 0);
486         return 0;
487 }
488
489 static const struct i2c_device_id lm3556_id[] = {
490         {LM3556_NAME, 0},
491         {}
492 };
493
494 MODULE_DEVICE_TABLE(i2c, lm3556_id);
495
496 static struct i2c_driver lm3556_i2c_driver = {
497         .driver = {
498                    .name = LM3556_NAME,
499                    .owner = THIS_MODULE,
500                    .pm = NULL,
501                    },
502         .probe = lm3556_probe,
503         .remove = __devexit_p(lm3556_remove),
504         .id_table = lm3556_id,
505 };
506
507 module_i2c_driver(lm3556_i2c_driver);
508
509 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3556");
510 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
511 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
512 MODULE_LICENSE("GPL v2");