summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/Kconfig1
-rw-r--r--drivers/regulator/arizona-micsupp.c78
-rw-r--r--sound/soc/codecs/wm5102.c4
-rw-r--r--sound/soc/codecs/wm5110.c4
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, &reg);
+ 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,