mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
ASoC: rockchip: i2s-tdm: Clean code
Change-Id: Ib4af14213873dac609d195976bd639bd6270e419 Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
This commit is contained in:
parent
bd60226a17
commit
baddcc7c35
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user