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

Commit a843d0c9 authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm/sde: trigger frame done if ctl is idle



Command mode display triggers next frame without waiting
for current frame transfer complete. In this case, MDP
HW transfers two frames and generates done interrupt status
 for two frames. SW may miss one interrupt if there is a
jiffie jump during these two frame done interrupt. This patch
checks the controller idle status for posted start triggered
frame to avoid invalid pingpong timeout issue.

Change-Id: I344357f19e051ebd5ff4d5555d7d27009803f7c2
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 00474817
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -1395,11 +1395,13 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start(
	struct sde_encoder_wait_info wait_info;
	int ret;
	bool frame_pending = true;
	struct sde_hw_ctl *ctl;

	if (!phys_enc || !phys_enc->hw_ctl) {
		SDE_ERROR("invalid argument(s)\n");
		return -EINVAL;
	}
	ctl = phys_enc->hw_ctl;

	wait_info.wq = &phys_enc->pending_kickoff_wq;
	wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt;
@@ -1440,7 +1442,18 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start(
			atomic_add_unless(
				&phys_enc->pending_ctlstart_cnt, -1, 0);
		}
	} else if ((ret == 0) &&
	    (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
	    atomic_read(&phys_enc->pending_kickoff_cnt) &&
	    ctl->ops.get_scheduler_status &&
	    (ctl->ops.get_scheduler_status(ctl) & BIT(0)) &&
	    phys_enc->parent_ops.handle_frame_done) {
		atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);

		phys_enc->parent_ops.handle_frame_done(
			phys_enc->parent, phys_enc,
			SDE_ENCODER_FRAME_EVENT_DONE |
			SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
	}

	return ret;
+9 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define   CTL_PREPARE                   0x0d0
#define   CTL_SW_RESET                  0x030
#define   CTL_SW_RESET_OVERRIDE         0x060
#define   CTL_STATUS                    0x064
#define   CTL_LAYER_EXTN_OFFSET         0x40
#define   CTL_ROT_TOP                   0x0C0
#define   CTL_ROT_FLUSH                 0x0C4
@@ -687,6 +688,13 @@ static u32 sde_hw_ctl_get_reset_status(struct sde_hw_ctl *ctx)
	return (u32)SDE_REG_READ(&ctx->hw, CTL_SW_RESET);
}

static u32 sde_hw_ctl_get_scheduler_status(struct sde_hw_ctl *ctx)
{
	if (!ctx)
		return 0;
	return (u32)SDE_REG_READ(&ctx->hw, CTL_STATUS);
}

static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx)
{
	struct sde_hw_blk_reg_map *c;
@@ -1226,6 +1234,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
			sde_hw_ctl_update_bitmask_periph_v1;
		ops->get_ctl_intf = sde_hw_ctl_get_intf_v1;
		ops->reset_post_disable = sde_hw_ctl_reset_post_disable;
		ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status;
	} else {
		ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
		ops->trigger_flush = sde_hw_ctl_trigger_flush;
+8 −1
Original line number Diff line number Diff line
/* 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.
 */

#ifndef _SDE_HW_CTL_H
@@ -287,6 +287,13 @@ struct sde_hw_ctl_ops {
	 */
	u32 (*get_reset)(struct sde_hw_ctl *ctx);

	/**
	 * get_scheduler_reset - check ctl scheduler status bit
	 * @ctx    : ctl path ctx pointer
	 * Returns: current value of ctl scheduler and idle status
	 */
	u32 (*get_scheduler_status)(struct sde_hw_ctl *ctx);

	/**
	 * hard_reset - force reset on ctl_path
	 * @ctx    : ctl path ctx pointer