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

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

Merge "msm: mdss: Fix tearing and hang issues for autorefresh"

parents 3bd221b5 d8d4a8e8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -267,7 +267,7 @@ struct mdss_mdp_ctl {
	u8 roi_changed;
	u8 valid_roi;

	int cmd_autorefresh_en;
	bool cmd_autorefresh_en;
	int autorefresh_frame_cnt;

	int (*start_fnc) (struct mdss_mdp_ctl *ctl);
+1 −2
Original line number Diff line number Diff line
@@ -1781,8 +1781,7 @@ int mdss_mdp_ctl_cmd_autorefresh_enable(struct mdss_mdp_ctl *ctl,
{
	int ret = 0;
	if (ctl->panel_data->panel_info.type == MIPI_CMD_PANEL) {
		mdss_mdp_cmd_set_autorefresh_mode(ctl,
				frame_cnt);
		ret = mdss_mdp_cmd_set_autorefresh_mode(ctl, frame_cnt);
	} else {
		pr_err("Mode not supported for this panel\n");
		ret = -EINVAL;
+30 −23
Original line number Diff line number Diff line
@@ -53,8 +53,11 @@ struct mdss_mdp_cmd_ctx {
	struct work_struct pp_done_work;
	struct mutex autorefresh_mtx;
	atomic_t pp_done_cnt;
	int autorefresh_pending;
	u8 autorefresh_init;

	int autorefresh_pending_frame_cnt;
	bool autorefresh_off_pending;
	bool autorefresh_init;

	struct mdss_intf_recovery intf_recovery;
	struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */
	u32 pp_timeout_report_cnt;
@@ -307,6 +310,9 @@ static void mdss_mdp_cmd_readptr_done(void *arg)
		complete_all(&ctx->readptr_done);
	}

	if (ctx->autorefresh_off_pending)
		ctx->autorefresh_off_pending = false;

	vsync_time = ktime_get();
	ctl->vsync_cnt++;
	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
@@ -765,7 +771,7 @@ static int __mdss_mdp_cmd_configure_autorefresh(struct mdss_mdp_ctl *ctl, int
		frame_cnt, bool delayed)
{
	struct mdss_mdp_cmd_ctx *ctx;
	int enable = frame_cnt ? 1 : 0;
	bool enable = frame_cnt ? true : false;

	if (!ctl || !ctl->mixer_left) {
		pr_err("invalid ctl structure\n");
@@ -778,26 +784,25 @@ static int __mdss_mdp_cmd_configure_autorefresh(struct mdss_mdp_ctl *ctl, int
	}

	if (frame_cnt == ctl->autorefresh_frame_cnt) {
		pr_err("No change to the refresh count\n");
		pr_debug("No change to the refresh count\n");
		return 0;
	}
	pr_debug("%s enable = %d frame_cnt = %d clk_cnt=%d\n", __func__,
	pr_debug("%s enable = %d frame_cnt = %d init=%d\n", __func__,
			enable, frame_cnt, ctx->autorefresh_init);

	mutex_lock(&ctx->autorefresh_mtx);

	if (enable) {
		if (delayed) {
			ctx->autorefresh_pending = frame_cnt;
			ctx->autorefresh_pending_frame_cnt = frame_cnt;
		} else {
			if (!ctx->autorefresh_init) {
				ctx->autorefresh_init = 1;
				ctx->autorefresh_init = true;
				mdss_mdp_cmd_clk_on(ctx);
			}
			mdss_mdp_pingpong_write(ctl->mixer_left->pingpong_base,
					MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG,
					(enable << 31) |
					(frame_cnt));
					BIT(31) | frame_cnt);
			/*
			 * This manual kickoff is needed to actually start the
			 * autorefresh feature. The h/w relies on one commit
@@ -806,9 +811,8 @@ static int __mdss_mdp_cmd_configure_autorefresh(struct mdss_mdp_ctl *ctl, int
			 */
			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
			ctl->autorefresh_frame_cnt = frame_cnt;
			ctl->cmd_autorefresh_en = 1;
			ctl->cmd_autorefresh_en = true;
		}

	} else {
		if (ctx->autorefresh_init) {
			/*
@@ -820,10 +824,12 @@ static int __mdss_mdp_cmd_configure_autorefresh(struct mdss_mdp_ctl *ctl, int
					MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
		}

		ctx->autorefresh_init = 0;
		ctx->autorefresh_init = false;
		ctx->autorefresh_pending_frame_cnt = 0;
		ctx->autorefresh_off_pending = true;

		ctl->autorefresh_frame_cnt = 0;
		ctl->cmd_autorefresh_en = 0;
		ctx->autorefresh_pending = 0;
		ctl->cmd_autorefresh_en = false;
	}

	mutex_unlock(&ctx->autorefresh_mtx);
@@ -837,7 +843,6 @@ static int __mdss_mdp_cmd_configure_autorefresh(struct mdss_mdp_ctl *ctl, int
 */
int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *ctl, int frame_cnt)
{

	return __mdss_mdp_cmd_configure_autorefresh(ctl, frame_cnt, true);
}

@@ -846,7 +851,7 @@ int mdss_mdp_cmd_set_autorefresh_mode(struct mdss_mdp_ctl *ctl, int frame_cnt)
 * there was are any pending requests from the sys fs node for the feature and
 * if so then it will enable in the h/w.
 */
int mdss_mdp_cmd_enable_cmd_autorefresh(struct mdss_mdp_ctl *ctl,
static int mdss_mdp_cmd_enable_cmd_autorefresh(struct mdss_mdp_ctl *ctl,
	int frame_cnt)
{
	return __mdss_mdp_cmd_configure_autorefresh(ctl, frame_cnt, false);
@@ -928,7 +933,7 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)

	mdss_mdp_cmd_set_sync_ctx(ctl, sctl);

	if (ctx->autorefresh_init) {
	if (ctx->autorefresh_init || ctx->autorefresh_off_pending) {
		/*
		 * If autorefresh is enabled then do not queue the frame till
		 * the next read ptr is done otherwise we might get a pp done
@@ -936,19 +941,20 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
		 */
		pr_debug("Wait for read pointer done before enabling PP irq\n");
		wait_for_completion(&ctx->readptr_done);
		mdss_mdp_cmd_clk_on(ctx);
	}

	mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
	if (sctx)
		mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, sctx->pp_num);

	if (!ctx->autorefresh_pending && !ctl->cmd_autorefresh_en) {
	if (!ctx->autorefresh_pending_frame_cnt && !ctl->cmd_autorefresh_en) {
		/* Kickoff */
		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
	} else {
		pr_debug("Enabling autorefresh in hardware.\n");
		mdss_mdp_cmd_enable_cmd_autorefresh(ctl,
				ctx->autorefresh_pending);
				ctx->autorefresh_pending_frame_cnt);
	}

	mdss_mdp_ctl_perf_set_transaction_status(ctl,
@@ -1124,9 +1130,9 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
		ctx->panel_power_state, panel_power_state);

	if (ctl->cmd_autorefresh_en) {
		int pre_suspend = ctx->autorefresh_pending;
		int pre_suspend = ctx->autorefresh_pending_frame_cnt;
		mdss_mdp_cmd_enable_cmd_autorefresh(ctl, 0);
		ctx->autorefresh_pending = pre_suspend;
		ctx->autorefresh_pending_frame_cnt = pre_suspend;
	}

	mutex_lock(&ctl->offlock);
@@ -1292,7 +1298,8 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl,
	INIT_WORK(&ctx->clk_work, clk_ctrl_work);
	INIT_WORK(&ctx->pp_done_work, pingpong_done_work);
	atomic_set(&ctx->pp_done_cnt, 0);
	ctx->autorefresh_init = 0;
	ctx->autorefresh_off_pending = false;
	ctx->autorefresh_init = false;
	INIT_LIST_HEAD(&ctx->vsync_handlers);

	ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery;
+36 −33
Original line number Diff line number Diff line
@@ -2550,7 +2550,7 @@ static ssize_t mdss_mdp_dyn_pu_store(struct device *dev,

	return count;
}
static ssize_t mdss_cmd_autorefresh_enabled(struct device *dev,
static ssize_t mdss_mdp_cmd_autorefresh_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	ssize_t ret = 0;
@@ -2580,86 +2580,89 @@ static ssize_t mdss_cmd_autorefresh_enabled(struct device *dev,
	return ret;
}

static inline int mdss_validate_autorefresh_param(int frame_cnt,
		struct mdss_mdp_ctl *ctl)
static inline int mdss_validate_autorefresh_param(struct mdss_mdp_ctl *ctl,
	int frame_cnt)
{
	int rc = 0;

	if (frame_cnt == ctl->autorefresh_frame_cnt) {
		/* No parameters were changed */
		rc = -EINVAL;
		pr_debug("No change to autorefresh parameters\n");
		goto no_change;
		goto exit;
	}

	/* Check for correctness. Frame cnt length is 16bits */
	if (frame_cnt < 0 || frame_cnt >= BIT(16)) {
		rc = -EINVAL;
		pr_err("Invalid frame_cnt=%d passed to autorefresh\n",
				frame_cnt);
		goto no_change;
		pr_err("frame cnt %d is out of range (16 bits).\n", frame_cnt);
		goto exit;
	}

	pr_debug("Setting autorefresh_enable=%d frame_cnt=%d\n",
			ctl->cmd_autorefresh_en,
			frame_cnt);
		ctl->cmd_autorefresh_en, frame_cnt);

no_change:
exit:
	return rc;
}

static ssize_t mdss_set_cmd_autorefresh(struct device *dev,
static ssize_t mdss_mdp_cmd_autorefresh_store(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t len)
{
	u32 data = 0;
	int frame_cnt, rc;
	struct fb_info *fbi = dev_get_drvdata(dev);
	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
	struct mdss_mdp_ctl *ctl;

	if (!mfd) {
		pr_err("Invalid mfd structure\n");
		len = 0;
		goto mode_fail;
		rc = -EINVAL;
		return rc;
	}

	ctl = mfd_to_ctl(mfd);
	if (!ctl) {
		pr_err("Invalid ctl structure\n");
		len = 0;
		goto mode_fail;
		rc = -EINVAL;
		return rc;
	}

	if (mfd->panel_info->type != MIPI_CMD_PANEL) {
		pr_err("Panel doesnt support autorefresh\n");
		len = 0;
		goto mode_fail;
		rc = -EINVAL;
		return rc;
	}

	if (1 != sscanf(buf, "%d", &data)) {
		pr_err("Not able to read video autorefresh value\n");
	} else if (!mdss_validate_autorefresh_param(data, ctl)) {
		if (ctl->autorefresh_frame_cnt) {
	rc = kstrtoint(buf, 10, &frame_cnt);
	if (rc) {
		pr_err("kstrtoint failed. rc=%d\n", rc);
		return rc;
	} else {
		rc = mdss_validate_autorefresh_param(ctl, frame_cnt);
		if (rc)
			return rc;

		if (frame_cnt) {
			/* enable autorefresh */
			mfd->mdp_sync_pt_data.threshold = 2;
			mfd->mdp_sync_pt_data.retire_threshold = 0;
		} else {
			/* disable autorefresh */
			mfd->mdp_sync_pt_data.threshold = 1;
			mfd->mdp_sync_pt_data.retire_threshold = 1;
		}
		mdss_mdp_ctl_cmd_autorefresh_enable(ctl,
				data);

		rc = mdss_mdp_ctl_cmd_autorefresh_enable(ctl, frame_cnt);
		if (rc)
			return rc;
	}
	pr_debug("Setting video autorefresh=%d cnt=%d\n",
			ctl->cmd_autorefresh_en,
			data);
		ctl->cmd_autorefresh_en, frame_cnt);

mode_fail:
	return len;
}


static DEVICE_ATTR(msm_cmd_autorefresh_en, S_IRUGO | S_IWUSR,
		mdss_cmd_autorefresh_enabled,
		mdss_set_cmd_autorefresh);
	mdss_mdp_cmd_autorefresh_show, mdss_mdp_cmd_autorefresh_store);
static DEVICE_ATTR(vsync_event, S_IRUGO, mdss_mdp_vsync_show_event, NULL);
static DEVICE_ATTR(ad, S_IRUGO | S_IWUSR | S_IWGRP, mdss_mdp_ad_show,
	mdss_mdp_ad_store);