/** * fsl_ssi_startup: create a new substream * * This is the first function called when a stream is opened. * * If this is the first stream open, then grab the IRQ and program most of * the SSI registers. */ static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); /* * If this is the first stream opened, then request the IRQ * and initialize the SSI registers. */ if (!ssi_private->playback && !ssi_private->capture) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; int ret; /* The 'name' should not have any slashes in it. */ ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { dev_err(substream->pcm->card->dev, "could not claim irq %u\n", ssi_private->irq); return ret; } /* * Section 16.5 of the MPC8610 reference manual says that the * SSI needs to be disabled before updating the registers we set * here. */ clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); /* * Program the SSI into I2S Slave Non-Network Synchronous mode. * Also enable the transmit and receive FIFO. * * FIXME: Little-endian samples require a different shift dir */ clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN)); out_be32(&ssi->stcr, CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP); out_be32(&ssi->srcr, CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP); /* * The DC and PM bits are only used if the SSI is the clock * master. */ /* 4. Enable the interrupts and DMA requests */ out_be32(&ssi->sier, SIER_FLAGS); /* * Set the watermark for transmit FIFI 0 and receive FIFO 0. We * don't use FIFO 1. We program the transmit water to signal a * DMA transfer if there are only two (or fewer) elements left * in the FIFO. Two elements equals one frame (left channel, * right channel). This value, however, depends on the depth of * the transmit buffer. * * We program the receive FIFO to notify us if at least two * elements (one frame) have been written to the FIFO. We could * make this value larger (and maybe we should), but this way * data will be written to memory as soon as it's available. */ out_be32(&ssi->sfcsr, CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2)); /* * We keep the SSI disabled because if we enable it, then the * DMA controller will start. It's not supposed to start until * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The * DMA controller will transfer one "BWC" of data (i.e. the * amount of data that the MR.BWC bits are set to). The reason * this is bad is because at this point, the PCM driver has not * finished initializing the DMA controller. */ } if (!ssi_private->first_stream) ssi_private->first_stream = substream; else { /* This is the second stream open, so we need to impose sample * rate and maybe sample size constraints. Note that this can * cause a race condition if the second stream is opened before * the first stream is fully initialized. * * We provide some protection by checking to make sure the first * stream is initialized, but it's not perfect. ALSA sometimes * re-initializes the driver with a different sample rate or * size. If the second stream is opened before the first stream * has received its final parameters, then the second stream may * be constrained to the wrong sample rate or size. * * FIXME: This code does not handle opening and closing streams * repeatedly. If you open two streams and then close the first * one, you may not be able to open another stream until you * close the second one as well. */ struct snd_pcm_runtime *first_runtime = ssi_private->first_stream->runtime; if (!first_runtime->sample_bits) { dev_err(substream->pcm->card->dev, "set sample size in %s stream first\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "capture" : "playback"); return -EAGAIN; } /* If we're in synchronous mode, then we need to constrain * the sample size as well. We don't support independent sample * rates in asynchronous mode. */ if (!ssi_private->asynchronous) snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, first_runtime->sample_bits, first_runtime->sample_bits); ssi_private->second_stream = substream; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ssi_private->playback++; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ssi_private->capture++; return 0; }
/** * fsl_ssi_startup: create a new substream * * This is the first function called when a stream is opened. * * If this is the first stream open, then grab the IRQ and program most of * the SSI registers. */ static int fsl_ssi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; /* * If this is the first stream opened, then request the IRQ * and initialize the SSI registers. */ if (!ssi_private->playback && !ssi_private->capture) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; int ret; ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { dev_err(substream->pcm->card->dev, "could not claim irq %u\n", ssi_private->irq); return ret; } /* * Section 16.5 of the MPC8610 reference manual says that the * SSI needs to be disabled before updating the registers we set * here. */ clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); /* * Program the SSI into I2S Slave Non-Network Synchronous mode. * Also enable the transmit and receive FIFO. * * FIXME: Little-endian samples require a different shift dir */ clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK, CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN); out_be32(&ssi->stcr, CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP); out_be32(&ssi->srcr, CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP); /* * The DC and PM bits are only used if the SSI is the clock * master. */ /* 4. Enable the interrupts and DMA requests */ out_be32(&ssi->sier, CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN); /* * Set the watermark for transmit FIFI 0 and receive FIFO 0. We * don't use FIFO 1. Since the SSI only supports stereo, the * watermark should never be an odd number. */ out_be32(&ssi->sfcsr, CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); /* * We keep the SSI disabled because if we enable it, then the * DMA controller will start. It's not supposed to start until * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The * DMA controller will transfer one "BWC" of data (i.e. the * amount of data that the MR.BWC bits are set to). The reason * this is bad is because at this point, the PCM driver has not * finished initializing the DMA controller. */ } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ssi_private->playback++; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ssi_private->capture++; return 0; }
/** * fsl_ssi_startup: create a new substream * * This is the first function called when a stream is opened. * * If this is the first stream open, then grab the IRQ and program most of * the SSI registers. */ static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; 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); clk_prepare_enable(ssi_private->coreclk); clk_prepare_enable(ssi_private->clk); /* When using dual fifo mode, it would be safer if we ensure * its period size to be an even number. If appearing to an * odd number, the 2nd fifo might be neglected by SDMA sciprt * at the end of each period. */ if (ssi_private->use_dual_fifo) snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); } /* * If this is the first stream opened, then request the IRQ * and initialize the SSI registers. */ if (!dai->active) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; /* * Section 16.5 of the MPC8610 reference manual says that the * SSI needs to be disabled before updating the registers we set * here. */ write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); /* * Program the SSI into I2S Slave Non-Network Synchronous mode. * Also enable the transmit and receive FIFO. * * FIXME: Little-endian samples require a different shift dir */ ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, CCSR_SSI_SCR_TFR_CLK_DIS | ssi_private->i2s_mode | (synchronous ? CCSR_SSI_SCR_SYN : 0)); write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr); write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); /* * The DC and PM bits are only used if the SSI is the clock * master. */ /* Enable the interrupts and DMA requests */ write_ssi(SIER_FLAGS, &ssi->sier); /* * Set the watermark for transmit FIFI 0 and receive FIFO 0. We * don't use FIFO 1. We program the transmit water to signal a * DMA transfer if there are only two (or fewer) elements left * in the FIFO. Two elements equals one frame (left channel, * right channel). This value, however, depends on the depth of * the transmit buffer. * * We program the receive FIFO to notify us if at least two * elements (one frame) have been written to the FIFO. We could * make this value larger (and maybe we should), but this way * data will be written to memory as soon as it's available. */ write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2) | CCSR_SSI_SFCSR_TFWM1(ssi_private->fifo_depth - 2) | CCSR_SSI_SFCSR_RFWM1(ssi_private->fifo_depth - 2), &ssi->sfcsr); /* Select Single/Dual fifo mode */ if (ssi_private->use_dual_fifo) { write_ssi_mask(&ssi->srcr, 0, CCSR_SSI_SRCR_RFEN1); write_ssi_mask(&ssi->stcr, 0, CCSR_SSI_STCR_TFEN1); write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TCH_EN); } else { write_ssi_mask(&ssi->srcr, CCSR_SSI_SRCR_RFEN1, 0); write_ssi_mask(&ssi->stcr, CCSR_SSI_STCR_TFEN1, 0); write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TCH_EN, 0); } /* * We keep the SSI disabled because if we enable it, then the * DMA controller will start. It's not supposed to start until * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The * DMA controller will transfer one "BWC" of data (i.e. the * amount of data that the MR.BWC bits are set to). The reason * this is bad is because at this point, the PCM driver has not * finished initializing the DMA controller. */ /* Set default slot number -- 2 */ write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK, CCSR_SSI_SxCCR_DC(2)); write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK, CCSR_SSI_SxCCR_DC(2)); spin_lock_irqsave(&ssi_private->baudclk_lock, flags); ssi_private->baudclk_locked = false; spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); } return 0; }
static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; if (!ssi_private->playback && !ssi_private->capture) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; int ret; ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { dev_err(substream->pcm->card->dev, "could not claim irq %u\n", ssi_private->irq); return ret; } clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN)); out_be32(&ssi->stcr, CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP); out_be32(&ssi->srcr, CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP); out_be32(&ssi->sier, SIER_FLAGS); out_be32(&ssi->sfcsr, CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); } if (!ssi_private->first_stream) ssi_private->first_stream = substream; else { struct snd_pcm_runtime *first_runtime = ssi_private->first_stream->runtime; if (!first_runtime->sample_bits) { dev_err(substream->pcm->card->dev, "set sample size in %s stream first\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "capture" : "playback"); return -EAGAIN; } if (!ssi_private->asynchronous) snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, first_runtime->sample_bits, first_runtime->sample_bits); ssi_private->second_stream = substream; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ssi_private->playback++; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ssi_private->capture++; return 0; }
/** * fsl_ssi_startup: create a new substream * * This is the first function called when a stream is opened. * * If this is the first stream open, then grab the IRQ and program most of * the SSI registers. */ static int fsl_ssi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; /* * If this is the first stream opened, then request the IRQ * and initialize the SSI registers. */ if (!ssi_private->playback && !ssi_private->capture) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; int ret; ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { dev_err(substream->pcm->card->dev, "could not claim irq %u\n", ssi_private->irq); return ret; } /* * Section 16.5 of the MPC8610 reference manual says that the * SSI needs to be disabled before updating the registers we set * here. */ clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); /* * Program the SSI into I2S Slave Non-Network Synchronous mode. * Also enable the transmit and receive FIFO. * * FIXME: Little-endian samples require a different shift dir */ clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK, CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN); out_be32(&ssi->stcr, CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP); out_be32(&ssi->srcr, CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP); /* * The DC and PM bits are only used if the SSI is the clock * master. */ /* 4. Enable the interrupts and DMA requests */ out_be32(&ssi->sier, CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN); /* * Set the watermark for transmit FIFI 0 and receive FIFO 0. We * don't use FIFO 1. Since the SSI only supports stereo, the * watermark should never be an odd number. */ out_be32(&ssi->sfcsr, CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); /* * We keep the SSI disabled because if we enable it, then the * DMA controller will start. It's not supposed to start until * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The * DMA controller will transfer one "BWC" of data (i.e. the * amount of data that the MR.BWC bits are set to). The reason * this is bad is because at this point, the PCM driver has not * finished initializing the DMA controller. */ } if (!ssi_private->first_stream) ssi_private->first_stream = substream; else { /* This is the second stream open, so we need to impose sample * rate and maybe sample size constraints. Note that this can * cause a race condition if the second stream is opened before * the first stream is fully initialized. * * We provide some protection by checking to make sure the first * stream is initialized, but it's not perfect. ALSA sometimes * re-initializes the driver with a different sample rate or * size. If the second stream is opened before the first stream * has received its final parameters, then the second stream may * be constrained to the wrong sample rate or size. * * FIXME: This code does not handle opening and closing streams * repeatedly. If you open two streams and then close the first * one, you may not be able to open another stream until you * close the second one as well. */ struct snd_pcm_runtime *first_runtime = ssi_private->first_stream->runtime; if (!first_runtime->rate || !first_runtime->sample_bits) { dev_err(substream->pcm->card->dev, "set sample rate and size in %s stream first\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "capture" : "playback"); return -EAGAIN; } snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, first_runtime->rate, first_runtime->rate); snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, first_runtime->sample_bits, first_runtime->sample_bits); ssi_private->second_stream = substream; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ssi_private->playback++; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ssi_private->capture++; return 0; }