diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/sh/fsi.c | 81 |
1 files changed, 50 insertions, 31 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1029a03c618e..4a9da6b5f4e1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -86,8 +86,8 @@ #define SE (1 << 0) /* Fix the master clock */ /* CLK_RST */ -#define B_CLK 0x00000010 -#define A_CLK 0x00000001 +#define CRB (1 << 4) +#define CRA (1 << 0) /* IO SHIFT / MACRO */ #define BI_SHIFT 12 @@ -187,6 +187,7 @@ struct fsi_master { u32 saved_iemsk; u32 saved_imsk; u32 saved_clk_rst; + u32 saved_soft_rst; }; /* @@ -556,20 +557,45 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) } /* - * ctrl function + * clock function */ +#define fsi_module_init(m, d) __fsi_module_clk_ctrl(m, d, 1) +#define fsi_module_kill(m, d) __fsi_module_clk_ctrl(m, d, 0) +static void __fsi_module_clk_ctrl(struct fsi_master *master, + struct device *dev, + int enable) +{ + pm_runtime_get_sync(dev); + + if (enable) { + /* enable only SR */ + fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); + fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); + } else { + /* clear all registers */ + fsi_master_mask_set(master, SOFT_RST, FSISR, 0); + } + + pm_runtime_put_sync(dev); +} -static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) +#define fsi_port_start(f) __fsi_port_clk_ctrl(f, 1) +#define fsi_port_stop(f) __fsi_port_clk_ctrl(f, 0) +static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable) { - u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); struct fsi_master *master = fsi_get_master(fsi); + u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR; + u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; + int is_master = fsi_is_clk_master(fsi); - if (enable) - fsi_master_mask_set(master, CLK_RST, val, val); - else - fsi_master_mask_set(master, CLK_RST, val, 0); + fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0); + if (is_master) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); } +/* + * ctrl function + */ static void fsi_fifo_init(struct fsi_priv *fsi, int is_play, struct snd_soc_dai *dai) @@ -622,18 +648,6 @@ static void fsi_fifo_init(struct fsi_priv *fsi, } } -static void fsi_soft_all_reset(struct fsi_master *master) -{ - /* port AB reset */ - fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); - mdelay(10); - - /* soft reset */ - fsi_master_mask_set(master, SOFT_RST, FSISR, 0); - fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); - mdelay(10); -} - static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) { struct snd_pcm_runtime *runtime; @@ -818,10 +832,8 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, fsi_irq_disable(fsi, is_play); - if (fsi_is_clk_master(fsi)) { - fsi_clk_ctrl(fsi, 0); + if (fsi_is_clk_master(fsi)) set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); - } fsi->rate = 0; @@ -843,8 +855,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, frames_to_bytes(runtime, runtime->period_size)); ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); fsi_irq_enable(fsi, is_play); + fsi_port_start(fsi); break; case SNDRV_PCM_TRIGGER_STOP: + fsi_port_stop(fsi); fsi_irq_disable(fsi, is_play); fsi_stream_pop(fsi, is_play); break; @@ -1018,7 +1032,6 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); udelay(10); - fsi_clk_ctrl(fsi, 1); ret = 0; } @@ -1233,9 +1246,7 @@ static int fsi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); dev_set_drvdata(&pdev->dev, master); - pm_runtime_get_sync(&pdev->dev); - fsi_soft_all_reset(master); - pm_runtime_put_sync(&pdev->dev); + fsi_module_init(master, &pdev->dev); ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, id_entry->name, master); @@ -1279,6 +1290,8 @@ static int fsi_remove(struct platform_device *pdev) master = dev_get_drvdata(&pdev->dev); + fsi_module_kill(master, &pdev->dev); + free_irq(master->irq, master); pm_runtime_disable(&pdev->dev); @@ -1334,6 +1347,9 @@ static int fsi_suspend(struct device *dev) master->saved_iemsk = fsi_core_read(master, iemsk); master->saved_imsk = fsi_core_read(master, imsk); master->saved_clk_rst = fsi_master_read(master, CLK_RST); + master->saved_soft_rst = fsi_master_read(master, SOFT_RST); + + fsi_module_kill(master, dev); pm_runtime_put_sync(dev); @@ -1347,14 +1363,17 @@ static int fsi_resume(struct device *dev) pm_runtime_get_sync(dev); - __fsi_resume(&master->fsia, dev, set_rate); - __fsi_resume(&master->fsib, dev, set_rate); + fsi_module_init(master, dev); + fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst); + fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk); fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); - fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); + + __fsi_resume(&master->fsia, dev, set_rate); + __fsi_resume(&master->fsib, dev, set_rate); pm_runtime_put_sync(dev); |