aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-12-27 09:16:10 -0500
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-01-03 11:00:04 -0500
commitf4f514734e3d398cfb70827615f129826ff84b06 (patch)
tree0132c27ebe85dab465266d01dbd413169bb6895b
parent3500b0be62c8cc2f93e8022dc70071ec31b067de (diff)
video: s3c-fb: Take a runtime PM reference when unblanked
When the framebuffer is unblanked hold a runtime PM reference. This prevents us powering down when userspace has left an image on the framebuffer and prepares the way for being able to power down the hardware when an application still has the device open. Since we now hold a runtime PM reference whenever the display is unblanked there is no need for the runtime power management to disable and enable the display, and doing so would lead to runtime PM trying to recurse into itself when called from the blanking code, so split the runtime PM into separate functions which only deal with the clocks. The PM core will runtime resume the device prior to system suspend. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-rw-r--r--drivers/video/s3c-fb.c66
1 files changed, 54 insertions, 12 deletions
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 2e0eef0a563f..688b9d8c396a 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -192,6 +192,7 @@ struct s3c_fb_vsync {
192 * @regs: The mapped hardware registers. 192 * @regs: The mapped hardware registers.
193 * @variant: Variant information for this hardware. 193 * @variant: Variant information for this hardware.
194 * @enabled: A bitmask of enabled hardware windows. 194 * @enabled: A bitmask of enabled hardware windows.
195 * @output_on: Flag if the physical output is enabled.
195 * @pdata: The platform configuration data passed with the device. 196 * @pdata: The platform configuration data passed with the device.
196 * @windows: The hardware windows that have been claimed. 197 * @windows: The hardware windows that have been claimed.
197 * @irq_no: IRQ line number 198 * @irq_no: IRQ line number
@@ -208,6 +209,7 @@ struct s3c_fb {
208 struct s3c_fb_variant variant; 209 struct s3c_fb_variant variant;
209 210
210 unsigned char enabled; 211 unsigned char enabled;
212 bool output_on;
211 213
212 struct s3c_fb_platdata *pdata; 214 struct s3c_fb_platdata *pdata;
213 struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; 215 struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
@@ -449,21 +451,28 @@ static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
449{ 451{
450 u32 vidcon0 = readl(sfb->regs + VIDCON0); 452 u32 vidcon0 = readl(sfb->regs + VIDCON0);
451 453
452 if (enable) 454 if (enable && !sfb->output_on)
455 pm_runtime_get_sync(sfb->dev);
456
457 if (enable) {
453 vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; 458 vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
454 else { 459 } else {
455 /* see the note in the framebuffer datasheet about 460 /* see the note in the framebuffer datasheet about
456 * why you cannot take both of these bits down at the 461 * why you cannot take both of these bits down at the
457 * same time. */ 462 * same time. */
458 463
459 if (!(vidcon0 & VIDCON0_ENVID)) 464 if (vidcon0 & VIDCON0_ENVID) {
460 return; 465 vidcon0 |= VIDCON0_ENVID;
461 466 vidcon0 &= ~VIDCON0_ENVID_F;
462 vidcon0 |= VIDCON0_ENVID; 467 }
463 vidcon0 &= ~VIDCON0_ENVID_F;
464 } 468 }
465 469
466 writel(vidcon0, sfb->regs + VIDCON0); 470 writel(vidcon0, sfb->regs + VIDCON0);
471
472 if (!enable && sfb->output_on)
473 pm_runtime_put_sync(sfb->dev);
474
475 sfb->output_on = enable;
467} 476}
468 477
469/** 478/**
@@ -1539,7 +1548,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1539 return 0; 1548 return 0;
1540} 1549}
1541 1550
1542#ifdef CONFIG_PM 1551#ifdef CONFIG_PM_SLEEP
1543static int s3c_fb_suspend(struct device *dev) 1552static int s3c_fb_suspend(struct device *dev)
1544{ 1553{
1545 struct platform_device *pdev = to_platform_device(dev); 1554 struct platform_device *pdev = to_platform_device(dev);
@@ -1609,11 +1618,40 @@ static int s3c_fb_resume(struct device *dev)
1609 1618
1610 return 0; 1619 return 0;
1611} 1620}
1612#else
1613#define s3c_fb_suspend NULL
1614#define s3c_fb_resume NULL
1615#endif 1621#endif
1616 1622
1623#ifdef CONFIG_PM_RUNTIME
1624static int s3c_fb_runtime_suspend(struct device *dev)
1625{
1626 struct platform_device *pdev = to_platform_device(dev);
1627 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1628
1629 if (!sfb->variant.has_clksel)
1630 clk_disable(sfb->lcd_clk);
1631
1632 clk_disable(sfb->bus_clk);
1633
1634 return 0;
1635}
1636
1637static int s3c_fb_runtime_resume(struct device *dev)
1638{
1639 struct platform_device *pdev = to_platform_device(dev);
1640 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1641 struct s3c_fb_platdata *pd = sfb->pdata;
1642
1643 clk_enable(sfb->bus_clk);
1644
1645 if (!sfb->variant.has_clksel)
1646 clk_enable(sfb->lcd_clk);
1647
1648 /* setup gpio and output polarity controls */
1649 pd->setup_gpio();
1650 writel(pd->vidcon1, sfb->regs + VIDCON1);
1651
1652 return 0;
1653}
1654#endif
1617 1655
1618#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) 1656#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
1619#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) 1657#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
@@ -1936,7 +1974,11 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1936}; 1974};
1937MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1975MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1938 1976
1939static UNIVERSAL_DEV_PM_OPS(s3cfb_pm_ops, s3c_fb_suspend, s3c_fb_resume, NULL); 1977static const struct dev_pm_ops s3cfb_pm_ops = {
1978 SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
1979 SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
1980 NULL)
1981};
1940 1982
1941static struct platform_driver s3c_fb_driver = { 1983static struct platform_driver s3c_fb_driver = {
1942 .probe = s3c_fb_probe, 1984 .probe = s3c_fb_probe,