brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 2822b53 Raw
165 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2017 The Linux Foundation. All rights reserved.4 */5 6#include "mdp5_kms.h"7 8/*9 * As of now, there are only 2 combinations possible for source split:10 *11 * Left | Right12 * -----|------13 *  LM0 | LM114 *  LM2 | LM515 *16 */17static int lm_right_pair[] = { 1, -1, 5, -1, -1, -1 };18 19static int get_right_pair_idx(struct mdp5_kms *mdp5_kms, int lm)20{21	int i;22	int pair_lm;23 24	pair_lm = lm_right_pair[lm];25	if (pair_lm < 0)26		return -EINVAL;27 28	for (i = 0; i < mdp5_kms->num_hwmixers; i++) {29		struct mdp5_hw_mixer *mixer = mdp5_kms->hwmixers[i];30 31		if (mixer->lm == pair_lm)32			return mixer->idx;33	}34 35	return -1;36}37 38int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,39		      uint32_t caps, struct mdp5_hw_mixer **mixer,40		      struct mdp5_hw_mixer **r_mixer)41{42	struct msm_drm_private *priv = s->dev->dev_private;43	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));44	struct mdp5_global_state *global_state = mdp5_get_global_state(s);45	struct mdp5_hw_mixer_state *new_state;46	int i;47 48	if (IS_ERR(global_state))49		return PTR_ERR(global_state);50 51	new_state = &global_state->hwmixer;52 53	for (i = 0; i < mdp5_kms->num_hwmixers; i++) {54		struct mdp5_hw_mixer *cur = mdp5_kms->hwmixers[i];55 56		/*57		 * skip if already in-use by a different CRTC. If there is a58		 * mixer already assigned to this CRTC, it means this call is59		 * a request to get an additional right mixer. Assume that the60		 * existing mixer is the 'left' one, and try to see if we can61		 * get its corresponding 'right' pair.62		 */63		if (new_state->hwmixer_to_crtc[cur->idx] &&64		    new_state->hwmixer_to_crtc[cur->idx] != crtc)65			continue;66 67		/* skip if doesn't support some required caps: */68		if (caps & ~cur->caps)69			continue;70 71		if (r_mixer) {72			int pair_idx;73 74			pair_idx = get_right_pair_idx(mdp5_kms, cur->lm);75			if (pair_idx < 0)76				return -EINVAL;77 78			if (new_state->hwmixer_to_crtc[pair_idx])79				continue;80 81			*r_mixer = mdp5_kms->hwmixers[pair_idx];82		}83 84		/*85		 * prefer a pair-able LM over an unpairable one. We can86		 * switch the CRTC from Normal mode to Source Split mode87		 * without requiring a full modeset if we had already88		 * assigned this CRTC a pair-able LM.89		 *90		 * TODO: There will be assignment sequences which would91		 * result in the CRTC requiring a full modeset, even92		 * if we have the LM resources to prevent it. For a platform93		 * with a few displays, we don't run out of pair-able LMs94		 * so easily. For now, ignore the possibility of requiring95		 * a full modeset.96		 */97		if (!(*mixer) || cur->caps & MDP_LM_CAP_PAIR)98			*mixer = cur;99	}100 101	if (!(*mixer))102		return -ENOMEM;103 104	if (r_mixer && !(*r_mixer))105		return -ENOMEM;106 107	DBG("assigning Layer Mixer %d to crtc %s", (*mixer)->lm, crtc->name);108 109	new_state->hwmixer_to_crtc[(*mixer)->idx] = crtc;110	if (r_mixer) {111		DBG("assigning Right Layer Mixer %d to crtc %s", (*r_mixer)->lm,112		    crtc->name);113		new_state->hwmixer_to_crtc[(*r_mixer)->idx] = crtc;114	}115 116	return 0;117}118 119int mdp5_mixer_release(struct drm_atomic_state *s, struct mdp5_hw_mixer *mixer)120{121	struct mdp5_global_state *global_state = mdp5_get_global_state(s);122	struct mdp5_hw_mixer_state *new_state;123 124	if (!mixer)125		return 0;126 127	if (IS_ERR(global_state))128		return PTR_ERR(global_state);129 130	new_state = &global_state->hwmixer;131 132	if (WARN_ON(!new_state->hwmixer_to_crtc[mixer->idx]))133		return -EINVAL;134 135	DBG("%s: release from crtc %s", mixer->name,136	    new_state->hwmixer_to_crtc[mixer->idx]->name);137 138	new_state->hwmixer_to_crtc[mixer->idx] = NULL;139 140	return 0;141}142 143static const char * const mixer_names[] = {144	"LM0", "LM1", "LM2", "LM3", "LM4", "LM5",145};146 147struct mdp5_hw_mixer *mdp5_mixer_init(struct drm_device *dev,148				      const struct mdp5_lm_instance *lm)149{150	struct mdp5_hw_mixer *mixer;151 152	mixer = devm_kzalloc(dev->dev, sizeof(*mixer), GFP_KERNEL);153	if (!mixer)154		return ERR_PTR(-ENOMEM);155 156	mixer->name = mixer_names[lm->id];157	mixer->lm = lm->id;158	mixer->caps = lm->caps;159	mixer->pp = lm->pp;160	mixer->dspp = lm->dspp;161	mixer->flush_mask = mdp_ctl_flush_mask_lm(lm->id);162 163	return mixer;164}165