leds: Add LM3559 flash driver support
[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
26 #include <linux/led-lm3559.h>
27
28 /*#define DEBUG*/
29
30 #define LM3559_ALLOWED_R_BYTES   1
31 #define LM3559_ALLOWED_W_BYTES   2
32 #define LM3559_MAX_RW_RETRIES    5
33 #define LM3559_I2C_RETRY_DELAY  10
34 #define LM3559_TORCH_STEP       64
35 #define LM3559_STROBE_STEP      24
36 #define LM3559_PRIVACY_STEP     32
37 #define LM3559_RGB_STEP         32
38
39 #define LM3559_ENABLE_REG       0x10
40 #define LM3559_PRIVACY_REG      0x11
41 #define LM3559_MSG_IND_REG      0x12
42 #define LM3559_MSG_BLINK_REG    0x13
43 #define LM3559_PWM_REG          0x14
44 #define LM3559_GPIO_REG         0x20
45 #define LM3559_VLED_MON_REG     0x30
46 #define LM3559_ADC_DELAY_REG    0x31
47 #define LM3559_VIN_MONITOR      0x80
48 #define LM3559_LAST_FLASH       0x81
49 #define LM3559_TORCH_BRIGHTNESS 0xA0
50 #define LM3559_FLASH_BRIGHTNESS 0xB0
51 #define LM3559_FLASH_DURATION   0xC0
52 #define LM3559_FLAG_REG         0xD0
53 #define LM3559_CONFIG_REG_1     0xE0
54 #define LM3559_CONFIG_REG_2     0xF0
55
56
57 #define LED_FAULT               0x04
58 #define THERMAL_SHUTDOWN        0x02
59 #define TX1_INTERRUPT_FAULT     0x08
60 #define THERMAL_MONITOR_FAULT   0x20
61 #define VOLTAGE_MONITOR_FAULT   0x80
62
63 struct lm3559_data {
64         struct i2c_client *client;
65         struct lm3559_platform_data *pdata;
66         struct led_classdev led_dev;
67         struct led_classdev spotlight_dev;
68         struct led_classdev msg_ind_red_class_dev;
69         struct led_classdev msg_ind_green_class_dev;
70         struct led_classdev msg_ind_blue_class_dev;
71         struct mutex enable_reg_lock;
72         struct work_struct wq;
73         int camera_strobe_brightness;
74         int flash_light_brightness;
75         int torch_light_brightness;
76         int privacy_light_brightness;
77         int msg_ind_light_brightness;
78         int blink_val;
79 };
80
81 #ifdef DEBUG
82 struct lm3559_reg {
83         const char *name;
84         uint8_t reg;
85 } lm3559_regs[] = {
86         { "ENABLE",             LM3559_ENABLE_REG},
87         { "PRIVACY",            LM3559_PRIVACY_REG},
88         { "MSG_IND",            LM3559_MSG_IND_REG},
89         { "MSG_BLINK",          LM3559_MSG_BLINK_REG},
90         { "PRIVACY_PWM",        LM3559_PWM_REG},
91         { "GPIO",               LM3559_GPIO_REG},
92         { "VLED_MON",           LM3559_VLED_MON_REG},
93         { "ADC_DELAY",          LM3559_ADC_DELAY_REG},
94         { "VIN_MONITOR",        LM3559_VIN_MONITOR},
95         { "LAST_FLASH",         LM3559_LAST_FLASH},
96         { "TORCH_BRIGHTNESS",   LM3559_TORCH_BRIGHTNESS},
97         { "FLASH_BRIGHTNESS",   LM3559_FLASH_BRIGHTNESS},
98         { "FLASH_DURATION",     LM3559_FLASH_DURATION},
99         { "FLAG",               LM3559_FLAG_REG},
100         { "CONFIG_REG_1",       LM3559_CONFIG_REG_1},
101         { "CONFIG_REG_2",       LM3559_CONFIG_REG_2},
102 };
103 #endif
104
105 static uint32_t lm3559_debug;
106 module_param_named(flash_debug, lm3559_debug, uint, 0664);
107
108 int lm3559_read_reg(struct lm3559_data *torch_data, uint8_t reg, uint8_t * val)
109 {
110         int err = -1;
111         int i = 0;
112         uint8_t dest_buffer;
113
114         if (!val) {
115                 pr_err("%s: invalid value pointer\n", __func__);
116                 return -EINVAL;
117         }
118         /* If I2C client doesn't exist */
119         if (torch_data->client == NULL) {
120                 pr_err("%s: null i2c client\n", __func__);
121                 return -EUNATCH;
122         }
123
124         do {
125                 dest_buffer = reg;
126                 err = i2c_master_send(torch_data->client, &dest_buffer,
127                         LM3559_ALLOWED_R_BYTES);
128                 if (err == LM3559_ALLOWED_R_BYTES)
129                         err = i2c_master_recv(torch_data->client, val,
130                                 LM3559_ALLOWED_R_BYTES);
131                 if (err != LM3559_ALLOWED_R_BYTES)
132                         msleep_interruptible(LM3559_I2C_RETRY_DELAY);
133         } while ((err != LM3559_ALLOWED_R_BYTES) &&
134                 ((++i) < LM3559_MAX_RW_RETRIES));
135
136         if (err != LM3559_ALLOWED_R_BYTES)
137                 return -EINVAL;
138
139         return 0;
140 }
141
142 int lm3559_write_reg(struct lm3559_data *torch_data, uint8_t reg, uint8_t val)
143 {
144         int bytes;
145         int i = 0;
146         uint8_t buf[LM3559_ALLOWED_W_BYTES] = { reg, val };
147
148         /* If I2C client doesn't exist */
149         if (torch_data->client == NULL) {
150                 pr_err("%s: null i2c client\n", __func__);
151                 return -EUNATCH;
152         }
153
154         do {
155                 bytes = i2c_master_send(torch_data->client, buf,
156                         LM3559_ALLOWED_W_BYTES);
157
158                 if (bytes != LM3559_ALLOWED_W_BYTES)
159                         msleep_interruptible(LM3559_I2C_RETRY_DELAY);
160         } while ((bytes != LM3559_ALLOWED_W_BYTES) &&
161                 ((++i) < LM3559_MAX_RW_RETRIES));
162
163         if (bytes != LM3559_ALLOWED_W_BYTES) {
164                 pr_err("%s: i2c_master_send error\n", __func__);
165                 return -EINVAL;
166         }
167
168         return 0;
169 }
170
171 #ifdef DEBUG
172 static ssize_t ld_lm3559_registers_show(struct device *dev,
173                               struct device_attribute *attr, char *buf)
174 {
175         struct i2c_client *client = container_of(dev->parent, struct i2c_client,
176                                                  dev);
177         struct lm3559_data *flash_data = i2c_get_clientdata(client);
178         unsigned i, n, reg_count;
179         uint8_t value = 0;
180
181         reg_count = sizeof(lm3559_regs) / sizeof(lm3559_regs[0]);
182         for (i = 0, n = 0; i < reg_count; i++) {
183                 lm3559_read_reg(flash_data, lm3559_regs[i].reg, &value);
184                 n += scnprintf(buf + n, PAGE_SIZE - n,
185                                "%-20s = 0x%02X\n",
186                                lm3559_regs[i].name,
187                                value);
188         }
189
190         return n;
191 }
192
193 static ssize_t ld_lm3559_registers_store(struct device *dev,
194                                struct device_attribute *attr,
195                                const char *buf, size_t count)
196 {
197         struct i2c_client *client = container_of(dev->parent,
198                 struct i2c_client, dev);
199         struct lm3559_data *flash_data = i2c_get_clientdata(client);
200         unsigned i, reg_count, value;
201         int error;
202         char name[30];
203
204         if (count >= 30) {
205                 pr_err("%s:input too long\n", __func__);
206                 return -1;
207         }
208
209         if (sscanf(buf, "%s %x", name, &value) != 2) {
210                 pr_err("%s:unable to parse input\n", __func__);
211                 return -1;
212         }
213
214         reg_count = sizeof(lm3559_regs) / sizeof(lm3559_regs[0]);
215         for (i = 0; i < reg_count; i++) {
216                 if (!strcmp(name, lm3559_regs[i].name)) {
217                         error = lm3559_write_reg(flash_data,
218                                 lm3559_regs[i].reg,
219                                 value);
220                         if (error) {
221                                 pr_err("%s:Failed to write register %s\n",
222                                         __func__, name);
223                                 return -1;
224                         }
225                         return count;
226                 }
227         }
228
229         pr_err("%s:no such register %s\n", __func__, name);
230         return -1;
231 }
232 static DEVICE_ATTR(registers, 0644, ld_lm3559_registers_show,
233                 ld_lm3559_registers_store);
234 #endif
235
236 int lm3559_init_registers(struct lm3559_data *torch_data)
237 {
238
239         if (lm3559_write_reg(torch_data, LM3559_TORCH_BRIGHTNESS,
240                              torch_data->pdata->torch_brightness_def) ||
241                 lm3559_write_reg(torch_data, LM3559_ADC_DELAY_REG,
242                              torch_data->pdata->adc_delay_reg_def) ||
243                 lm3559_write_reg(torch_data, LM3559_FLASH_BRIGHTNESS,
244                              torch_data->pdata->flash_brightness_def) ||
245                 lm3559_write_reg(torch_data, LM3559_FLASH_DURATION,
246                              torch_data->pdata->flash_duration_def) ||
247                 lm3559_write_reg(torch_data, LM3559_CONFIG_REG_1,
248                              torch_data->pdata->config_reg_1_def) ||
249                 lm3559_write_reg(torch_data, LM3559_CONFIG_REG_2,
250                              torch_data->pdata->config_reg_2_def) ||
251                 lm3559_write_reg(torch_data, LM3559_VIN_MONITOR,
252                              torch_data->pdata->vin_monitor_def) ||
253                 lm3559_write_reg(torch_data, LM3559_GPIO_REG,
254                              torch_data->pdata->gpio_reg_def) ||
255                 lm3559_write_reg(torch_data, LM3559_FLAG_REG,
256                              torch_data->pdata->flag_reg_def) ||
257                 lm3559_write_reg(torch_data, LM3559_PRIVACY_REG,
258                              torch_data->pdata->privacy_reg_def) ||
259                 lm3559_write_reg(torch_data, LM3559_MSG_IND_REG,
260                              torch_data->pdata->msg_ind_reg_def) ||
261                 lm3559_write_reg(torch_data, LM3559_MSG_BLINK_REG,
262                              torch_data->pdata->msg_ind_blink_reg_def) ||
263                 lm3559_write_reg(torch_data, LM3559_PWM_REG,
264                              torch_data->pdata->pwm_reg_def) ||
265                 lm3559_write_reg(torch_data, LM3559_ENABLE_REG,
266                              torch_data->pdata->enable_reg_def)) {
267                 pr_err("%s:Register initialization failed\n", __func__);
268                 return -EIO;
269         }
270         return 0;
271 }
272 static int lm3559_enable_led(struct lm3559_data *torch_data, uint8_t enable_val)
273 {
274         int err = 0;
275         uint8_t val = 0;
276         uint8_t temp_val;
277
278         mutex_lock(&torch_data->enable_reg_lock);
279         err = lm3559_read_reg(torch_data, LM3559_ENABLE_REG,
280                 &val);
281         if (err) {
282                 pr_err("%s: Reading 0x%X failed %i\n",
283                         __func__, LM3559_ENABLE_REG, err);
284                 goto unlock_and_return;
285         }
286
287         temp_val = (val | enable_val);
288         err = lm3559_write_reg(torch_data, LM3559_ENABLE_REG,
289                 temp_val);
290         if (err) {
291                 pr_err("%s: Writing to 0x%X failed %i\n",
292                         __func__, LM3559_ENABLE_REG, err);
293         }
294
295 unlock_and_return:
296         mutex_unlock(&torch_data->enable_reg_lock);
297         return err;
298 }
299
300 static int lm3559_disable_led(struct lm3559_data *torch_data,
301                 uint8_t enable_val)
302 {
303         int err = 0;
304         uint8_t val = 0;
305         uint8_t temp_val;
306
307         mutex_lock(&torch_data->enable_reg_lock);
308         err = lm3559_read_reg(torch_data, LM3559_ENABLE_REG,
309                 &val);
310         if (err) {
311                 pr_err("%s: Reading 0x%X failed %i\n",
312                         __func__, LM3559_ENABLE_REG, err);
313                 goto unlock_and_return;
314         }
315         temp_val = (val & enable_val);
316         err = lm3559_write_reg(torch_data, LM3559_ENABLE_REG,
317                 temp_val);
318         if (err) {
319                 pr_err("%s: Writing to 0x%X failed %i\n",
320                         __func__, LM3559_ENABLE_REG, err);
321         }
322
323 unlock_and_return:
324         mutex_unlock(&torch_data->enable_reg_lock);
325         return err;
326 }
327 static int lm3559_privacy_write(struct lm3559_data *torch_data)
328 {
329         int err = 0;
330         uint8_t privacy_light_val;
331         uint8_t err_flags;
332
333         err = lm3559_read_reg(torch_data, LM3559_FLAG_REG, &err_flags);
334         if (err) {
335                 pr_err("%s: Reading the status failed for %i\n",
336                         __func__, err);
337                 return -EIO;
338         }
339
340         if (torch_data->pdata->flags & LM3559_ERROR_CHECK) {
341                 if (err_flags & (VOLTAGE_MONITOR_FAULT |
342                         THERMAL_MONITOR_FAULT | LED_FAULT |
343                         THERMAL_SHUTDOWN)) {
344                                 pr_err("%s: Error indicated by the chip 0x%X\n",
345                                         __func__, err_flags);
346                                 return err_flags;
347                 }
348         }
349         if (torch_data->privacy_light_brightness) {
350                 privacy_light_val = (torch_data->pdata->privacy_reg_def & 0xf8);
351                 privacy_light_val |= (torch_data->privacy_light_brightness /
352                                 LM3559_PRIVACY_STEP);
353                 err = lm3559_write_reg(torch_data, LM3559_PRIVACY_REG,
354                         privacy_light_val);
355                 if (err) {
356                         pr_err("%s: Writing to 0x%X failed %i\n",
357                                 __func__, LM3559_PRIVACY_REG, err);
358                         return -EIO;
359                 }
360                 err = lm3559_write_reg(torch_data, LM3559_PWM_REG,
361                         torch_data->pdata->pwm_val);
362                 if (err) {
363                         pr_err("%s: Writing to 0x%X failed %i\n",
364                                 __func__, LM3559_PWM_REG, err);
365                         return -EIO;
366                 }
367                 err = lm3559_enable_led(torch_data,
368                         torch_data->pdata->privacy_enable_val);
369         } else {
370                 err = lm3559_disable_led(torch_data, 0xc0);
371         }
372
373         return err;
374 }
375
376 static int lm3559_torch_write(struct lm3559_data *torch_data)
377 {
378         int err = 0;
379         int temp_val;
380         int val = 0;;
381
382         if (torch_data->torch_light_brightness) {
383                 temp_val = torch_data->torch_light_brightness /
384                         LM3559_TORCH_STEP;
385                 val |= temp_val << 3;
386                 val |= temp_val;
387
388                 err = lm3559_write_reg(torch_data, LM3559_TORCH_BRIGHTNESS,
389                         val);
390
391                 if (err) {
392                         pr_err("%s: Writing to 0x%X failed %i\n",
393                                 __func__, LM3559_TORCH_BRIGHTNESS, err);
394                         return -EIO;
395                 }
396
397                 err = lm3559_write_reg(torch_data, LM3559_FLASH_DURATION,
398                         torch_data->pdata->flash_duration_def);
399                 if (err) {
400                         pr_err("%s: Writing to 0x%X failed %i\n",
401                                 __func__, LM3559_FLASH_DURATION, err);
402                         return -EIO;
403                 }
404
405                 err = lm3559_write_reg(torch_data, LM3559_VIN_MONITOR,
406                                         torch_data->pdata->vin_monitor_def);
407                 if (err) {
408                         pr_err("%s: Writing to 0x%X failed %i\n",
409                                 __func__, LM3559_VIN_MONITOR, err);
410                         return -EIO;
411                 }
412
413                 err = lm3559_enable_led(torch_data,
414                         torch_data->pdata->torch_enable_val);
415         } else {
416                 err = lm3559_disable_led(torch_data, 0xc0);
417         }
418
419         return err;
420 }
421
422 static int lm3559_strobe_write(struct lm3559_data *torch_data)
423 {
424         int err;
425         uint8_t err_flags;
426         uint8_t strobe_brightness;
427         int val;
428
429         err = lm3559_read_reg(torch_data, LM3559_FLAG_REG, &err_flags);
430         if (err) {
431                 pr_err("%s: Reading the status failed for %i\n",
432                         __func__, err);
433                 return -EIO;
434         }
435         if (torch_data->pdata->flags & LM3559_ERROR_CHECK) {
436                 if (err_flags & (VOLTAGE_MONITOR_FAULT |
437                         THERMAL_MONITOR_FAULT | LED_FAULT |
438                         THERMAL_SHUTDOWN)) {
439                         pr_err("%s: Error indicated by the chip 0x%X\n",
440                                 __func__, err_flags);
441                         return err_flags;
442                 }
443         }
444         if (torch_data->camera_strobe_brightness) {
445                 val = torch_data->camera_strobe_brightness / LM3559_STROBE_STEP;
446                 strobe_brightness = val << 4;
447                 strobe_brightness |= val ;
448
449                 err = lm3559_write_reg(torch_data, LM3559_FLASH_BRIGHTNESS,
450                         torch_data->camera_strobe_brightness);
451                 if (err) {
452                         pr_err("%s: Writing to 0x%X failed %i\n",
453                                 __func__, LM3559_FLASH_BRIGHTNESS, err);
454                         return -EIO;
455                 }
456
457                 err = lm3559_write_reg(torch_data, LM3559_TORCH_BRIGHTNESS,
458                         torch_data->pdata->torch_brightness_def);
459                 if (err) {
460                         pr_err("%s: Writing to 0x%X failed %i\n",
461                                 __func__, LM3559_TORCH_BRIGHTNESS, err);
462                         return -EIO;
463                 }
464
465                 err = lm3559_write_reg(torch_data, LM3559_FLASH_DURATION,
466                         torch_data->pdata->flash_duration_def);
467                 if (err) {
468                         pr_err("%s: Writing to 0x%X failed %i\n",
469                                 __func__, LM3559_FLASH_DURATION, err);
470                         return -EIO;
471                 }
472
473                 err = lm3559_write_reg(torch_data, LM3559_VIN_MONITOR,
474                                 torch_data->pdata->vin_monitor_def);
475                 if (err) {
476                         pr_err("%s: Writing to 0x%X failed %i\n",
477                                 __func__, LM3559_VIN_MONITOR, err);
478                         return -EIO;
479                 }
480
481                 err = lm3559_enable_led(torch_data,
482                         torch_data->pdata->flash_enable_val);
483         } else {
484                 err = lm3559_disable_led(torch_data, 0xc0);
485         }
486
487         return err;
488 }
489
490 static void lm3559_rgb_work(struct work_struct *work)
491 {
492         int err;
493         uint8_t val = 0;
494         uint8_t temp_val;
495         uint8_t rgb_val;
496
497         struct lm3559_data *msg_ind_data =
498                 container_of(work, struct lm3559_data, wq);
499
500         if (msg_ind_data->msg_ind_light_brightness) {
501                 if (msg_ind_data->blink_val) {
502                         err = lm3559_write_reg(msg_ind_data,
503                                 LM3559_MSG_BLINK_REG,
504                                 msg_ind_data->pdata->msg_ind_blink_val);
505                         if (err) {
506                                 pr_err("%s: Reading 0x%X failed %i\n",
507                                         __func__, LM3559_MSG_BLINK_REG, err);
508                                 return;
509                         }
510                 }
511
512                 rgb_val = msg_ind_data->pdata->msg_ind_val;
513                 rgb_val |= (msg_ind_data->msg_ind_light_brightness /
514                         LM3559_RGB_STEP);
515
516                 err = lm3559_write_reg(msg_ind_data, LM3559_MSG_IND_REG,
517                         rgb_val);
518                 if (err) {
519                         pr_err("%s: Writing reg 0x%X failed %i\n",
520                                 __func__, LM3559_MSG_IND_REG, err);
521                         return;
522                 }
523
524                 if (msg_ind_data->blink_val) {
525                         if (lm3559_debug)
526                                 pr_info("%s: Blink MSG LED\n", __func__);
527                         val = 0x80;
528                 }
529
530                 temp_val = (val | 0x40);
531                 err = lm3559_enable_led(msg_ind_data, temp_val);
532
533         } else {
534                 if (msg_ind_data->blink_val == 0) {
535                         if (lm3559_debug)
536                                 pr_info("%s: Turn off blink MSG LED\n",
537                                         __func__);
538                         val = 0x7f;
539                 } else {
540
541                         val = 0x3f;
542                 }
543                 err = lm3559_disable_led(msg_ind_data, val);
544         }
545 }
546
547 /* This is a dummy interface for the LED class this will clear
548 the error flag register */
549 static void lm3559_brightness_set(struct led_classdev *led_cdev,
550                                   enum led_brightness value)
551 {
552         int err;
553         uint8_t err_flags;
554
555         struct lm3559_data *torch_data =
556             container_of(led_cdev, struct lm3559_data, led_dev);
557
558         err = lm3559_read_reg(torch_data, LM3559_FLAG_REG, &err_flags);
559         if (err) {
560                 pr_err("%s: Reading the status failed for %i\n", __func__,
561                        err);
562                 return;
563         }
564         return;
565 }
566
567 static ssize_t lm3559_strobe_err_show(struct device *dev,
568                                  struct device_attribute *attr, char *buf)
569 {
570         int err;
571         uint8_t err_flags;
572         struct i2c_client *client = container_of(dev->parent,
573                                                  struct i2c_client, dev);
574         struct lm3559_data *torch_data = i2c_get_clientdata(client);
575
576         err = lm3559_read_reg(torch_data, LM3559_FLAG_REG, &err_flags);
577         if (err) {
578                 pr_err("%s: Reading the status failed for %i\n",
579                         __func__, err);
580                 return -EIO;
581         }
582
583         sprintf(buf, "%d\n", (err_flags & TX1_INTERRUPT_FAULT));
584
585         return sizeof(buf);
586 }
587 static DEVICE_ATTR(strobe_err, 0644, lm3559_strobe_err_show, NULL);
588
589 static ssize_t lm3559_torch_show(struct device *dev,
590                                  struct device_attribute *attr, char *buf)
591 {
592         struct i2c_client *client = container_of(dev->parent,
593                                                  struct i2c_client, dev);
594         struct lm3559_data *torch_data = i2c_get_clientdata(client);
595
596         sprintf(buf, "%d\n", torch_data->flash_light_brightness);
597
598         return sizeof(buf);
599 }
600
601
602 static ssize_t lm3559_torch_store(struct device *dev,
603                                   struct device_attribute *attr,
604                                   const char *buf, size_t count)
605 {
606         int err = 0;
607         unsigned long torch_val = LED_OFF;
608
609         struct i2c_client *client = container_of(dev->parent,
610                                                  struct i2c_client, dev);
611         struct lm3559_data *torch_data = i2c_get_clientdata(client);
612
613         err = strict_strtoul(buf, 10, &torch_val);
614         if (err) {
615                 pr_err("%s: Invalid parameter sent\n", __func__);
616                 return -1;
617         }
618
619         torch_data->torch_light_brightness = torch_val;
620         err = lm3559_torch_write(torch_data);
621
622         return err;
623
624 };
625 static DEVICE_ATTR(flash_light, 0644, lm3559_torch_show, lm3559_torch_store);
626
627 static void lm3559_spot_light_brightness_set(struct led_classdev *led_cdev,
628                                   enum led_brightness value)
629 {
630         struct lm3559_data *torch_data =
631             container_of(led_cdev, struct lm3559_data, spotlight_dev);
632
633         torch_data->torch_light_brightness = value;
634         lm3559_torch_write(torch_data);
635 }
636
637 static ssize_t lm3559_strobe_show(struct device *dev,
638                                   struct device_attribute *attr, char *buf)
639 {
640         struct i2c_client *client = container_of(dev->parent,
641                                                  struct i2c_client, dev);
642         struct lm3559_data *torch_data = i2c_get_clientdata(client);
643
644         sprintf(buf, "%d\n", torch_data->camera_strobe_brightness);
645
646         return sizeof(buf);
647 }
648
649 static ssize_t lm3559_strobe_store(struct device *dev,
650                                    struct device_attribute *attr,
651                                    const char *buf, size_t count)
652 {
653         int err;
654         unsigned long strobe_val = LED_OFF;
655
656         struct i2c_client *client = container_of(dev->parent,
657                                                  struct i2c_client, dev);
658         struct lm3559_data *torch_data = i2c_get_clientdata(client);
659
660         err = strict_strtoul(buf, 10, &strobe_val);
661         if (err) {
662                 pr_err("%s: Invalid parameter sent\n", __func__);
663                 return -1;
664         }
665
666         torch_data->camera_strobe_brightness = strobe_val;
667         err = lm3559_strobe_write(torch_data);
668
669         return err;
670 }
671 static DEVICE_ATTR(camera_strobe, 0644, lm3559_strobe_show,
672         lm3559_strobe_store);
673
674 static ssize_t lm3559_privacy_light_show(struct device *dev,
675                                   struct device_attribute *attr, char *buf)
676 {
677         struct i2c_client *client = container_of(dev->parent,
678                                                  struct i2c_client, dev);
679         struct lm3559_data *torch_data = i2c_get_clientdata(client);
680
681         sprintf(buf, "%d\n", torch_data->privacy_light_brightness);
682
683         return sizeof(buf);
684 }
685
686 static ssize_t lm3559_privacy_light_store(struct device *dev,
687                                    struct device_attribute *attr,
688                                    const char *buf, size_t count)
689 {
690         int err = 0;
691         unsigned long privacy_val = LED_OFF;
692
693         struct i2c_client *client = container_of(dev->parent,
694                                                  struct i2c_client, dev);
695         struct lm3559_data *torch_data = i2c_get_clientdata(client);
696
697         err = strict_strtoul(buf, 10, &privacy_val);
698         if (err) {
699                 pr_err("%s: Invalid parameter sent\n", __func__);
700                 return -1;
701         }
702
703         torch_data->privacy_light_brightness = privacy_val;
704         err = lm3559_privacy_write(torch_data);
705
706         return err;
707
708 };
709 static DEVICE_ATTR(privacy_light, 0644, lm3559_privacy_light_show,
710                    lm3559_privacy_light_store);
711
712
713 static void msg_ind_red_set(struct led_classdev *led_cdev,
714                             enum led_brightness value)
715 {
716         struct lm3559_data *msg_ind_data =
717             container_of(led_cdev, struct lm3559_data,
718                          msg_ind_red_class_dev);
719
720         msg_ind_data->msg_ind_light_brightness = value;
721         schedule_work(&msg_ind_data->wq);
722 }
723
724 static void msg_ind_green_set(struct led_classdev *led_cdev,
725                             enum led_brightness value)
726 {
727         struct lm3559_data *msg_ind_data =
728             container_of(led_cdev, struct lm3559_data,
729                          msg_ind_green_class_dev);
730
731         msg_ind_data->msg_ind_light_brightness = value;
732         schedule_work(&msg_ind_data->wq);
733 }
734
735 static void msg_ind_blue_set(struct led_classdev *led_cdev,
736                             enum led_brightness value)
737 {
738         struct lm3559_data *msg_ind_data =
739             container_of(led_cdev, struct lm3559_data,
740                          msg_ind_blue_class_dev);
741
742         msg_ind_data->msg_ind_light_brightness = value;
743         schedule_work(&msg_ind_data->wq);
744 }
745
746 static int msg_ind_red_blink(struct led_classdev *led_cdev,
747                 unsigned long *delay_on,
748                 unsigned long *delay_off)
749 {
750         struct lm3559_data *msg_ind_data =
751             container_of(led_cdev, struct lm3559_data,
752                          msg_ind_red_class_dev);
753
754         msg_ind_data->blink_val = *delay_on;
755         schedule_work(&msg_ind_data->wq);
756         return 0;
757 }
758
759 static int msg_ind_green_blink(struct led_classdev *led_cdev,
760                 unsigned long *delay_on,
761                 unsigned long *delay_off)
762 {
763         struct lm3559_data *msg_ind_data =
764             container_of(led_cdev, struct lm3559_data,
765                          msg_ind_green_class_dev);
766
767         msg_ind_data->blink_val = *delay_on;
768         schedule_work(&msg_ind_data->wq);
769         return 0;
770 }
771
772 static int msg_ind_blue_blink(struct led_classdev *led_cdev,
773                 unsigned long *delay_on,
774                 unsigned long *delay_off)
775 {
776         struct lm3559_data *msg_ind_data =
777             container_of(led_cdev, struct lm3559_data,
778                          msg_ind_blue_class_dev);
779
780         msg_ind_data->blink_val = *delay_on;
781         schedule_work(&msg_ind_data->wq);
782         return 0;
783 }
784
785 static int lm3559_probe(struct i2c_client *client,
786                         const struct i2c_device_id *id)
787 {
788         struct lm3559_platform_data *pdata = client->dev.platform_data;
789         struct lm3559_data *torch_data;
790         int err = -1;
791
792         if (pdata == NULL) {
793                 dev_err(&client->dev, "platform data is NULL. exiting.\n");
794                 return -ENODEV;
795         }
796
797         if (!pdata->flags) {
798                 pr_err("%s: Device does not exist\n", __func__);
799                 return -ENODEV;
800         }
801
802         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
803                 dev_err(&client->dev, "client not i2c capable\n");
804                 return -ENODEV;
805         }
806
807         torch_data = kzalloc(sizeof(struct lm3559_data), GFP_KERNEL);
808         if (torch_data == NULL) {
809                 dev_err(&client->dev, "kzalloc failed\n");
810                 return -ENOMEM;
811         }
812
813         torch_data->client = client;
814         torch_data->pdata = pdata;
815
816         mutex_init(&torch_data->enable_reg_lock);
817
818         i2c_set_clientdata(client, torch_data);
819
820         err = lm3559_init_registers(torch_data);
821         if (err < 0)
822                 goto error2;
823
824         INIT_WORK(&torch_data->wq, lm3559_rgb_work);
825
826         torch_data->led_dev.name = LM3559_LED_DEV;
827         torch_data->led_dev.brightness_set = lm3559_brightness_set;
828         torch_data->led_dev.brightness = LED_OFF;
829         torch_data->led_dev.max_brightness = 255;
830         err = led_classdev_register((struct device *)
831                                     &client->dev, &torch_data->led_dev);
832         if (err < 0) {
833                 err = -ENODEV;
834                 pr_err("%s: Register led class failed: %d\n",
835                         __func__, err);
836                 goto error3;
837         }
838
839         if (torch_data->pdata->flags & LM3559_TORCH) {
840                 if (lm3559_debug)
841                         pr_info("%s: Creating Torch\n", __func__);
842                 err = device_create_file(torch_data->led_dev.dev,
843                                          &dev_attr_flash_light);
844                 if (err < 0) {
845                         err = -ENODEV;
846                         pr_err("%s:File device creation failed: %d\n",
847                                 __func__, err);
848                         goto error4;
849                 }
850         }
851
852         if (torch_data->pdata->flags & LM3559_FLASH) {
853                 if (lm3559_debug)
854                         pr_info("%s: Creating Flash\n", __func__);
855                 err = device_create_file(torch_data->led_dev.dev,
856                                          &dev_attr_camera_strobe);
857                 if (err < 0) {
858                         err = -ENODEV;
859                         pr_err("%s:File device creation failed: %d\n",
860                                 __func__, err);
861                         goto error5;
862                 }
863                 err = device_create_file(torch_data->led_dev.dev,
864                                          &dev_attr_strobe_err);
865                 if (err < 0) {
866                         err = -ENODEV;
867                         pr_err("%s:File device creation failed: %d\n",
868                                 __func__, err);
869                         goto error6;
870                 }
871         }
872
873         if (torch_data->pdata->flags & LM3559_PRIVACY) {
874                 if (lm3559_debug)
875                         pr_info("%s: Creating Privacy\n", __func__);
876                 err = device_create_file(torch_data->led_dev.dev,
877                                          &dev_attr_privacy_light);
878                 if (err < 0) {
879                         err = -ENODEV;
880                         pr_err("%s:File device creation failed: %d\n",
881                                 __func__, err);
882                         goto error7;
883                 }
884         }
885
886         if (torch_data->pdata->flags & LM3559_FLASH_LIGHT) {
887                 if (lm3559_debug)
888                         pr_info("%s: Creating Spotlight\n", __func__);
889                 torch_data->spotlight_dev.name = LM3559_LED_SPOTLIGHT;
890                 torch_data->spotlight_dev.brightness_set =
891                         lm3559_spot_light_brightness_set;
892                 torch_data->spotlight_dev.brightness = LED_OFF;
893                 torch_data->spotlight_dev.max_brightness = 255;
894
895                 err = led_classdev_register((struct device *)
896                         &client->dev, &torch_data->spotlight_dev);
897                 if (err < 0) {
898                         err = -ENODEV;
899                         pr_err("%s: Register led class failed: %d\n",
900                                 __func__, err);
901                         goto error6;
902                 }
903         }
904
905         if (torch_data->pdata->flags & LM3559_MSG_IND_RED) {
906                 if (lm3559_debug)
907                         pr_info("%s: Creating MSG Red Indication\n",
908                         __func__);
909                 torch_data->msg_ind_red_class_dev.name = "red";
910                 torch_data->msg_ind_red_class_dev.brightness_set =
911                         msg_ind_red_set;
912                 torch_data->msg_ind_red_class_dev.blink_set =
913                         msg_ind_red_blink;
914                 torch_data->msg_ind_red_class_dev.brightness = LED_OFF;
915                 torch_data->msg_ind_red_class_dev.max_brightness = 255;
916
917                 err = led_classdev_register((struct device *)
918                         &client->dev, &torch_data->msg_ind_red_class_dev);
919                 if (err < 0) {
920                         pr_err("%s:Register Red LED class failed\n",
921                                 __func__);
922                         goto err_reg_red_class_failed;
923                 }
924         }
925
926         if (torch_data->pdata->flags & LM3559_MSG_IND_GREEN) {
927                 if (lm3559_debug)
928                         pr_info("%s: Creating MSG Green Indication\n",
929                         __func__);
930                 torch_data->msg_ind_green_class_dev.name = "green";
931                 torch_data->msg_ind_green_class_dev.brightness_set =
932                         msg_ind_green_set;
933                 torch_data->msg_ind_green_class_dev.blink_set =
934                         msg_ind_green_blink;
935                 torch_data->msg_ind_red_class_dev.brightness = LED_OFF;
936                 torch_data->msg_ind_red_class_dev.max_brightness = 255;
937                 err = led_classdev_register((struct device *)
938                         &client->dev, &torch_data->msg_ind_green_class_dev);
939                 if (err < 0) {
940                         pr_err("%s: Register Green LED class failed\n",
941                                 __func__);
942                         goto err_reg_green_class_failed;
943                 }
944         }
945
946         if (torch_data->pdata->flags & LM3559_MSG_IND_BLUE) {
947                 if (lm3559_debug)
948                         pr_info("%s: Creating MSG Blue Indication\n",
949                         __func__);
950                 torch_data->msg_ind_blue_class_dev.name = "blue";
951                 torch_data->msg_ind_blue_class_dev.brightness_set =
952                         msg_ind_blue_set;
953                 torch_data->msg_ind_blue_class_dev.blink_set =
954                         msg_ind_blue_blink;
955                 torch_data->msg_ind_blue_class_dev.brightness = LED_OFF;
956                 torch_data->msg_ind_blue_class_dev.max_brightness = 255;
957
958                 err = led_classdev_register((struct device *)
959                         &client->dev, &torch_data->msg_ind_blue_class_dev);
960                 if (err < 0) {
961                         pr_err("%s: Register Blue LED class failed\n",
962                                 __func__);
963                         goto err_reg_blue_class_failed;
964                 }
965         }
966 #ifdef DEBUG
967         err = device_create_file(torch_data->led_dev.dev, &dev_attr_registers);
968         if (err < 0)
969                 pr_err("%s:File device creation failed: %d\n", __func__, err);
970 #endif
971
972         return 0;
973
974 err_reg_blue_class_failed:
975         if (torch_data->pdata->flags & LM3559_MSG_IND_GREEN)
976                 led_classdev_unregister(&torch_data->msg_ind_green_class_dev);
977 err_reg_green_class_failed:
978         if (torch_data->pdata->flags & LM3559_MSG_IND_RED)
979                 led_classdev_unregister(&torch_data->msg_ind_red_class_dev);
980 err_reg_red_class_failed:
981         if (torch_data->pdata->flags & LM3559_PRIVACY)
982                 device_remove_file(torch_data->led_dev.dev,
983                         &dev_attr_privacy_light);
984 error7:
985         if (torch_data->pdata->flags & LM3559_FLASH_LIGHT)
986                 led_classdev_unregister(&torch_data->spotlight_dev);
987         if (torch_data->pdata->flags & LM3559_FLASH)
988                 device_remove_file(torch_data->led_dev.dev,
989                         &dev_attr_strobe_err);
990 error6:
991         if (torch_data->pdata->flags & LM3559_FLASH)
992                 device_remove_file(torch_data->led_dev.dev,
993                         &dev_attr_camera_strobe);
994 error5:
995         if (torch_data->pdata->flags & LM3559_TORCH)
996                 device_remove_file(torch_data->led_dev.dev,
997                         &dev_attr_flash_light);
998 error4:
999         led_classdev_unregister(&torch_data->led_dev);
1000 error3:
1001 error2:
1002         kfree(torch_data);
1003         return err;
1004 }
1005
1006 static int lm3559_remove(struct i2c_client *client)
1007 {
1008         struct lm3559_data *torch_data = i2c_get_clientdata(client);
1009
1010         if (torch_data->pdata->flags & LM3559_FLASH) {
1011                 device_remove_file(torch_data->led_dev.dev,
1012                                 &dev_attr_camera_strobe);
1013                 device_remove_file(torch_data->led_dev.dev,
1014                                 &dev_attr_strobe_err);
1015         }
1016         if (torch_data->pdata->flags & LM3559_TORCH)
1017                 device_remove_file(torch_data->led_dev.dev,
1018                                 &dev_attr_flash_light);
1019
1020         led_classdev_unregister(&torch_data->led_dev);
1021
1022         if (torch_data->pdata->flags & LM3559_FLASH_LIGHT)
1023                 led_classdev_unregister(&torch_data->spotlight_dev);
1024
1025         if (torch_data->pdata->flags & LM3559_PRIVACY)
1026                 device_remove_file(torch_data->led_dev.dev,
1027                                 &dev_attr_privacy_light);
1028
1029         if (torch_data->pdata->flags & LM3559_MSG_IND_RED)
1030                 led_classdev_unregister(&torch_data->msg_ind_red_class_dev);
1031
1032         if (torch_data->pdata->flags & LM3559_MSG_IND_GREEN)
1033                 led_classdev_unregister(&torch_data->msg_ind_green_class_dev);
1034
1035         if (torch_data->pdata->flags & LM3559_MSG_IND_BLUE)
1036                 led_classdev_unregister(&torch_data->msg_ind_blue_class_dev);
1037
1038 #ifdef DEBUG
1039         device_remove_file(torch_data->led_dev.dev, &dev_attr_registers);
1040 #endif
1041         kfree(torch_data->pdata);
1042         kfree(torch_data);
1043         return 0;
1044 }
1045
1046 static const struct i2c_device_id lm3559_id[] = {
1047         {LM3559_NAME, 0},
1048         {}
1049 };
1050
1051 static struct i2c_driver lm3559_i2c_driver = {
1052         .probe = lm3559_probe,
1053         .remove = lm3559_remove,
1054         .id_table = lm3559_id,
1055         .driver = {
1056                 .name = LM3559_NAME,
1057                 .owner = THIS_MODULE,
1058         },
1059 };
1060
1061 static int __init lm3559_init(void)
1062 {
1063         return i2c_add_driver(&lm3559_i2c_driver);
1064 }
1065
1066 static void lm3559_exit(void)
1067 {
1068         i2c_del_driver(&lm3559_i2c_driver);
1069 }
1070
1071 module_init(lm3559_init);
1072 module_exit(lm3559_exit);
1073
1074 /****************************************************************************/
1075
1076 MODULE_DESCRIPTION("Lighting driver for LM3559");
1077 MODULE_AUTHOR("MOTOROLA");
1078 MODULE_LICENSE("GPL");