aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_hubs.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-26 15:06:56 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-27 13:42:10 -0400
commitaf31a227e1abee06ccd88c2c52f4fb36b786cebe (patch)
tree1d828dbc011d4c8871f851ba4dcf6a3fe45995c7 /sound/soc/codecs/wm_hubs.c
parentf57b8488bc39f7674cbadf4e2db05a7db8ffa660 (diff)
ASoC: wm_hubs: Special case headphones for digital paths in more use cases
The optimisations which we can do with caching the headphone DCS result in wm_hubs have only been enabled in cases where class W is enabled. However, there are more use cases which can benefit from the cache, especially with WM8994 series devices with their more advanced digital routing. Rather than keying off the class W information from the CODECs have a check in wm_hubs for a suitable path and use that to determine if we can deploy our headphone optimisations. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm_hubs.c')
-rw-r--r--sound/soc/codecs/wm_hubs.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index f13f2886339..15aed8b7d98 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -109,6 +109,42 @@ irqreturn_t wm_hubs_dcs_done(int irq, void *data)
109} 109}
110EXPORT_SYMBOL_GPL(wm_hubs_dcs_done); 110EXPORT_SYMBOL_GPL(wm_hubs_dcs_done);
111 111
112static bool wm_hubs_dac_hp_direct(struct snd_soc_codec *codec)
113{
114 int reg;
115
116 /* If we're going via the mixer we'll need to do additional checks */
117 reg = snd_soc_read(codec, WM8993_OUTPUT_MIXER1);
118 if (!(reg & WM8993_DACL_TO_HPOUT1L)) {
119 if (reg & ~WM8993_DACL_TO_MIXOUTL) {
120 dev_vdbg(codec->dev, "Analogue paths connected: %x\n",
121 reg & ~WM8993_DACL_TO_HPOUT1L);
122 return false;
123 } else {
124 dev_vdbg(codec->dev, "HPL connected to mixer\n");
125 return false;
126 }
127 } else {
128 dev_vdbg(codec->dev, "HPL connected to DAC\n");
129 }
130
131 reg = snd_soc_read(codec, WM8993_OUTPUT_MIXER2);
132 if (!(reg & WM8993_DACR_TO_HPOUT1R)) {
133 if (reg & ~WM8993_DACR_TO_MIXOUTR) {
134 dev_vdbg(codec->dev, "Analogue paths connected: %x\n",
135 reg & ~WM8993_DACR_TO_HPOUT1R);
136 return false;
137 } else {
138 dev_vdbg(codec->dev, "HPR connected to mixer\n");
139 return false;
140 }
141 } else {
142 dev_vdbg(codec->dev, "HPR connected to DAC\n");
143 }
144
145 return true;
146}
147
112/* 148/*
113 * Startup calibration of the DC servo 149 * Startup calibration of the DC servo
114 */ 150 */
@@ -129,10 +165,10 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
129 165
130 /* If we're using a digital only path and have a previously 166 /* If we're using a digital only path and have a previously
131 * callibrated DC servo offset stored then use that. */ 167 * callibrated DC servo offset stored then use that. */
132 if (hubs->class_w && hubs->class_w_dcs) { 168 if (wm_hubs_dac_hp_direct(codec) && hubs->dac_hp_direct_dcs) {
133 dev_dbg(codec->dev, "Using cached DC servo offset %x\n", 169 dev_dbg(codec->dev, "Using cached DC servo offset %x\n",
134 hubs->class_w_dcs); 170 hubs->dac_hp_direct_dcs);
135 snd_soc_write(codec, dcs_reg, hubs->class_w_dcs); 171 snd_soc_write(codec, dcs_reg, hubs->dac_hp_direct_dcs);
136 wait_for_dc_servo(codec, 172 wait_for_dc_servo(codec,
137 WM8993_DCS_TRIG_DAC_WR_0 | 173 WM8993_DCS_TRIG_DAC_WR_0 |
138 WM8993_DCS_TRIG_DAC_WR_1); 174 WM8993_DCS_TRIG_DAC_WR_1);
@@ -207,8 +243,8 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
207 243
208 /* Save the callibrated offset if we're in class W mode and 244 /* Save the callibrated offset if we're in class W mode and
209 * therefore don't have any analogue signal mixed in. */ 245 * therefore don't have any analogue signal mixed in. */
210 if (hubs->class_w && !hubs->no_cache_class_w) 246 if (wm_hubs_dac_hp_direct(codec) && !hubs->no_cache_dac_hp_direct)
211 hubs->class_w_dcs = dcs_cfg; 247 hubs->dac_hp_direct_dcs = dcs_cfg;
212} 248}
213 249
214/* 250/*
@@ -224,7 +260,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
224 ret = snd_soc_put_volsw(kcontrol, ucontrol); 260 ret = snd_soc_put_volsw(kcontrol, ucontrol);
225 261
226 /* Updating the analogue gains invalidates the DC servo cache */ 262 /* Updating the analogue gains invalidates the DC servo cache */
227 hubs->class_w_dcs = 0; 263 hubs->dac_hp_direct_dcs = 0;
228 264
229 /* If we're applying an offset correction then updating the 265 /* If we're applying an offset correction then updating the
230 * callibration would be likely to introduce further offsets. */ 266 * callibration would be likely to introduce further offsets. */