Unverified Commit 8e5e0e71 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: fsl_sai: add several improvements

Merge series from Shengjiu Wang <shengjiu.wang@nxp.com>:

Add several improvements for the sai interface.
1.allow to set mclk rate with zero clk_id for master mode
2.add xlate_tdm_slot_mask() callback to avoid channel constrain
3.separate 'is_dsp_mode' for tx and rx
4.separate set_tdm_slot() for tx and rx
parents 94112d3d 1d911979
Loading
Loading
Loading
Loading
+62 −28
Original line number Diff line number Diff line
@@ -163,14 +163,46 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
	return iret;
}

static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
static int fsl_sai_set_dai_tdm_slot_tx(struct snd_soc_dai *cpu_dai, u32 tx_mask,
				       u32 rx_mask, int slots, int slot_width)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
	bool tx = true;

	sai->slots[tx] = slots;
	sai->slot_width[tx] = slot_width;

	return 0;
}

static int fsl_sai_set_dai_tdm_slot_rx(struct snd_soc_dai *cpu_dai, u32 tx_mask,
				       u32 rx_mask, int slots, int slot_width)
{
	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
	bool tx = false;

	sai->slots[tx] = slots;
	sai->slot_width[tx] = slot_width;

	return 0;
}

	sai->slots = slots;
	sai->slot_width = slot_width;
static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
				    u32 rx_mask, int slots, int slot_width)
{
	int ret;

	ret = fsl_sai_set_dai_tdm_slot_tx(cpu_dai, tx_mask, rx_mask, slots, slot_width);
	if (ret)
		return ret;

	return fsl_sai_set_dai_tdm_slot_rx(cpu_dai, tx_mask, rx_mask, slots, slot_width);
}

static int fsl_sai_xlate_tdm_slot_mask(unsigned int slots,
				       unsigned int *tx_mask, unsigned int *rx_mask)
{
	/* Leave it empty, don't change the value of tx_mask and rx_mask */
	return 0;
}

@@ -238,7 +270,6 @@ static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
	if (dir == SND_SOC_CLOCK_IN)
		return 0;

	if (freq > 0 && clk_id != FSL_SAI_CLK_BUS) {
	if (clk_id < 0 || clk_id >= FSL_SAI_MCLK_MAX) {
		dev_err(cpu_dai->dev, "Unknown clock id: %d\n", clk_id);
		return -EINVAL;
@@ -249,12 +280,13 @@ static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
		return -EINVAL;
	}

		if (sai->mclk_streams == 0) {
			ret = fsl_sai_set_mclk_rate(cpu_dai, clk_id, freq);
	if (sai->mclk_streams == 0 && freq > 0) {
		ret = fsl_sai_set_mclk_rate(cpu_dai,
					    clk_id ? clk_id : FSL_SAI_CLK_MAST1,
					    freq);
		if (ret < 0)
			return ret;
	}
	}

	ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, true);
	if (ret) {
@@ -280,7 +312,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
		val_cr4 |= FSL_SAI_CR4_MF;

	sai->is_pdm_mode = false;
	sai->is_dsp_mode = false;
	sai->is_dsp_mode[tx] = false;
	/* DAI mode */
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
@@ -309,7 +341,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
		 */
		val_cr2 |= FSL_SAI_CR2_BCP;
		val_cr4 |= FSL_SAI_CR4_FSE;
		sai->is_dsp_mode = true;
		sai->is_dsp_mode[tx] = true;
		break;
	case SND_SOC_DAIFMT_DSP_B:
		/*
@@ -317,7 +349,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
		 * frame sync asserts with the first bit of the frame.
		 */
		val_cr2 |= FSL_SAI_CR2_BCP;
		sai->is_dsp_mode = true;
		sai->is_dsp_mode[tx] = true;
		break;
	case SND_SOC_DAIFMT_PDM:
		val_cr2 |= FSL_SAI_CR2_BCP;
@@ -541,11 +573,11 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
	u32 watermark;
	int ret, i;

	if (sai->slot_width)
		slot_width = sai->slot_width;
	if (sai->slot_width[tx])
		slot_width = sai->slot_width[tx];

	if (sai->slots)
		slots = sai->slots;
	if (sai->slots[tx])
		slots = sai->slots[tx];
	else if (sai->bclk_ratio)
		slots = sai->bclk_ratio / slot_width;

@@ -600,7 +632,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
		}
	}

	if (!sai->is_dsp_mode && !sai->is_pdm_mode)
	if (!sai->is_dsp_mode[tx] && !sai->is_pdm_mode)
		val_cr4 |= FSL_SAI_CR4_SYWD(slot_width);

	val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
@@ -932,7 +964,8 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_tx_ops = {
	.set_bclk_ratio	= fsl_sai_set_dai_bclk_ratio,
	.set_sysclk	= fsl_sai_set_dai_sysclk,
	.set_fmt	= fsl_sai_set_dai_fmt_tx,
	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot,
	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot_tx,
	.xlate_tdm_slot_mask = fsl_sai_xlate_tdm_slot_mask,
	.hw_params	= fsl_sai_hw_params,
	.hw_free	= fsl_sai_hw_free,
	.trigger	= fsl_sai_trigger,
@@ -944,7 +977,8 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_rx_ops = {
	.set_bclk_ratio	= fsl_sai_set_dai_bclk_ratio,
	.set_sysclk	= fsl_sai_set_dai_sysclk,
	.set_fmt	= fsl_sai_set_dai_fmt_rx,
	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot,
	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot_rx,
	.xlate_tdm_slot_mask = fsl_sai_xlate_tdm_slot_mask,
	.hw_params	= fsl_sai_hw_params,
	.hw_free	= fsl_sai_hw_free,
	.trigger	= fsl_sai_trigger,
+3 −3
Original line number Diff line number Diff line
@@ -286,7 +286,7 @@ struct fsl_sai {

	bool is_consumer_mode[2];
	bool is_lsb_first;
	bool is_dsp_mode;
	bool is_dsp_mode[2];
	bool is_pdm_mode;
	bool is_multi_fifo_dma;
	bool synchronous[2];
@@ -296,8 +296,8 @@ struct fsl_sai {

	unsigned int mclk_id[2];
	unsigned int mclk_streams;
	unsigned int slots;
	unsigned int slot_width;
	unsigned int slots[2];
	unsigned int slot_width[2];
	unsigned int bclk_ratio;

	const struct fsl_sai_soc_data *soc_data;