Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 361aacfe authored by Nilaan Gunabalachandran's avatar Nilaan Gunabalachandran
Browse files

drm/msm/sde: modify RM to commit hw in check_only phase



SDE RM is modified to maintain hw allocation as part of
atomic_check_only phase. It ensures that if a topology is
checked and supported, the hw is maintained in a staging
state between check_only and commit phase. Cleanup for
validate is called as part of crtc destroy state.

Change-Id: I13c38bd689583ce316b43e827cb76f16e744adad
Signed-off-by: default avatarNilaan Gunabalachandran <ngunabal@codeaurora.org>
parent cb30afd5
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,20 @@ static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
	return to_sde_kms(priv->kms);
	return to_sde_kms(priv->kms);
}
}


static inline struct drm_encoder *_sde_crtc_get_encoder(struct drm_crtc *crtc)
{
	struct drm_encoder *enc;
	struct list_head *encoder_list;

	encoder_list = &crtc->dev->mode_config.encoder_list;

	list_for_each_entry(enc, encoder_list, head)
		if (enc->crtc == crtc)
			return enc;

	return NULL;
}

static inline int _sde_crtc_power_enable(struct sde_crtc *sde_crtc, bool enable)
static inline int _sde_crtc_power_enable(struct sde_crtc *sde_crtc, bool enable)
{
{
	struct drm_crtc *crtc;
	struct drm_crtc *crtc;
@@ -3029,6 +3043,8 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc,
{
{
	struct sde_crtc *sde_crtc;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *cstate;
	struct sde_crtc_state *cstate;
	struct drm_encoder *enc;
	struct sde_kms *sde_kms;


	if (!crtc || !state) {
	if (!crtc || !state) {
		SDE_ERROR("invalid argument(s)\n");
		SDE_ERROR("invalid argument(s)\n");
@@ -3037,9 +3053,14 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc,


	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
	cstate = to_sde_crtc_state(state);
	cstate = to_sde_crtc_state(state);
	enc = _sde_crtc_get_encoder(crtc);
	sde_kms = _sde_crtc_get_kms(crtc);


	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_DEBUG("crtc%d\n", crtc->base.id);


	if (sde_kms && enc)
		sde_rm_release(&sde_kms->rm, enc, true);

	__drm_atomic_helper_crtc_destroy_state(state);
	__drm_atomic_helper_crtc_destroy_state(state);


	/* destroy value helper */
	/* destroy value helper */
+1 −1
Original line number Original line Diff line number Diff line
@@ -3151,7 +3151,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)


	SDE_DEBUG_ENC(sde_enc, "encoder disabled\n");
	SDE_DEBUG_ENC(sde_enc, "encoder disabled\n");


	sde_rm_release(&sde_kms->rm, drm_enc);
	sde_rm_release(&sde_kms->rm, drm_enc, false);
}
}


void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
+50 −15
Original line number Original line Diff line number Diff line
@@ -18,7 +18,8 @@
#include "sde_hw_dsc.h"
#include "sde_hw_dsc.h"


#define RESERVED_BY_OTHER(h, r) \
#define RESERVED_BY_OTHER(h, r) \
	((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id))
	(((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) ||\
		((h)->rsvp_nxt && ((h)->rsvp_nxt->enc_id != (r)->enc_id)))


#define RM_RQ_LOCK(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_RESERVE_LOCK))
#define RM_RQ_LOCK(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_RESERVE_LOCK))
#define RM_RQ_CLEAR(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_RESERVE_CLEAR))
#define RM_RQ_CLEAR(r) ((r)->top_ctrl & BIT(SDE_RM_TOPCTL_RESERVE_CLEAR))
@@ -1452,6 +1453,30 @@ static struct sde_rm_rsvp *_sde_rm_get_rsvp(
	return NULL;
	return NULL;
}
}


static struct sde_rm_rsvp *_sde_rm_get_rsvp_nxt(
		struct sde_rm *rm,
		struct drm_encoder *enc)
{
	struct sde_rm_rsvp *i, *j;

	if (list_empty(&rm->rsvps))
		return NULL;

	list_for_each_entry(i, &rm->rsvps, list)
		if (i->enc_id == enc->base.id)
			break;

	j = i;
	list_for_each_entry_continue(j, &rm->rsvps, list)
		if (j->enc_id == enc->base.id)
			break;

	if (i && j && (i->seq != j->seq))
		return j;

	return NULL;
}

static struct drm_connector *_sde_rm_get_connector(
static struct drm_connector *_sde_rm_get_connector(
		struct drm_encoder *enc)
		struct drm_encoder *enc)
{
{
@@ -1539,7 +1564,7 @@ static void _sde_rm_release_rsvp(
	kfree(rsvp);
	kfree(rsvp);
}
}


void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc)
void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc, bool nxt)
{
{
	struct sde_rm_rsvp *rsvp;
	struct sde_rm_rsvp *rsvp;
	struct drm_connector *conn;
	struct drm_connector *conn;
@@ -1552,15 +1577,20 @@ void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc)


	mutex_lock(&rm->rm_lock);
	mutex_lock(&rm->rm_lock);


	if (nxt)
		rsvp = _sde_rm_get_rsvp_nxt(rm, enc);
	else
		rsvp = _sde_rm_get_rsvp(rm, enc);
		rsvp = _sde_rm_get_rsvp(rm, enc);
	if (!rsvp) {
	if (!rsvp) {
		SDE_ERROR("failed to find rsvp for enc %d\n", enc->base.id);
		SDE_ERROR("failed to find rsvp for enc %d, nxt %d",
				enc->base.id, nxt);
		goto end;
		goto end;
	}
	}


	conn = _sde_rm_get_connector(enc);
	conn = _sde_rm_get_connector(enc);
	if (!conn) {
	if (!conn) {
		SDE_ERROR("failed to get connector for enc %d\n", enc->base.id);
		SDE_ERROR("failed to get connector for enc %d, nxt %d",
				enc->base.id, nxt);
		goto end;
		goto end;
	}
	}


@@ -1651,6 +1681,12 @@ int sde_rm_reserve(


	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_BEGIN);
	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_BEGIN);


	rsvp_cur = _sde_rm_get_rsvp(rm, enc);
	rsvp_nxt = _sde_rm_get_rsvp_nxt(rm, enc);

	if (!test_only && rsvp_nxt)
		goto commit_rsvp;

	ret = _sde_rm_populate_requirements(rm, enc, crtc_state,
	ret = _sde_rm_populate_requirements(rm, enc, crtc_state,
			conn_state, &reqs);
			conn_state, &reqs);
	if (ret) {
	if (ret) {
@@ -1675,8 +1711,6 @@ int sde_rm_reserve(
		goto end;
		goto end;
	}
	}


	rsvp_cur = _sde_rm_get_rsvp(rm, enc);

	/*
	/*
	 * User can request that we clear out any reservation during the
	 * User can request that we clear out any reservation during the
	 * atomic_check phase by using this CLEAR bit
	 * atomic_check phase by using this CLEAR bit
@@ -1696,30 +1730,31 @@ int sde_rm_reserve(
	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_AFTER_RSVPNEXT);
	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_AFTER_RSVPNEXT);


	if (ret) {
	if (ret) {
		SDE_ERROR("failed to reserve hw resources: %d\n", ret);
		SDE_ERROR("failed to reserve hw resources: %d, test_only %d\n",
				ret, test_only);
		_sde_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
		_sde_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
		goto end;
	} else if (test_only && !RM_RQ_LOCK(&reqs)) {
	} else if (test_only && !RM_RQ_LOCK(&reqs)) {
		/*
		/*
		 * Normally, if test_only, test the reservation and then undo
		 * Normally, if test_only, test the reservation and then undo
		 * However, if the user requests LOCK, then keep the reservation
		 * However, if the user requests LOCK, then keep the reservation
		 * made during the atomic_check phase.
		 * made during the atomic_check phase.
		 */
		 */
		SDE_DEBUG("test_only: discard test rsvp[s%de%d]\n",
		SDE_DEBUG("test_only: rsvp[s%de%d]\n",
				rsvp_nxt->seq, rsvp_nxt->enc_id);
				rsvp_nxt->seq, rsvp_nxt->enc_id);
		_sde_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
		goto end;
	} else {
	} else {
		if (test_only && RM_RQ_LOCK(&reqs))
		if (test_only && RM_RQ_LOCK(&reqs))
			SDE_DEBUG("test_only & LOCK: lock rsvp[s%de%d]\n",
			SDE_DEBUG("test_only & LOCK: lock rsvp[s%de%d]\n",
					rsvp_nxt->seq, rsvp_nxt->enc_id);
					rsvp_nxt->seq, rsvp_nxt->enc_id);
	}


commit_rsvp:
	_sde_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
	_sde_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);

	ret = _sde_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
	ret = _sde_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
	}

	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_FINAL);


end:
end:
	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_FINAL);
	mutex_unlock(&rm->rm_lock);
	mutex_unlock(&rm->rm_lock);


	return ret;
	return ret;
+3 −2
Original line number Original line Diff line number Diff line
@@ -184,13 +184,14 @@ int sde_rm_reserve(struct sde_rm *rm,
		bool test_only);
		bool test_only);


/**
/**
 * sde_rm_reserve - Given the encoder for the display chain, release any
 * sde_rm_release - Given the encoder for the display chain, release any
 *	HW blocks previously reserved for that use case.
 *	HW blocks previously reserved for that use case.
 * @rm: SDE Resource Manager handle
 * @rm: SDE Resource Manager handle
 * @enc: DRM Encoder handle
 * @enc: DRM Encoder handle
 * @nxt: Choose option to release rsvp_nxt
 * @Return: 0 on Success otherwise -ERROR
 * @Return: 0 on Success otherwise -ERROR
 */
 */
void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc);
void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc, bool nxt);


/**
/**
 * sde_rm_get_mdp - Retrieve HW block for MDP TOP.
 * sde_rm_get_mdp - Retrieve HW block for MDP TOP.