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

Commit b4d9e044 authored by Ingrid Gallardo's avatar Ingrid Gallardo
Browse files

msm: mdss: add early wake up for dfps update



During early wake up notification, add the request
to update the fps to the default value, so we can
avoid this latency during the first frame update
after Idle.

Change-Id: I796a6ecba19f451e0f5e202c29e4de0d62a8cd5a
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent e7b7253a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1195,6 +1195,8 @@ struct mdss_data_type *mdss_mdp_get_mdata(void);
int mdss_mdp_secure_display_ctrl(unsigned int enable);

int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd,
	struct mdss_panel_data *pdata, int dfps);
int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
	struct file *file, struct mdp_layer_commit_v1 *ov_commit);
int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
+81 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
 *
 * 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
@@ -57,6 +57,7 @@ struct intf_timing_params {
};

struct mdss_mdp_video_ctx {
	struct mdss_mdp_ctl *ctl;
	u32 intf_num;
	char __iomem *base;
	u32 intf_type;
@@ -74,6 +75,7 @@ struct mdss_mdp_video_ctx {
	struct mutex vsync_mtx;
	struct list_head vsync_handlers;
	struct mdss_intf_recovery intf_recovery;
	struct work_struct early_wakeup_dfps_work;
};

static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx,
@@ -82,6 +84,8 @@ static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx,
static void mdss_mdp_fetch_end_config(struct mdss_mdp_video_ctx *ctx,
		struct mdss_mdp_ctl *ctl);

static void early_wakeup_dfps_update_work(struct work_struct *work);

static inline void mdp_video_write(struct mdss_mdp_video_ctx *ctx,
				   u32 reg, u32 val)
{
@@ -1386,6 +1390,7 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl,
	struct mdss_data_type *mdata = ctl->mdata;
	struct dsc_desc *dsc = NULL;

	ctx->ctl = ctl;
	ctx->intf_type = ctl->intf_type;
	init_completion(&ctx->vsync_comp);
	spin_lock_init(&ctx->vsync_lock);
@@ -1535,6 +1540,9 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
		return -EPERM;
	}

	/* Initialize early wakeup for the master ctx */
	INIT_WORK(&ctx->early_wakeup_dfps_work, early_wakeup_dfps_update_work);

	if (is_pingpong_split(ctl->mfd)) {
		if ((inum + 1) >= mdata->nintf) {
			pr_err("Intf not available for ping pong split: (%d)\n",
@@ -1617,6 +1625,65 @@ void mdss_mdp_switch_to_cmd_mode(struct mdss_mdp_ctl *ctl, int prep)
	mdss_bus_bandwidth_ctrl(false);
}

static void early_wakeup_dfps_update_work(struct work_struct *work)
{
	struct mdss_mdp_video_ctx *ctx =
		container_of(work, typeof(*ctx), early_wakeup_dfps_work);
	struct mdss_panel_data *pdata;
	struct mdss_panel_info *pinfo;
	struct msm_fb_data_type *mfd;
	struct mdss_mdp_ctl *ctl;
	int ret = 0;
	int dfps;

	if (!ctx) {
		pr_err("%s: invalid ctx\n", __func__);
		return;
	}

	ctl = ctx->ctl;

	if (!ctl || !ctl->panel_data || !ctl->mfd || !ctl->mfd->fbi) {
		pr_err("%s: invalid ctl\n", __func__);
		return;
	}

	pdata = ctl->panel_data;
	pinfo = &ctl->panel_data->panel_info;
	mfd =	ctl->mfd;

	if (!pinfo->dynamic_fps || !ctl->ops.config_fps_fnc ||
		!pdata->panel_info.default_fps) {
		pr_debug("%s: dfps not enabled on this panel\n", __func__);
		return;
	}

	/* get the default fps that was cached before any dfps update */
	dfps = pdata->panel_info.default_fps;

	ATRACE_BEGIN(__func__);

	if (dfps == pinfo->mipi.frame_rate) {
		pr_debug("%s: FPS is already %d\n",
			__func__, dfps);
		goto exit;
	}

	if (mdss_mdp_dfps_update_params(mfd, pdata, dfps))
		pr_err("failed to set dfps params!\n");

	/* update the HW with the new fps */
	ATRACE_BEGIN("fps_update_wq");
	ret = mdss_mdp_ctl_update_fps(ctl);
	ATRACE_END("fps_update_wq");
	if (ret)
		pr_err("early wakeup failed to set %d fps ret=%d\n",
			dfps, ret);

exit:
	ATRACE_END(__func__);
}

static int mdss_mdp_video_early_wake_up(struct mdss_mdp_ctl *ctl)
{
	u64 curr_time;
@@ -1649,6 +1716,19 @@ static int mdss_mdp_video_early_wake_up(struct mdss_mdp_ctl *ctl)
			 ctl->mfd->idle_state);
	}

	/*
	 * Schedule an fps update, so we can go to default fps before
	 * commit. Early wake up event is called from an interrupt
	 * context, so do this from work queue
	 */
	if (ctl->panel_data && ctl->panel_data->panel_info.dynamic_fps) {
		struct mdss_mdp_video_ctx *ctx;

		ctx = ctl->intf_ctx[MASTER_CTX];
		if (ctx)
			schedule_work(&ctx->early_wakeup_dfps_work);
	}

	return 0;
}

+44 −27
Original line number Diff line number Diff line
@@ -2723,7 +2723,7 @@ static void cache_initial_timings(struct mdss_panel_data *pdata)
	}
}

static void mdss_mdp_dfps_update_params(struct mdss_panel_data *pdata,
static void dfps_update_panel_params(struct mdss_panel_data *pdata,
	u32 new_fps)
{
	/* Keep initial values before any dfps update */
@@ -2759,6 +2759,45 @@ static void mdss_mdp_dfps_update_params(struct mdss_panel_data *pdata,
	}
}

int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd,
	struct mdss_panel_data *pdata, int dfps)
{
	struct fb_var_screeninfo *var = &mfd->fbi->var;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);

	mutex_lock(&mdp5_data->dfps_lock);

	pr_debug("new_fps:%d\n", dfps);

	if (dfps < pdata->panel_info.min_fps) {
		pr_err("Unsupported FPS. min_fps = %d\n",
				pdata->panel_info.min_fps);
		mutex_unlock(&mdp5_data->dfps_lock);
		return -EINVAL;
	} else if (dfps > pdata->panel_info.max_fps) {
		pr_warn("Unsupported FPS. Configuring to max_fps = %d\n",
				pdata->panel_info.max_fps);
		dfps = pdata->panel_info.max_fps;
	}

	dfps_update_panel_params(pdata, dfps);
	if (pdata->next)
		dfps_update_panel_params(pdata->next, dfps);

	/*
	 * Update the panel info in the upstream
	 * data, so any further call to get the screen
	 * info has the updated timings.
	 */
	mdss_panelinfo_to_fb_var(&pdata->panel_info, var);

	MDSS_XLOG(dfps);
	mutex_unlock(&mdp5_data->dfps_lock);

	return 0;
}


static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
@@ -2767,7 +2806,6 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev,
	struct fb_info *fbi = dev_get_drvdata(dev);
	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct fb_var_screeninfo *var = &mfd->fbi->var;

	rc = kstrtoint(buf, 10, &dfps);
	if (rc) {
@@ -2798,33 +2836,12 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev,
		return count;
	}

	mutex_lock(&mdp5_data->dfps_lock);
	if (dfps < pdata->panel_info.min_fps) {
		pr_err("Unsupported FPS. min_fps = %d\n",
				pdata->panel_info.min_fps);
		mutex_unlock(&mdp5_data->dfps_lock);
		return -EINVAL;
	} else if (dfps > pdata->panel_info.max_fps) {
		pr_warn("Unsupported FPS. Configuring to max_fps = %d\n",
				pdata->panel_info.max_fps);
		dfps = pdata->panel_info.max_fps;
	rc = mdss_mdp_dfps_update_params(mfd, pdata, dfps);
	if (rc) {
		pr_err("failed to set dfps params\n");
		return rc;
	}

	pr_debug("new_fps:%d\n", dfps);

	mdss_mdp_dfps_update_params(pdata, dfps);
	if (pdata->next)
		mdss_mdp_dfps_update_params(pdata->next, dfps);

	/*
	 * Update the panel info in the upstream
	 * data, so any further call to get the screen
	 * info has the updated timings.
	 */
	mdss_panelinfo_to_fb_var(&pdata->panel_info, var);

	MDSS_XLOG(dfps);
	mutex_unlock(&mdp5_data->dfps_lock);
	return count;
} /* dynamic_fps_sysfs_wta_dfps */