drm/tegra: dsi: Soft-reset controller on ->disable
authorThierry Reding <treding@nvidia.com>
Mon, 24 Nov 2014 15:29:40 +0000 (16:29 +0100)
committerThierry Reding <treding@nvidia.com>
Tue, 27 Jan 2015 09:14:39 +0000 (10:14 +0100)
This reset is necessary to properly clean up the internal state of the
controller.

Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/dsi.c

index e967ae1d6ca6e785323b50c02e3fc49152717d16..60b8022055462f3ef7b575282b7527aa4e208afb 100644 (file)
@@ -724,6 +724,30 @@ static void tegra_dsi_disable(struct tegra_dsi *dsi)
        usleep_range(5000, 10000);
 }
 
+static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
+{
+       u32 value;
+
+       value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
+       value &= ~DSI_POWER_CONTROL_ENABLE;
+       tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
+
+       usleep_range(300, 1000);
+
+       value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
+       value |= DSI_POWER_CONTROL_ENABLE;
+       tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
+
+       usleep_range(300, 1000);
+
+       value = tegra_dsi_readl(dsi, DSI_TRIGGER);
+       if (value)
+               tegra_dsi_writel(dsi, 0, DSI_TRIGGER);
+
+       if (dsi->slave)
+               tegra_dsi_soft_reset(dsi->slave);
+}
+
 static int tegra_output_dsi_disable(struct tegra_output *output)
 {
        struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
@@ -762,6 +786,7 @@ static int tegra_output_dsi_disable(struct tegra_output *output)
        if (err < 0)
                dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
 
+       tegra_dsi_soft_reset(dsi);
        tegra_dsi_disable(dsi);
 
        dsi->enabled = false;