diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-01 06:13:05 -1000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-01 06:13:05 -1000 |
commit | 965e32b18d6b6bbcb79f4a7308fc8bdb4d03e813 (patch) | |
tree | 5d558d0b194f51fb27976a5df2a03b73fb41bb4d /drivers/video/omap2/dss/rfbi.c | |
parent | e10b87d2b5b4574cdf3a5a19b22ca88b91ba7151 (diff) | |
parent | df5d3ed23cf73ee0763a8963003bda9b69d9620f (diff) |
Merge branch 'for-3.1-rc1' of git://gitorious.org/linux-omap-dss2/linux
* 'for-3.1-rc1' of git://gitorious.org/linux-omap-dss2/linux: (31 commits)
OMAP: DSS2: HDMI: fix hdmi clock name
HACK: OMAP: DSS2: clk hack for OMAP2/3
OMAP: DSS2: DSS: Fix context save/restore
OMAP: DSS2: DISPC: Fix context save/restore
OMAP: DSS2: Remove ctx loss count from dss.c
OMAP: DSS2: Remove unused code from display.c
OMAP: DSS2: DISPC: remove finegrained clk enables/disables
OMAP: DSS2: Remove unused opt_clock_available
OMAP: DSS2: Use PM runtime & HWMOD support
OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
OMAP: DSS2: Remove core_dump_clocks
OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count
OMAP: DSS2: rewrite use of context_loss_count
OMAP: DSS2: Remove clk optimization at dss init
OMAP: DSS2: Fix init and unit sequence
OMAP: DSS2: Clean up probe for DSS & DSI
OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
OMAP: DSS2: Fix FIFO threshold and burst size for OMAP4
OMAP: DSS2: DSI: sync when disabling a display
...
Diffstat (limited to 'drivers/video/omap2/dss/rfbi.c')
-rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 114 |
1 files changed, 95 insertions, 19 deletions
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index c06fbe0bc67..39f4c597026 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -33,6 +33,8 @@ #include <linux/hrtimer.h> #include <linux/seq_file.h> #include <linux/semaphore.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <video/omapdss.h> #include "dss.h" @@ -120,12 +122,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) return __raw_readl(rfbi.base + idx.idx); } -static void rfbi_enable_clocks(bool enable) +static int rfbi_runtime_get(void) { - if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + int r; + + DSSDBG("rfbi_runtime_get\n"); + + r = pm_runtime_get_sync(&rfbi.pdev->dev); + WARN_ON(r < 0); + return r < 0 ? r : 0; +} + +static void rfbi_runtime_put(void) +{ + int r; + + DSSDBG("rfbi_runtime_put\n"); + + r = pm_runtime_put(&rfbi.pdev->dev); + WARN_ON(r < 0); } void rfbi_bus_lock(void) @@ -805,7 +820,8 @@ void rfbi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + if (rfbi_runtime_get()) + return; DUMPREG(RFBI_REVISION); DUMPREG(RFBI_SYSCONFIG); @@ -836,7 +852,7 @@ void rfbi_dump_regs(struct seq_file *s) DUMPREG(RFBI_VSYNC_WIDTH); DUMPREG(RFBI_HSYNC_WIDTH); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + rfbi_runtime_put(); #undef DUMPREG } @@ -844,7 +860,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { int r; - rfbi_enable_clocks(1); + r = rfbi_runtime_get(); + if (r) + return r; r = omap_dss_start_device(dssdev); if (r) { @@ -879,6 +897,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) err1: omap_dss_stop_device(dssdev); err0: + rfbi_runtime_put(); return r; } EXPORT_SYMBOL(omapdss_rfbi_display_enable); @@ -889,7 +908,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) DISPC_IRQ_FRAMEDONE); omap_dss_stop_device(dssdev); - rfbi_enable_clocks(0); + rfbi_runtime_put(); } EXPORT_SYMBOL(omapdss_rfbi_display_disable); @@ -904,8 +923,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev) static int omap_rfbihw_probe(struct platform_device *pdev) { u32 rev; - u32 l; struct resource *rfbi_mem; + struct clk *clk; + int r; rfbi.pdev = pdev; @@ -914,46 +934,102 @@ static int omap_rfbihw_probe(struct platform_device *pdev) rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); if (!rfbi_mem) { DSSERR("can't get IORESOURCE_MEM RFBI\n"); - return -EINVAL; + r = -EINVAL; + goto err_ioremap; } rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); if (!rfbi.base) { DSSERR("can't ioremap RFBI\n"); - return -ENOMEM; + r = -ENOMEM; + goto err_ioremap; } - rfbi_enable_clocks(1); + pm_runtime_enable(&pdev->dev); + + r = rfbi_runtime_get(); + if (r) + goto err_get_rfbi; msleep(10); - rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; + if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630()) + clk = dss_get_ick(); + else + clk = clk_get(&pdev->dev, "ick"); + if (IS_ERR(clk)) { + DSSERR("can't get ick\n"); + r = PTR_ERR(clk); + goto err_get_ick; + } + + rfbi.l4_khz = clk_get_rate(clk) / 1000; - /* Enable autoidle and smart-idle */ - l = rfbi_read_reg(RFBI_SYSCONFIG); - l |= (1 << 0) | (2 << 3); - rfbi_write_reg(RFBI_SYSCONFIG, l); + clk_put(clk); rev = rfbi_read_reg(RFBI_REVISION); dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - rfbi_enable_clocks(0); + rfbi_runtime_put(); return 0; + +err_get_ick: + rfbi_runtime_put(); +err_get_rfbi: + pm_runtime_disable(&pdev->dev); + iounmap(rfbi.base); +err_ioremap: + return r; } static int omap_rfbihw_remove(struct platform_device *pdev) { + pm_runtime_disable(&pdev->dev); iounmap(rfbi.base); return 0; } +static int rfbi_runtime_suspend(struct device *dev) +{ + dispc_runtime_put(); + dss_runtime_put(); + + return 0; +} + +static int rfbi_runtime_resume(struct device *dev) +{ + int r; + + r = dss_runtime_get(); + if (r < 0) + goto err_get_dss; + + r = dispc_runtime_get(); + if (r < 0) + goto err_get_dispc; + + return 0; + +err_get_dispc: + dss_runtime_put(); +err_get_dss: + return r; +} + +static const struct dev_pm_ops rfbi_pm_ops = { + .runtime_suspend = rfbi_runtime_suspend, + .runtime_resume = rfbi_runtime_resume, +}; + static struct platform_driver omap_rfbihw_driver = { .probe = omap_rfbihw_probe, .remove = omap_rfbihw_remove, .driver = { .name = "omapdss_rfbi", .owner = THIS_MODULE, + .pm = &rfbi_pm_ops, }, }; |