leds-lp3952.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * LED driver for TI lp3952 controller
  3. *
  4. * Copyright (C) 2016, DAQRI, LLC.
  5. * Author: Tony Makkiel <tony.makkiel@daqri.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. */
  12. #include <linux/acpi.h>
  13. #include <linux/delay.h>
  14. #include <linux/gpio.h>
  15. #include <linux/i2c.h>
  16. #include <linux/io.h>
  17. #include <linux/kernel.h>
  18. #include <linux/leds.h>
  19. #include <linux/leds-lp3952.h>
  20. #include <linux/module.h>
  21. #include <linux/notifier.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/pm.h>
  24. #include <linux/reboot.h>
  25. #include <linux/regmap.h>
  26. static int lp3952_register_write(struct i2c_client *client, u8 reg, u8 val)
  27. {
  28. int ret;
  29. struct lp3952_led_array *priv = i2c_get_clientdata(client);
  30. ret = regmap_write(priv->regmap, reg, val);
  31. if (ret)
  32. dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n",
  33. __func__, reg, val, ret);
  34. return ret;
  35. }
  36. static void lp3952_on_off(struct lp3952_led_array *priv,
  37. enum lp3952_leds led_id, bool on)
  38. {
  39. int ret, val;
  40. dev_dbg(&priv->client->dev, "%s LED %d to %d\n", __func__, led_id, on);
  41. val = 1 << led_id;
  42. if (led_id == LP3952_LED_ALL)
  43. val = LP3952_LED_MASK_ALL;
  44. ret = regmap_update_bits(priv->regmap, LP3952_REG_LED_CTRL, val,
  45. on ? val : 0);
  46. if (ret)
  47. dev_err(&priv->client->dev, "%s, Error %d\n", __func__, ret);
  48. }
  49. /*
  50. * Using Imax to control brightness. There are 4 possible
  51. * setting 25, 50, 75 and 100 % of Imax. Possible values are
  52. * values 0-4. 0 meaning turn off.
  53. */
  54. static int lp3952_set_brightness(struct led_classdev *cdev,
  55. enum led_brightness value)
  56. {
  57. unsigned int reg, shift_val;
  58. struct lp3952_ctrl_hdl *led = container_of(cdev,
  59. struct lp3952_ctrl_hdl,
  60. cdev);
  61. struct lp3952_led_array *priv = (struct lp3952_led_array *)led->priv;
  62. dev_dbg(cdev->dev, "Brightness request: %d on %d\n", value,
  63. led->channel);
  64. if (value == LED_OFF) {
  65. lp3952_on_off(priv, led->channel, false);
  66. return 0;
  67. }
  68. if (led->channel > LP3952_RED_1) {
  69. dev_err(cdev->dev, " %s Invalid LED requested", __func__);
  70. return -EINVAL;
  71. }
  72. if (led->channel >= LP3952_BLUE_1) {
  73. reg = LP3952_REG_RGB1_MAX_I_CTRL;
  74. shift_val = (led->channel - LP3952_BLUE_1) * 2;
  75. } else {
  76. reg = LP3952_REG_RGB2_MAX_I_CTRL;
  77. shift_val = led->channel * 2;
  78. }
  79. /* Enable the LED in case it is not enabled already */
  80. lp3952_on_off(priv, led->channel, true);
  81. return regmap_update_bits(priv->regmap, reg, 3 << shift_val,
  82. --value << shift_val);
  83. }
  84. static int lp3952_get_label(struct device *dev, const char *label, char *dest)
  85. {
  86. int ret;
  87. const char *str;
  88. ret = device_property_read_string(dev, label, &str);
  89. if (!ret)
  90. strncpy(dest, str, LP3952_LABEL_MAX_LEN);
  91. return ret;
  92. }
  93. static int lp3952_register_led_classdev(struct lp3952_led_array *priv)
  94. {
  95. int i, acpi_ret, ret = -ENODEV;
  96. static const char *led_name_hdl[LP3952_LED_ALL] = {
  97. "blue2",
  98. "green2",
  99. "red2",
  100. "blue1",
  101. "green1",
  102. "red1"
  103. };
  104. for (i = 0; i < LP3952_LED_ALL; i++) {
  105. acpi_ret = lp3952_get_label(&priv->client->dev, led_name_hdl[i],
  106. priv->leds[i].name);
  107. if (acpi_ret)
  108. continue;
  109. priv->leds[i].cdev.name = priv->leds[i].name;
  110. priv->leds[i].cdev.brightness = LED_OFF;
  111. priv->leds[i].cdev.max_brightness = LP3952_BRIGHT_MAX;
  112. priv->leds[i].cdev.brightness_set_blocking =
  113. lp3952_set_brightness;
  114. priv->leds[i].channel = i;
  115. priv->leds[i].priv = priv;
  116. ret = devm_led_classdev_register(&priv->client->dev,
  117. &priv->leds[i].cdev);
  118. if (ret < 0) {
  119. dev_err(&priv->client->dev,
  120. "couldn't register LED %s\n",
  121. priv->leds[i].cdev.name);
  122. break;
  123. }
  124. }
  125. return ret;
  126. }
  127. static int lp3952_set_pattern_gen_cmd(struct lp3952_led_array *priv,
  128. u8 cmd_index, u8 r, u8 g, u8 b,
  129. enum lp3952_tt tt, enum lp3952_cet cet)
  130. {
  131. int ret;
  132. struct ptrn_gen_cmd line = {
  133. {
  134. {
  135. .r = r,
  136. .g = g,
  137. .b = b,
  138. .cet = cet,
  139. .tt = tt
  140. }
  141. }
  142. };
  143. if (cmd_index >= LP3952_CMD_REG_COUNT)
  144. return -EINVAL;
  145. ret = lp3952_register_write(priv->client,
  146. LP3952_REG_CMD_0 + cmd_index * 2,
  147. line.bytes.msb);
  148. if (ret)
  149. return ret;
  150. return lp3952_register_write(priv->client,
  151. LP3952_REG_CMD_0 + cmd_index * 2 + 1,
  152. line.bytes.lsb);
  153. }
  154. static int lp3952_configure(struct lp3952_led_array *priv)
  155. {
  156. int ret;
  157. /* Disable any LEDs on from any previous conf. */
  158. ret = lp3952_register_write(priv->client, LP3952_REG_LED_CTRL, 0);
  159. if (ret)
  160. return ret;
  161. /* enable rgb patter, loop */
  162. ret = lp3952_register_write(priv->client, LP3952_REG_PAT_GEN_CTRL,
  163. LP3952_PATRN_LOOP | LP3952_PATRN_GEN_EN);
  164. if (ret)
  165. return ret;
  166. /* Update Bit 6 (Active mode), Select both Led sets, Bit [1:0] */
  167. ret = lp3952_register_write(priv->client, LP3952_REG_ENABLES,
  168. LP3952_ACTIVE_MODE | LP3952_INT_B00ST_LDR);
  169. if (ret)
  170. return ret;
  171. /* Set Cmd1 for RGB intensity,cmd and transition time */
  172. return lp3952_set_pattern_gen_cmd(priv, 0, I46, I71, I100, TT0,
  173. CET197);
  174. }
  175. static const struct regmap_config lp3952_regmap = {
  176. .reg_bits = 8,
  177. .val_bits = 8,
  178. .max_register = REG_MAX,
  179. .cache_type = REGCACHE_RBTREE,
  180. };
  181. static int lp3952_probe(struct i2c_client *client,
  182. const struct i2c_device_id *id)
  183. {
  184. int status;
  185. struct lp3952_led_array *priv;
  186. priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
  187. if (!priv)
  188. return -ENOMEM;
  189. priv->client = client;
  190. priv->enable_gpio = devm_gpiod_get(&client->dev, "nrst",
  191. GPIOD_OUT_HIGH);
  192. if (IS_ERR(priv->enable_gpio)) {
  193. status = PTR_ERR(priv->enable_gpio);
  194. dev_err(&client->dev, "Failed to enable gpio: %d\n", status);
  195. return status;
  196. }
  197. priv->regmap = devm_regmap_init_i2c(client, &lp3952_regmap);
  198. if (IS_ERR(priv->regmap)) {
  199. int err = PTR_ERR(priv->regmap);
  200. dev_err(&client->dev, "Failed to allocate register map: %d\n",
  201. err);
  202. return err;
  203. }
  204. i2c_set_clientdata(client, priv);
  205. status = lp3952_configure(priv);
  206. if (status) {
  207. dev_err(&client->dev, "Probe failed. Device not found (%d)\n",
  208. status);
  209. return status;
  210. }
  211. status = lp3952_register_led_classdev(priv);
  212. if (status) {
  213. dev_err(&client->dev, "Unable to register led_classdev: %d\n",
  214. status);
  215. return status;
  216. }
  217. return 0;
  218. }
  219. static int lp3952_remove(struct i2c_client *client)
  220. {
  221. struct lp3952_led_array *priv;
  222. priv = i2c_get_clientdata(client);
  223. lp3952_on_off(priv, LP3952_LED_ALL, false);
  224. gpiod_set_value(priv->enable_gpio, 0);
  225. return 0;
  226. }
  227. static const struct i2c_device_id lp3952_id[] = {
  228. {LP3952_NAME, 0},
  229. {}
  230. };
  231. #ifdef CONFIG_ACPI
  232. static const struct acpi_device_id lp3952_acpi_match[] = {
  233. {"TXNW3952", 0},
  234. {}
  235. };
  236. MODULE_DEVICE_TABLE(acpi, lp3952_acpi_match);
  237. #endif
  238. static struct i2c_driver lp3952_i2c_driver = {
  239. .driver = {
  240. .name = LP3952_NAME,
  241. .acpi_match_table = ACPI_PTR(lp3952_acpi_match),
  242. },
  243. .probe = lp3952_probe,
  244. .remove = lp3952_remove,
  245. .id_table = lp3952_id,
  246. };
  247. module_i2c_driver(lp3952_i2c_driver);
  248. MODULE_AUTHOR("Tony Makkiel <tony.makkiel@daqri.com>");
  249. MODULE_DESCRIPTION("lp3952 I2C LED controller driver");
  250. MODULE_LICENSE("GPL v2");