aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChandrabhanu Mahapatra <cmahapatra@ti.com>2012-04-02 11:13:16 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-05-03 09:12:48 -0400
commitaed74b55004e1d6c7d445543ceed1d2f110969a1 (patch)
tree3fca3598efc38cf825505011f55ee0b791d84f14 /drivers
parent3dd606e435b36f8461d4c89227a41ac6976969c3 (diff)
OMAPDSS: DISPC: Enable predecimation
In OMAP3 and OMAP4, the DISPC Scaler can downscale an image up to 4 times, and up to 2 times in OMAP2. However, with predecimation, the image can be reduced to 16 times by fetching only the necessary pixels in memory. Then this predecimated image can be downscaled further by the DISPC scaler. The pipeline is configured to use a burst of size 8 * 128 bits which consists of 8 mini bursts of 16 bytes each. So, horizontal predecimation more than 16 can lead to complete discarding of such mini bursts. L3 interconnect may handover the bus to some other initiator and inturn delay the fetching of pixels leading to underflows. So, maximum predecimation limit is fixed at 16. Based on the downscaling required, a prior calculation of predecimation values for width and height of an image is done. Since, Predecimation reduces quality of an image higher priorty is given to DISPC Scaler for downscaling. This code was successfully tested on OMAP2, OMAP3 and OMAP4. Horizontal and vertical predecimation worked fine except for some synclost errors due to undocumented errata in OMAP3 which are fixed later and skewed images were seen on OMAP2 and OMAP3 during horizontal predecimation which will be addressed in the future patches. This code is based on code written by Lajos Molnar <lajos@ti.com> who had added predecimation support for NV12/YUV/rotated/SDMA buffers. Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/omap2/dss/dispc.c266
1 files changed, 185 insertions, 81 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 7a65eb07a2c4..8c96f5700f93 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1424,7 +1424,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1424 enum omap_color_mode color_mode, bool fieldmode, 1424 enum omap_color_mode color_mode, bool fieldmode,
1425 unsigned int field_offset, 1425 unsigned int field_offset,
1426 unsigned *offset0, unsigned *offset1, 1426 unsigned *offset0, unsigned *offset1,
1427 s32 *row_inc, s32 *pix_inc) 1427 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1428{ 1428{
1429 u8 ps; 1429 u8 ps;
1430 1430
@@ -1470,10 +1470,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1470 else 1470 else
1471 *offset0 = 0; 1471 *offset0 = 0;
1472 1472
1473 *row_inc = pixinc(1 + (screen_width - width) + 1473 *row_inc = pixinc(1 +
1474 (fieldmode ? screen_width : 0), 1474 (y_predecim * screen_width - x_predecim * width) +
1475 ps); 1475 (fieldmode ? screen_width : 0), ps);
1476 *pix_inc = pixinc(1, ps); 1476 *pix_inc = pixinc(x_predecim, ps);
1477 break; 1477 break;
1478 1478
1479 case OMAP_DSS_ROT_0 + 4: 1479 case OMAP_DSS_ROT_0 + 4:
@@ -1491,10 +1491,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1491 *offset0 = field_offset * screen_width * ps; 1491 *offset0 = field_offset * screen_width * ps;
1492 else 1492 else
1493 *offset0 = 0; 1493 *offset0 = 0;
1494 *row_inc = pixinc(1 - (screen_width + width) - 1494 *row_inc = pixinc(1 -
1495 (fieldmode ? screen_width : 0), 1495 (y_predecim * screen_width + x_predecim * width) -
1496 ps); 1496 (fieldmode ? screen_width : 0), ps);
1497 *pix_inc = pixinc(1, ps); 1497 *pix_inc = pixinc(x_predecim, ps);
1498 break; 1498 break;
1499 1499
1500 default: 1500 default:
@@ -1508,7 +1508,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1508 enum omap_color_mode color_mode, bool fieldmode, 1508 enum omap_color_mode color_mode, bool fieldmode,
1509 unsigned int field_offset, 1509 unsigned int field_offset,
1510 unsigned *offset0, unsigned *offset1, 1510 unsigned *offset0, unsigned *offset1,
1511 s32 *row_inc, s32 *pix_inc) 1511 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1512{ 1512{
1513 u8 ps; 1513 u8 ps;
1514 u16 fbw, fbh; 1514 u16 fbw, fbh;
@@ -1550,10 +1550,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1550 *offset0 = *offset1 + field_offset * screen_width * ps; 1550 *offset0 = *offset1 + field_offset * screen_width * ps;
1551 else 1551 else
1552 *offset0 = *offset1; 1552 *offset0 = *offset1;
1553 *row_inc = pixinc(1 + (screen_width - fbw) + 1553 *row_inc = pixinc(1 +
1554 (fieldmode ? screen_width : 0), 1554 (y_predecim * screen_width - fbw * x_predecim) +
1555 ps); 1555 (fieldmode ? screen_width : 0), ps);
1556 *pix_inc = pixinc(1, ps); 1556 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1557 color_mode == OMAP_DSS_COLOR_UYVY)
1558 *pix_inc = pixinc(x_predecim, 2 * ps);
1559 else
1560 *pix_inc = pixinc(x_predecim, ps);
1557 break; 1561 break;
1558 case OMAP_DSS_ROT_90: 1562 case OMAP_DSS_ROT_90:
1559 *offset1 = screen_width * (fbh - 1) * ps; 1563 *offset1 = screen_width * (fbh - 1) * ps;
@@ -1561,9 +1565,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1561 *offset0 = *offset1 + field_offset * ps; 1565 *offset0 = *offset1 + field_offset * ps;
1562 else 1566 else
1563 *offset0 = *offset1; 1567 *offset0 = *offset1;
1564 *row_inc = pixinc(screen_width * (fbh - 1) + 1 + 1568 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
1565 (fieldmode ? 1 : 0), ps); 1569 y_predecim + (fieldmode ? 1 : 0), ps);
1566 *pix_inc = pixinc(-screen_width, ps); 1570 *pix_inc = pixinc(-x_predecim * screen_width, ps);
1567 break; 1571 break;
1568 case OMAP_DSS_ROT_180: 1572 case OMAP_DSS_ROT_180:
1569 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; 1573 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
@@ -1572,10 +1576,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1572 else 1576 else
1573 *offset0 = *offset1; 1577 *offset0 = *offset1;
1574 *row_inc = pixinc(-1 - 1578 *row_inc = pixinc(-1 -
1575 (screen_width - fbw) - 1579 (y_predecim * screen_width - fbw * x_predecim) -
1576 (fieldmode ? screen_width : 0), 1580 (fieldmode ? screen_width : 0), ps);
1577 ps); 1581 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1578 *pix_inc = pixinc(-1, ps); 1582 color_mode == OMAP_DSS_COLOR_UYVY)
1583 *pix_inc = pixinc(-x_predecim, 2 * ps);
1584 else
1585 *pix_inc = pixinc(-x_predecim, ps);
1579 break; 1586 break;
1580 case OMAP_DSS_ROT_270: 1587 case OMAP_DSS_ROT_270:
1581 *offset1 = (fbw - 1) * ps; 1588 *offset1 = (fbw - 1) * ps;
@@ -1583,9 +1590,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1583 *offset0 = *offset1 - field_offset * ps; 1590 *offset0 = *offset1 - field_offset * ps;
1584 else 1591 else
1585 *offset0 = *offset1; 1592 *offset0 = *offset1;
1586 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - 1593 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
1587 (fieldmode ? 1 : 0), ps); 1594 y_predecim - (fieldmode ? 1 : 0), ps);
1588 *pix_inc = pixinc(screen_width, ps); 1595 *pix_inc = pixinc(x_predecim * screen_width, ps);
1589 break; 1596 break;
1590 1597
1591 /* mirroring */ 1598 /* mirroring */
@@ -1595,10 +1602,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1595 *offset0 = *offset1 + field_offset * screen_width * ps; 1602 *offset0 = *offset1 + field_offset * screen_width * ps;
1596 else 1603 else
1597 *offset0 = *offset1; 1604 *offset0 = *offset1;
1598 *row_inc = pixinc(screen_width * 2 - 1 + 1605 *row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
1599 (fieldmode ? screen_width : 0), 1606 (fieldmode ? screen_width : 0),
1600 ps); 1607 ps);
1601 *pix_inc = pixinc(-1, ps); 1608 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1609 color_mode == OMAP_DSS_COLOR_UYVY)
1610 *pix_inc = pixinc(-x_predecim, 2 * ps);
1611 else
1612 *pix_inc = pixinc(-x_predecim, ps);
1602 break; 1613 break;
1603 1614
1604 case OMAP_DSS_ROT_90 + 4: 1615 case OMAP_DSS_ROT_90 + 4:
@@ -1607,10 +1618,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1607 *offset0 = *offset1 + field_offset * ps; 1618 *offset0 = *offset1 + field_offset * ps;
1608 else 1619 else
1609 *offset0 = *offset1; 1620 *offset0 = *offset1;
1610 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + 1621 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
1611 (fieldmode ? 1 : 0), 1622 y_predecim + (fieldmode ? 1 : 0),
1612 ps); 1623 ps);
1613 *pix_inc = pixinc(screen_width, ps); 1624 *pix_inc = pixinc(x_predecim * screen_width, ps);
1614 break; 1625 break;
1615 1626
1616 case OMAP_DSS_ROT_180 + 4: 1627 case OMAP_DSS_ROT_180 + 4:
@@ -1619,10 +1630,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1619 *offset0 = *offset1 - field_offset * screen_width * ps; 1630 *offset0 = *offset1 - field_offset * screen_width * ps;
1620 else 1631 else
1621 *offset0 = *offset1; 1632 *offset0 = *offset1;
1622 *row_inc = pixinc(1 - screen_width * 2 - 1633 *row_inc = pixinc(1 - y_predecim * screen_width * 2 -
1623 (fieldmode ? screen_width : 0), 1634 (fieldmode ? screen_width : 0),
1624 ps); 1635 ps);
1625 *pix_inc = pixinc(1, ps); 1636 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1637 color_mode == OMAP_DSS_COLOR_UYVY)
1638 *pix_inc = pixinc(x_predecim, 2 * ps);
1639 else
1640 *pix_inc = pixinc(x_predecim, ps);
1626 break; 1641 break;
1627 1642
1628 case OMAP_DSS_ROT_270 + 4: 1643 case OMAP_DSS_ROT_270 + 4:
@@ -1631,10 +1646,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1631 *offset0 = *offset1 - field_offset * ps; 1646 *offset0 = *offset1 - field_offset * ps;
1632 else 1647 else
1633 *offset0 = *offset1; 1648 *offset0 = *offset1;
1634 *row_inc = pixinc(screen_width * (fbh - 1) - 1 - 1649 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
1635 (fieldmode ? 1 : 0), 1650 y_predecim - (fieldmode ? 1 : 0),
1636 ps); 1651 ps);
1637 *pix_inc = pixinc(-screen_width, ps); 1652 *pix_inc = pixinc(-x_predecim * screen_width, ps);
1638 break; 1653 break;
1639 1654
1640 default: 1655 default:
@@ -1725,13 +1740,17 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1725static int dispc_ovl_calc_scaling(enum omap_plane plane, 1740static int dispc_ovl_calc_scaling(enum omap_plane plane,
1726 enum omap_channel channel, u16 width, u16 height, 1741 enum omap_channel channel, u16 width, u16 height,
1727 u16 out_width, u16 out_height, 1742 u16 out_width, u16 out_height,
1728 enum omap_color_mode color_mode, bool *five_taps) 1743 enum omap_color_mode color_mode, bool *five_taps,
1744 int *x_predecim, int *y_predecim)
1729{ 1745{
1730 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1746 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1731 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 1747 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1732 const int maxsinglelinewidth = 1748 const int maxsinglelinewidth =
1733 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 1749 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
1750 const int max_decim_limit = 16;
1734 unsigned long fclk = 0; 1751 unsigned long fclk = 0;
1752 int decim_x, decim_y, error, min_factor;
1753 u16 in_width, in_height, in_width_max = 0;
1735 1754
1736 if (width == out_width && height == out_height) 1755 if (width == out_width && height == out_height)
1737 return 0; 1756 return 0;
@@ -1739,45 +1758,121 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1739 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 1758 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
1740 return -EINVAL; 1759 return -EINVAL;
1741 1760
1742 if (out_width < width / maxdownscale || 1761 *x_predecim = max_decim_limit;
1743 out_width > width * 8) 1762 *y_predecim = max_decim_limit;
1763
1764 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
1765 color_mode == OMAP_DSS_COLOR_CLUT2 ||
1766 color_mode == OMAP_DSS_COLOR_CLUT4 ||
1767 color_mode == OMAP_DSS_COLOR_CLUT8) {
1768 *x_predecim = 1;
1769 *y_predecim = 1;
1770 *five_taps = false;
1771 return 0;
1772 }
1773
1774 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
1775 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
1776
1777 min_factor = min(decim_x, decim_y);
1778
1779 if (decim_x > *x_predecim || out_width > width * 8)
1744 return -EINVAL; 1780 return -EINVAL;
1745 1781
1746 if (out_height < height / maxdownscale || 1782 if (decim_y > *y_predecim || out_height > height * 8)
1747 out_height > height * 8)
1748 return -EINVAL; 1783 return -EINVAL;
1749 1784
1750 if (cpu_is_omap24xx()) { 1785 if (cpu_is_omap24xx()) {
1751 if (width > maxsinglelinewidth)
1752 DSSERR("Cannot scale max input width exceeded");
1753 *five_taps = false; 1786 *five_taps = false;
1754 fclk = calc_fclk(channel, width, height, out_width, 1787
1755 out_height); 1788 do {
1789 in_height = DIV_ROUND_UP(height, decim_y);
1790 in_width = DIV_ROUND_UP(width, decim_x);
1791 fclk = calc_fclk(channel, in_width, in_height,
1792 out_width, out_height);
1793 error = (in_width > maxsinglelinewidth || !fclk ||
1794 fclk > dispc_fclk_rate());
1795 if (error) {
1796 if (decim_x == decim_y) {
1797 decim_x = min_factor;
1798 decim_y++;
1799 } else {
1800 swap(decim_x, decim_y);
1801 if (decim_x < decim_y)
1802 decim_x++;
1803 }
1804 }
1805 } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
1806 error);
1807
1808 if (in_width > maxsinglelinewidth) {
1809 DSSERR("Cannot scale max input width exceeded");
1810 return -EINVAL;
1811 }
1756 } else if (cpu_is_omap34xx()) { 1812 } else if (cpu_is_omap34xx()) {
1757 if (width > (maxsinglelinewidth * 2)) { 1813
1814 do {
1815 in_height = DIV_ROUND_UP(height, decim_y);
1816 in_width = DIV_ROUND_UP(width, decim_x);
1817 fclk = calc_fclk_five_taps(channel, in_width, in_height,
1818 out_width, out_height, color_mode);
1819
1820 if (in_width > maxsinglelinewidth)
1821 if (in_height > out_height &&
1822 in_height < out_height * 2)
1823 *five_taps = false;
1824 if (!*five_taps)
1825 fclk = calc_fclk(channel, in_width, in_height,
1826 out_width, out_height);
1827 error = (in_width > maxsinglelinewidth * 2 ||
1828 (in_width > maxsinglelinewidth && *five_taps) ||
1829 !fclk || fclk > dispc_fclk_rate());
1830 if (error) {
1831 if (decim_x == decim_y) {
1832 decim_x = min_factor;
1833 decim_y++;
1834 } else {
1835 swap(decim_x, decim_y);
1836 if (decim_x < decim_y)
1837 decim_x++;
1838 }
1839 }
1840 } while (decim_x <= *x_predecim && decim_y <= *y_predecim
1841 && error);
1842
1843 if (in_width > (maxsinglelinewidth * 2)) {
1758 DSSERR("Cannot setup scaling"); 1844 DSSERR("Cannot setup scaling");
1759 DSSERR("width exceeds maximum width possible"); 1845 DSSERR("width exceeds maximum width possible");
1760 return -EINVAL; 1846 return -EINVAL;
1761 } 1847 }
1762 fclk = calc_fclk_five_taps(channel, width, height, out_width, 1848
1763 out_height, color_mode); 1849 if (in_width > maxsinglelinewidth && *five_taps) {
1764 if (width > maxsinglelinewidth) { 1850 DSSERR("cannot setup scaling with five taps");
1765 if (height > out_height && height < out_height * 2) 1851 return -EINVAL;
1766 *five_taps = false;
1767 else {
1768 DSSERR("cannot setup scaling with five taps");
1769 return -EINVAL;
1770 }
1771 } 1852 }
1772 if (!*five_taps)
1773 fclk = calc_fclk(channel, width, height, out_width,
1774 out_height);
1775 } else { 1853 } else {
1776 if (width > maxsinglelinewidth) { 1854 int decim_x_min = decim_x;
1855 in_height = DIV_ROUND_UP(height, decim_y);
1856 in_width_max = dispc_fclk_rate() /
1857 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
1858 out_width);
1859 decim_x = DIV_ROUND_UP(width, in_width_max);
1860
1861 decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
1862 if (decim_x > *x_predecim)
1863 return -EINVAL;
1864
1865 do {
1866 in_width = DIV_ROUND_UP(width, decim_x);
1867 } while (decim_x <= *x_predecim &&
1868 in_width > maxsinglelinewidth && decim_x++);
1869
1870 if (in_width > maxsinglelinewidth) {
1777 DSSERR("Cannot scale width exceeds max line width"); 1871 DSSERR("Cannot scale width exceeds max line width");
1778 return -EINVAL; 1872 return -EINVAL;
1779 } 1873 }
1780 fclk = calc_fclk(channel, width, height, out_width, 1874
1875 fclk = calc_fclk(channel, in_width, in_height, out_width,
1781 out_height); 1876 out_height);
1782 } 1877 }
1783 1878
@@ -1792,6 +1887,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1792 return -EINVAL; 1887 return -EINVAL;
1793 } 1888 }
1794 1889
1890 *x_predecim = decim_x;
1891 *y_predecim = decim_y;
1795 return 0; 1892 return 0;
1796} 1893}
1797 1894
@@ -1807,8 +1904,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1807 s32 pix_inc; 1904 s32 pix_inc;
1808 u16 frame_height = oi->height; 1905 u16 frame_height = oi->height;
1809 unsigned int field_offset = 0; 1906 unsigned int field_offset = 0;
1810 u16 outw, outh; 1907 u16 in_height = oi->height;
1908 u16 in_width = oi->width;
1909 u16 out_width, out_height;
1811 enum omap_channel channel; 1910 enum omap_channel channel;
1911 int x_predecim = 1, y_predecim = 1;
1812 1912
1813 channel = dispc_ovl_get_channel_out(plane); 1913 channel = dispc_ovl_get_channel_out(plane);
1814 1914
@@ -1822,32 +1922,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1822 if (oi->paddr == 0) 1922 if (oi->paddr == 0)
1823 return -EINVAL; 1923 return -EINVAL;
1824 1924
1825 outw = oi->out_width == 0 ? oi->width : oi->out_width; 1925 out_width = oi->out_width == 0 ? oi->width : oi->out_width;
1826 outh = oi->out_height == 0 ? oi->height : oi->out_height; 1926 out_height = oi->out_height == 0 ? oi->height : oi->out_height;
1827 1927
1828 if (ilace && oi->height == outh) 1928 if (ilace && oi->height == out_height)
1829 fieldmode = 1; 1929 fieldmode = 1;
1830 1930
1831 if (ilace) { 1931 if (ilace) {
1832 if (fieldmode) 1932 if (fieldmode)
1833 oi->height /= 2; 1933 in_height /= 2;
1834 oi->pos_y /= 2; 1934 oi->pos_y /= 2;
1835 outh /= 2; 1935 out_height /= 2;
1836 1936
1837 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 1937 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1838 "out_height %d\n", 1938 "out_height %d\n",
1839 oi->height, oi->pos_y, outh); 1939 in_height, oi->pos_y, out_height);
1840 } 1940 }
1841 1941
1842 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 1942 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
1843 return -EINVAL; 1943 return -EINVAL;
1844 1944
1845 r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, 1945 r = dispc_ovl_calc_scaling(plane, channel, in_width, in_height,
1846 outw, outh, oi->color_mode, 1946 out_width, out_height, oi->color_mode, &five_taps,
1847 &five_taps); 1947 &x_predecim, &y_predecim);
1848 if (r) 1948 if (r)
1849 return r; 1949 return r;
1850 1950
1951 in_width = DIV_ROUND_UP(in_width, x_predecim);
1952 in_height = DIV_ROUND_UP(in_height, y_predecim);
1953
1851 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 1954 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
1852 oi->color_mode == OMAP_DSS_COLOR_UYVY || 1955 oi->color_mode == OMAP_DSS_COLOR_UYVY ||
1853 oi->color_mode == OMAP_DSS_COLOR_NV12) 1956 oi->color_mode == OMAP_DSS_COLOR_NV12)
@@ -1861,10 +1964,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1861 * so the integer part must be added to the base address of the 1964 * so the integer part must be added to the base address of the
1862 * bottom field. 1965 * bottom field.
1863 */ 1966 */
1864 if (!oi->height || oi->height == outh) 1967 if (!in_height || in_height == out_height)
1865 field_offset = 0; 1968 field_offset = 0;
1866 else 1969 else
1867 field_offset = oi->height / outh / 2; 1970 field_offset = in_height / out_height / 2;
1868 } 1971 }
1869 1972
1870 /* Fields are independent but interleaved in memory. */ 1973 /* Fields are independent but interleaved in memory. */
@@ -1873,14 +1976,16 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1873 1976
1874 if (oi->rotation_type == OMAP_DSS_ROT_DMA) 1977 if (oi->rotation_type == OMAP_DSS_ROT_DMA)
1875 calc_dma_rotation_offset(oi->rotation, oi->mirror, 1978 calc_dma_rotation_offset(oi->rotation, oi->mirror,
1876 oi->screen_width, oi->width, frame_height, 1979 oi->screen_width, in_width, frame_height,
1877 oi->color_mode, fieldmode, field_offset, 1980 oi->color_mode, fieldmode, field_offset,
1878 &offset0, &offset1, &row_inc, &pix_inc); 1981 &offset0, &offset1, &row_inc, &pix_inc,
1982 x_predecim, y_predecim);
1879 else 1983 else
1880 calc_vrfb_rotation_offset(oi->rotation, oi->mirror, 1984 calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
1881 oi->screen_width, oi->width, frame_height, 1985 oi->screen_width, in_width, frame_height,
1882 oi->color_mode, fieldmode, field_offset, 1986 oi->color_mode, fieldmode, field_offset,
1883 &offset0, &offset1, &row_inc, &pix_inc); 1987 &offset0, &offset1, &row_inc, &pix_inc,
1988 x_predecim, y_predecim);
1884 1989
1885 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 1990 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1886 offset0, offset1, row_inc, pix_inc); 1991 offset0, offset1, row_inc, pix_inc);
@@ -1899,19 +2004,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1899 dispc_ovl_set_row_inc(plane, row_inc); 2004 dispc_ovl_set_row_inc(plane, row_inc);
1900 dispc_ovl_set_pix_inc(plane, pix_inc); 2005 dispc_ovl_set_pix_inc(plane, pix_inc);
1901 2006
1902 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, 2007 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width,
1903 oi->height, outw, outh); 2008 in_height, out_width, out_height);
1904 2009
1905 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 2010 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
1906 2011
1907 dispc_ovl_set_pic_size(plane, oi->width, oi->height); 2012 dispc_ovl_set_pic_size(plane, in_width, in_height);
1908 2013
1909 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 2014 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
1910 dispc_ovl_set_scaling(plane, oi->width, oi->height, 2015 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
1911 outw, outh, 2016 out_height, ilace, five_taps, fieldmode,
1912 ilace, five_taps, fieldmode,
1913 oi->color_mode, oi->rotation); 2017 oi->color_mode, oi->rotation);
1914 dispc_ovl_set_vid_size(plane, outw, outh); 2018 dispc_ovl_set_vid_size(plane, out_width, out_height);
1915 dispc_ovl_set_vid_color_conv(plane, cconv); 2019 dispc_ovl_set_vid_color_conv(plane, cconv);
1916 } 2020 }
1917 2021