diff options
Diffstat (limited to 'drivers/video/omap2/dss/dispc.c')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 66 |
1 files changed, 46 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 | ||
1674 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 1686 | 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 | { | 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; |