Commit 7282f1b7 authored by Chandrabhanu Mahapatra's avatar Chandrabhanu Mahapatra Committed by Tomi Valkeinen

OMAPDSS: DISPC: Update Scaling Clock Logic

Clock requirements for scaling in OMAP2, OMAP3 and OMAP4 are different. In
OMAP2 and OMAP3 the required clock rate is a function of pixel clock, vertical
downscale ratio and horizontal downscale ratio whereas in OMAP4 it is a
function of pixel clock and horizontal downscale ratio only. Selection of 3-tap
vs 5-tap coefficients depends on clock rate line buffer width in OMAP3 whereas
in OMAP4 it is independent of clock rate and line buffer width. In OMAP2 3-tap
for vertical and 5-tap for horizontal scaling is used. In OMAP4 5-tap is used
both for horizontal and vertical scaling for better performance. Also, the
number and width of line buffers differs in OMAP3 and OMAP4.

So, clock functions have been fined tuned for OMAP3 and support has been added
added for OMAP4. This code has been tested on OMAP2, OMAP3 and OMAP4, and
scaling issues due to clock errors have been resolved.
Signed-off-by: default avatarChandrabhanu Mahapatra <cmahapatra@ti.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent debd9074
...@@ -1614,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, ...@@ -1614,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
u32 fclk = 0; u32 fclk = 0;
u64 tmp, pclk = dispc_mgr_pclk_rate(channel); u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
if (height <= out_height && width <= out_width)
return (unsigned long) pclk;
if (height > out_height) { if (height > out_height) {
struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
unsigned int ppl = dssdev->panel.timings.x_res; unsigned int ppl = dssdev->panel.timings.x_res;
...@@ -1668,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, ...@@ -1668,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
else else
vf = 1; 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, static int dispc_ovl_calc_scaling(enum omap_plane plane,
...@@ -1678,6 +1690,8 @@ 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); struct omap_overlay *ovl = omap_dss_get_overlay(plane);
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 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; unsigned long fclk = 0;
if (width == out_width && height == out_height) if (width == out_width && height == out_height)
...@@ -1694,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, ...@@ -1694,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
out_height > height * 8) out_height > height * 8)
return -EINVAL; return -EINVAL;
/* Must use 5-tap filter? */ if (cpu_is_omap24xx()) {
*five_taps = height > out_height * 2; if (width > maxsinglelinewidth)
DSSERR("Cannot scale max input width exceeded");
if (!*five_taps) { *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, fclk = calc_fclk(channel, width, height, out_width,
out_height); 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("required fclk rate = %lu Hz\n", fclk);
DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); 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, ...@@ -1734,7 +1760,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
bool ilace, bool replication) bool ilace, bool replication)
{ {
struct omap_overlay *ovl = omap_dss_get_overlay(plane); struct omap_overlay *ovl = omap_dss_get_overlay(plane);
bool five_taps = false; bool five_taps = true;
bool fieldmode = 0; bool fieldmode = 0;
int r, cconv = 0; int r, cconv = 0;
unsigned offset0, offset1; unsigned offset0, offset1;
......
...@@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = { ...@@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
[FEAT_PARAM_DOWNSCALE] = { 1, 2 }, [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[] = { static const struct dss_param_range omap3_dss_param_range[] = {
...@@ -316,6 +321,7 @@ 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_FINT] = { 750000, 2100000 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
[FEAT_PARAM_DOWNSCALE] = { 1, 4 }, [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
}; };
static const struct dss_param_range omap4_dss_param_range[] = { static const struct dss_param_range omap4_dss_param_range[] = {
...@@ -328,6 +334,7 @@ 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_FINT] = { 500000, 2500000 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 }, [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
}; };
/* OMAP2 DSS Features */ /* OMAP2 DSS Features */
......
...@@ -86,6 +86,7 @@ enum dss_range_param { ...@@ -86,6 +86,7 @@ enum dss_range_param {
FEAT_PARAM_DSIPLL_FINT, FEAT_PARAM_DSIPLL_FINT,
FEAT_PARAM_DSIPLL_LPDIV, FEAT_PARAM_DSIPLL_LPDIV,
FEAT_PARAM_DOWNSCALE, FEAT_PARAM_DOWNSCALE,
FEAT_PARAM_LINEWIDTH,
}; };
/* DSS Feature Functions */ /* DSS Feature Functions */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment