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