Merge branch 'topic/fsl-sai' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-fsl
This commit is contained in:
commit
3d8d0bd078
|
@ -126,6 +126,17 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
sai->slots = slots;
|
||||
sai->slot_width = slot_width;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int fsl_dir)
|
||||
{
|
||||
|
@ -354,13 +365,25 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((tx && sai->synchronous[TX]) || (!tx && !sai->synchronous[RX])) {
|
||||
/*
|
||||
* 1) For Asynchronous mode, we must set RCR2 register for capture, and
|
||||
* set TCR2 register for playback.
|
||||
* 2) For Tx sync with Rx clock, we must set RCR2 register for playback
|
||||
* and capture.
|
||||
* 3) For Rx sync with Tx clock, we must set TCR2 register for playback
|
||||
* and capture.
|
||||
* 4) For Tx and Rx are both Synchronous with another SAI, we just
|
||||
* ignore it.
|
||||
*/
|
||||
if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
|
||||
(!tx && !sai->synchronous[RX])) {
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
|
||||
FSL_SAI_CR2_MSEL_MASK,
|
||||
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
|
||||
FSL_SAI_CR2_DIV_MASK, savediv - 1);
|
||||
} else {
|
||||
} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
|
||||
(tx && !sai->synchronous[TX])) {
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
|
||||
FSL_SAI_CR2_MSEL_MASK,
|
||||
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
|
||||
|
@ -383,11 +406,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
|
|||
unsigned int channels = params_channels(params);
|
||||
u32 word_width = snd_pcm_format_width(params_format(params));
|
||||
u32 val_cr4 = 0, val_cr5 = 0;
|
||||
u32 slots = (channels == 1) ? 2 : channels;
|
||||
u32 slot_width = word_width;
|
||||
int ret;
|
||||
|
||||
if (sai->slots)
|
||||
slots = sai->slots;
|
||||
|
||||
if (sai->slot_width)
|
||||
slot_width = sai->slot_width;
|
||||
|
||||
if (!sai->is_slave_mode) {
|
||||
ret = fsl_sai_set_bclk(cpu_dai, tx,
|
||||
2 * word_width * params_rate(params));
|
||||
slots * slot_width * params_rate(params));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -399,21 +430,49 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
sai->mclk_streams |= BIT(substream->stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!sai->is_dsp_mode)
|
||||
val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
|
||||
val_cr4 |= FSL_SAI_CR4_SYWD(slot_width);
|
||||
|
||||
val_cr5 |= FSL_SAI_CR5_WNW(word_width);
|
||||
val_cr5 |= FSL_SAI_CR5_W0W(word_width);
|
||||
val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
|
||||
val_cr5 |= FSL_SAI_CR5_W0W(slot_width);
|
||||
|
||||
if (sai->is_lsb_first)
|
||||
val_cr5 |= FSL_SAI_CR5_FBT(0);
|
||||
else
|
||||
val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
|
||||
|
||||
val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
|
||||
val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
|
||||
|
||||
/*
|
||||
* For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
|
||||
* generate bclk and frame clock for Tx(Rx), we should set RCR4(TCR4),
|
||||
* RCR5(TCR5) and RMR(TMR) for playback(capture), or there will be sync
|
||||
* error.
|
||||
*/
|
||||
|
||||
if (!sai->is_slave_mode) {
|
||||
if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
|
||||
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
|
||||
val_cr4);
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
|
||||
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
|
||||
FSL_SAI_CR5_FBT_MASK, val_cr5);
|
||||
regmap_write(sai->regmap, FSL_SAI_TMR,
|
||||
~0UL - ((1 << channels) - 1));
|
||||
} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
|
||||
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
|
||||
val_cr4);
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
|
||||
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
|
||||
FSL_SAI_CR5_FBT_MASK, val_cr5);
|
||||
regmap_write(sai->regmap, FSL_SAI_RMR,
|
||||
~0UL - ((1 << channels) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
|
||||
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
|
||||
|
@ -550,6 +609,7 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
|
|||
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
|
||||
.set_sysclk = fsl_sai_set_dai_sysclk,
|
||||
.set_fmt = fsl_sai_set_dai_fmt,
|
||||
.set_tdm_slot = fsl_sai_set_dai_tdm_slot,
|
||||
.hw_params = fsl_sai_hw_params,
|
||||
.hw_free = fsl_sai_hw_free,
|
||||
.trigger = fsl_sai_trigger,
|
||||
|
|
|
@ -143,6 +143,9 @@ struct fsl_sai {
|
|||
|
||||
unsigned int mclk_id[2];
|
||||
unsigned int mclk_streams;
|
||||
unsigned int slots;
|
||||
unsigned int slot_width;
|
||||
|
||||
struct snd_dmaengine_dai_dma_data dma_params_rx;
|
||||
struct snd_dmaengine_dai_dma_data dma_params_tx;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue