diff options
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 66 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.c | 7 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.h | 1 |
3 files changed, 54 insertions, 20 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 78e51d953629..a5ec7f37c185 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1614,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, u32 fclk = 0; u64 tmp, pclk = dispc_mgr_pclk_rate(channel); + if (height <= out_height && width <= out_width) + return (unsigned long) pclk; + if (height > out_height) { struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); unsigned int ppl = dssdev->panel.timings.x_res; @@ -1668,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, else vf = 1; - return dispc_mgr_pclk_rate(channel) * vf * hf; + if (cpu_is_omap24xx()) { + if (vf > 1 && hf > 1) + return dispc_mgr_pclk_rate(channel) * 4; + else + return dispc_mgr_pclk_rate(channel) * 2; + } else if (cpu_is_omap34xx()) { + return dispc_mgr_pclk_rate(channel) * vf * hf; + } else { + return dispc_mgr_pclk_rate(channel) * hf; + } } static int dispc_ovl_calc_scaling(enum omap_plane plane, @@ -1678,6 +1690,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, { struct omap_overlay *ovl = omap_dss_get_overlay(plane); const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + const int maxsinglelinewidth = + dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); unsigned long fclk = 0; if (width == out_width && height == out_height) @@ -1694,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, out_height > height * 8) return -EINVAL; - /* Must use 5-tap filter? */ - *five_taps = height > out_height * 2; - - if (!*five_taps) { + if (cpu_is_omap24xx()) { + if (width > maxsinglelinewidth) + DSSERR("Cannot scale max input width exceeded"); + *five_taps = false; + fclk = calc_fclk(channel, width, height, out_width, + out_height); + } else if (cpu_is_omap34xx()) { + if (width > (maxsinglelinewidth * 2)) { + DSSERR("Cannot setup scaling"); + DSSERR("width exceeds maximum width possible"); + return -EINVAL; + } + fclk = calc_fclk_five_taps(channel, width, height, out_width, + out_height, color_mode); + if (width > maxsinglelinewidth) { + if (height > out_height && height < out_height * 2) + *five_taps = false; + else { + DSSERR("cannot setup scaling with five taps"); + return -EINVAL; + } + } + if (!*five_taps) + fclk = calc_fclk(channel, width, height, out_width, + out_height); + } else { + if (width > maxsinglelinewidth) { + DSSERR("Cannot scale width exceeds max line width"); + return -EINVAL; + } fclk = calc_fclk(channel, width, height, out_width, out_height); - - /* Try 5-tap filter if 3-tap fclk is too high */ - if (cpu_is_omap34xx() && height > out_height && - fclk > dispc_fclk_rate()) - *five_taps = true; } - if (width > (2048 >> *five_taps)) { - DSSERR("failed to set up scaling, fclk too low\n"); - return -EINVAL; - } - - if (*five_taps) - fclk = calc_fclk_five_taps(channel, width, height, - out_width, out_height, color_mode); - DSSDBG("required fclk rate = %lu Hz\n", fclk); DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); @@ -1734,7 +1760,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, bool ilace, bool replication) { struct omap_overlay *ovl = omap_dss_get_overlay(plane); - bool five_taps = false; + bool five_taps = true; bool fieldmode = 0; int r, cconv = 0; unsigned offset0, offset1; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index b402699168a5..5e4b829605da 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = { [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, + /* + * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC + * scaler cannot scale a image with width more than 768. + */ + [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, }; static const struct dss_param_range omap3_dss_param_range[] = { @@ -316,6 +321,7 @@ static const struct dss_param_range omap3_dss_param_range[] = { [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, + [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, }; static const struct dss_param_range omap4_dss_param_range[] = { @@ -328,6 +334,7 @@ static const struct dss_param_range omap4_dss_param_range[] = { [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, + [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, }; /* OMAP2 DSS Features */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 6a6c05dd45ce..cd833bbaac3d 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -86,6 +86,7 @@ enum dss_range_param { FEAT_PARAM_DSIPLL_FINT, FEAT_PARAM_DSIPLL_LPDIV, FEAT_PARAM_DOWNSCALE, + FEAT_PARAM_LINEWIDTH, }; /* DSS Feature Functions */ |