video: tegra: dc: set sor to sleep at vsync during dc shutdown
Anshuman Nath Kar [Wed, 13 Jul 2016 22:03:55 +0000 (15:03 -0700)]
bug 1865109

The DC shutdown sequence includes disabling the windows during
tegra_dc_blank and shutting down DC during sor_detach. However
since these two events are ansynchronous, it can lead to stray
pixels getting transmitted to the panel. Hence we sleep the sor
during tegra_dc_blank and detach it later.

Change-Id: I017cab4c46978ee2e7ab4cb2581f4e76b62a2506
Signed-off-by: Anshuman Nath Kar <anshumank@nvidia.com>
Reviewed-on: http://git-master/r/1180987
Reviewed-by: Santosh Galma <galmar@nvidia.com>
Tested-by: Santosh Galma <galmar@nvidia.com>
Reviewed-by: Venu Byravarasu <vbyravarasu@nvidia.com>
(cherry picked from commit f6507d5beb105bc79799073c66c6b8ab45318cd4)
Reviewed-on: http://git-master/r/1278024
Reviewed-by: Prafull Suryawanshi <prafulls@nvidia.com>
Tested-by: Prafull Suryawanshi <prafulls@nvidia.com>
Reviewed-by: Mitch Luban <mluban@nvidia.com>
(cherry picked from commit 8a367aab0c9e2f2f9df845945fa03b0b81bac41f)
Reviewed-on: http://git-master/r/1458808
Reviewed-by: Manish Tuteja <mtuteja@nvidia.com>
Tested-by: Manish Tuteja <mtuteja@nvidia.com>

drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv_defs.h
drivers/video/tegra/dc/dp.c
drivers/video/tegra/dc/hdmi2.0.c
drivers/video/tegra/dc/sor.c
drivers/video/tegra/dc/sor.h

index 246657c..976c828 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2017, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -4257,6 +4257,8 @@ static bool _tegra_dc_enable(struct tegra_dc *dc)
        if (dc->enabled)
                return true;
 
+       dc->shutdown = false;
+
        pm_runtime_get_sync(&dc->ndev->dev);
 
        if ((dc->out->type == TEGRA_DC_OUT_HDMI ||
@@ -4472,6 +4474,13 @@ int tegra_dc_blank(struct tegra_dc *dc, unsigned windows)
                dcwins[nr_win++]->flags &= ~TEGRA_WIN_FLAG_ENABLED;
        }
 
+       if (dc->shutdown) {
+               if ((dc->out->type == TEGRA_DC_OUT_HDMI) ||
+                       (dc->out->type == TEGRA_DC_OUT_DP))
+                       if (dc->out_ops && dc->out_ops->shutdown_interface)
+                               dc->out_ops->shutdown_interface(dc);
+       }
+
        /* Skip update for linsim */
        if (!tegra_platform_is_linsim()) {
                tegra_dc_update_windows(dcwins, nr_win, NULL, true);
@@ -4523,6 +4532,7 @@ static void _tegra_dc_disable(struct tegra_dc *dc)
 
 void tegra_dc_disable(struct tegra_dc *dc)
 {
+       dc->shutdown = true;
        tegra_dc_disable_irq_ops(dc, false);
 }
 
index 32ca888..468a926 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
- * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2017, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -135,6 +135,8 @@ struct tegra_dc_out_ops {
        /* Configure controller to receive hotplug events */
        int (*hotplug_init)(struct tegra_dc *dc);
        int (*set_hdr)(struct tegra_dc *dc);
+       /* shutdown the serial interface */
+       void (*shutdown_interface)(struct tegra_dc *dc);
 };
 
 struct tegra_dc_shift_clk_div {
@@ -184,6 +186,7 @@ struct tegra_dc {
        bool                            enabled;
        bool                            suspended;
        bool                            blanked;
+       bool                            shutdown;
 
        /* Some of the setup code could reset display even if
         * DC is already by bootloader.  This one-time mark is
index 2e986a6..77f4fee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/dp.c
  *
- * Copyright (c) 2011-2016, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -2723,6 +2723,15 @@ static bool tegra_dp_hpd_op_edid_read_prepare(void *drv_data)
        return true;
 }
 
+static void tegra_dc_dp_sor_sleep(struct tegra_dc *dc)
+{
+       struct tegra_dc_dp_data *dp = tegra_dc_get_outdata(dc);
+
+       if (dp->sor->sor_state == SOR_ATTACHED)
+               tegra_dc_sor_sleep(dp->sor);
+}
+
+
 static struct tegra_hpd_ops hpd_ops = {
        .edid_read = tegra_dp_hpd_op_edid_read,
        .edid_ready = tegra_dp_hpd_op_edid_ready,
@@ -2745,4 +2754,5 @@ struct tegra_dc_out_ops tegra_dc_dp_ops = {
        .suspend = tegra_dc_dp_suspend,
        .resume = tegra_dc_dp_resume,
        .hotplug_init = tegra_dc_dp_hotplug_init,
+       .shutdown_interface = tegra_dc_dp_sor_sleep,
 };
index c8be6b9..0428d05 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/hdmi2.0.c
  *
- * Copyright (c) 2014-2016, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION, All rights reserved.
  * Author: Animesh Kishore <ankishore@nvidia.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -2477,6 +2477,14 @@ static void tegra_dc_hdmi_postpoweron(struct tegra_dc *dc)
        _tegra_hdmivrr_activate(tegra_dc_get_outdata(dc), true);
 }
 
+static void tegra_dc_hdmi_sor_sleep(struct tegra_dc *dc)
+{
+       struct tegra_hdmi *hdmi = tegra_dc_get_outdata(dc);
+
+       if (hdmi->sor->sor_state == SOR_ATTACHED)
+               tegra_dc_sor_sleep(hdmi->sor);
+}
+
 struct tegra_dc_out_ops tegra_dc_hdmi2_0_ops = {
        .init = tegra_dc_hdmi_init,
        .destroy = tegra_dc_hdmi_destroy,
@@ -2496,4 +2504,5 @@ struct tegra_dc_out_ops tegra_dc_hdmi2_0_ops = {
        .vrr_update_monspecs = tegra_hdmivrr_update_monspecs,
        .set_hdr = tegra_dc_hdmi_set_hdr,
        .postpoweron = tegra_dc_hdmi_postpoweron,
+       .shutdown_interface = tegra_dc_hdmi_sor_sleep,
 };
index ea88df2..d4867c2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/tegra/dc/sor.c
  *
- * Copyright (c) 2011-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -1742,15 +1742,13 @@ void tegra_sor_stop_dc(struct tegra_dc_sor_data *sor)
        tegra_dc_put(dc);
 }
 
-void tegra_dc_sor_pre_detach(struct tegra_dc_sor_data *sor)
+void tegra_dc_sor_sleep(struct tegra_dc_sor_data *sor)
 {
        struct tegra_dc *dc = sor->dc;
 
-       if (sor->sor_state != SOR_ATTACHED)
+       if (sor->sor_state == SOR_SLEEP)
                return;
 
-       tegra_dc_get(dc);
-
 #if defined(CONFIG_ARCH_TEGRA_12x_SOC) || defined(CONFIG_ARCH_TEGRA_13x_SOC)
        /* Sleep mode */
        tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
@@ -1781,6 +1779,20 @@ void tegra_dc_sor_pre_detach(struct tegra_dc_sor_data *sor)
                dev_err(&dc->ndev->dev,
                        "dc timeout waiting for OPMOD = SLEEP\n");
        }
+       sor->sor_state = SOR_SLEEP;
+
+}
+
+void tegra_dc_sor_pre_detach(struct tegra_dc_sor_data *sor)
+{
+       struct tegra_dc *dc = sor->dc;
+
+       if (sor->sor_state != SOR_ATTACHED)
+               return;
+
+       tegra_dc_get(dc);
+
+       tegra_dc_sor_sleep(sor);
 
        sor->sor_state = SOR_DETACHING;
        tegra_dc_put(dc);
index 4d24a1f..c7052b7 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * drivers/video/tegra/dc/sor.h
  *
- * Copyright (c) 2011-2016, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION, All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -110,6 +110,7 @@ struct tegra_dc_sor_data {
                SOR_ATTACHED = 1,
                SOR_DETACHING,
                SOR_DETACHED,
+               SOR_SLEEP,
        } sor_state;
 
        u8      clk_type;
@@ -137,6 +138,7 @@ void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor);
 void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor);
 void tegra_dc_sor_detach(struct tegra_dc_sor_data *sor);
 void tegra_dc_sor_pre_detach(struct tegra_dc_sor_data *sor);
+void tegra_dc_sor_sleep(struct tegra_dc_sor_data *sor);
 void tegra_dc_sor_enable_lvds(struct tegra_dc_sor_data *sor,
        bool balanced, bool conforming);
 void tegra_dc_sor_disable(struct tegra_dc_sor_data *sor, bool is_lvds);