aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <nicoleotsuka@gmail.com>2017-09-13 23:07:09 -0400
committerMark Brown <broonie@kernel.org>2017-09-19 08:15:55 -0400
commitb0a7043d5c2ccdd306959f295bf1a62be025cbf5 (patch)
tree1248070818a6b852714387f2f73de881d47bb8d4
parent2db5f9e9fa0ebc3c023f7ac906946a3eef8f5498 (diff)
ASoC: fsl_ssi: Caculate bit clock rate using slot number and width
The set_sysclk() now is used to override the output bit clock rate. But this is not a common way to implement a set_dai_sysclk(). And this creates a problem when a general machine driver (simple-card for example) tries to do set_dai_sysclk() by passing an input clock rate for the baud clock instead of setting the bit clock rate as fsl_ssi driver expected. So this patch solves this problem by firstly removing set_sysclk() since the hw_params() can calculate the bit clock rate. Secondly, in order not to break those TDM use cases which previously might have been using set_sysclk() to override the bit clock rate, this patch changes the driver to calculate the bit clock rate using the slot number and the slot width from the via set_tdm_slot(). The patch also removes an obsolete comment of the dir parameter. Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/fsl/fsl_ssi.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 64598d1183f8..f2f51e06e22c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -197,12 +197,13 @@ struct fsl_ssi_soc_data {
197 * @use_dma: DMA is used or FIQ with stream filter 197 * @use_dma: DMA is used or FIQ with stream filter
198 * @use_dual_fifo: DMA with support for both FIFOs used 198 * @use_dual_fifo: DMA with support for both FIFOs used
199 * @fifo_deph: Depth of the SSI FIFOs 199 * @fifo_deph: Depth of the SSI FIFOs
200 * @slot_width: width of each DAI slot
201 * @slots: number of slots
200 * @rxtx_reg_val: Specific register settings for receive/transmit configuration 202 * @rxtx_reg_val: Specific register settings for receive/transmit configuration
201 * 203 *
202 * @clk: SSI clock 204 * @clk: SSI clock
203 * @baudclk: SSI baud clock for master mode 205 * @baudclk: SSI baud clock for master mode
204 * @baudclk_streams: Active streams that are using baudclk 206 * @baudclk_streams: Active streams that are using baudclk
205 * @bitclk_freq: bitclock frequency set by .set_dai_sysclk
206 * 207 *
207 * @dma_params_tx: DMA transmit parameters 208 * @dma_params_tx: DMA transmit parameters
208 * @dma_params_rx: DMA receive parameters 209 * @dma_params_rx: DMA receive parameters
@@ -233,12 +234,13 @@ struct fsl_ssi_private {
233 bool use_dual_fifo; 234 bool use_dual_fifo;
234 bool has_ipg_clk_name; 235 bool has_ipg_clk_name;
235 unsigned int fifo_depth; 236 unsigned int fifo_depth;
237 unsigned int slot_width;
238 unsigned int slots;
236 struct fsl_ssi_rxtx_reg_val rxtx_reg_val; 239 struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
237 240
238 struct clk *clk; 241 struct clk *clk;
239 struct clk *baudclk; 242 struct clk *baudclk;
240 unsigned int baudclk_streams; 243 unsigned int baudclk_streams;
241 unsigned int bitclk_freq;
242 244
243 /* regcache for volatile regs */ 245 /* regcache for volatile regs */
244 u32 regcache_sfcsr; 246 u32 regcache_sfcsr;
@@ -700,8 +702,8 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
700 * Note: This function can be only called when using SSI as DAI master 702 * Note: This function can be only called when using SSI as DAI master
701 * 703 *
702 * Quick instruction for parameters: 704 * Quick instruction for parameters:
703 * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels 705 * freq: Output BCLK frequency = samplerate * slots * slot_width
704 * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK. 706 * (In 2-channel I2S Master mode, slot_width is fixed 32)
705 */ 707 */
706static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, 708static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
707 struct snd_soc_dai *cpu_dai, 709 struct snd_soc_dai *cpu_dai,
@@ -712,15 +714,21 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
712 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret; 714 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
713 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; 715 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
714 unsigned long clkrate, baudrate, tmprate; 716 unsigned long clkrate, baudrate, tmprate;
717 unsigned int slots = params_channels(hw_params);
718 unsigned int slot_width = 32;
715 u64 sub, savesub = 100000; 719 u64 sub, savesub = 100000;
716 unsigned int freq; 720 unsigned int freq;
717 bool baudclk_is_used; 721 bool baudclk_is_used;
718 722
719 /* Prefer the explicitly set bitclock frequency */ 723 /* Override slots and slot_width if being specifically set... */
720 if (ssi_private->bitclk_freq) 724 if (ssi_private->slots)
721 freq = ssi_private->bitclk_freq; 725 slots = ssi_private->slots;
722 else 726 /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
723 freq = params_channels(hw_params) * 32 * params_rate(hw_params); 727 if (ssi_private->slot_width && slots != 2)
728 slot_width = ssi_private->slot_width;
729
730 /* Generate bit clock based on the slot number and slot width */
731 freq = slots * slot_width * params_rate(hw_params);
724 732
725 /* Don't apply it to any non-baudclk circumstance */ 733 /* Don't apply it to any non-baudclk circumstance */
726 if (IS_ERR(ssi_private->baudclk)) 734 if (IS_ERR(ssi_private->baudclk))
@@ -805,16 +813,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
805 return 0; 813 return 0;
806} 814}
807 815
808static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
809 int clk_id, unsigned int freq, int dir)
810{
811 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
812
813 ssi_private->bitclk_freq = freq;
814
815 return 0;
816}
817
818/** 816/**
819 * fsl_ssi_hw_params - program the sample size 817 * fsl_ssi_hw_params - program the sample size
820 * 818 *
@@ -1095,6 +1093,12 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
1095 struct regmap *regs = ssi_private->regs; 1093 struct regmap *regs = ssi_private->regs;
1096 u32 val; 1094 u32 val;
1097 1095
1096 /* The word length should be 8, 10, 12, 16, 18, 20, 22 or 24 */
1097 if (slot_width & 1 || slot_width < 8 || slot_width > 24) {
1098 dev_err(cpu_dai->dev, "invalid slot width: %d\n", slot_width);
1099 return -EINVAL;
1100 }
1101
1098 /* The slot number should be >= 2 if using Network mode or I2S mode */ 1102 /* The slot number should be >= 2 if using Network mode or I2S mode */
1099 regmap_read(regs, CCSR_SSI_SCR, &val); 1103 regmap_read(regs, CCSR_SSI_SCR, &val);
1100 val &= CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET; 1104 val &= CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET;
@@ -1121,6 +1125,9 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
1121 1125
1122 regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val); 1126 regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val);
1123 1127
1128 ssi_private->slot_width = slot_width;
1129 ssi_private->slots = slots;
1130
1124 return 0; 1131 return 0;
1125} 1132}
1126 1133
@@ -1191,7 +1198,6 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
1191 .hw_params = fsl_ssi_hw_params, 1198 .hw_params = fsl_ssi_hw_params,
1192 .hw_free = fsl_ssi_hw_free, 1199 .hw_free = fsl_ssi_hw_free,
1193 .set_fmt = fsl_ssi_set_dai_fmt, 1200 .set_fmt = fsl_ssi_set_dai_fmt,
1194 .set_sysclk = fsl_ssi_set_dai_sysclk,
1195 .set_tdm_slot = fsl_ssi_set_dai_tdm_slot, 1201 .set_tdm_slot = fsl_ssi_set_dai_tdm_slot,
1196 .trigger = fsl_ssi_trigger, 1202 .trigger = fsl_ssi_trigger,
1197}; 1203};