diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-04-20 21:33:52 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-04-26 06:42:11 -0400 |
commit | 1f5e2a319d2ba80bfea5c3b5cbafea09d5164a51 (patch) | |
tree | 179e316a0d9e928a054cf3d5a25f63373fe76eee | |
parent | 106c79ecf2db141fcd6073de55ebeb3f041e0509 (diff) |
ASoC: sh: fsi: Add module/port clock control function
The FIFO of each port were always working though it was not used
in current FSI driver.
This patch add module/port clock control function for fixing it.
This patch is also caring suspend/resume.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Simon Horman <simon@horms.net>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-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 @@ | |||
86 | #define SE (1 << 0) /* Fix the master clock */ | 86 | #define SE (1 << 0) /* Fix the master clock */ |
87 | 87 | ||
88 | /* CLK_RST */ | 88 | /* CLK_RST */ |
89 | #define B_CLK 0x00000010 | 89 | #define CRB (1 << 4) |
90 | #define A_CLK 0x00000001 | 90 | #define CRA (1 << 0) |
91 | 91 | ||
92 | /* IO SHIFT / MACRO */ | 92 | /* IO SHIFT / MACRO */ |
93 | #define BI_SHIFT 12 | 93 | #define BI_SHIFT 12 |
@@ -187,6 +187,7 @@ struct fsi_master { | |||
187 | u32 saved_iemsk; | 187 | u32 saved_iemsk; |
188 | u32 saved_imsk; | 188 | u32 saved_imsk; |
189 | u32 saved_clk_rst; | 189 | u32 saved_clk_rst; |
190 | u32 saved_soft_rst; | ||
190 | }; | 191 | }; |
191 | 192 | ||
192 | /* | 193 | /* |
@@ -556,20 +557,45 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) | |||
556 | } | 557 | } |
557 | 558 | ||
558 | /* | 559 | /* |
559 | * ctrl function | 560 | * clock function |
560 | */ | 561 | */ |
562 | #define fsi_module_init(m, d) __fsi_module_clk_ctrl(m, d, 1) | ||
563 | #define fsi_module_kill(m, d) __fsi_module_clk_ctrl(m, d, 0) | ||
564 | static void __fsi_module_clk_ctrl(struct fsi_master *master, | ||
565 | struct device *dev, | ||
566 | int enable) | ||
567 | { | ||
568 | pm_runtime_get_sync(dev); | ||
569 | |||
570 | if (enable) { | ||
571 | /* enable only SR */ | ||
572 | fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); | ||
573 | fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); | ||
574 | } else { | ||
575 | /* clear all registers */ | ||
576 | fsi_master_mask_set(master, SOFT_RST, FSISR, 0); | ||
577 | } | ||
578 | |||
579 | pm_runtime_put_sync(dev); | ||
580 | } | ||
561 | 581 | ||
562 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) | 582 | #define fsi_port_start(f) __fsi_port_clk_ctrl(f, 1) |
583 | #define fsi_port_stop(f) __fsi_port_clk_ctrl(f, 0) | ||
584 | static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable) | ||
563 | { | 585 | { |
564 | u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); | ||
565 | struct fsi_master *master = fsi_get_master(fsi); | 586 | struct fsi_master *master = fsi_get_master(fsi); |
587 | u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR; | ||
588 | u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; | ||
589 | int is_master = fsi_is_clk_master(fsi); | ||
566 | 590 | ||
567 | if (enable) | 591 | fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0); |
568 | fsi_master_mask_set(master, CLK_RST, val, val); | 592 | if (is_master) |
569 | else | 593 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
570 | fsi_master_mask_set(master, CLK_RST, val, 0); | ||
571 | } | 594 | } |
572 | 595 | ||
596 | /* | ||
597 | * ctrl function | ||
598 | */ | ||
573 | static void fsi_fifo_init(struct fsi_priv *fsi, | 599 | static void fsi_fifo_init(struct fsi_priv *fsi, |
574 | int is_play, | 600 | int is_play, |
575 | struct snd_soc_dai *dai) | 601 | struct snd_soc_dai *dai) |
@@ -622,18 +648,6 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
622 | } | 648 | } |
623 | } | 649 | } |
624 | 650 | ||
625 | static void fsi_soft_all_reset(struct fsi_master *master) | ||
626 | { | ||
627 | /* port AB reset */ | ||
628 | fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); | ||
629 | mdelay(10); | ||
630 | |||
631 | /* soft reset */ | ||
632 | fsi_master_mask_set(master, SOFT_RST, FSISR, 0); | ||
633 | fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); | ||
634 | mdelay(10); | ||
635 | } | ||
636 | |||
637 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | 651 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) |
638 | { | 652 | { |
639 | struct snd_pcm_runtime *runtime; | 653 | struct snd_pcm_runtime *runtime; |
@@ -818,10 +832,8 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
818 | 832 | ||
819 | fsi_irq_disable(fsi, is_play); | 833 | fsi_irq_disable(fsi, is_play); |
820 | 834 | ||
821 | if (fsi_is_clk_master(fsi)) { | 835 | if (fsi_is_clk_master(fsi)) |
822 | fsi_clk_ctrl(fsi, 0); | ||
823 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 836 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); |
824 | } | ||
825 | 837 | ||
826 | fsi->rate = 0; | 838 | fsi->rate = 0; |
827 | 839 | ||
@@ -843,8 +855,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
843 | frames_to_bytes(runtime, runtime->period_size)); | 855 | frames_to_bytes(runtime, runtime->period_size)); |
844 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); | 856 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); |
845 | fsi_irq_enable(fsi, is_play); | 857 | fsi_irq_enable(fsi, is_play); |
858 | fsi_port_start(fsi); | ||
846 | break; | 859 | break; |
847 | case SNDRV_PCM_TRIGGER_STOP: | 860 | case SNDRV_PCM_TRIGGER_STOP: |
861 | fsi_port_stop(fsi); | ||
848 | fsi_irq_disable(fsi, is_play); | 862 | fsi_irq_disable(fsi, is_play); |
849 | fsi_stream_pop(fsi, is_play); | 863 | fsi_stream_pop(fsi, is_play); |
850 | break; | 864 | break; |
@@ -1018,7 +1032,6 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
1018 | 1032 | ||
1019 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | 1033 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); |
1020 | udelay(10); | 1034 | udelay(10); |
1021 | fsi_clk_ctrl(fsi, 1); | ||
1022 | ret = 0; | 1035 | ret = 0; |
1023 | } | 1036 | } |
1024 | 1037 | ||
@@ -1233,9 +1246,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1233 | pm_runtime_enable(&pdev->dev); | 1246 | pm_runtime_enable(&pdev->dev); |
1234 | dev_set_drvdata(&pdev->dev, master); | 1247 | dev_set_drvdata(&pdev->dev, master); |
1235 | 1248 | ||
1236 | pm_runtime_get_sync(&pdev->dev); | 1249 | fsi_module_init(master, &pdev->dev); |
1237 | fsi_soft_all_reset(master); | ||
1238 | pm_runtime_put_sync(&pdev->dev); | ||
1239 | 1250 | ||
1240 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, | 1251 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, |
1241 | id_entry->name, master); | 1252 | id_entry->name, master); |
@@ -1279,6 +1290,8 @@ static int fsi_remove(struct platform_device *pdev) | |||
1279 | 1290 | ||
1280 | master = dev_get_drvdata(&pdev->dev); | 1291 | master = dev_get_drvdata(&pdev->dev); |
1281 | 1292 | ||
1293 | fsi_module_kill(master, &pdev->dev); | ||
1294 | |||
1282 | free_irq(master->irq, master); | 1295 | free_irq(master->irq, master); |
1283 | pm_runtime_disable(&pdev->dev); | 1296 | pm_runtime_disable(&pdev->dev); |
1284 | 1297 | ||
@@ -1334,6 +1347,9 @@ static int fsi_suspend(struct device *dev) | |||
1334 | master->saved_iemsk = fsi_core_read(master, iemsk); | 1347 | master->saved_iemsk = fsi_core_read(master, iemsk); |
1335 | master->saved_imsk = fsi_core_read(master, imsk); | 1348 | master->saved_imsk = fsi_core_read(master, imsk); |
1336 | master->saved_clk_rst = fsi_master_read(master, CLK_RST); | 1349 | master->saved_clk_rst = fsi_master_read(master, CLK_RST); |
1350 | master->saved_soft_rst = fsi_master_read(master, SOFT_RST); | ||
1351 | |||
1352 | fsi_module_kill(master, dev); | ||
1337 | 1353 | ||
1338 | pm_runtime_put_sync(dev); | 1354 | pm_runtime_put_sync(dev); |
1339 | 1355 | ||
@@ -1347,14 +1363,17 @@ static int fsi_resume(struct device *dev) | |||
1347 | 1363 | ||
1348 | pm_runtime_get_sync(dev); | 1364 | pm_runtime_get_sync(dev); |
1349 | 1365 | ||
1350 | __fsi_resume(&master->fsia, dev, set_rate); | 1366 | fsi_module_init(master, dev); |
1351 | __fsi_resume(&master->fsib, dev, set_rate); | ||
1352 | 1367 | ||
1368 | fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst); | ||
1369 | fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); | ||
1353 | fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); | 1370 | fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); |
1354 | fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk); | 1371 | fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk); |
1355 | fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); | 1372 | fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); |
1356 | fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); | 1373 | fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); |
1357 | fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); | 1374 | |
1375 | __fsi_resume(&master->fsia, dev, set_rate); | ||
1376 | __fsi_resume(&master->fsib, dev, set_rate); | ||
1358 | 1377 | ||
1359 | pm_runtime_put_sync(dev); | 1378 | pm_runtime_put_sync(dev); |
1360 | 1379 | ||