mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
ASoC: sh: fsi: Add runtime PM support
This patch add support runtime PM. Driver callbacks for Runtime PM are empty because the device registers are always re-initialized after pm_runtime_get_sync(). The Runtime PM functions replaces the clock framework module stop bit handling in this driver. Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com> Acked-by: Paul Mundt <lethal@linux-sh.org> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
d53bd80cb3
commit
785d1c45ce
1 changed files with 25 additions and 14 deletions
|
@ -17,7 +17,7 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
|
@ -105,7 +105,6 @@ struct fsi_priv {
|
||||||
struct fsi_master {
|
struct fsi_master {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int irq;
|
int irq;
|
||||||
struct clk *clk;
|
|
||||||
struct fsi_priv fsia;
|
struct fsi_priv fsia;
|
||||||
struct fsi_priv fsib;
|
struct fsi_priv fsib;
|
||||||
struct sh_fsi_platform_info *info;
|
struct sh_fsi_platform_info *info;
|
||||||
|
@ -559,7 +558,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
|
||||||
int is_master;
|
int is_master;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
clk_enable(master->clk);
|
pm_runtime_get_sync(dai->dev);
|
||||||
|
|
||||||
/* CKG1 */
|
/* CKG1 */
|
||||||
data = is_play ? (1 << 0) : (1 << 4);
|
data = is_play ? (1 << 0) : (1 << 4);
|
||||||
|
@ -674,7 +673,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
|
||||||
fsi_irq_disable(fsi, is_play);
|
fsi_irq_disable(fsi, is_play);
|
||||||
fsi_clk_ctrl(fsi, 0);
|
fsi_clk_ctrl(fsi, 0);
|
||||||
|
|
||||||
clk_disable(master->clk);
|
pm_runtime_put_sync(dai->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
|
@ -872,7 +871,6 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform);
|
||||||
static int fsi_probe(struct platform_device *pdev)
|
static int fsi_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
char clk_name[8];
|
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -903,14 +901,8 @@ static int fsi_probe(struct platform_device *pdev)
|
||||||
master->fsia.base = master->base;
|
master->fsia.base = master->base;
|
||||||
master->fsib.base = master->base + 0x40;
|
master->fsib.base = master->base + 0x40;
|
||||||
|
|
||||||
/* FSI is based on SPU mstp */
|
pm_runtime_enable(&pdev->dev);
|
||||||
snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
|
pm_runtime_resume(&pdev->dev);
|
||||||
master->clk = clk_get(NULL, clk_name);
|
|
||||||
if (IS_ERR(master->clk)) {
|
|
||||||
dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
|
|
||||||
ret = -EIO;
|
|
||||||
goto exit_iounmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
fsi_soc_dai[0].dev = &pdev->dev;
|
fsi_soc_dai[0].dev = &pdev->dev;
|
||||||
fsi_soc_dai[1].dev = &pdev->dev;
|
fsi_soc_dai[1].dev = &pdev->dev;
|
||||||
|
@ -935,6 +927,7 @@ exit_free_irq:
|
||||||
free_irq(irq, master);
|
free_irq(irq, master);
|
||||||
exit_iounmap:
|
exit_iounmap:
|
||||||
iounmap(master->base);
|
iounmap(master->base);
|
||||||
|
pm_runtime_disable(&pdev->dev);
|
||||||
exit_kfree:
|
exit_kfree:
|
||||||
kfree(master);
|
kfree(master);
|
||||||
master = NULL;
|
master = NULL;
|
||||||
|
@ -947,7 +940,7 @@ static int fsi_remove(struct platform_device *pdev)
|
||||||
snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
|
snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
|
||||||
snd_soc_unregister_platform(&fsi_soc_platform);
|
snd_soc_unregister_platform(&fsi_soc_platform);
|
||||||
|
|
||||||
clk_put(master->clk);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
free_irq(master->irq, master);
|
free_irq(master->irq, master);
|
||||||
|
|
||||||
|
@ -957,9 +950,27 @@ static int fsi_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fsi_runtime_nop(struct device *dev)
|
||||||
|
{
|
||||||
|
/* Runtime PM callback shared between ->runtime_suspend()
|
||||||
|
* and ->runtime_resume(). Simply returns success.
|
||||||
|
*
|
||||||
|
* This driver re-initializes all registers after
|
||||||
|
* pm_runtime_get_sync() anyway so there is no need
|
||||||
|
* to save and restore registers here.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dev_pm_ops fsi_pm_ops = {
|
||||||
|
.runtime_suspend = fsi_runtime_nop,
|
||||||
|
.runtime_resume = fsi_runtime_nop,
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver fsi_driver = {
|
static struct platform_driver fsi_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "sh_fsi",
|
.name = "sh_fsi",
|
||||||
|
.pm = &fsi_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = fsi_probe,
|
.probe = fsi_probe,
|
||||||
.remove = fsi_remove,
|
.remove = fsi_remove,
|
||||||
|
|
Loading…
Reference in a new issue