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

Commit 22da2c97 authored by Ashish Garg's avatar Ashish Garg Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: add recovery if TE is not coming from the panel



Enable TE irq for the panel when there is a pingpong timeout.
Wait for TE to come for five vsync cycles before starting the
recovery for panel dead. If the TE comes from the panel during
the wait, call panic for pingpong timeout.

Change-Id: I88d06562e3e19880bb327b5f347ed79057f0e8c3
Signed-off-by: default avatarAshish Garg <ashigarg@codeaurora.org>
Signed-off-by: default avatarVishnuvardhan Prodduturi <vproddut@codeaurora.org>
parent 6649213f
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -1754,6 +1754,18 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata)
	return 0;
}

static irqreturn_t test_hw_vsync_handler(int irq, void *data)
{
	struct mdss_panel_data *pdata = (struct mdss_panel_data *)data;

	pr_debug("HW VSYNC\n");
	MDSS_XLOG(0xaaa, irq);
	complete_all(&pdata->te_done);
	if (pdata->next)
		complete_all(&pdata->next->te_done);
	return IRQ_HANDLED;
}

int mdss_dsi_cont_splash_on(struct mdss_panel_data *pdata)
{
	int ret = 0;
@@ -3163,6 +3175,8 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
	struct device_node *dsi_pan_node = NULL;
	const char *ctrl_name;
	struct mdss_util_intf *util;
	static int te_irq_registered;
	struct mdss_panel_data *pdata;

	if (!pdev || !pdev->dev.of_node) {
		pr_err("%s: pdev not found for DSI controller\n", __func__);
@@ -3289,6 +3303,23 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
		disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
	}

	pdata = &ctrl_pdata->panel_data;
	init_completion(&pdata->te_done);
	if (pdata->panel_info.type == MIPI_CMD_PANEL) {
		if (!te_irq_registered) {
			rc = devm_request_irq(&pdev->dev,
				gpio_to_irq(pdata->panel_te_gpio),
				test_hw_vsync_handler, IRQF_TRIGGER_FALLING,
				"VSYNC_GPIO", &ctrl_pdata->panel_data);
			if (rc) {
				pr_err("%s: TE request_irq failed\n", __func__);
				goto error_shadow_clk_deinit;
			}
			te_irq_registered = 1;
			disable_irq_nosync(gpio_to_irq(pdata->panel_te_gpio));
		}
	}

	rc = mdss_dsi_get_bridge_chip_params(pinfo, ctrl_pdata, pdev);
	if (rc) {
		pr_err("%s: Failed to get bridge params\n", __func__);
@@ -4035,6 +4066,7 @@ static int mdss_dsi_parse_gpio_params(struct platform_device *ctrl_pdev,
	struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
	struct mdss_panel_data *pdata = &ctrl_pdata->panel_data;

	/*
	 * If disp_en_gpio has been set previously (disp_en_gpio > 0)
@@ -4056,6 +4088,7 @@ static int mdss_dsi_parse_gpio_params(struct platform_device *ctrl_pdev,
	if (!gpio_is_valid(ctrl_pdata->disp_te_gpio))
		pr_err("%s:%d, TE gpio not specified\n",
						__func__, __LINE__);
	pdata->panel_te_gpio = ctrl_pdata->disp_te_gpio;

	ctrl_pdata->bklt_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
		"qcom,platform-bklight-en-gpio", 0);
+2 −9
Original line number Diff line number Diff line
@@ -2481,15 +2481,8 @@ void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl)
		if (!ctrl->mdp_busy)
			rc = 1;
		spin_unlock_irqrestore(&ctrl->mdp_lock, flags);
		if (!rc) {
			if (mdss_dsi_mdp_busy_tout_check(ctrl)) {
		if (!rc && mdss_dsi_mdp_busy_tout_check(ctrl))
			pr_err("%s: timeout error\n", __func__);
				MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl",
					"dsi0_phy", "dsi1_ctrl", "dsi1_phy",
					"vbif", "vbif_nrt", "dbg_bus",
					"vbif_dbg_bus", "panic");
			}
		}
	}
	pr_debug("%s: done pid=%d\n", __func__, current->pid);
	MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, current->pid, XLOG_FUNC_EXIT);
+11 −0
Original line number Diff line number Diff line
@@ -4393,6 +4393,7 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
	struct mdp_output_layer __user *output_layer_user;
	struct mdp_frc_info *frc_info = NULL;
	struct mdp_frc_info __user *frc_info_user;
	struct msm_fb_data_type *mfd;

	ret = copy_from_user(&commit, argp, sizeof(struct mdp_layer_commit));
	if (ret) {
@@ -4400,6 +4401,16 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
		return ret;
	}

	mfd = (struct msm_fb_data_type *)info->par;
	if (!mfd)
		return -EINVAL;

	if (mfd->panel_info->panel_dead) {
		pr_debug("early commit return\n");
		MDSS_XLOG(mfd->panel_info->panel_dead);
		return 0;
	}

	output_layer_user = commit.commit_v1.output_layer;
	if (output_layer_user) {
		buffer_size = sizeof(struct mdp_output_layer);
+22 −3
Original line number Diff line number Diff line
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2017, 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
@@ -21,6 +21,7 @@
#include "mdss_debug.h"
#include "mdss_mdp_trace.h"
#include "mdss_dsi_clk.h"
#include <linux/interrupt.h>

#define MAX_RECOVERY_TRIALS 10
#define MAX_SESSIONS 2
@@ -1900,7 +1901,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
	struct mdss_mdp_cmd_ctx *ctx;
	struct mdss_panel_data *pdata;
	unsigned long flags;
	int rc = 0;
	int rc = 0, te_irq;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
	if (!ctx) {
@@ -1947,7 +1948,21 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
				__func__,
				ctl->num, rc, ctx->pp_timeout_report_cnt,
				atomic_read(&ctx->koff_cnt));
		if (ctx->pp_timeout_report_cnt == 0) {

		/* enable TE irq to check if it is coming from the panel */
		te_irq = gpio_to_irq(pdata->panel_te_gpio);
		enable_irq(te_irq);

		/* wait for 20ms to ensure we are getting the next TE */
		usleep_range(20000, 20010);

		reinit_completion(&pdata->te_done);
		rc = wait_for_completion_timeout(&pdata->te_done, KOFF_TIMEOUT);

		if (!rc) {
			MDSS_XLOG(0xbac);
			mdss_fb_report_panel_dead(ctl->mfd);
		} else if (ctx->pp_timeout_report_cnt == 0) {
			MDSS_XLOG(0xbad);
			MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", "dsi0_phy",
				"dsi1_ctrl", "dsi1_phy", "vbif", "vbif_nrt",
@@ -1959,6 +1974,10 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
				"dbg_bus", "vbif_dbg_bus", "panic");
			mdss_fb_report_panel_dead(ctl->mfd);
		}

		/* disable te irq */
		disable_irq_nosync(te_irq);

		ctx->pp_timeout_report_cnt++;
		rc = -EPERM;

+3 −0
Original line number Diff line number Diff line
@@ -809,6 +809,9 @@ struct mdss_panel_data {
	/* To store dsc cfg name passed by bootloader */
	char dsc_cfg_np_name[MDSS_MAX_PANEL_LEN];
	struct mdss_panel_data *next;

	int panel_te_gpio;
	struct completion te_done;
};

struct mdss_panel_debugfs_info {