Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
leds-lm355x.c
Go to the documentation of this file.
1 /*
2 * Simple driver for Texas Instruments LM355x LED Flash driver chip
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 
10 #include <linux/module.h>
11 #include <linux/delay.h>
12 #include <linux/i2c.h>
13 #include <linux/gpio.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/workqueue.h>
21 
25 };
26 
28  REG_FLAG = 0,
37 };
38 
39 /* operation mode */
41  MODE_SHDN = 0,
45 };
46 
47 /* register map info. */
52 };
53 
55  struct device *dev;
57 
61 
65 
69 
71  struct regmap *regmap;
72  struct mutex lock;
73 
74  unsigned int last_flag;
76 };
77 
78 /* specific indicator function for lm3556 */
96 };
97 
115 };
116 
126 };
127 
128 #define INDIC_PATTERN_SIZE 4
129 
130 struct indicator {
133 };
134 
135 /* indicator pattern data only for lm3556 */
136 static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
141 };
142 
143 static struct lm355x_reg_data lm3554_regs[REG_MAX] = {
144  [REG_FLAG] = {0xD0, 0xBF, 0},
145  [REG_TORCH_CFG] = {0xE0, 0x80, 7},
146  [REG_TORCH_CTRL] = {0xA0, 0x38, 3},
147  [REG_STROBE_CFG] = {0xE0, 0x04, 2},
148  [REG_FLASH_CTRL] = {0xB0, 0x78, 3},
149  [REG_INDI_CFG] = {0xE0, 0x08, 3},
150  [REG_INDI_CTRL] = {0xA0, 0xC0, 6},
151  [REG_OPMODE] = {0xA0, 0x03, 0},
152 };
153 
154 static struct lm355x_reg_data lm3556_regs[REG_MAX] = {
155  [REG_FLAG] = {0x0B, 0xFF, 0},
156  [REG_TORCH_CFG] = {0x0A, 0x10, 4},
157  [REG_TORCH_CTRL] = {0x09, 0x70, 4},
158  [REG_STROBE_CFG] = {0x0A, 0x20, 5},
159  [REG_FLASH_CTRL] = {0x09, 0x0F, 0},
160  [REG_INDI_CFG] = {0xFF, 0xFF, 0},
161  [REG_INDI_CTRL] = {0x09, 0x70, 4},
162  [REG_OPMODE] = {0x0A, 0x03, 0},
163 };
164 
165 static char lm355x_name[][I2C_NAME_SIZE] = {
168 };
169 
170 /* chip initialize */
171 static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
172 {
173  int ret;
174  unsigned int reg_val;
175  struct lm355x_platform_data *pdata = chip->pdata;
176 
177  /* input and output pins configuration */
178  switch (chip->type) {
179  case CHIP_LM3554:
180  reg_val = pdata->pin_tx2 | pdata->ntc_pin;
181  ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val);
182  if (ret < 0)
183  goto out;
184  reg_val = pdata->pass_mode;
185  ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val);
186  if (ret < 0)
187  goto out;
188  break;
189 
190  case CHIP_LM3556:
191  reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode;
192  ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val);
193  if (ret < 0)
194  goto out;
195  break;
196  default:
197  return -ENODATA;
198  }
199 
200  return ret;
201 out:
202  dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
203  return ret;
204 }
205 
206 /* chip control */
207 static void lm355x_control(struct lm355x_chip_data *chip,
208  u8 brightness, enum lm355x_mode opmode)
209 {
210  int ret;
211  unsigned int reg_val;
212  struct lm355x_platform_data *pdata = chip->pdata;
213  struct lm355x_reg_data *preg = chip->regs;
214 
215  ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag);
216  if (ret < 0)
217  goto out;
218  if (chip->last_flag & preg[REG_FLAG].mask)
219  dev_info(chip->dev, "%s Last FLAG is 0x%x\n",
220  lm355x_name[chip->type],
221  chip->last_flag & preg[REG_FLAG].mask);
222  /* brightness 0 means shutdown */
223  if (!brightness)
224  opmode = MODE_SHDN;
225 
226  switch (opmode) {
227  case MODE_TORCH:
228  ret =
230  preg[REG_TORCH_CTRL].mask,
231  (brightness - 1)
232  << preg[REG_TORCH_CTRL].shift);
233  if (ret < 0)
234  goto out;
235 
236  if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) {
237  ret =
239  preg[REG_TORCH_CFG].regno,
240  preg[REG_TORCH_CFG].mask,
241  0x01 <<
242  preg[REG_TORCH_CFG].shift);
243  if (ret < 0)
244  goto out;
245  opmode = MODE_SHDN;
246  dev_info(chip->dev,
247  "torch brt is set - ext. torch pin mode\n");
248  }
249  break;
250 
251  case MODE_FLASH:
252 
253  ret =
255  preg[REG_FLASH_CTRL].mask,
256  (brightness - 1)
257  << preg[REG_FLASH_CTRL].shift);
258  if (ret < 0)
259  goto out;
260 
261  if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) {
262  if (chip->type == CHIP_LM3554)
263  reg_val = 0x00;
264  else
265  reg_val = 0x01;
266  ret =
268  preg[REG_STROBE_CFG].regno,
269  preg[REG_STROBE_CFG].mask,
270  reg_val <<
271  preg[REG_STROBE_CFG].shift);
272  if (ret < 0)
273  goto out;
274  opmode = MODE_SHDN;
275  dev_info(chip->dev,
276  "flash brt is set - ext. strobe pin mode\n");
277  }
278  break;
279 
280  case MODE_INDIC:
281  ret =
283  preg[REG_INDI_CTRL].mask,
284  (brightness - 1)
285  << preg[REG_INDI_CTRL].shift);
286  if (ret < 0)
287  goto out;
288 
289  if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) {
290  ret =
292  preg[REG_INDI_CFG].regno,
293  preg[REG_INDI_CFG].mask,
294  0x01 <<
295  preg[REG_INDI_CFG].shift);
296  if (ret < 0)
297  goto out;
298  opmode = MODE_SHDN;
299  }
300  break;
301  case MODE_SHDN:
302  break;
303  default:
304  return;
305  }
306  /* operation mode control */
307  ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno,
308  preg[REG_OPMODE].mask,
309  opmode << preg[REG_OPMODE].shift);
310  if (ret < 0)
311  goto out;
312  return;
313 out:
314  dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
315  return;
316 }
317 
318 /* torch */
319 static void lm355x_deferred_torch_brightness_set(struct work_struct *work)
320 {
321  struct lm355x_chip_data *chip =
323 
324  mutex_lock(&chip->lock);
325  lm355x_control(chip, chip->br_torch, MODE_TORCH);
326  mutex_unlock(&chip->lock);
327 }
328 
329 static void lm355x_torch_brightness_set(struct led_classdev *cdev,
330  enum led_brightness brightness)
331 {
332  struct lm355x_chip_data *chip =
334 
335  chip->br_torch = brightness;
336  schedule_work(&chip->work_torch);
337 }
338 
339 /* flash */
340 static void lm355x_deferred_strobe_brightness_set(struct work_struct *work)
341 {
342  struct lm355x_chip_data *chip =
344 
345  mutex_lock(&chip->lock);
346  lm355x_control(chip, chip->br_flash, MODE_FLASH);
347  mutex_unlock(&chip->lock);
348 }
349 
350 static void lm355x_strobe_brightness_set(struct led_classdev *cdev,
351  enum led_brightness brightness)
352 {
353  struct lm355x_chip_data *chip =
355 
356  chip->br_flash = brightness;
357  schedule_work(&chip->work_flash);
358 }
359 
360 /* indicator */
361 static void lm355x_deferred_indicator_brightness_set(struct work_struct *work)
362 {
363  struct lm355x_chip_data *chip =
365 
366  mutex_lock(&chip->lock);
367  lm355x_control(chip, chip->br_indicator, MODE_INDIC);
368  mutex_unlock(&chip->lock);
369 }
370 
371 static void lm355x_indicator_brightness_set(struct led_classdev *cdev,
372  enum led_brightness brightness)
373 {
374  struct lm355x_chip_data *chip =
376 
377  chip->br_indicator = brightness;
379 }
380 
381 /* indicator pattern only for lm3556*/
382 static ssize_t lm3556_indicator_pattern_store(struct device *dev,
383  struct device_attribute *devAttr,
384  const char *buf, size_t size)
385 {
386  ssize_t ret;
387  struct led_classdev *led_cdev = dev_get_drvdata(dev);
388  struct lm355x_chip_data *chip =
389  container_of(led_cdev, struct lm355x_chip_data, cdev_indicator);
390  unsigned int state;
391 
392  ret = kstrtouint(buf, 10, &state);
393  if (ret)
394  goto out;
395  if (state > INDIC_PATTERN_SIZE - 1)
396  state = INDIC_PATTERN_SIZE - 1;
397 
398  ret = regmap_write(chip->regmap, 0x04,
399  indicator_pattern[state].blinking);
400  if (ret < 0)
401  goto out;
402 
403  ret = regmap_write(chip->regmap, 0x05,
404  indicator_pattern[state].period_cnt);
405  if (ret < 0)
406  goto out;
407 
408  return size;
409 out:
410  dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
411  return size;
412 }
413 
414 static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
415 
416 static const struct regmap_config lm355x_regmap = {
417  .reg_bits = 8,
418  .val_bits = 8,
419  .max_register = 0xFF,
420 };
421 
422 /* module initialize */
423 static int __devinit lm355x_probe(struct i2c_client *client,
424  const struct i2c_device_id *id)
425 {
426  struct lm355x_platform_data *pdata = client->dev.platform_data;
427  struct lm355x_chip_data *chip;
428 
429  int err;
430 
431  if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
432  dev_err(&client->dev, "i2c functionality check fail.\n");
433  return -EOPNOTSUPP;
434  }
435 
436  if (pdata == NULL) {
437  dev_err(&client->dev, "needs Platform Data.\n");
438  return -ENODATA;
439  }
440 
441  chip = devm_kzalloc(&client->dev,
442  sizeof(struct lm355x_chip_data), GFP_KERNEL);
443  if (!chip)
444  return -ENOMEM;
445 
446  chip->dev = &client->dev;
447  chip->type = id->driver_data;
448  switch (id->driver_data) {
449  case CHIP_LM3554:
450  chip->regs = lm3554_regs;
451  break;
452  case CHIP_LM3556:
453  chip->regs = lm3556_regs;
454  break;
455  default:
456  return -ENOSYS;
457  }
458  chip->pdata = pdata;
459 
460  chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap);
461  if (IS_ERR(chip->regmap)) {
462  err = PTR_ERR(chip->regmap);
463  dev_err(&client->dev,
464  "Failed to allocate register map: %d\n", err);
465  return err;
466  }
467 
468  mutex_init(&chip->lock);
469  i2c_set_clientdata(client, chip);
470 
471  err = lm355x_chip_init(chip);
472  if (err < 0)
473  goto err_out;
474 
475  /* flash */
476  INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set);
477  chip->cdev_flash.name = "flash";
478  chip->cdev_flash.max_brightness = 16;
479  chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
480  err = led_classdev_register((struct device *)
481  &client->dev, &chip->cdev_flash);
482  if (err < 0)
483  goto err_out;
484  /* torch */
485  INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set);
486  chip->cdev_torch.name = "torch";
487  chip->cdev_torch.max_brightness = 8;
488  chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
489  err = led_classdev_register((struct device *)
490  &client->dev, &chip->cdev_torch);
491  if (err < 0)
492  goto err_create_torch_file;
493  /* indicator */
494  INIT_WORK(&chip->work_indicator,
495  lm355x_deferred_indicator_brightness_set);
496  chip->cdev_indicator.name = "indicator";
497  if (id->driver_data == CHIP_LM3554)
498  chip->cdev_indicator.max_brightness = 4;
499  else
500  chip->cdev_indicator.max_brightness = 8;
501  chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
502  err = led_classdev_register((struct device *)
503  &client->dev, &chip->cdev_indicator);
504  if (err < 0)
505  goto err_create_indicator_file;
506  /* indicator pattern control only for LM3554 */
507  if (id->driver_data == CHIP_LM3556) {
508  err =
510  &dev_attr_pattern);
511  if (err < 0)
512  goto err_create_pattern_file;
513  }
514 
515  dev_info(&client->dev, "%s is initialized\n",
516  lm355x_name[id->driver_data]);
517  return 0;
518 
519 err_create_pattern_file:
521 err_create_indicator_file:
523 err_create_torch_file:
525 err_out:
526  return err;
527 }
528 
529 static int __devexit lm355x_remove(struct i2c_client *client)
530 {
531  struct lm355x_chip_data *chip = i2c_get_clientdata(client);
532  struct lm355x_reg_data *preg = chip->regs;
533 
534  regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
535  if (chip->type == CHIP_LM3556)
536  device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
538  flush_work(&chip->work_indicator);
540  flush_work(&chip->work_torch);
542  flush_work(&chip->work_flash);
543  dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]);
544 
545  return 0;
546 }
547 
548 static const struct i2c_device_id lm355x_id[] = {
551  {}
552 };
553 
554 MODULE_DEVICE_TABLE(i2c, lm355x_id);
555 
556 static struct i2c_driver lm355x_i2c_driver = {
557  .driver = {
558  .name = LM355x_NAME,
559  .owner = THIS_MODULE,
560  .pm = NULL,
561  },
562  .probe = lm355x_probe,
563  .remove = __devexit_p(lm355x_remove),
564  .id_table = lm355x_id,
565 };
566 
567 module_i2c_driver(lm355x_i2c_driver);
568 
569 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x");
570 MODULE_AUTHOR("Daniel Jeong <[email protected]>");
571 MODULE_AUTHOR("G.Shark Jeong <[email protected]>");
572 MODULE_LICENSE("GPL v2");