diff options
| -rw-r--r-- | drivers/regulator/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/regulator/arizona-micsupp.c | 78 | ||||
| -rw-r--r-- | sound/soc/codecs/wm5102.c | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/wm5110.c | 4 | 
4 files changed, 83 insertions, 4 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 551a22b07538..22b25115ed14 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -91,6 +91,7 @@ config REGULATOR_AAT2870  config REGULATOR_ARIZONA  	tristate "Wolfson Arizona class devices"  	depends on MFD_ARIZONA +	depends on SND_SOC  	help  	  Support for the regulators found on Wolfson Arizona class  	  devices. diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index a6d040cbf8ac..e87536bf0bed 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -21,6 +21,8 @@  #include <linux/regulator/machine.h>  #include <linux/gpio.h>  #include <linux/slab.h> +#include <linux/workqueue.h> +#include <sound/soc.h>  #include <linux/mfd/arizona/core.h>  #include <linux/mfd/arizona/pdata.h> @@ -34,6 +36,8 @@ struct arizona_micsupp {  	struct regulator_consumer_supply supply;  	struct regulator_init_data init_data; + +	struct work_struct check_cp_work;  };  static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, @@ -72,9 +76,73 @@ static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,  	return selector;  } +static void arizona_micsupp_check_cp(struct work_struct *work) +{ +	struct arizona_micsupp *micsupp = +		container_of(work, struct arizona_micsupp, check_cp_work); +	struct snd_soc_dapm_context *dapm = micsupp->arizona->dapm; +	struct arizona *arizona = micsupp->arizona; +	struct regmap *regmap = arizona->regmap; +	unsigned int reg; +	int ret; + +	ret = regmap_read(regmap, ARIZONA_MIC_CHARGE_PUMP_1, ®); +	if (ret != 0) { +		dev_err(arizona->dev, "Failed to read CP state: %d\n", ret); +		return; +	} + +	if (dapm) { +		if ((reg & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == +		    ARIZONA_CPMIC_ENA) +			snd_soc_dapm_force_enable_pin(dapm, "MICSUPP"); +		else +			snd_soc_dapm_disable_pin(dapm, "MICSUPP"); + +		snd_soc_dapm_sync(dapm); +	} +} + +static int arizona_micsupp_enable(struct regulator_dev *rdev) +{ +	struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); +	int ret; + +	ret = regulator_enable_regmap(rdev); + +	if (ret == 0) +		schedule_work(&micsupp->check_cp_work); + +	return ret; +} + +static int arizona_micsupp_disable(struct regulator_dev *rdev) +{ +	struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); +	int ret; + +	ret = regulator_disable_regmap(rdev); +	if (ret == 0) +		schedule_work(&micsupp->check_cp_work); + +	return ret; +} + +static int arizona_micsupp_set_bypass(struct regulator_dev *rdev, bool ena) +{ +	struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); +	int ret; + +	ret = regulator_set_bypass_regmap(rdev, ena); +	if (ret == 0) +		schedule_work(&micsupp->check_cp_work); + +	return ret; +} +  static struct regulator_ops arizona_micsupp_ops = { -	.enable = regulator_enable_regmap, -	.disable = regulator_disable_regmap, +	.enable = arizona_micsupp_enable, +	.disable = arizona_micsupp_disable,  	.is_enabled = regulator_is_enabled_regmap,  	.list_voltage = arizona_micsupp_list_voltage, @@ -84,7 +152,7 @@ static struct regulator_ops arizona_micsupp_ops = {  	.set_voltage_sel = regulator_set_voltage_sel_regmap,  	.get_bypass = regulator_get_bypass_regmap, -	.set_bypass = regulator_set_bypass_regmap, +	.set_bypass = arizona_micsupp_set_bypass,  };  static const struct regulator_desc arizona_micsupp = { @@ -109,7 +177,8 @@ static const struct regulator_desc arizona_micsupp = {  static const struct regulator_init_data arizona_micsupp_default = {  	.constraints = {  		.valid_ops_mask = REGULATOR_CHANGE_STATUS | -				REGULATOR_CHANGE_VOLTAGE, +				REGULATOR_CHANGE_VOLTAGE | +				REGULATOR_CHANGE_BYPASS,  		.min_uV = 1700000,  		.max_uV = 3300000,  	}, @@ -131,6 +200,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)  	}  	micsupp->arizona = arizona; +	INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);  	/*  	 * Since the chip usually supplies itself we provide some diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 1440b3f9b7bb..988e817dca05 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1152,6 +1152,8 @@ SND_SOC_DAPM_OUTPUT("SPKOUTRN"),  SND_SOC_DAPM_OUTPUT("SPKOUTRP"),  SND_SOC_DAPM_OUTPUT("SPKDAT1L"),  SND_SOC_DAPM_OUTPUT("SPKDAT1R"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"),  };  #define ARIZONA_MIXER_INPUT_ROUTES(name)	\ @@ -1364,6 +1366,8 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {  	{ "AEC Loopback", "SPKDAT1R", "OUT5R" },  	{ "SPKDAT1L", NULL, "OUT5L" },  	{ "SPKDAT1R", NULL, "OUT5R" }, + +	{ "MICSUPP", NULL, "SYSCLK" },  };  static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 7a090968c4f7..0320a32670d3 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -624,6 +624,8 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1L"),  SND_SOC_DAPM_OUTPUT("SPKDAT1R"),  SND_SOC_DAPM_OUTPUT("SPKDAT2L"),  SND_SOC_DAPM_OUTPUT("SPKDAT2R"), + +SND_SOC_DAPM_OUTPUT("MICSUPP"),  };  #define ARIZONA_MIXER_INPUT_ROUTES(name)	\ @@ -832,6 +834,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {  	{ "SPKDAT2L", NULL, "OUT6L" },  	{ "SPKDAT2R", NULL, "OUT6R" }, + +	{ "MICSUPP", NULL, "SYSCLK" },  };  static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,  | 
