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 2863befc925SMark Brown regcache_cache_only(wm8994->regmap, true); 287c3f13861SMark Brown regcache_mark_dirty(wm8994->regmap); 2889e501086SMark Brown 2899e501086SMark Brown wm8994->suspended = true; 2909e501086SMark Brown 2919e501086SMark Brown ret = regulator_bulk_disable(wm8994->num_supplies, 2929e501086SMark Brown wm8994->supplies); 2939e501086SMark Brown if (ret != 0) { 2949e501086SMark Brown dev_err(dev, "Failed to disable supplies: %d\n", ret); 2959e501086SMark Brown return ret; 296d450f19eSMark Brown } 2979e501086SMark Brown 2989e501086SMark Brown return 0; 2999e501086SMark Brown } 3009e501086SMark Brown 30177bd70e9SMark Brown static int wm8994_resume(struct device *dev) 30277bd70e9SMark Brown { 30377bd70e9SMark Brown struct wm8994 *wm8994 = dev_get_drvdata(dev); 304c3f13861SMark Brown int ret; 3059e501086SMark Brown 30677bd70e9SMark Brown /* We may have lied to the PM core about suspending */ 30777bd70e9SMark Brown if (!wm8994->suspended) 30877bd70e9SMark Brown return 0; 30977bd70e9SMark Brown 310559e0df6SMark Brown ret = regulator_bulk_enable(wm8994->num_supplies, 3119e501086SMark Brown wm8994->supplies); 3129e501086SMark Brown if (ret != 0) { 3139e501086SMark Brown dev_err(dev, "Failed to enable supplies: %d\n", ret); 3149e501086SMark Brown return ret; 3159e501086SMark Brown } 3169e501086SMark Brown 3173befc925SMark Brown regcache_cache_only(wm8994->regmap, false); 318c3f13861SMark Brown ret = regcache_sync(wm8994->regmap); 319c3f13861SMark Brown if (ret != 0) { 320c3f13861SMark Brown dev_err(dev, "Failed to restore register map: %d\n", ret); 321c3f13861SMark Brown goto err_enable; 32298ae1ccaSMark Brown } 323c9fbf7e0SMark Brown 324881de670SMark Brown /* Disable LDO pulldowns while the device is active */ 325881de670SMark Brown wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2, 326881de670SMark Brown WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, 327881de670SMark Brown 0); 328881de670SMark Brown 32977bd70e9SMark Brown wm8994->suspended = false; 33077bd70e9SMark Brown 3319e501086SMark Brown return 0; 332c3f13861SMark Brown 333c3f13861SMark Brown err_enable: 334c3f13861SMark Brown regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies); 335c3f13861SMark Brown 336c3f13861SMark Brown return ret; 3379e501086SMark Brown } 3389e501086SMark Brown #endif 3399e501086SMark Brown 3409e501086SMark Brown #ifdef CONFIG_REGULATOR 3419e501086SMark Brown static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) 3429e501086SMark Brown { 3439e501086SMark Brown struct wm8994_ldo_pdata *ldo_pdata; 3449e501086SMark Brown 3459e501086SMark Brown if (!pdata) 3469e501086SMark Brown return 0; 3479e501086SMark Brown 3489e501086SMark Brown ldo_pdata = &pdata->ldo[ldo]; 3499e501086SMark Brown 3509e501086SMark Brown if (!ldo_pdata->init_data) 3519e501086SMark Brown return 0; 3529e501086SMark Brown 3539e501086SMark Brown return ldo_pdata->init_data->num_consumer_supplies != 0; 3549e501086SMark Brown } 3559e501086SMark Brown #else 3569e501086SMark Brown static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) 3579e501086SMark Brown { 3589e501086SMark Brown return 0; 3599e501086SMark Brown } 3609e501086SMark Brown #endif 3619e501086SMark Brown 3629e501086SMark Brown /* 3639e501086SMark Brown * Instantiate the generic non-control parts of the device. 3649e501086SMark Brown */ 365559e0df6SMark Brown static int wm8994_device_init(struct wm8994 *wm8994, int irq) 3669e501086SMark Brown { 3679e501086SMark Brown struct wm8994_pdata *pdata = wm8994->dev->platform_data; 36834697898SMark Brown struct regmap_config *regmap_config; 369559e0df6SMark Brown const char *devname; 3709e501086SMark Brown int ret, i; 37126c34c25SMark Brown int pulls = 0; 3729e501086SMark Brown 3739e501086SMark Brown dev_set_drvdata(wm8994->dev, wm8994); 3749e501086SMark Brown 3759e501086SMark Brown /* Add the on-chip regulators first for bootstrapping */ 3769e501086SMark Brown ret = mfd_add_devices(wm8994->dev, -1, 3779e501086SMark Brown wm8994_regulator_devs, 3789e501086SMark Brown ARRAY_SIZE(wm8994_regulator_devs), 3799e501086SMark Brown NULL, 0); 3809e501086SMark Brown if (ret != 0) { 3819e501086SMark Brown dev_err(wm8994->dev, "Failed to add children: %d\n", ret); 382d6c645fcSMark Brown goto err_regmap; 3839e501086SMark Brown } 3849e501086SMark Brown 385559e0df6SMark Brown switch (wm8994->type) { 386b1f43bf3SMark Brown case WM1811: 387b1f43bf3SMark Brown wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies); 388b1f43bf3SMark Brown break; 389559e0df6SMark Brown case WM8994: 390559e0df6SMark Brown wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); 391559e0df6SMark Brown break; 392559e0df6SMark Brown case WM8958: 393559e0df6SMark Brown wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies); 394559e0df6SMark Brown break; 395559e0df6SMark Brown default: 396559e0df6SMark Brown BUG(); 397d6c645fcSMark Brown goto err_regmap; 398559e0df6SMark Brown } 399559e0df6SMark Brown 4002fa33494SMark Brown wm8994->supplies = devm_kzalloc(wm8994->dev, 4012fa33494SMark Brown sizeof(struct regulator_bulk_data) * 4022fa33494SMark Brown wm8994->num_supplies, GFP_KERNEL); 403fccbd21fSAxel Lin if (!wm8994->supplies) { 404fccbd21fSAxel Lin ret = -ENOMEM; 405d6c645fcSMark Brown goto err_regmap; 406fccbd21fSAxel Lin } 4079e501086SMark Brown 408559e0df6SMark Brown switch (wm8994->type) { 409b1f43bf3SMark Brown case WM1811: 410b1f43bf3SMark Brown for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++) 411b1f43bf3SMark Brown wm8994->supplies[i].supply = wm1811_main_supplies[i]; 412b1f43bf3SMark Brown break; 413559e0df6SMark Brown case WM8994: 4149e501086SMark Brown for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) 4159e501086SMark Brown wm8994->supplies[i].supply = wm8994_main_supplies[i]; 416559e0df6SMark Brown break; 417559e0df6SMark Brown case WM8958: 418559e0df6SMark Brown for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++) 419559e0df6SMark Brown wm8994->supplies[i].supply = wm8958_main_supplies[i]; 420559e0df6SMark Brown break; 421559e0df6SMark Brown default: 422559e0df6SMark Brown BUG(); 423d6c645fcSMark Brown goto err_regmap; 424559e0df6SMark Brown } 4259e501086SMark Brown 426559e0df6SMark Brown ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, 4279e501086SMark Brown wm8994->supplies); 4289e501086SMark Brown if (ret != 0) { 4299e501086SMark Brown dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); 4302fa33494SMark Brown goto err_regmap; 4319e501086SMark Brown } 4329e501086SMark Brown 433559e0df6SMark Brown ret = regulator_bulk_enable(wm8994->num_supplies, 4349e501086SMark Brown wm8994->supplies); 4359e501086SMark Brown if (ret != 0) { 4369e501086SMark Brown dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); 4377731074aSJoonyoung Shim goto err_get; 4389e501086SMark Brown } 4399e501086SMark Brown 4409e501086SMark Brown ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET); 4419e501086SMark Brown if (ret < 0) { 4429e501086SMark Brown dev_err(wm8994->dev, "Failed to read ID register\n"); 4439e501086SMark Brown goto err_enable; 4449e501086SMark Brown } 445559e0df6SMark Brown switch (ret) { 446b1f43bf3SMark Brown case 0x1811: 447b1f43bf3SMark Brown devname = "WM1811"; 448b1f43bf3SMark Brown if (wm8994->type != WM1811) 449b1f43bf3SMark Brown dev_warn(wm8994->dev, "Device registered as type %d\n", 450b1f43bf3SMark Brown wm8994->type); 451b1f43bf3SMark Brown wm8994->type = WM1811; 452b1f43bf3SMark Brown break; 453559e0df6SMark Brown case 0x8994: 454559e0df6SMark Brown devname = "WM8994"; 455559e0df6SMark Brown if (wm8994->type != WM8994) 456559e0df6SMark Brown dev_warn(wm8994->dev, "Device registered as type %d\n", 457559e0df6SMark Brown wm8994->type); 458559e0df6SMark Brown wm8994->type = WM8994; 459559e0df6SMark Brown break; 460559e0df6SMark Brown case 0x8958: 461559e0df6SMark Brown devname = "WM8958"; 462559e0df6SMark Brown if (wm8994->type != WM8958) 463559e0df6SMark Brown dev_warn(wm8994->dev, "Device registered as type %d\n", 464559e0df6SMark Brown wm8994->type); 465559e0df6SMark Brown wm8994->type = WM8958; 466559e0df6SMark Brown break; 467559e0df6SMark Brown default: 4689e501086SMark Brown dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", 4699e501086SMark Brown ret); 4709e501086SMark Brown ret = -EINVAL; 4719e501086SMark Brown goto err_enable; 4729e501086SMark Brown } 4739e501086SMark Brown 4749e501086SMark Brown ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION); 4759e501086SMark Brown if (ret < 0) { 4769e501086SMark Brown dev_err(wm8994->dev, "Failed to read revision register: %d\n", 4779e501086SMark Brown ret); 4789e501086SMark Brown goto err_enable; 4799e501086SMark Brown } 4807ed5849cSMark Brown wm8994->revision = ret; 4819e501086SMark Brown 482a2495bc7SMark Brown switch (wm8994->type) { 483a2495bc7SMark Brown case WM8994: 4847ed5849cSMark Brown switch (wm8994->revision) { 4859e501086SMark Brown case 0: 4869e501086SMark Brown case 1: 487559e0df6SMark Brown dev_warn(wm8994->dev, 488559e0df6SMark Brown "revision %c not fully supported\n", 4897ed5849cSMark Brown 'A' + wm8994->revision); 4909e501086SMark Brown break; 4919e501086SMark Brown default: 4929e501086SMark Brown break; 4939e501086SMark Brown } 494a2495bc7SMark Brown break; 495443e67edSMark Brown case WM1811: 496443e67edSMark Brown /* Revision C did not change the relevant layer */ 4977ed5849cSMark Brown if (wm8994->revision > 1) 4987ed5849cSMark Brown wm8994->revision++; 499443e67edSMark Brown break; 500a2495bc7SMark Brown default: 501a2495bc7SMark Brown break; 502a2495bc7SMark Brown } 5039e501086SMark Brown 5047ed5849cSMark Brown dev_info(wm8994->dev, "%s revision %c\n", devname, 5057ed5849cSMark Brown 'A' + wm8994->revision); 5069e501086SMark Brown 50734697898SMark Brown switch (wm8994->type) { 50834697898SMark Brown case WM1811: 50934697898SMark Brown regmap_config = &wm1811_regmap_config; 51034697898SMark Brown break; 51134697898SMark Brown case WM8994: 51234697898SMark Brown regmap_config = &wm8994_regmap_config; 51334697898SMark Brown break; 51434697898SMark Brown case WM8958: 51534697898SMark Brown regmap_config = &wm8958_regmap_config; 51634697898SMark Brown break; 51734697898SMark Brown default: 51834697898SMark Brown dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type); 51934697898SMark Brown return -EINVAL; 52034697898SMark Brown } 52134697898SMark Brown 52234697898SMark Brown ret = regmap_reinit_cache(wm8994->regmap, regmap_config); 52334697898SMark Brown if (ret != 0) { 52434697898SMark Brown dev_err(wm8994->dev, "Failed to reinit register cache: %d\n", 52534697898SMark Brown ret); 52634697898SMark Brown return ret; 52734697898SMark Brown } 5289e501086SMark Brown 5299e501086SMark Brown if (pdata) { 530c9fbf7e0SMark Brown wm8994->irq_base = pdata->irq_base; 5319e501086SMark Brown wm8994->gpio_base = pdata->gpio_base; 5329e501086SMark Brown 5339e501086SMark Brown /* GPIO configuration is only applied if it's non-zero */ 5349e501086SMark Brown for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { 5359e501086SMark Brown if (pdata->gpio_defaults[i]) { 5369e501086SMark Brown wm8994_set_bits(wm8994, WM8994_GPIO_1 + i, 5379e501086SMark Brown 0xffff, 5389e501086SMark Brown pdata->gpio_defaults[i]); 5399e501086SMark Brown } 5409e501086SMark Brown } 541881de670SMark Brown 542881de670SMark Brown wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven; 54326c34c25SMark Brown 54426c34c25SMark Brown if (pdata->spkmode_pu) 54526c34c25SMark Brown pulls |= WM8994_SPKMODE_PU; 5469e501086SMark Brown } 5479e501086SMark Brown 54826c34c25SMark Brown /* Disable unneeded pulls */ 549881de670SMark Brown wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2, 55026c34c25SMark Brown WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD | 55126c34c25SMark Brown WM8994_SPKMODE_PU | WM8994_CSNADDR_PD, 55226c34c25SMark Brown pulls); 553881de670SMark Brown 5549e501086SMark Brown /* In some system designs where the regulators are not in use, 5559e501086SMark Brown * we can achieve a small reduction in leakage currents by 5569e501086SMark Brown * floating LDO outputs. This bit makes no difference if the 5579e501086SMark Brown * LDOs are enabled, it only affects cases where the LDOs were 5589e501086SMark Brown * in operation and are then disabled. 5599e501086SMark Brown */ 5609e501086SMark Brown for (i = 0; i < WM8994_NUM_LDO_REGS; i++) { 5619e501086SMark Brown if (wm8994_ldo_in_use(pdata, i)) 5629e501086SMark Brown wm8994_set_bits(wm8994, WM8994_LDO_1 + i, 5639e501086SMark Brown WM8994_LDO1_DISCH, WM8994_LDO1_DISCH); 5649e501086SMark Brown else 5659e501086SMark Brown wm8994_set_bits(wm8994, WM8994_LDO_1 + i, 5669e501086SMark Brown WM8994_LDO1_DISCH, 0); 5679e501086SMark Brown } 5689e501086SMark Brown 569c9fbf7e0SMark Brown wm8994_irq_init(wm8994); 570c9fbf7e0SMark Brown 5719e501086SMark Brown ret = mfd_add_devices(wm8994->dev, -1, 5729e501086SMark Brown wm8994_devs, ARRAY_SIZE(wm8994_devs), 5739e501086SMark Brown NULL, 0); 5749e501086SMark Brown if (ret != 0) { 5759e501086SMark Brown dev_err(wm8994->dev, "Failed to add children: %d\n", ret); 576c9fbf7e0SMark Brown goto err_irq; 5779e501086SMark Brown } 5789e501086SMark Brown 579d450f19eSMark Brown pm_runtime_enable(wm8994->dev); 580d450f19eSMark Brown pm_runtime_resume(wm8994->dev); 581d450f19eSMark Brown 5829e501086SMark Brown return 0; 5839e501086SMark Brown 584c9fbf7e0SMark Brown err_irq: 585c9fbf7e0SMark Brown wm8994_irq_exit(wm8994); 5869e501086SMark Brown err_enable: 587559e0df6SMark Brown regulator_bulk_disable(wm8994->num_supplies, 5889e501086SMark Brown wm8994->supplies); 5899e501086SMark Brown err_get: 590559e0df6SMark Brown regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); 591d6c645fcSMark Brown err_regmap: 592d6c645fcSMark Brown regmap_exit(wm8994->regmap); 5939e501086SMark Brown mfd_remove_devices(wm8994->dev); 5949e501086SMark Brown return ret; 5959e501086SMark Brown } 5969e501086SMark Brown 5979e501086SMark Brown static void wm8994_device_exit(struct wm8994 *wm8994) 5989e501086SMark Brown { 599d450f19eSMark Brown pm_runtime_disable(wm8994->dev); 6009e501086SMark Brown mfd_remove_devices(wm8994->dev); 601c9fbf7e0SMark Brown wm8994_irq_exit(wm8994); 602559e0df6SMark Brown regulator_bulk_disable(wm8994->num_supplies, 6039e501086SMark Brown wm8994->supplies); 604559e0df6SMark Brown regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); 605d6c645fcSMark Brown regmap_exit(wm8994->regmap); 6069e501086SMark Brown } 6079e501086SMark Brown 608cf763c2eSMark Brown static const struct of_device_id wm8994_of_match[] = { 609cf763c2eSMark Brown { .compatible = "wlf,wm1811", }, 610cf763c2eSMark Brown { .compatible = "wlf,wm8994", }, 611cf763c2eSMark Brown { .compatible = "wlf,wm8958", }, 612cf763c2eSMark Brown { } 613cf763c2eSMark Brown }; 614cf763c2eSMark Brown MODULE_DEVICE_TABLE(of, wm8994_of_match); 615cf763c2eSMark Brown 6169e501086SMark Brown static int wm8994_i2c_probe(struct i2c_client *i2c, 6179e501086SMark Brown const struct i2c_device_id *id) 6189e501086SMark Brown { 6199e501086SMark Brown struct wm8994 *wm8994; 620d6c645fcSMark Brown int ret; 6219e501086SMark Brown 6222fa33494SMark Brown wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL); 623d0a11693SAxel Lin if (wm8994 == NULL) 6249e501086SMark Brown return -ENOMEM; 6259e501086SMark Brown 6269e501086SMark Brown i2c_set_clientdata(i2c, wm8994); 6279e501086SMark Brown wm8994->dev = &i2c->dev; 628c9fbf7e0SMark Brown wm8994->irq = i2c->irq; 629559e0df6SMark Brown wm8994->type = id->driver_data; 6309e501086SMark Brown 63134697898SMark Brown wm8994->regmap = regmap_init_i2c(i2c, &wm8994_base_regmap_config); 632d6c645fcSMark Brown if (IS_ERR(wm8994->regmap)) { 633d6c645fcSMark Brown ret = PTR_ERR(wm8994->regmap); 634d6c645fcSMark Brown dev_err(wm8994->dev, "Failed to allocate register map: %d\n", 635d6c645fcSMark Brown ret); 636d6c645fcSMark Brown return ret; 637d6c645fcSMark Brown } 638d6c645fcSMark Brown 639559e0df6SMark Brown return wm8994_device_init(wm8994, i2c->irq); 6409e501086SMark Brown } 6419e501086SMark Brown 6429e501086SMark Brown static int wm8994_i2c_remove(struct i2c_client *i2c) 6439e501086SMark Brown { 6449e501086SMark Brown struct wm8994 *wm8994 = i2c_get_clientdata(i2c); 6459e501086SMark Brown 6469e501086SMark Brown wm8994_device_exit(wm8994); 6479e501086SMark Brown 6489e501086SMark Brown return 0; 6499e501086SMark Brown } 6509e501086SMark Brown 6519e501086SMark Brown static const struct i2c_device_id wm8994_i2c_id[] = { 652b1f43bf3SMark Brown { "wm1811", WM1811 }, 65371d17184SMark Brown { "wm1811a", WM1811 }, 654559e0df6SMark Brown { "wm8994", WM8994 }, 655559e0df6SMark Brown { "wm8958", WM8958 }, 6569e501086SMark Brown { } 6579e501086SMark Brown }; 6589e501086SMark Brown MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); 6599e501086SMark Brown 660aad34310SMark Brown static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, 661aad34310SMark Brown NULL); 662d450f19eSMark Brown 6639e501086SMark Brown static struct i2c_driver wm8994_i2c_driver = { 6649e501086SMark Brown .driver = { 6659e501086SMark Brown .name = "wm8994", 6669e501086SMark Brown .owner = THIS_MODULE, 667d450f19eSMark Brown .pm = &wm8994_pm_ops, 668cf763c2eSMark Brown .of_match_table = wm8994_of_match, 6699e501086SMark Brown }, 6709e501086SMark Brown .probe = wm8994_i2c_probe, 6719e501086SMark Brown .remove = wm8994_i2c_remove, 6729e501086SMark Brown .id_table = wm8994_i2c_id, 6739e501086SMark Brown }; 6749e501086SMark Brown 6759e501086SMark Brown static int __init wm8994_i2c_init(void) 6769e501086SMark Brown { 6779e501086SMark Brown int ret; 6789e501086SMark Brown 6799e501086SMark Brown ret = i2c_add_driver(&wm8994_i2c_driver); 6809e501086SMark Brown if (ret != 0) 6819e501086SMark Brown pr_err("Failed to register wm8994 I2C driver: %d\n", ret); 6829e501086SMark Brown 6839e501086SMark Brown return ret; 6849e501086SMark Brown } 6859e501086SMark Brown module_init(wm8994_i2c_init); 6869e501086SMark Brown 6879e501086SMark Brown static void __exit wm8994_i2c_exit(void) 6889e501086SMark Brown { 6899e501086SMark Brown i2c_del_driver(&wm8994_i2c_driver); 6909e501086SMark Brown } 6919e501086SMark Brown module_exit(wm8994_i2c_exit); 6929e501086SMark Brown 6939e501086SMark Brown MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC"); 6949e501086SMark Brown MODULE_LICENSE("GPL"); 6959e501086SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 696