aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/dispc.c326
-rw-r--r--drivers/video/omap2/dss/dpi.c70
-rw-r--r--drivers/video/omap2/dss/dsi.c244
-rw-r--r--drivers/video/omap2/dss/dss.c376
-rw-r--r--drivers/video/omap2/dss/dss.h33
-rw-r--r--drivers/video/omap2/dss/hdmi.c161
-rw-r--r--drivers/video/omap2/dss/manager.c8
-rw-r--r--drivers/video/omap2/dss/overlay.c24
-rw-r--r--drivers/video/omap2/dss/rfbi.c110
-rw-r--r--drivers/video/omap2/dss/sdi.c40
-rw-r--r--drivers/video/omap2/dss/venc.c165
11 files changed, 923 insertions, 634 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ba1ccf709e14..5b095a38b201 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -34,6 +34,7 @@
34#include <linux/hardirq.h> 34#include <linux/hardirq.h>
35#include <linux/interrupt.h> 35#include <linux/interrupt.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/pm_runtime.h>
37 38
38#include <plat/sram.h> 39#include <plat/sram.h>
39#include <plat/clock.h> 40#include <plat/clock.h>
@@ -99,7 +100,11 @@ struct dispc_irq_stats {
99static struct { 100static struct {
100 struct platform_device *pdev; 101 struct platform_device *pdev;
101 void __iomem *base; 102 void __iomem *base;
103
104 int ctx_loss_cnt;
105
102 int irq; 106 int irq;
107 struct clk *dss_clk;
103 108
104 u32 fifo_size[3]; 109 u32 fifo_size[3];
105 110
@@ -146,13 +151,12 @@ static inline u32 dispc_read_reg(const u16 idx)
146#define RR(reg) \ 151#define RR(reg) \
147 dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)]) 152 dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
148 153
149void dispc_save_context(void) 154static void dispc_save_context(void)
150{ 155{
151 int i; 156 int i;
152 if (cpu_is_omap24xx())
153 return;
154 157
155 SR(SYSCONFIG); 158 DSSDBG("dispc_save_context\n");
159
156 SR(IRQENABLE); 160 SR(IRQENABLE);
157 SR(CONTROL); 161 SR(CONTROL);
158 SR(CONFIG); 162 SR(CONFIG);
@@ -320,10 +324,12 @@ void dispc_save_context(void)
320 SR(DIVISOR); 324 SR(DIVISOR);
321} 325}
322 326
323void dispc_restore_context(void) 327static void dispc_restore_context(void)
324{ 328{
325 int i; 329 int i;
326 RR(SYSCONFIG); 330
331 DSSDBG("dispc_restore_context\n");
332
327 /*RR(IRQENABLE);*/ 333 /*RR(IRQENABLE);*/
328 /*RR(CONTROL);*/ 334 /*RR(CONTROL);*/
329 RR(CONFIG); 335 RR(CONFIG);
@@ -507,14 +513,82 @@ void dispc_restore_context(void)
507#undef SR 513#undef SR
508#undef RR 514#undef RR
509 515
510static inline void enable_clocks(bool enable) 516static void dispc_init_ctx_loss_count(void)
511{ 517{
512 if (enable) 518 struct device *dev = &dispc.pdev->dev;
513 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 519 struct omap_display_platform_data *pdata = dev->platform_data;
514 else 520 struct omap_dss_board_info *board_data = pdata->board_data;
515 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 521 int cnt = 0;
522
523 /*
524 * get_context_loss_count returns negative on error. We'll ignore the
525 * error and store the error to ctx_loss_cnt, which will cause
526 * dispc_need_ctx_restore() call to return true.
527 */
528
529 if (board_data->get_context_loss_count)
530 cnt = board_data->get_context_loss_count(dev);
531
532 WARN_ON(cnt < 0);
533
534 dispc.ctx_loss_cnt = cnt;
535
536 DSSDBG("initial ctx_loss_cnt %u\n", cnt);
537}
538
539static bool dispc_need_ctx_restore(void)
540{
541 struct device *dev = &dispc.pdev->dev;
542 struct omap_display_platform_data *pdata = dev->platform_data;
543 struct omap_dss_board_info *board_data = pdata->board_data;
544 int cnt;
545
546 /*
547 * If get_context_loss_count is not available, assume that we need
548 * context restore always.
549 */
550 if (!board_data->get_context_loss_count)
551 return true;
552
553 cnt = board_data->get_context_loss_count(dev);
554 if (cnt < 0) {
555 dev_err(dev, "getting context loss count failed, will force "
556 "context restore\n");
557 dispc.ctx_loss_cnt = cnt;
558 return true;
559 }
560
561 if (cnt == dispc.ctx_loss_cnt)
562 return false;
563
564 DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt);
565 dispc.ctx_loss_cnt = cnt;
566
567 return true;
568}
569
570int dispc_runtime_get(void)
571{
572 int r;
573
574 DSSDBG("dispc_runtime_get\n");
575
576 r = pm_runtime_get_sync(&dispc.pdev->dev);
577 WARN_ON(r < 0);
578 return r < 0 ? r : 0;
579}
580
581void dispc_runtime_put(void)
582{
583 int r;
584
585 DSSDBG("dispc_runtime_put\n");
586
587 r = pm_runtime_put(&dispc.pdev->dev);
588 WARN_ON(r < 0);
516} 589}
517 590
591
518bool dispc_go_busy(enum omap_channel channel) 592bool dispc_go_busy(enum omap_channel channel)
519{ 593{
520 int bit; 594 int bit;
@@ -536,7 +610,7 @@ void dispc_go(enum omap_channel channel)
536 int bit; 610 int bit;
537 bool enable_bit, go_bit; 611 bool enable_bit, go_bit;
538 612
539 enable_clocks(1); 613 dispc_runtime_get();
540 614
541 if (channel == OMAP_DSS_CHANNEL_LCD || 615 if (channel == OMAP_DSS_CHANNEL_LCD ||
542 channel == OMAP_DSS_CHANNEL_LCD2) 616 channel == OMAP_DSS_CHANNEL_LCD2)
@@ -577,7 +651,7 @@ void dispc_go(enum omap_channel channel)
577 else 651 else
578 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); 652 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
579end: 653end:
580 enable_clocks(0); 654 dispc_runtime_put();
581} 655}
582 656
583static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) 657static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -1003,7 +1077,7 @@ static void dispc_set_burst_size(enum omap_plane plane,
1003{ 1077{
1004 int shift; 1078 int shift;
1005 1079
1006 enable_clocks(1); 1080 dispc_runtime_get();
1007 1081
1008 switch (plane) { 1082 switch (plane) {
1009 case OMAP_DSS_GFX: 1083 case OMAP_DSS_GFX:
@@ -1020,7 +1094,7 @@ static void dispc_set_burst_size(enum omap_plane plane,
1020 1094
1021 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); 1095 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
1022 1096
1023 enable_clocks(0); 1097 dispc_runtime_put();
1024} 1098}
1025 1099
1026static void dispc_configure_burst_sizes(void) 1100static void dispc_configure_burst_sizes(void)
@@ -1108,9 +1182,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
1108 else 1182 else
1109 bit = 10; 1183 bit = 10;
1110 1184
1111 enable_clocks(1); 1185 dispc_runtime_get();
1112 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); 1186 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
1113 enable_clocks(0); 1187 dispc_runtime_put();
1114} 1188}
1115 1189
1116void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) 1190void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1118,9 +1192,9 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
1118 u32 val; 1192 u32 val;
1119 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 1193 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
1120 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 1194 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
1121 enable_clocks(1); 1195 dispc_runtime_get();
1122 dispc_write_reg(DISPC_SIZE_MGR(channel), val); 1196 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1123 enable_clocks(0); 1197 dispc_runtime_put();
1124} 1198}
1125 1199
1126void dispc_set_digit_size(u16 width, u16 height) 1200void dispc_set_digit_size(u16 width, u16 height)
@@ -1128,9 +1202,9 @@ void dispc_set_digit_size(u16 width, u16 height)
1128 u32 val; 1202 u32 val;
1129 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 1203 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
1130 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 1204 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
1131 enable_clocks(1); 1205 dispc_runtime_get();
1132 dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); 1206 dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
1133 enable_clocks(0); 1207 dispc_runtime_put();
1134} 1208}
1135 1209
1136static void dispc_read_plane_fifo_sizes(void) 1210static void dispc_read_plane_fifo_sizes(void)
@@ -1142,7 +1216,7 @@ static void dispc_read_plane_fifo_sizes(void)
1142 1216
1143 unit = dss_feat_get_buffer_size_unit(); 1217 unit = dss_feat_get_buffer_size_unit();
1144 1218
1145 enable_clocks(1); 1219 dispc_runtime_get();
1146 1220
1147 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); 1221 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1148 1222
@@ -1152,7 +1226,7 @@ static void dispc_read_plane_fifo_sizes(void)
1152 dispc.fifo_size[plane] = size; 1226 dispc.fifo_size[plane] = size;
1153 } 1227 }
1154 1228
1155 enable_clocks(0); 1229 dispc_runtime_put();
1156} 1230}
1157 1231
1158u32 dispc_get_plane_fifo_size(enum omap_plane plane) 1232u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1176,7 +1250,7 @@ void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1176 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); 1250 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1177 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); 1251 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1178 1252
1179 enable_clocks(1); 1253 dispc_runtime_get();
1180 1254
1181 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", 1255 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
1182 plane, 1256 plane,
@@ -1190,17 +1264,17 @@ void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1190 FLD_VAL(high, hi_start, hi_end) | 1264 FLD_VAL(high, hi_start, hi_end) |
1191 FLD_VAL(low, lo_start, lo_end)); 1265 FLD_VAL(low, lo_start, lo_end));
1192 1266
1193 enable_clocks(0); 1267 dispc_runtime_put();
1194} 1268}
1195 1269
1196void dispc_enable_fifomerge(bool enable) 1270void dispc_enable_fifomerge(bool enable)
1197{ 1271{
1198 enable_clocks(1); 1272 dispc_runtime_get();
1199 1273
1200 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); 1274 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1201 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); 1275 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1202 1276
1203 enable_clocks(0); 1277 dispc_runtime_put();
1204} 1278}
1205 1279
1206static void _dispc_set_fir(enum omap_plane plane, 1280static void _dispc_set_fir(enum omap_plane plane,
@@ -1822,9 +1896,9 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1822 1896
1823void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) 1897void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
1824{ 1898{
1825 enable_clocks(1); 1899 dispc_runtime_get();
1826 _dispc_set_channel_out(plane, channel_out); 1900 _dispc_set_channel_out(plane, channel_out);
1827 enable_clocks(0); 1901 dispc_runtime_put();
1828} 1902}
1829 1903
1830static int _dispc_setup_plane(enum omap_plane plane, 1904static int _dispc_setup_plane(enum omap_plane plane,
@@ -2020,7 +2094,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
2020 int r; 2094 int r;
2021 u32 irq; 2095 u32 irq;
2022 2096
2023 enable_clocks(1); 2097 dispc_runtime_get();
2024 2098
2025 /* When we disable LCD output, we need to wait until frame is done. 2099 /* When we disable LCD output, we need to wait until frame is done.
2026 * Otherwise the DSS is still working, and turning off the clocks 2100 * Otherwise the DSS is still working, and turning off the clocks
@@ -2056,7 +2130,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
2056 DSSERR("failed to unregister FRAMEDONE isr\n"); 2130 DSSERR("failed to unregister FRAMEDONE isr\n");
2057 } 2131 }
2058 2132
2059 enable_clocks(0); 2133 dispc_runtime_put();
2060} 2134}
2061 2135
2062static void _enable_digit_out(bool enable) 2136static void _enable_digit_out(bool enable)
@@ -2069,10 +2143,10 @@ static void dispc_enable_digit_out(bool enable)
2069 struct completion frame_done_completion; 2143 struct completion frame_done_completion;
2070 int r; 2144 int r;
2071 2145
2072 enable_clocks(1); 2146 dispc_runtime_get();
2073 2147
2074 if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { 2148 if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
2075 enable_clocks(0); 2149 dispc_runtime_put();
2076 return; 2150 return;
2077 } 2151 }
2078 2152
@@ -2127,7 +2201,7 @@ static void dispc_enable_digit_out(bool enable)
2127 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2201 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2128 } 2202 }
2129 2203
2130 enable_clocks(0); 2204 dispc_runtime_put();
2131} 2205}
2132 2206
2133bool dispc_is_channel_enabled(enum omap_channel channel) 2207bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2158,9 +2232,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
2158 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2232 if (!dss_has_feature(FEAT_LCDENABLEPOL))
2159 return; 2233 return;
2160 2234
2161 enable_clocks(1); 2235 dispc_runtime_get();
2162 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); 2236 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
2163 enable_clocks(0); 2237 dispc_runtime_put();
2164} 2238}
2165 2239
2166void dispc_lcd_enable_signal(bool enable) 2240void dispc_lcd_enable_signal(bool enable)
@@ -2168,9 +2242,9 @@ void dispc_lcd_enable_signal(bool enable)
2168 if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) 2242 if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
2169 return; 2243 return;
2170 2244
2171 enable_clocks(1); 2245 dispc_runtime_get();
2172 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); 2246 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
2173 enable_clocks(0); 2247 dispc_runtime_put();
2174} 2248}
2175 2249
2176void dispc_pck_free_enable(bool enable) 2250void dispc_pck_free_enable(bool enable)
@@ -2178,19 +2252,19 @@ void dispc_pck_free_enable(bool enable)
2178 if (!dss_has_feature(FEAT_PCKFREEENABLE)) 2252 if (!dss_has_feature(FEAT_PCKFREEENABLE))
2179 return; 2253 return;
2180 2254
2181 enable_clocks(1); 2255 dispc_runtime_get();
2182 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); 2256 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2183 enable_clocks(0); 2257 dispc_runtime_put();
2184} 2258}
2185 2259
2186void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) 2260void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
2187{ 2261{
2188 enable_clocks(1); 2262 dispc_runtime_get();
2189 if (channel == OMAP_DSS_CHANNEL_LCD2) 2263 if (channel == OMAP_DSS_CHANNEL_LCD2)
2190 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); 2264 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
2191 else 2265 else
2192 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); 2266 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
2193 enable_clocks(0); 2267 dispc_runtime_put();
2194} 2268}
2195 2269
2196 2270
@@ -2213,27 +2287,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
2213 return; 2287 return;
2214 } 2288 }
2215 2289
2216 enable_clocks(1); 2290 dispc_runtime_get();
2217 if (channel == OMAP_DSS_CHANNEL_LCD2) 2291 if (channel == OMAP_DSS_CHANNEL_LCD2)
2218 REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3); 2292 REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
2219 else 2293 else
2220 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); 2294 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
2221 enable_clocks(0); 2295 dispc_runtime_put();
2222} 2296}
2223 2297
2224void dispc_set_loadmode(enum omap_dss_load_mode mode) 2298void dispc_set_loadmode(enum omap_dss_load_mode mode)
2225{ 2299{
2226 enable_clocks(1); 2300 dispc_runtime_get();
2227 REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); 2301 REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
2228 enable_clocks(0); 2302 dispc_runtime_put();
2229} 2303}
2230 2304
2231 2305
2232void dispc_set_default_color(enum omap_channel channel, u32 color) 2306void dispc_set_default_color(enum omap_channel channel, u32 color)
2233{ 2307{
2234 enable_clocks(1); 2308 dispc_runtime_get();
2235 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); 2309 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
2236 enable_clocks(0); 2310 dispc_runtime_put();
2237} 2311}
2238 2312
2239u32 dispc_get_default_color(enum omap_channel channel) 2313u32 dispc_get_default_color(enum omap_channel channel)
@@ -2244,9 +2318,9 @@ u32 dispc_get_default_color(enum omap_channel channel)
2244 channel != OMAP_DSS_CHANNEL_LCD && 2318 channel != OMAP_DSS_CHANNEL_LCD &&
2245 channel != OMAP_DSS_CHANNEL_LCD2); 2319 channel != OMAP_DSS_CHANNEL_LCD2);
2246 2320
2247 enable_clocks(1); 2321 dispc_runtime_get();
2248 l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); 2322 l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
2249 enable_clocks(0); 2323 dispc_runtime_put();
2250 2324
2251 return l; 2325 return l;
2252} 2326}
@@ -2255,7 +2329,7 @@ void dispc_set_trans_key(enum omap_channel ch,
2255 enum omap_dss_trans_key_type type, 2329 enum omap_dss_trans_key_type type,
2256 u32 trans_key) 2330 u32 trans_key)
2257{ 2331{
2258 enable_clocks(1); 2332 dispc_runtime_get();
2259 if (ch == OMAP_DSS_CHANNEL_LCD) 2333 if (ch == OMAP_DSS_CHANNEL_LCD)
2260 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); 2334 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
2261 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2335 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2264,14 +2338,14 @@ void dispc_set_trans_key(enum omap_channel ch,
2264 REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11); 2338 REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
2265 2339
2266 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); 2340 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
2267 enable_clocks(0); 2341 dispc_runtime_put();
2268} 2342}
2269 2343
2270void dispc_get_trans_key(enum omap_channel ch, 2344void dispc_get_trans_key(enum omap_channel ch,
2271 enum omap_dss_trans_key_type *type, 2345 enum omap_dss_trans_key_type *type,
2272 u32 *trans_key) 2346 u32 *trans_key)
2273{ 2347{
2274 enable_clocks(1); 2348 dispc_runtime_get();
2275 if (type) { 2349 if (type) {
2276 if (ch == OMAP_DSS_CHANNEL_LCD) 2350 if (ch == OMAP_DSS_CHANNEL_LCD)
2277 *type = REG_GET(DISPC_CONFIG, 11, 11); 2351 *type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2285,33 +2359,33 @@ void dispc_get_trans_key(enum omap_channel ch,
2285 2359
2286 if (trans_key) 2360 if (trans_key)
2287 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); 2361 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
2288 enable_clocks(0); 2362 dispc_runtime_put();
2289} 2363}
2290 2364
2291void dispc_enable_trans_key(enum omap_channel ch, bool enable) 2365void dispc_enable_trans_key(enum omap_channel ch, bool enable)
2292{ 2366{
2293 enable_clocks(1); 2367 dispc_runtime_get();
2294 if (ch == OMAP_DSS_CHANNEL_LCD) 2368 if (ch == OMAP_DSS_CHANNEL_LCD)
2295 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); 2369 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
2296 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2370 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2297 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); 2371 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
2298 else /* OMAP_DSS_CHANNEL_LCD2 */ 2372 else /* OMAP_DSS_CHANNEL_LCD2 */
2299 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); 2373 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
2300 enable_clocks(0); 2374 dispc_runtime_put();
2301} 2375}
2302void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) 2376void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
2303{ 2377{
2304 if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) 2378 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2305 return; 2379 return;
2306 2380
2307 enable_clocks(1); 2381 dispc_runtime_get();
2308 if (ch == OMAP_DSS_CHANNEL_LCD) 2382 if (ch == OMAP_DSS_CHANNEL_LCD)
2309 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); 2383 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2310 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2384 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2311 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2385 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2312 else /* OMAP_DSS_CHANNEL_LCD2 */ 2386 else /* OMAP_DSS_CHANNEL_LCD2 */
2313 REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); 2387 REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
2314 enable_clocks(0); 2388 dispc_runtime_put();
2315} 2389}
2316bool dispc_alpha_blending_enabled(enum omap_channel ch) 2390bool dispc_alpha_blending_enabled(enum omap_channel ch)
2317{ 2391{
@@ -2320,7 +2394,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
2320 if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) 2394 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2321 return false; 2395 return false;
2322 2396
2323 enable_clocks(1); 2397 dispc_runtime_get();
2324 if (ch == OMAP_DSS_CHANNEL_LCD) 2398 if (ch == OMAP_DSS_CHANNEL_LCD)
2325 enabled = REG_GET(DISPC_CONFIG, 18, 18); 2399 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2326 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2400 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2329,7 +2403,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
2329 enabled = REG_GET(DISPC_CONFIG2, 18, 18); 2403 enabled = REG_GET(DISPC_CONFIG2, 18, 18);
2330 else 2404 else
2331 BUG(); 2405 BUG();
2332 enable_clocks(0); 2406 dispc_runtime_put();
2333 2407
2334 return enabled; 2408 return enabled;
2335} 2409}
@@ -2339,7 +2413,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
2339{ 2413{
2340 bool enabled; 2414 bool enabled;
2341 2415
2342 enable_clocks(1); 2416 dispc_runtime_get();
2343 if (ch == OMAP_DSS_CHANNEL_LCD) 2417 if (ch == OMAP_DSS_CHANNEL_LCD)
2344 enabled = REG_GET(DISPC_CONFIG, 10, 10); 2418 enabled = REG_GET(DISPC_CONFIG, 10, 10);
2345 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2419 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2348,7 +2422,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
2348 enabled = REG_GET(DISPC_CONFIG2, 10, 10); 2422 enabled = REG_GET(DISPC_CONFIG2, 10, 10);
2349 else 2423 else
2350 BUG(); 2424 BUG();
2351 enable_clocks(0); 2425 dispc_runtime_put();
2352 2426
2353 return enabled; 2427 return enabled;
2354} 2428}
@@ -2376,12 +2450,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2376 return; 2450 return;
2377 } 2451 }
2378 2452
2379 enable_clocks(1); 2453 dispc_runtime_get();
2380 if (channel == OMAP_DSS_CHANNEL_LCD2) 2454 if (channel == OMAP_DSS_CHANNEL_LCD2)
2381 REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8); 2455 REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
2382 else 2456 else
2383 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); 2457 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2384 enable_clocks(0); 2458 dispc_runtime_put();
2385} 2459}
2386 2460
2387void dispc_set_parallel_interface_mode(enum omap_channel channel, 2461void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2413,7 +2487,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
2413 return; 2487 return;
2414 } 2488 }
2415 2489
2416 enable_clocks(1); 2490 dispc_runtime_get();
2417 2491
2418 if (channel == OMAP_DSS_CHANNEL_LCD2) { 2492 if (channel == OMAP_DSS_CHANNEL_LCD2) {
2419 l = dispc_read_reg(DISPC_CONTROL2); 2493 l = dispc_read_reg(DISPC_CONTROL2);
@@ -2427,7 +2501,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
2427 dispc_write_reg(DISPC_CONTROL, l); 2501 dispc_write_reg(DISPC_CONTROL, l);
2428 } 2502 }
2429 2503
2430 enable_clocks(0); 2504 dispc_runtime_put();
2431} 2505}
2432 2506
2433static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2507static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2480,10 +2554,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
2480 FLD_VAL(vbp, 31, 20); 2554 FLD_VAL(vbp, 31, 20);
2481 } 2555 }
2482 2556
2483 enable_clocks(1); 2557 dispc_runtime_get();
2484 dispc_write_reg(DISPC_TIMING_H(channel), timing_h); 2558 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2485 dispc_write_reg(DISPC_TIMING_V(channel), timing_v); 2559 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
2486 enable_clocks(0); 2560 dispc_runtime_put();
2487} 2561}
2488 2562
2489/* change name to mode? */ 2563/* change name to mode? */
@@ -2526,10 +2600,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
2526 BUG_ON(lck_div < 1); 2600 BUG_ON(lck_div < 1);
2527 BUG_ON(pck_div < 2); 2601 BUG_ON(pck_div < 2);
2528 2602
2529 enable_clocks(1); 2603 dispc_runtime_get();
2530 dispc_write_reg(DISPC_DIVISORo(channel), 2604 dispc_write_reg(DISPC_DIVISORo(channel),
2531 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); 2605 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2532 enable_clocks(0); 2606 dispc_runtime_put();
2533} 2607}
2534 2608
2535static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, 2609static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2548,7 +2622,7 @@ unsigned long dispc_fclk_rate(void)
2548 2622
2549 switch (dss_get_dispc_clk_source()) { 2623 switch (dss_get_dispc_clk_source()) {
2550 case OMAP_DSS_CLK_SRC_FCK: 2624 case OMAP_DSS_CLK_SRC_FCK:
2551 r = dss_clk_get_rate(DSS_CLK_FCK); 2625 r = clk_get_rate(dispc.dss_clk);
2552 break; 2626 break;
2553 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 2627 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2554 dsidev = dsi_get_dsidev_from_id(0); 2628 dsidev = dsi_get_dsidev_from_id(0);
@@ -2578,7 +2652,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
2578 2652
2579 switch (dss_get_lcd_clk_source(channel)) { 2653 switch (dss_get_lcd_clk_source(channel)) {
2580 case OMAP_DSS_CLK_SRC_FCK: 2654 case OMAP_DSS_CLK_SRC_FCK:
2581 r = dss_clk_get_rate(DSS_CLK_FCK); 2655 r = clk_get_rate(dispc.dss_clk);
2582 break; 2656 break;
2583 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 2657 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2584 dsidev = dsi_get_dsidev_from_id(0); 2658 dsidev = dsi_get_dsidev_from_id(0);
@@ -2617,7 +2691,8 @@ void dispc_dump_clocks(struct seq_file *s)
2617 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); 2691 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
2618 enum omap_dss_clk_source lcd_clk_src; 2692 enum omap_dss_clk_source lcd_clk_src;
2619 2693
2620 enable_clocks(1); 2694 if (dispc_runtime_get())
2695 return;
2621 2696
2622 seq_printf(s, "- DISPC -\n"); 2697 seq_printf(s, "- DISPC -\n");
2623 2698
@@ -2665,7 +2740,8 @@ void dispc_dump_clocks(struct seq_file *s)
2665 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", 2740 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2666 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); 2741 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
2667 } 2742 }
2668 enable_clocks(0); 2743
2744 dispc_runtime_put();
2669} 2745}
2670 2746
2671#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 2747#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2720,7 +2796,8 @@ void dispc_dump_regs(struct seq_file *s)
2720{ 2796{
2721#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) 2797#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
2722 2798
2723 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 2799 if (dispc_runtime_get())
2800 return;
2724 2801
2725 DUMPREG(DISPC_REVISION); 2802 DUMPREG(DISPC_REVISION);
2726 DUMPREG(DISPC_SYSCONFIG); 2803 DUMPREG(DISPC_SYSCONFIG);
@@ -2965,7 +3042,7 @@ void dispc_dump_regs(struct seq_file *s)
2965 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); 3042 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
2966 } 3043 }
2967 3044
2968 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 3045 dispc_runtime_put();
2969#undef DUMPREG 3046#undef DUMPREG
2970} 3047}
2971 3048
@@ -2986,9 +3063,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
2986 l |= FLD_VAL(acbi, 11, 8); 3063 l |= FLD_VAL(acbi, 11, 8);
2987 l |= FLD_VAL(acb, 7, 0); 3064 l |= FLD_VAL(acb, 7, 0);
2988 3065
2989 enable_clocks(1); 3066 dispc_runtime_get();
2990 dispc_write_reg(DISPC_POL_FREQ(channel), l); 3067 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2991 enable_clocks(0); 3068 dispc_runtime_put();
2992} 3069}
2993 3070
2994void dispc_set_pol_freq(enum omap_channel channel, 3071void dispc_set_pol_freq(enum omap_channel channel,
@@ -3109,7 +3186,7 @@ static void _omap_dispc_set_irqs(void)
3109 mask |= isr_data->mask; 3186 mask |= isr_data->mask;
3110 } 3187 }
3111 3188
3112 enable_clocks(1); 3189 dispc_runtime_get();
3113 3190
3114 old_mask = dispc_read_reg(DISPC_IRQENABLE); 3191 old_mask = dispc_read_reg(DISPC_IRQENABLE);
3115 /* clear the irqstatus for newly enabled irqs */ 3192 /* clear the irqstatus for newly enabled irqs */
@@ -3117,7 +3194,7 @@ static void _omap_dispc_set_irqs(void)
3117 3194
3118 dispc_write_reg(DISPC_IRQENABLE, mask); 3195 dispc_write_reg(DISPC_IRQENABLE, mask);
3119 3196
3120 enable_clocks(0); 3197 dispc_runtime_put();
3121} 3198}
3122 3199
3123int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) 3200int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3626,13 +3703,6 @@ static void _omap_dispc_initial_config(void)
3626{ 3703{
3627 u32 l; 3704 u32 l;
3628 3705
3629 l = dispc_read_reg(DISPC_SYSCONFIG);
3630 l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
3631 l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
3632 l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
3633 l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
3634 dispc_write_reg(DISPC_SYSCONFIG, l);
3635
3636 /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ 3706 /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
3637 if (dss_has_feature(FEAT_CORE_CLK_DIV)) { 3707 if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3638 l = dispc_read_reg(DISPC_DIVISOR); 3708 l = dispc_read_reg(DISPC_DIVISOR);
@@ -3664,9 +3734,9 @@ int dispc_enable_plane(enum omap_plane plane, bool enable)
3664{ 3734{
3665 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 3735 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
3666 3736
3667 enable_clocks(1); 3737 dispc_runtime_get();
3668 _dispc_enable_plane(plane, enable); 3738 _dispc_enable_plane(plane, enable);
3669 enable_clocks(0); 3739 dispc_runtime_put();
3670 3740
3671 return 0; 3741 return 0;
3672} 3742}
@@ -3693,7 +3763,7 @@ int dispc_setup_plane(enum omap_plane plane,
3693 ilace, color_mode, 3763 ilace, color_mode,
3694 rotation, mirror, channel); 3764 rotation, mirror, channel);
3695 3765
3696 enable_clocks(1); 3766 dispc_runtime_get();
3697 3767
3698 r = _dispc_setup_plane(plane, 3768 r = _dispc_setup_plane(plane,
3699 paddr, screen_width, 3769 paddr, screen_width,
@@ -3707,7 +3777,7 @@ int dispc_setup_plane(enum omap_plane plane,
3707 pre_mult_alpha, 3777 pre_mult_alpha,
3708 channel, puv_addr); 3778 channel, puv_addr);
3709 3779
3710 enable_clocks(0); 3780 dispc_runtime_put();
3711 3781
3712 return r; 3782 return r;
3713} 3783}
@@ -3718,9 +3788,19 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3718 u32 rev; 3788 u32 rev;
3719 int r = 0; 3789 int r = 0;
3720 struct resource *dispc_mem; 3790 struct resource *dispc_mem;
3791 struct clk *clk;
3721 3792
3722 dispc.pdev = pdev; 3793 dispc.pdev = pdev;
3723 3794
3795 clk = clk_get(&pdev->dev, "fck");
3796 if (IS_ERR(clk)) {
3797 DSSERR("can't get fck\n");
3798 r = PTR_ERR(clk);
3799 goto err_get_clk;
3800 }
3801
3802 dispc.dss_clk = clk;
3803
3724 spin_lock_init(&dispc.irq_lock); 3804 spin_lock_init(&dispc.irq_lock);
3725 3805
3726#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 3806#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3734,62 +3814,106 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3734 if (!dispc_mem) { 3814 if (!dispc_mem) {
3735 DSSERR("can't get IORESOURCE_MEM DISPC\n"); 3815 DSSERR("can't get IORESOURCE_MEM DISPC\n");
3736 r = -EINVAL; 3816 r = -EINVAL;
3737 goto fail0; 3817 goto err_ioremap;
3738 } 3818 }
3739 dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); 3819 dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
3740 if (!dispc.base) { 3820 if (!dispc.base) {
3741 DSSERR("can't ioremap DISPC\n"); 3821 DSSERR("can't ioremap DISPC\n");
3742 r = -ENOMEM; 3822 r = -ENOMEM;
3743 goto fail0; 3823 goto err_ioremap;
3744 } 3824 }
3745 dispc.irq = platform_get_irq(dispc.pdev, 0); 3825 dispc.irq = platform_get_irq(dispc.pdev, 0);
3746 if (dispc.irq < 0) { 3826 if (dispc.irq < 0) {
3747 DSSERR("platform_get_irq failed\n"); 3827 DSSERR("platform_get_irq failed\n");
3748 r = -ENODEV; 3828 r = -ENODEV;
3749 goto fail1; 3829 goto err_irq;
3750 } 3830 }
3751 3831
3752 r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, 3832 r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
3753 "OMAP DISPC", dispc.pdev); 3833 "OMAP DISPC", dispc.pdev);
3754 if (r < 0) { 3834 if (r < 0) {
3755 DSSERR("request_irq failed\n"); 3835 DSSERR("request_irq failed\n");
3756 goto fail1; 3836 goto err_irq;
3757 } 3837 }
3758 3838
3759 enable_clocks(1); 3839 dispc_init_ctx_loss_count();
3840
3841 pm_runtime_enable(&pdev->dev);
3842
3843 r = dispc_runtime_get();
3844 if (r)
3845 goto err_runtime_get;
3760 3846
3761 _omap_dispc_initial_config(); 3847 _omap_dispc_initial_config();
3762 3848
3763 _omap_dispc_initialize_irq(); 3849 _omap_dispc_initialize_irq();
3764 3850
3765 dispc_save_context();
3766
3767 rev = dispc_read_reg(DISPC_REVISION); 3851 rev = dispc_read_reg(DISPC_REVISION);
3768 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", 3852 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
3769 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 3853 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3770 3854
3771 enable_clocks(0); 3855 dispc_runtime_put();
3772 3856
3773 return 0; 3857 return 0;
3774fail1: 3858
3859err_runtime_get:
3860 pm_runtime_disable(&pdev->dev);
3861 free_irq(dispc.irq, dispc.pdev);
3862err_irq:
3775 iounmap(dispc.base); 3863 iounmap(dispc.base);
3776fail0: 3864err_ioremap:
3865 clk_put(dispc.dss_clk);
3866err_get_clk:
3777 return r; 3867 return r;
3778} 3868}
3779 3869
3780static int omap_dispchw_remove(struct platform_device *pdev) 3870static int omap_dispchw_remove(struct platform_device *pdev)
3781{ 3871{
3872 pm_runtime_disable(&pdev->dev);
3873
3874 clk_put(dispc.dss_clk);
3875
3782 free_irq(dispc.irq, dispc.pdev); 3876 free_irq(dispc.irq, dispc.pdev);
3783 iounmap(dispc.base); 3877 iounmap(dispc.base);
3784 return 0; 3878 return 0;
3785} 3879}
3786 3880
3881static int dispc_runtime_suspend(struct device *dev)
3882{
3883 dispc_save_context();
3884 clk_disable(dispc.dss_clk);
3885 dss_runtime_put();
3886
3887 return 0;
3888}
3889
3890static int dispc_runtime_resume(struct device *dev)
3891{
3892 int r;
3893
3894 r = dss_runtime_get();
3895 if (r < 0)
3896 return r;
3897
3898 clk_enable(dispc.dss_clk);
3899 if (dispc_need_ctx_restore())
3900 dispc_restore_context();
3901
3902 return 0;
3903}
3904
3905static const struct dev_pm_ops dispc_pm_ops = {
3906 .runtime_suspend = dispc_runtime_suspend,
3907 .runtime_resume = dispc_runtime_resume,
3908};
3909
3787static struct platform_driver omap_dispchw_driver = { 3910static struct platform_driver omap_dispchw_driver = {
3788 .probe = omap_dispchw_probe, 3911 .probe = omap_dispchw_probe,
3789 .remove = omap_dispchw_remove, 3912 .remove = omap_dispchw_remove,
3790 .driver = { 3913 .driver = {
3791 .name = "omapdss_dispc", 3914 .name = "omapdss_dispc",
3792 .owner = THIS_MODULE, 3915 .owner = THIS_MODULE,
3916 .pm = &dispc_pm_ops,
3793 }, 3917 },
3794}; 3918};
3795 3919
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index bab55cd4ac9a..f053b180ecd7 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -23,7 +23,6 @@
23#define DSS_SUBSYS_NAME "DPI" 23#define DSS_SUBSYS_NAME "DPI"
24 24
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/clk.h>
27#include <linux/delay.h> 26#include <linux/delay.h>
28#include <linux/err.h> 27#include <linux/err.h>
29#include <linux/errno.h> 28#include <linux/errno.h>
@@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
130 bool is_tft; 129 bool is_tft;
131 int r = 0; 130 int r = 0;
132 131
133 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
134
135 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, 132 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
136 dssdev->panel.acbi, dssdev->panel.acb); 133 dssdev->panel.acbi, dssdev->panel.acb);
137 134
@@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
144 r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, 141 r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
145 &fck, &lck_div, &pck_div); 142 &fck, &lck_div, &pck_div);
146 if (r) 143 if (r)
147 goto err0; 144 return r;
148 145
149 pck = fck / lck_div / pck_div / 1000; 146 pck = fck / lck_div / pck_div / 1000;
150 147
@@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
158 155
159 dispc_set_lcd_timings(dssdev->manager->id, t); 156 dispc_set_lcd_timings(dssdev->manager->id, t);
160 157
161err0: 158 return 0;
162 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
163 return r;
164} 159}
165 160
166static int dpi_basic_init(struct omap_dss_device *dssdev) 161static void dpi_basic_init(struct omap_dss_device *dssdev)
167{ 162{
168 bool is_tft; 163 bool is_tft;
169 164
@@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
175 OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); 170 OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
176 dispc_set_tft_data_lines(dssdev->manager->id, 171 dispc_set_tft_data_lines(dssdev->manager->id,
177 dssdev->phy.dpi.data_lines); 172 dssdev->phy.dpi.data_lines);
178
179 return 0;
180} 173}
181 174
182int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 175int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -186,30 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
186 r = omap_dss_start_device(dssdev); 179 r = omap_dss_start_device(dssdev);
187 if (r) { 180 if (r) {
188 DSSERR("failed to start device\n"); 181 DSSERR("failed to start device\n");
189 goto err0; 182 goto err_start_dev;
190 } 183 }
191 184
192 if (cpu_is_omap34xx()) { 185 if (cpu_is_omap34xx()) {
193 r = regulator_enable(dpi.vdds_dsi_reg); 186 r = regulator_enable(dpi.vdds_dsi_reg);
194 if (r) 187 if (r)
195 goto err1; 188 goto err_reg_enable;
196 } 189 }
197 190
198 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 191 r = dss_runtime_get();
192 if (r)
193 goto err_get_dss;
199 194
200 r = dpi_basic_init(dssdev); 195 r = dispc_runtime_get();
201 if (r) 196 if (r)
202 goto err2; 197 goto err_get_dispc;
198
199 dpi_basic_init(dssdev);
203 200
204 if (dpi_use_dsi_pll(dssdev)) { 201 if (dpi_use_dsi_pll(dssdev)) {
202 r = dsi_runtime_get(dpi.dsidev);
203 if (r)
204 goto err_get_dsi;
205
205 r = dsi_pll_init(dpi.dsidev, 0, 1); 206 r = dsi_pll_init(dpi.dsidev, 0, 1);
206 if (r) 207 if (r)
207 goto err2; 208 goto err_dsi_pll_init;
208 } 209 }
209 210
210 r = dpi_set_mode(dssdev); 211 r = dpi_set_mode(dssdev);
211 if (r) 212 if (r)
212 goto err3; 213 goto err_set_mode;
213 214
214 mdelay(2); 215 mdelay(2);
215 216
@@ -217,16 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
217 218
218 return 0; 219 return 0;
219 220
220err3: 221err_set_mode:
221 if (dpi_use_dsi_pll(dssdev)) 222 if (dpi_use_dsi_pll(dssdev))
222 dsi_pll_uninit(dpi.dsidev, true); 223 dsi_pll_uninit(dpi.dsidev, true);
223err2: 224err_dsi_pll_init:
224 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 225 if (dpi_use_dsi_pll(dssdev))
226 dsi_runtime_put(dpi.dsidev);
227err_get_dsi:
228 dispc_runtime_put();
229err_get_dispc:
230 dss_runtime_put();
231err_get_dss:
225 if (cpu_is_omap34xx()) 232 if (cpu_is_omap34xx())
226 regulator_disable(dpi.vdds_dsi_reg); 233 regulator_disable(dpi.vdds_dsi_reg);
227err1: 234err_reg_enable:
228 omap_dss_stop_device(dssdev); 235 omap_dss_stop_device(dssdev);
229err0: 236err_start_dev:
230 return r; 237 return r;
231} 238}
232EXPORT_SYMBOL(omapdss_dpi_display_enable); 239EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -238,9 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
238 if (dpi_use_dsi_pll(dssdev)) { 245 if (dpi_use_dsi_pll(dssdev)) {
239 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 246 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
240 dsi_pll_uninit(dpi.dsidev, true); 247 dsi_pll_uninit(dpi.dsidev, true);
248 dsi_runtime_put(dpi.dsidev);
241 } 249 }
242 250
243 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 251 dispc_runtime_put();
252 dss_runtime_put();
244 253
245 if (cpu_is_omap34xx()) 254 if (cpu_is_omap34xx())
246 regulator_disable(dpi.vdds_dsi_reg); 255 regulator_disable(dpi.vdds_dsi_reg);
@@ -252,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
252void dpi_set_timings(struct omap_dss_device *dssdev, 261void dpi_set_timings(struct omap_dss_device *dssdev,
253 struct omap_video_timings *timings) 262 struct omap_video_timings *timings)
254{ 263{
264 int r;
265
255 DSSDBG("dpi_set_timings\n"); 266 DSSDBG("dpi_set_timings\n");
256 dssdev->panel.timings = *timings; 267 dssdev->panel.timings = *timings;
257 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 268 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
269 r = dss_runtime_get();
270 if (r)
271 return;
272
273 r = dispc_runtime_get();
274 if (r) {
275 dss_runtime_put();
276 return;
277 }
278
258 dpi_set_mode(dssdev); 279 dpi_set_mode(dssdev);
259 dispc_go(dssdev->manager->id); 280 dispc_go(dssdev->manager->id);
281
282 dispc_runtime_put();
283 dss_runtime_put();
260 } 284 }
261} 285}
262EXPORT_SYMBOL(dpi_set_timings); 286EXPORT_SYMBOL(dpi_set_timings);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 1e2fd404651f..48b0cdf97ceb 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -36,6 +36,7 @@
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/debugfs.h> 38#include <linux/debugfs.h>
39#include <linux/pm_runtime.h>
39 40
40#include <video/omapdss.h> 41#include <video/omapdss.h>
41#include <plat/clock.h> 42#include <plat/clock.h>
@@ -267,8 +268,12 @@ struct dsi_isr_tables {
267struct dsi_data { 268struct dsi_data {
268 struct platform_device *pdev; 269 struct platform_device *pdev;
269 void __iomem *base; 270 void __iomem *base;
271
270 int irq; 272 int irq;
271 273
274 struct clk *dss_clk;
275 struct clk *sys_clk;
276
272 void (*dsi_mux_pads)(bool enable); 277 void (*dsi_mux_pads)(bool enable);
273 278
274 struct dsi_clock_info current_cinfo; 279 struct dsi_clock_info current_cinfo;
@@ -389,15 +394,6 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
389 return __raw_readl(dsi->base + idx.idx); 394 return __raw_readl(dsi->base + idx.idx);
390} 395}
391 396
392
393void dsi_save_context(void)
394{
395}
396
397void dsi_restore_context(void)
398{
399}
400
401void dsi_bus_lock(struct omap_dss_device *dssdev) 397void dsi_bus_lock(struct omap_dss_device *dssdev)
402{ 398{
403 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 399 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -1048,13 +1044,27 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
1048 return e; 1044 return e;
1049} 1045}
1050 1046
1051/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ 1047int dsi_runtime_get(struct platform_device *dsidev)
1052static inline void enable_clocks(bool enable)
1053{ 1048{
1054 if (enable) 1049 int r;
1055 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 1050 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1056 else 1051
1057 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 1052 DSSDBG("dsi_runtime_get\n");
1053
1054 r = pm_runtime_get_sync(&dsi->pdev->dev);
1055 WARN_ON(r < 0);
1056 return r < 0 ? r : 0;
1057}
1058
1059void dsi_runtime_put(struct platform_device *dsidev)
1060{
1061 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1062 int r;
1063
1064 DSSDBG("dsi_runtime_put\n");
1065
1066 r = pm_runtime_put(&dsi->pdev->dev);
1067 WARN_ON(r < 0);
1058} 1068}
1059 1069
1060/* source clock for DSI PLL. this could also be PCLKFREE */ 1070/* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1064,9 +1074,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1064 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1074 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1065 1075
1066 if (enable) 1076 if (enable)
1067 dss_clk_enable(DSS_CLK_SYSCK); 1077 clk_enable(dsi->sys_clk);
1068 else 1078 else
1069 dss_clk_disable(DSS_CLK_SYSCK); 1079 clk_disable(dsi->sys_clk);
1070 1080
1071 if (enable && dsi->pll_locked) { 1081 if (enable && dsi->pll_locked) {
1072 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) 1082 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1159,10 +1169,11 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1159{ 1169{
1160 unsigned long r; 1170 unsigned long r;
1161 int dsi_module = dsi_get_dsidev_id(dsidev); 1171 int dsi_module = dsi_get_dsidev_id(dsidev);
1172 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1162 1173
1163 if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { 1174 if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
1164 /* DSI FCLK source is DSS_CLK_FCK */ 1175 /* DSI FCLK source is DSS_CLK_FCK */
1165 r = dss_clk_get_rate(DSS_CLK_FCK); 1176 r = clk_get_rate(dsi->dss_clk);
1166 } else { 1177 } else {
1167 /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ 1178 /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
1168 r = dsi_get_pll_hsdiv_dsi_rate(dsidev); 1179 r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1271,7 +1282,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
1271 return -EINVAL; 1282 return -EINVAL;
1272 1283
1273 if (cinfo->use_sys_clk) { 1284 if (cinfo->use_sys_clk) {
1274 cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); 1285 cinfo->clkin = clk_get_rate(dsi->sys_clk);
1275 /* XXX it is unclear if highfreq should be used 1286 /* XXX it is unclear if highfreq should be used
1276 * with DSS_SYS_CLK source also */ 1287 * with DSS_SYS_CLK source also */
1277 cinfo->highfreq = 0; 1288 cinfo->highfreq = 0;
@@ -1320,7 +1331,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
1320 int match = 0; 1331 int match = 0;
1321 unsigned long dss_sys_clk, max_dss_fck; 1332 unsigned long dss_sys_clk, max_dss_fck;
1322 1333
1323 dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); 1334 dss_sys_clk = clk_get_rate(dsi->sys_clk);
1324 1335
1325 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 1336 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1326 1337
@@ -1610,7 +1621,6 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1610 dsi->vdds_dsi_reg = vdds_dsi; 1621 dsi->vdds_dsi_reg = vdds_dsi;
1611 } 1622 }
1612 1623
1613 enable_clocks(1);
1614 dsi_enable_pll_clock(dsidev, 1); 1624 dsi_enable_pll_clock(dsidev, 1);
1615 /* 1625 /*
1616 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. 1626 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1662,7 +1672,6 @@ err1:
1662 } 1672 }
1663err0: 1673err0:
1664 dsi_disable_scp_clk(dsidev); 1674 dsi_disable_scp_clk(dsidev);
1665 enable_clocks(0);
1666 dsi_enable_pll_clock(dsidev, 0); 1675 dsi_enable_pll_clock(dsidev, 0);
1667 return r; 1676 return r;
1668} 1677}
@@ -1680,7 +1689,6 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
1680 } 1689 }
1681 1690
1682 dsi_disable_scp_clk(dsidev); 1691 dsi_disable_scp_clk(dsidev);
1683 enable_clocks(0);
1684 dsi_enable_pll_clock(dsidev, 0); 1692 dsi_enable_pll_clock(dsidev, 0);
1685 1693
1686 DSSDBG("PLL uninit done\n"); 1694 DSSDBG("PLL uninit done\n");
@@ -1697,7 +1705,8 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1697 dispc_clk_src = dss_get_dispc_clk_source(); 1705 dispc_clk_src = dss_get_dispc_clk_source();
1698 dsi_clk_src = dss_get_dsi_clk_source(dsi_module); 1706 dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
1699 1707
1700 enable_clocks(1); 1708 if (dsi_runtime_get(dsidev))
1709 return;
1701 1710
1702 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); 1711 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
1703 1712
@@ -1740,7 +1749,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1740 1749
1741 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); 1750 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
1742 1751
1743 enable_clocks(0); 1752 dsi_runtime_put(dsidev);
1744} 1753}
1745 1754
1746void dsi_dump_clocks(struct seq_file *s) 1755void dsi_dump_clocks(struct seq_file *s)
@@ -1882,7 +1891,8 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
1882{ 1891{
1883#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) 1892#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
1884 1893
1885 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 1894 if (dsi_runtime_get(dsidev))
1895 return;
1886 dsi_enable_scp_clk(dsidev); 1896 dsi_enable_scp_clk(dsidev);
1887 1897
1888 DUMPREG(DSI_REVISION); 1898 DUMPREG(DSI_REVISION);
@@ -1956,7 +1966,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
1956 DUMPREG(DSI_PLL_CONFIGURATION2); 1966 DUMPREG(DSI_PLL_CONFIGURATION2);
1957 1967
1958 dsi_disable_scp_clk(dsidev); 1968 dsi_disable_scp_clk(dsidev);
1959 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 1969 dsi_runtime_put(dsidev);
1960#undef DUMPREG 1970#undef DUMPREG
1961} 1971}
1962 1972
@@ -2472,28 +2482,6 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
2472 dsi->dsi_mux_pads(false); 2482 dsi->dsi_mux_pads(false);
2473} 2483}
2474 2484
2475static int _dsi_wait_reset(struct platform_device *dsidev)
2476{
2477 int t = 0;
2478
2479 while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
2480 if (++t > 5) {
2481 DSSERR("soft reset failed\n");
2482 return -ENODEV;
2483 }
2484 udelay(1);
2485 }
2486
2487 return 0;
2488}
2489
2490static int _dsi_reset(struct platform_device *dsidev)
2491{
2492 /* Soft reset */
2493 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
2494 return _dsi_wait_reset(dsidev);
2495}
2496
2497static void dsi_config_tx_fifo(struct platform_device *dsidev, 2485static void dsi_config_tx_fifo(struct platform_device *dsidev,
2498 enum fifo_size size1, enum fifo_size size2, 2486 enum fifo_size size1, enum fifo_size size2,
2499 enum fifo_size size3, enum fifo_size size4) 2487 enum fifo_size size3, enum fifo_size size4)
@@ -4211,22 +4199,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4211 dsi_pll_uninit(dsidev, disconnect_lanes); 4199 dsi_pll_uninit(dsidev, disconnect_lanes);
4212} 4200}
4213 4201
4214static int dsi_core_init(struct platform_device *dsidev)
4215{
4216 /* Autoidle */
4217 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
4218
4219 /* ENWAKEUP */
4220 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
4221
4222 /* SIDLEMODE smart-idle */
4223 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
4224
4225 _dsi_initialize_irq(dsidev);
4226
4227 return 0;
4228}
4229
4230int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) 4202int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4231{ 4203{
4232 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4204 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4242,37 +4214,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4242 r = omap_dss_start_device(dssdev); 4214 r = omap_dss_start_device(dssdev);
4243 if (r) { 4215 if (r) {
4244 DSSERR("failed to start device\n"); 4216 DSSERR("failed to start device\n");
4245 goto err0; 4217 goto err_start_dev;
4246 } 4218 }
4247 4219
4248 enable_clocks(1); 4220 r = dsi_runtime_get(dsidev);
4249 dsi_enable_pll_clock(dsidev, 1);
4250
4251 r = _dsi_reset(dsidev);
4252 if (r) 4221 if (r)
4253 goto err1; 4222 goto err_get_dsi;
4223
4224 dsi_enable_pll_clock(dsidev, 1);
4254 4225
4255 dsi_core_init(dsidev); 4226 _dsi_initialize_irq(dsidev);
4256 4227
4257 r = dsi_display_init_dispc(dssdev); 4228 r = dsi_display_init_dispc(dssdev);
4258 if (r) 4229 if (r)
4259 goto err1; 4230 goto err_init_dispc;
4260 4231
4261 r = dsi_display_init_dsi(dssdev); 4232 r = dsi_display_init_dsi(dssdev);
4262 if (r) 4233 if (r)
4263 goto err2; 4234 goto err_init_dsi;
4264 4235
4265 mutex_unlock(&dsi->lock); 4236 mutex_unlock(&dsi->lock);
4266 4237
4267 return 0; 4238 return 0;
4268 4239
4269err2: 4240err_init_dsi:
4270 dsi_display_uninit_dispc(dssdev); 4241 dsi_display_uninit_dispc(dssdev);
4271err1: 4242err_init_dispc:
4272 enable_clocks(0);
4273 dsi_enable_pll_clock(dsidev, 0); 4243 dsi_enable_pll_clock(dsidev, 0);
4244 dsi_runtime_put(dsidev);
4245err_get_dsi:
4274 omap_dss_stop_device(dssdev); 4246 omap_dss_stop_device(dssdev);
4275err0: 4247err_start_dev:
4276 mutex_unlock(&dsi->lock); 4248 mutex_unlock(&dsi->lock);
4277 DSSDBG("dsi_display_enable FAILED\n"); 4249 DSSDBG("dsi_display_enable FAILED\n");
4278 return r; 4250 return r;
@@ -4300,7 +4272,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
4300 4272
4301 dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); 4273 dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
4302 4274
4303 enable_clocks(0); 4275 dsi_runtime_put(dsidev);
4304 dsi_enable_pll_clock(dsidev, 0); 4276 dsi_enable_pll_clock(dsidev, 0);
4305 4277
4306 omap_dss_stop_device(dssdev); 4278 omap_dss_stop_device(dssdev);
@@ -4450,6 +4422,42 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
4450 dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); 4422 dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
4451} 4423}
4452 4424
4425static int dsi_get_clocks(struct platform_device *dsidev)
4426{
4427 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4428 struct clk *clk;
4429
4430 clk = clk_get(&dsidev->dev, "fck");
4431 if (IS_ERR(clk)) {
4432 DSSERR("can't get fck\n");
4433 return PTR_ERR(clk);
4434 }
4435
4436 dsi->dss_clk = clk;
4437
4438 clk = clk_get(&dsidev->dev, "sys_clk");
4439 if (IS_ERR(clk)) {
4440 DSSERR("can't get sys_clk\n");
4441 clk_put(dsi->dss_clk);
4442 dsi->dss_clk = NULL;
4443 return PTR_ERR(clk);
4444 }
4445
4446 dsi->sys_clk = clk;
4447
4448 return 0;
4449}
4450
4451static void dsi_put_clocks(struct platform_device *dsidev)
4452{
4453 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4454
4455 if (dsi->dss_clk)
4456 clk_put(dsi->dss_clk);
4457 if (dsi->sys_clk)
4458 clk_put(dsi->sys_clk);
4459}
4460
4453/* DSI1 HW IP initialisation */ 4461/* DSI1 HW IP initialisation */
4454static int omap_dsi1hw_probe(struct platform_device *dsidev) 4462static int omap_dsi1hw_probe(struct platform_device *dsidev)
4455{ 4463{
@@ -4463,7 +4471,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4463 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); 4471 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
4464 if (!dsi) { 4472 if (!dsi) {
4465 r = -ENOMEM; 4473 r = -ENOMEM;
4466 goto err0; 4474 goto err_alloc;
4467 } 4475 }
4468 4476
4469 dsi->pdev = dsidev; 4477 dsi->pdev = dsidev;
@@ -4486,6 +4494,12 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4486 mutex_init(&dsi->lock); 4494 mutex_init(&dsi->lock);
4487 sema_init(&dsi->bus_lock, 1); 4495 sema_init(&dsi->bus_lock, 1);
4488 4496
4497 r = dsi_get_clocks(dsidev);
4498 if (r)
4499 goto err_get_clk;
4500
4501 pm_runtime_enable(&dsidev->dev);
4502
4489 INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, 4503 INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
4490 dsi_framedone_timeout_work_callback); 4504 dsi_framedone_timeout_work_callback);
4491 4505
@@ -4498,26 +4512,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4498 if (!dsi_mem) { 4512 if (!dsi_mem) {
4499 DSSERR("can't get IORESOURCE_MEM DSI\n"); 4513 DSSERR("can't get IORESOURCE_MEM DSI\n");
4500 r = -EINVAL; 4514 r = -EINVAL;
4501 goto err1; 4515 goto err_ioremap;
4502 } 4516 }
4503 dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); 4517 dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
4504 if (!dsi->base) { 4518 if (!dsi->base) {
4505 DSSERR("can't ioremap DSI\n"); 4519 DSSERR("can't ioremap DSI\n");
4506 r = -ENOMEM; 4520 r = -ENOMEM;
4507 goto err1; 4521 goto err_ioremap;
4508 } 4522 }
4509 dsi->irq = platform_get_irq(dsi->pdev, 0); 4523 dsi->irq = platform_get_irq(dsi->pdev, 0);
4510 if (dsi->irq < 0) { 4524 if (dsi->irq < 0) {
4511 DSSERR("platform_get_irq failed\n"); 4525 DSSERR("platform_get_irq failed\n");
4512 r = -ENODEV; 4526 r = -ENODEV;
4513 goto err2; 4527 goto err_get_irq;
4514 } 4528 }
4515 4529
4516 r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, 4530 r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
4517 dev_name(&dsidev->dev), dsi->pdev); 4531 dev_name(&dsidev->dev), dsi->pdev);
4518 if (r < 0) { 4532 if (r < 0) {
4519 DSSERR("request_irq failed\n"); 4533 DSSERR("request_irq failed\n");
4520 goto err2; 4534 goto err_get_irq;
4521 } 4535 }
4522 4536
4523 /* DSI VCs initialization */ 4537 /* DSI VCs initialization */
@@ -4529,7 +4543,9 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4529 4543
4530 dsi_calc_clock_param_ranges(dsidev); 4544 dsi_calc_clock_param_ranges(dsidev);
4531 4545
4532 enable_clocks(1); 4546 r = dsi_runtime_get(dsidev);
4547 if (r)
4548 goto err_get_dsi;
4533 4549
4534 rev = dsi_read_reg(dsidev, DSI_REVISION); 4550 rev = dsi_read_reg(dsidev, DSI_REVISION);
4535 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", 4551 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4537,14 +4553,19 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
4537 4553
4538 dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); 4554 dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
4539 4555
4540 enable_clocks(0); 4556 dsi_runtime_put(dsidev);
4541 4557
4542 return 0; 4558 return 0;
4543err2: 4559
4560err_get_dsi:
4561 free_irq(dsi->irq, dsi->pdev);
4562err_get_irq:
4544 iounmap(dsi->base); 4563 iounmap(dsi->base);
4545err1: 4564err_ioremap:
4565 pm_runtime_disable(&dsidev->dev);
4566err_get_clk:
4546 kfree(dsi); 4567 kfree(dsi);
4547err0: 4568err_alloc:
4548 return r; 4569 return r;
4549} 4570}
4550 4571
@@ -4554,6 +4575,10 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
4554 4575
4555 WARN_ON(dsi->scp_clk_refcount > 0); 4576 WARN_ON(dsi->scp_clk_refcount > 0);
4556 4577
4578 pm_runtime_disable(&dsidev->dev);
4579
4580 dsi_put_clocks(dsidev);
4581
4557 if (dsi->vdds_dsi_reg != NULL) { 4582 if (dsi->vdds_dsi_reg != NULL) {
4558 if (dsi->vdds_dsi_enabled) { 4583 if (dsi->vdds_dsi_enabled) {
4559 regulator_disable(dsi->vdds_dsi_reg); 4584 regulator_disable(dsi->vdds_dsi_reg);
@@ -4572,12 +4597,53 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
4572 return 0; 4597 return 0;
4573} 4598}
4574 4599
4600static int dsi_runtime_suspend(struct device *dev)
4601{
4602 struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
4603
4604 clk_disable(dsi->dss_clk);
4605
4606 dispc_runtime_put();
4607 dss_runtime_put();
4608
4609 return 0;
4610}
4611
4612static int dsi_runtime_resume(struct device *dev)
4613{
4614 struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
4615 int r;
4616
4617 r = dss_runtime_get();
4618 if (r)
4619 goto err_get_dss;
4620
4621 r = dispc_runtime_get();
4622 if (r)
4623 goto err_get_dispc;
4624
4625 clk_enable(dsi->dss_clk);
4626
4627 return 0;
4628
4629err_get_dispc:
4630 dss_runtime_put();
4631err_get_dss:
4632 return r;
4633}
4634
4635static const struct dev_pm_ops dsi_pm_ops = {
4636 .runtime_suspend = dsi_runtime_suspend,
4637 .runtime_resume = dsi_runtime_resume,
4638};
4639
4575static struct platform_driver omap_dsi1hw_driver = { 4640static struct platform_driver omap_dsi1hw_driver = {
4576 .probe = omap_dsi1hw_probe, 4641 .probe = omap_dsi1hw_probe,
4577 .remove = omap_dsi1hw_remove, 4642 .remove = omap_dsi1hw_remove,
4578 .driver = { 4643 .driver = {
4579 .name = "omapdss_dsi1", 4644 .name = "omapdss_dsi1",
4580 .owner = THIS_MODULE, 4645 .owner = THIS_MODULE,
4646 .pm = &dsi_pm_ops,
4581 }, 4647 },
4582}; 4648};
4583 4649
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 810ea8cbc1e6..a83c449d2ed1 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -29,6 +29,7 @@
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/platform_device.h> 31#include <linux/platform_device.h>
32#include <linux/pm_runtime.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
34#include <plat/clock.h> 35#include <plat/clock.h>
@@ -60,15 +61,11 @@ struct dss_reg {
60static struct { 61static struct {
61 struct platform_device *pdev; 62 struct platform_device *pdev;
62 void __iomem *base; 63 void __iomem *base;
64
63 int ctx_loss_cnt; 65 int ctx_loss_cnt;
64 66
65 struct clk *dpll4_m4_ck; 67 struct clk *dpll4_m4_ck;
66 struct clk *dss_ick; 68 struct clk *dss_clk;
67 struct clk *dss_fck;
68 struct clk *dss_sys_clk;
69 struct clk *dss_tv_fck;
70 struct clk *dss_video_fck;
71 unsigned num_clks_enabled;
72 69
73 unsigned long cache_req_pck; 70 unsigned long cache_req_pck;
74 unsigned long cache_prate; 71 unsigned long cache_prate;
@@ -88,13 +85,6 @@ static const char * const dss_generic_clk_source_names[] = {
88 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 85 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
89}; 86};
90 87
91static void dss_clk_enable_all_no_ctx(void);
92static void dss_clk_disable_all_no_ctx(void);
93static void dss_clk_enable_no_ctx(enum dss_clock clks);
94static void dss_clk_disable_no_ctx(enum dss_clock clks);
95
96static int _omap_dss_wait_reset(void);
97
98static inline void dss_write_reg(const struct dss_reg idx, u32 val) 88static inline void dss_write_reg(const struct dss_reg idx, u32 val)
99{ 89{
100 __raw_writel(val, dss.base + idx.idx); 90 __raw_writel(val, dss.base + idx.idx);
@@ -110,12 +100,10 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
110#define RR(reg) \ 100#define RR(reg) \
111 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) 101 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
112 102
113void dss_save_context(void) 103static void dss_save_context(void)
114{ 104{
115 if (cpu_is_omap24xx()) 105 DSSDBG("dss_save_context\n");
116 return;
117 106
118 SR(SYSCONFIG);
119 SR(CONTROL); 107 SR(CONTROL);
120 108
121 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 109 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -125,12 +113,10 @@ void dss_save_context(void)
125 } 113 }
126} 114}
127 115
128void dss_restore_context(void) 116static void dss_restore_context(void)
129{ 117{
130 if (_omap_dss_wait_reset()) 118 DSSDBG("dss_restore_context\n");
131 DSSERR("DSS not coming out of reset after sleep\n");
132 119
133 RR(SYSCONFIG);
134 RR(CONTROL); 120 RR(CONTROL);
135 121
136 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 122 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -235,6 +221,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
235 return dss_generic_clk_source_names[clk_src]; 221 return dss_generic_clk_source_names[clk_src];
236} 222}
237 223
224
238void dss_dump_clocks(struct seq_file *s) 225void dss_dump_clocks(struct seq_file *s)
239{ 226{
240 unsigned long dpll4_ck_rate; 227 unsigned long dpll4_ck_rate;
@@ -242,13 +229,14 @@ void dss_dump_clocks(struct seq_file *s)
242 const char *fclk_name, *fclk_real_name; 229 const char *fclk_name, *fclk_real_name;
243 unsigned long fclk_rate; 230 unsigned long fclk_rate;
244 231
245 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 232 if (dss_runtime_get())
233 return;
246 234
247 seq_printf(s, "- DSS -\n"); 235 seq_printf(s, "- DSS -\n");
248 236
249 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 237 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
250 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 238 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
251 fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); 239 fclk_rate = clk_get_rate(dss.dss_clk);
252 240
253 if (dss.dpll4_m4_ck) { 241 if (dss.dpll4_m4_ck) {
254 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 242 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -274,14 +262,15 @@ void dss_dump_clocks(struct seq_file *s)
274 fclk_rate); 262 fclk_rate);
275 } 263 }
276 264
277 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 265 dss_runtime_put();
278} 266}
279 267
280void dss_dump_regs(struct seq_file *s) 268void dss_dump_regs(struct seq_file *s)
281{ 269{
282#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) 270#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
283 271
284 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 272 if (dss_runtime_get())
273 return;
285 274
286 DUMPREG(DSS_REVISION); 275 DUMPREG(DSS_REVISION);
287 DUMPREG(DSS_SYSCONFIG); 276 DUMPREG(DSS_SYSCONFIG);
@@ -295,7 +284,7 @@ void dss_dump_regs(struct seq_file *s)
295 DUMPREG(DSS_SDI_STATUS); 284 DUMPREG(DSS_SDI_STATUS);
296 } 285 }
297 286
298 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 287 dss_runtime_put();
299#undef DUMPREG 288#undef DUMPREG
300} 289}
301 290
@@ -438,7 +427,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
438 } else { 427 } else {
439 if (cinfo->fck_div != 0) 428 if (cinfo->fck_div != 0)
440 return -EINVAL; 429 return -EINVAL;
441 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); 430 cinfo->fck = clk_get_rate(dss.dss_clk);
442 } 431 }
443 432
444 return 0; 433 return 0;
@@ -468,7 +457,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
468 457
469int dss_get_clock_div(struct dss_clock_info *cinfo) 458int dss_get_clock_div(struct dss_clock_info *cinfo)
470{ 459{
471 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); 460 cinfo->fck = clk_get_rate(dss.dss_clk);
472 461
473 if (dss.dpll4_m4_ck) { 462 if (dss.dpll4_m4_ck) {
474 unsigned long prate; 463 unsigned long prate;
@@ -513,7 +502,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
513 502
514 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 503 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
515 504
516 fck = dss_clk_get_rate(DSS_CLK_FCK); 505 fck = clk_get_rate(dss.dss_clk);
517 if (req_pck == dss.cache_req_pck && 506 if (req_pck == dss.cache_req_pck &&
518 ((cpu_is_omap34xx() && prate == dss.cache_prate) || 507 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
519 dss.cache_dss_cinfo.fck == fck)) { 508 dss.cache_dss_cinfo.fck == fck)) {
@@ -540,7 +529,7 @@ retry:
540 if (dss.dpll4_m4_ck == NULL) { 529 if (dss.dpll4_m4_ck == NULL) {
541 struct dispc_clock_info cur_dispc; 530 struct dispc_clock_info cur_dispc;
542 /* XXX can we change the clock on omap2? */ 531 /* XXX can we change the clock on omap2? */
543 fck = dss_clk_get_rate(DSS_CLK_FCK); 532 fck = clk_get_rate(dss.dss_clk);
544 fck_div = 1; 533 fck_div = 1;
545 534
546 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); 535 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -617,28 +606,6 @@ found:
617 return 0; 606 return 0;
618} 607}
619 608
620static int _omap_dss_wait_reset(void)
621{
622 int t = 0;
623
624 while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
625 if (++t > 1000) {
626 DSSERR("soft reset failed\n");
627 return -ENODEV;
628 }
629 udelay(1);
630 }
631
632 return 0;
633}
634
635static int _omap_dss_reset(void)
636{
637 /* Soft reset */
638 REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
639 return _omap_dss_wait_reset();
640}
641
642void dss_set_venc_output(enum omap_dss_venc_type type) 609void dss_set_venc_output(enum omap_dss_venc_type type)
643{ 610{
644 int l = 0; 611 int l = 0;
@@ -719,131 +686,45 @@ static bool dss_need_ctx_restore(void)
719 return true; 686 return true;
720} 687}
721 688
722static void save_all_ctx(void)
723{
724 DSSDBG("save context\n");
725
726 dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
727
728 dss_save_context();
729 dispc_save_context();
730#ifdef CONFIG_OMAP2_DSS_DSI
731 dsi_save_context();
732#endif
733
734 dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
735}
736
737static void restore_all_ctx(void)
738{
739 DSSDBG("restore context\n");
740
741 dss_clk_enable_all_no_ctx();
742
743 dss_restore_context();
744 dispc_restore_context();
745#ifdef CONFIG_OMAP2_DSS_DSI
746 dsi_restore_context();
747#endif
748
749 dss_clk_disable_all_no_ctx();
750}
751
752static int dss_get_clock(struct clk **clock, const char *clk_name)
753{
754 struct clk *clk;
755
756 clk = clk_get(&dss.pdev->dev, clk_name);
757
758 if (IS_ERR(clk)) {
759 DSSERR("can't get clock %s", clk_name);
760 return PTR_ERR(clk);
761 }
762
763 *clock = clk;
764
765 DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
766
767 return 0;
768}
769
770static int dss_get_clocks(void) 689static int dss_get_clocks(void)
771{ 690{
691 struct clk *clk;
772 int r; 692 int r;
773 struct clk *dpll4_m4_ck;
774 struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
775
776 dss.dss_ick = NULL;
777 dss.dss_fck = NULL;
778 dss.dss_sys_clk = NULL;
779 dss.dss_tv_fck = NULL;
780 dss.dss_video_fck = NULL;
781
782 r = dss_get_clock(&dss.dss_ick, "ick");
783 if (r)
784 goto err;
785 693
786 r = dss_get_clock(&dss.dss_fck, "fck"); 694 clk = clk_get(&dss.pdev->dev, "fck");
787 if (r) 695 if (IS_ERR(clk)) {
788 goto err; 696 DSSERR("can't get clock fck\n");
789 697 r = PTR_ERR(clk);
790 if (!pdata->opt_clock_available) {
791 r = -ENODEV;
792 goto err; 698 goto err;
793 } 699 }
794 700
795 if (pdata->opt_clock_available("sys_clk")) { 701 dss.dss_clk = clk;
796 r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
797 if (r)
798 goto err;
799 }
800
801 if (pdata->opt_clock_available("tv_clk")) {
802 r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
803 if (r)
804 goto err;
805 }
806
807 if (pdata->opt_clock_available("video_clk")) {
808 r = dss_get_clock(&dss.dss_video_fck, "video_clk");
809 if (r)
810 goto err;
811 }
812 702
813 if (cpu_is_omap34xx()) { 703 if (cpu_is_omap34xx()) {
814 dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); 704 clk = clk_get(NULL, "dpll4_m4_ck");
815 if (IS_ERR(dpll4_m4_ck)) { 705 if (IS_ERR(clk)) {
816 DSSERR("Failed to get dpll4_m4_ck\n"); 706 DSSERR("Failed to get dpll4_m4_ck\n");
817 r = PTR_ERR(dpll4_m4_ck); 707 r = PTR_ERR(clk);
818 goto err; 708 goto err;
819 } 709 }
820 } else if (cpu_is_omap44xx()) { 710 } else if (cpu_is_omap44xx()) {
821 dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); 711 clk = clk_get(NULL, "dpll_per_m5x2_ck");
822 if (IS_ERR(dpll4_m4_ck)) { 712 if (IS_ERR(clk)) {
823 DSSERR("Failed to get dpll_per_m5x2_ck\n"); 713 DSSERR("Failed to get dpll_per_m5x2_ck\n");
824 r = PTR_ERR(dpll4_m4_ck); 714 r = PTR_ERR(clk);
825 goto err; 715 goto err;
826 } 716 }
827 } else { /* omap24xx */ 717 } else { /* omap24xx */
828 dpll4_m4_ck = NULL; 718 clk = NULL;
829 } 719 }
830 720
831 dss.dpll4_m4_ck = dpll4_m4_ck; 721 dss.dpll4_m4_ck = clk;
832
833 722
834 return 0; 723 return 0;
835 724
836err: 725err:
837 if (dss.dss_ick) 726 if (dss.dss_clk)
838 clk_put(dss.dss_ick); 727 clk_put(dss.dss_clk);
839 if (dss.dss_fck)
840 clk_put(dss.dss_fck);
841 if (dss.dss_sys_clk)
842 clk_put(dss.dss_sys_clk);
843 if (dss.dss_tv_fck)
844 clk_put(dss.dss_tv_fck);
845 if (dss.dss_video_fck)
846 clk_put(dss.dss_video_fck);
847 if (dss.dpll4_m4_ck) 728 if (dss.dpll4_m4_ck)
848 clk_put(dss.dpll4_m4_ck); 729 clk_put(dss.dpll4_m4_ck);
849 730
@@ -854,139 +735,28 @@ static void dss_put_clocks(void)
854{ 735{
855 if (dss.dpll4_m4_ck) 736 if (dss.dpll4_m4_ck)
856 clk_put(dss.dpll4_m4_ck); 737 clk_put(dss.dpll4_m4_ck);
857 if (dss.dss_video_fck) 738 clk_put(dss.dss_clk);
858 clk_put(dss.dss_video_fck);
859 if (dss.dss_tv_fck)
860 clk_put(dss.dss_tv_fck);
861 if (dss.dss_sys_clk)
862 clk_put(dss.dss_sys_clk);
863 clk_put(dss.dss_fck);
864 clk_put(dss.dss_ick);
865}
866
867unsigned long dss_clk_get_rate(enum dss_clock clk)
868{
869 switch (clk) {
870 case DSS_CLK_ICK:
871 return clk_get_rate(dss.dss_ick);
872 case DSS_CLK_FCK:
873 return clk_get_rate(dss.dss_fck);
874 case DSS_CLK_SYSCK:
875 return clk_get_rate(dss.dss_sys_clk);
876 case DSS_CLK_TVFCK:
877 return clk_get_rate(dss.dss_tv_fck);
878 case DSS_CLK_VIDFCK:
879 return clk_get_rate(dss.dss_video_fck);
880 }
881
882 BUG();
883 return 0;
884} 739}
885 740
886static unsigned count_clk_bits(enum dss_clock clks) 741int dss_runtime_get(void)
887{ 742{
888 unsigned num_clks = 0; 743 int r;
889
890 if (clks & DSS_CLK_ICK)
891 ++num_clks;
892 if (clks & DSS_CLK_FCK)
893 ++num_clks;
894 if (clks & DSS_CLK_SYSCK)
895 ++num_clks;
896 if (clks & DSS_CLK_TVFCK)
897 ++num_clks;
898 if (clks & DSS_CLK_VIDFCK)
899 ++num_clks;
900
901 return num_clks;
902}
903
904static void dss_clk_enable_no_ctx(enum dss_clock clks)
905{
906 unsigned num_clks = count_clk_bits(clks);
907
908 if (clks & DSS_CLK_ICK)
909 clk_enable(dss.dss_ick);
910 if (clks & DSS_CLK_FCK)
911 clk_enable(dss.dss_fck);
912 if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
913 clk_enable(dss.dss_sys_clk);
914 if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
915 clk_enable(dss.dss_tv_fck);
916 if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
917 clk_enable(dss.dss_video_fck);
918
919 dss.num_clks_enabled += num_clks;
920}
921
922void dss_clk_enable(enum dss_clock clks)
923{
924 bool check_ctx = dss.num_clks_enabled == 0;
925
926 dss_clk_enable_no_ctx(clks);
927
928 /*
929 * HACK: On omap4 the registers may not be accessible right after
930 * enabling the clocks. At some point this will be handled by
931 * pm_runtime, but for the time begin this should make things work.
932 */
933 if (cpu_is_omap44xx() && check_ctx)
934 udelay(10);
935
936 if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
937 restore_all_ctx();
938}
939
940static void dss_clk_disable_no_ctx(enum dss_clock clks)
941{
942 unsigned num_clks = count_clk_bits(clks);
943
944 if (clks & DSS_CLK_ICK)
945 clk_disable(dss.dss_ick);
946 if (clks & DSS_CLK_FCK)
947 clk_disable(dss.dss_fck);
948 if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
949 clk_disable(dss.dss_sys_clk);
950 if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
951 clk_disable(dss.dss_tv_fck);
952 if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
953 clk_disable(dss.dss_video_fck);
954
955 dss.num_clks_enabled -= num_clks;
956}
957
958void dss_clk_disable(enum dss_clock clks)
959{
960 if (cpu_is_omap34xx()) {
961 unsigned num_clks = count_clk_bits(clks);
962
963 BUG_ON(dss.num_clks_enabled < num_clks);
964 744
965 if (dss.num_clks_enabled == num_clks) 745 DSSDBG("dss_runtime_get\n");
966 save_all_ctx();
967 }
968 746
969 dss_clk_disable_no_ctx(clks); 747 r = pm_runtime_get_sync(&dss.pdev->dev);
748 WARN_ON(r < 0);
749 return r < 0 ? r : 0;
970} 750}
971 751
972static void dss_clk_enable_all_no_ctx(void) 752void dss_runtime_put(void)
973{ 753{
974 enum dss_clock clks; 754 int r;
975
976 clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
977 if (cpu_is_omap34xx())
978 clks |= DSS_CLK_VIDFCK;
979 dss_clk_enable_no_ctx(clks);
980}
981 755
982static void dss_clk_disable_all_no_ctx(void) 756 DSSDBG("dss_runtime_put\n");
983{
984 enum dss_clock clks;
985 757
986 clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; 758 r = pm_runtime_put(&dss.pdev->dev);
987 if (cpu_is_omap34xx()) 759 WARN_ON(r < 0);
988 clks |= DSS_CLK_VIDFCK;
989 dss_clk_disable_no_ctx(clks);
990} 760}
991 761
992/* DEBUGFS */ 762/* DEBUGFS */
@@ -1001,7 +771,6 @@ void dss_debug_dump_clocks(struct seq_file *s)
1001} 771}
1002#endif 772#endif
1003 773
1004
1005/* DSS HW IP initialisation */ 774/* DSS HW IP initialisation */
1006static int omap_dsshw_probe(struct platform_device *pdev) 775static int omap_dsshw_probe(struct platform_device *pdev)
1007{ 776{
@@ -1028,19 +797,13 @@ static int omap_dsshw_probe(struct platform_device *pdev)
1028 if (r) 797 if (r)
1029 goto err_clocks; 798 goto err_clocks;
1030 799
1031 dss_clk_enable_all_no_ctx();
1032
1033 dss_init_ctx_loss_count(); 800 dss_init_ctx_loss_count();
1034 801
1035 /* disable LCD and DIGIT output. This seems to fix the synclost 802 pm_runtime_enable(&pdev->dev);
1036 * problem that we get, if the bootloader starts the DSS and
1037 * the kernel resets it */
1038 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
1039 803
1040 _omap_dss_reset(); 804 r = dss_runtime_get();
1041 805 if (r)
1042 /* autoidle */ 806 goto err_runtime_get;
1043 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
1044 807
1045 /* Select DPLL */ 808 /* Select DPLL */
1046 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); 809 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
@@ -1068,19 +831,19 @@ static int omap_dsshw_probe(struct platform_device *pdev)
1068 goto err_sdi; 831 goto err_sdi;
1069 } 832 }
1070 833
1071 dss_save_context();
1072
1073 rev = dss_read_reg(DSS_REVISION); 834 rev = dss_read_reg(DSS_REVISION);
1074 printk(KERN_INFO "OMAP DSS rev %d.%d\n", 835 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
1075 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 836 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1076 837
1077 dss_clk_disable_all_no_ctx(); 838 dss_runtime_put();
1078 839
1079 return 0; 840 return 0;
1080err_sdi: 841err_sdi:
1081 dpi_exit(); 842 dpi_exit();
1082err_dpi: 843err_dpi:
1083 dss_clk_disable_all_no_ctx(); 844 dss_runtime_put();
845err_runtime_get:
846 pm_runtime_disable(&pdev->dev);
1084 dss_put_clocks(); 847 dss_put_clocks();
1085err_clocks: 848err_clocks:
1086 iounmap(dss.base); 849 iounmap(dss.base);
@@ -1095,25 +858,40 @@ static int omap_dsshw_remove(struct platform_device *pdev)
1095 858
1096 iounmap(dss.base); 859 iounmap(dss.base);
1097 860
1098 /* 861 pm_runtime_disable(&pdev->dev);
1099 * As part of hwmod changes, DSS is not the only controller of dss
1100 * clocks; hwmod framework itself will also enable clocks during hwmod
1101 * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
1102 * need to disable clocks if their usecounts > 1.
1103 */
1104 WARN_ON(dss.num_clks_enabled > 0);
1105 862
1106 dss_put_clocks(); 863 dss_put_clocks();
1107 864
1108 return 0; 865 return 0;
1109} 866}
1110 867
868static int dss_runtime_suspend(struct device *dev)
869{
870 dss_save_context();
871 clk_disable(dss.dss_clk);
872 return 0;
873}
874
875static int dss_runtime_resume(struct device *dev)
876{
877 clk_enable(dss.dss_clk);
878 if (dss_need_ctx_restore())
879 dss_restore_context();
880 return 0;
881}
882
883static const struct dev_pm_ops dss_pm_ops = {
884 .runtime_suspend = dss_runtime_suspend,
885 .runtime_resume = dss_runtime_resume,
886};
887
1111static struct platform_driver omap_dsshw_driver = { 888static struct platform_driver omap_dsshw_driver = {
1112 .probe = omap_dsshw_probe, 889 .probe = omap_dsshw_probe,
1113 .remove = omap_dsshw_remove, 890 .remove = omap_dsshw_remove,
1114 .driver = { 891 .driver = {
1115 .name = "omapdss_dss", 892 .name = "omapdss_dss",
1116 .owner = THIS_MODULE, 893 .owner = THIS_MODULE,
894 .pm = &dss_pm_ops,
1117 }, 895 },
1118}; 896};
1119 897
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ceafe8a0e917..adeff04e964f 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -103,14 +103,6 @@ enum omap_parallel_interface_mode {
103 OMAP_DSS_PARALLELMODE_DSI, 103 OMAP_DSS_PARALLELMODE_DSI,
104}; 104};
105 105
106enum dss_clock {
107 DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */
108 DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */
109 DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */
110 DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */
111 DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/
112};
113
114enum dss_hdmi_venc_clk_source_select { 106enum dss_hdmi_venc_clk_source_select {
115 DSS_VENC_TV_CLK = 0, 107 DSS_VENC_TV_CLK = 0,
116 DSS_HDMI_M_PCLK = 1, 108 DSS_HDMI_M_PCLK = 1,
@@ -214,12 +206,10 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
214int dss_init_platform_driver(void); 206int dss_init_platform_driver(void);
215void dss_uninit_platform_driver(void); 207void dss_uninit_platform_driver(void);
216 208
209int dss_runtime_get(void);
210void dss_runtime_put(void);
211
217void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 212void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
218void dss_save_context(void);
219void dss_restore_context(void);
220void dss_clk_enable(enum dss_clock clks);
221void dss_clk_disable(enum dss_clock clks);
222unsigned long dss_clk_get_rate(enum dss_clock clk);
223const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 213const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
224void dss_dump_clocks(struct seq_file *s); 214void dss_dump_clocks(struct seq_file *s);
225 215
@@ -276,15 +266,15 @@ struct file_operations;
276int dsi_init_platform_driver(void); 266int dsi_init_platform_driver(void);
277void dsi_uninit_platform_driver(void); 267void dsi_uninit_platform_driver(void);
278 268
269int dsi_runtime_get(struct platform_device *dsidev);
270void dsi_runtime_put(struct platform_device *dsidev);
271
279void dsi_dump_clocks(struct seq_file *s); 272void dsi_dump_clocks(struct seq_file *s);
280void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, 273void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
281 const struct file_operations *debug_fops); 274 const struct file_operations *debug_fops);
282void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, 275void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
283 const struct file_operations *debug_fops); 276 const struct file_operations *debug_fops);
284 277
285void dsi_save_context(void);
286void dsi_restore_context(void);
287
288int dsi_init_display(struct omap_dss_device *display); 278int dsi_init_display(struct omap_dss_device *display);
289void dsi_irq_handler(void); 279void dsi_irq_handler(void);
290unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); 280unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -310,6 +300,13 @@ static inline int dsi_init_platform_driver(void)
310static inline void dsi_uninit_platform_driver(void) 300static inline void dsi_uninit_platform_driver(void)
311{ 301{
312} 302}
303static inline int dsi_runtime_get(struct platform_device *dsidev)
304{
305 return 0;
306}
307static inline void dsi_runtime_put(struct platform_device *dsidev)
308{
309}
313static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) 310static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
314{ 311{
315 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); 312 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -377,8 +374,8 @@ void dispc_dump_regs(struct seq_file *s);
377void dispc_irq_handler(void); 374void dispc_irq_handler(void);
378void dispc_fake_vsync_irq(void); 375void dispc_fake_vsync_irq(void);
379 376
380void dispc_save_context(void); 377int dispc_runtime_get(void);
381void dispc_restore_context(void); 378void dispc_runtime_put(void);
382 379
383void dispc_enable_sidle(void); 380void dispc_enable_sidle(void);
384void dispc_disable_sidle(void); 381void dispc_disable_sidle(void);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b630c988fd51..635cc002a438 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -30,6 +30,8 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h>
34#include <linux/clk.h>
33#include <video/omapdss.h> 35#include <video/omapdss.h>
34#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 36#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
35 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 37 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -52,6 +54,9 @@ static struct {
52 u8 edid_set; 54 u8 edid_set;
53 bool custom_set; 55 bool custom_set;
54 struct hdmi_config cfg; 56 struct hdmi_config cfg;
57
58 struct clk *sys_clk;
59 struct clk *hdmi_clk;
55} hdmi; 60} hdmi;
56 61
57/* 62/*
@@ -163,6 +168,27 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
163 return val; 168 return val;
164} 169}
165 170
171static int hdmi_runtime_get(void)
172{
173 int r;
174
175 DSSDBG("hdmi_runtime_get\n");
176
177 r = pm_runtime_get_sync(&hdmi.pdev->dev);
178 WARN_ON(r < 0);
179 return r < 0 ? r : 0;
180}
181
182static void hdmi_runtime_put(void)
183{
184 int r;
185
186 DSSDBG("hdmi_runtime_put\n");
187
188 r = pm_runtime_put(&hdmi.pdev->dev);
189 WARN_ON(r < 0);
190}
191
166int hdmi_init_display(struct omap_dss_device *dssdev) 192int hdmi_init_display(struct omap_dss_device *dssdev)
167{ 193{
168 DSSDBG("init_display\n"); 194 DSSDBG("init_display\n");
@@ -312,30 +338,11 @@ static int hdmi_phy_init(void)
312 return 0; 338 return 0;
313} 339}
314 340
315static int hdmi_wait_softreset(void)
316{
317 /* reset W1 */
318 REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
319
320 /* wait till SOFTRESET == 0 */
321 if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
322 DSSERR("sysconfig reset failed\n");
323 return -ETIMEDOUT;
324 }
325
326 return 0;
327}
328
329static int hdmi_pll_program(struct hdmi_pll_info *fmt) 341static int hdmi_pll_program(struct hdmi_pll_info *fmt)
330{ 342{
331 u16 r = 0; 343 u16 r = 0;
332 enum hdmi_clk_refsel refsel; 344 enum hdmi_clk_refsel refsel;
333 345
334 /* wait for wrapper reset */
335 r = hdmi_wait_softreset();
336 if (r)
337 return r;
338
339 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); 346 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
340 if (r) 347 if (r)
341 return r; 348 return r;
@@ -1065,7 +1072,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1065 unsigned long clkin, refclk; 1072 unsigned long clkin, refclk;
1066 u32 mf; 1073 u32 mf;
1067 1074
1068 clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000; 1075 clkin = clk_get_rate(hdmi.sys_clk) / 10000;
1069 /* 1076 /*
1070 * Input clock is predivided by N + 1 1077 * Input clock is predivided by N + 1
1071 * out put of which is reference clk 1078 * out put of which is reference clk
@@ -1099,16 +1106,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1099 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); 1106 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
1100} 1107}
1101 1108
1102static void hdmi_enable_clocks(int enable)
1103{
1104 if (enable)
1105 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
1106 DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
1107 else
1108 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
1109 DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
1110}
1111
1112static int hdmi_power_on(struct omap_dss_device *dssdev) 1109static int hdmi_power_on(struct omap_dss_device *dssdev)
1113{ 1110{
1114 int r, code = 0; 1111 int r, code = 0;
@@ -1116,7 +1113,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
1116 struct omap_video_timings *p; 1113 struct omap_video_timings *p;
1117 unsigned long phy; 1114 unsigned long phy;
1118 1115
1119 hdmi_enable_clocks(1); 1116 r = hdmi_runtime_get();
1117 if (r)
1118 return r;
1120 1119
1121 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); 1120 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
1122 1121
@@ -1181,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
1181 1180
1182 return 0; 1181 return 0;
1183err: 1182err:
1184 hdmi_enable_clocks(0); 1183 hdmi_runtime_put();
1185 return -EIO; 1184 return -EIO;
1186} 1185}
1187 1186
@@ -1192,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
1192 hdmi_wp_video_start(0); 1191 hdmi_wp_video_start(0);
1193 hdmi_phy_off(); 1192 hdmi_phy_off();
1194 hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); 1193 hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
1195 hdmi_enable_clocks(0); 1194 hdmi_runtime_put();
1196 1195
1197 hdmi.edid_set = 0; 1196 hdmi.edid_set = 0;
1198} 1197}
@@ -1687,14 +1686,43 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
1687}; 1686};
1688#endif 1687#endif
1689 1688
1689static int hdmi_get_clocks(struct platform_device *pdev)
1690{
1691 struct clk *clk;
1692
1693 clk = clk_get(&pdev->dev, "sys_clk");
1694 if (IS_ERR(clk)) {
1695 DSSERR("can't get sys_clk\n");
1696 return PTR_ERR(clk);
1697 }
1698
1699 hdmi.sys_clk = clk;
1700
1701 clk = clk_get(&pdev->dev, "fck");
1702 if (IS_ERR(clk)) {
1703 DSSERR("can't get fck\n");
1704 clk_put(hdmi.sys_clk);
1705 return PTR_ERR(clk);
1706 }
1707
1708 hdmi.hdmi_clk = clk;
1709
1710 return 0;
1711}
1712
1713static void hdmi_put_clocks(void)
1714{
1715 if (hdmi.sys_clk)
1716 clk_put(hdmi.sys_clk);
1717 if (hdmi.hdmi_clk)
1718 clk_put(hdmi.hdmi_clk);
1719}
1720
1690/* HDMI HW IP initialisation */ 1721/* HDMI HW IP initialisation */
1691static int omapdss_hdmihw_probe(struct platform_device *pdev) 1722static int omapdss_hdmihw_probe(struct platform_device *pdev)
1692{ 1723{
1693 struct resource *hdmi_mem; 1724 struct resource *hdmi_mem;
1694#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 1725 int r;
1695 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1696 int ret;
1697#endif
1698 1726
1699 hdmi.pdata = pdev->dev.platform_data; 1727 hdmi.pdata = pdev->dev.platform_data;
1700 hdmi.pdev = pdev; 1728 hdmi.pdev = pdev;
@@ -1714,17 +1742,25 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1714 return -ENOMEM; 1742 return -ENOMEM;
1715 } 1743 }
1716 1744
1745 r = hdmi_get_clocks(pdev);
1746 if (r) {
1747 iounmap(hdmi.base_wp);
1748 return r;
1749 }
1750
1751 pm_runtime_enable(&pdev->dev);
1752
1717 hdmi_panel_init(); 1753 hdmi_panel_init();
1718 1754
1719#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 1755#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1720 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 1756 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1721 1757
1722 /* Register ASoC codec DAI */ 1758 /* Register ASoC codec DAI */
1723 ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, 1759 r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
1724 &hdmi_codec_dai_drv, 1); 1760 &hdmi_codec_dai_drv, 1);
1725 if (ret) { 1761 if (r) {
1726 DSSERR("can't register ASoC HDMI audio codec\n"); 1762 DSSERR("can't register ASoC HDMI audio codec\n");
1727 return ret; 1763 return r;
1728 } 1764 }
1729#endif 1765#endif
1730 return 0; 1766 return 0;
@@ -1739,17 +1775,62 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
1739 snd_soc_unregister_codec(&pdev->dev); 1775 snd_soc_unregister_codec(&pdev->dev);
1740#endif 1776#endif
1741 1777
1778 pm_runtime_disable(&pdev->dev);
1779
1780 hdmi_put_clocks();
1781
1742 iounmap(hdmi.base_wp); 1782 iounmap(hdmi.base_wp);
1743 1783
1744 return 0; 1784 return 0;
1745} 1785}
1746 1786
1787static int hdmi_runtime_suspend(struct device *dev)
1788{
1789 clk_disable(hdmi.hdmi_clk);
1790 clk_disable(hdmi.sys_clk);
1791
1792 dispc_runtime_put();
1793 dss_runtime_put();
1794
1795 return 0;
1796}
1797
1798static int hdmi_runtime_resume(struct device *dev)
1799{
1800 int r;
1801
1802 r = dss_runtime_get();
1803 if (r < 0)
1804 goto err_get_dss;
1805
1806 r = dispc_runtime_get();
1807 if (r < 0)
1808 goto err_get_dispc;
1809
1810
1811 clk_enable(hdmi.sys_clk);
1812 clk_enable(hdmi.hdmi_clk);
1813
1814 return 0;
1815
1816err_get_dispc:
1817 dss_runtime_put();
1818err_get_dss:
1819 return r;
1820}
1821
1822static const struct dev_pm_ops hdmi_pm_ops = {
1823 .runtime_suspend = hdmi_runtime_suspend,
1824 .runtime_resume = hdmi_runtime_resume,
1825};
1826
1747static struct platform_driver omapdss_hdmihw_driver = { 1827static struct platform_driver omapdss_hdmihw_driver = {
1748 .probe = omapdss_hdmihw_probe, 1828 .probe = omapdss_hdmihw_probe,
1749 .remove = omapdss_hdmihw_remove, 1829 .remove = omapdss_hdmihw_remove,
1750 .driver = { 1830 .driver = {
1751 .name = "omapdss_hdmi", 1831 .name = "omapdss_hdmi",
1752 .owner = THIS_MODULE, 1832 .owner = THIS_MODULE,
1833 .pm = &hdmi_pm_ops,
1753 }, 1834 },
1754}; 1835};
1755 1836
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 49c0d77a5f24..13d72d5c714b 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -1314,6 +1314,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1314 1314
1315 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); 1315 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
1316 1316
1317 r = dispc_runtime_get();
1318 if (r)
1319 return r;
1320
1317 spin_lock_irqsave(&dss_cache.lock, flags); 1321 spin_lock_irqsave(&dss_cache.lock, flags);
1318 1322
1319 /* Configure overlays */ 1323 /* Configure overlays */
@@ -1458,7 +1462,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1458 } 1462 }
1459 1463
1460 r = 0; 1464 r = 0;
1461 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
1462 if (!dss_cache.irq_enabled) { 1465 if (!dss_cache.irq_enabled) {
1463 u32 mask; 1466 u32 mask;
1464 1467
@@ -1471,10 +1474,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1471 dss_cache.irq_enabled = true; 1474 dss_cache.irq_enabled = true;
1472 } 1475 }
1473 configure_dispc(); 1476 configure_dispc();
1474 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
1475 1477
1476 spin_unlock_irqrestore(&dss_cache.lock, flags); 1478 spin_unlock_irqrestore(&dss_cache.lock, flags);
1477 1479
1480 dispc_runtime_put();
1481
1478 return r; 1482 return r;
1479} 1483}
1480 1484
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index cfbfc57e9582..c84380c53c39 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
84 84
85 old_mgr = ovl->manager; 85 old_mgr = ovl->manager;
86 86
87 r = dispc_runtime_get();
88 if (r)
89 return r;
90
87 /* detach old manager */ 91 /* detach old manager */
88 if (old_mgr) { 92 if (old_mgr) {
89 r = ovl->unset_manager(ovl); 93 r = ovl->unset_manager(ovl);
90 if (r) { 94 if (r) {
91 DSSERR("detach failed\n"); 95 DSSERR("detach failed\n");
92 return r; 96 goto err;
93 } 97 }
94 98
95 r = old_mgr->apply(old_mgr); 99 r = old_mgr->apply(old_mgr);
96 if (r) 100 if (r)
97 return r; 101 goto err;
98 } 102 }
99 103
100 if (mgr) { 104 if (mgr) {
101 r = ovl->set_manager(ovl, mgr); 105 r = ovl->set_manager(ovl, mgr);
102 if (r) { 106 if (r) {
103 DSSERR("Failed to attach overlay\n"); 107 DSSERR("Failed to attach overlay\n");
104 return r; 108 goto err;
105 } 109 }
106 110
107 r = mgr->apply(mgr); 111 r = mgr->apply(mgr);
108 if (r) 112 if (r)
109 return r; 113 goto err;
110 } 114 }
111 115
116 dispc_runtime_put();
117
112 return size; 118 return size;
119
120err:
121 dispc_runtime_put();
122 return r;
113} 123}
114 124
115static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) 125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -507,7 +517,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
507 517
508 ovl->manager = mgr; 518 ovl->manager = mgr;
509 519
510 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
511 /* XXX: When there is an overlay on a DSI manual update display, and 520 /* XXX: When there is an overlay on a DSI manual update display, and
512 * the overlay is first disabled, then moved to tv, and enabled, we 521 * the overlay is first disabled, then moved to tv, and enabled, we
513 * seem to get SYNC_LOST_DIGIT error. 522 * seem to get SYNC_LOST_DIGIT error.
@@ -521,7 +530,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
521 * the overlay, but before moving the overlay to TV. 530 * the overlay, but before moving the overlay to TV.
522 */ 531 */
523 dispc_set_channel_out(ovl->id, mgr->id); 532 dispc_set_channel_out(ovl->id, mgr->id);
524 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
525 533
526 return 0; 534 return 0;
527} 535}
@@ -722,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
722 } 730 }
723 731
724 if (mgr) { 732 if (mgr) {
733 dispc_runtime_get();
734
725 for (i = 0; i < dss_feat_get_num_ovls(); i++) { 735 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
726 struct omap_overlay *ovl; 736 struct omap_overlay *ovl;
727 ovl = omap_dss_get_overlay(i); 737 ovl = omap_dss_get_overlay(i);
@@ -731,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
731 omap_dss_set_manager(ovl, mgr); 741 omap_dss_set_manager(ovl, mgr);
732 } 742 }
733 } 743 }
744
745 dispc_runtime_put();
734 } 746 }
735} 747}
736 748
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index a873104ee65a..2d31cc1e6270 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -34,6 +34,7 @@
34#include <linux/seq_file.h> 34#include <linux/seq_file.h>
35#include <linux/semaphore.h> 35#include <linux/semaphore.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/pm_runtime.h>
37 38
38#include <video/omapdss.h> 39#include <video/omapdss.h>
39#include "dss.h" 40#include "dss.h"
@@ -121,12 +122,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
121 return __raw_readl(rfbi.base + idx.idx); 122 return __raw_readl(rfbi.base + idx.idx);
122} 123}
123 124
124static void rfbi_enable_clocks(bool enable) 125static int rfbi_runtime_get(void)
125{ 126{
126 if (enable) 127 int r;
127 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 128
128 else 129 DSSDBG("rfbi_runtime_get\n");
129 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 130
131 r = pm_runtime_get_sync(&rfbi.pdev->dev);
132 WARN_ON(r < 0);
133 return r < 0 ? r : 0;
134}
135
136static void rfbi_runtime_put(void)
137{
138 int r;
139
140 DSSDBG("rfbi_runtime_put\n");
141
142 r = pm_runtime_put(&rfbi.pdev->dev);
143 WARN_ON(r < 0);
130} 144}
131 145
132void rfbi_bus_lock(void) 146void rfbi_bus_lock(void)
@@ -806,7 +820,8 @@ void rfbi_dump_regs(struct seq_file *s)
806{ 820{
807#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) 821#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
808 822
809 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 823 if (rfbi_runtime_get())
824 return;
810 825
811 DUMPREG(RFBI_REVISION); 826 DUMPREG(RFBI_REVISION);
812 DUMPREG(RFBI_SYSCONFIG); 827 DUMPREG(RFBI_SYSCONFIG);
@@ -837,7 +852,7 @@ void rfbi_dump_regs(struct seq_file *s)
837 DUMPREG(RFBI_VSYNC_WIDTH); 852 DUMPREG(RFBI_VSYNC_WIDTH);
838 DUMPREG(RFBI_HSYNC_WIDTH); 853 DUMPREG(RFBI_HSYNC_WIDTH);
839 854
840 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 855 rfbi_runtime_put();
841#undef DUMPREG 856#undef DUMPREG
842} 857}
843 858
@@ -845,7 +860,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
845{ 860{
846 int r; 861 int r;
847 862
848 rfbi_enable_clocks(1); 863 r = rfbi_runtime_get();
864 if (r)
865 return r;
849 866
850 r = omap_dss_start_device(dssdev); 867 r = omap_dss_start_device(dssdev);
851 if (r) { 868 if (r) {
@@ -880,6 +897,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
880err1: 897err1:
881 omap_dss_stop_device(dssdev); 898 omap_dss_stop_device(dssdev);
882err0: 899err0:
900 rfbi_runtime_put();
883 return r; 901 return r;
884} 902}
885EXPORT_SYMBOL(omapdss_rfbi_display_enable); 903EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -890,7 +908,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
890 DISPC_IRQ_FRAMEDONE); 908 DISPC_IRQ_FRAMEDONE);
891 omap_dss_stop_device(dssdev); 909 omap_dss_stop_device(dssdev);
892 910
893 rfbi_enable_clocks(0); 911 rfbi_runtime_put();
894} 912}
895EXPORT_SYMBOL(omapdss_rfbi_display_disable); 913EXPORT_SYMBOL(omapdss_rfbi_display_disable);
896 914
@@ -905,8 +923,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
905static int omap_rfbihw_probe(struct platform_device *pdev) 923static int omap_rfbihw_probe(struct platform_device *pdev)
906{ 924{
907 u32 rev; 925 u32 rev;
908 u32 l;
909 struct resource *rfbi_mem; 926 struct resource *rfbi_mem;
927 struct clk *clk;
928 int r;
910 929
911 rfbi.pdev = pdev; 930 rfbi.pdev = pdev;
912 931
@@ -915,46 +934,99 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
915 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); 934 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
916 if (!rfbi_mem) { 935 if (!rfbi_mem) {
917 DSSERR("can't get IORESOURCE_MEM RFBI\n"); 936 DSSERR("can't get IORESOURCE_MEM RFBI\n");
918 return -EINVAL; 937 r = -EINVAL;
938 goto err_ioremap;
919 } 939 }
920 rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); 940 rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
921 if (!rfbi.base) { 941 if (!rfbi.base) {
922 DSSERR("can't ioremap RFBI\n"); 942 DSSERR("can't ioremap RFBI\n");
923 return -ENOMEM; 943 r = -ENOMEM;
944 goto err_ioremap;
924 } 945 }
925 946
926 rfbi_enable_clocks(1); 947 pm_runtime_enable(&pdev->dev);
948
949 r = rfbi_runtime_get();
950 if (r)
951 goto err_get_rfbi;
927 952
928 msleep(10); 953 msleep(10);
929 954
930 rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; 955 clk = clk_get(&pdev->dev, "ick");
956 if (IS_ERR(clk)) {
957 DSSERR("can't get ick\n");
958 r = PTR_ERR(clk);
959 goto err_get_ick;
960 }
961
962 rfbi.l4_khz = clk_get_rate(clk) / 1000;
931 963
932 /* Enable autoidle and smart-idle */ 964 clk_put(clk);
933 l = rfbi_read_reg(RFBI_SYSCONFIG);
934 l |= (1 << 0) | (2 << 3);
935 rfbi_write_reg(RFBI_SYSCONFIG, l);
936 965
937 rev = rfbi_read_reg(RFBI_REVISION); 966 rev = rfbi_read_reg(RFBI_REVISION);
938 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", 967 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
939 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 968 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
940 969
941 rfbi_enable_clocks(0); 970 rfbi_runtime_put();
942 971
943 return 0; 972 return 0;
973
974err_get_ick:
975 rfbi_runtime_put();
976err_get_rfbi:
977 pm_runtime_disable(&pdev->dev);
978 iounmap(rfbi.base);
979err_ioremap:
980 return r;
944} 981}
945 982
946static int omap_rfbihw_remove(struct platform_device *pdev) 983static int omap_rfbihw_remove(struct platform_device *pdev)
947{ 984{
985 pm_runtime_disable(&pdev->dev);
948 iounmap(rfbi.base); 986 iounmap(rfbi.base);
949 return 0; 987 return 0;
950} 988}
951 989
990static int rfbi_runtime_suspend(struct device *dev)
991{
992 dispc_runtime_put();
993 dss_runtime_put();
994
995 return 0;
996}
997
998static int rfbi_runtime_resume(struct device *dev)
999{
1000 int r;
1001
1002 r = dss_runtime_get();
1003 if (r < 0)
1004 goto err_get_dss;
1005
1006 r = dispc_runtime_get();
1007 if (r < 0)
1008 goto err_get_dispc;
1009
1010 return 0;
1011
1012err_get_dispc:
1013 dss_runtime_put();
1014err_get_dss:
1015 return r;
1016}
1017
1018static const struct dev_pm_ops rfbi_pm_ops = {
1019 .runtime_suspend = rfbi_runtime_suspend,
1020 .runtime_resume = rfbi_runtime_resume,
1021};
1022
952static struct platform_driver omap_rfbihw_driver = { 1023static struct platform_driver omap_rfbihw_driver = {
953 .probe = omap_rfbihw_probe, 1024 .probe = omap_rfbihw_probe,
954 .remove = omap_rfbihw_remove, 1025 .remove = omap_rfbihw_remove,
955 .driver = { 1026 .driver = {
956 .name = "omapdss_rfbi", 1027 .name = "omapdss_rfbi",
957 .owner = THIS_MODULE, 1028 .owner = THIS_MODULE,
1029 .pm = &rfbi_pm_ops,
958 }, 1030 },
959}; 1031};
960 1032
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 0bd4b0350f80..3a688c871a45 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -20,13 +20,11 @@
20#define DSS_SUBSYS_NAME "SDI" 20#define DSS_SUBSYS_NAME "SDI"
21 21
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/clk.h>
24#include <linux/delay.h> 23#include <linux/delay.h>
25#include <linux/err.h> 24#include <linux/err.h>
26#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
27 26
28#include <video/omapdss.h> 27#include <video/omapdss.h>
29#include <plat/cpu.h>
30#include "dss.h" 28#include "dss.h"
31 29
32static struct { 30static struct {
@@ -60,14 +58,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
60 r = omap_dss_start_device(dssdev); 58 r = omap_dss_start_device(dssdev);
61 if (r) { 59 if (r) {
62 DSSERR("failed to start device\n"); 60 DSSERR("failed to start device\n");
63 goto err0; 61 goto err_start_dev;
64 } 62 }
65 63
66 r = regulator_enable(sdi.vdds_sdi_reg); 64 r = regulator_enable(sdi.vdds_sdi_reg);
67 if (r) 65 if (r)
68 goto err1; 66 goto err_reg_enable;
69 67
70 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); 68 r = dss_runtime_get();
69 if (r)
70 goto err_get_dss;
71
72 r = dispc_runtime_get();
73 if (r)
74 goto err_get_dispc;
71 75
72 sdi_basic_init(dssdev); 76 sdi_basic_init(dssdev);
73 77
@@ -80,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
80 r = dss_calc_clock_div(1, t->pixel_clock * 1000, 84 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
81 &dss_cinfo, &dispc_cinfo); 85 &dss_cinfo, &dispc_cinfo);
82 if (r) 86 if (r)
83 goto err2; 87 goto err_calc_clock_div;
84 88
85 fck = dss_cinfo.fck; 89 fck = dss_cinfo.fck;
86 lck_div = dispc_cinfo.lck_div; 90 lck_div = dispc_cinfo.lck_div;
@@ -101,27 +105,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
101 105
102 r = dss_set_clock_div(&dss_cinfo); 106 r = dss_set_clock_div(&dss_cinfo);
103 if (r) 107 if (r)
104 goto err2; 108 goto err_set_dss_clock_div;
105 109
106 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); 110 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
107 if (r) 111 if (r)
108 goto err2; 112 goto err_set_dispc_clock_div;
109 113
110 dss_sdi_init(dssdev->phy.sdi.datapairs); 114 dss_sdi_init(dssdev->phy.sdi.datapairs);
111 r = dss_sdi_enable(); 115 r = dss_sdi_enable();
112 if (r) 116 if (r)
113 goto err1; 117 goto err_sdi_enable;
114 mdelay(2); 118 mdelay(2);
115 119
116 dssdev->manager->enable(dssdev->manager); 120 dssdev->manager->enable(dssdev->manager);
117 121
118 return 0; 122 return 0;
119err2: 123
120 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 124err_sdi_enable:
125err_set_dispc_clock_div:
126err_set_dss_clock_div:
127err_calc_clock_div:
128 dispc_runtime_put();
129err_get_dispc:
130 dss_runtime_put();
131err_get_dss:
121 regulator_disable(sdi.vdds_sdi_reg); 132 regulator_disable(sdi.vdds_sdi_reg);
122err1: 133err_reg_enable:
123 omap_dss_stop_device(dssdev); 134 omap_dss_stop_device(dssdev);
124err0: 135err_start_dev:
125 return r; 136 return r;
126} 137}
127EXPORT_SYMBOL(omapdss_sdi_display_enable); 138EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -132,7 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
132 143
133 dss_sdi_disable(); 144 dss_sdi_disable();
134 145
135 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); 146 dispc_runtime_put();
147 dss_runtime_put();
136 148
137 regulator_disable(sdi.vdds_sdi_reg); 149 regulator_disable(sdi.vdds_sdi_reg);
138 150
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index bf0431f788c1..71e005df1759 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -33,6 +33,7 @@
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/regulator/consumer.h> 35#include <linux/regulator/consumer.h>
36#include <linux/pm_runtime.h>
36 37
37#include <video/omapdss.h> 38#include <video/omapdss.h>
38#include <plat/cpu.h> 39#include <plat/cpu.h>
@@ -293,6 +294,9 @@ static struct {
293 struct mutex venc_lock; 294 struct mutex venc_lock;
294 u32 wss_data; 295 u32 wss_data;
295 struct regulator *vdda_dac_reg; 296 struct regulator *vdda_dac_reg;
297
298 struct clk *tv_clk;
299 struct clk *tv_dac_clk;
296} venc; 300} venc;
297 301
298static inline void venc_write_reg(int idx, u32 val) 302static inline void venc_write_reg(int idx, u32 val)
@@ -381,17 +385,25 @@ static void venc_reset(void)
381#endif 385#endif
382} 386}
383 387
384static void venc_enable_clocks(int enable) 388static int venc_runtime_get(void)
385{ 389{
386 if (enable) { 390 int r;
387 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); 391
388 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) 392 DSSDBG("venc_runtime_get\n");
389 dss_clk_enable(DSS_CLK_VIDFCK); 393
390 } else { 394 r = pm_runtime_get_sync(&venc.pdev->dev);
391 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); 395 WARN_ON(r < 0);
392 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) 396 return r < 0 ? r : 0;
393 dss_clk_disable(DSS_CLK_VIDFCK); 397}
394 } 398
399static void venc_runtime_put(void)
400{
401 int r;
402
403 DSSDBG("venc_runtime_put\n");
404
405 r = pm_runtime_put(&venc.pdev->dev);
406 WARN_ON(r < 0);
395} 407}
396 408
397static const struct venc_config *venc_timings_to_config( 409static const struct venc_config *venc_timings_to_config(
@@ -410,8 +422,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
410{ 422{
411 u32 l; 423 u32 l;
412 424
413 venc_enable_clocks(1);
414
415 venc_reset(); 425 venc_reset();
416 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); 426 venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
417 427
@@ -452,8 +462,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
452 dssdev->platform_disable(dssdev); 462 dssdev->platform_disable(dssdev);
453 463
454 regulator_disable(venc.vdda_dac_reg); 464 regulator_disable(venc.vdda_dac_reg);
455
456 venc_enable_clocks(0);
457} 465}
458 466
459 467
@@ -491,6 +499,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
491 goto err1; 499 goto err1;
492 } 500 }
493 501
502 r = venc_runtime_get();
503 if (r)
504 goto err1;
505
494 venc_power_on(dssdev); 506 venc_power_on(dssdev);
495 507
496 venc.wss_data = 0; 508 venc.wss_data = 0;
@@ -524,6 +536,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
524 536
525 venc_power_off(dssdev); 537 venc_power_off(dssdev);
526 538
539 venc_runtime_put();
540
527 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 541 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
528 542
529 omap_dss_stop_device(dssdev); 543 omap_dss_stop_device(dssdev);
@@ -588,6 +602,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
588static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 602static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
589{ 603{
590 const struct venc_config *config; 604 const struct venc_config *config;
605 int r;
591 606
592 DSSDBG("venc_set_wss\n"); 607 DSSDBG("venc_set_wss\n");
593 608
@@ -598,16 +613,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
598 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 613 /* Invert due to VENC_L21_WC_CTL:INV=1 */
599 venc.wss_data = (wss ^ 0xfffff) << 8; 614 venc.wss_data = (wss ^ 0xfffff) << 8;
600 615
601 venc_enable_clocks(1); 616 r = venc_runtime_get();
617 if (r)
618 goto err;
602 619
603 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | 620 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
604 venc.wss_data); 621 venc.wss_data);
605 622
606 venc_enable_clocks(0); 623 venc_runtime_put();
607 624
625err:
608 mutex_unlock(&venc.venc_lock); 626 mutex_unlock(&venc.venc_lock);
609 627
610 return 0; 628 return r;
611} 629}
612 630
613static struct omap_dss_driver venc_driver = { 631static struct omap_dss_driver venc_driver = {
@@ -660,7 +678,8 @@ void venc_dump_regs(struct seq_file *s)
660{ 678{
661#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 679#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
662 680
663 venc_enable_clocks(1); 681 if (venc_runtime_get())
682 return;
664 683
665 DUMPREG(VENC_F_CONTROL); 684 DUMPREG(VENC_F_CONTROL);
666 DUMPREG(VENC_VIDOUT_CTRL); 685 DUMPREG(VENC_VIDOUT_CTRL);
@@ -704,16 +723,53 @@ void venc_dump_regs(struct seq_file *s)
704 DUMPREG(VENC_OUTPUT_CONTROL); 723 DUMPREG(VENC_OUTPUT_CONTROL);
705 DUMPREG(VENC_OUTPUT_TEST); 724 DUMPREG(VENC_OUTPUT_TEST);
706 725
707 venc_enable_clocks(0); 726 venc_runtime_put();
708 727
709#undef DUMPREG 728#undef DUMPREG
710} 729}
711 730
731static int venc_get_clocks(struct platform_device *pdev)
732{
733 struct clk *clk;
734
735 clk = clk_get(&pdev->dev, "fck");
736 if (IS_ERR(clk)) {
737 DSSERR("can't get fck\n");
738 return PTR_ERR(clk);
739 }
740
741 venc.tv_clk = clk;
742
743 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
744 clk = clk_get(&pdev->dev, "tv_dac_clk");
745 if (IS_ERR(clk)) {
746 DSSERR("can't get tv_dac_clk\n");
747 clk_put(venc.tv_clk);
748 return PTR_ERR(clk);
749 }
750 } else {
751 clk = NULL;
752 }
753
754 venc.tv_dac_clk = clk;
755
756 return 0;
757}
758
759static void venc_put_clocks(void)
760{
761 if (venc.tv_clk)
762 clk_put(venc.tv_clk);
763 if (venc.tv_dac_clk)
764 clk_put(venc.tv_dac_clk);
765}
766
712/* VENC HW IP initialisation */ 767/* VENC HW IP initialisation */
713static int omap_venchw_probe(struct platform_device *pdev) 768static int omap_venchw_probe(struct platform_device *pdev)
714{ 769{
715 u8 rev_id; 770 u8 rev_id;
716 struct resource *venc_mem; 771 struct resource *venc_mem;
772 int r;
717 773
718 venc.pdev = pdev; 774 venc.pdev = pdev;
719 775
@@ -724,22 +780,40 @@ static int omap_venchw_probe(struct platform_device *pdev)
724 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); 780 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
725 if (!venc_mem) { 781 if (!venc_mem) {
726 DSSERR("can't get IORESOURCE_MEM VENC\n"); 782 DSSERR("can't get IORESOURCE_MEM VENC\n");
727 return -EINVAL; 783 r = -EINVAL;
784 goto err_ioremap;
728 } 785 }
729 venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); 786 venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
730 if (!venc.base) { 787 if (!venc.base) {
731 DSSERR("can't ioremap VENC\n"); 788 DSSERR("can't ioremap VENC\n");
732 return -ENOMEM; 789 r = -ENOMEM;
790 goto err_ioremap;
733 } 791 }
734 792
735 venc_enable_clocks(1); 793 r = venc_get_clocks(pdev);
794 if (r)
795 goto err_get_clk;
796
797 pm_runtime_enable(&pdev->dev);
798
799 r = venc_runtime_get();
800 if (r)
801 goto err_get_venc;
736 802
737 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); 803 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
738 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); 804 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
739 805
740 venc_enable_clocks(0); 806 venc_runtime_put();
741 807
742 return omap_dss_register_driver(&venc_driver); 808 return omap_dss_register_driver(&venc_driver);
809
810err_get_venc:
811 pm_runtime_disable(&pdev->dev);
812 venc_put_clocks();
813err_get_clk:
814 iounmap(venc.base);
815err_ioremap:
816 return r;
743} 817}
744 818
745static int omap_venchw_remove(struct platform_device *pdev) 819static int omap_venchw_remove(struct platform_device *pdev)
@@ -750,16 +824,61 @@ static int omap_venchw_remove(struct platform_device *pdev)
750 } 824 }
751 omap_dss_unregister_driver(&venc_driver); 825 omap_dss_unregister_driver(&venc_driver);
752 826
827 pm_runtime_disable(&pdev->dev);
828 venc_put_clocks();
829
753 iounmap(venc.base); 830 iounmap(venc.base);
754 return 0; 831 return 0;
755} 832}
756 833
834static int venc_runtime_suspend(struct device *dev)
835{
836 if (venc.tv_dac_clk)
837 clk_disable(venc.tv_dac_clk);
838 clk_disable(venc.tv_clk);
839
840 dispc_runtime_put();
841 dss_runtime_put();
842
843 return 0;
844}
845
846static int venc_runtime_resume(struct device *dev)
847{
848 int r;
849
850 r = dss_runtime_get();
851 if (r < 0)
852 goto err_get_dss;
853
854 r = dispc_runtime_get();
855 if (r < 0)
856 goto err_get_dispc;
857
858 clk_enable(venc.tv_clk);
859 if (venc.tv_dac_clk)
860 clk_enable(venc.tv_dac_clk);
861
862 return 0;
863
864err_get_dispc:
865 dss_runtime_put();
866err_get_dss:
867 return r;
868}
869
870static const struct dev_pm_ops venc_pm_ops = {
871 .runtime_suspend = venc_runtime_suspend,
872 .runtime_resume = venc_runtime_resume,
873};
874
757static struct platform_driver omap_venchw_driver = { 875static struct platform_driver omap_venchw_driver = {
758 .probe = omap_venchw_probe, 876 .probe = omap_venchw_probe,
759 .remove = omap_venchw_remove, 877 .remove = omap_venchw_remove,
760 .driver = { 878 .driver = {
761 .name = "omapdss_venc", 879 .name = "omapdss_venc",
762 .owner = THIS_MODULE, 880 .owner = THIS_MODULE,
881 .pm = &venc_pm_ops,
763 }, 882 },
764}; 883};
765 884