2 * Copyright (C) 2016 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
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.
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
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/>.
20 struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
21 struct drm_plane *plane, uint32_t caps, uint32_t blkcfg)
23 struct msm_drm_private *priv = s->dev->dev_private;
24 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
25 struct mdp5_state *state;
26 struct mdp5_hw_pipe_state *old_state, *new_state;
27 struct mdp5_hw_pipe *hwpipe = NULL;
30 state = mdp5_get_state(s);
32 return ERR_CAST(state);
34 /* grab old_state after mdp5_get_state(), since now we hold lock: */
35 old_state = &mdp5_kms->state->hwpipe;
36 new_state = &state->hwpipe;
38 for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
39 struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
41 /* skip if already in-use.. check both new and old state,
42 * since we cannot immediately re-use a pipe that is
43 * released in the current update in some cases:
44 * (1) mdp5 can have SMP (non-double-buffered)
45 * (2) hw pipe previously assigned to different CRTC
46 * (vblanks might not be aligned)
48 if (new_state->hwpipe_to_plane[cur->idx] ||
49 old_state->hwpipe_to_plane[cur->idx])
52 /* skip if doesn't support some required caps: */
53 if (caps & ~cur->caps)
57 * don't assign a cursor pipe to a plane that isn't going to
60 if (cur->caps & MDP_PIPE_CAP_CURSOR &&
61 plane->type != DRM_PLANE_TYPE_CURSOR)
64 /* possible candidate, take the one with the
65 * fewest unneeded caps bits set:
67 if (!hwpipe || (hweight_long(cur->caps & ~caps) <
68 hweight_long(hwpipe->caps & ~caps)))
73 return ERR_PTR(-ENOMEM);
78 DBG("%s: alloc SMP blocks", hwpipe->name);
79 ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
80 hwpipe->pipe, blkcfg);
82 return ERR_PTR(-ENOMEM);
84 hwpipe->blkcfg = blkcfg;
87 DBG("%s: assign to plane %s for caps %x",
88 hwpipe->name, plane->name, caps);
89 new_state->hwpipe_to_plane[hwpipe->idx] = plane;
94 void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
96 struct msm_drm_private *priv = s->dev->dev_private;
97 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
98 struct mdp5_state *state = mdp5_get_state(s);
99 struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
104 if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
107 DBG("%s: release from plane %s", hwpipe->name,
108 new_state->hwpipe_to_plane[hwpipe->idx]->name);
111 DBG("%s: free SMP blocks", hwpipe->name);
112 mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
115 new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
118 void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
123 struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
124 uint32_t reg_offset, uint32_t caps)
126 struct mdp5_hw_pipe *hwpipe;
128 hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
130 return ERR_PTR(-ENOMEM);
132 hwpipe->name = pipe2name(pipe);
134 hwpipe->reg_offset = reg_offset;
136 hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);