[alsa-devel] [PATCH 0/3] ASoC: atmel_ssc_dai: fix and refactor
This patch set do following things: - Fix the DSP mode A setting. - Refactor the startup and shutdown function. - Only clean PDC when use PDC.
Bo Shen (3): ASoC: atmel_ssc_dai: fix the setting for DSP mode ASoC: atmel_ssc_dai: refactor the startup and shutdown ASoC: atmel_ssc_dai: only clean PDC when using PDC
sound/soc/atmel/atmel_ssc_dai.c | 54 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 29 deletions(-)
When SCC work in DSP A mode, the data outputs/inputs are shift out on falling edge, the frame sync are sample on the rising edge.
Reported-by: Songjun Wu songjun.wu@atmel.com Signed-off-by: Bo Shen voice.shen@atmel.com ---
sound/soc/atmel/atmel_ssc_dai.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 99ff35e..c1d93b8 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -512,7 +512,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | SSC_BF(RCMR_STTDLY, 1) | SSC_BF(RCMR_START, SSC_START_RISING_RF) - | SSC_BF(RCMR_CKI, SSC_CKI_RISING) + | SSC_BF(RCMR_CKI, SSC_CKI_FALLING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
@@ -527,7 +527,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | SSC_BF(TCMR_STTDLY, 1) | SSC_BF(TCMR_START, SSC_START_RISING_RF) - | SSC_BF(TCMR_CKI, SSC_CKI_RISING) + | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
@@ -556,7 +556,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, rcmr = SSC_BF(RCMR_PERIOD, 0) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_RISING_RF) - | SSC_BF(RCMR_CKI, SSC_CKI_RISING) + | SSC_BF(RCMR_CKI, SSC_CKI_FALLING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? SSC_CKS_PIN : SSC_CKS_CLOCK);
In startup function, enable ssc clock and in shutdown function, disable clock. And also remove disable ssc in shutdown function, as ssc is disabled in prepare function.
Signed-off-by: Bo Shen voice.shen@atmel.com ---
sound/soc/atmel/atmel_ssc_dai.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-)
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index c1d93b8..0ed5ac3 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -204,6 +204,13 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", ssc_readl(ssc_p->ssc->regs, SR));
+ /* Enable PMC peripheral clock for this SSC */ + pr_debug("atmel_ssc_dai: Starting clock\n"); + clk_enable(ssc_p->ssc->clk); + + /* Reset the SSC to keep it at a clean status */ + ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dir = 0; dir_mask = SSC_DIR_MASK_PLAYBACK; @@ -250,11 +257,6 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, dma_params = ssc_p->dma_params[dir];
if (dma_params != NULL) { - ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); - pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n", - (dir ? "receive" : "transmit"), - ssc_readl(ssc_p->ssc->regs, SR)); - dma_params->ssc = NULL; dma_params->substream = NULL; ssc_p->dma_params[dir] = NULL; @@ -266,10 +268,6 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, ssc_p->dir_mask &= ~dir_mask; if (!ssc_p->dir_mask) { if (ssc_p->initialized) { - /* Shutdown the SSC clock. */ - pr_debug("atmel_ssc_dai: Stopping clock\n"); - clk_disable(ssc_p->ssc->clk); - free_irq(ssc_p->ssc->irq, ssc_p); ssc_p->initialized = 0; } @@ -280,6 +278,10 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; } spin_unlock_irq(&ssc_p->lock); + + /* Shutdown the SSC clock. */ + pr_debug("atmel_ssc_dai: Stopping clock\n"); + clk_disable(ssc_p->ssc->clk); }
@@ -597,14 +599,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, rcmr, rfmr, tcmr, tfmr);
if (!ssc_p->initialized) { - - /* Enable PMC peripheral clock for this SSC */ - pr_debug("atmel_ssc_dai: Starting clock\n"); - clk_enable(ssc_p->ssc->clk); - - /* Reset the SSC and its PDC registers */ - ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); - ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
On Fri, Jan 30, 2015 at 05:38:43PM +0800, Bo Shen wrote:
In startup function, enable ssc clock and in shutdown function, disable clock. And also remove disable ssc in shutdown function, as ssc is disabled in prepare function.
Applied, thanks. You probably want to convert to clk_prepare_enable() too but that's a separate thing.
Hi Mark,
On 01/30/2015 09:20 PM, Mark Brown wrote:
On Fri, Jan 30, 2015 at 05:38:43PM +0800, Bo Shen wrote:
In startup function, enable ssc clock and in shutdown function, disable clock. And also remove disable ssc in shutdown function, as ssc is disabled in prepare function.
Applied, thanks. You probably want to convert to clk_prepare_enable() too but that's a separate thing.
OK, thanks, I will check that. As now, we prepare clock in ssc driver, then enable it in dai driver.
Best Regards, Bo Shen
Only using PDC, it needs to clean PDC registers.
Signed-off-by: Bo Shen voice.shen@atmel.com ---
sound/soc/atmel/atmel_ssc_dai.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 0ed5ac3..80eb1f1 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -599,15 +599,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, rcmr, rfmr, tcmr, tfmr);
if (!ssc_p->initialized) { - ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); - - ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); + if (!ssc_p->ssc->pdata->use_dma) { + ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); + ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); + ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); + ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); + + ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); + ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); + ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); + ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); + }
ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, ssc_p->name, ssc_p);
participants (2)
-
Bo Shen
-
Mark Brown