rockchip_drm_psr.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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. enum psr_state {
  20. PSR_FLUSH,
  21. PSR_ENABLE,
  22. PSR_DISABLE,
  23. };
  24. struct psr_drv {
  25. struct list_head list;
  26. struct drm_encoder *encoder;
  27. struct mutex lock;
  28. bool active;
  29. enum psr_state state;
  30. struct delayed_work flush_work;
  31. void (*set)(struct drm_encoder *encoder, bool enable);
  32. };
  33. static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
  34. {
  35. struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
  36. struct psr_drv *psr;
  37. mutex_lock(&drm_drv->psr_list_lock);
  38. list_for_each_entry(psr, &drm_drv->psr_list, list) {
  39. if (psr->encoder->crtc == crtc)
  40. goto out;
  41. }
  42. psr = ERR_PTR(-ENODEV);
  43. out:
  44. mutex_unlock(&drm_drv->psr_list_lock);
  45. return psr;
  46. }
  47. static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
  48. {
  49. struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
  50. struct psr_drv *psr;
  51. mutex_lock(&drm_drv->psr_list_lock);
  52. list_for_each_entry(psr, &drm_drv->psr_list, list) {
  53. if (psr->encoder == encoder)
  54. goto out;
  55. }
  56. psr = ERR_PTR(-ENODEV);
  57. out:
  58. mutex_unlock(&drm_drv->psr_list_lock);
  59. return psr;
  60. }
  61. static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
  62. {
  63. /*
  64. * Allowed finite state machine:
  65. *
  66. * PSR_ENABLE < = = = = = > PSR_FLUSH
  67. * | ^ |
  68. * | | |
  69. * v | |
  70. * PSR_DISABLE < - - - - - - - - -
  71. */
  72. if (state == psr->state || !psr->active)
  73. return;
  74. /* Already disabled in flush, change the state, but not the hardware */
  75. if (state == PSR_DISABLE && psr->state == PSR_FLUSH) {
  76. psr->state = state;
  77. return;
  78. }
  79. psr->state = state;
  80. /* Actually commit the state change to hardware */
  81. switch (psr->state) {
  82. case PSR_ENABLE:
  83. psr->set(psr->encoder, true);
  84. break;
  85. case PSR_DISABLE:
  86. case PSR_FLUSH:
  87. psr->set(psr->encoder, false);
  88. break;
  89. }
  90. }
  91. static void psr_set_state(struct psr_drv *psr, enum psr_state state)
  92. {
  93. mutex_lock(&psr->lock);
  94. psr_set_state_locked(psr, state);
  95. mutex_unlock(&psr->lock);
  96. }
  97. static void psr_flush_handler(struct work_struct *work)
  98. {
  99. struct psr_drv *psr = container_of(to_delayed_work(work),
  100. struct psr_drv, flush_work);
  101. /* If the state has changed since we initiated the flush, do nothing */
  102. mutex_lock(&psr->lock);
  103. if (psr->state == PSR_FLUSH)
  104. psr_set_state_locked(psr, PSR_ENABLE);
  105. mutex_unlock(&psr->lock);
  106. }
  107. /**
  108. * rockchip_drm_psr_activate - activate PSR on the given pipe
  109. * @encoder: encoder to obtain the PSR encoder
  110. *
  111. * Returns:
  112. * Zero on success, negative errno on failure.
  113. */
  114. int rockchip_drm_psr_activate(struct drm_encoder *encoder)
  115. {
  116. struct psr_drv *psr = find_psr_by_encoder(encoder);
  117. if (IS_ERR(psr))
  118. return PTR_ERR(psr);
  119. mutex_lock(&psr->lock);
  120. psr->active = true;
  121. mutex_unlock(&psr->lock);
  122. return 0;
  123. }
  124. EXPORT_SYMBOL(rockchip_drm_psr_activate);
  125. /**
  126. * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
  127. * @encoder: encoder to obtain the PSR encoder
  128. *
  129. * Returns:
  130. * Zero on success, negative errno on failure.
  131. */
  132. int rockchip_drm_psr_deactivate(struct drm_encoder *encoder)
  133. {
  134. struct psr_drv *psr = find_psr_by_encoder(encoder);
  135. if (IS_ERR(psr))
  136. return PTR_ERR(psr);
  137. mutex_lock(&psr->lock);
  138. psr->active = false;
  139. mutex_unlock(&psr->lock);
  140. cancel_delayed_work_sync(&psr->flush_work);
  141. return 0;
  142. }
  143. EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
  144. static void rockchip_drm_do_flush(struct psr_drv *psr)
  145. {
  146. psr_set_state(psr, PSR_FLUSH);
  147. mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS);
  148. }
  149. /**
  150. * rockchip_drm_psr_flush - flush a single pipe
  151. * @crtc: CRTC of the pipe to flush
  152. *
  153. * Returns:
  154. * 0 on success, -errno on fail
  155. */
  156. int rockchip_drm_psr_flush(struct drm_crtc *crtc)
  157. {
  158. struct psr_drv *psr = find_psr_by_crtc(crtc);
  159. if (IS_ERR(psr))
  160. return PTR_ERR(psr);
  161. rockchip_drm_do_flush(psr);
  162. return 0;
  163. }
  164. EXPORT_SYMBOL(rockchip_drm_psr_flush);
  165. /**
  166. * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
  167. * @dev: drm device
  168. *
  169. * Disable the PSR function for all registered encoders, and then enable the
  170. * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
  171. * changed during flush time, then keep the state no change after flush
  172. * timeout.
  173. *
  174. * Returns:
  175. * Zero on success, negative errno on failure.
  176. */
  177. void rockchip_drm_psr_flush_all(struct drm_device *dev)
  178. {
  179. struct rockchip_drm_private *drm_drv = dev->dev_private;
  180. struct psr_drv *psr;
  181. mutex_lock(&drm_drv->psr_list_lock);
  182. list_for_each_entry(psr, &drm_drv->psr_list, list)
  183. rockchip_drm_do_flush(psr);
  184. mutex_unlock(&drm_drv->psr_list_lock);
  185. }
  186. EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
  187. /**
  188. * rockchip_drm_psr_register - register encoder to psr driver
  189. * @encoder: encoder that obtain the PSR function
  190. * @psr_set: call back to set PSR state
  191. *
  192. * Returns:
  193. * Zero on success, negative errno on failure.
  194. */
  195. int rockchip_drm_psr_register(struct drm_encoder *encoder,
  196. void (*psr_set)(struct drm_encoder *, bool enable))
  197. {
  198. struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
  199. struct psr_drv *psr;
  200. if (!encoder || !psr_set)
  201. return -EINVAL;
  202. psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
  203. if (!psr)
  204. return -ENOMEM;
  205. INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
  206. mutex_init(&psr->lock);
  207. psr->active = true;
  208. psr->state = PSR_DISABLE;
  209. psr->encoder = encoder;
  210. psr->set = psr_set;
  211. mutex_lock(&drm_drv->psr_list_lock);
  212. list_add_tail(&psr->list, &drm_drv->psr_list);
  213. mutex_unlock(&drm_drv->psr_list_lock);
  214. return 0;
  215. }
  216. EXPORT_SYMBOL(rockchip_drm_psr_register);
  217. /**
  218. * rockchip_drm_psr_unregister - unregister encoder to psr driver
  219. * @encoder: encoder that obtain the PSR function
  220. * @psr_set: call back to set PSR state
  221. *
  222. * Returns:
  223. * Zero on success, negative errno on failure.
  224. */
  225. void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
  226. {
  227. struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
  228. struct psr_drv *psr, *n;
  229. mutex_lock(&drm_drv->psr_list_lock);
  230. list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
  231. if (psr->encoder == encoder) {
  232. cancel_delayed_work_sync(&psr->flush_work);
  233. list_del(&psr->list);
  234. kfree(psr);
  235. }
  236. }
  237. mutex_unlock(&drm_drv->psr_list_lock);
  238. }
  239. EXPORT_SYMBOL(rockchip_drm_psr_unregister);