From e6ed90581bfab234ceeff797e1efbd31d0cec219 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 Jan 2013 19:14:11 +0000 Subject: [PATCH 1/4] regulator: arizona-micsupp: Enable SYSCLK for charge pump If we are in non-bypass mode then the SYSCLK is required for full charge pump operation, otherwise we will fall back to bypass mode. Use the DAPM context exposed by the ASoC driver to manage this. Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 1 + drivers/regulator/arizona-micsupp.c | 75 +++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 3 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..d96cee48f593 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -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 = { @@ -131,6 +199,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 From 9fc50a2ead28afea1da19c22b1054f7e23d6eb45 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 Jan 2013 19:31:47 +0000 Subject: [PATCH 2/4] regulator: arizona-micsupp: Enable bypass in default constraints This will be used as part of low power accessory detect. Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index d96cee48f593..e87536bf0bed 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -177,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, }, From 55e7276e93f75ae032dbafca141a8403c7f1b450 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 Jan 2013 19:32:21 +0000 Subject: [PATCH 3/4] ASoC: wm5102: Provide MICSUPP widget for regulator driver Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 688ade080589..808608a053c2 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1109,6 +1109,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) \ @@ -1321,6 +1323,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, From 57a10a1fc3c42bdb5225ce22651d6f2b03ba8325 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 10 Jan 2013 19:32:33 +0000 Subject: [PATCH 4/4] ASoC: wm5110: Provide MICSUPP widget for regulator driver Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index ae80c8c28536..c1d46d608e5d 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -625,6 +625,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) \ @@ -833,6 +835,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,