diff options
author | Ben Dooks <ben-linux@fluff.org> | 2007-10-16 04:28:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:14 -0400 |
commit | c1f303bb21a63ed11edfb790e5701ab0ded62eff (patch) | |
tree | b2f83cce7cb85a52f6bde1f5066e67a93f1d5ffc | |
parent | 30dcc9093cc0617a10d84fea13371143f5c84ef0 (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.c | 35 |
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 | ||
1705 | static void sm501fb_resume_fb(struct sm501fb_info *info, | 1709 | static 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 | |||
1743 | static int sm501fb_resume(struct platform_device *pdev) | 1762 | static 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 | ||