mdp5_pipe.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. /*
  49. * don't assign a cursor pipe to a plane that isn't going to
  50. * be used as a cursor
  51. */
  52. if (cur->caps & MDP_PIPE_CAP_CURSOR &&
  53. plane->type != DRM_PLANE_TYPE_CURSOR)
  54. continue;
  55. /* possible candidate, take the one with the
  56. * fewest unneeded caps bits set:
  57. */
  58. if (!hwpipe || (hweight_long(cur->caps & ~caps) <
  59. hweight_long(hwpipe->caps & ~caps)))
  60. hwpipe = cur;
  61. }
  62. if (!hwpipe)
  63. return ERR_PTR(-ENOMEM);
  64. if (mdp5_kms->smp) {
  65. int ret;
  66. DBG("%s: alloc SMP blocks", hwpipe->name);
  67. ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
  68. hwpipe->pipe, blkcfg);
  69. if (ret)
  70. return ERR_PTR(-ENOMEM);
  71. hwpipe->blkcfg = blkcfg;
  72. }
  73. DBG("%s: assign to plane %s for caps %x",
  74. hwpipe->name, plane->name, caps);
  75. new_state->hwpipe_to_plane[hwpipe->idx] = plane;
  76. return hwpipe;
  77. }
  78. void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
  79. {
  80. struct msm_drm_private *priv = s->dev->dev_private;
  81. struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
  82. struct mdp5_state *state = mdp5_get_state(s);
  83. struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
  84. if (!hwpipe)
  85. return;
  86. if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
  87. return;
  88. DBG("%s: release from plane %s", hwpipe->name,
  89. new_state->hwpipe_to_plane[hwpipe->idx]->name);
  90. if (mdp5_kms->smp) {
  91. DBG("%s: free SMP blocks", hwpipe->name);
  92. mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
  93. }
  94. new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
  95. }
  96. void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
  97. {
  98. kfree(hwpipe);
  99. }
  100. struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
  101. uint32_t reg_offset, uint32_t caps)
  102. {
  103. struct mdp5_hw_pipe *hwpipe;
  104. hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
  105. if (!hwpipe)
  106. return ERR_PTR(-ENOMEM);
  107. hwpipe->name = pipe2name(pipe);
  108. hwpipe->pipe = pipe;
  109. hwpipe->reg_offset = reg_offset;
  110. hwpipe->caps = caps;
  111. hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
  112. spin_lock_init(&hwpipe->pipe_lock);
  113. return hwpipe;
  114. }