diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-26 20:06:56 +0100 | 
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-27 18:42:10 +0100 | 
| commit | af31a227e1abee06ccd88c2c52f4fb36b786cebe (patch) | |
| tree | 1d828dbc011d4c8871f851ba4dcf6a3fe45995c7 /sound/soc/codecs/wm_hubs.c | |
| parent | f57b8488bc39f7674cbadf4e2db05a7db8ffa660 (diff) | |
| download | olio-linux-3.10-af31a227e1abee06ccd88c2c52f4fb36b786cebe.tar.xz olio-linux-3.10-af31a227e1abee06ccd88c2c52f4fb36b786cebe.zip  | |
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.c | 48 | 
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)  }  EXPORT_SYMBOL_GPL(wm_hubs_dcs_done); +static bool wm_hubs_dac_hp_direct(struct snd_soc_codec *codec) +{ +	int reg; + +	/* If we're going via the mixer we'll need to do additional checks */ +	reg = snd_soc_read(codec, WM8993_OUTPUT_MIXER1); +	if (!(reg & WM8993_DACL_TO_HPOUT1L)) { +		if (reg & ~WM8993_DACL_TO_MIXOUTL) { +			dev_vdbg(codec->dev, "Analogue paths connected: %x\n", +				 reg & ~WM8993_DACL_TO_HPOUT1L); +			return false; +		} else { +			dev_vdbg(codec->dev, "HPL connected to mixer\n"); +			return false; +		} +	} else { +		dev_vdbg(codec->dev, "HPL connected to DAC\n"); +	} + +	reg = snd_soc_read(codec, WM8993_OUTPUT_MIXER2); +	if (!(reg & WM8993_DACR_TO_HPOUT1R)) { +		if (reg & ~WM8993_DACR_TO_MIXOUTR) { +			dev_vdbg(codec->dev, "Analogue paths connected: %x\n", +				 reg & ~WM8993_DACR_TO_HPOUT1R); +			return false; +		} else { +			dev_vdbg(codec->dev, "HPR connected to mixer\n"); +			return false; +		} +	} else { +		dev_vdbg(codec->dev, "HPR connected to DAC\n"); +	} + +	return true; +} +  /*   * Startup calibration of the DC servo   */ @@ -129,10 +165,10 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)  	/* If we're using a digital only path and have a previously  	 * callibrated DC servo offset stored then use that. */ -	if (hubs->class_w && hubs->class_w_dcs) { +	if (wm_hubs_dac_hp_direct(codec) && hubs->dac_hp_direct_dcs) {  		dev_dbg(codec->dev, "Using cached DC servo offset %x\n", -			hubs->class_w_dcs); -		snd_soc_write(codec, dcs_reg, hubs->class_w_dcs); +			hubs->dac_hp_direct_dcs); +		snd_soc_write(codec, dcs_reg, hubs->dac_hp_direct_dcs);  		wait_for_dc_servo(codec,  				  WM8993_DCS_TRIG_DAC_WR_0 |  				  WM8993_DCS_TRIG_DAC_WR_1); @@ -207,8 +243,8 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)  	/* Save the callibrated offset if we're in class W mode and  	 * therefore don't have any analogue signal mixed in. */ -	if (hubs->class_w && !hubs->no_cache_class_w) -		hubs->class_w_dcs = dcs_cfg; +	if (wm_hubs_dac_hp_direct(codec) && !hubs->no_cache_dac_hp_direct) +		hubs->dac_hp_direct_dcs = dcs_cfg;  }  /* @@ -224,7 +260,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,  	ret = snd_soc_put_volsw(kcontrol, ucontrol);  	/* Updating the analogue gains invalidates the DC servo cache */ -	hubs->class_w_dcs = 0; +	hubs->dac_hp_direct_dcs = 0;  	/* If we're applying an offset correction then updating the  	 * callibration would be likely to introduce further offsets. */  |