From 8cff88c5da2197aa601409d4a7ce8f83f8de8190 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Sat, 30 Apr 2011 14:09:53 +0300 Subject: OMAP: DSS2: remove update_mode from omapdss Remove the whole update_mode stuff from omapdss driver. If automatic update for manual update displays is needed, it's better implemented in higher layers. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/venc.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers/video/omap2/dss/venc.c') diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 980f919ed987..e7485fc41fca 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -538,20 +538,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev) return venc_panel_enable(dssdev); } -static enum omap_dss_update_mode venc_get_update_mode( - struct omap_dss_device *dssdev) -{ - return OMAP_DSS_UPDATE_AUTO; -} - -static int venc_set_update_mode(struct omap_dss_device *dssdev, - enum omap_dss_update_mode mode) -{ - if (mode != OMAP_DSS_UPDATE_AUTO) - return -EINVAL; - return 0; -} - static void venc_get_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { @@ -632,9 +618,6 @@ static struct omap_dss_driver venc_driver = { .get_resolution = omapdss_default_get_resolution, .get_recommended_bpp = omapdss_default_get_recommended_bpp, - .set_update_mode = venc_set_update_mode, - .get_update_mode = venc_get_update_mode, - .get_timings = venc_get_timings, .set_timings = venc_set_timings, .check_timings = venc_check_timings, -- cgit v1.2.3 From 525dae613638320c880afcc0d8d6dd27141fc4e4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 18 May 2011 11:59:21 +0300 Subject: OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK OMAP3430 requires an 96MHz clock to VENC's DAC, but no other OMAP needs it. Add a new feature, FEAT_VENC_REQUIRES_TV_DAC_CLK, which tells if the clock is needed on this platform, and use that feature in venc.c to decide if the clock needs enabling. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 3 ++- drivers/video/omap2/dss/dss_features.h | 1 + drivers/video/omap2/dss/venc.c | 16 ++++++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/video/omap2/dss/venc.c') diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 1c18888e5df3..a588380eec22 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -286,7 +286,8 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | - FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC, + FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | + FEAT_VENC_REQUIRES_TV_DAC_CLK, .num_mgrs = 2, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 07b346f7d916..3058e24946ad 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -51,6 +51,7 @@ enum dss_feat_id { FEAT_HDMI_CTS_SWMODE = 1 << 19, FEAT_HANDLE_UV_SEPARATE = 1 << 20, FEAT_ATTR2 = 1 << 21, + FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22, }; /* DSS register field id */ diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index e7485fc41fca..bf0431f788c1 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -38,6 +38,7 @@ #include #include "dss.h" +#include "dss_features.h" /* Venc registers */ #define VENC_REV_ID 0x00 @@ -382,12 +383,15 @@ static void venc_reset(void) static void venc_enable_clocks(int enable) { - if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | - DSS_CLK_VIDFCK); - else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | - DSS_CLK_VIDFCK); + if (enable) { + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); + if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) + dss_clk_enable(DSS_CLK_VIDFCK); + } else { + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); + if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) + dss_clk_disable(DSS_CLK_VIDFCK); + } } static const struct venc_config *venc_timings_to_config( -- cgit v1.2.3 From 4fbafaf371be780ed2cd73a520dfeafa1ea73e24 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 27 May 2011 10:52:19 +0300 Subject: 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 Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 326 +++++++++++++++++++++++---------- drivers/video/omap2/dss/dpi.c | 70 ++++--- drivers/video/omap2/dss/dsi.c | 244 ++++++++++++++++--------- drivers/video/omap2/dss/dss.c | 376 ++++++++------------------------------ drivers/video/omap2/dss/dss.h | 33 ++-- drivers/video/omap2/dss/hdmi.c | 161 ++++++++++++---- drivers/video/omap2/dss/manager.c | 8 +- drivers/video/omap2/dss/overlay.c | 24 ++- drivers/video/omap2/dss/rfbi.c | 110 +++++++++-- drivers/video/omap2/dss/sdi.c | 40 ++-- drivers/video/omap2/dss/venc.c | 165 ++++++++++++++--- 11 files changed, 923 insertions(+), 634 deletions(-) (limited to 'drivers/video/omap2/dss/venc.c') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ba1ccf709e14..5b095a38b201 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -99,7 +100,11 @@ struct dispc_irq_stats { static struct { struct platform_device *pdev; void __iomem *base; + + int ctx_loss_cnt; + int irq; + struct clk *dss_clk; u32 fifo_size[3]; @@ -146,13 +151,12 @@ static inline u32 dispc_read_reg(const u16 idx) #define RR(reg) \ dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)]) -void dispc_save_context(void) +static void dispc_save_context(void) { int i; - if (cpu_is_omap24xx()) - return; - SR(SYSCONFIG); + DSSDBG("dispc_save_context\n"); + SR(IRQENABLE); SR(CONTROL); SR(CONFIG); @@ -320,10 +324,12 @@ void dispc_save_context(void) SR(DIVISOR); } -void dispc_restore_context(void) +static void dispc_restore_context(void) { int i; - RR(SYSCONFIG); + + DSSDBG("dispc_restore_context\n"); + /*RR(IRQENABLE);*/ /*RR(CONTROL);*/ RR(CONFIG); @@ -507,14 +513,82 @@ void dispc_restore_context(void) #undef SR #undef RR -static inline void enable_clocks(bool enable) +static void dispc_init_ctx_loss_count(void) { - if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + struct device *dev = &dispc.pdev->dev; + struct omap_display_platform_data *pdata = dev->platform_data; + struct omap_dss_board_info *board_data = pdata->board_data; + int cnt = 0; + + /* + * get_context_loss_count returns negative on error. We'll ignore the + * error and store the error to ctx_loss_cnt, which will cause + * dispc_need_ctx_restore() call to return true. + */ + + if (board_data->get_context_loss_count) + cnt = board_data->get_context_loss_count(dev); + + WARN_ON(cnt < 0); + + dispc.ctx_loss_cnt = cnt; + + DSSDBG("initial ctx_loss_cnt %u\n", cnt); +} + +static bool dispc_need_ctx_restore(void) +{ + struct device *dev = &dispc.pdev->dev; + struct omap_display_platform_data *pdata = dev->platform_data; + struct omap_dss_board_info *board_data = pdata->board_data; + int cnt; + + /* + * If get_context_loss_count is not available, assume that we need + * context restore always. + */ + if (!board_data->get_context_loss_count) + return true; + + cnt = board_data->get_context_loss_count(dev); + if (cnt < 0) { + dev_err(dev, "getting context loss count failed, will force " + "context restore\n"); + dispc.ctx_loss_cnt = cnt; + return true; + } + + if (cnt == dispc.ctx_loss_cnt) + return false; + + DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt); + dispc.ctx_loss_cnt = cnt; + + return true; +} + +int dispc_runtime_get(void) +{ + int r; + + DSSDBG("dispc_runtime_get\n"); + + r = pm_runtime_get_sync(&dispc.pdev->dev); + WARN_ON(r < 0); + return r < 0 ? r : 0; +} + +void dispc_runtime_put(void) +{ + int r; + + DSSDBG("dispc_runtime_put\n"); + + r = pm_runtime_put(&dispc.pdev->dev); + WARN_ON(r < 0); } + bool dispc_go_busy(enum omap_channel channel) { int bit; @@ -536,7 +610,7 @@ void dispc_go(enum omap_channel channel) int bit; bool enable_bit, go_bit; - enable_clocks(1); + dispc_runtime_get(); if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) @@ -577,7 +651,7 @@ void dispc_go(enum omap_channel channel) else REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); end: - enable_clocks(0); + dispc_runtime_put(); } static 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, { int shift; - enable_clocks(1); + dispc_runtime_get(); switch (plane) { case OMAP_DSS_GFX: @@ -1020,7 +1094,7 @@ static void dispc_set_burst_size(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); - enable_clocks(0); + dispc_runtime_put(); } static void dispc_configure_burst_sizes(void) @@ -1108,9 +1182,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) else bit = 10; - enable_clocks(1); + dispc_runtime_get(); REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); - enable_clocks(0); + dispc_runtime_put(); } void 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) u32 val; BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - enable_clocks(1); + dispc_runtime_get(); dispc_write_reg(DISPC_SIZE_MGR(channel), val); - enable_clocks(0); + dispc_runtime_put(); } void dispc_set_digit_size(u16 width, u16 height) @@ -1128,9 +1202,9 @@ void dispc_set_digit_size(u16 width, u16 height) u32 val; BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - enable_clocks(1); + dispc_runtime_get(); dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); - enable_clocks(0); + dispc_runtime_put(); } static void dispc_read_plane_fifo_sizes(void) @@ -1142,7 +1216,7 @@ static void dispc_read_plane_fifo_sizes(void) unit = dss_feat_get_buffer_size_unit(); - enable_clocks(1); + dispc_runtime_get(); dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); @@ -1152,7 +1226,7 @@ static void dispc_read_plane_fifo_sizes(void) dispc.fifo_size[plane] = size; } - enable_clocks(0); + dispc_runtime_put(); } u32 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) dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); - enable_clocks(1); + dispc_runtime_get(); DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", plane, @@ -1190,17 +1264,17 @@ void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) FLD_VAL(high, hi_start, hi_end) | FLD_VAL(low, lo_start, lo_end)); - enable_clocks(0); + dispc_runtime_put(); } void dispc_enable_fifomerge(bool enable) { - enable_clocks(1); + dispc_runtime_get(); DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); - enable_clocks(0); + dispc_runtime_put(); } static void _dispc_set_fir(enum omap_plane plane, @@ -1822,9 +1896,9 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) { - enable_clocks(1); + dispc_runtime_get(); _dispc_set_channel_out(plane, channel_out); - enable_clocks(0); + dispc_runtime_put(); } static int _dispc_setup_plane(enum omap_plane plane, @@ -2020,7 +2094,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) int r; u32 irq; - enable_clocks(1); + dispc_runtime_get(); /* When we disable LCD output, we need to wait until frame is done. * 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) DSSERR("failed to unregister FRAMEDONE isr\n"); } - enable_clocks(0); + dispc_runtime_put(); } static void _enable_digit_out(bool enable) @@ -2069,10 +2143,10 @@ static void dispc_enable_digit_out(bool enable) struct completion frame_done_completion; int r; - enable_clocks(1); + dispc_runtime_get(); if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { - enable_clocks(0); + dispc_runtime_put(); return; } @@ -2127,7 +2201,7 @@ static void dispc_enable_digit_out(bool enable) spin_unlock_irqrestore(&dispc.irq_lock, flags); } - enable_clocks(0); + dispc_runtime_put(); } bool dispc_is_channel_enabled(enum omap_channel channel) @@ -2158,9 +2232,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high) if (!dss_has_feature(FEAT_LCDENABLEPOL)) return; - enable_clocks(1); + dispc_runtime_get(); REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); - enable_clocks(0); + dispc_runtime_put(); } void dispc_lcd_enable_signal(bool enable) @@ -2168,9 +2242,9 @@ void dispc_lcd_enable_signal(bool enable) if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) return; - enable_clocks(1); + dispc_runtime_get(); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); - enable_clocks(0); + dispc_runtime_put(); } void dispc_pck_free_enable(bool enable) @@ -2178,19 +2252,19 @@ void dispc_pck_free_enable(bool enable) if (!dss_has_feature(FEAT_PCKFREEENABLE)) return; - enable_clocks(1); + dispc_runtime_get(); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); - enable_clocks(0); + dispc_runtime_put(); } void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) { - enable_clocks(1); + dispc_runtime_get(); if (channel == OMAP_DSS_CHANNEL_LCD2) REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); else REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); - enable_clocks(0); + dispc_runtime_put(); } @@ -2213,27 +2287,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel, return; } - enable_clocks(1); + dispc_runtime_get(); if (channel == OMAP_DSS_CHANNEL_LCD2) REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3); else REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); - enable_clocks(0); + dispc_runtime_put(); } void dispc_set_loadmode(enum omap_dss_load_mode mode) { - enable_clocks(1); + dispc_runtime_get(); REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); - enable_clocks(0); + dispc_runtime_put(); } void dispc_set_default_color(enum omap_channel channel, u32 color) { - enable_clocks(1); + dispc_runtime_get(); dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); - enable_clocks(0); + dispc_runtime_put(); } u32 dispc_get_default_color(enum omap_channel channel) @@ -2244,9 +2318,9 @@ u32 dispc_get_default_color(enum omap_channel channel) channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2); - enable_clocks(1); + dispc_runtime_get(); l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); - enable_clocks(0); + dispc_runtime_put(); return l; } @@ -2255,7 +2329,7 @@ void dispc_set_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type type, u32 trans_key) { - enable_clocks(1); + dispc_runtime_get(); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2264,14 +2338,14 @@ void dispc_set_trans_key(enum omap_channel ch, REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11); dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); - enable_clocks(0); + dispc_runtime_put(); } void dispc_get_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type *type, u32 *trans_key) { - enable_clocks(1); + dispc_runtime_get(); if (type) { if (ch == OMAP_DSS_CHANNEL_LCD) *type = REG_GET(DISPC_CONFIG, 11, 11); @@ -2285,33 +2359,33 @@ void dispc_get_trans_key(enum omap_channel ch, if (trans_key) *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); - enable_clocks(0); + dispc_runtime_put(); } void dispc_enable_trans_key(enum omap_channel ch, bool enable) { - enable_clocks(1); + dispc_runtime_get(); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); else if (ch == OMAP_DSS_CHANNEL_DIGIT) REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); else /* OMAP_DSS_CHANNEL_LCD2 */ REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); - enable_clocks(0); + dispc_runtime_put(); } void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) { if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) return; - enable_clocks(1); + dispc_runtime_get(); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); else if (ch == OMAP_DSS_CHANNEL_DIGIT) REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); else /* OMAP_DSS_CHANNEL_LCD2 */ REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); - enable_clocks(0); + dispc_runtime_put(); } bool dispc_alpha_blending_enabled(enum omap_channel ch) { @@ -2320,7 +2394,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) return false; - enable_clocks(1); + dispc_runtime_get(); if (ch == OMAP_DSS_CHANNEL_LCD) enabled = REG_GET(DISPC_CONFIG, 18, 18); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2329,7 +2403,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) enabled = REG_GET(DISPC_CONFIG2, 18, 18); else BUG(); - enable_clocks(0); + dispc_runtime_put(); return enabled; } @@ -2339,7 +2413,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) { bool enabled; - enable_clocks(1); + dispc_runtime_get(); if (ch == OMAP_DSS_CHANNEL_LCD) enabled = REG_GET(DISPC_CONFIG, 10, 10); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2348,7 +2422,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) enabled = REG_GET(DISPC_CONFIG2, 10, 10); else BUG(); - enable_clocks(0); + dispc_runtime_put(); return enabled; } @@ -2376,12 +2450,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) return; } - enable_clocks(1); + dispc_runtime_get(); if (channel == OMAP_DSS_CHANNEL_LCD2) REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8); else REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); - enable_clocks(0); + dispc_runtime_put(); } void dispc_set_parallel_interface_mode(enum omap_channel channel, @@ -2413,7 +2487,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel, return; } - enable_clocks(1); + dispc_runtime_get(); if (channel == OMAP_DSS_CHANNEL_LCD2) { l = dispc_read_reg(DISPC_CONTROL2); @@ -2427,7 +2501,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel, dispc_write_reg(DISPC_CONTROL, l); } - enable_clocks(0); + dispc_runtime_put(); } static 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, FLD_VAL(vbp, 31, 20); } - enable_clocks(1); + dispc_runtime_get(); dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); - enable_clocks(0); + dispc_runtime_put(); } /* change name to mode? */ @@ -2526,10 +2600,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, BUG_ON(lck_div < 1); BUG_ON(pck_div < 2); - enable_clocks(1); + dispc_runtime_get(); dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); - enable_clocks(0); + dispc_runtime_put(); } static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, @@ -2548,7 +2622,7 @@ unsigned long dispc_fclk_rate(void) switch (dss_get_dispc_clk_source()) { case OMAP_DSS_CLK_SRC_FCK: - r = dss_clk_get_rate(DSS_CLK_FCK); + r = clk_get_rate(dispc.dss_clk); break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: dsidev = dsi_get_dsidev_from_id(0); @@ -2578,7 +2652,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) switch (dss_get_lcd_clk_source(channel)) { case OMAP_DSS_CLK_SRC_FCK: - r = dss_clk_get_rate(DSS_CLK_FCK); + r = clk_get_rate(dispc.dss_clk); break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: dsidev = dsi_get_dsidev_from_id(0); @@ -2617,7 +2691,8 @@ void dispc_dump_clocks(struct seq_file *s) enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); enum omap_dss_clk_source lcd_clk_src; - enable_clocks(1); + if (dispc_runtime_get()) + return; seq_printf(s, "- DISPC -\n"); @@ -2665,7 +2740,8 @@ void dispc_dump_clocks(struct seq_file *s) seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); } - enable_clocks(0); + + dispc_runtime_put(); } #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -2720,7 +2796,8 @@ void dispc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + if (dispc_runtime_get()) + return; DUMPREG(DISPC_REVISION); DUMPREG(DISPC_SYSCONFIG); @@ -2965,7 +3042,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); } - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + dispc_runtime_put(); #undef DUMPREG } @@ -2986,9 +3063,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, l |= FLD_VAL(acbi, 11, 8); l |= FLD_VAL(acb, 7, 0); - enable_clocks(1); + dispc_runtime_get(); dispc_write_reg(DISPC_POL_FREQ(channel), l); - enable_clocks(0); + dispc_runtime_put(); } void dispc_set_pol_freq(enum omap_channel channel, @@ -3109,7 +3186,7 @@ static void _omap_dispc_set_irqs(void) mask |= isr_data->mask; } - enable_clocks(1); + dispc_runtime_get(); old_mask = dispc_read_reg(DISPC_IRQENABLE); /* clear the irqstatus for newly enabled irqs */ @@ -3117,7 +3194,7 @@ static void _omap_dispc_set_irqs(void) dispc_write_reg(DISPC_IRQENABLE, mask); - enable_clocks(0); + dispc_runtime_put(); } int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) @@ -3626,13 +3703,6 @@ static void _omap_dispc_initial_config(void) { u32 l; - l = dispc_read_reg(DISPC_SYSCONFIG); - l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ - l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ - l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ - l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ - dispc_write_reg(DISPC_SYSCONFIG, l); - /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ if (dss_has_feature(FEAT_CORE_CLK_DIV)) { l = dispc_read_reg(DISPC_DIVISOR); @@ -3664,9 +3734,9 @@ int dispc_enable_plane(enum omap_plane plane, bool enable) { DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); - enable_clocks(1); + dispc_runtime_get(); _dispc_enable_plane(plane, enable); - enable_clocks(0); + dispc_runtime_put(); return 0; } @@ -3693,7 +3763,7 @@ int dispc_setup_plane(enum omap_plane plane, ilace, color_mode, rotation, mirror, channel); - enable_clocks(1); + dispc_runtime_get(); r = _dispc_setup_plane(plane, paddr, screen_width, @@ -3707,7 +3777,7 @@ int dispc_setup_plane(enum omap_plane plane, pre_mult_alpha, channel, puv_addr); - enable_clocks(0); + dispc_runtime_put(); return r; } @@ -3718,9 +3788,19 @@ static int omap_dispchw_probe(struct platform_device *pdev) u32 rev; int r = 0; struct resource *dispc_mem; + struct clk *clk; dispc.pdev = pdev; + clk = clk_get(&pdev->dev, "fck"); + if (IS_ERR(clk)) { + DSSERR("can't get fck\n"); + r = PTR_ERR(clk); + goto err_get_clk; + } + + dispc.dss_clk = clk; + spin_lock_init(&dispc.irq_lock); #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -3734,62 +3814,106 @@ static int omap_dispchw_probe(struct platform_device *pdev) if (!dispc_mem) { DSSERR("can't get IORESOURCE_MEM DISPC\n"); r = -EINVAL; - goto fail0; + goto err_ioremap; } dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); if (!dispc.base) { DSSERR("can't ioremap DISPC\n"); r = -ENOMEM; - goto fail0; + goto err_ioremap; } dispc.irq = platform_get_irq(dispc.pdev, 0); if (dispc.irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto fail1; + goto err_irq; } r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, "OMAP DISPC", dispc.pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto fail1; + goto err_irq; } - enable_clocks(1); + dispc_init_ctx_loss_count(); + + pm_runtime_enable(&pdev->dev); + + r = dispc_runtime_get(); + if (r) + goto err_runtime_get; _omap_dispc_initial_config(); _omap_dispc_initialize_irq(); - dispc_save_context(); - rev = dispc_read_reg(DISPC_REVISION); dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - enable_clocks(0); + dispc_runtime_put(); return 0; -fail1: + +err_runtime_get: + pm_runtime_disable(&pdev->dev); + free_irq(dispc.irq, dispc.pdev); +err_irq: iounmap(dispc.base); -fail0: +err_ioremap: + clk_put(dispc.dss_clk); +err_get_clk: return r; } static int omap_dispchw_remove(struct platform_device *pdev) { + pm_runtime_disable(&pdev->dev); + + clk_put(dispc.dss_clk); + free_irq(dispc.irq, dispc.pdev); iounmap(dispc.base); return 0; } +static int dispc_runtime_suspend(struct device *dev) +{ + dispc_save_context(); + clk_disable(dispc.dss_clk); + dss_runtime_put(); + + return 0; +} + +static int dispc_runtime_resume(struct device *dev) +{ + int r; + + r = dss_runtime_get(); + if (r < 0) + return r; + + clk_enable(dispc.dss_clk); + if (dispc_need_ctx_restore()) + dispc_restore_context(); + + return 0; +} + +static const struct dev_pm_ops dispc_pm_ops = { + .runtime_suspend = dispc_runtime_suspend, + .runtime_resume = dispc_runtime_resume, +}; + static struct platform_driver omap_dispchw_driver = { .probe = omap_dispchw_probe, .remove = omap_dispchw_remove, .driver = { .name = "omapdss_dispc", .owner = THIS_MODULE, + .pm = &dispc_pm_ops, }, }; diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index bab55cd4ac9a..f053b180ecd7 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -23,7 +23,6 @@ #define DSS_SUBSYS_NAME "DPI" #include -#include #include #include #include @@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) bool is_tft; int r = 0; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); @@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, &lck_div, &pck_div); if (r) - goto err0; + return r; pck = fck / lck_div / pck_div / 1000; @@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) dispc_set_lcd_timings(dssdev->manager->id, t); -err0: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); - return r; + return 0; } -static int dpi_basic_init(struct omap_dss_device *dssdev) +static void dpi_basic_init(struct omap_dss_device *dssdev) { bool is_tft; @@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev) OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); dispc_set_tft_data_lines(dssdev->manager->id, dssdev->phy.dpi.data_lines); - - return 0; } int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) @@ -186,30 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); - goto err0; + goto err_start_dev; } if (cpu_is_omap34xx()) { r = regulator_enable(dpi.vdds_dsi_reg); if (r) - goto err1; + goto err_reg_enable; } - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + r = dss_runtime_get(); + if (r) + goto err_get_dss; - r = dpi_basic_init(dssdev); + r = dispc_runtime_get(); if (r) - goto err2; + goto err_get_dispc; + + dpi_basic_init(dssdev); if (dpi_use_dsi_pll(dssdev)) { + r = dsi_runtime_get(dpi.dsidev); + if (r) + goto err_get_dsi; + r = dsi_pll_init(dpi.dsidev, 0, 1); if (r) - goto err2; + goto err_dsi_pll_init; } r = dpi_set_mode(dssdev); if (r) - goto err3; + goto err_set_mode; mdelay(2); @@ -217,16 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) return 0; -err3: +err_set_mode: if (dpi_use_dsi_pll(dssdev)) dsi_pll_uninit(dpi.dsidev, true); -err2: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); +err_dsi_pll_init: + if (dpi_use_dsi_pll(dssdev)) + dsi_runtime_put(dpi.dsidev); +err_get_dsi: + dispc_runtime_put(); +err_get_dispc: + dss_runtime_put(); +err_get_dss: if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); -err1: +err_reg_enable: omap_dss_stop_device(dssdev); -err0: +err_start_dev: return r; } EXPORT_SYMBOL(omapdss_dpi_display_enable); @@ -238,9 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) if (dpi_use_dsi_pll(dssdev)) { dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dsi_pll_uninit(dpi.dsidev, true); + dsi_runtime_put(dpi.dsidev); } - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + dispc_runtime_put(); + dss_runtime_put(); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); @@ -252,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable); void dpi_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { + int r; + DSSDBG("dpi_set_timings\n"); dssdev->panel.timings = *timings; if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + r = dss_runtime_get(); + if (r) + return; + + r = dispc_runtime_get(); + if (r) { + dss_runtime_put(); + return; + } + dpi_set_mode(dssdev); dispc_go(dssdev->manager->id); + + dispc_runtime_put(); + dss_runtime_put(); } } EXPORT_SYMBOL(dpi_set_timings); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 1e2fd404651f..48b0cdf97ceb 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -36,6 +36,7 @@ #include #include #include +#include #include