1 From fc451a2b34464376802a2e2da2caa695e0e21de3 Mon Sep 17 00:00:00 2001
2 From: Olivier Moysan <olivier.moysan@st.com>
3 Date: Wed, 10 Apr 2019 10:08:36 +0200
4 Subject: ASoC: stm32: sai: fix master clock management
6 [ Upstream commit e37c2deafe7058cf7989c4c47bbf1140cc867d89 ]
8 When master clock is used, master clock rate is set exclusively.
9 Parent clocks of master clock cannot be changed after a call to
10 clk_set_rate_exclusive(). So the parent clock of SAI kernel clock
12 Ensure also that exclusive rate operations are balanced
15 Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
16 Signed-off-by: Mark Brown <broonie@kernel.org>
17 Signed-off-by: Sasha Levin <sashal@kernel.org>
19 sound/soc/stm/stm32_sai_sub.c | 64 +++++++++++++++++++++++++----------
20 1 file changed, 47 insertions(+), 17 deletions(-)
22 diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
23 index bc69e68191ad1..1cf9df4b6f11c 100644
24 --- a/sound/soc/stm/stm32_sai_sub.c
25 +++ b/sound/soc/stm/stm32_sai_sub.c
27 #define SAI_IEC60958_STATUS_BYTES 24
29 #define SAI_MCLK_NAME_LEN 32
30 +#define SAI_RATE_11K 11025
33 * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
34 @@ -309,6 +310,25 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai,
38 +static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai,
41 + struct platform_device *pdev = sai->pdev;
42 + struct clk *parent_clk = sai->pdata->clk_x8k;
45 + if (!(rate % SAI_RATE_11K))
46 + parent_clk = sai->pdata->clk_x11k;
48 + ret = clk_set_parent(sai->sai_ck, parent_clk);
50 + dev_err(&pdev->dev, " Error %d setting sai_ck parent clock. %s",
51 + ret, ret == -EBUSY ?
52 + "Active stream rates conflict\n" : "\n");
57 static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
60 @@ -490,25 +510,29 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
61 struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
64 - if (dir == SND_SOC_CLOCK_OUT) {
65 + if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
66 ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
68 (unsigned int)~SAI_XCR1_NODIV);
72 - dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
73 - sai->mclk_rate = freq;
74 + /* If master clock is used, set parent clock now */
75 + ret = stm32_sai_set_parent_clock(sai, freq);
79 - if (sai->sai_mclk) {
80 - ret = clk_set_rate_exclusive(sai->sai_mclk,
83 - dev_err(cpu_dai->dev,
84 - "Could not set mclk rate\n");
87 + ret = clk_set_rate_exclusive(sai->sai_mclk, freq);
89 + dev_err(cpu_dai->dev,
91 + "Active streams have incompatible rates" :
92 + "Could not set mclk rate\n");
96 + dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
97 + sai->mclk_rate = freq;
101 @@ -916,11 +940,13 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
102 int cr1, mask, div = 0;
103 int sai_clk_rate, mclk_ratio, den;
104 unsigned int rate = params_rate(params);
107 - if (!(rate % 11025))
108 - clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
110 - clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
111 + if (!sai->sai_mclk) {
112 + ret = stm32_sai_set_parent_clock(sai, rate);
116 sai_clk_rate = clk_get_rate(sai->sai_ck);
118 if (STM_SAI_IS_F4(sai->pdata)) {
119 @@ -1075,9 +1101,13 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
120 regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV,
123 - clk_disable_unprepare(sai->sai_ck);
124 + /* Release mclk rate only if rate was actually set */
125 + if (sai->mclk_rate) {
126 + clk_rate_exclusive_put(sai->sai_mclk);
127 + sai->mclk_rate = 0;
130 - clk_rate_exclusive_put(sai->sai_mclk);
131 + clk_disable_unprepare(sai->sai_ck);
133 spin_lock_irqsave(&sai->irq_lock, flags);
134 sai->substream = NULL;