1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "mdp5_kms.h"
19
20struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
21 struct drm_plane *plane, uint32_t caps, uint32_t blkcfg)
22{
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;
28 int i;
29
30 state = mdp5_get_state(s);
31 if (IS_ERR(state))
32 return ERR_CAST(state);
33
34
35 old_state = &mdp5_kms->state->hwpipe;
36 new_state = &state->hwpipe;
37
38 for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
39 struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
40
41
42
43
44
45
46
47
48 if (new_state->hwpipe_to_plane[cur->idx] ||
49 old_state->hwpipe_to_plane[cur->idx])
50 continue;
51
52
53 if (caps & ~cur->caps)
54 continue;
55
56
57
58
59
60 if (cur->caps & MDP_PIPE_CAP_CURSOR &&
61 plane->type != DRM_PLANE_TYPE_CURSOR)
62 continue;
63
64
65
66
67 if (!hwpipe || (hweight_long(cur->caps & ~caps) <
68 hweight_long(hwpipe->caps & ~caps)))
69 hwpipe = cur;
70 }
71
72 if (!hwpipe)
73 return ERR_PTR(-ENOMEM);
74
75 if (mdp5_kms->smp) {
76 int ret;
77
78 DBG("%s: alloc SMP blocks", hwpipe->name);
79 ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
80 hwpipe->pipe, blkcfg);
81 if (ret)
82 return ERR_PTR(-ENOMEM);
83
84 hwpipe->blkcfg = blkcfg;
85 }
86
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;
90
91 return hwpipe;
92}
93
94void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
95{
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;
100
101 if (!hwpipe)
102 return;
103
104 if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
105 return;
106
107 DBG("%s: release from plane %s", hwpipe->name,
108 new_state->hwpipe_to_plane[hwpipe->idx]->name);
109
110 if (mdp5_kms->smp) {
111 DBG("%s: free SMP blocks", hwpipe->name);
112 mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
113 }
114
115 new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
116}
117
118void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
119{
120 kfree(hwpipe);
121}
122
123struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
124 uint32_t reg_offset, uint32_t caps)
125{
126 struct mdp5_hw_pipe *hwpipe;
127
128 hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
129 if (!hwpipe)
130 return ERR_PTR(-ENOMEM);
131
132 hwpipe->name = pipe2name(pipe);
133 hwpipe->pipe = pipe;
134 hwpipe->reg_offset = reg_offset;
135 hwpipe->caps = caps;
136 hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
137
138 return hwpipe;
139}
140