diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/tegra/dc/dsi.c | 160 |
1 files changed, 79 insertions, 81 deletions
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c index 36f91a64d8db..7e7abf5e1c2d 100644 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c @@ -2070,70 +2070,95 @@ static void tegra_dc_dsi_destroy(struct tegra_dc *dc) kfree(dsi); } -static void tegra_dc_dsi_disable(struct tegra_dc *dc) +static int tegra_dsi_deep_sleep(struct tegra_dc *dc, + struct tegra_dc_dsi_data *dsi) { - int err; - u32 val; - struct clk *base_clk; - struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); + int err = 0; + int val; + struct clk *parent_clk = NULL; + struct clk *base_clk = NULL; - tegra_dc_io_start(dc); - mutex_lock(&dsi->lock); + if (!dsi->enabled) { + err = -EPERM; + goto fail; + } - if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) - tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi); + err = tegra_dsi_set_to_lp_mode(dc, dsi); + if (err < 0) { + dev_err(&dc->ndev->dev, + "DSI failed to go to LP mode\n"); + goto fail; + } - if (dsi->info.power_saving_suspend) { - if (!dsi->enabled) - goto fail; + /* Suspend panel */ + err = tegra_dsi_send_panel_cmd(dc, dsi, + dsi->info.dsi_suspend_cmd, + dsi->info.n_suspend_cmd); + if (err < 0) { + dev_err(&dc->ndev->dev, + "dsi: Error sending suspend cmd\n"); + goto fail; + } - err = tegra_dsi_set_to_lp_mode(dc, dsi); + if (!dsi->ulpm) { + err = tegra_dsi_enter_ulpm(dsi); if (err < 0) { dev_err(&dc->ndev->dev, - "DSI failed to go to LP mode\n"); + "DSI failed to enter ulpm\n"); goto fail; } + } - err = tegra_dsi_send_panel_cmd(dc, dsi, - dsi->info.dsi_suspend_cmd, - dsi->info.n_suspend_cmd); - if (err < 0) { - dev_err(&dc->ndev->dev, - "dsi: Error sending suspend cmd\n"); - goto fail; - } + /* Suspend pad */ + val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL); + val = DSI_PAD_CONTROL_PAD_PDIO(0x3) | + DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) | + DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE); + tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL); - if (!dsi->ulpm) { - if (tegra_dsi_enter_ulpm(dsi) < 0) - printk(KERN_ERR "DSI failed to enter ulpm\n"); - } + /* Suspend core-logic */ + val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE); + tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL); - /* Suspend pad */ - val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL); - val = DSI_PAD_CONTROL_PAD_PDIO(0x3) | - DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) | - DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE); - tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL); + /* Disable dsi fast and slow clock */ + parent_clk = clk_get_parent(dsi->dsi_clk); + base_clk = clk_get_parent(parent_clk); + if (dsi->info.dsi_instance) + tegra_clk_cfg_ex(base_clk, + TEGRA_CLK_PLLD_CSI_OUT_ENB, + 0); + else + tegra_clk_cfg_ex(base_clk, + TEGRA_CLK_PLLD_DSI_OUT_ENB, + 0); - /* Suspend core-logic */ - val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE); - tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL); + /* Disable dsi source clock */ + clk_disable(dsi->dsi_clk); - /* Disable phy clock */ - base_clk = clk_get_parent(dsi->dsi_clk); - if (dsi->info.dsi_instance) - tegra_clk_cfg_ex(base_clk, - TEGRA_CLK_PLLD_CSI_OUT_ENB, - 0); - else - tegra_clk_cfg_ex(base_clk, - TEGRA_CLK_PLLD_DSI_OUT_ENB, - 0); + dsi->clk_ref = false; + dsi->enabled = false; - /* Disable DSI source clock */ - clk_disable(dsi->dsi_clk); - dsi->clk_ref = false; - dsi->enabled = false; + return 0; +fail: + return err; +} + +static void tegra_dc_dsi_disable(struct tegra_dc *dc) +{ + int err; + struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); + + tegra_dc_io_start(dc); + mutex_lock(&dsi->lock); + + if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) + tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi); + + if (dsi->info.power_saving_suspend) { + if (tegra_dsi_deep_sleep(dc, dsi) < 0) { + printk(KERN_ERR "DSI failed to enter deep sleep\n"); + goto fail; + } } else { if (dsi->info.dsi_early_suspend_cmd) { err = tegra_dsi_send_panel_cmd(dc, dsi, @@ -2147,8 +2172,10 @@ static void tegra_dc_dsi_disable(struct tegra_dc *dc) } if (!dsi->ulpm) { - if (tegra_dsi_enter_ulpm(dsi) < 0) + if (tegra_dsi_enter_ulpm(dsi) < 0) { printk(KERN_ERR "DSI failed to enter ulpm\n"); + goto fail; + } } } @@ -2161,8 +2188,6 @@ fail: static void tegra_dc_dsi_suspend(struct tegra_dc *dc) { struct tegra_dc_dsi_data *dsi; - int err; - u32 val; dsi = tegra_dc_get_outdata(dc); @@ -2180,37 +2205,10 @@ static void tegra_dc_dsi_suspend(struct tegra_dc *dc) } } - /* Suspend Panel */ - err = tegra_dsi_send_panel_cmd(dc, dsi, - dsi->info.dsi_suspend_cmd, - dsi->info.n_suspend_cmd); - if (err < 0) { - dev_err(&dc->ndev->dev, - "dsi: Error sending suspend cmd\n"); + if (tegra_dsi_deep_sleep(dc, dsi) < 0) { + printk(KERN_ERR "DSI failed to enter deep sleep\n"); goto fail; } - if (!dsi->ulpm) { - if (tegra_dsi_enter_ulpm(dsi) < 0) { - printk(KERN_ERR "DSI failed to enter ulpm\n"); - goto fail; - } - } - - /* Suspend pad */ - val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL); - val = DSI_PAD_CONTROL_PAD_PDIO(0x3) | - DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) | - DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE); - tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL); - - /* Suspend core-logic */ - val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE); - tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL); - - dsi->enabled = false; - - clk_disable(dsi->dsi_clk); - dsi->clk_ref = false; } fail: mutex_unlock(&dsi->lock); |