da9052_bl.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Backlight Driver for Dialog DA9052 PMICs
  4. *
  5. * Copyright(c) 2012 Dialog Semiconductor Ltd.
  6. *
  7. * Author: David Dajun Chen <dchen@diasemi.com>
  8. */
  9. #include <linux/backlight.h>
  10. #include <linux/delay.h>
  11. #include <linux/fb.h>
  12. #include <linux/module.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/mfd/da9052/da9052.h>
  15. #include <linux/mfd/da9052/reg.h>
  16. #define DA9052_MAX_BRIGHTNESS 0xFF
  17. enum {
  18. DA9052_WLEDS_OFF,
  19. DA9052_WLEDS_ON,
  20. };
  21. enum {
  22. DA9052_TYPE_WLED1,
  23. DA9052_TYPE_WLED2,
  24. DA9052_TYPE_WLED3,
  25. };
  26. static const unsigned char wled_bank[] = {
  27. DA9052_LED1_CONF_REG,
  28. DA9052_LED2_CONF_REG,
  29. DA9052_LED3_CONF_REG,
  30. };
  31. struct da9052_bl {
  32. struct da9052 *da9052;
  33. uint brightness;
  34. uint state;
  35. uint led_reg;
  36. };
  37. static int da9052_adjust_wled_brightness(struct da9052_bl *wleds)
  38. {
  39. unsigned char boost_en;
  40. unsigned char i_sink;
  41. int ret;
  42. boost_en = 0x3F;
  43. i_sink = 0xFF;
  44. if (wleds->state == DA9052_WLEDS_OFF) {
  45. boost_en = 0x00;
  46. i_sink = 0x00;
  47. }
  48. ret = da9052_reg_write(wleds->da9052, DA9052_BOOST_REG, boost_en);
  49. if (ret < 0)
  50. return ret;
  51. ret = da9052_reg_write(wleds->da9052, DA9052_LED_CONT_REG, i_sink);
  52. if (ret < 0)
  53. return ret;
  54. ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], 0x0);
  55. if (ret < 0)
  56. return ret;
  57. usleep_range(10000, 11000);
  58. if (wleds->brightness) {
  59. ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg],
  60. wleds->brightness);
  61. if (ret < 0)
  62. return ret;
  63. }
  64. return 0;
  65. }
  66. static int da9052_backlight_update_status(struct backlight_device *bl)
  67. {
  68. int brightness = bl->props.brightness;
  69. struct da9052_bl *wleds = bl_get_data(bl);
  70. wleds->brightness = brightness;
  71. wleds->state = DA9052_WLEDS_ON;
  72. return da9052_adjust_wled_brightness(wleds);
  73. }
  74. static int da9052_backlight_get_brightness(struct backlight_device *bl)
  75. {
  76. struct da9052_bl *wleds = bl_get_data(bl);
  77. return wleds->brightness;
  78. }
  79. static const struct backlight_ops da9052_backlight_ops = {
  80. .update_status = da9052_backlight_update_status,
  81. .get_brightness = da9052_backlight_get_brightness,
  82. };
  83. static int da9052_backlight_probe(struct platform_device *pdev)
  84. {
  85. struct backlight_device *bl;
  86. struct backlight_properties props;
  87. struct da9052_bl *wleds;
  88. wleds = devm_kzalloc(&pdev->dev, sizeof(struct da9052_bl), GFP_KERNEL);
  89. if (!wleds)
  90. return -ENOMEM;
  91. wleds->da9052 = dev_get_drvdata(pdev->dev.parent);
  92. wleds->brightness = 0;
  93. wleds->led_reg = platform_get_device_id(pdev)->driver_data;
  94. wleds->state = DA9052_WLEDS_OFF;
  95. memset(&props, 0, sizeof(struct backlight_properties));
  96. props.type = BACKLIGHT_RAW;
  97. props.max_brightness = DA9052_MAX_BRIGHTNESS;
  98. bl = devm_backlight_device_register(&pdev->dev, pdev->name,
  99. wleds->da9052->dev, wleds,
  100. &da9052_backlight_ops, &props);
  101. if (IS_ERR(bl)) {
  102. dev_err(&pdev->dev, "Failed to register backlight\n");
  103. return PTR_ERR(bl);
  104. }
  105. bl->props.max_brightness = DA9052_MAX_BRIGHTNESS;
  106. bl->props.brightness = 0;
  107. platform_set_drvdata(pdev, bl);
  108. return da9052_adjust_wled_brightness(wleds);
  109. }
  110. static void da9052_backlight_remove(struct platform_device *pdev)
  111. {
  112. struct backlight_device *bl = platform_get_drvdata(pdev);
  113. struct da9052_bl *wleds = bl_get_data(bl);
  114. wleds->brightness = 0;
  115. wleds->state = DA9052_WLEDS_OFF;
  116. da9052_adjust_wled_brightness(wleds);
  117. }
  118. static const struct platform_device_id da9052_wled_ids[] = {
  119. {
  120. .name = "da9052-wled1",
  121. .driver_data = DA9052_TYPE_WLED1,
  122. },
  123. {
  124. .name = "da9052-wled2",
  125. .driver_data = DA9052_TYPE_WLED2,
  126. },
  127. {
  128. .name = "da9052-wled3",
  129. .driver_data = DA9052_TYPE_WLED3,
  130. },
  131. { },
  132. };
  133. MODULE_DEVICE_TABLE(platform, da9052_wled_ids);
  134. static struct platform_driver da9052_wled_driver = {
  135. .probe = da9052_backlight_probe,
  136. .remove_new = da9052_backlight_remove,
  137. .id_table = da9052_wled_ids,
  138. .driver = {
  139. .name = "da9052-wled",
  140. },
  141. };
  142. module_platform_driver(da9052_wled_driver);
  143. MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
  144. MODULE_DESCRIPTION("Backlight driver for DA9052 PMIC");
  145. MODULE_LICENSE("GPL");