0001
0002
0003
0004
0005
0006 #include "mdp5_kms.h"
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 static int lm_right_pair[] = { 1, -1, 5, -1, -1, -1 };
0018
0019 static int get_right_pair_idx(struct mdp5_kms *mdp5_kms, int lm)
0020 {
0021 int i;
0022 int pair_lm;
0023
0024 pair_lm = lm_right_pair[lm];
0025 if (pair_lm < 0)
0026 return -EINVAL;
0027
0028 for (i = 0; i < mdp5_kms->num_hwmixers; i++) {
0029 struct mdp5_hw_mixer *mixer = mdp5_kms->hwmixers[i];
0030
0031 if (mixer->lm == pair_lm)
0032 return mixer->idx;
0033 }
0034
0035 return -1;
0036 }
0037
0038 int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,
0039 uint32_t caps, struct mdp5_hw_mixer **mixer,
0040 struct mdp5_hw_mixer **r_mixer)
0041 {
0042 struct msm_drm_private *priv = s->dev->dev_private;
0043 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
0044 struct mdp5_global_state *global_state = mdp5_get_global_state(s);
0045 struct mdp5_hw_mixer_state *new_state;
0046 int i;
0047
0048 if (IS_ERR(global_state))
0049 return PTR_ERR(global_state);
0050
0051 new_state = &global_state->hwmixer;
0052
0053 for (i = 0; i < mdp5_kms->num_hwmixers; i++) {
0054 struct mdp5_hw_mixer *cur = mdp5_kms->hwmixers[i];
0055
0056
0057
0058
0059
0060
0061
0062
0063 if (new_state->hwmixer_to_crtc[cur->idx] &&
0064 new_state->hwmixer_to_crtc[cur->idx] != crtc)
0065 continue;
0066
0067
0068 if (caps & ~cur->caps)
0069 continue;
0070
0071 if (r_mixer) {
0072 int pair_idx;
0073
0074 pair_idx = get_right_pair_idx(mdp5_kms, cur->lm);
0075 if (pair_idx < 0)
0076 return -EINVAL;
0077
0078 if (new_state->hwmixer_to_crtc[pair_idx])
0079 continue;
0080
0081 *r_mixer = mdp5_kms->hwmixers[pair_idx];
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 if (!(*mixer) || cur->caps & MDP_LM_CAP_PAIR)
0098 *mixer = cur;
0099 }
0100
0101 if (!(*mixer))
0102 return -ENOMEM;
0103
0104 if (r_mixer && !(*r_mixer))
0105 return -ENOMEM;
0106
0107 DBG("assigning Layer Mixer %d to crtc %s", (*mixer)->lm, crtc->name);
0108
0109 new_state->hwmixer_to_crtc[(*mixer)->idx] = crtc;
0110 if (r_mixer) {
0111 DBG("assigning Right Layer Mixer %d to crtc %s", (*r_mixer)->lm,
0112 crtc->name);
0113 new_state->hwmixer_to_crtc[(*r_mixer)->idx] = crtc;
0114 }
0115
0116 return 0;
0117 }
0118
0119 int mdp5_mixer_release(struct drm_atomic_state *s, struct mdp5_hw_mixer *mixer)
0120 {
0121 struct mdp5_global_state *global_state = mdp5_get_global_state(s);
0122 struct mdp5_hw_mixer_state *new_state;
0123
0124 if (!mixer)
0125 return 0;
0126
0127 if (IS_ERR(global_state))
0128 return PTR_ERR(global_state);
0129
0130 new_state = &global_state->hwmixer;
0131
0132 if (WARN_ON(!new_state->hwmixer_to_crtc[mixer->idx]))
0133 return -EINVAL;
0134
0135 DBG("%s: release from crtc %s", mixer->name,
0136 new_state->hwmixer_to_crtc[mixer->idx]->name);
0137
0138 new_state->hwmixer_to_crtc[mixer->idx] = NULL;
0139
0140 return 0;
0141 }
0142
0143 void mdp5_mixer_destroy(struct mdp5_hw_mixer *mixer)
0144 {
0145 kfree(mixer);
0146 }
0147
0148 static const char * const mixer_names[] = {
0149 "LM0", "LM1", "LM2", "LM3", "LM4", "LM5",
0150 };
0151
0152 struct mdp5_hw_mixer *mdp5_mixer_init(const struct mdp5_lm_instance *lm)
0153 {
0154 struct mdp5_hw_mixer *mixer;
0155
0156 mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
0157 if (!mixer)
0158 return ERR_PTR(-ENOMEM);
0159
0160 mixer->name = mixer_names[lm->id];
0161 mixer->lm = lm->id;
0162 mixer->caps = lm->caps;
0163 mixer->pp = lm->pp;
0164 mixer->dspp = lm->dspp;
0165 mixer->flush_mask = mdp_ctl_flush_mask_lm(lm->id);
0166
0167 return mixer;
0168 }