Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / drivers / i2c / chips / lp5521.c
1 /*
2  * drivers/i2c/chips/lp5521.c
3  *
4  * Copyright (C) 2007 Nokia Corporation
5  *
6  * Written by Mathias Nyman <mathias.nyman@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/i2c.h>
26 #include <linux/mutex.h>
27 #include <mach/gpio.h>
28
29 #define LP5521_DRIVER_NAME              "lp5521"
30
31 #ifdef LED_CONNECTED_WRONG
32 #define LP5521_REG_R_PWM                0x04
33 #define LP5521_REG_B_PWM                0x02
34 #else
35 #define LP5521_REG_R_PWM                0x02
36 #define LP5521_REG_B_PWM                0x04
37 #endif
38 #define LP5521_REG_ENABLE               0x00
39 #define LP5521_REG_OP_MODE              0x01
40 #define LP5521_REG_G_PWM                0x03
41 #define LP5521_REG_R_CNTRL              0x05
42 #define LP5521_REG_G_CNTRL              0x06
43 #define LP5521_REG_B_CNTRL              0x07
44 #define LP5521_REG_MISC                 0x08
45 #define LP5521_REG_R_CHANNEL_PC         0x09
46 #define LP5521_REG_G_CHANNEL_PC         0x0a
47 #define LP5521_REG_B_CHANNEL_PC         0x0b
48 #define LP5521_REG_STATUS               0x0c
49 #define LP5521_REG_RESET                0x0d
50 #define LP5521_REG_GPO                  0x0e
51 #define LP5521_REG_R_PROG_MEM           0x10
52 #define LP5521_REG_G_PROG_MEM           0x30
53 #define LP5521_REG_B_PROG_MEM           0x50
54
55 #define LP5521_MODE_LOAD                "load"
56 #define LP5521_MODE_RUN                 "run"
57 #define LP5521_MODE_DIRECT_CONTROL      "direct"
58
59 #define LP5521_CURRENT_1m5              0x0f
60 #define LP5521_CURRENT_3m1              0x1f
61 #define LP5521_CURRENT_4m7              0x2f
62 #define LP5521_CURRENT_6m3              0x3f
63 #define LP5521_CURRENT_7m9              0x4f
64 #define LP5521_CURRENT_9m5              0x5f
65 #define LP5521_CURRENT_11m1             0x6f
66 #define LP5521_CURRENT_12m7             0x7f
67 #define LP5521_CURRENT_14m3             0x8f
68 #define LP5521_CURRENT_15m9             0x9f
69 #define LP5521_CURRENT_17m5             0xaf
70 #define LP5521_CURRENT_19m1             0xbf
71 #define LP5521_CURRENT_20m7             0xcf
72 #define LP5521_CURRENT_22m3             0xdf
73 #define LP5521_CURRENT_23m9             0xef
74 #define LP5521_CURRENT_25m5             0xff
75
76 #define LP5521_PROGRAM_LENGTH           32      /* in bytes */
77
78 struct lp5521_chip {
79         struct mutex            lock;
80         struct i2c_client       *client;
81         char                    *mode;
82         int                     red;
83         int                     green;
84         int                     blue;
85 };
86
87 static int lp5521_set_mode(struct lp5521_chip *chip, char *mode);
88
89 static int lp5521_write(struct i2c_client *client, u8 reg, u8 value)
90 {
91         return i2c_smbus_write_byte_data(client, reg, value);
92 }
93
94 static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf)
95 {
96         s32 ret = i2c_smbus_read_byte_data(client, reg);
97
98         if (ret < 0)
99                 return -EIO;
100
101         *buf = ret;
102         return 0;
103 }
104
105 static int lp5521_configure(struct i2c_client *client)
106 {
107         int ret = 0;
108
109         /* Enable chip and set light to logarithmic mode*/
110         ret |= lp5521_write(client, LP5521_REG_ENABLE, 0xc0);
111
112         /* setting all color pwms to direct control mode */
113         ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3f);
114
115         /* setting current to 4.7 mA for all channels */
116         ret |= lp5521_write(client, LP5521_REG_R_CNTRL, LP5521_CURRENT_4m7);
117         ret |= lp5521_write(client, LP5521_REG_G_CNTRL, LP5521_CURRENT_4m7);
118         ret |= lp5521_write(client, LP5521_REG_B_CNTRL, LP5521_CURRENT_4m7);
119
120         /* Enable auto-powersave, set charge pump to auto, red to battery */
121         ret |= lp5521_write(client, LP5521_REG_MISC, 0x3c);
122
123         /* initialize all channels pwm to zero */
124         ret |= lp5521_write(client, LP5521_REG_R_PWM, 0);
125         ret |= lp5521_write(client, LP5521_REG_G_PWM, 0);
126         ret |= lp5521_write(client, LP5521_REG_B_PWM, 0);
127
128         /* Not much can be done about errors at this point */
129         return ret;
130 }
131
132 static int lp5521_load_program(struct lp5521_chip *chip, u8 *pattern)
133 {
134         struct i2c_client *client = chip->client;
135         int ret = 0;
136
137         /* Enter load program mode for all led channels */
138         ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15); /* 0001 0101 */
139         if (ret)
140                 return ret;
141
142         if (chip->red)
143                 ret |= i2c_smbus_write_i2c_block_data(client,
144                                                       LP5521_REG_R_PROG_MEM,
145                                                       LP5521_PROGRAM_LENGTH,
146                                                       pattern);
147         if (chip->green)
148                 ret |= i2c_smbus_write_i2c_block_data(client,
149                                                       LP5521_REG_G_PROG_MEM,
150                                                       LP5521_PROGRAM_LENGTH,
151                                                       pattern);
152         if (chip->blue)
153                 ret |= i2c_smbus_write_i2c_block_data(client,
154                                                       LP5521_REG_B_PROG_MEM,
155                                                       LP5521_PROGRAM_LENGTH,
156                                                       pattern);
157
158         return ret;
159 }
160
161 static int lp5521_run_program(struct lp5521_chip *chip)
162 {
163         struct i2c_client *client = chip->client;
164         int ret;
165         u8 mask = 0xc0;
166         u8 exec_state = 0;
167         u8 enable_reg;
168
169         ret = lp5521_read(client, LP5521_REG_ENABLE, &enable_reg);
170         if (ret)
171                 goto fail;
172
173         enable_reg &= mask;
174
175         /* set all active channels exec state to countinous run*/
176         exec_state |= (chip->red   << 5);
177         exec_state |= (chip->green << 3);
178         exec_state |= (chip->blue  << 1);
179
180         enable_reg |= exec_state;
181
182         ret |= lp5521_write(client, LP5521_REG_ENABLE, enable_reg);
183
184         /* set op-mode to run for active channels, disabled for others */
185         ret |= lp5521_write(client, LP5521_REG_OP_MODE, exec_state);
186
187 fail:
188         return ret;
189 }
190
191 /*--------------------------------------------------------------*/
192 /*                      Sysfs interface                         */
193 /*--------------------------------------------------------------*/
194
195 static ssize_t show_active_channels(struct device *dev,
196                             struct device_attribute *attr,
197                             char *buf)
198 {
199         struct lp5521_chip *chip = dev_get_drvdata(dev);
200         char channels[4];
201         int pos = 0;
202
203 #ifdef LED_CONNECTED_WRONG
204         if (chip->blue)
205                 pos += sprintf(channels + pos, "r");
206         if (chip->green)
207                 pos += sprintf(channels + pos, "g");
208         if (chip->red)
209                 pos += sprintf(channels + pos, "b");
210
211 #else
212         if (chip->red)
213                 pos += sprintf(channels + pos, "r");
214         if (chip->green)
215                 pos += sprintf(channels + pos, "g");
216         if (chip->blue)
217                 pos += sprintf(channels + pos, "b");
218 #endif
219
220         channels[pos] = '\0';
221
222         return sprintf(buf, "%s\n", channels);
223 }
224
225 static ssize_t store_active_channels(struct device *dev,
226                              struct device_attribute *attr,
227                              const char *buf, size_t len)
228 {
229         struct lp5521_chip *chip = dev_get_drvdata(dev);
230
231         chip->red = 0;
232         chip->green = 0;
233         chip->blue = 0;
234
235 #ifdef LED_CONNECTED_WRONG
236         if (strchr(buf, 'r') != NULL)
237                 chip->blue = 1;
238         if (strchr(buf, 'b') != NULL)
239                 chip->red = 1;
240 #else
241         if (strchr(buf, 'r') != NULL)
242                 chip->red = 1;
243         if (strchr(buf, 'b') != NULL)
244                 chip->blue = 1;
245 #endif
246         if (strchr(buf, 'g') != NULL)
247                 chip->green = 1;
248
249         return len;
250 }
251
252 static ssize_t show_color(struct device *dev,
253                             struct device_attribute *attr,
254                             char *buf)
255 {
256         struct i2c_client *client = to_i2c_client(dev);
257         int ret = 0;
258         u8 r, g, b;
259
260         ret |= lp5521_read(client, LP5521_REG_R_PWM, &r);
261         ret |= lp5521_read(client, LP5521_REG_G_PWM, &g);
262         ret |= lp5521_read(client, LP5521_REG_B_PWM, &b);
263
264         if (ret)
265                 return ret;
266
267         return sprintf(buf, "%.2x:%.2x:%.2x\n", r, g, b);
268 }
269
270 static ssize_t store_color(struct device *dev,
271                              struct device_attribute *attr,
272                              const char *buf, size_t len)
273 {
274         struct i2c_client *client = to_i2c_client(dev);
275         struct lp5521_chip *chip = i2c_get_clientdata(client);
276         int ret;
277         unsigned r, g, b;
278
279
280         ret = sscanf(buf, "%2x:%2x:%2x", &r, &g, &b);
281         if (ret != 3)
282                 return  -EINVAL;
283
284         mutex_lock(&chip->lock);
285
286         ret = lp5521_write(client, LP5521_REG_R_PWM, (u8)r);
287         ret = lp5521_write(client, LP5521_REG_G_PWM, (u8)g);
288         ret = lp5521_write(client, LP5521_REG_B_PWM, (u8)b);
289
290         mutex_unlock(&chip->lock);
291
292         return len;
293 }
294
295 static ssize_t store_load(struct device *dev,
296                              struct device_attribute *attr,
297                              const char *buf, size_t len)
298 {
299         struct lp5521_chip *chip = dev_get_drvdata(dev);
300         int  ret, nrchars, offset = 0, i = 0;
301         char c[3];
302         unsigned cmd;
303         u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
304
305         while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) {
306
307                 /* separate sscanfs because length is working only for %s */
308                 ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
309                 ret = sscanf(c, "%2x", &cmd);
310                 if (ret != 1)
311                         goto fail;
312                 pattern[i] = (u8)cmd;
313
314                 offset += nrchars;
315                 i++;
316         }
317
318         /* pattern commands are always two bytes long */
319         if (i % 2)
320                 goto fail;
321
322         mutex_lock(&chip->lock);
323
324         ret = lp5521_load_program(chip, pattern);
325         mutex_unlock(&chip->lock);
326
327         if (ret) {
328                 dev_err(dev, "lp5521 failed loading pattern\n");
329                 return ret;
330         }
331
332         return len;
333 fail:
334         dev_err(dev, "lp5521 wrong pattern format\n");
335         return -EINVAL;
336 }
337
338 static ssize_t show_mode(struct device *dev,
339                          struct device_attribute *attr,
340                          char *buf)
341 {
342         struct lp5521_chip *chip = dev_get_drvdata(dev);
343
344         return sprintf(buf, "%s\n", chip->mode);
345 }
346
347 static ssize_t store_mode(struct device *dev,
348                           struct device_attribute *attr,
349                           const char *buf, size_t len)
350 {
351         struct lp5521_chip *chip = dev_get_drvdata(dev);
352
353         mutex_lock(&chip->lock);
354
355         if (!strncmp(buf, "run", 3))
356                 lp5521_set_mode(chip, LP5521_MODE_RUN);
357         else if (!strncmp(buf, "load", 4))
358                 lp5521_set_mode(chip, LP5521_MODE_LOAD);
359         else if (!strncmp(buf, "direct", 6))
360                 lp5521_set_mode(chip, LP5521_MODE_DIRECT_CONTROL);
361
362         mutex_unlock(&chip->lock);
363
364         return len;
365 }
366
367 static ssize_t show_current(struct device *dev,
368                             struct device_attribute *attr,
369                             char *buf)
370 {
371         struct i2c_client *client = to_i2c_client(dev);
372         int ret = 0;
373         u8 r_curr, g_curr, b_curr;
374
375         ret |= lp5521_read(client, LP5521_REG_R_CNTRL, &r_curr);
376         ret |= lp5521_read(client, LP5521_REG_G_CNTRL, &g_curr);
377         ret |= lp5521_read(client, LP5521_REG_B_CNTRL, &b_curr);
378
379         if (ret)
380                 return ret;
381
382         r_curr = r_curr >> 4;
383         g_curr = g_curr >> 4;
384         b_curr = b_curr >> 4;
385
386         if (r_curr == g_curr && g_curr == b_curr)
387                 return sprintf(buf, "%x\n", r_curr);
388         else
389                 return sprintf(buf, "%x %x %x\n", r_curr, g_curr, b_curr);
390 }
391
392 static ssize_t store_current(struct device *dev,
393                              struct device_attribute *attr,
394                              const char *buf, size_t len)
395 {
396         struct lp5521_chip *chip = dev_get_drvdata(dev);
397         struct i2c_client *client = chip->client;
398         int ret;
399         unsigned curr;
400
401         ret = sscanf(buf, "%1x", &curr);
402         if (ret != 1)
403                 return  -EINVAL;
404
405         /* current level is determined by the 4 upper bits, rest is ones */
406         curr = (curr << 4) | 0x0f;
407
408         mutex_lock(&chip->lock);
409
410         ret |= lp5521_write(client, LP5521_REG_R_CNTRL, (u8)curr);
411         ret |= lp5521_write(client, LP5521_REG_G_CNTRL, (u8)curr);
412         ret |= lp5521_write(client, LP5521_REG_B_CNTRL, (u8)curr);
413
414         mutex_unlock(&chip->lock);
415
416         return len;
417 }
418
419 static DEVICE_ATTR(color, S_IRUGO | S_IWUGO, show_color, store_color);
420 static DEVICE_ATTR(load, S_IWUGO, NULL, store_load);
421 static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, store_mode);
422 static DEVICE_ATTR(active_channels, S_IRUGO | S_IWUGO,
423                    show_active_channels, store_active_channels);
424 static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
425
426 static int lp5521_register_sysfs(struct i2c_client *client)
427 {
428         struct device *dev = &client->dev;
429         int ret;
430
431         ret = device_create_file(dev, &dev_attr_color);
432         if (ret)
433                 goto fail1;
434         ret = device_create_file(dev, &dev_attr_load);
435         if (ret)
436                 goto fail2;
437         ret = device_create_file(dev, &dev_attr_active_channels);
438         if (ret)
439                 goto fail3;
440         ret = device_create_file(dev, &dev_attr_mode);
441         if (ret)
442                 goto fail4;
443         ret = device_create_file(dev, &dev_attr_led_current);
444         if (ret)
445                 goto fail5;
446         return 0;
447
448 fail5:
449         device_remove_file(dev, &dev_attr_mode);
450 fail4:
451         device_remove_file(dev, &dev_attr_active_channels);
452 fail3:
453         device_remove_file(dev, &dev_attr_load);
454 fail2:
455         device_remove_file(dev, &dev_attr_color);
456 fail1:
457         return ret;
458 }
459
460 static void lp5521_unregister_sysfs(struct i2c_client *client)
461 {
462         struct lp5521_chip *chip = i2c_get_clientdata(client);
463         struct device *dev = &client->dev;
464
465         device_remove_file(dev, &dev_attr_led_current);
466         device_remove_file(dev, &dev_attr_mode);
467         device_remove_file(dev, &dev_attr_active_channels);
468         device_remove_file(dev, &dev_attr_color);
469
470         if (!strcmp(chip->mode, LP5521_MODE_LOAD))
471                 device_remove_file(dev, &dev_attr_load);
472 }
473
474 /*--------------------------------------------------------------*/
475 /*                      Set chip operating mode                 */
476 /*--------------------------------------------------------------*/
477
478 static int lp5521_set_mode(struct lp5521_chip *chip, char *mode)
479 {
480         struct i2c_client *client = chip->client ;
481         int ret = 0;
482
483         /* if in that mode already do nothing, except for run */
484         if (!strcmp(mode, chip->mode) && strcmp(mode, LP5521_MODE_RUN))
485                 return 0;
486
487         if (!strcmp(mode, LP5521_MODE_RUN))
488                 ret = lp5521_run_program(chip);
489
490         if (!strcmp(mode, LP5521_MODE_LOAD))
491                 ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15);
492
493         if (!strcmp(mode, LP5521_MODE_DIRECT_CONTROL))
494                 ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
495
496         chip->mode = mode;
497
498         return ret;
499 }
500
501 /*--------------------------------------------------------------*/
502 /*                      Probe, Attach, Remove                   */
503 /*--------------------------------------------------------------*/
504 static struct i2c_driver lp5521_driver;
505
506 static int lp5521_probe(struct i2c_client *client,
507                 const struct i2c_device_id *id)
508 {
509         struct lp5521_chip *chip;
510         int ret = 0;
511
512         chip = kzalloc(sizeof(*chip), GFP_KERNEL);
513         if (!chip)
514                 return -ENOMEM;
515
516         chip->client    = client;
517         strncpy(client->name, LP5521_DRIVER_NAME, I2C_NAME_SIZE);
518         i2c_set_clientdata(client, chip);
519
520         mutex_init(&chip->lock);
521
522         ret = lp5521_configure(client);
523         if (ret < 0) {
524                 dev_err(&client->dev, "lp5521 error configuring chip \n");
525                 goto fail1;
526         }
527
528         /* Set default values */
529         chip->mode      = LP5521_MODE_DIRECT_CONTROL;
530         chip->red       = 1;
531         chip->green     = 1;
532         chip->blue      = 1;
533
534         ret = lp5521_register_sysfs(client);
535         if (ret)
536                 dev_err(&client->dev, "lp5521 registering sysfs failed \n");
537
538         return ret;
539
540 fail1:
541         kfree(chip);
542         return ret;
543 }
544
545 static int lp5521_remove(struct i2c_client *client)
546 {
547         struct lp5521_chip *chip = i2c_get_clientdata(client);
548
549         lp5521_unregister_sysfs(client);
550         kfree(chip);
551
552         return 0;
553 }
554
555 static const struct i2c_device_id lp5521_id[] = {
556         { LP5521_DRIVER_NAME, 0},
557         { },
558 };
559 MODULE_DEVICE_TABLE(i2c, lp5521_id);
560
561 static struct i2c_driver lp5521_driver = {
562         .driver = {
563                 .name   = LP5521_DRIVER_NAME,
564         },
565         .probe          = lp5521_probe,
566         .remove         = __devexit_p(lp5521_remove),
567         .id_table       = lp5521_id,
568 };
569
570 static int __init lp5521_init(void)
571 {
572         return i2c_add_driver(&lp5521_driver);
573 }
574
575 static void __exit lp5521_exit(void)
576 {
577         i2c_del_driver(&lp5521_driver);
578 }
579
580 MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
581 MODULE_DESCRIPTION("lp5521 LED driver");
582 MODULE_LICENSE("GPL");
583
584 module_init(lp5521_init);
585 module_exit(lp5521_exit);