mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 15:13:44 -04:00
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
This commit is contained in:
@@ -163,17 +163,49 @@ 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,
|
||||
u32 rx_mask, int slots, int slot_width)
|
||||
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 = slots;
|
||||
sai->slot_width = slot_width;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int fsl_sai_set_dai_bclk_ratio(struct snd_soc_dai *dai,
|
||||
unsigned int ratio)
|
||||
{
|
||||
@@ -238,22 +270,22 @@ 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;
|
||||
}
|
||||
if (clk_id < 0 || clk_id >= FSL_SAI_MCLK_MAX) {
|
||||
dev_err(cpu_dai->dev, "Unknown clock id: %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ERR_OR_NULL(sai->mclk_clk[clk_id])) {
|
||||
dev_err(cpu_dai->dev, "Unassigned clock: %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (IS_ERR_OR_NULL(sai->mclk_clk[clk_id])) {
|
||||
dev_err(cpu_dai->dev, "Unassigned clock: %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sai->mclk_streams == 0) {
|
||||
ret = fsl_sai_set_mclk_rate(cpu_dai, clk_id, freq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
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);
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user