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

Commit 2c430316 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: avoid staging pipes on frame done errors"

parents e9e45533 662698e4
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -1504,6 +1504,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)

		lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode);

		mixer[i].pipe_mask = mixer[i].flush_mask;
		mixer[i].flush_mask |= ctl->ops.get_bitmask_mixer(ctl,
			mixer[i].hw_lm->idx);

@@ -3313,6 +3314,34 @@ static void _sde_crtc_commit_kickoff_rot(struct drm_crtc *crtc,
	SDE_ATRACE_END("crtc_kickoff_rot");
}

/**
 * _sde_crtc_remove_pipe_flush - remove staged pipes from flush mask
 * @sde_crtc: Pointer to sde crtc structure
 */
static void _sde_crtc_remove_pipe_flush(struct sde_crtc *sde_crtc)
{
	struct sde_crtc_mixer *mixer;
	struct sde_hw_ctl *ctl;
	u32 i, flush_mask;

	if (!sde_crtc)
		return;

	mixer = sde_crtc->mixers;
	for (i = 0; i < sde_crtc->num_mixers; i++) {
		ctl = mixer[i].hw_ctl;
		if (!ctl || !ctl->ops.get_pending_flush ||
				!ctl->ops.clear_pending_flush ||
				!ctl->ops.update_pending_flush)
			continue;

		flush_mask = ctl->ops.get_pending_flush(ctl);
		flush_mask &= ~mixer[i].pipe_mask;
		ctl->ops.clear_pending_flush(ctl);
		ctl->ops.update_pending_flush(ctl, flush_mask);
	}
}

void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
{
	struct drm_encoder *encoder;
@@ -3321,6 +3350,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct sde_crtc_state *cstate;
	bool is_error;
	int ret;

	if (!crtc) {
@@ -3330,6 +3360,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
	dev = crtc->dev;
	sde_crtc = to_sde_crtc(crtc);
	sde_kms = _sde_crtc_get_kms(crtc);
	is_error = false;

	if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) {
		SDE_ERROR("invalid argument\n");
@@ -3396,7 +3427,11 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
		SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
				crtc->base.id,
				atomic_read(&sde_crtc->frame_pending));
		goto end;

		is_error = true;

		/* force offline rotation mode since the commit has no pipes */
		cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE;
	}

	if (atomic_inc_return(&sde_crtc->frame_pending) == 1) {
@@ -3423,14 +3458,16 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)

	sde_vbif_clear_errors(sde_kms);

	if (is_error)
		_sde_crtc_remove_pipe_flush(sde_crtc);

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		if (encoder->crtc != crtc)
			continue;

		sde_encoder_kickoff(encoder);
		sde_encoder_kickoff(encoder, is_error);
	}

end:
	reinit_completion(&sde_crtc->frame_done_comp);
	SDE_ATRACE_END("crtc_commit");
	return;
+2 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct sde_crtc_retire_event {
 * @encoder:	Encoder attached to this lm & ctl
 * @mixer_op_mode:	mixer blending operation mode
 * @flush_mask:	mixer flush mask for ctl, mixer and pipe
 * @pipe_mask:	mixer flush mask for pipe
 */
struct sde_crtc_mixer {
	struct sde_hw_mixer *hw_lm;
@@ -120,6 +121,7 @@ struct sde_crtc_mixer {
	struct drm_encoder *encoder;
	u32 mixer_op_mode;
	u32 flush_mask;
	u32 pipe_mask;
};

/**
+46 −5
Original line number Diff line number Diff line
@@ -3070,7 +3070,46 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
	}
}

void sde_encoder_kickoff(struct drm_encoder *drm_enc)
/**
 * _sde_encoder_reset_ctl_hw - reset h/w configuration for all ctl's associated
 *	with the specified encoder, and unstage all pipes from it
 * @encoder:	encoder pointer
 * Returns: 0 on success
 */
static int _sde_encoder_reset_ctl_hw(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc;
	struct sde_encoder_phys *phys;
	unsigned int i;
	int rc = 0;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}

	sde_enc = to_sde_encoder_virt(drm_enc);

	SDE_ATRACE_BEGIN("encoder_release_lm");
	SDE_DEBUG_ENC(sde_enc, "\n");

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		phys = sde_enc->phys_encs[i];
		if (!phys)
			continue;

		SDE_EVT32(DRMID(drm_enc), phys->intf_idx - INTF_0);

		rc = sde_encoder_helper_reset_mixers(phys, NULL);
		if (rc)
			SDE_EVT32(DRMID(drm_enc), rc, SDE_EVTLOG_ERROR);
	}

	SDE_ATRACE_END("encoder_release_lm");
	return rc;
}

void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error)
{
	struct sde_encoder_virt *sde_enc;
	struct sde_encoder_phys *phys;
@@ -3092,6 +3131,10 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc)
	mod_timer(&sde_enc->frame_done_timer, jiffies +
		((atomic_read(&sde_enc->frame_done_timeout) * HZ) / 1000));

	/* create a 'no pipes' commit to release buffers on errors */
	if (is_error)
		_sde_encoder_reset_ctl_hw(drm_enc);

	/* All phys encs are ready to go, trigger the kickoff */
	_sde_encoder_kickoff_phys(sde_enc);

@@ -3112,7 +3155,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc)
	SDE_ATRACE_END("encoder_kickoff");
}

int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc,
int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc,
		struct drm_framebuffer *fb)
{
	struct drm_encoder *drm_enc;
@@ -3129,8 +3172,6 @@ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc,
	memset(&mixer, 0, sizeof(mixer));

	/* reset associated CTL/LMs */
	if (phys_enc->hw_ctl->ops.clear_pending_flush)
		phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl);
	if (phys_enc->hw_ctl->ops.clear_all_blendstages)
		phys_enc->hw_ctl->ops.clear_all_blendstages(phys_enc->hw_ctl);

@@ -3170,7 +3211,7 @@ int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc,
	}

	if (!lm_valid) {
		SDE_DEBUG_ENC(to_sde_encoder_virt(drm_enc), "lm not found\n");
		SDE_ERROR_ENC(to_sde_encoder_virt(drm_enc), "lm not found\n");
		return -EFAULT;
	}
	return 0;
+3 −1
Original line number Diff line number Diff line
@@ -128,8 +128,10 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *encoder);
 * sde_encoder_kickoff - trigger a double buffer flip of the ctl path
 *	(i.e. ctl flush and start) immediately.
 * @encoder:	encoder pointer
 * @is_error:	whether the current commit needs to be aborted and replaced
 *		with a 'safe' commit
 */
void sde_encoder_kickoff(struct drm_encoder *encoder);
void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error);

/**
 * sde_encoder_wait_for_event - Waits for encoder events
+2 −2
Original line number Diff line number Diff line
@@ -522,12 +522,12 @@ void sde_encoder_helper_split_config(
		enum sde_intf interface);

/**
 * sde_encoder_helper_hw_release - prepare for h/w reset during disable
 * sde_encoder_helper_reset_mixers - reset mixers associated with phys enc
 * @phys_enc: Pointer to physical encoder structure
 * @fb: Optional fb for specifying new mixer output resolution, may be NULL
 * Return: Zero on success
 */
int sde_encoder_helper_hw_release(struct sde_encoder_phys *phys_enc,
int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc,
		struct drm_framebuffer *fb);

/**
Loading