mdp5_pipe.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright (C) 2016 Red Hat
  3. * Author: Rob Clark <robdclark@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published by
  7. * the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "mdp5_kms.h"
  18. struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
  19. struct drm_plane *plane, uint32_t caps, uint32_t blkcfg)
  20. {
  21. struct msm_drm_private *priv = s->dev->dev_private;
  22. struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
  23. struct mdp5_state *state;
  24. struct mdp5_hw_pipe_state *old_state, *new_state;
  25. struct mdp5_hw_pipe *hwpipe = NULL;
  26. int i;
  27. state = mdp5_get_state(s);
  28. if (IS_ERR(state))
  29. return ERR_CAST(state);
  30. /* grab old_state after mdp5_get_state(), since now we hold lock: */
  31. old_state = &mdp5_kms->state->hwpipe;
  32. new_state = &state->hwpipe;
  33. for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
  34. struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
  35. /* skip if already in-use.. check both new and old state,
  36. * since we cannot immediately re-use a pipe that is
  37. * released in the current update in some cases:
  38. * (1) mdp5 can have SMP (non-double-buffered)
  39. * (2) hw pipe previously assigned to different CRTC
  40. * (vblanks might not be aligned)
  41. */
  42. if (new_state->hwpipe_to_plane[cur->idx] ||
  43. old_state->hwpipe_to_plane[cur->idx])
  44. continue;
  45. /* skip if doesn't support some required caps: */
  46. if (caps & ~cur->caps)
  47. continue;
  48. /* possible candidate, take the one with the
  49. * fewest unneeded caps bits set:
  50. */
  51. if (!hwpipe || (hweight_long(cur->caps & ~caps) <
  52. hweight_long(hwpipe->caps & ~caps)))
  53. hwpipe = cur;
  54. }
  55. if (!hwpipe)
  56. return ERR_PTR(-ENOMEM);
  57. if (mdp5_kms->smp) {
  58. int ret;
  59. DBG("%s: alloc SMP blocks", hwpipe->name);
  60. ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
  61. hwpipe->pipe, blkcfg);
  62. if (ret)
  63. return ERR_PTR(-ENOMEM);
  64. hwpipe->blkcfg = blkcfg;
  65. }
  66. DBG("%s: assign to plane %s for caps %x",
  67. hwpipe->name, plane->name, caps);
  68. new_state->hwpipe_to_plane[hwpipe->idx] = plane;
  69. return hwpipe;
  70. }
  71. void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
  72. {
  73. struct msm_drm_private *priv = s->dev->dev_private;
  74. struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
  75. struct mdp5_state *state = mdp5_get_state(s);
  76. struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
  77. if (!hwpipe)
  78. return;
  79. if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
  80. return;
  81. DBG("%s: release from plane %s", hwpipe->name,
  82. new_state->hwpipe_to_plane[hwpipe->idx]->name);
  83. if (mdp5_kms->smp) {
  84. DBG("%s: free SMP blocks", hwpipe->name);
  85. mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
  86. }
  87. new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
  88. }
  89. void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
  90. {
  91. kfree(hwpipe);
  92. }
  93. struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
  94. uint32_t reg_offset, uint32_t caps)
  95. {
  96. struct mdp5_hw_pipe *hwpipe;
  97. hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
  98. if (!hwpipe)
  99. return ERR_PTR(-ENOMEM);
  100. hwpipe->name = pipe2name(pipe);
  101. hwpipe->pipe = pipe;
  102. hwpipe->reg_offset = reg_offset;
  103. hwpipe->caps = caps;
  104. hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
  105. spin_lock_init(&hwpipe->pipe_lock);
  106. return hwpipe;
  107. }