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

Commit cb78c355 authored by Jayant Shekhar's avatar Jayant Shekhar
Browse files

msm: mdss: Issue ctl sw reset when underrun happens



If underrun occurs in dual pipe mode (edp, or HDMI) then
there is a chance the 3d_mux will get confused and route
right to left and left to right. This will happen if it
is on the right side when the underrun condition happens.
To fix this following steps are required:

 - Disable HW recovery
 - When underrun is detected, wait for vsync.
 - Issue sw_reset to the ctl path.

This is required to cleanly reset the 3d_mux in case the
swap has occurred.

Change-Id: I8fbf747da4720c12d48bc1ee431bab6224148e31
Signed-off-by: default avatarJayant Shekhar <jshekhar@codeaurora.org>
parent 54f3fb1b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -186,6 +186,9 @@ struct mdss_mdp_ctl {

	struct mdss_panel_data *panel_data;
	struct mdss_mdp_vsync_handler vsync_handler;
	struct mdss_mdp_vsync_handler recover_underrun_handler;
	struct work_struct recover_work;
	struct work_struct remove_underrun_handler;

	struct mdss_mdp_img_rect roi;
	struct mdss_mdp_img_rect roi_bkup;
+19 −0
Original line number Diff line number Diff line
@@ -468,6 +468,21 @@ static int mdss_mdp_video_wait4comp(struct mdss_mdp_ctl *ctl, void *arg)
	return rc;
}

static void recover_underrun_work(struct work_struct *work)
{
	struct mdss_mdp_ctl *ctl =
		container_of(work, typeof(*ctl), recover_work);

	if (!ctl || !ctl->add_vsync_handler) {
		pr_err("ctl or vsync handler is NULL\n");
		return;
	}

	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
	ctl->add_vsync_handler(ctl, &ctl->recover_underrun_handler);
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
}

static void mdss_mdp_video_underrun_intr_done(void *arg)
{
	struct mdss_mdp_ctl *ctl = arg;
@@ -479,6 +494,9 @@ static void mdss_mdp_video_underrun_intr_done(void *arg)
	MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0", "dsi1", "edp", "hdmi", "panic");
	pr_debug("display underrun detected for ctl=%d count=%d\n", ctl->num,
			ctl->underrun_cnt);

	if (ctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE)
		schedule_work(&ctl->recover_work);
}

static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_ctl *ctl, int new_fps)
@@ -804,6 +822,7 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl)
	spin_lock_init(&ctx->vsync_lock);
	mutex_init(&ctx->vsync_mtx);
	atomic_set(&ctx->vsync_ref, 0);
	INIT_WORK(&ctl->recover_work, recover_underrun_work);

	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
				   mdss_mdp_video_vsync_intr_done, ctl);
+36 −0
Original line number Diff line number Diff line
@@ -1873,6 +1873,35 @@ pan_display_error:
	mutex_unlock(&mdp5_data->ov_lock);
}

static void remove_underrun_vsync_handler(struct work_struct *work)
{
	int rc;
	struct mdss_mdp_ctl *ctl =
		container_of(work, typeof(*ctl), remove_underrun_handler);

	if (!ctl || !ctl->remove_vsync_handler) {
		pr_err("ctl or vsync handler is NULL\n");
		return;
	}

	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
	rc = ctl->remove_vsync_handler(ctl,
			&ctl->recover_underrun_handler);
	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
}

static void mdss_mdp_recover_underrun_handler(struct mdss_mdp_ctl *ctl,
						ktime_t t)
{
	if (!ctl) {
		pr_err("ctl is NULL\n");
		return;
	}

	mdss_mdp_ctl_reset(ctl);
	schedule_work(&ctl->remove_underrun_handler);
}

/* function is called in irq context should have minimum processing */
static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
						ktime_t t)
@@ -3041,6 +3070,13 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init(
					mdss_mdp_overlay_handle_vsync;
	ctl->vsync_handler.cmd_post_flush = false;

	ctl->recover_underrun_handler.vsync_handler =
			mdss_mdp_recover_underrun_handler;
	ctl->recover_underrun_handler.cmd_post_flush = false;

	INIT_WORK(&ctl->remove_underrun_handler,
				remove_underrun_vsync_handler);

	if (mfd->split_display && pdata->next) {
		/* enable split display */
		rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);