0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/init.h>
0012 #include <linux/bitops.h>
0013 #include <linux/err.h>
0014 #include <linux/of.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regulator/driver.h>
0017 #include <linux/regulator/machine.h>
0018 #include <linux/regulator/of_regulator.h>
0019 #include <linux/slab.h>
0020 #include <linux/workqueue.h>
0021 #include <sound/soc.h>
0022
0023 #include <linux/mfd/arizona/core.h>
0024 #include <linux/mfd/arizona/pdata.h>
0025 #include <linux/mfd/arizona/registers.h>
0026
0027 #include <linux/mfd/madera/core.h>
0028 #include <linux/mfd/madera/pdata.h>
0029 #include <linux/mfd/madera/registers.h>
0030
0031 #include <linux/regulator/arizona-micsupp.h>
0032
0033 struct arizona_micsupp {
0034 struct regulator_dev *regulator;
0035 struct regmap *regmap;
0036 struct snd_soc_dapm_context **dapm;
0037 unsigned int enable_reg;
0038 struct device *dev;
0039
0040 struct regulator_consumer_supply supply;
0041 struct regulator_init_data init_data;
0042
0043 struct work_struct check_cp_work;
0044 };
0045
0046 static void arizona_micsupp_check_cp(struct work_struct *work)
0047 {
0048 struct arizona_micsupp *micsupp =
0049 container_of(work, struct arizona_micsupp, check_cp_work);
0050 struct snd_soc_dapm_context *dapm = *micsupp->dapm;
0051 struct snd_soc_component *component;
0052 unsigned int val;
0053 int ret;
0054
0055 ret = regmap_read(micsupp->regmap, micsupp->enable_reg, &val);
0056 if (ret != 0) {
0057 dev_err(micsupp->dev,
0058 "Failed to read CP state: %d\n", ret);
0059 return;
0060 }
0061
0062 if (dapm) {
0063 component = snd_soc_dapm_to_component(dapm);
0064
0065 if ((val & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) ==
0066 ARIZONA_CPMIC_ENA)
0067 snd_soc_component_force_enable_pin(component,
0068 "MICSUPP");
0069 else
0070 snd_soc_component_disable_pin(component, "MICSUPP");
0071
0072 snd_soc_dapm_sync(dapm);
0073 }
0074 }
0075
0076 static int arizona_micsupp_enable(struct regulator_dev *rdev)
0077 {
0078 struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
0079 int ret;
0080
0081 ret = regulator_enable_regmap(rdev);
0082
0083 if (ret == 0)
0084 schedule_work(&micsupp->check_cp_work);
0085
0086 return ret;
0087 }
0088
0089 static int arizona_micsupp_disable(struct regulator_dev *rdev)
0090 {
0091 struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
0092 int ret;
0093
0094 ret = regulator_disable_regmap(rdev);
0095 if (ret == 0)
0096 schedule_work(&micsupp->check_cp_work);
0097
0098 return ret;
0099 }
0100
0101 static int arizona_micsupp_set_bypass(struct regulator_dev *rdev, bool ena)
0102 {
0103 struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
0104 int ret;
0105
0106 ret = regulator_set_bypass_regmap(rdev, ena);
0107 if (ret == 0)
0108 schedule_work(&micsupp->check_cp_work);
0109
0110 return ret;
0111 }
0112
0113 static const struct regulator_ops arizona_micsupp_ops = {
0114 .enable = arizona_micsupp_enable,
0115 .disable = arizona_micsupp_disable,
0116 .is_enabled = regulator_is_enabled_regmap,
0117
0118 .list_voltage = regulator_list_voltage_linear_range,
0119 .map_voltage = regulator_map_voltage_linear_range,
0120
0121 .get_voltage_sel = regulator_get_voltage_sel_regmap,
0122 .set_voltage_sel = regulator_set_voltage_sel_regmap,
0123
0124 .get_bypass = regulator_get_bypass_regmap,
0125 .set_bypass = arizona_micsupp_set_bypass,
0126 };
0127
0128 static const struct linear_range arizona_micsupp_ranges[] = {
0129 REGULATOR_LINEAR_RANGE(1700000, 0, 0x1e, 50000),
0130 REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0),
0131 };
0132
0133 static const struct regulator_desc arizona_micsupp = {
0134 .name = "MICVDD",
0135 .supply_name = "CPVDD",
0136 .type = REGULATOR_VOLTAGE,
0137 .n_voltages = 32,
0138 .ops = &arizona_micsupp_ops,
0139
0140 .vsel_reg = ARIZONA_LDO2_CONTROL_1,
0141 .vsel_mask = ARIZONA_LDO2_VSEL_MASK,
0142 .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
0143 .enable_mask = ARIZONA_CPMIC_ENA,
0144 .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
0145 .bypass_mask = ARIZONA_CPMIC_BYPASS,
0146
0147 .linear_ranges = arizona_micsupp_ranges,
0148 .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ranges),
0149
0150 .enable_time = 3000,
0151
0152 .owner = THIS_MODULE,
0153 };
0154
0155 static const struct linear_range arizona_micsupp_ext_ranges[] = {
0156 REGULATOR_LINEAR_RANGE(900000, 0, 0x14, 25000),
0157 REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000),
0158 };
0159
0160 static const struct regulator_desc arizona_micsupp_ext = {
0161 .name = "MICVDD",
0162 .supply_name = "CPVDD",
0163 .type = REGULATOR_VOLTAGE,
0164 .n_voltages = 40,
0165 .ops = &arizona_micsupp_ops,
0166
0167 .vsel_reg = ARIZONA_LDO2_CONTROL_1,
0168 .vsel_mask = ARIZONA_LDO2_VSEL_MASK,
0169 .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
0170 .enable_mask = ARIZONA_CPMIC_ENA,
0171 .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
0172 .bypass_mask = ARIZONA_CPMIC_BYPASS,
0173
0174 .linear_ranges = arizona_micsupp_ext_ranges,
0175 .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges),
0176
0177 .enable_time = 3000,
0178
0179 .owner = THIS_MODULE,
0180 };
0181
0182 static const struct regulator_init_data arizona_micsupp_default = {
0183 .constraints = {
0184 .valid_ops_mask = REGULATOR_CHANGE_STATUS |
0185 REGULATOR_CHANGE_VOLTAGE |
0186 REGULATOR_CHANGE_BYPASS,
0187 .min_uV = 1700000,
0188 .max_uV = 3300000,
0189 },
0190
0191 .num_consumer_supplies = 1,
0192 };
0193
0194 static const struct regulator_init_data arizona_micsupp_ext_default = {
0195 .constraints = {
0196 .valid_ops_mask = REGULATOR_CHANGE_STATUS |
0197 REGULATOR_CHANGE_VOLTAGE |
0198 REGULATOR_CHANGE_BYPASS,
0199 .min_uV = 900000,
0200 .max_uV = 3300000,
0201 },
0202
0203 .num_consumer_supplies = 1,
0204 };
0205
0206 static const struct regulator_desc madera_micsupp = {
0207 .name = "MICVDD",
0208 .supply_name = "CPVDD1",
0209 .type = REGULATOR_VOLTAGE,
0210 .n_voltages = 40,
0211 .ops = &arizona_micsupp_ops,
0212
0213 .vsel_reg = MADERA_LDO2_CONTROL_1,
0214 .vsel_mask = MADERA_LDO2_VSEL_MASK,
0215 .enable_reg = MADERA_MIC_CHARGE_PUMP_1,
0216 .enable_mask = MADERA_CPMIC_ENA,
0217 .bypass_reg = MADERA_MIC_CHARGE_PUMP_1,
0218 .bypass_mask = MADERA_CPMIC_BYPASS,
0219
0220 .linear_ranges = arizona_micsupp_ext_ranges,
0221 .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges),
0222
0223 .enable_time = 3000,
0224
0225 .owner = THIS_MODULE,
0226 };
0227
0228 static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata,
0229 struct regulator_config *config,
0230 const struct regulator_desc *desc)
0231 {
0232 struct arizona_micsupp *micsupp = config->driver_data;
0233 struct device_node *np;
0234 struct regulator_init_data *init_data;
0235
0236 np = of_get_child_by_name(config->dev->of_node, "micvdd");
0237
0238 if (np) {
0239 config->of_node = np;
0240
0241 init_data = of_get_regulator_init_data(config->dev, np, desc);
0242
0243 if (init_data) {
0244 init_data->consumer_supplies = &micsupp->supply;
0245 init_data->num_consumer_supplies = 1;
0246
0247 pdata->init_data = init_data;
0248 }
0249 }
0250
0251 return 0;
0252 }
0253
0254 static int arizona_micsupp_common_init(struct platform_device *pdev,
0255 struct arizona_micsupp *micsupp,
0256 const struct regulator_desc *desc,
0257 struct arizona_micsupp_pdata *pdata)
0258 {
0259 struct regulator_config config = { };
0260 int ret;
0261
0262 INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);
0263
0264 micsupp->init_data.consumer_supplies = &micsupp->supply;
0265 micsupp->supply.supply = "MICVDD";
0266 micsupp->supply.dev_name = dev_name(micsupp->dev);
0267 micsupp->enable_reg = desc->enable_reg;
0268
0269 config.dev = micsupp->dev;
0270 config.driver_data = micsupp;
0271 config.regmap = micsupp->regmap;
0272
0273 if (IS_ENABLED(CONFIG_OF)) {
0274 if (!dev_get_platdata(micsupp->dev)) {
0275 ret = arizona_micsupp_of_get_pdata(pdata, &config,
0276 desc);
0277 if (ret < 0)
0278 return ret;
0279 }
0280 }
0281
0282 if (pdata->init_data)
0283 config.init_data = pdata->init_data;
0284 else
0285 config.init_data = &micsupp->init_data;
0286
0287
0288 regmap_update_bits(micsupp->regmap, micsupp->enable_reg,
0289 ARIZONA_CPMIC_BYPASS, 0);
0290
0291 micsupp->regulator = devm_regulator_register(&pdev->dev,
0292 desc,
0293 &config);
0294
0295 of_node_put(config.of_node);
0296
0297 if (IS_ERR(micsupp->regulator)) {
0298 ret = PTR_ERR(micsupp->regulator);
0299 dev_err(micsupp->dev, "Failed to register mic supply: %d\n",
0300 ret);
0301 return ret;
0302 }
0303
0304 platform_set_drvdata(pdev, micsupp);
0305
0306 return 0;
0307 }
0308
0309 static int arizona_micsupp_probe(struct platform_device *pdev)
0310 {
0311 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
0312 const struct regulator_desc *desc;
0313 struct arizona_micsupp *micsupp;
0314
0315 micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
0316 if (!micsupp)
0317 return -ENOMEM;
0318
0319 micsupp->regmap = arizona->regmap;
0320 micsupp->dapm = &arizona->dapm;
0321 micsupp->dev = arizona->dev;
0322
0323
0324
0325
0326
0327
0328 switch (arizona->type) {
0329 case WM5110:
0330 case WM8280:
0331 desc = &arizona_micsupp_ext;
0332 micsupp->init_data = arizona_micsupp_ext_default;
0333 break;
0334 default:
0335 desc = &arizona_micsupp;
0336 micsupp->init_data = arizona_micsupp_default;
0337 break;
0338 }
0339
0340 return arizona_micsupp_common_init(pdev, micsupp, desc,
0341 &arizona->pdata.micvdd);
0342 }
0343
0344 static int madera_micsupp_probe(struct platform_device *pdev)
0345 {
0346 struct madera *madera = dev_get_drvdata(pdev->dev.parent);
0347 struct arizona_micsupp *micsupp;
0348
0349 micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
0350 if (!micsupp)
0351 return -ENOMEM;
0352
0353 micsupp->regmap = madera->regmap;
0354 micsupp->dapm = &madera->dapm;
0355 micsupp->dev = madera->dev;
0356 micsupp->init_data = arizona_micsupp_ext_default;
0357
0358 return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp,
0359 &madera->pdata.micvdd);
0360 }
0361
0362 static struct platform_driver arizona_micsupp_driver = {
0363 .probe = arizona_micsupp_probe,
0364 .driver = {
0365 .name = "arizona-micsupp",
0366 },
0367 };
0368
0369 static struct platform_driver madera_micsupp_driver = {
0370 .probe = madera_micsupp_probe,
0371 .driver = {
0372 .name = "madera-micsupp",
0373 },
0374 };
0375
0376 static struct platform_driver * const arizona_micsupp_drivers[] = {
0377 &arizona_micsupp_driver,
0378 &madera_micsupp_driver,
0379 };
0380
0381 static int __init arizona_micsupp_init(void)
0382 {
0383 return platform_register_drivers(arizona_micsupp_drivers,
0384 ARRAY_SIZE(arizona_micsupp_drivers));
0385 }
0386 module_init(arizona_micsupp_init);
0387
0388 static void __exit arizona_micsupp_exit(void)
0389 {
0390 platform_unregister_drivers(arizona_micsupp_drivers,
0391 ARRAY_SIZE(arizona_micsupp_drivers));
0392 }
0393 module_exit(arizona_micsupp_exit);
0394
0395
0396 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0397 MODULE_DESCRIPTION("Arizona microphone supply driver");
0398 MODULE_LICENSE("GPL");
0399 MODULE_ALIAS("platform:arizona-micsupp");
0400 MODULE_ALIAS("platform:madera-micsupp");