1dfc0c82bSAxel Lin // SPDX-License-Identifier: GPL-2.0+
2dfc0c82bSAxel Lin //
3dfc0c82bSAxel Lin // arizona-micsupp.c  --  Microphone supply for Arizona devices
4dfc0c82bSAxel Lin //
5dfc0c82bSAxel Lin // Copyright 2012 Wolfson Microelectronics PLC.
6dfc0c82bSAxel Lin //
7dfc0c82bSAxel Lin // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8b667a45dSMark Brown 
9b667a45dSMark Brown #include <linux/module.h>
10b667a45dSMark Brown #include <linux/moduleparam.h>
11b667a45dSMark Brown #include <linux/init.h>
12b667a45dSMark Brown #include <linux/bitops.h>
13b667a45dSMark Brown #include <linux/err.h>
146f1c9c57SCharles Keepax #include <linux/of.h>
15b667a45dSMark Brown #include <linux/platform_device.h>
16b667a45dSMark Brown #include <linux/regulator/driver.h>
17b667a45dSMark Brown #include <linux/regulator/machine.h>
1836bcdf1bSCharles Keepax #include <linux/regulator/of_regulator.h>
19b667a45dSMark Brown #include <linux/slab.h>
20e6ed9058SMark Brown #include <linux/workqueue.h>
21e6ed9058SMark Brown #include <sound/soc.h>
22b667a45dSMark Brown 
23b667a45dSMark Brown #include <linux/mfd/arizona/core.h>
24b667a45dSMark Brown #include <linux/mfd/arizona/pdata.h>
25b667a45dSMark Brown #include <linux/mfd/arizona/registers.h>
26b667a45dSMark Brown 
277bd7916dSRichard Fitzgerald #include <linux/mfd/madera/core.h>
287bd7916dSRichard Fitzgerald #include <linux/mfd/madera/pdata.h>
297bd7916dSRichard Fitzgerald #include <linux/mfd/madera/registers.h>
307bd7916dSRichard Fitzgerald 
3122161f3eSRichard Fitzgerald #include <linux/regulator/arizona-micsupp.h>
3222161f3eSRichard Fitzgerald 
33b667a45dSMark Brown struct arizona_micsupp {
34b667a45dSMark Brown 	struct regulator_dev *regulator;
35e165983eSRichard Fitzgerald 	struct regmap *regmap;
36e165983eSRichard Fitzgerald 	struct snd_soc_dapm_context **dapm;
372da34b23SRichard Fitzgerald 	const struct regulator_desc *desc;
38e165983eSRichard Fitzgerald 	struct device *dev;
39b667a45dSMark Brown 
40b667a45dSMark Brown 	struct regulator_consumer_supply supply;
41b667a45dSMark Brown 	struct regulator_init_data init_data;
42e6ed9058SMark Brown 
43e6ed9058SMark Brown 	struct work_struct check_cp_work;
44b667a45dSMark Brown };
45b667a45dSMark Brown 
arizona_micsupp_check_cp(struct work_struct * work)46e6ed9058SMark Brown static void arizona_micsupp_check_cp(struct work_struct *work)
47e6ed9058SMark Brown {
48e6ed9058SMark Brown 	struct arizona_micsupp *micsupp =
49e6ed9058SMark Brown 		container_of(work, struct arizona_micsupp, check_cp_work);
50e165983eSRichard Fitzgerald 	struct snd_soc_dapm_context *dapm = *micsupp->dapm;
51e165983eSRichard Fitzgerald 	struct snd_soc_component *component;
522da34b23SRichard Fitzgerald 	const struct regulator_desc *desc = micsupp->desc;
53e165983eSRichard Fitzgerald 	unsigned int val;
54e6ed9058SMark Brown 	int ret;
55e6ed9058SMark Brown 
562da34b23SRichard Fitzgerald 	ret = regmap_read(micsupp->regmap, desc->enable_reg, &val);
57e6ed9058SMark Brown 	if (ret != 0) {
58e165983eSRichard Fitzgerald 		dev_err(micsupp->dev,
59e165983eSRichard Fitzgerald 			"Failed to read CP state: %d\n", ret);
60e6ed9058SMark Brown 		return;
61e6ed9058SMark Brown 	}
62e6ed9058SMark Brown 
63e6ed9058SMark Brown 	if (dapm) {
64e165983eSRichard Fitzgerald 		component = snd_soc_dapm_to_component(dapm);
65e165983eSRichard Fitzgerald 
662da34b23SRichard Fitzgerald 		if ((val & (desc->enable_mask | desc->bypass_mask)) ==
672da34b23SRichard Fitzgerald 		    desc->enable_mask)
6898cf9965SRichard Fitzgerald 			snd_soc_component_force_enable_pin(component,
6998cf9965SRichard Fitzgerald 							   "MICSUPP");
70e6ed9058SMark Brown 		else
7198cf9965SRichard Fitzgerald 			snd_soc_component_disable_pin(component, "MICSUPP");
72e6ed9058SMark Brown 
73e6ed9058SMark Brown 		snd_soc_dapm_sync(dapm);
74e6ed9058SMark Brown 	}
75e6ed9058SMark Brown }
76e6ed9058SMark Brown 
arizona_micsupp_enable(struct regulator_dev * rdev)77e6ed9058SMark Brown static int arizona_micsupp_enable(struct regulator_dev *rdev)
78e6ed9058SMark Brown {
79e6ed9058SMark Brown 	struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
80e6ed9058SMark Brown 	int ret;
81e6ed9058SMark Brown 
82e6ed9058SMark Brown 	ret = regulator_enable_regmap(rdev);
83e6ed9058SMark Brown 
84e6ed9058SMark Brown 	if (ret == 0)
85e6ed9058SMark Brown 		schedule_work(&micsupp->check_cp_work);
86e6ed9058SMark Brown 
87e6ed9058SMark Brown 	return ret;
88e6ed9058SMark Brown }
89e6ed9058SMark Brown 
arizona_micsupp_disable(struct regulator_dev * rdev)90e6ed9058SMark Brown static int arizona_micsupp_disable(struct regulator_dev *rdev)
91e6ed9058SMark Brown {
92e6ed9058SMark Brown 	struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
93e6ed9058SMark Brown 	int ret;
94e6ed9058SMark Brown 
95e6ed9058SMark Brown 	ret = regulator_disable_regmap(rdev);
96e6ed9058SMark Brown 	if (ret == 0)
97e6ed9058SMark Brown 		schedule_work(&micsupp->check_cp_work);
98e6ed9058SMark Brown 
99e6ed9058SMark Brown 	return ret;
100e6ed9058SMark Brown }
101e6ed9058SMark Brown 
arizona_micsupp_set_bypass(struct regulator_dev * rdev,bool ena)102e6ed9058SMark Brown static int arizona_micsupp_set_bypass(struct regulator_dev *rdev, bool ena)
103e6ed9058SMark Brown {
104e6ed9058SMark Brown 	struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev);
105e6ed9058SMark Brown 	int ret;
106e6ed9058SMark Brown 
107e6ed9058SMark Brown 	ret = regulator_set_bypass_regmap(rdev, ena);
108e6ed9058SMark Brown 	if (ret == 0)
109e6ed9058SMark Brown 		schedule_work(&micsupp->check_cp_work);
110e6ed9058SMark Brown 
111e6ed9058SMark Brown 	return ret;
112e6ed9058SMark Brown }
113e6ed9058SMark Brown 
1142773ead1SBhumika Goyal static const struct regulator_ops arizona_micsupp_ops = {
115e6ed9058SMark Brown 	.enable = arizona_micsupp_enable,
116e6ed9058SMark Brown 	.disable = arizona_micsupp_disable,
117b667a45dSMark Brown 	.is_enabled = regulator_is_enabled_regmap,
118b667a45dSMark Brown 
11971979aa3SCharles Keepax 	.list_voltage = regulator_list_voltage_linear_range,
12071979aa3SCharles Keepax 	.map_voltage = regulator_map_voltage_linear_range,
121b667a45dSMark Brown 
122b667a45dSMark Brown 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
123b667a45dSMark Brown 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
124e477ce07SMark Brown 
125e477ce07SMark Brown 	.get_bypass = regulator_get_bypass_regmap,
126e6ed9058SMark Brown 	.set_bypass = arizona_micsupp_set_bypass,
127b667a45dSMark Brown };
128b667a45dSMark Brown 
12960ab7f41SMatti Vaittinen static const struct linear_range arizona_micsupp_ranges[] = {
13071979aa3SCharles Keepax 	REGULATOR_LINEAR_RANGE(1700000, 0,    0x1e, 50000),
13171979aa3SCharles Keepax 	REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0),
13271979aa3SCharles Keepax };
13371979aa3SCharles Keepax 
134b667a45dSMark Brown static const struct regulator_desc arizona_micsupp = {
135b667a45dSMark Brown 	.name = "MICVDD",
136b667a45dSMark Brown 	.supply_name = "CPVDD",
137b667a45dSMark Brown 	.type = REGULATOR_VOLTAGE,
13871979aa3SCharles Keepax 	.n_voltages = 32,
139b667a45dSMark Brown 	.ops = &arizona_micsupp_ops,
140b667a45dSMark Brown 
141b667a45dSMark Brown 	.vsel_reg = ARIZONA_LDO2_CONTROL_1,
142b667a45dSMark Brown 	.vsel_mask = ARIZONA_LDO2_VSEL_MASK,
143b667a45dSMark Brown 	.enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
144b667a45dSMark Brown 	.enable_mask = ARIZONA_CPMIC_ENA,
145e477ce07SMark Brown 	.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
146e477ce07SMark Brown 	.bypass_mask = ARIZONA_CPMIC_BYPASS,
147b667a45dSMark Brown 
14871979aa3SCharles Keepax 	.linear_ranges = arizona_micsupp_ranges,
14971979aa3SCharles Keepax 	.n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ranges),
15071979aa3SCharles Keepax 
15195072818SMark Brown 	.enable_time = 3000,
15295072818SMark Brown 
153b667a45dSMark Brown 	.owner = THIS_MODULE,
154b667a45dSMark Brown };
155b667a45dSMark Brown 
15660ab7f41SMatti Vaittinen static const struct linear_range arizona_micsupp_ext_ranges[] = {
157d2e7491eSCharles Keepax 	REGULATOR_LINEAR_RANGE(900000,  0,    0x14, 25000),
158d2e7491eSCharles Keepax 	REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000),
159d2e7491eSCharles Keepax };
160d2e7491eSCharles Keepax 
161d2e7491eSCharles Keepax static const struct regulator_desc arizona_micsupp_ext = {
162d2e7491eSCharles Keepax 	.name = "MICVDD",
163d2e7491eSCharles Keepax 	.supply_name = "CPVDD",
164d2e7491eSCharles Keepax 	.type = REGULATOR_VOLTAGE,
165d2e7491eSCharles Keepax 	.n_voltages = 40,
166d2e7491eSCharles Keepax 	.ops = &arizona_micsupp_ops,
167d2e7491eSCharles Keepax 
168d2e7491eSCharles Keepax 	.vsel_reg = ARIZONA_LDO2_CONTROL_1,
169d2e7491eSCharles Keepax 	.vsel_mask = ARIZONA_LDO2_VSEL_MASK,
170d2e7491eSCharles Keepax 	.enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
171d2e7491eSCharles Keepax 	.enable_mask = ARIZONA_CPMIC_ENA,
172d2e7491eSCharles Keepax 	.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
173d2e7491eSCharles Keepax 	.bypass_mask = ARIZONA_CPMIC_BYPASS,
174d2e7491eSCharles Keepax 
175d2e7491eSCharles Keepax 	.linear_ranges = arizona_micsupp_ext_ranges,
176d2e7491eSCharles Keepax 	.n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges),
177d2e7491eSCharles Keepax 
178d2e7491eSCharles Keepax 	.enable_time = 3000,
179d2e7491eSCharles Keepax 
180d2e7491eSCharles Keepax 	.owner = THIS_MODULE,
181d2e7491eSCharles Keepax };
182d2e7491eSCharles Keepax 
183b667a45dSMark Brown static const struct regulator_init_data arizona_micsupp_default = {
184b667a45dSMark Brown 	.constraints = {
185b667a45dSMark Brown 		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
1869fc50a2eSMark Brown 				REGULATOR_CHANGE_VOLTAGE |
1879fc50a2eSMark Brown 				REGULATOR_CHANGE_BYPASS,
188b667a45dSMark Brown 		.min_uV = 1700000,
189b667a45dSMark Brown 		.max_uV = 3300000,
190b667a45dSMark Brown 	},
191b667a45dSMark Brown 
192b667a45dSMark Brown 	.num_consumer_supplies = 1,
193b667a45dSMark Brown };
194b667a45dSMark Brown 
195d2e7491eSCharles Keepax static const struct regulator_init_data arizona_micsupp_ext_default = {
196d2e7491eSCharles Keepax 	.constraints = {
197d2e7491eSCharles Keepax 		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
198d2e7491eSCharles Keepax 				REGULATOR_CHANGE_VOLTAGE |
199d2e7491eSCharles Keepax 				REGULATOR_CHANGE_BYPASS,
200d2e7491eSCharles Keepax 		.min_uV = 900000,
201d2e7491eSCharles Keepax 		.max_uV = 3300000,
202d2e7491eSCharles Keepax 	},
203d2e7491eSCharles Keepax 
204d2e7491eSCharles Keepax 	.num_consumer_supplies = 1,
205d2e7491eSCharles Keepax };
206d2e7491eSCharles Keepax 
2077bd7916dSRichard Fitzgerald static const struct regulator_desc madera_micsupp = {
2087bd7916dSRichard Fitzgerald 	.name = "MICVDD",
2097bd7916dSRichard Fitzgerald 	.supply_name = "CPVDD1",
2107bd7916dSRichard Fitzgerald 	.type = REGULATOR_VOLTAGE,
2117bd7916dSRichard Fitzgerald 	.n_voltages = 40,
2127bd7916dSRichard Fitzgerald 	.ops = &arizona_micsupp_ops,
2137bd7916dSRichard Fitzgerald 	.vsel_reg = MADERA_LDO2_CONTROL_1,
2147bd7916dSRichard Fitzgerald 	.vsel_mask = MADERA_LDO2_VSEL_MASK,
2157bd7916dSRichard Fitzgerald 	.enable_reg = MADERA_MIC_CHARGE_PUMP_1,
2167bd7916dSRichard Fitzgerald 	.enable_mask = MADERA_CPMIC_ENA,
2177bd7916dSRichard Fitzgerald 	.bypass_reg = MADERA_MIC_CHARGE_PUMP_1,
2187bd7916dSRichard Fitzgerald 	.bypass_mask = MADERA_CPMIC_BYPASS,
2197bd7916dSRichard Fitzgerald 
2207bd7916dSRichard Fitzgerald 	.linear_ranges = arizona_micsupp_ext_ranges,
2217bd7916dSRichard Fitzgerald 	.n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges),
2227bd7916dSRichard Fitzgerald 
2237bd7916dSRichard Fitzgerald 	.enable_time = 3000,
2247bd7916dSRichard Fitzgerald 
2257bd7916dSRichard Fitzgerald 	.owner = THIS_MODULE,
2267bd7916dSRichard Fitzgerald };
2277bd7916dSRichard Fitzgerald 
arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata * pdata,struct regulator_config * config,const struct regulator_desc * desc)22822161f3eSRichard Fitzgerald static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata,
229072e78b1SJavier Martinez Canillas 					struct regulator_config *config,
230072e78b1SJavier Martinez Canillas 					const struct regulator_desc *desc)
23136bcdf1bSCharles Keepax {
23236bcdf1bSCharles Keepax 	struct arizona_micsupp *micsupp = config->driver_data;
23336bcdf1bSCharles Keepax 	struct device_node *np;
23436bcdf1bSCharles Keepax 	struct regulator_init_data *init_data;
23536bcdf1bSCharles Keepax 
23622161f3eSRichard Fitzgerald 	np = of_get_child_by_name(config->dev->of_node, "micvdd");
23736bcdf1bSCharles Keepax 
23836bcdf1bSCharles Keepax 	if (np) {
23936bcdf1bSCharles Keepax 		config->of_node = np;
24036bcdf1bSCharles Keepax 
24122161f3eSRichard Fitzgerald 		init_data = of_get_regulator_init_data(config->dev, np, desc);
24236bcdf1bSCharles Keepax 
24336bcdf1bSCharles Keepax 		if (init_data) {
24436bcdf1bSCharles Keepax 			init_data->consumer_supplies = &micsupp->supply;
24536bcdf1bSCharles Keepax 			init_data->num_consumer_supplies = 1;
24636bcdf1bSCharles Keepax 
24722161f3eSRichard Fitzgerald 			pdata->init_data = init_data;
24836bcdf1bSCharles Keepax 		}
24936bcdf1bSCharles Keepax 	}
25036bcdf1bSCharles Keepax 
25136bcdf1bSCharles Keepax 	return 0;
25236bcdf1bSCharles Keepax }
25336bcdf1bSCharles Keepax 
arizona_micsupp_common_init(struct platform_device * pdev,struct arizona_micsupp * micsupp,const struct regulator_desc * desc,struct arizona_micsupp_pdata * pdata)2547d8d14b5SRichard Fitzgerald static int arizona_micsupp_common_init(struct platform_device *pdev,
2557d8d14b5SRichard Fitzgerald 				       struct arizona_micsupp *micsupp,
2567d8d14b5SRichard Fitzgerald 				       const struct regulator_desc *desc,
2577d8d14b5SRichard Fitzgerald 				       struct arizona_micsupp_pdata *pdata)
2587d8d14b5SRichard Fitzgerald {
2597d8d14b5SRichard Fitzgerald 	struct regulator_config config = { };
2607d8d14b5SRichard Fitzgerald 	int ret;
2617d8d14b5SRichard Fitzgerald 
2627d8d14b5SRichard Fitzgerald 	INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);
2637d8d14b5SRichard Fitzgerald 
2647d8d14b5SRichard Fitzgerald 	micsupp->init_data.consumer_supplies = &micsupp->supply;
2657d8d14b5SRichard Fitzgerald 	micsupp->supply.dev_name = dev_name(micsupp->dev);
2662da34b23SRichard Fitzgerald 	micsupp->desc = desc;
2677d8d14b5SRichard Fitzgerald 
2687d8d14b5SRichard Fitzgerald 	config.dev = micsupp->dev;
2697d8d14b5SRichard Fitzgerald 	config.driver_data = micsupp;
2707d8d14b5SRichard Fitzgerald 	config.regmap = micsupp->regmap;
2717d8d14b5SRichard Fitzgerald 
2727d8d14b5SRichard Fitzgerald 	if (IS_ENABLED(CONFIG_OF)) {
2737d8d14b5SRichard Fitzgerald 		if (!dev_get_platdata(micsupp->dev)) {
2747d8d14b5SRichard Fitzgerald 			ret = arizona_micsupp_of_get_pdata(pdata, &config,
2757d8d14b5SRichard Fitzgerald 							   desc);
2767d8d14b5SRichard Fitzgerald 			if (ret < 0)
2777d8d14b5SRichard Fitzgerald 				return ret;
2787d8d14b5SRichard Fitzgerald 		}
2797d8d14b5SRichard Fitzgerald 	}
2807d8d14b5SRichard Fitzgerald 
2817d8d14b5SRichard Fitzgerald 	if (pdata->init_data)
2827d8d14b5SRichard Fitzgerald 		config.init_data = pdata->init_data;
2837d8d14b5SRichard Fitzgerald 	else
2847d8d14b5SRichard Fitzgerald 		config.init_data = &micsupp->init_data;
2857d8d14b5SRichard Fitzgerald 
2867d8d14b5SRichard Fitzgerald 	/* Default to regulated mode */
2872da34b23SRichard Fitzgerald 	regmap_update_bits(micsupp->regmap, desc->enable_reg, desc->bypass_mask, 0);
2887d8d14b5SRichard Fitzgerald 
2897d8d14b5SRichard Fitzgerald 	micsupp->regulator = devm_regulator_register(&pdev->dev,
2907d8d14b5SRichard Fitzgerald 						     desc,
2917d8d14b5SRichard Fitzgerald 						     &config);
2927d8d14b5SRichard Fitzgerald 
2937d8d14b5SRichard Fitzgerald 	of_node_put(config.of_node);
2947d8d14b5SRichard Fitzgerald 
2957d8d14b5SRichard Fitzgerald 	if (IS_ERR(micsupp->regulator)) {
2967d8d14b5SRichard Fitzgerald 		ret = PTR_ERR(micsupp->regulator);
2977d8d14b5SRichard Fitzgerald 		dev_err(micsupp->dev, "Failed to register mic supply: %d\n",
2987d8d14b5SRichard Fitzgerald 			ret);
2997d8d14b5SRichard Fitzgerald 		return ret;
3007d8d14b5SRichard Fitzgerald 	}
3017d8d14b5SRichard Fitzgerald 
3027d8d14b5SRichard Fitzgerald 	platform_set_drvdata(pdev, micsupp);
3037d8d14b5SRichard Fitzgerald 
3047d8d14b5SRichard Fitzgerald 	return 0;
3057d8d14b5SRichard Fitzgerald }
3067d8d14b5SRichard Fitzgerald 
arizona_micsupp_probe(struct platform_device * pdev)307a5023574SBill Pemberton static int arizona_micsupp_probe(struct platform_device *pdev)
308b667a45dSMark Brown {
309b667a45dSMark Brown 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
310d2e7491eSCharles Keepax 	const struct regulator_desc *desc;
311b667a45dSMark Brown 	struct arizona_micsupp *micsupp;
312b667a45dSMark Brown 
313b667a45dSMark Brown 	micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
314820cd31eSSachin Kamat 	if (!micsupp)
315b667a45dSMark Brown 		return -ENOMEM;
316b667a45dSMark Brown 
317e165983eSRichard Fitzgerald 	micsupp->regmap = arizona->regmap;
318e165983eSRichard Fitzgerald 	micsupp->dapm = &arizona->dapm;
319e165983eSRichard Fitzgerald 	micsupp->dev = arizona->dev;
320b667a45dSMark Brown 
3219211402fSRichard Fitzgerald 	micsupp->supply.supply = "MICVDD";
3229211402fSRichard Fitzgerald 
323b667a45dSMark Brown 	/*
324b667a45dSMark Brown 	 * Since the chip usually supplies itself we provide some
325b667a45dSMark Brown 	 * default init_data for it.  This will be overridden with
326b667a45dSMark Brown 	 * platform data if provided.
327b667a45dSMark Brown 	 */
328d2e7491eSCharles Keepax 	switch (arizona->type) {
329d2e7491eSCharles Keepax 	case WM5110:
330f7293114SRichard Fitzgerald 	case WM8280:
331d2e7491eSCharles Keepax 		desc = &arizona_micsupp_ext;
332d2e7491eSCharles Keepax 		micsupp->init_data = arizona_micsupp_ext_default;
333d2e7491eSCharles Keepax 		break;
334d2e7491eSCharles Keepax 	default:
335d2e7491eSCharles Keepax 		desc = &arizona_micsupp;
336b667a45dSMark Brown 		micsupp->init_data = arizona_micsupp_default;
337d2e7491eSCharles Keepax 		break;
338d2e7491eSCharles Keepax 	}
339d2e7491eSCharles Keepax 
3407d8d14b5SRichard Fitzgerald 	return arizona_micsupp_common_init(pdev, micsupp, desc,
3417d8d14b5SRichard Fitzgerald 					   &arizona->pdata.micvdd);
342b667a45dSMark Brown }
343b667a45dSMark Brown 
madera_micsupp_probe(struct platform_device * pdev)3447bd7916dSRichard Fitzgerald static int madera_micsupp_probe(struct platform_device *pdev)
3457bd7916dSRichard Fitzgerald {
3467bd7916dSRichard Fitzgerald 	struct madera *madera = dev_get_drvdata(pdev->dev.parent);
3477bd7916dSRichard Fitzgerald 	struct arizona_micsupp *micsupp;
3487bd7916dSRichard Fitzgerald 
3497bd7916dSRichard Fitzgerald 	micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
3507bd7916dSRichard Fitzgerald 	if (!micsupp)
3517bd7916dSRichard Fitzgerald 		return -ENOMEM;
3527bd7916dSRichard Fitzgerald 
3537bd7916dSRichard Fitzgerald 	micsupp->regmap = madera->regmap;
3547bd7916dSRichard Fitzgerald 	micsupp->dapm = &madera->dapm;
3557bd7916dSRichard Fitzgerald 	micsupp->dev = madera->dev;
3567bd7916dSRichard Fitzgerald 	micsupp->init_data = arizona_micsupp_ext_default;
3577bd7916dSRichard Fitzgerald 
3589211402fSRichard Fitzgerald 	micsupp->supply.supply = "MICVDD";
3599211402fSRichard Fitzgerald 
3607bd7916dSRichard Fitzgerald 	return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp,
3617bd7916dSRichard Fitzgerald 					   &madera->pdata.micvdd);
3627bd7916dSRichard Fitzgerald }
3637bd7916dSRichard Fitzgerald 
364b667a45dSMark Brown static struct platform_driver arizona_micsupp_driver = {
365b667a45dSMark Brown 	.probe = arizona_micsupp_probe,
366b667a45dSMark Brown 	.driver		= {
367b667a45dSMark Brown 		.name	= "arizona-micsupp",
368*b65a0a8eSCharles Keepax 		.probe_type = PROBE_FORCE_SYNCHRONOUS,
369b667a45dSMark Brown 	},
370b667a45dSMark Brown };
371b667a45dSMark Brown 
3727bd7916dSRichard Fitzgerald static struct platform_driver madera_micsupp_driver = {
3737bd7916dSRichard Fitzgerald 	.probe = madera_micsupp_probe,
3747bd7916dSRichard Fitzgerald 	.driver		= {
3757bd7916dSRichard Fitzgerald 		.name	= "madera-micsupp",
376*b65a0a8eSCharles Keepax 		.probe_type = PROBE_FORCE_SYNCHRONOUS,
3777bd7916dSRichard Fitzgerald 	},
3787bd7916dSRichard Fitzgerald };
3797bd7916dSRichard Fitzgerald 
3807bd7916dSRichard Fitzgerald static struct platform_driver * const arizona_micsupp_drivers[] = {
3817bd7916dSRichard Fitzgerald 	&arizona_micsupp_driver,
3827bd7916dSRichard Fitzgerald 	&madera_micsupp_driver,
3837bd7916dSRichard Fitzgerald };
3847bd7916dSRichard Fitzgerald 
arizona_micsupp_init(void)3857bd7916dSRichard Fitzgerald static int __init arizona_micsupp_init(void)
3867bd7916dSRichard Fitzgerald {
3877bd7916dSRichard Fitzgerald 	return platform_register_drivers(arizona_micsupp_drivers,
3887bd7916dSRichard Fitzgerald 					 ARRAY_SIZE(arizona_micsupp_drivers));
3897bd7916dSRichard Fitzgerald }
3907bd7916dSRichard Fitzgerald module_init(arizona_micsupp_init);
3917bd7916dSRichard Fitzgerald 
arizona_micsupp_exit(void)3927bd7916dSRichard Fitzgerald static void __exit arizona_micsupp_exit(void)
3937bd7916dSRichard Fitzgerald {
3947bd7916dSRichard Fitzgerald 	platform_unregister_drivers(arizona_micsupp_drivers,
3957bd7916dSRichard Fitzgerald 				    ARRAY_SIZE(arizona_micsupp_drivers));
3967bd7916dSRichard Fitzgerald }
3977bd7916dSRichard Fitzgerald module_exit(arizona_micsupp_exit);
398b667a45dSMark Brown 
399b667a45dSMark Brown /* Module information */
400b667a45dSMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
401b667a45dSMark Brown MODULE_DESCRIPTION("Arizona microphone supply driver");
402b667a45dSMark Brown MODULE_LICENSE("GPL");
403b667a45dSMark Brown MODULE_ALIAS("platform:arizona-micsupp");
4047bd7916dSRichard Fitzgerald MODULE_ALIAS("platform:madera-micsupp");
405