rockchip_drm_psr.c 6.7 KB

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