diff options
author | Animesh Kishore <ankishore@nvidia.com> | 2011-08-26 15:22:41 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:01:40 -0400 |
commit | f78de6b4d64b550db4bef14801351893bef3ea4a (patch) | |
tree | 65fd408ca8a0dd4d5df371ce8b4a87a1c3cffadf /drivers/video | |
parent | 64f2e2884bd3399599854baaf5e95898b91f9673 (diff) |
video: tegra: dsi: deep sleep
Aggregate code for dsi deep sleep
Bug 862427
Original-Change-Id: I5296e6659112642f9fe0fb84bec1d5938014c33a
Reviewed-on: http://git-master/r/49506
Reviewed-by: Animesh Kishore <ankishore@nvidia.com>
Tested-by: Animesh Kishore <ankishore@nvidia.com>
Reviewed-by: Kevin Huang <kevinh@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Rebase-Id: Ref7c30c407efe88481af5f2d23e5892bb0d05ef3
Diffstat (limited to 'drivers/video')
-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 9c260ea7c..57208c2df 100644 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c | |||
@@ -2069,70 +2069,95 @@ static void tegra_dc_dsi_destroy(struct tegra_dc *dc) | |||
2069 | kfree(dsi); | 2069 | kfree(dsi); |
2070 | } | 2070 | } |
2071 | 2071 | ||
2072 | static void tegra_dc_dsi_disable(struct tegra_dc *dc) | 2072 | static int tegra_dsi_deep_sleep(struct tegra_dc *dc, |
2073 | struct tegra_dc_dsi_data *dsi) | ||
2073 | { | 2074 | { |
2074 | int err; | 2075 | int err = 0; |
2075 | u32 val; | 2076 | int val; |
2076 | struct clk *base_clk; | 2077 | struct clk *parent_clk = NULL; |
2077 | struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); | 2078 | struct clk *base_clk = NULL; |
2078 | 2079 | ||
2079 | tegra_dc_io_start(dc); | 2080 | if (!dsi->enabled) { |
2080 | mutex_lock(&dsi->lock); | 2081 | err = -EPERM; |
2082 | goto fail; | ||
2083 | } | ||
2081 | 2084 | ||
2082 | if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) | 2085 | err = tegra_dsi_set_to_lp_mode(dc, dsi); |
2083 | tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi); | 2086 | if (err < 0) { |
2087 | dev_err(&dc->ndev->dev, | ||
2088 | "DSI failed to go to LP mode\n"); | ||
2089 | goto fail; | ||
2090 | } | ||
2084 | 2091 | ||
2085 | if (dsi->info.power_saving_suspend) { | 2092 | /* Suspend panel */ |
2086 | if (!dsi->enabled) | 2093 | err = tegra_dsi_send_panel_cmd(dc, dsi, |
2087 | goto fail; | 2094 | dsi->info.dsi_suspend_cmd, |
2095 | dsi->info.n_suspend_cmd); | ||
2096 | if (err < 0) { | ||
2097 | dev_err(&dc->ndev->dev, | ||
2098 | "dsi: Error sending suspend cmd\n"); | ||
2099 | goto fail; | ||
2100 | } | ||
2088 | 2101 | ||
2089 | err = tegra_dsi_set_to_lp_mode(dc, dsi); | 2102 | if (!dsi->ulpm) { |
2103 | err = tegra_dsi_enter_ulpm(dsi); | ||
2090 | if (err < 0) { | 2104 | if (err < 0) { |
2091 | dev_err(&dc->ndev->dev, | 2105 | dev_err(&dc->ndev->dev, |
2092 | "DSI failed to go to LP mode\n"); | 2106 | "DSI failed to enter ulpm\n"); |
2093 | goto fail; | 2107 | goto fail; |
2094 | } | 2108 | } |
2109 | } | ||
2095 | 2110 | ||
2096 | err = tegra_dsi_send_panel_cmd(dc, dsi, | 2111 | /* Suspend pad */ |
2097 | dsi->info.dsi_suspend_cmd, | 2112 | val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL); |
2098 | dsi->info.n_suspend_cmd); | 2113 | val = DSI_PAD_CONTROL_PAD_PDIO(0x3) | |
2099 | if (err < 0) { | 2114 | DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) | |
2100 | dev_err(&dc->ndev->dev, | 2115 | DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE); |
2101 | "dsi: Error sending suspend cmd\n"); | 2116 | tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL); |
2102 | goto fail; | ||
2103 | } | ||
2104 | 2117 | ||
2105 | if (!dsi->ulpm) { | 2118 | /* Suspend core-logic */ |
2106 | if (tegra_dsi_enter_ulpm(dsi) < 0) | 2119 | val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE); |
2107 | printk(KERN_ERR "DSI failed to enter ulpm\n"); | 2120 | tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL); |
2108 | } | ||
2109 | 2121 | ||
2110 | /* Suspend pad */ | 2122 | /* Disable dsi fast and slow clock */ |
2111 | val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL); | 2123 | parent_clk = clk_get_parent(dsi->dsi_clk); |
2112 | val = DSI_PAD_CONTROL_PAD_PDIO(0x3) | | 2124 | base_clk = clk_get_parent(parent_clk); |
2113 | DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) | | 2125 | if (dsi->info.dsi_instance) |
2114 | DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE); | 2126 | tegra_clk_cfg_ex(base_clk, |
2115 | tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL); | 2127 | TEGRA_CLK_PLLD_CSI_OUT_ENB, |
2128 | 0); | ||
2129 | else | ||
2130 | tegra_clk_cfg_ex(base_clk, | ||
2131 | TEGRA_CLK_PLLD_DSI_OUT_ENB, | ||
2132 | 0); | ||
2116 | 2133 | ||
2117 | /* Suspend core-logic */ | 2134 | /* Disable dsi source clock */ |
2118 | val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE); | 2135 | clk_disable(dsi->dsi_clk); |
2119 | tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL); | ||
2120 | 2136 | ||
2121 | /* Disable phy clock */ | 2137 | dsi->clk_ref = false; |
2122 | base_clk = clk_get_parent(dsi->dsi_clk); | 2138 | dsi->enabled = false; |
2123 | if (dsi->info.dsi_instance) | ||
2124 | tegra_clk_cfg_ex(base_clk, | ||
2125 | TEGRA_CLK_PLLD_CSI_OUT_ENB, | ||
2126 | 0); | ||
2127 | else | ||
2128 | tegra_clk_cfg_ex(base_clk, | ||
2129 | TEGRA_CLK_PLLD_DSI_OUT_ENB, | ||
2130 | 0); | ||
2131 | 2139 | ||
2132 | /* Disable DSI source clock */ | 2140 | return 0; |
2133 | clk_disable(dsi->dsi_clk); | 2141 | fail: |
2134 | dsi->clk_ref = false; | 2142 | return err; |
2135 | dsi->enabled = false; | 2143 | } |
2144 | |||
2145 | static void tegra_dc_dsi_disable(struct tegra_dc *dc) | ||
2146 | { | ||
2147 | int err; | ||
2148 | struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); | ||
2149 | |||
2150 | tegra_dc_io_start(dc); | ||
2151 | mutex_lock(&dsi->lock); | ||
2152 | |||
2153 | if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) | ||
2154 | tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi); | ||
2155 | |||
2156 | if (dsi->info.power_saving_suspend) { | ||
2157 | if (tegra_dsi_deep_sleep(dc, dsi) < 0) { | ||
2158 | printk(KERN_ERR "DSI failed to enter deep sleep\n"); | ||
2159 | goto fail; | ||
2160 | } | ||
2136 | } else { | 2161 | } else { |
2137 | if (dsi->info.dsi_early_suspend_cmd) { | 2162 | if (dsi->info.dsi_early_suspend_cmd) { |
2138 | err = tegra_dsi_send_panel_cmd(dc, dsi, | 2163 | err = tegra_dsi_send_panel_cmd(dc, dsi, |
@@ -2146,8 +2171,10 @@ static void tegra_dc_dsi_disable(struct tegra_dc *dc) | |||
2146 | } | 2171 | } |
2147 | 2172 | ||
2148 | if (!dsi->ulpm) { | 2173 | if (!dsi->ulpm) { |
2149 | if (tegra_dsi_enter_ulpm(dsi) < 0) | 2174 | if (tegra_dsi_enter_ulpm(dsi) < 0) { |
2150 | printk(KERN_ERR "DSI failed to enter ulpm\n"); | 2175 | printk(KERN_ERR "DSI failed to enter ulpm\n"); |
2176 | goto fail; | ||
2177 | } | ||
2151 | } | 2178 | } |
2152 | } | 2179 | } |
2153 | 2180 | ||
@@ -2160,8 +2187,6 @@ fail: | |||
2160 | static void tegra_dc_dsi_suspend(struct tegra_dc *dc) | 2187 | static void tegra_dc_dsi_suspend(struct tegra_dc *dc) |
2161 | { | 2188 | { |
2162 | struct tegra_dc_dsi_data *dsi; | 2189 | struct tegra_dc_dsi_data *dsi; |
2163 | int err; | ||
2164 | u32 val; | ||
2165 | 2190 | ||
2166 | dsi = tegra_dc_get_outdata(dc); | 2191 | dsi = tegra_dc_get_outdata(dc); |
2167 | 2192 | ||
@@ -2179,37 +2204,10 @@ static void tegra_dc_dsi_suspend(struct tegra_dc *dc) | |||
2179 | } | 2204 | } |
2180 | } | 2205 | } |
2181 | 2206 | ||
2182 | /* Suspend Panel */ | 2207 | if (tegra_dsi_deep_sleep(dc, dsi) < 0) { |
2183 | err = tegra_dsi_send_panel_cmd(dc, dsi, | 2208 | printk(KERN_ERR "DSI failed to enter deep sleep\n"); |
2184 | dsi->info.dsi_suspend_cmd, | ||
2185 | dsi->info.n_suspend_cmd); | ||
2186 | if (err < 0) { | ||
2187 | dev_err(&dc->ndev->dev, | ||
2188 | "dsi: Error sending suspend cmd\n"); | ||
2189 | goto fail; | 2209 | goto fail; |
2190 | } | 2210 | } |
2191 | if (!dsi->ulpm) { | ||
2192 | if (tegra_dsi_enter_ulpm(dsi) < 0) { | ||
2193 | printk(KERN_ERR "DSI failed to enter ulpm\n"); | ||
2194 | goto fail; | ||
2195 | } | ||
2196 | } | ||
2197 | |||
2198 | /* Suspend pad */ | ||
2199 | val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL); | ||
2200 | val = DSI_PAD_CONTROL_PAD_PDIO(0x3) | | ||
2201 | DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) | | ||
2202 | DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE); | ||
2203 | tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL); | ||
2204 | |||
2205 | /* Suspend core-logic */ | ||
2206 | val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE); | ||
2207 | tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL); | ||
2208 | |||
2209 | dsi->enabled = false; | ||
2210 | |||
2211 | clk_disable(dsi->dsi_clk); | ||
2212 | dsi->clk_ref = false; | ||
2213 | } | 2211 | } |
2214 | fail: | 2212 | fail: |
2215 | mutex_unlock(&dsi->lock); | 2213 | mutex_unlock(&dsi->lock); |