aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Tanure2021-03-06 18:55:47 +0000
committerMark Brown2021-03-10 13:14:25 +0000
commit43fc357199f90c0e6ee7082fb0a989b0560be2d6 (patch)
treede75dc0337b9c9c0d45c0f779823beafe050d26c
parent621d65f3b868611df62ae4dc4eb1a37b85e4e8c0 (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.c86
-rw-r--r--sound/soc/codecs/cs42l42.h1
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__ */