Skip to content

Commit ef3e1b8

Browse files
committed
ASoC: cs42l42: Fix handling of hard reset
Merge series from Stefan Binding <[email protected]>: These patches fix 3 problems with hard reset: 1. Ensure a minimum reset pulse width 2. Deal with ACPI overriding the requested default GPIO state 3. Avoid a race condition when hard-resetting a SoundWire peripheral that is already enumerated
2 parents 781118b + 2d066c6 commit ef3e1b8

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

sound/soc/codecs/cs42l42-sdw.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
344344
switch (status) {
345345
case SDW_SLAVE_ATTACHED:
346346
dev_dbg(cs42l42->dev, "ATTACHED\n");
347+
348+
/*
349+
* The SoundWire core can report stale ATTACH notifications
350+
* if we hard-reset CS42L42 in probe() but it had already been
351+
* enumerated. Reject the ATTACH if we haven't yet seen an
352+
* UNATTACH report for the device being in reset.
353+
*/
354+
if (cs42l42->sdw_waiting_first_unattach)
355+
break;
356+
347357
/*
348358
* Initialise codec, this only needs to be done once.
349359
* When resuming from suspend, resume callback will handle re-init of codec,
@@ -354,6 +364,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
354364
break;
355365
case SDW_SLAVE_UNATTACHED:
356366
dev_dbg(cs42l42->dev, "UNATTACHED\n");
367+
368+
if (cs42l42->sdw_waiting_first_unattach) {
369+
/*
370+
* SoundWire core has seen that CS42L42 is not on
371+
* the bus so release RESET and wait for ATTACH.
372+
*/
373+
cs42l42->sdw_waiting_first_unattach = false;
374+
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
375+
}
376+
357377
break;
358378
default:
359379
break;

sound/soc/codecs/cs42l42.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2320,7 +2320,26 @@ int cs42l42_common_probe(struct cs42l42_private *cs42l42,
23202320

23212321
if (cs42l42->reset_gpio) {
23222322
dev_dbg(cs42l42->dev, "Found reset GPIO\n");
2323-
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
2323+
2324+
/*
2325+
* ACPI can override the default GPIO state we requested
2326+
* so ensure that we start with RESET low.
2327+
*/
2328+
gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
2329+
2330+
/* Ensure minimum reset pulse width */
2331+
usleep_range(10, 500);
2332+
2333+
/*
2334+
* On SoundWire keep the chip in reset until we get an UNATTACH
2335+
* notification from the SoundWire core. This acts as a
2336+
* synchronization point to reject stale ATTACH notifications
2337+
* if the chip was already enumerated before we reset it.
2338+
*/
2339+
if (cs42l42->sdw_peripheral)
2340+
cs42l42->sdw_waiting_first_unattach = true;
2341+
else
2342+
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
23242343
}
23252344
usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
23262345

sound/soc/codecs/cs42l42.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct cs42l42_private {
5353
u8 stream_use;
5454
bool hp_adc_up_pending;
5555
bool suspended;
56+
bool sdw_waiting_first_unattach;
5657
bool init_done;
5758
};
5859

0 commit comments

Comments
 (0)