Move the enable/disable of clocks to cs42l42_mute_stream so the record
path also get clocks.

Signed-off-by: Lucas Tanure <tanur...@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 85 +++++++++++++++++++++-----------------
 sound/soc/codecs/cs42l42.h |  1 +
 2 files changed, 48 insertions(+), 38 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 663a6a8104171..670f28f09ae01 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -786,52 +786,62 @@ 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;
        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;
@@ -846,8 +856,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 e17a0c0aeb4a0..59e6eccb8d731 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -769,6 +769,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__ */
-- 
2.30.1

Reply via email to