Skip to content

Commit a5450ab

Browse files
Judy Hsiaobroonie
authored andcommitted
ASoC: rockchip: i2s: switch BCLK to GPIO
We discoverd that the state of BCLK on, LRCLK off and SD_MODE on may cause the speaker melting issue. Removing LRCLK while BCLK is present can cause unexpected output behavior including a large DC output voltage as described in the Max98357a datasheet. In order to: 1. prevent BCLK from turning on by other component. 2. keep BCLK and LRCLK being present at the same time This patch switches BCLK to GPIO func before LRCLK output, and configures BCLK func back during LRCLK is output. Without this fix, BCLK is turned on 11 ms earlier than LRCK by the da7219. With this fix, BCLK is turned on only 0.4 ms earlier than LRCK by the rockchip codec. Signed-off-by: Judy Hsiao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 3911535 commit a5450ab

File tree

1 file changed

+129
-31
lines changed

1 file changed

+129
-31
lines changed

sound/soc/rockchip/rockchip_i2s.c

Lines changed: 129 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/of_gpio.h>
1414
#include <linux/of_device.h>
1515
#include <linux/clk.h>
16+
#include <linux/pinctrl/consumer.h>
1617
#include <linux/pm_runtime.h>
1718
#include <linux/regmap.h>
1819
#include <linux/spinlock.h>
@@ -54,8 +55,40 @@ struct rk_i2s_dev {
5455
const struct rk_i2s_pins *pins;
5556
unsigned int bclk_ratio;
5657
spinlock_t lock; /* tx/rx lock */
58+
struct pinctrl *pinctrl;
59+
struct pinctrl_state *bclk_on;
60+
struct pinctrl_state *bclk_off;
5761
};
5862

63+
static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)
64+
{
65+
int ret = 0;
66+
67+
if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))
68+
ret = pinctrl_select_state(i2s->pinctrl,
69+
i2s->bclk_on);
70+
71+
if (ret)
72+
dev_err(i2s->dev, "bclk enable failed %d\n", ret);
73+
74+
return ret;
75+
}
76+
77+
static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)
78+
{
79+
80+
int ret = 0;
81+
82+
if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))
83+
ret = pinctrl_select_state(i2s->pinctrl,
84+
i2s->bclk_off);
85+
86+
if (ret)
87+
dev_err(i2s->dev, "bclk disable failed %d\n", ret);
88+
89+
return ret;
90+
}
91+
5992
static int i2s_runtime_suspend(struct device *dev)
6093
{
6194
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
@@ -92,38 +125,49 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
92125
return snd_soc_dai_get_drvdata(dai);
93126
}
94127

95-
static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
128+
static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
96129
{
97130
unsigned int val = 0;
98131
int retry = 10;
132+
int ret = 0;
99133

100134
spin_lock(&i2s->lock);
101135
if (on) {
102-
regmap_update_bits(i2s->regmap, I2S_DMACR,
103-
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
136+
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
137+
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
138+
if (ret < 0)
139+
goto end;
104140

105-
regmap_update_bits(i2s->regmap, I2S_XFER,
106-
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
107-
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
141+
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
142+
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
143+
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
144+
if (ret < 0)
145+
goto end;
108146

109147
i2s->tx_start = true;
110148
} else {
111149
i2s->tx_start = false;
112150

113-
regmap_update_bits(i2s->regmap, I2S_DMACR,
114-
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
151+
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
152+
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
153+
if (ret < 0)
154+
goto end;
115155

116156
if (!i2s->rx_start) {
117-
regmap_update_bits(i2s->regmap, I2S_XFER,
118-
I2S_XFER_TXS_START |
119-
I2S_XFER_RXS_START,
120-
I2S_XFER_TXS_STOP |
121-
I2S_XFER_RXS_STOP);
157+
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
158+
I2S_XFER_TXS_START |
159+
I2S_XFER_RXS_START,
160+
I2S_XFER_TXS_STOP |
161+
I2S_XFER_RXS_STOP);
162+
if (ret < 0)
163+
goto end;
122164

123165
udelay(150);
124-
regmap_update_bits(i2s->regmap, I2S_CLR,
125-
I2S_CLR_TXC | I2S_CLR_RXC,
126-
I2S_CLR_TXC | I2S_CLR_RXC);
166+
ret = regmap_update_bits(i2s->regmap, I2S_CLR,
167+
I2S_CLR_TXC | I2S_CLR_RXC,
168+
I2S_CLR_TXC | I2S_CLR_RXC);
169+
if (ret < 0)
170+
goto end;
127171

128172
regmap_read(i2s->regmap, I2S_CLR, &val);
129173

@@ -138,44 +182,57 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
138182
}
139183
}
140184
}
185+
end:
141186
spin_unlock(&i2s->lock);
187+
if (ret < 0)
188+
dev_err(i2s->dev, "lrclk update failed\n");
189+
190+
return ret;
142191
}
143192

144-
static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
193+
static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
145194
{
146195
unsigned int val = 0;
147196
int retry = 10;
197+
int ret = 0;
148198

149199
spin_lock(&i2s->lock);
150200
if (on) {
151-
regmap_update_bits(i2s->regmap, I2S_DMACR,
201+
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
152202
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
203+
if (ret < 0)
204+
goto end;
153205

154-
regmap_update_bits(i2s->regmap, I2S_XFER,
206+
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
155207
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
156208
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
209+
if (ret < 0)
210+
goto end;
157211

158212
i2s->rx_start = true;
159213
} else {
160214
i2s->rx_start = false;
161215

162-
regmap_update_bits(i2s->regmap, I2S_DMACR,
216+
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
163217
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
218+
if (ret < 0)
219+
goto end;
164220

165221
if (!i2s->tx_start) {
166-
regmap_update_bits(i2s->regmap, I2S_XFER,
222+
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
167223
I2S_XFER_TXS_START |
168224
I2S_XFER_RXS_START,
169225
I2S_XFER_TXS_STOP |
170226
I2S_XFER_RXS_STOP);
171-
227+
if (ret < 0)
228+
goto end;
172229
udelay(150);
173-
regmap_update_bits(i2s->regmap, I2S_CLR,
230+
ret = regmap_update_bits(i2s->regmap, I2S_CLR,
174231
I2S_CLR_TXC | I2S_CLR_RXC,
175232
I2S_CLR_TXC | I2S_CLR_RXC);
176-
233+
if (ret < 0)
234+
goto end;
177235
regmap_read(i2s->regmap, I2S_CLR, &val);
178-
179236
/* Should wait for clear operation to finish */
180237
while (val) {
181238
regmap_read(i2s->regmap, I2S_CLR, &val);
@@ -187,7 +244,12 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
187244
}
188245
}
189246
}
247+
end:
190248
spin_unlock(&i2s->lock);
249+
if (ret < 0)
250+
dev_err(i2s->dev, "lrclk update failed\n");
251+
252+
return ret;
191253
}
192254

193255
static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
@@ -425,17 +487,26 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
425487
case SNDRV_PCM_TRIGGER_RESUME:
426488
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
427489
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
428-
rockchip_snd_rxctrl(i2s, 1);
490+
ret = rockchip_snd_rxctrl(i2s, 1);
429491
else
430-
rockchip_snd_txctrl(i2s, 1);
492+
ret = rockchip_snd_txctrl(i2s, 1);
493+
/* Do not turn on bclk if lrclk open fails. */
494+
if (ret < 0)
495+
return ret;
496+
i2s_pinctrl_select_bclk_on(i2s);
431497
break;
432498
case SNDRV_PCM_TRIGGER_SUSPEND:
433499
case SNDRV_PCM_TRIGGER_STOP:
434500
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
435-
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
436-
rockchip_snd_rxctrl(i2s, 0);
437-
else
438-
rockchip_snd_txctrl(i2s, 0);
501+
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
502+
if (!i2s->tx_start)
503+
i2s_pinctrl_select_bclk_off(i2s);
504+
ret = rockchip_snd_rxctrl(i2s, 0);
505+
} else {
506+
if (!i2s->rx_start)
507+
i2s_pinctrl_select_bclk_off(i2s);
508+
ret = rockchip_snd_txctrl(i2s, 0);
509+
}
439510
break;
440511
default:
441512
ret = -EINVAL;
@@ -736,6 +807,33 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
736807
}
737808

738809
i2s->bclk_ratio = 64;
810+
i2s->pinctrl = devm_pinctrl_get(&pdev->dev);
811+
if (IS_ERR(i2s->pinctrl))
812+
dev_err(&pdev->dev, "failed to find i2s pinctrl\n");
813+
814+
i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl,
815+
"bclk_on");
816+
if (IS_ERR_OR_NULL(i2s->bclk_on))
817+
dev_err(&pdev->dev, "failed to find i2s default state\n");
818+
else
819+
dev_dbg(&pdev->dev, "find i2s bclk state\n");
820+
821+
i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl,
822+
"bclk_off");
823+
if (IS_ERR_OR_NULL(i2s->bclk_off))
824+
dev_err(&pdev->dev, "failed to find i2s gpio state\n");
825+
else
826+
dev_dbg(&pdev->dev, "find i2s bclk_off state\n");
827+
828+
i2s_pinctrl_select_bclk_off(i2s);
829+
830+
i2s->playback_dma_data.addr = res->start + I2S_TXDR;
831+
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
832+
i2s->playback_dma_data.maxburst = 4;
833+
834+
i2s->capture_dma_data.addr = res->start + I2S_RXDR;
835+
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
836+
i2s->capture_dma_data.maxburst = 4;
739837

740838
dev_set_drvdata(&pdev->dev, i2s);
741839

0 commit comments

Comments
 (0)