diff options
| -rw-r--r-- | include/sound/wm2000.h | 3 | ||||
| -rw-r--r-- | sound/soc/codecs/wm2000.c | 35 | ||||
| -rw-r--r-- | sound/soc/codecs/wm2000.h | 3 | 
3 files changed, 34 insertions, 7 deletions
diff --git a/include/sound/wm2000.h b/include/sound/wm2000.h index aa388ca9ec6..4de81f41c90 100644 --- a/include/sound/wm2000.h +++ b/include/sound/wm2000.h @@ -15,9 +15,6 @@ struct wm2000_platform_data {  	/** Filename for system-specific image to download to device. */  	const char *download_file; -	/** Divide MCLK by 2 for system clock? */ -	unsigned int mclkdiv2:1; -  	/** Disable speech clarity enhancement, for use when an  	 * external algorithm is used. */  	unsigned int speech_enh_disable:1; diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index eb96b876809..f2ac38b61a1 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -26,6 +26,7 @@  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/firmware.h> +#include <linux/clk.h>  #include <linux/delay.h>  #include <linux/pm.h>  #include <linux/i2c.h> @@ -62,6 +63,7 @@ enum wm2000_anc_mode {  struct wm2000_priv {  	struct i2c_client *i2c;  	struct regmap *regmap; +	struct clk *mclk;  	struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; @@ -71,7 +73,6 @@ struct wm2000_priv {  	unsigned int anc_eng_ena:1;  	unsigned int spk_ena:1; -	unsigned int mclk_div:1;  	unsigned int speech_clarity:1;  	int anc_download_size; @@ -133,6 +134,7 @@ static int wm2000_poll_bit(struct i2c_client *i2c,  static int wm2000_power_up(struct i2c_client *i2c, int analogue)  {  	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); +	unsigned long rate;  	int ret;  	BUG_ON(wm2000->anc_mode != ANC_OFF); @@ -145,7 +147,8 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)  		return ret;  	} -	if (!wm2000->mclk_div) { +	rate = clk_get_rate(wm2000->mclk); +	if (rate <= 13500000) {  		dev_dbg(&i2c->dev, "Disabling MCLK divider\n");  		wm2000_write(i2c, WM2000_REG_SYS_CTL2,  			     WM2000_MCLK_DIV2_ENA_CLR); @@ -552,6 +555,15 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000,  		return -EINVAL;  	} +	/* Maintain clock while active */ +	if (anc_transitions[i].source == ANC_OFF) { +		ret = clk_prepare_enable(wm2000->mclk); +		if (ret != 0) { +			dev_err(&i2c->dev, "Failed to enable MCLK: %d\n", ret); +			return ret; +		} +	} +  	for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) {  		if (!anc_transitions[i].step[j])  			break; @@ -561,7 +573,10 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000,  			return ret;  	} -	return 0; +	if (anc_transitions[i].dest == ANC_OFF) +		clk_disable_unprepare(wm2000->mclk); + +	return ret;  }  static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) @@ -651,6 +666,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,  }  static const struct snd_kcontrol_new wm2000_controls[] = { +	SOC_SINGLE("ANC Volume", WM2000_REG_ANC_GAIN_CTRL, 0, 255, 0),  	SOC_SINGLE_BOOL_EXT("WM2000 ANC Switch", 0,  			    wm2000_anc_mode_get,  			    wm2000_anc_mode_put), @@ -725,6 +741,9 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg)  {  	switch (reg) {  	case WM2000_REG_SYS_START: +	case WM2000_REG_ANC_GAIN_CTRL: +	case WM2000_REG_MSE_TH1: +	case WM2000_REG_MSE_TH2:  	case WM2000_REG_SPEECH_CLARITY:  	case WM2000_REG_SYS_WATCHDOG:  	case WM2000_REG_ANA_VMID_PD_TIME: @@ -760,6 +779,8 @@ static int wm2000_probe(struct snd_soc_codec *codec)  {  	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +	snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP); +  	/* This will trigger a transition to standby mode by default */  	wm2000_anc_set_mode(wm2000); @@ -848,10 +869,16 @@ static int wm2000_i2c_probe(struct i2c_client *i2c,  	reg = wm2000_read(i2c, WM2000_REG_REVISON);  	dev_info(&i2c->dev, "revision %c\n", reg + 'A'); +	wm2000->mclk = devm_clk_get(&i2c->dev, "MCLK"); +	if (IS_ERR(wm2000->mclk)) { +		ret = PTR_ERR(wm2000->mclk); +		dev_err(&i2c->dev, "Failed to get MCLK: %d\n", ret); +		goto err_supplies; +	} +  	filename = "wm2000_anc.bin";  	pdata = dev_get_platdata(&i2c->dev);  	if (pdata) { -		wm2000->mclk_div = pdata->mclkdiv2;  		wm2000->speech_clarity = !pdata->speech_enh_disable;  		if (pdata->download_file) diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index abcd82a9399..fb812cd9e77 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h @@ -10,6 +10,9 @@  #define _WM2000_H  #define WM2000_REG_SYS_START	    0x8000 +#define WM2000_REG_ANC_GAIN_CTRL    0x8fa2 +#define WM2000_REG_MSE_TH2          0x8fdf +#define WM2000_REG_MSE_TH1          0x8fe0  #define WM2000_REG_SPEECH_CLARITY   0x8fef  #define WM2000_REG_SYS_WATCHDOG     0x8ff6  #define WM2000_REG_ANA_VMID_PD_TIME 0x8ff7  |