backlight.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rtthread.h>
  11. #define DBG_TAG "rtdm.backlight"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #include <stdlib.h>
  15. #include <drivers/core/dm.h>
  16. #include <drivers/backlight.h>
  17. static struct rt_dm_ida backlight_ida = RT_DM_IDA_INIT(GRAPHIC_BACKLIGHT);
  18. static rt_ssize_t _backlight_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  19. {
  20. rt_ssize_t res;
  21. int brightness_len;
  22. rt_uint32_t brightness;
  23. char string[sizeof("4294967295")];
  24. struct rt_backlight_device *bl = rt_container_of(dev, struct rt_backlight_device, parent);
  25. if ((res = rt_backlight_get_brightness(bl, &brightness)))
  26. {
  27. return res;
  28. }
  29. brightness_len = rt_sprintf(string, "%u", brightness);
  30. if (pos < brightness_len)
  31. {
  32. size = rt_min_t(rt_size_t, size, brightness_len - pos);
  33. rt_strncpy(buffer, &string[pos], size);
  34. return size;
  35. }
  36. else
  37. {
  38. return 0;
  39. }
  40. }
  41. static rt_ssize_t _backlight_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  42. {
  43. rt_ssize_t res;
  44. rt_uint32_t brightness = atoi(buffer);
  45. struct rt_backlight_device *bl = rt_container_of(dev, struct rt_backlight_device, parent);
  46. if (brightness > bl->props.max_brightness)
  47. {
  48. LOG_D("%s: brightness(%u) > max_brightness(%u)",
  49. rt_dm_dev_get_name(dev), brightness, bl->props.max_brightness);
  50. return -RT_EINVAL;
  51. }
  52. if ((res = rt_backlight_set_brightness(bl, brightness)))
  53. {
  54. return res;
  55. }
  56. LOG_D("%s: brightness to %u", rt_dm_dev_get_name(dev), brightness);
  57. return size;
  58. }
  59. #ifdef RT_USING_DEVICE_OPS
  60. const static struct rt_device_ops _backlight_ops =
  61. {
  62. .read = _backlight_read,
  63. .write = _backlight_write,
  64. };
  65. #endif
  66. rt_err_t rt_backlight_register(struct rt_backlight_device *bl)
  67. {
  68. rt_err_t err;
  69. int device_id;
  70. const char *dev_name;
  71. if (!bl || !bl->ops)
  72. {
  73. return -RT_EINVAL;
  74. }
  75. if ((device_id = rt_dm_ida_alloc(&backlight_ida)) < 0)
  76. {
  77. return -RT_EFULL;
  78. }
  79. rt_dm_dev_set_name(&bl->parent, "backlight%u", device_id);
  80. dev_name = rt_dm_dev_get_name(&bl->parent);
  81. rt_mutex_init(&bl->lock, dev_name, RT_IPC_FLAG_PRIO);
  82. bl->parent.type = RT_Device_Class_Char;
  83. #ifdef RT_USING_DEVICE_OPS
  84. bl->parent.ops = &_backlight_ops;
  85. #else
  86. bl->parent.read = _backlight_read;
  87. bl->parent.write = _backlight_write;
  88. #endif
  89. bl->parent.master_id = backlight_ida.master_id;
  90. bl->parent.device_id = device_id;
  91. if ((err = rt_device_register(&bl->parent, dev_name, RT_DEVICE_FLAG_RDWR)))
  92. {
  93. rt_dm_ida_free(&backlight_ida, device_id);
  94. return err;
  95. }
  96. return RT_EOK;
  97. }
  98. rt_err_t rt_backlight_unregister(struct rt_backlight_device *bl)
  99. {
  100. if (!bl)
  101. {
  102. return -RT_EINVAL;
  103. }
  104. rt_backlight_set_power(bl, RT_BACKLIGHT_POWER_POWERDOWN);
  105. rt_dm_ida_free(&backlight_ida, bl->parent.device_id);
  106. rt_device_unregister(&bl->parent);
  107. return RT_EOK;
  108. }
  109. rt_err_t rt_backlight_set_power(struct rt_backlight_device *bl, enum rt_backlight_power power)
  110. {
  111. rt_err_t err;
  112. enum rt_backlight_power old_power;
  113. if (!bl || power >= RT_BACKLIGHT_POWER_NR)
  114. {
  115. return -RT_EINVAL;
  116. }
  117. rt_mutex_take(&bl->lock, RT_WAITING_FOREVER);
  118. old_power = bl->props.power;
  119. bl->props.power = power;
  120. if ((err = bl->ops->update_status(bl)))
  121. {
  122. bl->props.power = old_power;
  123. }
  124. rt_mutex_release(&bl->lock);
  125. return err;
  126. }
  127. rt_err_t rt_backlight_get_power(struct rt_backlight_device *bl, enum rt_backlight_power *out_power)
  128. {
  129. if (!bl || !out_power)
  130. {
  131. return -RT_EINVAL;
  132. }
  133. rt_mutex_take(&bl->lock, RT_WAITING_FOREVER);
  134. *out_power = bl->props.power;
  135. rt_mutex_release(&bl->lock);
  136. return RT_EOK;
  137. }
  138. rt_err_t rt_backlight_set_brightness(struct rt_backlight_device *bl, rt_uint32_t brightness)
  139. {
  140. rt_err_t err;
  141. rt_uint32_t old_brightness;
  142. if (!bl || brightness > bl->props.max_brightness)
  143. {
  144. return -RT_EINVAL;
  145. }
  146. rt_mutex_take(&bl->lock, RT_WAITING_FOREVER);
  147. old_brightness = bl->props.brightness;
  148. bl->props.brightness = brightness;
  149. if ((err = bl->ops->update_status(bl)))
  150. {
  151. bl->props.brightness = old_brightness;
  152. }
  153. rt_mutex_release(&bl->lock);
  154. return err;
  155. }
  156. rt_err_t rt_backlight_get_brightness(struct rt_backlight_device *bl, rt_uint32_t *out_brightness)
  157. {
  158. rt_err_t err;
  159. if (!bl || !out_brightness)
  160. {
  161. return -RT_EINVAL;
  162. }
  163. rt_mutex_take(&bl->lock, RT_WAITING_FOREVER);
  164. if (bl->ops->get_brightness)
  165. {
  166. err = bl->ops->get_brightness(bl, out_brightness);
  167. }
  168. else
  169. {
  170. *out_brightness = rt_backlight_power_brightness(bl);
  171. err = RT_EOK;
  172. }
  173. rt_mutex_release(&bl->lock);
  174. return err;
  175. }