aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-05-27 03:52:19 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-07-25 03:22:04 -0400
commit4fbafaf371be780ed2cd73a520dfeafa1ea73e24 (patch)
tree50be77c643fe710ce07bfea5e21587f9f5c38ac5 /drivers
parentde3050a74e2d2830189ceaa5f5fc05b776518d68 (diff)
OMAP: DSS2: Use PM runtime & HWMOD support
Use PM runtime and HWMOD support to handle enabling and disabling of DSS modules. Each DSS module will have get and put functions which can be used to enable and disable that module. The functions use pm_runtime and hwmod opt-clocks to enable the hardware. Acked-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers')
-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 ba1ccf709e1..5b095a38b20 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 bab55cd4ac9..f053b180ecd 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 1e2fd404651..48b0cdf97ce 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 810ea8cbc1e..a83c449d2ed 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 ceafe8a0e91..adeff04e964 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 b630c988fd5..635cc002a43 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 49c0d77a5f2..13d72d5c714 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 cfbfc57e958..c84380c53c3 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 a873104ee65..2d31cc1e627 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 0bd4b0350f8..3a688c871a4 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 bf0431f788c..71e005df175 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