diff options
Diffstat (limited to 'drivers/video/omap2/dss/dispc.c')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 484 |
1 files changed, 235 insertions, 249 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index eac768ff2d3..7a9a2e7d968 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -33,8 +33,6 @@ #include <linux/workqueue.h> #include <linux/hardirq.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> #include <plat/sram.h> #include <plat/clock.h> @@ -94,11 +92,7 @@ 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]; @@ -108,7 +102,6 @@ static struct { u32 error_irqs; struct work_struct error_work; - bool ctx_valid; u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -141,34 +134,18 @@ static inline u32 dispc_read_reg(const u16 idx) return __raw_readl(dispc.base + idx); } -static int dispc_get_ctx_loss_count(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 (!board_data->get_context_loss_count) - return -ENOENT; - - cnt = board_data->get_context_loss_count(dev); - - WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); - - return cnt; -} - #define SR(reg) \ dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) #define RR(reg) \ dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)]) -static void dispc_save_context(void) +void dispc_save_context(void) { int i; + if (cpu_is_omap24xx()) + return; - DSSDBG("dispc_save_context\n"); - + SR(SYSCONFIG); SR(IRQENABLE); SR(CONTROL); SR(CONFIG); @@ -181,8 +158,7 @@ static void dispc_save_context(void) SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_GLOBAL_ALPHA)) - SR(GLOBAL_ALPHA); + SR(GLOBAL_ALPHA); SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -212,25 +188,20 @@ static void dispc_save_context(void) SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_CPR)) { - SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); - } + SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { - if (dss_has_feature(FEAT_CPR)) { - SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); - } + SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); + SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); } - if (dss_has_feature(FEAT_PRELOAD)) - SR(OVL_PRELOAD(OMAP_DSS_GFX)); + SR(OVL_PRELOAD(OMAP_DSS_GFX)); /* VID1 */ SR(OVL_BA0(OMAP_DSS_VIDEO1)); @@ -255,10 +226,8 @@ static void dispc_save_context(void) for (i = 0; i < 5; i++) SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); - } + for (i = 0; i < 8; i++) + SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -279,8 +248,7 @@ static void dispc_save_context(void) if (dss_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - if (dss_has_feature(FEAT_PRELOAD)) - SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); + SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); /* VID2 */ SR(OVL_BA0(OMAP_DSS_VIDEO2)); @@ -305,10 +273,8 @@ static void dispc_save_context(void) for (i = 0; i < 5; i++) SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); - } + for (i = 0; i < 8; i++) + SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -329,35 +295,16 @@ static void dispc_save_context(void) if (dss_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - if (dss_has_feature(FEAT_PRELOAD)) - SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); + SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); if (dss_has_feature(FEAT_CORE_CLK_DIV)) SR(DIVISOR); - - dispc.ctx_loss_cnt = dispc_get_ctx_loss_count(); - dispc.ctx_valid = true; - - DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); } -static void dispc_restore_context(void) +void dispc_restore_context(void) { - int i, ctx; - - DSSDBG("dispc_restore_context\n"); - - if (!dispc.ctx_valid) - return; - - ctx = dispc_get_ctx_loss_count(); - - if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) - return; - - DSSDBG("ctx_loss_count: saved %d, current %d\n", - dispc.ctx_loss_cnt, ctx); - + int i; + RR(SYSCONFIG); /*RR(IRQENABLE);*/ /*RR(CONTROL);*/ RR(CONFIG); @@ -370,8 +317,7 @@ static void dispc_restore_context(void) RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_GLOBAL_ALPHA)) - RR(GLOBAL_ALPHA); + RR(GLOBAL_ALPHA); RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -401,25 +347,20 @@ static void dispc_restore_context(void) RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_CPR)) { - RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); - } + RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); - if (dss_has_feature(FEAT_CPR)) { - RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); - } + RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); + RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); } - if (dss_has_feature(FEAT_PRELOAD)) - RR(OVL_PRELOAD(OMAP_DSS_GFX)); + RR(OVL_PRELOAD(OMAP_DSS_GFX)); /* VID1 */ RR(OVL_BA0(OMAP_DSS_VIDEO1)); @@ -444,10 +385,8 @@ static void dispc_restore_context(void) for (i = 0; i < 5; i++) RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); - } + for (i = 0; i < 8; i++) + RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -468,8 +407,7 @@ static void dispc_restore_context(void) if (dss_has_feature(FEAT_ATTR2)) RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - if (dss_has_feature(FEAT_PRELOAD)) - RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); + RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); /* VID2 */ RR(OVL_BA0(OMAP_DSS_VIDEO2)); @@ -494,10 +432,8 @@ static void dispc_restore_context(void) for (i = 0; i < 5; i++) RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); - } + for (i = 0; i < 8; i++) + RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -518,8 +454,7 @@ static void dispc_restore_context(void) if (dss_has_feature(FEAT_ATTR2)) RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - if (dss_has_feature(FEAT_PRELOAD)) - RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); + RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); if (dss_has_feature(FEAT_CORE_CLK_DIV)) RR(DIVISOR); @@ -536,35 +471,19 @@ static void dispc_restore_context(void) * the context is fully restored */ RR(IRQENABLE); - - DSSDBG("context restored\n"); } #undef SR #undef RR -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) +static inline void enable_clocks(bool enable) { - int r; - - DSSDBG("dispc_runtime_put\n"); - - r = pm_runtime_put(&dispc.pdev->dev); - WARN_ON(r < 0); + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } - bool dispc_go_busy(enum omap_channel channel) { int bit; @@ -586,6 +505,8 @@ void dispc_go(enum omap_channel channel) int bit; bool enable_bit, go_bit; + enable_clocks(1); + if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) bit = 0; /* LCDENABLE */ @@ -599,7 +520,7 @@ void dispc_go(enum omap_channel channel) enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; if (!enable_bit) - return; + goto end; if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) @@ -614,7 +535,7 @@ void dispc_go(enum omap_channel channel) if (go_bit) { DSSERR("GO bit not down for channel %d\n", channel); - return; + goto end; } DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : @@ -624,6 +545,8 @@ void dispc_go(enum omap_channel channel) REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit); else REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); +end: + enable_clocks(0); } static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) @@ -997,7 +920,7 @@ static void _dispc_set_color_mode(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } -void dispc_set_channel_out(enum omap_plane plane, +static void _dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel) { int shift; @@ -1050,6 +973,8 @@ void dispc_set_burst_size(enum omap_plane plane, int shift; u32 val; + enable_clocks(1); + switch (plane) { case OMAP_DSS_GFX: shift = 6; @@ -1066,6 +991,8 @@ void dispc_set_burst_size(enum omap_plane plane, val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); val = FLD_MOD(val, burst_size, shift+1, shift); dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); + + enable_clocks(0); } void dispc_enable_gamma_table(bool enable) @@ -1102,7 +1029,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) else bit = 10; + enable_clocks(1); REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); + enable_clocks(0); } void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) @@ -1110,7 +1039,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_write_reg(DISPC_SIZE_MGR(channel), val); + enable_clocks(0); } void dispc_set_digit_size(u16 width, u16 height) @@ -1118,7 +1049,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_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); + enable_clocks(0); } static void dispc_read_plane_fifo_sizes(void) @@ -1127,6 +1060,8 @@ static void dispc_read_plane_fifo_sizes(void) int plane; u8 start, end; + enable_clocks(1); + dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { @@ -1134,6 +1069,8 @@ static void dispc_read_plane_fifo_sizes(void) start, end); dispc.fifo_size[plane] = size; } + + enable_clocks(0); } u32 dispc_get_plane_fifo_size(enum omap_plane plane) @@ -1148,6 +1085,8 @@ void dispc_setup_plane_fifo(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); + DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", plane, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), @@ -1159,12 +1098,18 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), FLD_VAL(high, hi_start, hi_end) | FLD_VAL(low, lo_start, lo_end)); + + enable_clocks(0); } void dispc_enable_fifomerge(bool enable) { + enable_clocks(1); + DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); + + enable_clocks(0); } static void _dispc_set_fir(enum omap_plane plane, @@ -1784,7 +1729,14 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, return dispc_pclk_rate(channel) * vf * hf; } -int dispc_setup_plane(enum omap_plane plane, +void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) +{ + enable_clocks(1); + _dispc_set_channel_out(plane, channel_out); + enable_clocks(0); +} + +static int _dispc_setup_plane(enum omap_plane plane, u32 paddr, u16 screen_width, u16 pos_x, u16 pos_y, u16 width, u16 height, @@ -1792,7 +1744,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_color_mode color_mode, bool ilace, enum omap_dss_rotation_type rotation_type, - u8 rotation, bool mirror, + u8 rotation, int mirror, u8 global_alpha, u8 pre_mult_alpha, enum omap_channel channel, u32 puv_addr) { @@ -1806,14 +1758,6 @@ int dispc_setup_plane(enum omap_plane plane, u16 frame_height = height; unsigned int field_offset = 0; - DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " - "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", - plane, paddr, screen_width, pos_x, pos_y, - width, height, - out_width, out_height, - ilace, color_mode, - rotation, mirror, channel); - if (paddr == 0) return -EINVAL; @@ -1959,13 +1903,9 @@ int dispc_setup_plane(enum omap_plane plane, return 0; } -int dispc_enable_plane(enum omap_plane plane, bool enable) +static void _dispc_enable_plane(enum omap_plane plane, bool enable) { - DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); - - return 0; } static void dispc_disable_isr(void *data, u32 mask) @@ -1989,6 +1929,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) int r; u32 irq; + enable_clocks(1); + /* When we disable LCD output, we need to wait until frame is done. * Otherwise the DSS is still working, and turning off the clocks * prevents DSS from going to OFF mode */ @@ -2022,6 +1964,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) if (r) DSSERR("failed to unregister FRAMEDONE isr\n"); } + + enable_clocks(0); } static void _enable_digit_out(bool enable) @@ -2034,8 +1978,12 @@ static void dispc_enable_digit_out(bool enable) struct completion frame_done_completion; int r; - if (REG_GET(DISPC_CONTROL, 1, 1) == enable) + enable_clocks(1); + + if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { + enable_clocks(0); return; + } if (enable) { unsigned long flags; @@ -2087,6 +2035,8 @@ static void dispc_enable_digit_out(bool enable) _omap_dispc_set_irqs(); spin_unlock_irqrestore(&dispc.irq_lock, flags); } + + enable_clocks(0); } bool dispc_is_channel_enabled(enum omap_channel channel) @@ -2117,7 +2067,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high) if (!dss_has_feature(FEAT_LCDENABLEPOL)) return; + enable_clocks(1); REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); + enable_clocks(0); } void dispc_lcd_enable_signal(bool enable) @@ -2125,7 +2077,9 @@ void dispc_lcd_enable_signal(bool enable) if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) return; + enable_clocks(1); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); + enable_clocks(0); } void dispc_pck_free_enable(bool enable) @@ -2133,15 +2087,19 @@ void dispc_pck_free_enable(bool enable) if (!dss_has_feature(FEAT_PCKFREEENABLE)) return; + enable_clocks(1); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); + enable_clocks(0); } void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) { + enable_clocks(1); 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); } @@ -2164,21 +2122,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel, return; } + enable_clocks(1); 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); } void dispc_set_loadmode(enum omap_dss_load_mode mode) { + enable_clocks(1); REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); + enable_clocks(0); } void dispc_set_default_color(enum omap_channel channel, u32 color) { + enable_clocks(1); dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); + enable_clocks(0); } u32 dispc_get_default_color(enum omap_channel channel) @@ -2189,7 +2153,9 @@ u32 dispc_get_default_color(enum omap_channel channel) channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2); + enable_clocks(1); l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); + enable_clocks(0); return l; } @@ -2198,6 +2164,7 @@ void dispc_set_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type type, u32 trans_key) { + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2206,12 +2173,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); } void dispc_get_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type *type, u32 *trans_key) { + enable_clocks(1); if (type) { if (ch == OMAP_DSS_CHANNEL_LCD) *type = REG_GET(DISPC_CONFIG, 11, 11); @@ -2225,28 +2194,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); } void dispc_enable_trans_key(enum omap_channel ch, bool enable) { + enable_clocks(1); 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); } void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) { if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) return; + enable_clocks(1); 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); } bool dispc_alpha_blending_enabled(enum omap_channel ch) { @@ -2255,6 +2229,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) return false; + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) enabled = REG_GET(DISPC_CONFIG, 18, 18); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2263,6 +2238,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) enabled = REG_GET(DISPC_CONFIG2, 18, 18); else BUG(); + enable_clocks(0); return enabled; } @@ -2272,6 +2248,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) { bool enabled; + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) enabled = REG_GET(DISPC_CONFIG, 10, 10); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2280,6 +2257,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) enabled = REG_GET(DISPC_CONFIG2, 10, 10); else BUG(); + enable_clocks(0); return enabled; } @@ -2307,10 +2285,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) return; } + enable_clocks(1); 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); } void dispc_set_parallel_interface_mode(enum omap_channel channel, @@ -2342,6 +2322,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel, return; } + enable_clocks(1); + if (channel == OMAP_DSS_CHANNEL_LCD2) { l = dispc_read_reg(DISPC_CONTROL2); l = FLD_MOD(l, stallmode, 11, 11); @@ -2353,6 +2335,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel, l = FLD_MOD(l, gpout1, 16, 16); dispc_write_reg(DISPC_CONTROL, l); } + + enable_clocks(0); } static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, @@ -2405,8 +2389,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, FLD_VAL(vbp, 31, 20); } + enable_clocks(1); dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); + enable_clocks(0); } /* change name to mode? */ @@ -2449,8 +2435,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_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); + enable_clocks(0); } static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, @@ -2469,7 +2457,7 @@ unsigned long dispc_fclk_rate(void) switch (dss_get_dispc_clk_source()) { case OMAP_DSS_CLK_SRC_FCK: - r = clk_get_rate(dispc.dss_clk); + r = dss_clk_get_rate(DSS_CLK_FCK); break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: dsidev = dsi_get_dsidev_from_id(0); @@ -2499,7 +2487,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) switch (dss_get_lcd_clk_source(channel)) { case OMAP_DSS_CLK_SRC_FCK: - r = clk_get_rate(dispc.dss_clk); + r = dss_clk_get_rate(DSS_CLK_FCK); break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: dsidev = dsi_get_dsidev_from_id(0); @@ -2538,8 +2526,7 @@ 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; - if (dispc_runtime_get()) - return; + enable_clocks(1); seq_printf(s, "- DISPC -\n"); @@ -2587,8 +2574,7 @@ 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); } - - dispc_runtime_put(); + enable_clocks(0); } #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -2643,8 +2629,7 @@ void dispc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) - if (dispc_runtime_get()) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DISPC_REVISION); DUMPREG(DISPC_SYSCONFIG); @@ -2664,8 +2649,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_GLOBAL_ALPHA)) - DUMPREG(DISPC_GLOBAL_ALPHA); + DUMPREG(DISPC_GLOBAL_ALPHA); DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -2696,25 +2680,20 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_CPR)) { - DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); - } + DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); - if (dss_has_feature(FEAT_CPR)) { - DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); - DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - } + DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); + DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); } - if (dss_has_feature(FEAT_PRELOAD)) - DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); + DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); @@ -2765,16 +2744,14 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); - } + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -2835,17 +2812,14 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); - - if (dss_has_feature(FEAT_FIR_COEF_V)) { - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); - } + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -2884,12 +2858,10 @@ void dispc_dump_regs(struct seq_file *s) if (dss_has_feature(FEAT_ATTR2)) DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - if (dss_has_feature(FEAT_PRELOAD)) { - DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); - DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); - } + DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); + DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); - dispc_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -2910,7 +2882,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_write_reg(DISPC_POL_FREQ(channel), l); + enable_clocks(0); } void dispc_set_pol_freq(enum omap_channel channel, @@ -3031,11 +3005,15 @@ static void _omap_dispc_set_irqs(void) mask |= isr_data->mask; } + enable_clocks(1); + old_mask = dispc_read_reg(DISPC_IRQENABLE); /* clear the irqstatus for newly enabled irqs */ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); dispc_write_reg(DISPC_IRQENABLE, mask); + + enable_clocks(0); } int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) @@ -3544,6 +3522,13 @@ 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); @@ -3569,25 +3554,67 @@ static void _omap_dispc_initial_config(void) dispc_read_plane_fifo_sizes(); } +int dispc_enable_plane(enum omap_plane plane, bool enable) +{ + DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); + + enable_clocks(1); + _dispc_enable_plane(plane, enable); + enable_clocks(0); + + return 0; +} + +int dispc_setup_plane(enum omap_plane plane, + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, + u16 width, u16 height, + u16 out_width, u16 out_height, + enum omap_color_mode color_mode, + bool ilace, + enum omap_dss_rotation_type rotation_type, + u8 rotation, bool mirror, u8 global_alpha, + u8 pre_mult_alpha, enum omap_channel channel, + u32 puv_addr) +{ + int r = 0; + + DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> " + "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", + plane, paddr, screen_width, pos_x, pos_y, + width, height, + out_width, out_height, + ilace, color_mode, + rotation, mirror, channel); + + enable_clocks(1); + + r = _dispc_setup_plane(plane, + paddr, screen_width, + pos_x, pos_y, + width, height, + out_width, out_height, + color_mode, ilace, + rotation_type, + rotation, mirror, + global_alpha, + pre_mult_alpha, + channel, puv_addr); + + enable_clocks(0); + + return r; +} + /* DISPC HW IP initialisation */ 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, "dss_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get dss_clk\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 @@ -3601,103 +3628,62 @@ static int omap_dispchw_probe(struct platform_device *pdev) if (!dispc_mem) { DSSERR("can't get IORESOURCE_MEM DISPC\n"); r = -EINVAL; - goto err_ioremap; + goto fail0; } dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); if (!dispc.base) { DSSERR("can't ioremap DISPC\n"); r = -ENOMEM; - goto err_ioremap; + goto fail0; } dispc.irq = platform_get_irq(dispc.pdev, 0); if (dispc.irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto err_irq; + goto fail1; } r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, "OMAP DISPC", dispc.pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto err_irq; + goto fail1; } - pm_runtime_enable(&pdev->dev); - - r = dispc_runtime_get(); - if (r) - goto err_runtime_get; + enable_clocks(1); _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)); - dispc_runtime_put(); + enable_clocks(0); return 0; - -err_runtime_get: - pm_runtime_disable(&pdev->dev); - free_irq(dispc.irq, dispc.pdev); -err_irq: +fail1: iounmap(dispc.base); -err_ioremap: - clk_put(dispc.dss_clk); -err_get_clk: +fail0: 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); - 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, }, }; |