diff options
author | Lucas Tanure | 2021-03-06 18:55:47 +0000 |
---|---|---|
committer | Mark Brown | 2021-03-10 13:14:25 +0000 |
commit | 43fc357199f90c0e6ee7082fb0a989b0560be2d6 (patch) | |
tree | de75dc0337b9c9c0d45c0f779823beafe050d26c | |
parent | 621d65f3b868611df62ae4dc4eb1a37b85e4e8c0 (diff) |
ASoC: cs42l42: Set clock source for both ways of stream
Move the enable/disable of clocks to cs42l42_mute_stream so the record
path also get clocks.
Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20210306185553.62053-10-tanureal@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/codecs/cs42l42.c | 86 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l42.h | 1 |
2 files changed, 49 insertions, 38 deletions
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 0b5c8e4afff0..2dca55dfa46d 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -784,52 +784,63 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction) +static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) { struct snd_soc_component *component = dai->component; + struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); unsigned int regval; u8 fullScaleVol; if (mute) { - /* Mark SCLK as not present to turn on the internal - * oscillator. - */ - snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, - CS42L42_SCLK_PRESENT_MASK, 0); - - snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, - CS42L42_PLL_START_MASK, - 0 << CS42L42_PLL_START_SHIFT); - /* Mute the headphone */ - snd_soc_component_update_bits(component, CS42L42_HP_CTL, - CS42L42_HP_ANA_AMUTE_MASK | - CS42L42_HP_ANA_BMUTE_MASK, - CS42L42_HP_ANA_AMUTE_MASK | - CS42L42_HP_ANA_BMUTE_MASK); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_component_update_bits(component, CS42L42_HP_CTL, + CS42L42_HP_ANA_AMUTE_MASK | + CS42L42_HP_ANA_BMUTE_MASK, + CS42L42_HP_ANA_AMUTE_MASK | + CS42L42_HP_ANA_BMUTE_MASK); + + cs42l42->stream_use &= ~(1 << stream); + if(!cs42l42->stream_use) { + /* + * Switch to the internal oscillator. + * SCLK must remain running until after this clock switch. + * Without a source of clock the I2C bus doesn't work. + */ + snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, + CS42L42_SCLK_PRESENT_MASK, 0); + snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, + CS42L42_PLL_START_MASK, 0); + } } else { - snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, - CS42L42_PLL_START_MASK, - 1 << CS42L42_PLL_START_SHIFT); - /* Read the headphone load */ - regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT); - if (((regval & CS42L42_RLA_STAT_MASK) >> - CS42L42_RLA_STAT_SHIFT) == CS42L42_RLA_STAT_15_OHM) { - fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK; - } else { - fullScaleVol = 0; + if (!cs42l42->stream_use) { + /* SCLK must be running before codec unmute */ + snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, + CS42L42_PLL_START_MASK, 1); + + /* Mark SCLK as present, turn off internal oscillator */ + snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, + CS42L42_SCLK_PRESENT_MASK, + CS42L42_SCLK_PRESENT_MASK); } + cs42l42->stream_use |= 1 << stream; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* Read the headphone load */ + regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT); + if (((regval & CS42L42_RLA_STAT_MASK) >> CS42L42_RLA_STAT_SHIFT) == + CS42L42_RLA_STAT_15_OHM) { + fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK; + } else { + fullScaleVol = 0; + } - /* Un-mute the headphone, set the full scale volume flag */ - snd_soc_component_update_bits(component, CS42L42_HP_CTL, - CS42L42_HP_ANA_AMUTE_MASK | - CS42L42_HP_ANA_BMUTE_MASK | - CS42L42_HP_FULL_SCALE_VOL_MASK, fullScaleVol); - - /* Mark SCLK as present, turn off internal oscillator */ - snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, - CS42L42_SCLK_PRESENT_MASK, - CS42L42_SCLK_PRESENT_MASK); + /* Un-mute the headphone, set the full scale volume flag */ + snd_soc_component_update_bits(component, CS42L42_HP_CTL, + CS42L42_HP_ANA_AMUTE_MASK | + CS42L42_HP_ANA_BMUTE_MASK | + CS42L42_HP_FULL_SCALE_VOL_MASK, fullScaleVol); + } } return 0; @@ -844,8 +855,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = { .hw_params = cs42l42_pcm_hw_params, .set_fmt = cs42l42_set_dai_fmt, .set_sysclk = cs42l42_set_sysclk, - .mute_stream = cs42l42_mute, - .no_capture_mute = 1, + .mute_stream = cs42l42_mute_stream, }; static struct snd_soc_dai_driver cs42l42_dai = { diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 4b448c102f53..3dcbfebc53b0 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -768,6 +768,7 @@ struct cs42l42_private { u8 bias_thresholds[CS42L42_NUM_BIASES]; u8 hs_bias_ramp_rate; u8 hs_bias_ramp_time; + u8 stream_use; }; #endif /* __CS42L42_H__ */ |