diff options
| author | Jingoo Han <jg1.han@samsung.com> | 2010-12-17 02:45:46 -0500 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2010-12-20 11:05:43 -0500 |
| commit | 4959212c18669f254daa0ae796ad676b67939ba2 (patch) | |
| tree | ad7957b2e9bac2687c14a9f92eff6637d127fe3d /drivers | |
| parent | 3b80ffdef001ac7ff53bdcb80ad2baadb5953f91 (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')
| -rw-r--r-- | drivers/video/s3c-fb.c | 111 |
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 | ||
| 1017 | static 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 | |||
| 1027 | static 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 | |||
| 1016 | static struct fb_ops s3c_fb_ops = { | 1037 | static 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 |
| 1457 | static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) | 1491 | static 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 | |||
| 1511 | static 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 | |||
| 1549 | int 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 | ||
| 1476 | static int s3c_fb_resume(struct platform_device *pdev) | 1569 | int 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 | }; |
| 1711 | MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); | 1808 | MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); |
| 1712 | 1809 | ||
| 1810 | static 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 | |||
| 1713 | static struct platform_driver s3c_fb_driver = { | 1817 | static 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 | ||
