xref: /openbmc/linux/drivers/mfd/wm8994-core.c (revision 4740f73f)
19e501086SMark Brown /*
29e501086SMark Brown  * wm8994-core.c  --  Device access for Wolfson WM8994
39e501086SMark Brown  *
49e501086SMark Brown  * Copyright 2009 Wolfson Microelectronics PLC.
59e501086SMark Brown  *
69e501086SMark Brown  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
79e501086SMark Brown  *
89e501086SMark Brown  *  This program is free software; you can redistribute  it and/or modify it
99e501086SMark Brown  *  under  the terms of  the GNU General  Public License as published by the
109e501086SMark Brown  *  Free Software Foundation;  either version 2 of the  License, or (at your
119e501086SMark Brown  *  option) any later version.
129e501086SMark Brown  *
139e501086SMark Brown  */
149e501086SMark Brown 
159e501086SMark Brown #include <linux/kernel.h>
169e501086SMark Brown #include <linux/module.h>
175a0e3ad6STejun Heo #include <linux/slab.h>
189e501086SMark Brown #include <linux/i2c.h>
19d6c645fcSMark Brown #include <linux/err.h>
209e501086SMark Brown #include <linux/delay.h>
219e501086SMark Brown #include <linux/mfd/core.h>
22d450f19eSMark Brown #include <linux/pm_runtime.h>
23d6c645fcSMark Brown #include <linux/regmap.h>
249e501086SMark Brown #include <linux/regulator/consumer.h>
259e501086SMark Brown #include <linux/regulator/machine.h>
269e501086SMark Brown 
279e501086SMark Brown #include <linux/mfd/wm8994/core.h>
289e501086SMark Brown #include <linux/mfd/wm8994/pdata.h>
299e501086SMark Brown #include <linux/mfd/wm8994/registers.h>
309e501086SMark Brown 
31c3f13861SMark Brown #include "wm8994.h"
329e501086SMark Brown 
339e501086SMark Brown /**
349e501086SMark Brown  * wm8994_reg_read: Read a single WM8994 register.
359e501086SMark Brown  *
369e501086SMark Brown  * @wm8994: Device to read from.
379e501086SMark Brown  * @reg: Register to read.
389e501086SMark Brown  */
399e501086SMark Brown int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
409e501086SMark Brown {
41d6c645fcSMark Brown 	unsigned int val;
429e501086SMark Brown 	int ret;
439e501086SMark Brown 
44d6c645fcSMark Brown 	ret = regmap_read(wm8994->regmap, reg, &val);
459e501086SMark Brown 
469e501086SMark Brown 	if (ret < 0)
479e501086SMark Brown 		return ret;
489e501086SMark Brown 	else
49d6c645fcSMark Brown 		return val;
509e501086SMark Brown }
519e501086SMark Brown EXPORT_SYMBOL_GPL(wm8994_reg_read);
529e501086SMark Brown 
539e501086SMark Brown /**
549e501086SMark Brown  * wm8994_bulk_read: Read multiple WM8994 registers
559e501086SMark Brown  *
569e501086SMark Brown  * @wm8994: Device to read from
579e501086SMark Brown  * @reg: First register
589e501086SMark Brown  * @count: Number of registers
59316b6cc0SMark Brown  * @buf: Buffer to fill.  The data will be returned big endian.
609e501086SMark Brown  */
619e501086SMark Brown int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
629e501086SMark Brown 		     int count, u16 *buf)
639e501086SMark Brown {
64d6c645fcSMark Brown 	return regmap_bulk_read(wm8994->regmap, reg, buf, count);
659e501086SMark Brown }
669e501086SMark Brown 
679e501086SMark Brown /**
689e501086SMark Brown  * wm8994_reg_write: Write a single WM8994 register.
699e501086SMark Brown  *
709e501086SMark Brown  * @wm8994: Device to write to.
719e501086SMark Brown  * @reg: Register to write to.
729e501086SMark Brown  * @val: Value to write.
739e501086SMark Brown  */
749e501086SMark Brown int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
759e501086SMark Brown 		     unsigned short val)
769e501086SMark Brown {
77d6c645fcSMark Brown 	return regmap_write(wm8994->regmap, reg, val);
789e501086SMark Brown }
799e501086SMark Brown EXPORT_SYMBOL_GPL(wm8994_reg_write);
809e501086SMark Brown 
819e501086SMark Brown /**
82e93c5387SMark Brown  * wm8994_bulk_write: Write multiple WM8994 registers
83e93c5387SMark Brown  *
84e93c5387SMark Brown  * @wm8994: Device to write to
85e93c5387SMark Brown  * @reg: First register
86e93c5387SMark Brown  * @count: Number of registers
874277163cSMark Brown  * @buf: Buffer to write from.  Data must be big-endian formatted.
88e93c5387SMark Brown  */
89e93c5387SMark Brown int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
9007e73fbbSMark Brown 		      int count, const u16 *buf)
91e93c5387SMark Brown {
92d6c645fcSMark Brown 	return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
93e93c5387SMark Brown }
94e93c5387SMark Brown EXPORT_SYMBOL_GPL(wm8994_bulk_write);
95e93c5387SMark Brown 
96e93c5387SMark Brown /**
979e501086SMark Brown  * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
989e501086SMark Brown  *
999e501086SMark Brown  * @wm8994: Device to write to.
1009e501086SMark Brown  * @reg: Register to write to.
1019e501086SMark Brown  * @mask: Mask of bits to set.
1029e501086SMark Brown  * @val: Value to set (unshifted)
1039e501086SMark Brown  */
1049e501086SMark Brown int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
1059e501086SMark Brown 		    unsigned short mask, unsigned short val)
1069e501086SMark Brown {
107d6c645fcSMark Brown 	return regmap_update_bits(wm8994->regmap, reg, mask, val);
1089e501086SMark Brown }
1099e501086SMark Brown EXPORT_SYMBOL_GPL(wm8994_set_bits);
1109e501086SMark Brown 
1119e501086SMark Brown static struct mfd_cell wm8994_regulator_devs[] = {
112d450f19eSMark Brown 	{
113d450f19eSMark Brown 		.name = "wm8994-ldo",
114d450f19eSMark Brown 		.id = 1,
115d450f19eSMark Brown 		.pm_runtime_no_callbacks = true,
116d450f19eSMark Brown 	},
117d450f19eSMark Brown 	{
118d450f19eSMark Brown 		.name = "wm8994-ldo",
119d450f19eSMark Brown 		.id = 2,
120d450f19eSMark Brown 		.pm_runtime_no_callbacks = true,
121d450f19eSMark Brown 	},
1229e501086SMark Brown };
1239e501086SMark Brown 
124c9fbf7e0SMark Brown static struct resource wm8994_codec_resources[] = {
125c9fbf7e0SMark Brown 	{
126c9fbf7e0SMark Brown 		.start = WM8994_IRQ_TEMP_SHUT,
127c9fbf7e0SMark Brown 		.end   = WM8994_IRQ_TEMP_WARN,
128c9fbf7e0SMark Brown 		.flags = IORESOURCE_IRQ,
129c9fbf7e0SMark Brown 	},
130c9fbf7e0SMark Brown };
131c9fbf7e0SMark Brown 
132c9fbf7e0SMark Brown static struct resource wm8994_gpio_resources[] = {
133c9fbf7e0SMark Brown 	{
134c9fbf7e0SMark Brown 		.start = WM8994_IRQ_GPIO(1),
135c9fbf7e0SMark Brown 		.end   = WM8994_IRQ_GPIO(11),
136c9fbf7e0SMark Brown 		.flags = IORESOURCE_IRQ,
137c9fbf7e0SMark Brown 	},
138c9fbf7e0SMark Brown };
139c9fbf7e0SMark Brown 
1409e501086SMark Brown static struct mfd_cell wm8994_devs[] = {
141c9fbf7e0SMark Brown 	{
142c9fbf7e0SMark Brown 		.name = "wm8994-codec",
143c9fbf7e0SMark Brown 		.num_resources = ARRAY_SIZE(wm8994_codec_resources),
144c9fbf7e0SMark Brown 		.resources = wm8994_codec_resources,
145c9fbf7e0SMark Brown 	},
146c9fbf7e0SMark Brown 
147c9fbf7e0SMark Brown 	{
148c9fbf7e0SMark Brown 		.name = "wm8994-gpio",
149c9fbf7e0SMark Brown 		.num_resources = ARRAY_SIZE(wm8994_gpio_resources),
150c9fbf7e0SMark Brown 		.resources = wm8994_gpio_resources,
151d450f19eSMark Brown 		.pm_runtime_no_callbacks = true,
152c9fbf7e0SMark Brown 	},
1539e501086SMark Brown };
1549e501086SMark Brown 
1559e501086SMark Brown /*
1569e501086SMark Brown  * Supplies for the main bulk of CODEC; the LDO supplies are ignored
1579e501086SMark Brown  * and should be handled via the standard regulator API supply
1589e501086SMark Brown  * management.
1599e501086SMark Brown  */
160b1f43bf3SMark Brown static const char *wm1811_main_supplies[] = {
161b1f43bf3SMark Brown 	"DBVDD1",
162b1f43bf3SMark Brown 	"DBVDD2",
163b1f43bf3SMark Brown 	"DBVDD3",
164b1f43bf3SMark Brown 	"DCVDD",
165b1f43bf3SMark Brown 	"AVDD1",
166b1f43bf3SMark Brown 	"AVDD2",
167b1f43bf3SMark Brown 	"CPVDD",
168b1f43bf3SMark Brown 	"SPKVDD1",
169b1f43bf3SMark Brown 	"SPKVDD2",
170b1f43bf3SMark Brown };
171b1f43bf3SMark Brown 
1729e501086SMark Brown static const char *wm8994_main_supplies[] = {
1739e501086SMark Brown 	"DBVDD",
1749e501086SMark Brown 	"DCVDD",
1759e501086SMark Brown 	"AVDD1",
1769e501086SMark Brown 	"AVDD2",
1779e501086SMark Brown 	"CPVDD",
1789e501086SMark Brown 	"SPKVDD1",
1799e501086SMark Brown 	"SPKVDD2",
1809e501086SMark Brown };
1819e501086SMark Brown 
182559e0df6SMark Brown static const char *wm8958_main_supplies[] = {
183559e0df6SMark Brown 	"DBVDD1",
184559e0df6SMark Brown 	"DBVDD2",
185559e0df6SMark Brown 	"DBVDD3",
186559e0df6SMark Brown 	"DCVDD",
187559e0df6SMark Brown 	"AVDD1",
188559e0df6SMark Brown 	"AVDD2",
189559e0df6SMark Brown 	"CPVDD",
190559e0df6SMark Brown 	"SPKVDD1",
191559e0df6SMark Brown 	"SPKVDD2",
192559e0df6SMark Brown };
193559e0df6SMark Brown 
1949e501086SMark Brown #ifdef CONFIG_PM
195d450f19eSMark Brown static int wm8994_suspend(struct device *dev)
1969e501086SMark Brown {
1979e501086SMark Brown 	struct wm8994 *wm8994 = dev_get_drvdata(dev);
1989e501086SMark Brown 	int ret;
1999e501086SMark Brown 
20077bd70e9SMark Brown 	/* Don't actually go through with the suspend if the CODEC is
20177bd70e9SMark Brown 	 * still active (eg, for audio passthrough from CP. */
20277bd70e9SMark Brown 	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
20377bd70e9SMark Brown 	if (ret < 0) {
20477bd70e9SMark Brown 		dev_err(dev, "Failed to read power status: %d\n", ret);
20577bd70e9SMark Brown 	} else if (ret & WM8994_VMID_SEL_MASK) {
20677bd70e9SMark Brown 		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
20777bd70e9SMark Brown 		return 0;
20877bd70e9SMark Brown 	}
20977bd70e9SMark Brown 
2105f40c6b6SMark Brown 	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
2115f40c6b6SMark Brown 	if (ret < 0) {
2125f40c6b6SMark Brown 		dev_err(dev, "Failed to read power status: %d\n", ret);
2135f40c6b6SMark Brown 	} else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
2145f40c6b6SMark Brown 			  WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
2155f40c6b6SMark Brown 			  WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
2165f40c6b6SMark Brown 		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
2175f40c6b6SMark Brown 		return 0;
2185f40c6b6SMark Brown 	}
2195f40c6b6SMark Brown 
2205f40c6b6SMark Brown 	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
2215f40c6b6SMark Brown 	if (ret < 0) {
2225f40c6b6SMark Brown 		dev_err(dev, "Failed to read power status: %d\n", ret);
2235f40c6b6SMark Brown 	} else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
2245f40c6b6SMark Brown 			  WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
2255f40c6b6SMark Brown 			  WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
2265f40c6b6SMark Brown 		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
2275f40c6b6SMark Brown 		return 0;
2285f40c6b6SMark Brown 	}
2295f40c6b6SMark Brown 
2305f40c6b6SMark Brown 	switch (wm8994->type) {
2315f40c6b6SMark Brown 	case WM8958:
232b5488b6eSMark Brown 	case WM1811:
2335f40c6b6SMark Brown 		ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1);
2345f40c6b6SMark Brown 		if (ret < 0) {
2355f40c6b6SMark Brown 			dev_err(dev, "Failed to read power status: %d\n", ret);
2365f40c6b6SMark Brown 		} else if (ret & WM8958_MICD_ENA) {
2375f40c6b6SMark Brown 			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
2385f40c6b6SMark Brown 			return 0;
2395f40c6b6SMark Brown 		}
2405f40c6b6SMark Brown 		break;
2415f40c6b6SMark Brown 	default:
2425f40c6b6SMark Brown 		break;
2435f40c6b6SMark Brown 	}
2445f40c6b6SMark Brown 
245a3462490SMark Brown 	switch (wm8994->type) {
246a3462490SMark Brown 	case WM1811:
247a3462490SMark Brown 		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
248a3462490SMark Brown 		if (ret < 0) {
249a3462490SMark Brown 			dev_err(dev, "Failed to read jackdet: %d\n", ret);
250a3462490SMark Brown 		} else if (ret & WM1811_JACKDET_MODE_MASK) {
251a3462490SMark Brown 			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
252a3462490SMark Brown 			return 0;
253a3462490SMark Brown 		}
254a3462490SMark Brown 		break;
255a3462490SMark Brown 	default:
256a3462490SMark Brown 		break;
257a3462490SMark Brown 	}
258a3462490SMark Brown 
259e7c248a0SMark Brown 	switch (wm8994->type) {
260e7c248a0SMark Brown 	case WM1811:
261e7c248a0SMark Brown 		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
262e7c248a0SMark Brown 		if (ret < 0) {
263e7c248a0SMark Brown 			dev_err(dev, "Failed to read jackdet: %d\n", ret);
264e7c248a0SMark Brown 		} else if (ret & WM1811_JACKDET_MODE_MASK) {
265e7c248a0SMark Brown 			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
266e7c248a0SMark Brown 			return 0;
267e7c248a0SMark Brown 		}
268e7c248a0SMark Brown 		break;
269e7c248a0SMark Brown 	default:
270e7c248a0SMark Brown 		break;
271e7c248a0SMark Brown 	}
272e7c248a0SMark Brown 
273881de670SMark Brown 	/* Disable LDO pulldowns while the device is suspended if we
274881de670SMark Brown 	 * don't know that something will be driving them. */
275881de670SMark Brown 	if (!wm8994->ldo_ena_always_driven)
276881de670SMark Brown 		wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
277881de670SMark Brown 				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
278881de670SMark Brown 				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
279881de670SMark Brown 
280f40dff9eSMark Brown 	/* Explicitly put the device into reset in case regulators
281f40dff9eSMark Brown 	 * don't get disabled in order to ensure consistent restart.
282f40dff9eSMark Brown 	 */
283be79cf2fSMark Brown 	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
284be79cf2fSMark Brown 			 wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
285f40dff9eSMark Brown 
286ed393dcdSMark Brown 	regcache_mark_dirty(wm8994->regmap);
287ed393dcdSMark Brown 
28878a27cd3SChris Rattray 	/* Restore GPIO registers to prevent problems with mismatched
28978a27cd3SChris Rattray 	 * pin configurations.
29078a27cd3SChris Rattray 	 */
291ed393dcdSMark Brown 	ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1,
292ed393dcdSMark Brown 				   WM8994_GPIO_11);
29378a27cd3SChris Rattray 	if (ret != 0)
29478a27cd3SChris Rattray 		dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
29578a27cd3SChris Rattray 
2961a2017b7SMark Brown 	/* In case one of the GPIOs is used as a wake input. */
2971a2017b7SMark Brown 	ret = regcache_sync_region(wm8994->regmap,
2981a2017b7SMark Brown 				   WM8994_INTERRUPT_STATUS_1_MASK,
2991a2017b7SMark Brown 				   WM8994_INTERRUPT_STATUS_1_MASK);
3001a2017b7SMark Brown 	if (ret != 0)
3011a2017b7SMark Brown 		dev_err(dev, "Failed to restore interrupt mask: %d\n", ret);
3021a2017b7SMark Brown 
3033befc925SMark Brown 	regcache_cache_only(wm8994->regmap, true);
30477bd70e9SMark Brown 	wm8994->suspended = true;
30577bd70e9SMark Brown 
306559e0df6SMark Brown 	ret = regulator_bulk_disable(wm8994->num_supplies,
3079e501086SMark Brown 				     wm8994->supplies);
3089e501086SMark Brown 	if (ret != 0) {
3099e501086SMark Brown 		dev_err(dev, "Failed to disable supplies: %d\n", ret);
3109e501086SMark Brown 		return ret;
3119e501086SMark Brown 	}
3129e501086SMark Brown 
3139e501086SMark Brown 	return 0;
3149e501086SMark Brown }
3159e501086SMark Brown 
316d450f19eSMark Brown static int wm8994_resume(struct device *dev)
3179e501086SMark Brown {
3189e501086SMark Brown 	struct wm8994 *wm8994 = dev_get_drvdata(dev);
319c3f13861SMark Brown 	int ret;
3209e501086SMark Brown 
32177bd70e9SMark Brown 	/* We may have lied to the PM core about suspending */
32277bd70e9SMark Brown 	if (!wm8994->suspended)
32377bd70e9SMark Brown 		return 0;
32477bd70e9SMark Brown 
325559e0df6SMark Brown 	ret = regulator_bulk_enable(wm8994->num_supplies,
3269e501086SMark Brown 				    wm8994->supplies);
3279e501086SMark Brown 	if (ret != 0) {
3289e501086SMark Brown 		dev_err(dev, "Failed to enable supplies: %d\n", ret);
3299e501086SMark Brown 		return ret;
3309e501086SMark Brown 	}
3319e501086SMark Brown 
3323befc925SMark Brown 	regcache_cache_only(wm8994->regmap, false);
333c3f13861SMark Brown 	ret = regcache_sync(wm8994->regmap);
334c3f13861SMark Brown 	if (ret != 0) {
335c3f13861SMark Brown 		dev_err(dev, "Failed to restore register map: %d\n", ret);
336c3f13861SMark Brown 		goto err_enable;
33798ae1ccaSMark Brown 	}
338c9fbf7e0SMark Brown 
339881de670SMark Brown 	/* Disable LDO pulldowns while the device is active */
340881de670SMark Brown 	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
341881de670SMark Brown 			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
342881de670SMark Brown 			0);
343881de670SMark Brown 
34477bd70e9SMark Brown 	wm8994->suspended = false;
34577bd70e9SMark Brown 
3469e501086SMark Brown 	return 0;
347c3f13861SMark Brown 
348c3f13861SMark Brown err_enable:
349c3f13861SMark Brown 	regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
350c3f13861SMark Brown 
351c3f13861SMark Brown 	return ret;
3529e501086SMark Brown }
3539e501086SMark Brown #endif
3549e501086SMark Brown 
3559e501086SMark Brown #ifdef CONFIG_REGULATOR
3569e501086SMark Brown static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
3579e501086SMark Brown {
3589e501086SMark Brown 	struct wm8994_ldo_pdata *ldo_pdata;
3599e501086SMark Brown 
3609e501086SMark Brown 	if (!pdata)
3619e501086SMark Brown 		return 0;
3629e501086SMark Brown 
3639e501086SMark Brown 	ldo_pdata = &pdata->ldo[ldo];
3649e501086SMark Brown 
3659e501086SMark Brown 	if (!ldo_pdata->init_data)
3669e501086SMark Brown 		return 0;
3679e501086SMark Brown 
3689e501086SMark Brown 	return ldo_pdata->init_data->num_consumer_supplies != 0;
3699e501086SMark Brown }
3709e501086SMark Brown #else
3719e501086SMark Brown static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
3729e501086SMark Brown {
3739e501086SMark Brown 	return 0;
3749e501086SMark Brown }
3759e501086SMark Brown #endif
3769e501086SMark Brown 
377a73e5df1SBill Pemberton static const struct reg_default wm8994_revc_patch[] = {
378462835e4SMark Brown 	{ 0x102, 0x3 },
379462835e4SMark Brown 	{ 0x56, 0x3 },
380462835e4SMark Brown 	{ 0x817, 0x0 },
381462835e4SMark Brown 	{ 0x102, 0x0 },
382462835e4SMark Brown };
383462835e4SMark Brown 
384a73e5df1SBill Pemberton static const struct reg_default wm8958_reva_patch[] = {
385462835e4SMark Brown 	{ 0x102, 0x3 },
386462835e4SMark Brown 	{ 0xcb, 0x81 },
387462835e4SMark Brown 	{ 0x817, 0x0 },
388462835e4SMark Brown 	{ 0x102, 0x0 },
389462835e4SMark Brown };
390462835e4SMark Brown 
391a73e5df1SBill Pemberton static const struct reg_default wm1811_reva_patch[] = {
392462835e4SMark Brown 	{ 0x102, 0x3 },
3939282a7b9SMark Brown 	{ 0x56, 0xc07 },
394462835e4SMark Brown 	{ 0x5d, 0x7e },
395462835e4SMark Brown 	{ 0x5e, 0x0 },
396462835e4SMark Brown 	{ 0x102, 0x0 },
397462835e4SMark Brown };
398462835e4SMark Brown 
3999e501086SMark Brown /*
4009e501086SMark Brown  * Instantiate the generic non-control parts of the device.
4019e501086SMark Brown  */
402f791be49SBill Pemberton static int wm8994_device_init(struct wm8994 *wm8994, int irq)
4039e501086SMark Brown {
4049e501086SMark Brown 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
40534697898SMark Brown 	struct regmap_config *regmap_config;
406462835e4SMark Brown 	const struct reg_default *regmap_patch = NULL;
407559e0df6SMark Brown 	const char *devname;
408462835e4SMark Brown 	int ret, i, patch_regs;
40926c34c25SMark Brown 	int pulls = 0;
4109e501086SMark Brown 
4119e501086SMark Brown 	dev_set_drvdata(wm8994->dev, wm8994);
4129e501086SMark Brown 
4139e501086SMark Brown 	/* Add the on-chip regulators first for bootstrapping */
4149e501086SMark Brown 	ret = mfd_add_devices(wm8994->dev, -1,
4159e501086SMark Brown 			      wm8994_regulator_devs,
4169e501086SMark Brown 			      ARRAY_SIZE(wm8994_regulator_devs),
41755692af5SMark Brown 			      NULL, 0, NULL);
4189e501086SMark Brown 	if (ret != 0) {
4199e501086SMark Brown 		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
4209db4249fSMark Brown 		goto err;
4219e501086SMark Brown 	}
4229e501086SMark Brown 
423559e0df6SMark Brown 	switch (wm8994->type) {
424b1f43bf3SMark Brown 	case WM1811:
425b1f43bf3SMark Brown 		wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
426b1f43bf3SMark Brown 		break;
427559e0df6SMark Brown 	case WM8994:
428559e0df6SMark Brown 		wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
429559e0df6SMark Brown 		break;
430559e0df6SMark Brown 	case WM8958:
431559e0df6SMark Brown 		wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies);
432559e0df6SMark Brown 		break;
433559e0df6SMark Brown 	default:
434559e0df6SMark Brown 		BUG();
4359db4249fSMark Brown 		goto err;
436559e0df6SMark Brown 	}
437559e0df6SMark Brown 
4382fa33494SMark Brown 	wm8994->supplies = devm_kzalloc(wm8994->dev,
4392fa33494SMark Brown 					sizeof(struct regulator_bulk_data) *
4402fa33494SMark Brown 					wm8994->num_supplies, GFP_KERNEL);
441fccbd21fSAxel Lin 	if (!wm8994->supplies) {
442fccbd21fSAxel Lin 		ret = -ENOMEM;
4439db4249fSMark Brown 		goto err;
444fccbd21fSAxel Lin 	}
4459e501086SMark Brown 
446559e0df6SMark Brown 	switch (wm8994->type) {
447b1f43bf3SMark Brown 	case WM1811:
448b1f43bf3SMark Brown 		for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
449b1f43bf3SMark Brown 			wm8994->supplies[i].supply = wm1811_main_supplies[i];
450b1f43bf3SMark Brown 		break;
451559e0df6SMark Brown 	case WM8994:
4529e501086SMark Brown 		for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
4539e501086SMark Brown 			wm8994->supplies[i].supply = wm8994_main_supplies[i];
454559e0df6SMark Brown 		break;
455559e0df6SMark Brown 	case WM8958:
456559e0df6SMark Brown 		for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++)
457559e0df6SMark Brown 			wm8994->supplies[i].supply = wm8958_main_supplies[i];
458559e0df6SMark Brown 		break;
459559e0df6SMark Brown 	default:
460559e0df6SMark Brown 		BUG();
4619db4249fSMark Brown 		goto err;
462559e0df6SMark Brown 	}
4639e501086SMark Brown 
464559e0df6SMark Brown 	ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
4659e501086SMark Brown 				 wm8994->supplies);
4669e501086SMark Brown 	if (ret != 0) {
4679e501086SMark Brown 		dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
4689db4249fSMark Brown 		goto err;
4699e501086SMark Brown 	}
4709e501086SMark Brown 
471559e0df6SMark Brown 	ret = regulator_bulk_enable(wm8994->num_supplies,
4729e501086SMark Brown 				    wm8994->supplies);
4739e501086SMark Brown 	if (ret != 0) {
4749e501086SMark Brown 		dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
4757731074aSJoonyoung Shim 		goto err_get;
4769e501086SMark Brown 	}
4779e501086SMark Brown 
4789e501086SMark Brown 	ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);
4799e501086SMark Brown 	if (ret < 0) {
4809e501086SMark Brown 		dev_err(wm8994->dev, "Failed to read ID register\n");
4819e501086SMark Brown 		goto err_enable;
4829e501086SMark Brown 	}
483559e0df6SMark Brown 	switch (ret) {
484b1f43bf3SMark Brown 	case 0x1811:
485b1f43bf3SMark Brown 		devname = "WM1811";
486b1f43bf3SMark Brown 		if (wm8994->type != WM1811)
487b1f43bf3SMark Brown 			dev_warn(wm8994->dev, "Device registered as type %d\n",
488b1f43bf3SMark Brown 				 wm8994->type);
489b1f43bf3SMark Brown 		wm8994->type = WM1811;
490b1f43bf3SMark Brown 		break;
491559e0df6SMark Brown 	case 0x8994:
492559e0df6SMark Brown 		devname = "WM8994";
493559e0df6SMark Brown 		if (wm8994->type != WM8994)
494559e0df6SMark Brown 			dev_warn(wm8994->dev, "Device registered as type %d\n",
495559e0df6SMark Brown 				 wm8994->type);
496559e0df6SMark Brown 		wm8994->type = WM8994;
497559e0df6SMark Brown 		break;
498559e0df6SMark Brown 	case 0x8958:
499559e0df6SMark Brown 		devname = "WM8958";
500559e0df6SMark Brown 		if (wm8994->type != WM8958)
501559e0df6SMark Brown 			dev_warn(wm8994->dev, "Device registered as type %d\n",
502559e0df6SMark Brown 				 wm8994->type);
503559e0df6SMark Brown 		wm8994->type = WM8958;
504559e0df6SMark Brown 		break;
505559e0df6SMark Brown 	default:
5069e501086SMark Brown 		dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",
5079e501086SMark Brown 			ret);
5089e501086SMark Brown 		ret = -EINVAL;
5099e501086SMark Brown 		goto err_enable;
5109e501086SMark Brown 	}
5119e501086SMark Brown 
5129e501086SMark Brown 	ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION);
5139e501086SMark Brown 	if (ret < 0) {
5149e501086SMark Brown 		dev_err(wm8994->dev, "Failed to read revision register: %d\n",
5159e501086SMark Brown 			ret);
5169e501086SMark Brown 		goto err_enable;
5179e501086SMark Brown 	}
518cc7a7279SMark Brown 	wm8994->revision = ret & WM8994_CHIP_REV_MASK;
519cc7a7279SMark Brown 	wm8994->cust_id = (ret & WM8994_CUST_ID_MASK) >> WM8994_CUST_ID_SHIFT;
5209e501086SMark Brown 
521a2495bc7SMark Brown 	switch (wm8994->type) {
522a2495bc7SMark Brown 	case WM8994:
5237ed5849cSMark Brown 		switch (wm8994->revision) {
5249e501086SMark Brown 		case 0:
5259e501086SMark Brown 		case 1:
526559e0df6SMark Brown 			dev_warn(wm8994->dev,
527559e0df6SMark Brown 				 "revision %c not fully supported\n",
5287ed5849cSMark Brown 				 'A' + wm8994->revision);
5299e501086SMark Brown 			break;
530462835e4SMark Brown 		case 2:
531462835e4SMark Brown 		case 3:
532462835e4SMark Brown 			regmap_patch = wm8994_revc_patch;
533462835e4SMark Brown 			patch_regs = ARRAY_SIZE(wm8994_revc_patch);
534462835e4SMark Brown 			break;
5359e501086SMark Brown 		default:
5369e501086SMark Brown 			break;
5379e501086SMark Brown 		}
538a2495bc7SMark Brown 		break;
539462835e4SMark Brown 
540462835e4SMark Brown 	case WM8958:
541462835e4SMark Brown 		switch (wm8994->revision) {
542462835e4SMark Brown 		case 0:
543462835e4SMark Brown 			regmap_patch = wm8958_reva_patch;
544462835e4SMark Brown 			patch_regs = ARRAY_SIZE(wm8958_reva_patch);
545462835e4SMark Brown 			break;
546462835e4SMark Brown 		default:
547462835e4SMark Brown 			break;
548462835e4SMark Brown 		}
549462835e4SMark Brown 		break;
550462835e4SMark Brown 
551443e67edSMark Brown 	case WM1811:
552443e67edSMark Brown 		/* Revision C did not change the relevant layer */
5537ed5849cSMark Brown 		if (wm8994->revision > 1)
5547ed5849cSMark Brown 			wm8994->revision++;
555462835e4SMark Brown 		switch (wm8994->revision) {
556462835e4SMark Brown 		case 0:
557462835e4SMark Brown 		case 1:
558a0cc0209SMark Brown 		case 2:
559a0cc0209SMark Brown 		case 3:
560462835e4SMark Brown 			regmap_patch = wm1811_reva_patch;
561462835e4SMark Brown 			patch_regs = ARRAY_SIZE(wm1811_reva_patch);
562443e67edSMark Brown 			break;
563a2495bc7SMark Brown 		default:
564a2495bc7SMark Brown 			break;
565a2495bc7SMark Brown 		}
566462835e4SMark Brown 		break;
567462835e4SMark Brown 
568462835e4SMark Brown 	default:
569462835e4SMark Brown 		break;
570462835e4SMark Brown 	}
5719e501086SMark Brown 
572cc7a7279SMark Brown 	dev_info(wm8994->dev, "%s revision %c CUST_ID %02x\n", devname,
573cc7a7279SMark Brown 		 'A' + wm8994->revision, wm8994->cust_id);
5749e501086SMark Brown 
57534697898SMark Brown 	switch (wm8994->type) {
57634697898SMark Brown 	case WM1811:
57734697898SMark Brown 		regmap_config = &wm1811_regmap_config;
57834697898SMark Brown 		break;
57934697898SMark Brown 	case WM8994:
58034697898SMark Brown 		regmap_config = &wm8994_regmap_config;
58134697898SMark Brown 		break;
58234697898SMark Brown 	case WM8958:
58334697898SMark Brown 		regmap_config = &wm8958_regmap_config;
58434697898SMark Brown 		break;
58534697898SMark Brown 	default:
58634697898SMark Brown 		dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);
58734697898SMark Brown 		return -EINVAL;
58834697898SMark Brown 	}
58934697898SMark Brown 
59034697898SMark Brown 	ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
59134697898SMark Brown 	if (ret != 0) {
59234697898SMark Brown 		dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",
59334697898SMark Brown 			ret);
59434697898SMark Brown 		return ret;
59534697898SMark Brown 	}
5969e501086SMark Brown 
597462835e4SMark Brown 	if (regmap_patch) {
598462835e4SMark Brown 		ret = regmap_register_patch(wm8994->regmap, regmap_patch,
599462835e4SMark Brown 					    patch_regs);
600462835e4SMark Brown 		if (ret != 0) {
601462835e4SMark Brown 			dev_err(wm8994->dev, "Failed to register patch: %d\n",
602462835e4SMark Brown 				ret);
6039db4249fSMark Brown 			goto err;
604462835e4SMark Brown 		}
605462835e4SMark Brown 	}
606462835e4SMark Brown 
6079e501086SMark Brown 	if (pdata) {
608c9fbf7e0SMark Brown 		wm8994->irq_base = pdata->irq_base;
6099e501086SMark Brown 		wm8994->gpio_base = pdata->gpio_base;
6109e501086SMark Brown 
6119e501086SMark Brown 		/* GPIO configuration is only applied if it's non-zero */
6129e501086SMark Brown 		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
6139e501086SMark Brown 			if (pdata->gpio_defaults[i]) {
6149e501086SMark Brown 				wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
6159e501086SMark Brown 						0xffff,
6169e501086SMark Brown 						pdata->gpio_defaults[i]);
6179e501086SMark Brown 			}
6189e501086SMark Brown 		}
619881de670SMark Brown 
620881de670SMark Brown 		wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
62126c34c25SMark Brown 
62226c34c25SMark Brown 		if (pdata->spkmode_pu)
62326c34c25SMark Brown 			pulls |= WM8994_SPKMODE_PU;
6249e501086SMark Brown 	}
6259e501086SMark Brown 
62626c34c25SMark Brown 	/* Disable unneeded pulls */
627881de670SMark Brown 	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
62826c34c25SMark Brown 			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD |
62926c34c25SMark Brown 			WM8994_SPKMODE_PU | WM8994_CSNADDR_PD,
63026c34c25SMark Brown 			pulls);
631881de670SMark Brown 
6329e501086SMark Brown 	/* In some system designs where the regulators are not in use,
6339e501086SMark Brown 	 * we can achieve a small reduction in leakage currents by
6349e501086SMark Brown 	 * floating LDO outputs.  This bit makes no difference if the
6359e501086SMark Brown 	 * LDOs are enabled, it only affects cases where the LDOs were
6369e501086SMark Brown 	 * in operation and are then disabled.
6379e501086SMark Brown 	 */
6389e501086SMark Brown 	for (i = 0; i < WM8994_NUM_LDO_REGS; i++) {
6399e501086SMark Brown 		if (wm8994_ldo_in_use(pdata, i))
6409e501086SMark Brown 			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
6419e501086SMark Brown 					WM8994_LDO1_DISCH, WM8994_LDO1_DISCH);
6429e501086SMark Brown 		else
6439e501086SMark Brown 			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
6449e501086SMark Brown 					WM8994_LDO1_DISCH, 0);
6459e501086SMark Brown 	}
6469e501086SMark Brown 
647c9fbf7e0SMark Brown 	wm8994_irq_init(wm8994);
648c9fbf7e0SMark Brown 
6499e501086SMark Brown 	ret = mfd_add_devices(wm8994->dev, -1,
6509e501086SMark Brown 			      wm8994_devs, ARRAY_SIZE(wm8994_devs),
65155692af5SMark Brown 			      NULL, 0, NULL);
6529e501086SMark Brown 	if (ret != 0) {
6539e501086SMark Brown 		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
654c9fbf7e0SMark Brown 		goto err_irq;
6559e501086SMark Brown 	}
6569e501086SMark Brown 
657d450f19eSMark Brown 	pm_runtime_enable(wm8994->dev);
658ee67b0cdSMark Brown 	pm_runtime_idle(wm8994->dev);
659d450f19eSMark Brown 
6609e501086SMark Brown 	return 0;
6619e501086SMark Brown 
662c9fbf7e0SMark Brown err_irq:
663c9fbf7e0SMark Brown 	wm8994_irq_exit(wm8994);
6649e501086SMark Brown err_enable:
665559e0df6SMark Brown 	regulator_bulk_disable(wm8994->num_supplies,
6669e501086SMark Brown 			       wm8994->supplies);
6679e501086SMark Brown err_get:
668559e0df6SMark Brown 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
6699db4249fSMark Brown err:
6709e501086SMark Brown 	mfd_remove_devices(wm8994->dev);
6719e501086SMark Brown 	return ret;
6729e501086SMark Brown }
6739e501086SMark Brown 
6744740f73fSBill Pemberton static void wm8994_device_exit(struct wm8994 *wm8994)
6759e501086SMark Brown {
676d450f19eSMark Brown 	pm_runtime_disable(wm8994->dev);
6779e501086SMark Brown 	mfd_remove_devices(wm8994->dev);
678c9fbf7e0SMark Brown 	wm8994_irq_exit(wm8994);
679559e0df6SMark Brown 	regulator_bulk_disable(wm8994->num_supplies,
6809e501086SMark Brown 			       wm8994->supplies);
681559e0df6SMark Brown 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
6829e501086SMark Brown }
6839e501086SMark Brown 
684cf763c2eSMark Brown static const struct of_device_id wm8994_of_match[] = {
685cf763c2eSMark Brown 	{ .compatible = "wlf,wm1811", },
686cf763c2eSMark Brown 	{ .compatible = "wlf,wm8994", },
687cf763c2eSMark Brown 	{ .compatible = "wlf,wm8958", },
688cf763c2eSMark Brown 	{ }
689cf763c2eSMark Brown };
690cf763c2eSMark Brown MODULE_DEVICE_TABLE(of, wm8994_of_match);
691cf763c2eSMark Brown 
692f791be49SBill Pemberton static int wm8994_i2c_probe(struct i2c_client *i2c,
6939e501086SMark Brown 				      const struct i2c_device_id *id)
6949e501086SMark Brown {
6959e501086SMark Brown 	struct wm8994 *wm8994;
696d6c645fcSMark Brown 	int ret;
6979e501086SMark Brown 
6982fa33494SMark Brown 	wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);
699d0a11693SAxel Lin 	if (wm8994 == NULL)
7009e501086SMark Brown 		return -ENOMEM;
7019e501086SMark Brown 
7029e501086SMark Brown 	i2c_set_clientdata(i2c, wm8994);
7039e501086SMark Brown 	wm8994->dev = &i2c->dev;
704c9fbf7e0SMark Brown 	wm8994->irq = i2c->irq;
705559e0df6SMark Brown 	wm8994->type = id->driver_data;
7069e501086SMark Brown 
7079db4249fSMark Brown 	wm8994->regmap = devm_regmap_init_i2c(i2c, &wm8994_base_regmap_config);
708d6c645fcSMark Brown 	if (IS_ERR(wm8994->regmap)) {
709d6c645fcSMark Brown 		ret = PTR_ERR(wm8994->regmap);
710d6c645fcSMark Brown 		dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
711d6c645fcSMark Brown 			ret);
712d6c645fcSMark Brown 		return ret;
713d6c645fcSMark Brown 	}
714d6c645fcSMark Brown 
715559e0df6SMark Brown 	return wm8994_device_init(wm8994, i2c->irq);
7169e501086SMark Brown }
7179e501086SMark Brown 
7184740f73fSBill Pemberton static int wm8994_i2c_remove(struct i2c_client *i2c)
7199e501086SMark Brown {
7209e501086SMark Brown 	struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
7219e501086SMark Brown 
7229e501086SMark Brown 	wm8994_device_exit(wm8994);
7239e501086SMark Brown 
7249e501086SMark Brown 	return 0;
7259e501086SMark Brown }
7269e501086SMark Brown 
7279e501086SMark Brown static const struct i2c_device_id wm8994_i2c_id[] = {
728b1f43bf3SMark Brown 	{ "wm1811", WM1811 },
72971d17184SMark Brown 	{ "wm1811a", WM1811 },
730559e0df6SMark Brown 	{ "wm8994", WM8994 },
731559e0df6SMark Brown 	{ "wm8958", WM8958 },
7329e501086SMark Brown 	{ }
7339e501086SMark Brown };
7349e501086SMark Brown MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
7359e501086SMark Brown 
736aad34310SMark Brown static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume,
737aad34310SMark Brown 			    NULL);
738d450f19eSMark Brown 
7399e501086SMark Brown static struct i2c_driver wm8994_i2c_driver = {
7409e501086SMark Brown 	.driver = {
7419e501086SMark Brown 		.name = "wm8994",
7429e501086SMark Brown 		.owner = THIS_MODULE,
743d450f19eSMark Brown 		.pm = &wm8994_pm_ops,
744cf763c2eSMark Brown 		.of_match_table = wm8994_of_match,
7459e501086SMark Brown 	},
7469e501086SMark Brown 	.probe = wm8994_i2c_probe,
74784449216SBill Pemberton 	.remove = wm8994_i2c_remove,
7489e501086SMark Brown 	.id_table = wm8994_i2c_id,
7499e501086SMark Brown };
7509e501086SMark Brown 
751ceb57d27SMark Brown module_i2c_driver(wm8994_i2c_driver);
7529e501086SMark Brown 
7539e501086SMark Brown MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
7549e501086SMark Brown MODULE_LICENSE("GPL");
7559e501086SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
756