path: root/src
diff options
authorJulius Werner <>2016-11-01 02:46:22 (GMT)
committerchrome-bot <>2016-11-02 02:18:11 (GMT)
commit577f0a316631266b35560f21672790cb49656f3f (patch)
tree6a125f2fe75fbe94651f08d7ac5f6045da1601ad /src
parentdfffe58ca6242fcdb4c5020235ab7f221772ecd5 (diff)
sound: max98357a: Add disable callback
The Maxim MAX98357a amplifier is a little picky about its input signals. Its datasheet demands that the I2S LRCLK must not be removed while the BCLK is still running. Violating that constraint seems to make it very angry and take it out on your speaker induction coil (and surrounding plastic). Unfortunately, some I2S controllers (like Rockchip's) don't make it possible to keep LRCLK running without feeding new data, and stopping BCLK is a pain since it can only be gated from a completely different register set (that depthcharge usually doesn't need to touch). To solve this problem elegantly (and prevent the chance of running into this quirk of this particular amplifier again in the future), let's just always disable the amp again when we're done playing audio. BRANCH=gru BUG=chrome-os-partner:59038 TEST=Rebooted Kevin many times in developer mode and always let the timer run out. Observed how the speaker membrane didn't visibly jerk around anymore, there was no audible pop during kernel handoff, and I no longer noticed the odor of melting plastic in my office. (Note: I didn't test the other two boards using this amplifier, Lars and Kunimitsu, although I have no reason to believe that this fix would cause a problem on them. The olfactory impact on those platforms is currently unknown.) Change-Id: If149be2f24cda85aa8e29ae89933da7226bab594 Signed-off-by: Julius Werner <> Reviewed-on: Tested-by: Xing Zheng <> Reviewed-by: Aaron Durbin <>
Diffstat (limited to 'src')
1 files changed, 8 insertions, 0 deletions
diff --git a/src/drivers/sound/max98357a.c b/src/drivers/sound/max98357a.c
index 44cb4a8..09ee40d 100644
--- a/src/drivers/sound/max98357a.c
+++ b/src/drivers/sound/max98357a.c
@@ -26,12 +26,20 @@ static int max98357a_enable(SoundRouteComponentOps *me)
return gpio_set(codec->sdmode_gpio, 1);
+static int max98357a_disable(SoundRouteComponentOps *me)
+ max98357aCodec *codec = container_of(me, max98357aCodec, component.ops);
+ return gpio_set(codec->sdmode_gpio, 0);
max98357aCodec *new_max98357a_codec(GpioOps *ops)
max98357aCodec *codec = xzalloc(sizeof(*codec));
codec->sdmode_gpio = ops;
codec->component.ops.enable = &max98357a_enable;
+ codec->component.ops.disable = &max98357a_disable;
return codec;