1 /*
2 * drivers/leds/leds-lm3643.c
3 * General device driver for TI LM3643, FLASH LED Driver
4 *
5 * Copyright (C) 2014 Texas Instruments
6 *
7 * Contact: Daniel Jeong <gshark.jeong@gmail.com>
8 * Ldd-Mlp <ldd-mlp@list.ti.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
20 #include <linux/module.h>
21 #include <linux/i2c.h>
22 #include <linux/gpio.h>
23 #include <linux/leds.h>
24 #include <linux/slab.h>
25 #include <linux/platform_device.h>
26 #include <linux/fs.h>
27 #include <linux/regmap.h>
28 #include <linux/workqueue.h>
29 #include <linux/platform_data/leds-lm3643.h>
31 /* registers definitions */
32 #define REG_ENABLE 0x01
33 #define REG_FLASH_LED0_BR 0x03
34 #define REG_FLASH_LED1_BR 0x04
35 #define REG_TORCH_LED0_BR 0x05
36 #define REG_TORCH_LED1_BR 0x06
37 #define REG_FLASH_TOUT 0x08
38 #define REG_FLAG0 0x0a
39 #define REG_FLAG1 0x0b
41 enum lm3643_devid {
42 ID_FLASH0 = 0x0,
43 ID_FLASH1,
44 ID_TORCH0,
45 ID_TORCH1,
46 ID_MAX
47 };
49 enum lm3643_mode {
50 MODE_STDBY = 0x0,
51 MODE_IR,
52 MODE_TORCH,
53 MODE_FLASH,
54 MODE_MAX
55 };
57 enum lm3643_devfile {
58 DFILE_FLASH0_ENABLE = 0,
59 DFILE_FLASH0_ONOFF,
60 DFILE_FLASH0_SOURCE,
61 DFILE_FLASH0_TIMEOUT,
62 DFILE_FLASH1_ENABLE,
63 DFILE_FLASH1_ONOFF,
64 DFILE_TORCH0_ENABLE,
65 DFILE_TORCH0_ONOFF,
66 DFILE_TORCH0_SOURCE,
67 DFILE_TORCH1_ENABLE,
68 DFILE_TORCH1_ONOFF,
69 DFILE_MAX
70 };
72 #define to_lm3643(_ctrl, _no) container_of(_ctrl, struct lm3643, cdev[_no])
74 struct lm3643 {
75 struct device *dev;
77 u8 brightness[ID_MAX];
78 struct work_struct work[ID_MAX];
79 struct led_classdev cdev[ID_MAX];
81 struct lm3643_platform_data *pdata;
82 struct regmap *regmap;
83 struct mutex lock;
84 };
86 static void lm3643_read_flag(struct lm3643 *pchip)
87 {
89 int rval;
90 unsigned int flag0, flag1;
92 rval = regmap_read(pchip->regmap, REG_FLAG0, &flag0);
93 rval |= regmap_read(pchip->regmap, REG_FLAG1, &flag1);
95 if (rval < 0)
96 dev_err(pchip->dev, "i2c access fail.\n");
98 dev_info(pchip->dev, "[flag1] 0x%x, [flag0] 0x%x\n",
99 flag1 & 0x1f, flag0);
100 }
102 /* torch0 brightness control */
103 static void lm3643_deferred_torch0_brightness_set(struct work_struct *work)
104 {
105 struct lm3643 *pchip = container_of(work,
106 struct lm3643, work[ID_TORCH0]);
108 if (regmap_update_bits(pchip->regmap,
109 REG_TORCH_LED0_BR, 0x7f,
110 pchip->brightness[ID_TORCH0]))
111 dev_err(pchip->dev, "i2c access fail.\n");
112 lm3643_read_flag(pchip);
113 }
115 static void lm3643_torch0_brightness_set(struct led_classdev *cdev,
116 enum led_brightness brightness)
117 {
118 struct lm3643 *pchip =
119 container_of(cdev, struct lm3643, cdev[ID_TORCH0]);
121 pchip->brightness[ID_TORCH0] = brightness;
122 schedule_work(&pchip->work[ID_TORCH0]);
123 }
125 /* torch1 brightness control */
126 static void lm3643_deferred_torch1_brightness_set(struct work_struct *work)
127 {
128 struct lm3643 *pchip = container_of(work,
129 struct lm3643, work[ID_TORCH1]);
131 if (regmap_update_bits(pchip->regmap,
132 REG_TORCH_LED1_BR, 0x7f,
133 pchip->brightness[ID_TORCH1]))
134 dev_err(pchip->dev, "i2c access fail.\n");
135 lm3643_read_flag(pchip);
136 }
138 static void lm3643_torch1_brightness_set(struct led_classdev *cdev,
139 enum led_brightness brightness)
140 {
141 struct lm3643 *pchip =
142 container_of(cdev, struct lm3643, cdev[ID_TORCH1]);
144 pchip->brightness[ID_TORCH1] = brightness;
145 schedule_work(&pchip->work[ID_TORCH1]);
146 }
148 /* flash0 brightness control */
149 static void lm3643_deferred_flash0_brightness_set(struct work_struct *work)
150 {
151 struct lm3643 *pchip = container_of(work,
152 struct lm3643, work[ID_FLASH0]);
154 if (regmap_update_bits(pchip->regmap,
155 REG_FLASH_LED0_BR, 0x7f,
156 pchip->brightness[ID_FLASH0]))
157 dev_err(pchip->dev, "i2c access fail.\n");
158 lm3643_read_flag(pchip);
159 }
161 static void lm3643_flash0_brightness_set(struct led_classdev *cdev,
162 enum led_brightness brightness)
163 {
164 struct lm3643 *pchip =
165 container_of(cdev, struct lm3643, cdev[ID_FLASH0]);
167 pchip->brightness[ID_FLASH0] = brightness;
168 schedule_work(&pchip->work[ID_FLASH0]);
169 }
171 /* flash1 brightness control */
172 static void lm3643_deferred_flash1_brightness_set(struct work_struct *work)
173 {
174 struct lm3643 *pchip = container_of(work,
175 struct lm3643, work[ID_FLASH1]);
177 if (regmap_update_bits(pchip->regmap,
178 REG_FLASH_LED1_BR, 0x7f,
179 pchip->brightness[ID_FLASH1]))
180 dev_err(pchip->dev, "i2c access fail.\n");
181 lm3643_read_flag(pchip);
182 }
184 static void lm3643_flash1_brightness_set(struct led_classdev *cdev,
185 enum led_brightness brightness)
186 {
187 struct lm3643 *pchip =
188 container_of(cdev, struct lm3643, cdev[ID_FLASH1]);
190 pchip->brightness[ID_FLASH1] = brightness;
191 schedule_work(&pchip->work[ID_FLASH1]);
192 }
194 struct lm3643_devices {
195 struct led_classdev cdev;
196 work_func_t func;
197 };
199 static struct lm3643_devices lm3643_leds[ID_MAX] = {
200 [ID_FLASH0] = {
201 .cdev.name = "flash0",
202 .cdev.brightness = 0,
203 .cdev.max_brightness = 0x7f,
204 .cdev.brightness_set = lm3643_flash0_brightness_set,
205 .cdev.default_trigger = "flash0",
206 .func = lm3643_deferred_flash0_brightness_set},
207 [ID_FLASH1] = {
208 .cdev.name = "flash1",
209 .cdev.brightness = 0,
210 .cdev.max_brightness = 0x7f,
211 .cdev.brightness_set = lm3643_flash1_brightness_set,
212 .cdev.default_trigger = "flash1",
213 .func = lm3643_deferred_flash1_brightness_set},
214 [ID_TORCH0] = {
215 .cdev.name = "torch0",
216 .cdev.brightness = 0,
217 .cdev.max_brightness = 0x7f,
218 .cdev.brightness_set = lm3643_torch0_brightness_set,
219 .cdev.default_trigger = "torch0",
220 .func = lm3643_deferred_torch0_brightness_set},
221 [ID_TORCH1] = {
222 .cdev.name = "torch1",
223 .cdev.brightness = 0,
224 .cdev.max_brightness = 0x7f,
225 .cdev.brightness_set = lm3643_torch1_brightness_set,
226 .cdev.default_trigger = "torch1",
227 .func = lm3643_deferred_torch1_brightness_set},
228 };
230 static void lm3643_led_unregister(struct lm3643 *pchip, enum lm3643_devid id)
231 {
232 int icnt;
234 for (icnt = id; icnt > 0; icnt--)
235 led_classdev_unregister(&pchip->cdev[icnt - 1]);
236 }
238 static int lm3643_led_register(struct lm3643 *pchip)
239 {
240 int icnt, rval;
242 for (icnt = 0; icnt < ID_MAX; icnt++) {
243 INIT_WORK(&pchip->work[icnt], lm3643_leds[icnt].func);
244 pchip->cdev[icnt].name = lm3643_leds[icnt].cdev.name;
245 pchip->cdev[icnt].max_brightness =
246 lm3643_leds[icnt].cdev.max_brightness;
247 pchip->cdev[icnt].brightness =
248 lm3643_leds[icnt].cdev.brightness;
249 pchip->cdev[icnt].brightness_set =
250 lm3643_leds[icnt].cdev.brightness_set;
251 pchip->cdev[icnt].default_trigger =
252 lm3643_leds[icnt].cdev.default_trigger;
253 rval = led_classdev_register((struct device *)
254 pchip->dev, &pchip->cdev[icnt]);
255 if (rval < 0) {
256 lm3643_led_unregister(pchip, icnt);
257 return rval;
258 }
259 }
260 return 0;
261 }
263 /* device files to control registers */
264 struct lm3643_commands {
265 char *str;
266 int size;
267 };
269 enum lm3643_cmd_id {
270 CMD_ENABLE = 0,
271 CMD_DISABLE,
272 CMD_ON,
273 CMD_OFF,
274 CMD_IRMODE,
275 CMD_OVERRIDE,
276 CMD_MAX
277 };
279 struct lm3643_commands cmds[CMD_MAX] = {
280 [CMD_ENABLE] = {"enable", 6},
281 [CMD_DISABLE] = {"disable", 7},
282 [CMD_ON] = {"on", 2},
283 [CMD_OFF] = {"off", 3},
284 [CMD_IRMODE] = {"irmode", 6},
285 [CMD_OVERRIDE] = {"override", 8},
286 };
288 struct lm3643_files {
289 enum lm3643_devid id;
290 struct device_attribute attr;
291 };
293 static size_t lm3643_ctrl(struct device *dev,
294 const char *buf, enum lm3643_devid id,
295 enum lm3643_devfile dfid, size_t size)
296 {
297 struct led_classdev *led_cdev = dev_get_drvdata(dev);
298 struct lm3643 *pchip = to_lm3643(led_cdev, id);
299 enum lm3643_cmd_id icnt;
300 int tout, rval;
302 mutex_lock(&pchip->lock);
303 for (icnt = 0; icnt < CMD_MAX; icnt++) {
304 if (strncmp(buf, cmds[icnt].str, cmds[icnt].size) == 0)
305 break;
306 }
308 switch (dfid) {
309 /* led 0 enable */
310 case DFILE_FLASH0_ENABLE:
311 case DFILE_TORCH0_ENABLE:
312 if (icnt == CMD_ENABLE)
313 rval =
314 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x1,
315 0x1);
316 else if (icnt == CMD_DISABLE)
317 rval =
318 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x1,
319 0x0);
320 break;
321 /* led 1 enable, flash override */
322 case DFILE_FLASH1_ENABLE:
323 if (icnt == CMD_ENABLE) {
324 rval = regmap_update_bits(pchip->regmap,
325 REG_FLASH_LED0_BR, 0x80, 0x0);
326 rval |=
327 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x2,
328 0x2);
329 } else if (icnt == CMD_DISABLE) {
330 rval =
331 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x2,
332 0x0);
333 } else if (icnt == CMD_OVERRIDE) {
334 rval = regmap_update_bits(pchip->regmap,
335 REG_FLASH_LED0_BR, 0x80,
336 0x80);
337 rval |=
338 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x2,
339 0x2);
340 }
341 break;
342 /* led 1 enable, torch override */
343 case DFILE_TORCH1_ENABLE:
344 if (icnt == CMD_ENABLE) {
345 rval = regmap_update_bits(pchip->regmap,
346 REG_TORCH_LED0_BR, 0x80, 0x0);
347 rval |=
348 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x2,
349 0x2);
350 } else if (icnt == CMD_DISABLE) {
351 rval =
352 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x2,
353 0x0);
354 } else if (icnt == CMD_OVERRIDE) {
355 rval = regmap_update_bits(pchip->regmap,
356 REG_TORCH_LED0_BR, 0x80,
357 0x80);
358 rval |=
359 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x2,
360 0x2);
361 }
362 break;
363 /* mode control flash/ir */
364 case DFILE_FLASH0_ONOFF:
365 case DFILE_FLASH1_ONOFF:
366 if (icnt == CMD_ON)
367 rval =
368 regmap_update_bits(pchip->regmap, REG_ENABLE, 0xc,
369 0xc);
370 else if (icnt == CMD_OFF)
371 rval =
372 regmap_update_bits(pchip->regmap, REG_ENABLE, 0xc,
373 0x0);
374 else if (icnt == CMD_IRMODE)
375 rval =
376 regmap_update_bits(pchip->regmap, REG_ENABLE, 0xc,
377 0x4);
378 break;
379 /* mode control torch */
380 case DFILE_TORCH0_ONOFF:
381 case DFILE_TORCH1_ONOFF:
382 if (icnt == CMD_ON)
383 rval =
384 regmap_update_bits(pchip->regmap, REG_ENABLE, 0xc,
385 0x8);
386 else if (icnt == CMD_OFF)
387 rval =
388 regmap_update_bits(pchip->regmap, REG_ENABLE, 0xc,
389 0x0);
390 break;
391 /* strobe pin control */
392 case DFILE_FLASH0_SOURCE:
393 if (icnt == CMD_ON)
394 rval =
395 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x20,
396 0x20);
397 else if (icnt == CMD_OFF)
398 rval =
399 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x20,
400 0x0);
401 break;
402 case DFILE_TORCH0_SOURCE:
403 if (icnt == CMD_ON)
404 rval =
405 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x10,
406 0x10);
407 else if (icnt == CMD_OFF)
408 rval =
409 regmap_update_bits(pchip->regmap, REG_ENABLE, 0x10,
410 0x0);
411 break;
412 /* flash time out */
413 case DFILE_FLASH0_TIMEOUT:
414 rval = kstrtouint((const char *)buf, 10, &tout);
415 if (rval < 0)
416 break;
417 rval = regmap_update_bits(pchip->regmap,
418 REG_FLASH_TOUT, 0x0f, tout);
419 break;
420 default:
421 dev_err(pchip->dev, "error : undefined dev file\n");
422 break;
423 }
424 lm3643_read_flag(pchip);
425 mutex_unlock(&pchip->lock);
426 return size;
427 }
429 /* flash enable control */
430 static ssize_t lm3643_flash0_enable_store(struct device *dev,
431 struct device_attribute *devAttr,
432 const char *buf, size_t size)
433 {
434 return lm3643_ctrl(dev, buf, ID_FLASH0, DFILE_FLASH0_ENABLE, size);
435 }
437 static ssize_t lm3643_flash1_enable_store(struct device *dev,
438 struct device_attribute *devAttr,
439 const char *buf, size_t size)
440 {
441 return lm3643_ctrl(dev, buf, ID_FLASH1, DFILE_FLASH1_ENABLE, size);
442 }
444 /* flash onoff control */
445 static ssize_t lm3643_flash0_onoff_store(struct device *dev,
446 struct device_attribute *devAttr,
447 const char *buf, size_t size)
448 {
449 return lm3643_ctrl(dev, buf, ID_FLASH0, DFILE_FLASH0_ONOFF, size);
450 }
452 static ssize_t lm3643_flash1_onoff_store(struct device *dev,
453 struct device_attribute *devAttr,
454 const char *buf, size_t size)
455 {
456 return lm3643_ctrl(dev, buf, ID_FLASH1, DFILE_FLASH1_ONOFF, size);
457 }
459 /* flash timeout control */
460 static ssize_t lm3643_flash0_timeout_store(struct device *dev,
461 struct device_attribute *devAttr,
462 const char *buf, size_t size)
463 {
464 return lm3643_ctrl(dev, buf, ID_FLASH0, DFILE_FLASH0_TIMEOUT, size);
465 }
467 /* flash source control */
468 static ssize_t lm3643_flash0_source_store(struct device *dev,
469 struct device_attribute *devAttr,
470 const char *buf, size_t size)
471 {
472 return lm3643_ctrl(dev, buf, ID_FLASH0, DFILE_FLASH0_SOURCE, size);
473 }
475 /* torch enable control */
476 static ssize_t lm3643_torch0_enable_store(struct device *dev,
477 struct device_attribute *devAttr,
478 const char *buf, size_t size)
479 {
480 return lm3643_ctrl(dev, buf, ID_FLASH0, DFILE_TORCH0_ENABLE, size);
481 }
483 static ssize_t lm3643_torch1_enable_store(struct device *dev,
484 struct device_attribute *devAttr,
485 const char *buf, size_t size)
486 {
487 return lm3643_ctrl(dev, buf, ID_TORCH1, DFILE_TORCH1_ENABLE, size);
488 }
490 /* torch onoff control */
491 static ssize_t lm3643_torch0_onoff_store(struct device *dev,
492 struct device_attribute *devAttr,
493 const char *buf, size_t size)
494 {
495 return lm3643_ctrl(dev, buf, ID_TORCH0, DFILE_TORCH0_ONOFF, size);
496 }
498 static ssize_t lm3643_torch1_onoff_store(struct device *dev,
499 struct device_attribute *devAttr,
500 const char *buf, size_t size)
501 {
502 return lm3643_ctrl(dev, buf, ID_TORCH1, DFILE_TORCH1_ONOFF, size);
503 }
505 /* torch source control */
506 static ssize_t lm3643_torch0_source_store(struct device *dev,
507 struct device_attribute *devAttr,
508 const char *buf, size_t size)
509 {
510 return lm3643_ctrl(dev, buf, ID_TORCH0, DFILE_TORCH0_SOURCE, size);
511 }
513 #define lm3643_attr(_name, _show, _store)\
514 {\
515 .attr = {\
516 .name = _name,\
517 .mode = 0644,\
518 },\
519 .show = _show,\
520 .store = _store,\
521 }
523 static struct lm3643_files lm3643_devfiles[DFILE_MAX] = {
524 [DFILE_FLASH0_ENABLE] = {
525 .id = ID_FLASH0,
526 .attr =
527 lm3643_attr("enable", NULL,
528 lm3643_flash0_enable_store),
529 },
530 [DFILE_FLASH0_ONOFF] = {
531 .id = ID_FLASH0,
532 .attr =
533 lm3643_attr("onoff", NULL,
534 lm3643_flash0_onoff_store),
535 },
536 [DFILE_FLASH0_SOURCE] = {
537 .id = ID_FLASH0,
538 .attr =
539 lm3643_attr("source", NULL,
540 lm3643_flash0_source_store),
541 },
542 [DFILE_FLASH0_TIMEOUT] = {
543 .id = ID_FLASH0,
544 .attr =
545 lm3643_attr("timeout", NULL,
546 lm3643_flash0_timeout_store),
547 },
548 [DFILE_FLASH1_ENABLE] = {
549 .id = ID_FLASH1,
550 .attr =
551 lm3643_attr("enable", NULL,
552 lm3643_flash1_enable_store),
553 },
554 [DFILE_FLASH1_ONOFF] = {
555 .id = ID_FLASH1,
556 .attr =
557 lm3643_attr("onoff", NULL,
558 lm3643_flash1_onoff_store),
559 },
560 [DFILE_TORCH0_ENABLE] = {
561 .id = ID_TORCH0,
562 .attr =
563 lm3643_attr("enable", NULL,
564 lm3643_torch0_enable_store),
565 },
566 [DFILE_TORCH0_ONOFF] = {
567 .id = ID_TORCH0,
568 .attr =
569 lm3643_attr("onoff", NULL,
570 lm3643_torch0_onoff_store),
571 },
572 [DFILE_TORCH0_SOURCE] = {
573 .id = ID_TORCH0,
574 .attr =
575 lm3643_attr("source", NULL,
576 lm3643_torch0_source_store),
577 },
578 [DFILE_TORCH1_ENABLE] = {
579 .id = ID_TORCH1,
580 .attr =
581 lm3643_attr("enable", NULL,
582 lm3643_torch1_enable_store),
583 },
584 [DFILE_TORCH1_ONOFF] = {
585 .id = ID_TORCH1,
586 .attr =
587 lm3643_attr("onoff", NULL,
588 lm3643_torch1_onoff_store),
589 }
590 };
592 static void lm3643_df_remove(struct lm3643 *pchip, enum lm3643_devfile dfid)
593 {
594 enum lm3643_devfile icnt;
596 for (icnt = dfid; icnt > 0; icnt--)
597 device_remove_file(pchip->cdev[lm3643_devfiles[icnt - 1].id].
598 dev, &lm3643_devfiles[icnt - 1].attr);
599 }
601 static int lm3643_df_create(struct lm3643 *pchip)
602 {
603 enum lm3643_devfile icnt;
604 int rval;
606 for (icnt = 0; icnt < DFILE_MAX; icnt++) {
607 rval =
608 device_create_file(pchip->cdev[lm3643_devfiles[icnt].id].
609 dev, &lm3643_devfiles[icnt].attr);
610 if (rval < 0) {
611 lm3643_df_remove(pchip, icnt);
612 return rval;
613 }
614 }
615 return 0;
616 }
618 static const struct regmap_config lm3643_regmap = {
619 .reg_bits = 8,
620 .val_bits = 8,
621 .max_register = 0xff,
622 };
624 static int lm3643_probe(struct i2c_client *client,
625 const struct i2c_device_id *id)
626 {
627 struct lm3643 *pchip;
628 int rval;
630 /* i2c check */
631 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
632 dev_err(&client->dev, "i2c functionality check fail.\n");
633 return -EOPNOTSUPP;
634 }
636 pchip = devm_kzalloc(&client->dev, sizeof(struct lm3643), GFP_KERNEL);
637 if (!pchip)
638 return -ENOMEM;
640 pchip->dev = &client->dev;
641 pchip->regmap = devm_regmap_init_i2c(client, &lm3643_regmap);
642 if (IS_ERR(pchip->regmap)) {
643 rval = PTR_ERR(pchip->regmap);
644 dev_err(&client->dev, "Failed to allocate register map: %d\n",
645 rval);
646 return rval;
647 }
648 mutex_init(&pchip->lock);
649 i2c_set_clientdata(client, pchip);
651 /* led class register */
652 rval = lm3643_led_register(pchip);
653 if (rval < 0)
654 return rval;
656 /* create dev files */
657 rval = lm3643_df_create(pchip);
658 if (rval < 0) {
659 lm3643_led_unregister(pchip, ID_MAX);
660 return rval;
661 }
663 dev_info(pchip->dev, "lm3643 leds initialized\n");
664 return 0;
665 }
667 static int lm3643_remove(struct i2c_client *client)
668 {
669 struct lm3643 *pchip = i2c_get_clientdata(client);
671 lm3643_df_remove(pchip, DFILE_MAX);
672 lm3643_led_unregister(pchip, ID_MAX);
674 return 0;
675 }
677 static const struct i2c_device_id lm3643_id[] = {
678 {LM3643_NAME, 0},
679 {}
680 };
682 MODULE_DEVICE_TABLE(i2c, lm3643_id);
684 static struct i2c_driver lm3643_i2c_driver = {
685 .driver = {
686 .name = LM3643_NAME,
687 .owner = THIS_MODULE,
688 .pm = NULL,
689 },
690 .probe = lm3643_probe,
691 .remove = lm3643_remove,
692 .id_table = lm3643_id,
693 };
695 module_i2c_driver(lm3643_i2c_driver);
697 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3643");
698 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
699 MODULE_LICENSE("GPL v2");