Blame view

drivers/mfd/wm8994-core.c 17.6 KB
9e5010866   Mark Brown   mfd: Add initial ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /*
   * wm8994-core.c  --  Device access for Wolfson WM8994
   *
   * Copyright 2009 Wolfson Microelectronics PLC.
   *
   * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   *
   *  This program is free software; you can redistribute  it and/or modify it
   *  under  the terms of  the GNU General  Public License as published by the
   *  Free Software Foundation;  either version 2 of the  License, or (at your
   *  option) any later version.
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
9e5010866   Mark Brown   mfd: Add initial ...
18
  #include <linux/i2c.h>
d6c645fc0   Mark Brown   mfd: Convert WM89...
19
  #include <linux/err.h>
9e5010866   Mark Brown   mfd: Add initial ...
20
21
  #include <linux/delay.h>
  #include <linux/mfd/core.h>
d450f19ee   Mark Brown   mfd: Implement ru...
22
  #include <linux/pm_runtime.h>
d6c645fc0   Mark Brown   mfd: Convert WM89...
23
  #include <linux/regmap.h>
9e5010866   Mark Brown   mfd: Add initial ...
24
25
26
27
28
29
  #include <linux/regulator/consumer.h>
  #include <linux/regulator/machine.h>
  
  #include <linux/mfd/wm8994/core.h>
  #include <linux/mfd/wm8994/pdata.h>
  #include <linux/mfd/wm8994/registers.h>
c3f138617   Mark Brown   mfd: Enable regis...
30
  #include "wm8994.h"
9e5010866   Mark Brown   mfd: Add initial ...
31
32
33
34
35
36
37
38
39
  
  /**
   * wm8994_reg_read: Read a single WM8994 register.
   *
   * @wm8994: Device to read from.
   * @reg: Register to read.
   */
  int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
  {
d6c645fc0   Mark Brown   mfd: Convert WM89...
40
  	unsigned int val;
9e5010866   Mark Brown   mfd: Add initial ...
41
  	int ret;
d6c645fc0   Mark Brown   mfd: Convert WM89...
42
  	ret = regmap_read(wm8994->regmap, reg, &val);
9e5010866   Mark Brown   mfd: Add initial ...
43
44
45
46
  
  	if (ret < 0)
  		return ret;
  	else
d6c645fc0   Mark Brown   mfd: Convert WM89...
47
  		return val;
9e5010866   Mark Brown   mfd: Add initial ...
48
49
50
51
52
53
54
55
56
  }
  EXPORT_SYMBOL_GPL(wm8994_reg_read);
  
  /**
   * wm8994_bulk_read: Read multiple WM8994 registers
   *
   * @wm8994: Device to read from
   * @reg: First register
   * @count: Number of registers
316b6cc08   Mark Brown   mfd: Push byte sw...
57
   * @buf: Buffer to fill.  The data will be returned big endian.
9e5010866   Mark Brown   mfd: Add initial ...
58
59
60
61
   */
  int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
  		     int count, u16 *buf)
  {
d6c645fc0   Mark Brown   mfd: Convert WM89...
62
  	return regmap_bulk_read(wm8994->regmap, reg, buf, count);
9e5010866   Mark Brown   mfd: Add initial ...
63
  }
9e5010866   Mark Brown   mfd: Add initial ...
64

9e5010866   Mark Brown   mfd: Add initial ...
65
66
67
68
69
70
71
72
73
74
  /**
   * wm8994_reg_write: Write a single WM8994 register.
   *
   * @wm8994: Device to write to.
   * @reg: Register to write to.
   * @val: Value to write.
   */
  int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
  		     unsigned short val)
  {
d6c645fc0   Mark Brown   mfd: Convert WM89...
75
  	return regmap_write(wm8994->regmap, reg, val);
9e5010866   Mark Brown   mfd: Add initial ...
76
77
78
79
  }
  EXPORT_SYMBOL_GPL(wm8994_reg_write);
  
  /**
e93c53870   Mark Brown   mfd: Add WM8994 b...
80
81
82
83
84
   * wm8994_bulk_write: Write multiple WM8994 registers
   *
   * @wm8994: Device to write to
   * @reg: First register
   * @count: Number of registers
4277163c2   Mark Brown   mfd: Push byte sw...
85
   * @buf: Buffer to write from.  Data must be big-endian formatted.
e93c53870   Mark Brown   mfd: Add WM8994 b...
86
87
   */
  int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
07e73fbb2   Mark Brown   mfd: Constify WM8...
88
  		      int count, const u16 *buf)
e93c53870   Mark Brown   mfd: Add WM8994 b...
89
  {
d6c645fc0   Mark Brown   mfd: Convert WM89...
90
  	return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
e93c53870   Mark Brown   mfd: Add WM8994 b...
91
92
93
94
  }
  EXPORT_SYMBOL_GPL(wm8994_bulk_write);
  
  /**
9e5010866   Mark Brown   mfd: Add initial ...
95
96
97
98
99
100
101
102
103
104
   * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
   *
   * @wm8994: Device to write to.
   * @reg: Register to write to.
   * @mask: Mask of bits to set.
   * @val: Value to set (unshifted)
   */
  int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
  		    unsigned short mask, unsigned short val)
  {
d6c645fc0   Mark Brown   mfd: Convert WM89...
105
  	return regmap_update_bits(wm8994->regmap, reg, mask, val);
9e5010866   Mark Brown   mfd: Add initial ...
106
107
108
109
  }
  EXPORT_SYMBOL_GPL(wm8994_set_bits);
  
  static struct mfd_cell wm8994_regulator_devs[] = {
d450f19ee   Mark Brown   mfd: Implement ru...
110
111
112
113
114
115
116
117
118
119
  	{
  		.name = "wm8994-ldo",
  		.id = 1,
  		.pm_runtime_no_callbacks = true,
  	},
  	{
  		.name = "wm8994-ldo",
  		.id = 2,
  		.pm_runtime_no_callbacks = true,
  	},
9e5010866   Mark Brown   mfd: Add initial ...
120
  };
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  static struct resource wm8994_codec_resources[] = {
  	{
  		.start = WM8994_IRQ_TEMP_SHUT,
  		.end   = WM8994_IRQ_TEMP_WARN,
  		.flags = IORESOURCE_IRQ,
  	},
  };
  
  static struct resource wm8994_gpio_resources[] = {
  	{
  		.start = WM8994_IRQ_GPIO(1),
  		.end   = WM8994_IRQ_GPIO(11),
  		.flags = IORESOURCE_IRQ,
  	},
  };
9e5010866   Mark Brown   mfd: Add initial ...
136
  static struct mfd_cell wm8994_devs[] = {
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
137
138
139
140
141
142
143
144
145
146
  	{
  		.name = "wm8994-codec",
  		.num_resources = ARRAY_SIZE(wm8994_codec_resources),
  		.resources = wm8994_codec_resources,
  	},
  
  	{
  		.name = "wm8994-gpio",
  		.num_resources = ARRAY_SIZE(wm8994_gpio_resources),
  		.resources = wm8994_gpio_resources,
d450f19ee   Mark Brown   mfd: Implement ru...
147
  		.pm_runtime_no_callbacks = true,
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
148
  	},
9e5010866   Mark Brown   mfd: Add initial ...
149
150
151
152
153
154
155
  };
  
  /*
   * Supplies for the main bulk of CODEC; the LDO supplies are ignored
   * and should be handled via the standard regulator API supply
   * management.
   */
b1f43bf3a   Mark Brown   mfd: Add WM1811 s...
156
157
158
159
160
161
162
163
164
165
166
  static const char *wm1811_main_supplies[] = {
  	"DBVDD1",
  	"DBVDD2",
  	"DBVDD3",
  	"DCVDD",
  	"AVDD1",
  	"AVDD2",
  	"CPVDD",
  	"SPKVDD1",
  	"SPKVDD2",
  };
9e5010866   Mark Brown   mfd: Add initial ...
167
168
169
170
171
172
173
174
175
  static const char *wm8994_main_supplies[] = {
  	"DBVDD",
  	"DCVDD",
  	"AVDD1",
  	"AVDD2",
  	"CPVDD",
  	"SPKVDD1",
  	"SPKVDD2",
  };
559e0df6b   Mark Brown   mfd: Add initial ...
176
177
178
179
180
181
182
183
184
185
186
  static const char *wm8958_main_supplies[] = {
  	"DBVDD1",
  	"DBVDD2",
  	"DBVDD3",
  	"DCVDD",
  	"AVDD1",
  	"AVDD2",
  	"CPVDD",
  	"SPKVDD1",
  	"SPKVDD2",
  };
9e5010866   Mark Brown   mfd: Add initial ...
187
  #ifdef CONFIG_PM
d450f19ee   Mark Brown   mfd: Implement ru...
188
  static int wm8994_suspend(struct device *dev)
9e5010866   Mark Brown   mfd: Add initial ...
189
190
191
  {
  	struct wm8994 *wm8994 = dev_get_drvdata(dev);
  	int ret;
77bd70e90   Mark Brown   mfd: Don't suspen...
192
193
194
195
196
197
198
199
200
201
202
  	/* Don't actually go through with the suspend if the CODEC is
  	 * still active (eg, for audio passthrough from CP. */
  	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
  	if (ret < 0) {
  		dev_err(dev, "Failed to read power status: %d
  ", ret);
  	} else if (ret & WM8994_VMID_SEL_MASK) {
  		dev_dbg(dev, "CODEC still active, ignoring suspend
  ");
  		return 0;
  	}
5f40c6b65   Mark Brown   mfd: Add more che...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
  	if (ret < 0) {
  		dev_err(dev, "Failed to read power status: %d
  ", ret);
  	} else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
  			  WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
  			  WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
  		dev_dbg(dev, "CODEC still active, ignoring suspend
  ");
  		return 0;
  	}
  
  	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
  	if (ret < 0) {
  		dev_err(dev, "Failed to read power status: %d
  ", ret);
  	} else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
  			  WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
  			  WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
  		dev_dbg(dev, "CODEC still active, ignoring suspend
  ");
  		return 0;
  	}
  
  	switch (wm8994->type) {
  	case WM8958:
b5488b6e8   Mark Brown   mfd: Update wm899...
229
  	case WM1811:
5f40c6b65   Mark Brown   mfd: Add more che...
230
231
232
233
234
235
236
237
238
239
240
241
242
  		ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1);
  		if (ret < 0) {
  			dev_err(dev, "Failed to read power status: %d
  ", ret);
  		} else if (ret & WM8958_MICD_ENA) {
  			dev_dbg(dev, "CODEC still active, ignoring suspend
  ");
  			return 0;
  		}
  		break;
  	default:
  		break;
  	}
a3462490b   Mark Brown   mfd: Test for jac...
243
244
245
246
247
248
249
  	switch (wm8994->type) {
  	case WM1811:
  		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
  		if (ret < 0) {
  			dev_err(dev, "Failed to read jackdet: %d
  ", ret);
  		} else if (ret & WM1811_JACKDET_MODE_MASK) {
e7c248a04   Mark Brown   mfd: Test for jac...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  			dev_dbg(dev, "CODEC still active, ignoring suspend
  ");
  			return 0;
  		}
  		break;
  	default:
  		break;
  	}
  
  	switch (wm8994->type) {
  	case WM1811:
  		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
  		if (ret < 0) {
  			dev_err(dev, "Failed to read jackdet: %d
  ", ret);
  		} else if (ret & WM1811_JACKDET_MODE_MASK) {
a3462490b   Mark Brown   mfd: Test for jac...
266
267
268
269
270
271
272
273
  			dev_dbg(dev, "CODEC still active, ignoring suspend
  ");
  			return 0;
  		}
  		break;
  	default:
  		break;
  	}
881de6704   Mark Brown   mfd: Allow WM8994...
274
275
276
277
278
279
  	/* Disable LDO pulldowns while the device is suspended if we
  	 * don't know that something will be driving them. */
  	if (!wm8994->ldo_ena_always_driven)
  		wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
  				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
  				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
f40dff9ed   Mark Brown   mfd: Put WM8994 i...
280
281
282
  	/* Explicitly put the device into reset in case regulators
  	 * don't get disabled in order to ensure consistent restart.
  	 */
be79cf2fd   Mark Brown   mfd: Don't hard c...
283
284
  	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
  			 wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
f40dff9ed   Mark Brown   mfd: Put WM8994 i...
285

ed393dcd4   Mark Brown   mfd: Use regcache...
286
  	regcache_mark_dirty(wm8994->regmap);
78a27cd3e   Chris Rattray   mfd: Restore wm89...
287
288
289
  	/* Restore GPIO registers to prevent problems with mismatched
  	 * pin configurations.
  	 */
ed393dcd4   Mark Brown   mfd: Use regcache...
290
291
  	ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1,
  				   WM8994_GPIO_11);
78a27cd3e   Chris Rattray   mfd: Restore wm89...
292
293
294
  	if (ret != 0)
  		dev_err(dev, "Failed to restore GPIO registers: %d
  ", ret);
1a2017b71   Mark Brown   mfd: Also restore...
295
296
297
298
299
300
301
  	/* In case one of the GPIOs is used as a wake input. */
  	ret = regcache_sync_region(wm8994->regmap,
  				   WM8994_INTERRUPT_STATUS_1_MASK,
  				   WM8994_INTERRUPT_STATUS_1_MASK);
  	if (ret != 0)
  		dev_err(dev, "Failed to restore interrupt mask: %d
  ", ret);
3befc925c   Mark Brown   mfd: Put WM8994 i...
302
  	regcache_cache_only(wm8994->regmap, true);
77bd70e90   Mark Brown   mfd: Don't suspen...
303
  	wm8994->suspended = true;
559e0df6b   Mark Brown   mfd: Add initial ...
304
  	ret = regulator_bulk_disable(wm8994->num_supplies,
9e5010866   Mark Brown   mfd: Add initial ...
305
306
307
308
309
310
311
312
313
  				     wm8994->supplies);
  	if (ret != 0) {
  		dev_err(dev, "Failed to disable supplies: %d
  ", ret);
  		return ret;
  	}
  
  	return 0;
  }
d450f19ee   Mark Brown   mfd: Implement ru...
314
  static int wm8994_resume(struct device *dev)
9e5010866   Mark Brown   mfd: Add initial ...
315
316
  {
  	struct wm8994 *wm8994 = dev_get_drvdata(dev);
c3f138617   Mark Brown   mfd: Enable regis...
317
  	int ret;
9e5010866   Mark Brown   mfd: Add initial ...
318

77bd70e90   Mark Brown   mfd: Don't suspen...
319
320
321
  	/* We may have lied to the PM core about suspending */
  	if (!wm8994->suspended)
  		return 0;
559e0df6b   Mark Brown   mfd: Add initial ...
322
  	ret = regulator_bulk_enable(wm8994->num_supplies,
9e5010866   Mark Brown   mfd: Add initial ...
323
324
325
326
327
328
  				    wm8994->supplies);
  	if (ret != 0) {
  		dev_err(dev, "Failed to enable supplies: %d
  ", ret);
  		return ret;
  	}
3befc925c   Mark Brown   mfd: Put WM8994 i...
329
  	regcache_cache_only(wm8994->regmap, false);
c3f138617   Mark Brown   mfd: Enable regis...
330
331
332
333
334
  	ret = regcache_sync(wm8994->regmap);
  	if (ret != 0) {
  		dev_err(dev, "Failed to restore register map: %d
  ", ret);
  		goto err_enable;
98ae1ccaf   Mark Brown   mfd: Fix WM8994 I...
335
  	}
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
336

881de6704   Mark Brown   mfd: Allow WM8994...
337
338
339
340
  	/* Disable LDO pulldowns while the device is active */
  	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
  			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
  			0);
77bd70e90   Mark Brown   mfd: Don't suspen...
341
  	wm8994->suspended = false;
9e5010866   Mark Brown   mfd: Add initial ...
342
  	return 0;
c3f138617   Mark Brown   mfd: Enable regis...
343
344
345
346
347
  
  err_enable:
  	regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
  
  	return ret;
9e5010866   Mark Brown   mfd: Add initial ...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  }
  #endif
  
  #ifdef CONFIG_REGULATOR
  static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
  {
  	struct wm8994_ldo_pdata *ldo_pdata;
  
  	if (!pdata)
  		return 0;
  
  	ldo_pdata = &pdata->ldo[ldo];
  
  	if (!ldo_pdata->init_data)
  		return 0;
  
  	return ldo_pdata->init_data->num_consumer_supplies != 0;
  }
  #else
  static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
  {
  	return 0;
  }
  #endif
462835e4a   Mark Brown   mfd/ASoC: Convert...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  static const __devinitdata struct reg_default wm8994_revc_patch[] = {
  	{ 0x102, 0x3 },
  	{ 0x56, 0x3 },
  	{ 0x817, 0x0 },
  	{ 0x102, 0x0 },
  };
  
  static const __devinitdata struct reg_default wm8958_reva_patch[] = {
  	{ 0x102, 0x3 },
  	{ 0xcb, 0x81 },
  	{ 0x817, 0x0 },
  	{ 0x102, 0x0 },
  };
  
  static const __devinitdata struct reg_default wm1811_reva_patch[] = {
  	{ 0x102, 0x3 },
a0cc0209a   Mark Brown   mfd: Improve perf...
388
  	{ 0x56, 0x7 },
462835e4a   Mark Brown   mfd/ASoC: Convert...
389
390
391
392
  	{ 0x5d, 0x7e },
  	{ 0x5e, 0x0 },
  	{ 0x102, 0x0 },
  };
9e5010866   Mark Brown   mfd: Add initial ...
393
394
395
  /*
   * Instantiate the generic non-control parts of the device.
   */
abc0cceae   Mark Brown   mfd: Add __devini...
396
  static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
9e5010866   Mark Brown   mfd: Add initial ...
397
398
  {
  	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
346978980   Mark Brown   mfd: Initialise W...
399
  	struct regmap_config *regmap_config;
462835e4a   Mark Brown   mfd/ASoC: Convert...
400
  	const struct reg_default *regmap_patch = NULL;
559e0df6b   Mark Brown   mfd: Add initial ...
401
  	const char *devname;
462835e4a   Mark Brown   mfd/ASoC: Convert...
402
  	int ret, i, patch_regs;
26c34c25e   Mark Brown   mfd: Disable more...
403
  	int pulls = 0;
9e5010866   Mark Brown   mfd: Add initial ...
404

9e5010866   Mark Brown   mfd: Add initial ...
405
406
407
408
409
410
411
412
413
414
  	dev_set_drvdata(wm8994->dev, wm8994);
  
  	/* Add the on-chip regulators first for bootstrapping */
  	ret = mfd_add_devices(wm8994->dev, -1,
  			      wm8994_regulator_devs,
  			      ARRAY_SIZE(wm8994_regulator_devs),
  			      NULL, 0);
  	if (ret != 0) {
  		dev_err(wm8994->dev, "Failed to add children: %d
  ", ret);
9db4249fa   Mark Brown   mfd: wm8994: Conv...
415
  		goto err;
9e5010866   Mark Brown   mfd: Add initial ...
416
  	}
559e0df6b   Mark Brown   mfd: Add initial ...
417
  	switch (wm8994->type) {
b1f43bf3a   Mark Brown   mfd: Add WM1811 s...
418
419
420
  	case WM1811:
  		wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
  		break;
559e0df6b   Mark Brown   mfd: Add initial ...
421
422
423
424
425
426
427
428
  	case WM8994:
  		wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
  		break;
  	case WM8958:
  		wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies);
  		break;
  	default:
  		BUG();
9db4249fa   Mark Brown   mfd: wm8994: Conv...
429
  		goto err;
559e0df6b   Mark Brown   mfd: Add initial ...
430
  	}
2fa334946   Mark Brown   mfd: Convert wm89...
431
432
433
  	wm8994->supplies = devm_kzalloc(wm8994->dev,
  					sizeof(struct regulator_bulk_data) *
  					wm8994->num_supplies, GFP_KERNEL);
fccbd21f3   Axel Lin   mfd: Fix wm8994_d...
434
435
  	if (!wm8994->supplies) {
  		ret = -ENOMEM;
9db4249fa   Mark Brown   mfd: wm8994: Conv...
436
  		goto err;
fccbd21f3   Axel Lin   mfd: Fix wm8994_d...
437
  	}
9e5010866   Mark Brown   mfd: Add initial ...
438

559e0df6b   Mark Brown   mfd: Add initial ...
439
  	switch (wm8994->type) {
b1f43bf3a   Mark Brown   mfd: Add WM1811 s...
440
441
442
443
  	case WM1811:
  		for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
  			wm8994->supplies[i].supply = wm1811_main_supplies[i];
  		break;
559e0df6b   Mark Brown   mfd: Add initial ...
444
445
446
447
448
449
450
451
452
453
  	case WM8994:
  		for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
  			wm8994->supplies[i].supply = wm8994_main_supplies[i];
  		break;
  	case WM8958:
  		for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++)
  			wm8994->supplies[i].supply = wm8958_main_supplies[i];
  		break;
  	default:
  		BUG();
9db4249fa   Mark Brown   mfd: wm8994: Conv...
454
  		goto err;
559e0df6b   Mark Brown   mfd: Add initial ...
455
456
457
  	}
  		
  	ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
9e5010866   Mark Brown   mfd: Add initial ...
458
459
460
461
  				 wm8994->supplies);
  	if (ret != 0) {
  		dev_err(wm8994->dev, "Failed to get supplies: %d
  ", ret);
9db4249fa   Mark Brown   mfd: wm8994: Conv...
462
  		goto err;
9e5010866   Mark Brown   mfd: Add initial ...
463
  	}
559e0df6b   Mark Brown   mfd: Add initial ...
464
  	ret = regulator_bulk_enable(wm8994->num_supplies,
9e5010866   Mark Brown   mfd: Add initial ...
465
466
467
468
  				    wm8994->supplies);
  	if (ret != 0) {
  		dev_err(wm8994->dev, "Failed to enable supplies: %d
  ", ret);
7731074ab   Joonyoung Shim   mfd: Fix WM8994 e...
469
  		goto err_get;
9e5010866   Mark Brown   mfd: Add initial ...
470
471
472
473
474
475
476
477
  	}
  
  	ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);
  	if (ret < 0) {
  		dev_err(wm8994->dev, "Failed to read ID register
  ");
  		goto err_enable;
  	}
559e0df6b   Mark Brown   mfd: Add initial ...
478
  	switch (ret) {
b1f43bf3a   Mark Brown   mfd: Add WM1811 s...
479
480
481
482
483
484
485
486
  	case 0x1811:
  		devname = "WM1811";
  		if (wm8994->type != WM1811)
  			dev_warn(wm8994->dev, "Device registered as type %d
  ",
  				 wm8994->type);
  		wm8994->type = WM1811;
  		break;
559e0df6b   Mark Brown   mfd: Add initial ...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
  	case 0x8994:
  		devname = "WM8994";
  		if (wm8994->type != WM8994)
  			dev_warn(wm8994->dev, "Device registered as type %d
  ",
  				 wm8994->type);
  		wm8994->type = WM8994;
  		break;
  	case 0x8958:
  		devname = "WM8958";
  		if (wm8994->type != WM8958)
  			dev_warn(wm8994->dev, "Device registered as type %d
  ",
  				 wm8994->type);
  		wm8994->type = WM8958;
  		break;
  	default:
9e5010866   Mark Brown   mfd: Add initial ...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  		dev_err(wm8994->dev, "Device is not a WM8994, ID is %x
  ",
  			ret);
  		ret = -EINVAL;
  		goto err_enable;
  	}
  
  	ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION);
  	if (ret < 0) {
  		dev_err(wm8994->dev, "Failed to read revision register: %d
  ",
  			ret);
  		goto err_enable;
  	}
cc7a72794   Mark Brown   mfd: Read CUST_ID...
518
519
  	wm8994->revision = ret & WM8994_CHIP_REV_MASK;
  	wm8994->cust_id = (ret & WM8994_CUST_ID_MASK) >> WM8994_CUST_ID_SHIFT;
9e5010866   Mark Brown   mfd: Add initial ...
520

a2495bc72   Mark Brown   mfd: Restructure ...
521
522
  	switch (wm8994->type) {
  	case WM8994:
7ed5849c2   Mark Brown   mfd: Mark WM1811 ...
523
  		switch (wm8994->revision) {
a2495bc72   Mark Brown   mfd: Restructure ...
524
525
  		case 0:
  		case 1:
559e0df6b   Mark Brown   mfd: Add initial ...
526
527
528
  			dev_warn(wm8994->dev,
  				 "revision %c not fully supported
  ",
7ed5849c2   Mark Brown   mfd: Mark WM1811 ...
529
  				 'A' + wm8994->revision);
a2495bc72   Mark Brown   mfd: Restructure ...
530
  			break;
462835e4a   Mark Brown   mfd/ASoC: Convert...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
  		case 2:
  		case 3:
  			regmap_patch = wm8994_revc_patch;
  			patch_regs = ARRAY_SIZE(wm8994_revc_patch);
  			break;
  		default:
  			break;
  		}
  		break;
  
  	case WM8958:
  		switch (wm8994->revision) {
  		case 0:
  			regmap_patch = wm8958_reva_patch;
  			patch_regs = ARRAY_SIZE(wm8958_reva_patch);
  			break;
a2495bc72   Mark Brown   mfd: Restructure ...
547
548
549
  		default:
  			break;
  		}
9e5010866   Mark Brown   mfd: Add initial ...
550
  		break;
462835e4a   Mark Brown   mfd/ASoC: Convert...
551

443e67ed8   Mark Brown   mfd: Correct revi...
552
553
  	case WM1811:
  		/* Revision C did not change the relevant layer */
7ed5849c2   Mark Brown   mfd: Mark WM1811 ...
554
555
  		if (wm8994->revision > 1)
  			wm8994->revision++;
462835e4a   Mark Brown   mfd/ASoC: Convert...
556
557
558
  		switch (wm8994->revision) {
  		case 0:
  		case 1:
a0cc0209a   Mark Brown   mfd: Improve perf...
559
560
  		case 2:
  		case 3:
462835e4a   Mark Brown   mfd/ASoC: Convert...
561
562
563
564
565
566
  			regmap_patch = wm1811_reva_patch;
  			patch_regs = ARRAY_SIZE(wm1811_reva_patch);
  			break;
  		default:
  			break;
  		}
443e67ed8   Mark Brown   mfd: Correct revi...
567
  		break;
462835e4a   Mark Brown   mfd/ASoC: Convert...
568

9e5010866   Mark Brown   mfd: Add initial ...
569
  	default:
9e5010866   Mark Brown   mfd: Add initial ...
570
571
  		break;
  	}
cc7a72794   Mark Brown   mfd: Read CUST_ID...
572
573
574
  	dev_info(wm8994->dev, "%s revision %c CUST_ID %02x
  ", devname,
  		 'A' + wm8994->revision, wm8994->cust_id);
9e5010866   Mark Brown   mfd: Add initial ...
575

346978980   Mark Brown   mfd: Initialise W...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  	switch (wm8994->type) {
  	case WM1811:
  		regmap_config = &wm1811_regmap_config;
  		break;
  	case WM8994:
  		regmap_config = &wm8994_regmap_config;
  		break;
  	case WM8958:
  		regmap_config = &wm8958_regmap_config;
  		break;
  	default:
  		dev_err(wm8994->dev, "Unknown device type %d
  ", wm8994->type);
  		return -EINVAL;
  	}
  
  	ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
  	if (ret != 0) {
  		dev_err(wm8994->dev, "Failed to reinit register cache: %d
  ",
  			ret);
  		return ret;
  	}
9e5010866   Mark Brown   mfd: Add initial ...
599

462835e4a   Mark Brown   mfd/ASoC: Convert...
600
601
602
603
604
605
606
  	if (regmap_patch) {
  		ret = regmap_register_patch(wm8994->regmap, regmap_patch,
  					    patch_regs);
  		if (ret != 0) {
  			dev_err(wm8994->dev, "Failed to register patch: %d
  ",
  				ret);
9db4249fa   Mark Brown   mfd: wm8994: Conv...
607
  			goto err;
462835e4a   Mark Brown   mfd/ASoC: Convert...
608
609
  		}
  	}
9e5010866   Mark Brown   mfd: Add initial ...
610
  	if (pdata) {
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
611
  		wm8994->irq_base = pdata->irq_base;
9e5010866   Mark Brown   mfd: Add initial ...
612
613
614
615
616
617
618
619
620
621
  		wm8994->gpio_base = pdata->gpio_base;
  
  		/* GPIO configuration is only applied if it's non-zero */
  		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
  			if (pdata->gpio_defaults[i]) {
  				wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
  						0xffff,
  						pdata->gpio_defaults[i]);
  			}
  		}
881de6704   Mark Brown   mfd: Allow WM8994...
622
623
  
  		wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
26c34c25e   Mark Brown   mfd: Disable more...
624
625
626
  
  		if (pdata->spkmode_pu)
  			pulls |= WM8994_SPKMODE_PU;
9e5010866   Mark Brown   mfd: Add initial ...
627
  	}
26c34c25e   Mark Brown   mfd: Disable more...
628
  	/* Disable unneeded pulls */
881de6704   Mark Brown   mfd: Allow WM8994...
629
  	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
26c34c25e   Mark Brown   mfd: Disable more...
630
631
632
  			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD |
  			WM8994_SPKMODE_PU | WM8994_CSNADDR_PD,
  			pulls);
881de6704   Mark Brown   mfd: Allow WM8994...
633

9e5010866   Mark Brown   mfd: Add initial ...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
  	/* In some system designs where the regulators are not in use,
  	 * we can achieve a small reduction in leakage currents by
  	 * floating LDO outputs.  This bit makes no difference if the
  	 * LDOs are enabled, it only affects cases where the LDOs were
  	 * in operation and are then disabled.
  	 */
  	for (i = 0; i < WM8994_NUM_LDO_REGS; i++) {
  		if (wm8994_ldo_in_use(pdata, i))
  			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
  					WM8994_LDO1_DISCH, WM8994_LDO1_DISCH);
  		else
  			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
  					WM8994_LDO1_DISCH, 0);
  	}
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
648
  	wm8994_irq_init(wm8994);
9e5010866   Mark Brown   mfd: Add initial ...
649
650
651
652
653
654
  	ret = mfd_add_devices(wm8994->dev, -1,
  			      wm8994_devs, ARRAY_SIZE(wm8994_devs),
  			      NULL, 0);
  	if (ret != 0) {
  		dev_err(wm8994->dev, "Failed to add children: %d
  ", ret);
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
655
  		goto err_irq;
9e5010866   Mark Brown   mfd: Add initial ...
656
  	}
d450f19ee   Mark Brown   mfd: Implement ru...
657
  	pm_runtime_enable(wm8994->dev);
ee67b0cd5   Mark Brown   mfd: wm8994: We d...
658
  	pm_runtime_idle(wm8994->dev);
d450f19ee   Mark Brown   mfd: Implement ru...
659

9e5010866   Mark Brown   mfd: Add initial ...
660
  	return 0;
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
661
662
  err_irq:
  	wm8994_irq_exit(wm8994);
9e5010866   Mark Brown   mfd: Add initial ...
663
  err_enable:
559e0df6b   Mark Brown   mfd: Add initial ...
664
  	regulator_bulk_disable(wm8994->num_supplies,
9e5010866   Mark Brown   mfd: Add initial ...
665
666
  			       wm8994->supplies);
  err_get:
559e0df6b   Mark Brown   mfd: Add initial ...
667
  	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
9db4249fa   Mark Brown   mfd: wm8994: Conv...
668
  err:
9e5010866   Mark Brown   mfd: Add initial ...
669
  	mfd_remove_devices(wm8994->dev);
9e5010866   Mark Brown   mfd: Add initial ...
670
671
  	return ret;
  }
abc0cceae   Mark Brown   mfd: Add __devini...
672
  static __devexit void wm8994_device_exit(struct wm8994 *wm8994)
9e5010866   Mark Brown   mfd: Add initial ...
673
  {
d450f19ee   Mark Brown   mfd: Implement ru...
674
  	pm_runtime_disable(wm8994->dev);
9e5010866   Mark Brown   mfd: Add initial ...
675
  	mfd_remove_devices(wm8994->dev);
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
676
  	wm8994_irq_exit(wm8994);
559e0df6b   Mark Brown   mfd: Add initial ...
677
  	regulator_bulk_disable(wm8994->num_supplies,
9e5010866   Mark Brown   mfd: Add initial ...
678
  			       wm8994->supplies);
559e0df6b   Mark Brown   mfd: Add initial ...
679
  	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
9e5010866   Mark Brown   mfd: Add initial ...
680
  }
cf763c2e6   Mark Brown   mfd: Add basic de...
681
682
683
684
685
686
687
  static const struct of_device_id wm8994_of_match[] = {
  	{ .compatible = "wlf,wm1811", },
  	{ .compatible = "wlf,wm8994", },
  	{ .compatible = "wlf,wm8958", },
  	{ }
  };
  MODULE_DEVICE_TABLE(of, wm8994_of_match);
027d67665   Mark Brown   mfd: wm8994: Add ...
688
689
  static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
  				      const struct i2c_device_id *id)
9e5010866   Mark Brown   mfd: Add initial ...
690
691
  {
  	struct wm8994 *wm8994;
d6c645fc0   Mark Brown   mfd: Convert WM89...
692
  	int ret;
9e5010866   Mark Brown   mfd: Add initial ...
693

2fa334946   Mark Brown   mfd: Convert wm89...
694
  	wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);
d0a116939   Axel Lin   mfd: Fix incorrec...
695
  	if (wm8994 == NULL)
9e5010866   Mark Brown   mfd: Add initial ...
696
  		return -ENOMEM;
9e5010866   Mark Brown   mfd: Add initial ...
697
698
699
  
  	i2c_set_clientdata(i2c, wm8994);
  	wm8994->dev = &i2c->dev;
c9fbf7e07   Mark Brown   mfd: Add WM8994 i...
700
  	wm8994->irq = i2c->irq;
559e0df6b   Mark Brown   mfd: Add initial ...
701
  	wm8994->type = id->driver_data;
9e5010866   Mark Brown   mfd: Add initial ...
702

9db4249fa   Mark Brown   mfd: wm8994: Conv...
703
  	wm8994->regmap = devm_regmap_init_i2c(i2c, &wm8994_base_regmap_config);
d6c645fc0   Mark Brown   mfd: Convert WM89...
704
705
706
707
708
  	if (IS_ERR(wm8994->regmap)) {
  		ret = PTR_ERR(wm8994->regmap);
  		dev_err(wm8994->dev, "Failed to allocate register map: %d
  ",
  			ret);
d6c645fc0   Mark Brown   mfd: Convert WM89...
709
710
  		return ret;
  	}
559e0df6b   Mark Brown   mfd: Add initial ...
711
  	return wm8994_device_init(wm8994, i2c->irq);
9e5010866   Mark Brown   mfd: Add initial ...
712
  }
027d67665   Mark Brown   mfd: wm8994: Add ...
713
  static __devexit int wm8994_i2c_remove(struct i2c_client *i2c)
9e5010866   Mark Brown   mfd: Add initial ...
714
715
716
717
718
719
720
  {
  	struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
  
  	wm8994_device_exit(wm8994);
  
  	return 0;
  }
9e5010866   Mark Brown   mfd: Add initial ...
721
  static const struct i2c_device_id wm8994_i2c_id[] = {
b1f43bf3a   Mark Brown   mfd: Add WM1811 s...
722
  	{ "wm1811", WM1811 },
71d171847   Mark Brown   mfd: Add WM1811A ...
723
  	{ "wm1811a", WM1811 },
559e0df6b   Mark Brown   mfd: Add initial ...
724
725
  	{ "wm8994", WM8994 },
  	{ "wm8958", WM8958 },
9e5010866   Mark Brown   mfd: Add initial ...
726
727
728
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
aad343107   Mark Brown   mfd: Staticise WM...
729
730
  static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume,
  			    NULL);
d450f19ee   Mark Brown   mfd: Implement ru...
731

9e5010866   Mark Brown   mfd: Add initial ...
732
733
  static struct i2c_driver wm8994_i2c_driver = {
  	.driver = {
d450f19ee   Mark Brown   mfd: Implement ru...
734
735
736
  		.name = "wm8994",
  		.owner = THIS_MODULE,
  		.pm = &wm8994_pm_ops,
cf763c2e6   Mark Brown   mfd: Add basic de...
737
  		.of_match_table = wm8994_of_match,
9e5010866   Mark Brown   mfd: Add initial ...
738
739
  	},
  	.probe = wm8994_i2c_probe,
027d67665   Mark Brown   mfd: wm8994: Add ...
740
  	.remove = __devexit_p(wm8994_i2c_remove),
9e5010866   Mark Brown   mfd: Add initial ...
741
742
  	.id_table = wm8994_i2c_id,
  };
ceb57d27e   Mark Brown   mfd: Convert wm89...
743
  module_i2c_driver(wm8994_i2c_driver);
9e5010866   Mark Brown   mfd: Add initial ...
744
745
746
747
  
  MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");