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

Commit 5db43498 authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm/sde: avoid frame_done event trigger for idle scenario



Current sde video mode encoder triggers frame done event
without checking pending frame count in vblank_wait
API call. That may lead to multiple frame_done events
for last frame during encoder disable sequence. It can
be avoided by managing frame_done event trigger along
with retire fence because retire fence trigger always
checks the pending frame count. It also avoids the
frame_event callback from two different places
and reduced event thread workload.

Change-Id: I4bf0723f559c8c235bf56d8a676f6b6e8b6d6381
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent be6924f0
Loading
Loading
Loading
Loading
+18 −23
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-only
/*
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */
 */


#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -474,7 +474,8 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
	if (sde_encoder_phys_vid_is_master(phys_enc)) {
	if (sde_encoder_phys_vid_is_master(phys_enc)) {
		if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
		if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
					-1, 0))
					-1, 0))
			event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
			event |= SDE_ENCODER_FRAME_EVENT_DONE |
				 SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
				SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
				SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
	}
	}


@@ -493,9 +494,10 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
				phys_enc);
				phys_enc);


	SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0,
	SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0,
			old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0,
			old_cnt, atomic_read(&phys_enc->pending_kickoff_cnt),
			reset_status ? SDE_EVTLOG_ERROR : 0,
			flush_register, event,
			flush_register, event,
			pend_ret_fence_cnt);
			atomic_read(&phys_enc->pending_retire_fence_cnt));


	/* Signal any waiting atomic commit thread */
	/* Signal any waiting atomic commit thread */
	wake_up_all(&phys_enc->pending_kickoff_wq);
	wake_up_all(&phys_enc->pending_kickoff_wq);
@@ -821,26 +823,23 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
{
{
	struct sde_encoder_wait_info wait_info;
	struct sde_encoder_wait_info wait_info;
	int ret = 0;
	int ret = 0;
	u32 event = 0;
	u32 event = 0, event_helper = 0;
	u32 event_helper = 0;


	if (!phys_enc) {
	if (!phys_enc) {
		pr_err("invalid encoder\n");
		pr_err("invalid encoder\n");
		return -EINVAL;
		return -EINVAL;
	}
	}


	wait_info.wq = &phys_enc->pending_kickoff_wq;
	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;

	if (!sde_encoder_phys_vid_is_master(phys_enc)) {
	if (!sde_encoder_phys_vid_is_master(phys_enc)) {
		/* signal done for slave video encoder, unless it is pp-split */
		/* signal done for slave video encoder, unless it is pp-split */
		if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify) {
		if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify)
			event = SDE_ENCODER_FRAME_EVENT_DONE;
			event = SDE_ENCODER_FRAME_EVENT_DONE;
		goto end;
		goto end;
	}
	}
		return 0;

	}
	wait_info.wq = &phys_enc->pending_kickoff_wq;
	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;


	/* Wait for kickoff to complete */
	/* Wait for kickoff to complete */
	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
@@ -849,15 +848,11 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
	event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
	event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
			| SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
			| SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;


	if (notify) {
	if (notify && (ret == -ETIMEDOUT)) {
		if (ret == -ETIMEDOUT) {
		event = SDE_ENCODER_FRAME_EVENT_ERROR;
		event = SDE_ENCODER_FRAME_EVENT_ERROR;
			if (atomic_add_unless(
		if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
				&phys_enc->pending_retire_fence_cnt, -1, 0))
				-1, 0))
			event |= event_helper;
			event |= event_helper;
		} else if (!ret) {
			event = SDE_ENCODER_FRAME_EVENT_DONE;
		}
	}
	}


end:
end: