diff options
-rw-r--r-- | arch/arm/mach-omap2/clock2420_data.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock2430_data.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock3xxx_data.c | 14 | ||||
-rw-r--r-- | drivers/video/omap2/dss/core.c | 343 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.c | 334 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 13 |
6 files changed, 360 insertions, 360 deletions
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 0a992bc8d0d8..9ece62a44a3f 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c | |||
@@ -1786,10 +1786,10 @@ static struct omap_clk omap2420_clks[] = { | |||
1786 | CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X), | 1786 | CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X), |
1787 | CLK(NULL, "gfx_ick", &gfx_ick, CK_242X), | 1787 | CLK(NULL, "gfx_ick", &gfx_ick, CK_242X), |
1788 | /* DSS domain clocks */ | 1788 | /* DSS domain clocks */ |
1789 | CLK("omapdss", "ick", &dss_ick, CK_242X), | 1789 | CLK("omapdss_dss", "ick", &dss_ick, CK_242X), |
1790 | CLK("omapdss", "dss1_fck", &dss1_fck, CK_242X), | 1790 | CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_242X), |
1791 | CLK("omapdss", "dss2_fck", &dss2_fck, CK_242X), | 1791 | CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_242X), |
1792 | CLK("omapdss", "tv_fck", &dss_54m_fck, CK_242X), | 1792 | CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_242X), |
1793 | /* L3 domain clocks */ | 1793 | /* L3 domain clocks */ |
1794 | CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X), | 1794 | CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X), |
1795 | CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X), | 1795 | CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X), |
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 5c647ce05b04..61006ae7eac4 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c | |||
@@ -1890,10 +1890,10 @@ static struct omap_clk omap2430_clks[] = { | |||
1890 | CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), | 1890 | CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), |
1891 | CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), | 1891 | CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), |
1892 | /* DSS domain clocks */ | 1892 | /* DSS domain clocks */ |
1893 | CLK("omapdss", "ick", &dss_ick, CK_243X), | 1893 | CLK("omapdss_dss", "ick", &dss_ick, CK_243X), |
1894 | CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X), | 1894 | CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_243X), |
1895 | CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X), | 1895 | CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_243X), |
1896 | CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X), | 1896 | CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_243X), |
1897 | /* L3 domain clocks */ | 1897 | /* L3 domain clocks */ |
1898 | CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X), | 1898 | CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X), |
1899 | CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X), | 1899 | CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X), |
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 052ac329282f..2e47d16fce77 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c | |||
@@ -3357,13 +3357,13 @@ static struct omap_clk omap3xxx_clks[] = { | |||
3357 | CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX), | 3357 | CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX), |
3358 | CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX), | 3358 | CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX), |
3359 | CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX), | 3359 | CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX), |
3360 | CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), | 3360 | CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), |
3361 | CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | 3361 | CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), |
3362 | CLK("omapdss", "tv_fck", &dss_tv_fck, CK_3XXX), | 3362 | CLK("omapdss_dss", "tv_fck", &dss_tv_fck, CK_3XXX), |
3363 | CLK("omapdss", "video_fck", &dss_96m_fck, CK_3XXX), | 3363 | CLK("omapdss_dss", "video_fck", &dss_96m_fck, CK_3XXX), |
3364 | CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_3XXX), | 3364 | CLK("omapdss_dss", "dss2_fck", &dss2_alwon_fck, CK_3XXX), |
3365 | CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1), | 3365 | CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1), |
3366 | CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | 3366 | CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), |
3367 | CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX), | 3367 | CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX), |
3368 | CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), | 3368 | CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), |
3369 | CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), | 3369 | CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), |
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index e399ca22e514..255935541d0d 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -34,32 +34,18 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include <plat/clock.h> | ||
38 | 37 | ||
39 | #include "dss.h" | 38 | #include "dss.h" |
40 | #include "dss_features.h" | 39 | #include "dss_features.h" |
41 | 40 | ||
42 | static struct { | 41 | static struct { |
43 | struct platform_device *pdev; | 42 | struct platform_device *pdev; |
44 | int ctx_id; | ||
45 | |||
46 | struct clk *dss_ick; | ||
47 | struct clk *dss1_fck; | ||
48 | struct clk *dss2_fck; | ||
49 | struct clk *dss_54m_fck; | ||
50 | struct clk *dss_96m_fck; | ||
51 | unsigned num_clks_enabled; | ||
52 | 43 | ||
53 | struct regulator *vdds_dsi_reg; | 44 | struct regulator *vdds_dsi_reg; |
54 | struct regulator *vdds_sdi_reg; | 45 | struct regulator *vdds_sdi_reg; |
55 | struct regulator *vdda_dac_reg; | 46 | struct regulator *vdda_dac_reg; |
56 | } core; | 47 | } core; |
57 | 48 | ||
58 | static void dss_clk_enable_all_no_ctx(void); | ||
59 | static void dss_clk_disable_all_no_ctx(void); | ||
60 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
61 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
62 | |||
63 | static char *def_disp_name; | 49 | static char *def_disp_name; |
64 | module_param_named(def_disp, def_disp_name, charp, 0); | 50 | module_param_named(def_disp, def_disp_name, charp, 0); |
65 | MODULE_PARM_DESC(def_disp_name, "default display name"); | 51 | MODULE_PARM_DESC(def_disp_name, "default display name"); |
@@ -69,297 +55,6 @@ unsigned int dss_debug; | |||
69 | module_param_named(debug, dss_debug, bool, 0644); | 55 | module_param_named(debug, dss_debug, bool, 0644); |
70 | #endif | 56 | #endif |
71 | 57 | ||
72 | /* CONTEXT */ | ||
73 | static int dss_get_ctx_id(void) | ||
74 | { | ||
75 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
76 | int r; | ||
77 | |||
78 | if (!pdata->get_last_off_on_transaction_id) | ||
79 | return 0; | ||
80 | r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); | ||
81 | if (r < 0) { | ||
82 | dev_err(&core.pdev->dev, "getting transaction ID failed, " | ||
83 | "will force context restore\n"); | ||
84 | r = -1; | ||
85 | } | ||
86 | return r; | ||
87 | } | ||
88 | |||
89 | int dss_need_ctx_restore(void) | ||
90 | { | ||
91 | int id = dss_get_ctx_id(); | ||
92 | |||
93 | if (id < 0 || id != core.ctx_id) { | ||
94 | DSSDBG("ctx id %d -> id %d\n", | ||
95 | core.ctx_id, id); | ||
96 | core.ctx_id = id; | ||
97 | return 1; | ||
98 | } else { | ||
99 | return 0; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static void save_all_ctx(void) | ||
104 | { | ||
105 | DSSDBG("save context\n"); | ||
106 | |||
107 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
108 | |||
109 | dss_save_context(); | ||
110 | dispc_save_context(); | ||
111 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
112 | dsi_save_context(); | ||
113 | #endif | ||
114 | |||
115 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
116 | } | ||
117 | |||
118 | static void restore_all_ctx(void) | ||
119 | { | ||
120 | DSSDBG("restore context\n"); | ||
121 | |||
122 | dss_clk_enable_all_no_ctx(); | ||
123 | |||
124 | dss_restore_context(); | ||
125 | dispc_restore_context(); | ||
126 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
127 | dsi_restore_context(); | ||
128 | #endif | ||
129 | |||
130 | dss_clk_disable_all_no_ctx(); | ||
131 | } | ||
132 | |||
133 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
134 | /* CLOCKS */ | ||
135 | static void core_dump_clocks(struct seq_file *s) | ||
136 | { | ||
137 | int i; | ||
138 | struct clk *clocks[5] = { | ||
139 | core.dss_ick, | ||
140 | core.dss1_fck, | ||
141 | core.dss2_fck, | ||
142 | core.dss_54m_fck, | ||
143 | core.dss_96m_fck | ||
144 | }; | ||
145 | |||
146 | seq_printf(s, "- CORE -\n"); | ||
147 | |||
148 | seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); | ||
149 | |||
150 | for (i = 0; i < 5; i++) { | ||
151 | if (!clocks[i]) | ||
152 | continue; | ||
153 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
154 | clocks[i]->name, | ||
155 | clk_get_rate(clocks[i]), | ||
156 | clocks[i]->usecount); | ||
157 | } | ||
158 | } | ||
159 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
160 | |||
161 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
162 | { | ||
163 | struct clk *clk; | ||
164 | |||
165 | clk = clk_get(&core.pdev->dev, clk_name); | ||
166 | |||
167 | if (IS_ERR(clk)) { | ||
168 | DSSERR("can't get clock %s", clk_name); | ||
169 | return PTR_ERR(clk); | ||
170 | } | ||
171 | |||
172 | *clock = clk; | ||
173 | |||
174 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int dss_get_clocks(void) | ||
180 | { | ||
181 | int r; | ||
182 | |||
183 | core.dss_ick = NULL; | ||
184 | core.dss1_fck = NULL; | ||
185 | core.dss2_fck = NULL; | ||
186 | core.dss_54m_fck = NULL; | ||
187 | core.dss_96m_fck = NULL; | ||
188 | |||
189 | r = dss_get_clock(&core.dss_ick, "ick"); | ||
190 | if (r) | ||
191 | goto err; | ||
192 | |||
193 | r = dss_get_clock(&core.dss1_fck, "dss1_fck"); | ||
194 | if (r) | ||
195 | goto err; | ||
196 | |||
197 | r = dss_get_clock(&core.dss2_fck, "dss2_fck"); | ||
198 | if (r) | ||
199 | goto err; | ||
200 | |||
201 | r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); | ||
202 | if (r) | ||
203 | goto err; | ||
204 | |||
205 | r = dss_get_clock(&core.dss_96m_fck, "video_fck"); | ||
206 | if (r) | ||
207 | goto err; | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err: | ||
212 | if (core.dss_ick) | ||
213 | clk_put(core.dss_ick); | ||
214 | if (core.dss1_fck) | ||
215 | clk_put(core.dss1_fck); | ||
216 | if (core.dss2_fck) | ||
217 | clk_put(core.dss2_fck); | ||
218 | if (core.dss_54m_fck) | ||
219 | clk_put(core.dss_54m_fck); | ||
220 | if (core.dss_96m_fck) | ||
221 | clk_put(core.dss_96m_fck); | ||
222 | |||
223 | return r; | ||
224 | } | ||
225 | |||
226 | static void dss_put_clocks(void) | ||
227 | { | ||
228 | if (core.dss_96m_fck) | ||
229 | clk_put(core.dss_96m_fck); | ||
230 | clk_put(core.dss_54m_fck); | ||
231 | clk_put(core.dss1_fck); | ||
232 | clk_put(core.dss2_fck); | ||
233 | clk_put(core.dss_ick); | ||
234 | } | ||
235 | |||
236 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
237 | { | ||
238 | switch (clk) { | ||
239 | case DSS_CLK_ICK: | ||
240 | return clk_get_rate(core.dss_ick); | ||
241 | case DSS_CLK_FCK1: | ||
242 | return clk_get_rate(core.dss1_fck); | ||
243 | case DSS_CLK_FCK2: | ||
244 | return clk_get_rate(core.dss2_fck); | ||
245 | case DSS_CLK_54M: | ||
246 | return clk_get_rate(core.dss_54m_fck); | ||
247 | case DSS_CLK_96M: | ||
248 | return clk_get_rate(core.dss_96m_fck); | ||
249 | } | ||
250 | |||
251 | BUG(); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static unsigned count_clk_bits(enum dss_clock clks) | ||
256 | { | ||
257 | unsigned num_clks = 0; | ||
258 | |||
259 | if (clks & DSS_CLK_ICK) | ||
260 | ++num_clks; | ||
261 | if (clks & DSS_CLK_FCK1) | ||
262 | ++num_clks; | ||
263 | if (clks & DSS_CLK_FCK2) | ||
264 | ++num_clks; | ||
265 | if (clks & DSS_CLK_54M) | ||
266 | ++num_clks; | ||
267 | if (clks & DSS_CLK_96M) | ||
268 | ++num_clks; | ||
269 | |||
270 | return num_clks; | ||
271 | } | ||
272 | |||
273 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
274 | { | ||
275 | unsigned num_clks = count_clk_bits(clks); | ||
276 | |||
277 | if (clks & DSS_CLK_ICK) | ||
278 | clk_enable(core.dss_ick); | ||
279 | if (clks & DSS_CLK_FCK1) | ||
280 | clk_enable(core.dss1_fck); | ||
281 | if (clks & DSS_CLK_FCK2) | ||
282 | clk_enable(core.dss2_fck); | ||
283 | if (clks & DSS_CLK_54M) | ||
284 | clk_enable(core.dss_54m_fck); | ||
285 | if (clks & DSS_CLK_96M) | ||
286 | clk_enable(core.dss_96m_fck); | ||
287 | |||
288 | core.num_clks_enabled += num_clks; | ||
289 | } | ||
290 | |||
291 | void dss_clk_enable(enum dss_clock clks) | ||
292 | { | ||
293 | bool check_ctx = core.num_clks_enabled == 0; | ||
294 | |||
295 | dss_clk_enable_no_ctx(clks); | ||
296 | |||
297 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
298 | restore_all_ctx(); | ||
299 | } | ||
300 | |||
301 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
302 | { | ||
303 | unsigned num_clks = count_clk_bits(clks); | ||
304 | |||
305 | if (clks & DSS_CLK_ICK) | ||
306 | clk_disable(core.dss_ick); | ||
307 | if (clks & DSS_CLK_FCK1) | ||
308 | clk_disable(core.dss1_fck); | ||
309 | if (clks & DSS_CLK_FCK2) | ||
310 | clk_disable(core.dss2_fck); | ||
311 | if (clks & DSS_CLK_54M) | ||
312 | clk_disable(core.dss_54m_fck); | ||
313 | if (clks & DSS_CLK_96M) | ||
314 | clk_disable(core.dss_96m_fck); | ||
315 | |||
316 | core.num_clks_enabled -= num_clks; | ||
317 | } | ||
318 | |||
319 | void dss_clk_disable(enum dss_clock clks) | ||
320 | { | ||
321 | if (cpu_is_omap34xx()) { | ||
322 | unsigned num_clks = count_clk_bits(clks); | ||
323 | |||
324 | BUG_ON(core.num_clks_enabled < num_clks); | ||
325 | |||
326 | if (core.num_clks_enabled == num_clks) | ||
327 | save_all_ctx(); | ||
328 | } | ||
329 | |||
330 | dss_clk_disable_no_ctx(clks); | ||
331 | } | ||
332 | |||
333 | static void dss_clk_enable_all_no_ctx(void) | ||
334 | { | ||
335 | enum dss_clock clks; | ||
336 | |||
337 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
338 | if (cpu_is_omap34xx()) | ||
339 | clks |= DSS_CLK_96M; | ||
340 | dss_clk_enable_no_ctx(clks); | ||
341 | } | ||
342 | |||
343 | static void dss_clk_disable_all_no_ctx(void) | ||
344 | { | ||
345 | enum dss_clock clks; | ||
346 | |||
347 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
348 | if (cpu_is_omap34xx()) | ||
349 | clks |= DSS_CLK_96M; | ||
350 | dss_clk_disable_no_ctx(clks); | ||
351 | } | ||
352 | |||
353 | static void dss_clk_disable_all(void) | ||
354 | { | ||
355 | enum dss_clock clks; | ||
356 | |||
357 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
358 | if (cpu_is_omap34xx()) | ||
359 | clks |= DSS_CLK_96M; | ||
360 | dss_clk_disable(clks); | ||
361 | } | ||
362 | |||
363 | /* REGULATORS */ | 58 | /* REGULATORS */ |
364 | 59 | ||
365 | struct regulator *dss_get_vdds_dsi(void) | 60 | struct regulator *dss_get_vdds_dsi(void) |
@@ -404,18 +99,7 @@ struct regulator *dss_get_vdda_dac(void) | |||
404 | return reg; | 99 | return reg; |
405 | } | 100 | } |
406 | 101 | ||
407 | /* DEBUGFS */ | ||
408 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 102 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
409 | static void dss_debug_dump_clocks(struct seq_file *s) | ||
410 | { | ||
411 | core_dump_clocks(s); | ||
412 | dss_dump_clocks(s); | ||
413 | dispc_dump_clocks(s); | ||
414 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
415 | dsi_dump_clocks(s); | ||
416 | #endif | ||
417 | } | ||
418 | |||
419 | static int dss_debug_show(struct seq_file *s, void *unused) | 103 | static int dss_debug_show(struct seq_file *s, void *unused) |
420 | { | 104 | { |
421 | void (*func)(struct seq_file *) = s->private; | 105 | void (*func)(struct seq_file *) = s->private; |
@@ -508,21 +192,15 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
508 | dss_init_overlay_managers(pdev); | 192 | dss_init_overlay_managers(pdev); |
509 | dss_init_overlays(pdev); | 193 | dss_init_overlays(pdev); |
510 | 194 | ||
511 | r = dss_get_clocks(); | ||
512 | if (r) | ||
513 | goto err_clocks; | ||
514 | |||
515 | dss_clk_enable_all_no_ctx(); | ||
516 | |||
517 | core.ctx_id = dss_get_ctx_id(); | ||
518 | DSSDBG("initial ctx id %u\n", core.ctx_id); | ||
519 | |||
520 | r = dss_init_platform_driver(); | 195 | r = dss_init_platform_driver(); |
521 | if (r) { | 196 | if (r) { |
522 | DSSERR("Failed to initialize DSS platform driver\n"); | 197 | DSSERR("Failed to initialize DSS platform driver\n"); |
523 | goto err_dss; | 198 | goto err_dss; |
524 | } | 199 | } |
525 | 200 | ||
201 | /* keep clocks enabled to prevent context saves/restores during init */ | ||
202 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
203 | |||
526 | r = rfbi_init(); | 204 | r = rfbi_init(); |
527 | if (r) { | 205 | if (r) { |
528 | DSSERR("Failed to initialize rfbi\n"); | 206 | DSSERR("Failed to initialize rfbi\n"); |
@@ -588,7 +266,7 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
588 | pdata->default_device = dssdev; | 266 | pdata->default_device = dssdev; |
589 | } | 267 | } |
590 | 268 | ||
591 | dss_clk_disable_all(); | 269 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); |
592 | 270 | ||
593 | return 0; | 271 | return 0; |
594 | 272 | ||
@@ -611,9 +289,6 @@ err_dpi: | |||
611 | err_rfbi: | 289 | err_rfbi: |
612 | dss_uninit_platform_driver(); | 290 | dss_uninit_platform_driver(); |
613 | err_dss: | 291 | err_dss: |
614 | dss_clk_disable_all_no_ctx(); | ||
615 | dss_put_clocks(); | ||
616 | err_clocks: | ||
617 | 292 | ||
618 | return r; | 293 | return r; |
619 | } | 294 | } |
@@ -636,16 +311,6 @@ static int omap_dss_remove(struct platform_device *pdev) | |||
636 | 311 | ||
637 | dss_uninit_platform_driver(); | 312 | dss_uninit_platform_driver(); |
638 | 313 | ||
639 | /* | ||
640 | * As part of hwmod changes, DSS is not the only controller of dss | ||
641 | * clocks; hwmod framework itself will also enable clocks during hwmod | ||
642 | * init for dss, and autoidle is set in h/w for DSS. Hence, there's no | ||
643 | * need to disable clocks if their usecounts > 1. | ||
644 | */ | ||
645 | WARN_ON(core.num_clks_enabled > 0); | ||
646 | |||
647 | dss_put_clocks(); | ||
648 | |||
649 | dss_uninit_overlays(pdev); | 314 | dss_uninit_overlays(pdev); |
650 | dss_uninit_overlay_managers(pdev); | 315 | dss_uninit_overlay_managers(pdev); |
651 | 316 | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 01406f48f438..72b395d69aae 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <plat/display.h> |
34 | #include <plat/clock.h> | ||
34 | #include "dss.h" | 35 | #include "dss.h" |
35 | 36 | ||
36 | #define DSS_BASE 0x48050000 | 37 | #define DSS_BASE 0x48050000 |
@@ -61,8 +62,15 @@ struct dss_reg { | |||
61 | static struct { | 62 | static struct { |
62 | struct platform_device *pdev; | 63 | struct platform_device *pdev; |
63 | void __iomem *base; | 64 | void __iomem *base; |
65 | int ctx_id; | ||
64 | 66 | ||
65 | struct clk *dpll4_m4_ck; | 67 | struct clk *dpll4_m4_ck; |
68 | struct clk *dss_ick; | ||
69 | struct clk *dss1_fck; | ||
70 | struct clk *dss2_fck; | ||
71 | struct clk *dss_54m_fck; | ||
72 | struct clk *dss_96m_fck; | ||
73 | unsigned num_clks_enabled; | ||
66 | 74 | ||
67 | unsigned long cache_req_pck; | 75 | unsigned long cache_req_pck; |
68 | unsigned long cache_prate; | 76 | unsigned long cache_prate; |
@@ -75,6 +83,11 @@ static struct { | |||
75 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; | 83 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; |
76 | } dss; | 84 | } dss; |
77 | 85 | ||
86 | static void dss_clk_enable_all_no_ctx(void); | ||
87 | static void dss_clk_disable_all_no_ctx(void); | ||
88 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
89 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
90 | |||
78 | static int _omap_dss_wait_reset(void); | 91 | static int _omap_dss_wait_reset(void); |
79 | 92 | ||
80 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) | 93 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) |
@@ -640,6 +653,301 @@ static void dss_exit(void) | |||
640 | iounmap(dss.base); | 653 | iounmap(dss.base); |
641 | } | 654 | } |
642 | 655 | ||
656 | /* CONTEXT */ | ||
657 | static int dss_get_ctx_id(void) | ||
658 | { | ||
659 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
660 | int r; | ||
661 | |||
662 | if (!pdata->board_data->get_last_off_on_transaction_id) | ||
663 | return 0; | ||
664 | r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); | ||
665 | if (r < 0) { | ||
666 | dev_err(&dss.pdev->dev, "getting transaction ID failed, " | ||
667 | "will force context restore\n"); | ||
668 | r = -1; | ||
669 | } | ||
670 | return r; | ||
671 | } | ||
672 | |||
673 | int dss_need_ctx_restore(void) | ||
674 | { | ||
675 | int id = dss_get_ctx_id(); | ||
676 | |||
677 | if (id < 0 || id != dss.ctx_id) { | ||
678 | DSSDBG("ctx id %d -> id %d\n", | ||
679 | dss.ctx_id, id); | ||
680 | dss.ctx_id = id; | ||
681 | return 1; | ||
682 | } else { | ||
683 | return 0; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | static void save_all_ctx(void) | ||
688 | { | ||
689 | DSSDBG("save context\n"); | ||
690 | |||
691 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
692 | |||
693 | dss_save_context(); | ||
694 | dispc_save_context(); | ||
695 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
696 | dsi_save_context(); | ||
697 | #endif | ||
698 | |||
699 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
700 | } | ||
701 | |||
702 | static void restore_all_ctx(void) | ||
703 | { | ||
704 | DSSDBG("restore context\n"); | ||
705 | |||
706 | dss_clk_enable_all_no_ctx(); | ||
707 | |||
708 | dss_restore_context(); | ||
709 | dispc_restore_context(); | ||
710 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
711 | dsi_restore_context(); | ||
712 | #endif | ||
713 | |||
714 | dss_clk_disable_all_no_ctx(); | ||
715 | } | ||
716 | |||
717 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
718 | { | ||
719 | struct clk *clk; | ||
720 | |||
721 | clk = clk_get(&dss.pdev->dev, clk_name); | ||
722 | |||
723 | if (IS_ERR(clk)) { | ||
724 | DSSERR("can't get clock %s", clk_name); | ||
725 | return PTR_ERR(clk); | ||
726 | } | ||
727 | |||
728 | *clock = clk; | ||
729 | |||
730 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static int dss_get_clocks(void) | ||
736 | { | ||
737 | int r; | ||
738 | |||
739 | dss.dss_ick = NULL; | ||
740 | dss.dss1_fck = NULL; | ||
741 | dss.dss2_fck = NULL; | ||
742 | dss.dss_54m_fck = NULL; | ||
743 | dss.dss_96m_fck = NULL; | ||
744 | |||
745 | r = dss_get_clock(&dss.dss_ick, "ick"); | ||
746 | if (r) | ||
747 | goto err; | ||
748 | |||
749 | r = dss_get_clock(&dss.dss1_fck, "dss1_fck"); | ||
750 | if (r) | ||
751 | goto err; | ||
752 | |||
753 | r = dss_get_clock(&dss.dss2_fck, "dss2_fck"); | ||
754 | if (r) | ||
755 | goto err; | ||
756 | |||
757 | r = dss_get_clock(&dss.dss_54m_fck, "tv_fck"); | ||
758 | if (r) | ||
759 | goto err; | ||
760 | |||
761 | r = dss_get_clock(&dss.dss_96m_fck, "video_fck"); | ||
762 | if (r) | ||
763 | goto err; | ||
764 | |||
765 | return 0; | ||
766 | |||
767 | err: | ||
768 | if (dss.dss_ick) | ||
769 | clk_put(dss.dss_ick); | ||
770 | if (dss.dss1_fck) | ||
771 | clk_put(dss.dss1_fck); | ||
772 | if (dss.dss2_fck) | ||
773 | clk_put(dss.dss2_fck); | ||
774 | if (dss.dss_54m_fck) | ||
775 | clk_put(dss.dss_54m_fck); | ||
776 | if (dss.dss_96m_fck) | ||
777 | clk_put(dss.dss_96m_fck); | ||
778 | |||
779 | return r; | ||
780 | } | ||
781 | |||
782 | static void dss_put_clocks(void) | ||
783 | { | ||
784 | if (dss.dss_96m_fck) | ||
785 | clk_put(dss.dss_96m_fck); | ||
786 | clk_put(dss.dss_54m_fck); | ||
787 | clk_put(dss.dss1_fck); | ||
788 | clk_put(dss.dss2_fck); | ||
789 | clk_put(dss.dss_ick); | ||
790 | } | ||
791 | |||
792 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
793 | { | ||
794 | switch (clk) { | ||
795 | case DSS_CLK_ICK: | ||
796 | return clk_get_rate(dss.dss_ick); | ||
797 | case DSS_CLK_FCK1: | ||
798 | return clk_get_rate(dss.dss1_fck); | ||
799 | case DSS_CLK_FCK2: | ||
800 | return clk_get_rate(dss.dss2_fck); | ||
801 | case DSS_CLK_54M: | ||
802 | return clk_get_rate(dss.dss_54m_fck); | ||
803 | case DSS_CLK_96M: | ||
804 | return clk_get_rate(dss.dss_96m_fck); | ||
805 | } | ||
806 | |||
807 | BUG(); | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static unsigned count_clk_bits(enum dss_clock clks) | ||
812 | { | ||
813 | unsigned num_clks = 0; | ||
814 | |||
815 | if (clks & DSS_CLK_ICK) | ||
816 | ++num_clks; | ||
817 | if (clks & DSS_CLK_FCK1) | ||
818 | ++num_clks; | ||
819 | if (clks & DSS_CLK_FCK2) | ||
820 | ++num_clks; | ||
821 | if (clks & DSS_CLK_54M) | ||
822 | ++num_clks; | ||
823 | if (clks & DSS_CLK_96M) | ||
824 | ++num_clks; | ||
825 | |||
826 | return num_clks; | ||
827 | } | ||
828 | |||
829 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
830 | { | ||
831 | unsigned num_clks = count_clk_bits(clks); | ||
832 | |||
833 | if (clks & DSS_CLK_ICK) | ||
834 | clk_enable(dss.dss_ick); | ||
835 | if (clks & DSS_CLK_FCK1) | ||
836 | clk_enable(dss.dss1_fck); | ||
837 | if (clks & DSS_CLK_FCK2) | ||
838 | clk_enable(dss.dss2_fck); | ||
839 | if (clks & DSS_CLK_54M) | ||
840 | clk_enable(dss.dss_54m_fck); | ||
841 | if (clks & DSS_CLK_96M) | ||
842 | clk_enable(dss.dss_96m_fck); | ||
843 | |||
844 | dss.num_clks_enabled += num_clks; | ||
845 | } | ||
846 | |||
847 | void dss_clk_enable(enum dss_clock clks) | ||
848 | { | ||
849 | bool check_ctx = dss.num_clks_enabled == 0; | ||
850 | |||
851 | dss_clk_enable_no_ctx(clks); | ||
852 | |||
853 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
854 | restore_all_ctx(); | ||
855 | } | ||
856 | |||
857 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
858 | { | ||
859 | unsigned num_clks = count_clk_bits(clks); | ||
860 | |||
861 | if (clks & DSS_CLK_ICK) | ||
862 | clk_disable(dss.dss_ick); | ||
863 | if (clks & DSS_CLK_FCK1) | ||
864 | clk_disable(dss.dss1_fck); | ||
865 | if (clks & DSS_CLK_FCK2) | ||
866 | clk_disable(dss.dss2_fck); | ||
867 | if (clks & DSS_CLK_54M) | ||
868 | clk_disable(dss.dss_54m_fck); | ||
869 | if (clks & DSS_CLK_96M) | ||
870 | clk_disable(dss.dss_96m_fck); | ||
871 | |||
872 | dss.num_clks_enabled -= num_clks; | ||
873 | } | ||
874 | |||
875 | void dss_clk_disable(enum dss_clock clks) | ||
876 | { | ||
877 | if (cpu_is_omap34xx()) { | ||
878 | unsigned num_clks = count_clk_bits(clks); | ||
879 | |||
880 | BUG_ON(dss.num_clks_enabled < num_clks); | ||
881 | |||
882 | if (dss.num_clks_enabled == num_clks) | ||
883 | save_all_ctx(); | ||
884 | } | ||
885 | |||
886 | dss_clk_disable_no_ctx(clks); | ||
887 | } | ||
888 | |||
889 | static void dss_clk_enable_all_no_ctx(void) | ||
890 | { | ||
891 | enum dss_clock clks; | ||
892 | |||
893 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
894 | if (cpu_is_omap34xx()) | ||
895 | clks |= DSS_CLK_96M; | ||
896 | dss_clk_enable_no_ctx(clks); | ||
897 | } | ||
898 | |||
899 | static void dss_clk_disable_all_no_ctx(void) | ||
900 | { | ||
901 | enum dss_clock clks; | ||
902 | |||
903 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
904 | if (cpu_is_omap34xx()) | ||
905 | clks |= DSS_CLK_96M; | ||
906 | dss_clk_disable_no_ctx(clks); | ||
907 | } | ||
908 | |||
909 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
910 | /* CLOCKS */ | ||
911 | static void core_dump_clocks(struct seq_file *s) | ||
912 | { | ||
913 | int i; | ||
914 | struct clk *clocks[5] = { | ||
915 | dss.dss_ick, | ||
916 | dss.dss1_fck, | ||
917 | dss.dss2_fck, | ||
918 | dss.dss_54m_fck, | ||
919 | dss.dss_96m_fck | ||
920 | }; | ||
921 | |||
922 | seq_printf(s, "- CORE -\n"); | ||
923 | |||
924 | seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); | ||
925 | |||
926 | for (i = 0; i < 5; i++) { | ||
927 | if (!clocks[i]) | ||
928 | continue; | ||
929 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
930 | clocks[i]->name, | ||
931 | clk_get_rate(clocks[i]), | ||
932 | clocks[i]->usecount); | ||
933 | } | ||
934 | } | ||
935 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
936 | |||
937 | /* DEBUGFS */ | ||
938 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
939 | void dss_debug_dump_clocks(struct seq_file *s) | ||
940 | { | ||
941 | core_dump_clocks(s); | ||
942 | dss_dump_clocks(s); | ||
943 | dispc_dump_clocks(s); | ||
944 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
945 | dsi_dump_clocks(s); | ||
946 | #endif | ||
947 | } | ||
948 | #endif | ||
949 | |||
950 | |||
643 | /* DSS HW IP initialisation */ | 951 | /* DSS HW IP initialisation */ |
644 | static int omap_dsshw_probe(struct platform_device *pdev) | 952 | static int omap_dsshw_probe(struct platform_device *pdev) |
645 | { | 953 | { |
@@ -648,6 +956,15 @@ static int omap_dsshw_probe(struct platform_device *pdev) | |||
648 | 956 | ||
649 | dss.pdev = pdev; | 957 | dss.pdev = pdev; |
650 | 958 | ||
959 | r = dss_get_clocks(); | ||
960 | if (r) | ||
961 | goto err_clocks; | ||
962 | |||
963 | dss_clk_enable_all_no_ctx(); | ||
964 | |||
965 | dss.ctx_id = dss_get_ctx_id(); | ||
966 | DSSDBG("initial ctx id %u\n", dss.ctx_id); | ||
967 | |||
651 | #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT | 968 | #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT |
652 | /* DISPC_CONTROL */ | 969 | /* DISPC_CONTROL */ |
653 | if (omap_readl(0x48050440) & 1) /* LCD enabled? */ | 970 | if (omap_readl(0x48050440) & 1) /* LCD enabled? */ |
@@ -660,15 +977,30 @@ static int omap_dsshw_probe(struct platform_device *pdev) | |||
660 | goto err_dss; | 977 | goto err_dss; |
661 | } | 978 | } |
662 | 979 | ||
663 | err_dss: | 980 | dss_clk_disable_all_no_ctx(); |
981 | return 0; | ||
664 | 982 | ||
983 | err_dss: | ||
984 | dss_clk_disable_all_no_ctx(); | ||
985 | dss_put_clocks(); | ||
986 | err_clocks: | ||
665 | return r; | 987 | return r; |
666 | } | 988 | } |
667 | 989 | ||
668 | static int omap_dsshw_remove(struct platform_device *pdev) | 990 | static int omap_dsshw_remove(struct platform_device *pdev) |
669 | { | 991 | { |
992 | |||
670 | dss_exit(); | 993 | dss_exit(); |
671 | 994 | ||
995 | /* | ||
996 | * As part of hwmod changes, DSS is not the only controller of dss | ||
997 | * clocks; hwmod framework itself will also enable clocks during hwmod | ||
998 | * init for dss, and autoidle is set in h/w for DSS. Hence, there's no | ||
999 | * need to disable clocks if their usecounts > 1. | ||
1000 | */ | ||
1001 | WARN_ON(dss.num_clks_enabled > 0); | ||
1002 | |||
1003 | dss_put_clocks(); | ||
672 | return 0; | 1004 | return 0; |
673 | } | 1005 | } |
674 | 1006 | ||
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 37c4544e8907..c535ee1db3ee 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -169,11 +169,6 @@ struct seq_file; | |||
169 | struct platform_device; | 169 | struct platform_device; |
170 | 170 | ||
171 | /* core */ | 171 | /* core */ |
172 | void dss_clk_enable(enum dss_clock clks); | ||
173 | void dss_clk_disable(enum dss_clock clks); | ||
174 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
175 | int dss_need_ctx_restore(void); | ||
176 | void dss_dump_clocks(struct seq_file *s); | ||
177 | struct bus_type *dss_get_bus(void); | 172 | struct bus_type *dss_get_bus(void); |
178 | struct regulator *dss_get_vdds_dsi(void); | 173 | struct regulator *dss_get_vdds_dsi(void); |
179 | struct regulator *dss_get_vdds_sdi(void); | 174 | struct regulator *dss_get_vdds_sdi(void); |
@@ -219,8 +214,16 @@ void dss_uninit_platform_driver(void); | |||
219 | 214 | ||
220 | void dss_save_context(void); | 215 | void dss_save_context(void); |
221 | void dss_restore_context(void); | 216 | void dss_restore_context(void); |
217 | void dss_clk_enable(enum dss_clock clks); | ||
218 | void dss_clk_disable(enum dss_clock clks); | ||
219 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
220 | int dss_need_ctx_restore(void); | ||
221 | void dss_dump_clocks(struct seq_file *s); | ||
222 | 222 | ||
223 | void dss_dump_regs(struct seq_file *s); | 223 | void dss_dump_regs(struct seq_file *s); |
224 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
225 | void dss_debug_dump_clocks(struct seq_file *s); | ||
226 | #endif | ||
224 | 227 | ||
225 | void dss_sdi_init(u8 datapairs); | 228 | void dss_sdi_init(u8 datapairs); |
226 | int dss_sdi_enable(void); | 229 | int dss_sdi_enable(void); |