aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/arizona-micsupp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/arizona-micsupp.c')
-rw-r--r--drivers/regulator/arizona-micsupp.c78
1 files changed, 74 insertions, 4 deletions
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 @@
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 = {
@@ -109,7 +177,8 @@ static const struct regulator_desc arizona_micsupp = {
109static const struct regulator_init_data arizona_micsupp_default = { 177static const struct regulator_init_data arizona_micsupp_default = {
110 .constraints = { 178 .constraints = {
111 .valid_ops_mask = REGULATOR_CHANGE_STATUS | 179 .valid_ops_mask = REGULATOR_CHANGE_STATUS |
112 REGULATOR_CHANGE_VOLTAGE, 180 REGULATOR_CHANGE_VOLTAGE |
181 REGULATOR_CHANGE_BYPASS,
113 .min_uV = 1700000, 182 .min_uV = 1700000,
114 .max_uV = 3300000, 183 .max_uV = 3300000,
115 }, 184 },
@@ -131,6 +200,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
131 } 200 }
132 201
133 micsupp->arizona = arizona; 202 micsupp->arizona = arizona;
203 INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);
134 204
135 /* 205 /*
136 * Since the chip usually supplies itself we provide some 206 * Since the chip usually supplies itself we provide some