mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 21:33:52 +00:00
ASoC: cs42l42: Fix handling of hard reset
Merge series from Stefan Binding <sbinding@opensource.cirrus.com>: 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
This commit is contained in:
commit
ef3e1b8a31
3 changed files with 41 additions and 1 deletions
|
@ -344,6 +344,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
|
|||
switch (status) {
|
||||
case SDW_SLAVE_ATTACHED:
|
||||
dev_dbg(cs42l42->dev, "ATTACHED\n");
|
||||
|
||||
/*
|
||||
* The SoundWire core can report stale ATTACH notifications
|
||||
* if we hard-reset CS42L42 in probe() but it had already been
|
||||
* enumerated. Reject the ATTACH if we haven't yet seen an
|
||||
* UNATTACH report for the device being in reset.
|
||||
*/
|
||||
if (cs42l42->sdw_waiting_first_unattach)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Initialise codec, this only needs to be done once.
|
||||
* 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,
|
|||
break;
|
||||
case SDW_SLAVE_UNATTACHED:
|
||||
dev_dbg(cs42l42->dev, "UNATTACHED\n");
|
||||
|
||||
if (cs42l42->sdw_waiting_first_unattach) {
|
||||
/*
|
||||
* SoundWire core has seen that CS42L42 is not on
|
||||
* the bus so release RESET and wait for ATTACH.
|
||||
*/
|
||||
cs42l42->sdw_waiting_first_unattach = false;
|
||||
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -2320,7 +2320,26 @@ int cs42l42_common_probe(struct cs42l42_private *cs42l42,
|
|||
|
||||
if (cs42l42->reset_gpio) {
|
||||
dev_dbg(cs42l42->dev, "Found reset GPIO\n");
|
||||
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
|
||||
|
||||
/*
|
||||
* ACPI can override the default GPIO state we requested
|
||||
* so ensure that we start with RESET low.
|
||||
*/
|
||||
gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
|
||||
|
||||
/* Ensure minimum reset pulse width */
|
||||
usleep_range(10, 500);
|
||||
|
||||
/*
|
||||
* On SoundWire keep the chip in reset until we get an UNATTACH
|
||||
* notification from the SoundWire core. This acts as a
|
||||
* synchronization point to reject stale ATTACH notifications
|
||||
* if the chip was already enumerated before we reset it.
|
||||
*/
|
||||
if (cs42l42->sdw_peripheral)
|
||||
cs42l42->sdw_waiting_first_unattach = true;
|
||||
else
|
||||
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
|
||||
}
|
||||
usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ struct cs42l42_private {
|
|||
u8 stream_use;
|
||||
bool hp_adc_up_pending;
|
||||
bool suspended;
|
||||
bool sdw_waiting_first_unattach;
|
||||
bool init_done;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue