rockchip_drm_psr.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  3. * Author: Yakir Yang <ykk@rock-chips.com>
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <drm/drmP.h>
  15. #include <drm/drm_crtc_helper.h>
  16. #include "rockchip_drm_drv.h"
  17. #include "rockchip_drm_psr.h"
  18. #define PSR_FLUSH_TIMEOUT_MS 100
  19. struct psr_drv {
  20. struct list_head list;
  21. struct drm_encoder *encoder;
  22. struct mutex lock;
  23. int inhibit_count;
  24. bool enabled;
  25. struct delayed_work flush_work;
  26. int (*set)(struct drm_encoder *encoder, bool enable);
  27. };
  28. static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
  29. {
  30. struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
  31. struct psr_drv *psr;
  32. mutex_lock(&drm_drv->psr_list_lock);
  33. list_for_each_entry(psr, &drm_drv->psr_list, list) {
  34. if (psr->encoder == encoder)
  35. goto out;
  36. }
  37. psr = ERR_PTR(-ENODEV);
  38. out:
  39. mutex_unlock(&drm_drv->psr_list_lock);
  40. return psr;
  41. }
  42. static int psr_set_state_locked(struct psr_drv *psr, bool enable)
  43. {
  44. int ret;
  45. if (psr->inhibit_count > 0)
  46. return -EINVAL;
  47. if (enable == psr->enabled)
  48. return 0;
  49. ret = psr->set(psr->encoder, enable);
  50. if (ret)
  51. return ret;
  52. psr->enabled = enable;
  53. return 0;
  54. }
  55. static void psr_flush_handler(struct work_struct *work)
  56. {
  57. struct psr_drv *psr = container_of(to_delayed_work(work),
  58. struct psr_drv, flush_work);
  59. mutex_lock(&psr->lock);
  60. psr_set_state_locked(psr, true);
  61. mutex_unlock(&psr->lock);
  62. }
  63. /**
  64. * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder
  65. * @encoder: encoder to obtain the PSR encoder
  66. *
  67. * Decrements PSR inhibit count on given encoder. Should be called only
  68. * for a PSR inhibit count increment done before. If PSR inhibit counter
  69. * reaches zero, PSR flush work is scheduled to make the hardware enter
  70. * PSR mode in PSR_FLUSH_TIMEOUT_MS.
  71. *
  72. * Returns:
  73. * Zero on success, negative errno on failure.
  74. */
  75. int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder)
  76. {
  77. struct psr_drv *psr = find_psr_by_encoder(encoder);
  78. if (IS_ERR(psr))
  79. return PTR_ERR(psr);
  80. mutex_lock(&psr->lock);
  81. --psr->inhibit_count;
  82. WARN_ON(psr->inhibit_count < 0);
  83. if (!psr->inhibit_count)
  84. mod_delayed_work(system_wq, &psr->flush_work,
  85. PSR_FLUSH_TIMEOUT_MS);
  86. mutex_unlock(&psr->lock);
  87. return 0;
  88. }
  89. EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put);
  90. /**
  91. * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
  92. * @encoder: encoder to obtain the PSR encoder
  93. *
  94. * Increments PSR inhibit count on given encoder. This function guarantees
  95. * that after it returns PSR is turned off on given encoder and no PSR-related
  96. * hardware state change occurs at least until a matching call to
  97. * rockchip_drm_psr_inhibit_put() is done.
  98. *
  99. * Returns:
  100. * Zero on success, negative errno on failure.
  101. */
  102. int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder)
  103. {
  104. struct psr_drv *psr = find_psr_by_encoder(encoder);
  105. if (IS_ERR(psr))
  106. return PTR_ERR(psr);
  107. mutex_lock(&psr->lock);
  108. psr_set_state_locked(psr, false);
  109. ++psr->inhibit_count;
  110. mutex_unlock(&psr->lock);
  111. cancel_delayed_work_sync(&psr->flush_work);
  112. return 0;
  113. }
  114. EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get);
  115. static void rockchip_drm_do_flush(struct psr_drv *psr)
  116. {
  117. cancel_delayed_work_sync(&psr->flush_work);
  118. mutex_lock(&psr->lock);
  119. if (!psr_set_state_locked(psr, false))
  120. mod_delayed_work(system_wq, &psr->flush_work,
  121. PSR_FLUSH_TIMEOUT_MS);
  122. mutex_unlock(&psr->lock);
  123. }
  124. /**
  125. * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
  126. * @dev: drm device
  127. *
  128. * Disable the PSR function for all registered encoders, and then enable the
  129. * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
  130. * changed during flush time, then keep the state no change after flush
  131. * timeout.
  132. *
  133. * Returns:
  134. * Zero on success, negative errno on failure.
  135. */
  136. void rockchip_drm_psr_flush_all(struct drm_device *dev)
  137. {
  138. struct rockchip_drm_private *drm_drv = dev->dev_private;
  139. struct psr_drv *psr;
  140. mutex_lock(&drm_drv->psr_list_lock);
  141. list_for_each_entry(psr, &drm_drv->psr_list, list)
  142. rockchip_drm_do_flush(psr);
  143. mutex_unlock(&drm_drv->psr_list_lock);
  144. }
  145. EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
  146. /**
  147. * rockchip_drm_psr_register - register encoder to psr driver
  148. * @encoder: encoder that obtain the PSR function
  149. * @psr_set: call back to set PSR state
  150. *
  151. * The function returns with PSR inhibit counter initialized with one
  152. * and the caller (typically encoder driver) needs to call
  153. * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR
  154. * enable request.
  155. *
  156. * Returns:
  157. * Zero on success, negative errno on failure.
  158. */
  159. int rockchip_drm_psr_register(struct drm_encoder *encoder,
  160. int (*psr_set)(struct drm_encoder *, bool enable))
  161. {
  162. struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
  163. struct psr_drv *psr;
  164. if (!encoder || !psr_set)
  165. return -EINVAL;
  166. psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
  167. if (!psr)
  168. return -ENOMEM;
  169. INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
  170. mutex_init(&psr->lock);
  171. psr->inhibit_count = 1;
  172. psr->enabled = false;
  173. psr->encoder = encoder;
  174. psr->set = psr_set;
  175. mutex_lock(&drm_drv->psr_list_lock);
  176. list_add_tail(&psr->list, &drm_drv->psr_list);
  177. mutex_unlock(&drm_drv->psr_list_lock);
  178. return 0;
  179. }
  180. EXPORT_SYMBOL(rockchip_drm_psr_register);
  181. /**
  182. * rockchip_drm_psr_unregister - unregister encoder to psr driver
  183. * @encoder: encoder that obtain the PSR function
  184. * @psr_set: call back to set PSR state
  185. *
  186. * It is expected that the PSR inhibit counter is 1 when this function is
  187. * called, which corresponds to a state when related encoder has been
  188. * disconnected from any CRTCs and its driver called
  189. * rockchip_drm_psr_inhibit_get() to stop the PSR logic.
  190. *
  191. * Returns:
  192. * Zero on success, negative errno on failure.
  193. */
  194. void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
  195. {
  196. struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
  197. struct psr_drv *psr, *n;
  198. mutex_lock(&drm_drv->psr_list_lock);
  199. list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
  200. if (psr->encoder == encoder) {
  201. /*
  202. * Any other value would mean that the encoder
  203. * is still in use.
  204. */
  205. WARN_ON(psr->inhibit_count != 1);
  206. list_del(&psr->list);
  207. kfree(psr);
  208. }
  209. }
  210. mutex_unlock(&drm_drv->psr_list_lock);
  211. }
  212. EXPORT_SYMBOL(rockchip_drm_psr_unregister);