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

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

Merge "drm/sde: report MDP underrun error only if not stabilized"

parents 4e72dda7 bf9dde89
Loading
Loading
Loading
Loading
+64 −1
Original line number Diff line number Diff line
@@ -44,6 +44,13 @@
/* timeout in frames waiting for frame done */
#define SDE_ENCODER_FRAME_DONE_TIMEOUT	60

/* timeout in msecs */
#define SDE_ENCODER_UNDERRUN_TIMEOUT	200
/* underrun count threshold value */
#define SDE_ENCODER_UNDERRUN_CNT_MAX	10
/* 3 vsync time period in msec, report underrun  */
#define SDE_ENCODER_UNDERRUN_DELTA	50

#define MISR_BUFF_SIZE	256

/*
@@ -155,6 +162,11 @@ static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = {
 * @crtc_frame_event:		callback event
 * @frame_done_timeout:		frame done timeout in Hz
 * @frame_done_timer:		watchdog timer for frame done event
 * @last_underrun_ts:		variable to hold the last occurred underrun
 *				timestamp
 * @underrun_cnt_dwork:		underrun counter for delayed work
 * @dwork:			delayed work for deferring the reporting
 *				of underrun error
 */
struct sde_encoder_virt {
	struct drm_encoder base;
@@ -181,6 +193,9 @@ struct sde_encoder_virt {
	u32 crtc_frame_event;
	atomic_t frame_done_timeout;
	struct timer_list frame_done_timer;
	atomic_t last_underrun_ts;
	atomic_t underrun_cnt_dwork;
	struct delayed_work dwork;
};

#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -597,14 +612,28 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
static void sde_encoder_underrun_callback(struct drm_encoder *drm_enc,
		struct sde_encoder_phys *phy_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;

	if (!phy_enc)
		return;

	sde_enc = to_sde_encoder_virt(drm_enc);

	SDE_ATRACE_BEGIN("encoder_underrun_callback");
	atomic_inc(&phy_enc->underrun_cnt);
	SDE_EVT32(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt));

	sde_recovery_set_events(SDE_UNDERRUN);
	/* schedule delayed work if it has not scheduled or executed earlier */
	if ((!atomic_read(&sde_enc->last_underrun_ts)) &&
		(!atomic_read(&sde_enc->underrun_cnt_dwork))) {
		schedule_delayed_work(&sde_enc->dwork,
			msecs_to_jiffies(SDE_ENCODER_UNDERRUN_TIMEOUT));
	}

	/* take snapshot of current underrun and increment the count */
	atomic_set(&sde_enc->last_underrun_ts, jiffies);
	atomic_inc(&sde_enc->underrun_cnt_dwork);

	trace_sde_encoder_underrun(DRMID(drm_enc),
		atomic_read(&phy_enc->underrun_cnt));
	SDE_DBG_CTRL("stop_ftrace");
@@ -1391,6 +1420,37 @@ static void sde_encoder_frame_done_timeout(unsigned long data)
			SDE_ENCODER_FRAME_EVENT_ERROR);
}

static void sde_encoder_underrun_work_func(struct work_struct *work)
{
	struct sde_encoder_virt *sde_enc =
		container_of(work, struct sde_encoder_virt, dwork.work);

	unsigned long delta, time;

	if (!sde_enc) {
		SDE_ERROR("invalid parameters\n");
		return;
	}

	delta = jiffies - atomic_read(&sde_enc->last_underrun_ts);
	time = jiffies_to_msecs(delta);

	/*
	 * report underrun error when it exceeds the threshold count
	 * and the occurrence of last underrun error is less than 3
	 * vsync period.
	 */
	if (atomic_read(&sde_enc->underrun_cnt_dwork) >
			SDE_ENCODER_UNDERRUN_CNT_MAX &&
			time < SDE_ENCODER_UNDERRUN_DELTA) {
		sde_recovery_set_events(SDE_UNDERRUN);
	}

	/* reset underrun last timestamp and counter */
	atomic_set(&sde_enc->last_underrun_ts, 0);
	atomic_set(&sde_enc->underrun_cnt_dwork, 0);
}

struct drm_encoder *sde_encoder_init(
		struct drm_device *dev,
		struct msm_display_info *disp_info)
@@ -1421,8 +1481,11 @@ struct drm_encoder *sde_encoder_init(
	drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs);

	atomic_set(&sde_enc->frame_done_timeout, 0);
	atomic_set(&sde_enc->last_underrun_ts, 0);
	atomic_set(&sde_enc->underrun_cnt_dwork, 0);
	setup_timer(&sde_enc->frame_done_timer, sde_encoder_frame_done_timeout,
			(unsigned long) sde_enc);
	INIT_DELAYED_WORK(&sde_enc->dwork, sde_encoder_underrun_work_func);

	_sde_encoder_init_debugfs(drm_enc, sde_enc, sde_kms);