struct device_attribute dev_attr;
struct platform_device *pdev;
- unsigned long sysrate;
bool new_binding;
bool ssi_on_imx;
bool use_dual_fifo;
+ bool baudclk_locked;
u8 i2s_mode;
+ spinlock_t baudclk_lock;
struct clk *coreclk;
struct clk *clk;
struct snd_dmaengine_dai_dma_data dma_params_tx;
struct fsl_ssi_private *ssi_private =
snd_soc_dai_get_drvdata(rtd->cpu_dai);
int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
+ unsigned long flags;
if (ssi_private->ssi_on_imx) {
pm_runtime_get_sync(dai->dev);
* this is bad is because at this point, the PCM driver has not
* finished initializing the DMA controller.
*/
+
+ spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
+ ssi_private->baudclk_locked = false;
+ spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
}
return 0;
u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
unsigned int channels = params_channels(hw_params);
- int ret;
/*
* If we're in synchronous mode, and the SSI is already enabled,
if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
return 0;
- if (ssi_private->sysrate) {
- ret = clk_set_rate(ssi_private->clk, ssi_private->sysrate);
- if (ret) {
- dev_err(cpu_dai->dev, "failed to set clock rate\n");
- return ret;
- }
- }
-
/*
* FIXME: The documentation says that SxCCR[WL] should not be
* modified while the SSI is enabled. The only time this can
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+ unsigned long flags;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RDMAE, 0);
}
- if ((read_ssi(&ssi->scr) & (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0)
+ if ((read_ssi(&ssi->scr) & (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) {
write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
+ spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
+ ssi_private->baudclk_locked = false;
+ spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
+ }
break;
default:
{
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
- int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
+ int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
- unsigned long clkrate, sysrate = 0;
+ unsigned long clkrate, sysrate = 0, baudrate, flags;
u64 sub, savesub = 100000;
/*
do_div(sub, freq);
if (sub < savesub) {
- ssi_private->sysrate = sysrate;
+ baudrate = sysrate;
savesub = sub;
pm = i;
}
else
write_ssi_mask(&ssi->srccr, mask, stccr);
+ spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
+ if (!ssi_private->baudclk_locked) {
+ ret = clk_set_rate(ssi_private->clk, baudrate);
+ if (ret) {
+ spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
+ dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
+ return -EINVAL;
+ }
+ ssi_private->baudclk_locked = true;
+ }
+ spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
+
return 0;
}
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
write_ssi_mask(&ssi->sier, SIER_FLAGS, 0);
-
- ssi_private->sysrate = 0;
}
if (ssi_private->ssi_on_imx) {
/* Older 8610 DTs didn't have the fifo-depth property */
ssi_private->fifo_depth = 8;
+ ssi_private->baudclk_locked = false;
+ spin_lock_init(&ssi_private->baudclk_lock);
+
if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
ssi_private->ssi_on_imx = true;
ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
}
- ssi_private->sysrate = 0;
-
/* Initialize the the device_attribute structure */
dev_attr = &ssi_private->dev_attr;
sysfs_attr_init(&dev_attr->attr);