aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 58ee64594f07..ce880f3bccc7 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -41,6 +41,7 @@ struct rk_i2s_dev {
*/
bool tx_start;
bool rx_start;
+ bool is_master_mode;
};
static int i2s_runtime_suspend(struct device *dev)
@@ -174,9 +175,11 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_CBS_CFS:
/* Set source clock in Master mode */
val = I2S_CKR_MSS_MASTER;
+ i2s->is_master_mode = true;
break;
case SND_SOC_DAIFMT_CBM_CFM:
val = I2S_CKR_MSS_SLAVE;
+ i2s->is_master_mode = false;
break;
default:
return -EINVAL;
@@ -228,6 +231,26 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
struct rk_i2s_dev *i2s = to_info(dai);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int val = 0;
+ unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck;
+
+ if (i2s->is_master_mode) {
+ mclk_rate = clk_get_rate(i2s->mclk);
+ bclk_rate = 2 * 32 * params_rate(params);
+ if (bclk_rate && mclk_rate % bclk_rate)
+ return -EINVAL;
+
+ div_bclk = mclk_rate / bclk_rate;
+ div_lrck = bclk_rate / params_rate(params);
+ regmap_update_bits(i2s->regmap, I2S_CKR,
+ I2S_CKR_MDIV_MASK,
+ I2S_CKR_MDIV(div_bclk));
+
+ regmap_update_bits(i2s->regmap, I2S_CKR,
+ I2S_CKR_TSD_MASK |
+ I2S_CKR_RSD_MASK,
+ I2S_CKR_TSD(div_lrck) |
+ I2S_CKR_RSD(div_lrck));
+ }
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8: