summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorAshish Garg <ashigarg@codeaurora.org>2017-05-18 15:54:39 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-18 23:46:32 -0700
commit44aa99c22023f7173a9889edc836072cd66b2732 (patch)
treeb2ae97b8fcd3413ed0f2b62a3bb2e572a629b295 /drivers/video/fbdev
parent5404e35069576a8cd8203065f60975e34a5f727b (diff)
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: Ashish Garg <ashigarg@codeaurora.org> Signed-off-by: Vishnuvardhan Prodduturi <vproddut@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c34
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c23
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h3
5 files changed, 71 insertions, 11 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index c7cac996e5c0..797c8b4a2eb1 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1815,6 +1815,18 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata)
return 0;
}
+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;
@@ -3296,6 +3308,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__);
@@ -3421,6 +3435,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__);
@@ -4241,6 +4272,8 @@ static int mdss_dsi_parse_gpio_params(struct platform_device *ctrl_pdev,
* If disp_en_gpio has been set previously (disp_en_gpio > 0)
* while parsing the panel node, then do not override it
*/
+ struct mdss_panel_data *pdata = &ctrl_pdata->panel_data;
+
if (ctrl_pdata->disp_en_gpio <= 0) {
ctrl_pdata->disp_en_gpio = of_get_named_gpio(
ctrl_pdev->dev.of_node,
@@ -4257,6 +4290,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);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 1a471155072b..007272dabae2 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -2558,15 +2558,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)) {
- 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", "dsi_dbg_bus", "panic");
- }
- }
+ if (!rc && mdss_dsi_mdp_busy_tout_check(ctrl))
+ pr_err("%s: timeout error\n", __func__);
}
pr_debug("%s: done pid=%d\n", __func__, current->pid);
MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, current->pid, XLOG_FUNC_EXIT);
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 4eca9cb39223..c0fd48519124 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -4630,6 +4630,7 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
struct mdp_output_layer __user *output_layer_user;
struct mdp_destination_scaler_data *ds_data = NULL;
struct mdp_destination_scaler_data __user *ds_data_user;
+ struct msm_fb_data_type *mfd;
ret = copy_from_user(&commit, argp, sizeof(struct mdp_layer_commit));
if (ret) {
@@ -4637,6 +4638,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);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index bdbec0b4e721..2e017fe5ec02 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -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
@@ -2090,7 +2091,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) {
@@ -2144,7 +2145,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",
@@ -2158,6 +2173,10 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
"dsi_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;
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index fa1df94976f9..37b0ca7aa44b 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -997,6 +997,9 @@ struct mdss_panel_data {
* are still on; panel will recover after unblank
*/
bool panel_disable_mode;
+
+ int panel_te_gpio;
+ struct completion te_done;
};
struct mdss_panel_debugfs_info {