0001
0002
0003
0004
0005
0006
0007 #include "mdp5_kms.h"
0008
0009 int mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane,
0010 uint32_t caps, uint32_t blkcfg,
0011 struct mdp5_hw_pipe **hwpipe,
0012 struct mdp5_hw_pipe **r_hwpipe)
0013 {
0014 struct msm_drm_private *priv = s->dev->dev_private;
0015 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
0016 struct mdp5_global_state *new_global_state, *old_global_state;
0017 struct mdp5_hw_pipe_state *old_state, *new_state;
0018 int i, j;
0019
0020 new_global_state = mdp5_get_global_state(s);
0021 if (IS_ERR(new_global_state))
0022 return PTR_ERR(new_global_state);
0023
0024
0025 old_global_state = mdp5_get_existing_global_state(mdp5_kms);
0026
0027 old_state = &old_global_state->hwpipe;
0028 new_state = &new_global_state->hwpipe;
0029
0030 for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
0031 struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
0032
0033
0034
0035
0036
0037
0038
0039
0040 if (new_state->hwpipe_to_plane[cur->idx] ||
0041 old_state->hwpipe_to_plane[cur->idx])
0042 continue;
0043
0044
0045 if (caps & ~cur->caps)
0046 continue;
0047
0048
0049
0050
0051
0052 if (cur->caps & MDP_PIPE_CAP_CURSOR &&
0053 plane->type != DRM_PLANE_TYPE_CURSOR)
0054 continue;
0055
0056
0057
0058
0059 if (!(*hwpipe) || (hweight_long(cur->caps & ~caps) <
0060 hweight_long((*hwpipe)->caps & ~caps))) {
0061 bool r_found = false;
0062
0063 if (r_hwpipe) {
0064 for (j = i + 1; j < mdp5_kms->num_hwpipes;
0065 j++) {
0066 struct mdp5_hw_pipe *r_cur =
0067 mdp5_kms->hwpipes[j];
0068
0069
0070 if (r_cur->caps != cur->caps)
0071 continue;
0072
0073
0074 if (cur->pipe > r_cur->pipe)
0075 continue;
0076
0077 *r_hwpipe = r_cur;
0078 r_found = true;
0079 break;
0080 }
0081 }
0082
0083 if (!r_hwpipe || r_found)
0084 *hwpipe = cur;
0085 }
0086 }
0087
0088 if (!(*hwpipe))
0089 return -ENOMEM;
0090
0091 if (r_hwpipe && !(*r_hwpipe))
0092 return -ENOMEM;
0093
0094 if (mdp5_kms->smp) {
0095 int ret;
0096
0097
0098 WARN_ON(r_hwpipe);
0099
0100 DBG("%s: alloc SMP blocks", (*hwpipe)->name);
0101 ret = mdp5_smp_assign(mdp5_kms->smp, &new_global_state->smp,
0102 (*hwpipe)->pipe, blkcfg);
0103 if (ret)
0104 return -ENOMEM;
0105
0106 (*hwpipe)->blkcfg = blkcfg;
0107 }
0108
0109 DBG("%s: assign to plane %s for caps %x",
0110 (*hwpipe)->name, plane->name, caps);
0111 new_state->hwpipe_to_plane[(*hwpipe)->idx] = plane;
0112
0113 if (r_hwpipe) {
0114 DBG("%s: assign to right of plane %s for caps %x",
0115 (*r_hwpipe)->name, plane->name, caps);
0116 new_state->hwpipe_to_plane[(*r_hwpipe)->idx] = plane;
0117 }
0118
0119 return 0;
0120 }
0121
0122 int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
0123 {
0124 struct msm_drm_private *priv = s->dev->dev_private;
0125 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
0126 struct mdp5_global_state *state;
0127 struct mdp5_hw_pipe_state *new_state;
0128
0129 if (!hwpipe)
0130 return 0;
0131
0132 state = mdp5_get_global_state(s);
0133 if (IS_ERR(state))
0134 return PTR_ERR(state);
0135
0136 new_state = &state->hwpipe;
0137
0138 if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
0139 return -EINVAL;
0140
0141 DBG("%s: release from plane %s", hwpipe->name,
0142 new_state->hwpipe_to_plane[hwpipe->idx]->name);
0143
0144 if (mdp5_kms->smp) {
0145 DBG("%s: free SMP blocks", hwpipe->name);
0146 mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
0147 }
0148
0149 new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
0150
0151 return 0;
0152 }
0153
0154 void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
0155 {
0156 kfree(hwpipe);
0157 }
0158
0159 struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
0160 uint32_t reg_offset, uint32_t caps)
0161 {
0162 struct mdp5_hw_pipe *hwpipe;
0163
0164 hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
0165 if (!hwpipe)
0166 return ERR_PTR(-ENOMEM);
0167
0168 hwpipe->name = pipe2name(pipe);
0169 hwpipe->pipe = pipe;
0170 hwpipe->reg_offset = reg_offset;
0171 hwpipe->caps = caps;
0172 hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
0173
0174 return hwpipe;
0175 }