diff options
Diffstat (limited to 'drivers/regulator/arizona-micsupp.c')
-rw-r--r-- | drivers/regulator/arizona-micsupp.c | 78 |
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 | ||
39 | static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, | 43 | static 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 | ||
79 | static 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, ®); | ||
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 | |||
106 | static 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 | |||
119 | static 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 | |||
131 | static 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 | |||
75 | static struct regulator_ops arizona_micsupp_ops = { | 143 | static 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 | ||
90 | static const struct regulator_desc arizona_micsupp = { | 158 | static const struct regulator_desc arizona_micsupp = { |
@@ -109,7 +177,8 @@ static const struct regulator_desc arizona_micsupp = { | |||
109 | static const struct regulator_init_data arizona_micsupp_default = { | 177 | static 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 |