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

Commit fa5ee530 authored by Terence Hampson's avatar Terence Hampson Committed by Matt Wagantall
Browse files

mdss: mdp: enable dsi mode switch during atomic commit



Enable mode switch to occur if atomic commit is being used.
Previously feature was implemented for prepare/commit pairings.

Change-Id: I5eb1b5512a695fd6412e30728eabe129159d7d96
Signed-off-by: default avatarTerence Hampson <thampson@codeaurora.org>
parent 2dc63774
Loading
Loading
Loading
Loading
+69 −30
Original line number Diff line number Diff line
@@ -2820,6 +2820,67 @@ static int mdss_fb_pan_display_ex(struct fb_info *info,
	return ret;
}

u32 mdss_fb_get_mode_switch(struct msm_fb_data_type *mfd)
{
	/* If there is no attached mfd then there is no pending mode switch */
	if (!mfd)
		return 0;

	if (mfd->pending_switch)
		return mfd->switch_new_mode;

	return 0;
}

/*
 * __ioctl_transition_dyn_mode_state() - State machine for mode switch
 * @mfd:	Framebuffer data structure for display
 * @cmd:	ioctl that was called
 * @validate:	used with atomic commit when doing validate layers
 *
 * This function assists with dynamic mode switch of DSI panel. States
 * are used to make sure that panel mode switch occurs on next
 * prepare/sync/commit (for legacy) and validate/pre_commit (for
 * atomic commit) pairing. This state machine insure that calculation
 * and return values (such as buffer release fences) are based on the
 * panel mode being switching into.
 */
int __ioctl_transition_dyn_mode_state(struct msm_fb_data_type *mfd,
		unsigned int cmd, int validate)
{
	if (cmd == MDSS_MDP_NO_UPDATE_REQUESTED)
		return 0;

	mutex_lock(&mfd->switch_lock);
	switch (cmd) {
	case MSMFB_BUFFER_SYNC:
		if (mfd->switch_state == MDSS_MDP_WAIT_FOR_SYNC) {
			mdss_fb_set_mdp_sync_pt_threshold(mfd,
				mfd->switch_new_mode);
			mfd->switch_state = MDSS_MDP_WAIT_FOR_COMMIT;
		}
		break;
	case MSMFB_OVERLAY_PREPARE:
		if (mfd->switch_state == MDSS_MDP_WAIT_FOR_PREP) {
			mfd->pending_switch = true;
			mfd->switch_state = MDSS_MDP_WAIT_FOR_SYNC;
		}
		break;
	case MSMFB_ATOMIC_COMMIT:
		if ((mfd->switch_state == MDSS_MDP_WAIT_FOR_PREP) && validate) {
			mfd->pending_switch = true;
			mfd->switch_state = MDSS_MDP_WAIT_FOR_SYNC;
		} else if (mfd->switch_state == MDSS_MDP_WAIT_FOR_SYNC) {
			mdss_fb_set_mdp_sync_pt_threshold(mfd,
				mfd->switch_new_mode);
			mfd->switch_state = MDSS_MDP_WAIT_FOR_COMMIT;
		}
		break;
	}
	mutex_unlock(&mfd->switch_lock);
	return 0;
}

int mdss_fb_atomic_commit(struct fb_info *info,
	struct mdp_layer_commit  *commit)
{
@@ -2854,10 +2915,13 @@ int mdss_fb_atomic_commit(struct fb_info *info,
	commit_v1 = &commit->commit_v1;
	if (commit_v1->flags & MDP_VALIDATE_LAYER) {
		ret = mdss_fb_wait_for_kickoff(mfd);
		if (ret)
		if (ret) {
			pr_err("wait for kickoff failed\n");
		else
		} else {
			__ioctl_transition_dyn_mode_state(mfd,
				MSMFB_ATOMIC_COMMIT, 1);
			ret = mfd->mdp.atomic_validate(mfd, commit_v1);
		}
		goto end;
	} else {
		ret = mdss_fb_pan_idle(mfd);
@@ -3000,7 +3064,7 @@ static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd)
		if (ret)
			pr_err("DSI mode switch has failed");
		else
			mfd->mdp.pend_mode_switch(mfd, false);
			mfd->pending_switch = false;
	}
	if (fb_backup->disp_commit.flags & MDP_DISPLAY_COMMIT_OVERLAY) {
		if (mfd->mdp.kickoff_fnc)
@@ -3037,6 +3101,7 @@ static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd)
		mutex_lock(&mfd->switch_lock);
		mfd->switch_state = MDSS_MDP_NO_UPDATE_REQUESTED;
		mutex_unlock(&mfd->switch_lock);
		mfd->panel.type = new_dsi_mode;
		pr_debug("Dynamic mode switch completed\n");
	}

@@ -3793,32 +3858,6 @@ static int __ioctl_wait_idle(struct msm_fb_data_type *mfd, u32 cmd)
	return ret;
}

int __ioctl_transition_dyn_mode_state(struct msm_fb_data_type *mfd,
		unsigned int cmd)
{

	if (cmd == MDSS_MDP_NO_UPDATE_REQUESTED)
		return 0;

	mutex_lock(&mfd->switch_lock);
	switch (cmd) {
	case MSMFB_BUFFER_SYNC:
		if (mfd->switch_state == MDSS_MDP_WAIT_FOR_SYNC) {
			mdss_fb_set_mdp_sync_pt_threshold(mfd,
				mfd->switch_new_mode);
			mfd->switch_state = MDSS_MDP_WAIT_FOR_COMMIT;
		}
		break;
	case MSMFB_OVERLAY_PREPARE:
		if (mfd->switch_state == MDSS_MDP_WAIT_FOR_PREP) {
			mfd->mdp.pend_mode_switch(mfd, true);
			mfd->switch_state = MDSS_MDP_WAIT_FOR_SYNC;
		}
	}
	mutex_unlock(&mfd->switch_lock);
	return 0;
}

/*
 * mdss_fb_do_ioctl() - MDSS Framebuffer ioctl function
 * @info:	pointer to framebuffer info
@@ -3863,7 +3902,7 @@ int mdss_fb_do_ioctl(struct fb_info *info, unsigned int cmd,
	if (ret)
		goto exit;

	__ioctl_transition_dyn_mode_state(mfd, cmd);
	__ioctl_transition_dyn_mode_state(mfd, cmd, 0);

	switch (cmd) {
	case MSMFB_CURSOR:
+2 −2
Original line number Diff line number Diff line
@@ -187,8 +187,6 @@ struct msm_mdp_interface {
	/* called to release resources associated to the process */
	int (*release_fnc)(struct msm_fb_data_type *mfd, bool release_all,
				uint32_t pid);
	void (*pend_mode_switch)(struct msm_fb_data_type *mfd,
					bool pend_switch);
	int (*mode_switch)(struct msm_fb_data_type *mfd,
					u32 mode);
	int (*mode_switch_post)(struct msm_fb_data_type *mfd,
@@ -341,6 +339,7 @@ struct msm_fb_data_type {
	/* Following is used for dynamic mode switch */
	enum dyn_mode_switch_state switch_state;
	u32 switch_new_mode;
	bool pending_switch;
	struct mutex switch_lock;
};

@@ -426,4 +425,5 @@ int mdss_fb_compat_ioctl(struct fb_info *info, unsigned int cmd,
			 unsigned long arg);
int mdss_fb_atomic_commit(struct fb_info *info,
	struct mdp_layer_commit  *commit);
u32 mdss_fb_get_mode_switch(struct msm_fb_data_type *mfd);
#endif /* MDSS_FB_H */
+1 −3
Original line number Diff line number Diff line
@@ -601,7 +601,6 @@ struct mdss_overlay_private {
	int retire_cnt;
	bool kickoff_released;
	u32 cursor_ndx[2];
	bool dyn_mode_switch; /* Used in prepare, bw calc for new mode */
};

struct mdss_mdp_set_ot_params {
@@ -1000,8 +999,7 @@ int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
int mdss_mdp_get_prefetch_lines(struct mdss_mdp_ctl *ctl);
int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_pipe **left_plist, int left_cnt,
		struct mdss_mdp_pipe **right_plist, int right_cnt,
		bool mode_switch);
		struct mdss_mdp_pipe **right_plist, int right_cnt);
int mdss_mdp_perf_bw_check_pipe(struct mdss_mdp_perf_params *perf,
		struct mdss_mdp_pipe *pipe);
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
+8 −4
Original line number Diff line number Diff line
@@ -1197,12 +1197,11 @@ static void __mdss_mdp_perf_calc_ctl_helper(struct mdss_mdp_ctl *ctl,

int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_pipe **left_plist, int left_cnt,
		struct mdss_mdp_pipe **right_plist, int right_cnt,
		bool mode_switch)
		struct mdss_mdp_pipe **right_plist, int right_cnt)
{
	struct mdss_data_type *mdata = ctl->mdata;
	struct mdss_mdp_perf_params perf;
	u32 bw, threshold, i;
	u32 bw, threshold, i, mode_switch;
	u64 bw_sum_of_intfs = 0;
	bool is_video_mode;

@@ -1226,7 +1225,12 @@ int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl,
	bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000);
	pr_debug("calculated bandwidth=%uk\n", bw);

	is_video_mode = mode_switch ? ctl->is_video_mode : !ctl->is_video_mode;
	/* mfd validation happens in func */
	mode_switch = mdss_fb_get_mode_switch(ctl->mfd);
	if (mode_switch)
		is_video_mode = (mode_switch == MIPI_VIDEO_PANEL);
	else
		is_video_mode = ctl->is_video_mode;
	threshold = (is_video_mode ||
		mdss_mdp_video_mode_intf_connected(ctl)) ?
		mdata->max_bw_low : mdata->max_bw_high;
+1 −1
Original line number Diff line number Diff line
@@ -1078,7 +1078,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
	}

	ret = mdss_mdp_perf_bw_check(mdp5_data->ctl, left_plist, left_cnt,
		right_plist, right_cnt, false);
		right_plist, right_cnt);
	if (ret) {
		pr_err("bw validation check failed: %d\n", ret);
		goto validate_exit;
Loading