diff options
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 110 |
1 files changed, 64 insertions, 46 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9c23ce8..d655689 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -86,13 +86,13 @@ struct dispc_features { u16 sw_max; u16 vp_max; u16 hp_max; - int (*calc_scaling) (enum omap_channel channel, + int (*calc_scaling) (enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, u16 pos_x, unsigned long *core_clk); - unsigned long (*calc_core_clk) (enum omap_channel channel, + unsigned long (*calc_core_clk) (enum omap_plane plane, u16 width, u16 height, u16 out_width, u16 out_height); u8 num_fifos; @@ -236,6 +236,8 @@ static const struct { }; static void _omap_dispc_set_irqs(void); +static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); +static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); static inline void dispc_write_reg(const u16 idx, u32 val) { @@ -1919,22 +1921,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width, * This function is used to avoid synclosts in OMAP3, because of some * undocumented horizontal position and timing related limitations. */ -static int check_horiz_timing_omap3(enum omap_channel channel, +static int check_horiz_timing_omap3(enum omap_plane plane, const struct omap_video_timings *t, u16 pos_x, u16 width, u16 height, u16 out_width, u16 out_height) { int DS = DIV_ROUND_UP(height, out_height); - unsigned long nonactive, lclk, pclk; + unsigned long nonactive; static const u8 limits[3] = { 8, 10, 20 }; u64 val, blank; + unsigned long pclk = dispc_plane_pclk_rate(plane); + unsigned long lclk = dispc_plane_lclk_rate(plane); int i; nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; - pclk = dispc_mgr_pclk_rate(channel); - if (dss_mgr_is_lcd(channel)) - lclk = dispc_mgr_lclk_rate(channel); - else - lclk = dispc_fclk_rate(); i = 0; if (out_height < height) @@ -1971,13 +1970,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel, return 0; } -static unsigned long calc_core_clk_five_taps(enum omap_channel channel, +static unsigned long calc_core_clk_five_taps(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode) { u32 core_clk = 0; - u64 tmp, pclk = dispc_mgr_pclk_rate(channel); + u64 tmp; + unsigned long pclk = dispc_plane_pclk_rate(plane); if (height <= out_height && width <= out_width) return (unsigned long) pclk; @@ -2011,10 +2011,10 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel, return core_clk; } -static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, +static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, u16 height, u16 out_width, u16 out_height) { - unsigned long pclk = dispc_mgr_pclk_rate(channel); + unsigned long pclk = dispc_plane_pclk_rate(plane); if (height > out_height && width > out_width) return pclk * 4; @@ -2022,11 +2022,11 @@ static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, return pclk * 2; } -static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, +static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, u16 height, u16 out_width, u16 out_height) { unsigned int hf, vf; - unsigned long pclk = dispc_mgr_pclk_rate(channel); + unsigned long pclk = dispc_plane_pclk_rate(plane); /* * FIXME how to determine the 'A' factor @@ -2049,10 +2049,10 @@ static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, return pclk * vf * hf; } -static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, +static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, u16 height, u16 out_width, u16 out_height) { - unsigned long pclk = dispc_mgr_pclk_rate(channel); + unsigned long pclk = dispc_plane_pclk_rate(plane); if (width > out_width) return DIV_ROUND_UP(pclk, out_width) * width; @@ -2060,7 +2060,7 @@ static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, return pclk; } -static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, +static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, @@ -2072,12 +2072,13 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, int min_factor = min(*decim_x, *decim_y); const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + *five_taps = false; do { in_height = DIV_ROUND_UP(height, *decim_y); in_width = DIV_ROUND_UP(width, *decim_x); - *core_clk = dispc.feat->calc_core_clk(channel, in_width, + *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, out_width, out_height); error = (in_width > maxsinglelinewidth || !*core_clk || *core_clk > dispc_core_clk_rate()); @@ -2100,7 +2101,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, return 0; } -static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, +static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, @@ -2116,18 +2117,19 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, do { in_height = DIV_ROUND_UP(height, *decim_y); in_width = DIV_ROUND_UP(width, *decim_x); - *core_clk = calc_core_clk_five_taps(channel, mgr_timings, + *core_clk = calc_core_clk_five_taps(plane, mgr_timings, in_width, in_height, out_width, out_height, color_mode); - error = check_horiz_timing_omap3(channel, mgr_timings, pos_x, - in_width, in_height, out_width, out_height); + error = check_horiz_timing_omap3(plane, mgr_timings, + pos_x, in_width, in_height, out_width, + out_height); if (in_width > maxsinglelinewidth) if (in_height > out_height && in_height < out_height * 2) *five_taps = false; if (!*five_taps) - *core_clk = dispc.feat->calc_core_clk(channel, in_width, + *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, out_width, out_height); error = (error || in_width > maxsinglelinewidth * 2 || @@ -2145,7 +2147,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, } } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); - if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height, + if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height, out_width, out_height)){ DSSERR("horizontal timing too tight\n"); return -EINVAL; @@ -2164,7 +2166,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, return 0; } -static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, +static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, @@ -2176,9 +2178,10 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, u16 in_height = DIV_ROUND_UP(height, *decim_y); const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + unsigned long pclk = dispc_plane_pclk_rate(plane); + + in_width_max = dispc_core_clk_rate() / DIV_ROUND_UP(pclk, out_width); - in_width_max = dispc_core_clk_rate() / - DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width); *decim_x = DIV_ROUND_UP(width, in_width_max); *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; @@ -2195,13 +2198,13 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, return -EINVAL; } - *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height, + *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, out_width, out_height); return 0; } static int dispc_ovl_calc_scaling(enum omap_plane plane, - enum omap_overlay_caps caps, enum omap_channel channel, + enum omap_overlay_caps caps, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, @@ -2242,9 +2245,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, if (decim_y > *y_predecim || out_height > height * 8) return -EINVAL; - ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height, - out_width, out_height, color_mode, five_taps, x_predecim, - y_predecim, &decim_x, &decim_y, pos_x, &core_clk); + ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height, + out_width, out_height, color_mode, five_taps, + x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk); if (ret) return ret; @@ -2265,12 +2268,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, } static int dispc_ovl_setup_common(enum omap_plane plane, - enum omap_channel channel, enum omap_overlay_caps caps, - u32 paddr, u32 p_uv_addr, u16 screen_width, int pos_x, - int pos_y, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode, u8 rotation, bool mirror, - u8 zorder, u8 pre_mult_alpha, u8 global_alpha, - enum omap_dss_rotation_type rotation_type, + enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, + u16 screen_width, int pos_x, int pos_y, u16 width, u16 height, + u16 out_width, u16 out_height, enum omap_color_mode color_mode, + u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha, + u8 global_alpha, enum omap_dss_rotation_type rotation_type, bool replication, const struct omap_video_timings *mgr_timings) { bool five_taps = true; @@ -2309,7 +2311,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, if (!dss_feat_color_mode_supported(plane, color_mode)) return -EINVAL; - r = dispc_ovl_calc_scaling(plane, caps, channel, mgr_timings, in_width, + r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width, in_height, out_width, out_height, color_mode, &five_taps, &x_predecim, &y_predecim, pos_x, rotation_type); @@ -2424,12 +2426,11 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, oi->color_mode, oi->rotation, oi->mirror, channel, replication); - r = dispc_ovl_setup_common(plane, channel, ovl->caps, oi->paddr, - oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y, - oi->width, oi->height, oi->out_width, oi->out_height, - oi->color_mode, oi->rotation, oi->mirror, oi->zorder, - oi->pre_mult_alpha, oi->global_alpha, oi->rotation_type, - replication, mgr_timings); + r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr, + oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, + oi->out_width, oi->out_height, oi->color_mode, oi->rotation, + oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, + oi->rotation_type, replication, mgr_timings); return r; } @@ -2989,6 +2990,23 @@ unsigned long dispc_core_clk_rate(void) return fclk / lcd; } +static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) +{ + enum omap_channel channel = dispc_ovl_get_channel_out(plane); + + return dispc_mgr_pclk_rate(channel); +} + +static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) +{ + enum omap_channel channel = dispc_ovl_get_channel_out(plane); + + if (dss_mgr_is_lcd(channel)) + return dispc_mgr_lclk_rate(channel); + else + return dispc_fclk_rate(); + +} static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) { int lcd, pcd; |