aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <Guangyu.Chen@freescale.com>2014-01-06 03:43:19 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:47:38 -0400
commit1f5e453015ae9881c9bede2fcbf62a4ab3a15f4b (patch)
treed0b958d195171a0887707577288f2b28c551419f
parent3d184d6f16500c70699df6e9a610af74a96e3955 (diff)
ENGR00295423-2 ASoC: fsl_ssi: Don't set clock rate in hw_params()
Leaving clk_set_rate() in hw_params() is a bit dangerous when handling two substreams. So we let set_sysclk() finish the clk_set_rate() directly. This patch also adds spinlock to protect the baud clock configuration so that it won't be broken during race. Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
-rw-r--r--sound/soc/fsl/fsl_ssi.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index ce18518add3d..46f574895f73 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -134,11 +134,12 @@ struct fsl_ssi_private {
134 struct device_attribute dev_attr; 134 struct device_attribute dev_attr;
135 struct platform_device *pdev; 135 struct platform_device *pdev;
136 136
137 unsigned long sysrate;
138 bool new_binding; 137 bool new_binding;
139 bool ssi_on_imx; 138 bool ssi_on_imx;
140 bool use_dual_fifo; 139 bool use_dual_fifo;
140 bool baudclk_locked;
141 u8 i2s_mode; 141 u8 i2s_mode;
142 spinlock_t baudclk_lock;
142 struct clk *coreclk; 143 struct clk *coreclk;
143 struct clk *clk; 144 struct clk *clk;
144 struct snd_dmaengine_dai_dma_data dma_params_tx; 145 struct snd_dmaengine_dai_dma_data dma_params_tx;
@@ -330,6 +331,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
330 struct fsl_ssi_private *ssi_private = 331 struct fsl_ssi_private *ssi_private =
331 snd_soc_dai_get_drvdata(rtd->cpu_dai); 332 snd_soc_dai_get_drvdata(rtd->cpu_dai);
332 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; 333 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
334 unsigned long flags;
333 335
334 if (ssi_private->ssi_on_imx) { 336 if (ssi_private->ssi_on_imx) {
335 pm_runtime_get_sync(dai->dev); 337 pm_runtime_get_sync(dai->dev);
@@ -428,6 +430,10 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
428 * this is bad is because at this point, the PCM driver has not 430 * this is bad is because at this point, the PCM driver has not
429 * finished initializing the DMA controller. 431 * finished initializing the DMA controller.
430 */ 432 */
433
434 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
435 ssi_private->baudclk_locked = false;
436 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
431 } 437 }
432 438
433 return 0; 439 return 0;
@@ -456,7 +462,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
456 u32 wl = CCSR_SSI_SxCCR_WL(sample_size); 462 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
457 int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; 463 int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
458 unsigned int channels = params_channels(hw_params); 464 unsigned int channels = params_channels(hw_params);
459 int ret;
460 465
461 /* 466 /*
462 * If we're in synchronous mode, and the SSI is already enabled, 467 * If we're in synchronous mode, and the SSI is already enabled,
@@ -465,14 +470,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
465 if (enabled && ssi_private->cpu_dai_drv.symmetric_rates) 470 if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
466 return 0; 471 return 0;
467 472
468 if (ssi_private->sysrate) {
469 ret = clk_set_rate(ssi_private->clk, ssi_private->sysrate);
470 if (ret) {
471 dev_err(cpu_dai->dev, "failed to set clock rate\n");
472 return ret;
473 }
474 }
475
476 /* 473 /*
477 * FIXME: The documentation says that SxCCR[WL] should not be 474 * FIXME: The documentation says that SxCCR[WL] should not be
478 * modified while the SSI is enabled. The only time this can 475 * modified while the SSI is enabled. The only time this can
@@ -511,6 +508,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
511 struct snd_soc_pcm_runtime *rtd = substream->private_data; 508 struct snd_soc_pcm_runtime *rtd = substream->private_data;
512 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); 509 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
513 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 510 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
511 unsigned long flags;
514 512
515 switch (cmd) { 513 switch (cmd) {
516 case SNDRV_PCM_TRIGGER_START: 514 case SNDRV_PCM_TRIGGER_START:
@@ -538,8 +536,12 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
538 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); 536 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
539 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RDMAE, 0); 537 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RDMAE, 0);
540 } 538 }
541 if ((read_ssi(&ssi->scr) & (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) 539 if ((read_ssi(&ssi->scr) & (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) {
542 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); 540 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
541 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
542 ssi_private->baudclk_locked = false;
543 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
544 }
543 break; 545 break;
544 546
545 default: 547 default:
@@ -669,9 +671,9 @@ static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
669{ 671{
670 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); 672 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
671 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 673 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
672 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; 674 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
673 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; 675 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
674 unsigned long clkrate, sysrate = 0; 676 unsigned long clkrate, sysrate = 0, baudrate, flags;
675 u64 sub, savesub = 100000; 677 u64 sub, savesub = 100000;
676 678
677 /* 679 /*
@@ -708,7 +710,7 @@ static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
708 do_div(sub, freq); 710 do_div(sub, freq);
709 711
710 if (sub < savesub) { 712 if (sub < savesub) {
711 ssi_private->sysrate = sysrate; 713 baudrate = sysrate;
712 savesub = sub; 714 savesub = sub;
713 pm = i; 715 pm = i;
714 } 716 }
@@ -734,6 +736,18 @@ static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
734 else 736 else
735 write_ssi_mask(&ssi->srccr, mask, stccr); 737 write_ssi_mask(&ssi->srccr, mask, stccr);
736 738
739 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
740 if (!ssi_private->baudclk_locked) {
741 ret = clk_set_rate(ssi_private->clk, baudrate);
742 if (ret) {
743 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
744 dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
745 return -EINVAL;
746 }
747 ssi_private->baudclk_locked = true;
748 }
749 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
750
737 return 0; 751 return 0;
738} 752}
739 753
@@ -775,8 +789,6 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
775 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 789 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
776 790
777 write_ssi_mask(&ssi->sier, SIER_FLAGS, 0); 791 write_ssi_mask(&ssi->sier, SIER_FLAGS, 0);
778
779 ssi_private->sysrate = 0;
780 } 792 }
781 793
782 if (ssi_private->ssi_on_imx) { 794 if (ssi_private->ssi_on_imx) {
@@ -974,6 +986,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
974 /* Older 8610 DTs didn't have the fifo-depth property */ 986 /* Older 8610 DTs didn't have the fifo-depth property */
975 ssi_private->fifo_depth = 8; 987 ssi_private->fifo_depth = 8;
976 988
989 ssi_private->baudclk_locked = false;
990 spin_lock_init(&ssi_private->baudclk_lock);
991
977 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { 992 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
978 ssi_private->ssi_on_imx = true; 993 ssi_private->ssi_on_imx = true;
979 994
@@ -1004,8 +1019,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1004 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); 1019 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
1005 } 1020 }
1006 1021
1007 ssi_private->sysrate = 0;
1008
1009 /* Initialize the the device_attribute structure */ 1022 /* Initialize the the device_attribute structure */
1010 dev_attr = &ssi_private->dev_attr; 1023 dev_attr = &ssi_private->dev_attr;
1011 sysfs_attr_init(&dev_attr->attr); 1024 sysfs_attr_init(&dev_attr->attr);