From 493ab32ea2faeaec1f07dcd1c9c710d4d4a7d2fb Mon Sep 17 00:00:00 2001 From: hwangjae lee Date: Mon, 10 Dec 2018 10:18:49 +0900 Subject: [PATCH] [RAMEN9610-9310][Robusta2] fbdev: dev: DPU recovery when read timeout is occurred Change-Id: I2287eb166b7e1713b90208b5758a137a8f39b4d5 Signed-off-by: hwangjae lee --- drivers/video/fbdev/exynos/dpu20/decon.h | 2 ++ drivers/video/fbdev/exynos/dpu20/decon_core.c | 1 + drivers/video/fbdev/exynos/dpu20/decon_dsi.c | 11 ++++++++--- drivers/video/fbdev/exynos/dpu20/dsim_drv.c | 9 ++++++++- .../fbdev/exynos/dpu20/panels/hix83112a_mipi_lcd.c | 5 ++++- .../fbdev/exynos/dpu20/panels/nov36672a_mipi_lcd.c | 5 ++++- .../fbdev/exynos/dpu20/panels/s6e3fa0_mipi_lcd.c | 5 ++++- 7 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/exynos/dpu20/decon.h b/drivers/video/fbdev/exynos/dpu20/decon.h index 6e40c07c5732..91938c11c13a 100644 --- a/drivers/video/fbdev/exynos/dpu20/decon.h +++ b/drivers/video/fbdev/exynos/dpu20/decon.h @@ -966,6 +966,7 @@ struct decon_device { struct mutex lock; struct mutex pm_lock; + struct mutex rcv_lock; /* recovery lock */ spinlock_t slock; #if defined(CONFIG_EXYNOS_READ_ESD_SOLUTION) struct decon_esd esd; @@ -1421,6 +1422,7 @@ int dpu_pm_domain_check_status(struct exynos_pm_domain *pm_domain); int decon_set_out_sd_state(struct decon_device *decon, enum decon_state state); int decon_update_last_regs(struct decon_device *decon, struct decon_reg_data *regs); +int decon_handle_recovery(struct decon_device *decon); int register_lcd_status_notifier(struct notifier_block *nb); int unregister_lcd_status_notifier(struct notifier_block *nb); diff --git a/drivers/video/fbdev/exynos/dpu20/decon_core.c b/drivers/video/fbdev/exynos/dpu20/decon_core.c index 2463fc33d9d2..3d8271455350 100755 --- a/drivers/video/fbdev/exynos/dpu20/decon_core.c +++ b/drivers/video/fbdev/exynos/dpu20/decon_core.c @@ -4073,6 +4073,7 @@ static int decon_probe(struct platform_device *pdev) #if defined(CONFIG_EXYNOS_READ_ESD_SOLUTION) mutex_init(&decon->esd.lock); #endif + mutex_init(&decon->rcv_lock); decon_enter_shutdown_reset(decon); diff --git a/drivers/video/fbdev/exynos/dpu20/decon_dsi.c b/drivers/video/fbdev/exynos/dpu20/decon_dsi.c index 3afffd9ff860..62e8e6d087a0 100755 --- a/drivers/video/fbdev/exynos/dpu20/decon_dsi.c +++ b/drivers/video/fbdev/exynos/dpu20/decon_dsi.c @@ -385,7 +385,7 @@ void decon_destroy_vsync_thread(struct decon_device *decon) #if defined(CONFIG_EXYNOS_READ_ESD_SOLUTION) #define ESD_RECOVERY_RETRY_CNT 5 -static int decon_handle_esd(struct decon_device *decon) +int decon_handle_recovery(struct decon_device *decon) { struct dsim_device *dsim; int ret = 0; @@ -399,6 +399,8 @@ static int decon_handle_esd(struct decon_device *decon) return -EINVAL; } + mutex_lock(&decon->rcv_lock); + decon_bypass_on(decon); dsim = container_of(decon->out_sd[0], struct dsim_device, sd); dsim->esd_recovering = true; @@ -460,6 +462,9 @@ static int decon_handle_esd(struct decon_device *decon) decon_set_bypass(decon, true); decon_bypass_off(decon); + + mutex_unlock(&decon->rcv_lock); + decon_info("%s -\n", __func__); return ret; @@ -473,7 +478,7 @@ static void decon_esd_process(int esd, struct decon_device *decon) case DSIM_ESD_CHECK_ERROR: decon_err("%s, It is not ESD, \ but DDI is abnormal state(%d)\n", __func__, esd); - ret = decon_handle_esd(decon); + ret = decon_handle_recovery(decon); if (ret) decon_err("%s, failed to recover ESD\n", __func__); break; @@ -482,7 +487,7 @@ static void decon_esd_process(int esd, struct decon_device *decon) break; case DSIM_ESD_ERROR: decon_err("%s, ESD is detected(%d)\n", __func__, esd); - ret = decon_handle_esd(decon); + ret = decon_handle_recovery(decon); if (ret) decon_err("%s, failed to recover ESD\n", __func__); break; diff --git a/drivers/video/fbdev/exynos/dpu20/dsim_drv.c b/drivers/video/fbdev/exynos/dpu20/dsim_drv.c index db7fe6c84f43..8407e9548343 100755 --- a/drivers/video/fbdev/exynos/dpu20/dsim_drv.c +++ b/drivers/video/fbdev/exynos/dpu20/dsim_drv.c @@ -275,6 +275,7 @@ int dsim_read_data(struct dsim_device *dsim, u32 id, u32 addr, u32 cnt, u8 *buf) u32 rx_fifo_depth = DSIM_RX_FIFO_MAX_DEPTH; struct decon_device *decon = get_decon_drvdata(0); struct dsim_regs regs; + int ret2 = 0; decon_hiber_block_exit(decon); @@ -297,6 +298,12 @@ int dsim_read_data(struct dsim_device *dsim, u32 id, u32 addr, u32 cnt, u8 *buf) dsim_write_data(dsim, id, addr, 0); if (!wait_for_completion_timeout(&dsim->rd_comp, MIPI_RD_TIMEOUT)) { dsim_err("MIPI DSIM read Timeout!\n"); + decon_handle_recovery(decon); + if (decon->esd.thread) { + ret2 = wake_up_process(decon->esd.thread); + dsim_info("%s:%d, wakeup esd thread(%d)\n", __func__, + __LINE__, ret2); + } return -ETIMEDOUT; } @@ -1353,10 +1360,10 @@ static ssize_t dsim_cmd_sysfs_store(struct device *dev, switch (cmd) { case 1: - ret = dsim_cmd_sysfs_read(dsim); #if defined(CONFIG_EXYNOS_PANEL_INIT_LPDT) dsim_reg_set_cmd_transfer_mode(dsim->id, 1); #endif + ret = dsim_cmd_sysfs_read(dsim); call_panel_ops(dsim, dump, dsim); #if defined(CONFIG_EXYNOS_PANEL_INIT_LPDT) dsim_reg_set_cmd_transfer_mode(dsim->id, 0); diff --git a/drivers/video/fbdev/exynos/dpu20/panels/hix83112a_mipi_lcd.c b/drivers/video/fbdev/exynos/dpu20/panels/hix83112a_mipi_lcd.c index 2578e9a01894..ab7623e81755 100755 --- a/drivers/video/fbdev/exynos/dpu20/panels/hix83112a_mipi_lcd.c +++ b/drivers/video/fbdev/exynos/dpu20/panels/hix83112a_mipi_lcd.c @@ -547,7 +547,10 @@ static int hix83112a_read_state(struct dsim_device *dsim) for (i = 0; i < RETRY; i++) { ret = dsim_read_data(dsim, MIPI_DSI_DCS_READ, MIPI_DCS_GET_POWER_MODE, 0x1, buf); - if (ret < 0) { + if (ret == -ETIMEDOUT) { + dsim_info("recovery is already operated\n"); + return DSIM_ESD_OK; + } else if ((ret < 0) && (ret != -ETIMEDOUT)) { dsim_err("Failed to read panel REG 0x%02X!: 0x%02x, i(%d)\n", MIPI_DCS_GET_POWER_MODE, *(unsigned int *)buf & 0xFF, i); diff --git a/drivers/video/fbdev/exynos/dpu20/panels/nov36672a_mipi_lcd.c b/drivers/video/fbdev/exynos/dpu20/panels/nov36672a_mipi_lcd.c index 68fc7d2ad569..9b52de04c212 100755 --- a/drivers/video/fbdev/exynos/dpu20/panels/nov36672a_mipi_lcd.c +++ b/drivers/video/fbdev/exynos/dpu20/panels/nov36672a_mipi_lcd.c @@ -538,7 +538,10 @@ static int nov36672a_read_state(struct dsim_device *dsim) for (i = 0; i < RETRY; i++) { ret = dsim_read_data(dsim, MIPI_DSI_DCS_READ, MIPI_DCS_GET_POWER_MODE, 0x1, buf); - if (ret < 0) { + if (ret == -ETIMEDOUT) { + dsim_info("recovery is already operated\n"); + return DSIM_ESD_OK; + } else if ((ret < 0) && (ret != -ETIMEDOUT)) { dsim_err("Failed to read panel REG 0x%02X!: 0x%02x, i(%d)\n", MIPI_DCS_GET_POWER_MODE, *(unsigned int *)buf & 0xFF, i); diff --git a/drivers/video/fbdev/exynos/dpu20/panels/s6e3fa0_mipi_lcd.c b/drivers/video/fbdev/exynos/dpu20/panels/s6e3fa0_mipi_lcd.c index 52b4a4a1f204..2617f1fdfa7c 100644 --- a/drivers/video/fbdev/exynos/dpu20/panels/s6e3fa0_mipi_lcd.c +++ b/drivers/video/fbdev/exynos/dpu20/panels/s6e3fa0_mipi_lcd.c @@ -686,7 +686,10 @@ static int s6e3fa0_read_state(struct dsim_device *dsim) for (i = 0; i < RETRY; i++) { ret = dsim_read_data(dsim, MIPI_DSI_DCS_READ, MIPI_DCS_GET_POWER_MODE, 0x1, buf); - if (ret < 0) { + if (ret == -ETIMEDOUT) { + dsim_info("recovery is already operated\n"); + return DSIM_ESD_OK; + } else if ((ret < 0) && (ret != -ETIMEDOUT)) { dsim_err("Failed to read panel REG 0x%02X!: 0x%02x, i(%d)\n", MIPI_DCS_GET_POWER_MODE, *(unsigned int *)buf & 0xFF, i); -- 2.20.1