ASoC: rockchip: i2s-tdm: Clean code

Change-Id: Ib4af14213873dac609d195976bd639bd6270e419
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
This commit is contained in:
Sugar Zhang 2020-11-04 18:15:31 +08:00 committed by Tao Huang
parent bd60226a17
commit baddcc7c35
2 changed files with 148 additions and 152 deletions

View File

@ -254,8 +254,8 @@ static void rockchip_snd_xfer_reset_deassert(struct rk_i2s_tdm_dev *i2s_tdm,
}
/*
* to make sure tx/rx reset at the same time when clk_trcm > 0
* if not, will lead lrck is abnormal.
* make sure both tx and rx are reset at the same time for sync lrck
* when clk_trcm > 0
*/
static void rockchip_snd_xfer_sync_reset(struct rk_i2s_tdm_dev *i2s_tdm)
{
@ -455,7 +455,6 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,
mask = I2S_CKR_MSS_MASK;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* Set source clock in Master mode */
val = I2S_CKR_MSS_MASTER;
i2s_tdm->is_master_mode = true;
break;
@ -473,10 +472,10 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,
mask = I2S_CKR_CKP_MASK;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
val = I2S_CKR_CKP_NEG;
val = I2S_CKR_CKP_NORMAL;
break;
case SND_SOC_DAIFMT_IB_NF:
val = I2S_CKR_CKP_POS;
val = I2S_CKR_CKP_INVERTED;
break;
default:
ret = -EINVAL;
@ -651,7 +650,6 @@ static int rockchip_i2s_tdm_calibrate_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
{
struct clk *mclk_root;
struct clk *mclk_parent;
/* It's 256 times higher than a high sample rate */
unsigned int mclk_parent_freq;
int ret;
@ -687,22 +685,12 @@ static int rockchip_i2s_tdm_calibrate_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
}
ret = clk_set_parent(mclk_parent, mclk_root);
if (ret < 0) {
dev_err(i2s_tdm->dev, "parent: %s set root: %s failed: %d\n",
__clk_get_name(mclk_parent),
__clk_get_name(mclk_root),
ret);
if (ret)
goto out;
}
ret = clk_set_rate(mclk_parent, mclk_parent_freq);
if (ret < 0) {
dev_err(i2s_tdm->dev, "parent: %s set freq: %d failed: %d\n",
__clk_get_name(mclk_parent),
mclk_parent_freq,
ret);
if (ret)
goto out;
}
out:
return ret;
@ -726,24 +714,14 @@ static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
}
ret = clk_set_rate(i2s_tdm->mclk_tx, i2s_tdm->mclk_tx_freq);
if (ret < 0) {
dev_err(i2s_tdm->dev,
"Set mclk_tx: %s freq: %d failed: %d\n",
__clk_get_name(i2s_tdm->mclk_tx),
i2s_tdm->mclk_tx_freq, ret);
if (ret)
goto err;
}
ret = clk_set_rate(i2s_tdm->mclk_rx, i2s_tdm->mclk_rx_freq);
if (ret < 0) {
dev_err(i2s_tdm->dev,
"Set mclk_rx: %s freq: %d failed: %d\n",
__clk_get_name(i2s_tdm->mclk_rx),
i2s_tdm->mclk_rx_freq, ret);
if (ret)
goto err;
}
/* Using mclk_rx is ok. */
/* mclk_rx is also ok. */
*mclk = i2s_tdm->mclk_tx;
} else {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@ -755,12 +733,8 @@ static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
}
ret = clk_set_rate(*mclk, mclk_freq);
if (ret < 0) {
dev_err(i2s_tdm->dev, "Set mclk_%s: %s freq: %d failed: %d\n",
substream->stream ? "rx" : "tx",
__clk_get_name(*mclk), mclk_freq, ret);
if (ret)
goto err;
}
}
return 0;
@ -769,6 +743,131 @@ static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
return ret;
}
static int rockchip_i2s_io_multiplex(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
int usable_chs = MULTIPLEX_CH_MAX;
unsigned int val = 0;
if (!i2s_tdm->io_multiplex)
return 0;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
struct snd_pcm_str *playback_str =
&substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (playback_str->substream_opened) {
regmap_read(i2s_tdm->regmap, I2S_TXCR, &val);
val &= I2S_TXCR_CSR_MASK;
usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val);
}
regmap_read(i2s_tdm->regmap, I2S_RXCR, &val);
val &= I2S_RXCR_CSR_MASK;
if (to_ch_num(val) > usable_chs) {
dev_err(i2s_tdm->dev,
"Capture chs(%d) > usable chs(%d)\n",
to_ch_num(val), usable_chs);
return -EINVAL;
}
switch (val) {
case I2S_CHN_4:
val = I2S_IO_6CH_OUT_4CH_IN;
break;
case I2S_CHN_6:
val = I2S_IO_4CH_OUT_6CH_IN;
break;
case I2S_CHN_8:
val = I2S_IO_2CH_OUT_8CH_IN;
break;
default:
val = I2S_IO_8CH_OUT_2CH_IN;
break;
}
} else {
struct snd_pcm_str *capture_str =
&substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
if (capture_str->substream_opened) {
regmap_read(i2s_tdm->regmap, I2S_RXCR, &val);
val &= I2S_RXCR_CSR_MASK;
usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val);
}
regmap_read(i2s_tdm->regmap, I2S_TXCR, &val);
val &= I2S_TXCR_CSR_MASK;
if (to_ch_num(val) > usable_chs) {
dev_err(i2s_tdm->dev,
"Playback chs(%d) > usable chs(%d)\n",
to_ch_num(val), usable_chs);
return -EINVAL;
}
switch (val) {
case I2S_CHN_4:
val = I2S_IO_4CH_OUT_6CH_IN;
break;
case I2S_CHN_6:
val = I2S_IO_6CH_OUT_4CH_IN;
break;
case I2S_CHN_8:
val = I2S_IO_8CH_OUT_2CH_IN;
break;
default:
val = I2S_IO_2CH_OUT_8CH_IN;
break;
}
}
val <<= i2s_tdm->soc_data->grf_shift;
val |= (I2S_IO_DIRECTION_MASK << i2s_tdm->soc_data->grf_shift) << 16;
regmap_write(i2s_tdm->grf, i2s_tdm->soc_data->grf_reg_offset, val);
return 0;
}
static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai,
unsigned int div_bclk,
unsigned int div_lrck,
unsigned int fmt)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
if (!i2s_tdm->clk_trcm)
return 0;
spin_lock(&i2s_tdm->lock);
if (atomic_read(&i2s_tdm->refcount))
rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm);
regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,
I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK,
I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk));
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK,
I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck));
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
regmap_update_bits(i2s_tdm->regmap, I2S_TXCR,
I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
fmt);
else
regmap_update_bits(i2s_tdm->regmap, I2S_RXCR,
I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,
fmt);
if (atomic_read(&i2s_tdm->refcount))
rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm);
spin_unlock(&i2s_tdm->lock);
return 0;
}
static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@ -833,23 +932,12 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
val |= I2S_CHN_2;
break;
default:
dev_err(i2s_tdm->dev, "invalid channel: %d\n",
params_channels(params));
ret = -EINVAL;
goto err;
}
if (i2s_tdm->clk_trcm) {
spin_lock(&i2s_tdm->lock);
if (atomic_read(&i2s_tdm->refcount))
rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm);
regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,
I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK,
I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk));
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK,
I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck));
rockchip_i2s_trcm_mode(substream, dai, div_bclk, div_lrck, val);
} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,
I2S_CLKDIV_TXM_MASK,
@ -857,6 +945,9 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
I2S_CKR_TSD_MASK,
I2S_CKR_TSD(div_lrck));
regmap_update_bits(i2s_tdm->regmap, I2S_TXCR,
I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
val);
} else {
regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,
I2S_CLKDIV_RXM_MASK,
@ -864,109 +955,12 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
I2S_CKR_RSD_MASK,
I2S_CKR_RSD(div_lrck));
}
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
regmap_update_bits(i2s_tdm->regmap, I2S_RXCR,
I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,
val);
else
regmap_update_bits(i2s_tdm->regmap, I2S_TXCR,
I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
val);
if (i2s_tdm->io_multiplex) {
int usable_chs = MULTIPLEX_CH_MAX;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
struct snd_pcm_str *playback_str =
&substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (playback_str->substream_opened) {
regmap_read(i2s_tdm->regmap, I2S_TXCR, &val);
val &= I2S_TXCR_CSR_MASK;
usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val);
}
regmap_read(i2s_tdm->regmap, I2S_RXCR, &val);
val &= I2S_RXCR_CSR_MASK;
if (to_ch_num(val) > usable_chs) {
dev_err(i2s_tdm->dev,
"Capture chs(%d) > usable chs(%d)\n",
to_ch_num(val), usable_chs);
ret = -EINVAL;
goto err;
}
switch (val) {
case I2S_CHN_4:
val = I2S_IO_6CH_OUT_4CH_IN;
break;
case I2S_CHN_6:
val = I2S_IO_4CH_OUT_6CH_IN;
break;
case I2S_CHN_8:
val = I2S_IO_2CH_OUT_8CH_IN;
break;
default:
val = I2S_IO_8CH_OUT_2CH_IN;
break;
}
} else {
struct snd_pcm_str *capture_str =
&substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
if (capture_str->substream_opened) {
regmap_read(i2s_tdm->regmap, I2S_RXCR, &val);
val &= I2S_RXCR_CSR_MASK;
usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val);
}
regmap_read(i2s_tdm->regmap, I2S_TXCR, &val);
val &= I2S_TXCR_CSR_MASK;
if (to_ch_num(val) > usable_chs) {
dev_err(i2s_tdm->dev,
"Playback chs(%d) > usable chs(%d)\n",
to_ch_num(val), usable_chs);
ret = -EINVAL;
goto err;
}
switch (val) {
case I2S_CHN_4:
val = I2S_IO_4CH_OUT_6CH_IN;
break;
case I2S_CHN_6:
val = I2S_IO_6CH_OUT_4CH_IN;
break;
case I2S_CHN_8:
val = I2S_IO_8CH_OUT_2CH_IN;
break;
default:
val = I2S_IO_2CH_OUT_8CH_IN;
break;
}
}
val <<= i2s_tdm->soc_data->grf_shift;
val |= (I2S_IO_DIRECTION_MASK << i2s_tdm->soc_data->grf_shift) << 16;
regmap_write(i2s_tdm->grf, i2s_tdm->soc_data->grf_reg_offset, val);
}
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
I2S_DMACR_TDL(16));
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
I2S_DMACR_RDL(16));
if (i2s_tdm->clk_trcm) {
if (atomic_read(&i2s_tdm->refcount))
rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm);
spin_unlock(&i2s_tdm->lock);
}
return 0;
ret = rockchip_i2s_io_multiplex(substream, dai);
err:
return ret;
@ -1316,10 +1310,8 @@ static int rockchip_i2s_tdm_dai_prepare(struct platform_device *pdev,
*soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_tdm_dai,
sizeof(rockchip_i2s_tdm_dai), GFP_KERNEL);
if (!(*soc_dai)) {
dev_err(&pdev->dev, "Failed to duplicate i2s_tdm_dai\n");
if (!(*soc_dai))
return -ENOMEM;
}
return 0;
}
@ -1480,7 +1472,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
int val;
ret = rockchip_i2s_tdm_dai_prepare(pdev, &soc_dai);
if (ret < 0)
if (ret)
return ret;
i2s_tdm = devm_kzalloc(&pdev->dev, sizeof(*i2s_tdm), GFP_KERNEL);
@ -1623,6 +1615,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
goto err_pm_disable;
}
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
I2S_DMACR_TDL(16));
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
I2S_DMACR_RDL(16));
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
I2S_CKR_TRCM_MASK, i2s_tdm->clk_trcm);

View File

@ -101,8 +101,8 @@
#define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT)
#define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT)
#define I2S_CKR_CKP_SHIFT 26
#define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_CKP_NORMAL (0 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_CKP_INVERTED (1 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT)
#define I2S_CKR_RLP_SHIFT 25
#define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT)