aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/arizona-micsupp.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-10 14:14:11 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-13 07:31:02 -0500
commite6ed90581bfab234ceeff797e1efbd31d0cec219 (patch)
treec1afd3e0731c64e744a35933a3aa0778d8c4f8a3 /drivers/regulator/arizona-micsupp.c
parent9931faca02c604c22335f5a935a501bb2ace6e20 (diff)
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 <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/arizona-micsupp.c')
-rw-r--r--drivers/regulator/arizona-micsupp.c75
1 files changed, 72 insertions, 3 deletions
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 @@
21#include <linux/regulator/machine.h> 21#include <linux/regulator/machine.h>
22#include <linux/gpio.h> 22#include <linux/gpio.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/workqueue.h>
25#include <sound/soc.h>
24 26
25#include <linux/mfd/arizona/core.h> 27#include <linux/mfd/arizona/core.h>
26#include <linux/mfd/arizona/pdata.h> 28#include <linux/mfd/arizona/pdata.h>
@@ -34,6 +36,8 @@ struct arizona_micsupp {
34 36
35 struct regulator_consumer_supply supply; 37 struct regulator_consumer_supply supply;
36 struct regulator_init_data init_data; 38 struct regulator_init_data init_data;
39
40 struct work_struct check_cp_work;
37}; 41};
38 42
39static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, 43static int arizona_micsupp_list_voltage(struct regulator_dev *rdev,
@@ -72,9 +76,73 @@ static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,
72 return selector; 76 return selector;
73} 77}
74 78
79static void arizona_micsupp_check_cp(struct work_struct *work)
80{
81 struct arizona_micsupp *micsupp =
82 container_of(work, struct arizona_micsupp, check_cp_work);
83 struct snd_soc_dapm_context *dapm = micsupp->arizona->dapm;
84 struct arizona *arizona = micsupp->arizona;
85 struct regmap *regmap = arizona->regmap;
86 unsigned int reg;
87 int ret;
88
89 ret = regmap_read(regmap, ARIZONA_MIC_CHARGE_PUMP_1, &reg);
90 if (ret != 0) {
91 dev_err(arizona->dev, "Failed to read CP state: %d\n", ret);
92 return;
93 }
94
95 if (dapm) {
96 if ((reg & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) ==
97 ARIZONA_CPMIC_ENA)
98 snd_soc_dapm_force_enable_pin(dapm, "MICSUPP");
99 else
100 snd_soc_dapm_disable_pin(dapm, "MICSUPP");
101
102 snd_soc_dapm_sync(dapm);
103 }
104}
105
106static int arizona_micsupp_enable(struct regulator_dev *rdev)
107{
108 struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
109 int ret;
110
111 ret = regulator_enable_regmap(rdev);
112
113 if (ret == 0)
114 schedule_work(&micsupp->check_cp_work);
115
116 return ret;
117}
118
119static int arizona_micsupp_disable(struct regulator_dev *rdev)
120{
121 struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
122 int ret;
123
124 ret = regulator_disable_regmap(rdev);
125 if (ret == 0)
126 schedule_work(&micsupp->check_cp_work);
127
128 return ret;
129}
130
131static int arizona_micsupp_set_bypass(struct regulator_dev *rdev, bool ena)
132{
133 struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
134 int ret;
135
136 ret = regulator_set_bypass_regmap(rdev, ena);
137 if (ret == 0)
138 schedule_work(&micsupp->check_cp_work);
139
140 return ret;
141}
142
75static struct regulator_ops arizona_micsupp_ops = { 143static struct regulator_ops arizona_micsupp_ops = {
76 .enable = regulator_enable_regmap, 144 .enable = arizona_micsupp_enable,
77 .disable = regulator_disable_regmap, 145 .disable = arizona_micsupp_disable,
78 .is_enabled = regulator_is_enabled_regmap, 146 .is_enabled = regulator_is_enabled_regmap,
79 147
80 .list_voltage = arizona_micsupp_list_voltage, 148 .list_voltage = arizona_micsupp_list_voltage,
@@ -84,7 +152,7 @@ static struct regulator_ops arizona_micsupp_ops = {
84 .set_voltage_sel = regulator_set_voltage_sel_regmap, 152 .set_voltage_sel = regulator_set_voltage_sel_regmap,
85 153
86 .get_bypass = regulator_get_bypass_regmap, 154 .get_bypass = regulator_get_bypass_regmap,
87 .set_bypass = regulator_set_bypass_regmap, 155 .set_bypass = arizona_micsupp_set_bypass,
88}; 156};
89 157
90static const struct regulator_desc arizona_micsupp = { 158static const struct regulator_desc arizona_micsupp = {
@@ -131,6 +199,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
131 } 199 }
132 200
133 micsupp->arizona = arizona; 201 micsupp->arizona = arizona;
202 INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);
134 203
135 /* 204 /*
136 * Since the chip usually supplies itself we provide some 205 * Since the chip usually supplies itself we provide some