diff options
Diffstat (limited to 'drivers/video/omap2/dss/dispc.c')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 131 |
1 files changed, 73 insertions, 58 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 829be3bbafcc..68a11e382f3a 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -1686,14 +1686,74 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, | |||
1686 | return dispc_mgr_pclk_rate(channel) * vf * hf; | 1686 | return dispc_mgr_pclk_rate(channel) * vf * hf; |
1687 | } | 1687 | } |
1688 | 1688 | ||
1689 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | ||
1690 | enum omap_channel channel, u16 width, u16 height, | ||
1691 | u16 out_width, u16 out_height, | ||
1692 | enum omap_color_mode color_mode, bool *five_taps) | ||
1693 | { | ||
1694 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | ||
1695 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | ||
1696 | unsigned long fclk = 0; | ||
1697 | |||
1698 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { | ||
1699 | if (width != out_width || height != out_height) | ||
1700 | return -EINVAL; | ||
1701 | else | ||
1702 | return 0; | ||
1703 | } | ||
1704 | |||
1705 | if (out_width < width / maxdownscale || | ||
1706 | out_width > width * 8) | ||
1707 | return -EINVAL; | ||
1708 | |||
1709 | if (out_height < height / maxdownscale || | ||
1710 | out_height > height * 8) | ||
1711 | return -EINVAL; | ||
1712 | |||
1713 | /* Must use 5-tap filter? */ | ||
1714 | *five_taps = height > out_height * 2; | ||
1715 | |||
1716 | if (!*five_taps) { | ||
1717 | fclk = calc_fclk(channel, width, height, out_width, | ||
1718 | out_height); | ||
1719 | |||
1720 | /* Try 5-tap filter if 3-tap fclk is too high */ | ||
1721 | if (cpu_is_omap34xx() && height > out_height && | ||
1722 | fclk > dispc_fclk_rate()) | ||
1723 | *five_taps = true; | ||
1724 | } | ||
1725 | |||
1726 | if (width > (2048 >> *five_taps)) { | ||
1727 | DSSERR("failed to set up scaling, fclk too low\n"); | ||
1728 | return -EINVAL; | ||
1729 | } | ||
1730 | |||
1731 | if (*five_taps) | ||
1732 | fclk = calc_fclk_five_taps(channel, width, height, | ||
1733 | out_width, out_height, color_mode); | ||
1734 | |||
1735 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | ||
1736 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | ||
1737 | |||
1738 | if (!fclk || fclk > dispc_fclk_rate()) { | ||
1739 | DSSERR("failed to set up scaling, " | ||
1740 | "required fclk rate = %lu Hz, " | ||
1741 | "current fclk rate = %lu Hz\n", | ||
1742 | fclk, dispc_fclk_rate()); | ||
1743 | return -EINVAL; | ||
1744 | } | ||
1745 | |||
1746 | return 0; | ||
1747 | } | ||
1748 | |||
1689 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | 1749 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, |
1690 | bool ilace, enum omap_channel channel, bool replication, | 1750 | bool ilace, enum omap_channel channel, bool replication, |
1691 | u32 fifo_low, u32 fifo_high) | 1751 | u32 fifo_low, u32 fifo_high) |
1692 | { | 1752 | { |
1693 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | 1753 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
1694 | bool five_taps = 0; | 1754 | bool five_taps = false; |
1695 | bool fieldmode = 0; | 1755 | bool fieldmode = 0; |
1696 | int cconv = 0; | 1756 | int r, cconv = 0; |
1697 | unsigned offset0, offset1; | 1757 | unsigned offset0, offset1; |
1698 | s32 row_inc; | 1758 | s32 row_inc; |
1699 | s32 pix_inc; | 1759 | s32 pix_inc; |
@@ -1727,61 +1787,16 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
1727 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) | 1787 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) |
1728 | return -EINVAL; | 1788 | return -EINVAL; |
1729 | 1789 | ||
1730 | if (plane == OMAP_DSS_GFX) { | 1790 | r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, |
1731 | if (oi->width != oi->out_width || oi->height != oi->out_height) | 1791 | oi->out_width, oi->out_height, oi->color_mode, |
1732 | return -EINVAL; | 1792 | &five_taps); |
1733 | } else { | 1793 | if (r) |
1734 | /* video plane */ | 1794 | return r; |
1735 | |||
1736 | unsigned long fclk = 0; | ||
1737 | |||
1738 | if (oi->out_width < oi->width / maxdownscale || | ||
1739 | oi->out_width > oi->width * 8) | ||
1740 | return -EINVAL; | ||
1741 | |||
1742 | if (oi->out_height < oi->height / maxdownscale || | ||
1743 | oi->out_height > oi->height * 8) | ||
1744 | return -EINVAL; | ||
1745 | |||
1746 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || | ||
1747 | oi->color_mode == OMAP_DSS_COLOR_UYVY || | ||
1748 | oi->color_mode == OMAP_DSS_COLOR_NV12) | ||
1749 | cconv = 1; | ||
1750 | |||
1751 | /* Must use 5-tap filter? */ | ||
1752 | five_taps = oi->height > oi->out_height * 2; | ||
1753 | |||
1754 | if (!five_taps) { | ||
1755 | fclk = calc_fclk(channel, oi->width, oi->height, | ||
1756 | oi->out_width, oi->out_height); | ||
1757 | |||
1758 | /* Try 5-tap filter if 3-tap fclk is too high */ | ||
1759 | if (cpu_is_omap34xx() && oi->height > oi->out_height && | ||
1760 | fclk > dispc_fclk_rate()) | ||
1761 | five_taps = true; | ||
1762 | } | ||
1763 | |||
1764 | if (oi->width > (2048 >> five_taps)) { | ||
1765 | DSSERR("failed to set up scaling, fclk too low\n"); | ||
1766 | return -EINVAL; | ||
1767 | } | ||
1768 | |||
1769 | if (five_taps) | ||
1770 | fclk = calc_fclk_five_taps(channel, oi->width, | ||
1771 | oi->height, oi->out_width, | ||
1772 | oi->out_height, oi->color_mode); | ||
1773 | |||
1774 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | ||
1775 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | ||
1776 | 1795 | ||
1777 | if (!fclk || fclk > dispc_fclk_rate()) { | 1796 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || |
1778 | DSSERR("failed to set up scaling, " | 1797 | oi->color_mode == OMAP_DSS_COLOR_UYVY || |
1779 | "required fclk rate = %lu Hz, " | 1798 | oi->color_mode == OMAP_DSS_COLOR_NV12) |
1780 | "current fclk rate = %lu Hz\n", | 1799 | cconv = 1; |
1781 | fclk, dispc_fclk_rate()); | ||
1782 | return -EINVAL; | ||
1783 | } | ||
1784 | } | ||
1785 | 1800 | ||
1786 | if (ilace && !fieldmode) { | 1801 | if (ilace && !fieldmode) { |
1787 | /* | 1802 | /* |
@@ -1836,7 +1851,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | |||
1836 | 1851 | ||
1837 | dispc_ovl_set_pic_size(plane, oi->width, oi->height); | 1852 | dispc_ovl_set_pic_size(plane, oi->width, oi->height); |
1838 | 1853 | ||
1839 | if (plane != OMAP_DSS_GFX) { | 1854 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { |
1840 | dispc_ovl_set_scaling(plane, oi->width, oi->height, | 1855 | dispc_ovl_set_scaling(plane, oi->width, oi->height, |
1841 | oi->out_width, oi->out_height, | 1856 | oi->out_width, oi->out_height, |
1842 | ilace, five_taps, fieldmode, | 1857 | ilace, five_taps, fieldmode, |