aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJohn Hsu <KCHSU0@nuvoton.com>2016-08-04 04:52:06 -0400
committerMark Brown <broonie@kernel.org>2016-08-04 16:58:57 -0400
commitca6ac305f017472a172e53345264abdb495eba46 (patch)
tree70d78f47b9fd6d8cd1fc717070e41b6bc1cbbd35 /sound
parente7ca8fcd15049b1e48ae2ef1434a68a51ef0ead5 (diff)
ASoC: nau8825: fix bug in playback when suspend
In chromium, the following steps will make codec function fail. \1. plug in headphones, Play music \2. run "powerd_dbus_suspend" \3. resume from S3 After resume, the jack detection will restart and make configuration for the headset. Meanwhile, the playback prepares and starts to work. The two sequences will conflict and make wrong register configuration. Originally, the driver adds protection for the case when it finds the playback is active. But the "powerd_dbus_suspend" command will close the pcm stream before suspend. Therefore, the driver can't detect the playback after resume, and the protection not works. For the issue, the driver raises protection every time after resume. The protection will release after jack detection and configuration completes, and then the playback just will goes on. Signed-off-by: John Hsu <KCHSU0@nuvoton.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/nau8825.c51
1 files changed, 12 insertions, 39 deletions
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index 5c9707ac4bbf..20d2f1578b87 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -212,31 +212,6 @@ static const unsigned short logtable[256] = {
212 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 212 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
213}; 213};
214 214
215static struct snd_soc_dai *nau8825_get_codec_dai(struct nau8825 *nau8825)
216{
217 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(nau8825->dapm);
218 struct snd_soc_component *component = &codec->component;
219 struct snd_soc_dai *codec_dai, *_dai;
220
221 list_for_each_entry_safe(codec_dai, _dai, &component->dai_list, list) {
222 if (!strncmp(codec_dai->name, NUVOTON_CODEC_DAI,
223 strlen(NUVOTON_CODEC_DAI)))
224 return codec_dai;
225 }
226 return NULL;
227}
228
229static bool nau8825_dai_is_active(struct nau8825 *nau8825)
230{
231 struct snd_soc_dai *codec_dai = nau8825_get_codec_dai(nau8825);
232
233 if (codec_dai) {
234 if (codec_dai->playback_active || codec_dai->capture_active)
235 return true;
236 }
237 return false;
238}
239
240/** 215/**
241 * nau8825_sema_acquire - acquire the semaphore of nau88l25 216 * nau8825_sema_acquire - acquire the semaphore of nau88l25
242 * @nau8825: component to register the codec private data with 217 * @nau8825: component to register the codec private data with
@@ -1205,6 +1180,8 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
1205 struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 1180 struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
1206 unsigned int val_len = 0; 1181 unsigned int val_len = 0;
1207 1182
1183 nau8825_sema_acquire(nau8825, 2 * HZ);
1184
1208 switch (params_width(params)) { 1185 switch (params_width(params)) {
1209 case 16: 1186 case 16:
1210 val_len |= NAU8825_I2S_DL_16; 1187 val_len |= NAU8825_I2S_DL_16;
@@ -1225,6 +1202,9 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
1225 regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, 1202 regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
1226 NAU8825_I2S_DL_MASK, val_len); 1203 NAU8825_I2S_DL_MASK, val_len);
1227 1204
1205 /* Release the semaphone. */
1206 nau8825_sema_release(nau8825);
1207
1228 return 0; 1208 return 0;
1229} 1209}
1230 1210
@@ -1234,6 +1214,8 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
1234 struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 1214 struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
1235 unsigned int ctrl1_val = 0, ctrl2_val = 0; 1215 unsigned int ctrl1_val = 0, ctrl2_val = 0;
1236 1216
1217 nau8825_sema_acquire(nau8825, 2 * HZ);
1218
1237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1219 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1238 case SND_SOC_DAIFMT_CBM_CFM: 1220 case SND_SOC_DAIFMT_CBM_CFM:
1239 ctrl2_val |= NAU8825_I2S_MS_MASTER; 1221 ctrl2_val |= NAU8825_I2S_MS_MASTER;
@@ -1282,6 +1264,9 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
1282 regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, 1264 regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
1283 NAU8825_I2S_MS_MASK, ctrl2_val); 1265 NAU8825_I2S_MS_MASK, ctrl2_val);
1284 1266
1267 /* Release the semaphone. */
1268 nau8825_sema_release(nau8825);
1269
1285 return 0; 1270 return 0;
1286} 1271}
1287 1272
@@ -2241,20 +2226,8 @@ static int __maybe_unused nau8825_resume(struct snd_soc_codec *codec)
2241 2226
2242 regcache_cache_only(nau8825->regmap, false); 2227 regcache_cache_only(nau8825->regmap, false);
2243 regcache_sync(nau8825->regmap); 2228 regcache_sync(nau8825->regmap);
2244 if (nau8825_is_jack_inserted(nau8825->regmap)) { 2229 nau8825->xtalk_protect = true;
2245 /* If the jack is inserted, we need to check whether the play- 2230 nau8825_sema_acquire(nau8825, 0);
2246 * back is active before suspend. If active, the driver has to
2247 * raise the protection for cross talk function to avoid the
2248 * playback recovers before cross talk process finish. Other-
2249 * wise, the playback will be interfered by cross talk func-
2250 * tion. It is better to apply hardware related parameters
2251 * before starting playback or record.
2252 */
2253 if (nau8825_dai_is_active(nau8825)) {
2254 nau8825->xtalk_protect = true;
2255 nau8825_sema_acquire(nau8825, 0);
2256 }
2257 }
2258 enable_irq(nau8825->irq); 2231 enable_irq(nau8825->irq);
2259 2232
2260 return 0; 2233 return 0;