aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
authorChandrabhanu Mahapatra <cmahapatra@ti.com>2011-12-19 03:33:56 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-01-02 01:51:29 -0500
commit7282f1b7c9b5210114ce1ebb0ea5fe8a63fd5778 (patch)
treebb5dc70dcd6789d22953c45742662edb0422b01f /drivers/video/omap2
parentdebd90749b7440ad5fc02e4f0d1e8a696385f196 (diff)
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: Chandrabhanu Mahapatra <cmahapatra@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/dss/dispc.c66
-rw-r--r--drivers/video/omap2/dss/dss_features.c7
-rw-r--r--drivers/video/omap2/dss/dss_features.h1
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,
1614 u32 fclk = 0; 1614 u32 fclk = 0;
1615 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 1615 u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
1616 1616
1617 if (height <= out_height && width <= out_width)
1618 return (unsigned long) pclk;
1619
1617 if (height > out_height) { 1620 if (height > out_height) {
1618 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); 1621 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
1619 unsigned int ppl = dssdev->panel.timings.x_res; 1622 unsigned int ppl = dssdev->panel.timings.x_res;
@@ -1668,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1668 else 1671 else
1669 vf = 1; 1672 vf = 1;
1670 1673
1671 return dispc_mgr_pclk_rate(channel) * vf * hf; 1674 if (cpu_is_omap24xx()) {
1675 if (vf > 1 && hf > 1)
1676 return dispc_mgr_pclk_rate(channel) * 4;
1677 else
1678 return dispc_mgr_pclk_rate(channel) * 2;
1679 } else if (cpu_is_omap34xx()) {
1680 return dispc_mgr_pclk_rate(channel) * vf * hf;
1681 } else {
1682 return dispc_mgr_pclk_rate(channel) * hf;
1683 }
1672} 1684}
1673 1685
1674static int dispc_ovl_calc_scaling(enum omap_plane plane, 1686static int dispc_ovl_calc_scaling(enum omap_plane plane,
@@ -1678,6 +1690,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1678{ 1690{
1679 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1691 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1680 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 1692 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1693 const int maxsinglelinewidth =
1694 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
1681 unsigned long fclk = 0; 1695 unsigned long fclk = 0;
1682 1696
1683 if (width == out_width && height == out_height) 1697 if (width == out_width && height == out_height)
@@ -1694,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1694 out_height > height * 8) 1708 out_height > height * 8)
1695 return -EINVAL; 1709 return -EINVAL;
1696 1710
1697 /* Must use 5-tap filter? */ 1711 if (cpu_is_omap24xx()) {
1698 *five_taps = height > out_height * 2; 1712 if (width > maxsinglelinewidth)
1699 1713 DSSERR("Cannot scale max input width exceeded");
1700 if (!*five_taps) { 1714 *five_taps = false;
1715 fclk = calc_fclk(channel, width, height, out_width,
1716 out_height);
1717 } else if (cpu_is_omap34xx()) {
1718 if (width > (maxsinglelinewidth * 2)) {
1719 DSSERR("Cannot setup scaling");
1720 DSSERR("width exceeds maximum width possible");
1721 return -EINVAL;
1722 }
1723 fclk = calc_fclk_five_taps(channel, width, height, out_width,
1724 out_height, color_mode);
1725 if (width > maxsinglelinewidth) {
1726 if (height > out_height && height < out_height * 2)
1727 *five_taps = false;
1728 else {
1729 DSSERR("cannot setup scaling with five taps");
1730 return -EINVAL;
1731 }
1732 }
1733 if (!*five_taps)
1734 fclk = calc_fclk(channel, width, height, out_width,
1735 out_height);
1736 } else {
1737 if (width > maxsinglelinewidth) {
1738 DSSERR("Cannot scale width exceeds max line width");
1739 return -EINVAL;
1740 }
1701 fclk = calc_fclk(channel, width, height, out_width, 1741 fclk = calc_fclk(channel, width, height, out_width,
1702 out_height); 1742 out_height);
1703
1704 /* Try 5-tap filter if 3-tap fclk is too high */
1705 if (cpu_is_omap34xx() && height > out_height &&
1706 fclk > dispc_fclk_rate())
1707 *five_taps = true;
1708 } 1743 }
1709 1744
1710 if (width > (2048 >> *five_taps)) {
1711 DSSERR("failed to set up scaling, fclk too low\n");
1712 return -EINVAL;
1713 }
1714
1715 if (*five_taps)
1716 fclk = calc_fclk_five_taps(channel, width, height,
1717 out_width, out_height, color_mode);
1718
1719 DSSDBG("required fclk rate = %lu Hz\n", fclk); 1745 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1720 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); 1746 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1721 1747
@@ -1734,7 +1760,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1734 bool ilace, bool replication) 1760 bool ilace, bool replication)
1735{ 1761{
1736 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1762 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1737 bool five_taps = false; 1763 bool five_taps = true;
1738 bool fieldmode = 0; 1764 bool fieldmode = 0;
1739 int r, cconv = 0; 1765 int r, cconv = 0;
1740 unsigned offset0, offset1; 1766 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[] = {
304 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, 304 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
305 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, 305 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
306 [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, 306 [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
307 /*
308 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
309 * scaler cannot scale a image with width more than 768.
310 */
311 [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
307}; 312};
308 313
309static const struct dss_param_range omap3_dss_param_range[] = { 314static const struct dss_param_range omap3_dss_param_range[] = {
@@ -316,6 +321,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
316 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 321 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
317 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 322 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
318 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 323 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
324 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
319}; 325};
320 326
321static const struct dss_param_range omap4_dss_param_range[] = { 327static const struct dss_param_range omap4_dss_param_range[] = {
@@ -328,6 +334,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
328 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 334 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
329 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 335 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
330 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 336 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
337 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
331}; 338};
332 339
333/* OMAP2 DSS Features */ 340/* 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 {
86 FEAT_PARAM_DSIPLL_FINT, 86 FEAT_PARAM_DSIPLL_FINT,
87 FEAT_PARAM_DSIPLL_LPDIV, 87 FEAT_PARAM_DSIPLL_LPDIV,
88 FEAT_PARAM_DOWNSCALE, 88 FEAT_PARAM_DOWNSCALE,
89 FEAT_PARAM_LINEWIDTH,
89}; 90};
90 91
91/* DSS Feature Functions */ 92/* DSS Feature Functions */