Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: nau8825: Fix jack detection across suspend

Jack plug status is rechecked at resume to handle plug/unplug
in S3 when the chip has no power.

Suspend/resume callbacks are moved from the i2c dev_pm_ops to
snd_soc_codec_driver. soc_resume_deferred is a delayed work
which may trigger nau8825_set_bias_level. The bias change races
against dev_pm_ops, causing jack detection issues.
soc_resume_deferred ensures bias change and snd_soc_codec_driver
suspend/resume are sequenced correctly.

Signed-off-by: Ben Zhang <benzh@chromium.org>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Ben Zhang and committed by
Mark Brown
e6cee900 f55532a0

+71 -55
+71 -55
sound/soc/codecs/nau8825.c
··· 343 343 SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL, 344 344 0), 345 345 346 - /* ADC for button press detection */ 347 - SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, 348 - NAU8825_SAR_ADC_EN_SFT, 0), 346 + /* ADC for button press detection. A dapm supply widget is used to 347 + * prevent dapm_power_widgets keeping the codec at SND_SOC_BIAS_ON 348 + * during suspend. 349 + */ 350 + SND_SOC_DAPM_SUPPLY("SAR", NAU8825_REG_SAR_CTRL, 351 + NAU8825_SAR_ADC_EN_SFT, 0, NULL, 0), 349 352 350 353 SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0), 351 354 SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0), ··· 610 607 611 608 static void nau8825_restart_jack_detection(struct regmap *regmap) 612 609 { 610 + /* Chip needs one FSCLK cycle in order to generate interrupts, 611 + * as we cannot guarantee one will be provided by the system. Turning 612 + * master mode on then off enables us to generate that FSCLK cycle 613 + * with a minimum of contention on the clock bus. 614 + */ 615 + regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, 616 + NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER); 617 + regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, 618 + NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE); 619 + 613 620 /* this will restart the entire jack detection process including MIC/GND 614 621 * switching and create interrupts. We have to go from 0 to 1 and back 615 622 * to 0 to restart. ··· 741 728 struct regmap *regmap = nau8825->regmap; 742 729 int active_irq, clear_irq = 0, event = 0, event_mask = 0; 743 730 744 - regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq); 731 + if (regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq)) { 732 + dev_err(nau8825->dev, "failed to read irq status\n"); 733 + return IRQ_NONE; 734 + } 745 735 746 736 if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) == 747 737 NAU8825_JACK_EJECTION_DETECTED) { ··· 1157 1141 return ret; 1158 1142 } 1159 1143 } 1160 - 1161 - ret = regcache_sync(nau8825->regmap); 1162 - if (ret) { 1163 - dev_err(codec->dev, 1164 - "Failed to sync cache: %d\n", ret); 1165 - return ret; 1166 - } 1167 1144 } 1168 - 1169 1145 break; 1170 1146 1171 1147 case SND_SOC_BIAS_OFF: 1172 1148 if (nau8825->mclk_freq) 1173 1149 clk_disable_unprepare(nau8825->mclk); 1174 - 1175 - regcache_mark_dirty(nau8825->regmap); 1176 1150 break; 1177 1151 } 1178 1152 return 0; 1179 1153 } 1154 + 1155 + #ifdef CONFIG_PM 1156 + static int nau8825_suspend(struct snd_soc_codec *codec) 1157 + { 1158 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 1159 + 1160 + disable_irq(nau8825->irq); 1161 + regcache_cache_only(nau8825->regmap, true); 1162 + regcache_mark_dirty(nau8825->regmap); 1163 + 1164 + return 0; 1165 + } 1166 + 1167 + static int nau8825_resume(struct snd_soc_codec *codec) 1168 + { 1169 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 1170 + 1171 + /* The chip may lose power and reset in S3. regcache_sync restores 1172 + * register values including configurations for sysclk, irq, and 1173 + * jack/button detection. 1174 + */ 1175 + regcache_cache_only(nau8825->regmap, false); 1176 + regcache_sync(nau8825->regmap); 1177 + 1178 + /* Check the jack plug status directly. If the headset is unplugged 1179 + * during S3 when the chip has no power, there will be no jack 1180 + * detection irq even after the nau8825_restart_jack_detection below, 1181 + * because the chip just thinks no headset has ever been plugged in. 1182 + */ 1183 + if (!nau8825_is_jack_inserted(nau8825->regmap)) { 1184 + nau8825_eject_jack(nau8825); 1185 + snd_soc_jack_report(nau8825->jack, 0, SND_JACK_HEADSET); 1186 + } 1187 + 1188 + enable_irq(nau8825->irq); 1189 + 1190 + /* Run jack detection to check the type (OMTP or CTIA) of the headset 1191 + * if there is one. This handles the case where a different type of 1192 + * headset is plugged in during S3. This triggers an IRQ iff a headset 1193 + * is already plugged in. 1194 + */ 1195 + nau8825_restart_jack_detection(nau8825->regmap); 1196 + 1197 + return 0; 1198 + } 1199 + #else 1200 + #define nau8825_suspend NULL 1201 + #define nau8825_resume NULL 1202 + #endif 1180 1203 1181 1204 static struct snd_soc_codec_driver nau8825_codec_driver = { 1182 1205 .probe = nau8825_codec_probe, ··· 1223 1168 .set_pll = nau8825_set_pll, 1224 1169 .set_bias_level = nau8825_set_bias_level, 1225 1170 .suspend_bias_off = true, 1171 + .suspend = nau8825_suspend, 1172 + .resume = nau8825_resume, 1226 1173 1227 1174 .controls = nau8825_controls, 1228 1175 .num_controls = ARRAY_SIZE(nau8825_controls), ··· 1334 1277 regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL, 1335 1278 NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR); 1336 1279 1337 - /* Chip needs one FSCLK cycle in order to generate interrupts, 1338 - * as we cannot guarantee one will be provided by the system. Turning 1339 - * master mode on then off enables us to generate that FSCLK cycle 1340 - * with a minimum of contention on the clock bus. 1341 - */ 1342 - regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, 1343 - NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER); 1344 - regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, 1345 - NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE); 1346 - 1347 1280 ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL, 1348 1281 nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, 1349 1282 "nau8825", nau8825); ··· 1401 1354 return 0; 1402 1355 } 1403 1356 1404 - #ifdef CONFIG_PM_SLEEP 1405 - static int nau8825_suspend(struct device *dev) 1406 - { 1407 - struct i2c_client *client = to_i2c_client(dev); 1408 - struct nau8825 *nau8825 = dev_get_drvdata(dev); 1409 - 1410 - disable_irq(client->irq); 1411 - regcache_cache_only(nau8825->regmap, true); 1412 - regcache_mark_dirty(nau8825->regmap); 1413 - 1414 - return 0; 1415 - } 1416 - 1417 - static int nau8825_resume(struct device *dev) 1418 - { 1419 - struct i2c_client *client = to_i2c_client(dev); 1420 - struct nau8825 *nau8825 = dev_get_drvdata(dev); 1421 - 1422 - regcache_cache_only(nau8825->regmap, false); 1423 - regcache_sync(nau8825->regmap); 1424 - enable_irq(client->irq); 1425 - 1426 - return 0; 1427 - } 1428 - #endif 1429 - 1430 - static const struct dev_pm_ops nau8825_pm = { 1431 - SET_SYSTEM_SLEEP_PM_OPS(nau8825_suspend, nau8825_resume) 1432 - }; 1433 - 1434 1357 static const struct i2c_device_id nau8825_i2c_ids[] = { 1435 1358 { "nau8825", 0 }, 1436 1359 { } ··· 1427 1410 .name = "nau8825", 1428 1411 .of_match_table = of_match_ptr(nau8825_of_ids), 1429 1412 .acpi_match_table = ACPI_PTR(nau8825_acpi_match), 1430 - .pm = &nau8825_pm, 1431 1413 }, 1432 1414 .probe = nau8825_i2c_probe, 1433 1415 .remove = nau8825_i2c_remove,