aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/s3c-fb.c
diff options
context:
space:
mode:
authorJingoo Han <jg1.han@samsung.com>2010-12-17 02:45:46 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-12-20 11:05:43 -0500
commit4959212c18669f254daa0ae796ad676b67939ba2 (patch)
treead7957b2e9bac2687c14a9f92eff6637d127fe3d /drivers/video/s3c-fb.c
parent3b80ffdef001ac7ff53bdcb80ad2baadb5953f91 (diff)
s3c-fb: add support for runtime pm
This patch adds support for runtime pm using the functions. - pm_runtime_get_sync() - pm_runtime_put_sync() pm_runtime_get_sync() and pm_runtime_put_sync() are called when open or release function of framebufer driver is called to inform the system if hardware is idle or not. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video/s3c-fb.c')
-rw-r--r--drivers/video/s3c-fb.c111
1 files changed, 107 insertions, 4 deletions
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index f9aca9d13d1b..83ce9a04d872 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -23,6 +23,7 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/pm_runtime.h>
26 27
27#include <mach/map.h> 28#include <mach/map.h>
28#include <plat/regs-fb-v4.h> 29#include <plat/regs-fb-v4.h>
@@ -1013,8 +1014,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
1013 return ret; 1014 return ret;
1014} 1015}
1015 1016
1017static int s3c_fb_open(struct fb_info *info, int user)
1018{
1019 struct s3c_fb_win *win = info->par;
1020 struct s3c_fb *sfb = win->parent;
1021
1022 pm_runtime_get_sync(sfb->dev);
1023
1024 return 0;
1025}
1026
1027static int s3c_fb_release(struct fb_info *info, int user)
1028{
1029 struct s3c_fb_win *win = info->par;
1030 struct s3c_fb *sfb = win->parent;
1031
1032 pm_runtime_put_sync(sfb->dev);
1033
1034 return 0;
1035}
1036
1016static struct fb_ops s3c_fb_ops = { 1037static struct fb_ops s3c_fb_ops = {
1017 .owner = THIS_MODULE, 1038 .owner = THIS_MODULE,
1039 .fb_open = s3c_fb_open,
1040 .fb_release = s3c_fb_release,
1018 .fb_check_var = s3c_fb_check_var, 1041 .fb_check_var = s3c_fb_check_var,
1019 .fb_set_par = s3c_fb_set_par, 1042 .fb_set_par = s3c_fb_set_par,
1020 .fb_blank = s3c_fb_blank, 1043 .fb_blank = s3c_fb_blank,
@@ -1322,6 +1345,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1322 1345
1323 clk_enable(sfb->bus_clk); 1346 clk_enable(sfb->bus_clk);
1324 1347
1348 pm_runtime_enable(sfb->dev);
1349
1325 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1350 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1326 if (!res) { 1351 if (!res) {
1327 dev_err(dev, "failed to find registers\n"); 1352 dev_err(dev, "failed to find registers\n");
@@ -1360,6 +1385,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1360 1385
1361 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1386 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
1362 1387
1388 platform_set_drvdata(pdev, sfb);
1389 pm_runtime_get_sync(sfb->dev);
1390
1363 /* setup gpio and output polarity controls */ 1391 /* setup gpio and output polarity controls */
1364 1392
1365 pd->setup_gpio(); 1393 pd->setup_gpio();
@@ -1400,6 +1428,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1400 } 1428 }
1401 1429
1402 platform_set_drvdata(pdev, sfb); 1430 platform_set_drvdata(pdev, sfb);
1431 pm_runtime_put_sync(sfb->dev);
1403 1432
1404 return 0; 1433 return 0;
1405 1434
@@ -1434,6 +1463,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1434 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1463 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1435 int win; 1464 int win;
1436 1465
1466 pm_runtime_get_sync(sfb->dev);
1467
1437 for (win = 0; win < S3C_FB_MAX_WIN; win++) 1468 for (win = 0; win < S3C_FB_MAX_WIN; win++)
1438 if (sfb->windows[win]) 1469 if (sfb->windows[win])
1439 s3c_fb_release_win(sfb, sfb->windows[win]); 1470 s3c_fb_release_win(sfb, sfb->windows[win]);
@@ -1450,12 +1481,74 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1450 1481
1451 kfree(sfb); 1482 kfree(sfb);
1452 1483
1484 pm_runtime_put_sync(sfb->dev);
1485 pm_runtime_disable(sfb->dev);
1486
1453 return 0; 1487 return 0;
1454} 1488}
1455 1489
1456#ifdef CONFIG_PM 1490#ifdef CONFIG_PM
1457static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) 1491static int s3c_fb_suspend(struct device *dev)
1492{
1493 struct platform_device *pdev = to_platform_device(dev);
1494 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1495 struct s3c_fb_win *win;
1496 int win_no;
1497
1498 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
1499 win = sfb->windows[win_no];
1500 if (!win)
1501 continue;
1502
1503 /* use the blank function to push into power-down */
1504 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1505 }
1506
1507 clk_disable(sfb->bus_clk);
1508 return 0;
1509}
1510
1511static int s3c_fb_resume(struct device *dev)
1512{
1513 struct platform_device *pdev = to_platform_device(dev);
1514 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1515 struct s3c_fb_platdata *pd = sfb->pdata;
1516 struct s3c_fb_win *win;
1517 int win_no;
1518
1519 clk_enable(sfb->bus_clk);
1520
1521 /* setup registers */
1522 writel(pd->vidcon1, sfb->regs + VIDCON1);
1523
1524 /* zero all windows before we do anything */
1525 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1526 s3c_fb_clear_win(sfb, win_no);
1527
1528 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1529 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1530
1531 regs += (win_no * 8);
1532 writel(0xffffff, regs + WKEYCON0);
1533 writel(0xffffff, regs + WKEYCON1);
1534 }
1535
1536 /* restore framebuffers */
1537 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1538 win = sfb->windows[win_no];
1539 if (!win)
1540 continue;
1541
1542 dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
1543 s3c_fb_set_par(win->fbinfo);
1544 }
1545
1546 return 0;
1547}
1548
1549int s3c_fb_runtime_suspend(struct device *dev)
1458{ 1550{
1551 struct platform_device *pdev = to_platform_device(dev);
1459 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1552 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1460 struct s3c_fb_win *win; 1553 struct s3c_fb_win *win;
1461 int win_no; 1554 int win_no;
@@ -1473,8 +1566,9 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
1473 return 0; 1566 return 0;
1474} 1567}
1475 1568
1476static int s3c_fb_resume(struct platform_device *pdev) 1569int s3c_fb_runtime_resume(struct device *dev)
1477{ 1570{
1571 struct platform_device *pdev = to_platform_device(dev);
1478 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1572 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1479 struct s3c_fb_platdata *pd = sfb->pdata; 1573 struct s3c_fb_platdata *pd = sfb->pdata;
1480 struct s3c_fb_win *win; 1574 struct s3c_fb_win *win;
@@ -1509,9 +1603,12 @@ static int s3c_fb_resume(struct platform_device *pdev)
1509 1603
1510 return 0; 1604 return 0;
1511} 1605}
1606
1512#else 1607#else
1513#define s3c_fb_suspend NULL 1608#define s3c_fb_suspend NULL
1514#define s3c_fb_resume NULL 1609#define s3c_fb_resume NULL
1610#define s3c_fb_runtime_suspend NULL
1611#define s3c_fb_runtime_resume NULL
1515#endif 1612#endif
1516 1613
1517 1614
@@ -1710,15 +1807,21 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1710}; 1807};
1711MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1808MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1712 1809
1810static const struct dev_pm_ops s3cfb_pm_ops = {
1811 .suspend = s3c_fb_suspend,
1812 .resume = s3c_fb_resume,
1813 .runtime_suspend = s3c_fb_runtime_suspend,
1814 .runtime_resume = s3c_fb_runtime_resume,
1815};
1816
1713static struct platform_driver s3c_fb_driver = { 1817static struct platform_driver s3c_fb_driver = {
1714 .probe = s3c_fb_probe, 1818 .probe = s3c_fb_probe,
1715 .remove = __devexit_p(s3c_fb_remove), 1819 .remove = __devexit_p(s3c_fb_remove),
1716 .suspend = s3c_fb_suspend,
1717 .resume = s3c_fb_resume,
1718 .id_table = s3c_fb_driver_ids, 1820 .id_table = s3c_fb_driver_ids,
1719 .driver = { 1821 .driver = {
1720 .name = "s3c-fb", 1822 .name = "s3c-fb",
1721 .owner = THIS_MODULE, 1823 .owner = THIS_MODULE,
1824 .pm = &s3cfb_pm_ops,
1722 }, 1825 },
1723}; 1826};
1724 1827