aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZidan Wang <zidan.wang@freescale.com>2015-11-24 02:31:54 -0500
committerMark Brown <broonie@kernel.org>2015-11-25 07:03:30 -0500
commitc1df29648f1e3ffb8bac38e27a22b50f5c019adf (patch)
tree8466c9c78537b40e8c30b3d969ae582bfdffa6c5
parent51659ca069ce5bdf20675a7967a39ef8419e87f2 (diff)
ASoC: fsl_sai: add tdm slots operation support
Add tdm slots operation support. If tdm slots and slot width have been configured in machine driver, we should use these values. Otherwise, using relevant channels and word length to set slots and slot width. SAI will generate BCLK depends on sample rate, slots and slot width. And there may be unused BCLK cycles before each LRCLK transition. Signed-off-by: Zidan Wang <zidan.wang@freescale.com> Acked-by: Nicolin Chen <nicoleotsuka@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/fsl/fsl_sai.c31
-rw-r--r--sound/soc/fsl/fsl_sai.h3
2 files changed, 28 insertions, 6 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 520dbadaa8b1..43ba5dc26775 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -126,6 +126,17 @@ out:
126 return IRQ_HANDLED; 126 return IRQ_HANDLED;
127} 127}
128 128
129static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
130 u32 rx_mask, int slots, int slot_width)
131{
132 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
133
134 sai->slots = slots;
135 sai->slot_width = slot_width;
136
137 return 0;
138}
139
129static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, 140static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
130 int clk_id, unsigned int freq, int fsl_dir) 141 int clk_id, unsigned int freq, int fsl_dir)
131{ 142{
@@ -395,11 +406,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
395 unsigned int channels = params_channels(params); 406 unsigned int channels = params_channels(params);
396 u32 word_width = snd_pcm_format_width(params_format(params)); 407 u32 word_width = snd_pcm_format_width(params_format(params));
397 u32 val_cr4 = 0, val_cr5 = 0; 408 u32 val_cr4 = 0, val_cr5 = 0;
409 u32 slots = (channels == 1) ? 2 : channels;
410 u32 slot_width = word_width;
398 int ret; 411 int ret;
399 412
413 if (sai->slots)
414 slots = sai->slots;
415
416 if (sai->slot_width)
417 slot_width = sai->slot_width;
418
400 if (!sai->is_slave_mode) { 419 if (!sai->is_slave_mode) {
401 ret = fsl_sai_set_bclk(cpu_dai, tx, 420 ret = fsl_sai_set_bclk(cpu_dai, tx,
402 2 * word_width * params_rate(params)); 421 slots * slot_width * params_rate(params));
403 if (ret) 422 if (ret)
404 return ret; 423 return ret;
405 424
@@ -411,21 +430,20 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
411 430
412 sai->mclk_streams |= BIT(substream->stream); 431 sai->mclk_streams |= BIT(substream->stream);
413 } 432 }
414
415 } 433 }
416 434
417 if (!sai->is_dsp_mode) 435 if (!sai->is_dsp_mode)
418 val_cr4 |= FSL_SAI_CR4_SYWD(word_width); 436 val_cr4 |= FSL_SAI_CR4_SYWD(slot_width);
419 437
420 val_cr5 |= FSL_SAI_CR5_WNW(word_width); 438 val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
421 val_cr5 |= FSL_SAI_CR5_W0W(word_width); 439 val_cr5 |= FSL_SAI_CR5_W0W(slot_width);
422 440
423 if (sai->is_lsb_first) 441 if (sai->is_lsb_first)
424 val_cr5 |= FSL_SAI_CR5_FBT(0); 442 val_cr5 |= FSL_SAI_CR5_FBT(0);
425 else 443 else
426 val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); 444 val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
427 445
428 val_cr4 |= FSL_SAI_CR4_FRSZ(channels); 446 val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
429 447
430 /* 448 /*
431 * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will 449 * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
@@ -591,6 +609,7 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
591static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { 609static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
592 .set_sysclk = fsl_sai_set_dai_sysclk, 610 .set_sysclk = fsl_sai_set_dai_sysclk,
593 .set_fmt = fsl_sai_set_dai_fmt, 611 .set_fmt = fsl_sai_set_dai_fmt,
612 .set_tdm_slot = fsl_sai_set_dai_tdm_slot,
594 .hw_params = fsl_sai_hw_params, 613 .hw_params = fsl_sai_hw_params,
595 .hw_free = fsl_sai_hw_free, 614 .hw_free = fsl_sai_hw_free,
596 .trigger = fsl_sai_trigger, 615 .trigger = fsl_sai_trigger,
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index b95fbc3f68eb..d9ed7be8cb34 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -143,6 +143,9 @@ struct fsl_sai {
143 143
144 unsigned int mclk_id[2]; 144 unsigned int mclk_id[2];
145 unsigned int mclk_streams; 145 unsigned int mclk_streams;
146 unsigned int slots;
147 unsigned int slot_width;
148
146 struct snd_dmaengine_dai_dma_data dma_params_rx; 149 struct snd_dmaengine_dai_dma_data dma_params_rx;
147 struct snd_dmaengine_dai_dma_data dma_params_tx; 150 struct snd_dmaengine_dai_dma_data dma_params_tx;
148}; 151};