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

Commit d2288839 authored by Dhaval Patel's avatar Dhaval Patel Committed by Ray Zhang
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>
Signed-off-by: default avatarRay Zhang <rayz@codeaurora.org>
Signed-off-by: default avatarBruce Hoo <bingchua@codeaurora.org>
parent 45ca9aa5
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -1427,11 +1427,13 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start(
	struct sde_encoder_wait_info wait_info;
	struct sde_encoder_wait_info wait_info;
	int ret;
	int ret;
	bool frame_pending = true;
	bool frame_pending = true;
	struct sde_hw_ctl *ctl;


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


	wait_info.wq = &phys_enc->pending_kickoff_wq;
	wait_info.wq = &phys_enc->pending_kickoff_wq;
	wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt;
	wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt;
@@ -1474,6 +1476,18 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start(
			atomic_inc_return(&phys_enc->ctlstart_timeout);
			atomic_inc_return(&phys_enc->ctlstart_timeout);
		}
		}


	} 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;
	return ret;
+10 −1
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@
#define   CTL_PREPARE                   0x0d0
#define   CTL_PREPARE                   0x0d0
#define   CTL_SW_RESET                  0x030
#define   CTL_SW_RESET                  0x030
#define   CTL_SW_RESET_OVERRIDE         0x060
#define   CTL_SW_RESET_OVERRIDE         0x060
#define   CTL_STATUS                    0x064
#define   CTL_LAYER_EXTN_OFFSET         0x40
#define   CTL_LAYER_EXTN_OFFSET         0x40
#define   CTL_ROT_TOP                   0x0C0
#define   CTL_ROT_TOP                   0x0C0
#define   CTL_ROT_FLUSH                 0x0C4
#define   CTL_ROT_FLUSH                 0x0C4
@@ -709,6 +710,13 @@ static u32 sde_hw_ctl_get_reset_status(struct sde_hw_ctl *ctx)
	return (u32)SDE_REG_READ(&ctx->hw, CTL_SW_RESET);
	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)
static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx)
{
{
	struct sde_hw_blk_reg_map *c;
	struct sde_hw_blk_reg_map *c;
@@ -1273,6 +1281,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
			sde_hw_ctl_update_bitmask_periph_v1;
			sde_hw_ctl_update_bitmask_periph_v1;
		ops->get_ctl_intf = sde_hw_ctl_get_intf_v1;
		ops->get_ctl_intf = sde_hw_ctl_get_intf_v1;
		ops->reset_post_disable = sde_hw_ctl_reset_post_disable;
		ops->reset_post_disable = sde_hw_ctl_reset_post_disable;
		ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status;
	} else {
	} else {
		ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
		ops->update_pending_flush = sde_hw_ctl_update_pending_flush;
		ops->trigger_flush = sde_hw_ctl_trigger_flush;
		ops->trigger_flush = sde_hw_ctl_trigger_flush;
+8 −1
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -296,6 +296,13 @@ struct sde_hw_ctl_ops {
	 */
	 */
	u32 (*get_reset)(struct sde_hw_ctl *ctx);
	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
	 * hard_reset - force reset on ctl_path
	 * @ctx    : ctl path ctx pointer
	 * @ctx    : ctl path ctx pointer