Blame view
drivers/regulator/arizona-micsupp.c
9.92 KB
dfc0c82b3 regulator: arizon... |
1 2 3 4 5 6 7 |
// SPDX-License-Identifier: GPL-2.0+ // // arizona-micsupp.c -- Microphone supply for Arizona devices // // Copyright 2012 Wolfson Microelectronics PLC. // // Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
b667a45d9 regulator: arizon... |
8 9 10 11 12 13 |
#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/bitops.h> #include <linux/err.h> |
6f1c9c57b regulator: arizon... |
14 |
#include <linux/of.h> |
b667a45d9 regulator: arizon... |
15 16 17 |
#include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> |
36bcdf1bb regulator: arizon... |
18 |
#include <linux/regulator/of_regulator.h> |
b667a45d9 regulator: arizon... |
19 |
#include <linux/slab.h> |
e6ed90581 regulator: arizon... |
20 21 |
#include <linux/workqueue.h> #include <sound/soc.h> |
b667a45d9 regulator: arizon... |
22 23 24 25 |
#include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/pdata.h> #include <linux/mfd/arizona/registers.h> |
7bd7916dc regulator: arizon... |
26 27 28 |
#include <linux/mfd/madera/core.h> #include <linux/mfd/madera/pdata.h> #include <linux/mfd/madera/registers.h> |
22161f3eb regulator: arizon... |
29 |
#include <linux/regulator/arizona-micsupp.h> |
b667a45d9 regulator: arizon... |
30 31 |
struct arizona_micsupp { struct regulator_dev *regulator; |
e165983e5 regulator: arizon... |
32 33 34 35 |
struct regmap *regmap; struct snd_soc_dapm_context **dapm; unsigned int enable_reg; struct device *dev; |
b667a45d9 regulator: arizon... |
36 37 38 |
struct regulator_consumer_supply supply; struct regulator_init_data init_data; |
e6ed90581 regulator: arizon... |
39 40 |
struct work_struct check_cp_work; |
b667a45d9 regulator: arizon... |
41 |
}; |
e6ed90581 regulator: arizon... |
42 43 44 45 |
static void arizona_micsupp_check_cp(struct work_struct *work) { struct arizona_micsupp *micsupp = container_of(work, struct arizona_micsupp, check_cp_work); |
e165983e5 regulator: arizon... |
46 47 48 |
struct snd_soc_dapm_context *dapm = *micsupp->dapm; struct snd_soc_component *component; unsigned int val; |
e6ed90581 regulator: arizon... |
49 |
int ret; |
e165983e5 regulator: arizon... |
50 |
ret = regmap_read(micsupp->regmap, micsupp->enable_reg, &val); |
e6ed90581 regulator: arizon... |
51 |
if (ret != 0) { |
e165983e5 regulator: arizon... |
52 53 54 |
dev_err(micsupp->dev, "Failed to read CP state: %d ", ret); |
e6ed90581 regulator: arizon... |
55 56 57 58 |
return; } if (dapm) { |
e165983e5 regulator: arizon... |
59 60 61 |
component = snd_soc_dapm_to_component(dapm); if ((val & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == |
e6ed90581 regulator: arizon... |
62 |
ARIZONA_CPMIC_ENA) |
98cf9965c regulator: arizon... |
63 64 |
snd_soc_component_force_enable_pin(component, "MICSUPP"); |
e6ed90581 regulator: arizon... |
65 |
else |
98cf9965c regulator: arizon... |
66 |
snd_soc_component_disable_pin(component, "MICSUPP"); |
e6ed90581 regulator: arizon... |
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
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; } |
2773ead13 regulator: arizon... |
108 |
static const struct regulator_ops arizona_micsupp_ops = { |
e6ed90581 regulator: arizon... |
109 110 |
.enable = arizona_micsupp_enable, .disable = arizona_micsupp_disable, |
b667a45d9 regulator: arizon... |
111 |
.is_enabled = regulator_is_enabled_regmap, |
71979aa3c regulator: arizon... |
112 113 |
.list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, |
b667a45d9 regulator: arizon... |
114 115 116 |
.get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, |
e477ce075 regulator: arizon... |
117 118 |
.get_bypass = regulator_get_bypass_regmap, |
e6ed90581 regulator: arizon... |
119 |
.set_bypass = arizona_micsupp_set_bypass, |
b667a45d9 regulator: arizon... |
120 |
}; |
60ab7f415 regulator: use li... |
121 |
static const struct linear_range arizona_micsupp_ranges[] = { |
71979aa3c regulator: arizon... |
122 123 124 |
REGULATOR_LINEAR_RANGE(1700000, 0, 0x1e, 50000), REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0), }; |
b667a45d9 regulator: arizon... |
125 126 127 128 |
static const struct regulator_desc arizona_micsupp = { .name = "MICVDD", .supply_name = "CPVDD", .type = REGULATOR_VOLTAGE, |
71979aa3c regulator: arizon... |
129 |
.n_voltages = 32, |
b667a45d9 regulator: arizon... |
130 131 132 133 134 135 |
.ops = &arizona_micsupp_ops, .vsel_reg = ARIZONA_LDO2_CONTROL_1, .vsel_mask = ARIZONA_LDO2_VSEL_MASK, .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, .enable_mask = ARIZONA_CPMIC_ENA, |
e477ce075 regulator: arizon... |
136 137 |
.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, .bypass_mask = ARIZONA_CPMIC_BYPASS, |
b667a45d9 regulator: arizon... |
138 |
|
71979aa3c regulator: arizon... |
139 140 |
.linear_ranges = arizona_micsupp_ranges, .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ranges), |
950728185 regulator: arizon... |
141 |
.enable_time = 3000, |
b667a45d9 regulator: arizon... |
142 143 |
.owner = THIS_MODULE, }; |
60ab7f415 regulator: use li... |
144 |
static const struct linear_range arizona_micsupp_ext_ranges[] = { |
d2e7491e2 regulator: arizon... |
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
REGULATOR_LINEAR_RANGE(900000, 0, 0x14, 25000), REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000), }; static const struct regulator_desc arizona_micsupp_ext = { .name = "MICVDD", .supply_name = "CPVDD", .type = REGULATOR_VOLTAGE, .n_voltages = 40, .ops = &arizona_micsupp_ops, .vsel_reg = ARIZONA_LDO2_CONTROL_1, .vsel_mask = ARIZONA_LDO2_VSEL_MASK, .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, .enable_mask = ARIZONA_CPMIC_ENA, .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, .bypass_mask = ARIZONA_CPMIC_BYPASS, .linear_ranges = arizona_micsupp_ext_ranges, .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges), .enable_time = 3000, .owner = THIS_MODULE, }; |
b667a45d9 regulator: arizon... |
170 171 172 |
static const struct regulator_init_data arizona_micsupp_default = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS | |
9fc50a2ea regulator: arizon... |
173 174 |
REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_BYPASS, |
b667a45d9 regulator: arizon... |
175 176 177 178 179 180 |
.min_uV = 1700000, .max_uV = 3300000, }, .num_consumer_supplies = 1, }; |
d2e7491e2 regulator: arizon... |
181 182 183 184 185 186 187 188 189 190 191 |
static const struct regulator_init_data arizona_micsupp_ext_default = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_BYPASS, .min_uV = 900000, .max_uV = 3300000, }, .num_consumer_supplies = 1, }; |
7bd7916dc regulator: arizon... |
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
static const struct regulator_desc madera_micsupp = { .name = "MICVDD", .supply_name = "CPVDD1", .type = REGULATOR_VOLTAGE, .n_voltages = 40, .ops = &arizona_micsupp_ops, .vsel_reg = MADERA_LDO2_CONTROL_1, .vsel_mask = MADERA_LDO2_VSEL_MASK, .enable_reg = MADERA_MIC_CHARGE_PUMP_1, .enable_mask = MADERA_CPMIC_ENA, .bypass_reg = MADERA_MIC_CHARGE_PUMP_1, .bypass_mask = MADERA_CPMIC_BYPASS, .linear_ranges = arizona_micsupp_ext_ranges, .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges), .enable_time = 3000, .owner = THIS_MODULE, }; |
22161f3eb regulator: arizon... |
213 |
static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata, |
072e78b12 regulator: of: Ad... |
214 215 |
struct regulator_config *config, const struct regulator_desc *desc) |
36bcdf1bb regulator: arizon... |
216 |
{ |
36bcdf1bb regulator: arizon... |
217 218 219 |
struct arizona_micsupp *micsupp = config->driver_data; struct device_node *np; struct regulator_init_data *init_data; |
22161f3eb regulator: arizon... |
220 |
np = of_get_child_by_name(config->dev->of_node, "micvdd"); |
36bcdf1bb regulator: arizon... |
221 222 223 |
if (np) { config->of_node = np; |
22161f3eb regulator: arizon... |
224 |
init_data = of_get_regulator_init_data(config->dev, np, desc); |
36bcdf1bb regulator: arizon... |
225 226 227 228 |
if (init_data) { init_data->consumer_supplies = &micsupp->supply; init_data->num_consumer_supplies = 1; |
22161f3eb regulator: arizon... |
229 |
pdata->init_data = init_data; |
36bcdf1bb regulator: arizon... |
230 231 232 233 234 |
} } return 0; } |
7d8d14b51 regulator: arizon... |
235 236 237 238 |
static int arizona_micsupp_common_init(struct platform_device *pdev, struct arizona_micsupp *micsupp, const struct regulator_desc *desc, struct arizona_micsupp_pdata *pdata) |
b667a45d9 regulator: arizon... |
239 |
{ |
b667a45d9 regulator: arizon... |
240 |
struct regulator_config config = { }; |
b667a45d9 regulator: arizon... |
241 |
int ret; |
e6ed90581 regulator: arizon... |
242 |
INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp); |
b667a45d9 regulator: arizon... |
243 |
|
b667a45d9 regulator: arizon... |
244 245 |
micsupp->init_data.consumer_supplies = &micsupp->supply; micsupp->supply.supply = "MICVDD"; |
7d8d14b51 regulator: arizon... |
246 |
micsupp->supply.dev_name = dev_name(micsupp->dev); |
e165983e5 regulator: arizon... |
247 |
micsupp->enable_reg = desc->enable_reg; |
b667a45d9 regulator: arizon... |
248 |
|
7d8d14b51 regulator: arizon... |
249 |
config.dev = micsupp->dev; |
b667a45d9 regulator: arizon... |
250 |
config.driver_data = micsupp; |
7d8d14b51 regulator: arizon... |
251 |
config.regmap = micsupp->regmap; |
b667a45d9 regulator: arizon... |
252 |
|
36bcdf1bb regulator: arizon... |
253 |
if (IS_ENABLED(CONFIG_OF)) { |
7d8d14b51 regulator: arizon... |
254 |
if (!dev_get_platdata(micsupp->dev)) { |
22161f3eb regulator: arizon... |
255 256 |
ret = arizona_micsupp_of_get_pdata(pdata, &config, desc); |
36bcdf1bb regulator: arizon... |
257 258 259 260 |
if (ret < 0) return ret; } } |
22161f3eb regulator: arizon... |
261 262 |
if (pdata->init_data) config.init_data = pdata->init_data; |
b667a45d9 regulator: arizon... |
263 264 |
else config.init_data = &micsupp->init_data; |
7d8d14b51 regulator: arizon... |
265 266 |
/* Default to regulated mode */ regmap_update_bits(micsupp->regmap, micsupp->enable_reg, |
6dc027c97 regulator: arizon... |
267 |
ARIZONA_CPMIC_BYPASS, 0); |
b6b7709cf regulator: arizon... |
268 |
micsupp->regulator = devm_regulator_register(&pdev->dev, |
d2e7491e2 regulator: arizon... |
269 |
desc, |
b6b7709cf regulator: arizon... |
270 |
&config); |
a7b976ae4 regulator: arizon... |
271 272 |
of_node_put(config.of_node); |
b667a45d9 regulator: arizon... |
273 274 |
if (IS_ERR(micsupp->regulator)) { ret = PTR_ERR(micsupp->regulator); |
7d8d14b51 regulator: arizon... |
275 276 |
dev_err(micsupp->dev, "Failed to register mic supply: %d ", |
b667a45d9 regulator: arizon... |
277 278 279 280 281 282 283 284 |
ret); return ret; } platform_set_drvdata(pdev, micsupp); return 0; } |
7d8d14b51 regulator: arizon... |
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
static int arizona_micsupp_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); const struct regulator_desc *desc; struct arizona_micsupp *micsupp; micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL); if (!micsupp) return -ENOMEM; micsupp->regmap = arizona->regmap; micsupp->dapm = &arizona->dapm; micsupp->dev = arizona->dev; /* * Since the chip usually supplies itself we provide some * default init_data for it. This will be overridden with * platform data if provided. */ switch (arizona->type) { case WM5110: case WM8280: desc = &arizona_micsupp_ext; micsupp->init_data = arizona_micsupp_ext_default; break; default: desc = &arizona_micsupp; micsupp->init_data = arizona_micsupp_default; break; } return arizona_micsupp_common_init(pdev, micsupp, desc, &arizona->pdata.micvdd); } |
7bd7916dc regulator: arizon... |
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
static int madera_micsupp_probe(struct platform_device *pdev) { struct madera *madera = dev_get_drvdata(pdev->dev.parent); struct arizona_micsupp *micsupp; micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL); if (!micsupp) return -ENOMEM; micsupp->regmap = madera->regmap; micsupp->dapm = &madera->dapm; micsupp->dev = madera->dev; micsupp->init_data = arizona_micsupp_ext_default; return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp, &madera->pdata.micvdd); } |
b667a45d9 regulator: arizon... |
336 337 |
static struct platform_driver arizona_micsupp_driver = { .probe = arizona_micsupp_probe, |
b667a45d9 regulator: arizon... |
338 339 |
.driver = { .name = "arizona-micsupp", |
b667a45d9 regulator: arizon... |
340 341 |
}, }; |
7bd7916dc regulator: arizon... |
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
static struct platform_driver madera_micsupp_driver = { .probe = madera_micsupp_probe, .driver = { .name = "madera-micsupp", }, }; static struct platform_driver * const arizona_micsupp_drivers[] = { &arizona_micsupp_driver, &madera_micsupp_driver, }; static int __init arizona_micsupp_init(void) { return platform_register_drivers(arizona_micsupp_drivers, ARRAY_SIZE(arizona_micsupp_drivers)); } module_init(arizona_micsupp_init); static void __exit arizona_micsupp_exit(void) { platform_unregister_drivers(arizona_micsupp_drivers, ARRAY_SIZE(arizona_micsupp_drivers)); } module_exit(arizona_micsupp_exit); |
b667a45d9 regulator: arizon... |
367 368 369 370 371 372 |
/* Module information */ MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_DESCRIPTION("Arizona microphone supply driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:arizona-micsupp"); |
7bd7916dc regulator: arizon... |
373 |
MODULE_ALIAS("platform:madera-micsupp"); |