| From 7c721d3496bd45f9aaed4c51b3cd1476e598fb94 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 11 Oct 2019 06:39:39 -0700 |
| Subject: drm/msm/dsi: Implement reset correctly |
| |
| From: Jeffrey Hugo <jeffrey.l.hugo@gmail.com> |
| |
| [ Upstream commit 78e31c42261779a01bc73472d0f65f15378e9de3 ] |
| |
| On msm8998, vblank timeouts are observed because the DSI controller is not |
| reset properly, which ends up stalling the MDP. This is because the reset |
| logic is not correct per the hardware documentation. |
| |
| The documentation states that after asserting reset, software should wait |
| some time (no indication of how long), or poll the status register until it |
| returns 0 before deasserting reset. |
| |
| wmb() is insufficient for this purpose since it just ensures ordering, not |
| timing between writes. Since asserting and deasserting reset occurs on the |
| same register, ordering is already guaranteed by the architecture, making |
| the wmb extraneous. |
| |
| Since we would define a timeout for polling the status register to avoid a |
| possible infinite loop, lets just use a static delay of 20 ms, since 16.666 |
| ms is the time available to process one frame at 60 fps. |
| |
| Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") |
| Cc: Hai Li <hali@codeaurora.org> |
| Cc: Rob Clark <robdclark@gmail.com> |
| Signed-off-by: Jeffrey Hugo <jeffrey.l.hugo@gmail.com> |
| Reviewed-by: Sean Paul <sean@poorly.run> |
| [seanpaul renamed RESET_DELAY to DSI_RESET_TOGGLE_DELAY_MS] |
| Signed-off-by: Sean Paul <seanpaul@chromium.org> |
| Link: https://patchwork.freedesktop.org/patch/msgid/20191011133939.16551-1-jeffrey.l.hugo@gmail.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/gpu/drm/msm/dsi/dsi_host.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c |
| index 6f240021705b0..e49b414c012c6 100644 |
| --- a/drivers/gpu/drm/msm/dsi/dsi_host.c |
| +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c |
| @@ -33,6 +33,8 @@ |
| #include "sfpb.xml.h" |
| #include "dsi_cfg.h" |
| |
| +#define DSI_RESET_TOGGLE_DELAY_MS 20 |
| + |
| static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) |
| { |
| u32 ver; |
| @@ -909,7 +911,7 @@ static void dsi_sw_reset(struct msm_dsi_host *msm_host) |
| wmb(); /* clocks need to be enabled before reset */ |
| |
| dsi_write(msm_host, REG_DSI_RESET, 1); |
| - wmb(); /* make sure reset happen */ |
| + msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */ |
| dsi_write(msm_host, REG_DSI_RESET, 0); |
| } |
| |
| @@ -1288,7 +1290,7 @@ static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host) |
| |
| /* dsi controller can only be reset while clocks are running */ |
| dsi_write(msm_host, REG_DSI_RESET, 1); |
| - wmb(); /* make sure reset happen */ |
| + msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */ |
| dsi_write(msm_host, REG_DSI_RESET, 0); |
| wmb(); /* controller out of reset */ |
| dsi_write(msm_host, REG_DSI_CTRL, data0); |
| -- |
| 2.20.1 |
| |