video: tegra: dsi: Dont program initialized panels
Rakesh Iyer [Wed, 6 Feb 2013 00:04:03 +0000 (16:04 -0800)]
Do not program some panels that the bootloader has already initialized.
This avoids periods of blanking during boot.

Bug 1219004

Change-Id: Ie08b20a0892d62dc1b960d37f709eda933e886cc
Signed-off-by: Rakesh Iyer <riyer@nvidia.com>
Reviewed-on: http://git-master/r/197685
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Jon Mayo <jmayo@nvidia.com>

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dsi.c

index 97b0137..c50dc04 100644 (file)
@@ -512,6 +512,7 @@ struct tegra_dc_out {
 #define TEGRA_DC_OUT_ONE_SHOT_MODE             (1 << 3)
 #define TEGRA_DC_OUT_N_SHOT_MODE               (1 << 4)
 #define TEGRA_DC_OUT_ONE_SHOT_LP_MODE          (1 << 5)
+#define TEGRA_DC_OUT_INITIALIZED_MODE          (1 << 6)
 
 #define TEGRA_DC_ALIGN_MSB             0
 #define TEGRA_DC_ALIGN_LSB             1
index e4f7971..8167c8c 100644 (file)
@@ -1819,7 +1819,8 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
 
        tegra_dc_unpowergate_locked(dc);
 
-       if (dc->out->enable)
+       if (!(dc->out->flags & TEGRA_DC_OUT_INITIALIZED_MODE) &&
+           dc->out->enable)
                dc->out->enable(&dc->ndev->dev);
 
        tegra_dc_setup_clk(dc, dc->clk);
@@ -2097,6 +2098,12 @@ static void _tegra_dc_disable(struct tegra_dc *dc)
 
        if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
                mutex_unlock(&dc->one_shot_lock);
+
+       /*
+        * We will need to reinitialize the display the next time panel
+        * is enabled.
+        */
+       dc->out->flags &= ~TEGRA_DC_OUT_INITIALIZED_MODE;
 }
 
 void tegra_dc_disable(struct tegra_dc *dc)
index e95aeef..9ae3491 100644 (file)
@@ -3215,6 +3215,43 @@ static void tegra_dsi_send_dc_frames(struct tegra_dc *dc,
        }
 }
 
+static void tegra_dsi_setup_initialized_panel(struct tegra_dc_dsi_data *dsi)
+{
+       regulator_enable(dsi->avdd_dsi_csi);
+
+       dsi->status.init = DSI_MODULE_INIT;
+       dsi->status.lphs = DSI_LPHS_IN_HS_MODE;
+       dsi->status.driven = DSI_DRIVEN_MODE_DC;
+       dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_DC;
+       dsi->status.clk_out = DSI_PHYCLK_OUT_EN;
+       dsi->status.lp_op = DSI_LP_OP_NOT_INIT;
+       dsi->status.dc_stream = DSI_DC_STREAM_ENABLE;
+
+       if (dsi->info.video_clock_mode == TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS)
+               dsi->status.clk_mode = DSI_PHYCLK_CONTINUOUS;
+       else
+               dsi->status.clk_mode = DSI_PHYCLK_TX_ONLY;
+
+       if (!(dsi->info.ganged_type)) {
+               if (dsi->info.video_burst_mode ==
+                       TEGRA_DSI_VIDEO_NONE_BURST_MODE ||
+                       dsi->info.video_burst_mode ==
+                       TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END)
+                       dsi->status.clk_burst = DSI_CLK_BURST_NONE_BURST;
+               else
+                       dsi->status.clk_burst = DSI_CLK_BURST_BURST_MODE;
+       }
+
+       if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE)
+               dsi->status.vtype = DSI_VIDEO_TYPE_CMD_MODE;
+       else
+               dsi->status.vtype = DSI_VIDEO_TYPE_VIDEO_MODE;
+
+       tegra_dsi_clk_enable(dsi);
+
+       dsi->enabled = true;
+}
+
 static void _tegra_dc_dsi_enable(struct tegra_dc *dc)
 {
        struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
@@ -3223,6 +3260,15 @@ static void _tegra_dc_dsi_enable(struct tegra_dc *dc)
        mutex_lock(&dsi->lock);
        tegra_dc_io_start(dc);
 
+       /*
+        * Do not program this panel as the bootloader as has already
+        * initialized it. This avoids periods of blanking during boot.
+        */
+       if (dc->out->flags & TEGRA_DC_OUT_INITIALIZED_MODE) {
+               tegra_dsi_setup_initialized_panel(dsi);
+               goto fail;
+       }
+
        /* Stop DC stream before configuring DSI registers
         * to avoid visible glitches on panel during transition
         * from bootloader to kernel driver
@@ -4153,6 +4199,16 @@ static long tegra_dc_dsi_setup_clk(struct tegra_dc *dc, struct clk *clk)
        struct clk *parent_clk;
        struct clk *base_clk;
 
+       /* divide by 1000 to avoid overflow */
+       dc->mode.pclk /= 1000;
+       rate = (dc->mode.pclk * dc->shift_clk_div.mul * 2)
+                               / dc->shift_clk_div.div;
+       rate *= 1000;
+       dc->mode.pclk *= 1000;
+
+       if (dc->out->flags & TEGRA_DC_OUT_INITIALIZED_MODE)
+               goto skip_setup;
+
        if (clk == dc->clk) {
                parent_clk = clk_get_sys(NULL,
                                dc->out->parent_clk ? : "pll_d_out0");
@@ -4175,19 +4231,13 @@ static long tegra_dc_dsi_setup_clk(struct tegra_dc *dc, struct clk *clk)
                }
        }
 
-       /* divide by 1000 to avoid overflow */
-       dc->mode.pclk /= 1000;
-       rate = (dc->mode.pclk * dc->shift_clk_div.mul * 2)
-                               / dc->shift_clk_div.div;
-       rate *= 1000;
-       dc->mode.pclk *= 1000;
-
        if (rate != clk_get_rate(base_clk))
                clk_set_rate(base_clk, rate);
 
        if (clk_get_parent(clk) != parent_clk)
                clk_set_parent(clk, parent_clk);
 
+skip_setup:
        return tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
 }