aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2007-10-16 04:28:37 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:14 -0400
commitc1f303bb21a63ed11edfb790e5701ab0ded62eff (patch)
treeb2f83cce7cb85a52f6bde1f5066e67a93f1d5ffc
parent30dcc9093cc0617a10d84fea13371143f5c84ef0 (diff)
sm501fb: update suspend and resume code
The suspend and resume code is failing to restore the CRT control register, thus causing the CRT data-path to get changed if the SM501 experiences a reset over suspend. Also move some of the debug messages to dev_dbg() level and ensure that the suspend code does not try and restore anything it did not manage to save. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/sm501fb.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index c86df126f93a..fc0cdc830360 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -62,6 +62,8 @@ struct sm501fb_info {
62 struct resource *regs_res; /* registers resource */ 62 struct resource *regs_res; /* registers resource */
63 struct sm501_platdata_fb *pdata; /* our platform data */ 63 struct sm501_platdata_fb *pdata; /* our platform data */
64 64
65 unsigned long pm_crt_ctrl; /* pm: crt ctrl save */
66
65 int irq; 67 int irq;
66 int swap_endian; /* set to swap rgb=>bgr */ 68 int swap_endian; /* set to swap rgb=>bgr */
67 void __iomem *regs; /* remapped registers */ 69 void __iomem *regs; /* remapped registers */
@@ -1687,9 +1689,11 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info,
1687 goto err_nocursor; 1689 goto err_nocursor;
1688 } 1690 }
1689 1691
1692 dev_dbg(info->dev, "suspending screen to %p\n", par->store_fb);
1693 dev_dbg(info->dev, "suspending cursor to %p\n", par->store_cursor);
1694
1690 memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); 1695 memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
1691 memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); 1696 memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
1692
1693 /* blank the relevant interface to ensure unit power minimised */ 1697 /* blank the relevant interface to ensure unit power minimised */
1694 (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); 1698 (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
1695 1699
@@ -1697,9 +1701,9 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info,
1697 1701
1698 err_nocursor: 1702 err_nocursor:
1699 vfree(par->store_fb); 1703 vfree(par->store_fb);
1704 par->store_fb = NULL;
1700 1705
1701 return -ENOMEM; 1706 return -ENOMEM;
1702
1703} 1707}
1704 1708
1705static void sm501fb_resume_fb(struct sm501fb_info *info, 1709static void sm501fb_resume_fb(struct sm501fb_info *info,
@@ -1717,8 +1721,16 @@ static void sm501fb_resume_fb(struct sm501fb_info *info,
1717 1721
1718 /* restore the data */ 1722 /* restore the data */
1719 1723
1720 memcpy_toio(par->screen.k_addr, par->store_fb, par->screen.size); 1724 dev_dbg(info->dev, "restoring screen from %p\n", par->store_fb);
1721 memcpy_toio(par->cursor.k_addr, par->store_cursor, par->cursor.size); 1725 dev_dbg(info->dev, "restoring cursor from %p\n", par->store_cursor);
1726
1727 if (par->store_fb)
1728 memcpy_toio(par->screen.k_addr, par->store_fb,
1729 par->screen.size);
1730
1731 if (par->store_cursor)
1732 memcpy_toio(par->cursor.k_addr, par->store_cursor,
1733 par->cursor.size);
1722 1734
1723 vfree(par->store_fb); 1735 vfree(par->store_fb);
1724 vfree(par->store_cursor); 1736 vfree(par->store_cursor);
@@ -1731,6 +1743,9 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
1731{ 1743{
1732 struct sm501fb_info *info = platform_get_drvdata(pdev); 1744 struct sm501fb_info *info = platform_get_drvdata(pdev);
1733 1745
1746 /* store crt control to resume with */
1747 info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
1748
1734 sm501fb_suspend_fb(info, HEAD_CRT); 1749 sm501fb_suspend_fb(info, HEAD_CRT);
1735 sm501fb_suspend_fb(info, HEAD_PANEL); 1750 sm501fb_suspend_fb(info, HEAD_PANEL);
1736 1751
@@ -1740,12 +1755,24 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
1740 return 0; 1755 return 0;
1741} 1756}
1742 1757
1758#define SM501_CRT_CTRL_SAVE (SM501_DC_CRT_CONTROL_TVP | \
1759 SM501_DC_CRT_CONTROL_SEL)
1760
1761
1743static int sm501fb_resume(struct platform_device *pdev) 1762static int sm501fb_resume(struct platform_device *pdev)
1744{ 1763{
1745 struct sm501fb_info *info = platform_get_drvdata(pdev); 1764 struct sm501fb_info *info = platform_get_drvdata(pdev);
1765 unsigned long crt_ctrl;
1746 1766
1747 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1); 1767 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1);
1748 1768
1769 /* restore the items we want to be saved for crt control */
1770
1771 crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
1772 crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
1773 crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
1774 writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
1775
1749 sm501fb_resume_fb(info, HEAD_CRT); 1776 sm501fb_resume_fb(info, HEAD_CRT);
1750 sm501fb_resume_fb(info, HEAD_PANEL); 1777 sm501fb_resume_fb(info, HEAD_PANEL);
1751 1778